| draft-ietf-quic-qpack-03.txt | draft-ietf-quic-qpack-04.txt | |||
|---|---|---|---|---|
| QUIC C. Krasic | QUIC C. Krasic | |||
| Internet-Draft Netflix | Internet-Draft Netflix | |||
| Intended status: Standards Track M. Bishop | Intended status: Standards Track M. Bishop | |||
| Expires: April 6, 2019 Akamai Technologies | Expires: June 7, 2019 Akamai Technologies | |||
| A. Frindell, Ed. | A. Frindell, Ed. | |||
| October 03, 2018 | December 04, 2018 | |||
| QPACK: Header Compression for HTTP over QUIC | QPACK: Header Compression for HTTP over QUIC | |||
| draft-ietf-quic-qpack-03 | draft-ietf-quic-qpack-04 | |||
| Abstract | Abstract | |||
| This specification defines QPACK, a compression format for | This specification defines QPACK, a compression format for | |||
| efficiently representing HTTP header fields, to be used in HTTP/QUIC. | efficiently representing HTTP header fields, to be used in HTTP/3. | |||
| This is a variation of HPACK header compression that seeks to reduce | This is a variation of HPACK header compression that seeks to reduce | |||
| head-of-line blocking. | head-of-line blocking. | |||
| Note to Readers | Note to Readers | |||
| Discussion of this draft takes place on the QUIC working group | Discussion of this draft takes place on the QUIC working group | |||
| mailing list (quic@ietf.org), which is archived at | mailing list (quic@ietf.org), which is archived at | |||
| https://mailarchive.ietf.org/arch/search/?email_list=quic [1]. | https://mailarchive.ietf.org/arch/search/?email_list=quic [1]. | |||
| Working Group information can be found at https://github.com/quicwg | Working Group information can be found at https://github.com/quicwg | |||
| skipping to change at page 1, line 46 ¶ | skipping to change at page 1, line 46 ¶ | |||
| Internet-Drafts are working documents of the Internet Engineering | Internet-Drafts are working documents of the Internet Engineering | |||
| Task Force (IETF). Note that other groups may also distribute | Task Force (IETF). Note that other groups may also distribute | |||
| working documents as Internet-Drafts. The list of current Internet- | working documents as Internet-Drafts. The list of current Internet- | |||
| Drafts is at https://datatracker.ietf.org/drafts/current/. | Drafts is at https://datatracker.ietf.org/drafts/current/. | |||
| Internet-Drafts are draft documents valid for a maximum of six months | Internet-Drafts are draft documents valid for a maximum of six months | |||
| and may be updated, replaced, or obsoleted by other documents at any | and may be updated, replaced, or obsoleted by other documents at any | |||
| time. It is inappropriate to use Internet-Drafts as reference | time. It is inappropriate to use Internet-Drafts as reference | |||
| material or to cite them other than as "work in progress." | material or to cite them other than as "work in progress." | |||
| This Internet-Draft will expire on April 6, 2019. | This Internet-Draft will expire on June 7, 2019. | |||
| Copyright Notice | Copyright Notice | |||
| Copyright (c) 2018 IETF Trust and the persons identified as the | Copyright (c) 2018 IETF Trust and the persons identified as the | |||
| document authors. All rights reserved. | document authors. All rights reserved. | |||
| This document is subject to BCP 78 and the IETF Trust's Legal | This document is subject to BCP 78 and the IETF Trust's Legal | |||
| Provisions Relating to IETF Documents | Provisions Relating to IETF Documents | |||
| (https://trustee.ietf.org/license-info) in effect on the date of | (https://trustee.ietf.org/license-info) in effect on the date of | |||
| publication of this document. Please review these documents | publication of this document. Please review these documents | |||
| carefully, as they describe your rights and restrictions with respect | carefully, as they describe your rights and restrictions with respect | |||
| to this document. Code Components extracted from this document must | to this document. Code Components extracted from this document must | |||
| include Simplified BSD License text as described in Section 4.e of | include Simplified BSD License text as described in Section 4.e of | |||
| the Trust Legal Provisions and are provided without warranty as | the Trust Legal Provisions and are provided without warranty as | |||
| described in the Simplified BSD License. | described in the Simplified BSD License. | |||
| Table of Contents | Table of Contents | |||
| 1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . 3 | 1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . 3 | |||
| 2. Header Tables . . . . . . . . . . . . . . . . . . . . . . . . 4 | 1.1. Conventions and Definitions . . . . . . . . . . . . . . . 4 | |||
| 2.1. Static Table . . . . . . . . . . . . . . . . . . . . . . 4 | 1.2. Notational Conventions . . . . . . . . . . . . . . . . . 4 | |||
| 2.2. Dynamic Table . . . . . . . . . . . . . . . . . . . . . . 4 | 2. Compression Process Overview . . . . . . . . . . . . . . . . 5 | |||
| 2.2.1. Maximum Table Size . . . . . . . . . . . . . . . . . 5 | 2.1. Encoder . . . . . . . . . . . . . . . . . . . . . . . . . 5 | |||
| 2.2.2. Calculating Table Size . . . . . . . . . . . . . . . 6 | 2.1.1. Reference Tracking . . . . . . . . . . . . . . . . . 6 | |||
| 2.2.3. Absolute Indexing . . . . . . . . . . . . . . . . . . 6 | 2.1.2. Blocked Dynamic Table Insertions . . . . . . . . . . 6 | |||
| 2.2.4. Relative Indexing . . . . . . . . . . . . . . . . . . 6 | 2.1.3. Avoiding Head-of-Line Blocking . . . . . . . . . . . 7 | |||
| 2.2.5. Post-Base Indexing . . . . . . . . . . . . . . . . . 7 | 2.1.4. Largest Known Received . . . . . . . . . . . . . . . 7 | |||
| 2.3. Avoiding Head-of-Line Blocking in HTTP/QUIC . . . . . . . 8 | 2.2. Decoder . . . . . . . . . . . . . . . . . . . . . . . . . 8 | |||
| 2.3.1. State Synchronization . . . . . . . . . . . . . . . . 9 | 2.2.1. State Synchronization . . . . . . . . . . . . . . . . 8 | |||
| 3. Conventions and Definitions . . . . . . . . . . . . . . . . . 10 | 2.2.2. Blocked Decoding . . . . . . . . . . . . . . . . . . 9 | |||
| 3.1. Notational Conventions . . . . . . . . . . . . . . . . . 10 | 3. Header Tables . . . . . . . . . . . . . . . . . . . . . . . . 9 | |||
| 4. Configuration . . . . . . . . . . . . . . . . . . . . . . . . 10 | 3.1. Static Table . . . . . . . . . . . . . . . . . . . . . . 9 | |||
| 5. Wire Format . . . . . . . . . . . . . . . . . . . . . . . . . 11 | 3.2. Dynamic Table . . . . . . . . . . . . . . . . . . . . . . 9 | |||
| 5.1. Primitives . . . . . . . . . . . . . . . . . . . . . . . 11 | 3.2.1. Maximum Table Size . . . . . . . . . . . . . . . . . 10 | |||
| 5.1.1. Prefixed Integers . . . . . . . . . . . . . . . . . . 11 | 3.2.2. Calculating Table Size . . . . . . . . . . . . . . . 10 | |||
| 5.1.2. String Literals . . . . . . . . . . . . . . . . . . . 11 | 3.2.3. Absolute Indexing . . . . . . . . . . . . . . . . . . 11 | |||
| 5.2. QPACK Encoder Stream . . . . . . . . . . . . . . . . . . 12 | 3.2.4. Relative Indexing . . . . . . . . . . . . . . . . . . 11 | |||
| 5.2.1. Insert With Name Reference . . . . . . . . . . . . . 12 | 3.2.5. Post-Base Indexing . . . . . . . . . . . . . . . . . 12 | |||
| 5.2.2. Insert Without Name Reference . . . . . . . . . . . . 13 | 3.2.6. Invalid References . . . . . . . . . . . . . . . . . 12 | |||
| 5.2.3. Duplicate . . . . . . . . . . . . . . . . . . . . . . 13 | 4. Wire Format . . . . . . . . . . . . . . . . . . . . . . . . . 13 | |||
| 5.2.4. Dynamic Table Size Update . . . . . . . . . . . . . . 14 | 4.1. Primitives . . . . . . . . . . . . . . . . . . . . . . . 13 | |||
| 5.3. QPACK Decoder Stream . . . . . . . . . . . . . . . . . . 14 | 4.1.1. Prefixed Integers . . . . . . . . . . . . . . . . . . 13 | |||
| 5.3.1. Table State Synchronize . . . . . . . . . . . . . . . 14 | 4.1.2. String Literals . . . . . . . . . . . . . . . . . . . 13 | |||
| 5.3.2. Header Acknowledgement . . . . . . . . . . . . . . . 15 | 4.2. Stream Types . . . . . . . . . . . . . . . . . . . . . . 13 | |||
| 5.3.3. Stream Cancellation . . . . . . . . . . . . . . . . . 16 | 4.3. Encoder Stream . . . . . . . . . . . . . . . . . . . . . 14 | |||
| 5.4. Request and Push Streams . . . . . . . . . . . . . . . . 17 | 4.3.1. Insert With Name Reference . . . . . . . . . . . . . 14 | |||
| 5.4.1. Header Data Prefix . . . . . . . . . . . . . . . . . 17 | 4.3.2. Insert Without Name Reference . . . . . . . . . . . . 15 | |||
| 5.4.2. Instructions . . . . . . . . . . . . . . . . . . . . 18 | 4.3.3. Duplicate . . . . . . . . . . . . . . . . . . . . . . 15 | |||
| 6. Error Handling . . . . . . . . . . . . . . . . . . . . . . . 21 | 4.3.4. Dynamic Table Size Update . . . . . . . . . . . . . . 16 | |||
| 7. Encoding Strategies . . . . . . . . . . . . . . . . . . . . . 22 | ||||
| 7.1. Single Pass Encoding . . . . . . . . . . . . . . . . . . 22 | 4.4. Decoder Stream . . . . . . . . . . . . . . . . . . . . . 16 | |||
| 7.2. Preventing Eviction Races . . . . . . . . . . . . . . . . 22 | 4.4.1. Table State Synchronize . . . . . . . . . . . . . . . 16 | |||
| 7.3. Reference Tracking . . . . . . . . . . . . . . . . . . . 22 | 4.4.2. Header Acknowledgement . . . . . . . . . . . . . . . 17 | |||
| 7.3.1. Blocked Dynamic Table Insertions . . . . . . . . . . 22 | 4.4.3. Stream Cancellation . . . . . . . . . . . . . . . . . 18 | |||
| 7.3.2. Blocked Decoding . . . . . . . . . . . . . . . . . . 23 | 4.5. Request and Push Streams . . . . . . . . . . . . . . . . 18 | |||
| 7.4. Speculative table updates . . . . . . . . . . . . . . . . 23 | 4.5.1. Header Data Prefix . . . . . . . . . . . . . . . . . 18 | |||
| 7.5. Sample One Pass Encoding Algorithm . . . . . . . . . . . 24 | 4.5.2. Indexed Header Field . . . . . . . . . . . . . . . . 20 | |||
| 8. Security Considerations . . . . . . . . . . . . . . . . . . . 26 | 4.5.3. Indexed Header Field With Post-Base Index . . . . . . 21 | |||
| 9. IANA Considerations . . . . . . . . . . . . . . . . . . . . . 26 | 4.5.4. Literal Header Field With Name Reference . . . . . . 21 | |||
| 9.1. Settings Registration . . . . . . . . . . . . . . . . . . 26 | 4.5.5. Literal Header Field With Post-Base Name Reference . 22 | |||
| 9.2. Stream Type Registration . . . . . . . . . . . . . . . . 26 | 4.5.6. Literal Header Field Without Name Reference . . . . . 22 | |||
| 9.3. Error Code Registration . . . . . . . . . . . . . . . . . 26 | 5. Configuration . . . . . . . . . . . . . . . . . . . . . . . . 23 | |||
| 10. References . . . . . . . . . . . . . . . . . . . . . . . . . 27 | 6. Error Handling . . . . . . . . . . . . . . . . . . . . . . . 23 | |||
| 10.1. Normative References . . . . . . . . . . . . . . . . . . 27 | 7. Security Considerations . . . . . . . . . . . . . . . . . . . 24 | |||
| 10.2. Informative References . . . . . . . . . . . . . . . . . 28 | 8. IANA Considerations . . . . . . . . . . . . . . . . . . . . . 24 | |||
| 10.3. URIs . . . . . . . . . . . . . . . . . . . . . . . . . . 28 | 8.1. Settings Registration . . . . . . . . . . . . . . . . . . 24 | |||
| Appendix A. Static Table . . . . . . . . . . . . . . . . . . . . 28 | 8.2. Stream Type Registration . . . . . . . . . . . . . . . . 24 | |||
| Appendix B. Change Log . . . . . . . . . . . . . . . . . . . . . 33 | 8.3. Error Code Registration . . . . . . . . . . . . . . . . . 24 | |||
| B.1. Since draft-ietf-quic-qpack-02 . . . . . . . . . . . . . 33 | 9. References . . . . . . . . . . . . . . . . . . . . . . . . . 25 | |||
| B.2. Since draft-ietf-quic-qpack-01 . . . . . . . . . . . . . 33 | 9.1. Normative References . . . . . . . . . . . . . . . . . . 25 | |||
| B.3. Since draft-ietf-quic-qpack-00 . . . . . . . . . . . . . 33 | 9.2. Informative References . . . . . . . . . . . . . . . . . 26 | |||
| B.4. Since draft-ietf-quic-qcram-00 . . . . . . . . . . . . . 34 | 9.3. URIs . . . . . . . . . . . . . . . . . . . . . . . . . . 26 | |||
| Appendix A. Static Table . . . . . . . . . . . . . . . . . . . . 26 | ||||
| Appendix B. Sample One Pass Encoding Algorithm . . . . . . . . . 31 | ||||
| Appendix C. Change Log . . . . . . . . . . . . . . . . . . . . . 33 | ||||
| C.1. Since draft-ietf-quic-qpack-03 . . . . . . . . . . . . . 33 | ||||
| C.2. Since draft-ietf-quic-qpack-02 . . . . . . . . . . . . . 33 | ||||
| C.3. Since draft-ietf-quic-qpack-01 . . . . . . . . . . . . . 33 | ||||
| C.4. Since draft-ietf-quic-qpack-00 . . . . . . . . . . . . . 33 | ||||
| C.5. Since draft-ietf-quic-qcram-00 . . . . . . . . . . . . . 34 | ||||
| Acknowledgments . . . . . . . . . . . . . . . . . . . . . . . . . 34 | Acknowledgments . . . . . . . . . . . . . . . . . . . . . . . . . 34 | |||
| Authors' Addresses . . . . . . . . . . . . . . . . . . . . . . . 34 | Authors' Addresses . . . . . . . . . . . . . . . . . . . . . . . 34 | |||
| 1. Introduction | 1. Introduction | |||
| The QUIC transport protocol was designed from the outset to support | The QUIC transport protocol was designed from the outset to support | |||
| HTTP semantics, and its design subsumes many of the features of | HTTP semantics, and its design subsumes many of the features of | |||
| HTTP/2. HTTP/2 uses HPACK ([RFC7541]) for header compression, but | HTTP/2. HTTP/2 uses HPACK ([RFC7541]) for header compression, but | |||
| QUIC's stream multiplexing comes into some conflict with HPACK. A | QUIC's stream multiplexing comes into some conflict with HPACK. A | |||
| key goal of the design of QUIC is to improve stream multiplexing | key goal of the design of QUIC is to improve stream multiplexing | |||
| relative to HTTP/2 by reducing head-of-line blocking. If HPACK were | relative to HTTP/2 by reducing head-of-line blocking. If HPACK were | |||
| used for HTTP/QUIC, it would induce head-of-line blocking due to | used for HTTP/3, it would induce head-of-line blocking due to built- | |||
| built-in assumptions of a total ordering across frames on all | in assumptions of a total ordering across frames on all streams. | |||
| streams. | ||||
| QUIC is described in [QUIC-TRANSPORT]. The HTTP/QUIC mapping is | QUIC is described in [QUIC-TRANSPORT]. The HTTP/3 mapping is | |||
| described in [QUIC-HTTP]. For a full description of HTTP/2, see | described in [HTTP3]. For a full description of HTTP/2, see | |||
| [RFC7540]. The description of HPACK is [RFC7541]. | [RFC7540]. The description of HPACK is [RFC7541]. | |||
| QPACK reuses core concepts from HPACK, but is redesigned to allow | QPACK reuses core concepts from HPACK, but is redesigned to allow | |||
| correctness in the presence of out-of-order delivery, with | correctness in the presence of out-of-order delivery, with | |||
| flexibility for implementations to balance between resilience against | flexibility for implementations to balance between resilience against | |||
| head-of-line blocking and optimal compression ratio. The design | head-of-line blocking and optimal compression ratio. The design | |||
| goals are to closely approach the compression ratio of HPACK with | goals are to closely approach the compression ratio of HPACK with | |||
| substantially less head-of-line blocking under the same loss | substantially less head-of-line blocking under the same loss | |||
| conditions. | conditions. | |||
| QPACK preserves the ordering of header fields within each header | 1.1. Conventions and Definitions | |||
| list. An encoder MUST emit header field representations in the order | ||||
| they appear in the input header list. A decoder MUST must emit | ||||
| header fields in the order their representations appear in the input | ||||
| header block. | ||||
| 2. Header Tables | The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", | |||
| "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and | ||||
| "OPTIONAL" in this document are to be interpreted as described in BCP | ||||
| 14 [RFC2119] [RFC8174] when, and only when, they appear in all | ||||
| capitals, as shown here. | ||||
| Definitions of terms that are used in this document: | ||||
| Header field: A name-value pair sent as part of an HTTP message. | ||||
| Header list: An ordered collection of header fields associated with | ||||
| an HTTP message. A header list can contain multiple header fields | ||||
| with the same name. It can also contain duplicate header fields. | ||||
| Header block: The compressed representation of a header list. | ||||
| Encoder: An implementation which transforms a header list into a | ||||
| header block. | ||||
| Decoder: An implementation which transforms a header block into a | ||||
| header list. | ||||
| Absolute Index: A unique index for each entry in the dynamic table. | ||||
| Base Index: An absolute index in a header block from which relative | ||||
| indices are made. | ||||
| Largest Reference: The largest absolute index of an entry referenced | ||||
| in a header block. | ||||
| QPACK is a name, not an acronym. | ||||
| 1.2. Notational Conventions | ||||
| Diagrams use the format described in Section 3.1 of [RFC2360], with | ||||
| the following additional conventions: | ||||
| x (A) Indicates that x is A bits long | ||||
| x (A+) Indicates that x uses the prefixed integer encoding defined | ||||
| in Section 5.1 of [RFC7541], beginning with an A-bit prefix. | ||||
| x ... Indicates that x is variable-length and extends to the end of | ||||
| the region. | ||||
| 2. Compression Process Overview | ||||
| Like HPACK, QPACK uses two tables for associating header fields to | Like HPACK, QPACK uses two tables for associating header fields to | |||
| indices. The static table (see Section 2.1) is predefined and | indices. The static table (see Section 3.1) is predefined and | |||
| contains common header fields (some of them with an empty value). | contains common header fields (some of them with an empty value). | |||
| The dynamic table (see Section 2.2) is built up over the course of | The dynamic table (see Section 3.2) is built up over the course of | |||
| the connection and can be used by the encoder to index header fields | the connection and can be used by the encoder to index header fields | |||
| repeated in the encoded header lists. | in the encoded header lists. | |||
| QPACK instructions appear in three different types of streams: | ||||
| o The encoder uses a unidirectional stream to modify the state of | ||||
| the dynamic table without emitting header fields associated with | ||||
| any particular request. | ||||
| o HEADERS and PUSH_PROMISE frames on request and push streams | ||||
| reference the table state without modifying it. | ||||
| o The decoder sends feedback to the encoder on a unidirectional | ||||
| stream. This feedback enables the encoder to manage dynamic table | ||||
| state. | ||||
| 2.1. Encoder | ||||
| An encoder compresses a header list by emitting either an indexed or | ||||
| a literal representation for each header field in the list. | ||||
| References to the static table and literal representations do not | ||||
| require any dynamic state and never risk head-of-line blocking. | ||||
| References to the dynamic table risk head-of-line blocking if the | ||||
| encoder has not received an acknowledgement indicating the entry is | ||||
| available at the decoder. | ||||
| An encoder MAY insert any entry in the dynamic table it chooses; it | ||||
| is not limited to header fields it is compressing. | ||||
| QPACK preserves the ordering of header fields within each header | ||||
| list. An encoder MUST emit header field representations in the order | ||||
| they appear in the input header list. | ||||
| QPACK is designed to contain the more complex state tracking to the | ||||
| encoder, while the decoder is relatively simple. | ||||
| 2.1.1. Reference Tracking | ||||
| An encoder MUST ensure that a header block which references a dynamic | ||||
| table entry is not received by the decoder after the referenced entry | ||||
| has been evicted. Hence the encoder needs to track information about | ||||
| each compressed header block that references the dynamic table until | ||||
| that header block is acknowledged by the decoder. | ||||
| 2.1.2. Blocked Dynamic Table Insertions | ||||
| An encoder MUST NOT insert an entry into the dynamic table (or | ||||
| duplicate an existing entry) if doing so would evict an entry with | ||||
| unacknowledged references. For header blocks that might rely on the | ||||
| newly added entry, the encoder can use a literal representation and | ||||
| maybe insert the entry later. | ||||
| To ensure that the encoder is not prevented from adding new entries, | ||||
| the encoder can avoid referencing entries that are close to eviction. | ||||
| Rather than reference such an entry, the encoder can emit a Duplicate | ||||
| instruction (see Section 4.3.3), and reference the duplicate instead. | ||||
| Determining which entries are too close to eviction to reference is | ||||
| an encoder preference. One heuristic is to target a fixed amount of | ||||
| available space in the dynamic table: either unused space or space | ||||
| that can be reclaimed by evicting unreferenced entries. To achieve | ||||
| this, the encoder can maintain a draining index, which is the | ||||
| smallest absolute index in the dynamic table that it will emit a | ||||
| reference for. As new entries are inserted, the encoder increases | ||||
| the draining index to maintain the section of the table that it will | ||||
| not reference. If the encoder does not create new references to | ||||
| entries with an absolute index lower than the draining index, the | ||||
| number of unacknowledged references to those entries will eventually | ||||
| become zero, allowing them to be evicted. | ||||
| +----------+---------------------------------+--------+ | ||||
| | Draining | Referenceable | Unused | | ||||
| | Entries | Entries | Space | | ||||
| +----------+---------------------------------+--------+ | ||||
| ^ ^ ^ | ||||
| | | | | ||||
| Dropping Draining Index Base Index / | ||||
| Point Insertion Point | ||||
| Figure 1: Draining Dynamic Table Entries | ||||
| 2.1.3. Avoiding Head-of-Line Blocking | ||||
| Because QUIC does not guarantee order between data on different | ||||
| streams, a header block might reference an entry in the dynamic table | ||||
| that has not yet been received. | ||||
| Each header block contains a Largest Reference (Section 4.5.1) which | ||||
| identifies the table state necessary for decoding. If the greatest | ||||
| absolute index in the dynamic table is less than the value of the | ||||
| Largest Reference, the stream is considered "blocked." While | ||||
| blocked, header field data SHOULD remain in the blocked stream's flow | ||||
| control window. When the Largest Reference is zero, the frame | ||||
| contains no references to the dynamic table and can always be | ||||
| processed immediately. A stream becomes unblocked when the greatest | ||||
| absolute index in the dynamic table becomes greater than or equal to | ||||
| the Largest Reference for all header blocks the decoder has started | ||||
| reading from the stream. If the decoder encounters a header block | ||||
| where the actual largest reference is not equal to the Largest | ||||
| Reference declared in the prefix, it MAY treat this as a stream error | ||||
| of type HTTP_QPACK_DECOMPRESSION_FAILED. | ||||
| The SETTINGS_QPACK_BLOCKED_STREAMS setting (see Section 5) specifies | ||||
| an upper bound on the number of streams which can be blocked. An | ||||
| encoder MUST limit the number of streams which could become blocked | ||||
| to the value of SETTINGS_QPACK_BLOCKED_STREAMS at all times. Note | ||||
| that the decoder might not actually become blocked on every stream | ||||
| which risks becoming blocked. If the decoder encounters more blocked | ||||
| streams than it promised to support, it MUST treat this as a stream | ||||
| error of type HTTP_QPACK_DECOMPRESSION_FAILED. | ||||
| An encoder can decide whether to risk having a stream become blocked. | ||||
| If permitted by the value of SETTINGS_QPACK_BLOCKED_STREAMS, | ||||
| compression efficiency can often be improved by referencing dynamic | ||||
| table entries that are still in transit, but if there is loss or | ||||
| reordering the stream can become blocked at the decoder. An encoder | ||||
| avoids the risk of blocking by only referencing dynamic table entries | ||||
| which have been acknowledged, but this could mean using literals. | ||||
| Since literals make the header block larger, this can result in the | ||||
| encoder becoming blocked on congestion or flow control limits. | ||||
| 2.1.4. Largest Known Received | ||||
| In order to identify which dynamic table entries can be safely used | ||||
| without a stream becoming blocked, the encoder tracks the absolute | ||||
| index of the decoder's Largest Known Received entry. | ||||
| When blocking references are permitted, the encoder uses header block | ||||
| acknowledgement to identify the Largest Known Received index, as | ||||
| described in Section 4.4.2. | ||||
| To acknowledge dynamic table entries which are not referenced by | ||||
| header blocks, for example because the encoder or the decoder have | ||||
| chosen not to risk blocked streams, the decoder sends a Table State | ||||
| Synchronize instruction (see Section 4.4.1). | ||||
| 2.2. Decoder | ||||
| As in HPACK, the decoder processes header blocks and emits the | ||||
| corresponding header lists. It also processes dynamic table | ||||
| modifications from instructions on the encoder stream. | ||||
| The decoder MUST emit header fields in the order their | ||||
| representations appear in the input header block. | ||||
| 2.2.1. State Synchronization | ||||
| The decoder stream (Section 4.4) signals key events at the decoder | ||||
| that permit the encoder to track the decoder's state. These events | ||||
| are: | ||||
| o Complete processing of a header block | ||||
| o Abandonment of a stream which might have remaining header blocks | ||||
| o Receipt of new dynamic table entries | ||||
| Knowledge that a header block with references to the dynamic table | ||||
| has been processed permits the encoder to evict entries to which no | ||||
| unacknowledged references remain, regardless of whether those | ||||
| references were potentially blocking (see Section 2.1.2). When a | ||||
| stream is reset or abandoned, the indication that these header blocks | ||||
| will never be processed serves a similar function; see Section 4.4.3. | ||||
| The decoder chooses when to emit Table State Synchronize instructions | ||||
| (see Section 4.4.1). Emitting an instruction after adding each new | ||||
| dynamic table entry will provide the most timely feedback to the | ||||
| encoder, but could be redundant with other decoder feedback. By | ||||
| delaying a Table State Synchronize instruction, the decoder might be | ||||
| able to coalesce multiple Table State Synchronize instructions, or | ||||
| replace them entirely with Header Acknowledgements (see | ||||
| Section 4.4.2). However, delaying too long may lead to compression | ||||
| inefficiencies if the encoder waits for an entry to be acknowledged | ||||
| before using it. | ||||
| 2.2.2. Blocked Decoding | ||||
| To track blocked streams, the necessary Largest Reference value for | ||||
| each stream can be used. Whenever the decoder processes a table | ||||
| update, it can begin decoding any blocked streams that now have their | ||||
| dependencies satisfied. | ||||
| 3. Header Tables | ||||
| Unlike in HPACK, entries in the QPACK static and dynamic tables are | Unlike in HPACK, entries in the QPACK static and dynamic tables are | |||
| addressed separately. The following sections describe how entries in | addressed separately. The following sections describe how entries in | |||
| each table are addressed. | each table are addressed. | |||
| 2.1. Static Table | 3.1. Static Table | |||
| The static table consists of a predefined static list of header | The static table consists of a predefined static list of header | |||
| fields, each of which has a fixed index over time. Its entries are | fields, each of which has a fixed index over time. Its entries are | |||
| defined in Appendix A. | defined in Appendix A. | |||
| A decoder that encounters an invalid static table index on a request | Note the QPACK static table is indexed from 0, whereas the HPACK | |||
| stream or push stream MUST treat this as a stream error of type | static table is indexed from 1. | |||
| "HTTP_QPACK_DECOMPRESSION_FAILED". If this index is received on the | ||||
| encoder stream, this MUST be treated as a connection error of type | ||||
| "HTTP_QPACK_ENCODER_STREAM_ERROR". | ||||
| 2.2. Dynamic Table | When the decoder encounters an invalid static table index on a | |||
| request stream or push stream it MUST treat this as a stream error of | ||||
| type "HTTP_QPACK_DECOMPRESSION_FAILED". If this index is received on | ||||
| the encoder stream, this MUST be treated as a connection error of | ||||
| type "HTTP_QPACK_ENCODER_STREAM_ERROR". | ||||
| 3.2. Dynamic Table | ||||
| The dynamic table consists of a list of header fields maintained in | The dynamic table consists of a list of header fields maintained in | |||
| first-in, first-out order. The dynamic table is initially empty. | first-in, first-out order. The dynamic table is initially empty. | |||
| Entries are added by instructions on the encoder stream (see | Entries are added by instructions on the encoder stream (see | |||
| Section 5.2). | Section 4.3). | |||
| The maximum size of the dynamic table can be modified by the encoder, | The maximum size of the dynamic table can be modified by the encoder, | |||
| subject to a decoder-controlled limit (see Section 4 and | subject to a decoder-controlled limit (see Section 5 and | |||
| Section 5.2.4). The initial maximum size is determined by the | Section 4.3.4). The initial maximum size is determined by the | |||
| corresponding setting when HTTP requests or responses are first | corresponding setting when HTTP requests or responses are first | |||
| permitted to be sent. For clients using 0-RTT data in HTTP/QUIC, the | permitted to be sent. For clients using 0-RTT data in HTTP/3, the | |||
| table size is the remembered value of the setting, even if the server | table size is the remembered value of the setting, even if the server | |||
| later specifies a larger maximum in its SETTINGS frame. For HTTP/ | later specifies a larger maximum in its SETTINGS frame. For HTTP/3 | |||
| QUIC servers and HTTP/QUIC clients when 0-RTT is not attempted or is | servers and HTTP/3 clients when 0-RTT is not attempted or is | |||
| rejected, the initial maximum table size is the value of the setting | rejected, the initial maximum table size is the value of the setting | |||
| in the peer's SETTINGS frame. | in the peer's SETTINGS frame. | |||
| Before a new entry is added to the dynamic table, entries are evicted | 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 | from the end of the dynamic table until the size of the dynamic table | |||
| is less than or equal to (maximum size - new entry size) or until the | is less than or equal to (maximum size - new entry size) or until the | |||
| table is empty. The encoder MUST NOT evict a dynamic table entry | table is empty. The encoder MUST NOT evict a dynamic table entry | |||
| unless it has first been acknowledged by the decoder. | unless it has first been acknowledged by the decoder. | |||
| If the size of the new entry is less than or equal to the maximum | If the size of the new entry is less than or equal to the maximum | |||
| skipping to change at page 5, line 28 ¶ | skipping to change at page 10, line 22 ¶ | |||
| "HTTP_QPACK_ENCODER_STREAM_ERROR". | "HTTP_QPACK_ENCODER_STREAM_ERROR". | |||
| A new entry can reference an entry in the dynamic table that will be | A new entry can reference an entry in the dynamic table that will be | |||
| evicted when adding this new entry into the dynamic table. | evicted when adding this new entry into the dynamic table. | |||
| Implementations are cautioned to avoid deleting the referenced name | Implementations are cautioned to avoid deleting the referenced name | |||
| if the referenced entry is evicted from the dynamic table prior to | if the referenced entry is evicted from the dynamic table prior to | |||
| inserting the new entry. | inserting the new entry. | |||
| The dynamic table can contain duplicate entries (i.e., entries with | The dynamic table can contain duplicate entries (i.e., entries with | |||
| the same name and same value). Therefore, duplicate entries MUST NOT | the same name and same value). Therefore, duplicate entries MUST NOT | |||
| be treated as an error by a decoder. | be treated as an error by the decoder. | |||
| 2.2.1. Maximum Table Size | 3.2.1. Maximum Table Size | |||
| The encoder decides how to update the dynamic table and as such can | The encoder decides how to update the dynamic table and as such can | |||
| control how much memory is used by the dynamic table. To limit the | control how much memory is used by the dynamic table. To limit the | |||
| memory requirements of the decoder, the dynamic table size is | memory requirements of the decoder, the dynamic table size is | |||
| strictly bounded. | strictly bounded. | |||
| The decoder determines the maximum size that the encoder is permitted | The decoder determines the maximum size that the encoder is permitted | |||
| to use for the dynamic table. In HTTP/QUIC, this value is determined | to use for the dynamic table. In HTTP/3, this value is determined by | |||
| by the SETTINGS_HEADER_TABLE_SIZE setting (see Section 4). | the SETTINGS_HEADER_TABLE_SIZE setting (see Section 5). | |||
| An encoder can choose to use less capacity than this maximum size | An encoder can choose to use less capacity than this maximum size | |||
| (see Section 5.2.4), but the chosen size MUST stay lower than or | (see Section 4.3.4), but the chosen size MUST stay lower than or | |||
| equal to the maximum set by the decoder. Whenever the maximum size | equal to the maximum set by the decoder. Whenever the maximum size | |||
| for the dynamic table is reduced, entries are evicted from the end of | for the dynamic table is reduced, entries are evicted from the end of | |||
| the dynamic table until the size of the dynamic table is less than or | the dynamic table until the size of the dynamic table is less than or | |||
| equal to the maximum size. | equal to the maximum size. | |||
| This mechanism can be used to completely clear entries from the | This mechanism can be used to completely clear entries from the | |||
| dynamic table by setting a maximum size of 0, which can subsequently | dynamic table by setting a maximum size of 0, which can subsequently | |||
| be restored. | be restored. | |||
| 2.2.2. Calculating Table Size | 3.2.2. Calculating Table Size | |||
| The size of the dynamic table is the sum of the size of its entries. | 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 octets (as | The size of an entry is the sum of its name's length in bytes (as | |||
| defined in Section 5.1.2), its value's length in octets, and 32. | defined in Section 4.1.2), its value's length in bytes, and 32. | |||
| The size of an entry is calculated using the length of its name and | The size of an entry is calculated using the length of its name and | |||
| value without any Huffman encoding applied. | value without any Huffman encoding applied. | |||
| "MaxEntries" is the maximum number of entries that the dynamic table | "MaxEntries" is the maximum number of entries that the dynamic table | |||
| can have. The smallest entry has empty name and value strings and | can have. The smallest entry has empty name and value strings and | |||
| has the size of 32. The MaxEntries is calculated as | has the size of 32. The MaxEntries is calculated as | |||
| MaxEntries = floor( MaxTableSize / 32 ) | MaxEntries = floor( MaxTableSize / 32 ) | |||
| MaxTableSize is the maximum size of the dynamic table as specified by | MaxTableSize is the maximum size of the dynamic table as specified by | |||
| the decoder (see Section 2.2.1). | the decoder (see Section 3.2.1). | |||
| 2.2.3. Absolute Indexing | 3.2.3. Absolute Indexing | |||
| Each entry possesses both an absolute index which is fixed for the | Each entry possesses both an absolute index which is fixed for the | |||
| lifetime of that entry and a relative index which changes over time | lifetime of that entry and a relative index which changes based on | |||
| based on the context of the reference. The first entry inserted has | the context of the reference. The first entry inserted has an | |||
| an absolute index of "1"; indices increase sequentially with each | absolute index of "1"; indices increase sequentially with each | |||
| insertion. | insertion. | |||
| 2.2.4. Relative Indexing | 3.2.4. Relative Indexing | |||
| The relative index begins at zero and increases in the opposite | The relative index begins at zero and increases in the opposite | |||
| direction from the absolute index. Determining which entry has a | direction from the absolute index. Determining which entry has a | |||
| relative index of "0" depends on the context of the reference. | relative index of "0" depends on the context of the reference. | |||
| On the encoder stream, a relative index of "0" always refers to the | On the encoder stream, a relative index of "0" always refers to the | |||
| most recently inserted value in the dynamic table. Note that this | most recently inserted value in the dynamic table. Note that this | |||
| means the entry referenced by a given relative index will change | means the entry referenced by a given relative index will change | |||
| while interpreting instructions on the encoder stream. | while interpreting instructions on the encoder stream. | |||
| skipping to change at page 7, line 22 ¶ | skipping to change at page 12, line 4 ¶ | |||
| Insertion Point Dropping Point | Insertion Point Dropping Point | |||
| n = count of entries inserted | n = count of entries inserted | |||
| d = count of entries dropped | d = count of entries dropped | |||
| Example Dynamic Table Indexing - Control Stream | Example Dynamic Table Indexing - Control Stream | |||
| Because frames from request streams can be delivered out of order | Because frames from request streams can be delivered out of order | |||
| with instructions on the encoder stream, relative indices are | with instructions on the encoder stream, relative indices are | |||
| relative to the Base Index at the beginning of the header block (see | relative to the Base Index at the beginning of the header block (see | |||
| Section 5.4.1). The Base Index is an absolute index. When | Section 4.5.1). The Base Index is an absolute index. When | |||
| interpreting the rest of the frame, the entry identified by Base | interpreting the rest of the frame, the entry identified by Base | |||
| Index has a relative index of zero. The relative indices of entries | Index has a relative index of zero. The relative indices of entries | |||
| do not change while interpreting headers on a request or push stream. | do not change while interpreting headers on a request or push stream. | |||
| Base Index | Base Index | |||
| | | | | |||
| V | V | |||
| +---+-----+-----+-----+-------+ | +---+-----+-----+-----+-------+ | |||
| | n | n-1 | n-2 | ... | d+1 | Absolute Index | | n | n-1 | n-2 | ... | d+1 | Absolute Index | |||
| +---+-----+ - +-----+ - + | +---+-----+ - +-----+ - + | |||
| | 0 | ... | n-d-3 | Relative Index | | 0 | ... | n-d-3 | Relative Index | |||
| +-----+-----+-------+ | +-----+-----+-------+ | |||
| n = count of entries inserted | n = count of entries inserted | |||
| d = count of entries dropped | d = count of entries dropped | |||
| Example Dynamic Table Indexing - Relative Index on Request Stream | Example Dynamic Table Indexing - Relative Index on Request Stream | |||
| 2.2.5. Post-Base Indexing | 3.2.5. Post-Base Indexing | |||
| A header block on the request stream can reference entries added | A header block on the request stream can reference entries added | |||
| after the entry identified by the Base Index. This allows an encoder | after the entry identified by the Base Index. This allows an encoder | |||
| to process a header block in a single pass and include references to | to process a header block in a single pass and include references to | |||
| entries added while processing this (or other) header blocks. Newly | entries added while processing this (or other) header blocks. Newly | |||
| added entries are referenced using Post-Base instructions. Indices | added entries are referenced using Post-Base instructions. Indices | |||
| for Post-Base instructions increase in the same direction as absolute | for Post-Base instructions increase in the same direction as absolute | |||
| indices, but the zero value is one higher than the Base Index. | indices, but the zero value is one higher than the Base Index. | |||
| Base Index | Base Index | |||
| skipping to change at page 8, line 19 ¶ | skipping to change at page 12, line 47 ¶ | |||
| | n | n-1 | n-2 | ... | d+1 | Absolute Index | | n | n-1 | n-2 | ... | d+1 | Absolute Index | |||
| +---+-----+-----+-----+-----+ | +---+-----+-----+-----+-----+ | |||
| | 1 | 0 | Post-Base Index | | 1 | 0 | Post-Base Index | |||
| +---+-----+ | +---+-----+ | |||
| n = count of entries inserted | n = count of entries inserted | |||
| d = count of entries dropped | d = count of entries dropped | |||
| Example Dynamic Table Indexing - Post-Base Index on Request Stream | Example Dynamic Table Indexing - Post-Base Index on Request Stream | |||
| 3.2.6. Invalid References | ||||
| If the decoder encounters a reference on a request or push stream to | If the decoder encounters a reference on a request or push stream to | |||
| a dynamic table entry which has already been dropped or which has an | a dynamic table entry which has already been evicted or which has an | |||
| absolute index greater than the declared Largest Reference (see | absolute index greater than the declared Largest Reference (see | |||
| Section 5.4.1), it MUST treat this as a stream error of type | Section 4.5.1), it MUST treat this as a stream error of type | |||
| "HTTP_QPACK_DECOMPRESSION_FAILED". | "HTTP_QPACK_DECOMPRESSION_FAILED". | |||
| If the decoder encounters a reference on the encoder stream to a | If the decoder encounters a reference on the encoder stream to a | |||
| dynamic table entry which has already been dropped, it MUST treat | dynamic table entry which has already been dropped, it MUST treat | |||
| this as a connection error of type "HTTP_QPACK_ENCODER_STREAM_ERROR". | this as a connection error of type "HTTP_QPACK_ENCODER_STREAM_ERROR". | |||
| 2.3. Avoiding Head-of-Line Blocking in HTTP/QUIC | 4. Wire Format | |||
| Because QUIC does not guarantee order between data on different | ||||
| streams, a header block might reference an entry in the dynamic table | ||||
| that has not yet been received. | ||||
| Each header block contains a Largest Reference which identifies the | ||||
| table state necessary for decoding. If the greatest absolute index | ||||
| in the dynamic table is less than the value of the Largest Reference, | ||||
| the stream is considered "blocked." While blocked, header field data | ||||
| should remain in the blocked stream's flow control window. When the | ||||
| Largest Reference is zero, the frame contains no references to the | ||||
| dynamic table and can always be processed immediately. A stream | ||||
| becomes unblocked when the greatest absolute index in the dynamic | ||||
| table becomes greater than or equal to the Largest Reference for all | ||||
| header blocks the decoder has started reading from the stream. If a | ||||
| decoder encounters a header block where the actual largest reference | ||||
| is not equal to the Largest Reference declared in the prefix, it MAY | ||||
| treat this as a stream error of type HTTP_QPACK_DECOMPRESSION_FAILED. | ||||
| A decoder can permit the possibility of blocked streams by setting | ||||
| SETTINGS_QPACK_BLOCKED_STREAMS to a non-zero value (see Section 4). | ||||
| This setting specifies an upper bound on the number of streams which | ||||
| can be blocked. | ||||
| An encoder can decide whether to risk having a stream become blocked. | ||||
| If permitted by the value of SETTINGS_QPACK_BLOCKED_STREAMS, | ||||
| compression efficiency can be improved by referencing dynamic table | ||||
| entries that are still in transit, but if there is loss or reordering | ||||
| the stream can become blocked at the decoder. An encoder avoids the | ||||
| risk of blocking by only referencing dynamic table entries which have | ||||
| been acknowledged, but this means using literals. Since literals | ||||
| make the header block larger, this can result in the encoder becoming | ||||
| blocked on congestion or flow control limits. | ||||
| An encoder MUST limit the number of streams which could become | ||||
| blocked to the value of SETTINGS_QPACK_BLOCKED_STREAMS at all times. | ||||
| Note that the decoder might not actually become blocked on every | ||||
| stream which risks becoming blocked. If the decoder encounters more | ||||
| blocked streams than it promised to support, it MUST treat this as a | ||||
| stream error of type HTTP_QPACK_DECOMPRESSION_FAILED. | ||||
| 2.3.1. State Synchronization | ||||
| The decoder stream (Section 5.3) signals key events at the decoder | ||||
| that permit the encoder to track the decoder's state. These events | ||||
| are: | ||||
| o Complete processing of a header block | ||||
| o Abandonment of a stream which might have remaining header blocks | ||||
| o Receipt of new dynamic table entries | ||||
| Regardless of whether a header block contained blocking references, | ||||
| the knowledge that it has been processed permits the encoder to evict | ||||
| entries to which no unacknowledged references remain; see | ||||
| Section 7.3.1. When a stream is reset or abandoned, the indication | ||||
| that these header blocks will never be processed serves a similar | ||||
| function; see Section 5.3.3. | ||||
| For the encoder to identify which dynamic table entries can be safely | ||||
| used without a stream becoming blocked, the encoder tracks the | ||||
| absolute index of the decoder's Largest Known Received entry. | ||||
| When blocking references are permitted, the encoder uses | ||||
| acknowledgement of header blocks to identify the Largest Known | ||||
| Received index, as described in Section 5.3.2. | ||||
| To acknowledge dynamic table entries which are not referenced by | ||||
| header blocks, for example because the encoder or the decoder have | ||||
| chosen not to risk blocked streams, the decoder sends a Table State | ||||
| Synchronize instruction (see Section 5.3.1). | ||||
| 3. Conventions and Definitions | ||||
| The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", | ||||
| "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and | ||||
| "OPTIONAL" in this document are to be interpreted as described in BCP | ||||
| 14 [RFC2119] [RFC8174] when, and only when, they appear in all | ||||
| capitals, as shown here. | ||||
| Definitions of terms that are used in this document: | ||||
| Header field: A name-value pair sent as part of an HTTP message. | ||||
| Header list: The ordered collection of header fields associated with | ||||
| an HTTP message. A header list can contain multiple header fields | ||||
| with the same name. It can also contain duplicate header fields. | ||||
| Header block: The compressed representation of a header list. | ||||
| Encoder: An implementation which transforms a header list into a | ||||
| header block. | ||||
| Decoder: An implementation which transforms a header block into a | ||||
| header list. | ||||
| QPACK is a name, not an acronym. | ||||
| 3.1. Notational Conventions | ||||
| Diagrams use the format described in Section 3.1 of [RFC2360], with | 4.1. Primitives | |||
| the following additional conventions: | ||||
| x (A) Indicates that x is A bits long | 4.1.1. Prefixed Integers | |||
| x (A+) Indicates that x uses the prefixed integer encoding defined | The prefixed integer from Section 5.1 of [RFC7541] is used heavily | |||
| in Section 5.1 of [RFC7541], beginning with an A-bit prefix. | throughout this document. The format from [RFC7541] is used | |||
| unmodified. QPACK implementations MUST be able to decode integers up | ||||
| to 62 bits long. | ||||
| x ... Indicates that x is variable-length and extends to the end of | 4.1.2. String Literals | |||
| the region. | ||||
| 4. Configuration | The string literal defined by Section 5.2 of [RFC7541] is also used | |||
| throughout. This string format includes optional Huffman encoding. | ||||
| QPACK defines two settings which are included in the HTTP/QUIC | HPACK defines string literals to begin on a byte boundary. They | |||
| SETTINGS frame. | begin with a single flag (indicating whether the string is Huffman- | |||
| coded), followed by the Length encoded as a 7-bit prefix integer, and | ||||
| finally Length bytes of data. When Huffman encoding is enabled, the | ||||
| Huffman table from Appendix B of [RFC7541] is used without | ||||
| modification. | ||||
| SETTINGS_HEADER_TABLE_SIZE (0x1): An integer with a maximum value of | This document expands the definition of string literals and permits | |||
| 2^30 - 1. The default value is 4,096 bytes. See Section 2.2 for | them to begin other than on a byte boundary. An "N-bit prefix string | |||
| usage. | literal" begins with the same Huffman flag, followed by the length | |||
| encoded as an (N-1)-bit prefix integer. The remainder of the string | ||||
| literal is unmodified. | ||||
| SETTINGS_QPACK_BLOCKED_STREAMS (0x7): An integer with a maximum | A string literal without a prefix length noted is an 8-bit prefix | |||
| value of 2^16 - 1. The default value is 100. See Section 2.3. | string literal and follows the definitions in [RFC7541] without | |||
| modification. | ||||
| 5. Wire Format | 4.2. Stream Types | |||
| QPACK instructions occur in three locations, each of which uses a | QPACK instructions occur in three locations, each of which uses a | |||
| separate instruction space: | separate instruction space: | |||
| o The encoder stream is a unidirectional stream of type "0x48" | o The encoder stream is a unidirectional stream of type "0x48" | |||
| (ASCII 'H') which carries table updates from encoder to decoder. | (ASCII 'H') which carries table updates from encoder to decoder. | |||
| Instructions on this stream modify the dynamic table state without | ||||
| generating output to any particular request. | ||||
| o The decoder stream is a unidirectional stream of type "0x68" | o The decoder stream is a unidirectional stream of type "0x68" | |||
| (ASCII 'h') which carries acknowledgements of table modifications | (ASCII 'h') which carries acknowledgements of table modifications | |||
| and header processing from decoder to encoder. | and header processing from decoder to encoder. | |||
| o Finally, the contents of HEADERS and PUSH_PROMISE frames on | o Finally, the contents of HEADERS and PUSH_PROMISE frames on | |||
| request streams and push streams reference the QPACK table state. | request streams and push streams reference the QPACK table state. | |||
| There MUST be exactly one of each unidirectional stream type in each | There MUST be exactly one of each unidirectional stream type in each | |||
| direction. Receipt of a second instance of either stream type MUST | direction. Receipt of a second instance of either stream type MUST | |||
| be treated as a connection error of HTTP_WRONG_STREAM_COUNT. Closure | be treated as a connection error of HTTP_WRONG_STREAM_COUNT. Closure | |||
| of either unidirectional stream MUST be treated as a connection error | of either unidirectional stream MUST be treated as a connection error | |||
| of type HTTP_CLOSED_CRITICAL_STREAM. | of type HTTP_CLOSED_CRITICAL_STREAM. | |||
| This section describes the instructions which are possible on each | This section describes the instructions which are possible on each | |||
| stream type. | stream type. | |||
| All table updates occur on the encoder stream. Request streams and | 4.3. Encoder Stream | |||
| push streams only carry header blocks that do not modify the state of | ||||
| the table. | ||||
| 5.1. Primitives | ||||
| 5.1.1. Prefixed Integers | ||||
| The prefixed integer from Section 5.1 of [RFC7541] is used heavily | ||||
| throughout this document. The format from [RFC7541] is used | ||||
| unmodified. QPACK implementations MUST be able to decode integers up | ||||
| to 62 bits long. | ||||
| 5.1.2. String Literals | ||||
| The string literal defined by Section 5.2 of [RFC7541] is also used | ||||
| throughout. This string format includes optional Huffman encoding. | ||||
| HPACK defines string literals to begin on a byte boundary. They | ||||
| begin with a single flag (indicating whether the string is Huffman- | ||||
| coded), followed by the Length encoded as a 7-bit prefix integer, and | ||||
| finally Length octets of data. When Huffman encoding is enabled, the | ||||
| Huffman table from Appendix B of [RFC7541] is used without | ||||
| modification. | ||||
| This document expands the definition of string literals and permits | ||||
| them to begin other than on a byte boundary. An "N-bit prefix string | ||||
| literal" begins with the same Huffman flag, followed by the length | ||||
| encoded as an (N-1)-bit prefix integer. The remainder of the string | ||||
| literal is unmodified. | ||||
| A string literal without a prefix length noted is an 8-bit prefix | ||||
| string literal and follows the definitions in [RFC7541] without | ||||
| modification. | ||||
| 5.2. QPACK Encoder Stream | ||||
| Table updates can add a table entry, possibly using existing entries | Table updates can add a table entry, possibly using existing entries | |||
| to avoid transmitting redundant information. The name can be | to avoid transmitting redundant information. The name can be | |||
| transmitted as a reference to an existing entry in the static or the | transmitted as a reference to an existing entry in the static or the | |||
| dynamic table or as a string literal. For entries which already | dynamic table or as a string literal. For entries which already | |||
| exist in the dynamic table, the full entry can also be used by | exist in the dynamic table, the full entry can also be used by | |||
| reference, creating a duplicate entry. | reference, creating a duplicate entry. | |||
| The contents of the encoder stream are an unframed sequence of the | The contents of the encoder stream are an unframed sequence of the | |||
| following instructions. | following instructions. | |||
| 5.2.1. Insert With Name Reference | 4.3.1. Insert With Name Reference | |||
| An addition to the header table where the header field name matches | An addition to the header table where the header field name matches | |||
| the header field name of an entry stored in the static table or the | the header field name of an entry stored in the static table or the | |||
| dynamic table starts with the '1' one-bit pattern. The "S" bit | dynamic table starts with the '1' one-bit pattern. The "S" bit | |||
| indicates whether the reference is to the static (S=1) or dynamic | indicates whether the reference is to the static (S=1) or dynamic | |||
| (S=0) table. The 6-bit prefix integer (see Section 5.1 of [RFC7541]) | (S=0) table. The 6-bit prefix integer (see Section 5.1 of [RFC7541]) | |||
| that follows is used to locate the table entry for the header name. | that follows is used to locate the table entry for the header name. | |||
| When S=1, the number represents the static table index; when S=0, the | When S=1, the number represents the static table index; when S=0, the | |||
| number is the relative index of the entry in the dynamic table. | number is the relative index of the entry in the dynamic table. | |||
| The header name reference is followed by the header field value | The header name reference is followed by the header field value | |||
| represented as a string literal (see Section 5.2 of [RFC7541]). | represented as a string literal (see Section 5.2 of [RFC7541]). | |||
| 0 1 2 3 4 5 6 7 | 0 1 2 3 4 5 6 7 | |||
| +---+---+---+---+---+---+---+---+ | +---+---+---+---+---+---+---+---+ | |||
| | 1 | S | Name Index (6+) | | | 1 | S | Name Index (6+) | | |||
| +---+---+-----------------------+ | +---+---+-----------------------+ | |||
| | H | Value Length (7+) | | | H | Value Length (7+) | | |||
| +---+---------------------------+ | +---+---------------------------+ | |||
| | Value String (Length octets) | | | Value String (Length bytes) | | |||
| +-------------------------------+ | +-------------------------------+ | |||
| Insert Header Field -- Indexed Name | Insert Header Field -- Indexed Name | |||
| 5.2.2. Insert Without Name Reference | 4.3.2. Insert Without Name Reference | |||
| An addition to the header table where both the header field name and | An addition to the header table where both the header field name and | |||
| the header field value are represented as string literals (see | the header field value are represented as string literals (see | |||
| Section 5.1) starts with the '01' two-bit pattern. | Section 4.1) starts with the '01' two-bit pattern. | |||
| The name is represented as a 6-bit prefix string literal, while the | The name is represented as a 6-bit prefix string literal, while the | |||
| value is represented as an 8-bit prefix string literal. | value is represented as an 8-bit prefix string literal. | |||
| 0 1 2 3 4 5 6 7 | 0 1 2 3 4 5 6 7 | |||
| +---+---+---+---+---+---+---+---+ | +---+---+---+---+---+---+---+---+ | |||
| | 0 | 1 | H | Name Length (5+) | | | 0 | 1 | H | Name Length (5+) | | |||
| +---+---+---+-------------------+ | +---+---+---+-------------------+ | |||
| | Name String (Length octets) | | | Name String (Length bytes) | | |||
| +---+---------------------------+ | +---+---------------------------+ | |||
| | H | Value Length (7+) | | | H | Value Length (7+) | | |||
| +---+---------------------------+ | +---+---------------------------+ | |||
| | Value String (Length octets) | | | Value String (Length bytes) | | |||
| +-------------------------------+ | +-------------------------------+ | |||
| Insert Header Field -- New Name | Insert Header Field -- New Name | |||
| 5.2.3. Duplicate | 4.3.3. Duplicate | |||
| Duplication of an existing entry in the dynamic table starts with the | Duplication of an existing entry in the dynamic table starts with the | |||
| '000' three-bit pattern. The relative index of the existing entry is | '000' three-bit pattern. The relative index of the existing entry is | |||
| represented as an integer with a 5-bit prefix. | represented as an integer with a 5-bit prefix. | |||
| 0 1 2 3 4 5 6 7 | 0 1 2 3 4 5 6 7 | |||
| +---+---+---+---+---+---+---+---+ | +---+---+---+---+---+---+---+---+ | |||
| | 0 | 0 | 0 | Index (5+) | | | 0 | 0 | 0 | Index (5+) | | |||
| +---+---+---+-------------------+ | +---+---+---+-------------------+ | |||
| Figure 1: Duplicate | Figure 2: Duplicate | |||
| The existing entry is re-inserted into the dynamic table without | The existing entry is re-inserted into the dynamic table without | |||
| resending either the name or the value. This is useful to mitigate | resending either the name or the value. This is useful to mitigate | |||
| the eviction of older entries which are frequently referenced, both | the eviction of older entries which are frequently referenced, both | |||
| to avoid the need to resend the header and to avoid the entry in the | to avoid the need to resend the header and to avoid the entry in the | |||
| table blocking the ability to insert new headers. | table blocking the ability to insert new headers. | |||
| 5.2.4. Dynamic Table Size Update | 4.3.4. Dynamic Table Size Update | |||
| An encoder informs the decoder of a change to the size of the dynamic | An encoder informs the decoder of a change to the size of the dynamic | |||
| table using an instruction which begins with the '001' three-bit | table using an instruction which begins with the '001' three-bit | |||
| pattern. The new maximum table size is represented as an integer | pattern. The new maximum table size is represented as an integer | |||
| with a 5-bit prefix (see Section 5.1 of [RFC7541]). | with a 5-bit prefix (see Section 5.1 of [RFC7541]). | |||
| 0 1 2 3 4 5 6 7 | 0 1 2 3 4 5 6 7 | |||
| +---+---+---+---+---+---+---+---+ | +---+---+---+---+---+---+---+---+ | |||
| | 0 | 0 | 1 | Max size (5+) | | | 0 | 0 | 1 | Max size (5+) | | |||
| +---+---+---+-------------------+ | +---+---+---+-------------------+ | |||
| Figure 2: Maximum Dynamic Table Size Change | Figure 3: Maximum Dynamic Table Size Change | |||
| The new maximum size MUST be lower than or equal to the limit | The new maximum size MUST be lower than or equal to the limit | |||
| determined by the protocol using QPACK. A value that exceeds this | determined by the protocol using QPACK. A value that exceeds this | |||
| limit MUST be treated as a connection error of type | limit MUST be treated as a connection error of type | |||
| "HTTP_QPACK_ENCODER_STREAM_ERROR". In HTTP/QUIC, this limit is the | "HTTP_QPACK_ENCODER_STREAM_ERROR". In HTTP/3, this limit is the | |||
| value of the SETTINGS_HEADER_TABLE_SIZE parameter (see Section 4) | value of the SETTINGS_HEADER_TABLE_SIZE parameter (see Section 5) | |||
| received from the decoder. | received from the decoder. | |||
| Reducing the maximum size of the dynamic table can cause entries to | Reducing the maximum size of the dynamic table can cause entries to | |||
| be evicted (see Section 4.3 of [RFC7541]). This MUST NOT cause the | be evicted (see Section 4.3 of [RFC7541]). This MUST NOT cause the | |||
| eviction of entries with outstanding references (see Section 7.3). | eviction of entries with outstanding references (see Section 2.1.1). | |||
| Changing the size of the dynamic table is not acknowledged as this | Changing the size of the dynamic table is not acknowledged as this | |||
| instruction does not insert an entry. | instruction does not insert an entry. | |||
| 5.3. QPACK Decoder Stream | 4.4. Decoder Stream | |||
| The decoder stream carries information used to ensure consistency of | The decoder stream carries information used to ensure consistency of | |||
| the dynamic table. Information is sent from the QPACK decoder to the | the dynamic table. Information is sent from the decoder to the | |||
| QPACK encoder; that is, the server informs the client about the | encoder; that is, the server informs the client about the processing | |||
| processing of the client's header blocks and table updates, and the | of the client's header blocks and table updates, and the client | |||
| client informs the server about the processing of the server's header | informs the server about the processing of the server's header blocks | |||
| blocks and table updates. | and table updates. | |||
| The contents of the decoder stream are an unframed sequence of the | The contents of the decoder stream are an unframed sequence of the | |||
| following instructions. | following instructions. | |||
| 5.3.1. Table State Synchronize | 4.4.1. Table State Synchronize | |||
| The Table State Synchronize instruction begins with the '00' two-bit | The Table State Synchronize instruction begins with the '00' two-bit | |||
| pattern. The instruction specifies the total number of dynamic table | pattern. The instruction specifies the total number of dynamic table | |||
| inserts and duplications since the last Table State Synchronize or | inserts and duplications since the last Table State Synchronize or | |||
| Header Acknowledgement that increased the Largest Known Received | Header Acknowledgement that increased the Largest Known Received | |||
| dynamic table entry. This is encoded as a 6-bit prefix integer. The | dynamic table entry (see Section 2.1.4). This is encoded as a 6-bit | |||
| encoder uses this value to determine which table entries might cause | prefix integer. The encoder uses this value to determine which table | |||
| a stream to become blocked, as described in Section 2.3.1. | entries might cause a stream to become blocked, as described in | |||
| Section 2.2.1. | ||||
| 0 1 2 3 4 5 6 7 | 0 1 2 3 4 5 6 7 | |||
| +---+---+---+---+---+---+---+---+ | +---+---+---+---+---+---+---+---+ | |||
| | 0 | 0 | Insert Count (6+) | | | 0 | 0 | Insert Count (6+) | | |||
| +---+---+-----------------------+ | +---+---+-----------------------+ | |||
| Figure 3: Table State Synchronize | Figure 4: Table State Synchronize | |||
| An encoder that receives an Insert Count equal to zero or one that | An encoder that receives an Insert Count equal to zero or one that | |||
| increases Largest Known Received beyond what the encoder has sent | increases Largest Known Received beyond what the encoder has sent | |||
| MUST treat this as a connection error of type | MUST treat this as a connection error of type | |||
| "HTTP_QPACK_DECODER_STREAM_ERROR". | "HTTP_QPACK_DECODER_STREAM_ERROR". | |||
| A decoder chooses when to emit Table State Synchronize instructions. | 4.4.2. Header Acknowledgement | |||
| Emitting a Table State Synchronize after adding each new dynamic | ||||
| table entry will provide the most timely feedback to the encoder, but | ||||
| could be redundant with other decoder feedback. By delaying a | ||||
| Table State Synchronize, a decoder might be able to coalesce multiple | ||||
| Table State Synchronize instructions, or replace them entirely with | ||||
| Header Acknowledgements. However, delaying too long may lead to | ||||
| compression inefficiencies if the encoder waits for an entry to be | ||||
| acknowledged before using it. | ||||
| 5.3.2. Header Acknowledgement | ||||
| After processing a header block whose declared Largest Reference is | After processing a header block whose declared Largest Reference is | |||
| not zero, the decoder emits a Header Acknowledgement instruction on | not zero, the decoder emits a Header Acknowledgement instruction on | |||
| the decoder stream. The instruction begins with the '1' one-bit | the decoder stream. The instruction begins with the '1' one-bit | |||
| pattern and includes the request stream's stream ID, encoded as a | pattern and includes the request stream's stream ID, encoded as a | |||
| 7-bit prefix integer. It is used by the peer's QPACK encoder to know | 7-bit prefix integer. It is used by the peer's encoder to know when | |||
| when it is safe to evict an entry. | it is safe to evict an entry, and possibly update Largest Known | |||
| Received. | ||||
| 0 1 2 3 4 5 6 7 | 0 1 2 3 4 5 6 7 | |||
| +---+---+---+---+---+---+---+---+ | +---+---+---+---+---+---+---+---+ | |||
| | 1 | Stream ID (7+) | | | 1 | Stream ID (7+) | | |||
| +---+---------------------------+ | +---+---------------------------+ | |||
| Figure 4: Header Acknowledgement | Figure 5: Header Acknowledgement | |||
| The same Stream ID can be identified multiple times, as multiple | The same Stream ID can be identified multiple times, as multiple | |||
| header blocks can be sent on a single stream in the case of | header blocks can be sent on a single stream in the case of | |||
| intermediate responses, trailers, and pushed requests. Since header | intermediate responses, trailers, and pushed requests. Since header | |||
| frames on each stream are received and processed in order, this gives | frames on each stream are received and processed in order, this gives | |||
| the encoder precise feedback on which header blocks within a stream | the encoder precise feedback on which header blocks within a stream | |||
| have been fully processed. | have been fully processed. | |||
| If an encoder receives a Header Acknowledgement instruction referring | If an encoder receives a Header Acknowledgement instruction referring | |||
| to a stream on which every header block with a non-zero Largest | to a stream on which every header block with a non-zero Largest | |||
| skipping to change at page 16, line 21 ¶ | skipping to change at page 18, line 14 ¶ | |||
| When blocking references are permitted, the encoder uses | When blocking references are permitted, the encoder uses | |||
| acknowledgement of header blocks to update the Largest Known Received | acknowledgement of header blocks to update the Largest Known Received | |||
| index. If a header block was potentially blocking, the | index. If a header block was potentially blocking, the | |||
| acknowledgement implies that the decoder has received all dynamic | acknowledgement implies that the decoder has received all dynamic | |||
| table state necessary to process the header block. If the Largest | table state necessary to process the header block. If the Largest | |||
| Reference of an acknowledged header block was greater than the | Reference of an acknowledged header block was greater than the | |||
| encoder's current Largest Known Received index, the block's Largest | encoder's current Largest Known Received index, the block's Largest | |||
| Reference becomes the new Largest Known Received. | Reference becomes the new Largest Known Received. | |||
| 5.3.3. Stream Cancellation | 4.4.3. Stream Cancellation | |||
| A stream that is reset might have multiple outstanding header blocks | ||||
| with dynamic table references. A decoder that receives a stream | ||||
| reset before the end of a stream generates a Stream Cancellation | ||||
| instruction on the decoder stream. Similarly, a decoder that | ||||
| abandons reading of a stream needs to signal this using the Stream | ||||
| Cancellation instruction. This signals to the encoder that all | ||||
| references to the dynamic table on that stream are no longer | ||||
| outstanding. A decoder with a maximum dynamic table size equal to | ||||
| zero MAY omit sending Stream Cancellations, because the encoder | ||||
| cannot have any dynamic table references. | ||||
| An encoder cannot infer from this instruction that any updates to the | ||||
| dynamic table have been received. | ||||
| The instruction begins with the '01' two-bit pattern. The | The instruction begins with the '01' two-bit pattern. The | |||
| instruction includes the stream ID of the affected stream - a request | instruction includes the stream ID of the affected stream - a request | |||
| or push stream - encoded as a 6-bit prefix integer. | or push stream - encoded as a 6-bit prefix integer. | |||
| 0 1 2 3 4 5 6 7 | 0 1 2 3 4 5 6 7 | |||
| +---+---+---+---+---+---+---+---+ | +---+---+---+---+---+---+---+---+ | |||
| | 0 | 1 | Stream ID (6+) | | | 0 | 1 | Stream ID (6+) | | |||
| +---+---+-----------------------+ | +---+---+-----------------------+ | |||
| Figure 5: Stream Cancellation | Figure 6: Stream Cancellation | |||
| 5.4. Request and Push Streams | A stream that is reset might have multiple outstanding header blocks | |||
| with dynamic table references. When an endpoint receives a stream | ||||
| reset before the end of a stream, it generates a Stream Cancellation | ||||
| instruction on the decoder stream. Similarly, when an endpoint | ||||
| abandons reading of a stream it needs to signal this using the Stream | ||||
| Cancellation instruction. This signals to the encoder that all | ||||
| references to the dynamic table on that stream are no longer | ||||
| outstanding. A decoder with a maximum dynamic table size equal to | ||||
| zero MAY omit sending Stream Cancellations, because the encoder | ||||
| cannot have any dynamic table references. | ||||
| An encoder cannot infer from this instruction that any updates to the | ||||
| dynamic table have been received. | ||||
| 4.5. Request and Push Streams | ||||
| HEADERS and PUSH_PROMISE frames on request and push streams reference | HEADERS and PUSH_PROMISE frames on request and push streams reference | |||
| the dynamic table in a particular state without modifying it. Frames | the dynamic table in a particular state without modifying it. Frames | |||
| on these streams emit the headers for an HTTP request or response. | on these streams emit the headers for an HTTP request or response. | |||
| 5.4.1. Header Data Prefix | 4.5.1. Header Data Prefix | |||
| Header data is prefixed with two integers, "Largest Reference" and | Header data is prefixed with two integers, "Largest Reference" and | |||
| "Base Index". | "Base Index". | |||
| 0 1 2 3 4 5 6 7 | 0 1 2 3 4 5 6 7 | |||
| +---+---+---+---+---+---+---+---+ | +---+---+---+---+---+---+---+---+ | |||
| | Largest Reference (8+) | | | Largest Reference (8+) | | |||
| +---+---------------------------+ | +---+---------------------------+ | |||
| | S | Delta Base Index (7+) | | | S | Delta Base Index (7+) | | |||
| +---+---------------------------+ | +---+---------------------------+ | |||
| | Compressed Headers ... | | Compressed Headers ... | |||
| +-------------------------------+ | +-------------------------------+ | |||
| Figure 6: Frame Payload | Figure 7: Frame Payload | |||
| 4.5.1.1. Largest Reference | ||||
| "Largest Reference" identifies the largest absolute dynamic index | "Largest Reference" identifies the largest absolute dynamic index | |||
| referenced in the block. Blocking decoders use the Largest Reference | referenced in the block. Blocking decoders use the Largest Reference | |||
| to determine when it is safe to process the rest of the block. If | to determine when it is safe to process the rest of the block. If | |||
| Largest Reference is greater than zero, the encoder transforms it as | Largest Reference is greater than zero, the encoder transforms it as | |||
| follows before encoding: | follows before encoding: | |||
| LargestReference = LargestReference mod 2*MaxEntries + 1 | LargestReference = (LargestReference mod (2 * MaxEntries)) + 1 | |||
| The decoder reconstructs the Largest Reference using the following | The decoder reconstructs the Largest Reference using the following | |||
| algorithm: | algorithm: | |||
| if LargestReference > 0: | if LargestReference > 0: | |||
| LargestReference -= 1 | LargestReference -= 1 | |||
| CurrentWrapped = TableLargestAbsoluteIndex mod 2*MaxEntries | CurrentWrapped = TotalNumberOfInserts mod (2 * MaxEntries) | |||
| if CurrentWrapped >= LargestReference + MaxEntries: | if CurrentWrapped >= LargestReference + MaxEntries: | |||
| # Largest Reference wrapped around 1 extra time | # Largest Reference wrapped around 1 extra time | |||
| LargestReference += 2*MaxEntries | LargestReference += 2 * MaxEntries | |||
| else if CurrentWrapped + MaxEntries < LargestReference | else if CurrentWrapped + MaxEntries < LargestReference | |||
| # Decoder wrapped around 1 extra time | # Decoder wrapped around 1 extra time | |||
| CurrentWrapped += 2*MaxEntries | CurrentWrapped += 2 * MaxEntries | |||
| LargestReference += | LargestReference += TotalNumberOfInserts - CurrentWrapped | |||
| (TableLargestAbsoluteIndex - CurrentWrapped) | ||||
| TableLargestAbsoluteIndex is the Absolute Index of the most recently | TotalNumberOfInserts is the total number of inserts into the | |||
| inserted item in the decoder's dynamic table. This encoding limits | decoder's dynamic table. This encoding limits the length of the | |||
| the length of the prefix on long-lived connections. | prefix on long-lived connections. | |||
| 4.5.1.2. Base Index | ||||
| "Base Index" is used to resolve references in the dynamic table as | "Base Index" is used to resolve references in the dynamic table as | |||
| described in Section 2.2.4. | described in Section 3.2.4. | |||
| To save space, Base Index is encoded relative to Largest Reference | To save space, Base Index is encoded relative to Largest Reference | |||
| using a one-bit sign and the "Delta Base Index" value. A sign bit of | using a one-bit sign and the "Delta Base Index" value. A sign bit of | |||
| 0 indicates that the Base Index has an absolute index that is greater | 0 indicates that the Base Index has an absolute index that is greater | |||
| than or equal to the Largest Reference; the value of Delta Base Index | than or equal to the Largest Reference; the value of Delta Base Index | |||
| is added to the Largest Reference to determine the absolute value of | is added to the Largest Reference to determine the absolute value of | |||
| the Base Index. A sign bit of 1 indicates that the Base Index is | the Base Index. A sign bit of 1 indicates that the Base Index is | |||
| less than the Largest Reference. That is: | less than the Largest Reference. That is: | |||
| if sign == 0: | if sign == 0: | |||
| baseIndex = largestReference + deltaBaseIndex | baseIndex = largestReference + deltaBaseIndex | |||
| else: | else: | |||
| baseIndex = largestReference - deltaBaseIndex | baseIndex = largestReference - deltaBaseIndex | |||
| A single-pass encoder is expected to determine the absolute value of | A single-pass encoder determines the absolute value of Base Index | |||
| Base Index before encoding a header block. If the encoder inserted | before encoding a header block. If the encoder inserted entries in | |||
| entries in the dynamic table while encoding the header block, Largest | the dynamic table while encoding the header block, Largest Reference | |||
| Reference will be greater than Base Index, so the encoded difference | will be greater than Base Index, so the encoded difference is | |||
| is negative and the sign bit is set to 1. If the header block did | negative and the sign bit is set to 1. If the header block did not | |||
| not reference the most recent entry in the table and did not insert | reference the most recent entry in the table and did not insert any | |||
| any new entries, Base Index will be greater than the Largest | new entries, Base Index will be greater than the Largest Reference, | |||
| Reference, so the delta will be positive and the sign bit is set to | so the delta will be positive and the sign bit is set to 0. | |||
| 0. | ||||
| An encoder that produces table updates before encoding a header block | An encoder that produces table updates before encoding a header block | |||
| might set Largest Reference and Base Index to the same value. When | might set Largest Reference and Base Index to the same value. When | |||
| Largest Reference and Base Index are equal, the Delta Base Index is | Largest Reference and Base Index are equal, the Delta Base Index is | |||
| encoded with a zero sign bit. A sign bit set to 1 when the Delta | encoded with a zero sign bit. A sign bit set to 1 when the Delta | |||
| Base Index is 0 MUST be treated as a decoder error. | Base Index is 0 MUST be treated as a decoder error. | |||
| A header block that does not reference the dynamic table can use any | A header block that does not reference the dynamic table can use any | |||
| value for Base Index; setting both Largest Reference and Base Index | value for Base Index; setting both Largest Reference and Base Index | |||
| to zero is the most efficient encoding. | to zero is the most efficient encoding. | |||
| 5.4.2. Instructions | 4.5.2. Indexed Header Field | |||
| 5.4.2.1. Indexed Header Field | ||||
| An indexed header field representation identifies an entry in either | An indexed header field representation identifies an entry in either | |||
| the static table or the dynamic table and causes that header field to | the static table or the dynamic table and causes that header field to | |||
| be added to the decoded header list, as described in Section 3.2 of | be added to the decoded header list, as described in Section 3.2 of | |||
| [RFC7541]. | [RFC7541]. | |||
| 0 1 2 3 4 5 6 7 | 0 1 2 3 4 5 6 7 | |||
| +---+---+---+---+---+---+---+---+ | +---+---+---+---+---+---+---+---+ | |||
| | 1 | S | Index (6+) | | | 1 | S | Index (6+) | | |||
| +---+---+-----------------------+ | +---+---+-----------------------+ | |||
| skipping to change at page 19, line 20 ¶ | skipping to change at page 21, line 8 ¶ | |||
| Indexed Header Field | Indexed Header Field | |||
| If the entry is in the static table, or in the dynamic table with an | If the entry is in the static table, or in the dynamic table with an | |||
| absolute index less than or equal to Base Index, this representation | absolute index less than or equal to Base Index, this representation | |||
| starts with the '1' 1-bit pattern, followed by the "S" bit indicating | starts with the '1' 1-bit pattern, followed by the "S" bit indicating | |||
| whether the reference is into the static (S=1) or dynamic (S=0) | whether the reference is into the static (S=1) or dynamic (S=0) | |||
| table. Finally, the relative index of the matching header field is | table. Finally, the relative index of the matching header field is | |||
| represented as an integer with a 6-bit prefix (see Section 5.1 of | represented as an integer with a 6-bit prefix (see Section 5.1 of | |||
| [RFC7541]). | [RFC7541]). | |||
| 5.4.2.2. Indexed Header Field With Post-Base Index | 4.5.3. Indexed Header Field With Post-Base Index | |||
| If the entry is in the dynamic table with an absolute index greater | If the entry is in the dynamic table with an absolute index greater | |||
| than Base Index, the representation starts with the '0001' 4-bit | than Base Index, the representation starts with the '0001' 4-bit | |||
| pattern, followed by the post-base index (see Section 2.2.5) of the | pattern, followed by the post-base index (see Section 3.2.5) of the | |||
| matching header field, represented as an integer with a 4-bit prefix | matching header field, represented as an integer with a 4-bit prefix | |||
| (see Section 5.1 of [RFC7541]). | (see Section 5.1 of [RFC7541]). | |||
| 0 1 2 3 4 5 6 7 | 0 1 2 3 4 5 6 7 | |||
| +---+---+---+---+---+---+---+---+ | +---+---+---+---+---+---+---+---+ | |||
| | 0 | 0 | 0 | 1 | Index (4+) | | | 0 | 0 | 0 | 1 | Index (4+) | | |||
| +---+---+---+---+---------------+ | +---+---+---+---+---------------+ | |||
| Indexed Header Field with Post-Base Index | Indexed Header Field with Post-Base Index | |||
| 5.4.2.3. Literal Header Field With Name Reference | 4.5.4. Literal Header Field With Name Reference | |||
| A literal header field with a name reference represents a header | A literal header field with a name reference represents a header | |||
| where the header field name matches the header field name of an entry | where the header field name matches the header field name of an entry | |||
| stored in the static table or the dynamic table. | stored in the static table or the dynamic table. | |||
| If the entry is in the static table, or in the dynamic table with an | If the entry is in the static table, or in the dynamic table with an | |||
| absolute index less than or equal to Base Index, this representation | absolute index less than or equal to Base Index, this representation | |||
| starts with the '01' two-bit pattern. If the entry is in the dynamic | starts with the '01' two-bit pattern. If the entry is in the dynamic | |||
| table with an absolute index greater than Base Index, the | table with an absolute index greater than Base Index, the | |||
| representation starts with the '0000' four-bit pattern. | representation starts with the '0000' four-bit pattern. | |||
| skipping to change at page 20, line 14 ¶ | skipping to change at page 22, line 11 ¶ | |||
| representation to forward this header field. This bit is intended | representation to forward this header field. This bit is intended | |||
| for protecting header field values that are not to be put at risk by | for protecting header field values that are not to be put at risk by | |||
| compressing them (see Section 7.1 of [RFC7541] for more details). | compressing them (see Section 7.1 of [RFC7541] for more details). | |||
| 0 1 2 3 4 5 6 7 | 0 1 2 3 4 5 6 7 | |||
| +---+---+---+---+---+---+---+---+ | +---+---+---+---+---+---+---+---+ | |||
| | 0 | 1 | N | S |Name Index (4+)| | | 0 | 1 | N | S |Name Index (4+)| | |||
| +---+---+---+---+---------------+ | +---+---+---+---+---------------+ | |||
| | H | Value Length (7+) | | | H | Value Length (7+) | | |||
| +---+---------------------------+ | +---+---------------------------+ | |||
| | Value String (Length octets) | | | Value String (Length bytes) | | |||
| +-------------------------------+ | +-------------------------------+ | |||
| Literal Header Field With Name Reference | Literal Header Field With Name Reference | |||
| For entries in the static table or in the dynamic table with an | For entries in the static table or in the dynamic table with an | |||
| absolute index less than or equal to Base Index, the header field | absolute index less than or equal to Base Index, the header field | |||
| name is represented using the relative index of that entry, which is | name is represented using the relative index of that entry, which is | |||
| represented as an integer with a 4-bit prefix (see Section 5.1 of | represented as an integer with a 4-bit prefix (see Section 5.1 of | |||
| [RFC7541]). The "S" bit indicates whether the reference is to the | [RFC7541]). The "S" bit indicates whether the reference is to the | |||
| static (S=1) or dynamic (S=0) table. | static (S=1) or dynamic (S=0) table. | |||
| 5.4.2.4. Literal Header Field With Post-Base Name Reference | 4.5.5. Literal Header Field With Post-Base Name Reference | |||
| For entries in the dynamic table with an absolute index greater than | For entries in the dynamic table with an absolute index greater than | |||
| Base Index, the header field name is represented using the post-base | Base Index, the header field name is represented using the post-base | |||
| index of that entry (see Section 2.2.5) encoded as an integer with a | index of that entry (see Section 3.2.5) encoded as an integer with a | |||
| 3-bit prefix. | 3-bit prefix. | |||
| 0 1 2 3 4 5 6 7 | 0 1 2 3 4 5 6 7 | |||
| +---+---+---+---+---+---+---+---+ | +---+---+---+---+---+---+---+---+ | |||
| | 0 | 0 | 0 | 0 | N |NameIdx(3+)| | | 0 | 0 | 0 | 0 | N |NameIdx(3+)| | |||
| +---+---+---+---+---+-----------+ | +---+---+---+---+---+-----------+ | |||
| | H | Value Length (7+) | | | H | Value Length (7+) | | |||
| +---+---------------------------+ | +---+---------------------------+ | |||
| | Value String (Length octets) | | | Value String (Length bytes) | | |||
| +-------------------------------+ | +-------------------------------+ | |||
| Literal Header Field With Post-Base Name Reference | Literal Header Field With Post-Base Name Reference | |||
| 5.4.2.5. Literal Header Field Without Name Reference | 4.5.6. Literal Header Field Without Name Reference | |||
| An addition to the header table where both the header field name and | An addition to the header table where both the header field name and | |||
| the header field value are represented as string literals (see | the header field value are represented as string literals (see | |||
| Section 5.1) starts with the '001' three-bit pattern. | Section 4.1) starts with the '001' three-bit pattern. | |||
| The fourth bit, 'N', indicates whether an intermediary is permitted | The fourth bit, 'N', indicates whether an intermediary is permitted | |||
| to add this header to the dynamic header table on subsequent hops. | to add this header to the dynamic header table on subsequent hops. | |||
| When the 'N' bit is set, the encoded header MUST always be encoded | When the 'N' bit is set, the encoded header MUST always be encoded | |||
| with a literal representation. In particular, when a peer sends a | with a literal representation. In particular, when a peer sends a | |||
| header field that it received represented as a literal header field | header field that it received represented as a literal header field | |||
| with the 'N' bit set, it MUST use a literal representation to forward | with the 'N' bit set, it MUST use a literal representation to forward | |||
| this header field. This bit is intended for protecting header field | this header field. This bit is intended for protecting header field | |||
| values that are not to be put at risk by compressing them (see | values that are not to be put at risk by compressing them (see | |||
| Section 7.1 of [RFC7541] for more details). | Section 7.1 of [RFC7541] for more details). | |||
| The name is represented as a 4-bit prefix string literal, while the | The name is represented as a 4-bit prefix string literal, while the | |||
| value is represented as an 8-bit prefix string literal. | value is represented as an 8-bit prefix string literal. | |||
| 0 1 2 3 4 5 6 7 | 0 1 2 3 4 5 6 7 | |||
| +---+---+---+---+---+---+---+---+ | +---+---+---+---+---+---+---+---+ | |||
| | 0 | 0 | 1 | N | H |NameLen(3+)| | | 0 | 0 | 1 | N | H |NameLen(3+)| | |||
| +---+---+---+---+---+-----------+ | +---+---+---+---+---+-----------+ | |||
| | Name String (Length octets) | | | Name String (Length bytes) | | |||
| +---+---------------------------+ | +---+---------------------------+ | |||
| | H | Value Length (7+) | | | H | Value Length (7+) | | |||
| +---+---------------------------+ | +---+---------------------------+ | |||
| | Value String (Length octets) | | | Value String (Length bytes) | | |||
| +-------------------------------+ | +-------------------------------+ | |||
| Literal Header Field Without Name Reference | Literal Header Field Without Name Reference | |||
| 5. Configuration | ||||
| QPACK defines two settings which are included in the HTTP/3 SETTINGS | ||||
| frame. | ||||
| SETTINGS_HEADER_TABLE_SIZE (0x1): An integer with a maximum value of | ||||
| 2^30 - 1. The default value is zero bytes. See Section 3.2 for | ||||
| usage. | ||||
| SETTINGS_QPACK_BLOCKED_STREAMS (0x7): An integer with a maximum | ||||
| value of 2^16 - 1. The default value is zero. See Section 2.1.3. | ||||
| 6. Error Handling | 6. Error Handling | |||
| The following error codes are defined for HTTP/QUIC to indicate | The following error codes are defined for HTTP/3 to indicate failures | |||
| failures of QPACK which prevent the stream or connection from | of QPACK which prevent the stream or connection from continuing: | |||
| continuing: | ||||
| HTTP_QPACK_DECOMPRESSION_FAILED (TBD): The decoder failed to | HTTP_QPACK_DECOMPRESSION_FAILED (TBD): The decoder failed to | |||
| interpret an instruction on a request or push stream and is not | interpret an instruction on a request or push stream and is not | |||
| able to continue decoding that header block. | able to continue decoding that header block. | |||
| HTTP_QPACK_ENCODER_STREAM_ERROR (TBD): | ||||
| The decoder failed to interpret an instruction on the encoder | HTTP_QPACK_ENCODER_STREAM_ERROR (TBD): The decoder failed to | |||
| stream. HTTP_QPACK_DECODER_STREAM_ERROR (TBD): | interpret an instruction on the encoder stream. | |||
| The encoder failed to interpret an instruction on the decoder | HTTP_QPACK_DECODER_STREAM_ERROR (TBD): The encoder failed to | |||
| stream. | interpret an instruction on the decoder stream. | |||
| Upon encountering an error, an implementation MAY elect to treat it | Upon encountering an error, an implementation MAY elect to treat it | |||
| as a connection error even if this document prescribes that it MUST | as a connection error even if this document prescribes that it MUST | |||
| be treated as a stream error. | be treated as a stream error. | |||
| 7. Encoding Strategies | 7. Security Considerations | |||
| 7.1. Single Pass Encoding | ||||
| An encoder making a single pass over a list of headers must choose | ||||
| Base Index before knowing Largest Reference. When trying to | ||||
| reference a header inserted to the table after encoding has begun, | ||||
| the entry is encoded with different instructions that tell the | ||||
| decoder to use an absolute index greater than the Base Index. | ||||
| 7.2. Preventing Eviction Races | ||||
| Due to out-of-order arrival, QPACK's eviction algorithm requires | ||||
| changes (relative to HPACK) to avoid the possibility that an indexed | ||||
| representation is decoded after the referenced entry has already been | ||||
| evicted. QPACK employs a two-phase eviction algorithm, in which the | ||||
| encoder will not evict entries that have outstanding (unacknowledged) | ||||
| references. | ||||
| 7.3. Reference Tracking | ||||
| An encoder MUST ensure that a header block which references a dynamic | ||||
| table entry is not received by the decoder after the referenced entry | ||||
| has already been evicted. An encoder also respects the limit set by | ||||
| the decoder on the number of streams that are allowed to become | ||||
| blocked. Even if the decoder is willing to tolerate blocked streams, | ||||
| the encoder might choose to avoid them in certain cases. | ||||
| In order to enable this, the encoder will need to track outstanding | ||||
| (unacknowledged) header blocks and table updates using feedback | ||||
| received from the decoder. | ||||
| 7.3.1. Blocked Dynamic Table Insertions | ||||
| An encoder MUST NOT insert an entry into the dynamic table (or | ||||
| duplicate an existing entry) if doing so would evict an entry with | ||||
| unacknowledged references. For header blocks that might rely on the | ||||
| newly added entry, the encoder can use a literal representation and | ||||
| maybe insert the entry later. | ||||
| To ensure that the encoder is not prevented from adding new entries, | ||||
| the encoder can avoid referencing entries that will be evicted | ||||
| soonest. Rather than reference such an entry, the encoder SHOULD | ||||
| emit a Duplicate instruction (see Section 5.2.3), and reference the | ||||
| duplicate instead. | ||||
| Determining which entries are too close to eviction to reference is | ||||
| an encoder preference. One heuristic is to target a fixed amount of | ||||
| available space in the dynamic table: either unused space or space | ||||
| that can be reclaimed by evicting unreferenced entries. To achieve | ||||
| this, the encoder can maintain a draining index, which is the | ||||
| smallest absolute index in the dynamic table that it will emit a | ||||
| reference for. As new entries are inserted, the encoder increases | ||||
| the draining index to maintain the section of the table that it will | ||||
| not reference. Draining entries - entries with an absolute index | ||||
| lower than the draining index - will not accumulate new references. | ||||
| The number of unacknowledged references to draining entries will | ||||
| eventually become zero, making the entry available for eviction. | ||||
| +----------+---------------------------------+--------+ | ||||
| | Draining | Referenceable | Unused | | ||||
| | Entries | Entries | Space | | ||||
| +----------+---------------------------------+--------+ | ||||
| ^ ^ ^ | ||||
| | | | | ||||
| Dropping Draining Index Base Index / | ||||
| Point Insertion Point | ||||
| Figure 7: Draining Dynamic Table Entries | ||||
| 7.3.2. Blocked Decoding | ||||
| For header blocks encoded in non-blocking mode, the encoder needs to | ||||
| forego indexed representations that refer to table updates which have | ||||
| not yet been acknowledged (see Section 5.3). Since all table updates | ||||
| are processed in sequence on the control stream, an index into the | ||||
| dynamic table is sufficient to track which entries have been | ||||
| acknowledged. | ||||
| To track blocked streams, the necessary Base Index value for each | ||||
| stream can be used. Whenever the decoder processes a table update, | ||||
| it can begin decoding any blocked streams that now have their | ||||
| dependencies satisfied. | ||||
| 7.4. Speculative table updates | ||||
| Implementations can _speculatively_ send instructions on the encoder | ||||
| stream which are not needed for any current HTTP request or response. | ||||
| Such headers could be used strategically to improve performance. For | ||||
| instance, the encoder might decide to _refresh_ by sending Duplicate | ||||
| representations for popular header fields (Section 5.2.3), ensuring | ||||
| they have small indices and hence minimal size on the wire. | ||||
| 7.5. Sample One Pass Encoding Algorithm | ||||
| Pseudo-code for single pass encoding, excluding handling of | ||||
| duplicates, non-blocking mode, and reference tracking. | ||||
| baseIndex = dynamicTable.baseIndex | ||||
| largestReference = 0 | ||||
| for header in headers: | ||||
| staticIdx = staticTable.getIndex(header) | ||||
| if staticIdx: | ||||
| encodeIndexReference(streamBuffer, staticIdx) | ||||
| continue | ||||
| dynamicIdx = dynamicTable.getIndex(header) | ||||
| if !dynamicIdx: | ||||
| # No matching entry. Either insert+index or encode literal | ||||
| nameIdx = getNameIndex(header) | ||||
| if shouldIndex(header) and dynamicTable.canIndex(header): | ||||
| encodeLiteralWithIncrementalIndex(controlBuffer, nameIdx, | ||||
| header) | ||||
| dynamicTable.add(header) | ||||
| dynamicIdx = dynamicTable.baseIndex | ||||
| if !dynamicIdx: | ||||
| # Couldn't index it, literal | ||||
| if nameIdx <= staticTable.size: | ||||
| encodeLiteral(streamBuffer, nameIndex, header) | ||||
| else: | ||||
| # encode literal, possibly with nameIdx above baseIndex | ||||
| encodeDynamicLiteral(streamBuffer, nameIndex, baseIndex, | ||||
| header) | ||||
| largestReference = max(largestReference, | ||||
| dynamicTable.toAbsolute(nameIdx)) | ||||
| else: | ||||
| # Dynamic index reference | ||||
| assert(dynamicIdx) | ||||
| largestReference = max(largestReference, dynamicIdx) | ||||
| # Encode dynamicIdx, possibly with dynamicIdx above baseIndex | ||||
| encodeDynamicIndexReference(streamBuffer, dynamicIdx, | ||||
| baseIndex) | ||||
| # encode the prefix | ||||
| encodeInteger(prefixBuffer, 0x00, largestReference, 8) | ||||
| if baseIndex >= largestReference: | ||||
| encodeInteger(prefixBuffer, 0, baseIndex - largestReference, 7) | ||||
| else: | ||||
| encodeInteger(prefixBuffer, 0x80, | ||||
| largestReference - baseIndex, 7) | ||||
| return controlBuffer, prefixBuffer + streamBuffer | ||||
| 8. Security Considerations | ||||
| TBD. | TBD. | |||
| 9. IANA Considerations | 8. IANA Considerations | |||
| 9.1. Settings Registration | 8.1. Settings Registration | |||
| This document creates two new settings in the "HTTP/QUIC Settings" | This document creates two new settings in the "HTTP/3 Settings" | |||
| registry established in [QUIC-HTTP]. | registry established in [HTTP3]. | |||
| The entries in the following table are registered by this document. | The entries in the following table are registered by this document. | |||
| +-----------------------+------+---------------+ | +-----------------------+------+---------------+ | |||
| | Setting Name | Code | Specification | | | Setting Name | Code | Specification | | |||
| +-----------------------+------+---------------+ | +-----------------------+------+---------------+ | |||
| | HEADER_TABLE_SIZE | 0x1 | Section 4 | | | HEADER_TABLE_SIZE | 0x1 | Section 5 | | |||
| | | | | | | | | | | |||
| | QPACK_BLOCKED_STREAMS | 0x7 | Section 4 | | | QPACK_BLOCKED_STREAMS | 0x7 | Section 5 | | |||
| +-----------------------+------+---------------+ | +-----------------------+------+---------------+ | |||
| 9.2. Stream Type Registration | 8.2. Stream Type Registration | |||
| This document creates two new settings in the "HTTP/QUIC Stream Type" | This document creates two new settings in the "HTTP/3 Stream Type" | |||
| registry established in [QUIC-HTTP]. | registry established in [HTTP3]. | |||
| The entries in the following table are registered by this document. | The entries in the following table are registered by this document. | |||
| +----------------------+------+---------------+--------+ | +----------------------+------+---------------+--------+ | |||
| | Stream Type | Code | Specification | Sender | | | Stream Type | Code | Specification | Sender | | |||
| +----------------------+------+---------------+--------+ | +----------------------+------+---------------+--------+ | |||
| | QPACK Encoder Stream | 0x48 | Section 5 | Both | | | QPACK Encoder Stream | 0x48 | Section 4 | Both | | |||
| | | | | | | | | | | | | |||
| | QPACK Decoder Stream | 0x68 | Section 5 | Both | | | QPACK Decoder Stream | 0x68 | Section 4 | Both | | |||
| +----------------------+------+---------------+--------+ | +----------------------+------+---------------+--------+ | |||
| 9.3. Error Code Registration | 8.3. Error Code Registration | |||
| This document establishes the following new error codes in the "HTTP/ | This document establishes the following new error codes in the | |||
| QUIC Error Code" registry established in [QUIC-HTTP]. | "HTTP/3 Error Code" registry established in [HTTP3]. | |||
| +------------------------------+------+--------------+--------------+ | +------------------------------+------+--------------+--------------+ | |||
| | Name | Code | Description | Specificatio | | | Name | Code | Description | Specificatio | | |||
| | | | | n | | | | | | n | | |||
| +------------------------------+------+--------------+--------------+ | +------------------------------+------+--------------+--------------+ | |||
| | HTTP_QPACK_DECOMPRESSION_FAI | TBD | Decompressio | Section 6 | | | HTTP_QPACK_DECOMPRESSION_FAI | TBD | Decompressio | Section 6 | | |||
| | LED | | n of a | | | | LED | | n of a | | | |||
| | | | header block | | | | | | header block | | | |||
| | | | failed | | | | | | failed | | | |||
| | | | | | | | | | | | | |||
| | HTTP_QPACK_ENCODER_STREAM_ER | TBD | Error on the | Section 6 | | | HTTP_QPACK_ENCODER_STREAM_ER | TBD | Error on the | Section 6 | | |||
| | ROR | | encoder | | | | ROR | | encoder | | | |||
| | | | stream | | | | | | stream | | | |||
| | | | | | | | | | | | | |||
| | HTTP_QPACK_DECODER_STREAM_ER | TBD | Error on the | Section 6 | | | HTTP_QPACK_DECODER_STREAM_ER | TBD | Error on the | Section 6 | | |||
| | ROR | | decoder | | | | ROR | | decoder | | | |||
| | | | stream | | | | | | stream | | | |||
| +------------------------------+------+--------------+--------------+ | +------------------------------+------+--------------+--------------+ | |||
| 10. References | 9. References | |||
| 10.1. Normative References | 9.1. Normative References | |||
| [QUIC-HTTP] | [HTTP3] Bishop, M., Ed., "Hypertext Transfer Protocol Version 3 | |||
| Bishop, M., Ed., "Hypertext Transfer Protocol (HTTP) over | (HTTP/3)", draft-ietf-quic-http-16 (work in progress), | |||
| QUIC", draft-ietf-quic-http-15 (work in progress), October | December 2018. | |||
| 2018. | ||||
| [QUIC-TRANSPORT] | [QUIC-TRANSPORT] | |||
| Iyengar, J., Ed. and M. Thomson, Ed., "QUIC: A UDP-Based | Iyengar, J., Ed. and M. Thomson, Ed., "QUIC: A UDP-Based | |||
| Multiplexed and Secure Transport", draft-ietf-quic- | Multiplexed and Secure Transport", draft-ietf-quic- | |||
| transport-14 (work in progress), October 2018. | transport-16 (work in progress), December 2018. | |||
| [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate | [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate | |||
| Requirement Levels", BCP 14, RFC 2119, | Requirement Levels", BCP 14, RFC 2119, | |||
| DOI 10.17487/RFC2119, March 1997, | DOI 10.17487/RFC2119, March 1997, | |||
| <https://www.rfc-editor.org/info/rfc2119>. | <https://www.rfc-editor.org/info/rfc2119>. | |||
| [RFC7541] Peon, R. and H. Ruellan, "HPACK: Header Compression for | [RFC7541] Peon, R. and H. Ruellan, "HPACK: Header Compression for | |||
| HTTP/2", RFC 7541, DOI 10.17487/RFC7541, May 2015, | HTTP/2", RFC 7541, DOI 10.17487/RFC7541, May 2015, | |||
| <https://www.rfc-editor.org/info/rfc7541>. | <https://www.rfc-editor.org/info/rfc7541>. | |||
| [RFC8174] Leiba, B., "Ambiguity of Uppercase vs Lowercase in RFC | [RFC8174] Leiba, B., "Ambiguity of Uppercase vs Lowercase in RFC | |||
| 2119 Key Words", BCP 14, RFC 8174, DOI 10.17487/RFC8174, | 2119 Key Words", BCP 14, RFC 8174, DOI 10.17487/RFC8174, | |||
| May 2017, <https://www.rfc-editor.org/info/rfc8174>. | May 2017, <https://www.rfc-editor.org/info/rfc8174>. | |||
| 10.2. Informative References | 9.2. Informative References | |||
| [RFC2360] Scott, G., "Guide for Internet Standards Writers", BCP 22, | [RFC2360] Scott, G., "Guide for Internet Standards Writers", BCP 22, | |||
| RFC 2360, DOI 10.17487/RFC2360, June 1998, | RFC 2360, DOI 10.17487/RFC2360, June 1998, | |||
| <https://www.rfc-editor.org/info/rfc2360>. | <https://www.rfc-editor.org/info/rfc2360>. | |||
| [RFC7540] Belshe, M., Peon, R., and M. Thomson, Ed., "Hypertext | [RFC7540] Belshe, M., Peon, R., and M. Thomson, Ed., "Hypertext | |||
| Transfer Protocol Version 2 (HTTP/2)", RFC 7540, | Transfer Protocol Version 2 (HTTP/2)", RFC 7540, | |||
| DOI 10.17487/RFC7540, May 2015, | DOI 10.17487/RFC7540, May 2015, | |||
| <https://www.rfc-editor.org/info/rfc7540>. | <https://www.rfc-editor.org/info/rfc7540>. | |||
| 10.3. URIs | 9.3. URIs | |||
| [1] https://mailarchive.ietf.org/arch/search/?email_list=quic | [1] https://mailarchive.ietf.org/arch/search/?email_list=quic | |||
| [2] https://github.com/quicwg | [2] https://github.com/quicwg | |||
| [3] https://github.com/quicwg/base-drafts/labels/-qpack | [3] https://github.com/quicwg/base-drafts/labels/-qpack | |||
| Appendix A. Static Table | Appendix A. Static Table | |||
| +------+-----------------------------+------------------------------+ | +------+-----------------------------+------------------------------+ | |||
| skipping to change at page 33, line 5 ¶ | skipping to change at page 31, line 5 ¶ | |||
| | | | | | | | | | | |||
| | 95 | user-agent | | | | 95 | user-agent | | | |||
| | | | | | | | | | | |||
| | 96 | x-forwarded-for | | | | 96 | x-forwarded-for | | | |||
| | | | | | | | | | | |||
| | 97 | x-frame-options | deny | | | 97 | x-frame-options | deny | | |||
| | | | | | | | | | | |||
| | 98 | x-frame-options | sameorigin | | | 98 | x-frame-options | sameorigin | | |||
| +------+-----------------------------+------------------------------+ | +------+-----------------------------+------------------------------+ | |||
| Appendix B. Change Log | Appendix B. Sample One Pass Encoding Algorithm | |||
| Pseudo-code for single pass encoding, excluding handling of | ||||
| duplicates, non-blocking mode, and reference tracking. | ||||
| baseIndex = dynamicTable.baseIndex | ||||
| largestReference = 0 | ||||
| for header in headers: | ||||
| staticIdx = staticTable.getIndex(header) | ||||
| if staticIdx: | ||||
| encodeIndexReference(streamBuffer, staticIdx) | ||||
| continue | ||||
| dynamicIdx = dynamicTable.getIndex(header) | ||||
| if !dynamicIdx: | ||||
| # No matching entry. Either insert+index or encode literal | ||||
| nameIdx = getNameIndex(header) | ||||
| if shouldIndex(header) and dynamicTable.canIndex(header): | ||||
| encodeLiteralWithIncrementalIndex(controlBuffer, nameIdx, | ||||
| header) | ||||
| dynamicTable.add(header) | ||||
| dynamicIdx = dynamicTable.baseIndex | ||||
| if !dynamicIdx: | ||||
| # Couldn't index it, literal | ||||
| if nameIdx <= staticTable.size: | ||||
| encodeLiteral(streamBuffer, nameIndex, header) | ||||
| else: | ||||
| # encode literal, possibly with nameIdx above baseIndex | ||||
| encodeDynamicLiteral(streamBuffer, nameIndex, baseIndex, | ||||
| header) | ||||
| largestReference = max(largestReference, | ||||
| dynamicTable.toAbsolute(nameIdx)) | ||||
| else: | ||||
| # Dynamic index reference | ||||
| assert(dynamicIdx) | ||||
| largestReference = max(largestReference, dynamicIdx) | ||||
| # Encode dynamicIdx, possibly with dynamicIdx above baseIndex | ||||
| encodeDynamicIndexReference(streamBuffer, dynamicIdx, | ||||
| baseIndex) | ||||
| # encode the prefix | ||||
| encodeInteger(prefixBuffer, 0x00, largestReference, 8) | ||||
| if baseIndex >= largestReference: | ||||
| encodeInteger(prefixBuffer, 0, baseIndex - largestReference, 7) | ||||
| else: | ||||
| encodeInteger(prefixBuffer, 0x80, | ||||
| largestReference - baseIndex, 7) | ||||
| return controlBuffer, prefixBuffer + streamBuffer | ||||
| Appendix C. Change Log | ||||
| *RFC Editor's Note:* Please remove this section prior to | *RFC Editor's Note:* Please remove this section prior to | |||
| publication of a final version of this document. | publication of a final version of this document. | |||
| B.1. Since draft-ietf-quic-qpack-02 | C.1. Since draft-ietf-quic-qpack-03 | |||
| Substantial editorial reorganization; no technical changes. | ||||
| C.2. Since draft-ietf-quic-qpack-02 | ||||
| o Largest Reference encoded modulo MaxEntries (#1763) | o Largest Reference encoded modulo MaxEntries (#1763) | |||
| o New Static Table (#1355) | o New Static Table (#1355) | |||
| o Table Size Update with Insert Count=0 is a connection error | o Table Size Update with Insert Count=0 is a connection error | |||
| (#1762) | (#1762) | |||
| o Stream Cancellations are optional when | o Stream Cancellations are optional when | |||
| SETTINGS_HEADER_TABLE_SIZE=0 (#1761) | SETTINGS_HEADER_TABLE_SIZE=0 (#1761) | |||
| skipping to change at page 33, line 32 ¶ | skipping to change at page 33, line 36 ¶ | |||
| o Implementations must handle 62 bit integers (#1760) | o Implementations must handle 62 bit integers (#1760) | |||
| o Different error types for each QPACK stream, other changes to | o Different error types for each QPACK stream, other changes to | |||
| error handling (#1726) | error handling (#1726) | |||
| o Preserve header field order (#1725) | o Preserve header field order (#1725) | |||
| o Initial table size is the maximum permitted when table is first | o Initial table size is the maximum permitted when table is first | |||
| usable (#1642) | usable (#1642) | |||
| B.2. Since draft-ietf-quic-qpack-01 | C.3. Since draft-ietf-quic-qpack-01 | |||
| o Only header blocks that reference the dynamic table are | o Only header blocks that reference the dynamic table are | |||
| acknowledged (#1603, #1605) | acknowledged (#1603, #1605) | |||
| B.3. Since draft-ietf-quic-qpack-00 | C.4. Since draft-ietf-quic-qpack-00 | |||
| o Renumbered instructions for consistency (#1471, #1472) | o Renumbered instructions for consistency (#1471, #1472) | |||
| o Decoder is allowed to validate largest reference (#1404, #1469) | o Decoder is allowed to validate largest reference (#1404, #1469) | |||
| o Header block acknowledgments also acknowledge the associated | o Header block acknowledgments also acknowledge the associated | |||
| largest reference (#1370, #1400) | largest reference (#1370, #1400) | |||
| o Added an acknowledgment for unread streams (#1371, #1400) | o Added an acknowledgment for unread streams (#1371, #1400) | |||
| skipping to change at page 33, line 49 ¶ | skipping to change at page 34, line 4 ¶ | |||
| o Renumbered instructions for consistency (#1471, #1472) | o Renumbered instructions for consistency (#1471, #1472) | |||
| o Decoder is allowed to validate largest reference (#1404, #1469) | o Decoder is allowed to validate largest reference (#1404, #1469) | |||
| o Header block acknowledgments also acknowledge the associated | o Header block acknowledgments also acknowledge the associated | |||
| largest reference (#1370, #1400) | largest reference (#1370, #1400) | |||
| o Added an acknowledgment for unread streams (#1371, #1400) | o Added an acknowledgment for unread streams (#1371, #1400) | |||
| o Removed framing from encoder stream (#1361,#1467) | o Removed framing from encoder stream (#1361,#1467) | |||
| o Control streams use typed unidirectional streams rather than fixed | o Control streams use typed unidirectional streams rather than fixed | |||
| stream IDs (#910,#1359) | stream IDs (#910,#1359) | |||
| B.4. Since draft-ietf-quic-qcram-00 | C.5. Since draft-ietf-quic-qcram-00 | |||
| o Separate instruction sets for table updates and header blocks | o Separate instruction sets for table updates and header blocks | |||
| (#1235, #1142, #1141) | (#1235, #1142, #1141) | |||
| o Reworked indexing scheme (#1176, #1145, #1136, #1130, #1125, | o Reworked indexing scheme (#1176, #1145, #1136, #1130, #1125, | |||
| #1314) | #1314) | |||
| o Added mechanisms that support one-pass encoding (#1138, #1320) | o Added mechanisms that support one-pass encoding (#1138, #1320) | |||
| o Added a setting to control the number of blocked decoders (#238, | o Added a setting to control the number of blocked decoders (#238, | |||
| End of changes. 122 change blocks. | ||||
| 531 lines changed or deleted | 545 lines changed or added | |||
This html diff was produced by rfcdiff 1.45. The latest version is available from http://tools.ietf.org/tools/rfcdiff/ | ||||