Пример #1
0
        public async void ChecklistProcessingToFailStateUnitTest()
        {
            logger.LogDebug("--> " + System.Reflection.MethodBase.GetCurrentMethod().Name);
            logger.BeginScope(System.Reflection.MethodBase.GetCurrentMethod().Name);

            RTPChannel rtpChannel = new RTPChannel(false, null);

            var iceSession = new IceSession(rtpChannel, RTCIceComponent.rtp, null);

            iceSession.StartGathering();

            Assert.NotNull(iceSession);
            Assert.NotEmpty(iceSession.Candidates);

            foreach (var hostCandidate in iceSession.Candidates)
            {
                logger.LogDebug($"host candidate: {hostCandidate}");
            }

            var remoteCandidate = RTCIceCandidate.Parse("candidate:408132416 1 udp 2113937151 192.168.11.50 51268 typ host generation 0 ufrag CI7o network-cost 999");
            await iceSession.AddRemoteCandidate(remoteCandidate);

            iceSession.SetRemoteCredentials("CI7o", "xxxxxxxxxxxx");
            iceSession.StartGathering();

            logger.LogDebug($"ICE session retry interval {iceSession.RTO}ms.");

            // The defaults are 5 STUN requests and for a checklist with one entry they will be 500ms apart.
            await Task.Delay(4000);

            Assert.Equal(IceSession.ChecklistEntryState.Failed, iceSession._checklist.Single().State);
            Assert.Equal(IceSession.ChecklistState.Failed, iceSession._checklistState);
            Assert.Equal(RTCIceConnectionState.failed, iceSession.ConnectionState);
        }
Пример #2
0
        public void GetHostCandidatesForRTPBindUnitTest()
        {
            logger.LogDebug("--> " + System.Reflection.MethodBase.GetCurrentMethod().Name);
            logger.BeginScope(System.Reflection.MethodBase.GetCurrentMethod().Name);

            var        localAddress = NetServices.InternetDefaultAddress;
            RTPSession rtpSession   = new RTPSession(true, true, true, localAddress);

            // Add a track to the session in order to initialise the RTPChannel.
            MediaStreamTrack dummyTrack = new MediaStreamTrack(null, SDPMediaTypesEnum.audio, false, new List <SDPMediaFormat> {
                new SDPMediaFormat(SDPMediaFormatsEnum.PCMU)
            });

            rtpSession.addTrack(dummyTrack);

            RTPChannel rtpChannel = rtpSession.GetRtpChannel(SDPMediaTypesEnum.audio);

            logger.LogDebug($"RTP channel RTP socket local end point {rtpChannel.RTPLocalEndPoint}.");

            var iceSession = new IceSession(rtpChannel, RTCIceComponent.rtp, null);

            iceSession.StartGathering();

            Assert.NotNull(iceSession);
            Assert.NotEmpty(iceSession.Candidates);
            Assert.True(localAddress.Equals(IPAddress.Parse(iceSession.Candidates.Single().address)));

            foreach (var hostCandidate in iceSession.Candidates)
            {
                logger.LogDebug(hostCandidate.ToString());
            }
        }
Пример #3
0
        public async void ChecklistConstructionUnitTest()
        {
            logger.LogDebug("--> " + System.Reflection.MethodBase.GetCurrentMethod().Name);
            logger.BeginScope(System.Reflection.MethodBase.GetCurrentMethod().Name);

            RTPChannel rtpChannel = new RTPChannel(false, null);

            var iceSession = new IceSession(rtpChannel, RTCIceComponent.rtp, null);

            iceSession.StartGathering();

            Assert.NotNull(iceSession);
            Assert.NotEmpty(iceSession.Candidates);

            foreach (var hostCandidate in iceSession.Candidates)
            {
                logger.LogDebug($"host candidate: {hostCandidate}");
            }

            var remoteCandidate = RTCIceCandidate.Parse("candidate:408132416 1 udp 2113937151 192.168.11.50 51268 typ host generation 0 ufrag CI7o network-cost 999");
            await iceSession.AddRemoteCandidate(remoteCandidate);

            var remoteCandidate2 = RTCIceCandidate.Parse("candidate:408132417 1 udp 2113937150 192.168.11.50 51268 typ host generation 0 ufrag CI7o network-cost 999");
            await iceSession.AddRemoteCandidate(remoteCandidate2);

            foreach (var entry in iceSession._checklist)
            {
                logger.LogDebug($"checklist entry: {entry.LocalCandidate} -> {entry.RemoteCandidate}");
            }

            Assert.Single(iceSession._checklist);
        }
