/// <summary>
        /// Processes specified request through this dialog.
        /// </summary>
        /// <param name="e">Method arguments.</param>
        /// <returns>Returns true if this dialog processed specified request, otherwise false.</returns>
        /// <exception cref="ArgumentNullException">Is raised when <b>e</b> is null reference.</exception>
        protected internal override bool ProcessRequest(SIP_RequestReceivedEventArgs e)
        {
            if (e == null)
            {
                throw new ArgumentNullException("e");
            }

            if (base.ProcessRequest(e))
            {
                return true;
            }

            // We must support: INVITE(re-invite),UPDATE,ACK,  [BYE will be handled by base class]

            #region INVITE

            if (e.Request.RequestLine.Method == SIP_Methods.INVITE)
            {
                /* RFC 3261 14.2.
                    A UAS that receives a second INVITE before it sends the final
                    response to a first INVITE with a lower CSeq sequence number on the
                    same dialog MUST return a 500 (Server Internal Error) response to the
                    second INVITE and MUST include a Retry-After header field with a
                    randomly chosen value of between 0 and 10 seconds.

                    A UAS that receives an INVITE on a dialog while an INVITE it had sent
                    on that dialog is in progress MUST return a 491 (Request Pending)
                    response to the received INVITE.
                */

                if (m_pActiveInvite != null && m_pActiveInvite is SIP_ServerTransaction &&
                    (m_pActiveInvite).Request.CSeq.SequenceNumber < e.Request.CSeq.SequenceNumber)
                {
                    SIP_Response response =
                        Stack.CreateResponse(
                            SIP_ResponseCodes.x500_Server_Internal_Error +
                            ": INVITE with a lower CSeq is pending(RFC 3261 14.2).",
                            e.Request);
                    response.RetryAfter = new SIP_t_RetryAfter("10");
                    e.ServerTransaction.SendResponse(response);

                    return true;
                }
                if (m_pActiveInvite != null && m_pActiveInvite is SIP_ClientTransaction)
                {
                    e.ServerTransaction.SendResponse(
                        Stack.CreateResponse(SIP_ResponseCodes.x491_Request_Pending, e.Request));

                    return true;
                }

                // Force server transaction creation and set it as active INVITE transaction.
                m_pActiveInvite = e.ServerTransaction;
                m_pActiveInvite.StateChanged += delegate
                                                    {
                                                        if (m_pActiveInvite.State ==
                                                            SIP_TransactionState.Terminated)
                                                        {
                                                            m_pActiveInvite = null;
                                                        }
                                                    };
                // Once we send 2xx response, we need to retransmit it while get ACK or timeout. (RFC 3261 13.3.1.4.)
                ((SIP_ServerTransaction) m_pActiveInvite).ResponseSent +=
                    delegate(object s, SIP_ResponseSentEventArgs a)
                        {
                            if (a.Response.StatusCodeType == SIP_StatusCodeType.Success)
                            {
                                m_pUasInvite2xxRetransmits.Add(new UasInvite2xxRetransmit(this, a.Response));
                            }
                        };

                OnReinvite(((SIP_ServerTransaction) m_pActiveInvite));

                return true;
            }

                #endregion

                #region ACK

            else if (e.Request.RequestLine.Method == SIP_Methods.ACK)
            {
                // Search corresponding INVITE 2xx retransmit entry and dispose it.
                foreach (UasInvite2xxRetransmit t in m_pUasInvite2xxRetransmits)
                {
                    if (t.MatchAck(e.Request))
                    {
                        t.Dispose();
                        if (State == SIP_DialogState.Early)
                        {
                            SetState(SIP_DialogState.Confirmed, true);

                            // TODO: If Terminating
                        }

                        return true;
                    }
                }

                return false;
            }

                #endregion

                #region UPDATE

                //else if(request.RequestLine.Method == SIP_Methods.UPDATE){
                // TODO:
                //}

                #endregion

                // RFC 5057 5.6. Refusing New Usages. Decline(603 Decline) new dialog usages.
            else if (SIP_Utils.MethodCanEstablishDialog(e.Request.RequestLine.Method))
            {
                e.ServerTransaction.SendResponse(
                    Stack.CreateResponse(
                        SIP_ResponseCodes.x603_Decline + " : New dialog usages not allowed (RFC 5057).",
                        e.Request));

                return true;
            }
            else
            {
                return false;
            }
        }
        /// <summary>
        /// Processes specified request through this dialog.
        /// </summary>
        /// <param name="e">Method arguments.</param>
        /// <returns>Returns true if this dialog processed specified request, otherwise false.</returns>
        /// <exception cref="ArgumentNullException">Is raised when <b>e</b> is null reference.</exception>
        protected internal override bool ProcessRequest(SIP_RequestReceivedEventArgs e)
        {
            if (e == null)
            {
                throw new ArgumentNullException("e");
            }

            if (base.ProcessRequest(e))
            {
                return(true);
            }

            // We must support: INVITE(re-invite),UPDATE,ACK,  [BYE will be handled by base class]

            #region INVITE

            if (e.Request.RequestLine.Method == SIP_Methods.INVITE)
            {
                /* RFC 3261 14.2.
                 *  A UAS that receives a second INVITE before it sends the final
                 *  response to a first INVITE with a lower CSeq sequence number on the
                 *  same dialog MUST return a 500 (Server Internal Error) response to the
                 *  second INVITE and MUST include a Retry-After header field with a
                 *  randomly chosen value of between 0 and 10 seconds.
                 *
                 *  A UAS that receives an INVITE on a dialog while an INVITE it had sent
                 *  on that dialog is in progress MUST return a 491 (Request Pending)
                 *  response to the received INVITE.
                 */

                if (m_pActiveInvite != null && m_pActiveInvite is SIP_ServerTransaction &&
                    (m_pActiveInvite).Request.CSeq.SequenceNumber < e.Request.CSeq.SequenceNumber)
                {
                    SIP_Response response =
                        Stack.CreateResponse(
                            SIP_ResponseCodes.x500_Server_Internal_Error +
                            ": INVITE with a lower CSeq is pending(RFC 3261 14.2).",
                            e.Request);
                    response.RetryAfter = new SIP_t_RetryAfter("10");
                    e.ServerTransaction.SendResponse(response);

                    return(true);
                }
                if (m_pActiveInvite != null && m_pActiveInvite is SIP_ClientTransaction)
                {
                    e.ServerTransaction.SendResponse(
                        Stack.CreateResponse(SIP_ResponseCodes.x491_Request_Pending, e.Request));

                    return(true);
                }

                // Force server transaction creation and set it as active INVITE transaction.
                m_pActiveInvite = e.ServerTransaction;
                m_pActiveInvite.StateChanged += delegate
                {
                    if (m_pActiveInvite.State ==
                        SIP_TransactionState.Terminated)
                    {
                        m_pActiveInvite = null;
                    }
                };
                // Once we send 2xx response, we need to retransmit it while get ACK or timeout. (RFC 3261 13.3.1.4.)
                ((SIP_ServerTransaction)m_pActiveInvite).ResponseSent +=
                    delegate(object s, SIP_ResponseSentEventArgs a)
                {
                    if (a.Response.StatusCodeType == SIP_StatusCodeType.Success)
                    {
                        m_pUasInvite2xxRetransmits.Add(new UasInvite2xxRetransmit(this, a.Response));
                    }
                };

                OnReinvite(((SIP_ServerTransaction)m_pActiveInvite));

                return(true);
            }

            #endregion

            #region ACK

            else if (e.Request.RequestLine.Method == SIP_Methods.ACK)
            {
                // Search corresponding INVITE 2xx retransmit entry and dispose it.
                foreach (UasInvite2xxRetransmit t in m_pUasInvite2xxRetransmits)
                {
                    if (t.MatchAck(e.Request))
                    {
                        t.Dispose();
                        if (State == SIP_DialogState.Early)
                        {
                            SetState(SIP_DialogState.Confirmed, true);

                            // TODO: If Terminating
                        }

                        return(true);
                    }
                }

                return(false);
            }

            #endregion

            #region UPDATE

            //else if(request.RequestLine.Method == SIP_Methods.UPDATE){
            // TODO:
            //}

            #endregion

            // RFC 5057 5.6. Refusing New Usages. Decline(603 Decline) new dialog usages.
            else if (SIP_Utils.MethodCanEstablishDialog(e.Request.RequestLine.Method))
            {
                e.ServerTransaction.SendResponse(
                    Stack.CreateResponse(
                        SIP_ResponseCodes.x603_Decline + " : New dialog usages not allowed (RFC 5057).",
                        e.Request));

                return(true);
            }
            else
            {
                return(false);
            }
        }
