/// <summary> /// Returns the index value for the given header field in the static table. Returns -1 if the /// header field is not in the static table. /// </summary> /// <param name="name"></param> /// <param name="value"></param> /// <returns></returns> internal static int GetIndexInsensitive(ICharSequence name, ICharSequence value) { int index = GetIndex(name); if ((uint)index > SharedConstants.TooBigOrNegative /* == -1*/) { return(-1); } uint uLength = (uint)Length; // Note this assumes all entries for a given header field are sequential. while ((uint)index <= uLength) { HpackHeaderField entry = GetEntry(index); if (HpackUtil.EqualsVariableTime(name, entry._name) && HpackUtil.EqualsVariableTime(value, entry._value)) { return(index); } index++; } return(-1); }
public void AppendToHeaderList(ICharSequence name, ICharSequence value) { _headersLength += HpackHeaderField.SizeOf(name, value); _exceededMaxLength |= _headersLength > _maxHeaderListSize; if (_exceededMaxLength || _validationException is object) { // We don't store the header since we've already failed validation requirements. return; } if (_validate) { try { _previousType = HpackDecoder.Validate(_streamId, name, _previousType); } catch (Http2Exception ex) { _validationException = ex; return; } } _ = _headers.Add(name, value); }
/// <summary> /// create a map CharSequenceMap header name to index value to allow quick lookup /// </summary> static CharSequenceMap <int> CreateMap() { int length = StaticTable.Length; CharSequenceMap <int> ret = new CharSequenceMap <int>(true, UnsupportedValueConverter <int> .Instance, length); // Iterate through the static table in reverse order to // save the smallest index for a given name in the map. for (int index = length; index > 0; index--) { HpackHeaderField entry = GetEntry(index); ICharSequence name = entry._name; _ = ret.Set(name, index); } return(ret); }
private ICharSequence ReadName(int index) { if ((uint)index <= (uint)HpackStaticTable.Length) { HpackHeaderField hpackHeaderField = HpackStaticTable.GetEntry(index); return(hpackHeaderField._name); } if ((uint)(index - HpackStaticTable.Length) <= (uint)_hpackDynamicTable.Length()) { HpackHeaderField hpackHeaderField = _hpackDynamicTable.GetEntry(index - HpackStaticTable.Length); return(hpackHeaderField._name); } ThrowHelper.ThrowHttp2Exception_ReadNameIllegalIndexValue(); return(null); }
void EncodeHeadersEnforceMaxHeaderListSize(int streamId, IByteBuffer output, IHttp2Headers headers, ISensitivityDetector sensitivityDetector) { long headerSize = 0; // To ensure we stay consistent with our peer check the size is valid before we potentially modify HPACK state. foreach (HeaderEntry <ICharSequence, ICharSequence> header in headers) { ICharSequence name = header.Key; ICharSequence value = header.Value; // OK to increment now and check for bounds after because this value is limited to unsigned int and will not // overflow. headerSize += HpackHeaderField.SizeOf(name, value); if (headerSize > _maxHeaderListSize) { Http2CodecUtil.HeaderListSizeExceeded(streamId, _maxHeaderListSize, false); } } EncodeHeadersIgnoreMaxHeaderListSize(@output, headers, sensitivityDetector); }
void EncodeHeadersIgnoreMaxHeaderListSize(IByteBuffer output, IHttp2Headers headers, ISensitivityDetector sensitivityDetector) { foreach (HeaderEntry <ICharSequence, ICharSequence> header in headers) { ICharSequence name = header.Key; ICharSequence value = header.Value; EncodeHeader(output, name, value, sensitivityDetector.IsSensitive(name, value), HpackHeaderField.SizeOf(name, value)); } }
public bool EqualsForTest(HpackHeaderField other) { return(HpackUtil.EqualsVariableTime(_name, other._name) && HpackUtil.EqualsVariableTime(_value, other._value)); }
public void Decode(IByteBuffer input, ISink sink) { int index = 0; int nameLength = 0; int valueLength = 0; byte state = ReadHeaderRepresentation; bool huffmanEncoded = false; ICharSequence name = null; HpackUtil.IndexType indexType = HpackUtil.IndexType.None; while (input.IsReadable()) { switch (state) { case ReadHeaderRepresentation: byte b = input.ReadByte(); if (_maxDynamicTableSizeChangeRequired && (b & 0xE0) != 0x20) { // HpackEncoder MUST signal maximum dynamic table size change ThrowHelper.ThrowHttp2Exception_MaxDynamicTableSizeChangeRequired(); } if (b > 127) { // Indexed Header Field index = b & 0x7F; switch (index) { case 0: ThrowHelper.ThrowHttp2Exception_DecodeIllegalIndexValue(); break; case 0x7F: state = ReadIndexedHeader; break; default: HpackHeaderField idxHeader = GetIndexedHeader(index); sink.AppendToHeaderList(idxHeader._name, idxHeader._value); break; } } else if ((b & 0x40) == 0x40) { // Literal Header Field with Incremental Indexing indexType = HpackUtil.IndexType.Incremental; index = b & 0x3F; switch (index) { case 0: state = ReadLiteralHeaderNameLengthPrefix; break; case 0x3F: state = ReadIndexedHeaderName; break; default: // Index was stored as the prefix name = ReadName(index); nameLength = name.Count; state = ReadLiteralHeaderValueLengthPrefix; break; } } else if ((b & 0x20) == 0x20) { // Dynamic Table Size Update index = b & 0x1F; if (index == 0x1F) { state = ReadMaxDynamicTableSize; } else { SetDynamicTableSize(index); state = ReadHeaderRepresentation; } } else { // Literal Header Field without Indexing / never Indexed indexType = ((b & 0x10) == 0x10) ? HpackUtil.IndexType.Never : HpackUtil.IndexType.None; index = b & 0x0F; switch (index) { case 0: state = ReadLiteralHeaderNameLengthPrefix; break; case 0x0F: state = ReadIndexedHeaderName; break; default: // Index was stored as the prefix name = ReadName(index); nameLength = name.Count; state = ReadLiteralHeaderValueLengthPrefix; break; } } break; case ReadMaxDynamicTableSize: SetDynamicTableSize(DecodeULE128(input, (long)index)); state = ReadHeaderRepresentation; break; case ReadIndexedHeader: HpackHeaderField indexedHeader = GetIndexedHeader(DecodeULE128(input, index)); sink.AppendToHeaderList(indexedHeader._name, indexedHeader._value); state = ReadHeaderRepresentation; break; case ReadIndexedHeaderName: // Header Name matches an entry in the Header Table name = ReadName(DecodeULE128(input, index)); nameLength = name.Count; state = ReadLiteralHeaderValueLengthPrefix; break; case ReadLiteralHeaderNameLengthPrefix: b = input.ReadByte(); huffmanEncoded = (b & 0x80) == 0x80; index = b & 0x7F; if (index == 0x7f) { state = ReadLiteralHeaderNameLength; } else { nameLength = index; state = ReadLiteralHeaderName; } break; case ReadLiteralHeaderNameLength: // Header Name is a Literal String nameLength = DecodeULE128(input, index); state = ReadLiteralHeaderName; break; case ReadLiteralHeaderName: // Wait until entire name is readable if (input.ReadableBytes < nameLength) { ThrowHelper.ThrowArgumentException_NotEnoughData(input); } name = ReadStringLiteral(input, nameLength, huffmanEncoded); state = ReadLiteralHeaderValueLengthPrefix; break; case ReadLiteralHeaderValueLengthPrefix: b = input.ReadByte(); huffmanEncoded = (b & 0x80) == 0x80; index = b & 0x7F; switch (index) { case 0x7f: state = ReadLiteralHeaderValueLength; break; case 0: InsertHeader(sink, name, AsciiString.Empty, indexType); state = ReadHeaderRepresentation; break; default: valueLength = index; state = ReadLiteralHeaderValue; break; } break; case ReadLiteralHeaderValueLength: // Header Value is a Literal String valueLength = DecodeULE128(input, index); state = ReadLiteralHeaderValue; break; case ReadLiteralHeaderValue: // Wait until entire value is readable if (input.ReadableBytes < valueLength) { ThrowHelper.ThrowArgumentException_NotEnoughData(input); } ICharSequence value = ReadStringLiteral(input, valueLength, huffmanEncoded); InsertHeader(sink, name, value, indexType); state = ReadHeaderRepresentation; break; default: ThrowHelper.ThrowException_ShouldNotReachHere(state); break; } } if (state != ReadHeaderRepresentation) { ThrowHelper.ThrowConnectionError_IncompleteHeaderBlockFragment(); } }