hpack

Imports

Imports #

"fmt"
"io"
"bytes"
"errors"
"fmt"
"bytes"
"errors"
"io"
"sync"

Constants & Variables

ErrInvalidHuffman var #

ErrInvalidHuffman is returned for errors found decoding Huffman-encoded strings.

var ErrInvalidHuffman = *ast.CallExpr

ErrStringLength var #

ErrStringLength is returned by Decoder.Write when the max string length (as configured by Decoder.SetMaxStringLength) would be violated.

var ErrStringLength = *ast.CallExpr

bufPool var #

var bufPool = sync.Pool{...}

buildRootOnce var #

var buildRootOnce sync.Once

errNeedMore var #

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

errVarintOverflow var #

var errVarintOverflow = DecodingError{...}

huffmanCodeLen var #

var huffmanCodeLen = [256]uint8{...}

huffmanCodes var #

var huffmanCodes = [256]uint32{...}

indexedFalse const #

const indexedFalse

indexedNever const #

const indexedNever

indexedTrue const #

const indexedTrue indexType = iota

initialHeaderTableSize const #

const initialHeaderTableSize = 4096

lazyRootHuffmanNode var #

var lazyRootHuffmanNode *node

staticTable var #

var staticTable = *ast.UnaryExpr

uint32Max const #

const uint32Max = *ast.UnaryExpr

Type Aliases

InvalidIndexError type #

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 type #

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()

indexType type #

type indexType int

Structs

Decoder struct #

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
}

DecodingError struct #

A DecodingError is something the spec defines as a decoding error.

type DecodingError struct {
Err error
}

Encoder struct #

type Encoder struct {
dynTab dynamicTable
minSize uint32
maxSizeLimit uint32
tableSizeUpdate bool
w io.Writer
buf []byte
}

HeaderField struct #

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
}

dynamicTable struct #

type dynamicTable struct {
table headerFieldTable
size uint32
maxSize uint32
allowedMaxSize uint32
}

headerFieldTable struct #

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
}

node struct #

type node struct {
_ incomparable
children *[256]*node
codeLen uint8
sym byte
}

pairNameValue struct #

type pairNameValue struct {
name string
value string
}

undecodedString struct #

type undecodedString struct {
isHuff bool
b []byte
}

Functions

AppendHuffmanString function #

AppendHuffmanString appends s, as encoded in Huffman codes, to dst and returns the extended buffer.

func AppendHuffmanString(dst []byte, s string) []byte

Close method #

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 method #

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 method #

EmitEnabled reports whether calls to the emitFunc provided to NewDecoder are currently enabled. The default is true.

func (d *Decoder) EmitEnabled() bool

Error method #

func (e InvalidIndexError) Error() string

Error method #

func (de DecodingError) Error() string

HuffmanDecode function #

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 function #

HuffmanDecodeToString decodes the string in v.

func HuffmanDecodeToString(v []byte) (string, error)

HuffmanEncodeLength function #

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 method #

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 method #

MaxDynamicTableSize returns the current dynamic header table size.

func (e *Encoder) MaxDynamicTableSize() (v uint32)

NewDecoder function #

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 function #

NewEncoder returns a new Encoder which performs HPACK encoding. An encoded data is written to w.

func NewEncoder(w io.Writer) *Encoder

SetAllowedMaxDynamicTableSize method #

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 method #

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 method #

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 method #

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)

SetMaxDynamicTableSize method #

func (d *Decoder) SetMaxDynamicTableSize(v uint32)

SetMaxDynamicTableSizeLimit method #

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 method #

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 method #

Size returns the size of an entry per RFC 7541 section 4.1.

func (hf HeaderField) Size() uint32

String method #

func (hf HeaderField) String() string

Write method #

func (d *Decoder) Write(p []byte) (n int, err error)

WriteField method #

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

add method #

func (dt *dynamicTable) add(f HeaderField)

addEntry method #

addEntry adds a new entry.

func (t *headerFieldTable) addEntry(f HeaderField)

appendHpackString function #

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 function #

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 function #

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 function #

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 function #

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 function #

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

at method #

func (d *Decoder) at(i uint64) (hf HeaderField, ok bool)

buildRootHuffmanNode function #

func buildRootHuffmanNode()

callEmit method #

func (d *Decoder) callEmit(hf HeaderField) error

decodeString method #

func (d *Decoder) decodeString(u undecodedString) (string, error)

encodeTypeByte function #

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

evict method #

If we're too big, evict old stuff.

func (dt *dynamicTable) evict()

evictOldest method #

evictOldest evicts the n oldest entries in the table.

func (t *headerFieldTable) evictOldest(n int)

getRootHuffmanNode function #

func getRootHuffmanNode() *node

huffmanDecode function #

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 method #

idToIndex converts a unique id to an HPACK index. See Section 2.3.3.

func (t *headerFieldTable) idToIndex(id uint64) uint64

indexed method #

func (v indexType) indexed() bool

init method #

func (t *headerFieldTable) init()

len method #

len reports the number of entries in the table.

func (t *headerFieldTable) len() int

maxTableIndex method #

func (d *Decoder) maxTableIndex() int

newInternalNode function #

func newInternalNode() *node

parseDynamicTableSizeUpdate method #

(same invariants and behavior as parseHeaderFieldRepr)

func (d *Decoder) parseDynamicTableSizeUpdate() error

parseFieldIndexed method #

(same invariants and behavior as parseHeaderFieldRepr)

func (d *Decoder) parseFieldIndexed() error

parseFieldLiteral method #

(same invariants and behavior as parseHeaderFieldRepr)

func (d *Decoder) parseFieldLiteral(n uint8, it indexType) error

parseHeaderFieldRepr method #

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 method #

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 function #

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)

searchTable method #

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)

sensitive method #

func (v indexType) sensitive() bool

setMaxSize method #

func (dt *dynamicTable) setMaxSize(v uint32)

shouldIndex method #

shouldIndex reports whether f should be indexed.

func (e *Encoder) shouldIndex(f HeaderField) bool

Generated with Arrow