3. Reference Tables
Unlike HPACK, entries in the QPACK static and dynamic tables are addressed separately. The following sections describe how entries in each table are addressed.
3.1 Static Table
The static table consists of a predefined list of field lines, each of which has a fixed index over time. Its entries are defined in Appendix A.
All entries in the static table have a name and a value. However, values can be empty (that is, have a length of 0). Each entry is identified by a unique index.
Note that the QPACK static table is indexed from 0, whereas the HPACK static table is indexed from 1.
When the decoder encounters an invalid static table index in a field line representation, it MUST treat this as a connection error of type QPACK_DECOMPRESSION_FAILED. If this index is received on the encoder stream, it MUST be treated as a connection error of type QPACK_ENCODER_STREAM_ERROR.
3.2 Dynamic Table
The dynamic table consists of a list of field lines maintained in first-in, first-out order. A QPACK encoder and decoder share a dynamic table that is initially empty. The encoder adds entries to the dynamic table and sends them to the decoder via instructions on the encoder stream; see Section 4.3.
The dynamic table can contain duplicate entries (that is, entries with the same name and same value). Therefore, duplicate entries MUST NOT be treated as an error by the decoder.
A dynamic table entry can have an empty value.
3.2.1 Dynamic Table Size
The size of the dynamic table is the sum of the size of its entries.
The size of an entry is the sum of its name's length in bytes, its value's length in bytes, and 32. The size of an entry is calculated using the length of its name and value without any Huffman encoding applied.
3.2.2 Dynamic Table Capacity and Eviction
The encoder sets the capacity of the dynamic table, which serves as the upper limit on its size. The initial capacity of the dynamic table is zero. The encoder sends a Set Dynamic Table Capacity instruction (Section 4.3.1) with a non-zero capacity to begin using the dynamic table.
Before a new entry is added to the dynamic table, entries are evicted from the end of the dynamic table until the size of the dynamic table is less than or equal to (table capacity - size of new entry). The encoder MUST NOT cause a dynamic table entry to be evicted unless that entry is evictable; see Section 2.1.1. The new entry is then added to the table. It is an error if the encoder attempts to add an entry that is larger than the dynamic table capacity; the decoder MUST treat this as a connection error of type QPACK_ENCODER_STREAM_ERROR.
A new entry can reference an entry in the dynamic table that will be evicted when adding this new entry to the dynamic table. Implementations need to take care to avoid deleting the referenced name or value from the dynamic table before the new entry is evicted.
Whenever the encoder reduces the dynamic table capacity (Section 4.3.1), entries are evicted from the end of the dynamic table until the size of the dynamic table is less than or equal to the new table capacity. This mechanism can be used to completely clear entries from the dynamic table by setting a capacity of 0, which can subsequently be restored.
3.2.3 Maximum Dynamic Table Capacity
To limit the memory requirements of the decoder, the decoder limits the maximum value the encoder is permitted to set for the dynamic table capacity. In HTTP/3, this limit is determined by the value of SETTINGS_QPACK_MAX_TABLE_CAPACITY sent by the decoder; see Section 5. The encoder MUST NOT set a dynamic table capacity that exceeds this maximum, but it can choose to use a lower dynamic table capacity; see Section 4.3.1.
For clients using 0-RTT data in HTTP/3, the server's maximum table capacity is the remembered value of the setting, or zero if no value was previously sent. When the client's 0-RTT value of the setting is zero, the server MAY set it to a non-zero value in its SETTINGS frame. If the remembered value is non-zero, the server MUST send the same non-zero value in its SETTINGS frame. If it specifies any other value, or omits SETTINGS_QPACK_MAX_TABLE_CAPACITY from SETTINGS, the encoder MUST treat this as a connection error of type QPACK_DECODER_STREAM_ERROR.
For clients that are not using 0-RTT data (either because they are not attempting 0-RTT or because it was rejected) and all HTTP/3 servers, the maximum table capacity is 0 until the encoder processes a SETTINGS frame with a non-zero value of SETTINGS_QPACK_MAX_TABLE_CAPACITY.
When the maximum table capacity is zero, the encoder MUST NOT insert entries into the dynamic table, and MUST NOT send any encoder instructions on the encoder stream.
3.2.4 Absolute Indexing
Each entry possesses an absolute index that is fixed for the lifetime of that entry. The first entry inserted has an absolute index of 0; indices increase by one with each insertion.
3.2.5 Relative Indexing
Relative indices begin at zero and increase in the opposite direction from the absolute index. Determining which entry has a relative index of 0 depends on the context of the reference.
In encoder instructions (Section 4.3), a relative index of 0 refers to the most recently inserted value in the dynamic table. Note that this means the entry referenced by a given relative index will change while interpreting instructions on the encoder stream.
+-----+---------------+-------+
| n-1 | ... | d | Absolute Index
+ - - +---------------+ - - - +
| 0 | ... | n-d-1 | Relative Index
+-----+---------------+-------+
^ |
| V
Insertion Point Dropping Point
n = count of entries inserted
d = count of entries dropped
Figure 2: Example Dynamic Table Indexing - Encoder Stream
Unlike encoder instructions, relative indices in field line representations are relative to the Base at the beginning of the encoded field section; see Section 4.5.1. This ensures that references are stable even if encoded field sections and dynamic table updates are processed out of order.
In a field line representation, a relative index of 0 refers to the entry with absolute index equal to Base - 1.
Base
|
V
+-----+-----+-----+-----+-------+
| n-1 | n-2 | n-3 | ... | d | Absolute Index
+-----+-----+ - +-----+ - +
| 0 | ... | n-d-3 | Relative Index
+-----+-----+-------+
n = count of entries inserted
d = count of entries dropped
In this example, Base = n - 2
Figure 3: Example Dynamic Table Indexing - Relative Index in
Representation
3.2.6 Post-Base Indexing
Post-Base indices are used in field line representations for entries with an absolute index greater than or equal to Base, starting at 0 for the entry with absolute index equal to Base, and increasing in the same direction as the absolute index.
Post-Base indexing allows an encoder to process a field section in a single pass and include references to entries added while processing this (or other) field sections.
Base
|
V
+-----+-----+-----+-----+-----+
| n-1 | n-2 | n-3 | ... | d | Absolute Index
+-----+-----+-----+-----+-----+
| 1 | 0 | Post-Base Index
+-----+-----+
n = count of entries inserted
d = count of entries dropped
In this example, Base = n - 2
Figure 4: Example Dynamic Table Indexing - Post-Base Index in
Representation