/// <summary> /// Continues receiving and processing of the message in half-sync mode. /// </summary> /// <param name="socketAsObject">The connection.</param> private void Pool_Server_ContinueHalfSyncReceiving(object socketAsObject) { BinaryLogWriter binaryLogWriter = this.ITransportContext.BinaryLogWriter; XHttpConnection xHttpConnection = null; XHttpPhysicalConnection xHttpPhysicalConnection = null; Socket socket = (Socket) socketAsObject; byte protocolVersion; string remoteUri = null; int sequenceNo = 0; GenuineConnectionType genuineConnectionType = GenuineConnectionType.None; Guid hostId = Guid.Empty; HttpPacketType httpPacketType = HttpPacketType.Unkown; string connectionName; int remoteHostUniqueIdentifier; try { // server & sender - parse messages, execute them, send confirmation // server & listener - if messages are available, send them all. otherwise set available flag and hold the connection for a while // first, read the header Stream inputStream = this.LowLevel_ParseHttpContent(GenuineUtility.GetTimeout(GenuineUtility.ConvertToMilliseconds(this.ITransportContext.IParameterProvider[GenuineParameter.XHttpReadHttpMessageTimeout])), false, socket, null, out protocolVersion, out remoteUri, out sequenceNo, out genuineConnectionType, out hostId, out httpPacketType, out connectionName, out remoteHostUniqueIdentifier); // who it was HostInformation remote = this.ITransportContext.KnownHosts["_ghttp://" + hostId.ToString("N")]; remote.UpdateUri(remote.Uri, remoteHostUniqueIdentifier); remote.ProtocolVersion = protocolVersion; // get the connection lock (remote.PersistentConnectionEstablishingLock) { xHttpConnection = this._persistent.Get(remote.Uri, connectionName) as XHttpConnection; if (httpPacketType == HttpPacketType.Establishing_ResetConnection && xHttpConnection != null) { xHttpConnection.Dispose(GenuineExceptions.Get_Receive_ConnectionClosed("The connection was closed by HttpPacketType.Establishing_ResetConnection client request.")); xHttpConnection = null; } if (xHttpConnection == null) { using (new ReaderAutoLocker(this._disposeLock)) { if (this._disposed) throw OperationException.WrapException(this._disposeReason); // provide a possibility to decline the connection ConnectionAcceptedCancellableEventParameter connectionAcceptedCancellableEventParameter = new ConnectionAcceptedCancellableEventParameter(); connectionAcceptedCancellableEventParameter.Socket = socket; connectionAcceptedCancellableEventParameter.IPEndPoint = (IPEndPoint) socket.RemoteEndPoint; this.ITransportContext.IGenuineEventProvider.Fire(new GenuineEventArgs(GenuineEventType.GHttpConnectionAccepted, null, null, connectionAcceptedCancellableEventParameter)); if (connectionAcceptedCancellableEventParameter.Cancel) throw GenuineExceptions.Get_Connect_CanNotAcceptIncomingConnection("Connection accepting was cancelled by the event consumer."); xHttpConnection = this.Pool_CreateConnection(remote, remote.Uri, false, connectionName); } } } bool theSamePacketIsRequested; lock (xHttpConnection.Listener.PhysicalConnectionStateLock) { if (httpPacketType == HttpPacketType.Listening) { // if there is an already registered listener request - release it if (xHttpConnection.Listener.ConnectionAvailable && xHttpConnection.Listener.Socket != socket) { // shut down the previous physical connection this.LowLevel_SendServerError(new PhysicalConnectionAndSocket(xHttpConnection.Listener, socket)); // GenuineThreadPool.QueueUserWorkItem(new WaitCallback(this.LowLevel_SendServerError), new PhysicalConnectionAndSocket(xHttpConnection.Listener, socket), true); xHttpConnection.Listener.AcquireIfAvailable(); } xHttpConnection.Listener.Socket = socket; xHttpPhysicalConnection = xHttpConnection.Listener; } else { xHttpConnection.Sender.Socket = socket; xHttpPhysicalConnection = xHttpConnection.Sender; } theSamePacketIsRequested = xHttpPhysicalConnection.SequenceNo == sequenceNo && xHttpPhysicalConnection.SentContent != null; #if DEBUG xHttpPhysicalConnection.TypeOfSocket = "Accepted"; #endif xHttpPhysicalConnection.Remote.PhysicalAddress = socket.RemoteEndPoint; xHttpPhysicalConnection.Remote.LocalPhysicalAddress = socket.LocalEndPoint; } // lock (xHttpConnection.Listener.PhysicalConnectionStateLock) // renew connection lifetime xHttpConnection.Renew(); xHttpPhysicalConnection.XHttpConnection.SignalState(GenuineEventType.GeneralConnectionEstablished, null, null); // if the same packet stream is requested, send the response if (theSamePacketIsRequested) { // skip the current stream inputStream.Close(); // send the stream and initiate receiving this.LowLevel_SendHttpContent(remote.ExpireTime, null, null, null, null, xHttpPhysicalConnection, genuineConnectionType, HttpPacketType.RequestRepeated, true, true, true, true); return ; } lock (xHttpConnection.Listener.PhysicalConnectionStateLock) { // if desynchronization, report and continue if (httpPacketType != HttpPacketType.Establishing_ResetConnection && xHttpPhysicalConnection.SequenceNo > sequenceNo || sequenceNo > xHttpPhysicalConnection.SequenceNo + 1) { // LOG: if ( binaryLogWriter != null && binaryLogWriter[LogCategory.Connection] > 0 ) { binaryLogWriter.WriteEvent(LogCategory.Connection, "XHttpConnectionManager.Pool_Server_ContinueHalfSyncreceiving", LogMessageType.ConnectionStreamDesynchronization, GenuineExceptions.Get_Debugging_GeneralWarning("Stream desynchronization."), null, xHttpPhysicalConnection.Remote, null, GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name, xHttpPhysicalConnection.ConnectionLevelSecurity, xHttpPhysicalConnection.ConnectionLevelSecurity == null ? null : xHttpPhysicalConnection.ConnectionLevelSecurity.Name, xHttpConnection.DbgConnectionId, 0, 0, 0, null, null, null, null, "Stream desynchronization error. Received sequence number: {0}. Expected sequence number: {1}.", xHttpPhysicalConnection.SequenceNo, sequenceNo); } // send the stream and initiate receiving this.LowLevel_SendHttpContent(remote.ExpireTime, null, null, null, null, xHttpPhysicalConnection, genuineConnectionType, HttpPacketType.Desynchronization, false, true, true, true); return ; } // the next sequence is requested if (xHttpPhysicalConnection.SentContent != null) { // release the content xHttpPhysicalConnection.SentContent.Close(); xHttpPhysicalConnection.SentContent = null; } // respond with the same seq No xHttpPhysicalConnection.SequenceNo = sequenceNo; xHttpPhysicalConnection.Socket = socket; xHttpPhysicalConnection.MessagesBeingSent.Clear(); } // LOG: if ( binaryLogWriter != null && binaryLogWriter[LogCategory.Connection] > 0 ) { binaryLogWriter.WriteEvent(LogCategory.Connection, "XHttpConnectionManager.Pool_Server_ContinueHalfSyncreceiving", LogMessageType.ReceivingFinished, null, null, xHttpPhysicalConnection.Remote, null, GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name, xHttpPhysicalConnection.ConnectionLevelSecurity, xHttpPhysicalConnection.ConnectionLevelSecurity == null ? null : xHttpPhysicalConnection.ConnectionLevelSecurity.Name, xHttpConnection.DbgConnectionId, 0, 0, 0, null, null, null, null, "HTTP Stream received. Packet type: {0}.", Enum.Format(typeof(HttpPacketType), httpPacketType, "g")); } // analyze the type of the packet switch(httpPacketType) { case HttpPacketType.Establishing_ResetConnection: case HttpPacketType.Establishing: // mark the remote host as client lock (remote.PersistentConnectionEstablishingLock) remote.GenuinePersistentConnectionState = GenuinePersistentConnectionState.Accepted; // read CLSS streams BinaryReader binaryReader = new BinaryReader(inputStream); Stream clsseStream = null; GenuineChunkedStream outputStream = new GenuineChunkedStream(false); // process the sender info int writtenSize = binaryReader.ReadInt32(); using (new GenuineChunkedStreamSizeLabel(outputStream)) { if (xHttpConnection.Sender.ConnectionLevelSecurity != null && ! xHttpConnection.Sender.ConnectionLevelSecurity.IsEstablished) { using (Stream clssData = new DelimiterStream(inputStream, writtenSize)) { clsseStream = xHttpConnection.Sender.ConnectionLevelSecurity.EstablishSession(clssData, true); } } if (clsseStream != null) GenuineUtility.CopyStreamToStream(clsseStream, outputStream); } // process the listener info writtenSize = binaryReader.ReadInt32(); using (new GenuineChunkedStreamSizeLabel(outputStream)) { if (xHttpConnection.Listener.ConnectionLevelSecurity != null && ! xHttpConnection.Listener.ConnectionLevelSecurity.IsEstablished) { using (Stream clssData = new DelimiterStream(inputStream, writtenSize)) { clsseStream = xHttpConnection.Listener.ConnectionLevelSecurity.EstablishSession(clssData, true); } } if (clsseStream != null) GenuineUtility.CopyStreamToStream(clsseStream, outputStream); } // skip remaining part of the packet inputStream.Close(); this.LowLevel_SendHttpContent(remote.ExpireTime, null, outputStream, null, null, xHttpPhysicalConnection, genuineConnectionType, httpPacketType, false, true, true, false); break; case HttpPacketType.Listening: // if messages are available, send them immediately // otherwise put the connection off for a while // skip the remaining content inputStream.Close(); Pool_Server_ProcessListenerRequest(xHttpConnection, xHttpPhysicalConnection); break; case HttpPacketType.Usual: // apply CLSS if it was established if (xHttpPhysicalConnection.ConnectionLevelSecurity != null) inputStream = xHttpPhysicalConnection.ConnectionLevelSecurity.Decrypt(inputStream); Pool_Server_ProcessSenderRequest(xHttpConnection, xHttpPhysicalConnection, inputStream); break; default: throw GenuineExceptions.Get_Receive_IncorrectData("Unexpected type of the packet."); } } catch(Exception ex) { try { // LOG: if ( binaryLogWriter != null && binaryLogWriter[LogCategory.Connection] > 0 ) { binaryLogWriter.WriteEvent(LogCategory.Connection, "XHttpConnectionManager.Pool_Server_ContinueHalfSyncreceiving", LogMessageType.ReceivingFinished, ex, null, xHttpPhysicalConnection.Remote, null, GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name, xHttpPhysicalConnection.ConnectionLevelSecurity, xHttpPhysicalConnection.ConnectionLevelSecurity == null ? null : xHttpPhysicalConnection.ConnectionLevelSecurity.Name, xHttpConnection.DbgConnectionId, 0, 0, 0, null, null, null, null, "Error occurred while receiving HTTP Stream. Sequence No: {0}. Connection type: {1}. Packet type: {2}.", sequenceNo, genuineConnectionType, httpPacketType); } SocketUtility.CloseSocket(socket); } catch { } } }
/// <summary> /// Handles the incoming HTTP request. /// </summary> /// <param name="httpServerRequestResultAsObject">The HTTP request.</param> public void HandleIncomingRequest(object httpServerRequestResultAsObject) { BinaryLogWriter binaryLogWriter = this.ITransportContext.BinaryLogWriter; HttpServerRequestResult httpServerRequestResult = (HttpServerRequestResult) httpServerRequestResultAsObject; HttpServerConnection httpServerConnection = null; bool postponeResponse = false; try { // get the stream HttpRequest httpRequest = httpServerRequestResult.HttpContext.Request; Stream incomingStream = httpRequest.InputStream; if (incomingStream.Length <= 0) { // LOG: if ( binaryLogWriter != null && binaryLogWriter[LogCategory.LowLevelTransport] > 0 ) { binaryLogWriter.WriteEvent(LogCategory.Connection, "HttpServerConnectionManager.HandleIncomingRequest", LogMessageType.LowLevelTransport_AsyncReceivingCompleted, null, null, null, null, GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name, null, null, -1, 0, 0, 0, null, null, null, null, "Empty content has been received. It will be ignored."); } return ; } // LOG: if ( binaryLogWriter != null && binaryLogWriter[LogCategory.LowLevelTransport] > 0 ) { bool writeContent = binaryLogWriter[LogCategory.LowLevelTransport] > 1; GenuineChunkedStream content = null; if (writeContent) { content = new GenuineChunkedStream(false); GenuineUtility.CopyStreamToStream(incomingStream, content); } binaryLogWriter.WriteTransportContentEvent(LogCategory.LowLevelTransport, "HttpServerConnectionManager.HandleIncomingRequest", LogMessageType.LowLevelTransport_AsyncReceivingCompleted, null, null, null, writeContent ? content : null, GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name, -1, (int) httpServerRequestResult.HttpContext.Request.ContentLength, httpServerRequestResult.HttpContext.Request.UserHostAddress, null, null, "HTTP request has been received."); if (writeContent) incomingStream = content; } BinaryReader binaryReader = new BinaryReader(incomingStream); // read the header byte protocolVersion; GenuineConnectionType genuineConnectionType; Guid hostId; HttpPacketType httpPacketType; int sequenceNo; string connectionName; int remoteHostUniqueIdentifier; HttpMessageCoder.ReadRequestHeader(binaryReader, out protocolVersion, out genuineConnectionType, out hostId, out httpPacketType, out sequenceNo, out connectionName, out remoteHostUniqueIdentifier); HostInformation remote = this.ITransportContext.KnownHosts["_ghttp://" + hostId.ToString("N")]; remote.ProtocolVersion = protocolVersion; // remote.Renew(this._hostRenewingSpan, false); remote.PhysicalAddress = httpRequest.UserHostAddress; // raise an event if we were not recognized remote.UpdateUri(remote.Uri, remoteHostUniqueIdentifier); // LOG: if ( binaryLogWriter != null && binaryLogWriter[LogCategory.Connection] > 0 ) { binaryLogWriter.WriteEvent(LogCategory.Connection, "HttpServerConnectionManager.HandleIncomingRequest", LogMessageType.ReceivingFinished, null, null, remote, null, GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name, null, null, -1, 0, 0, 0, null, null, null, null, "HTTP request is being processed. Packet type: {0}. Sequence no: {1}. Content length: {2}. Host address: {3}.", Enum.Format(typeof(HttpPacketType), httpPacketType, "g"), sequenceNo, httpRequest.ContentLength, httpRequest.UserHostAddress); } // prepare the output stream GenuineChunkedStream outputStream = new GenuineChunkedStream(false); BinaryWriter binaryWriter = new BinaryWriter(outputStream); HttpMessageCoder.WriteResponseHeader(binaryWriter, protocolVersion, this.ITransportContext.ConnectionManager.Local.Uri, sequenceNo, httpPacketType, remote.LocalHostUniqueIdentifier); // analyze the received packet switch(genuineConnectionType) { case GenuineConnectionType.Persistent: { // get the server connection lock (remote.PersistentConnectionEstablishingLock) { httpServerConnection = this._persistent.Get(remote.Uri, connectionName) as HttpServerConnection; if (httpServerConnection != null && httpServerConnection._disposed) httpServerConnection = null; // initialize CLSS from the very beginning, if necessary if (httpPacketType == HttpPacketType.Establishing_ResetConnection) { if (httpServerConnection != null) httpServerConnection.Dispose(GenuineExceptions.Get_Receive_ConnectionClosed("Client sends Establishing_ResetCLSS flag.")); httpServerConnection = null; } if (httpServerConnection == null) { // create the new connection httpServerConnection = new HttpServerConnection(this.ITransportContext, hostId, remote, connectionName, GenuineUtility.ConvertToMilliseconds(this.ITransportContext.IParameterProvider[GenuineParameter.ClosePersistentConnectionAfterInactivity]) + GenuineUtility.ConvertToMilliseconds(this.ITransportContext.IParameterProvider[GenuineParameter.MaxTimeSpanToReconnect])); if ( binaryLogWriter != null && binaryLogWriter[LogCategory.Connection] > 0 ) { binaryLogWriter.WriteConnectionParameterEvent(LogCategory.Connection, "HttpServerConnectionManager.HandleIncomingRequest", LogMessageType.ConnectionParameters, null, remote, this.ITransportContext.IParameterProvider, GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name, httpServerConnection.DbgConnectionId, "HTTP connection is being established."); } this._persistent.Set(remote.Uri, connectionName, httpServerConnection); // and CLSS string securitySessionName = this.ITransportContext.IParameterProvider[GenuineParameter.SecuritySessionForPersistentConnections] as string; if (securitySessionName != null) { httpServerConnection.Sender_SecuritySession = this.ITransportContext.IKeyStore.GetKey(securitySessionName).CreateSecuritySession(securitySessionName, null); httpServerConnection.Listener_SecuritySession = this.ITransportContext.IKeyStore.GetKey(securitySessionName).CreateSecuritySession(securitySessionName, null); } // LOG: if ( binaryLogWriter != null && binaryLogWriter[LogCategory.Connection] > 0 ) { binaryLogWriter.WriteEvent(LogCategory.Connection, "HttpServerConnectionManager.HandleIncomingRequest", LogMessageType.ConnectionEstablished, null, null, remote, null, GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name, httpServerConnection.Sender_SecuritySession, securitySessionName, httpServerConnection.DbgConnectionId, (int) GenuineConnectionType.Persistent, 0, 0, this.GetType().Name, null, null, null, "The connection is being established."); } // LOG: if ( binaryLogWriter != null && binaryLogWriter[LogCategory.HostInformation] > 0 ) { binaryLogWriter.WriteHostInformationEvent("HttpServerConnectionManager.HandleIncomingRequest", LogMessageType.HostInformationCreated, null, remote, GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name, httpServerConnection.Sender_SecuritySession, securitySessionName, httpServerConnection.DbgConnectionId, "HostInformation is ready for actions."); } this.ITransportContext.IGenuineEventProvider.Fire(new GenuineEventArgs(GenuineEventType.GHttpConnectionAccepted, null, remote, httpRequest.UserHostAddress)); } } httpServerConnection.Renew(); httpServerConnection.SignalState(GenuineEventType.GeneralConnectionEstablished, null, null); switch(httpPacketType) { case HttpPacketType.Establishing_ResetConnection: case HttpPacketType.Establishing: Stream clsseStream = Stream.Null; // establish the CLSS // P/Sender int length = binaryReader.ReadInt32(); if (httpServerConnection.Sender_SecuritySession != null) { using (Stream senderClssReading = new DelimiterStream(incomingStream, length)) { clsseStream = httpServerConnection.Sender_SecuritySession.EstablishSession( senderClssReading, true); } } if (clsseStream == null) clsseStream = Stream.Null; using (new GenuineChunkedStreamSizeLabel(outputStream)) GenuineUtility.CopyStreamToStream(clsseStream, outputStream); // P/Listener length = binaryReader.ReadInt32(); clsseStream = Stream.Null; if (httpServerConnection.Listener_SecuritySession != null) clsseStream = httpServerConnection.Listener_SecuritySession.EstablishSession( new DelimiterStream(incomingStream, length), true); if (clsseStream == null) clsseStream = Stream.Null; using (new GenuineChunkedStreamSizeLabel(outputStream)) GenuineUtility.CopyStreamToStream(clsseStream, outputStream); // write the answer Stream finalStream = outputStream; this.LowLevel_SendStream(httpServerRequestResult.HttpContext, false, null, false, ref finalStream, httpServerConnection); break; case HttpPacketType.Listening: postponeResponse = this.LowLevel_ProcessListenerRequest(httpServerRequestResult, httpServerConnection, sequenceNo); break; case HttpPacketType.Usual: this.LowLevel_ProcessSenderRequest(genuineConnectionType, incomingStream, httpServerRequestResult, httpServerConnection, sequenceNo, remote); break; default: // LOG: if ( binaryLogWriter != null && binaryLogWriter[LogCategory.Connection] > 0 ) { binaryLogWriter.WriteEvent(LogCategory.Connection, "HttpServerConnectionManager.HandleIncomingRequest", LogMessageType.Error, GenuineExceptions.Get_Debugging_GeneralWarning("Unexpected type of the packet."), null, remote, null, GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name, null, null, httpServerConnection == null ? -1 : httpServerConnection.DbgConnectionId, 0, 0, 0, null, null, null, null, "Unexpected type of the packet. Packet type: {0}. Sequence no: {1}. Content length: {2}. Host address: {3}.", Enum.Format(typeof(HttpPacketType), httpPacketType, "g"), sequenceNo, httpRequest.ContentLength, httpRequest.UserHostAddress); } break; } } break; case GenuineConnectionType.Named: throw new NotSupportedException("Named connections are not supported."); case GenuineConnectionType.Invocation: // renew the host remote.Renew(this._closeInvocationConnectionAfterInactivity, false); this.LowLevel_ProcessSenderRequest(genuineConnectionType, incomingStream, httpServerRequestResult, null, sequenceNo, remote); break; } } catch(Exception ex) { // LOG: if ( binaryLogWriter != null && binaryLogWriter[LogCategory.Connection] > 0 ) { binaryLogWriter.WriteEvent(LogCategory.Connection, "HttpServerConnectionManager.HandleIncomingRequest", LogMessageType.ReceivingFinished, ex, null, null, null, GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name, null, null, -1, 0, 0, 0, null, null, null, null, "Error occurred while processing incoming HTTP request."); } } finally { if (! postponeResponse) httpServerRequestResult.Complete(true); } }
/// <summary> /// 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; }