Skip to content
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

Discuss HTTP/QUIC Connection Closure #1712

Merged
merged 4 commits into from
Sep 10, 2018
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
185 changes: 106 additions & 79 deletions draft-ietf-quic-http.md
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,9 @@ can indicate that it is not authoritative for a request by sending a 421
(Misdirected Request) status code in response to the request (see Section 9.1.2
of {{!RFC7540}}).

The considerations discussed in Section 9.1 of {{?RFC7540}} also apply to the
management of HTTP/QUIC connections.

# Stream Mapping and Usage {#stream-mapping}

A QUIC stream provides reliable in-order delivery of bytes, but makes no
Expand Down Expand Up @@ -1042,73 +1045,7 @@ 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 ID of the last
client-initiated request that was or might be processed in this connection,
which enables client and server to agree on which requests were accepted prior
to the connection shutdown. This identifier MAY be lower than the stream limit
identified by a QUIC MAX_STREAM_ID frame, and MAY be zero if no requests were
processed. Servers SHOULD NOT increase the MAX_STREAM_ID limit after sending a
GOAWAY frame.

Once sent, the server MUST cancel requests sent on streams with an identifier
higher than the included last Stream ID. 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 ID than
indicated in the GOAWAY frame, those requests are considered cancelled
({{request-cancellation}}). Clients SHOULD reset any streams above this ID with
the error code HTTP_REQUEST_CANCELLED. Servers MAY also cancel requests on
streams below the indicated ID if these requests were not processed.

Requests on Stream IDs less than or equal to the Stream ID in the GOAWAY frame
might have been processed; their status cannot be known until they are completed
successfully, reset individually, or the connection terminates.

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 APPLICATION_CLOSE
frame MUST be used. However, a GOAWAY MAY be sent first to provide additional
detail to clients and to allow the client to retry requests. Including the
GOAWAY frame in the same packet as the QUIC APPLICATION_CLOSE frame improves the
chances of the frame being received by clients.

If a connection terminates without a GOAWAY frame, the last Stream ID is
effectively the highest possible Stream ID (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
shutdown could subsequently encounter an error condition. The last stream
identifier from the last GOAWAY frame received indicates which streams could
have been acted upon. A server MUST NOT increase the value they send in the
last Stream ID, since clients might already have retried unprocessed 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 ID 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 ID. This
ensures that a connection can be cleanly shut down without losing requests.

Once all requests on streams at or below the identified stream number have been
completed or cancelled, and all promised server push responses associated with
those requests have been completed or cancelled, the connection can be closed
using an Immediate Close (see {{QUIC-TRANSPORT}}). An endpoint that completes a
graceful shutdown SHOULD use the QUIC APPLICATION_CLOSE frame with the
HTTP_NO_ERROR code.

See {{connection-shutdown}} for more information on the use of the GOAWAY frame.

### MAX_PUSH_ID {#frame-max-push-id}

Expand Down Expand Up @@ -1150,21 +1087,111 @@ variable-length integer as a connection error of type
HTTP_MALFORMED_FRAME.


# Connection Management
# Connection Closure

Once established, an HTTP/QUIC connection can be used for many requests and
responses over time until the connection is closed. Connection closure can
happen in any of several different ways.

## Idle Connections

Each QUIC endpoint declares an idle timeout during the handshake. If the
connection remains idle (no packets received) for longer than this duration, the
peer will assume that the connection has been closed. HTTP/QUIC implementations
will need to open a new connection for new requests if the existing connection
has been idle for longer than the server's advertised idle timeout, and SHOULD
do so if approaching the idle timeout.

HTTP clients are expected to use QUIC PING frames to keep connections open while
there are responses outstanding for requests or server pushes. If the client is
not expecting a response from the server, allowing an idle connection to time
out is preferred over expending effort maintaining a connection that might not
be needed. A gateway MAY use PING to maintain connections in anticipation of
need rather than incur the latency cost of connection establishment to servers.
Servers SHOULD NOT use PING frames to keep a connection open.

## Connection Shutdown

Even when a connection is not idle, either endpoint can decide to stop using the
connection and let the connection close gracefully. Since clients drive request
generation, clients perform a connection shutdown by not sending additional
requests on the connection; responses and pushed responses associated to
previous requests will continue to completion. Servers perform the same
function by communicating with clients.

Servers initiate the shutdown of a connection by sending a GOAWAY frame
({{frame-goaway}}). The GOAWAY frame indicates that client-initiated requests
on lower stream IDs were or might be processed in this connection, while
requests on the indicated stream ID and greater were not accepted. This enables
client and server to agree on which requests were accepted prior to the
connection shutdown. This identifier MAY be lower than the stream limit
identified by a QUIC MAX_STREAM_ID frame, and MAY be zero if no requests were
processed. Servers SHOULD NOT increase the QUIC MAX_STREAM_ID limit after
sending a GOAWAY frame.

Once sent, the server MUST cancel requests sent on streams with an identifier
higher than the indicated last Stream ID. 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 ID than
indicated in the GOAWAY frame, those requests are considered cancelled
({{request-cancellation}}). Clients SHOULD reset any streams above this ID with
the error code HTTP_REQUEST_CANCELLED. Servers MAY also cancel requests on
streams below the indicated ID if these requests were not processed.

QUIC connections are persistent. All of the considerations in Section 9.1 of
{{?RFC7540}} apply to the management of QUIC connections.
Requests on Stream IDs less than the Stream ID in the GOAWAY frame might have
been processed; their status cannot be known until they are completed
successfully, reset individually, or the connection terminates.

HTTP clients are expected to use QUIC PING frames to keep connections open.
Servers SHOULD NOT use PING frames to keep a connection open. A client SHOULD
NOT use PING frames for this purpose unless there are responses outstanding for
requests or server pushes. If the client is not expecting a response from the
server, allowing an idle connection to time out (based on the idle_timeout
transport parameter) is preferred over expending effort maintaining a connection
that might not be needed. A gateway MAY use PING to maintain connections in
anticipation of need rather than incur the latency cost of connection
establishment to servers.
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.

A client that is unable to retry requests loses all requests that are in flight
when the server closes the connection. A server MAY send multiple GOAWAY frames
indicating different stream IDs, but MUST NOT increase the value they send in
the last Stream ID, since clients might already have retried unprocessed
requests on another connection. A server that is attempting to gracefully shut
down a connection SHOULD send an initial GOAWAY frame with the last Stream ID
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 ID. This ensures that a
connection can be cleanly shut down without losing requests.

Once all accepted requests have been processed, the server can permit the
connection to become idle, or MAY initiate an immediate closure of the
connection. An endpoint that completes a graceful shutdown SHOULD use the
HTTP_NO_ERROR code when closing the connection.

## Immediate Application Closure

An HTTP/QUIC implementation can immediately close the QUIC connection at any
time. This results in sending a QUIC APPLICATION_CLOSE frame to the peer; the
error code in this frame indicates to the peer why the connection is being
closed. See {{errors}} for error codes which can be used when closing a
connection.

Before closing the connection, a GOAWAY MAY be sent to allow the client to retry
some requests. Including the GOAWAY frame in the same packet as the QUIC
APPLICATION_CLOSE frame improves the chances of the frame being received by
clients.

## Transport Closure

For various reasons, the QUIC transport could indicate to the application layer
that the connection has terminated. This might be due to an explicit closure
by the peer, a transport-level error, or a change in network topology which
interrupts connectivity.

If a connection terminates without a GOAWAY frame, clients MUST assume that any
request which was sent, whether in whole or in part, might have been processed.

# Error Handling {#errors}

Expand Down