예제 #1
0
        /// <summary>
        /// An asynchronous task that attempts to send a single OPTIONS request.
        /// </summary>
        /// <param name="sipTransport">The transport object to use for the send.</param>
        /// <param name="dst">The destination end point to send the request to.</param>
        /// <returns>The received IP address in the response Via header. This indicates the local IP address that was used to
        /// reach the destination.</returns>
        private static async Task <IPAddress> SendOptionsTaskAsync(SIPTransport sipTransport, SIPURI dst)
        {
            TaskCompletionSource <IPAddress> tcs = new TaskCompletionSource <IPAddress>();

            try
            {
                sipTransport.SIPTransportResponseReceived += (SIPEndPoint localSIPEndPoint, SIPEndPoint remoteEndPoint, SIPResponse sipResponse) =>
                {
                    Log.LogDebug($"Response received {localSIPEndPoint.ToString()}<-{remoteEndPoint.ToString()}: {sipResponse.ShortDescription}");
                    //Log.LogDebug(sipResponse.ToString());

                    tcs.SetResult(IPAddress.Parse(sipResponse.Header.Vias.TopViaHeader.ReceivedFromIPAddress));
                };

                var optionsRequest = sipTransport.GetRequest(SIPMethodsEnum.OPTIONS, dst);

                //Log.LogDebug(optionsRequest.ToString());

                SocketError sendResult = await sipTransport.SendRequestAsync(optionsRequest);

                if (sendResult != SocketError.Success)
                {
                    Log.LogWarning($"Attempt to send request failed with {sendResult}.");
                    tcs.SetResult(null);
                }
            }
            catch (Exception excp)
            {
                Log.LogError($"Exception SendOptionsTask. {excp.Message}");
                tcs.SetResult(null);
            }

            return(await tcs.Task);
        }
        private SIPRequest GetRegistrationRequest(SIPEndPoint localSIPEndPoint)
        {
            try
            {
                string realm = (m_realm != null) ? m_realm : IPSocket.ParseHostFromSocket(m_registrarHost);

                SIPURI registerURI = m_sipAccountAOR.CopyOf();
                registerURI.User = null;

                SIPRequest registerRequest = m_sipTransport.GetRequest(
                    SIPMethodsEnum.REGISTER,
                    registerURI,
                    new SIPToHeader(null, m_sipAccountAOR, null),
                    localSIPEndPoint);

                registerRequest.Header.From       = new SIPFromHeader(null, m_sipAccountAOR, CallProperties.CreateNewTag());
                registerRequest.Header.Contact[0] = new SIPContactHeader(null, m_contactURI);
                registerRequest.Header.CSeq       = ++m_cseq;
                registerRequest.Header.CallId     = m_callID;
                registerRequest.Header.UserAgent  = (!UserAgent.IsNullOrBlank()) ? UserAgent : m_userAgent;
                registerRequest.Header.Expires    = m_expiry;

                return(registerRequest);
            }
            catch (Exception excp)
            {
                logger.LogError("Exception GetRegistrationRequest. " + excp.Message);
                throw excp;
            }
        }
