Exemplo n.º 1
0
        /// <summary>
        /// This method is called when new request is received.
        /// </summary>
        /// <param name="e">Request event arguments.</param>
        private void OnRequestReceived(SIP_RequestReceivedEventArgs e)
        {
            SIP_Request request = e.Request;

            try{
                #region Statefull

                // Statefull
                if ((m_ProxyMode & SIP_ProxyMode.Statefull) != 0)
                {
                    // Statefull proxy is transaction statefull proxy only,
                    // what don't create dialogs and keep dialog state.

                    /* RFC 3261 16.10.
                     *  StateFull proxy:
                     *          If a matching response context is found, the element MUST
                     *          immediately return a 200 (OK) response to the CANCEL request.
                     *
                     *          If a response context is not found, the element does not have any
                     *          knowledge of the request to apply the CANCEL to.  It MUST statelessly
                     *          forward the CANCEL request (it may have statelessly forwarded the
                     *          associated request previously).
                     */
                    if (e.Request.RequestLine.Method == SIP_Methods.CANCEL)
                    {
                        // Don't do server transaction before we get CANCEL matching transaction.
                        SIP_ServerTransaction trToCancel = m_pStack.TransactionLayer.MatchCancelToTransaction(e.Request);
                        if (trToCancel != null)
                        {
                            trToCancel.Cancel();
                            e.ServerTransaction.SendResponse(m_pStack.CreateResponse(SIP_ResponseCodes.x200_Ok, request));
                        }
                        else
                        {
                            ForwardRequest(false, e, true);
                        }
                    }
                    // ACK never creates transaction, it's always passed directly to transport layer.
                    else if (e.Request.RequestLine.Method == SIP_Methods.ACK)
                    {
                        ForwardRequest(false, e, true);
                    }
                    else
                    {
                        ForwardRequest(true, e, true);
                    }
                }

                #endregion

                #region B2BUA

                // B2BUA
                else if ((m_ProxyMode & SIP_ProxyMode.B2BUA) != 0)
                {
                    m_pB2BUA.OnRequestReceived(e);
                }

                #endregion

                #region Stateless

                // Stateless
                else if ((m_ProxyMode & SIP_ProxyMode.Stateless) != 0)
                {
                    // Stateless proxy don't do transaction, just forwards all.
                    ForwardRequest(false, e, true);
                }

                #endregion

                #region Proxy won't accept command

                else
                {
                    e.ServerTransaction.SendResponse(m_pStack.CreateResponse(SIP_ResponseCodes.x501_Not_Implemented, request));
                }

                #endregion
            }
            catch (Exception x) {
                try{
                    m_pStack.TransportLayer.SendResponse(m_pStack.CreateResponse(SIP_ResponseCodes.x500_Server_Internal_Error + ": " + x.Message, e.Request));
                }
                catch {
                    // Skip transport layer exception if send fails.
                }

                // Don't raise OnError for transport errors.
                if (!(x is SIP_TransportException))
                {
                    m_pStack.OnError(x);
                }
            }
        }
