Пример #1
0
 /// <summary>
 /// This method is called when caller dialog client transaction receives response.
 /// </summary>
 /// <param name="sender">Sender.</param>
 /// <param name="e">Event data.</param>
 private void m_pCaller_ResponseReceived(object sender, SIP_ResponseReceivedEventArgs e)
 {
     SIP_ServerTransaction serverTransaction = (SIP_ServerTransaction)e.ClientTransaction.Tag;
     //SIP_Response response = serverTransaction.Request.CreateResponse(e.Response.StatusCode_ReasonPhrase);
     //CopyMessage(e.Response,response,new string[]{"Via:","Call-Id:","To:","From:","CSeq:","Contact:","Route:","Record-Route:","Allow:","Supported:"});
     //serverTransaction.SendResponse(response);
 }
Пример #2
0
        /// <summary>
        /// This method is called when new response is received.
        /// </summary>
        /// <param name="e">Response event arguments.</param>
        private void OnResponseReceived(SIP_ResponseReceivedEventArgs e)
        {
            if ((m_ProxyMode & SIP_ProxyMode.B2BUA) != 0)
            {
                m_pB2BUA.OnResponseReceived(e);
            }
            else
            {
                /* This method is called when stateless proxy gets response or statefull proxy
                 * has no matching server transaction.
                 */

                /* RFC 3261 16.11.
                 *  When a response arrives at a stateless proxy, the proxy MUST inspect the sent-by
                 *  value in the first (topmost) Via header field value. If that address matches the proxy,
                 *  (it equals a value this proxy has inserted into previous requests) the proxy MUST
                 *  remove that header field value from the response and forward the result to the
                 *  location indicated in the next Via header field value.
                 */
                // Just remove topmost Via:, sent-by check is done in transport layer.
                e.Response.Via.RemoveTopMostValue();

                if ((m_ProxyMode & SIP_ProxyMode.Statefull) != 0)
                {
                    // We should not reach here. This happens when no matching client transaction found.
                    // RFC 3161 18.1.2 orders to forward them statelessly.
                    m_pStack.TransportLayer.SendResponse(e.Response);
                }
                else if ((m_ProxyMode & SIP_ProxyMode.Stateless) != 0)
                {
                    m_pStack.TransportLayer.SendResponse(e.Response);
                }
            }
        }
Пример #3
0
        private void Send_ResponseReceived(object sender, SIP_ResponseReceivedEventArgs e)
        {
            SIP_RequestSender send = sender as SIP_RequestSender;

            if (e.Response.StatusCodeType == SIP_StatusCodeType.Success)
            {
                _aliveCount--;
                send.ResponseReceived -= Send_ResponseReceived;
            }
        }
Пример #4
0
        /// <summary>
        /// This method is called when new response is received.
        /// </summary>
        /// <param name="e">Response event arguments.</param>
        private void OnResponseReceived(SIP_ResponseReceivedEventArgs e)
        {
            if ((m_ProxyMode & SIP_ProxyMode.B2BUA) != 0)
            {
                m_pB2BUA.OnResponseReceived(e);
            }
            else if ((m_ProxyMode & SIP_ProxyMode.Statefull) != 0)
            {
                /* RFC 6026 7.3. Proxy Considerations.
                 *  This document changes the behavior of transaction-stateful proxies to
                 *  not forward stray INVITE responses.  When receiving any SIP response,
                 *  a transaction-stateful proxy MUST compare the transaction identifier
                 *  in that response against its existing transaction state machines.
                 *  The proxy MUST NOT forward the response if there is no matching
                 *  transaction state machine.
                 */
            }
            else
            {
                /* This method is called when stateless proxy gets response.
                 */

                /* RFC 3261 16.11.
                 *  When a response arrives at a stateless proxy, the proxy MUST inspect the sent-by
                 *  value in the first (topmost) Via header field value. If that address matches the proxy,
                 *  (it equals a value this proxy has inserted into previous requests) the proxy MUST
                 *  remove that header field value from the response and forward the result to the
                 *  location indicated in the next Via header field value.
                 */
                // Just remove topmost Via:, sent-by check is done in transport layer.
                e.Response.Via.RemoveTopMostValue();

                if ((m_ProxyMode & SIP_ProxyMode.Statefull) != 0)
                {
                    // We should not reach here. This happens when no matching client transaction found.
                    // RFC 3161 18.1.2 orders to forward them statelessly.
                    m_pStack.TransportLayer.SendResponse(e.Response);
                }
                else if ((m_ProxyMode & SIP_ProxyMode.Stateless) != 0)
                {
                    m_pStack.TransportLayer.SendResponse(e.Response);
                }
            }
        }
