Esempio n. 1
0
        private void m_pStack_RequestReceived(object sender, SIP_RequestReceivedEventArgs e)
        {
            try
            {
                #region CANCEL

                if (e.Request.RequestLine.Method == SIP_Methods.CANCEL)
                {
                    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));
                    }
                }

                #endregion

                #region BYE

                else if (e.Request.RequestLine.Method == SIP_Methods.BYE)
                {
                    // Currently we match BYE to dialog and it processes it,
                    // so BYE what reaches here doesnt match to any dialog.

                    e.ServerTransaction.SendResponse(m_pStack.CreateResponse(SIP_ResponseCodes.x481_Call_Transaction_Does_Not_Exist, e.Request));
                }

                #endregion

                #region INVITE

                else if (e.Request.RequestLine.Method == SIP_Methods.INVITE)
                {

                    #region Incoming call

                    if (e.Dialog == null)
                    {
                        #region Validate incoming call

                        // We don't accept more than 1 call at time.
                        if (connected || m_pCall != null)
                        {
                            e.ServerTransaction.SendResponse(m_pStack.CreateResponse(SIP_ResponseCodes.x600_Busy_Everywhere, e.Request));
                            return;
                        }

                        // We don't accept SDP offerless calls.
                        if (e.Request.ContentType == null || e.Request.ContentType.ToLower().IndexOf("application/sdp") == -1)
                        {
                            e.ServerTransaction.SendResponse(m_pStack.CreateResponse(SIP_ResponseCodes.x606_Not_Acceptable + 
                                ": We don't accpet SDP offerless calls.", e.Request));
                            return;
                        }

                        SDP_Message sdpOffer = SDP_Message.Parse(Encoding.UTF8.GetString(e.Request.Data));

                        // Check if we can accept any media stream.
                        bool canAccept = false;
                        foreach (SDP_MediaDescription media in sdpOffer.MediaDescriptions)
                        {
                            if (CanSupportMedia(media))
                            {
                                canAccept = true;

                                break;
                            }
                        }

                        if (!canAccept)
                        {
                            e.ServerTransaction.SendResponse(m_pStack.CreateResponse(SIP_ResponseCodes.x606_Not_Acceptable, e.Request));

                            return;
                        }

                        #endregion

                        // Send ringing to remote-party.
                        SIP_Response responseRinging = m_pStack.CreateResponse(SIP_ResponseCodes.x180_Ringing, e.Request, e.Flow);
                        responseRinging.To.Tag = SIP_Utils.CreateTag();
                        e.ServerTransaction.SendResponse(responseRinging);

                        SIP_Dialog_Invite dialog = (SIP_Dialog_Invite)m_pStack.TransactionLayer.GetOrCreateDialog(e.ServerTransaction, responseRinging);

                        // We need invoke here, otherwise we block SIP stack RequestReceived event while incoming call UI showed.
                        this.BeginInvoke(new MethodInvoker(delegate()
                        {
                            try
                            {
                                //m_pPlayer.Play(ResManager.GetStream("ringing.wav"), 20);

                                // Call accepted.
                                RTP_MultimediaSession rtpMultimediaSession = new RTP_MultimediaSession(RTP_Utils.GenerateCNAME());

                                // Build local SDP template
                                SDP_Message sdpLocal = new SDP_Message();
                                sdpLocal.Version = "0";
                                sdpLocal.Origin = new SDP_Origin("-", sdpLocal.GetHashCode(), 1, "IN", "IP4", 
                                    System.Net.Dns.GetHostAddresses("")[0].ToString());
                                sdpLocal.SessionName = "SIP Call";
                                sdpLocal.Times.Add(new SDP_Time(0, 0));

                                ProcessMediaOffer(dialog, e.ServerTransaction, rtpMultimediaSession, sdpOffer, sdpLocal);

                                // Create call.
                                m_pCall = new SIP_Call(m_pStack, dialog, rtpMultimediaSession, sdpLocal);
                                m_pCall.StateChanged += new EventHandler(m_pCall_StateChanged);
                                m_pCall_StateChanged(m_pCall, new EventArgs());

                                if (m_IsDebug)
                                {
                                    wfrm_RTP_Debug rtpDebug = new wfrm_RTP_Debug(m_pCall.RtpMultimediaSession);
                                    rtpDebug.Show();
                                }

                                connected = true;

                            }
                            catch (Exception x1)
                            {
                                MessageBox.Show("Error: " + x1.Message, "Error:", MessageBoxButtons.OK, MessageBoxIcon.Error);
                                connected = false;
                                m_pConnect.Image = global::PowerSDR.Properties.Resources.call;
                            }
                        }));
                    }

                    #endregion

                    #region Re-INVITE

                    else
                    {
                        try
                        {
                            // Remote-party provided SDP offer.
                            if (e.Request.ContentType != null && e.Request.ContentType.ToLower().IndexOf("application/sdp") > -1)
                            {
                                ProcessMediaOffer(m_pCall.Dialog, e.ServerTransaction, m_pCall.RtpMultimediaSession, 
                                    SDP_Message.Parse(Encoding.UTF8.GetString(e.Request.Data)), m_pCall.LocalSDP);

                                // Remote-party is holding a call.
                                if (IsRemotePartyHolding(SDP_Message.Parse(Encoding.UTF8.GetString(e.Request.Data))))
                                {
                                    // We need invoke here, we are running on thread pool thread.
                                    this.BeginInvoke(new MethodInvoker(delegate()
                                    {
                                        m_pStatusBar.Items[0].Text = "Remote party holding a call";
                                    }));

                                    //m_pPlayer.Play(ResManager.GetStream("onhold.wav"), 20);
                                }
                                // Call is active.
                                else
                                {
                                    // We need invoke here, we are running on thread pool thread.
                                    this.BeginInvoke(new MethodInvoker(delegate()
                                    {
                                        m_pStatusBar.Items[0].Text = "Call established";
                                    }));

                                    m_pPlayer.Stop();
                                }
                            }
                            // Error: Re-INVITE can't be SDP offerless.
                            else
                            {
                                e.ServerTransaction.SendResponse(m_pStack.CreateResponse(SIP_ResponseCodes.x500_Server_Internal_Error + 
                                    ": Re-INVITE must contain SDP offer.", e.Request));
                            }
                        }
                        catch (Exception x1)
                        {
                            e.ServerTransaction.SendResponse(m_pStack.CreateResponse(SIP_ResponseCodes.x500_Server_Internal_Error + 
                                ": " + x1.Message, e.Request));
                        }
                    }

                    #endregion
                }

                #endregion

                #region ACK

                else if (e.Request.RequestLine.Method == SIP_Methods.ACK)
                {
                    // Abandoned ACK, just skip it.
                }

                #endregion

                #region MESSAGE

                else if (e.Request.RequestLine.Method == SIP_Methods.MESSAGE)
                {
                    e.ServerTransaction.SendResponse(m_pStack.CreateResponse(SIP_ResponseCodes.x200_Ok, e.Request));
                    byte[] msg = e.Request.Data;
                    ASCIIEncoding buffer = new ASCIIEncoding();
                    string data = buffer.GetString(msg);
                    string answer = "";

                    if (debug && !console.ConsoleClosing)
                        console.Invoke(new DebugCallbackFunction(console.DebugCallback), data);

                    if (op_mode == VoIP_mode.Server)
                        answer = console.CAT_server_socket.ProcessData(msg, msg.Length);
                    else
                    {
                        if (console.CAT_client_socket.ProcessData(msg, msg.Length, out answer))
                            SendMessage(answer, "CAT");
                    }
                }

                #endregion

                #region Other

                else
                {
                    // ACK is response less method.
                    if (e.Request.RequestLine.Method != SIP_Methods.ACK)
                    {
                        e.ServerTransaction.SendResponse(m_pStack.CreateResponse(SIP_ResponseCodes.x501_Not_Implemented, e.Request));
                    }
                }

                #endregion
            }
            catch
            {
                e.ServerTransaction.SendResponse(m_pStack.CreateResponse(SIP_ResponseCodes.x500_Server_Internal_Error, e.Request));
            }
        }
