/// <summary>
        /// Completes the HTTP request.
        /// </summary>
        /// <param name="ar">The result of the HTTP request.</param>
        private void OnRequestCompleted(IAsyncResult ar)
        {
            HttpWebResponse httpWebResponse = null;
            Stream          inputStream     = null;
            ConnectionInfo  connectionInfo  = null;

            try
            {
                connectionInfo = (ConnectionInfo)ar.AsyncState;
                HttpWebRequest httpWebRequest = connectionInfo.HttpWebRequest;
#if (FRM20)
                // timeout has been already set
                try
                {
                    httpWebResponse = (HttpWebResponse)httpWebRequest.GetResponse();
                }
                catch (WebException ex)
                {
                    if (ex.Status == WebExceptionStatus.Timeout)
                    {
                        return;
                    }
                }
#else
                httpWebResponse = (HttpWebResponse)httpWebRequest.EndGetResponse(ar);
#endif
                this.Remote.Renew(this._hostRenewingSpan, false);

                // process the content
                inputStream = httpWebResponse.GetResponseStream();

#if DEBUG
//				if (this.ITransportContext.IEventLogger.AcceptBinaryData)
//				{
//					byte[] content = new byte[(int) httpWebResponse.ContentLength];
//					GenuineUtility.ReadDataFromStream(inputStream, content, 0, content.Length);
//
//					this.ITransportContext.IEventLogger.Log(LogMessageCategory.Traffic, null, "HttpInvocationConnection.OnRequestCompleted",
//						content, "The content of the response received by the HttpInvocationConnection. Size: {0}.", content.Length);
//					inputStream = new MemoryStream(content, false);
//				}
#endif

                BinaryReader   binaryReader = new BinaryReader(inputStream);
                string         serverUri;
                int            sequenceNo;
                HttpPacketType httpPacketType;
                int            remoteHostUniqueIdentifier;
                HttpMessageCoder.ReadResponseHeader(binaryReader, out serverUri, out sequenceNo, out httpPacketType, out remoteHostUniqueIdentifier);

#if DEBUG
//				this.ITransportContext.IEventLogger.Log(LogMessageCategory.TransportLayer, null, "HttpInvocationConnection.OnRequestCompleted",
//					null, "The invocation request returned. Server uri: {0}. Sequence no: {1}. Packet type: {2}. Content-encoding: {3}. Content-length: {4}. Protocol version: {5}. Response uri: \"{6}\". Server: \"{7}\". Status code: {8}. Status description: \"{9}\".",
//					serverUri, sequenceNo, Enum.Format(typeof(HttpPacketType), httpPacketType, "g"),
//					httpWebResponse.ContentEncoding, httpWebResponse.ContentLength,
//					httpWebResponse.ProtocolVersion, httpWebResponse.ResponseUri,
//					httpWebResponse.Server, httpWebResponse.StatusCode, httpWebResponse.StatusDescription);
#endif

                // if the remote host has asked to terminate a connection
                if (httpPacketType == HttpPacketType.ClosedManually || httpPacketType == HttpPacketType.Desynchronization || httpPacketType == HttpPacketType.SenderError)
                {
                    throw GenuineExceptions.Get_Receive_ConnectionClosed();
                }

                // skip the first byte
                if (binaryReader.ReadByte() != 0)
                {
                    if (!connectionInfo.Message.IsOneWay)
                    {
//						this.ITransportContext.IEventLogger.Log(LogMessageCategory.FatalError, GenuineExceptions.Get_Processing_LogicError("The invocation response doesn't contain any messages."), "HttpInvocationConnection.OnRequestCompleted",
//							null, "The HTTP response doesn't contain content. The response to the request was not received.");
                    }
                }
                else
                {
                    // fetch and process the response messages
                    using (BufferKeeper bufferKeeper = new BufferKeeper(0))
                    {
                        using (LabelledStream labelledStream = new LabelledStream(this.ITransportContext, inputStream, bufferKeeper.Buffer))
                        {
                            GenuineChunkedStream receivedRequest = new GenuineChunkedStream(true);
                            GenuineUtility.CopyStreamToStream(labelledStream, receivedRequest);
                            this.ITransportContext.IIncomingStreamHandler.HandleMessage(receivedRequest, this.Remote, GenuineConnectionType.Invocation, string.Empty, -1, true, null, null, null);
                        }
                    }
                }
            }
            catch (Exception ex)
            {
//				this.ITransportContext.IEventLogger.Log(LogMessageCategory.Error, ex, "HttpInvocationConnection.OnRequestCompleted",
//					null, "Exception occurred during receiving a response to an invocation request.");

                // dispatch the exception to the caller context
                if (connectionInfo != null)
                {
                    this.ITransportContext.IIncomingStreamHandler.DispatchException(connectionInfo.Message, ex);
                }
            }
            finally
            {
                if (inputStream != null)
                {
                    inputStream.Close();
                }
                if (httpWebResponse != null)
                {
                    httpWebResponse.Close();
                }

                // release the connection
                if (connectionInfo != null)
                {
                    this.ReleaseConnectionEntry(connectionInfo.Index);
                }
            }
        }
        /// <summary>
        /// Reads messages from the stream and processes them.
        /// </summary>
        /// <param name="stream">The source stream.</param>
        /// <param name="xHttpPhysicalConnection">The connection.</param>
        private void LowLevel_ParseLabelledStream(Stream stream, XHttpPhysicalConnection xHttpPhysicalConnection)
        {
            BinaryReader binaryReader = new BinaryReader(stream);

            while ( binaryReader.ReadByte() == 0 )
            {
                using (LabelledStream labelledStream = new LabelledStream(this.ITransportContext, stream, xHttpPhysicalConnection.AsyncReceiveBuffer))
                {
                    GenuineChunkedStream receivedContent = new GenuineChunkedStream(true);
                    GenuineUtility.CopyStreamToStream(labelledStream, receivedContent);
                    this.ITransportContext.IIncomingStreamHandler.HandleMessage(receivedContent, xHttpPhysicalConnection.Remote, xHttpPhysicalConnection.XHttpConnection.GenuineConnectionType, xHttpPhysicalConnection.XHttpConnection.ConnectionName, xHttpPhysicalConnection.XHttpConnection.DbgConnectionId, false, null, xHttpPhysicalConnection.ConnectionLevelSecurity, null);
                }
            }
        }
        /// <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>
        /// Reads messages from the stream and processes them.
        /// </summary>
        /// <param name="stream">The source stream.</param>
        /// <param name="intermediateBuffer">The intermediate buffer.</param>
        /// <param name="httpClientConnection">The connection.</param>
        /// <param name="connectionLevelSecuritySession">The Connection Level Security Session that decrypted this message.</param>
        public void LowLevel_ParseLabelledStream(Stream stream, byte[] intermediateBuffer, HttpClientConnection httpClientConnection, SecuritySession connectionLevelSecuritySession)
        {
            bool directExecution = httpClientConnection.GenuineConnectionType == GenuineConnectionType.Invocation;

            BinaryReader binaryReader = new BinaryReader(stream);

            while ( binaryReader.ReadByte() == 0 )
            {
                using (LabelledStream labelledStream = new LabelledStream(this.ITransportContext, stream, intermediateBuffer))
                {
                    if (directExecution)
                        this.ITransportContext.IIncomingStreamHandler.HandleMessage(labelledStream, httpClientConnection.Remote, httpClientConnection.GenuineConnectionType, httpClientConnection.ConnectionName, httpClientConnection.DbgConnectionId, true, null, connectionLevelSecuritySession, null);
                    else
                    {
                        GenuineChunkedStream receivedContent = new GenuineChunkedStream(true);
                        GenuineUtility.CopyStreamToStream(labelledStream, receivedContent);
                        this.ITransportContext.IIncomingStreamHandler.HandleMessage(receivedContent, httpClientConnection.Remote, httpClientConnection.GenuineConnectionType, httpClientConnection.ConnectionName, httpClientConnection.DbgConnectionId, false, null, connectionLevelSecuritySession, null);
                    }
                }
            }
        }