RE: Issue with the H2 state machine

No, because that would prohibit ridiculously large trailers (i.e. using CONTINUATION), which might be stupid but are permitted.  The spec is saying that any HEADERS frame after the final status code has to be trailers, and therefore that block is the last thing on the stream.  Alternatively stated, you can't send your trailers but then send more body.

-----Original Message-----
From: Willy Tarreau [mailto:w@1wt.eu] 
Sent: Friday, July 21, 2017 7:27 AM
To: Ilari Liusvaara <ilariliusvaara@welho.com>
Cc: ietf-http-wg@w3.org
Subject: Re: Issue with the H2 state machine

On Fri, Jul 21, 2017 at 12:33:29PM +0300, Ilari Liusvaara wrote:
> On Fri, Jul 21, 2017 at 11:03:17AM +0200, Willy Tarreau wrote:
> > On Fri, Jul 21, 2017 at 11:57:20AM +0300, Ilari Liusvaara wrote:
> > > On Fri, Jul 21, 2017 at 10:39:41AM +0200, Willy Tarreau wrote:
> > > > On Fri, Jul 21, 2017 at 10:17:44AM +0200, Willy Tarreau wrote:
> > > > 
> > > > Also I think I found a typo here in 8.1 :
> > > > 
> > > >    An endpoint that receives a HEADERS
> > > >    frame without the END_STREAM flag set after receiving a final (non-
> > > >    informational) status code MUST treat the corresponding request or
> > > >    response as malformed (Section 8.1.2.6).
> > > > 
> > > > I think it should use s/END_STREAM/END_HEADERS/ given that DATA 
> > > > frames are still allowed here. I can file an errata if confirmed.
> > > 
> > > I think it is correct, just somewhat confusing. This seem to be 
> > > requirement that there can be at most one header block at the very 
> > > end after headers that sends the final status code.
> > 
> > But if a DATA frame follows, the END_STREAM is on the DATA frame, 
> > not the headers frame. There's even exactly this example in 8.1.3 
> > page 59. That's indeed a bit confusing :-/
> 
> Those examples are written in bit confusing way. In the last example, 
> the END_STREAM flag on the DATA frame is NOT set. However, the 
> END_STREAM flag on the last HEADERS frame IS set.
> 
> The last example could be written as:
> 
> HEADERS(END_HEADERS):
> :status => 100
> extension-field => bar
> 
> HEADERS(END_HEADERS)
> :status => 200
> content-length => 123
> content-type => image/jpeg
> trailer => Foo
> 
> DATA()
> {binary data}
> 
> HEADERS(END_STREAM,END_HEADERS)
> foo = bar
> 
> 
> Also, END_STREAM in HEADERS is bit special in that if HEADERS has 
> END_STREAM but not END_HEADERS, then the stream will go on a bit to 
> receive the CONTINUATION frames until END_HEADERS is asserted.
> 
> Example:
> 
> HEADERS(END_HEADERS):
> :status => 100
> extension-field => bar
> 
> HEADERS(END_HEADERS)
> :status => 200
> content-length => 123
> content-type => image/jpeg
> trailer => Foo, Zot
> 
> DATA()
> {binary data}
> 
> HEADERS(END_STREAM)
> foo = bar
> 
> CONTINUATION(END_HEADERS)
> zot = qux
> 
> <-- The half-stream is closed here.

Sorry I added confusion myself, what I meant is that it's the last frame of the stream which holds the END_STREAM and not the HEADERS frame of the last HEADERS block. Look at the previous example on the same page, it properly carries END_STREAM on DATA, not on HEADERS.

My point is that END_STREAM should be on the last frame half-closing the STREAM unless the last frame is a CONTINUATION frame in which case the flag is in the previous HEADERS frame (with CONTINUATION being considered as an extra fragment of HEADERS frame).

If we had END_STREAM on the HEADERS frame even before DATA as 8.1 seems to mention, there would be no way to know whether or not DATA frames are expected.

However if we rewrite the sentence in 8.1 like this :

   An endpoint that receives a HEADERS frame without end END_HEADERS
   flag set after receiving a final (non-informational) status code
   MUST treat the corresponding request or response as malformed.

Then it totally makes sense given that the HEADERS frame must be terminated before seeing a DATA frame.

Willy

Received on Monday, 24 July 2017 17:17:06 UTC