public void AbortPendingStreamDataWrites(Http2StreamOutputFlowControl flowControl) { lock (_writeLock) { flowControl.Abort(); } }
public bool TryUpdateStreamWindow(Http2StreamOutputFlowControl flowControl, int bytes) { lock (_writeLock) { return(flowControl.TryUpdateWindow(bytes)); } }
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)); } }