New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Move GOAWAY from transport to HTTP #697
Changes from 2 commits
f0dcde1
c08f315
177db7c
d7d0bc2
56cce38
c7160d9
7989bc1
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -594,81 +594,60 @@ The payload consists of: | |
### GOAWAY {#frame-goaway} | ||
|
||
The GOAWAY frame (type=0x7) is used to initiate graceful shutdown of a | ||
connection. GOAWAY allows an endpoint to stop accepting new streams while still | ||
finishing processing of previously established streams. This enables | ||
administrative actions, like server maintenance. | ||
|
||
There is an inherent race condition between an endpoint starting new streams and | ||
the remote sending a GOAWAY frame. To deal with this case, the GOAWAY contains | ||
the stream identifier of the last peer-initiated stream that was or might be | ||
processed on the sending endpoint in this connection. For instance, if the | ||
server sends a GOAWAY frame, the identified stream is the highest-numbered | ||
stream initiated by the client. This MAY be lower than the stream limit | ||
identified by a QUIC MAX_STREAM_ID frame. | ||
|
||
Once sent, the sender will refuse requests sent on streams initiated by the | ||
receiver if the stream has an identifier higher than the included last stream | ||
identifier. Receivers of a GOAWAY frame MUST NOT send new requests on the | ||
connection, although a new connection can be established for new streams. | ||
|
||
If the receiver of the GOAWAY has sent requests on streams with a higher stream | ||
identifier than what is indicated in the GOAWAY frame, those streams are not or | ||
will not be processed. The receiver of the GOAWAY frame can treat the requests | ||
as though they had never been sent at all, thereby allowing those requests to be | ||
retried later on a new connection. Servers SHOULD treat requests on streams | ||
above this ID as stream errors of type HTTP_REQUEST_CANCELLED. | ||
|
||
Endpoints SHOULD send a GOAWAY frame when the closing of a connection is known | ||
in advance, even if the window is small, so that the remote peer can know | ||
whether a stream has been partially processed or not. For example, if an HTTP | ||
client sends a POST at the same time that a server closes a QUIC connection, the | ||
client cannot know if the server started to process that POST request if the | ||
server does not send a GOAWAY frame to indicate what streams it might have acted | ||
on. | ||
|
||
For unexpected closures caused by error conditions, transport-level mechanisms | ||
SHOULD be used. However, a GOAWAY MAY still be sent to provide additional | ||
detail to clients. | ||
|
||
~~~~~~~~~~ drawing | ||
+---------------------------------------------------------------+ | ||
| Last-Stream-ID (32) | | ||
+---------------------------------------------------------------+ | ||
| [Error Code (32)] | | ||
+---------------------------------------------------------------+ | ||
| [Additional Debug Data (*)] ... | ||
+---------------------------------------------------------------+ | ||
~~~~~~~~~~ | ||
{: #fig-goaway title="GOAWAY frame payload"} | ||
|
||
The GOAWAY frame does not define any flags. | ||
|
||
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 last stream identifier in the GOAWAY frame contains the highest-numbered | ||
stream identifier for which the sender of the GOAWAY frame might have taken some | ||
action on or might yet take action on. All streams up to and including the | ||
identified stream might have been processed in some way. The last stream | ||
identifier can be set to 0 if no streams were processed. | ||
|
||
> Note: In this context, "processed" means that some data from the stream was | ||
> passed to some higher layer of software that might have taken some action as a | ||
> result. | ||
|
||
If a connection terminates without a GOAWAY frame, the last stream identifier is | ||
effectively the highest possible stream identifier. | ||
|
||
Reattempting requests on streams with lower- or equal-numbered identifiers is | ||
not possible, with the exception of idempotent actions like HTTP GET, PUT, or | ||
DELETE. Any protocol activity that used higher-numbered streams can be safely | ||
retried using a new connection. | ||
|
||
Activity on streams numbered lower or equal to the last stream identifier might | ||
still complete successfully. The sender of a GOAWAY frame might gracefully shut | ||
down a connection by sending a GOAWAY frame, maintaining the connection in an | ||
"open" state until all in-progress streams complete. | ||
connection by a server. GOAWAY allows a server to stop accepting new requests | ||
while still finishing processing of previously received requests. This enables | ||
administrative actions, like server maintenance. GOAWAY by itself does not | ||
close a connection. | ||
|
||
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. | ||
|
||
There is an inherent race condition between a client sending new requests and | ||
the server sending a GOAWAY frame. To deal with this case, the GOAWAY contains | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We never explained the nature of that race condition in 7540, and now it's bugging me. Should we open an issue to track this? Maybe the right way to fix this is to change the description. Say that this frame exists to allow client and server to agree on what requests were accepted and which were rejected. GOAWAY identifies the last request that the client can make and the server will accept. All requests that are sent on higher-numbered streams are implicitly cancelled. Described that way, there isn't a need to talk about the race condition. |
||
the stream identifier of the last client-initiated request that was or might be | ||
processed in this connection. This MAY be lower than the stream limit | ||
identified by a QUIC MAX_STREAM_ID frame, and MAY be zero if no requsets were | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. typo: requsets |
||
processed. Servers SHOULD NOT increase the MAX_STREAM_ID limit after sending a | ||
GOAWAY frame. | ||
|
||
Note: | ||
: In this context, "processed" means that some data from the stream was | ||
passed to some higher layer of software that might have taken some action as | ||
a result. | ||
|
||
Once sent, the server will refuse requests sent on streams with an identifier | ||
higher than the included last stream identifier. Clients MUST NOT send new | ||
requests on the connection after receiving GOAWAY, although requests might | ||
already be in transit. A new connection can be established for new requests. | ||
|
||
If the client has sent requests on streams with a higher stream identifier than | ||
indicated in the GOAWAY frame, those requests were not and will not be | ||
processed. The client can treat the requests as though they had never been sent | ||
at all, thereby allowing those requests to be retried later on a new connection. | ||
Servers SHOULD reset new streams above this ID with the error code | ||
HTTP_REQUEST_CANCELLED. Servers MAY also reset streams below the indicated ID | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. s/Servers SHOULD reset new streams/Endpoints SHOULD reset client-initiated streams/ It's not especially graceful, but the server might see those streams as open, and cancelling them avoids problems. Also, this isn't about the server, because clients should also reset their requests and avoid retransmissions. Separately, I wonder: HTTP_REQUEST_CANCELLED from the client doesn't have the effect that we want: it doesn't guarantee that the request wasn't processed by the server; it can't. Do we need some text on that. |
||
with HTTP_REQUEST_CANCELLED if the associated requests were not processed. | ||
|
||
Automatically retrying requests on streams with lower- or equal-numbered | ||
identifiers is not possible, unless this is otherwise permitted (e.g. idempotent | ||
actions like GET, PUT, or DELETE). These requests remain open until they are | ||
completed successfully, reset, or the connection terminates. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The "remain open" clause here is potentially confusing. The problem here is that stream state can't be affected by these HTTP frames. I think that you might remove this last sentence. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think the sentence itself is worth emphasizing rather than dropping, but I agree that it's a little awkward to say that the request "remains open," since that sounds more like the stream this text refers to in 7540. Hopefully a more appropriate phrase for a request will occur to me when it's not half past bedtime. |
||
|
||
Servers SHOULD send a GOAWAY frame when the closing of a connection is known | ||
in advance, even if the advance notice is small, so that the remote peer can | ||
know whether a stream has been partially processed or not. For example, if an | ||
HTTP client sends a POST at the same time that a server closes a QUIC | ||
connection, the client cannot know if the server started to process that POST | ||
request if the server does not send a GOAWAY frame to indicate what streams it | ||
might have acted on. | ||
|
||
For unexpected closures caused by error conditions, a QUIC CONNECTION_CLOSE | ||
frame MUST be used. However, a GOAWAY MAY be sent first to provide additional | ||
detail to clients. If a connection terminates without a GOAWAY frame, the last | ||
stream identifier is effectively the highest possible stream identifier (as | ||
determined by QUIC's MAX_STREAM_ID). | ||
|
||
An endpoint MAY send multiple GOAWAY frames if circumstances change. For | ||
instance, an endpoint that sends GOAWAY without an error code during graceful | ||
|
@@ -681,25 +660,13 @@ requests on another connection. | |
A client that is unable to retry requests loses all requests that are in flight | ||
when the server closes the connection. A server that is attempting to | ||
gracefully shut down a connection SHOULD send an initial GOAWAY frame with the | ||
last stream identifier set to 2^32-1. This signals to the client that a | ||
shutdown is imminent and that initiating further requests is prohibited. After | ||
allowing time for any in-flight requests (at least one round-trip time), the | ||
server MAY send another GOAWAY frame with an updated last stream identifier. | ||
last stream identifier set to the current value of QUIC's MAX_STREAM_ID and | ||
SHOULD NOT increase the MAX_STREAM_ID thereafter. This signals to the client | ||
that a shutdown is imminent and that initiating further requests is prohibited. | ||
After allowing time for any in-flight requests (at least one round-trip time), | ||
the server MAY send another GOAWAY frame with an updated last stream identifier. | ||
This ensures that a connection can be cleanly shut down without losing requests. | ||
|
||
After sending a GOAWAY frame, the sender MUST reset any existing or subsequently | ||
opened streams with an HTTP_REQUEST_CANCELLED error code. | ||
|
||
The GOAWAY frame contains an optional 32-bit error code ({{http-error-codes}}) | ||
that contains the reason for closing the connection. If no error has been | ||
encountered, this field MAY be omitted. | ||
|
||
Endpoints MAY append opaque data to the payload of any GOAWAY frame. Additional | ||
debug data is intended for diagnostic purposes only and carries no semantic | ||
value. Debug information could contain security- or privacy-sensitive data. | ||
Logged or otherwise persistently stored debug data MUST have adequate safeguards | ||
to prevent unauthorized access. | ||
|
||
|
||
# Error Handling {#errors} | ||
|
||
|
@@ -713,9 +680,9 @@ the cause of a connection or stream error. | |
|
||
## HTTP-Defined QUIC Error Codes {#http-error-codes} | ||
|
||
QUIC allocates error codes 0x0000-0x3FFF to application protocol definition. | ||
The following error codes are defined by HTTP for use in QUIC RST_STREAM, | ||
GOAWAY, and CONNECTION_CLOSE frames. | ||
QUIC allocates error codes 0x0000-0x3FFF to application protocol definition. The | ||
following error codes are defined by HTTP for use in QUIC RST_STREAM and | ||
CONNECTION_CLOSE frames. | ||
|
||
HTTP_PUSH_REFUSED (0x01): | ||
: The server has attempted to push content which the client will not accept | ||
|
@@ -854,7 +821,8 @@ PING (0x6): | |
: PING frames do not exist, since QUIC provides equivalent functionality. | ||
|
||
GOAWAY (0x7): | ||
: The error code in GOAWAY is optional. See {{frame-goaway}}. | ||
: GOAWAY is sent only from server to client and does not contain an error code. | ||
See {{frame-goaway}}. | ||
|
||
WINDOW_UPDATE (0x8): | ||
: WINDOW_UPDATE frames do not exist, since QUIC provides flow control. | ||
|
@@ -1155,6 +1123,7 @@ The original authors of this specification were Robbie Shade and Mike Warres. | |
- Cite RFC 5234 (#404) | ||
- Return to a single stream per request (#245,#557) | ||
- Use separate frame type and settings registries from HTTP/2 (#81) | ||
- SETTINGS_ENABLE_PUSH instead of SETTINGS_DISABLE_PUSH (#477) | ||
- Restored GOAWAY (#696) | ||
|
||
## Since draft-ietf-quic-http-03 | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that we should explicitly say that a client doesn't need to send GOAWAY: it just stops sending requests.