/// <summary>
        /// Accepts the connection.
        /// </summary>
        /// <param name="clientSocket">The socket.</param>
        void IAcceptConnectionConsumer.AcceptConnection(Socket clientSocket)
        {
            BinaryLogWriter binaryLogWriter = this.ITransportContext.BinaryLogWriter;
            //			GenuineConnectionType genuineConnectionType = GenuineConnectionType.None;
            string remoteUri = "Unknown.";
            string remoteAddress = "Address of the remote host.";
            string connectionName;
            int remoteHostUniqueIdentifier;
            TcpSocketInfo tcpSocketInfo = null;
            HostInformation hostInformation = null;

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

            using (new ThreadDataSlotKeeper(OccupiedThreadSlots.SocketDuringEstablishing, clientSocket))
            {
                try
                {
                    // provide a possibility to decline the connection
                    ConnectionAcceptedCancellableEventParameter connectionAcceptedCancellableEventParameter = new ConnectionAcceptedCancellableEventParameter();
                    connectionAcceptedCancellableEventParameter.Socket = clientSocket;
                    connectionAcceptedCancellableEventParameter.IPEndPoint = (IPEndPoint) clientSocket.RemoteEndPoint;
                    this.ITransportContext.IGenuineEventProvider.Fire(new GenuineEventArgs(GenuineEventType.GTcpConnectionAccepted, null, null, connectionAcceptedCancellableEventParameter));
                    if (connectionAcceptedCancellableEventParameter.Cancel)
                        throw GenuineExceptions.Get_Connect_CanNotAcceptIncomingConnection("Connection accepting was cancelled by the event consumer.");

                    // accept the connection
                    Exception reasonOfStateLost = null;
                    tcpSocketInfo = this.LowLevel_AcceptConnection(clientSocket,
                        this.Local.Uri, out remoteUri, out remoteAddress, out connectionName, out remoteHostUniqueIdentifier, out reasonOfStateLost);

                    // get the remote host
                    hostInformation = this.ITransportContext.KnownHosts[remoteUri];
                    if (remoteAddress != null)
                        hostInformation.UpdateUrl(remoteAddress);
                    tcpSocketInfo.Remote = hostInformation;
                    hostInformation.PhysicalAddress = tcpSocketInfo.Socket.RemoteEndPoint;
                    hostInformation.LocalPhysicalAddress = tcpSocketInfo.Socket.LocalEndPoint;

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

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

                        switch (tcpSocketInfo.GenuineConnectionType)
                        {
                            case GenuineConnectionType.Persistent:
                                lock (hostInformation.PersistentConnectionEstablishingLock)
                                {
                                    if (hostInformation.GenuinePersistentConnectionState == GenuinePersistentConnectionState.Opened)
                                        throw GenuineExceptions.Get_Processing_LogicError("Remote host tries to open persistent connection while it's a server.");
                                    hostInformation.GenuinePersistentConnectionState = GenuinePersistentConnectionState.Accepted;

                                    // close existent connection
                                    lock (this._persistent.SyncRoot)
                                    {
                                        TcpSocketInfo existentSocketInfo = this._persistent.Get(remoteUri, connectionName) as TcpSocketInfo;
                                        if (existentSocketInfo != null)
                                        {
                                            lock (existentSocketInfo)
                                                tcpSocketInfo.MessageContainer = existentSocketInfo.MessageContainer;
                                            this.SocketFailed(GenuineExceptions.Get_Connect_ConnectionReestablished(), existentSocketInfo);
                                            this.LowLevel_CloseConnection(existentSocketInfo);
                                        }
                                        else
                                        {
                                            tcpSocketInfo.MessageContainer = new MessageContainer(this.ITransportContext);
                                        }

                                        // register the new connection
                                        this._persistent.Set(remoteUri, 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.IAcceptConnectionConsumer.AcceptConnection",
                                        LogMessageType.ConnectionEstablished, null, null, tcpSocketInfo.Remote, null,
                                        GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name,
                                        tcpSocketInfo.ConnectionLevelSecurity,
                                        tcpSocketInfo.ConnectionLevelSecurity == null ? null : tcpSocketInfo.ConnectionLevelSecurity.Name,
                                        tcpSocketInfo.DbgConnectionId, (int) tcpSocketInfo.GenuineConnectionType, 0, 0, this.GetType().Name, hostInformation.LocalPhysicalAddress.ToString(), hostInformation.PhysicalAddress.ToString(), null,
                                        "The persistent connection is established.");
                                }

                                // to avoid sending previous messages, encrypted by previously used Security Sessions
                                if (reasonOfStateLost != null)
                                {
                                    tcpSocketInfo.MessagesSentSynchronously.ReleaseAllMessages();
                                    tcpSocketInfo.MessageContainer.Dispose(reasonOfStateLost);
                                    tcpSocketInfo.MessageContainer = new MessageContainer(this.ITransportContext);
                                }

                                // start processing
                                this.Pool_StartSending(tcpSocketInfo);
                                this.Pool_InitiateReceiving(tcpSocketInfo, this.ITransportContext.IParameterProvider);
                                break;

                            case GenuineConnectionType.Named:
                                // register the new connection
                                string fullConnectionName = remoteUri + "/" + tcpSocketInfo.ConnectionName;
                                tcpSocketInfo.MessageContainer = new MessageContainer(this.ITransportContext);
                                lock (this._named)
                                    this._named[fullConnectionName] = tcpSocketInfo;

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

                                // start processing
                                this.Pool_StartSending(tcpSocketInfo);
                                this.Pool_InitiateReceiving(tcpSocketInfo, this.ITransportContext.IParameterProvider);

                                tcpSocketInfo.CloseConnectionAfterInactivity = GenuineUtility.ConvertToMilliseconds(this.ITransportContext.IParameterProvider[GenuineParameter.CloseNamedConnectionAfterInactivity]);
                                break;

                            case GenuineConnectionType.Invocation:
                                // register the new connection
                                tcpSocketInfo.TcpInvocationFiniteAutomatonState = TcpInvocationFiniteAutomatonState.ServerAwaiting;
                                this._knownInvocationConnections[tcpSocketInfo.ConnectionName] = tcpSocketInfo;

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

                                // start processing
                                this.Pool_InitiateReceiving(tcpSocketInfo, this.ITransportContext.IParameterProvider);

                                tcpSocketInfo.CloseConnectionAfterInactivity = GenuineUtility.ConvertToMilliseconds(this.ITransportContext.IParameterProvider[GenuineParameter.CloseInvocationConnectionAfterInactivity]);
                                break;
                        }
                    }

                    // start the shutdown timer
                    tcpSocketInfo.Renew();
                }
                catch(Exception ex)
                {
                    // LOG:
                    if ( binaryLogWriter != null && binaryLogWriter[LogCategory.AcceptingConnection] > 0 )
                        binaryLogWriter.WriteEvent(LogCategory.AcceptingConnection, "TcpConnectionManager.IAcceptConnectionConsumer.AcceptConnection",
                            LogMessageType.ConnectionAccepting, ex, null, hostInformation, null,
                            GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name,
                            null, null, tcpSocketInfo == null ? -1 : tcpSocketInfo.DbgConnectionId,
                            0, 0, 0, null, null, null, null,
                            "The inbound connection has not been accepted.");

                    SocketUtility.CloseSocket(clientSocket);
                }
            }
        }
        /// <summary>
        /// Continues receiving and processing of the message in half-sync mode.
        /// </summary>
        /// <param name="socketAsObject">The connection.</param>
        private void Pool_Server_ContinueHalfSyncReceiving(object socketAsObject)
        {
            BinaryLogWriter binaryLogWriter = this.ITransportContext.BinaryLogWriter;

            XHttpConnection xHttpConnection = null;
            XHttpPhysicalConnection xHttpPhysicalConnection = null;
            Socket socket = (Socket) socketAsObject;

            byte protocolVersion;
            string remoteUri = null;
            int sequenceNo = 0;
            GenuineConnectionType genuineConnectionType = GenuineConnectionType.None;
            Guid hostId = Guid.Empty;
            HttpPacketType httpPacketType = HttpPacketType.Unkown;
            string connectionName;
            int remoteHostUniqueIdentifier;

            try
            {
                // server & sender - parse messages, execute them, send confirmation
                // server & listener - if messages are available, send them all. otherwise set available flag and hold the connection for a while

                // first, read the header
                Stream inputStream = this.LowLevel_ParseHttpContent(GenuineUtility.GetTimeout(GenuineUtility.ConvertToMilliseconds(this.ITransportContext.IParameterProvider[GenuineParameter.XHttpReadHttpMessageTimeout])),
                    false, socket, null, out protocolVersion, out remoteUri, out sequenceNo, out genuineConnectionType, out hostId, out httpPacketType, out connectionName, out remoteHostUniqueIdentifier);

                // who it was
                HostInformation remote = this.ITransportContext.KnownHosts["_ghttp://" + hostId.ToString("N")];
                remote.UpdateUri(remote.Uri, remoteHostUniqueIdentifier);
                remote.ProtocolVersion = protocolVersion;

                // get the connection
                lock (remote.PersistentConnectionEstablishingLock)
                {
                    xHttpConnection = this._persistent.Get(remote.Uri, connectionName) as XHttpConnection;

                    if (httpPacketType == HttpPacketType.Establishing_ResetConnection && xHttpConnection != null)
                    {
                        xHttpConnection.Dispose(GenuineExceptions.Get_Receive_ConnectionClosed("The connection was closed by HttpPacketType.Establishing_ResetConnection client request."));
                        xHttpConnection = null;
                    }

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

                            // provide a possibility to decline the connection
                            ConnectionAcceptedCancellableEventParameter connectionAcceptedCancellableEventParameter = new ConnectionAcceptedCancellableEventParameter();
                            connectionAcceptedCancellableEventParameter.Socket = socket;
                            connectionAcceptedCancellableEventParameter.IPEndPoint = (IPEndPoint) socket.RemoteEndPoint;
                            this.ITransportContext.IGenuineEventProvider.Fire(new GenuineEventArgs(GenuineEventType.GHttpConnectionAccepted, null, null, connectionAcceptedCancellableEventParameter));
                            if (connectionAcceptedCancellableEventParameter.Cancel)
                                throw GenuineExceptions.Get_Connect_CanNotAcceptIncomingConnection("Connection accepting was cancelled by the event consumer.");

                            xHttpConnection = this.Pool_CreateConnection(remote, remote.Uri, false, connectionName);
                        }
                    }
                }

                bool theSamePacketIsRequested;

                lock (xHttpConnection.Listener.PhysicalConnectionStateLock)
                {
                    if (httpPacketType == HttpPacketType.Listening)
                    {
                        // if there is an already registered listener request - release it
                        if (xHttpConnection.Listener.ConnectionAvailable && xHttpConnection.Listener.Socket != socket)
                        {
                            // shut down the previous physical connection
                            this.LowLevel_SendServerError(new PhysicalConnectionAndSocket(xHttpConnection.Listener, socket));
            //							GenuineThreadPool.QueueUserWorkItem(new WaitCallback(this.LowLevel_SendServerError), new PhysicalConnectionAndSocket(xHttpConnection.Listener, socket), true);
                            xHttpConnection.Listener.AcquireIfAvailable();
                        }

                        xHttpConnection.Listener.Socket = socket;
                        xHttpPhysicalConnection = xHttpConnection.Listener;
                    }
                    else
                    {
                        xHttpConnection.Sender.Socket = socket;
                        xHttpPhysicalConnection = xHttpConnection.Sender;
                    }

                    theSamePacketIsRequested = xHttpPhysicalConnection.SequenceNo == sequenceNo && xHttpPhysicalConnection.SentContent != null;

            #if DEBUG
                    xHttpPhysicalConnection.TypeOfSocket = "Accepted";
            #endif

                    xHttpPhysicalConnection.Remote.PhysicalAddress = socket.RemoteEndPoint;
                    xHttpPhysicalConnection.Remote.LocalPhysicalAddress = socket.LocalEndPoint;
                }	// lock (xHttpConnection.Listener.PhysicalConnectionStateLock)

                // renew connection lifetime
                xHttpConnection.Renew();
                xHttpPhysicalConnection.XHttpConnection.SignalState(GenuineEventType.GeneralConnectionEstablished, null, null);

                // if the same packet stream is requested, send the response
                if (theSamePacketIsRequested)
                {
                    // skip the current stream
                    inputStream.Close();

                    // send the stream and initiate receiving
                    this.LowLevel_SendHttpContent(remote.ExpireTime, null, null, null, null, xHttpPhysicalConnection, genuineConnectionType, HttpPacketType.RequestRepeated, true, true, true, true);
                    return ;
                }

                lock (xHttpConnection.Listener.PhysicalConnectionStateLock)
                {
                    // if desynchronization, report and continue
                    if (httpPacketType != HttpPacketType.Establishing_ResetConnection && xHttpPhysicalConnection.SequenceNo > sequenceNo || sequenceNo > xHttpPhysicalConnection.SequenceNo + 1)
                    {
                        // LOG:
                        if ( binaryLogWriter != null && binaryLogWriter[LogCategory.Connection] > 0 )
                        {
                            binaryLogWriter.WriteEvent(LogCategory.Connection, "XHttpConnectionManager.Pool_Server_ContinueHalfSyncreceiving",
                                LogMessageType.ConnectionStreamDesynchronization, GenuineExceptions.Get_Debugging_GeneralWarning("Stream desynchronization."),
                                null, xHttpPhysicalConnection.Remote, null,
                                GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name,
                                xHttpPhysicalConnection.ConnectionLevelSecurity, xHttpPhysicalConnection.ConnectionLevelSecurity == null ? null : xHttpPhysicalConnection.ConnectionLevelSecurity.Name,
                                xHttpConnection.DbgConnectionId, 0, 0, 0, null, null, null, null,
                                "Stream desynchronization error. Received sequence number: {0}. Expected sequence number: {1}.", xHttpPhysicalConnection.SequenceNo, sequenceNo);
                        }

                        // send the stream and initiate receiving
                        this.LowLevel_SendHttpContent(remote.ExpireTime, null, null, null, null, xHttpPhysicalConnection, genuineConnectionType, HttpPacketType.Desynchronization, false, true, true, true);
                        return ;
                    }

                    // the next sequence is requested
                    if (xHttpPhysicalConnection.SentContent != null)
                    {
                        // release the content
                        xHttpPhysicalConnection.SentContent.Close();
                        xHttpPhysicalConnection.SentContent = null;
                    }

                    // respond with the same seq No
                    xHttpPhysicalConnection.SequenceNo = sequenceNo;
                    xHttpPhysicalConnection.Socket = socket;
                    xHttpPhysicalConnection.MessagesBeingSent.Clear();
                }

                // LOG:
                if ( binaryLogWriter != null && binaryLogWriter[LogCategory.Connection] > 0 )
                {
                    binaryLogWriter.WriteEvent(LogCategory.Connection, "XHttpConnectionManager.Pool_Server_ContinueHalfSyncreceiving",
                        LogMessageType.ReceivingFinished, null,
                        null, xHttpPhysicalConnection.Remote, null,
                        GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name,
                        xHttpPhysicalConnection.ConnectionLevelSecurity, xHttpPhysicalConnection.ConnectionLevelSecurity == null ? null : xHttpPhysicalConnection.ConnectionLevelSecurity.Name,
                        xHttpConnection.DbgConnectionId, 0, 0, 0, null, null, null, null,
                        "HTTP Stream received. Packet type: {0}.", Enum.Format(typeof(HttpPacketType), httpPacketType, "g"));
                }

                // analyze the type of the packet
                switch(httpPacketType)
                {
                    case HttpPacketType.Establishing_ResetConnection:
                    case HttpPacketType.Establishing:
                        // mark the remote host as client
                        lock (remote.PersistentConnectionEstablishingLock)
                            remote.GenuinePersistentConnectionState = GenuinePersistentConnectionState.Accepted;

                        // read CLSS streams
                        BinaryReader binaryReader = new BinaryReader(inputStream);
                        Stream clsseStream = null;
                        GenuineChunkedStream outputStream = new GenuineChunkedStream(false);

                        // process the sender info
                        int writtenSize = binaryReader.ReadInt32();

                        using (new GenuineChunkedStreamSizeLabel(outputStream))
                        {
                            if (xHttpConnection.Sender.ConnectionLevelSecurity != null && ! xHttpConnection.Sender.ConnectionLevelSecurity.IsEstablished)
                            {
                                using (Stream clssData = new DelimiterStream(inputStream, writtenSize))
                                {
                                    clsseStream = xHttpConnection.Sender.ConnectionLevelSecurity.EstablishSession(clssData, true);
                                }
                            }

                            if (clsseStream != null)
                                GenuineUtility.CopyStreamToStream(clsseStream, outputStream);
                        }

                        // process the listener info
                        writtenSize = binaryReader.ReadInt32();
                        using (new GenuineChunkedStreamSizeLabel(outputStream))
                        {
                            if (xHttpConnection.Listener.ConnectionLevelSecurity != null && ! xHttpConnection.Listener.ConnectionLevelSecurity.IsEstablished)
                            {
                                using (Stream clssData = new DelimiterStream(inputStream, writtenSize))
                                {
                                    clsseStream = xHttpConnection.Listener.ConnectionLevelSecurity.EstablishSession(clssData, true);
                                }
                            }

                            if (clsseStream != null)
                                GenuineUtility.CopyStreamToStream(clsseStream, outputStream);
                        }

                        // skip remaining part of the packet
                        inputStream.Close();

                        this.LowLevel_SendHttpContent(remote.ExpireTime, null, outputStream, null, null, xHttpPhysicalConnection,
                            genuineConnectionType, httpPacketType, false, true, true, false);
                        break;

                    case HttpPacketType.Listening:
                        // if messages are available, send them immediately
                        // otherwise put the connection off for a while

                        // skip the remaining content
                        inputStream.Close();
                        Pool_Server_ProcessListenerRequest(xHttpConnection, xHttpPhysicalConnection);
                        break;

                    case HttpPacketType.Usual:
                        // apply CLSS if it was established
                        if (xHttpPhysicalConnection.ConnectionLevelSecurity != null)
                            inputStream = xHttpPhysicalConnection.ConnectionLevelSecurity.Decrypt(inputStream);
                        Pool_Server_ProcessSenderRequest(xHttpConnection, xHttpPhysicalConnection, inputStream);
                        break;

                    default:
                        throw GenuineExceptions.Get_Receive_IncorrectData("Unexpected type of the packet.");
                }
            }
            catch(Exception ex)
            {
                try
                {
                    // LOG:
                    if ( binaryLogWriter != null && binaryLogWriter[LogCategory.Connection] > 0 )
                    {
                        binaryLogWriter.WriteEvent(LogCategory.Connection, "XHttpConnectionManager.Pool_Server_ContinueHalfSyncreceiving",
                            LogMessageType.ReceivingFinished, ex,
                            null, xHttpPhysicalConnection.Remote, null,
                            GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name,
                            xHttpPhysicalConnection.ConnectionLevelSecurity, xHttpPhysicalConnection.ConnectionLevelSecurity == null ? null : xHttpPhysicalConnection.ConnectionLevelSecurity.Name,
                            xHttpConnection.DbgConnectionId, 0, 0, 0, null, null, null, null,
                            "Error occurred while receiving HTTP Stream. Sequence No: {0}. Connection type: {1}. Packet type: {2}.",
                            sequenceNo, genuineConnectionType, httpPacketType);
                    }

                    SocketUtility.CloseSocket(socket);
                }
                catch
                {
                }
            }
        }