/// <summary> /// This method is called when REGISTER has finished. /// </summary> /// <param name="sender">Sender.</param> /// <param name="e">Event data.</param> private void m_pRegisterSender_ResponseReceived(object sender, SIP_ResponseReceivedEventArgs e) { m_pFlow = e.ClientTransaction.Flow; if (e.Response.StatusCodeType == SIP_StatusCodeType.Success) { SetState(SIP_UA_RegistrationState.Registered); OnRegistered(); m_pFlow.SendKeepAlives = true; } else { SetState(SIP_UA_RegistrationState.Error); OnError(e); } // REMOVE ME: if (this.AutoFixContact && (m_pContact is SIP_Uri)) { // If Via: received or rport paramter won't match to our sent-by, use received and rport to construct new contact value. SIP_Uri cContact = ((SIP_Uri)m_pContact); IPAddress cContactIP = Net_Utils.IsIPAddress(cContact.Host) ? IPAddress.Parse(cContact.Host) : null; SIP_t_ViaParm via = e.Response.Via.GetTopMostValue(); if (via != null && cContactIP != null) { IPEndPoint ep = new IPEndPoint(via.Received != null ? via.Received : cContactIP, via.RPort > 0 ? via.RPort : cContact.Port); if (!cContactIP.Equals(ep.Address) || cContact.Port != via.RPort) { // Unregister old contact. BeginUnregister(false); // Fix contact. cContact.Host = ep.Address.ToString(); cContact.Port = ep.Port; m_pRegisterSender.Dispose(); m_pRegisterSender = null; BeginRegister(m_AutoRefresh); return; } } } if (m_AutoRefresh) { // Set registration refresh timer. m_pTimer.Enabled = true; } m_pRegisterSender.Dispose(); m_pRegisterSender = null; }
/// <summary> /// Default constructor. /// </summary> /// <param name="stack">Owner SIP stack.</param> /// <param name="flow">Transaction data flow.</param> /// <param name="request">SIP request that transaction will handle.</param> /// <exception cref="ArgumentNullException">Is raised when <b>stack</b>,<b>flow</b> or <b>request</b> is null reference.</exception> public SIP_Transaction(SIP_Stack stack, SIP_Flow flow, SIP_Request request) { if (stack == null) { throw new ArgumentNullException("stack"); } if (flow == null) { throw new ArgumentNullException("flow"); } if (request == null) { throw new ArgumentNullException("request"); } m_pStack = stack; m_pFlow = flow; m_pRequest = request; m_Method = request.RequestLine.Method; m_CreateTime = DateTime.Now; m_pResponses = new List <SIP_Response>(); // Validate Via: SIP_t_ViaParm via = request.Via.GetTopMostValue(); if (via == null) { throw new ArgumentException("Via: header is missing !"); } if (via.Branch == null) { throw new ArgumentException("Via: header 'branch' parameter is missing !"); } m_ID = via.Branch; if (this is SIP_ServerTransaction) { /* * We use branch and sent-by as indexing key for transaction, the only special what we need to * do is to handle CANCEL, because it has same branch as transaction to be canceled. * For avoiding key collision, we add branch + '-' + 'sent-by' + CANCEL for cancel index key. * ACK has also same branch, but we won't do transaction for ACK, so it isn't problem. */ string key = request.Via.GetTopMostValue().Branch + '-' + request.Via.GetTopMostValue().SentBy; if (request.RequestLine.Method == SIP_Methods.CANCEL) { key += "-CANCEL"; } m_Key = key; } else { m_Key = m_ID + "-" + request.RequestLine.Method; } }
/// <summary> /// Creates new client transaction. /// </summary> /// <param name="flow">SIP data flow which is used to send request.</param> /// <param name="request">SIP request that transaction will handle.</param> /// <param name="addVia">If true, transaction will add <b>Via:</b> header, otherwise it's user responsibility.</param> /// <exception cref="ObjectDisposedException">Is raised when this class is Disposed and this method is accessed.</exception> /// <exception cref="ArgumentNullException">Is raised when <b>flow</b> or <b>request</b> is null reference.</exception> /// <returns>Returns created transaction.</returns> public SIP_ClientTransaction CreateClientTransaction(SIP_Flow flow, SIP_Request request, bool addVia) { if (m_IsDisposed) { throw new ObjectDisposedException(this.GetType().Name); } if (flow == null) { throw new ArgumentNullException("flow"); } if (request == null) { throw new ArgumentNullException("request"); } // Add Via: if (addVia) { SIP_t_ViaParm via = new SIP_t_ViaParm(); via.ProtocolName = "SIP"; via.ProtocolVersion = "2.0"; via.ProtocolTransport = flow.Transport; via.SentBy = new HostEndPoint("transport_layer_will_replace_it", -1); via.Branch = SIP_t_ViaParm.CreateBranch(); via.RPort = 0; request.Via.AddToTop(via.ToStringValue()); } lock (m_pClientTransactions){ SIP_ClientTransaction transaction = new SIP_ClientTransaction(m_pStack, flow, request); m_pClientTransactions.Add(transaction.Key, transaction); transaction.StateChanged += new EventHandler(delegate(object s, EventArgs e){ if (transaction.State == SIP_TransactionState.Terminated) { lock (m_pClientTransactions){ m_pClientTransactions.Remove(transaction.Key); } } }); SIP_Dialog dialog = MatchDialog(request); if (dialog != null) { dialog.AddTransaction(transaction); } return(transaction); } }
/// <summary> /// Creates new client transaction. /// </summary> /// <param name="flow">SIP data flow which is used to send request.</param> /// <param name="request">SIP request that transaction will handle.</param> /// <param name="addVia">If true, transaction will add <b>Via:</b> header, otherwise it's user responsibility.</param> /// <exception cref="ObjectDisposedException">Is raised when this class is Disposed and this method is accessed.</exception> /// <exception cref="ArgumentNullException">Is raised when <b>flow</b> or <b>request</b> is null reference.</exception> /// <returns>Returns created transaction.</returns> public SIP_ClientTransaction CreateClientTransaction(SIP_Flow flow, SIP_Request request, bool addVia) { if (m_IsDisposed) { throw new ObjectDisposedException(GetType().Name); } if (flow == null) { throw new ArgumentNullException("flow"); } if (request == null) { throw new ArgumentNullException("request"); } // Add Via: if (addVia) { SIP_t_ViaParm via = new SIP_t_ViaParm(); via.ProtocolName = "SIP"; via.ProtocolVersion = "2.0"; via.ProtocolTransport = flow.Transport; via.SentBy = new HostEndPoint("transport_layer_will_replace_it", -1); via.Branch = SIP_t_ViaParm.CreateBranch(); via.RPort = 0; request.Via.AddToTop(via.ToStringValue()); } lock (m_pClientTransactions) { SIP_ClientTransaction transaction = new SIP_ClientTransaction(m_pStack, flow, request); m_pClientTransactions.Add(transaction.Key, transaction); transaction.StateChanged += delegate { if (transaction.State == SIP_TransactionState.Terminated) { lock (m_pClientTransactions) { m_pClientTransactions.Remove(transaction.Key); } } }; return transaction; } }