예제 #3
0
        /// <summary>
        /// Initiates a SUBSCRIBE request to a notification server.
        /// </summary>
        /// <param name="subscribeToURI">The SIP user that dialog notifications are being subscribed to.</param>
        public void Subscribe(SIPURI subscribeURI, int expiry, SIPEventPackage sipEventPackage, string subscribeCallID, SIPURI contactURI)
        {
            try
            {
                if (m_attempts >= MAX_SUBSCRIBE_ATTEMPTS)
                {
                    Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.NotifierClient, SIPMonitorEventTypesEnum.SubscribeFailed, "Susbcription to " + subscribeURI.ToString() + " reached the maximum number of allowed attempts without a failure condition.", null));
                    m_subscribed = false;
                    SubscriptionFailed(subscribeURI, SIPResponseStatusCodesEnum.InternalServerError, "Subscription reached the maximum number of allowed attempts.");
                    m_waitForSubscribeResponse.Set();
                }
                else
                {
                    m_attempts++;
                    m_localCSeq++;

                    SIPRequest subscribeRequest = m_sipTransport.GetRequest(
                        SIPMethodsEnum.SUBSCRIBE,
                        m_resourceURI,
                        new SIPToHeader(null, subscribeURI, m_subscriptionToTag),
                        null);


                    if (contactURI != null)
                    {
                        subscribeRequest.Header.Contact = new List <SIPContactHeader>()
                        {
                            new SIPContactHeader(null, contactURI)
                        };
                    }

                    subscribeRequest.Header.From    = new SIPFromHeader(null, new SIPURI(m_authUsername, m_authDomain, null, SIPSchemesEnum.sip, SIPProtocolsEnum.udp), m_subscriptionFromTag);
                    subscribeRequest.Header.CSeq    = m_localCSeq;
                    subscribeRequest.Header.Expires = expiry;
                    subscribeRequest.Header.Event   = sipEventPackage.ToString();
                    subscribeRequest.Header.CallId  = subscribeCallID;

                    if (!m_filter.IsNullOrBlank())
                    {
                        subscribeRequest.Body = m_filter;
                        subscribeRequest.Header.ContentLength = m_filter.Length;
                        subscribeRequest.Header.ContentType   = m_filterTextType;
                    }

                    SIPNonInviteTransaction subscribeTransaction = m_sipTransport.CreateNonInviteTransaction(subscribeRequest, m_outboundProxy);
                    subscribeTransaction.NonInviteTransactionFinalResponseReceived += SubscribeTransactionFinalResponseReceived;
                    subscribeTransaction.NonInviteTransactionTimedOut += SubsribeTransactionTimedOut;

                    m_sipTransport.SendSIPReliable(subscribeTransaction);

                    LastSubscribeAttempt = DateTime.Now;
                }
            }
            catch (Exception excp)
            {
                logger.LogError("Exception SIPNotifierClient Subscribe. " + excp.Message);
                SubscriptionFailed(m_resourceURI, SIPResponseStatusCodesEnum.InternalServerError, "Exception Subscribing. " + excp.Message);
                m_waitForSubscribeResponse.Set();
            }
        }
예제 #4
0
        private SIPRequest ByeRequest()
        {
            SIPURI        uri        = new SIPURI(_cameraId, _remoteEndPoint.ToHost(), "");
            SIPRequest    byeRequest = _m_sipTransport.GetRequest(SIPMethodsEnum.BYE, uri);
            SIPFromHeader from       = new SIPFromHeader(null, _sipRequest.URI, _realReqSession.Header.From.FromTag);
            SIPHeader     header     = new SIPHeader(from, byeRequest.Header.To, _realReqSession.Header.CSeq, _realReqSession.Header.CallId);

            header.ContentType     = "application/DDCP";
            header.Expires         = byeRequest.Header.Expires;
            header.CSeqMethod      = byeRequest.Header.CSeqMethod;
            header.Vias            = byeRequest.Header.Vias;
            header.MaxForwards     = byeRequest.Header.MaxForwards;
            header.UserAgent       = _userAgent;
            byeRequest.Header.From = from;
            byeRequest.Header      = header;
            return(byeRequest);
        }
