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

Possible SETTINGS_ACK proposal #84

Merged
merged 2 commits into from Dec 15, 2016
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
100 changes: 75 additions & 25 deletions draft-ietf-quic-http.md
Expand Up @@ -157,6 +157,11 @@ additional framing. Note that a request or response without a body will cause
this stream to be half-closed in the corresponding direction without
transferring data.

Pairs of streams must be utilized sequentially, with no gaps. The data stream
MUST be reserved with the QUIC implementation when the message control stream
is opened or reserved, and MUST be closed after transferring the body, or else
closed immediately after sending the request headers if there is no body.

HTTP does not need to do any separate multiplexing when using QUIC - data sent
over a QUIC stream always maps to a particular HTTP transaction. Requests and
responses are considered complete when the corresponding QUIC streams are closed
Expand All @@ -177,18 +182,19 @@ HTTP response on the same streams as the request.
An HTTP message (request or response) consists of:

1. for a response only, zero or more header blocks (a sequence of HEADERS frames
with End Header Block set on the last) on the control stream containing the
message headers of informational (1xx) HTTP responses (see {{!RFC7230}}, Section
3.2 and {{!RFC7231}}, Section 6.2),
with End Header Block set on the last) on the control stream containing the
message headers of informational (1xx) HTTP responses (see {{!RFC7230}},
Section 3.2 and {{!RFC7231}}, Section 6.2),

2. one header block on the control stream containing the message headers (see
{{!RFC7230}}, Section 3.2),
{{!RFC7230}}, Section 3.2),

3. the payload body (see {{!RFC7230}}, Section 3.3), sent on the data stream
3. the payload body (see {{!RFC7230}}, Section 3.3), sent on the data stream,

4. optionally, one header block on the control stream containing the
trailer-part, if present (see {{!RFC7230}}, Section 4.1.2).
trailer-part, if present (see {{!RFC7230}}, Section 4.1.2).

The data stream MUST be half-closed immediately after the transfer of the body.
If the message does not contain a body, the corresponding data stream MUST still
be half-closed without transferring any data. The "chunked" transfer encoding
defined in Section 4.1 of {{!RFC7230}} MUST NOT be used.
Expand Down Expand Up @@ -549,20 +555,38 @@ SETTINGS frame MUST be processed in the order they appear, with no other frame
processing between values. Unsupported parameters MUST be ignored.

Once all values have been processed, if the REQUEST_ACK flag was set, the
recipient MUST immediately emit a SETTINGS_ACK frame listing the identifiers
whose values were understood and applied. (If none of the values were
understood, the SETTINGS_ACK frame will be empty, but MUST still be sent.) Upon
receiving an SETTINGS_ACK frame, the sender of the altered parameters can rely
on the setting having been applied.

TODO:
: The above text was written for HTTP/2 -- QUIC has cross-stream timing issues
here that need to be solved.

recipient MUST immediately emit the following:

- On the connection control stream, a SETTINGS_ACK frame listing the
identifiers whose values were understood and applied. (If none of the values
were understood, the SETTINGS_ACK frame will be empty, but MUST still be
sent.)

- On each request control stream which is not in the "half-closed (local)" or
"closed" state, an empty SETTINGS_ACK frame.

The SETTINGS_ACK frame on the connection control stream contains the highest
stream number which was open at the time the SETTINGS frame was received. All
streams with higher numbers can safely be assumed to have the new settings in
effect when they open.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's say that the opening of a stream is delayed (loss looks like a delay for this stuff). Stream N gets through, but stream N-2 takes another RTT or so to open. What is the receiver of the SETTINGS frame expected to do in this case? Is it expected to play out the SETTINGS_ACK when the stream finally makes it through?

The problem here is that stream N-2 might have been skipped by the other side. How does a receiver know what to do with that uncertainty? It can't hold onto the SETTINGS_ACK indefinitely.

I think that we need to mandate no stream skipping in this case.

The next problem is in correlating the SETTINGS_ACK with the SETTINGS. I think that your scheme almost works, but we probably want to include some text on how this correlation is expected to work:

  • for every SETTINGS that requests acknowledgment, there is a SETTINGS_ACK
  • for every SETTINGS_ACK, every open stream less or equal to the included stream number will contain a SETTINGS_ACK