Exemplo n.º 2
0
        /// <summary>
        /// This method is called when SIP stack received new message.
        /// </summary>
        /// <param name="sender">Sender.</param>
        /// <param name="e">Event data.</param>
        private void m_pStack_RequestReceived(object sender, SIP_RequestReceivedEventArgs e)
        {
            // TODO: Performance: rise events on thread pool or see if this method called on pool aready, then we may not keep lock for events ?

            if (e.Request.RequestLine.Method == SIP_Methods.CANCEL)
            {
                /* RFC 3261 9.2.
                 *  If the UAS did not find a matching transaction for the CANCEL
                 *  according to the procedure above, it SHOULD respond to the CANCEL
                 *  with a 481 (Call Leg/Transaction Does Not Exist).
                 *
                 *  Regardless of the method of the original request, as long as the
                 *  CANCEL matched an existing transaction, the UAS answers the CANCEL
                 *  request itself with a 200 (OK) response.
                 */

                SIP_ServerTransaction trToCancel = m_pStack.TransactionLayer.MatchCancelToTransaction(e.Request);
                if (trToCancel != null)
                {
                    trToCancel.Cancel();
                    e.ServerTransaction.SendResponse(m_pStack.CreateResponse(SIP_ResponseCodes.x200_Ok, e.Request));
                }
                else
                {
                    e.ServerTransaction.SendResponse(m_pStack.CreateResponse(SIP_ResponseCodes.x481_Call_Transaction_Does_Not_Exist, e.Request));
                }
            }
            else if (e.Request.RequestLine.Method == SIP_Methods.BYE)
            {
                /* RFC 3261 15.1.2.
                 *  If the BYE does not match an existing dialog, the UAS core SHOULD generate a 481
                 *  (Call/Transaction Does Not Exist) response and pass that to the server transaction.
                 */
                // TODO:

                SIP_Dialog dialog = m_pStack.TransactionLayer.MatchDialog(e.Request);
                if (dialog != null)
                {
                    e.ServerTransaction.SendResponse(m_pStack.CreateResponse(SIP_ResponseCodes.x200_Ok, e.Request));
                    dialog.Terminate();
                }
                else
                {
                    e.ServerTransaction.SendResponse(m_pStack.CreateResponse(SIP_ResponseCodes.x481_Call_Transaction_Does_Not_Exist, e.Request));
                }
            }
            else if (e.Request.RequestLine.Method == SIP_Methods.INVITE)
            {
                // Supress INVITE retransmissions.
                e.ServerTransaction.SendResponse(m_pStack.CreateResponse(SIP_ResponseCodes.x100_Trying, e.Request));

                // Create call.
                SIP_UA_Call call = new SIP_UA_Call(this, e.ServerTransaction);
                call.StateChanged += new EventHandler(Call_StateChanged);
                m_pCalls.Add(call);

                OnIncomingCall(call);
            }
            else
            {
                OnRequestReceived(e);
            }
        }