예제 #5
0
        /// <summary>
        /// Initialises a SIP tranpsort to act as the client in a single request/response exchange.
        /// </summary>
        /// <param name="testClientChannel">The client SIP channel to test.</param>
        /// <param name="serverUri">The URI of the server end point to test the client against.</param>
        /// <param name="tcs">The task completion source that this method will set if it receives the expected response.</param>
        private async Task RunClient(SIPChannel testClientChannel, SIPURI serverUri, TaskCompletionSource <bool> tcs)
        {
            logger.LogDebug($"Starting client task for {testClientChannel.ListeningSIPEndPoint}.");

            var clientSIPTransport = new SIPTransport();

            try
            {
                clientSIPTransport.AddSIPChannel(testClientChannel);

                logger.LogDebug($"RunClient test channel created on {testClientChannel.ListeningSIPEndPoint}.");

                clientSIPTransport.SIPTransportResponseReceived += (SIPEndPoint localSIPEndPoint, SIPEndPoint remoteEndPoint, SIPResponse sipResponse) =>
                {
                    logger.LogDebug($"Expected response received {localSIPEndPoint}<-{remoteEndPoint}: {sipResponse.ShortDescription}");

                    if (sipResponse.Status == SIPResponseStatusCodesEnum.Ok)
                    {
                        // Got the expected response, set the signal.
                        tcs.SetResult(true);
                    }
                };

                clientSIPTransport.SIPRequestOutTraceEvent += (SIPEndPoint localSIPEndPoint, SIPEndPoint remoteEndPoint, SIPRequest sipRequest) =>
                {
                    logger.LogDebug($"CLIENT REQUEST OUT {localSIPEndPoint}->{remoteEndPoint}");
                    logger.LogDebug(sipRequest.ToString());
                };

                clientSIPTransport.SIPResponseInTraceEvent += (SIPEndPoint localSIPEndPoint, SIPEndPoint remoteEndPoint, SIPResponse sipResponse) =>
                {
                    logger.LogDebug($"CLIENT RESPONSE IN {localSIPEndPoint}<-{remoteEndPoint}");
                    logger.LogDebug(sipResponse.ToString());
                };

                var optionsRequest = clientSIPTransport.GetRequest(SIPMethodsEnum.OPTIONS, serverUri);

                clientSIPTransport.SendRequest(optionsRequest);

                await tcs.Task;
            }
            catch (Exception excp)
            {
                logger.LogError($"Exception RunClient. {excp.Message}");
            }
            finally
            {
                logger.LogDebug($"Client task completed for {testClientChannel.ListeningSIPEndPoint}.");
                clientSIPTransport.Shutdown();
                logger.LogDebug($"Client task SIP transport shutdown.");
            }
        }
        private void SendNotifyRequestForSubscription(SIPEventSubscription subscription)
        {
            try
            {
                subscription.SubscriptionDialogue.CSeq++;

                //logger.Debug(DateTime.Now.ToString("HH:mm:ss:fff") + " Sending NOTIFY request for " + subscription.SubscriptionDialogue.Owner + " event " + subscription.SubscriptionEventPackage.ToString()
                //    + " and " + subscription.ResourceURI.ToString() + " to " + subscription.SubscriptionDialogue.RemoteTarget.ToString() + ", cseq=" + (subscription.SubscriptionDialogue.CSeq) + ".");

                int secondsRemaining = Convert.ToInt32(subscription.LastSubscribe.AddSeconds(subscription.Expiry).Subtract(DateTime.Now).TotalSeconds % Int32.MaxValue);

                SIPRequest notifyRequest = m_sipTransport.GetRequest(SIPMethodsEnum.NOTIFY, subscription.SubscriptionDialogue.RemoteTarget);
                notifyRequest.Header.From              = SIPFromHeader.ParseFromHeader(subscription.SubscriptionDialogue.LocalUserField.ToString());
                notifyRequest.Header.To                = SIPToHeader.ParseToHeader(subscription.SubscriptionDialogue.RemoteUserField.ToString());
                notifyRequest.Header.Event             = subscription.SubscriptionEventPackage.ToString();
                notifyRequest.Header.CSeq              = subscription.SubscriptionDialogue.CSeq;
                notifyRequest.Header.CallId            = subscription.SubscriptionDialogue.CallId;
                notifyRequest.Body                     = subscription.GetNotifyBody();
                notifyRequest.Header.ContentLength     = notifyRequest.Body.Length;
                notifyRequest.Header.SubscriptionState = "active;expires=" + secondsRemaining.ToString();
                notifyRequest.Header.ContentType       = subscription.NotifyContentType;
                notifyRequest.Header.ProxySendFrom     = subscription.SubscriptionDialogue.ProxySendFrom;

                // If the outbound proxy is a loopback address, as it will normally be for local deployments, then it cannot be overriden.
                SIPEndPoint dstEndPoint = m_outboundProxy;
                if (m_outboundProxy != null && IPAddress.IsLoopback(m_outboundProxy.Address))
                {
                    dstEndPoint = m_outboundProxy;
                }
                else if (subscription.SubscriptionDialogue.ProxySendFrom != null)
                {
                    // The proxy will always be listening on UDP port 5060 for requests from internal servers.
                    dstEndPoint = new SIPEndPoint(SIPProtocolsEnum.udp, new IPEndPoint(SIPEndPoint.ParseSIPEndPoint(subscription.SubscriptionDialogue.ProxySendFrom).Address, m_defaultSIPPort));
                }

                SIPNonInviteTransaction notifyTransaction = m_sipTransport.CreateNonInviteTransaction(notifyRequest, dstEndPoint, m_sipTransport.GetDefaultSIPEndPoint(dstEndPoint), m_outboundProxy);
                notifyTransaction.NonInviteTransactionFinalResponseReceived += (local, remote, transaction, response) => { NotifyTransactionFinalResponseReceived(local, remote, transaction, response, subscription); };
                m_sipTransport.SendSIPReliable(notifyTransaction);

                //logger.Debug(notifyRequest.ToString());

                MonitorLogEvent_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Notifier, SIPMonitorEventTypesEnum.NotifySent, "Notification sent for " + subscription.SubscriptionEventPackage.ToString() + " and " + subscription.ResourceURI.ToString() + " to " + subscription.SubscriptionDialogue.RemoteTarget.ToString() + " (cseq=" + notifyRequest.Header.CSeq + ").", subscription.SubscriptionDialogue.Owner));

                subscription.NotificationSent();
            }
            catch (Exception excp)
            {
                logger.Error("Exception SendNotifyRequestForSubscription. " + excp.Message);
                throw;
            }
        }
