Exemple #1
0
        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));
            }
        }