Subject: [#228] PUSH_PROMISE with CONTINUATION can end a stream

From: Martin Thomson <[email-masked]>
Date: Mon, 12 Aug 2013 23:47:27 +0100

https://github.com/http2/http2-spec/issues/228

PUSH_PROMISE does not have an END_STREAM flag.

However, a sender might emit a PUSH_PROMISE followed by a CONTINUATION
with the END_STREAM set. As specified, this ends the stream.

I think that we need to either prohibit this, or we add END_STREAM to
PUSH_PROMISE.  I don't care which.  Bike shed... go!

---

From: James M Snell <[email-masked]>
Date: Mon, 12 Aug 2013 15:54:32 -0700

I see no reason at all why PUSH_PROMISE can't have END_STREAM.

---

From: Jeff Pinner <[email-masked]>
Date: Mon, 12 Aug 2013 15:56:13 -0700

or just take the END_STREAM flag off of CONTINUATION and rely on the
initial frame for the flags for the group.

---

From: Jeff Pinner <[email-masked]>
Date: Mon, 12 Aug 2013 15:58:18 -0700

PUSH_PROMISE is hop-by-hop -- if you end the stream with a push promise
flag you have to tell intermediates to forward the flag on some other
frame, and that may or may not break the semantics of the layered
application.

---

From: James M Snell <[email-masked]>
Date: Mon, 12 Aug 2013 16:01:04 -0700

How so? Intermediary receives a PUSH_PROMISE with END_STREAM, if it
chooses not to forward that on, it sends an empty DATA frame with
END_STREAM, none of the semantics are changed really. That said, I
have no strong opinion about it one way or the other.

On Mon, Aug 12, 2013 at 3:58 PM, Jeff Pinner <[email-masked]> wrote:
> PUSH_PROMISE is hop-by-hop -- if you end the stream with a push promise flag
> you have to tell intermediates to forward the flag on some other frame, and
> that may or may not break the semantics of the layered application.
>
>

---

From: Martin Thomson <[email-masked]>
Date: Tue, 13 Aug 2013 00:29:28 +0100

> that may or may not break the semantics of the layered application.

This is a good point.  It's especially bad if the intermediary already
forwarded the last frame.  Not that we should be allowing that to
happen of course, since PUSH_PROMISE shouldn't be the last frame in a
response...

I tend to think that prohibition is the most reasonable reaction.  I'm
not that keen to move the END_STREAM bit off the last frame on the
stream, even if it is technically the same
but-we-had-to-split-it-up-a-little-so-that-it-fits frame.  It spreads
the frame processing logic over multiple headers in ways that will
probably lead to implementation errors.

---

From: Jeff Pinner <[email-masked]>
Date: Mon, 12 Aug 2013 16:38:11 -0700

I think it might be better to move the logic off rather than add flags for
all frames that might be continued. This keeps the mechanism as simple as
possible -- i.e. extend the previous frame by "length" bytes until you see
END_HEADERS flag.

Then we don't have to worry about other flags (e.g. the reserved
END_MESSAGE), or future extensible if CONTINUES is used for other frames
with header blocks.

On Mon, Aug 12, 2013 at 4:29 PM, Martin Thomson <[email-masked]>wrote:

> flag

---

From: Martin Thomson <[email-masked]>
Date: Tue, 13 Aug 2013 00:58:38 +0100

> possible -- i.e. extend the previous frame by "length" bytes until you see

I could be convinced to accept that reasoning - fewer places to look
for bits seems like a good thing.  I was hoping that it would be the
last frame, but given the nature of continuations, this is tempting.
What do others think?

END_HEADERS is on HEADERS + PUSH_PROMISE + CONTINUATION, but
END_STREAM is only on HEADERS.  Later, END_MESSAGE might only be on
HEADERS or DATA, depending on how things work out.

---

From: Roberto Peon <[email-masked]>
Date: Mon, 12 Aug 2013 17:06:06 -0700

That is no big deal-- you just emit an empty data frame with the flag set.
'Course this argument goes both ways...
-=R

---

From: Martin Thomson <[email-masked]>
Date: Tue, 13 Aug 2013 01:19:16 +0100

> That is no big deal-- you just emit an empty data frame with the flag set.

Not if you intended to transmit trailers, but I can't say that that
bothers me all that much :)

> 'Course this argument goes both ways...

:)