/// <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(); } } }