/// <summary> /// Sends the error to the remote host. /// </summary> /// <param name="PhysicalConnectionAndSocketAsObject">The context.</param> public void LowLevel_SendServerError(object PhysicalConnectionAndSocketAsObject) { BinaryLogWriter binaryLogWriter = this.ITransportContext.BinaryLogWriter; try { PhysicalConnectionAndSocket physicalConnectionAndSocket = (PhysicalConnectionAndSocket) PhysicalConnectionAndSocketAsObject; try { // send the response int timeout = GenuineUtility.GetTimeout(30000); SyncSocketWritingStream syncSocketWritingStream = new SyncSocketWritingStream(this, physicalConnectionAndSocket.Socket, timeout, physicalConnectionAndSocket.XHttpPhysicalConnection.XHttpConnection.DbgConnectionId, physicalConnectionAndSocket.XHttpPhysicalConnection.Remote); StreamWriter streamWriter = new StreamWriter(new NonClosableStream(syncSocketWritingStream), Encoding.ASCII, 3500); streamWriter.WriteLine("HTTP/1.1 409 Conflict\r\nServer: GXHTTP\r\nDate: {0}\r\nX-Powered-By: Genuine Channels\r\nContent-Length: 0\r\n\r\n"); streamWriter.Flush(); streamWriter.Close(); binaryLogWriter.WriteEvent(LogCategory.Transport, "XHttpConnectionManager.LowLevel_SendServerError", LogMessageType.SynchronousSendingFinished, GenuineExceptions.Get_Debugging_GeneralWarning("409 Conflict HTTP response has been sent."), null, null, null, GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name, null, null, -1, 0, 0, 0, null, null, null, null, "409 Conflict HTTP response has been sent."); } catch (Exception ex) { binaryLogWriter.WriteEvent(LogCategory.Transport, "XHttpConnectionManager.LowLevel_SendServerError", LogMessageType.SynchronousSendingFinished, ex, null, null, null, GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name, null, null, -1, 0, 0, 0, null, null, null, null, "409 Conflict HTTP response cannot be sent."); } finally { SocketUtility.CloseSocket(physicalConnectionAndSocket.Socket); } } catch { } }
/// <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); } }