/// <summary>
 /// Reads the response from the stream.
 /// </summary>
 /// <param name="binaryReader">The source.</param>
 /// <param name="serverUri">The fetched server uri.</param>
 /// <param name="sequenceNo">The packet number.</param>
 /// <param name="httpPacketType">The type of the packet.</param>
 /// <param name="remoteHostUniqueIdentifier">The unique identifier of the HostInformation used by the remote host.</param>
 public static void ReadResponseHeader(BinaryReader binaryReader, out string serverUri, out int sequenceNo, out HttpPacketType httpPacketType, out int remoteHostUniqueIdentifier)
 {
     if (binaryReader.ReadByte() != MessageCoder.COMMAND_MAGIC_CODE)
         throw GenuineExceptions.Get_Receive_IncorrectData();
     serverUri = binaryReader.ReadString();
     sequenceNo = binaryReader.ReadInt32();
     httpPacketType = (HttpPacketType) binaryReader.ReadByte();
     remoteHostUniqueIdentifier = binaryReader.ReadInt32();
 }
        /// <summary>
        /// Parses the HTTP header.
        /// </summary>
        /// <param name="binaryReader">The source binary reader.</param>
        /// <param name="protocolVersion">The version of the protocol.</param>
        /// <param name="genuineConnectionType">The type of connection.</param>
        /// <param name="hostId">The identifier of the remote host.</param>
        /// <param name="httpPacketType">The type of the packet.</param>
        /// <param name="sequenceNo">The packet number.</param>
        /// <param name="connectionName">The name of the connection.</param>
        /// <param name="remoteHostUniqueIdentifier">The unique identifier of the HostInformation used by the remote host.</param>
        public static void ReadRequestHeader(BinaryReader binaryReader, out byte protocolVersion, out GenuineConnectionType genuineConnectionType, out Guid hostId, out HttpPacketType httpPacketType, out int sequenceNo, out string connectionName, out int remoteHostUniqueIdentifier)
        {
            if (binaryReader.ReadByte() != MessageCoder.COMMAND_MAGIC_CODE)
                throw GenuineExceptions.Get_Receive_IncorrectData();

            protocolVersion = binaryReader.ReadByte();
            genuineConnectionType = (GenuineConnectionType) binaryReader.ReadByte();
            hostId = new Guid(binaryReader.ReadBytes(16));
            httpPacketType = (HttpPacketType) binaryReader.ReadByte();
            sequenceNo = binaryReader.ReadInt32();

            connectionName = "$/__GC/" + hostId;
            remoteHostUniqueIdentifier = 0;

            if (protocolVersion >= 0x1)
            {
                connectionName = binaryReader.ReadString();
                remoteHostUniqueIdentifier = binaryReader.ReadInt32();
            }
        }
 /// <summary>
 /// Writes HTTP header to the specified binary writer.
 /// </summary>
 /// <param name="binaryWriter">The binary writer.</param>
 /// <param name="protocolVersion">The version of the protocol.</param>
 /// <param name="genuineConnectionType">The type of connection.</param>
 /// <param name="hostId">The id of the remote host.</param>
 /// <param name="httpPacketType">The type of the packet.</param>
 /// <param name="sequenceNo">The packet number.</param>
 /// <param name="connectionName">The name of the connection.</param>
 /// <param name="localHostUniqueIdentifier">The unique identifier of the local HostInformation.</param>
 public static void WriteRequestHeader(BinaryWriter binaryWriter, byte protocolVersion, GenuineConnectionType genuineConnectionType, byte[] hostId, HttpPacketType httpPacketType, int sequenceNo, string connectionName, int localHostUniqueIdentifier)
 {
     binaryWriter.Write((byte) MessageCoder.COMMAND_MAGIC_CODE);
     binaryWriter.Write((byte) protocolVersion);
     binaryWriter.Write((byte) genuineConnectionType);
     binaryWriter.Write(hostId);
     binaryWriter.Write((byte) httpPacketType);
     binaryWriter.Write((int) sequenceNo);
     binaryWriter.Write(connectionName);
     binaryWriter.Write((int) localHostUniqueIdentifier);
 }
