Beispiel #1
0
        public void EndAuthenticateAsServer(IAsyncResult ar)
        {
            try
            {
                SIPConnection sipTLSConnection = (SIPConnection)ar.AsyncState;
                SslStream     sslStream        = (SslStream)sipTLSConnection.SIPStream;

                sslStream.EndAuthenticateAsServer(ar);

                // Set timeouts for the read and write to 5 seconds.
                sslStream.ReadTimeout  = 5000;
                sslStream.WriteTimeout = 5000;

                m_connectedSockets.Add(sipTLSConnection.RemoteEndPoint.ToString(), sipTLSConnection);

                sipTLSConnection.SIPSocketDisconnected += SIPTLSSocketDisconnected;
                sipTLSConnection.SIPMessageReceived    += SIPTLSMessageReceived;
                //byte[] receiveBuffer = new byte[MaxSIPTCPMessageSize];
                sipTLSConnection.SIPStream.BeginRead(sipTLSConnection.SocketBuffer, 0, MaxSIPTCPMessageSize, new AsyncCallback(ReceiveCallback), sipTLSConnection);
            }
            catch (Exception excp)
            {
                logger.Error("Exception SIPTLSChannel EndAuthenticateAsServer. " + excp);
                //throw excp;
            }
        }
Beispiel #2
0
        public void ReceiveCallback(IAsyncResult ar)
        {
            SIPConnection sipTLSConnection = (SIPConnection)ar.AsyncState;

            if (sipTLSConnection != null && sipTLSConnection.SIPStream != null && sipTLSConnection.SIPStream.CanRead)
            {
                try
                {
                    int bytesRead = sipTLSConnection.SIPStream.EndRead(ar);
                    if (sipTLSConnection.SocketReadCompleted(bytesRead))
                    {
                        sipTLSConnection.SIPStream.BeginRead(sipTLSConnection.SocketBuffer, sipTLSConnection.SocketBufferEndPosition, MaxSIPTCPMessageSize - sipTLSConnection.SocketBufferEndPosition, new AsyncCallback(ReceiveCallback), sipTLSConnection);
                    }
                }
                catch (SocketException sockExcp)  // Occurs if the remote end gets disconnected.
                {
                    logger.Warn("SocketException SIPTLSChannel ReceiveCallback. " + sockExcp);
                }
                catch (Exception excp)
                {
                    logger.Warn("Exception SIPTLSChannel ReceiveCallback. " + excp);
                    SIPTLSSocketDisconnected(sipTLSConnection.RemoteEndPoint);
                }
            }
        }
Beispiel #3
0
        private void AcceptConnections(string threadName)
        {
            try
            {
                Thread.CurrentThread.Name = threadName;

                logger.Debug("SIPTLSChannel socket on " + m_localSIPEndPoint + " accept connections thread started.");

                while (!Closed)
                {
                    try
                    {
                        TcpClient tcpClient = m_tlsServerListener.AcceptTcpClient();
                        tcpClient.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);

                        IPEndPoint remoteEndPoint = (IPEndPoint)tcpClient.Client.RemoteEndPoint;
                        logger.Debug("SIP TLS Channel connection accepted from " + remoteEndPoint + ".");

                        SslStream sslStream = new SslStream(tcpClient.GetStream(), false);

                        SIPConnection sipTLSConnection = new SIPConnection(this, tcpClient, sslStream, remoteEndPoint, SIPProtocolsEnum.tls, SIPConnectionsEnum.Listener);

                        sslStream.BeginAuthenticateAsServer(m_serverCertificate, EndAuthenticateAsServer, sipTLSConnection);

                        //sslStream.AuthenticateAsServer(m_serverCertificate, false, SslProtocols.Tls, false);
                        //// Display the properties and settings for the authenticated stream.
                        ////DisplaySecurityLevel(sslStream);
                        ////DisplaySecurityServices(sslStream);
                        ////DisplayCertificateInformation(sslStream);
                        ////DisplayStreamProperties(sslStream);

                        //// Set timeouts for the read and write to 5 seconds.
                        //sslStream.ReadTimeout = 5000;
                        //sslStream.WriteTimeout = 5000;

                        ////SIPConnection sipTLSConnection = new SIPConnection(this, sslStream, remoteEndPoint, SIPProtocolsEnum.tls, SIPConnectionsEnum.Listener);
                        //m_connectedSockets.Add(remoteEndPoint.ToString(), sipTLSConnection);

                        //sipTLSConnection.SIPSocketDisconnected += SIPTLSSocketDisconnected;
                        //sipTLSConnection.SIPMessageReceived += SIPTLSMessageReceived;
                        ////byte[] receiveBuffer = new byte[MaxSIPTCPMessageSize];
                        //sipTLSConnection.SIPStream.BeginRead(sipTLSConnection.SocketBuffer, 0, MaxSIPTCPMessageSize, new AsyncCallback(ReceiveCallback), sipTLSConnection);
                    }
                    catch (Exception e)
                    {
                        logger.Error("SIPTLSChannel Accept Connection Exception. " + e);
                        //sslStream.Close();
                        //tcpClient.Close();
                    }
                }

                logger.Debug("SIPTLSChannel socket on " + m_localSIPEndPoint + " listening halted.");
            }
            catch (Exception excp)
            {
                logger.Error("Exception SIPTLSChannel Listen. " + excp);
                //throw excp;
            }
        }
