コード例 #1
0
        public void WriteResponseHeaders(int streamId, int statusCode, IHeaderDictionary headers)
        {
            lock (_writeLock)
            {
                _outgoingFrame.PrepareHeaders(Http2HeadersFrameFlags.NONE, streamId);

                var done = _hpackEncoder.BeginEncode(statusCode, EnumerateHeaders(headers), _outgoingFrame.Payload, out var payloadLength);
                _outgoingFrame.Length = payloadLength;

                if (done)
                {
                    _outgoingFrame.HeadersFlags = Http2HeadersFrameFlags.END_HEADERS;
                }

                Append(_outgoingFrame.Raw);

                while (!done)
                {
                    _outgoingFrame.PrepareContinuation(Http2ContinuationFrameFlags.NONE, streamId);

                    done = _hpackEncoder.Encode(_outgoingFrame.Payload, out var length);
                    _outgoingFrame.Length = length;

                    if (done)
                    {
                        _outgoingFrame.ContinuationFlags = Http2ContinuationFrameFlags.END_HEADERS;
                    }

                    Append(_outgoingFrame.Raw);
                }
            }
        }
コード例 #2
0
        private void FinishWritingHeaders(int streamId, int payloadLength, bool done)
        {
            var buffer = _headerEncodingBuffer.AsSpan();

            _outgoingFrame.PayloadLength = payloadLength;
            if (done)
            {
                _outgoingFrame.HeadersFlags |= Http2HeadersFrameFlags.END_HEADERS;
            }

            WriteHeaderUnsynchronized();
            _outputWriter.Write(buffer.Slice(0, payloadLength));

            while (!done)
            {
                _outgoingFrame.PrepareContinuation(Http2ContinuationFrameFlags.NONE, streamId);

                done = _hpackEncoder.Encode(buffer, out payloadLength);
                _outgoingFrame.PayloadLength = payloadLength;

                if (done)
                {
                    _outgoingFrame.ContinuationFlags = Http2ContinuationFrameFlags.END_HEADERS;
                }

                WriteHeaderUnsynchronized();
                _outputWriter.Write(buffer.Slice(0, payloadLength));
            }
        }
コード例 #3
0
        // Optional header fields for padding and priority are not implemented.

        /* https://tools.ietf.org/html/rfc7540#section-6.2
         +---------------+
         |Pad Length? (8)|
         +-+-------------+-----------------------------------------------+
         |E|                 Stream Dependency? (31)                     |
         +-+-------------+-----------------------------------------------+
         |  Weight? (8)  |
         +-+-------------+-----------------------------------------------+
         |                   Header Block Fragment (*)                 ...
         +---------------------------------------------------------------+
         |                           Padding (*)                       ...
         +---------------------------------------------------------------+
         */
        public void WriteResponseHeaders(int streamId, int statusCode, IHeaderDictionary headers)
        {
            lock (_writeLock)
            {
                if (_completed)
                {
                    return;
                }

                try
                {
                    _outgoingFrame.PrepareHeaders(Http2HeadersFrameFlags.NONE, streamId);
                    var buffer = _headerEncodingBuffer.AsSpan();
                    var done   = _hpackEncoder.BeginEncode(statusCode, EnumerateHeaders(headers), buffer, out var payloadLength);

                    _outgoingFrame.PayloadLength = payloadLength;

                    if (done)
                    {
                        _outgoingFrame.HeadersFlags = Http2HeadersFrameFlags.END_HEADERS;
                    }

                    WriteHeaderUnsynchronized();
                    _outputWriter.Write(buffer.Slice(0, payloadLength));

                    while (!done)
                    {
                        _outgoingFrame.PrepareContinuation(Http2ContinuationFrameFlags.NONE, streamId);

                        done = _hpackEncoder.Encode(buffer, out payloadLength);
                        _outgoingFrame.PayloadLength = payloadLength;

                        if (done)
                        {
                            _outgoingFrame.ContinuationFlags = Http2ContinuationFrameFlags.END_HEADERS;
                        }

                        WriteHeaderUnsynchronized();
                        _outputWriter.Write(buffer.Slice(0, payloadLength));
                    }
                }
                catch (HPackEncodingException hex)
                {
                    // Header errors are fatal to the connection. We don't have a direct way to signal this to the Http2Connection.
                    _connectionContext.Abort(new ConnectionAbortedException("", hex));
                    throw new InvalidOperationException("", hex); // Report the error to the user if this was the first write.
                }
            }
        }