public void AbortPendingStreamDataWrites(Http2StreamOutputFlowControl flowControl)
 {
     lock (_writeLock)
     {
         flowControl.Abort();
     }
 }
 public bool TryUpdateStreamWindow(Http2StreamOutputFlowControl flowControl, int bytes)
 {
     lock (_writeLock)
     {
         return(flowControl.TryUpdateWindow(bytes));
     }
 }
Exemplo n.º 3
0
        public Http2Stream(Http2StreamContext context)
            : base(context)
        {
            _context           = context;
            _outputFlowControl = new Http2StreamOutputFlowControl(context.ConnectionOutputFlowControl, context.ClientPeerSettings.InitialWindowSize);

            Output = new Http2OutputProducer(context.StreamId, context.FrameWriter, _outputFlowControl, context.TimeoutControl, context.MemoryPool);
        }
 public Http2OutputProducer(
     int streamId,
     Http2FrameWriter frameWriter,
     Http2StreamOutputFlowControl flowControl,
     ITimeoutControl timeoutControl,
     MemoryPool <byte> pool)
 {
     _streamId                = streamId;
     _frameWriter             = frameWriter;
     _flowControl             = flowControl;
     _dataPipe                = CreateDataPipe(pool);
     _flusher                 = new StreamSafePipeFlusher(_dataPipe.Writer, timeoutControl);
     _dataWriteProcessingTask = ProcessDataWrites();
 }
        private async Task WriteDataAsyncAwaited(int streamId, Http2StreamOutputFlowControl flowControl, ReadOnlySequence <byte> data, long dataLength, bool endStream)
        {
            while (dataLength > 0)
            {
                Http2OutputFlowControlAwaitable availabilityAwaitable;
                var writeTask = Task.CompletedTask;

                lock (_writeLock)
                {
                    if (_completed || flowControl.IsAborted)
                    {
                        break;
                    }

                    var actual = flowControl.AdvanceUpToAndWait(dataLength, out availabilityAwaitable);

                    if (actual > 0)
                    {
                        if (actual < dataLength)
                        {
                            writeTask   = WriteDataUnsynchronizedAsync(streamId, data.Slice(0, actual), endStream: false);
                            data        = data.Slice(actual);
                            dataLength -= actual;
                        }
                        else
                        {
                            writeTask  = WriteDataUnsynchronizedAsync(streamId, data, endStream);
                            dataLength = 0;
                        }
                    }
                }

                // This awaitable releases continuations in FIFO order when the window updates.
                // It should be very rare for a continuation to run without any availability.
                if (availabilityAwaitable != null)
                {
                    await availabilityAwaitable;
                }

                await writeTask;
            }

            // Ensure that the application continuation isn't executed inline by ProcessWindowUpdateFrameAsync.
            await ThreadPoolAwaitable.Instance;
        }
        public Task WriteDataAsync(int streamId, Http2StreamOutputFlowControl flowControl, ReadOnlySequence <byte> data, bool endStream)
        {
            // The Length property of a ReadOnlySequence can be expensive, so we cache the value.
            var dataLength = data.Length;

            lock (_writeLock)
            {
                if (_completed || flowControl.IsAborted)
                {
                    return(Task.CompletedTask);
                }

                // Zero-length data frames are allowed to be sent immediately even if there is no space available in the flow control window.
                // https://httpwg.org/specs/rfc7540.html#rfc.section.6.9.1
                if (dataLength != 0 && dataLength > flowControl.Available)
                {
                    return(WriteDataAsyncAwaited(streamId, flowControl, data, dataLength, endStream));
                }

                // This cast is safe since if dataLength would overflow an int, it's guaranteed to be greater than the available flow control window.
                flowControl.Advance((int)dataLength);
                return(WriteDataUnsynchronizedAsync(streamId, data, endStream));
            }
        }