Esempio n. 4
0
        /// <summary>
        /// Writes the HTTP response header.
        /// </summary>
        /// <param name="binaryWriter">The destination.</param>
        /// <param name="protocolVersion">The version of the protocol.</param>
        /// <param name="serverUri">The server uri.</param>
        /// <param name="sequenceNo">The packet number.</param>
        /// <param name="httpPacketType">The type of the packet.</param>
        /// <param name="localHostUniqueIdentifier">The unique identifier of the local HostInformation.</param>
        public static void WriteResponseHeader(BinaryWriter binaryWriter, byte protocolVersion, string serverUri, int sequenceNo, HttpPacketType httpPacketType, int localHostUniqueIdentifier)
        {
            binaryWriter.Write((byte)MessageCoder.COMMAND_MAGIC_CODE);
            binaryWriter.Write(serverUri);
            binaryWriter.Write((int)sequenceNo);
            binaryWriter.Write((byte)httpPacketType);

            if (protocolVersion > 0)
            {
                binaryWriter.Write((int)localHostUniqueIdentifier);
            }
        }
        /// <summary>
        /// Writes the HTTP response header.
        /// </summary>
        /// <param name="binaryWriter">The destination.</param>
        /// <param name="protocolVersion">The version of the protocol.</param>
        /// <param name="serverUri">The server uri.</param>
        /// <param name="sequenceNo">The packet number.</param>
        /// <param name="httpPacketType">The type of the packet.</param>
        /// <param name="localHostUniqueIdentifier">The unique identifier of the local HostInformation.</param>
        public static void WriteResponseHeader(BinaryWriter binaryWriter, byte protocolVersion, string serverUri, int sequenceNo, HttpPacketType httpPacketType, int localHostUniqueIdentifier)
        {
            binaryWriter.Write((byte) MessageCoder.COMMAND_MAGIC_CODE);
            binaryWriter.Write(serverUri);
            binaryWriter.Write((int) sequenceNo);
            binaryWriter.Write((byte) httpPacketType);

            if (protocolVersion > 0)
                binaryWriter.Write((int) localHostUniqueIdentifier);
        }
Esempio n. 6
0
 /// <summary>
 /// Writes HTTP header to the specified binary writer.
 /// </summary>
 /// <param name="binaryWriter">The binary writer.</param>
 /// <param name="protocolVersion">The version of the protocol.</param>
 /// <param name="genuineConnectionType">The type of connection.</param>
 /// <param name="hostId">The id of the remote host.</param>
 /// <param name="httpPacketType">The type of the packet.</param>
 /// <param name="sequenceNo">The packet number.</param>
 /// <param name="connectionName">The name of the connection.</param>
 /// <param name="localHostUniqueIdentifier">The unique identifier of the local HostInformation.</param>
 public static void WriteRequestHeader(BinaryWriter binaryWriter, byte protocolVersion, GenuineConnectionType genuineConnectionType, byte[] hostId, HttpPacketType httpPacketType, int sequenceNo, string connectionName, int localHostUniqueIdentifier)
 {
     binaryWriter.Write((byte)MessageCoder.COMMAND_MAGIC_CODE);
     binaryWriter.Write((byte)protocolVersion);
     binaryWriter.Write((byte)genuineConnectionType);
     binaryWriter.Write(hostId);
     binaryWriter.Write((byte)httpPacketType);
     binaryWriter.Write((int)sequenceNo);
     binaryWriter.Write(connectionName);
     binaryWriter.Write((int)localHostUniqueIdentifier);
 }
