public Task OnDataAsync(Http2Frame dataFrame) { // Since padding isn't buffered, immediately count padding bytes as read for flow control purposes. if (dataFrame.DataHasPadding) { // Add 1 byte for the padding length prefix. OnDataRead(dataFrame.DataPadLength + 1); } var payload = dataFrame.DataPayload; var endStream = dataFrame.DataEndStream; if (payload.Length > 0) { RequestBodyStarted = true; if (endStream) { // No need to send any more window updates for this stream now that we've received all the data. // Call before flushing the request body pipe, because that might induce a window update. _inputFlowControl.StopWindowUpdates(); } _inputFlowControl.Advance(payload.Length); if (IsAborted) { // Ignore data frames for aborted streams, but only after counting them for purposes of connection level flow control. return(Task.CompletedTask); } // This check happens after flow control so that when we throw and abort, the byte count is returned to the connection // level accounting. if (InputRemaining.HasValue) { // https://tools.ietf.org/html/rfc7540#section-8.1.2.6 if (payload.Length > InputRemaining.Value) { throw new Http2StreamErrorException(StreamId, CoreStrings.Http2StreamErrorMoreDataThanLength, Http2ErrorCode.PROTOCOL_ERROR); } InputRemaining -= payload.Length; } RequestBodyPipe.Writer.Write(payload); var flushTask = RequestBodyPipe.Writer.FlushAsync(); // It shouldn't be possible for the RequestBodyPipe to fill up an return an incomplete task if // _inputFlowControl.Advance() didn't throw. Debug.Assert(flushTask.IsCompleted); } if (endStream) { OnEndStreamReceived(); } return(Task.CompletedTask); }
public Task OnDataAsync(Http2Frame dataFrame) { // TODO: content-length accounting // Since padding isn't buffered, immediately count padding bytes as read for flow control purposes. if (dataFrame.DataHasPadding) { // Add 1 byte for the padding length prefix. OnDataRead(dataFrame.DataPadLength + 1); } var payload = dataFrame.DataPayload; var endStream = (dataFrame.DataFlags & Http2DataFrameFlags.END_STREAM) == Http2DataFrameFlags.END_STREAM; if (payload.Count > 0) { RequestBodyStarted = true; if (endStream) { // No need to send any more window updates for this stream now that we've received all the data. // Call before flushing the request body pipe, because that might induce a window update. _inputFlowControl.StopWindowUpdates(); } _inputFlowControl.Advance(payload.Count); RequestBodyPipe.Writer.Write(payload); var flushTask = RequestBodyPipe.Writer.FlushAsync(); // It shouldn't be possible for the RequestBodyPipe to fill up an return an incomplete task if // _inputFlowControl.Advance() didn't throw. Debug.Assert(flushTask.IsCompleted); } if (endStream) { OnEndStreamReceived(); } return(Task.CompletedTask); }