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

Interaction of FIN and message parsing #2003

Merged
merged 5 commits into from
Nov 28, 2018
Merged

Interaction of FIN and message parsing #2003

merged 5 commits into from
Nov 28, 2018

Conversation

MikeBishop
Copy link
Contributor

Fixes #1972.

While the discussion on the issue wasn't conclusive in either direction, I think the presence of CONNECT and early response means servers will need to be processing HTTP messages as they arrive, rather than waiting for the FIN as an end-of-message signal. Also, if the message is large, the alternative risks deadlock on a large POST.

This PR expands on the "stream state change isn't part of the message framing" language to clarify that both peers MUST be able to process complete HTTP messages regardless of whether the stream has been closed or not.

@MikeBishop MikeBishop added design An issue that affects the design of the protocol; resolution requires consensus. -http labels Nov 14, 2018
@RyanTheOptimist
Copy link
Contributor

Maybe I'm not thinking about this the right way, but if a body does not have a content-length, then how is the end of the message determined, if not by the end of the stream?

@MikeBishop
Copy link
Contributor Author

MikeBishop commented Nov 14, 2018

That's true, and should have been obvious. Ugh.

Let's take that point back to the issue; this PR might be DOA.


Changes to the state of a request stream do not directly affect message
processing. Endpoints MUST process complete HTTP messages without relying on
stream closure as an end-of-message signal. For example, servers do not abort a
Copy link
Member

Choose a reason for hiding this comment

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

This is wrong. The statement to make is:

The end of a stream (in either direction) indicates the end of a message.
Incomplete messages can be processed, and ideally endpoints do that after receiving a complete header block.

@MikeBishop
Copy link
Contributor Author

Updated with Martin's suggestion: End of stream data is end of message, but you SHOULD be consuming partial messages without waiting for the end. End of stream with a partial message is an error.

@MikeBishop MikeBishop dismissed martinthomson’s stale review November 19, 2018 19:25

Incorporated suggestion.

draft-ietf-quic-http.md Outdated Show resolved Hide resolved
Copy link
Member

@martinthomson martinthomson left a comment

Choose a reason for hiding this comment

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

Iff you take the suggestions.

draft-ietf-quic-http.md Outdated Show resolved Hide resolved
draft-ietf-quic-http.md Outdated Show resolved Hide resolved
Co-Authored-By: MikeBishop <mbishop@evequefou.be>
@MikeBishop MikeBishop changed the title Don't wait for FIN to process complete messages Interaction of FIN and message parsing Nov 20, 2018
@MikeBishop
Copy link
Contributor Author

@RyanatGoogle and @martinduke, I'd ideally like your input before I merge this.

Copy link
Contributor

@RyanTheOptimist RyanTheOptimist left a comment

Choose a reason for hiding this comment

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

Looks great to me!

@martinduke
Copy link
Contributor

Thanks, this addresses my concern. I don't see how the client MUST has any force given that there's no time limit; perhaps it ought to be a SHOULD?

corresponding QUIC stream is closed in the appropriate direction.
After sending a request, a client MUST close the stream for sending; after
sending a final response, the server MUST close the stream for sending. At
this point, the QUIC stream is fully closed.
Copy link
Member

Choose a reason for hiding this comment

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

To @martinduke's comment, maybe it is enough to say "A message is terminated when the stream is closed." Instead of all these words.

Copy link
Member

Choose a reason for hiding this comment

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

Oh, and now I realize that this is what it said before... Not sure whether this is an improvement then.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah, the original provoking issue was that he didn't FIN, the server didn't respond, and both are doing totally spec-compliant things. With this language, it's at least clarified that while the server SHOULD process that request on receipt, it isn't required to until the stream closes, so the client needs to close promptly.

@MikeBishop
Copy link
Contributor Author

You're right that a MUST with no deadline is somewhat toothless, but I don't think it's SHOULD-level. (If we were to fully expand it, you MUST close it eventually and SHOULD do so promptly.)

I think the force is actually in the server's SHOULD: While the server SHOULD process messages before you FIN, it's not obligated to. Therefore, if you want to ensure a response, you'll need to close promptly as a practical matter.