Beispiel #4
0
        private void EndConnect(IAsyncResult ar)
        {
            object[]   stateObj    = (object[])ar.AsyncState;
            TcpClient  tcpClient   = (TcpClient)stateObj[0];
            IPEndPoint dstEndPoint = (IPEndPoint)stateObj[1];

            byte[] buffer   = (byte[])stateObj[2];
            string serverCN = (string)stateObj[3];

            try
            {
                m_connectingSockets.Remove(dstEndPoint.ToString());

                tcpClient.EndConnect(ar);

                SslStream sslStream = new SslStream(tcpClient.GetStream(), false, new RemoteCertificateValidationCallback(ValidateServerCertificate), null);
                //DisplayCertificateInformation(sslStream);

                SIPConnection callerConnection = new SIPConnection(this, tcpClient, sslStream, dstEndPoint, SIPProtocolsEnum.tls, SIPConnectionsEnum.Caller);
                sslStream.BeginAuthenticateAsClient(serverCN, EndAuthenticateAsClient, new object[] { tcpClient, dstEndPoint, buffer, callerConnection });
                //sslStream.AuthenticateAsClient(serverCN);

                //if (tcpClient != null && tcpClient.Connected)
                //{
                //    SIPConnection callerConnection = new SIPConnection(this, sslStream, dstEndPoint, SIPProtocolsEnum.tls, SIPConnectionsEnum.Caller);
                //    m_connectedSockets.Add(dstEndPoint.ToString(), callerConnection);

                //    callerConnection.SIPSocketDisconnected += SIPTLSSocketDisconnected;
                //    callerConnection.SIPMessageReceived += SIPTLSMessageReceived;
                //    //byte[] receiveBuffer = new byte[MaxSIPTCPMessageSize];
                //    callerConnection.SIPStream.BeginRead(callerConnection.SocketBuffer, 0, MaxSIPTCPMessageSize, new AsyncCallback(ReceiveCallback), callerConnection);

                //    logger.Debug("Established TLS connection to " + dstEndPoint + ".");

                //    callerConnection.SIPStream.BeginWrite(buffer, 0, buffer.Length, EndSend, callerConnection);
                //}
                //else
                //{
                //    logger.Warn("Could not establish TLS connection to " + dstEndPoint + ".");
                //}
            }
            catch (Exception excp)
            {
                logger.Error("Exception SIPTLSChannel EndConnect. " + excp);

                if (tcpClient != null)
                {
                    try
                    {
                        tcpClient.Close();
                    }
                    catch (Exception closeExcp)
                    {
                        logger.Warn("Exception SIPTLSChannel EndConnect Close TCP Client. " + closeExcp);
                    }
                }
            }
        }