Where this doesn't work is when the receiver of a SETTINGS frame opens a stream. Say a server sends SETTINGS at and then a client opens stream 7. The server cannot know whether stream 7 was open at the time that the client received the SETTINGS frame. Even if the opening frame on stream 7 is in the same packet as the client's SETTINGS_ACK, there is no good way to know what order the client actually performed these two actions. Thus, if stream 7 is still open when a second SETTINGS is sent, the SETTINGS_ACK that the server receives on stream 7 could correspond to either settings.

The only fix I'm aware of is to set start AND end markers on the control stream SETTINGS_ACK.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The first case is the corner-case from line 572 -- because QUIC mandates that streams be opened "sequentially," stream-skipping is already prohibited. (Should that be made clearer?) The fact that I've seen stream N opened means N-2 is in-flight, even if I haven't seen it yet. That means, having received a SETTINGS frame, I can go ahead and send a SETTINGS_ACK on N-2 without having yet received a frame because it's not out-of-order at the remote side.

Your suggested correlation text looks a lot like what I have at line 576 about what's needed to consider the ACK "finished."  I might need to add a note that all previous SETTINGS frames have to be "finished" before a subsequent one can be -- ACKs on-stream are fully ordered.

I don't see the issue when the receiver of SETTINGS opens the stream. There are two possible orderings:

SETTINGS processed before stream created. Then the SETTINGS_ACK on stream 3 will not cover the new stream, and the stream abides by the new settings from the start.

  • Stream created before SETTINGS processed. Then the SETTINGS_ACK on stream 3 will cover the new stream, and the sender will expect a STREAM_ACK (which may be the first frame on the stream).

What am I missing?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that you have it. Thanks for walking through it with me. The sequential thing definitely needs work. "Sequential" just means in order, which doesn't correspond to a mandate to use every number.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added some text to the Stream Usage section explicitly requiring no stream-skipping, just to be thorough.


For already-open streams, the empty SETTINGS_ACK frame indicates the point at
which the new settings took effect, if they did so before the peer half-closed
the stream. If the peer closed the stream before receiving the SETTINGS frame,
the previous settings were in effect for the full lifetime of that stream.

In certain conditions, the SETTINGS_ACK frame can be the first frame on a given
stream -- this simply indicates that the new settings apply from the beginning
of that stream.

If the sender of a SETTINGS frame with the REQUEST_ACK flag set does not
receive an acknowledgement within a reasonable amount of time, it MAY issue a
connection error ([RFC7540] Section 5.4.1) of type SETTINGS_TIMEOUT.

receive full acknowledgement within a reasonable amount of time, it MAY issue a
connection error ([RFC7540] Section 5.4.1) of type SETTINGS_TIMEOUT. A full
acknowledgement has occurred when a SETTINGS_ACK frame has been received on the
connection control stream, and all message control streams with a Stream ID
through those given in the SETTINGS_ACK frame have either closed or had a
SETTINGS_ACK frame sent.


### PUSH_PROMISE {#frame-push-promise}

Expand Down Expand Up @@ -626,13 +650,39 @@ frames provide equivalent functionality. Frame type 0x9 is reserved.
### SETTINGS_ACK Frame {#frame-settings-ack}

The SETTINGS_ACK frame (id = 0x0b) acknowledges receipt and application
of specific values in the peer's SETTINGS frame. It contains a list of
SETTINGS identifiers which the sender has understood and applied. This
list MAY be empty.
of specific values in the peer's SETTINGS frame. Depending on the stream where
it is sent, it takes two different forms.

On the connection control stream, it contains information about how and when the
sender has processed the most recently-received SETTINGS frame, and has the
following payload:

~~~~~~~~~~~~~~~
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
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Highest Local Stream (32) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Highest Remote Stream (32) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Unrecognized Identifiers (*) ...
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
~~~~~~~~~~~~~~~
{: #fig-settings-ack title="SETTINGS_ACK connection control stream format"}

Highest Local Stream (32 bits):
: The highest locally-initiated Stream ID which is not in the "idle" state

Highest Remote Stream (32 bits):
: The highest peer-initiated Stream ID which is not in the "idle" state

Unrecognized Identifiers:
: A list of 16-bit SETTINGS identifiers which the sender has not understood
and therefore ignored. This list MAY be empty.

Any SETTINGS_ACK frame whose length is not a multiple of two bytes MUST
be treated as a connection error ({{errors}}) of type
`FRAME_SIZE_ERROR`.
On message control streams, the SETTINGS_ACK frame carries no payload, and is
strictly a synchronization marker for settings application. See
{{settings-synchronization}} for more detail.

# Error Handling {#errors}

Expand Down