From b1d50145ab9f0fbc2f4cc00908e4081814a9178f Mon Sep 17 00:00:00 2001 From: Martin Thomson Date: Wed, 18 Oct 2017 17:28:31 +1100 Subject: [PATCH 1/3] Maximal change for HTTP integer encoding This didn't turn out to be that disruptive. I'm somewhat worried that I missed something actually. Given that the changes are small, I think that I would prefer this over #887 for #877. The most interesting change here is that extension frame types that mention Stream IDs will have to change. I am not aware of any proposed thus far, so maybe it's not too much of a cost to bear. It further confirms my view that we shouldn't be using Stream IDs at this layer anyway. Based on this, I don't see any need for a middle-ground change. The biggest cost here is in taking the larger Stream ID space, not in taking the integer encoding. --- draft-ietf-quic-http.md | 103 ++++++++++++++++++++++++---------------- 1 file changed, 63 insertions(+), 40 deletions(-) diff --git a/draft-ietf-quic-http.md b/draft-ietf-quic-http.md index 074a2b8672..f8b7c63ad6 100644 --- a/draft-ietf-quic-http.md +++ b/draft-ietf-quic-http.md @@ -85,6 +85,9 @@ defined in {{!RFC2119}}. Field definitions are given in Augmented Backus-Naur Form (ABNF), as defined in {{!RFC5234}}. +This document uses the variable-length integer encoding from +{{QUIC-TRANSPORT}}. + # QUIC Advertisement @@ -362,7 +365,7 @@ This header consists of a 32-bit Push ID, which identifies a server push (see 0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -| Push ID (32) | +| Push ID (i) | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ~~~~~ {: #fig-push-stream-header title="Push Stream Header"} @@ -415,6 +418,9 @@ All frames have the following format: ~~~~~~~~~~ {: #fig-frame title="HTTP/QUIC frame format"} +Note that the first four octets of the frame use a fixed-size encoding; a +variable-length integer encoding is used for the contents of frames. + ## Frame Definitions {#frames} ### DATA {#frame-data} @@ -485,9 +491,9 @@ The flags defined are: 0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Prioritized Request ID (32) | + | Prioritized Request ID (i) | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Stream Dependency ID (32) | + | Stream Dependency ID (i) | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Weight (8) | +-+-+-+-+-+-+-+-+ @@ -497,16 +503,16 @@ The flags defined are: The PRIORITY frame payload has the following fields: Prioritized Request ID: - : A 32-bit identifier for a request. This contains the stream ID of a request - stream when the PUSH_PRIORITIZED flag is clear, or a Push ID when the - PUSH_PRIORITIZED flag is set. + : A variable-length integer that identifies a request. This contains + the Stream ID of a request stream when the PUSH_PRIORITIZED flag is clear, + or a Push ID when the PUSH_PRIORITIZED flag is set. Stream Dependency ID: - : A 32-bit stream identifier for a dependent request. This contains the - stream ID of a request stream when the PUSH_DEPENDENT flag is clear, or a - Push ID when the PUSH_DEPENDENT flag is set. A request stream ID of 0 - indicates a dependency on the root stream. For details of dependencies, - see {{priority}} and {{!RFC7540}}, Section 5.3. + : A variable length integer that identifies a dependent request. This + contains the Stream ID of a request stream when the PUSH_DEPENDENT flag is + clear, or a Push ID when the PUSH_DEPENDENT flag is set. A request Stream + ID of 0 indicates a dependency on the root stream. For details of + dependencies, see {{priority}} and {{!RFC7540}}, Section 5.3. Weight: : An unsigned 8-bit integer representing a priority weight for the stream (see @@ -534,15 +540,18 @@ HTTP_MALFORMED_PRIORITY error, unless it references stream ID 0. A PRIORITY that sets a PUSH_PRIORITIZED or PUSH_DEPENDENT flag, but then references a non-existent Push ID MUST be treated as a HTTP_MALFORMED_PRIORITY error. -The length of a PRIORITY frame is 9 octets. A PRIORITY frame with any other -length MUST be treated as a connection error of type HTTP_MALFORMED_PRIORITY. +A PRIORITY frame MUST contain only the identified fields. A PRIORITY frame that +contains more or fewer fields, or a PRIORITY frame that includes a truncated +integer encoding MUST be treated as a connection error of type +HTTP_MALFORMED_PRIORITY. ### CANCEL_PUSH {#frame-cancel-push} The CANCEL_PUSH frame (type=0x3) is used to request cancellation of server push prior to the push stream being created. The CANCEL_PUSH frame identifies a -server push request by Push ID (see {{frame-push-promise}}). +server push request by Push ID (see {{frame-push-promise}}) using a +variable-length integer. When a server receives this frame, it aborts sending the response for the identified server push. If the server has not yet started to send the server @@ -569,8 +578,9 @@ that is being cancelled (see {{frame-push-promise}}). If the client receives a CANCEL_PUSH frame, that frame might identify a Push ID that has not yet been mentioned by a PUSH_PROMISE frame. -A server MUST treat a CANCEL_PUSH frame payload that is other than 4 octets in -length as a connection error of type HTTP_MALFORMED_CANCEL_PUSH. +A server MUST treat a CANCEL_PUSH frame payload does not contain exactly one +variable-length integer as a connection error of type +HTTP_MALFORMED_CANCEL_PUSH. ### SETTINGS {#frame-settings} @@ -605,7 +615,7 @@ value. 0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Identifier (16) | Length (16) | + | Identifier (16) | Length (i) ... +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Contents (?) ... +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ @@ -638,20 +648,17 @@ HTTP_MALFORMED_SETTINGS. #### Integer encoding -Settings which are integers are transmitted in network byte order. Leading -zero octets are permitted, but implementations SHOULD use only as many bytes as -are needed to represent the value. An integer MUST NOT be represented in more -bytes than would be used to transfer the maximum permitted value. +Settings which are integers use the QUIC variable-length integer encoding. #### Defined SETTINGS Parameters {#settings-parameters} The following settings are defined in HTTP/QUIC: SETTINGS_HEADER_TABLE_SIZE (0x1): - : An integer with a maximum value of 2^32 - 1. This value MUST be zero. + : An integer with a maximum value of 2^30 - 1. This value MUST be zero. SETTINGS_MAX_HEADER_LIST_SIZE (0x6): - : An integer with a maximum value of 2^32 - 1 + : An integer with a maximum value of 2^30 - 1 #### Usage in 0-RTT @@ -691,7 +698,7 @@ server to client, as in HTTP/2. The PUSH_PROMISE frame defines no flags. 0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Push ID (32) | + | Push ID (i) ... +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Header Block (*) ... +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ @@ -701,9 +708,9 @@ server to client, as in HTTP/2. The PUSH_PROMISE frame defines no flags. The payload consists of: Push ID: -: A 32-bit identifier for the server push request. A push ID is used in push - stream header ({{server-push}}), CANCEL_PUSH frames ({{frame-cancel-push}}), - and PRIORITY frames ({{frame-priority}}). +: A variable-length integer that identifies the server push request. A push ID + is used in push stream header ({{server-push}}), CANCEL_PUSH frames + ({{frame-cancel-push}}), and PRIORITY frames ({{frame-priority}}). Header Block: : HPACK-compressed request headers for the promised response. @@ -743,10 +750,12 @@ administrative actions, like server maintenance. GOAWAY by itself does not close a connection. (Note that clients do not need to send GOAWAY to gracefully close a connection; they simply stop making new requests.) -The GOAWAY frame does not define any flags, and the payload is a QUIC stream -identifier. The GOAWAY frame applies to the connection, not a specific stream. -An endpoint MUST treat a GOAWAY frame on a stream other than the control stream -as a connection error ({{errors}}) of type HTTP_WRONG_STREAM. +The GOAWAY frame does not define any flags, and the payload is a QUIC Stream ID +encoded as a variable-length integer. + +The GOAWAY frame applies to the connection, not a specific stream. An endpoint +MUST treat a GOAWAY frame on a stream other than the control stream as a +connection error ({{errors}}) of type HTTP_WRONG_STREAM. New client requests might already have been sent before the client receives the server's GOAWAY frame. The GOAWAY frame contains the stream identifier of the @@ -841,14 +850,15 @@ sending a MAX_PUSH_ID frame as the server fulfills or cancels server pushes. The MAX_PUSH_ID frame has no defined flags. -The MAX_PUSH_ID frame carries a 32-bit Push ID that identifies the maximum value -for a Push ID that the server can use (see {{frame-push-promise}}). A -MAX_PUSH_ID frame cannot reduce the maximum Push ID; receipt of a MAX_PUSH_ID -that contains a smaller value than previously received MUST be treated as a -connection error of type HTTP_MALFORMED_MAX_PUSH_ID. +The MAX_PUSH_ID frame carries a single variable-length integer that identifies +the maximum value for a Push ID that the server can use (see +{{frame-push-promise}}). A MAX_PUSH_ID frame cannot reduce the maximum Push ID; +receipt of a MAX_PUSH_ID that contains a smaller value than previously received +MUST be treated as a connection error of type HTTP_MALFORMED_MAX_PUSH_ID. -A server MUST treat a MAX_PUSH_ID frame payload that is other than 4 octets in -length as a connection error of type HTTP_MALFORMED_MAX_PUSH_ID. +A server MUST treat a MAX_PUSH_ID frame payload that does not contain a single +variable-length integer as a connection error of type +HTTP_MALFORMED_MAX_PUSH_ID. # Connection Management @@ -966,6 +976,13 @@ applicable to both protocols at once. These departures are noted in this section. +## Streams {#h2-streams} + +HTTP/QUIC permits use of a larger number of streams (2^62-1) then HTTP/2. The +considerations about exhaustion of stream identifier space apply, though the +space is significantly larger such that it is likely that other limits in QUIC +are reached first, such asthe limit on the connection flow control window. + ## HTTP Frame Types {#h2-frames} Many framing concepts from HTTP/2 can be elided away on QUIC, because the @@ -999,7 +1016,13 @@ HEADERS frames. To achieve in-order delivery of priority changes in HTTP/QUIC, PRIORITY frames are sent on the control stream and the PRIORITY section is removed from the HEADERS frame. -Other than this issue, frame type HTTP/2 extensions are typically portable to +Frame type definitions in HTTP/QUIC often use the QUIC variable-length integer +encoding. In particular, Stream IDs use this encoding, which allow for a larger +range of possible values than the encoding used in HTTP/2. Redefinition of the +encoding of extension frame types might be necessary if the encoding includes a +Stream ID. + +Other than these issues, frame type HTTP/2 extensions are typically portable to QUIC simply by replacing Stream 0 in HTTP/2 with Stream 1 in HTTP/QUIC. HTTP/QUIC extensions will not assume ordering, but would not be harmed by ordering, and would be portable to HTTP/2 in the same manner. @@ -1342,7 +1365,7 @@ The original authors of this specification were Robbie Shade and Mike Warres. ## Since draft-ietf-quic-http-06 -Nothing yet. +- Changes for integer encodings in QUIC (#595) ## Since draft-ietf-quic-http-05 From d241018a4d2dff60509b573ed79a1b8a6bdf1f36 Mon Sep 17 00:00:00 2001 From: Martin Thomson Date: Thu, 19 Oct 2017 09:52:00 +1100 Subject: [PATCH 2/3] Missed a few fixed-size integers And a nit --- draft-ietf-quic-http.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/draft-ietf-quic-http.md b/draft-ietf-quic-http.md index f8b7c63ad6..e738d42776 100644 --- a/draft-ietf-quic-http.md +++ b/draft-ietf-quic-http.md @@ -358,8 +358,8 @@ allows a server to fulfill promises in the order that best suits its needs. The server push response is conveyed on a push stream. A push stream is a server-initiated stream. A push stream includes a header (see {{fig-push-stream-header}}) that identifies the PUSH_PROMISE that it fulfills. -This header consists of a 32-bit Push ID, which identifies a server push (see -{{frame-push-promise}}). +This header consists of a Push ID, encoded as a variable-length integer. The +Push ID identifies a server push (see {{frame-push-promise}}). ~~~~~ 0 1 2 3 @@ -370,9 +370,9 @@ This header consists of a 32-bit Push ID, which identifies a server push (see ~~~~~ {: #fig-push-stream-header title="Push Stream Header"} -A push stream always starts with a 32-bit Push ID. A client MUST treat -receiving a push stream that contains fewer than 4 octets as a connection error -of type HTTP_MALFORMED_PUSH. +A push stream always starts with a Push ID. A client MUST treat receiving a +push stream that contains a truncated variable-length integer as a connection +error of type HTTP_MALFORMED_PUSH. A server SHOULD use Push IDs sequentially, starting at 0. A client uses the MAX_PUSH_ID frame ({{frame-max-push-id}}) to limit the number of pushes that a @@ -981,7 +981,7 @@ These departures are noted in this section. HTTP/QUIC permits use of a larger number of streams (2^62-1) then HTTP/2. The considerations about exhaustion of stream identifier space apply, though the space is significantly larger such that it is likely that other limits in QUIC -are reached first, such asthe limit on the connection flow control window. +are reached first, such as the limit on the connection flow control window. ## HTTP Frame Types {#h2-frames} From 200926b69bf819db951b677f6042f9b6b4492b94 Mon Sep 17 00:00:00 2001 From: Martin Thomson Date: Thu, 19 Oct 2017 11:27:55 +1100 Subject: [PATCH 3/3] More fixed-size integer residue --- draft-ietf-quic-http.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/draft-ietf-quic-http.md b/draft-ietf-quic-http.md index e738d42776..adf73f3e83 100644 --- a/draft-ietf-quic-http.md +++ b/draft-ietf-quic-http.md @@ -572,8 +572,9 @@ type HTTP_WRONG_STREAM. The CANCEL_PUSH frame has no defined flags. -The CANCEL_PUSH frame carries a 32-bit Push ID that identifies the server push -that is being cancelled (see {{frame-push-promise}}). +The CANCEL_PUSH frame carries a Push ID encoded as a variable-length integer. +The Push ID identifies the server push that is being cancelled (see +{{frame-push-promise}}). If the client receives a CANCEL_PUSH frame, that frame might identify a Push ID that has not yet been mentioned by a PUSH_PROMISE frame.