Beispiel #5
0
        private void AcceptConnections(string threadName)
        {
            try
            {
                Thread.CurrentThread.Name = threadName;

                logger.Debug("SIPTCPChannel socket on " + m_localSIPEndPoint + " accept connections thread started.");

                while (!Closed)
                {
                    try
                    {
                        TcpClient tcpClient = m_tcpServerListener.AcceptTcpClient();

                        if (!Closed)
                        {
                            tcpClient.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
                            tcpClient.LingerState = new LingerOption(false, 0);
                            //clientSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);

                            //IPEndPoint remoteEndPoint = (IPEndPoint)clientSocket.RemoteEndPoint;
                            IPEndPoint remoteEndPoint = (IPEndPoint)tcpClient.Client.RemoteEndPoint;
                            logger.Debug("SIP TCP Channel connection accepted from " + remoteEndPoint + ".");

                            //SIPTCPConnection sipTCPClient = new SIPTCPConnection(this, clientSocket, remoteEndPoint, SIPTCPConnectionsEnum.Listener);
                            SIPConnection sipTCPConnection = new SIPConnection(this, tcpClient, tcpClient.GetStream(), remoteEndPoint, SIPProtocolsEnum.tcp, SIPConnectionsEnum.Listener);
                            //SIPConnection sipTCPClient = new SIPConnection(this, tcpClient.Client, remoteEndPoint, SIPProtocolsEnum.tcp, SIPConnectionsEnum.Listener);

                            lock (m_connectedSockets)
                            {
                                m_connectedSockets.Add(remoteEndPoint.ToString(), sipTCPConnection);
                            }

                            sipTCPConnection.SIPSocketDisconnected += SIPTCPSocketDisconnected;
                            sipTCPConnection.SIPMessageReceived    += SIPTCPMessageReceived;
                            // clientSocket.BeginReceive(sipTCPClient.SocketBuffer, 0, SIPTCPConnection.MaxSIPTCPMessageSize, SocketFlags.None, new AsyncCallback(sipTCPClient.ReceiveCallback), null);
                            //byte[] receiveBuffer = new byte[MaxSIPTCPMessageSize];
                            sipTCPConnection.SIPStream.BeginRead(sipTCPConnection.SocketBuffer, 0, MaxSIPTCPMessageSize, new AsyncCallback(ReceiveCallback), sipTCPConnection);
                        }
                    }
                    catch (Exception acceptExcp)
                    {
                        // This exception gets thrown if the remote end disconnects during the socket accept.
                        logger.Warn("Exception SIPTCPChannel  accepting socket (" + acceptExcp.GetType() + "). " + acceptExcp.Message);
                    }
                }

                logger.Debug("SIPTCPChannel socket on " + m_localSIPEndPoint + " listening halted.");
            }
            catch (Exception excp)
            {
                logger.Error("Exception SIPTCPChannel Listen. " + excp.Message);
                //throw excp;
            }
        }
Beispiel #6
0
 private void EndSend(IAsyncResult ar)
 {
     try
     {
         SIPConnection sipConnection = (SIPConnection)ar.AsyncState;
         sipConnection.SIPStream.EndWrite(ar);
     }
     catch (Exception excp)
     {
         logger.Error("Exception EndSend. " + excp);
     }
 }
Beispiel #7
0
        private void EndSend(IAsyncResult ar)
        {
            try
            {
                SIPConnection sipTCPConnection = (SIPConnection)ar.AsyncState;
                sipTCPConnection.SIPStream.EndWrite(ar);

                //logger.Debug("EndSend on TCP " + SIPChannelEndPoint.ToString() + ".");
            }
            catch (Exception excp)
            {
                logger.Error("Exception EndSend. " + excp.Message);
            }
        }