Exemplo n.º 3
0
        /// <summary>
        /// This method is called when new request is received.
        /// </summary>
        /// <param name="e">Request event arguments.</param>
        internal void OnRequestReceived(SIP_RequestReceivedEventArgs e)
        {
            SIP_Request request = e.Request;

            if (request.RequestLine.Method == SIP_Methods.CANCEL)
            {
                /* RFC 3261 9.2.
                 *  If the UAS did not find a matching transaction for the CANCEL
                 *  according to the procedure above, it SHOULD respond to the CANCEL
                 *  with a 481 (Call Leg/Transaction Does Not Exist).
                 *
                 *  Regardless of the method of the original request, as long as the
                 *  CANCEL matched an existing transaction, the UAS answers the CANCEL
                 *  request itself with a 200 (OK) response.
                 */

                SIP_ServerTransaction trToCancel = m_pProxy.Stack.TransactionLayer.MatchCancelToTransaction(e.Request);
                if (trToCancel != null)
                {
                    trToCancel.Cancel();
                    //e.ServerTransaction.SendResponse(request.CreateResponse(SIP_ResponseCodes.x200_Ok));
                }
                else
                {
                    //e.ServerTransaction.SendResponse(request.CreateResponse(SIP_ResponseCodes.x481_Call_Transaction_Does_Not_Exist));
                }
            }
            // We never should ge BYE here, because transport layer must match it to dialog.
            else if (request.RequestLine.Method == SIP_Methods.BYE)
            {
                /* RFC 3261 15.1.2.
                 *  If the BYE does not match an existing dialog, the UAS core SHOULD generate a 481
                 *  (Call/Transaction Does Not Exist) response and pass that to the server transaction.
                 */
                //e.ServerTransaction.SendResponse(request.CreateResponse(SIP_ResponseCodes.x481_Call_Transaction_Does_Not_Exist));
            }
            // We never should ge ACK here, because transport layer must match it to dialog.
            else if (request.RequestLine.Method == SIP_Methods.ACK)
            {
                // ACK is response less request, so we may not return error to it.
            }
            // B2BUA must respond to OPTIONS request, not to forward it.
            else if (request.RequestLine.Method == SIP_Methods.OPTIONS)      /*
                                                                              * SIP_Response response = e.Request.CreateResponse(SIP_ResponseCodes.x200_Ok);
                                                                              * // Add Allow to non ACK response.
                                                                              * if(e.Request.RequestLine.Method != SIP_Methods.ACK){
                                                                              * response.Allow.Add("INVITE,ACK,OPTIONS,CANCEL,BYE,PRACK,MESSAGE,UPDATE");
                                                                              * }
                                                                              * // Add Supported to 2xx non ACK response.
                                                                              * if(response.StatusCodeType == SIP_StatusCodeType.Success && e.Request.RequestLine.Method != SIP_Methods.ACK){
                                                                              * response.Supported.Add("100rel,timer");
                                                                              * }
                                                                              * e.ServerTransaction.SendResponse(response);*/
            {
            }
            // We never should get PRACK here, because transport layer must match it to dialog.
            else if (request.RequestLine.Method == SIP_Methods.PRACK)
            {
                //e.ServerTransaction.SendResponse(request.CreateResponse(SIP_ResponseCodes.x481_Call_Transaction_Does_Not_Exist));
            }
            // We never should get UPDATE here, because transport layer must match it to dialog.
            else if (request.RequestLine.Method == SIP_Methods.UPDATE)
            {
                //e.ServerTransaction.SendResponse(request.CreateResponse(SIP_ResponseCodes.x481_Call_Transaction_Does_Not_Exist));
            }
            else
            {
                /* draft-marjou-sipping-b2bua-00 4.1.3.
                 *  When the UAS of the B2BUA receives an upstream SIP request, its
                 *  associated UAC generates a new downstream SIP request with its new
                 *  Via, Max-Forwards, Call-Id, CSeq, and Contact header fields. Route
                 *  header fields of the upstream request are copied in the downstream
                 *  request, except the first Route header if it is under the
                 *  responsibility of the B2BUA.  Record-Route header fields of the
                 *  upstream request are not copied in the new downstream request, as
                 *  Record-Route is only meaningful for the upstream dialog.  The UAC
                 *  SHOULD copy other header fields and body from the upstream request
                 *  into this downstream request before sending it.
                 */

                SIP_Request b2buaRequest = e.Request.Copy();
                b2buaRequest.Via.RemoveAll();
                b2buaRequest.MaxForwards         = 70;
                b2buaRequest.CallID              = SIP_t_CallID.CreateCallID().CallID;
                b2buaRequest.CSeq.SequenceNumber = 1;
                b2buaRequest.Contact.RemoveAll();
                // b2buaRequest.Contact.Add(m_pProxy.CreateContact(b2buaRequest.To.Address).ToStringValue());
                if (b2buaRequest.Route.Count > 0 && m_pProxy.IsLocalRoute(SIP_Uri.Parse(b2buaRequest.Route.GetTopMostValue().Address.Uri.ToString())))
                {
                    b2buaRequest.Route.RemoveTopMostValue();
                }
                b2buaRequest.RecordRoute.RemoveAll();

                // Remove our Authorization header if it's there.
                foreach (SIP_SingleValueHF <SIP_t_Credentials> header in b2buaRequest.ProxyAuthorization.HeaderFields)
                {
                    try{
                        Auth_HttpDigest digest = new Auth_HttpDigest(header.ValueX.AuthData, b2buaRequest.RequestLine.Method);
                        if (m_pProxy.Stack.Realm == digest.Realm)
                        {
                            b2buaRequest.ProxyAuthorization.Remove(header);
                        }
                    }
                    catch {
                        // We don't care errors here. This can happen if remote server xxx auth method here and
                        // we don't know how to parse it, so we leave it as is.
                    }
                }

                //--- Add/replace default fields. ------------------------------------------
                b2buaRequest.Allow.RemoveAll();
                b2buaRequest.Supported.RemoveAll();
                // Accept to non ACK,BYE request.
                if (request.RequestLine.Method != SIP_Methods.ACK && request.RequestLine.Method != SIP_Methods.BYE)
                {
                    b2buaRequest.Allow.Add("INVITE,ACK,OPTIONS,CANCEL,BYE,PRACK");
                }
                // Supported to non ACK request.
                if (request.RequestLine.Method != SIP_Methods.ACK)
                {
                    b2buaRequest.Supported.Add("100rel,timer");
                }
                // Remove Require: header.
                b2buaRequest.Require.RemoveAll();

                // RFC 4028 7.4. For re-INVITE and UPDATE we need to add Session-Expires and Min-SE: headers.
                if (request.RequestLine.Method == SIP_Methods.INVITE || request.RequestLine.Method == SIP_Methods.UPDATE)
                {
                    b2buaRequest.SessionExpires = new SIP_t_SessionExpires(m_pProxy.Stack.SessionExpries, "uac");
                    b2buaRequest.MinSE          = new SIP_t_MinSE(m_pProxy.Stack.MinimumSessionExpries);
                }

                // Forward request.
                //m_pProxy.ForwardRequest(true,e,b2buaRequest,false);
            }
        }