Esempio n. 7
0
        /// <summary>
        /// Parses the HTTP header.
        /// </summary>
        /// <param name="binaryReader">The source binary reader.</param>
        /// <param name="protocolVersion">The version of the protocol.</param>
        /// <param name="genuineConnectionType">The type of connection.</param>
        /// <param name="hostId">The identifier of the remote host.</param>
        /// <param name="httpPacketType">The type of the packet.</param>
        /// <param name="sequenceNo">The packet number.</param>
        /// <param name="connectionName">The name of the connection.</param>
        /// <param name="remoteHostUniqueIdentifier">The unique identifier of the HostInformation used by the remote host.</param>
        public static void ReadRequestHeader(BinaryReader binaryReader, out byte protocolVersion, out GenuineConnectionType genuineConnectionType, out Guid hostId, out HttpPacketType httpPacketType, out int sequenceNo, out string connectionName, out int remoteHostUniqueIdentifier)
        {
            if (binaryReader.ReadByte() != MessageCoder.COMMAND_MAGIC_CODE)
            {
                throw GenuineExceptions.Get_Receive_IncorrectData();
            }

            protocolVersion       = binaryReader.ReadByte();
            genuineConnectionType = (GenuineConnectionType)binaryReader.ReadByte();
            hostId         = new Guid(binaryReader.ReadBytes(16));
            httpPacketType = (HttpPacketType)binaryReader.ReadByte();
            sequenceNo     = binaryReader.ReadInt32();

            connectionName             = "$/__GC/" + hostId;
            remoteHostUniqueIdentifier = 0;

            if (protocolVersion >= 0x1)
            {
                connectionName             = binaryReader.ReadString();
                remoteHostUniqueIdentifier = binaryReader.ReadInt32();
            }
        }