Beispiel #8
0
        private void EndAuthenticateAsClient(IAsyncResult ar)
        {
            try
            {
                object[]      stateObj         = (object[])ar.AsyncState;
                TcpClient     tcpClient        = (TcpClient)stateObj[0];
                IPEndPoint    dstEndPoint      = (IPEndPoint)stateObj[1];
                byte[]        buffer           = (byte[])stateObj[2];
                SIPConnection callerConnection = (SIPConnection)stateObj[3];

                SslStream sslStream = (SslStream)callerConnection.SIPStream;

                sslStream.EndAuthenticateAsClient(ar);

                if (tcpClient != null && tcpClient.Connected)
                {
                    //SIPConnection callerConnection = new SIPConnection(this, sslStream, dstEndPoint, SIPProtocolsEnum.tls, SIPConnectionsEnum.Caller);
                    m_connectedSockets.Add(callerConnection.RemoteEndPoint.ToString(), callerConnection);

                    callerConnection.SIPSocketDisconnected += SIPTLSSocketDisconnected;
                    callerConnection.SIPMessageReceived    += SIPTLSMessageReceived;
                    //byte[] receiveBuffer = new byte[MaxSIPTCPMessageSize];
                    callerConnection.SIPStream.BeginRead(callerConnection.SocketBuffer, 0, MaxSIPTCPMessageSize, new AsyncCallback(ReceiveCallback), callerConnection);

                    logger.Debug("Established TLS connection to " + callerConnection.RemoteEndPoint + ".");

                    callerConnection.SIPStream.BeginWrite(buffer, 0, buffer.Length, EndSend, callerConnection);
                }
                else
                {
                    logger.Warn("Could not establish TLS connection to " + callerConnection.RemoteEndPoint + ".");
                }
            }
            catch (Exception excp)
            {
                logger.Error("Exception SIPTLSChannel EndAuthenticateAsClient. " + excp);
            }
        }
Beispiel #9
0
        public override void Send(IPEndPoint dstEndPoint, byte[] buffer, string serverCertificateName)
        {
            try
            {
                if (buffer == null)
                {
                    throw new ApplicationException("An empty buffer was specified to Send in SIPTLSChannel.");
                }
                else if (LocalTCPSockets.Contains(dstEndPoint.ToString()))
                {
                    logger.Error("SIPTLSChannel blocked Send to " + dstEndPoint.ToString() + " as it was identified as a locally hosted TCP socket.\r\n" + Encoding.UTF8.GetString(buffer));
                    throw new ApplicationException("A Send call was made in SIPTLSChannel to send to another local TCP socket.");
                }
                else
                {
                    bool sent = false;
                    bool existingConnection = false;

                    // Lookup a client socket that is connected to the destination.
                    //m_sipConn(buffer, buffer.Length, destinationEndPoint);
                    if (m_connectedSockets.ContainsKey(dstEndPoint.ToString()))
                    {
                        existingConnection = true;
                        SIPConnection sipTLSClient = m_connectedSockets[dstEndPoint.ToString()];

                        try
                        {
                            if (sipTLSClient.SIPStream != null && sipTLSClient.SIPStream.CanWrite)
                            {
                                sipTLSClient.SIPStream.BeginWrite(buffer, 0, buffer.Length, new AsyncCallback(EndSend), sipTLSClient);
                                sent = true;
                                sipTLSClient.LastTransmission = DateTime.Now;
                            }
                            else
                            {
                                logger.Warn("A SIPTLSChannel write operation to " + dstEndPoint + " was dropped as the stream was null or could not be written to.");
                            }
                        }
                        catch (SocketException)
                        {
                            logger.Warn("Could not send to TLS socket " + dstEndPoint + ", closing and removing.");
                            sipTLSClient.SIPStream.Close();
                            m_connectedSockets.Remove(dstEndPoint.ToString());
                        }
                    }

                    if (!sent && !existingConnection)
                    {
                        if (serverCertificateName.IsNullOrBlank())
                        {
                            throw new ApplicationException("The SIP TLS Channel must be provided with the name of the expected server certificate, please use alternative method.");
                        }

                        if (!m_connectingSockets.Contains(dstEndPoint.ToString()))
                        {
                            logger.Debug("Attempting to establish TLS connection to " + dstEndPoint + ".");
                            TcpClient tcpClient = new TcpClient();
                            tcpClient.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
                            tcpClient.Client.Bind(m_localSIPEndPoint.GetIPEndPoint());

                            m_connectingSockets.Add(dstEndPoint.ToString());
                            tcpClient.BeginConnect(dstEndPoint.Address, dstEndPoint.Port, EndConnect, new object[] { tcpClient, dstEndPoint, buffer, serverCertificateName });
                        }
                        else
                        {
                            logger.Warn("Could not send SIP packet to TLS " + dstEndPoint + " and another connection was already in progress so dropping message.");
                        }
                    }
                }
            }
            catch (Exception excp)
            {
                logger.Error("Exception (" + excp.GetType().ToString() + ") SIPTLSChannel Send (sendto=>" + dstEndPoint + "). " + excp);
                throw excp;
            }
        }
