Пример #1
0
        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);
        }
Пример #2
0
        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);
        }