Пример #5
0
 /// <summary>
 /// This method is called when SIP stack receives new response.
 /// </summary>
 /// <param name="sender">Sender.</param>
 /// <param name="e">Event data.</param>
 private void m_pStack_ResponseReceived(object sender, SIP_ResponseReceivedEventArgs e)
 {
     OnResponseReceived(e);
 }
Пример #6
0
 /// <summary>
 /// This method is called when new response is received.
 /// </summary>
 /// <param name="e">Response event arguments.</param>
 internal void OnResponseReceived(SIP_ResponseReceivedEventArgs e)
 {
     // If we get response here, that means we have stray response, just do nothing.
     // All reponses must match to transactions, so we never should reach here.
 }
Пример #7
0
        /// <summary>
        /// This method is called when initial INVITE sender got response.
        /// </summary>
        /// <param name="sender">Sender.</param>
        /// <param name="e">Event data.</param>
        private void m_pInitialInviteSender_ResponseReceived(object sender, SIP_ResponseReceivedEventArgs e)
        {
            try{
                lock (m_pLock){
                    // If remote party provided SDP, parse it.
                    if (e.Response.ContentType != null && e.Response.ContentType.ToLower().IndexOf("application/sdp") > -1)
                    {
                        m_pRemoteSDP = SDP_Message.Parse(Encoding.UTF8.GetString(e.Response.Data));

                        // TODO: If parsing failed, end call.
                    }

                    if (e.Response.StatusCodeType == SIP_StatusCodeType.Provisional)
                    {
                        if (e.Response.StatusCode == 180)
                        {
                            SetState(SIP_UA_CallState.Ringing);
                        }
                        else if (e.Response.StatusCode == 182)
                        {
                            SetState(SIP_UA_CallState.Queued);
                        }
                        // We don't care other status responses.

                        /* RFC 3261 13.2.2.1.
                         *  Zero, one or multiple provisional responses may arrive before one or
                         *  more final responses are received.  Provisional responses for an
                         *  INVITE request can create "early dialogs".  If a provisional response
                         *  has a tag in the To field, and if the dialog ID of the response does
                         *  not match an existing dialog, one is constructed using the procedures
                         *  defined in Section 12.1.2.
                         */
                        if (e.Response.StatusCode > 100 && e.Response.To.Tag != null)
                        {
                            m_pEarlyDialogs.Add((SIP_Dialog_Invite)m_pUA.Stack.TransactionLayer.GetOrCreateDialog(e.ClientTransaction, e.Response));
                        }
                    }
                    else if (e.Response.StatusCodeType == SIP_StatusCodeType.Success)
                    {
                        m_StartTime = DateTime.Now;
                        SetState(SIP_UA_CallState.Active);

                        m_pDialog = m_pUA.Stack.TransactionLayer.GetOrCreateDialog(e.ClientTransaction, e.Response);
                        m_pDialog.StateChanged += new EventHandler(m_pDialog_StateChanged);

                        /* Exit all all other dialogs created by this call (due to forking).
                         * That is not defined in RFC but, since UAC can send BYE to early and confirmed dialogs,
                         * because of this all 100% valid.
                         */
                        foreach (SIP_Dialog_Invite dialog in m_pEarlyDialogs.ToArray())
                        {
                            if (!m_pDialog.Equals(dialog))
                            {
                                dialog.Terminate("Another forking leg accepted.", true);
                            }
                        }
                    }
                    else
                    {
                        /* RFC 3261 13.2.2.3.
                         *  All early dialogs are considered terminated upon reception of the non-2xx final response.
                         */
                        foreach (SIP_Dialog_Invite dialog in m_pEarlyDialogs.ToArray())
                        {
                            dialog.Terminate("All early dialogs are considered terminated upon reception of the non-2xx final response. (RFC 3261 13.2.2.3)", false);
                        }
                        m_pEarlyDialogs.Clear();

                        Error();

                        SetState(SIP_UA_CallState.Terminated);
                    }
                }
            }
            catch (Exception x) {
                m_pUA.Stack.OnError(x);
            }
        }
Пример #8
0
 /// <summary>
 /// This method is called when new response is received.
 /// </summary>
 /// <param name="e">Response event arguments.</param>
 internal void OnResponseReceived(SIP_ResponseReceivedEventArgs e)
 {
     // If we get response here, that means we have stray response, just do nothing.
     // All reponses must match to transactions, so we never should reach here.
 }