Пример #4
0
        public async void ChecklistProcessingUnitTest()
        {
            logger.LogDebug("--> " + System.Reflection.MethodBase.GetCurrentMethod().Name);
            logger.BeginScope(System.Reflection.MethodBase.GetCurrentMethod().Name);

            RTPChannel rtpChannel = new RTPChannel(false, null);

            var iceSession = new IceSession(rtpChannel, RTCIceComponent.rtp, null);

            iceSession.StartGathering();

            Assert.NotNull(iceSession);
            Assert.NotEmpty(iceSession.Candidates);

            foreach (var hostCandidate in iceSession.Candidates)
            {
                logger.LogDebug($"host candidate: {hostCandidate}");
            }

            var remoteCandidate = RTCIceCandidate.Parse("candidate:408132416 1 udp 2113937151 192.168.11.50 51268 typ host generation 0 ufrag CI7o network-cost 999");
            await iceSession.AddRemoteCandidate(remoteCandidate);

            iceSession.SetRemoteCredentials("CI7o", "xxxxxxxxxxxx");
            iceSession.StartGathering();

            await Task.Delay(2000);

            var checklistEntry = iceSession._checklist.Single();

            logger.LogDebug($"Checklist entry state {checklistEntry.State}, last check sent at {checklistEntry.LastCheckSentAt}.");

            Assert.Equal(IceSession.ChecklistEntryState.InProgress, checklistEntry.State);
        }
Пример #5
0
        public AudioChannel()
        {
            // Set up the device that will play the audio from the RTP received from the remote end of the call.
            m_waveOut      = new WaveOut();
            m_waveProvider = new BufferedWaveProvider(_waveFormat);
            m_waveOut.Init(m_waveProvider);
            m_waveOut.Play();

            // Set up the input device that will provide audio samples that can be encoded, packaged into RTP and sent to
            // the remote end of the call.
            m_waveInEvent = new WaveInEvent();
            m_waveInEvent.BufferMilliseconds = 20;
            m_waveInEvent.NumberOfBuffers    = 1;
            m_waveInEvent.DeviceNumber       = 0;
            m_waveInEvent.DataAvailable     += RTPChannelSampleAvailable;
            m_waveInEvent.WaveFormat         = _waveFormat;

            // Create a UDP socket to use for sending and receiving RTP packets.
            int port = FreePort.FindNextAvailableUDPPort(DEFAULT_START_RTP_PORT);

            _rtpEndPoint = new IPEndPoint(_defaultLocalAddress, port);
            m_rtpChannel = new RTPChannel(_rtpEndPoint);
            m_rtpChannel.OnFrameReady += RTPChannelSampleReceived;


            _audioLogger.Debug("RTP channel endpoint " + _rtpEndPoint.ToString());
        }
Пример #6
0
        /// <summary>
        /// 确认接收视频请求
        /// </summary>
        /// <param name="response">响应消息</param>
        /// <returns></returns>
        public void AckRequest(SIPResponse response)
        {
            _rtpChannel = new RTPChannel(_remoteEndPoint.GetIPEndPoint(), _mediaPort[0], _mediaPort[1], FrameTypesEnum.H264);
            _rtpChannel.OnFrameReady += _rtpChannel_OnFrameReady;
            _rtpChannel.Start();

            SIPURI           localUri      = new SIPURI(_msgCore.LocalSIPId, _msgCore.LocalEndPoint.ToHost(), "");
            SIPURI           remoteUri     = new SIPURI(_deviceId, _remoteEndPoint.ToHost(), "");
            SIPRequest       ackReq        = _msgCore.Transport.GetRequest(SIPMethodsEnum.ACK, remoteUri);
            SIPFromHeader    from          = new SIPFromHeader(null, response.Header.From.FromURI, response.Header.From.FromTag);
            SIPToHeader      to            = new SIPToHeader(null, remoteUri, response.Header.To.ToTag);
            SIPContactHeader contactHeader = new SIPContactHeader(null, localUri);
            SIPHeader        header        = new SIPHeader(from, to, response.Header.CSeq, response.Header.CallId);

            header.CSeqMethod = SIPMethodsEnum.ACK;
            header.Contact    = response.Header.Contact;
            header.Contact.Clear();
            header.Contact.Add(contactHeader);
            header.Vias          = response.Header.Vias;
            header.MaxForwards   = response.Header.MaxForwards;
            header.ContentLength = response.Header.ContentLength;
            header.UserAgent     = _msgCore.UserAgent;
            header.Allow         = null;
            ackReq.Header        = header;
            _okTag   = response.Header.To.ToTag;
            _contact = header.Contact.FirstOrDefault();
            _via     = header.Vias;
            _msgCore.Transport.SendRequest(_remoteEndPoint, ackReq);
        }
