Exemplo n.º 1
0
        private void OnIndexedHeaderField(int index, IHttpHeadersHandler handler)
        {
            var header = GetHeader(index);

            handler.OnHeader(new Span <byte>(header.Name), new Span <byte>(header.Value));
            _state = State.Ready;
        }
Exemplo n.º 2
0
        public void Decode(Span <byte> data, bool endHeaders, IHttpHeadersHandler handler)
        {
            for (var i = 0; i < data.Length; i++)
            {
                OnByte(data[i], handler);
            }

            if (endHeaders && _state != State.Ready)
            {
                throw new HPackDecodingException(CoreStrings.HPackErrorIncompleteHeaderBlock);
            }
        }
Exemplo n.º 3
0
        private void ProcessHeaderValue(IHttpHeadersHandler handler)
        {
            OnString(nextState: State.Ready);

            var headerNameSpan  = new Span <byte>(_headerName, 0, _headerNameLength);
            var headerValueSpan = new Span <byte>(_headerValueOctets, 0, _headerValueLength);

            handler.OnHeader(headerNameSpan, headerValueSpan);

            if (_index)
            {
                _dynamicTable.Insert(headerNameSpan, headerValueSpan);
            }
        }
Exemplo n.º 4
0
        public void Decode(ReadOnlySequence <byte> data, bool endHeaders, IHttpHeadersHandler handler)
        {
            foreach (var segment in data)
            {
                var span = segment.Span;
                for (var i = 0; i < span.Length; i++)
                {
                    OnByte(span[i], handler);
                }
            }

            if (endHeaders)
            {
                if (_state != State.Ready)
                {
                    throw new HPackDecodingException(CoreStrings.HPackErrorIncompleteHeaderBlock);
                }

                _headersObserved = false;
            }
        }
