/// <summary>
        /// Initiates an asynchronous call to the HTTP handler.
        /// </summary>
        /// <param name="context">An HttpContext object that provides references to intrinsic server objects (for example, Request, Response, Session, and Server) used to service HTTP requests.</param>
        /// <param name="cb">The AsyncCallback to call when the asynchronous method call is complete. If cb is a null reference (Nothing in Visual Basic), the delegate is not called.</param>
        /// <param name="extraData">Any extra data needed to process the request.</param>
        /// <returns>An IAsyncResult that contains information about the status of the process.</returns>
        public IAsyncResult BeginProcessRequest(HttpContext context, AsyncCallback cb, object extraData)
        {
            try
            {
                HttpServerRequestResult httpServerRequestResult = new HttpServerRequestResult(context, cb, extraData);
                httpServerRequestResult.IPrincipal = Thread.CurrentPrincipal;

                lock (this._httpServerConnectionManagerLock)
                    if (this._httpServerConnectionManager == null)
                    {
                        GenuineHttpServerChannel serverChannel = ChannelServices.GetChannel("ghttp") as GenuineHttpServerChannel;
                        if (serverChannel == null)
                        {
                            throw GenuineExceptions.Get_Receive_NoServerChannel();
                        }

                        this._httpServerConnectionManager = serverChannel.ITransportContext.ConnectionManager as HttpServerConnectionManager;
                    }

//				GenuineThreadPool.QueueUserWorkItem(new WaitCallback(this._httpServerConnectionManager.HandleIncomingRequest), httpServerRequestResult, true);
                this._httpServerConnectionManager.HandleIncomingRequest(httpServerRequestResult);
                return(httpServerRequestResult);
            }
            catch (Exception ex)
            {
                // LOG:
                BinaryLogWriter binaryLogWriter = GenuineLoggingServices.BinaryLogWriter;
                if (binaryLogWriter != null && binaryLogWriter[LogCategory.AcceptingConnection] > 0)
                {
                    binaryLogWriter.WriteEvent(LogCategory.AcceptingConnection, "HttpServerHandler.BeginProcessRequest",
                                               LogMessageType.ConnectionAccepting, ex, null, null, null,
                                               GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name,
                                               null, null, -1, 0, 0, 0, null, null, null, null,
                                               "Can't process an incoming connection.");
                }
                throw;
            }
        }
        /// <summary>
        /// Initiates an asynchronous call to the HTTP handler.
        /// </summary>
        /// <param name="context">An HttpContext object that provides references to intrinsic server objects (for example, Request, Response, Session, and Server) used to service HTTP requests.</param>
        /// <param name="cb">The AsyncCallback to call when the asynchronous method call is complete. If cb is a null reference (Nothing in Visual Basic), the delegate is not called.</param>
        /// <param name="extraData">Any extra data needed to process the request.</param>
        /// <returns>An IAsyncResult that contains information about the status of the process.</returns>
        public IAsyncResult BeginProcessRequest(HttpContext context, AsyncCallback cb, object extraData)
        {
            try
            {
                HttpServerRequestResult httpServerRequestResult = new HttpServerRequestResult(context, cb, extraData);
                httpServerRequestResult.IPrincipal = Thread.CurrentPrincipal;

                lock (this._httpServerConnectionManagerLock)
                    if (this._httpServerConnectionManager == null)
                    {
                        GenuineHttpServerChannel serverChannel = ChannelServices.GetChannel("ghttp") as GenuineHttpServerChannel;
                        if (serverChannel == null)
                            throw GenuineExceptions.Get_Receive_NoServerChannel();

                        this._httpServerConnectionManager = serverChannel.ITransportContext.ConnectionManager as HttpServerConnectionManager;
                    }

            //				GenuineThreadPool.QueueUserWorkItem(new WaitCallback(this._httpServerConnectionManager.HandleIncomingRequest), httpServerRequestResult, true);
                this._httpServerConnectionManager.HandleIncomingRequest(httpServerRequestResult);
                return httpServerRequestResult;
            }
            catch(Exception ex)
            {
                // LOG:
                BinaryLogWriter binaryLogWriter = GenuineLoggingServices.BinaryLogWriter;
                if ( binaryLogWriter != null && binaryLogWriter[LogCategory.AcceptingConnection] > 0 )
                {
                    binaryLogWriter.WriteEvent(LogCategory.AcceptingConnection, "HttpServerHandler.BeginProcessRequest",
                        LogMessageType.ConnectionAccepting, ex, null, null, null,
                        GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name,
                        null, null, -1, 0, 0, 0, null, null, null, null,
                        "Can't process an incoming connection.");
                }
                throw;
            }
        }
        /// <summary>
        /// Processes incoming requests and responses.
        /// </summary>
        /// <param name="stream">The stream containing a request or a response.</param>
        /// <param name="remote">The remote host.</param>
        /// <param name="genuineConnectionType">The type of the connection.</param>
        /// <param name="connectionName">Connection id to send a response through.</param>
        /// <param name="dbgConnectionId">The identifier of the connection, which is used for debugging purposes only.</param>
        /// <param name="useThisThread">True to invoke the target in the current thread.</param>
        /// <param name="iMessageRegistrator">The message registrator.</param>
        /// <param name="connectionLevelSecuritySession">Connection Level Security Session.</param>
        /// <param name="httpServerRequestResult">The HTTP request through which the message was received.</param>
        /// <returns>True if it's a one-way message.</returns>
        public bool HandleMessage(Stream stream, HostInformation remote, GenuineConnectionType genuineConnectionType, string connectionName, int dbgConnectionId, bool useThisThread, IMessageRegistrator iMessageRegistrator, SecuritySession connectionLevelSecuritySession, HttpServerRequestResult httpServerRequestResult)
        {
            // read the Security Session name
            BinaryReader binaryReader = new BinaryReader(stream);
            string sessionName = binaryReader.ReadString();
            Message message = null;
            BinaryLogWriter binaryLogWriter = this.ITransportContext.BinaryLogWriter;

            // and decode the packet
            SecuritySession securitySession = remote.GetSecuritySession(sessionName, this.ITransportContext.IKeyStore);
            if (securitySession == null)
            {
                // LOG:
                if ( binaryLogWriter != null && binaryLogWriter[LogCategory.Security] > 0 )
                {
                    binaryLogWriter.WriteEvent(LogCategory.Security, "GenuineReceivingHandler.HandleMessage",
                        LogMessageType.SecuritySessionApplied, GenuineExceptions.Get_Security_ContextNotFound(sessionName),
                        message, remote,
                        null, GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name,
                        securitySession, sessionName, dbgConnectionId,
                        0, 0, 0, null, null, null, null,
                        "The requested Security Session can not be constructed or established. The name of Security Session: {0}.",
                        sessionName);
                }

                this.ITransportContext.IGenuineEventProvider.Fire(new GenuineEventArgs(GenuineEventType.SecuritySessionWasNotFound, GenuineExceptions.Get_Security_ContextNotFound(sessionName),
                    remote, null));

                return true;
            }

            // decode the stream and roll back if it was a Security Session's message
            stream = securitySession.Decrypt(stream);
            if (stream == null)
                return true;

            // read the message
            message = MessageCoder.Deserialize(stream, sessionName);
            message.ConnectionName = connectionName;
            message.SecuritySessionParameters._connectionName = connectionName;
            message.SecuritySessionParameters._genuineConnectionType = genuineConnectionType;
            message.Sender = remote;
            message.ITransportContext = this.ITransportContext;
            message.ConnectionLevelSecuritySession = connectionLevelSecuritySession;
            message.HttpServerRequestResult = httpServerRequestResult;

            // LOG:
            if ( binaryLogWriter != null && binaryLogWriter[LogCategory.Security] > 0 )
            {
                binaryLogWriter.WriteEvent(LogCategory.Security, "GenuineReceivingHandler.HandleMessage",
                    LogMessageType.SecuritySessionApplied, null, message, remote,
                    null, GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name,
                    securitySession, sessionName, dbgConnectionId,
                    0, 0, 0, null, null, null, null,
                    "The Security Session has been used for decrypting the message.");
            }

            // LOG:
            if ( binaryLogWriter != null && binaryLogWriter[LogCategory.MessageProcessing] > 0 )
            {
                bool readContent = this.ITransportContext.BinaryLogWriter[LogCategory.MessageProcessing] > 1;
                if (readContent)
                {
                    GenuineChunkedStream streamClone = new GenuineChunkedStream();
                    GenuineUtility.CopyStreamToStream(message.Stream, streamClone);
                    message.Stream = streamClone;
                }

                binaryLogWriter.WriteMessageCreatedEvent("GenuineReceivingHandler.HandleMessage",
                    LogMessageType.MessageReceived, null, message, message.ReplyToId > 0, remote,
                    readContent ? message.Stream : null,
                    message.ITransportHeaders[Message.TransportHeadersInvocationTarget] as string, message.ITransportHeaders[Message.TransportHeadersMethodName] as string,
                    GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name, connectionName, dbgConnectionId,
                    connectionLevelSecuritySession == null ? -1 : connectionLevelSecuritySession.SecuritySessionId,
                    connectionLevelSecuritySession == null ? null : connectionLevelSecuritySession.Name,
                    securitySession == null ? -1 : securitySession.SecuritySessionId,
                    securitySession.Name,
                    "The message has been received.");
            }

            if (message.ReplyToId == PING_MESSAGE_REPLYID)
                return true;

            if (iMessageRegistrator != null && iMessageRegistrator.WasRegistered(remote.Uri, message.MessageId, message.ReplyToId))
            {
                // LOG:
                if ( binaryLogWriter != null && binaryLogWriter[LogCategory.MessageProcessing] > 0 )
                    binaryLogWriter.WriteEvent(LogCategory.MessageProcessing, "GenuineReceivingHandler.HandleMessage",
                        LogMessageType.MessageDispatched, GenuineExceptions.Get_Debugging_GeneralWarning("The message has been already processed."), message, remote,
                        null,
                        GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name, securitySession, securitySession.Name,
                        dbgConnectionId,
                        GenuineUtility.TickCount, 0, message.SeqNo, null, null, null, null,
                        "The message has been already processed. Therefore, this message is ignored.");

                return true;
            }

            // if it's a response, then direct the message to the response handler
            if (message.ReplyToId > 0)
            {
                message.IsOneWay = true;
                IResponseProcessor iResponseProcessor = GenuineReceivingHandler._responseHandlers[message.ReplyToId] as IResponseProcessor;

                // nothing waits for this request
                if (iResponseProcessor == null)
                    return true;

                // 2.5.1: set the answer flag
                if (iResponseProcessor.Message != null)
                    iResponseProcessor.Message.HasBeenAsnwered = true;

                if (iResponseProcessor.IsShortInProcessing)
                {
                    iResponseProcessor.ProcessRespose(message);

            #if TRIAL
            #else
                    if (iResponseProcessor.IsExpired(GenuineUtility.TickCount))
                        GenuineReceivingHandler._responseHandlers.Remove(message.ReplyToId);
            #endif

                    return true;
                }
            }

            // take care about the thread and call context
            if (useThisThread)
                InternalExecuteMessage(message);
            else
                GenuineThreadPool.QueueUserWorkItem(this._waitCallback_InternalExecuteMessagewaitCallback, message, false);

            return message.IsOneWay;
        }
        /// <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 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;
        }