Пример #7
0
        public void MultipleRtpChannelLoopbackUnitTest()
        {
            logger.LogDebug("--> " + System.Reflection.MethodBase.GetCurrentMethod().Name);
            logger.BeginScope(System.Reflection.MethodBase.GetCurrentMethod().Name);

            const int PACKET_LENGTH = 100;

            List <Task> tasks = new List <Task>();

            for (int i = 0; i < 3; i++)
            {
                var t = Task.Run(async() =>
                {
                    RTPChannel channel1 = new RTPChannel(false, null);

                    bool testResult = false;
                    ManualResetEventSlim testCompleteEvent = new ManualResetEventSlim(false);

                    RTPChannel channel2         = new RTPChannel(false, null);
                    channel2.OnRTPDataReceived += (lep, rep, pkt) =>
                    {
                        logger.LogDebug($"RTP data receive packet length {pkt.Length}.");
                        testResult = pkt.Length == PACKET_LENGTH;
                        testCompleteEvent.Set();
                    };

                    channel1.Start();
                    channel2.Start();

                    // Give the socket receive tasks time to fire up.
                    await Task.Delay(2000);

                    IPAddress channel2Address = (channel2.RTPLocalEndPoint.AddressFamily == AddressFamily.InterNetworkV6) ? IPAddress.IPv6Loopback : IPAddress.Loopback;
                    IPEndPoint channel2Dst    = new IPEndPoint(channel2Address, channel2.RTPPort);

                    logger.LogDebug($"Attempting to send packet from {channel1.RTPLocalEndPoint} to {channel2Dst}.");

                    var sendResult = channel1.SendAsync(RTPChannelSocketsEnum.RTP, channel2Dst, new byte[PACKET_LENGTH]);

                    logger.LogDebug($"Send result {sendResult}.");

                    testCompleteEvent.Wait(TimeSpan.FromSeconds(TEST_TIMEOUT_SECONDS));

                    Assert.True(testResult);

                    channel1.Close("normal");
                    channel2.Close("normal");
                });

                tasks.Add(t);
            }

            CancellationTokenSource cts = new CancellationTokenSource();

            Assert.True(Task.WaitAll(tasks.ToArray(), 10000, cts.Token));

            logger.LogDebug($"Test complete.");
        }
Пример #8
0
        public void Start(string endpoint)
        {
            this.endpoint = endpoint;

            var caller   = "1003";
            var password = passwords[0];
            var port     = FreePort.FindNextAvailableUDPPort(15090);

            rtpChannel = new RTPChannel
            {
                DontTimeout    = true,
                RemoteEndPoint = new IPEndPoint(IPAddress.Parse(asterisk), port)
            };

            rtpChannel.SetFrameType(FrameTypesEnum.Audio);
            rtpChannel.ReservePorts(15000, 15090);
            rtpChannel.OnFrameReady += RtpChannel_OnFrameReady;

            uac = new SIPClientUserAgent(transport, null, null, null, null);

            var uri    = SIPURI.ParseSIPURIRelaxed($"{ endpoint }@{ asterisk }");
            var from   = (new SIPFromHeader(caller, new SIPURI(caller, asterisk, null), null)).ToString();
            var random = Crypto.GetRandomInt(5).ToString();
            var sdp    = new SDP
            {
                Version     = 2,
                Username    = "******",
                SessionId   = random,
                Address     = localIPEndPoint.Address.ToString(),
                SessionName = "redfox_" + random,
                Timing      = "0 0",
                Connection  = new SDPConnectionInformation(publicIPAddress.ToString())
            };

            var announcement = new SDPMediaAnnouncement
            {
                Media        = SDPMediaTypesEnum.audio,
                MediaFormats = new List <SDPMediaFormat>()
                {
                    new SDPMediaFormat((int)SDPMediaFormatsEnum.PCMU, "PCMU", 8000)
                },
                Port = rtpChannel.RTPPort
            };

            sdp.Media.Add(announcement);

            var descriptor = new SIPCallDescriptor(caller, password, uri.ToString(), from, null, null, null, null, SIPCallDirection.Out, SDP.SDP_MIME_CONTENTTYPE, sdp.ToString(), null);

            uac.CallTrying   += Uac_CallTrying;
            uac.CallRinging  += Uac_CallRinging;
            uac.CallAnswered += Uac_CallAnswered;
            uac.CallFailed   += Uac_CallFailed;

            uac.Call(descriptor);
        }