Esempio n. 8
0
 /// <summary>
 /// Reads the response from the stream.
 /// </summary>
 /// <param name="binaryReader">The source.</param>
 /// <param name="serverUri">The fetched server uri.</param>
 /// <param name="sequenceNo">The packet number.</param>
 /// <param name="httpPacketType">The type of the packet.</param>
 /// <param name="remoteHostUniqueIdentifier">The unique identifier of the HostInformation used by the remote host.</param>
 public static void ReadResponseHeader(BinaryReader binaryReader, out string serverUri, out int sequenceNo, out HttpPacketType httpPacketType, out int remoteHostUniqueIdentifier)
 {
     if (binaryReader.ReadByte() != MessageCoder.COMMAND_MAGIC_CODE)
     {
         throw GenuineExceptions.Get_Receive_IncorrectData();
     }
     serverUri                  = binaryReader.ReadString();
     sequenceNo                 = binaryReader.ReadInt32();
     httpPacketType             = (HttpPacketType)binaryReader.ReadByte();
     remoteHostUniqueIdentifier = binaryReader.ReadInt32();
 }
 /// <summary>
 /// Creates and returns the stream with a written response header.
 /// </summary>
 /// <param name="httpPacketType">The type of the packet.</param>
 /// <param name="sequenceNo">The sequence number.</param>
 /// <param name="remote">The HostInformation of the remote host.</param>
 /// <returns>The stream with a written response header.</returns>
 public GenuineChunkedStream LowLevel_CreateStreamWithHeader(HttpPacketType httpPacketType, int sequenceNo, HostInformation remote)
 {
     GenuineChunkedStream output = new GenuineChunkedStream(false);
     BinaryWriter binaryWriter = new BinaryWriter(output);
     HttpMessageCoder.WriteResponseHeader(binaryWriter, remote.ProtocolVersion, this.ITransportContext.ConnectionManager.Local.Uri, sequenceNo, httpPacketType, remote.LocalHostUniqueIdentifier);
     return output;
 }
        /// <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;
                }
            }
        }
        /// <summary>
        /// Sends HTTP content to the remote host.
        /// Does not process exceptions.
        /// Automatically initiates asynchronous receiving.
        /// Automatically manages stream seqNo for clients' connections.
        /// </summary>
        /// <param name="timeout">Operation timeout.</param>
        /// <param name="message">The message.</param>
        /// <param name="content">The content sent instead of the message.</param>
        /// <param name="exceptionToBeSent">The exception being sent in the response.</param>
        /// <param name="messageContainer">The message container.</param>
        /// <param name="xHttpPhysicalConnection">The physical connection.</param>
        /// <param name="genuineConnectionType">The type of the connection.</param>
        /// <param name="httpPacketType">The type of the HTTP packet.</param>
        /// <param name="repeatSending">Whether the content was already packed.</param>
        /// <param name="synchronous">Whether to send content synchronously.</param>
        /// <param name="startAutomaticReceiving">Indicates whether to start automatic receiving of the response/request if the type of the sending is synchronous.</param>
        /// <param name="applyClss">A boolean value indicating whether the CLSS should be applied.</param>
        private void LowLevel_SendHttpContent(int timeout, Message message, 
            GenuineChunkedStream content, Exception exceptionToBeSent,
            MessageContainer messageContainer, XHttpPhysicalConnection xHttpPhysicalConnection,
            GenuineConnectionType genuineConnectionType, HttpPacketType httpPacketType,
            bool repeatSending, bool synchronous, bool startAutomaticReceiving, bool applyClss
            )
        {
            BinaryLogWriter binaryLogWriter = this.ITransportContext.BinaryLogWriter;

            // check whether the connection is valid and available
            xHttpPhysicalConnection.CheckConnectionStatus();

            // prevent the ping
            if (! xHttpPhysicalConnection.IsSender)
                xHttpPhysicalConnection.XHttpConnection.LastTimeContentWasSent = GenuineUtility.TickCount;

            // valid copies
            Socket socket;
            Stream sentContent;

            // to prevent from changing sequence information or disposing sent content during its encryption
            lock (xHttpPhysicalConnection.PhysicalConnectionStateLock)
            {
                if (! repeatSending)
                {
                    if (xHttpPhysicalConnection.XHttpConnection.IsClient)
                        xHttpPhysicalConnection.SequenceNo ++;

                    if (message != null || (message == null && content == null && exceptionToBeSent == null))
                    {
                        GenuineChunkedStream packedMessages = new GenuineChunkedStream(false);
                        MessageCoder.FillInLabelledStream(message, messageContainer,
                            xHttpPhysicalConnection.MessagesBeingSent, packedMessages,
                            xHttpPhysicalConnection.AsyncSendBuffer,
                            (int) this.ITransportContext.IParameterProvider[GenuineParameter.HttpRecommendedPacketSize]);

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

                                binaryLogWriter.WriteEvent(LogCategory.Transport, "XHttpConnectionManager.LowLevel_SendHttpContent",
                                    LogMessageType.MessageIsSentAsynchronously, null, nextMessage, xHttpPhysicalConnection.Remote, null,
                                    GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name, xHttpPhysicalConnection.ConnectionLevelSecurity, null,
                                    xHttpPhysicalConnection.XHttpConnection.DbgConnectionId, xHttpPhysicalConnection.SequenceNo, 0, 0, null, null, null, null,
                                    "The message will be sent in the {0} stream N: {1}.",
                                    xHttpPhysicalConnection == xHttpPhysicalConnection.XHttpConnection.Sender ? "SENDER" : "LISTENER",
                                    xHttpPhysicalConnection.SequenceNo);
                            }
                        }

                        xHttpPhysicalConnection.SentContent = packedMessages;
                    }
                    else if (content != null)
                    {
                        xHttpPhysicalConnection.MessagesBeingSent.Clear();
                        xHttpPhysicalConnection.SentContent = content;
                    }
                    else //if (exceptionToBeSent != null)
                    {
            #if DEBUG
                        Debug.Assert(httpPacketType == HttpPacketType.SenderError);
            #endif

                        Exception exception = OperationException.WrapException(exceptionToBeSent);
                        GenuineChunkedStream output = new GenuineChunkedStream(false);
                        BinaryFormatter binaryFormatter = new BinaryFormatter(new RemotingSurrogateSelector(), new StreamingContext(StreamingContextStates.Other));
                        binaryFormatter.Serialize(output, exception);

                        xHttpPhysicalConnection.MessagesBeingSent.Clear();
                        xHttpPhysicalConnection.SentContent = output;
                    }

                    // client applies CLSSE only to the actual content
                    if (applyClss && xHttpPhysicalConnection.XHttpConnection.IsClient && xHttpPhysicalConnection.ConnectionLevelSecurity != null)
                    {
                        GenuineChunkedStream encryptedContent = new GenuineChunkedStream(false);
                        xHttpPhysicalConnection.ConnectionLevelSecurity.Encrypt(xHttpPhysicalConnection.SentContent, encryptedContent);
                        xHttpPhysicalConnection.SentContent = encryptedContent;
                    }

                    // write the binary header
                    GenuineChunkedStream resultStream = new GenuineChunkedStream(false);
                    BinaryWriter binaryWriter = new BinaryWriter(resultStream);

                    if (xHttpPhysicalConnection.XHttpConnection.IsClient)
                        HttpMessageCoder.WriteRequestHeader(binaryWriter, MessageCoder.PROTOCOL_VERSION, genuineConnectionType, xHttpPhysicalConnection.XHttpConnection.HostId, httpPacketType, xHttpPhysicalConnection.SequenceNo, xHttpPhysicalConnection.XHttpConnection.ConnectionName, xHttpPhysicalConnection.XHttpConnection.Remote.LocalHostUniqueIdentifier);
                    else
                        HttpMessageCoder.WriteResponseHeader(binaryWriter, xHttpPhysicalConnection.XHttpConnection.Remote.ProtocolVersion, this.ITransportContext.ConnectionManager.Local.Uri, xHttpPhysicalConnection.SequenceNo, httpPacketType, xHttpPhysicalConnection.XHttpConnection.Remote.LocalHostUniqueIdentifier);

                    resultStream.WriteStream(xHttpPhysicalConnection.SentContent);
                    xHttpPhysicalConnection.SentContent = resultStream;

                    // while server applies CLSSE to the entire response (except HTTP stuff, of course)
                    if (applyClss && ! xHttpPhysicalConnection.XHttpConnection.IsClient && xHttpPhysicalConnection.ConnectionLevelSecurity != null)
                    {
                        GenuineChunkedStream encryptedContent = new GenuineChunkedStream(false);
                        xHttpPhysicalConnection.ConnectionLevelSecurity.Encrypt(xHttpPhysicalConnection.SentContent, encryptedContent);
                        xHttpPhysicalConnection.SentContent = encryptedContent;
                    }

                    // generally it's impossible to have xHttpPhysicalConnection.SentContent without available length in the current implementation
                    // nevertheless, it's necessary to calculate the final length of the content if it's unknown
                    if (! xHttpPhysicalConnection.SentContent.CanSeek)
                    {
                        GenuineChunkedStream actualContent = new GenuineChunkedStream(false);
                        GenuineUtility.CopyStreamToStream(xHttpPhysicalConnection.SentContent, actualContent, xHttpPhysicalConnection.AsyncSendBuffer);
                        xHttpPhysicalConnection.SentContent = actualContent;
                    }

                    // write the header and compose final content
                    resultStream = new GenuineChunkedStream(false);
                    StreamWriter streamWriter = new StreamWriter(new NonClosableStream(resultStream), Encoding.ASCII, 3500);

                    if (xHttpPhysicalConnection.XHttpConnection.IsClient)
                        streamWriter.Write("POST /{0} HTTP/1.1\r\nAccept: */*\r\nContent-Type: application/octet-stream\r\nContent-Length: {1}\r\nUser-Agent: {2}\r\nHost: {3}\r\nConnection: Keep-Alive\r\nPragma: no-cache\r\n\r\n",
                            xHttpPhysicalConnection.EntryUri, xHttpPhysicalConnection.SentContent.Length, xHttpPhysicalConnection.XHttpConnection.UserAgent, xHttpPhysicalConnection.LocalEndPoint);
                    else
                    {
                        string now = DateTime.Now.ToString("r");
                        streamWriter.Write("HTTP/1.1 200 OK\r\nServer: GXHTTP\r\nDate: {0}\r\nX-Powered-By: Genuine Channels\r\nCache-Control: private\r\nContent-Type: application/octet-stream\r\nContent-Length: {1}\r\n\r\n",
                            now, xHttpPhysicalConnection.SentContent.Length);
                    }

                    streamWriter.Flush();
                    streamWriter.Close();
                    resultStream.WriteStream(xHttpPhysicalConnection.SentContent);

                    xHttpPhysicalConnection.SentContent = resultStream;
                }
                else
                {
                    xHttpPhysicalConnection.SentContent.Position = 0;
                }

                socket = xHttpPhysicalConnection.Socket;
                sentContent = xHttpPhysicalConnection.SentContent;
            }	// lock (xHttpPhysicalConnection.PhysicalConnectionStateLock)

            if (synchronous)
            {
                // send the content
                SyncSocketWritingStream syncSocketWritingStream = new SyncSocketWritingStream(this, socket, timeout, xHttpPhysicalConnection.XHttpConnection.DbgConnectionId, xHttpPhysicalConnection.Remote);
                GenuineUtility.CopyStreamToStreamPhysically(sentContent, syncSocketWritingStream, xHttpPhysicalConnection.AsyncSendBuffer);

                // automatically start receiving the response/request
                if (startAutomaticReceiving)
                {
                    if (xHttpPhysicalConnection.XHttpConnection.IsClient)
                        this.LowLevel_HalfSync_Client_StartReceiving(xHttpPhysicalConnection);
                    else
                        this.LowLevel_HalfSync_Server_StartReceiving(xHttpPhysicalConnection.Socket);
                }
            }
            else
            {
                xHttpPhysicalConnection.AsyncSendBufferCurrentPosition = 0;
                xHttpPhysicalConnection.AsyncSendBufferIsLastPacket = false;
                xHttpPhysicalConnection.AsyncSendBufferSizeOfValidContent = 0;
                xHttpPhysicalConnection.AsyncSendStream = sentContent;

                this.LowLevel_InitiateAsyncSending(xHttpPhysicalConnection);
            }
        }
        /// <summary>
        /// Parses HTTP request or response.
        /// </summary>
        /// <param name="timeout">The reading timeout.</param>
        /// <param name="client">Specifies the parsing logic.</param>
        /// <param name="socket">The connection.</param>
        /// <param name="connectionLevelSecurity">Connection-level Security Session.</param>
        /// <param name="protocolVersion">The version of the protocol.</param>
        /// <param name="uri">The URI of the remote host.</param>
        /// <param name="sequenceNo">The sequence no of the parsing packet.</param>
        /// <param name="genuineConnectionType">The type of the connection.</param>
        /// <param name="hostId">The identifier of the host.</param>
        /// <param name="httpPacketType">The type of the HTTP packet.</param>
        /// <param name="connectionName">The name of the connection.</param>
        /// <param name="remoteHostUniqueIdentifier">The unique identifier of the HostInformation used by the remote host.</param>
        /// <returns>A stream based on the specified socket.</returns>
        private Stream LowLevel_ParseHttpContent(int timeout, bool client, Socket socket, SecuritySession connectionLevelSecurity, out byte protocolVersion, out string uri, out int sequenceNo, out GenuineConnectionType genuineConnectionType, out Guid hostId, out HttpPacketType httpPacketType, out string connectionName, out int remoteHostUniqueIdentifier)
        {
            BinaryLogWriter binaryLogWriter = this.ITransportContext.BinaryLogWriter;
            protocolVersion = MessageCoder.PROTOCOL_VERSION;
            uri = null;
            genuineConnectionType = GenuineConnectionType.None;
            hostId = Guid.Empty;
            httpPacketType = HttpPacketType.Unkown;
            connectionName = null;

            // read the entire header
            Stream inputStream = new BufferedStream(new SyncSocketStream(socket, this, timeout));

            int contentLength = -1;

            #if DEBUG
            GenuineChunkedStream httpHeadersContent = new GenuineChunkedStream(false);
            StreamWriter httpTraffic = new StreamWriter(httpHeadersContent);
            #endif

            GXHTTPHeaderParser gxhttpHeaderParser = new GXHTTPHeaderParser(client);
            int indexOfFirstDigit;
            int indexOfLastDigit;

            for ( ; ; )
            {
                string line = this.LowLevel_ReadToUpperLine(inputStream, out indexOfFirstDigit, out indexOfLastDigit);

            #if DEBUG
                httpTraffic.Write(line);
                httpTraffic.Write(Environment.NewLine);
            #endif

                if (line.Length <= 0)
                    break;

                if (gxhttpHeaderParser.ParseHeader(line, indexOfFirstDigit, indexOfLastDigit) == GXHTTPHeaderParser.HeaderFields.Expect100Continue && gxhttpHeaderParser.IsHttp11)
                    this.LowLevel_Send100Continue(socket);
            }

            contentLength = (int) gxhttpHeaderParser.ContentLength;

            #if DEBUG
            // LOG:
            if ( binaryLogWriter != null && binaryLogWriter[LogCategory.LowLevelTransport] > 0 )
            {
                binaryLogWriter.WriteTransportContentEvent(LogCategory.LowLevelTransport, "XHttpConnectionManager.LowLevel_ParseHttpContent",
                    LogMessageType.LowLevelTransport_SyncReceivingCompleted, null, null, null,
                    binaryLogWriter[LogCategory.LowLevelTransport] > 1 ? httpHeadersContent : null,
                    GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name,
                    -1, contentLength, socket.RemoteEndPoint.ToString(),
                    null, null,
                    "XHTTP Headers parsed. Content Length: {0}.", contentLength);
            }

            httpHeadersContent.Dispose();
            #endif

            // ok, the header has been successfully skipped
            if (contentLength < 0)
                throw GenuineExceptions.Get_Receive_IncorrectData();

            // TODO: fix this! there is socket -> buffer -> delimiter chain, while it must be socket -> delimiter -> buffer
            // and we know the content length
            inputStream = new DelimiterStream(inputStream, contentLength);

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

                binaryLogWriter.WriteTransportContentEvent(LogCategory.LowLevelTransport, "XHttpConnectionManager.LowLevel_ParseHttpContent",
                    LogMessageType.LowLevelTransport_SyncReceivingCompleted, null, null, null,
                    writeContent ? contentCopy : null,
                    GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name,
                    -1, contentLength, socket.RemoteEndPoint.ToString(),
                    null, null,
                    "XHTTP Message.", contentLength);

                if (writeContent)
                    inputStream = contentCopy;
            }

            // server always encrypts the entire content, including response headers
            if (client && connectionLevelSecurity != null && connectionLevelSecurity.IsEstablished)
                inputStream = connectionLevelSecurity.Decrypt(inputStream);

            BinaryReader binaryReader = new BinaryReader(inputStream);

            // read binary header
            if (client)
                HttpMessageCoder.ReadResponseHeader(binaryReader, out uri, out sequenceNo, out httpPacketType, out remoteHostUniqueIdentifier);
            else
                HttpMessageCoder.ReadRequestHeader(binaryReader, out protocolVersion, out genuineConnectionType, out hostId, out httpPacketType, out sequenceNo, out connectionName, out remoteHostUniqueIdentifier);

            return inputStream;
        }