Esempio n. 2
0
        private void Call(SIP_t_NameAddress from, SIP_t_NameAddress to)
        {
            if (from == null)
            {
                throw new ArgumentNullException("from");
            }
            if (to == null)
            {
                throw new ArgumentNullException("to");
            }

            #region Setup RTP session

            RTP_MultimediaSession rtpMultimediaSession = new RTP_MultimediaSession(RTP_Utils.GenerateCNAME());
            RTP_Session rtpSession = CreateRtpSession(rtpMultimediaSession);
            // Port search failed.
            if (rtpSession == null)
            {
                throw new Exception("Calling not possible, RTP session failed to allocate IP end points.");
            }

            if (m_IsDebug)
            {
                wfrm_RTP_Debug rtpDebug = new wfrm_RTP_Debug(rtpMultimediaSession);
                rtpDebug.Show();
            }

            #endregion

            #region Create SDP offer

            SDP_Message sdpOffer = new SDP_Message();
            sdpOffer.Version = "0";
            sdpOffer.Origin = new SDP_Origin("-", sdpOffer.GetHashCode(), 1, "IN", "IP4", System.Net.Dns.GetHostAddresses("")[0].ToString());
            sdpOffer.SessionName = "SIP Call";
            sdpOffer.Times.Add(new SDP_Time(0, 0));

            #region Add 1 audio stream

            SDP_MediaDescription mediaStream = new SDP_MediaDescription(SDP_MediaTypes.audio, 0, 1, "RTP/AVP", null);

            rtpSession.NewReceiveStream += delegate(object s, RTP_ReceiveStreamEventArgs e)
            {
                AudioOut_RTP audioOut = new AudioOut_RTP(m_pAudioOutDevice, e.Stream, m_pAudioCodecs);
                audioOut.Start();
                mediaStream.Tags["rtp_audio_out"] = audioOut;
            };

            if (!HandleNAT(mediaStream, rtpSession))
            {
                throw new Exception("Calling not possible, because of NAT or firewall restrictions.");
            }

            foreach (KeyValuePair<int, AudioCodec> entry in m_pAudioCodecs)
            {
                mediaStream.Attributes.Add(new SDP_Attribute("rtpmap", entry.Key + " " + entry.Value.Name + "/" + entry.Value.CompressedAudioFormat.SamplesPerSecond));
                mediaStream.MediaFormats.Add(entry.Key.ToString());
            }
            mediaStream.Attributes.Add(new SDP_Attribute("ptime", "20"));
            mediaStream.Attributes.Add(new SDP_Attribute("sendrecv", ""));
            mediaStream.Tags["rtp_session"] = rtpSession;
            mediaStream.Tags["audio_codecs"] = m_pAudioCodecs;
            sdpOffer.MediaDescriptions.Add(mediaStream);

            #endregion

            #endregion

            // Create INVITE request.
            SIP_Request invite = m_pStack.CreateRequest(SIP_Methods.INVITE, to, from);
            invite.ContentType = "application/sdp";
            invite.Data = sdpOffer.ToByte();

            SIP_RequestSender sender = m_pStack.CreateRequestSender(invite);

            // Create call.
            m_pCall = new SIP_Call(m_pStack, sender, rtpMultimediaSession);
            m_pCall.LocalSDP = sdpOffer;
            m_pCall.StateChanged += new EventHandler(m_pCall_StateChanged);

            bool finalResponseSeen = false;
            List<SIP_Dialog_Invite> earlyDialogs = new List<SIP_Dialog_Invite>();
            sender.ResponseReceived += delegate(object s, SIP_ResponseReceivedEventArgs e)
            {
                // Skip 2xx retransmited response.
                if (finalResponseSeen)
                {
                    return;
                }
                if (e.Response.StatusCode >= 200)
                {
                    finalResponseSeen = true;
                }

                try
                {
                    #region Provisional

                    if (e.Response.StatusCodeType == SIP_StatusCodeType.Provisional)
                    {
                        /* 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)
                        {
                            earlyDialogs.Add((SIP_Dialog_Invite)e.GetOrCreateDialog);
                        }

                        // 180_Ringing.
                        if (e.Response.StatusCode == 180)
                        {
                            //m_pPlayer.Play(ResManager.GetStream("ringing.wav"), 10);

                            // We need BeginInvoke here, otherwise we block client transaction.
                            m_pStatusBar.BeginInvoke(new MethodInvoker(delegate()
                            {
                                m_pStatusBar.Items[0].Text = "Ringing";
                            }));
                        }
                    }

                    #endregion

                    #region Success

                    else if (e.Response.StatusCodeType == SIP_StatusCodeType.Success)
                    {
                        SIP_Dialog dialog = e.GetOrCreateDialog;

                        /* 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, 
                           all this is 100% valid.
                        */
                        foreach (SIP_Dialog_Invite d in earlyDialogs.ToArray())
                        {
                            if (!d.Equals(dialog))
                            {
                                d.Terminate("Another forking leg accepted.", true);
                            }
                        }

                        m_pCall.InitCalling(dialog, sdpOffer);

                        // Remote-party provided SDP.
                        if (e.Response.ContentType != null && e.Response.ContentType.ToLower().IndexOf("application/sdp") > -1)
                        {
                            try
                            {
                                // SDP offer. We sent offerless INVITE, we need to send SDP answer in ACK request.'
                                if (e.ClientTransaction.Request.ContentType == null || e.ClientTransaction.Request.ContentType.ToLower().IndexOf("application/sdp") == -1)
                                {
                                    // Currently we never do it, so it never happens. This is place holder, if we ever support it.
                                }
                                // SDP answer to our offer.
                                else
                                {
                                    // This method takes care of ACK sending and 2xx response retransmission ACK sending.
                                    HandleAck(m_pCall.Dialog, e.ClientTransaction);

                                    ProcessMediaAnswer(m_pCall, m_pCall.LocalSDP, SDP_Message.Parse(Encoding.UTF8.GetString(e.Response.Data)));
                                }
                            }
                            catch
                            {
                                m_pCall.Terminate("SDP answer parsing/processing failed.");
                            }
                        }
                        else
                        {
                            // If we provided SDP offer, there must be SDP answer.
                            if (e.ClientTransaction.Request.ContentType != null && e.ClientTransaction.Request.ContentType.ToLower().IndexOf("application/sdp") > -1)
                            {
                                m_pCall.Terminate("Invalid 2xx response, required SDP answer is missing.");
                            }
                        }

                        // Stop ringing.
                        m_pPlayer.Stop();
                    }

                    #endregion

                    #region Failure

                    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 earlyDialogs.ToArray())
                        {
                            dialog.Terminate("All early dialogs are considered terminated upon reception of the non-2xx final response. (RFC 3261 13.2.2.3)", false);
                        }

                        // We need BeginInvoke here, otherwise we block client transaction while message box open.
                        if (m_pCall.State != SIP_CallState.Terminating)
                        {
                            this.BeginInvoke(new MethodInvoker(delegate()
                            {
                                m_pConnect.Image = global::PowerSDR.Properties.Resources.call;
                                connected = false;
                                MessageBox.Show("Calling failed: " + e.Response.StatusCode_ReasonPhrase, "Error:", MessageBoxButtons.OK, MessageBoxIcon.Error);
                            }));
                        }

                        // We need BeginInvoke here, otherwise we block client transaction.
                        m_pStatusBar.BeginInvoke(new MethodInvoker(delegate()
                        {
                            m_pStatusBar.Items[0].Text = "";
                        }));
                        // Stop calling or ringing.
                        m_pPlayer.Stop();

                        // Terminate call.
                        m_pCall.Terminate("Remote party rejected a call.", false);
                    }

                    #endregion
                }
                catch (Exception x)
                {
                    // We need BeginInvoke here, otherwise we block client transaction while message box open.
                    this.BeginInvoke(new MethodInvoker(delegate()
                    {
                        MessageBox.Show("Error: " + x.Message, "Error:", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    }));
                }
            };

            m_pStatusBar.Items[0].Text = "Calling";
            m_pStatusBar.Items[1].Text = "00:00:00";
            //m_pPlayer.Play(ResManager.GetStream("calling.wav"), 10);

            // Start calling.
            sender.Start();
        }