Пример #9
0
 /// <summary>
 /// This method is called when caller dialog client transaction receives response.
 /// </summary>
 /// <param name="sender">Sender.</param>
 /// <param name="e">Event data.</param>
 private void m_pCaller_ResponseReceived(object sender, SIP_ResponseReceivedEventArgs e)
 {
     SIP_ServerTransaction serverTransaction = (SIP_ServerTransaction) e.ClientTransaction.Tag;
     //SIP_Response response = serverTransaction.Request.CreateResponse(e.Response.StatusCode_ReasonPhrase);
     //CopyMessage(e.Response,response,new string[]{"Via:","Call-Id:","To:","From:","CSeq:","Contact:","Route:","Record-Route:","Allow:","Supported:"});
     //serverTransaction.SendResponse(response);
 }
Пример #10
0
        /// <summary>
        /// This method is called when new response is received.
        /// </summary>
        /// <param name="e">Response event arguments.</param>
        private void OnResponseReceived(SIP_ResponseReceivedEventArgs e)
        {
            if ((m_ProxyMode & SIP_ProxyMode.B2BUA) != 0)
            {
                m_pB2BUA.OnResponseReceived(e);
            }
            else
            {
                /* This method is called when stateless proxy gets response or statefull proxy
                   has no matching server transaction.
                */

                /* RFC 3261 16.11.
                    When a response arrives at a stateless proxy, the proxy MUST inspect the sent-by 
                    value in the first (topmost) Via header field value. If that address matches the proxy,
                    (it equals a value this proxy has inserted into previous requests) the proxy MUST 
                    remove that header field value from the response and forward the result to the 
                    location indicated in the next Via header field value.
                */
                // Just remove topmost Via:, sent-by check is done in transport layer.
                e.Response.Via.RemoveTopMostValue();

                if ((m_ProxyMode & SIP_ProxyMode.Statefull) != 0)
                {
                    // We should not reach here. This happens when no matching client transaction found.
                    // RFC 3161 18.1.2 orders to forward them statelessly.
                    m_pStack.TransportLayer.SendResponse(e.Response);
                }
                else if ((m_ProxyMode & SIP_ProxyMode.Stateless) != 0)
                {
                    m_pStack.TransportLayer.SendResponse(e.Response);
                }
            }
        }
Пример #11
0
 /// <summary>
 /// This method is called when SIP stack receives new response.
 /// </summary>
 /// <param name="sender">Sender.</param>
 /// <param name="e">Event data.</param>
 private void m_pStack_ResponseReceived(object sender, SIP_ResponseReceivedEventArgs e)
 {
     OnResponseReceived(e);
 }
Пример #12
0
        /// <summary>
        /// This method is called when initial INVITE sender got response.
        /// </summary>
        /// <param name="sender">Sender.</param>
        /// <param name="e">Event data.</param>
        private void m_pInitialInviteSender_ResponseReceived(object sender, SIP_ResponseReceivedEventArgs e)
        {
            lock (m_pLock)
            {
                // If remote party provided SDP, parse it.               
                if (e.Response.ContentType != null &&
                    e.Response.ContentType.ToLower().IndexOf("application/sdp") > -1)
                {
                    m_pRemoteSDP = SDP_Message.Parse(Encoding.UTF8.GetString(e.Response.Data));

                    // TODO: If parsing failed, end call.
                }

                if (e.Response.StatusCodeType == SIP_StatusCodeType.Provisional)
                {
                    if (e.Response.StatusCode == 180)
                    {
                        SetState(SIP_UA_CallState.Ringing);
                    }
                    else if (e.Response.StatusCode == 182)
                    {
                        SetState(SIP_UA_CallState.Queued);
                    }
                    // We don't care other status responses.

                    /* RFC 3261 13.2.2.1.
                        Zero, one or multiple provisional responses may arrive before one or
                        more final responses are received.  Provisional responses for an
                        INVITE request can create "early dialogs".  If a provisional response
                        has a tag in the To field, and if the dialog ID of the response does
                        not match an existing dialog, one is constructed using the procedures
                        defined in Section 12.1.2.
                    */
                    if (e.Response.StatusCode > 100 && e.Response.To.Tag != null)
                    {
                        m_pEarlyDialogs.Add(m_pUA.Stack.TransactionLayer.GetOrCreateDialog(
                                                e.ClientTransaction, e.Response));
                    }
                }
                else if (e.Response.StatusCodeType == SIP_StatusCodeType.Success)
                {
                    m_StartTime = DateTime.Now;
                    SetState(SIP_UA_CallState.Active);

                    m_pDialog = m_pUA.Stack.TransactionLayer.GetOrCreateDialog(e.ClientTransaction, e.Response);
                    m_pDialog.StateChanged += m_pDialog_StateChanged;

                    /* Exit all all other dialogs created by this call (due to forking).
                       That is not defined in RFC but, since UAC can send BYE to early and confirmed dialogs, 
                       because of this all 100% valid.
                    */
                    foreach (SIP_Dialog dialog in m_pEarlyDialogs.ToArray())
                    {
                        if (!m_pDialog.Equals(dialog))
                        {
                            dialog.Terminate("Another forking leg accepted.", true);
                        }
                    }
                }
                else
                {
                    /* RFC 3261 13.2.2.3.
                        All early dialogs are considered terminated upon reception of the non-2xx final response.
                    */
                    foreach (SIP_Dialog dialog in m_pEarlyDialogs.ToArray())
                    {
                        dialog.Terminate(
                            "All early dialogs are considered terminated upon reception of the non-2xx final response. (RFC 3261 13.2.2.3)",
                            false);
                    }
                    m_pEarlyDialogs.Clear();

                    Error();

                    SetState(SIP_UA_CallState.Terminated);
                }
            }
        }
