/// <summary>
        /// Sends the response to the remote host.
        /// </summary>
        /// <param name="httpContext">The http context.</param>
        /// <param name="listener">True if it's a listener.</param>
        /// <param name="httpServerConnection">The connection containing CLSS.</param>
        /// <param name="applyClss">Indicates whether it is necessary to apply Connection Level Security Session.</param>
        /// <param name="content">The content being sent to the remote host.</param>
        /// <param name="httpServerConnectionForDebugging">The connection that will be mentioned in the debug records.</param>
        public void LowLevel_SendStream(HttpContext httpContext, bool listener, HttpServerConnection httpServerConnection, bool applyClss, ref Stream content, HttpServerConnection httpServerConnectionForDebugging)
        {
            BinaryLogWriter binaryLogWriter = this.ITransportContext.BinaryLogWriter;

            try
            {
                if (applyClss)
                {
                    // detect clss
                    SecuritySession clss = null;
                    if (httpServerConnection != null && listener && httpServerConnection.Listener_SecuritySession != null && httpServerConnection.Listener_SecuritySession.IsEstablished)
                        clss = httpServerConnection.Listener_SecuritySession;
                    if (httpServerConnection != null && ! listener && httpServerConnection.Sender_SecuritySession != null && httpServerConnection.Sender_SecuritySession.IsEstablished)
                        clss = httpServerConnection.Sender_SecuritySession;

                    // apply clss
                    if (clss != null)
                    {
                        GenuineChunkedStream encryptedContent = new GenuineChunkedStream(false);
                        clss.Encrypt(content, encryptedContent);
                        content = encryptedContent;
                    }
                }

            #if DEBUG
                Debug.Assert(content.CanSeek);
                Debug.Assert(content.Length >= 0);
            #endif

                // prepare the response
                HttpResponse response = httpContext.Response;
                response.ContentType = "application/octet-stream";
                response.StatusCode = 200;
                response.StatusDescription = "OK";
                int contentLength = (int) content.Length;
                response.AppendHeader("Content-Length", contentLength.ToString() );

                // write the response
                Stream responseStream = response.OutputStream;
                GenuineUtility.CopyStreamToStream(content, responseStream, contentLength);
                this.ITransportContext.ConnectionManager.IncreaseBytesSent(contentLength);

            #if DEBUG
                // the content must end up here
                Debug.Assert(content.ReadByte() == -1);
            #endif

                // LOG:
                if ( binaryLogWriter != null && binaryLogWriter[LogCategory.LowLevelTransport] > 0 )
                {
                    bool writeContent = binaryLogWriter[LogCategory.LowLevelTransport] > 1;
                    GenuineChunkedStream copiedContent = null;
                    if (writeContent)
                    {
                        copiedContent = new GenuineChunkedStream(false);
                        GenuineUtility.CopyStreamToStream(content, copiedContent);
                    }

                    binaryLogWriter.WriteTransportContentEvent(LogCategory.LowLevelTransport, "HttpServerConnectionManager.LowLevel_SendStream",
                        LogMessageType.LowLevelTransport_AsyncSendingInitiating, null, null, httpServerConnectionForDebugging.Remote,
                        copiedContent,
                        GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name, httpServerConnectionForDebugging.DbgConnectionId,
                        (int) content.Length, null, null, null,
                        "Response is sent back to the client. Buffer: {0}; BufferOutput: {1}; Charset: {2}; ContentEncoding: {3}; ContentType: {4}; IsClientConnected: {5}; StatusCode: {6}; StatusDescription: {7}; SuppressContent: {8}; Content-Length: {9}. Connection: {10}.",
                        response.Buffer, response.BufferOutput, response.Charset,
                        response.ContentEncoding, response.ContentType, response.IsClientConnected,
                        response.StatusCode, response.StatusDescription, response.SuppressContent,
                        contentLength, listener ? "LISTENER" : "SENDER");
                }
            }
            catch(Exception ex)
            {
                // LOG:
                if ( binaryLogWriter != null && binaryLogWriter[LogCategory.Connection] > 0 )
                {
                    binaryLogWriter.WriteEvent(LogCategory.Connection, "HttpServerConnectionManager.LowLevel_SendStream",
                        LogMessageType.MessageIsSentAsynchronously, ex, null, httpServerConnectionForDebugging.Remote, null,
                        GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name, null, null,
                        httpServerConnectionForDebugging.DbgConnectionId, 0, 0, 0, null, null, null, null,
                        "Error occurred while sending a response.");
                }
                throw;
            }
        }
        /// <summary>
        /// Processes the sender's request.
        /// </summary>
        /// <param name="genuineConnectionType">The type of the connection.</param>
        /// <param name="input">The incoming data.</param>
        /// <param name="httpServerRequestResult">The request.</param>
        /// <param name="httpServerConnection">The connection.</param>
        /// <param name="sequenceNo">The sequence number.</param>
        /// <param name="remote">The information about remote host.</param>
        public void LowLevel_ProcessSenderRequest(GenuineConnectionType genuineConnectionType, Stream input, HttpServerRequestResult httpServerRequestResult, HttpServerConnection httpServerConnection, int sequenceNo, HostInformation remote)
        {
            BinaryLogWriter binaryLogWriter = this.ITransportContext.BinaryLogWriter;
            GenuineChunkedStream outputStream = null;

            // parse the incoming stream
            bool directExecution = genuineConnectionType != GenuineConnectionType.Persistent;
            BinaryReader binaryReader = new BinaryReader(input);

            using (BufferKeeper bufferKeeper = new BufferKeeper(0))
            {
                switch(genuineConnectionType)
                {
                    case GenuineConnectionType.Persistent:
                        Exception gotException = null;

                        try
                        {
                            if (httpServerConnection.Sender_SecuritySession != null)
                            {
                                input = httpServerConnection.Sender_SecuritySession.Decrypt(input);
                                binaryReader = new BinaryReader(input);
                            }

                            while (binaryReader.ReadByte() == 0)
                                using(LabelledStream labelledStream = new LabelledStream(this.ITransportContext, input, bufferKeeper.Buffer))
                                {
                                    GenuineChunkedStream receivedContent = new GenuineChunkedStream(true);
                                    GenuineUtility.CopyStreamToStream(labelledStream, receivedContent);
                                    this.ITransportContext.IIncomingStreamHandler.HandleMessage(receivedContent, httpServerConnection.Remote, genuineConnectionType, httpServerConnection.ConnectionName, httpServerConnection.DbgConnectionId, false, this._iMessageRegistrator, httpServerConnection.Sender_SecuritySession, httpServerRequestResult);
                                }
                        }
                        catch(Exception ex)
                        {
                            gotException = ex;

                            // LOG:
                            if ( binaryLogWriter != null && binaryLogWriter[LogCategory.Connection] > 0 )
                            {
                                binaryLogWriter.WriteEvent(LogCategory.Connection, "HttpServerConnectionManager.LowLevel_ProcessSenderRequest",
                                    LogMessageType.Error, ex, null, httpServerConnection.Remote, null,
                                    GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name, null, null,
                                    httpServerConnection.DbgConnectionId, 0, 0, 0, null, null, null, null,
                                    "Error occurred while processing the sender request N: {0}.", httpServerConnection.Sender_SequenceNo);
                            }
                        }

                        if (gotException != null)
                        {
                            gotException = OperationException.WrapException(gotException);
                            outputStream = this.LowLevel_CreateStreamWithHeader(HttpPacketType.SenderError, sequenceNo, remote);
                            BinaryFormatter binaryFormatter = new BinaryFormatter(new RemotingSurrogateSelector(), new StreamingContext(StreamingContextStates.Other));
                            binaryFormatter.Serialize(outputStream, gotException);
                        }
                        else
                        {
                            // serialize and send the empty response
                            outputStream = this.LowLevel_CreateStreamWithHeader(HttpPacketType.SenderResponse, sequenceNo, remote);
                            MessageCoder.FillInLabelledStream(null, null, null, outputStream,
                                bufferKeeper.Buffer, (int) this.ITransportContext.IParameterProvider[GenuineParameter.HttpRecommendedPacketSize]);
                        }
                        break;

                    case GenuineConnectionType.Invocation:
                        // register the http context as an invocation waiters
                        string connectionGuid = Guid.NewGuid().ToString("N");

                        try
                        {
                            if (binaryReader.ReadByte() != 0)
                            {
                                // LOG:
                                if ( binaryLogWriter != null )
                                {
                                    binaryLogWriter.WriteImplementationWarningEvent("HttpServerConnectionManager.LowLevel_ProcessSenderRequest", LogMessageType.Error,
                                        GenuineExceptions.Get_Debugging_GeneralWarning("The invocation request doesn't contain any messages."),
                                        GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name,
                                        "The invocation request doesn't contain any messages.");
                                }
                            }

                            using(LabelledStream labelledStream = new LabelledStream(this.ITransportContext, input, bufferKeeper.Buffer))
                            {
                                // process the response
                                this._invocation[connectionGuid] = null;
                                this.ITransportContext.IIncomingStreamHandler.HandleMessage(labelledStream, remote, genuineConnectionType, connectionGuid, -1, true, null, null, httpServerRequestResult);
                            }

                            if (binaryReader.ReadByte() != 1)
                            {
                                // LOG:
                                if ( binaryLogWriter != null )
                                {
                                    binaryLogWriter.WriteImplementationWarningEvent("HttpServerConnectionManager.LowLevel_ProcessSenderRequest", LogMessageType.Error,
                                        GenuineExceptions.Get_Debugging_GeneralWarning("The invocation request must not contain more than one message."),
                                        GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name,
                                        "The invocation request must not contain more than one message.");
                                }
                            }

                            // if there is a response, serialize it
                            outputStream = this.LowLevel_CreateStreamWithHeader(HttpPacketType.Usual, sequenceNo, remote);
                            Message message = this._invocation[connectionGuid] as Message;
                            MessageCoder.FillInLabelledStream(message, null, null, outputStream,
                                bufferKeeper.Buffer, (int) this.ITransportContext.IParameterProvider[GenuineParameter.HttpRecommendedPacketSize]);
                        }
                        finally
                        {
                            this._invocation.Remove(connectionGuid);
                        }
                        break;
                }
            }

            // report back to the client
            Stream finalStream = outputStream;
            this.LowLevel_SendStream(httpServerRequestResult.HttpContext, false, null, true, ref finalStream, httpServerConnection);
        }
        /// <summary>
        /// Handles the incoming HTTP request.
        /// </summary>
        /// <param name="httpServerRequestResultAsObject">The HTTP request.</param>
        public void HandleIncomingRequest(object httpServerRequestResultAsObject)
        {
            BinaryLogWriter binaryLogWriter = this.ITransportContext.BinaryLogWriter;

            HttpServerRequestResult httpServerRequestResult = (HttpServerRequestResult) httpServerRequestResultAsObject;
            HttpServerConnection httpServerConnection = null;
            bool postponeResponse = false;

            try
            {
                // get the stream
                HttpRequest httpRequest = httpServerRequestResult.HttpContext.Request;
                Stream incomingStream = httpRequest.InputStream;

                if (incomingStream.Length <= 0)
                {
                    // LOG:
                    if ( binaryLogWriter != null && binaryLogWriter[LogCategory.LowLevelTransport] > 0 )
                    {
                        binaryLogWriter.WriteEvent(LogCategory.Connection, "HttpServerConnectionManager.HandleIncomingRequest",
                            LogMessageType.LowLevelTransport_AsyncReceivingCompleted, null, null, null, null,
                            GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name, null, null,
                            -1, 0, 0, 0, null, null, null, null,
                            "Empty content has been received. It will be ignored.");
                    }

                    return ;
                }

                // LOG:
                if ( binaryLogWriter != null && binaryLogWriter[LogCategory.LowLevelTransport] > 0 )
                {
                    bool writeContent = binaryLogWriter[LogCategory.LowLevelTransport] > 1;
                    GenuineChunkedStream content = null;
                    if (writeContent)
                    {
                        content = new GenuineChunkedStream(false);
                        GenuineUtility.CopyStreamToStream(incomingStream, content);
                    }

                    binaryLogWriter.WriteTransportContentEvent(LogCategory.LowLevelTransport, "HttpServerConnectionManager.HandleIncomingRequest",
                        LogMessageType.LowLevelTransport_AsyncReceivingCompleted, null, null, null,
                        writeContent ? content : null,
                        GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name, -1, (int) httpServerRequestResult.HttpContext.Request.ContentLength,
                        httpServerRequestResult.HttpContext.Request.UserHostAddress,
                        null, null,
                        "HTTP request has been received.");

                    if (writeContent)
                        incomingStream = content;
                }

                BinaryReader binaryReader = new BinaryReader(incomingStream);

                // read the header
                byte protocolVersion;
                GenuineConnectionType genuineConnectionType;
                Guid hostId;
                HttpPacketType httpPacketType;
                int sequenceNo;
                string connectionName;
                int remoteHostUniqueIdentifier;
                HttpMessageCoder.ReadRequestHeader(binaryReader, out protocolVersion, out genuineConnectionType, out hostId, out httpPacketType, out sequenceNo, out connectionName, out remoteHostUniqueIdentifier);

                HostInformation remote = this.ITransportContext.KnownHosts["_ghttp://" + hostId.ToString("N")];
                remote.ProtocolVersion = protocolVersion;
            //				remote.Renew(this._hostRenewingSpan, false);
                remote.PhysicalAddress = httpRequest.UserHostAddress;

                // raise an event if we were not recognized
                remote.UpdateUri(remote.Uri, remoteHostUniqueIdentifier);

                // LOG:
                if ( binaryLogWriter != null && binaryLogWriter[LogCategory.Connection] > 0 )
                {
                    binaryLogWriter.WriteEvent(LogCategory.Connection, "HttpServerConnectionManager.HandleIncomingRequest",
                        LogMessageType.ReceivingFinished, null, null, remote, null,
                        GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name, null, null, -1,
                        0, 0, 0, null, null, null, null,
                        "HTTP request is being processed. Packet type: {0}. Sequence no: {1}. Content length: {2}. Host address: {3}.",
                        Enum.Format(typeof(HttpPacketType), httpPacketType, "g"), sequenceNo, httpRequest.ContentLength, httpRequest.UserHostAddress);
                }

                // prepare the output stream
                GenuineChunkedStream outputStream = new GenuineChunkedStream(false);
                BinaryWriter binaryWriter = new BinaryWriter(outputStream);
                HttpMessageCoder.WriteResponseHeader(binaryWriter, protocolVersion, this.ITransportContext.ConnectionManager.Local.Uri, sequenceNo, httpPacketType, remote.LocalHostUniqueIdentifier);

                // analyze the received packet
                switch(genuineConnectionType)
                {
                    case GenuineConnectionType.Persistent:
                    {
                        // get the server connection
                        lock (remote.PersistentConnectionEstablishingLock)
                        {
                            httpServerConnection = this._persistent.Get(remote.Uri, connectionName) as HttpServerConnection;
                            if (httpServerConnection != null && httpServerConnection._disposed)
                                httpServerConnection = null;

                            // initialize CLSS from the very beginning, if necessary
                            if (httpPacketType == HttpPacketType.Establishing_ResetConnection)
                            {
                                if (httpServerConnection != null)
                                    httpServerConnection.Dispose(GenuineExceptions.Get_Receive_ConnectionClosed("Client sends Establishing_ResetCLSS flag."));
                                httpServerConnection = null;
                            }

                            if (httpServerConnection == null)
                            {
                                // create the new connection
                                httpServerConnection = new HttpServerConnection(this.ITransportContext, hostId, remote, connectionName,
                                    GenuineUtility.ConvertToMilliseconds(this.ITransportContext.IParameterProvider[GenuineParameter.ClosePersistentConnectionAfterInactivity]) + GenuineUtility.ConvertToMilliseconds(this.ITransportContext.IParameterProvider[GenuineParameter.MaxTimeSpanToReconnect]));

                                if ( binaryLogWriter != null && binaryLogWriter[LogCategory.Connection] > 0 )
                                {
                                    binaryLogWriter.WriteConnectionParameterEvent(LogCategory.Connection, "HttpServerConnectionManager.HandleIncomingRequest",
                                        LogMessageType.ConnectionParameters, null, remote, this.ITransportContext.IParameterProvider,
                                        GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name, httpServerConnection.DbgConnectionId,
                                        "HTTP connection is being established.");
                                }

                                this._persistent.Set(remote.Uri, connectionName, httpServerConnection);

                                // and CLSS
                                string securitySessionName = this.ITransportContext.IParameterProvider[GenuineParameter.SecuritySessionForPersistentConnections] as string;
                                if (securitySessionName != null)
                                {
                                    httpServerConnection.Sender_SecuritySession = this.ITransportContext.IKeyStore.GetKey(securitySessionName).CreateSecuritySession(securitySessionName, null);
                                    httpServerConnection.Listener_SecuritySession = this.ITransportContext.IKeyStore.GetKey(securitySessionName).CreateSecuritySession(securitySessionName, null);
                                }

                                // LOG:
                                if ( binaryLogWriter != null && binaryLogWriter[LogCategory.Connection] > 0 )
                                {
                                    binaryLogWriter.WriteEvent(LogCategory.Connection, "HttpServerConnectionManager.HandleIncomingRequest",
                                        LogMessageType.ConnectionEstablished, null, null, remote, null,
                                        GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name, httpServerConnection.Sender_SecuritySession, securitySessionName,
                                        httpServerConnection.DbgConnectionId, (int) GenuineConnectionType.Persistent, 0, 0, this.GetType().Name, null, null, null,
                                        "The connection is being established.");
                                }

                                // LOG:
                                if ( binaryLogWriter != null && binaryLogWriter[LogCategory.HostInformation] > 0 )
                                {
                                    binaryLogWriter.WriteHostInformationEvent("HttpServerConnectionManager.HandleIncomingRequest",
                                        LogMessageType.HostInformationCreated, null, remote,
                                        GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name, httpServerConnection.Sender_SecuritySession,
                                        securitySessionName, httpServerConnection.DbgConnectionId,
                                        "HostInformation is ready for actions.");
                                }

                                this.ITransportContext.IGenuineEventProvider.Fire(new GenuineEventArgs(GenuineEventType.GHttpConnectionAccepted, null, remote, httpRequest.UserHostAddress));
                            }
                        }

                        httpServerConnection.Renew();
                        httpServerConnection.SignalState(GenuineEventType.GeneralConnectionEstablished, null, null);

                        switch(httpPacketType)
                        {
                            case HttpPacketType.Establishing_ResetConnection:
                            case HttpPacketType.Establishing:
                                Stream clsseStream = Stream.Null;

                                // establish the CLSS
                                // P/Sender
                                int length = binaryReader.ReadInt32();
                                if (httpServerConnection.Sender_SecuritySession != null)
                                {
                                    using (Stream senderClssReading = new DelimiterStream(incomingStream, length))
                                    {
                                        clsseStream = httpServerConnection.Sender_SecuritySession.EstablishSession(
                                            senderClssReading, true);
                                    }
                                }

                                if (clsseStream == null)
                                    clsseStream = Stream.Null;

                                using (new GenuineChunkedStreamSizeLabel(outputStream))
                                    GenuineUtility.CopyStreamToStream(clsseStream, outputStream);

                                // P/Listener
                                length = binaryReader.ReadInt32();
                                clsseStream = Stream.Null;
                                if (httpServerConnection.Listener_SecuritySession != null)
                                    clsseStream = httpServerConnection.Listener_SecuritySession.EstablishSession(
                                        new DelimiterStream(incomingStream, length), true);

                                if (clsseStream == null)
                                    clsseStream = Stream.Null;

                                using (new GenuineChunkedStreamSizeLabel(outputStream))
                                    GenuineUtility.CopyStreamToStream(clsseStream, outputStream);

                                // write the answer
                                Stream finalStream = outputStream;
                                this.LowLevel_SendStream(httpServerRequestResult.HttpContext, false, null, false, ref finalStream, httpServerConnection);
                                break;

                            case HttpPacketType.Listening:
                                postponeResponse = this.LowLevel_ProcessListenerRequest(httpServerRequestResult, httpServerConnection, sequenceNo);
                                break;

                            case HttpPacketType.Usual:
                                this.LowLevel_ProcessSenderRequest(genuineConnectionType, incomingStream, httpServerRequestResult, httpServerConnection, sequenceNo, remote);
                                break;

                            default:
                                // LOG:
                                if ( binaryLogWriter != null && binaryLogWriter[LogCategory.Connection] > 0 )
                                {
                                    binaryLogWriter.WriteEvent(LogCategory.Connection, "HttpServerConnectionManager.HandleIncomingRequest",
                                        LogMessageType.Error, GenuineExceptions.Get_Debugging_GeneralWarning("Unexpected type of the packet."), null, remote, null,
                                        GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name, null, null, httpServerConnection == null ? -1 : httpServerConnection.DbgConnectionId,
                                        0, 0, 0, null, null, null, null,
                                        "Unexpected type of the packet. Packet type: {0}. Sequence no: {1}. Content length: {2}. Host address: {3}.",
                                        Enum.Format(typeof(HttpPacketType), httpPacketType, "g"), sequenceNo, httpRequest.ContentLength, httpRequest.UserHostAddress);
                                }
                                break;
                        }
                    }
                        break;

                    case GenuineConnectionType.Named:
                        throw new NotSupportedException("Named connections are not supported.");

                    case GenuineConnectionType.Invocation:
                        // renew the host
                        remote.Renew(this._closeInvocationConnectionAfterInactivity, false);

                        this.LowLevel_ProcessSenderRequest(genuineConnectionType, incomingStream, httpServerRequestResult, null, sequenceNo, remote);
                        break;
                }
            }
            catch(Exception ex)
            {
                // LOG:
                if ( binaryLogWriter != null && binaryLogWriter[LogCategory.Connection] > 0 )
                {
                    binaryLogWriter.WriteEvent(LogCategory.Connection, "HttpServerConnectionManager.HandleIncomingRequest",
                        LogMessageType.ReceivingFinished, ex, null, null, null,
                        GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name, null, null, -1,
                        0, 0, 0, null, null, null, null,
                        "Error occurred while processing incoming HTTP request.");
                }
            }
            finally
            {
                if (! postponeResponse)
                    httpServerRequestResult.Complete(true);
            }
        }
        /// <summary>
        /// Handles the listener request.
        /// </summary>
        /// <param name="httpServerRequestResult">The request.</param>
        /// <param name="httpServerConnection">The connection.</param>
        /// <param name="requestedSequenceNo">The sequence number.</param>
        /// <returns>True if the response should be delayed.</returns>
        public bool LowLevel_ProcessListenerRequest(HttpServerRequestResult httpServerRequestResult, HttpServerConnection httpServerConnection, int requestedSequenceNo)
        {
            BinaryLogWriter binaryLogWriter = this.ITransportContext.BinaryLogWriter;
            GenuineChunkedStream responseStream = null;

            lock (httpServerConnection.Listener_Lock)
            {
                // if there is an already registered listener request, release it
                if (httpServerConnection.Listener != null)
                {
                    try
                    {
                        this.LowLevel_ReportServerError(httpServerConnection.Listener.HttpContext);
                    }
                    finally
                    {
                        httpServerConnection.Listener.Complete(false);
                        httpServerConnection.Listener = null;
                    }
                }

                try
                {
                    Debug.Assert(httpServerConnection.Listener == null);

                    // if the previous content requested - send it
                    if (requestedSequenceNo == httpServerConnection.Listener_SequenceNo && httpServerConnection.Listener_SentStream != null)
                    {
                        httpServerConnection.Listener_SentStream.Position = 0;
                        this.LowLevel_SendStream(httpServerRequestResult.HttpContext, true, httpServerConnection, false, ref httpServerConnection.Listener_SentStream, httpServerConnection);
                        return false;
                    }

                    // if too old content version requested - send an error
                    if (requestedSequenceNo < httpServerConnection.Listener_SequenceNo || requestedSequenceNo > httpServerConnection.Listener_SequenceNo + 1)
                    {
                        // LOG:
                        if ( binaryLogWriter != null && binaryLogWriter[LogCategory.Connection] > 0 )
                        {
                            string errorMessage = string.Format("Desynchronization error. Current sequence number: {0}. Requested sequence number: {1}.", httpServerConnection.Listener_SequenceNo, requestedSequenceNo);
                            binaryLogWriter.WriteEvent(LogCategory.Connection, "HttpServerConnectionManager.LowLevel_ProcessListenerRequest",
                                LogMessageType.Error, GenuineExceptions.Get_Debugging_GeneralWarning(errorMessage), null, httpServerConnection.Remote, null,
                                GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name, null, null,
                                httpServerConnection.DbgConnectionId, 0, 0, 0, null, null, null, null,
                                errorMessage);
                        }

                        // send the error
                        Stream errorResponseStream = this.LowLevel_CreateStreamWithHeader(HttpPacketType.Desynchronization, requestedSequenceNo, httpServerConnection.Remote);
                        MessageCoder.FillInLabelledStream(null, null, null, (GenuineChunkedStream) errorResponseStream, httpServerConnection.Listener_IntermediateBuffer, (int) this.ITransportContext.IParameterProvider[GenuineParameter.HttpRecommendedPacketSize]);
                        this.LowLevel_SendStream(httpServerRequestResult.HttpContext, true, httpServerConnection, true, ref errorResponseStream, httpServerConnection);
                        return false;
                    }

                    // the next sequence is requested
                    if (httpServerConnection.Listener_SentStream != null)
                    {
                        // release the content
                        httpServerConnection.Listener_MessagesBeingSent.Clear();

                        httpServerConnection.Listener_SentStream.Close();
                        httpServerConnection.Listener_SentStream = null;
                    }

                    Message message = httpServerConnection.Listener_MessageContainer.GetMessage();
                    if (message == null)
                    {
                        // LOG:
                        if ( binaryLogWriter != null && binaryLogWriter[LogCategory.Connection] > 0 )
                        {
                            binaryLogWriter.WriteEvent(LogCategory.Connection, "HttpServerConnectionManager.LowLevel_ProcessListenerRequest",
                                LogMessageType.ReceivingFinished, null, null, httpServerConnection.Remote, null,
                                GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name, null, null,
                                httpServerConnection.DbgConnectionId, 0, 0, 0, null, null, null, null,
                                "Listener request is postponed.");
                        }

                        // no data is available, postpone the request
                        httpServerConnection.Listener_Opened = GenuineUtility.TickCount;
                        httpServerConnection.Listener = httpServerRequestResult;
                        httpServerConnection.Listener_SequenceNo = requestedSequenceNo;
                        return true;
                    }

                    // some data is available, gather the stream and send it
                    responseStream = this.LowLevel_CreateStreamWithHeader(HttpPacketType.Usual, requestedSequenceNo, httpServerConnection.Remote);
                    MessageCoder.FillInLabelledStream(message, httpServerConnection.Listener_MessageContainer,
                        httpServerConnection.Listener_MessagesBeingSent, responseStream,
                        httpServerConnection.Listener_IntermediateBuffer,
                        (int) this.ITransportContext.IParameterProvider[GenuineParameter.HttpRecommendedPacketSize]);

                    // LOG:
                    if ( binaryLogWriter != null && binaryLogWriter[LogCategory.MessageProcessing] > 0 )
                    {
                        for ( int i = 0; i < httpServerConnection.Listener_MessagesBeingSent.Count; i++)
                        {
                            Message nextMessage = (Message) httpServerConnection.Listener_MessagesBeingSent[i];

                            binaryLogWriter.WriteEvent(LogCategory.MessageProcessing, "HttpServerConnectionManager.LowLevel_ProcessListenerRequest",
                                LogMessageType.MessageIsSentAsynchronously, null, nextMessage, httpServerConnection.Remote, null,
                                GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name, httpServerConnection.Listener_SecuritySession,
                                null,
                                httpServerConnection.DbgConnectionId, httpServerConnection.Listener_SequenceNo, 0, 0, null, null, null, null,
                                "The message is sent in the LISTENER stream N: {0}.", httpServerConnection.Listener_SequenceNo);
                        }
                    }

                    httpServerConnection.Listener_SentStream = responseStream;
                    httpServerConnection.Listener_SequenceNo = requestedSequenceNo;
                    this.LowLevel_SendStream(httpServerRequestResult.HttpContext, true, httpServerConnection, true, ref httpServerConnection.Listener_SentStream, httpServerConnection);
                }
                catch(Exception ex)
                {
                    // LOG:
                    if ( binaryLogWriter != null && binaryLogWriter[LogCategory.Connection] > 0 )
                    {
                        binaryLogWriter.WriteEvent(LogCategory.Connection, "HttpServerConnectionManager.LowLevel_ProcessListenerRequest",
                            LogMessageType.Error, ex, null, httpServerConnection.Remote, null,
                            GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name, null, null,
                            httpServerConnection.DbgConnectionId, 0, 0, 0, null, null, null, null,
                            "Error occurred while processing the listener request N: {0}.", httpServerConnection.Listener_SequenceNo);
                    }
                }
            }

            return false;
        }
        /// <summary>
        /// Sends the packet with empty content and specified type of packet to the remote host
        /// through the listening connection.
        /// </summary>
        /// <param name="httpServerConnection">The connection.</param>
        /// <param name="httpPacketType">The type of packet.</param>
        private void Pool_SendThroughListener(HttpServerConnection httpServerConnection, HttpPacketType httpPacketType)
        {
            lock (httpServerConnection.Listener_Lock)
            {
                if ( httpServerConnection.Listener == null )
                    return ;

                try
                {
                    Stream outputStream = this.LowLevel_CreateStreamWithHeader(httpPacketType, httpServerConnection.Listener_SequenceNo, httpServerConnection.Remote);
                    this.LowLevel_SendStream(httpServerConnection.Listener.HttpContext, true, httpServerConnection, true, ref outputStream, httpServerConnection);
                }
                finally
                {
                    httpServerConnection.Listener.Complete(false);
                    httpServerConnection.Listener = null;
                }
            }
        }