/// <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> /// 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> /// Sends the stream to the remote host. /// </summary> /// <param name="message">The message.</param> public void SendMessage(Message message) { int availableConnectionEntry = 0; HttpWebRequest httpWebRequest = null; try { // serialize the message GenuineChunkedStream stream = new GenuineChunkedStream(false); using (BufferKeeper bufferKeeper = new BufferKeeper(0)) { MessageCoder.FillInLabelledStream(message, null, null, stream, bufferKeeper.Buffer, (int)this.ITransportContext.IParameterProvider[GenuineParameter.HttpRecommendedPacketSize]); } // add the header GenuineChunkedStream resultStream = new GenuineChunkedStream(false); BinaryWriter binaryWriter = new BinaryWriter(resultStream); HttpMessageCoder.WriteRequestHeader(binaryWriter, MessageCoder.PROTOCOL_VERSION, GenuineConnectionType.Invocation, this.ITransportContext.BinaryHostIdentifier, HttpPacketType.Usual, message.MessageId, string.Empty, this.Remote.LocalHostUniqueIdentifier); if (stream.CanSeek) { resultStream.WriteStream(stream); } else { GenuineUtility.CopyStreamToStream(stream, resultStream); } // get a connection availableConnectionEntry = FindAvailableConnectionEntry(); httpWebRequest = this.InitializeRequest("__GC_INVC_" + availableConnectionEntry.ToString(), this._keepalive); this.InitiateSending(new ConnectionInfo(httpWebRequest, availableConnectionEntry, message), resultStream, this._httpAsynchronousRequestTimeout); } catch { try { if (httpWebRequest != null) { httpWebRequest.Abort(); } } catch { } this.ReleaseConnectionEntry(availableConnectionEntry); throw; } }
/// <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 unsafe static 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> /// 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(); } } } } }
/// <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> /// Completes the HTTP request. /// </summary> /// <param name="ar">The result of the HTTP request.</param> private void OnRequestCompleted(IAsyncResult ar) { HttpWebResponse httpWebResponse = null; Stream inputStream = null; ConnectionInfo connectionInfo = null; try { connectionInfo = (ConnectionInfo)ar.AsyncState; HttpWebRequest httpWebRequest = connectionInfo.HttpWebRequest; #if (FRM20) // timeout has been already set try { httpWebResponse = (HttpWebResponse)httpWebRequest.GetResponse(); } catch (WebException ex) { if (ex.Status == WebExceptionStatus.Timeout) { return; } } #else httpWebResponse = (HttpWebResponse)httpWebRequest.EndGetResponse(ar); #endif this.Remote.Renew(this._hostRenewingSpan, false); // process the content inputStream = httpWebResponse.GetResponseStream(); #if DEBUG // if (this.ITransportContext.IEventLogger.AcceptBinaryData) // { // byte[] content = new byte[(int) httpWebResponse.ContentLength]; // GenuineUtility.ReadDataFromStream(inputStream, content, 0, content.Length); // // this.ITransportContext.IEventLogger.Log(LogMessageCategory.Traffic, null, "HttpInvocationConnection.OnRequestCompleted", // content, "The content of the response received by the HttpInvocationConnection. Size: {0}.", content.Length); // inputStream = new MemoryStream(content, false); // } #endif BinaryReader binaryReader = new BinaryReader(inputStream); string serverUri; int sequenceNo; HttpPacketType httpPacketType; int remoteHostUniqueIdentifier; HttpMessageCoder.ReadResponseHeader(binaryReader, out serverUri, out sequenceNo, out httpPacketType, out remoteHostUniqueIdentifier); #if DEBUG // this.ITransportContext.IEventLogger.Log(LogMessageCategory.TransportLayer, null, "HttpInvocationConnection.OnRequestCompleted", // null, "The invocation request returned. Server uri: {0}. Sequence no: {1}. Packet type: {2}. Content-encoding: {3}. Content-length: {4}. Protocol version: {5}. Response uri: \"{6}\". Server: \"{7}\". Status code: {8}. Status description: \"{9}\".", // serverUri, sequenceNo, Enum.Format(typeof(HttpPacketType), httpPacketType, "g"), // httpWebResponse.ContentEncoding, httpWebResponse.ContentLength, // httpWebResponse.ProtocolVersion, httpWebResponse.ResponseUri, // httpWebResponse.Server, httpWebResponse.StatusCode, httpWebResponse.StatusDescription); #endif // if the remote host has asked to terminate a connection if (httpPacketType == HttpPacketType.ClosedManually || httpPacketType == HttpPacketType.Desynchronization || httpPacketType == HttpPacketType.SenderError) { throw GenuineExceptions.Get_Receive_ConnectionClosed(); } // skip the first byte if (binaryReader.ReadByte() != 0) { if (!connectionInfo.Message.IsOneWay) { // this.ITransportContext.IEventLogger.Log(LogMessageCategory.FatalError, GenuineExceptions.Get_Processing_LogicError("The invocation response doesn't contain any messages."), "HttpInvocationConnection.OnRequestCompleted", // null, "The HTTP response doesn't contain content. The response to the request was not received."); } } else { // fetch and process the response messages using (BufferKeeper bufferKeeper = new BufferKeeper(0)) { using (LabelledStream labelledStream = new LabelledStream(this.ITransportContext, inputStream, bufferKeeper.Buffer)) { GenuineChunkedStream receivedRequest = new GenuineChunkedStream(true); GenuineUtility.CopyStreamToStream(labelledStream, receivedRequest); this.ITransportContext.IIncomingStreamHandler.HandleMessage(receivedRequest, this.Remote, GenuineConnectionType.Invocation, string.Empty, -1, true, null, null, null); } } } } catch (Exception ex) { // this.ITransportContext.IEventLogger.Log(LogMessageCategory.Error, ex, "HttpInvocationConnection.OnRequestCompleted", // null, "Exception occurred during receiving a response to an invocation request."); // dispatch the exception to the caller context if (connectionInfo != null) { this.ITransportContext.IIncomingStreamHandler.DispatchException(connectionInfo.Message, ex); } } finally { if (inputStream != null) { inputStream.Close(); } if (httpWebResponse != null) { httpWebResponse.Close(); } // release the connection if (connectionInfo != null) { this.ReleaseConnectionEntry(connectionInfo.Index); } } }