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); } }
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); } else { _state = State.HeaderValueLengthContinue; } break; case State.HeaderValueLengthContinue: if (_integerDecoder.Decode(b)) { OnStringLength(_integerDecoder.Value, nextState: State.HeaderValue); } break; case State.HeaderValue: _stringOctets[_stringIndex++] = b; if (_stringIndex == _stringLength) { 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); } } 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."); } }