Exemplo n.º 5
0
        private void OnByte(byte b, IHttpHeadersHandler handler)
        {
            int intResult;

            switch (_state)
            {
            case State.Ready:
                if ((b & IndexedHeaderFieldMask) == IndexedHeaderFieldRepresentation)
                {
                    _headersObserved = true;
                    var val = b & ~IndexedHeaderFieldMask;

                    if (_integerDecoder.BeginTryDecode((byte)val, IndexedHeaderFieldPrefix, out intResult))
                    {
                        OnIndexedHeaderField(intResult, handler);
                    }
                    else
                    {
                        _state = State.HeaderFieldIndex;
                    }
                }
                else if ((b & LiteralHeaderFieldWithIncrementalIndexingMask) == LiteralHeaderFieldWithIncrementalIndexingRepresentation)
                {
                    _headersObserved = true;
                    _index           = true;
                    var val = b & ~LiteralHeaderFieldWithIncrementalIndexingMask;

                    if (val == 0)
                    {
                        _state = State.HeaderNameLength;
                    }
                    else if (_integerDecoder.BeginTryDecode((byte)val, LiteralHeaderFieldWithIncrementalIndexingPrefix, out intResult))
                    {
                        OnIndexedHeaderName(intResult);
                    }
                    else
                    {
                        _state = State.HeaderNameIndex;
                    }
                }
                else if ((b & LiteralHeaderFieldWithoutIndexingMask) == LiteralHeaderFieldWithoutIndexingRepresentation)
                {
                    _headersObserved = true;
                    _index           = false;
                    var val = b & ~LiteralHeaderFieldWithoutIndexingMask;

                    if (val == 0)
                    {
                        _state = State.HeaderNameLength;
                    }
                    else if (_integerDecoder.BeginTryDecode((byte)val, LiteralHeaderFieldWithoutIndexingPrefix, out intResult))
                    {
                        OnIndexedHeaderName(intResult);
                    }
                    else
                    {
                        _state = State.HeaderNameIndex;
                    }
                }
                else if ((b & LiteralHeaderFieldNeverIndexedMask) == LiteralHeaderFieldNeverIndexedRepresentation)
                {
                    _headersObserved = true;
                    _index           = false;
                    var val = b & ~LiteralHeaderFieldNeverIndexedMask;

                    if (val == 0)
                    {
                        _state = State.HeaderNameLength;
                    }
                    else if (_integerDecoder.BeginTryDecode((byte)val, LiteralHeaderFieldNeverIndexedPrefix, out intResult))
                    {
                        OnIndexedHeaderName(intResult);
                    }
                    else
                    {
                        _state = State.HeaderNameIndex;
                    }
                }
                else if ((b & DynamicTableSizeUpdateMask) == DynamicTableSizeUpdateRepresentation)
                {
                    // https://tools.ietf.org/html/rfc7541#section-4.2
                    // This dynamic table size
                    // update MUST occur at the beginning of the first header block
                    // following the change to the dynamic table size.
                    if (_headersObserved)
                    {
                        throw new HPackDecodingException(CoreStrings.HPackErrorDynamicTableSizeUpdateNotAtBeginningOfHeaderBlock);
                    }

                    if (_integerDecoder.BeginTryDecode((byte)(b & ~DynamicTableSizeUpdateMask), DynamicTableSizeUpdatePrefix, out intResult))
                    {
                        SetDynamicHeaderTableSize(intResult);
                    }
                    else
                    {
                        _state = State.DynamicTableSizeUpdate;
                    }
                }
                else
                {
                    // Can't happen
                    throw new HPackDecodingException($"Byte value {b} does not encode a valid header field representation.");
                }

                break;

            case State.HeaderFieldIndex:
                if (_integerDecoder.TryDecode(b, out intResult))
                {
                    OnIndexedHeaderField(intResult, handler);
                }

                break;

            case State.HeaderNameIndex:
                if (_integerDecoder.TryDecode(b, out intResult))
                {
                    OnIndexedHeaderName(intResult);
                }

                break;

            case State.HeaderNameLength:
                _huffman = (b & HuffmanMask) != 0;

                if (_integerDecoder.BeginTryDecode((byte)(b & ~HuffmanMask), StringLengthPrefix, out intResult))
                {
                    OnStringLength(intResult, nextState: State.HeaderName);
                }
                else
                {
                    _state = State.HeaderNameLengthContinue;
                }

                break;

            case State.HeaderNameLengthContinue:
                if (_integerDecoder.TryDecode(b, out intResult))
                {
                    OnStringLength(intResult, nextState: State.HeaderName);
                }

                break;

            case State.HeaderName:
                _stringOctets[_stringIndex++] = b;

                if (_stringIndex == _stringLength)
                {
                    OnString(nextState: State.HeaderValueLength);
                }

                break;

            case State.HeaderValueLength:
                _huffman = (b & HuffmanMask) != 0;

                if (_integerDecoder.BeginTryDecode((byte)(b & ~HuffmanMask), StringLengthPrefix, out intResult))
                {
                    OnStringLength(intResult, nextState: State.HeaderValue);
                    if (intResult == 0)
                    {
                        ProcessHeaderValue(handler);
                    }
                }
                else
                {
                    _state = State.HeaderValueLengthContinue;
                }

                break;

            case State.HeaderValueLengthContinue:
                if (_integerDecoder.TryDecode(b, out intResult))
                {
                    OnStringLength(intResult, nextState: State.HeaderValue);
                    if (intResult == 0)
                    {
                        ProcessHeaderValue(handler);
                    }
                }

                break;

            case State.HeaderValue:
                _stringOctets[_stringIndex++] = b;

                if (_stringIndex == _stringLength)
                {
                    ProcessHeaderValue(handler);
                }

                break;

            case State.DynamicTableSizeUpdate:
                if (_integerDecoder.TryDecode(b, out intResult))
                {
                    SetDynamicHeaderTableSize(intResult);
                    _state = State.Ready;
                }

                break;

            default:
                // Can't happen
                throw new HPackDecodingException("The HPACK decoder reached an invalid state.");
            }
        }
