Imports #
"fmt"
"io"
"bytes"
"errors"
"fmt"
"bytes"
"errors"
"io"
"sync"
"fmt"
"io"
"bytes"
"errors"
"fmt"
"bytes"
"errors"
"io"
"sync"
ErrInvalidHuffman is returned for errors found decoding Huffman-encoded strings.
var ErrInvalidHuffman = *ast.CallExpr
ErrStringLength is returned by Decoder.Write when the max string length (as configured by Decoder.SetMaxStringLength) would be violated.
var ErrStringLength = *ast.CallExpr
var bufPool = sync.Pool{...}
var buildRootOnce sync.Once
errNeedMore is an internal sentinel error value that means the buffer is truncated and we need to read more data before we can continue parsing.
var errNeedMore = *ast.CallExpr
var errVarintOverflow = DecodingError{...}
var huffmanCodeLen = [256]uint8{...}
var huffmanCodes = [256]uint32{...}
const indexedFalse
const indexedNever
const indexedTrue indexType = iota
const initialHeaderTableSize = 4096
var lazyRootHuffmanNode *node
var staticTable = *ast.UnaryExpr
const uint32Max = *ast.UnaryExpr
An InvalidIndexError is returned when an encoder references a table entry before the static table or after the end of the dynamic table.
type InvalidIndexError int
incomparable is a zero-width, non-comparable type. Adding it to a struct makes that struct also non-comparable, and generally doesn't add any size (as long as it's first).
type incomparable [0]func()
type indexType int
A Decoder is the decoding context for incremental processing of header blocks.
type Decoder struct {
dynTab dynamicTable
emit func(f HeaderField)
emitEnabled bool
maxStrLen int
buf []byte
saveBuf bytes.Buffer
firstField bool
}
A DecodingError is something the spec defines as a decoding error.
type DecodingError struct {
Err error
}
type Encoder struct {
dynTab dynamicTable
minSize uint32
maxSizeLimit uint32
tableSizeUpdate bool
w io.Writer
buf []byte
}
A HeaderField is a name-value pair. Both the name and value are treated as opaque sequences of octets.
type HeaderField struct {
Name string
Value string
Sensitive bool
}
type dynamicTable struct {
table headerFieldTable
size uint32
maxSize uint32
allowedMaxSize uint32
}
headerFieldTable implements a list of HeaderFields. This is used to implement the static and dynamic tables.
type headerFieldTable struct {
ents []HeaderField
evictCount uint64
byName map[string]uint64
byNameValue map[pairNameValue]uint64
}
type node struct {
_ incomparable
children *[256]*node
codeLen uint8
sym byte
}
type pairNameValue struct {
name string
value string
}
type undecodedString struct {
isHuff bool
b []byte
}
AppendHuffmanString appends s, as encoded in Huffman codes, to dst and returns the extended buffer.
func AppendHuffmanString(dst []byte, s string) []byte
Close declares that the decoding is complete and resets the Decoder to be reused again for a new header block. If there is any remaining data in the decoder's buffer, Close returns an error.
func (d *Decoder) Close() error
DecodeFull decodes an entire block. TODO: remove this method and make it incremental later? This is easier for debugging now.
func (d *Decoder) DecodeFull(p []byte) ([]HeaderField, error)
EmitEnabled reports whether calls to the emitFunc provided to NewDecoder are currently enabled. The default is true.
func (d *Decoder) EmitEnabled() bool
func (e InvalidIndexError) Error() string
func (de DecodingError) Error() string
HuffmanDecode decodes the string in v and writes the expanded result to w, returning the number of bytes written to w and the Write call's return value. At most one Write call is made.
func HuffmanDecode(w io.Writer, v []byte) (int, error)
HuffmanDecodeToString decodes the string in v.
func HuffmanDecodeToString(v []byte) (string, error)
HuffmanEncodeLength returns the number of bytes required to encode s in Huffman codes. The result is round up to byte boundary.
func HuffmanEncodeLength(s string) uint64
IsPseudo reports whether the header field is an http2 pseudo header. That is, it reports whether it starts with a colon. It is not otherwise guaranteed to be a valid pseudo header field, though.
func (hf HeaderField) IsPseudo() bool
MaxDynamicTableSize returns the current dynamic header table size.
func (e *Encoder) MaxDynamicTableSize() (v uint32)
NewDecoder returns a new decoder with the provided maximum dynamic table size. The emitFunc will be called for each valid field parsed, in the same goroutine as calls to Write, before Write returns.
func NewDecoder(maxDynamicTableSize uint32, emitFunc func(f HeaderField)) *Decoder
NewEncoder returns a new Encoder which performs HPACK encoding. An encoded data is written to w.
func NewEncoder(w io.Writer) *Encoder
SetAllowedMaxDynamicTableSize sets the upper bound that the encoded stream (via dynamic table size updates) may set the maximum size to.
func (d *Decoder) SetAllowedMaxDynamicTableSize(v uint32)
SetEmitEnabled controls whether the emitFunc provided to NewDecoder should be called. The default is true. This facility exists to let servers enforce MAX_HEADER_LIST_SIZE while still decoding and keeping in-sync with decoder state, but without doing unnecessary decompression or generating unnecessary garbage for header fields past the limit.
func (d *Decoder) SetEmitEnabled(v bool)
SetEmitFunc changes the callback used when new header fields are decoded. It must be non-nil. It does not affect EmitEnabled.
func (d *Decoder) SetEmitFunc(emitFunc func(f HeaderField))
SetMaxDynamicTableSize changes the dynamic header table size to v. The actual size is bounded by the value passed to SetMaxDynamicTableSizeLimit.
func (e *Encoder) SetMaxDynamicTableSize(v uint32)
func (d *Decoder) SetMaxDynamicTableSize(v uint32)
SetMaxDynamicTableSizeLimit changes the maximum value that can be specified in SetMaxDynamicTableSize to v. By default, it is set to 4096, which is the same size of the default dynamic header table size described in HPACK specification. If the current maximum dynamic header table size is strictly greater than v, "Header Table Size Update" will be done in the next WriteField call and the maximum dynamic header table size is truncated to v.
func (e *Encoder) SetMaxDynamicTableSizeLimit(v uint32)
SetMaxStringLength sets the maximum size of a HeaderField name or value string. If a string exceeds this length (even after any decompression), Write will return ErrStringLength. A value of 0 means unlimited and is the default from NewDecoder.
func (d *Decoder) SetMaxStringLength(n int)
Size returns the size of an entry per RFC 7541 section 4.1.
func (hf HeaderField) Size() uint32
func (hf HeaderField) String() string
func (d *Decoder) Write(p []byte) (n int, err error)
WriteField encodes f into a single Write to e's underlying Writer. This function may also produce bytes for "Header Table Size Update" if necessary. If produced, it is done before encoding f.
func (e *Encoder) WriteField(f HeaderField) error
func (dt *dynamicTable) add(f HeaderField)
addEntry adds a new entry.
func (t *headerFieldTable) addEntry(f HeaderField)
appendHpackString appends s, as encoded in "String Literal" representation, to dst and returns the extended buffer. s will be encoded in Huffman codes only when it produces strictly shorter byte string.
func appendHpackString(dst []byte, s string) []byte
appendIndexed appends index i, as encoded in "Indexed Header Field" representation, to dst and returns the extended buffer.
func appendIndexed(dst []byte, i uint64) []byte
appendIndexedName appends f and index i referring indexed name entry, as encoded in one of "Literal Header field - Indexed Name" representation variants, to dst and returns the extended buffer. If f.Sensitive is true, "Never Indexed" representation is used. If f.Sensitive is false and indexing is true, "Incremental Indexing" representation is used.
func appendIndexedName(dst []byte, f HeaderField, i uint64, indexing bool) []byte
appendNewName appends f, as encoded in one of "Literal Header field - New Name" representation variants, to dst and returns the extended buffer. If f.Sensitive is true, "Never Indexed" representation is used. If f.Sensitive is false and indexing is true, "Incremental Indexing" representation is used.
func appendNewName(dst []byte, f HeaderField, indexing bool) []byte
appendTableSize appends v, as encoded in "Header Table Size Update" representation, to dst and returns the extended buffer.
func appendTableSize(dst []byte, v uint32) []byte
appendVarInt appends i, as encoded in variable integer form using n bit prefix, to dst and returns the extended buffer. See https://httpwg.org/specs/rfc7541.html#integer.representation
func appendVarInt(dst []byte, n byte, i uint64) []byte
func (d *Decoder) at(i uint64) (hf HeaderField, ok bool)
func buildRootHuffmanNode()
func (d *Decoder) callEmit(hf HeaderField) error
func (d *Decoder) decodeString(u undecodedString) (string, error)
encodeTypeByte returns type byte. If sensitive is true, type byte for "Never Indexed" representation is returned. If sensitive is false and indexing is true, type byte for "Incremental Indexing" representation is returned. Otherwise, type byte for "Without Indexing" is returned.
func encodeTypeByte(indexing bool, sensitive bool) byte
If we're too big, evict old stuff.
func (dt *dynamicTable) evict()
evictOldest evicts the n oldest entries in the table.
func (t *headerFieldTable) evictOldest(n int)
func getRootHuffmanNode() *node
huffmanDecode decodes v to buf. If maxLen is greater than 0, attempts to write more to buf than maxLen bytes will return ErrStringLength.
func huffmanDecode(buf *bytes.Buffer, maxLen int, v []byte) error
idToIndex converts a unique id to an HPACK index. See Section 2.3.3.
func (t *headerFieldTable) idToIndex(id uint64) uint64
func (v indexType) indexed() bool
func (t *headerFieldTable) init()
len reports the number of entries in the table.
func (t *headerFieldTable) len() int
func (d *Decoder) maxTableIndex() int
func newInternalNode() *node
(same invariants and behavior as parseHeaderFieldRepr)
func (d *Decoder) parseDynamicTableSizeUpdate() error
(same invariants and behavior as parseHeaderFieldRepr)
func (d *Decoder) parseFieldIndexed() error
(same invariants and behavior as parseHeaderFieldRepr)
func (d *Decoder) parseFieldLiteral(n uint8, it indexType) error
returns errNeedMore if there isn't enough data available. any other error is fatal. consumes d.buf iff it returns nil. precondition: must be called with len(d.buf) > 0
func (d *Decoder) parseHeaderFieldRepr() error
readString reads an hpack string from p. It returns a reference to the encoded string data to permit deferring decode costs until after the caller verifies all data is present.
func (d *Decoder) readString(p []byte) (u undecodedString, remain []byte, err error)
readVarInt reads an unsigned variable length integer off the beginning of p. n is the parameter as described in https://httpwg.org/specs/rfc7541.html#rfc.section.5.1. n must always be between 1 and 8. The returned remain buffer is either a smaller suffix of p, or err != nil. The error is errNeedMore if p doesn't contain a complete integer.
func readVarInt(n byte, p []byte) (i uint64, remain []byte, err error)
search finds f in the table. If there is no match, i is 0. If both name and value match, i is the matched index and nameValueMatch becomes true. If only name matches, i points to that index and nameValueMatch becomes false. The returned index is a 1-based HPACK index. For dynamic tables, HPACK says that index 1 should be the newest entry, but t.ents[0] is the oldest entry, meaning t.ents is reversed for dynamic tables. Hence, when t is a dynamic table, the return value i actually refers to the entry t.ents[t.len()-i]. All tables are assumed to be a dynamic tables except for the global staticTable. See Section 2.3.3.
func (t *headerFieldTable) search(f HeaderField) (i uint64, nameValueMatch bool)
searchTable searches f in both stable and dynamic header tables. The static header table is searched first. Only when there is no exact match for both name and value, the dynamic header table is then searched. If there is no match, i is 0. If both name and value match, i is the matched index and nameValueMatch becomes true. If only name matches, i points to that index and nameValueMatch becomes false.
func (e *Encoder) searchTable(f HeaderField) (i uint64, nameValueMatch bool)
func (v indexType) sensitive() bool
func (dt *dynamicTable) setMaxSize(v uint32)
shouldIndex reports whether f should be indexed.
func (e *Encoder) shouldIndex(f HeaderField) bool
Generated with Arrow