Пример #9
0
        /// <summary>
        /// rtcp包回调事件处理
        /// </summary>
        /// <param name="buffer"></param>
        /// <param name="rtcpSocket"></param>
        private void _rtpChannel_OnControlDataReceived(byte[] buffer, Socket rtcpSocket)
        {
            _rtcpSocket = rtcpSocket;
            DateTime packetTimestamp = DateTime.Now;

            _rtcpTimestamp = RTPChannel.DateTimeToNptTimestamp90K(DateTime.Now);
            if (_rtcpRemoteEndPoint != null)
            {
                SendRtcpSenderReport(RTPChannel.DateTimeToNptTimestamp(packetTimestamp), _rtcpTimestamp);
            }
        }
Пример #10
0
        /// <param name="rtpListenAddress">The local IP address to establish the RTP listener socket on.</param>
        /// <param name="sdpAdvertiseAddress">The public IP address to put into the SDP sent back to the caller.</param>
        /// <param name="request">The INVITE request that instigated the RTP diagnostics job.</param>
        public RTPDiagnosticsJob(IPAddress rtpListenAddress, IPAddress sdpAdvertiseAddress, SIPServerUserAgent uas, SIPRequest request)
        {
            m_request         = request;
            m_remoteSDP       = SDP.ParseSDPDescription(request.Body);
            RemoteRTPEndPoint = new IPEndPoint(IPAddress.Parse(m_remoteSDP.Connection.ConnectionAddress), m_remoteSDP.Media[0].Port);
            UAS = uas;
            //m_rawSourceStream = new RawSourceWaveStream(m_outStream, WaveFormat.CreateMuLawFormat(8000, 1));
            //m_waveFileWriter = new WaveFileWriter("out.wav", new WaveFormat(8000, 16, 1));
            m_waveFileWriter = new WaveFileWriter("out.wav", new WaveFormat(8000, 16, 1));
            //m_outPCMStream = WaveFormatConversionStream.CreatePcmStream(m_rawSourceStream);
            //m_rawRTPPayloadWriter = new StreamWriter("out.rtp");
            //m_rawRTPPayloadReader = new StreamReader("in.rtp");
            //IPEndPoint rtpListenEndPoint = null;
            IPEndPoint rtpListenEndPoint = null;

            NetServices.CreateRandomUDPListener(rtpListenAddress, RTP_PORTRANGE_START, RTP_PORTRANGE_END, m_inUsePorts, out rtpListenEndPoint);
            RTPListenEndPoint = rtpListenEndPoint;
            m_inUsePorts.Add(rtpListenEndPoint.Port);
            //RTPListenEndPoint = new IPEndPoint(rtpListenAddress, RTP_PORTRANGE_START);
            m_rtpChannel = new RTPChannel(RTPListenEndPoint);
            m_rtpChannel.SampleReceived += SampleReceived;
            ThreadPool.QueueUserWorkItem(delegate { GetAudioSamples(); });

            LocalSDP = new SDP()
            {
                SessionId   = Crypto.GetRandomString(6),
                Address     = sdpAdvertiseAddress.ToString(),
                SessionName = "sipsorcery",
                Timing      = "0 0",
                Connection  = new SDPConnectionInformation(sdpAdvertiseAddress.ToString()),
                Media       = new List <SDPMediaAnnouncement>()
                {
                    new SDPMediaAnnouncement()
                    {
                        Media        = SDPMediaTypesEnum.audio,
                        Port         = RTPListenEndPoint.Port,
                        MediaFormats = new List <SDPMediaFormat>()
                        {
                            new SDPMediaFormat((int)SDPMediaFormatsEnum.PCMU)
                        }
                    }
                }
            };
        }