示例#3
0
 /// <summary>
 /// Raises <b>TerminatedByRemoteParty</b> event.
 /// </summary>
 /// <param name="bye">BYE request.</param>
 private void OnTerminatedByRemoteParty(SIP_RequestReceivedEventArgs bye)
 {
     if (TerminatedByRemoteParty != null)
     {
         TerminatedByRemoteParty(this, bye);
     }
 }
示例#4
0
 /// <summary>
 /// Raises <b>RequestReceived</b> event.
 /// </summary>
 /// <param name="e">Event data.</param>
 internal void OnRequestReceived(SIP_RequestReceivedEventArgs e)
 {
     if (RequestReceived != null)
     {
         RequestReceived(this, e);
     }
 }
示例#5
0
        /// <summary>
        /// Processes specified request through this dialog.
        /// </summary>
        /// <param name="e">Method arguments.</param>
        /// <returns>Returns true if this dialog processed specified response, otherwise false.</returns>
        /// <exception cref="ArgumentNullException">Is raised when <b>e</b> is null reference.</exception>
        protected internal virtual bool ProcessRequest(SIP_RequestReceivedEventArgs e)
        {
            if (e == null)
            {
                throw new ArgumentNullException("e");
            }

            if (e.Request.RequestLine.Method == SIP_Methods.BYE)
            {
                e.ServerTransaction.SendResponse(m_pStack.CreateResponse(SIP_ResponseCodes.x200_Ok, e.Request));

                m_IsTerminatedByRemoteParty = true;
                OnTerminatedByRemoteParty(e);
                SetState(SIP_DialogState.Terminated, true);

                return true;
            }

            return false;
        }