Пример #13
0
            /// <summary>
            /// Is called when client transactions receives response.
            /// </summary>
            /// <param name="sender">Sender.</param>
            /// <param name="e">Event data.</param>
            private void ClientTransaction_ResponseReceived(object sender, SIP_ResponseReceivedEventArgs e)
            {
                lock (m_pLock)
                {
                    m_HasReceivedResponse = true;

                    /* RFC 3261 16.7 Response Processing.
                        1.  Find the appropriate response context
                        2.  Update timer C for provisional responses
                 
                        Steps 3 - 10 done in ProxyContext.ProcessResponse method.
                    */

                    #region 1. Find Context

                    // Done, m_pOwner is it.

                    #endregion

                    #region 2. Update timer C for provisional responses

                    /* For an INVITE transaction, if the response is a provisional
                       response with status codes 101 to 199 inclusive (i.e., anything
                       but 100), the proxy MUST reset timer C for that client
                       transaction.  The timer MAY be reset to a different value, but
                       this value MUST be greater than 3 minutes.
                    */
                    if (m_pTimerC != null && e.Response.StatusCode >= 101 && e.Response.StatusCode <= 199)
                    {
                        m_pTimerC.Interval = 3*60*1000;
                    }

                    #endregion

                    /*
                    // If 401 or 407 (Authentication required), see i we have specified realm(s) credentials, 
                    // if so try to authenticate.
                    if(e.Response.StatusCode == 401 || e.Response.StatusCode == 407){
                        SIP_t_Challenge[] challanges = null;
                        if(e.Response.StatusCode == 401){
                            challanges = e.Response.WWWAuthenticate.GetAllValues();
                        }
                        else{
                            challanges = e.Response.ProxyAuthenticate.GetAllValues();
                        }

                        // TODO: Porbably we need to auth only if we can provide authentication data to all realms ?

                        SIP_Request request = m_pServerTransaction.Request.Copy();
                        request.CSeq.SequenceNumber++;
                        bool hasAny = false;
                        foreach(SIP_t_Challenge challange in challanges){
                            Auth_HttpDigest authDigest = new Auth_HttpDigest(challange.AuthData,m_pServerTransaction.Request.Method);
                            NetworkCredential credential = GetCredential(authDigest.Realm);
                            if(credential != null){
                                // Don't authenticate again, if we tried already once and failed.
                                // FIX ME: if user passed authorization, then works wrong.
                                if(e.ClientTransaction.Request.Authorization.Count == 0 && e.ClientTransaction.Request.ProxyAuthorization.Count == 0){
                                    authDigest.RequestMethod = m_pServerTransaction.Request.Method;
                                    authDigest.Uri           = e.ClientTransaction.Request.Uri;
                                    authDigest.Realm         = credential.Domain;
                                    authDigest.UserName      = credential.UserName;
                                    authDigest.Password      = credential.Password;
                                    authDigest.CNonce        = Auth_HttpDigest.CreateNonce();
                                    authDigest.Qop           = authDigest.Qop;
                                    authDigest.Opaque        = authDigest.Opaque;
                                    authDigest.Algorithm     = authDigest.Algorithm;
                                    if(e.Response.StatusCode == 401){
                                        request.Authorization.Add(authDigest.ToAuthorization());
                                    }
                                    else{
                                        request.ProxyAuthorization.Add(authDigest.ToAuthorization());
                                    }
                                    hasAny = true;
                                }
                            }
                        }
                        if(hasAny){
                            // CreateClientTransaction((SIP_Target)e.ClientTransaction.Tag,request);
                            return;
                        }
                    }*/

                    if (e.Response.StatusCodeType != SIP_StatusCodeType.Provisional)
                    {
                        m_IsCompleted = true;
                    }

                    m_pOwner.ProcessResponse(this, m_pTransaction, e.Response);
                }
            }