/// <summary>
        /// Processes failed sockets.
        /// </summary>
        /// <param name="exception">The source exception.</param>
        /// <param name="tcpSocketInfo">The socket.</param>
        private void SocketFailed(Exception exception, TcpSocketInfo tcpSocketInfo)
        {
            BinaryLogWriter binaryLogWriter = this.ITransportContext.BinaryLogWriter;

            try
            {
                lock (tcpSocketInfo)
                {
                    // if connection's resources were released
                    if (! tcpSocketInfo.IsValid)
                        return ;

                    tcpSocketInfo.IsValid = false;
                    tcpSocketInfo.LockForSending = true;
                }

                // LOG:
                if ( binaryLogWriter != null && binaryLogWriter[LogCategory.Connection] > 0 )
                {
                    binaryLogWriter.WriteEvent(LogCategory.Connection, "TcpConnectionManager.SocketFailed",
                        LogMessageType.ConnectionFailed, exception, null, tcpSocketInfo.Remote, null,
                        GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name,
                        tcpSocketInfo.ConnectionLevelSecurity,
                        tcpSocketInfo.ConnectionLevelSecurity == null ? null : tcpSocketInfo.ConnectionLevelSecurity.Name,
                        tcpSocketInfo.DbgConnectionId, 0, 0, 0, null, null, null, null,
                        "TCP connection has failed.");
                }

                // choose the type of the connection
                switch (tcpSocketInfo.GenuineConnectionType)
                {
                    case GenuineConnectionType.Persistent:
                        // determine whether the problem is critical
                        bool criticalError = ConnectionManager.IsExceptionCritical(exception as OperationException) ||
                            (int) this.ITransportContext.IParameterProvider[GenuineParameter.ReconnectionTries] <= 0 ||
                            ((TimeSpan) this.ITransportContext.IParameterProvider[GenuineParameter.SleepBetweenReconnections]).TotalMilliseconds <= 0;
                        bool queueWasOverflowed = false;

                        lock (tcpSocketInfo)
                        {
                            try
                            {
                                if (tcpSocketInfo.Message != null)
                                {
                                    tcpSocketInfo.Message.SerializedContent.Position = 0;
                                    tcpSocketInfo.MessageContainer.AddMessage(tcpSocketInfo.Message, false);
                                }
                                tcpSocketInfo.Message = null;
                            }
                            catch(Exception)
                            {
                                // queue is overrun
                                criticalError = true;
                                queueWasOverflowed = true;
                            }

                            try
                            {
                                // it automatically resets the stream position
                                tcpSocketInfo.MessagesSentSynchronously.MoveMessages(tcpSocketInfo.MessageContainer);
                            }
                            catch(Exception)
                            {
                                // queue is overrun
                                criticalError = true;
                                queueWasOverflowed = true;
                            }
                        }

                        // check whether it is a primary connection failure
                        if (! object.ReferenceEquals(tcpSocketInfo, this._persistent.Get(tcpSocketInfo.PrimaryRemoteUri, tcpSocketInfo.ConnectionName)) &&
                            ! queueWasOverflowed)
                        {
                            // it's either the previous stub or a parallel connection
                            // close it silently
                            GenuineThreadPool.QueueUserWorkItem(new WaitCallback(this.LowLevel_CloseConnection), tcpSocketInfo, false);
                            return ;
                        }

                        if (criticalError)
                        {
                            // LOG:
                            if ( binaryLogWriter != null && binaryLogWriter[LogCategory.Connection] > 0 )
                                binaryLogWriter.WriteEvent(LogCategory.Connection, "TcpConnectionManager.SocketFailed",
                                    LogMessageType.ConnectionReestablished, exception, null, tcpSocketInfo.Remote, null,
                                    GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name,
                                    null, null, tcpSocketInfo.DbgConnectionId, 0, 0, 0, null, null, null, null,
                                    "The connection cannot be reestablished due to the critical exception.");

                            this.Pool_DestroyPersistentConnection(tcpSocketInfo, exception);
                            return ;
                        }

                        // the error is not critical and the connection will be possibly restored
                        tcpSocketInfo.SignalState(GenuineEventType.GeneralConnectionReestablishing, exception, null);

                        try
                        {
                            // try to reestablish the connection
                            lock (this._persistent.SyncRoot)
                            {
                                TcpSocketInfo existentSocketInfo = this._persistent.Get(tcpSocketInfo.PrimaryRemoteUri, tcpSocketInfo.ConnectionName) as TcpSocketInfo;

                                // FIX 2.5.2. We can reestablish a connection if and only if no connections have been
                                // already established. Otherwise, we can overwrite currently established connection
                                if (ReferenceEquals(existentSocketInfo, tcpSocketInfo))
                                {
                                    lock (tcpSocketInfo)
                                    {
                                        // create stub connection
                                        TcpSocketInfo connectionWithQueue = new TcpSocketInfo(null, this.ITransportContext, tcpSocketInfo.ConnectionName
            #if DEBUG
                                            ,"Stub for the persistent connection while it's being established."
            #endif
                                            );
                                        connectionWithQueue.LockForSending = true;
                                        connectionWithQueue.MessageContainer = tcpSocketInfo.MessageContainer;
                                        connectionWithQueue.CloseConnectionAfterInactivity = GenuineUtility.ConvertToMilliseconds(this.ITransportContext.IParameterProvider[GenuineParameter.MaxTimeSpanToReconnect]);
                                        connectionWithQueue.Remote = tcpSocketInfo.Remote;

                                        connectionWithQueue.GenuineConnectionType = GenuineConnectionType.Persistent;
                                        connectionWithQueue.IsServer = tcpSocketInfo.IsServer;
                                        connectionWithQueue.Renew();

                                        // LOG:
                                        if ( binaryLogWriter != null && binaryLogWriter[LogCategory.Connection] > 0 )
                                            binaryLogWriter.WriteEvent(LogCategory.Connection, "TcpConnectionManager.SocketFailed",
                                                LogMessageType.ConnectionReestablishing, exception, null, tcpSocketInfo.Remote, null,
                                                GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name,
                                                null, null, connectionWithQueue.DbgConnectionId, 0, 0, 0, null, null, null, null,
                                                "The stub connection is constructed after exception.");

                                        connectionWithQueue.Remote.Renew(connectionWithQueue.CloseConnectionAfterInactivity, false);
                                        this._persistent.Set(tcpSocketInfo.PrimaryRemoteUri, tcpSocketInfo.ConnectionName, connectionWithQueue);

                                        // initiate connection reestablishing
                                        if (tcpSocketInfo.Remote.GenuinePersistentConnectionState == GenuinePersistentConnectionState.Opened)
                                            GenuineThreadPool.QueueUserWorkItem(new WaitCallback(this.ReestablishConnection), connectionWithQueue, true);
                                    }
                                }
                                else
                                {
                                    // LOG:
                                    if ( binaryLogWriter != null && binaryLogWriter[LogCategory.Connection] > 0 )
                                        binaryLogWriter.WriteEvent(LogCategory.Connection, "TcpConnectionManager.SocketFailed",
                                            LogMessageType.ConnectionReestablishing, exception, null, tcpSocketInfo.Remote, null,
                                            GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name,
                                            null, null, tcpSocketInfo.DbgConnectionId, 0, 0, 0, null, null, null, null,
                                            "The connection establishing has not been initiated since the original TcpSocketInfo is absent.");
                                }
                            }
                        }
                        catch(Exception ex)
                        {
                            // LOG:
                            if ( binaryLogWriter != null && binaryLogWriter[LogCategory.Connection] > 0 )
                                binaryLogWriter.WriteEvent(LogCategory.Connection, "TcpConnectionManager.SocketFailed",
                                    LogMessageType.ConnectionReestablishing, ex, null,
                                    tcpSocketInfo == null ? null : tcpSocketInfo.Remote, null,
                                    GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name,
                                    null, null, tcpSocketInfo.DbgConnectionId, 0, 0, 0, null, null, null, null,
                                    "An exception is occurred while trying to initiate connection reestablishing.");

                            // queue overloaded or fatal connection error
                            // force connection closing
                            this.SocketFailed(GenuineExceptions.Get_Receive_ConnectionClosed(), tcpSocketInfo);
                            return ;
                        }
                        break;

                    case GenuineConnectionType.Named:
                        // update the pool
                        string fullConnectionName = GetNamedConnectionName(tcpSocketInfo.IsServer, tcpSocketInfo.Remote, tcpSocketInfo.ConnectionName);

                        lock (this._named)
                        {
                            if (object.ReferenceEquals(this._named[fullConnectionName], tcpSocketInfo))
                                this._named.Remove(fullConnectionName);
                        }

                        // release queue
                        if (tcpSocketInfo.MessageContainer != null)
                            tcpSocketInfo.MessageContainer.Dispose(exception);

                        // release all of them
                        if (exception is GenuineExceptions.ChannelClosed || exception is GenuineExceptions.ServerHasBeenRestarted)
                            this.ITransportContext.KnownHosts.ReleaseHostResources(tcpSocketInfo.Remote, exception);
                        break;

                    case GenuineConnectionType.Invocation:
                        lock (tcpSocketInfo)
                        {
                            switch (tcpSocketInfo.TcpInvocationFiniteAutomatonState)
                            {
                                case TcpInvocationFiniteAutomatonState.ClientAvailable:
                                case TcpInvocationFiniteAutomatonState.ClientReceiving:
                                case TcpInvocationFiniteAutomatonState.ClientSending:
                                    // break client state cycle according to FA transition diagram
                                    lock (this._invocation)
                                    {
                                        ArrayList connections = (ArrayList) this._invocation[tcpSocketInfo.Remote.Url];
                                        if (connections != null)
                                            lock (connections)
                                                connections.Remove(tcpSocketInfo);
                                    }

                                    lock (tcpSocketInfo)
                                    {
                                        if (tcpSocketInfo.InitialMessage != null)
                                            if (tcpSocketInfo.InitialMessage.IsResendAfterFail && ! tcpSocketInfo.InitialMessage.IsSynchronous)
                                            {
                                                Message message = tcpSocketInfo.InitialMessage;
                                                tcpSocketInfo.InitialMessage = null;
                                                this.Send(message);
                                            }
                                            else
                                            {
                                                this.ITransportContext.IIncomingStreamHandler.DispatchException(tcpSocketInfo.InitialMessage, exception);
                                                tcpSocketInfo.InitialMessage = null;
                                            }
                                    }
                                    break;

                                case TcpInvocationFiniteAutomatonState.ServerAwaiting:
                                case TcpInvocationFiniteAutomatonState.ServerExecution:
                                case TcpInvocationFiniteAutomatonState.ServerSending:
                                    lock (this._knownInvocationConnections.SyncRoot)
                                        this._knownInvocationConnections.Remove(tcpSocketInfo.ConnectionName);
                                    break;
                            }
                        }
                        break;
                }

                // close the socket
                GenuineThreadPool.QueueUserWorkItem(new WaitCallback(LowLevel_CloseConnection), tcpSocketInfo, false);
            }
            catch(Exception ex)
            {
                // LOG:
                if ( binaryLogWriter != null )
                    binaryLogWriter.WriteImplementationWarningEvent("TcpConnectionManager.SocketFailed",
                        LogMessageType.Warning, ex, GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name,
                        "An unexpected exception is raised inside TcpConnectionManager.SocketFailed method. Most likely, something must be fixed.");
            }
        }
 /// <summary>
 /// Sets correct connection state and parameters when the current operation is successfully completed.
 /// </summary>
 /// <param name="tcpSocketInfo"></param>
 private void Pool_HandleAvailableInvocationOrOneWayConnection(TcpSocketInfo tcpSocketInfo)
 {
     if (tcpSocketInfo.CloseConnectionAfterInactivity <= 0)
         this.SocketFailed(GenuineExceptions.Get_Connection_LifetimeCycleEnded(), tcpSocketInfo);
     else
         tcpSocketInfo.Renew();
 }
        /// <summary>
        /// Sends the message to the remote host.
        /// Returns a response if corresponding Security Session parameters are set and 
        /// the initial message is not one-way.
        /// </summary>
        /// <param name="message">Message to be sent synchronously.</param>
        /// <param name="tcpSocketInfo">Socket connection.</param>
        private void SendSync(Message message, TcpSocketInfo tcpSocketInfo)
        {
            SyncMessageSlot syncMessageSlot = null;

            // try to acquire the read access
            bool sendAccessGranted = true;
            lock (tcpSocketInfo)
            {
                if (tcpSocketInfo.LockForSending)
                {
                    // wait until the current sending finishes
                    syncMessageSlot = new SyncMessageSlot();
                    tcpSocketInfo.MessageContainer.AddMessage(syncMessageSlot, false);
                    sendAccessGranted = false;
                }
                else
                    tcpSocketInfo.LockForSending = true;
            }

            if (! sendAccessGranted)
            {
                // allow SyncSinkStackProcess to influence on the message processing
                WaitHandle[] waitHandles = null;
                if (message.CancelSending != null)
                {
                    waitHandles = new WaitHandle[2];
                    waitHandles[1] = message.CancelSending;
                }
                else
                    waitHandles = new WaitHandle[1];
                waitHandles[0] = syncMessageSlot.ConnectionAvailable;

                // wait for any of events
                int milliseconds = GenuineUtility.GetMillisecondsLeft(message.FinishTime);
                if (milliseconds <= 0)
                    throw GenuineExceptions.Get_Send_ServerDidNotReply();

                int resultFlag = WaitHandle.WaitAny(waitHandles, milliseconds, false);
                if ( resultFlag == WaitHandle.WaitTimeout )
                {
                    lock (syncMessageSlot)
                    {
                        syncMessageSlot.IsValid = false;
                        // initiate sending of the next message
                        if (syncMessageSlot.TcpSocketInfo != null)
                            this.Pool_StartSending(syncMessageSlot.TcpSocketInfo);
                    }
                    throw GenuineExceptions.Get_Send_ServerDidNotReply();
                }

                if (resultFlag == 1)
                    throw GenuineExceptions.Get_Send_Timeout();

                // rethrow the exception
                if (syncMessageSlot.SyncWaitException != null)
                    throw OperationException.WrapException(syncMessageSlot.SyncWaitException);
                tcpSocketInfo = syncMessageSlot.TcpSocketInfo;
            }

            // send it
            this.LowLevel_SendSync(message, tcpSocketInfo);

            switch(tcpSocketInfo.GenuineConnectionType)
            {
                case GenuineConnectionType.Persistent:
                case GenuineConnectionType.Named:
                    message.IsResendAfterFail = false;
                    this.Pool_StartSending(tcpSocketInfo);
                    break;

                case GenuineConnectionType.Invocation:
                    // it's necessary to provide correct infomation, de bene esse
                    lock (tcpSocketInfo)
                    {
                        tcpSocketInfo.TcpInvocationFiniteAutomatonState = TcpInvocationFiniteAutomatonState.ClientReceiving;
                        tcpSocketInfo.Renew();
                    }

                    //					if (! tcpSocketInfo.IsServer && ! message.IsOneWay)
                    //					{
                    //						// read the response
                    //						using (Stream stream = this.LowLevel_ReadSync(tcpSocketInfo, message.FinishTime))
                    //							this.ITransportContext.IIncomingStreamHandler.HandleMessage(stream, tcpSocketInfo.Remote, tcpSocketInfo.GenuineConnectionType, tcpSocketInfo.ConnectionName, true, null, tcpSocketInfo.ConnectionLevelSecurity, null);
                    //					}

                    lock (tcpSocketInfo)
                    {
                        tcpSocketInfo.TcpInvocationFiniteAutomatonState = TcpInvocationFiniteAutomatonState.ClientAvailable;
                        tcpSocketInfo.Renew();
                    }
                    break;
            }
        }
        /// <summary>
        /// Acquires a connection according to message parameters or throw the corresponding exception
        /// if it's impossible.
        /// </summary>
        /// <param name="message">The message being sent.</param>
        /// <returns>The acquired connection.</returns>
        private TcpSocketInfo GetConnectionForSending(Message message)
        {
            BinaryLogWriter binaryLogWriter = this.ITransportContext.BinaryLogWriter;
            TcpSocketInfo tcpSocketInfo = null;
            string uri = null;
            bool isServer = false;
            string remoteUri = null;
            int remoteHostUniqueIdentifier;

            using (new ReaderAutoLocker(this._disposeLock))
            {
                if (this._disposed)
                    throw OperationException.WrapException(this._disposeReason);

                switch (message.SecuritySessionParameters.GenuineConnectionType)
                {
                    case GenuineConnectionType.Persistent:
                        uri = message.Recipient.Url;
                        if (message.ConnectionName == null)
                            message.ConnectionName = message.SecuritySessionParameters.ConnectionName;

                        lock (message.Recipient.PersistentConnectionEstablishingLock)
                        {
                            switch (message.Recipient.GenuinePersistentConnectionState)
                            {
                                case GenuinePersistentConnectionState.NotEstablished:
                                    if (message.Recipient.Url == null)
                                        throw GenuineExceptions.Get_Send_DestinationIsUnreachable(message.Recipient.Uri);
                                    message.Recipient.GenuinePersistentConnectionState = GenuinePersistentConnectionState.Opened;
                                    break;

                                case GenuinePersistentConnectionState.Accepted:
                                    isServer = true;
                                    uri = message.Recipient.Uri;
                                    break;
                            }

                            // if it's possible to establish a connection to the remote host
                            if (! isServer)
                            {
                                tcpSocketInfo = this._persistent.Get(uri, message.ConnectionName) as TcpSocketInfo;

                                if (tcpSocketInfo != null && !tcpSocketInfo.IsValid)
                                {
                                    this._persistent.Remove(uri, message.ConnectionName);
                                    tcpSocketInfo = null;
                                }

                                if (tcpSocketInfo == null)
                                {
                                    // try to establish a persistent connection
                                    tcpSocketInfo = LowLevel_OpenConnection(message.Recipient, GenuineConnectionType.Persistent, this.Local.Uri, this.LocalPort, message.ConnectionName, out remoteUri, out remoteHostUniqueIdentifier);

                                    // update remote host info
                                    message.Recipient.UpdateUri(remoteUri, remoteHostUniqueIdentifier);
                                    message.Recipient.PhysicalAddress = tcpSocketInfo.Socket.RemoteEndPoint;
                                    message.Recipient.LocalPhysicalAddress = tcpSocketInfo.Socket.LocalEndPoint;
                                    tcpSocketInfo.Remote = message.Recipient;

                                    // LOG:
                                    if ( binaryLogWriter != null && binaryLogWriter[LogCategory.HostInformation] > 0 )
                                    {
                                        binaryLogWriter.WriteHostInformationEvent("TcpConnectionManager.LowLevel_OpenConnection",
                                            LogMessageType.HostInformationCreated, null, message.Recipient,
                                            GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name, tcpSocketInfo.ConnectionLevelSecurity,
                                            tcpSocketInfo.ConnectionLevelSecurity == null ? null : tcpSocketInfo.ConnectionLevelSecurity.Name,
                                            tcpSocketInfo.DbgConnectionId,
                                            "HostInformation is ready for actions.");
                                    }

                                    // OK, connection established
                                    tcpSocketInfo.MessageContainer = new MessageContainer(this.ITransportContext);
                                    this._persistent.Set(uri, tcpSocketInfo.ConnectionName, tcpSocketInfo);

                                    tcpSocketInfo.CloseConnectionAfterInactivity = GenuineUtility.ConvertToMilliseconds(this.ITransportContext.IParameterProvider[GenuineParameter.ClosePersistentConnectionAfterInactivity]);
                                    tcpSocketInfo.Renew();
                                    tcpSocketInfo.SignalState(GenuineEventType.GeneralConnectionEstablished, null, null);

                                    // LOG:
                                    if ( binaryLogWriter != null && binaryLogWriter[LogCategory.Connection] > 0 )
                                    {
                                        binaryLogWriter.WriteEvent(LogCategory.Connection, "TcpConnectionManager.GetConnectionForSending",
                                            LogMessageType.ConnectionEstablished, null, null, tcpSocketInfo.Remote, null,
                                            GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name,
                                            tcpSocketInfo.ConnectionLevelSecurity,
                                            tcpSocketInfo.ConnectionLevelSecurity == null ? null : tcpSocketInfo.ConnectionLevelSecurity.Name,
                                            tcpSocketInfo.DbgConnectionId, (int) message.SecuritySessionParameters.GenuineConnectionType, 0, 0, this.GetType().Name, message.Recipient.LocalPhysicalAddress.ToString(), message.Recipient.PhysicalAddress.ToString(), null,
                                            "The connection to the remote host is established.");
                                    }

                                    this.Pool_StartSending(tcpSocketInfo);
                                    this.Pool_InitiateReceiving(tcpSocketInfo, this.ITransportContext.IParameterProvider);
                                }
                            }
                            else
                            {
                                // remote host is a client and if there is no connection to it, it's unreachable
                                tcpSocketInfo = this._persistent.Get(uri, message.ConnectionName) as TcpSocketInfo;
                                if (tcpSocketInfo == null)
                                    throw GenuineExceptions.Get_Send_DestinationIsUnreachable(message.Recipient.Uri);
                            }
                        }
                        break;

                    case GenuineConnectionType.Named:
                        if (message.ConnectionName == null)
                            message.ConnectionName = message.SecuritySessionParameters.ConnectionName;

                        isServer = message.Recipient.Url == null;
                        string fullConnectionName = this.GetNamedConnectionName(isServer, message.Recipient, message.ConnectionName);

                        try
                        {
                            // if it's possible to establish a connection to the remote host
                            if (! isServer)
                            {
                                bool shouldBeEstablished = false;
                                lock (this._named)
                                {
                                    tcpSocketInfo = this._named[fullConnectionName] as TcpSocketInfo;

                                    // if it's necessary to establish a connection
                                    if (tcpSocketInfo == null)
                                    {
                                        shouldBeEstablished = true;

                                        // register a message queue for this connection
                                        tcpSocketInfo = new TcpSocketInfo(null, this.ITransportContext, message.ConnectionName
            #if DEBUG
                                            ,"Stub for the named connection while it's being established."
            #endif
                                            );
                                        tcpSocketInfo.Remote = message.Recipient;
                                        tcpSocketInfo.GenuineConnectionType = GenuineConnectionType.Named;
                                        tcpSocketInfo.LockForSending = true;
                                        tcpSocketInfo.CloseConnectionAfterInactivity = GenuineUtility.ConvertToMilliseconds(this.ITransportContext.IParameterProvider[GenuineParameter.ConnectTimeout]);
                                        tcpSocketInfo.MessageContainer = new MessageContainer(this.ITransportContext);
                                        tcpSocketInfo.Renew();
                                        this._named[fullConnectionName] = tcpSocketInfo;
                                    }
                                }

                                if (shouldBeEstablished)
                                {
                                    // try to establish named connection
                                    tcpSocketInfo = LowLevel_OpenConnection(message.Recipient, GenuineConnectionType.Named, this.Local.Uri, this.LocalPort, message.ConnectionName, out remoteUri, out remoteHostUniqueIdentifier);

                                    // update remote host info
                                    message.Recipient.UpdateUri(remoteUri, remoteHostUniqueIdentifier);
                                    message.Recipient.PhysicalAddress = tcpSocketInfo.Socket.RemoteEndPoint;
                                    message.Recipient.LocalPhysicalAddress = tcpSocketInfo.Socket.LocalEndPoint;
                                    tcpSocketInfo.Remote = message.Recipient;

                                    // calculate the time to close the connection after
                                    if (message.SecuritySessionParameters.CloseAfterInactivity == TimeSpan.MinValue)
                                        tcpSocketInfo.CloseConnectionAfterInactivity = GenuineUtility.ConvertToMilliseconds(this.ITransportContext.IParameterProvider[GenuineParameter.CloseNamedConnectionAfterInactivity]);
                                    else
                                        tcpSocketInfo.CloseConnectionAfterInactivity = GenuineUtility.ConvertToMilliseconds(message.SecuritySessionParameters.CloseAfterInactivity);
                                    tcpSocketInfo.Renew();

                                    // and exchange it with the registered queue
                                    lock (this._named)
                                    {
                                        TcpSocketInfo stubWithQueue = (TcpSocketInfo) this._named[fullConnectionName];
                                        this._named[fullConnectionName] = tcpSocketInfo;
                                        tcpSocketInfo.MessageContainer = stubWithQueue.MessageContainer;
                                    }

                                    // LOG:
                                    if ( binaryLogWriter != null && binaryLogWriter[LogCategory.Connection] > 0 )
                                    {
                                        binaryLogWriter.WriteEvent(LogCategory.Connection, "TcpConnectionManager.GetConnectionForSending",
                                            LogMessageType.ConnectionEstablished, null, null, tcpSocketInfo.Remote, null,
                                            GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name,
                                            tcpSocketInfo.ConnectionLevelSecurity,
                                            tcpSocketInfo.ConnectionLevelSecurity == null ? null : tcpSocketInfo.ConnectionLevelSecurity.Name,
                                            tcpSocketInfo.DbgConnectionId, (int) message.SecuritySessionParameters.GenuineConnectionType, 0, 0, this.GetType().Name, message.Recipient.LocalPhysicalAddress.ToString(), message.Recipient.PhysicalAddress.ToString(), null,
                                            "The connection to the remote host is established.");
                                    }

                                    this.Pool_StartSending(tcpSocketInfo);
                                    this.Pool_InitiateReceiving(tcpSocketInfo, this.ITransportContext.IParameterProvider);
                                }
                            }
                            else
                            {
                                // remote host is a client and if there are no connection to it, it's unreachable
                                lock (this._named)
                                    tcpSocketInfo = this._named[fullConnectionName] as TcpSocketInfo;
                                if (tcpSocketInfo == null)
                                {
                                    Exception exception = GenuineExceptions.Get_Send_DestinationIsUnreachable(message.Recipient.Uri);

                                    // LOG:
                                    if ( binaryLogWriter != null && binaryLogWriter[LogCategory.Connection] > 0 )
                                    {
                                        binaryLogWriter.WriteEvent(LogCategory.Connection, "TcpConnectionManager.GetConnectionForSending",
                                            LogMessageType.ConnectionEstablished, exception, message, message.Recipient, null,
                                            GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name,
                                            null, null, -1, (int) message.SecuritySessionParameters.GenuineConnectionType, 0, 0, this.GetType().Name, null, null, null,
                                            "The connection to the remote host cannot be established.");
                                    }

                                    throw exception;
                                }
                            }
                        }
                        catch(Exception ex)
                        {
                            tcpSocketInfo.Remote = message.Recipient;
                            this.SocketFailed(ex, tcpSocketInfo);

                            TcpSocketInfo existingConnection = null;
                            lock (this._named)
                                existingConnection = this._named[fullConnectionName] as TcpSocketInfo;

                            this.SocketFailed(ex, existingConnection);
            //
            //							MessageContainer messageContainerToBeClearedUp = null;
            //							lock (this._named)
            //							{
            //								TcpSocketInfo existingConnection = this._named[fullConnectionName] as TcpSocketInfo;
            //								if (existingConnection != null)
            //									messageContainerToBeClearedUp = existingConnection.MessageContainer;
            //								this._named.Remove(fullConnectionName);
            //							}
            //
            //							if (messageContainerToBeClearedUp != null)
            //								messageContainerToBeClearedUp.Dispose(ex);
            //
            //							if (ConnectionManager.IsExceptionCritical(ex as OperationException))
            //								message.Recipient.Dispose(ex);
                            throw;
                        }
                        break;

                    case GenuineConnectionType.Invocation:

                        // TODO: remove it after updating this code
                        throw new ApplicationException("This version of Genuine Channels does not support the Invocation Connection Pattern.");

                        //						// if it's a request, it's necessary to open the connection
                        //						if (message.ConnectionId == null || ! message.ConnectionId.StartsWith("~"))
                        //						{
                        //							// try to find inactive one
                        //							ArrayList invocationConnections = null;
                        //							lock (this._invocationConnections.SyncRoot)
                        //							{
                        //								invocationConnections = this._invocationConnections[message.Recipient.Url] as ArrayList;
                        //								if (invocationConnections == null)
                        //									this._invocationConnections[message.Recipient.Url] = invocationConnections = new ArrayList();
                        //							}
                        //
                        //							lock (invocationConnections)
                        //								for ( int i = 0; i < invocationConnections.Count ; i++ )
                        //								{
                        //									tcpSocketInfo = (TcpSocketInfo) invocationConnections[i];
                        //									if (tcpSocketInfo.IsValid && tcpSocketInfo.TcpInvocationFiniteAutomatonState == TcpInvocationFiniteAutomatonState.ClientAvailable)
                        //									{
                        //										// connection may be broken
                        //										message.IsResendAfterFail = true;
                        //										tcpSocketInfo.TcpInvocationFiniteAutomatonState = TcpInvocationFiniteAutomatonState.ClientSending;
                        //										tcpSocketInfo.InitialMessage = message;
                        //										break;
                        //									}
                        //									else
                        //										tcpSocketInfo = null;
                        //								}
                        //
                        //							if (tcpSocketInfo == null)
                        //							{
                        //								// it is necessary to open a new one
                        //								tcpSocketInfo = LowLevel_OpenConnection(message.Recipient, GenuineConnectionType.Invocation, this.Local.Uri, this.LocalPort, null, out remoteUri);
                        //								tcpSocketInfo.Remote = message.Recipient;
                        //
                        //								// update remote host info
                        //								message.Recipient.UpdateUri(remoteUri);
                        //								tcpSocketInfo.Remote = message.Recipient;
                        //								tcpSocketInfo.TcpInvocationFiniteAutomatonState = TcpInvocationFiniteAutomatonState.ClientSending;
                        //								tcpSocketInfo.InitialMessage = message;
                        //								message.IsResendAfterFail = false;
                        //
                        //								// calculate the time to close the connection after
                        //								if (message.SecuritySessionParameters.CloseAfterInactivity == TimeSpan.MinValue)
                        //									tcpSocketInfo.CloseConnectionAfterInactivity = GenuineUtility.ConvertToMilliseconds(this.ITransportContext.IParameterProvider[GenuineParameter.CloseInvocationConnectionAfterInactivity]);
                        //								else
                        //									tcpSocketInfo.CloseConnectionAfterInactivity = GenuineUtility.ConvertToMilliseconds(message.SecuritySessionParameters.CloseAfterInactivity);
                        //								tcpSocketInfo.Renew();
                        //
                        //								// add opened connection to connection pool
                        //								lock (this._invocationConnections.SyncRoot)
                        //								{
                        //									ArrayList connections = (ArrayList) this._invocationConnections[message.Recipient.Url];
                        //									lock (connections)
                        //										connections.Add(tcpSocketInfo);
                        //								}
                        //
                        //								this.Pool_InitiateReceiving(tcpSocketInfo, this.ITransportContext.IParameterProvider);
                        //							}
                        //						}
                        //						else
                        //						{
                        //							// it's a reply, it's necessary just to send the response through
                        //							// the existent connection with the given name
                        //							tcpSocketInfo = this._knownInvocationConnections[message.ConnectionId] as TcpSocketInfo;
                        //							if (tcpSocketInfo == null)
                        //								throw GenuineExceptions.Get_Send_NoNamedConnectionFound(message.ConnectionId);
                        //							tcpSocketInfo.TcpInvocationFiniteAutomatonState = TcpInvocationFiniteAutomatonState.ServerSending;
                        //							tcpSocketInfo.InitialMessage = message;
                        //						}
                        //
                        //						tcpSocketInfo.Renew();
                        //						break;

                    default:
                        throw GenuineExceptions.Get_Connect_CanNotConnectToRemoteHost(message.Recipient.PrimaryUri, "Invalid type of connection requested.");
                }
            }

            return tcpSocketInfo;
        }