Пример #11
0
        public async void RtpChannelLoopbackUnitTest()
        {
            logger.LogDebug("--> " + System.Reflection.MethodBase.GetCurrentMethod().Name);
            logger.BeginScope(System.Reflection.MethodBase.GetCurrentMethod().Name);

            RTPChannel channel1 = new RTPChannel(false, null);

            bool testResult = false;
            ManualResetEventSlim testCompleteEvent = new ManualResetEventSlim(false);

            RTPChannel channel2 = new RTPChannel(false, null);

            channel2.OnRTPDataReceived += (lep, rep, pkt) =>
            {
                logger.LogDebug($"RTP data receive packet length {pkt.Length}.");
                testResult = true;
                testCompleteEvent.Set();
            };

            channel1.Start();
            channel2.Start();

            // Give the socket receive tasks time to fire up.
            await Task.Delay(1000);

            IPAddress  channel2Address = (channel2.RTPLocalEndPoint.AddressFamily == AddressFamily.InterNetworkV6) ? IPAddress.IPv6Loopback : IPAddress.Loopback;
            IPEndPoint channel2Dst     = new IPEndPoint(channel2Address, channel2.RTPPort);

            logger.LogDebug($"Attempting to send packet from {channel1.RTPLocalEndPoint} to {channel2Dst}.");

            var sendResult = channel1.SendAsync(RTPChannelSocketsEnum.RTP, channel2Dst, new byte[] { 0x00 });

            logger.LogDebug($"Send result {sendResult}.");

            testCompleteEvent.Wait(TimeSpan.FromSeconds(TEST_TIMEOUT_SECONDS));

            Assert.True(testResult);

            channel1.Close("normal");
            channel2.Close("normal");

            logger.LogDebug($"Test complete.");
        }
Пример #12
0
        /// <summary>
        /// sip初始化完成事件
        /// </summary>
        /// <param name="sipRequest">sip请求</param>
        /// <param name="localEndPoint">本地终结点</param>
        /// <param name="remoteEndPoint">远程终结点</param>
        /// <param name="sipAccount">sip账户</param>
        private void messageCore_SipRequestInited(SIPRequest sipRequest, SIPEndPoint localEndPoint, SIPEndPoint remoteEndPoint, SIPAccount sipAccount)
        {
            _sipInited      = true;
            _sipRequest     = sipRequest;
            _localEndPoint  = localEndPoint;
            _remoteEndPoint = remoteEndPoint;
            _sipAccount     = sipAccount;

            _rtpRemoteEndPoint                 = new IPEndPoint(remoteEndPoint.Address, remoteEndPoint.Port);
            _rtpChannel                        = new RTPChannel(_rtpRemoteEndPoint);
            _rtpChannel.OnFrameReady          += _rtpChannel_OnFrameReady;
            _rtpChannel.OnControlDataReceived += _rtpChannel_OnControlDataReceived;

            if (SipStatusHandler != null)
            {
                SipStatusHandler(SipServiceStatus.Inited);
            }
            _messageCore.SipRequestInited -= messageCore_SipRequestInited;
        }
Пример #13
0
        public event Action <byte[], int> OnRemoteVideoSampleReady;     // Fires when a remote video sample is ready for display.

        public RTPManager(bool includeAudio, bool includeVideo)
        {
            if (includeAudio)
            {
                // Create a UDP socket to use for sending and receiving RTP audio packets.
                _rtpAudioChannel = new RTPChannel();
                _rtpAudioChannel.SetFrameType(FrameTypesEnum.Audio);
                _rtpAudioChannel.ReservePorts(DEFAULT_START_RTP_PORT, DEFAULT_END_RTP_PORT);
                _rtpAudioChannel.OnFrameReady += AudioFrameReady;
            }

            if (includeVideo)
            {
                _rtpVideoChannel = new RTPChannel();
                _rtpVideoChannel.SetFrameType(FrameTypesEnum.VP8);
                _rtpVideoChannel.ReservePorts(DEFAULT_START_RTP_PORT, DEFAULT_END_RTP_PORT);
                _rtpVideoChannel.OnFrameReady            += VideoFrameReady;
                _rtpVideoChannel.OnRTPSocketDisconnected += () => { };
            }
        }
Пример #14
0
        public void RtpChannelCreateManyUnitTest()
        {
            logger.LogDebug("--> " + System.Reflection.MethodBase.GetCurrentMethod().Name);
            logger.BeginScope(System.Reflection.MethodBase.GetCurrentMethod().Name);

            List <RTPChannel> channels = new List <RTPChannel>();

            for (int i = 0; i < 10; i++)
            {
                RTPChannel channel = new RTPChannel(true, null);
                channels.Add(channel);
            }

            Assert.Equal(10, channels.Count);

            foreach (var channel in channels)
            {
                channel.Close("normal");
            }
        }
