3. Referenztabellen (Reference Tables)
Im Gegensatz zu HPACK verwendet QPACK zwei Tabellen zum Referenzieren von Feldzeilen: eine statische Tabelle und eine dynamische Tabelle.
3.1 Statische Tabelle (Static Table)
Die statische Tabelle besteht aus einer vordefinierten Liste von Feldzeilen, von denen jede einen festen und unveränderlichen Wert hat, der möglicherweise leer ist. Ihre vollständige Definition ist in Anhang A angegeben. Einträge in der statischen Tabelle ändern sich niemals.
Auf die statische Tabelle kann unter Verwendung eines statischen Index verwiesen werden.
Da die statische Tabelle in dieser Spezifikation definiert ist und der Satz von Feldzeilen relativ klein und stabil ist, kann eine effiziente Implementierung unter Verwendung perfekter Hashing oder anderer Techniken zum Auffinden von Einträgen erreicht werden.
3.2 Dynamische Tabelle (Dynamic Table)
Die dynamische Tabelle besteht aus einer geordneten Liste von Feldzeilen, die in der Reihenfolge, in der sie eingefügt wurden, nach dem Prinzip "First In First Out" (FIFO) verwaltet wird. Wie die statische Tabelle ist ein Eintrag in der dynamischen Tabelle eine Feldzeile mit einem Namen und einem Wert.
Auf die dynamische Tabelle kann unter Verwendung eines dynamischen Index verwiesen werden. Die dynamische Tabelle ist anfangs leer. Einträge werden hinzugefügt, wenn Einfügungsanweisungen auf dem Encoder-Stream empfangen werden (siehe Abschnitt 4.3).
Die dynamische Tabelle kann doppelte Feldzeilen enthalten (d. h. einen Eintrag mit einem Namen und Wert, die mit denen eines anderen Eintrags identisch sind). Daher MÜSSEN doppelte Feldzeilen NICHT als Fehler vom Decoder behandelt werden.
3.2.1 Größe der dynamischen Tabelle (Dynamic Table Size)
Die Größe der dynamischen Tabelle ist die Summe der Größe ihrer Einträge.
Die Größe eines Eintrags ist die Summe der Länge in Oktetten seines Namens (wie in Abschnitt 4.1.2 definiert), der Länge in Oktetten seines Werts (definiert in Abschnitt 4.1.2) und 32.
Die Größe des Eintrags wird wie folgt berechnet:
Größe = Länge(Name) + Länge(Wert) + 32
Die Größe eines Eintrags ist größer als die Größe der Feldzeile um einen festen Overhead. Der Overhead umfasst einen geschätzten Zuweisungs-Overhead von 32 Oktetten. Dies könnte die übergeordnete oder ungefähre Datenstruktur zum Referenzieren des Eintrags in einer Hash-Struktur, Zeichenfolgenpuffer oder andere strukturierte Daten umfassen. Eine Implementierung kann wählen, unterschiedliche Datenstrukturen zu verwenden oder einen anderen Overhead-Betrag zu haben; dies ändert nichts an der Größenberechnung, die vom Encoder und Decoder angewendet wird.
3.2.2 Kapazität der dynamischen Tabelle (Dynamic Table Capacity)
Die Kapazität der dynamischen Tabelle wird vom Decoder festgelegt und dem Encoder mitgeteilt; siehe Abschnitt 3.2.3.
Ein Encoder MUSS sicherstellen, dass die Größe der dynamischen Tabelle kleiner oder gleich der Kapazität der dynamischen Tabelle ist.
In HTTP/3 wird die Kapazität durch den Wert des SETTINGS_QPACK_MAX_TABLE_CAPACITY-Parameters (siehe Abschnitt 5) bestimmt, den der Encoder vom Decoder empfängt. Der Encoder MUSS die Kapazität auf den Wert des Parameters setzen, wenn er ihn empfängt. In HTTP/3 MUSS der Encoder den Empfang dieses Parameters als Genehmigung zur Verwendung der dynamischen Tabelle interpretieren.
Wenn ein Encoder keinen Wert für diesen Parameter erhalten hat, MUSS er den Standardwert von 0 verwenden. Eine Kapazität von 0 bedeutet, dass die dynamische Tabelle nicht verwendet wird und keine Einträge hinzugefügt werden können.
3.2.3 Entfernung aus der dynamischen Tabelle (Eviction from the Dynamic Table)
Bevor ein neuer Eintrag zur dynamischen Tabelle hinzugefügt wird, werden Einträge vom Ende der dynamischen Tabelle entfernt, bis die Größe der dynamischen Tabelle kleiner oder gleich (Kapazität der dynamischen Tabelle - neue Eintragsgröße) ist oder bis die Tabelle leer ist.
Der Encoder DARF NICHT die Entfernung eines dynamischen Tabelleneintrags verursachen, es sei denn:
-
Der Eintrag ist nicht mehr in einer Gruppe von erforderlichen Einfügungszählern vorhanden, die auf einem bekannten blockierten Stream verarbeitet werden, oder
-
Der Encoder hat eine Abschnittsbestätigung (siehe Abschnitt 4.4.1) erhalten, die auf den neuesten erforderlichen Einfügungszähler verweist, bei dem der Eintrag enthalten war.
Wenn der älteste Eintrag der dynamischen Tabelle entfernt wird, wird sein Index wiederverwendet, um auf den neuen Eintrag zu verweisen.
3.2.4 Absolute und relative Indizierung (Absolute Indexing)
Jeder Eintrag hat einen absoluten eindeutigen und unveränderlichen Index, der zugewiesen wird, wenn ein Eintrag in die dynamische Tabelle eingefügt wird; siehe Abschnitt 4.3.1. Dem ersten Eintrag, der in die dynamische Tabelle eingefügt wird, wird der absolute Index 0 zugewiesen.
Beachten Sie, dass der absolute Wert des Index für einen gegebenen Eintrag größer sein kann als die Anzahl der derzeit in der Tabelle vorhandenen Einträge. Daher kann er nicht als Array-Index in einer Implementierung verwendet werden.
3.2.5 Relative Indizierung (Relative Indexing)
Anweisungen des Encoder-Streams (siehe Abschnitt 4.3) und Feldzeilendarstellungen (siehe Abschnitt 4.5) unter Verwendung relativer Indizierung verweisen auf Einträge, indem sie den Wert eines relativen Index angeben.
Der relative Index eines Eintrags ist die Differenz zwischen dem absoluten Index des Eintrags und dem größten absoluten Index des referenzierbaren Satzes. Der größte absolute Index ist gleich dem erforderlichen Einfügungszähler minus eins oder dem Wert der Basis, abhängig vom Kontext.
Für Anweisungen des Encoder-Streams verweist der größte absolute Index auf den zuletzt eingefügten Eintrag:
größter_absoluter_Index = Einfügungszähler - 1
Für Feldzeilendarstellungen verweist der größte absolute Index auf die Basis im kodierten Feldabschnitt; siehe Abschnitt 4.5.1.
größter_absoluter_Index = Basis
Der Eintrag mit dem größten absoluten Index hat einen relativen Index von 0. Das erste eingefügte Element hat einen relativen Index von (Einfügungszähler - 1), der nur mit jeder neuen Einfügung zunimmt.
3.2.6 Post-Base-Indizierung (Post-Base Indexing)
Feldzeilendarstellungen in kodierten Feldabschnitten (siehe Abschnitt 4.5) können Post-Base-Indizierung verwenden, um auf Einträge zu verweisen, die nach dem Wert der Basis hinzugefügt wurden, beginnend bei null. Der Encoder kann entscheiden, auf kürzlich eingefügte Einträge zu verweisen, die noch nicht in der dynamischen Tabelle des Decoders verfügbar sind. Die Bestimmung des absoluten Index dieser Einträge verwendet den Wert der Basis des kodierten Feldabschnitts und den Post-Base-Index des Eintrags wie folgt:
absoluter_Index = Basis + Post_Base_Index
Ein Encoder MUSS sicherstellen, dass der auf diese Weise berechnete absolute Index auf einen Post-Base-Eintrag verweist, und ein Decoder MUSS eine Referenz auf einen Eintrag, der kein Post-Base-Eintrag ist, als Stream-Fehler vom Typ QPACK_DECOMPRESSION_FAILED behandeln.