Esempio n. 3
0
        /// <summary>
        /// Is called when SIP stack has received request.
        /// </summary>
        /// <param name="sender">Sender.</param>
        /// <param name="e">Event data.</param>
        private void m_pStack_RequestReceived(object sender,SIP_RequestReceivedEventArgs e)
        {
            try{
                #region CANCEL

                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));
                    }
                }

                #endregion

                #region BYE

                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.
                    */

                    // Currently we match BYE to dialog and it processes it,
                    // so BYE what reaches here doesnt match to any dialog.

                    e.ServerTransaction.SendResponse(m_pStack.CreateResponse(SIP_ResponseCodes.x481_Call_Transaction_Does_Not_Exist,e.Request));
                }

                #endregion

                #region INVITE

                else if(e.Request.RequestLine.Method == SIP_Methods.INVITE){

                    #region Incoming call

                    if(e.Dialog == null){
                        #region Validate incoming call

                        // We don't accept more than 1 call at time.
                        if(m_pIncomingCallUI != null || m_pCall != null){
                            e.ServerTransaction.SendResponse(m_pStack.CreateResponse(SIP_ResponseCodes.x600_Busy_Everywhere,e.Request));

                            return;
                        }

                        // We don't accept SDP offerless calls.
                        if(e.Request.ContentType == null || e.Request.ContentType.ToLower().IndexOf("application/sdp") == -1){
                            e.ServerTransaction.SendResponse(m_pStack.CreateResponse(SIP_ResponseCodes.x606_Not_Acceptable + ": We don't accpet SDP offerless calls.",e.Request));

                            return;
                        }

                        SDP_Message sdpOffer = SDP_Message.Parse(Encoding.UTF8.GetString(e.Request.Data));

                        // Check if we can accept any media stream.
                        bool canAccept = false;
                        foreach(SDP_MediaDescription media in sdpOffer.MediaDescriptions){
                            if(CanSupportMedia(media)){
                                canAccept = true;

                                break;
                            }
                        }
                        if(!canAccept){
                            e.ServerTransaction.SendResponse(m_pStack.CreateResponse(SIP_ResponseCodes.x606_Not_Acceptable,e.Request));

                            return;
                        }
                        
                        #endregion
                                                                        
                        // Send ringing to remote-party.
                        SIP_Response responseRinging = m_pStack.CreateResponse(SIP_ResponseCodes.x180_Ringing,e.Request,e.Flow);
                        responseRinging.To.Tag = SIP_Utils.CreateTag();
                        e.ServerTransaction.SendResponse(responseRinging);

                        SIP_Dialog_Invite dialog = (SIP_Dialog_Invite)m_pStack.TransactionLayer.GetOrCreateDialog(e.ServerTransaction,responseRinging);
                                                
                        // We need invoke here, otherwise we block SIP stack RequestReceived event while incoming call UI showed.
                        this.BeginInvoke(new MethodInvoker(delegate(){
                            try{
                                m_pPlayer.Play(ResManager.GetStream("ringing.wav"),20);

                                // Show incoming call UI.
                                m_pIncomingCallUI = new wfrm_IncomingCall(e.ServerTransaction);
                                // Call accepted.
                                if(m_pIncomingCallUI.ShowDialog(this) == DialogResult.Yes){  
                                    RTP_MultimediaSession rtpMultimediaSession = new RTP_MultimediaSession(RTP_Utils.GenerateCNAME());

                                    // Build local SDP template
                                    SDP_Message sdpLocal = new SDP_Message();
                                    sdpLocal.Version = "0";
                                    sdpLocal.Origin = new SDP_Origin("-",sdpLocal.GetHashCode(),1,"IN","IP4",System.Net.Dns.GetHostAddresses("")[0].ToString());
                                    sdpLocal.SessionName = "SIP Call";            
                                    sdpLocal.Times.Add(new SDP_Time(0,0));
                           
                                    ProcessMediaOffer(dialog,e.ServerTransaction,rtpMultimediaSession,sdpOffer,sdpLocal);

                                    // Create call.
                                    m_pCall = new SIP_Call(m_pStack,dialog,rtpMultimediaSession,sdpLocal);
                                    m_pCall.StateChanged += new EventHandler(m_pCall_StateChanged);
                                    m_pCall_StateChanged(m_pCall,new EventArgs());

                                    if(m_IsDebug){
                                        wfrm_RTP_Debug rtpDebug = new wfrm_RTP_Debug(m_pCall.RtpMultimediaSession);
                                        rtpDebug.Show();
                                    }
                                }
                                // Call rejected.
                                else{
                                    // Transaction response is sent in call UI.

                                    dialog.Terminate(null,false);
                                }
                                m_pIncomingCallUI = null;
                                m_pPlayer.Stop();
                            }
                            catch(Exception x1){
                                MessageBox.Show("Error: " + x1.Message,"Error:",MessageBoxButtons.OK,MessageBoxIcon.Error);
                            }
                        }));
                    }

                    #endregion

                    #region Re-INVITE

                    else{
                        try{                                                        
                            // Remote-party provided SDP offer.
                            if(e.Request.ContentType != null && e.Request.ContentType.ToLower().IndexOf("application/sdp") > -1){
                                ProcessMediaOffer(m_pCall.Dialog,e.ServerTransaction,m_pCall.RtpMultimediaSession,SDP_Message.Parse(Encoding.UTF8.GetString(e.Request.Data)),m_pCall.LocalSDP);

                                // We are holding a call.
                                if(m_pToggleOnHold.Text == "Unhold"){
                                    // We don't need to do anything here.
                                }
                                // Remote-party is holding a call.
                                else if(IsRemotePartyHolding(SDP_Message.Parse(Encoding.UTF8.GetString(e.Request.Data)))){
                                    // We need invoke here, we are running on thread pool thread.
                                    this.BeginInvoke(new MethodInvoker(delegate(){
                                        m_pStatusBar.Items["text"].Text = "Remote party holding a call";                                    
                                    }));

                                    m_pPlayer.Play(ResManager.GetStream("onhold.wav"),20);
                                }
                                // Call is active.
                                else{
                                    // We need invoke here, we are running on thread pool thread.
                                    this.BeginInvoke(new MethodInvoker(delegate(){
                                        m_pStatusBar.Items["text"].Text = "Call established";                                    
                                    }));

                                    m_pPlayer.Stop();
                                }
                            }
                            // Error: Re-INVITE can't be SDP offerless.
                            else{
                                e.ServerTransaction.SendResponse(m_pStack.CreateResponse(SIP_ResponseCodes.x500_Server_Internal_Error + ": Re-INVITE must contain SDP offer.",e.Request));
                            }
                        }
                        catch(Exception x1){
                            e.ServerTransaction.SendResponse(m_pStack.CreateResponse(SIP_ResponseCodes.x500_Server_Internal_Error + ": " + x1.Message,e.Request));
                        }
                    }

                    #endregion
                }

                #endregion

                #region ACK

                else if(e.Request.RequestLine.Method == SIP_Methods.ACK){
                    // Abandoned ACK, just skip it.
                }

                #endregion

                #region Other

                else{
                    // ACK is response less method.
                    if(e.Request.RequestLine.Method != SIP_Methods.ACK){
                        e.ServerTransaction.SendResponse(m_pStack.CreateResponse(SIP_ResponseCodes.x501_Not_Implemented,e.Request));
                    }
                }

                #endregion
            }
            catch{
                e.ServerTransaction.SendResponse(m_pStack.CreateResponse(SIP_ResponseCodes.x500_Server_Internal_Error,e.Request));
            }
        }