예제 #7
0
        /// <summary>
        /// 查询设备目录请求
        /// </summary>
        /// <returns></returns>
        private SIPRequest QueryItems(SIPEndPoint remoteEndPoint, string remoteSIPId)
        {
            string fromTag = CallProperties.CreateNewTag();
            string toTag   = CallProperties.CreateNewTag();
            int    cSeq    = CallProperties.CreateNewCSeq();
            string callId  = CallProperties.CreateNewCallId();

            SIPURI        remoteUri  = new SIPURI(remoteSIPId, remoteEndPoint.ToHost(), "");
            SIPURI        localUri   = new SIPURI(LocalSIPId, LocalEP.ToHost(), "");
            SIPFromHeader from       = new SIPFromHeader(null, localUri, fromTag);
            SIPToHeader   to         = new SIPToHeader(null, remoteUri, null);
            SIPRequest    catalogReq = Transport.GetRequest(SIPMethodsEnum.MESSAGE, remoteUri);

            catalogReq.Header.From        = from;
            catalogReq.Header.Contact     = null;
            catalogReq.Header.Allow       = null;
            catalogReq.Header.To          = to;
            catalogReq.Header.UserAgent   = SIPConstants.SIP_USERAGENT_STRING;
            catalogReq.Header.CSeq        = cSeq;
            catalogReq.Header.CallId      = callId;
            catalogReq.Header.ContentType = "application/MANSCDP+xml";

            return(catalogReq);
        }
