/// <summary> /// Gets existing or creates new dialog. /// </summary> /// <param name="transaction">Owner transaction what forces to create dialog.</param> /// <param name="response">Response what forces to create dialog.</param> /// <returns>Returns dialog.</returns> /// <exception cref="ArgumentNullException">Is raised when <b>transaction</b> or <b>response</b> is null.</exception> public SIP_Dialog GetOrCreateDialog(SIP_Transaction transaction, SIP_Response response) { if (transaction == null) { throw new ArgumentNullException("transaction"); } if (response == null) { throw new ArgumentNullException("response"); } string dialogID = ""; if (transaction is SIP_ServerTransaction) { dialogID = response.CallID + "-" + response.To.Tag + "-" + response.From.Tag; } else { dialogID = response.CallID + "-" + response.From.Tag + "-" + response.To.Tag; } lock (m_pDialogs){ SIP_Dialog dialog = null; m_pDialogs.TryGetValue(dialogID, out dialog); // Dialog doesn't exist, create it. if (dialog == null) { if (response.CSeq.RequestMethod.ToUpper() == SIP_Methods.INVITE) { dialog = new SIP_Dialog_Invite(); dialog.Init(m_pStack, transaction, response); dialog.StateChanged += delegate(object s, EventArgs a){ if (dialog.State == SIP_DialogState.Terminated) { m_pDialogs.Remove(dialog.ID); } }; m_pDialogs.Add(dialog.ID, dialog); } else { throw new ArgumentException("Method '" + response.CSeq.RequestMethod + "' has no dialog handler."); } } return(dialog); } }
/// <summary> /// Cleans up any resources being used. /// </summary> public void Dispose() { lock (m_pLock){ if (m_IsDisposed) { return; } m_IsDisposed = true; m_pDialog.m_pUasInvite2xxRetransmits.Remove(this); if (m_pTimer != null) { m_pTimer.Dispose(); m_pTimer = null; } m_pDialog = null; m_pResponse = null; } }
/// <summary> /// Default constructor. /// </summary> /// <param name="dialog">Owner INVITE dialog.</param> /// <param name="invite">INVITE request which 2xx retransmission to wait.</param> /// <exception cref="ArgumentNullException">Is raised when <b>dialog</b> or <b>invite</b> is null reference.</exception> public UacInvite2xxRetransmissionWaiter(SIP_Dialog_Invite dialog, SIP_Request invite) { if (dialog == null) { throw new ArgumentNullException("dialog"); } if (invite == null) { throw new ArgumentNullException("invite"); } m_pDialog = dialog; m_pInvite = invite; /* RFC 3261 13.2.2.4. * The UAC core considers the INVITE transaction completed 64*T1 seconds * after the reception of the first 2xx response. */ m_pTimer = new TimerEx(64 * SIP_TimerConstants.T1, false); m_pTimer.Elapsed += new System.Timers.ElapsedEventHandler(m_pTimer_Elapsed); m_pTimer.Enabled = true; }
/// <summary> /// Default constructor. /// </summary> /// <param name="dialog">Owner INVITE dialog.</param> /// <param name="response">INVITE 2xx response.</param> /// <exception cref="ArgumentNullException">Is raised when <b>dialog</b> or <b>response</b> is null reference.</exception> public UasInvite2xxRetransmit(SIP_Dialog_Invite dialog, SIP_Response response) { if (dialog == null) { throw new ArgumentNullException("dialog"); } if (response == null) { throw new ArgumentNullException("response"); } m_pDialog = dialog; m_pResponse = response; /* RFC 3261 13.3.1.4. * Once the response has been constructed, it is passed to the INVITE * server transaction. Note, however, that the INVITE server * transaction will be destroyed as soon as it receives this final * response and passes it to the transport. Therefore, it is necessary * to periodically pass the response directly to the transport until the * ACK arrives. The 2xx response is passed to the transport with an * interval that starts at T1 seconds and doubles for each * retransmission until it reaches T2 seconds (T1 and T2 are defined in * Section 17). Response retransmissions cease when an ACK request for * the response is received. This is independent of whatever transport * protocols are used to send the response. * * Since 2xx is retransmitted end-to-end, there may be hops between * UAS and UAC that are UDP. To ensure reliable delivery across * these hops, the response is retransmitted periodically even if the * transport at the UAS is reliable. */ m_pTimer = new TimerEx(SIP_TimerConstants.T1, false); m_pTimer.Elapsed += new System.Timers.ElapsedEventHandler(m_pTimer_Elapsed); m_pTimer.Enabled = true; }
/// <summary> /// Initializes call from Calling state to active.. /// </summary> /// <param name="dialog">SIP dialog.</param> /// <param name="localSDP">Local SDP.</param> /// <exception cref="ArgumentNullException">Is raised when <b>dialog</b> or <b>localSDP</b> is null reference.</exception> internal void InitCalling(SIP_Dialog dialog, SDP_Message localSDP) { if (dialog == null) { throw new ArgumentNullException("dialog"); } if (localSDP == null) { throw new ArgumentNullException("localSDP"); } m_pDialog = (SIP_Dialog_Invite)dialog; m_pFlow = dialog.Flow; m_pLocalSDP = localSDP; m_StartTime = DateTime.Now; dialog.StateChanged += new EventHandler(m_pDialog_StateChanged); SetState(SIP_CallState.Active); // Start ping timer. m_pKeepAliveTimer = new TimerEx(40000); m_pKeepAliveTimer.Elapsed += new System.Timers.ElapsedEventHandler(m_pKeepAliveTimer_Elapsed); m_pKeepAliveTimer.Enabled = true; }
/// <summary> /// Cleans up any resource being used. /// </summary> public void Dispose() { lock (m_pLock) { if (this.State == SIP_CallState.Disposed) { return; } SetState(SIP_CallState.Disposed); // TODO: Clean up m_pStack = null; m_pLocalSDP = null; if (m_pDialog != null) { m_pDialog.Dispose(); m_pDialog = null; } m_pFlow = null; if (m_pKeepAliveTimer != null) { m_pKeepAliveTimer.Dispose(); m_pKeepAliveTimer = null; } this.StateChanged = null; } }
/// <summary> /// Incoming call constructor. /// </summary> /// <param name="stack">Reference to SIP stack.</param> /// <param name="dialog">Reference SIP dialog.</param> /// <param name="session">Call RTP multimedia session.</param> /// <param name="localSDP">Local SDP.</param> /// <exception cref="ArgumentNullException">Is raised when <b>stack</b>,<b>dialog</b>,<b>session</b> or <b>localSDP</b> is null reference.</exception> internal SIP_Call(SIP_Stack stack, SIP_Dialog dialog, RTP_MultimediaSession session, SDP_Message localSDP) { if (stack == null) { throw new ArgumentNullException("stack"); } if (dialog == null) { throw new ArgumentNullException("dialog"); } if (session == null) { throw new ArgumentNullException("session"); } if (localSDP == null) { throw new ArgumentNullException("localSDP"); } m_pStack = stack; m_pDialog = (SIP_Dialog_Invite)dialog; m_pRtpMultimediaSession = session; m_pLocalSDP = localSDP; m_StartTime = DateTime.Now; m_pFlow = dialog.Flow; dialog.StateChanged += new EventHandler(m_pDialog_StateChanged); SetState(SIP_CallState.Active); // Start ping timer. m_pKeepAliveTimer = new TimerEx(40000); m_pKeepAliveTimer.Elapsed += new System.Timers.ElapsedEventHandler(m_pKeepAliveTimer_Elapsed); m_pKeepAliveTimer.Enabled = true; }
/// <summary> /// Gets existing or creates new dialog. /// </summary> /// <param name="transaction">Owner transaction what forces to create dialog.</param> /// <param name="response">Response what forces to create dialog.</param> /// <returns>Returns dialog.</returns> /// <exception cref="ArgumentNullException">Is raised when <b>transaction</b> or <b>response</b> is null.</exception> public SIP_Dialog GetOrCreateDialog(SIP_Transaction transaction,SIP_Response response) { if(transaction == null){ throw new ArgumentNullException("transaction"); } if(response == null){ throw new ArgumentNullException("response"); } string dialogID = ""; if(transaction is SIP_ServerTransaction){ dialogID = response.CallID + "-" + response.To.Tag + "-" + response.From.Tag; } else{ dialogID = response.CallID + "-" + response.From.Tag + "-" + response.To.Tag; } lock(m_pDialogs){ SIP_Dialog dialog = null; m_pDialogs.TryGetValue(dialogID,out dialog); // Dialog doesn't exist, create it. if(dialog == null){ if(response.CSeq.RequestMethod.ToUpper() == SIP_Methods.INVITE){ dialog = new SIP_Dialog_Invite(); dialog.Init(m_pStack,transaction,response); dialog.StateChanged += delegate(object s,EventArgs a){ if(dialog.State == SIP_DialogState.Terminated){ m_pDialogs.Remove(dialog.ID); } }; m_pDialogs.Add(dialog.ID,dialog); } else{ throw new ArgumentException("Method '" + response.CSeq.RequestMethod + "' has no dialog handler."); } } return dialog; } }