Beispiel #10
0
        /// <summary>
        /// Periodically checks the established connections and closes any that have not had a transmission for a specified
        /// period or where the number of connections allowed per IP address has been exceeded. Only relevant for connection
        /// oriented channels such as TCP and TLS.
        /// </summary>
        protected void PruneConnections(string threadName)
        {
            try
            {
                Thread.CurrentThread.Name = threadName;

                Thread.Sleep(INITIALPRUNE_CONNECTIONS_DELAY);

                while (!Closed)
                {
                    bool checkComplete = false;

                    while (!checkComplete)
                    {
                        try
                        {
                            SIPConnection inactiveConnection = null;
                            Dictionary <string, SIPConnection> connections = GetConnectionsList();

                            lock (connections)
                            {
                                var inactiveConnectionKey = (from connection in connections
                                                             where connection.Value.LastTransmission < DateTime.Now.AddMinutes(PRUNE_NOTRANSMISSION_MINUTES * -1)
                                                             select connection.Key).FirstOrDefault();

                                if (inactiveConnectionKey != null)
                                {
                                    inactiveConnection = connections[inactiveConnectionKey];
                                    connections.Remove(inactiveConnectionKey);
                                }
                            }

                            if (inactiveConnection != null)
                            {
                                logger.Debug("Pruning inactive connection on " + SIPChannelContactURI + " to remote end point " + inactiveConnection.RemoteEndPoint.ToString() + ".");
                                inactiveConnection.Close();
                            }
                            else
                            {
                                checkComplete = true;
                            }
                        }
                        catch (SocketException)
                        {
                            // Will be thrown if the socket is already closed.
                        }
                        catch (Exception pruneExcp)
                        {
                            logger.Error("Exception PruneConnections (pruning). " + pruneExcp.Message);
                            checkComplete = true;
                        }
                    }

                    Thread.Sleep(PRUNE_CONNECTIONS_INTERVAL);
                    checkComplete = false;
                }

                logger.Debug("SIPChannel socket on " + m_localSIPEndPoint.ToString() + " pruning connections halted.");
            }
            catch (Exception excp)
            {
                logger.Error("Exception SIPChannel PruneConnections. " + excp.Message);
            }
        }
Beispiel #11
0
        /// <summary>
        /// Processes the receive buffer after a read from the connected socket.
        /// </summary>
        /// <param name="bytesRead">The number of bytes that were read into the receive buffer.</param>
        /// <returns>True if the receive was processed correctly, false if the socket returned 0 bytes or was disconnected.</returns>
        public bool SocketReadCompleted(int bytesRead)
        {
            try
            {
                if (bytesRead > 0)
                {
                    SocketBufferEndPosition += bytesRead;
                    int bytesSkipped = 0;

                    // Attempt to extract a SIP message from the receive buffer.
                    byte[] sipMsgBuffer = SIPConnection.ProcessReceive(SocketBuffer, 0, SocketBufferEndPosition, out bytesSkipped);

                    while (sipMsgBuffer != null)
                    {
                        // A SIP message is available.
                        if (SIPMessageReceived != null)
                        {
                            LastTransmission = DateTime.Now;
                            SIPMessageReceived(m_owningChannel, new SIPEndPoint(SIPProtocolsEnum.tcp, RemoteEndPoint), sipMsgBuffer);
                        }

                        SocketBufferEndPosition -= (sipMsgBuffer.Length + bytesSkipped);

                        if (SocketBufferEndPosition == 0)
                        {
                            //Array.Clear(SocketBuffer, 0, SocketBuffer.Length);
                            break;
                        }
                        else
                        {
                            // Do a left shift on the receive array.
                            Array.Copy(SocketBuffer, sipMsgBuffer.Length + bytesSkipped, SocketBuffer, 0, SocketBufferEndPosition);
                            //Array.Clear(SocketBuffer, SocketBufferEndPosition, SocketBuffer.Length - SocketBufferEndPosition);

                            // Try and extract another SIP message from the receive buffer.
                            sipMsgBuffer = SIPConnection.ProcessReceive(SocketBuffer, 0, SocketBufferEndPosition, out bytesSkipped);
                        }
                    }

                    return(true);
                }
                else
                {
                    //logger.Debug("SIP " + ConnectionProtocol + " socket to " + RemoteEndPoint + " was disconnected, closing.");
                    //SIPStream.Close();
                    Close();
                    SIPSocketDisconnected(RemoteEndPoint);

                    return(false);
                }
            }
            catch (ObjectDisposedException)
            {
                // Will occur if the owning channel closed the connection.
                SIPSocketDisconnected(RemoteEndPoint);
                return(false);
            }
            catch (SocketException)
            {
                // Will occur if the owning channel closed the connection.
                SIPSocketDisconnected(RemoteEndPoint);
                return(false);
            }
            catch (Exception excp)
            {
                logger.Error("Exception SIPConnection SocketReadCompleted. " + excp.Message);
                throw;
            }
        }