Exemplo n.º 6
0
        public void OnByte(byte b, IHttpHeadersHandler handler)
        {
            switch (_state)
            {
            case State.Ready:
                if ((b & IndexedHeaderFieldMask) == IndexedHeaderFieldRepresentation)
                {
                    var val = b & ~IndexedHeaderFieldMask;

                    if (_integerDecoder.BeginDecode((byte)val, IndexedHeaderFieldPrefix))
                    {
                        OnIndexedHeaderField(_integerDecoder.Value, handler);
                    }
                    else
                    {
                        _state = State.HeaderFieldIndex;
                    }
                }
                else if ((b & LiteralHeaderFieldWithIncrementalIndexingMask) == LiteralHeaderFieldWithIncrementalIndexingRepresentation)
                {
                    _index = true;
                    var val = b & ~LiteralHeaderFieldWithIncrementalIndexingMask;

                    if (val == 0)
                    {
                        _state = State.HeaderNameLength;
                    }
                    else if (_integerDecoder.BeginDecode((byte)val, LiteralHeaderFieldWithIncrementalIndexingPrefix))
                    {
                        OnIndexedHeaderName(_integerDecoder.Value);
                    }
                    else
                    {
                        _state = State.HeaderNameIndex;
                    }
                }
                else if ((b & LiteralHeaderFieldWithoutIndexingMask) == LiteralHeaderFieldWithoutIndexingRepresentation)
                {
                    _index = false;
                    var val = b & ~LiteralHeaderFieldWithoutIndexingMask;

                    if (val == 0)
                    {
                        _state = State.HeaderNameLength;
                    }
                    else if (_integerDecoder.BeginDecode((byte)val, LiteralHeaderFieldWithoutIndexingPrefix))
                    {
                        OnIndexedHeaderName(_integerDecoder.Value);
                    }
                    else
                    {
                        _state = State.HeaderNameIndex;
                    }
                }
                else if ((b & LiteralHeaderFieldNeverIndexedMask) == LiteralHeaderFieldNeverIndexedRepresentation)
                {
                    _index = false;
                    var val = b & ~LiteralHeaderFieldNeverIndexedMask;

                    if (val == 0)
                    {
                        _state = State.HeaderNameLength;
                    }
                    else if (_integerDecoder.BeginDecode((byte)val, LiteralHeaderFieldNeverIndexedPrefix))
                    {
                        OnIndexedHeaderName(_integerDecoder.Value);
                    }
                    else
                    {
                        _state = State.HeaderNameIndex;
                    }
                }
                else if ((b & DynamicTableSizeUpdateMask) == DynamicTableSizeUpdateRepresentation)
                {
                    if (_integerDecoder.BeginDecode((byte)(b & ~DynamicTableSizeUpdateMask), DynamicTableSizeUpdatePrefix))
                    {
                        // TODO: validate that it's less than what's defined via SETTINGS
                        _dynamicTable.Resize(_integerDecoder.Value);
                    }
                    else
                    {
                        _state = State.DynamicTableSizeUpdate;
                    }
                }
                else
                {
                    // Can't happen
                    throw new HPackDecodingException($"Byte value {b} does not encode a valid header field representation.");
                }

                break;

            case State.HeaderFieldIndex:
                if (_integerDecoder.Decode(b))
                {
                    OnIndexedHeaderField(_integerDecoder.Value, handler);
                }

                break;

            case State.HeaderNameIndex:
                if (_integerDecoder.Decode(b))
                {
                    OnIndexedHeaderName(_integerDecoder.Value);
                }

                break;

            case State.HeaderNameLength:
                _huffman = (b & HuffmanMask) != 0;

                if (_integerDecoder.BeginDecode((byte)(b & ~HuffmanMask), StringLengthPrefix))
                {
                    OnStringLength(_integerDecoder.Value, nextState: State.HeaderName);
                }
                else
                {
                    _state = State.HeaderNameLengthContinue;
                }

                break;

            case State.HeaderNameLengthContinue:
                if (_integerDecoder.Decode(b))
                {
                    OnStringLength(_integerDecoder.Value, nextState: State.HeaderName);
                }

                break;

            case State.HeaderName:
                _stringOctets[_stringIndex++] = b;

                if (_stringIndex == _stringLength)
                {
                    OnString(nextState: State.HeaderValueLength);
                }

                break;

            case State.HeaderValueLength:
                _huffman = (b & HuffmanMask) != 0;

                if (_integerDecoder.BeginDecode((byte)(b & ~HuffmanMask), StringLengthPrefix))
                {
                    OnStringLength(_integerDecoder.Value, nextState: State.HeaderValue);
                    if (_integerDecoder.Value == 0)
                    {
                        ProcessHeaderValue(handler);
                    }
                }
                else
                {
                    _state = State.HeaderValueLengthContinue;
                }

                break;

            case State.HeaderValueLengthContinue:
                if (_integerDecoder.Decode(b))
                {
                    OnStringLength(_integerDecoder.Value, nextState: State.HeaderValue);
                    if (_integerDecoder.Value == 0)
                    {
                        ProcessHeaderValue(handler);
                    }
                }

                break;

            case State.HeaderValue:
                _stringOctets[_stringIndex++] = b;

                if (_stringIndex == _stringLength)
                {
                    ProcessHeaderValue(handler);
                }

                break;

            case State.DynamicTableSizeUpdate:
                if (_integerDecoder.Decode(b))
                {
                    if (_integerDecoder.Value > _maxDynamicTableSize)
                    {
                        throw new HPackDecodingException(
                                  CoreStrings.FormatHPackErrorDynamicTableSizeUpdateTooLarge(_integerDecoder.Value, _maxDynamicTableSize));
                    }

                    _dynamicTable.Resize(_integerDecoder.Value);
                    _state = State.Ready;
                }

                break;

            default:
                // Can't happen
                throw new HPackDecodingException("The HPACK decoder reached an invalid state.");
            }
        }