// Additional data has arrived for the request stream. Add it to our request stream buffer, // update any necessary state (e.g. FINs), and trigger any waiting readers. public void ReceiveData(DataFrame dataFrame) { if (Disposed) { // TODO: Send reset? return; } Contract.Assert(_incomingStream != null); ArraySegment<byte> data = dataFrame.Data; // TODO: Decompression? _incomingStream.Write(data.Array, data.Offset, data.Count); if (dataFrame.IsFin) { FinReceived = true; _incomingStream.Dispose(); } }
private void SaveDataFrame(Http2Stream stream, DataFrame dataFrame) { lock (_writeLock) { string originalPath = stream.Headers.GetValue(":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); stream.Dispose(); } 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 } } }
public DataFrameReceivedEventArgs(DataFrame frame) { Id = frame.StreamId; DataAmount = frame.Buffer.Length - Constants.FramePreambleSize; }
private void SaveDataFrame(Http2Stream stream, DataFrame dataFrame) { lock (_writeLock) { string path = stream.Headers.GetValue(":path".ToLower()); try { string pathToSave = AssemblyPath + @"\Root" + path; if (!Directory.Exists(Path.GetDirectoryName(pathToSave))) { throw new DirectoryNotFoundException("Access denied"); } _fileHelper.SaveToFile(dataFrame.Data.Array, dataFrame.Data.Offset, dataFrame.Data.Count, pathToSave, stream.ReceivedDataAmount != 0); } catch (Exception ex) { Console.WriteLine(ex.Message); stream.WriteDataFrame(new byte[0], true); stream.Dispose(); } stream.ReceivedDataAmount += dataFrame.FrameLength; if (dataFrame.IsEndStream) { if (!stream.EndStreamSent) { //send terminator stream.WriteDataFrame(new byte[0], true); Console.WriteLine("Terminator was sent"); } _fileHelper.RemoveStream(AssemblyPath + @"\Root" + path); } } }
// Send a Fin frame public void EndRequest() { DataFrame terminator = new DataFrame(_id); FinSent = true; _writeQueue.WriteFrameAsync(terminator, _priority); }
/// <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="dataFrame">The data frame.</param> public void WriteDataFrame(DataFrame dataFrame) { if (IsFlowControlBlocked == false) { _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 FrameSentArgs(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(byte[] data, bool isEndStream) { var dataFrame = new DataFrame(_id, new ArraySegment<byte>(data), isEndStream); if (IsFlowControlBlocked == false) { _writeQueue.WriteFrame(dataFrame); SentDataAmount += dataFrame.FrameLength; _flowCrtlManager.DataFrameSentHandler(this, new DataFrameSentEventArgs(dataFrame)); if (dataFrame.IsEndStream) { Console.WriteLine("Transfer end"); EndStreamSent = true; } if (OnFrameSent != null) { OnFrameSent(this, new FrameSentArgs(dataFrame)); } } else { _unshippedFrames.Enqueue(dataFrame); } }
// Does not support overlapped writes due to flow control backpressure implementation. public async override Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) { CheckDisposed(); cancellationToken.ThrowIfCancellationRequested(); // TODO: Compression? _onStart(); int written = 0; do { if (_flowControlCredit <= 0) { // await a backpressure task until we get a window update. await WaitForFlowCreditAsync(cancellationToken); CheckDisposed(); cancellationToken.ThrowIfCancellationRequested(); } int subCount = Math.Min(Math.Min(_flowControlCredit, count - written), Constants.MaxDataFrameContentSize); DataFrame dataFrame = new DataFrame(_streamId, new ArraySegment<byte>(buffer, offset, subCount)); // TODO: Flags? Compression? written += subCount; offset += subCount; _flowControlCredit -= subCount; await _writeQueue.WriteFrameAsync(dataFrame, _priority); } while (written < count); }