private void SaveDataFrame(Http2Stream stream, DataFrame dataFrame) { string originalPath = stream.Headers.GetValue(CommonHeaders.Path.ToLower()); //If user sets the empty file in get command we return notFound webpage string fileName = string.IsNullOrEmpty(Path.GetFileName(originalPath)) ? Index : Path.GetFileName(originalPath); string path = Path.Combine(AssemblyPath, fileName); try { _fileHelper.SaveToFile(dataFrame.Data.Array, dataFrame.Data.Offset, dataFrame.Data.Count, path, stream.ReceivedDataAmount != 0); } catch (IOException) { Http2Logger.LogError("File is still downloading. Repeat request later"); stream.Close(ResetStatusCode.InternalError); return; } stream.ReceivedDataAmount += dataFrame.Data.Count; if (dataFrame.IsEndStream) { if (stream.HalfClosedRemote) { //send terminator stream.WriteDataFrame(new ArraySegment<byte>(new byte[0]), true); Http2Logger.LogConsole("Terminator was sent"); } _fileHelper.RemoveStream(path); Http2Logger.LogConsole("Bytes received: " + stream.ReceivedDataAmount); } }
private void HandleDataFrame(DataFrame dataFrame, out Http2Stream stream) { stream = GetStream(dataFrame.StreamId); //Aggressive window update if (stream != null) { Http2Logger.LogDebug("Data frame. StreamId: {0} Length: {1}", dataFrame.StreamId, dataFrame.FrameLength); if (stream.IsFlowControlEnabled) { stream.WriteWindowUpdate(Constants.MaxFrameContentSize); } } else { throw new Http2StreamNotFoundException(dataFrame.StreamId); } }
private void SaveDataFrame(Http2Stream stream, DataFrame dataFrame) { string originalPath = stream.Headers.GetValue(CommonHeaders.Path.ToLower()); //If user sets the empty file in get command we return notFound webpage string fileName = string.IsNullOrEmpty(Path.GetFileName(originalPath)) ? Index : Path.GetFileName(originalPath); string path = Path.Combine(AssemblyPath, fileName); try { _fileHelper.SaveToFile(dataFrame.Data.Array, dataFrame.Data.Offset, dataFrame.Data.Count, path, stream.ReceivedDataAmount != 0); } catch (IOException) { Http2Logger.LogError("File is still downloading. Repeat request later"); //stream.WriteDataFrame(new byte[0], true); //RST always has endstream flag //_fileHelper.RemoveStream(path); stream.Dispose(ResetStatusCode.InternalError); return; } stream.ReceivedDataAmount += dataFrame.FrameLength; if (dataFrame.IsEndStream) { if (!stream.EndStreamSent) { //send terminator stream.WriteDataFrame(new byte[0], true); Http2Logger.LogConsole("Terminator was sent"); } _fileHelper.RemoveStream(path); Http2Logger.LogConsole("Bytes received " + stream.ReceivedDataAmount); #if DEBUG const string wayToServerRoot1 = @"..\..\..\..\Drop\Root"; const string wayToServerRoot2 = @".\Root"; var areFilesEqual = _fileHelper.CompareFiles(path, wayToServerRoot1 + originalPath) || _fileHelper.CompareFiles(path, wayToServerRoot2 + originalPath); if (!areFilesEqual) { Console.ForegroundColor = ConsoleColor.Red; Http2Logger.LogError("Files are NOT EQUAL!"); } else { Console.ForegroundColor = ConsoleColor.Green; Http2Logger.LogConsole("Files are EQUAL!"); } Console.ForegroundColor = ConsoleColor.Gray; #endif } }
/// <summary> /// Writes the data frame. Method is used for pushing unshipped frames. /// If flow control manager has blocked stream, frames are adding to the unshippedFrames collection. /// After window update for that stream they will be delivered. /// </summary> /// <param name="dataFrame">The data frame.</param> private void WriteDataFrame(DataFrame dataFrame) { if (dataFrame == null) throw new ArgumentNullException("dataFrame is null"); if (Closed) return; if (!IsFlowControlBlocked) { _writeQueue.WriteFrame(dataFrame); SentDataAmount += dataFrame.Data.Count; _flowCrtlManager.DataFrameSentHandler(this, new DataFrameSentEventArgs(dataFrame)); if (dataFrame.IsEndStream) { Http2Logger.LogDebug("Bytes sent: {0}", SentDataAmount); HalfClosedLocal = true; } if (OnFrameSent != null) { OnFrameSent(this, new FrameSentEventArgs(dataFrame)); } } else { _unshippedFrames.Enqueue(dataFrame); } }
/// <summary> /// Writes the data frame. /// If flow control manager has blocked stream, frames are adding to the unshippedFrames collection. /// After window update for that stream they will be delivered. /// </summary> /// <param name="data">The data.</param> /// <param name="isEndStream">if set to <c>true</c> [is fin].</param> public void WriteDataFrame(ArraySegment<byte> data, bool isEndStream) { if (data.Array == null) throw new ArgumentNullException("data is null"); if (Closed) return; var dataFrame = new DataFrame(_id, data, isEndStream, true); Http2Logger.LogDebug( "Sending DATA frame: stream id={0}, payload len={1}, has pad={2}, pad high={3}, pad low={4}, " + "end stream={5}", dataFrame.StreamId, dataFrame.PayloadLength, dataFrame.HasPadding, dataFrame.PadHigh, dataFrame.PadLow, dataFrame.IsEndStream); //We cant let lesser frame that were passed through flow control window //be sent before greater frames that were not passed through flow control window //09 -> 6.9.1. The Flow Control Window //The sender MUST NOT //send a flow controlled frame with a length that exceeds the space //available in either of the flow control windows advertised by the receiver. if (_unshippedFrames.Count != 0 || WindowSize - dataFrame.Data.Count < 0) { _unshippedFrames.Enqueue(dataFrame); return; } if (!IsFlowControlBlocked) { _writeQueue.WriteFrame(dataFrame); SentDataAmount += dataFrame.Data.Count; _flowCrtlManager.DataFrameSentHandler(this, new DataFrameSentEventArgs(dataFrame)); if (dataFrame.IsEndStream) { Http2Logger.LogDebug("Transfer end"); Http2Logger.LogDebug("Sent bytes: {0}", SentDataAmount); HalfClosedLocal = true; } if (OnFrameSent != null) { OnFrameSent(this, new FrameSentEventArgs(dataFrame)); } } else { _unshippedFrames.Enqueue(dataFrame); } }
/// <summary> /// Writes the data frame. Method is used for pushing unshipped frames. /// If flow control manager has blocked stream, frames are adding to the unshippedFrames collection. /// After window update for that stream they will be delivered. /// </summary> /// <param name="dataFrame">The data frame.</param> private void WriteDataFrame(DataFrame dataFrame) { if (dataFrame == null) throw new ArgumentNullException("dataFrame is null"); if (Disposed) return; if (!IsFlowControlBlocked) { _writeQueue.WriteFrame(dataFrame); SentDataAmount += dataFrame.FrameLength; _flowCrtlManager.DataFrameSentHandler(this, new DataFrameSentEventArgs(dataFrame)); if (dataFrame.IsEndStream) { Http2Logger.LogDebug("Transfer end"); EndStreamSent = true; } if (OnFrameSent != null) { OnFrameSent(this, new FrameSentEventArgs(dataFrame)); } } else { _unshippedFrames.Enqueue(dataFrame); } }
/// <summary> /// Writes the data frame. /// If flow control manager has blocked stream, frames are adding to the unshippedFrames collection. /// After window update for that stream they will be delivered. /// </summary> /// <param name="data">The data.</param> /// <param name="isEndStream">if set to <c>true</c> [is fin].</param> public void WriteDataFrame(ArraySegment<byte> data, bool isEndStream) { if (data.Array == null) throw new ArgumentNullException("data is null"); if (Disposed) return; var dataFrame = new DataFrame(_id, data, isEndStream); //We cant let lesser frame that were passed through flow control window //be sent before greater frames that were not passed through flow control window //09 -> 6.9.1. The Flow Control Window //The sender MUST NOT //send a flow controlled frame with a length that exceeds the space //available in either of the flow control windows advertised by the receiver. if (_unshippedFrames.Count != 0 || WindowSize - dataFrame.Data.Count < 0) { _unshippedFrames.Enqueue(dataFrame); return; } if (!IsFlowControlBlocked) { _writeQueue.WriteFrame(dataFrame); SentDataAmount += dataFrame.FrameLength; _flowCrtlManager.DataFrameSentHandler(this, new DataFrameSentEventArgs(dataFrame)); if (dataFrame.IsEndStream) { Http2Logger.LogDebug("Transfer end"); EndStreamSent = true; } if (OnFrameSent != null) { OnFrameSent(this, new FrameSentEventArgs(dataFrame)); } } else { _unshippedFrames.Enqueue(dataFrame); } }
private void HandleDataFrame(DataFrame dataFrame, out Http2Stream stream) { //09 -> 6.1. DATA //DATA frames MUST be associated with a stream. If a DATA frame is //received whose stream identifier field is 0x0, the recipient MUST //respond with a connection error (Section 5.4.1) of type //PROTOCOL_ERROR. if (dataFrame.StreamId == 0) { throw new ProtocolError(ResetStatusCode.ProtocolError, "Incoming continuation frame with id = 0"); } stream = GetStream(dataFrame.StreamId); //Aggressive window update if (stream != null) { Http2Logger.LogDebug("Data frame. StreamId: {0} Length: {1}", dataFrame.StreamId, dataFrame.FrameLength); if (stream.IsFlowControlEnabled) { stream.WriteWindowUpdate(Constants.MaxFrameContentSize); } } else { throw new Http2StreamNotFoundException(dataFrame.StreamId); } }
private void HandleDataFrame(DataFrame dataFrame, out Http2Stream stream) { Http2Logger.LogDebug("DATA frame: stream id={0}, payload len={1}, has pad={2}, pad high={3}, pad low={4}, " + "end stream={5}", dataFrame.StreamId, dataFrame.PayloadLength, dataFrame.HasPadding, dataFrame.PadHigh, dataFrame.PadLow, dataFrame.IsEndStream); /* 12 -> 6.1 DATA frames MUST be associated with a stream. If a DATA frame is received whose stream identifier field is 0x0, the recipient MUST respond with a connection error of type PROTOCOL_ERROR. */ if (dataFrame.StreamId == 0) throw new ProtocolError(ResetStatusCode.ProtocolError, "Incoming continuation frame with stream id=0"); /* 12 -> 6.1 An endpoint that has not enabled DATA frame compression MUST treat the receipt of a DATA frame with the COMPRESSED flag set as a connection error of type PROTOCOL_ERROR. */ if (dataFrame.IsCompressed) throw new ProtocolError(ResetStatusCode.ProtocolError, "GZIP compression is not enabled"); stream = GetStream(dataFrame.StreamId); if (stream.Closed) throw new Http2StreamNotFoundException(dataFrame.StreamId); if (!(stream.Opened || stream.HalfClosedLocal)) throw new ProtocolError(ResetStatusCode.ProtocolError, "data in non opened or half closed local stream"); if (stream.IsFlowControlEnabled && !dataFrame.IsEndStream) { stream.WriteWindowUpdate(Constants.MaxFramePayloadSize); } }