예제 #8
0
        /// <summary>
        /// An asynchronous task that attempts to send a single OPTIONS request.
        /// </summary>
        /// <param name="sipTransport">The transport object to use for the send.</param>
        /// <param name="dst">The destination end point to send the request to.</param>
        /// <returns>True if the expected response was recevived, false otherwise.</returns>
        private static async Task <bool> SendOptionsTaskAsync(SIPTransport sipTransport, SIPURI dst)
        {
            TaskCompletionSource <bool> tcs = new TaskCompletionSource <bool>();

            try
            {
                sipTransport.SIPRequestOutTraceEvent += (localEP, remoteEP, req) =>
                {
                    logger.LogDebug($"Request sent: {localEP}->{remoteEP}");
                    logger.LogDebug(req.ToString());
                };

                sipTransport.SIPResponseInTraceEvent += (localEP, remoteEP, resp) =>
                {
                    logger.LogDebug($"Response received: {localEP}<-{remoteEP}");
                    logger.LogDebug(resp.ToString());
                };

                var optionsRequest = sipTransport.GetRequest(SIPMethodsEnum.OPTIONS, dst);

                sipTransport.SIPTransportResponseReceived += (SIPEndPoint localSIPEndPoint, SIPEndPoint remoteEndPoint, SIPResponse sipResponse) =>
                {
                    if (sipResponse.Header.CSeqMethod == SIPMethodsEnum.OPTIONS && sipResponse.Header.CallId == optionsRequest.Header.CallId)
                    {
                        logger.LogDebug($"Expected response received {localSIPEndPoint.ToString()}<-{remoteEndPoint.ToString()}: {sipResponse.ShortDescription}");
                        tcs.SetResult(true);
                    }
                };

                SocketError sendResult = await sipTransport.SendRequestAsync(optionsRequest);

                if (sendResult != SocketError.Success)
                {
                    logger.LogWarning($"Attempt to send request failed with {sendResult}.");
                    tcs.SetResult(false);
                }
            }
            catch (Exception excp)
            {
                logger.LogError($"Exception SendOptionsTask. {excp.Message}");
                tcs.SetResult(false);
            }

            return(await tcs.Task);
        }
        /// <summary>
        /// 查询设备目录请求
        /// </summary>
        /// <returns></returns>
        private SIPRequest QueryItems(string fromTag, string toTag, int cSeq, string callId)
        {
            SIPURI        remoteUri  = new SIPURI(RemoteSIPId, RemoteEndPoint.ToHost(), "");
            SIPURI        localUri   = new SIPURI(LocalSIPId, LocalEndPoint.ToHost(), "");
            SIPFromHeader from       = new SIPFromHeader(null, localUri, fromTag);
            SIPToHeader   to         = new SIPToHeader(null, remoteUri, toTag);
            SIPRequest    catalogReq = Transport.GetRequest(SIPMethodsEnum.MESSAGE, remoteUri);

            catalogReq.Header.From        = from;
            catalogReq.Header.Contact     = null;
            catalogReq.Header.Allow       = null;
            catalogReq.Header.To          = to;
            catalogReq.Header.UserAgent   = UserAgent;
            catalogReq.Header.CSeq        = cSeq;
            catalogReq.Header.CallId      = callId;
            catalogReq.Header.ContentType = "application/MANSCDP+xml";
            return(catalogReq);
        }
        /// <summary>
        /// Initialises a SIP tranpsort to act as the client in a single request/response exchange.
        /// </summary>
        /// <param name="testClientChannel">The client SIP channel to test.</param>
        /// <param name="serverUri">The URI of the server end point to test the client against.</param>
        /// <param name="tcs">The task completion source that this method will set if it receives the expected response.</param>
        private async Task RunClient(SIPChannel testClientChannel, SIPURI serverUri, TaskCompletionSource <bool> tcs)
        {
            logger.LogDebug($"Starting client task for {testClientChannel.SIPChannelEndPoint.ToString()}.");

            var clientSIPTransport = new SIPTransport();

            try
            {
                clientSIPTransport.AddSIPChannel(testClientChannel);

                logger.LogDebug(clientSIPTransport.GetDefaultSIPEndPoint().ToString());

                clientSIPTransport.SIPTransportResponseReceived += (SIPEndPoint localSIPEndPoint, SIPEndPoint remoteEndPoint, SIPResponse sipResponse) =>
                {
                    logger.LogDebug($"Response received {localSIPEndPoint.ToString()}<-{remoteEndPoint.ToString()}: {sipResponse.ShortDescription}");
                    logger.LogDebug(sipResponse.ToString());

                    if (sipResponse.Status == SIPResponseStatusCodesEnum.Ok)
                    {
                        // Got the expected response, set the signal.
                        tcs.SetResult(true);
                    }
                };

                var optionsRequest = clientSIPTransport.GetRequest(SIPMethodsEnum.OPTIONS, serverUri);

                logger.LogDebug(optionsRequest.ToString());

                clientSIPTransport.SendRequest(optionsRequest);

                await tcs.Task;
            }
            finally
            {
                logger.LogDebug($"Client task completed for {testClientChannel.SIPChannelEndPoint.ToString()}.");
                clientSIPTransport.Shutdown();
            }
        }
 static void Main(string[] args)
 {
     try
     {
         var sipTransport = new SIPTransport(SIPDNSManager.ResolveSIPService, new SIPTransactionEngine());
         sipTransport.SIPTransportRequestReceived  += SIPRequestReceived;
         sipTransport.SIPTransportResponseReceived += SIPResponseReceived;
         X509Certificate2 cert       = new X509Certificate2("test-cert.cer");
         SIPTLSChannel    tlsChannel = new SIPTLSChannel(cert, new IPEndPoint(IPAddress.Any, 5061));
         sipTransport.AddSIPChannel(tlsChannel);
         var optionsReq = sipTransport.GetRequest(SIPMethodsEnum.OPTIONS, SIPURI.ParseSIPURI("sips:67.222.131.147:5061"));
         sipTransport.SendRequest(optionsReq);
     }
     catch (Exception excp)
     {
         Console.WriteLine("Exception Main. " + excp);
     }
     finally
     {
         Console.WriteLine("Press any key to exit...");
         Console.Read();
     }
 }
        public void TcpTrickleReceiveTest()
        {
            TaskCompletionSource <bool> testComplete = new TaskCompletionSource <bool>();

            IPEndPoint listenEP   = new IPEndPoint(IPAddress.Loopback, 9066);
            var        transport  = new SIPTransport();
            var        tcpChannel = new SIPTCPChannel(new IPEndPoint(IPAddress.Loopback, 9067));

            tcpChannel.DisableLocalTCPSocketsCheck = true;
            transport.AddSIPChannel(tcpChannel);

            int requestCount  = 10;
            int recvdReqCount = 0;

            Task.Run(() =>
            {
                TcpListener listener = new TcpListener(listenEP);
                listener.Start();
                var tcpClient = listener.AcceptTcpClient();
                logger.LogDebug($"TCP listener accepted client with remote end point {tcpClient.Client.RemoteEndPoint}.");
                for (int i = 0; i < requestCount; i++)
                {
                    logger.LogDebug($"Sending request {i}.");

                    var req         = transport.GetRequest(SIPMethodsEnum.OPTIONS, SIPURI.ParseSIPURIRelaxed($"{i}@sipsorcery.com"));
                    byte[] reqBytes = Encoding.UTF8.GetBytes(req.ToString());

                    tcpClient.GetStream().Write(reqBytes, 0, reqBytes.Length);
                    tcpClient.GetStream().Flush();

                    Task.Delay(30).Wait();
                }
                tcpClient.GetStream().Close();
            });

            transport.SIPTransportRequestReceived += (SIPEndPoint localSIPEndPoint, SIPEndPoint remoteEndPoint, SIPRequest sipRequest) =>
            {
                logger.LogDebug($"Request received {localSIPEndPoint.ToString()}<-{remoteEndPoint.ToString()}: {sipRequest.StatusLine}");
                logger.LogDebug(sipRequest.ToString());
                Interlocked.Increment(ref recvdReqCount);

                if (recvdReqCount == requestCount)
                {
                    testComplete.SetResult(true);
                }
            };

            transport.SIPTransportResponseReceived += (SIPEndPoint localSIPEndPoint, SIPEndPoint remoteEndPoint, SIPResponse sipResponse) =>
            {
                logger.LogDebug($"Response received {localSIPEndPoint.ToString()}<-{remoteEndPoint.ToString()}: {sipResponse.ShortDescription}");
                logger.LogDebug(sipResponse.ToString());
            };

            tcpChannel.ConnectClientAsync(listenEP, null, null).Wait();

            Task.WhenAny(new Task[] { testComplete.Task, Task.Delay(5000) }).Wait();

            transport.Shutdown();

            Assert.IsTrue(testComplete.Task.IsCompleted);
            Assert.IsTrue(testComplete.Task.Result);
            Assert.AreEqual(requestCount, recvdReqCount, $"The count of {recvdReqCount} for the requests received did not match what was expected.");
        }
