private void HandleContinuation(ContinuationFrame contFrame, out Http2Stream stream) { if (!(_lastFrame is ContinuationFrame || _lastFrame is HeadersFrame)) throw new ProtocolError(ResetStatusCode.ProtocolError, "Last frame was not headers or continuation"); Http2Logger.LogDebug("New continuation with id = " + contFrame.StreamId); if (contFrame.StreamId == 0) { throw new ProtocolError(ResetStatusCode.ProtocolError, "Incoming continuation frame with id = 0"); } var serHeaders = new byte[contFrame.CompressedHeaders.Count]; Buffer.BlockCopy(contFrame.CompressedHeaders.Array, contFrame.CompressedHeaders.Offset, serHeaders, 0, serHeaders.Length); var decomprHeaders = _comprProc.Decompress(serHeaders); var contHeaders = new HeadersList(decomprHeaders); foreach (var header in contHeaders) { Http2Logger.LogDebug("Stream {0} header: {1}={2}", contFrame.StreamId, header.Key, header.Value); } contFrame.Headers.AddRange(contHeaders); var sequence = _headersSequences.Find(seq => seq.StreamId == contFrame.StreamId); if (sequence == null) { sequence = new HeadersSequence(contFrame.StreamId, contFrame); _headersSequences.Add(sequence); } else { sequence.AddHeaders(contFrame); } if (!sequence.IsComplete) { stream = null; return; } stream = GetStream(contFrame.StreamId); if (stream == null) { stream = CreateStream(sequence.Headers, contFrame.StreamId, sequence.Priority); } else { stream.Headers.AddRange(sequence.Headers); } }
private void HandleContinuation(ContinuationFrame contFrame, out Http2Stream stream) { if (!(_lastFrame is ContinuationFrame || _lastFrame is HeadersFrame)) throw new ProtocolError(ResetStatusCode.ProtocolError, "Last frame was not headers or continuation"); Http2Logger.LogDebug("New continuation with id = " + contFrame.StreamId); //09 -> 6.10. CONTINUATION //CONTINUATION frames MUST be associated with a stream. If a //CONTINUATION frame is received whose stream identifier field is 0x0, //the recipient MUST respond with a connection error (Section 5.4.1) of //type PROTOCOL_ERROR. if (contFrame.StreamId == 0) { throw new ProtocolError(ResetStatusCode.ProtocolError, "Incoming continuation frame with id = 0"); } var serHeaders = new byte[contFrame.CompressedHeaders.Count]; Buffer.BlockCopy(contFrame.CompressedHeaders.Array, contFrame.CompressedHeaders.Offset, serHeaders, 0, serHeaders.Length); var decomprHeaders = _comprProc.Decompress(serHeaders); var contHeaders = new HeadersList(decomprHeaders); foreach (var header in contHeaders) { Http2Logger.LogDebug("Stream {0} header: {1}={2}", contFrame.StreamId, header.Key, header.Value); } contFrame.Headers.AddRange(contHeaders); var sequence = _headersSequences.Find(contFrame.StreamId); if (sequence == null) { sequence = new HeadersSequence(contFrame.StreamId, contFrame); _headersSequences.Add(sequence); } else { sequence.AddHeaders(contFrame); } if (!sequence.IsComplete) { stream = null; return; } stream = GetStream(contFrame.StreamId); if (stream == null) { stream = CreateStream(sequence); ValidateHeaders(stream); } else { stream.Headers = sequence.Headers; ValidateHeaders(stream); } }
private void HandleContinuation(ContinuationFrame contFrame, out Http2Stream stream) { Http2Logger.LogDebug("CONTINUATION frame: stream id={0}, payload len={1}, has pad={2}, pad high={3}," + " pad low={4}, end headers={5}", contFrame.StreamId, contFrame.PayloadLength, contFrame.HasPadding, contFrame.PadHigh, contFrame.PadLow, contFrame.IsEndHeaders); if (!(_lastFrame is ContinuationFrame || _lastFrame is HeadersFrame)) throw new ProtocolError(ResetStatusCode.ProtocolError, "Last frame was not headers or continuation"); /* 12 -> 6.10 CONTINUATION frames MUST be associated with a stream. If a CONTINUATION frame is received whose stream identifier field is 0x0, the recipient MUST respond with a connection error of type PROTOCOL_ERROR. */ if (contFrame.StreamId == 0) throw new ProtocolError(ResetStatusCode.ProtocolError, "Incoming continuation frame with stream id=0"); var serHeaders = new byte[contFrame.CompressedHeaders.Count]; Buffer.BlockCopy(contFrame.CompressedHeaders.Array, contFrame.CompressedHeaders.Offset, serHeaders, 0, serHeaders.Length); var decomprHeaders = _comprProc.Decompress(serHeaders); var contHeaders = new HeadersList(decomprHeaders); foreach (var header in contHeaders) { Http2Logger.LogDebug("Stream {0} header: {1}={2}", contFrame.StreamId, header.Key, header.Value); } contFrame.Headers.AddRange(contHeaders); var sequence = _headersSequences.Find(contFrame.StreamId); if (sequence == null) { sequence = new HeadersSequence(contFrame.StreamId, contFrame); _headersSequences.Add(sequence); } else { sequence.AddHeaders(contFrame); } if (!sequence.IsComplete) { stream = null; return; } stream = GetStream(contFrame.StreamId); if (stream.Idle || stream.ReservedRemote) { stream = CreateStream(sequence); ValidateHeaders(stream); } else if (stream.Opened || stream.HalfClosedLocal) { stream.Headers = sequence.Headers;//Modify by the last accepted frame ValidateHeaders(stream); } else if (stream.HalfClosedRemote) { throw new ProtocolError(ResetStatusCode.ProtocolError, "continuation for half closed remote stream"); } else { throw new Http2StreamNotFoundException(contFrame.StreamId); } }