public SipResult SipResult; // The ultimate request result /// <summary> /// Constructor /// </summary> /// <param name="request">The request being submitted.</param> /// <param name="dialog">The <see cref="SipDialog" /> for requests that initiate a dialog (or <c>null</c>).</param> /// <param name="callback">The application callback (or <c>null</c>).</param> /// <param name="state">The application state (or <c>null</c>).</param> public ClientAsyncResult(SipRequest request, SipDialog dialog, AsyncCallback callback, object state) : base(null, callback, state) { this.Request = request; this.Dialog = dialog; this.SipResult = null; }
/// <summary> /// Constructor. /// </summary> /// <param name="request">The initiating <see cref="SipRequest" />.</param> /// <param name="dialog">The <see cref="SipDialog" /> for requests that initiate a dialog (or <c>null</c>).</param> /// <param name="agent">The <see cref="ISipAgent" /> that sent the request and received the response.</param> /// <param name="response">The final <see cref="SipResponse" />.</param> public SipResult(SipRequest request, SipDialog dialog, ISipAgent agent, SipResponse response) { this.Request = request; this.Response = response; this.Status = response.Status; this.Dialog = dialog; this.Agent = agent; }
/// <summary> /// Constructor. /// </summary> /// <param name="request">The initiating <see cref="SipRequest" />.</param> /// <param name="dialog">The <see cref="SipDialog" /> for requests that initiate a dialog (or <c>null</c>).</param> /// <param name="agent">The <see cref="ISipAgent" /> that sent the request and received the response.</param> /// <param name="status">The final operation status.</param> public SipResult(SipRequest request, SipDialog dialog, ISipAgent agent, SipStatus status) { this.Request = request; this.Response = null; this.Status = status; this.Dialog = dialog; this.Agent = agent; }
/// <summary> /// Constuctor. /// </summary> /// <param name="dialog">The <see cref="SipDialog" />.</param> /// <param name="transaction">The <see cref="SipTransaction" /> associated with the event (or <c>null</c>).</param> /// <param name="core">The <see cref="SipCore" /> that raised the event.</param> /// <param name="clientRequest">Pass the <see cref="SipRequest" /> received for server side dialog creation (or <c>null</c>).</param> /// <param name="serverResult">The <see cref="SipResult" /> returned by the server, completing its side of the dialog creation (or <c>null</c>).</param> internal SipDialogEventArgs(SipDialog dialog, SipTransaction transaction, SipCore core, SipRequest clientRequest, SipResult serverResult) { this.Dialog = dialog; this.Transaction = transaction; this.Core = core; this.ClientRequest = clientRequest; this.ServerResult = serverResult; this.Response = null; }
/// <summary> /// Constuctor. /// </summary> /// <param name="status">The <see cref="SipStatus" />.</param> /// <param name="response">The received <see cref="SipResponse" /> (or <c>null</c>).</param> /// <param name="transaction">The <see cref="SipClientTransaction" />.</param> /// <param name="dialog">The associated <see cref="SipDialog" /> (or <c>null</c>).</param> /// <param name="agent">The <see cref="SipClientAgent" /> that processed the response.</param> /// <param name="core">The <see cref="SipCore" /> that raised the event.</param> internal SipResponseEventArgs(SipStatus status, SipResponse response, SipClientTransaction transaction, SipDialog dialog, SipClientAgent agent, SipCore core) { this.Status = status; this.Response = response; this.Transaction = transaction; this.Dialog = dialog; this.Agent = agent; this.Core = core; }
/// <summary> /// Constuctor. /// </summary> /// <param name="request">The received <see cref="SipRequest" />.</param> /// <param name="transaction">The associated <see cref="SipServerTransaction" />.</param> /// <param name="dialog">The associated <see cref="SipDialog" /> (or <c>null</c>).</param> /// <param name="agent">The <see cref="SipServerAgent" /> that processed the request.</param> /// <param name="core">The <see cref="SipCore" /> that raised the event.</param> /// <param name="inviteRequest">The original INVITE <see cref="SipRequest" />.</param> internal SipRequestEventArgs(SipRequest request, SipServerTransaction transaction, SipDialog dialog, SipServerAgent agent, SipCore core, SipRequest inviteRequest) { this.Request = request; this.Transaction = transaction; this.Dialog = dialog; this.Agent = agent; this.Core = core; this.InviteRequest = inviteRequest; }
/// <summary> /// Called when an INVITE transaction completes. /// </summary> /// <param name="transaction">The source <see cref="SipClientTransaction" />.</param> /// <param name="status">The completion status.</param> /// <param name="response">The final response (or <c>null</c>).</param> /// <remarks> /// <para> /// The <paramref name="response"/> parameter will be passed as <c>null</c> if /// the transaction was completed without receiving a final message (such /// as a timeout). In this case, the agent should look to the <paramref name="status"/> /// property for the final disposition of the transaction. /// </para> /// <para> /// This method also handles the resubmission of the request with additional /// authentication information if necessary. /// </para> /// <para> /// The method may create a custom ACK <see cref="SipResponse" /> to be delivered /// back to the server by saving the response in the <paramref name="response"/> parameter. /// Otherwise, if this value is left as <c>null</c>, the client transaction will /// generate a default ACK response and send it. /// </para> /// </remarks> internal void OnInviteComplete(SipClientTransaction transaction, SipStatus status, SipResponse response) { var arClient = (ClientAsyncResult)transaction.AgentState; var args = new SipResponseEventArgs(status, response, transaction, arClient.Dialog, this, this.core); if (response == null) { // The operation has completed without receiving a final response (probably // due to a time out or some kind of transport related problem). arClient.SipResult = new SipResult(arClient.Request, arClient.Dialog, this, status); arClient.Notify(); core.OnResponseReceived(args); core.OnInviteFailed(args, status); return; } // We have the final response. Compute the dialog ID from the response's // Call-ID, and To/From tags and assign it to the dialog. arClient.Dialog.ID = SipDialog.GetDialogID(response); // Call the core's OnInviteConfirmed() method so it can perform // any dialog specific activities. if (response.IsSuccess) { core.OnInviteConfirmed(args); } else { core.OnInviteFailed(args, status); } // Signal completion of the async operation. arClient.SipResult = new SipResult(arClient.Request, arClient.Dialog, this, response); arClient.Notify(); }
public void Invite_Call_Vitelity() { Assert.Inconclusive("Manual Test: Comment this out to perform this test."); // Attempt an outbound call against the Vitelity.com service SipBasicCore core = null; SipDialog dialog = null; SipCoreSettings settings; SipRequest request; string sdp; try { // These settings are hardcoded for my Vitelity.com account // and my home network. This test also assumes that the router // is forwarding UDP port 5060 packets to the test computer. settings = new SipCoreSettings(); settings.LocalContact = "sip:jslill@" + Dns.GetHostEntry("www.lilltek.com").AddressList.IPv4Only()[0].ToString() + ":5060"; settings.UserName = "******"; settings.Password = "******"; core = new SipBasicCore(settings); core.Start(); //core.StartAutoRegistration("sip:sip4.vitelity.net","sip:[email protected]"); //Assert.IsTrue(core.AutoRegistration); //Assert.IsTrue(core.IsRegistered); // Make a call to my cellphone request = new SipRequest(SipMethod.Invite, "sip:[email protected]", null); request.SetHeader(SipHeader.To, new SipContactValue("sip:[email protected]")); request.SetHeader(SipHeader.From, new SipContactValue("sip:[email protected]")); request.SetHeader(SipHeader.ContentType, SipHelper.SdpMimeType); sdp = @"v=0 o=- 0 2 IN IP4 192.168.1.200 s=LillTek SIP c=IN IP4 192.168.1.200 t=0 0 m=audio 29318 RTP/AVP 107 119 100 106 0 105 98 8 101 a=alt:1 1 : AEnD+akt rmmTsDRh 192.168.1.200 29318 a=fmtp:101 0-15 a=rtpmap:107 BV32/16000 a=rtpmap:119 BV32-FEC/16000 a=rtpmap:100 SPEEX/16000 a=rtpmap:106 SPEEX-FEC/16000 a=rtpmap:105 SPEEX-FEC/8000 a=rtpmap:98 iLBC/8000 a=rtpmap:101 telephone-event/8000 a=sendrecv "; request.Contents = Helper.ToUTF8(sdp); dialog = core.CreateDialog(request, (SipContactValue)settings.LocalContact, null); Thread.Sleep(30000); // Wait 30 seconds to monitor the packets via NetMon //core.StopAutoRegistration(); } finally { if (core != null) { core.Stop(); } } }
/// <summary> /// Executes a synchronous SIP request transaction. /// </summary> /// <param name="request">The <see cref="SipRequest" /> to be submitted.</param> /// <param name="dialog">The <see cref="SipDialog" /> for requests that initiate a dialog (or <c>null</c>).</param> /// <returns>The <see cref="SipResult" /> detailing the result of the operation.</returns> /// <remarks> /// <note> /// This method adds reasonable <b>Call-ID</b> and <b>CSeq</b> headers to the request if these /// headers are not already present. /// </note> /// </remarks> public SipResult Request(SipRequest request, SipDialog dialog) { var ar = BeginRequest(request, dialog, null, null); return(EndRequest(ar)); }
/// <summary> /// Initiates an asynchronous SIP request transaction. /// </summary> /// <param name="request">The <see cref="SipRequest" /> to be submitted.</param> /// <param name="dialog">The <see cref="SipDialog" /> for requests that initiate a dialog (or <c>null</c>).</param> /// <param name="callback">The delegate to be called when the operation completes (or <c>null</c>).</param> /// <param name="state">Application defined state (or <c>null</c>).</param> /// <returns>The <see cref="IAsyncResult" /> to be used to track the operation's progress.</returns> /// <remarks> /// <para> /// All requests to <see cref="BeginRequest(SipRequest,SipDialog,AsyncCallback,object)" /> must be matched with a /// call to <see cref="EndRequest" />. /// </para> /// <note> /// This method adds reasonable <b>Call-ID</b> and <b>CSeq</b> headers to the request if these /// headers are not already present. /// </note> /// </remarks> public IAsyncResult BeginRequest(SipRequest request, SipDialog dialog, AsyncCallback callback, object state) { ClientAsyncResult arClient = new ClientAsyncResult(request, dialog, callback, state); SipValue viaValue; SipCSeqValue vCSeq; string transactionID; SipClientTransaction transaction; ISipTransport transport; NetworkBinding remoteEP; if (dialog != null && request.Method != SipMethod.Invite) { throw new InvalidOperationException("Dialogs may be created only for INVITE requests."); } arClient.Dialog = dialog; transport = router.SelectTransport(this, request, out remoteEP); if (transport == null) { throw new SipException("No approriate transport is available."); } // Initialize the request's Via header and transaction ID as necessary. transactionID = SipHelper.GenerateBranchID(); viaValue = new SipValue(string.Format("SIP/2.0/{0} {1}", transport.Name, transport.Settings.ExternalBinding.Address)); viaValue["branch"] = transactionID; viaValue["rport"] = string.Empty; request.PrependHeader(SipHeader.Via, viaValue); // Initialize common headers as necessary if (!request.ContainsHeader(SipHeader.CallID)) { request.AddHeader(SipHeader.CallID, SipHelper.GenerateCallID()); } vCSeq = request.GetHeader <SipCSeqValue>(SipHeader.CSeq); if (vCSeq == null) { vCSeq = new SipCSeqValue(SipHelper.GenCSeq(), request.MethodText); request.AddHeader(SipHeader.CSeq, vCSeq); } // Initialize the transaction transaction = new SipClientTransaction(this, request, transactionID, transport, remoteEP); transaction.AgentState = arClient; // Handle initial dialog INVITE specific initialization if (dialog != null && request.Method == SipMethod.Invite && dialog.State == SipDialogState.Waiting) { // Client-side dialogs need to know the transaction so // they'll be able to send the confirming ACK. dialog.InitiatingTransaction = transaction; // Dialogs need to know about the sequence number used in INVITE requests so // that the ACK can be generated with the same sequence number. dialog.AckCSeq = vCSeq.Number; // The dialog has been intialized enough to be added to the core's // early dialog table. core.AddEarlyDialog(dialog); } // Start the transaction using (TimedLock.Lock(this)) { transactions.Add(transactionID, transaction); } transaction.Start(); arClient.Started(); return(arClient); }