Beispiel #12
0
        private void EndConnect(IAsyncResult ar)
        {
            bool       connected   = false;
            IPEndPoint dstEndPoint = null;

            try
            {
                object[]  stateObj  = (object[])ar.AsyncState;
                TcpClient tcpClient = (TcpClient)stateObj[0];
                dstEndPoint = (IPEndPoint)stateObj[1];
                byte[] buffer = (byte[])stateObj[2];

                m_connectingSockets.Remove(dstEndPoint.ToString());

                tcpClient.EndConnect(ar);

                if (tcpClient != null && tcpClient.Connected)
                {
                    logger.Debug("Established TCP connection to " + dstEndPoint + ".");
                    connected = true;

                    m_connectionFailureStrikes.Remove(dstEndPoint.ToString());
                    m_connectionFailures.Remove(dstEndPoint.ToString());

                    SIPConnection callerConnection = new SIPConnection(this, tcpClient, tcpClient.GetStream(), dstEndPoint, SIPProtocolsEnum.tcp, SIPConnectionsEnum.Caller);
                    m_connectedSockets.Add(dstEndPoint.ToString(), callerConnection);

                    callerConnection.SIPSocketDisconnected += SIPTCPSocketDisconnected;
                    callerConnection.SIPMessageReceived    += SIPTCPMessageReceived;
                    //byte[] receiveBuffer = new byte[MaxSIPTCPMessageSize];
                    callerConnection.SIPStream.BeginRead(callerConnection.SocketBuffer, 0, MaxSIPTCPMessageSize, new AsyncCallback(ReceiveCallback), callerConnection);
                    callerConnection.SIPStream.BeginWrite(buffer, 0, buffer.Length, EndSend, callerConnection);
                }
                else
                {
                    logger.Warn("Could not establish TCP connection to " + dstEndPoint + ".");
                }
            }
            catch (SocketException sockExcp)
            {
                logger.Warn("SocketException SIPTCPChannel EndConnect. " + sockExcp.Message);
            }
            catch (Exception excp)
            {
                logger.Error("Exception SIPTCPChannel EndConnect (" + excp.GetType() + "). " + excp.Message);
            }
            finally
            {
                if (!connected && dstEndPoint != null)
                {
                    if (m_connectionFailureStrikes.ContainsKey(dstEndPoint.ToString()))
                    {
                        m_connectionFailureStrikes[dstEndPoint.ToString()] = m_connectionFailureStrikes[dstEndPoint.ToString()] + 1;
                    }
                    else
                    {
                        m_connectionFailureStrikes.Add(dstEndPoint.ToString(), 1);
                    }

                    if (m_connectionFailureStrikes[dstEndPoint.ToString()] >= CONNECTION_ATTEMPTS_ALLOWED)
                    {
                        if (!m_connectionFailures.ContainsKey(dstEndPoint.ToString()))
                        {
                            m_connectionFailures.Add(dstEndPoint.ToString(), DateTime.Now);
                        }

                        m_connectionFailureStrikes.Remove(dstEndPoint.ToString());
                    }
                }
            }
        }
