3. 引用表 (Reference Tables)
与 HPACK 不同, QPACK static table 和 dynamic table 中的条目分别寻址. 以下各节描述每个表中的条目如何寻址.
3.1 静态表 (Static Table)
static table 由预定义的 field lines 列表组成, 其中每个 field line 的索引在时间上保持固定. 其条目定义见 Appendix A.
static table 中的所有条目都有名称和值. 但是, 值可以为空 (即长度为 0). 每个条目由唯一索引标识.
注意, QPACK static table 从 0 开始索引, 而 HPACK static table 从 1 开始索引.
当 decoder 在 field line representation 中遇到无效 static table index 时, 它 MUST 将此视为 QPACK_DECOMPRESSION_FAILED 类型的连接错误. 如果该索引是在 encoder stream 上收到的, 则 MUST 将其视为 QPACK_ENCODER_STREAM_ERROR 类型的连接错误.
3.2 动态表 (Dynamic Table)
dynamic table 由以先进先出顺序维护的 field lines 列表组成. QPACK encoder 和 decoder 共享一个初始为空的 dynamic table. encoder 向 dynamic table 添加条目, 并通过 encoder stream 上的指令将它们发送给 decoder; 见 Section 4.3.
dynamic table 可以包含重复条目 (即具有相同名称和相同值的条目). 因此, decoder MUST NOT 将重复条目视为错误.
dynamic table 条目可以具有空值.
3.2.1 Dynamic Table 大小 (Dynamic Table Size)
dynamic table 的大小是其条目大小之和.
一个条目的大小等于其名称的字节长度, 其值的字节长度以及 32 的总和. 条目大小使用未应用任何 Huffman 编码时名称和值的长度计算.
3.2.2 Dynamic Table 容量和驱逐 (Dynamic Table Capacity and Eviction)
encoder 设置 dynamic table 的容量, 该容量作为其大小上限. dynamic table 的初始容量为零. encoder 发送容量非零的 Set Dynamic Table Capacity 指令 (Section 4.3.1), 以开始使用 dynamic table.
在向 dynamic table 添加新条目之前, 会从 dynamic table 末尾驱逐条目, 直到 dynamic table 的大小小于或等于 (table capacity - 新条目大小). 除非某个 dynamic table 条目可驱逐, encoder MUST NOT 导致该条目被驱逐; 见 Section 2.1.1. 随后将新条目添加到表中. 如果 encoder 尝试添加大于 dynamic table capacity 的条目, 这是错误; decoder MUST 将此视为 QPACK_ENCODER_STREAM_ERROR 类型的连接错误.
新条目可以引用 dynamic table 中某个条目, 而该条目会在添加此新条目时被驱逐. 实现需要注意, 在新条目被驱逐之前, 不要从 dynamic table 中删除被引用的名称或值.
每当 encoder 减小 dynamic table capacity (Section 4.3.1) 时, 都会从 dynamic table 末尾驱逐条目, 直到 dynamic table 的大小小于或等于新的 table capacity. 可以通过将容量设置为 0 来使用此机制完全清空 dynamic table 中的条目, 之后还可以恢复容量.
3.2.3 最大 Dynamic Table 容量 (Maximum Dynamic Table Capacity)
为限制 decoder 的内存需求, decoder 会限制 encoder 可为 dynamic table capacity 设置的最大值. 在 HTTP/3 中, 此限制由 decoder 发送的 SETTINGS_QPACK_MAX_TABLE_CAPACITY 值确定; 见 Section 5. encoder MUST NOT 设置超过此最大值的 dynamic table capacity, 但可以选择使用更低的 dynamic table capacity; 见 Section 4.3.1.
对于在 HTTP/3 中使用 0-RTT 数据的客户端, 服务器的 maximum table capacity 是该设置被记住的值; 如果先前未发送过值, 则为零. 当客户端该设置的 0-RTT 值为零时, 服务器 MAY 在其 SETTINGS 帧中将其设置为非零值. 如果记住的值为非零, 服务器 MUST 在其 SETTINGS 帧中发送相同的非零值. 如果它指定任何其他值, 或在 SETTINGS 中省略 SETTINGS_QPACK_MAX_TABLE_CAPACITY, encoder MUST 将此视为 QPACK_DECODER_STREAM_ERROR 类型的连接错误.
对于未使用 0-RTT 数据的客户端 (无论是因为未尝试 0-RTT, 还是因为 0-RTT 被拒绝) 以及所有 HTTP/3 服务器, 在 encoder 处理到 SETTINGS_QPACK_MAX_TABLE_CAPACITY 值非零的 SETTINGS 帧之前, maximum table capacity 为 0.
当 maximum table capacity 为零时, encoder MUST NOT 向 dynamic table 插入条目, 并且 MUST NOT 在 encoder stream 上发送任何 encoder instructions.
3.2.4 绝对索引 (Absolute Indexing)
每个条目都有一个 absolute index, 在该条目的生命周期内保持固定. 插入的第一个条目的 absolute index 为 0; 每次插入时索引递增 1.
3.2.5 相对索引 (Relative Indexing)
relative indices 从 0 开始, 并沿 absolute index 的相反方向递增. 哪个条目的 relative index 为 0 取决于引用上下文.
在 encoder instructions (Section 4.3) 中, relative index 0 指向 dynamic table 中最近插入的值. 注意, 这意味着在解释 encoder stream 上的指令时, 给定 relative index 所引用的条目会发生变化.
+-----+---------------+-------+
| 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
与 encoder instructions 不同, field line representations 中的 relative indices 相对于已编码 field section 开始处的 Base; 见 Section 4.5.1. 这确保即使已编码 field sections 和 dynamic table updates 被乱序处理, 引用仍保持稳定.
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 索引 (Post-Base Indexing)
Post-Base indices 用于 field line representations 中 absolute index 大于或等于 Base 的条目, 从 absolute index 等于 Base 的条目处以 0 开始, 并沿 absolute index 的相同方向递增.
Post-Base indexing 允许 encoder 单遍处理 field section, 并包含对处理此 field section (或其他 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