/// <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>
        /// Destroys the specified connection and releases absolutely all resources belonging to
        /// the remote host the connection points at.
        /// </summary>
        /// <param name="tcpSocketInfo">The connection.</param>
        /// <param name="reason">The reason of disposing connection resources.</param>
        private void Pool_DestroyPersistentConnection(TcpSocketInfo tcpSocketInfo, Exception reason)
        {
            bool disposeMessages = false;
            bool connectionAvailable = true;

            // the queue
            lock (this._persistent.SyncRoot)
            {
                TcpSocketInfo currentTcpSocketInfo = this._persistent.Get(tcpSocketInfo.PrimaryRemoteUri, tcpSocketInfo.ConnectionName) as TcpSocketInfo;

                // if it's still the stub
                if (object.ReferenceEquals(currentTcpSocketInfo, tcpSocketInfo))
                {
                    this._persistent.Remove(tcpSocketInfo.PrimaryRemoteUri, tcpSocketInfo.ConnectionName);
                    connectionAvailable = this._persistent.Get(tcpSocketInfo.PrimaryRemoteUri, null) != null;
                    disposeMessages = true;
                }
            }

            // release messages
            if (disposeMessages)
                tcpSocketInfo.MessageContainer.Dispose(reason);

            // release HostInformation if there are no connections available
            if (! connectionAvailable)
            {
                tcpSocketInfo.SignalState(GenuineEventType.GeneralConnectionClosed, reason, null);
                this.ITransportContext.KnownHosts.ReleaseHostResources(tcpSocketInfo.Remote, reason);
            }

            GenuineThreadPool.QueueUserWorkItem(new WaitCallback(LowLevel_CloseConnection), tcpSocketInfo, false);
        }