public Http2OutputProducer( int streamId, Http2FrameWriter frameWriter, StreamOutputFlowControl flowControl, ITimeoutControl timeoutControl, MemoryPool <byte> pool, Http2Stream stream, IKestrelTrace log) { _streamId = streamId; _frameWriter = frameWriter; _flowControl = flowControl; _stream = stream; _dataPipe = CreateDataPipe(pool); _flusher = new TimingPipeFlusher(_dataPipe.Writer, timeoutControl, log); _dataWriteProcessingTask = ProcessDataWrites(); }
public bool TryPop(out Http2Stream result) { int size = _size - 1; Http2StreamAsValueType[] array = _array; if ((uint)size >= (uint)array.Length) { result = default; return(false); } _size = size; result = array[size]; array[size] = default; return(true); }
public Http2OutputProducer(Http2Stream stream, Http2StreamContext context, StreamOutputFlowControl flowControl) { _stream = stream; _frameWriter = context.FrameWriter; _flowControl = flowControl; _memoryPool = context.MemoryPool; _log = context.ServiceContext.Log; _pipe = CreateDataPipe(_memoryPool); _pipeWriter = new ConcurrentPipeWriter(_pipe.Writer, _memoryPool, _dataWriterLock); _pipeReader = _pipe.Reader; // No need to pass in timeoutControl here, since no minDataRates are passed to the TimingPipeFlusher. // The minimum output data rate is enforced at the connection level by Http2FrameWriter. _flusher = new TimingPipeFlusher(_pipeWriter, timeoutControl: null, _log); _dataWriteProcessingTask = ProcessDataWrites(); }
public void RemoveExpired(long now) { int size = _size; Http2StreamAsValueType[] array = _array; var removeCount = CalculateRemoveCount(now, size, array); if (removeCount == 0) { return; } var newSize = size - removeCount; // Dispose removed streams for (var i = 0; i < removeCount; i++) { Http2Stream stream = array[i]; stream.Dispose(); } // Move remaining streams for (var i = 0; i < newSize; i++) { array[i] = array[i + removeCount]; } // Clear unused array indexes for (var i = newSize; i < size; i++) { array[i] = default; } _size = newSize; }
private Http2MessageBody(Http2Stream context) : base(context) { _context = context; }
private async Task ProcessHeadersFrameAsync <TContext>(IHttpApplication <TContext> application) { if (_currentHeadersStream != null) { throw new Http2ConnectionErrorException(CoreStrings.FormatHttp2ErrorHeadersInterleaved(_incomingFrame.Type, _incomingFrame.StreamId, _currentHeadersStream.StreamId), Http2ErrorCode.PROTOCOL_ERROR); } if (_incomingFrame.StreamId == 0) { throw new Http2ConnectionErrorException(CoreStrings.FormatHttp2ErrorStreamIdZero(_incomingFrame.Type), Http2ErrorCode.PROTOCOL_ERROR); } if (_incomingFrame.HeadersHasPadding && _incomingFrame.HeadersPadLength >= _incomingFrame.Length) { throw new Http2ConnectionErrorException(CoreStrings.FormatHttp2ErrorPaddingTooLong(_incomingFrame.Type), Http2ErrorCode.PROTOCOL_ERROR); } if (_incomingFrame.HeadersHasPriority && _incomingFrame.HeadersStreamDependency == _incomingFrame.StreamId) { throw new Http2ConnectionErrorException(CoreStrings.FormatHttp2ErrorStreamSelfDependency(_incomingFrame.Type, _incomingFrame.StreamId), Http2ErrorCode.PROTOCOL_ERROR); } if (_streams.TryGetValue(_incomingFrame.StreamId, out var stream)) { // http://httpwg.org/specs/rfc7540.html#rfc.section.5.1 // // ...an endpoint that receives any frames after receiving a frame with the // END_STREAM flag set MUST treat that as a connection error (Section 5.4.1) // of type STREAM_CLOSED, unless the frame is permitted as described below. // // (The allowed frame types after END_STREAM are WINDOW_UPDATE, RST_STREAM and PRIORITY) if (stream.EndStreamReceived) { throw new Http2ConnectionErrorException(CoreStrings.FormatHttp2ErrorStreamHalfClosedRemote(_incomingFrame.Type, stream.StreamId), Http2ErrorCode.STREAM_CLOSED); } // This is the last chance for the client to send END_STREAM if ((_incomingFrame.HeadersFlags & Http2HeadersFrameFlags.END_STREAM) == 0) { throw new Http2ConnectionErrorException(CoreStrings.Http2ErrorHeadersWithTrailersNoEndStream, Http2ErrorCode.PROTOCOL_ERROR); } // Since we found an active stream, this HEADERS frame contains trailers _currentHeadersStream = stream; _requestHeaderParsingState = RequestHeaderParsingState.Trailers; var endHeaders = (_incomingFrame.HeadersFlags & Http2HeadersFrameFlags.END_HEADERS) == Http2HeadersFrameFlags.END_HEADERS; await DecodeTrailersAsync(endHeaders, _incomingFrame.HeadersPayload); } else if (_incomingFrame.StreamId <= _highestOpenedStreamId) { // http://httpwg.org/specs/rfc7540.html#rfc.section.5.1.1 // // The first use of a new stream identifier implicitly closes all streams in the "idle" // state that might have been initiated by that peer with a lower-valued stream identifier. // // If we couldn't find the stream, it was previously closed (either implicitly or with // END_STREAM or RST_STREAM). throw new Http2ConnectionErrorException(CoreStrings.FormatHttp2ErrorStreamClosed(_incomingFrame.Type, _incomingFrame.StreamId), Http2ErrorCode.STREAM_CLOSED); } else { // Start a new stream _currentHeadersStream = new Http2Stream(new Http2StreamContext { ConnectionId = ConnectionId, StreamId = _incomingFrame.StreamId, ServiceContext = _context.ServiceContext, ConnectionFeatures = _context.ConnectionFeatures, MemoryPool = _context.MemoryPool, LocalEndPoint = _context.LocalEndPoint, RemoteEndPoint = _context.RemoteEndPoint, StreamLifetimeHandler = this, ClientPeerSettings = _clientSettings, FrameWriter = _frameWriter, ConnectionOutputFlowControl = _outputFlowControl, TimeoutControl = this, }); if ((_incomingFrame.HeadersFlags & Http2HeadersFrameFlags.END_STREAM) == Http2HeadersFrameFlags.END_STREAM) { await _currentHeadersStream.OnDataAsync(Constants.EmptyData, endStream : true); } _currentHeadersStream.Reset(); var endHeaders = (_incomingFrame.HeadersFlags & Http2HeadersFrameFlags.END_HEADERS) == Http2HeadersFrameFlags.END_HEADERS; await DecodeHeadersAsync(application, endHeaders, _incomingFrame.HeadersPayload); } }
public Http2MessageBody(Http2Stream context) : base(context) { _context = context; }
public ForHttp2(Http2Stream context) : base(context) { }
protected Http2MessageBody(Http2Stream context) : base(context) { _context = context; }
private Http2StreamAsValueType(Http2Stream value) => _value = value;
private void PushWithResize(Http2Stream item) { Array.Resize(ref _array, 2 * _array.Length); _array[_size] = item; _size++; }
private Http2MessageBody(Http2Stream context, MinDataRate minRequestBodyDataRate) : base(context, minRequestBodyDataRate) { _context = context; }
private async Task ProcessHeadersFrameAsync <TContext>(IHttpApplication <TContext> application) { if (_currentHeadersStream != null) { throw new Http2ConnectionErrorException(Http2ErrorCode.PROTOCOL_ERROR); } if (_incomingFrame.StreamId == 0) { throw new Http2ConnectionErrorException(Http2ErrorCode.PROTOCOL_ERROR); } if (_incomingFrame.HeadersHasPadding && _incomingFrame.HeadersPadLength >= _incomingFrame.Length) { throw new Http2ConnectionErrorException(Http2ErrorCode.PROTOCOL_ERROR); } if (_incomingFrame.HeadersHasPriority && _incomingFrame.HeadersStreamDependency == _incomingFrame.StreamId) { throw new Http2ConnectionErrorException(Http2ErrorCode.PROTOCOL_ERROR); } if (_streams.TryGetValue(_incomingFrame.StreamId, out var stream)) { // http://httpwg.org/specs/rfc7540.html#rfc.section.5.1 // // ...an endpoint that receives any frames after receiving a frame with the // END_STREAM flag set MUST treat that as a connection error (Section 5.4.1) // of type STREAM_CLOSED, unless the frame is permitted as described below. // // (The allowed frame types for this situation are WINDOW_UPDATE, RST_STREAM and PRIORITY) if (stream.EndStreamReceived) { throw new Http2ConnectionErrorException(Http2ErrorCode.STREAM_CLOSED); } // TODO: trailers } else if (_incomingFrame.StreamId <= _highestOpenedStreamId) { // http://httpwg.org/specs/rfc7540.html#rfc.section.5.1.1 // // The first use of a new stream identifier implicitly closes all streams in the "idle" // state that might have been initiated by that peer with a lower-valued stream identifier. // // If we couldn't find the stream, it was previously closed (either implicitly or with // END_STREAM or RST_STREAM). throw new Http2ConnectionErrorException(Http2ErrorCode.STREAM_CLOSED); } else { // Start a new stream _currentHeadersStream = new Http2Stream <TContext>(application, new Http2StreamContext { ConnectionId = ConnectionId, StreamId = _incomingFrame.StreamId, ServiceContext = _context.ServiceContext, ConnectionFeatures = _context.ConnectionFeatures, PipeFactory = _context.PipeFactory, LocalEndPoint = _context.LocalEndPoint, RemoteEndPoint = _context.RemoteEndPoint, StreamLifetimeHandler = this, FrameWriter = _frameWriter }); if ((_incomingFrame.HeadersFlags & Http2HeadersFrameFlags.END_STREAM) == Http2HeadersFrameFlags.END_STREAM) { await _currentHeadersStream.OnDataAsync(Constants.EmptyData, endStream : true); } _currentHeadersStream.Reset(); var endHeaders = (_incomingFrame.HeadersFlags & Http2HeadersFrameFlags.END_HEADERS) == Http2HeadersFrameFlags.END_HEADERS; await DecodeHeadersAsync(endHeaders, _incomingFrame.HeadersPayload); } }