예제 #13
0
        public void TcpTrickleReceiveTest()
        {
            TaskCompletionSource <bool> testComplete = new TaskCompletionSource <bool>();

            IPEndPoint listenEP   = new IPEndPoint(IPAddress.Loopback, 9067);
            var        transport  = new SIPTransport();
            var        tcpChannel = new SIPTCPChannel(new IPEndPoint(IPAddress.Loopback, 9066));

            tcpChannel.DisableLocalTCPSocketsCheck = true;
            transport.AddSIPChannel(tcpChannel);

            int requestCount  = 10;
            int recvdReqCount = 0;

            Task.Run(() =>
            {
                try
                {
                    TcpListener listener = new TcpListener(listenEP);
                    listener.Start();
                    var tcpClient = listener.AcceptTcpClient();
                    logger.LogDebug($"Dummy TCP listener accepted client with remote end point {tcpClient.Client.RemoteEndPoint}.");
                    for (int i = 0; i < requestCount; i++)
                    {
                        logger.LogDebug($"Sending request {i}.");

                        var req         = transport.GetRequest(SIPMethodsEnum.OPTIONS, tcpChannel.GetContactURI(SIPSchemesEnum.sip, listenEP.Address));
                        byte[] reqBytes = Encoding.UTF8.GetBytes(req.ToString());

                        tcpClient.GetStream().Write(reqBytes, 0, reqBytes.Length);
                        tcpClient.GetStream().Flush();

                        Task.Delay(30).Wait();
                    }
                    tcpClient.GetStream().Close();
                }
                catch (Exception excp)
                {
                    logger.LogError($"Exception on dummy TCP listener task. {excp.Message}");
                    testComplete.SetResult(false);
                }
            });

            transport.SIPTransportRequestReceived += (SIPEndPoint localSIPEndPoint, SIPEndPoint remoteEndPoint, SIPRequest sipRequest) =>
            {
                logger.LogDebug($"Request received {localSIPEndPoint.ToString()}<-{remoteEndPoint.ToString()}: {sipRequest.StatusLine}");
                logger.LogDebug(sipRequest.ToString());
                Interlocked.Increment(ref recvdReqCount);

                if (recvdReqCount == requestCount)
                {
                    testComplete.SetResult(true);
                }
            };

            transport.SIPTransportResponseReceived += (SIPEndPoint localSIPEndPoint, SIPEndPoint remoteEndPoint, SIPResponse sipResponse) =>
            {
                logger.LogDebug($"Response received {localSIPEndPoint.ToString()}<-{remoteEndPoint.ToString()}: {sipResponse.ShortDescription}");
                logger.LogDebug(sipResponse.ToString());
            };

            tcpChannel.ConnectClientAsync(listenEP, null, null).Wait();

            Task.WhenAny(new Task[] { testComplete.Task, Task.Delay(TRANSPORT_TEST_TIMEOUT) }).Wait();

            transport.Shutdown();

            // Give the SIP transport time to shutdown. Keeps exception messages out of the logs.
            Task.Delay(500).Wait();

            Assert.True(testComplete.Task.IsCompleted);
            Assert.True(testComplete.Task.Result);
            Assert.True(requestCount == recvdReqCount, $"The count of {recvdReqCount} for the requests received did not match what was expected.");
        }