Exemplo n.º 4
0
        /// <summary>
        /// This method is called when new request is received.
        /// </summary>
        /// <param name="e">Request event arguments.</param>
        private void OnRequestReceived(SIP_RequestReceivedEventArgs e)
        {
            /* RFC 3261 16.12. ????????? Forward does all thse steps.
             *  1. The proxy will inspect the Request-URI.  If it indicates a
             *     resource owned by this proxy, the proxy will replace it with
             *     the results of running a location service.  Otherwise, the
             *     proxy will not change the Request-URI.
             *
             *  2. The proxy will inspect the URI in the topmost Route header
             *     field value.  If it indicates this proxy, the proxy removes it
             *     from the Route header field (this route node has been reached).
             *
             *  3. The proxy will forward the request to the resource indicated
             *     by the URI in the topmost Route header field value or in the
             *     Request-URI if no Route header field is present.  The proxy
             *     determines the address, port and transport to use when
             *     forwarding the request by applying the procedures in [4] to that URI.
             */

            SIP_Request request = e.Request;

            try
            {
                #region Registrar

                // Registrar
                if ((m_ProxyMode & SIP_ProxyMode.Registrar) != 0 &&
                    request.RequestLine.Method == SIP_Methods.REGISTER)
                {
                    m_pRegistrar.Register(e);
                }

                #endregion

                #region Presence

                /*
                 * // Presence
                 * else if((m_ProxyMode & SIP_ProxyMode.Presence) != 0 && (request.Method == "SUBSCRIBE" || request.Method == "NOTIFY")){
                 *
                 * }
                 */
                #endregion

                #region Statefull

                // Statefull
                else if ((m_ProxyMode & SIP_ProxyMode.Statefull) != 0)
                {
                    // Statefull proxy is transaction statefull proxy only,
                    // what don't create dialogs and keep dialog state.

                    /* RFC 3261 16.10.
                     *  StateFull proxy:
                     *          If a matching response context is found, the element MUST
                     *          immediately return a 200 (OK) response to the CANCEL request.
                     *
                     *          If a response context is not found, the element does not have any
                     *          knowledge of the request to apply the CANCEL to.  It MUST statelessly
                     *          forward the CANCEL request (it may have statelessly forwarded the
                     *          associated request previously).
                     */
                    if (e.Request.RequestLine.Method == SIP_Methods.CANCEL)
                    {
                        // Don't do server transaction before we get CANCEL matching transaction.
                        SIP_ServerTransaction trToCancel =
                            m_pStack.TransactionLayer.MatchCancelToTransaction(e.Request);
                        if (trToCancel != null)
                        {
                            trToCancel.Cancel();
                            e.ServerTransaction.SendResponse(m_pStack.CreateResponse(
                                                                 SIP_ResponseCodes.x200_Ok, request));
                        }
                        else
                        {
                            ForwardRequest(false, e);
                        }
                    }
                    // ACK never creates transaction, it's always passed directly to transport layer.
                    else if (e.Request.RequestLine.Method == SIP_Methods.ACK)
                    {
                        ForwardRequest(false, e);
                    }
                    else
                    {
                        ForwardRequest(true, e);
                    }
                }

                #endregion

                #region B2BUA

                // B2BUA
                else if ((m_ProxyMode & SIP_ProxyMode.B2BUA) != 0)
                {
                    m_pB2BUA.OnRequestReceived(e);
                }

                #endregion

                #region Stateless

                // Stateless
                else if ((m_ProxyMode & SIP_ProxyMode.Stateless) != 0)
                {
                    // Stateless proxy don't do transaction, just forwards all.
                    ForwardRequest(false, e);
                }

                #endregion

                #region Proxy won't accept command

                else
                {
                    e.ServerTransaction.SendResponse(
                        m_pStack.CreateResponse(SIP_ResponseCodes.x501_Not_Implemented, request));
                }

                #endregion
            }
            catch (Exception x)
            {
                try
                {
                    m_pStack.TransportLayer.SendResponse(
                        m_pStack.CreateResponse(
                            SIP_ResponseCodes.x500_Server_Internal_Error + ": " + x.Message, e.Request));
                }
                catch
                {
                    // Skip transport layer exception if send fails.
                }

                // Don't raise OnError for transport errors.
                if (!(x is SIP_TransportException))
                {
                    m_pStack.OnError(x);
                }
            }
        }