private async Task ProcessHeadersFrame(FrameHeader frameHeader) { Debug.Assert(frameHeader.Type == FrameType.Headers); bool endStream = frameHeader.EndStreamFlag; int streamId = frameHeader.StreamId; Http2Stream http2Stream = GetStream(streamId); if (http2Stream == null) { _incomingBuffer.Discard(frameHeader.Length); // Don't wait for completion, which could happen asynchronously. ValueTask ignored = SendRstStreamAsync(streamId, Http2ProtocolErrorCode.StreamClosed); return; } // TODO: Figure out how to cache this delegate. // Probably want to pass a state object to Decode. HPackDecoder.HeaderCallback headerCallback = http2Stream.OnResponseHeader; _hpackDecoder.Decode(GetFrameData(_incomingBuffer.ActiveSpan.Slice(0, frameHeader.Length), frameHeader.PaddedFlag, frameHeader.PriorityFlag), headerCallback); _incomingBuffer.Discard(frameHeader.Length); while (!frameHeader.EndHeadersFlag) { frameHeader = await ReadFrameAsync().ConfigureAwait(false); if (frameHeader.Type != FrameType.Continuation || frameHeader.StreamId != streamId) { throw new Http2ProtocolException(Http2ProtocolErrorCode.ProtocolError); } _hpackDecoder.Decode(_incomingBuffer.ActiveSpan.Slice(0, frameHeader.Length), headerCallback); _incomingBuffer.Discard(frameHeader.Length); } _hpackDecoder.CompleteDecode(); http2Stream.OnResponseHeadersComplete(endStream); if (endStream) { RemoveStream(http2Stream); } }