From 16b12a1647378d8067381dbf7973ee543c85b5fc Mon Sep 17 00:00:00 2001 From: Martin Thomson Date: Thu, 27 Jul 2017 15:41:03 +1000 Subject: [PATCH 1/5] Define a Push ID --- draft-ietf-quic-http.md | 285 ++++++++++++++++++++++++++++++---------- 1 file changed, 212 insertions(+), 73 deletions(-) diff --git a/draft-ietf-quic-http.md b/draft-ietf-quic-http.md index 35b5539eb3..c31802ea34 100644 --- a/draft-ietf-quic-http.md +++ b/draft-ietf-quic-http.md @@ -216,7 +216,7 @@ Since most connection-level concerns will be managed by QUIC, the primary use of Stream 1 will be for the SETTINGS frame when the connection opens and for PRIORITY frames subsequently. -## HTTP Message Exchanges +## HTTP Message Exchanges {#request-response} A client sends an HTTP request on a new QUIC stream. A server sends an HTTP response on the same stream as the request. @@ -313,15 +313,23 @@ as a stream error of type HTTP_CONNECT_ERROR ({{http-error-codes}}). Correspondingly, a proxy MUST send a TCP segment with the RST bit set if it detects an error with the stream or the QUIC connection. -## Stream Priorities {#priority} +## Request Prioritization {#priority} HTTP/QUIC uses the priority scheme described in {{!RFC7540}}, Section 5.3. In -this priority scheme, a given stream can be designated as dependent upon another -stream, which expresses the preference that the latter stream (the "parent" -stream) be allocated resources before the former stream (the "dependent" -stream). Taken together, the dependencies across all streams in a connection -form a dependency tree. The structure of the dependency tree changes as PRIORITY -frames add, remove, or change the dependency links between streams. +this priority scheme, a given request can be designated as dependent upon +another request, which expresses the preference that the latter stream (the +"parent" request) be allocated resources before the former stream (the +"dependent" request). Taken together, the dependencies across all requests in a +connection form a dependency tree. The structure of the dependency tree changes +as PRIORITY frames add, remove, or change the dependency links between requests. + +HTTP/2 defines its priorities in terms of streams whereas HTTP over QUIC +identifies requests. The PRIORITY frame {{frame-priority}} identifies a request +either by identifying the stream that carries a request or by using a Push ID +({{frame-push-promise}}). Other than the means of identifying requests, the +prioritization system is identical to that in HTTP/2. + +Only a client can prioritize requests. A server MUST NOT send a PRIORITY frame. ## Server Push @@ -332,15 +340,36 @@ pushes via the SETTINGS_ENABLE_PUSH setting in the SETTINGS frame (see {{connection-establishment}}), which is disabled by default. As with server push for HTTP/2, the server initiates a server push by sending a -PUSH_PROMISE frame containing the Stream ID of the stream to be pushed, as well -as request header fields attributed to the request. The PUSH_PROMISE frame is -sent on the stream of the associated (client-initiated) request, while the -Promised Stream ID field specifies the Stream ID of the server-initiated -request. - -The server push response is conveyed in the same way as a non-server-push -response, with response headers and (if present) trailers carried by HEADERS -frames, and response body (if any) carried by DATA frames. +PUSH_PROMISE frame that includes request header fields attributed to the +request. The PUSH_PROMISE frame is sent on a response stream. Unlike HTTP/2, +the PUSH_PROMISE does not reference a stream; when a server fulfills a promise, +the stream that carries the stream headers references the PUSH_PROMISE. This +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}}). + +~~~~~ + 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) | ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +~~~~~ +{: #fig-push-stream-header title="Push Stream Header"} + +Each Push ID MUST only be used once in a push stream header. If a push stream +header includes a Push ID that was used in another push stream header, the +client MUST treat this as a connection error of type HTTP_DUPLICATE_PUSH. The +same Push ID can be used in multiple PUSH_PROMISE frames (see +{{frame-push-promise}}). + +After the push stream header, a push contains a response ({{request-response}}), +with response headers and (if present) trailers carried by HEADERS frames sent +on the control stream, and response body (if any) carried by DATA frames. If a promised push stream is not needed by the client, the client SHOULD send a QUIC STOP_SENDING on the promised stream with an appropriate error code (e.g. @@ -348,7 +377,8 @@ HTTP_PUSH_REFUSED, HTTP_PUSH_ALREADY_IN_CACHE; see {{errors}}). This asks the server not to transfer the data and indicates that it will be discarded upon receipt. -# HTTP Framing Layer + +# HTTP Framing Layer {#http-framing-layer} Frames are used on each stream. This section describes HTTP framing in QUIC and highlights some differences from HTTP/2 framing. For more detail on differences @@ -408,15 +438,28 @@ without EHB set, followed by a HEADERS frame with EHB set. ### PRIORITY {#frame-priority} The PRIORITY (type=0x02) frame specifies the sender-advised priority of a stream -and is substantially different from {{!RFC7540}}. In order to support ordering, -it MUST be sent only on the control stream. The format has been modified to -accommodate not being sent on-stream and the larger stream ID space of QUIC. +and is substantially different in format from {{!RFC7540}}. In order to ensure +that prioritization is processed in a consistent order, PRIORITY frames MUST be +sent on the control stream. A PRIORITY frame sent on any other stream MUST be +treated as a HTTP_WRONG_STREAM error. -The semantics of the Stream Dependency, Weight, and E flag are the same as in -HTTP/2. +The format has been modified to accommodate not being sent on a request stream, +to allow for identification of server pushes, and the larger stream ID space of +QUIC. The semantics of the Stream Dependency, Weight, and E flag are otherwise +the same as in HTTP/2. The flags defined are: + PUSH_PRIORITIZED (0x04): + : Indicates that the Prioritized Stream is a server push rather than a + request. If set, this flag indicates that the Prioritized Stream identifies + a response stream and the Promise Index field is present. + + PUSH_DEPENDENT (0x02): + : Indicates a dependency on a pushed request. If set, this flag indicates + that the Dependent Stream identifies a response stream and that the + Dependent Promise Index field is present. + E (0x01): : Indicates that the stream dependency is exclusive (see {{!RFC7540}}, Section 5.3). @@ -425,9 +468,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 Stream (32) | + | Prioritized Request (32) | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Dependent Stream (32) | + | Dependent Request (32) | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Weight (8) | +-+-+-+-+-+-+-+-+ @@ -436,29 +479,94 @@ The flags defined are: The PRIORITY frame payload has the following fields: - Prioritized Stream: - : A 32-bit stream identifier for the request stream whose priority is being - updated. + Prioritized Request: + : 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 + flag is set. Stream Dependency: - : A 32-bit stream identifier for the request stream that this stream depends - on (see {{priority}} and {{!RFC7540}}, Section 5.3). + : 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). Weight: : An unsigned 8-bit integer representing a priority weight for the stream (see {{!RFC7540}}, Section 5.3). Add one to the value to obtain a weight between 1 and 256. +A PRIORITY frame identifies a request to priotize, and a request upon which that +request is dependent. A request is identified by the stream ID of a request +when the corresponding PUSH_PRIORITIZED or PUSH_DEPENDENT flag is not set. +Setting the PUSH or PUSH_DEPENDENT flag causes the frame to identify a +PUSH_PROMISE using a Push ID (see {{frame-push-promise}} for details). + +A PRIORITY frame MAY identify no request by using a stream ID of 0; as in +{{!RFC7540}}, this makes the request dependent on the root of the dependency +tree. + A PRIORITY frame MAY identify a dependent stream with a stream ID of 0; as in {{!RFC7540}}, this makes the request dependent on the root of the dependency tree. Stream ID 0 and stream ID 1 cannot be reprioritized; an attempt to reprioritize these stream MUST be treated as a connection error of type HTTP_MALFORMED_PRIORITY. +A PRIORITY frame that does not reference a request MUST be treated as a +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. +### CANCEL_REQUEST {#frame-cancel-request} + +The CANCEL_REQUEST frame (type=0x3) is used to request cancellation of a request +prior to the response stream being created. This frame can be used to cancel +server push requests that are initiated with a PUSH_PROMISE. + +The CANCEL_REQUEST frame identifies a server push request by Push ID (see +{{frame-push-promise}}). + +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 +push, it can use the receipt of a CANCEL_REQUEST frame to avoid opening a +stream. If the push stream has been opened by the server, the server SHOULD +sent a QUIC RST_STREAM frame on those streams and cease transmission of the +response. + +A server can send this frame to indicate that it won't be sending a response +prior to creation of a push stream. Once the push stream has been created, a +RST_STREAM with a CANCELLED code can be used instead. + +A CANCEL_REQUEST frame is sent on the control stream. Sending a CANCEL_REQUEST +frame on a stream other than the control stream MUST be treated as a +HTTP_WRONG_STREAM error. + +The CANCEL_REQUEST frame has no defined flags. + +~~~~~~~~~~ drawing + 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) | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +~~~~~~~~~~ +{: #fig-cancel-request title="CANCEL_REQUEST frame payload"} + +The CANCEL_REQUEST frame payload has the following fields: + + Push ID: + : A 32-bit Push ID that identifies the request (see {{frame-push-promise}}). + +A CANCEL_REQUEST frame always contains a four octet payload. A server MUST +treat a CANCEL_REQUEST frame payload that is other than 4 octets in length, or a +CANCEL_REQUEST frame that identifies an unknown Push ID as an +HTTP_MALFORMED_CANCEL_REQUEST error. + + ### SETTINGS {#frame-settings} The SETTINGS frame (type=0x4) conveys configuration parameters that affect how @@ -571,16 +679,17 @@ are safe to retry are sent in 0-RTT.) If the connection was closed before the SETTINGS frame was received, clients SHOULD discard any cached values and use the defaults above on the next connection. + ### PUSH_PROMISE {#frame-push-promise} The PUSH_PROMISE frame (type=0x05) is used to carry a request header set from -server to client, as in HTTP/2. It defines no flags. +server to client, as in HTTP/2. The PUSH_PROMISE frame defines no flags. ~~~~~~~~~~ drawing 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 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Promised Stream ID (32) | + | Push ID (32) | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Header Block (*) ... +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ @@ -589,12 +698,35 @@ server to client, as in HTTP/2. It defines no flags. The payload consists of: - Promised Stream ID: - : A 32-bit Stream ID indicating the QUIC stream on which the response will be - sent - - Payload: - : HPACK-compressed request headers for the promised response. +Push ID: +: A 32-bit identifier for the server push request. This identifier is used in + push stream header ({{server-push}}), CANCEL_REQUEST frames + ({{frame-cancel-request}}), and PRIORITY frames ({{frame-priority}}) to + identify this request. + +Header Block: +: HPACK-compressed request headers for the promised response. + +A server MAY use the same Push ID in multiple PUSH_PROMISE frames. This allows +the server to use the same server push in response to multiple concurrent +requests. Referencing the same server push ensures that a PUSH_PROMISE can be +made in relation to every response in which server push might be needed without +causing duplicating pushes. + +A server that uses the same Push ID in multiple PUSH_PROMISE frames MUST include +the same header fields each time. The octets of the header block MAY be +different due to differing encoding, but the header fields and their values MUST +be identical. Note that ordering of header fields is significant. A client +MUST treat receipt of a PUSH_PROMISE with conflicting header field values for +the same Push ID as a connection error of type HTTP_MALFORMED_PUSH_PROMISE. + +A server SHOULD avoid sending a PUSH_PROMISE that includes a Push ID that was +fulfilled prior to the request being made. Though a client needs to handle +receiving a promised response prior to it being promised due to reordering of +stream delivery, clients might be unable to reuse a pushed response that was +long since consumed. \[Editor's Note: should we include a count of the number of +promises that a push fulfils in the push stream header? That would remove this +problem.] ### GOAWAY {#frame-goaway} @@ -746,6 +878,9 @@ HTTP_SETTINGS_ON_WRONG_STREAM (0x0F): HTTP_MULTIPLE_SETTINGS (0x10): : More than one SETTINGS frame was received. +HTTP_DUPLICATE_PUSH (0x11): +: Multiple push streams used the same Push ID. + # Considerations for Transitioning from HTTP/2 @@ -817,14 +952,17 @@ PRIORITY (0x2): RST_STREAM (0x3): : RST_STREAM frames do not exist, since QUIC provides stream lifecycle - management. + management. The same code point is used for the CANCEL_REQUEST frame + ({{frame-cancel-request}}). SETTINGS (0x4): : SETTINGS frames are sent only at the beginning of the connection. See {{frame-settings}} and {{h2-settings}}. PUSH_PROMISE (0x5): -: See {{frame-push-promise}}. +: The PUSH_PROMISE does not reference the stream that carries the response to + the pushed request; instead the push stream references the PUSH_PROMISE frame. + See {{frame-push-promise}}. PING (0x6): : PING frames do not exist, since QUIC provides equivalent functionality. @@ -1012,20 +1150,20 @@ Specification: The entries in the following table are registered by this document. - |---------------|------|-------------------------| - | Frame Type | Code | Specification | - |---------------|:----:|-------------------------| - | DATA | 0x0 | {{frame-data}} | - | HEADERS | 0x1 | {{frame-headers}} | - | PRIORITY | 0x2 | {{frame-priority}} | - | Reserved | 0x3 | N/A | - | SETTINGS | 0x4 | {{frame-settings}} | - | PUSH_PROMISE | 0x5 | {{frame-push-promise}} | - | Reserved | 0x6 | N/A | - | GOAWAY | 0x7 | {{frame-goaway}} | - | Reserved | 0x8 | N/A | - | Reserved | 0x9 | N/A | - |---------------|------|-------------------------| +|----------------|------|--------------------------| +| Frame Type | Code | Specification | +|----------------|:----:|--------------------------| +| DATA | 0x0 | {{frame-data}} | +| HEADERS | 0x1 | {{frame-headers}} | +| PRIORITY | 0x2 | {{frame-priority}} | +| CANCEL_REQUEST | 0x3 | {{frame-cancel-request}} | +| SETTINGS | 0x4 | {{frame-settings}} | +| PUSH_PROMISE | 0x5 | {{frame-push-promise}} | +| Reserved | 0x6 | N/A | +| GOAWAY | 0x7 | {{frame-goaway}} | +| Reserved | 0x8 | N/A | +| Reserved | 0x9 | N/A | +|----------------|------|--------------------------| ## Settings Parameters {#iana-settings} @@ -1095,25 +1233,26 @@ Specification: The entries in the following table are registered by this document. -|-----------------------------------|--------|----------------------------------------------|------------------------| -| Name | Code | Description | Specification | -|-----------------------------------|--------|----------------------------------------------|------------------------| -| HTTP_PUSH_REFUSED | 0x01 | Client refused pushed content | {{http-error-codes}} | -| HTTP_INTERNAL_ERROR | 0x02 | Internal error | {{http-error-codes}} | -| HTTP_PUSH_ALREADY_IN_CACHE | 0x03 | Pushed content already cached | {{http-error-codes}} | -| HTTP_REQUEST_CANCELLED | 0x04 | Data no longer needed | {{http-error-codes}} | -| HTTP_HPACK_DECOMPRESSION_FAILED | 0x05 | HPACK cannot continue | {{http-error-codes}} | -| HTTP_CONNECT_ERROR | 0x06 | TCP reset or error on CONNECT request | {{http-error-codes}} | -| HTTP_EXCESSIVE_LOAD | 0x07 | Peer generating excessive load | {{http-error-codes}} | -| HTTP_VERSION_FALLBACK | 0x08 | Retry over HTTP/2 | {{http-error-codes}} | -| HTTP_MALFORMED_HEADERS | 0x09 | Invalid HEADERS frame | {{http-error-codes}} | -| HTTP_MALFORMED_PRIORITY | 0x0A | Invalid PRIORITY frame | {{http-error-codes}} | -| HTTP_MALFORMED_SETTINGS | 0x0B | Invalid SETTINGS frame | {{http-error-codes}} | -| HTTP_MALFORMED_PUSH_PROMISE | 0x0C | Invalid PUSH_PROMISE frame | {{http-error-codes}} | -| HTTP_INTERRUPTED_HEADERS | 0x0E | Incomplete HEADERS block | {{http-error-codes}} | -| HTTP_SETTINGS_ON_WRONG_STREAM | 0x0F | SETTINGS frame on a request control stream | {{http-error-codes}} | -| HTTP_MULTIPLE_SETTINGS | 0x10 | Multiple SETTINGS frames | {{http-error-codes}} | -|-----------------------------------|--------|----------------------------------------------|------------------------| +|-----------------------------------|--------|----------------------------------------|----------------------| +| Name | Code | Description | Specification | +|-----------------------------------|--------|----------------------------------------|----------------------| +| HTTP_PUSH_REFUSED | 0x01 | Client refused pushed content | {{http-error-codes}} | +| HTTP_INTERNAL_ERROR | 0x02 | Internal error | {{http-error-codes}} | +| HTTP_PUSH_ALREADY_IN_CACHE | 0x03 | Pushed content already cached | {{http-error-codes}} | +| HTTP_REQUEST_CANCELLED | 0x04 | Data no longer needed | {{http-error-codes}} | +| HTTP_HPACK_DECOMPRESSION_FAILED | 0x05 | HPACK cannot continue | {{http-error-codes}} | +| HTTP_CONNECT_ERROR | 0x06 | TCP reset or error on CONNECT request | {{http-error-codes}} | +| HTTP_EXCESSIVE_LOAD | 0x07 | Peer generating excessive load | {{http-error-codes}} | +| HTTP_VERSION_FALLBACK | 0x08 | Retry over HTTP/2 | {{http-error-codes}} | +| HTTP_MALFORMED_HEADERS | 0x09 | Invalid HEADERS frame | {{http-error-codes}} | +| HTTP_MALFORMED_PRIORITY | 0x0A | Invalid PRIORITY frame | {{http-error-codes}} | +| HTTP_MALFORMED_SETTINGS | 0x0B | Invalid SETTINGS frame | {{http-error-codes}} | +| HTTP_MALFORMED_PUSH_PROMISE | 0x0C | Invalid PUSH_PROMISE frame | {{http-error-codes}} | +| HTTP_INTERRUPTED_HEADERS | 0x0E | Incomplete HEADERS block | {{http-error-codes}} | +| HTTP_WRONG_STREAM | 0x0F | A frame was sent on the wrong stream | {{http-error-codes}} | +| HTTP_MULTIPLE_SETTINGS | 0x10 | Multiple SETTINGS frames | {{http-error-codes}} | +| HTTP_DUPLICATE_PUSH | 0x11 | Duplicate server push | {{http-error-codes}} | +|-----------------------------------|--------|----------------------------------------|----------------------| --- back From 4b3fb33da81b1c919577ba0c22f98d54e9d579c0 Mon Sep 17 00:00:00 2001 From: Martin Thomson Date: Mon, 31 Jul 2017 11:50:32 +1000 Subject: [PATCH 2/5] Mike's editorial comments --- draft-ietf-quic-http.md | 96 +++++++++++++++++------------------------ 1 file changed, 40 insertions(+), 56 deletions(-) diff --git a/draft-ietf-quic-http.md b/draft-ietf-quic-http.md index c31802ea34..35388a0624 100644 --- a/draft-ietf-quic-http.md +++ b/draft-ietf-quic-http.md @@ -368,14 +368,14 @@ same Push ID can be used in multiple PUSH_PROMISE frames (see {{frame-push-promise}}). After the push stream header, a push contains a response ({{request-response}}), -with response headers and (if present) trailers carried by HEADERS frames sent -on the control stream, and response body (if any) carried by DATA frames. +with response headers, a response body (if any) carried by DATA frames, then +trailers (if any) carried by HEADERS frames. -If a promised push stream is not needed by the client, the client SHOULD send a -QUIC STOP_SENDING on the promised stream with an appropriate error code (e.g. -HTTP_PUSH_REFUSED, HTTP_PUSH_ALREADY_IN_CACHE; see {{errors}}). This asks the -server not to transfer the data and indicates that it will be discarded upon -receipt. +If a promised server push is not needed by the client, the client SHOULD send a +CANCEL_PUSH frame; if the push stream is already open, a QUIC STOP_SENDING frame +with an appropriate error code can be used instead (e.g., HTTP_PUSH_REFUSED, +HTTP_PUSH_ALREADY_IN_CACHE; see {{errors}}). This asks the server not to +transfer the data and indicates that it will be discarded upon receipt. # HTTP Framing Layer {#http-framing-layer} @@ -452,13 +452,10 @@ The flags defined are: PUSH_PRIORITIZED (0x04): : Indicates that the Prioritized Stream is a server push rather than a - request. If set, this flag indicates that the Prioritized Stream identifies - a response stream and the Promise Index field is present. + request. PUSH_DEPENDENT (0x02): - : Indicates a dependency on a pushed request. If set, this flag indicates - that the Dependent Stream identifies a response stream and that the - Dependent Promise Index field is present. + : Indicates a dependency on a server push. E (0x01): : Indicates that the stream dependency is exclusive (see {{!RFC7540}}, Section @@ -481,15 +478,15 @@ The PRIORITY frame payload has the following fields: Prioritized Request: : 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 - flag is set. + stream when the PUSH_PRIORITIZED flag is clear, or a Push ID when the + PUSH_PRIORITIZED flag is set. Stream Dependency: : 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). + see {{priority}} and {!RFC7540}}, Section 5.3. Weight: : An unsigned 8-bit integer representing a priority weight for the stream (see @@ -502,9 +499,9 @@ when the corresponding PUSH_PRIORITIZED or PUSH_DEPENDENT flag is not set. Setting the PUSH or PUSH_DEPENDENT flag causes the frame to identify a PUSH_PROMISE using a Push ID (see {{frame-push-promise}} for details). -A PRIORITY frame MAY identify no request by using a stream ID of 0; as in -{{!RFC7540}}, this makes the request dependent on the root of the dependency -tree. +A PRIORITY frame MAY identify no request in the Prioritized Request field by +using a stream ID of 0; as in {{!RFC7540}}, this makes the request dependent on +the root of the dependency tree. A PRIORITY frame MAY identify a dependent stream with a stream ID of 0; as in {{!RFC7540}}, this makes the request dependent on the root of the dependency @@ -521,50 +518,37 @@ 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. -### CANCEL_REQUEST {#frame-cancel-request} - -The CANCEL_REQUEST frame (type=0x3) is used to request cancellation of a request -prior to the response stream being created. This frame can be used to cancel -server push requests that are initiated with a PUSH_PROMISE. +### CANCEL_PUSH {#frame-cancel-push} -The CANCEL_REQUEST frame identifies a server push request by Push ID (see -{{frame-push-promise}}). +The CANCEL_PUSH frame (type=0x3) is used to request cancellation of server push +prior to the push stream being created. The CANCEL_REQUEST frame identifies a +server push request by Push ID (see {{frame-push-promise}}). 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 -push, it can use the receipt of a CANCEL_REQUEST frame to avoid opening a +push, it can use the receipt of a CANCEL_PUSH frame to avoid opening a stream. If the push stream has been opened by the server, the server SHOULD sent a QUIC RST_STREAM frame on those streams and cease transmission of the response. A server can send this frame to indicate that it won't be sending a response -prior to creation of a push stream. Once the push stream has been created, a -RST_STREAM with a CANCELLED code can be used instead. +prior to creation of a push stream. Once the push stream has been created, +sending CANCEL_PUSH has no effect on the state of the push stream. A QUIC +RST_STREAM frame SHOULD be used instead to cancel transmission of the server +push response. -A CANCEL_REQUEST frame is sent on the control stream. Sending a CANCEL_REQUEST -frame on a stream other than the control stream MUST be treated as a -HTTP_WRONG_STREAM error. - -The CANCEL_REQUEST frame has no defined flags. - -~~~~~~~~~~ drawing - 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) | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -~~~~~~~~~~ -{: #fig-cancel-request title="CANCEL_REQUEST frame payload"} +A CANCEL_PUSH frame is sent on the control stream. Sending a CANCEL_PUSH frame +on a stream other than the control stream MUST be treated as a stream error of +type HTTP_WRONG_STREAM. -The CANCEL_REQUEST frame payload has the following fields: +The CANCEL_PUSH frame has no defined flags. - Push ID: - : A 32-bit Push ID that identifies the request (see {{frame-push-promise}}). +The CANCEL_PUSH frame carries a 32-bit Push ID that identifies the server push +that is being cancelled (see {{frame-push-promise}}). -A CANCEL_REQUEST frame always contains a four octet payload. A server MUST -treat a CANCEL_REQUEST frame payload that is other than 4 octets in length, or a -CANCEL_REQUEST frame that identifies an unknown Push ID as an -HTTP_MALFORMED_CANCEL_REQUEST error. +A server MUST treat a CANCEL_PUSH frame payload that is other than 4 octets in +length, or a CANCEL_PUSH frame that identifies an unknown Push ID as a +connection error of type HTTP_MALFORMED_CANCEL_PUSH. ### SETTINGS {#frame-settings} @@ -699,10 +683,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. This identifier is used in - push stream header ({{server-push}}), CANCEL_REQUEST frames - ({{frame-cancel-request}}), and PRIORITY frames ({{frame-priority}}) to - identify this request. +: 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}}). Header Block: : HPACK-compressed request headers for the promised response. @@ -952,8 +935,8 @@ PRIORITY (0x2): RST_STREAM (0x3): : RST_STREAM frames do not exist, since QUIC provides stream lifecycle - management. The same code point is used for the CANCEL_REQUEST frame - ({{frame-cancel-request}}). + management. The same code point is used for the CANCEL_PUSH frame + ({{frame-cancel-push}}). SETTINGS (0x4): : SETTINGS frames are sent only at the beginning of the connection. See @@ -1156,7 +1139,7 @@ The entries in the following table are registered by this document. | DATA | 0x0 | {{frame-data}} | | HEADERS | 0x1 | {{frame-headers}} | | PRIORITY | 0x2 | {{frame-priority}} | -| CANCEL_REQUEST | 0x3 | {{frame-cancel-request}} | +| CANCEL_PUSH | 0x3 | {{frame-cancel-push}} | | SETTINGS | 0x4 | {{frame-settings}} | | PUSH_PROMISE | 0x5 | {{frame-push-promise}} | | Reserved | 0x6 | N/A | @@ -1273,6 +1256,7 @@ The original authors of this specification were Robbie Shade and Mike Warres. - Use separate frame type and settings registries from HTTP/2 (#81) - SETTINGS_ENABLE_PUSH instead of SETTINGS_DISABLE_PUSH (#477) - Restored GOAWAY (#696) +- Identify server push using Push ID rather than a stream ID (#702,#281) ## Since draft-ietf-quic-http-03 From 7343bd8abf9aad6a6f0732e2cb95d8d9ae380771 Mon Sep 17 00:00:00 2001 From: Martin Thomson Date: Thu, 3 Aug 2017 17:01:39 +1000 Subject: [PATCH 3/5] Editorial cleanup --- draft-ietf-quic-http.md | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/draft-ietf-quic-http.md b/draft-ietf-quic-http.md index 35388a0624..7a3233d48e 100644 --- a/draft-ietf-quic-http.md +++ b/draft-ietf-quic-http.md @@ -486,7 +486,7 @@ The PRIORITY frame payload has the following fields: 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. + see {{priority}} and {{!RFC7540}}, Section 5.3. Weight: : An unsigned 8-bit integer representing a priority weight for the stream (see @@ -499,14 +499,12 @@ when the corresponding PUSH_PRIORITIZED or PUSH_DEPENDENT flag is not set. Setting the PUSH or PUSH_DEPENDENT flag causes the frame to identify a PUSH_PROMISE using a Push ID (see {{frame-push-promise}} for details). -A PRIORITY frame MAY identify no request in the Prioritized Request field by -using a stream ID of 0; as in {{!RFC7540}}, this makes the request dependent on -the root of the dependency tree. - -A PRIORITY frame MAY identify a dependent stream with a stream ID of 0; as in +A PRIORITY frame MAY identify a Stream Dependency with a stream ID of 0; as in {{!RFC7540}}, this makes the request dependent on the root of the dependency -tree. Stream ID 0 and stream ID 1 cannot be reprioritized; an attempt to -reprioritize these stream MUST be treated as a connection error of type +tree. + +Stream ID 0 and stream ID 1 cannot be reprioritized. A Prioritized Request that +identifies Stream 0 or 1 MUST be treated as a connection error of type HTTP_MALFORMED_PRIORITY. A PRIORITY frame that does not reference a request MUST be treated as a @@ -521,7 +519,7 @@ length 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_REQUEST frame identifies a +prior to the push stream being created. The CANCEL_PUSH frame identifies a server push request by Push ID (see {{frame-push-promise}}). When a server receives this frame, it aborts sending the response for the From cb44d94019cfa2cc519f0394afbbcebcc2ab07a2 Mon Sep 17 00:00:00 2001 From: Martin Thomson Date: Fri, 4 Aug 2017 11:58:43 +1000 Subject: [PATCH 4/5] Edit's inspired by Jana's review --- draft-ietf-quic-http.md | 62 ++++++++++++++++++++++------------------- 1 file changed, 33 insertions(+), 29 deletions(-) diff --git a/draft-ietf-quic-http.md b/draft-ietf-quic-http.md index 7a3233d48e..75a9d7b62c 100644 --- a/draft-ietf-quic-http.md +++ b/draft-ietf-quic-http.md @@ -329,7 +329,8 @@ either by identifying the stream that carries a request or by using a Push ID ({{frame-push-promise}}). Other than the means of identifying requests, the prioritization system is identical to that in HTTP/2. -Only a client can prioritize requests. A server MUST NOT send a PRIORITY frame. +Only a client can send PRIORITY frames. A server MUST NOT send a PRIORITY +frame. ## Server Push @@ -465,9 +466,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 (32) | + | Prioritized Request ID (32) | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Dependent Request (32) | + | Stream Dependency ID (32) | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Weight (8) | +-+-+-+-+-+-+-+-+ @@ -476,12 +477,12 @@ The flags defined are: The PRIORITY frame payload has the following fields: - Prioritized Request: + 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. - Stream Dependency: + 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 @@ -494,17 +495,19 @@ The PRIORITY frame payload has the following fields: 1 and 256. A PRIORITY frame identifies a request to priotize, and a request upon which that -request is dependent. A request is identified by the stream ID of a request -when the corresponding PUSH_PRIORITIZED or PUSH_DEPENDENT flag is not set. -Setting the PUSH or PUSH_DEPENDENT flag causes the frame to identify a -PUSH_PROMISE using a Push ID (see {{frame-push-promise}} for details). - -A PRIORITY frame MAY identify a Stream Dependency with a stream ID of 0; as in -{{!RFC7540}}, this makes the request dependent on the root of the dependency +request is dependent. A Prioritized Request ID or Stream Dependency ID +identifies a client initiated request using the corresponding stream ID when the +corresponding PUSH_PRIORITIZED or PUSH_DEPENDENT flag is not set. Setting the +PUSH_PRIORITIZED or PUSH_DEPENDENT flag causes the Prioritized Request ID or +Stream Dependency ID (respectively) to identify a server push using a Push ID +(see {{frame-push-promise}} for details). + +A PRIORITY frame MAY identify a Stream Dependency ID using a stream ID of 0; as +in {{!RFC7540}}, this makes the request dependent on the root of the dependency tree. -Stream ID 0 and stream ID 1 cannot be reprioritized. A Prioritized Request that -identifies Stream 0 or 1 MUST be treated as a connection error of type +Stream ID 0 and stream ID 1 cannot be reprioritized. A Prioritized Request ID +that identifies Stream 0 or 1 MUST be treated as a connection error of type HTTP_MALFORMED_PRIORITY. A PRIORITY frame that does not reference a request MUST be treated as a @@ -544,17 +547,19 @@ 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}}). +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, or a CANCEL_PUSH frame that identifies an unknown Push ID as a -connection error of type HTTP_MALFORMED_CANCEL_PUSH. +length as a connection error of type HTTP_MALFORMED_CANCEL_PUSH. ### SETTINGS {#frame-settings} The SETTINGS frame (type=0x4) conveys configuration parameters that affect how endpoints communicate, such as preferences and constraints on peer behavior, and -is substantially different from {{!RFC7540}}. Individually, a SETTINGS parameter -can also be referred to as a "setting". +is different from {{!RFC7540}}. Individually, a SETTINGS parameter can also be +referred to as a "setting". SETTINGS parameters are not negotiated; they describe characteristics of the sending peer, which can be used by the receiving peer. However, a negotiation @@ -692,7 +697,7 @@ A server MAY use the same Push ID in multiple PUSH_PROMISE frames. This allows the server to use the same server push in response to multiple concurrent requests. Referencing the same server push ensures that a PUSH_PROMISE can be made in relation to every response in which server push might be needed without -causing duplicating pushes. +duplicating pushes. A server that uses the same Push ID in multiple PUSH_PROMISE frames MUST include the same header fields each time. The octets of the header block MAY be @@ -701,13 +706,12 @@ be identical. Note that ordering of header fields is significant. A client MUST treat receipt of a PUSH_PROMISE with conflicting header field values for the same Push ID as a connection error of type HTTP_MALFORMED_PUSH_PROMISE. -A server SHOULD avoid sending a PUSH_PROMISE that includes a Push ID that was -fulfilled prior to the request being made. Though a client needs to handle -receiving a promised response prior to it being promised due to reordering of -stream delivery, clients might be unable to reuse a pushed response that was -long since consumed. \[Editor's Note: should we include a count of the number of -promises that a push fulfils in the push stream header? That would remove this -problem.] +Allowing duplicate references to the same Push ID is primarily to reduce +duplication caused by concurrent requests. A server SHOULD avoid reusing a Push +ID over a long period. Clients are likely to consume server push responses and +not retain them for reuse over time. Clients that see a PUSH_PROMISE that uses +a Push ID that they have since consumed and discarded are forced to ignore the +PUSH_PROMISE. ### GOAWAY {#frame-goaway} @@ -941,9 +945,9 @@ SETTINGS (0x4): {{frame-settings}} and {{h2-settings}}. PUSH_PROMISE (0x5): -: The PUSH_PROMISE does not reference the stream that carries the response to - the pushed request; instead the push stream references the PUSH_PROMISE frame. - See {{frame-push-promise}}. +: The PUSH_PROMISE does not reference a stream; instead the push stream + references the PUSH_PROMISE frame using a Push ID. See + {{frame-push-promise}}. PING (0x6): : PING frames do not exist, since QUIC provides equivalent functionality. From d7b14bf0b4348dce65e80ed4a1bbe6f693733a6b Mon Sep 17 00:00:00 2001 From: Martin Thomson Date: Fri, 4 Aug 2017 16:58:01 +1000 Subject: [PATCH 5/5] hyphenate --- draft-ietf-quic-http.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/draft-ietf-quic-http.md b/draft-ietf-quic-http.md index 75a9d7b62c..d6aa01fcdd 100644 --- a/draft-ietf-quic-http.md +++ b/draft-ietf-quic-http.md @@ -496,7 +496,7 @@ The PRIORITY frame payload has the following fields: A PRIORITY frame identifies a request to priotize, and a request upon which that request is dependent. A Prioritized Request ID or Stream Dependency ID -identifies a client initiated request using the corresponding stream ID when the +identifies a client-initiated request using the corresponding stream ID when the corresponding PUSH_PRIORITIZED or PUSH_DEPENDENT flag is not set. Setting the PUSH_PRIORITIZED or PUSH_DEPENDENT flag causes the Prioritized Request ID or Stream Dependency ID (respectively) to identify a server push using a Push ID