public void WriteHeadersFrame(HeadersList headers, bool isEndStream, bool isEndHeaders) { if (headers == null) throw new ArgumentNullException("headers is null"); if (Closed) return; var frame = new HeadersFrame(_id, true) { IsEndHeaders = isEndHeaders, IsEndStream = isEndStream, Headers = headers, }; _writeQueue.WriteFrame(frame); if (frame.IsEndStream) { HalfClosedLocal = true; } else if (ReservedLocal) { HalfClosedRemote = true; } if (OnFrameSent != null) { OnFrameSent(this, new FrameSentEventArgs(frame)); } }
private void HandleHeaders(HeadersFrame headersFrame, out Http2Stream stream) { Http2Logger.LogDebug("New headers with id = " + headersFrame.StreamId); //spec 06: //If a HEADERS 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 [PROTOCOL_ERROR]. if (headersFrame.StreamId == 0) { throw new ProtocolError(ResetStatusCode.ProtocolError, "Incoming headers frame with id = 0"); } var serializedHeaders = new byte[headersFrame.CompressedHeaders.Count]; Buffer.BlockCopy(headersFrame.CompressedHeaders.Array, headersFrame.CompressedHeaders.Offset, serializedHeaders, 0, serializedHeaders.Length); var decompressedHeaders = _comprProc.Decompress(serializedHeaders); var headers = new HeadersList(decompressedHeaders); foreach (var header in headers) { Http2Logger.LogDebug("Stream {0} header: {1}={2}", headersFrame.StreamId, header.Key, header.Value); } headersFrame.Headers.AddRange(headers); var sequence = _headersSequences.Find(seq => seq.StreamId == headersFrame.StreamId); if (sequence == null) { sequence = new HeadersSequence(headersFrame.StreamId, headersFrame); _headersSequences.Add(sequence); } else { sequence.AddHeaders(headersFrame); } if (headersFrame.HasPriority) { sequence.Priority = headersFrame.Priority; } if (!sequence.IsComplete) { stream = null; return; } stream = GetStream(headersFrame.StreamId); if (stream == null) { stream = CreateStream(sequence.Headers, headersFrame.StreamId, sequence.Priority); } else { stream.Headers.AddRange(sequence.Headers); } }
private void HandleHeaders(HeadersFrame headersFrame, out Http2Stream stream) { Http2Logger.LogDebug("HEADERS frame: stream id={0}, payload len={1}, has pad={2}, pad high={3}, pad low={4}, " + "end stream={5}, has priority={6}, exclusive={7}, dependency={8}, weight={9}", headersFrame.StreamId, headersFrame.PayloadLength, headersFrame.HasPadding, headersFrame.PadHigh, headersFrame.PadLow, headersFrame.IsEndStream, headersFrame.HasPriority, headersFrame.Exclusive, headersFrame.StreamDependency, headersFrame.Weight); /* 12 -> 6.2 HEADERS frames MUST be associated with a stream. If a HEADERS frame is received whose stream identifier field is 0x0, the recipient MUST respond with a connection error of type PROTOCOL_ERROR. */ if (headersFrame.StreamId == 0) throw new ProtocolError(ResetStatusCode.ProtocolError, "Incoming headers frame with stream id=0"); var serializedHeaders = new byte[headersFrame.CompressedHeaders.Count]; Buffer.BlockCopy(headersFrame.CompressedHeaders.Array, headersFrame.CompressedHeaders.Offset, serializedHeaders, 0, serializedHeaders.Length); var decompressedHeaders = _comprProc.Decompress(serializedHeaders); var headers = new HeadersList(decompressedHeaders); foreach (var header in headers) { Http2Logger.LogDebug("{1}={2}", headersFrame.StreamId, header.Key, header.Value); } headersFrame.Headers.AddRange(headers); var sequence = _headersSequences.Find(headersFrame.StreamId); if (sequence == null) { sequence = new HeadersSequence(headersFrame.StreamId, headersFrame); _headersSequences.Add(sequence); } else { sequence.AddHeaders(headersFrame); } if (headersFrame.HasPriority) { //TODO: Priority was deprecated, now we need to use Dependency and Weight //sequence.Priority = headersFrame.Priority; } if (!sequence.IsComplete) { stream = null; return; } stream = GetStream(headersFrame.StreamId); if (stream.Idle) { stream = CreateStream(sequence); ValidateHeaders(stream); } else if (stream.ReservedRemote) { stream = CreateStream(sequence); stream.HalfClosedLocal = true; 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, "headers for half closed remote stream"); } else { throw new Http2StreamNotFoundException(headersFrame.StreamId); } }
public void WriteHeadersFrame(HeadersList headers, bool isEndStream, bool isEndHeaders) { if (headers == null) throw new ArgumentNullException("headers is null"); if (Disposed) return; var frame = new HeadersFrame(_id, Priority) { IsEndHeaders = isEndHeaders, IsEndStream = isEndStream, Headers = headers, }; _writeQueue.WriteFrame(frame); if (frame.IsEndStream) { EndStreamSent = true; } if (OnFrameSent != null) { OnFrameSent(this, new FrameSentEventArgs(frame)); } }
public void WriteHeadersFrame(HeadersList headers, bool isEndStream, bool isEndHeaders) { if (headers == null) throw new ArgumentNullException("headers is null"); if (Disposed) return; Headers.AddRange(headers); byte[] headerBytes = _compressionProc.Compress(headers); var frame = new HeadersFrame(_id, headerBytes, Priority) { IsEndHeaders = isEndHeaders, IsEndStream = isEndStream, }; _writeQueue.WriteFrame(frame); if (frame.IsEndStream) { EndStreamSent = true; } if (OnFrameSent != null) { OnFrameSent(this, new FrameSentArgs(frame)); } }