Пример #15
0
        private void Transport_SIPTransportRequestReceived(SIPEndPoint localSIPEndPoint, SIPEndPoint remoteEndPoint, SIPRequest sipRequest)
        {
            var endpoint = new SIPEndPoint(SIPProtocolsEnum.udp, publicIPAddress, localSIPEndPoint.Port);

            if (sipRequest.Method == SIPMethodsEnum.INVITE)
            {
                if (transaction != null)
                {
                    return;
                }

                logger.DebugFormat("{0} Incoming call from {1}", prefix, sipRequest.Header.From.FromURI.User);

                transaction = transport.CreateUASTransaction(sipRequest, remoteEndPoint, endpoint, null);
                agent       = new SIPServerUserAgent(
                    transport,
                    null,
                    sipRequest.Header.From.FromURI.User,
                    null,
                    SIPCallDirection.In,
                    null,
                    null,
                    null,
                    transaction);

                agent.CallCancelled       += Agent_CallCancelled;
                agent.TransactionComplete += Agent_TransactionComplete;

                agent.Progress(SIPResponseStatusCodesEnum.Trying, null, null, null, null);
                agent.Progress(SIPResponseStatusCodesEnum.Ringing, null, null, null, null);

                var answer  = SDP.ParseSDPDescription(agent.CallRequest.Body);
                var address = IPAddress.Parse(answer.Connection.ConnectionAddress);
                var port    = answer.Media.FirstOrDefault(m => m.Media == SDPMediaTypesEnum.audio).Port;
                var random  = Crypto.GetRandomInt(5).ToString();
                var sdp     = new SDP
                {
                    Version     = 2,
                    Username    = "******",
                    SessionId   = random,
                    Address     = localIPEndPoint.Address.ToString(),
                    SessionName = "redfox_" + random,
                    Timing      = "0 0",
                    Connection  = new SDPConnectionInformation(publicIPAddress.ToString())
                };

                rtpChannel = new RTPChannel
                {
                    DontTimeout    = true,
                    RemoteEndPoint = new IPEndPoint(address, port)
                };

                rtpChannel.SetFrameType(FrameTypesEnum.Audio);
                // TODO Fix hardcoded ports
                rtpChannel.ReservePorts(15000, 15090);
                rtpChannel.OnFrameReady += Channel_OnFrameReady;
                rtpChannel.Start();

                // Send some setup parameters to punch a hole in the firewall/router
                rtpChannel.SendRTPRaw(new byte[] { 80, 95, 198, 88, 55, 96, 225, 141, 215, 205, 185, 242, 00 });

                rtpChannel.OnControlDataReceived       += (b) => { logger.Debug($"{prefix} Control Data Received; {b.Length} bytes"); };
                rtpChannel.OnControlSocketDisconnected += () => { logger.Debug($"{prefix} Control Socket Disconnected"); };

                var announcement = new SDPMediaAnnouncement
                {
                    Media        = SDPMediaTypesEnum.audio,
                    MediaFormats = new List <SDPMediaFormat>()
                    {
                        new SDPMediaFormat((int)SDPMediaFormatsEnum.PCMU, "PCMU", 8000)
                    },
                    Port = rtpChannel.RTPPort
                };

                sdp.Media.Add(announcement);

                SetState(State.Listening, sipRequest.Header.From.FromURI.User);

                agent.Progress(SIPResponseStatusCodesEnum.Accepted, null, null, null, null);
                agent.Answer(SDP.SDP_MIME_CONTENTTYPE, sdp.ToString(), null, SIPDialogueTransferModesEnum.NotAllowed);

                SetState(State.Busy, "");
                return;
            }
            if (sipRequest.Method == SIPMethodsEnum.BYE)
            {
                if (State != State.Busy)
                {
                    return;
                }

                logger.DebugFormat("{0} Hangup from {1}", prefix, sipRequest.Header.From.FromURI.User);

                var noninvite = transport.CreateNonInviteTransaction(sipRequest, remoteEndPoint, endpoint, null);
                var response  = SIPTransport.GetResponse(sipRequest, SIPResponseStatusCodesEnum.Ok, null);

                noninvite.SendFinalResponse(response);

                SetState(State.Finished, Endpoint);

                rtpChannel.OnFrameReady -= Channel_OnFrameReady;
                rtpChannel.Close();

                agent.TransactionComplete -= Agent_TransactionComplete;
                agent.CallCancelled       -= Agent_CallCancelled;
                agent       = null;
                transaction = null;

                SetState(State.Ready, Endpoint);

                return;
            }
            if (sipRequest.Method == SIPMethodsEnum.ACK)
            {
            }
            if (sipRequest.Method == SIPMethodsEnum.CANCEL)
            {
            }
        }