/// <summary>
        /// Copies data from the input stream to output stream.
        /// </summary>
        /// <param name="inputStream">The stream to copy from.</param>
        /// <param name="outputStream">The stream to copy to.</param>
        /// <param name="size">The size to be copied.</param>
        /// <returns>Number of remained bytes.</returns>
        public static int CopyStreamToStream(Stream inputStream, Stream outputStream, int size)
        {
            if (size <= 0)
                return 0;

            using(BufferKeeper bufferKeeper = new BufferKeeper(0))
            {
                int bufSize = bufferKeeper.Buffer.Length;
                int readSize = inputStream.Read(bufferKeeper.Buffer, 0, Math.Min(bufSize, size));
                while (readSize > 0 && size > 0)
                {
                    outputStream.Write(bufferKeeper.Buffer, 0, readSize);
                    size -= readSize;

                    if (size <= 0)
                        return size;

                    readSize = inputStream.Read(bufferKeeper.Buffer, 0, Math.Min(bufSize, size));
                }
            }

            return size;
        }
        /// <summary>
        /// Copies the content of the input stream into the output stream without touching a part 
        /// with the specified size in the end of the input stream.
        /// </summary>
        /// <param name="inputStream">The incoming data.</param>
        /// <param name="outputStream">The output data.</param>
        /// <param name="signSize">The size of the intact block.</param>
        /// <returns>The untouched block wrapped into a stream.</returns>
        public static byte[] CopyStreamToStreamExceptSign(Stream inputStream, Stream outputStream, int signSize)
        {
            using(BufferKeeper bufferKeeper = new BufferKeeper(0))
            {
                int bufSize = bufferKeeper.Buffer.Length;
                int readSize = inputStream.Read(bufferKeeper.Buffer, 0, bufSize);
                int validSize = 0;

                while (readSize > 0)
                {
                    validSize += readSize;

                    if (validSize > signSize)
                    {
                        // pour off the current content
                        outputStream.Write(bufferKeeper.Buffer, 0, validSize - signSize);
                        Buffer.BlockCopy(bufferKeeper.Buffer, validSize - signSize, bufferKeeper.Buffer, 0, signSize);
                        validSize = signSize;
                    }

                    readSize = inputStream.Read(bufferKeeper.Buffer, validSize, bufSize - validSize);
                }

                byte[] sign = new byte[validSize];
                Buffer.BlockCopy(bufferKeeper.Buffer, 0, sign, 0, validSize);
                return sign;
            }
        }
        /// <summary>
        /// Copies data from one stream to another.
        /// </summary>
        /// <param name="inputStream">Stream to copy from.</param>
        /// <param name="outputStream">Stream to copy to.</param>
        public static void CopyStreamToStream(Stream inputStream, Stream outputStream)
        {
            GenuineChunkedStream inputGenuineChunkedStream = inputStream as GenuineChunkedStream;
            if (inputGenuineChunkedStream != null)
            {
                inputGenuineChunkedStream.WriteTo(outputStream);
                return ;
            }

            using(BufferKeeper bufferKeeper = new BufferKeeper(0))
            {
                int bufSize = bufferKeeper.Buffer.Length;
                int readSize = inputStream.Read(bufferKeeper.Buffer, 0, bufSize);
                while (readSize > 0)
                {
                    outputStream.Write(bufferKeeper.Buffer, 0, readSize);
                    readSize = inputStream.Read(bufferKeeper.Buffer, 0, bufSize);
                }
            }
        }
        /// <summary>
        /// Fills up the destination with a sequence of bytes read from the source stream.
        /// </summary>
        /// <param name="destination">The destination.</param>
        /// <param name="offset">The zero-based byte offset in buffer at which to begin copying bytes to the current stream.</param>
        /// <param name="count">The number of bytes to be written to the destination.</param>
        /// <param name="sourceStream">The source.</param>
        public static unsafe void Read(byte *destination, int offset, int count, Stream sourceStream)
        {
            using (BufferKeeper bufferKeeper = new BufferKeeper(0))
            {
                while ( count > 0 )
                {
                    // read data to the intermediate buffer
                    int sizeOfTheNextPortion = Math.Min(bufferKeeper.Buffer.Length, count);
                    GenuineUtility.ReadDataFromStream(sourceStream, bufferKeeper.Buffer, 0, sizeOfTheNextPortion);
                    fixed (byte *source = bufferKeeper.Buffer)
                        RtlCopyMemory32(destination + offset, source, sizeOfTheNextPortion);

                    offset += sizeOfTheNextPortion;
                    count -= sizeOfTheNextPortion;
                }
            }
        }
        /// <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>
        /// Puts down a content of the stream.
        /// </summary>
        /// <param name="stream">The stream containing content.</param>
        private void WriteBinaryContent(Stream stream)
        {
            if (stream == null)
                this.BinaryWriter.Write( (bool) false );
            else
            {
                this.BinaryWriter.Write( (bool) true );

                using (BufferKeeper bufferKeeper = new BufferKeeper(0))
                {
                    for ( ; ; )
                    {
                        int bytesRead = stream.Read(bufferKeeper.Buffer, 0, bufferKeeper.Buffer.Length);

                        // if the end of the stream has been reached
                        if (bytesRead <= 0)
                        {
                            this.BinaryWriter.Write( (int) 0);
                            stream.Position = 0;
                            return ;
                        }

                        this.BinaryWriter.Write( (int) bytesRead);
                        this.BinaryWriter.Write(bufferKeeper.Buffer, 0, bytesRead);
                    }
                }

            }
        }
 /// <summary>
 /// Closes the current stream and releases any resources associated with the current stream.
 /// </summary>
 public override void Close()
 {
     // read the remaining bytes
     if (this._assumedLength > 0)
         using ( BufferKeeper bufferKeeper = new BufferKeeper(0) )
         {
             while (this._assumedLength > 0)
             {
                 int bytesRead = this._underlyingStream.Read(bufferKeeper.Buffer, 0, (int) this._assumedLength);
                 this._assumedLength -= bytesRead;
                 if (bytesRead == 0)
                     throw GenuineExceptions.Get_Receive_IncorrectData();
             }
         }
 }