public void Encode(string name, string value, byte[] buffer, ref int offset, ref int bytesAvailableInBuffer) { if (name == null) { throw new ArgumentNullException(nameof(name)); } var header = GetIndexedHeader(name, value); if (header != null && header.Name.Length >= _maxDynamicTableSize) { header = null; } if (header != null && header.Value.Equals(value)) { var flagOffset = offset; IntegerCodec.Encode(7, header.IndexPosition, buffer, ref offset, ref bytesAvailableInBuffer); buffer[flagOffset] += 128; return; } //Literal Header Field with Incremental Indexing — New Name if (header == null) { buffer[offset++] = 64; bytesAvailableInBuffer -= 1; _dynamicTable.Append(name, value); EncodeLiteral(name, buffer, ref offset, ref bytesAvailableInBuffer); } else { var flagOffset = offset; IntegerCodec.Encode(6, header.IndexPosition, buffer, ref offset, ref bytesAvailableInBuffer); buffer[flagOffset] += 64; } EncodeLiteral(value, buffer, ref offset, ref bytesAvailableInBuffer); }
public void Decode(byte[] buffer, ref int offset, ref int count) { while (count > 0) { _headerEventArgs.IsIndexingAllowed = true; // 6.1 Indexed Header Field Representation if ((buffer[offset] & 128) == 128) { var index = buffer[offset] & ~128; if (index == 0) { throw new DecoderException(Http2ErrorCode.ProtocolError, "HPACK, Indexed header 0 is not allowed."); } ++offset; --count; AssignIndexedHeaderToEventArgs(index); } // 6.2.1 Literal Header Field else if ((buffer[offset] & 64) == 64) { var index = buffer[offset] & ~64; ++offset; --count; // Header name is in the static or dynamic table if (index > 0) { AssignIndexedHeaderToEventArgs(index); } else { _headerEventArgs.Name = ReadStringLiteral(buffer, ref offset, ref count); } _headerEventArgs.Value = ReadStringLiteral(buffer, ref offset, ref count); // A literal header field with incremental indexing representation results in appending a // header field to the decoded header list and inserting it as a new entry into the dynamic table _dynamicTable.Append(_headerEventArgs.Name, _headerEventArgs.Value); } // 6.2.2 Literal Header Field without Indexing else if ((buffer[offset] & 240) == 0) { var index = buffer[offset] & ~240; ++offset; --count; // Header name is in the static or dynamic table if (index > 0) { AssignIndexedHeaderToEventArgs(index); } else { _headerEventArgs.Name = ReadStringLiteral(buffer, ref offset, ref count); } _headerEventArgs.Value = ReadStringLiteral(buffer, ref offset, ref count); } // 6.2.3 Literal Header Field Never Indexed else if ((buffer[offset] & 240) == 16) { var index = buffer[offset] & ~240; ++offset; --count; // Header name is in the static or dynamic table if (index > 0) { AssignIndexedHeaderToEventArgs(index); } else { _headerEventArgs.Name = ReadStringLiteral(buffer, ref offset, ref count); } _headerEventArgs.Value = ReadStringLiteral(buffer, ref offset, ref count); _headerEventArgs.IsIndexingAllowed = false; } // 6.3 Dynamic Table Size Update else if ((buffer[offset] & 224) == 32) { var maxSize = buffer[offset] & ~224; ++offset; --count; if (DynamicTableSizeReceived != null) { DynamicTableSizeReceived(this, new DynamicTableSizeReceivedEventArgs(maxSize)); } return; } if (HeaderDecoded != null) { HeaderDecoded(this, _headerEventArgs); } } }