@martinduke
Copy link
Contributor

It sounds like there's a blanket rule except for one special flower - HTTP_CONNECT. So perhaps we should just call out the exception rather than dancing around it, e.g.

"With the exception of requests that contain the CONNECT method, senders use a FIN to indicate the end of an HTTP request or response. Absent CONNECT, senders MUST NOT make the sending of FIN dependent on receipt of a response from the peer.

Absent CONNECT, senders MUST NOT send additional data on the stream after the request or response.

However, due to the possible presence of a CONNECT method, and the opportunity to send HTTP_EARLY_DATA, servers SHOULD begin processing partial HTTP messages once enough of the message has been received to make progress. If a client stream terminates without enough of the HTTP message to provide a complete response, the server SHOULD abort its response with the error code HTTP_INCOMPLETE_REQUEST."

This MUST strikes me as a testable condition.

@MikeBishop
Copy link
Contributor Author

Formally, the data transferred on the TCP connection is the body of the HTTP request, so it's not a special flower in that sense. But it's special in that it's the only case where the server MUST process the headers before the end of the "message."

The requirement that the client MUST NOT make FIN dependent on receiving anything would be a good wording improvement.

@martinduke
Copy link
Contributor

Alright, how about this:

"Senders use a FIN to indicate the end of an HTTP request or response. Absent a CONNECT method in the request, senders MUST NOT make the sending of FIN dependent on receipt of a response from the peer.

However, due to the possible presence of a CONNECT method, and the opportunity to send HTTP_EARLY_DATA, servers SHOULD begin processing partial HTTP messages once enough of the message has been received to make progress. If a client stream terminates without enough of the HTTP message to provide a complete response, the server SHOULD abort its response with the error code HTTP_INCOMPLETE_REQUEST."

I'm open to making the server requirement a similar MUST -- "servers MUST NOT be dependent on a FIN to start processing..." if people think that would help avoid CONNECT deadlocks.

@martinthomson
Copy link
Member

Not seeing how early data (or HTTP_EARLY_DATA, whatever that is) has any bearing on this. I would drop the first particle from the second paragraph and concentrate on the recommendations: process when you can, use HTTP_INCOMPLETE_REQUEST if you need to.

I don't think we need a MUST attached to the recommendations - if you don't follow the recommendations, then it's your loss.

@martinduke
Copy link
Contributor

or HTTP_EARLY_DATA, whatever that is

Argh, I meant HTTP_EARLY_RESPONSE.

As for the final wording, I am happy with whatever you guys decide.

@MikeBishop
Copy link
Contributor Author

Did something along those lines -- see what you think.

Copy link
Member

@martinthomson martinthomson left a comment

Choose a reason for hiding this comment

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

WFM

corresponding QUIC stream is closed in the appropriate direction.
After sending a request, a client MUST close the stream for sending; clients
MUST NOT make stream closure dependent on receiving a response to their request,
unless using the CONNECT method (see {{the-connect-method}}). After sending a
Copy link
Member

Choose a reason for hiding this comment

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

This sentence is confusing to me, because it is unclear what "unless" applies to.

How about changing the sentence to: Unless using the CONNECT method (see {{the-connect-method}}), a client MUST close the stream for sending after sending a request. Clients MUST NOT make stream closure dependent on receiving a response to the request.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

And this highlights the confusion, because I meant the "unless" to be on the opposite clause. :-)

With the formulation we've already got, the entire CONNECT stream is one large HTTP request message, so it doesn't make sense to say you don't need to close a stream after the request in that case. However, stream closure most definitely depends on the response you get back to the headers of your CONNECT request.

Copy link
Contributor

@martinduke martinduke left a comment

Choose a reason for hiding this comment

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

I like @kazuho's working slightly better, but aside from that, ship it!

@MikeBishop MikeBishop merged commit 87b0ef7 into master Nov 28, 2018
@MikeBishop MikeBishop deleted the http/no_waiting branch February 6, 2019 00:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
-http design An issue that affects the design of the protocol; resolution requires consensus.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

http deadlock with stream FIN choices
6 participants