Beispiel #13
0
        public override void Send(IPEndPoint dstEndPoint, byte[] buffer)
        {
            try
            {
                if (buffer == null)
                {
                    throw new ApplicationException("An empty buffer was specified to Send in SIPTCPChannel.");
                }
                else if (LocalTCPSockets.Contains(dstEndPoint.ToString()))
                {
                    logger.Error("SIPTCPChannel blocked Send to " + dstEndPoint.ToString() + " as it was identified as a locally hosted TCP socket.\r\n" + Encoding.UTF8.GetString(buffer));
                    throw new ApplicationException("A Send call was made in SIPTCPChannel to send to another local TCP socket.");
                }
                else
                {
                    bool sent = false;

                    // Lookup a client socket that is connected to the destination.
                    //m_sipConn(buffer, buffer.Length, destinationEndPoint);
                    if (m_connectedSockets.ContainsKey(dstEndPoint.ToString()))
                    {
                        SIPConnection sipTCPClient = m_connectedSockets[dstEndPoint.ToString()];

                        try
                        {
                            //logger.Warn("TCP channel BeginWrite from " + SIPChannelEndPoint.ToString() + " to " + sipTCPClient.RemoteEndPoint + ": " + Encoding.ASCII.GetString(buffer, 0, 32) + ".");
                            sipTCPClient.SIPStream.BeginWrite(buffer, 0, buffer.Length, new AsyncCallback(EndSend), sipTCPClient);
                            //logger.Warn("TCP channel BeginWrite complete from " + SIPChannelEndPoint.ToString() + " to " + sipTCPClient.RemoteEndPoint + ".");
                            //sipTCPClient.SIPStream.Flush();
                            sent = true;
                            sipTCPClient.LastTransmission = DateTime.Now;
                        }
                        catch (SocketException)
                        {
                            logger.Warn("Could not send to TCP socket " + dstEndPoint + ", closing and removing.");
                            sipTCPClient.SIPStream.Close();
                            m_connectedSockets.Remove(dstEndPoint.ToString());
                        }
                    }

                    if (!sent)
                    {
                        if (m_connectionFailures.ContainsKey(dstEndPoint.ToString()) && m_connectionFailures[dstEndPoint.ToString()] < DateTime.Now.AddSeconds(FAILED_CONNECTION_DONTUSE_INTERVAL * -1))
                        {
                            m_connectionFailures.Remove(dstEndPoint.ToString());
                        }

                        if (m_connectionFailures.ContainsKey(dstEndPoint.ToString()))
                        {
                            throw new ApplicationException("TCP connection attempt to " + dstEndPoint.ToString() + " was not attempted, too many failures.");
                        }
                        else if (!m_connectingSockets.Contains(dstEndPoint.ToString()))
                        {
                            logger.Debug("Attempting to establish TCP connection to " + dstEndPoint + ".");

                            TcpClient tcpClient = new TcpClient();
                            tcpClient.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
                            tcpClient.Client.Bind(m_localSIPEndPoint.GetIPEndPoint());

                            m_connectingSockets.Add(dstEndPoint.ToString());
                            tcpClient.BeginConnect(dstEndPoint.Address, dstEndPoint.Port, EndConnect, new object[] { tcpClient, dstEndPoint, buffer });
                        }
                        else
                        {
                            //logger.Warn("Could not send SIP packet to TCP " + dstEndPoint + " and another connection was already in progress so dropping message.");
                        }
                    }
                }
            }
            catch (ApplicationException appExcp)
            {
                logger.Warn("ApplicationException SIPTCPChannel Send (sendto=>" + dstEndPoint + "). " + appExcp.Message);
                throw;
            }
            catch (Exception excp)
            {
                logger.Error("Exception (" + excp.GetType().ToString() + ") SIPTCPChannel Send (sendto=>" + dstEndPoint + "). " + excp.Message);
                throw;
            }
        }