Subject: Questions about stream state transitions

From: Shigeki Ohtsu <[email-masked]>
Date: Wed, 17 Jul 2013 21:39:43 +0900

Hi,

The stream state is newly introduced in the draft-04. For my understandings,
I've just wrote a table diagram for the stream states transition to cover
 all scenarios in the case of sending and receiving frames.

The table is listed in

http://html5.ohtsu.org/HTTP2_Stream_State.pdf

In writing this, I have the folowing five questions which are painted gray in
the table field.

(1) Receiving RST_STREAM in "idle"
Is it a stream error with PROTOCOL_ERROR or falled into "closed" state?

(2) Receivng PRIRORITY and WINDOW_UPDATE in "half closed(local)"
They are not necessary. So is it to be an error or ignored?

(3) Sending PRIORITY in "half closed(remote)"
No description about this case is in the draft. Is it prohibited?

(4) Receiving RST_STREAM in "closed"
The draft says that " An endpoint that sends a RST_STREAM frame MUST ignore
frames that it receives on closed streams after it has sent a RST_STREAM frame."

Is this ignored always in the closed state or only in the case
after RST_STREAM sent?

(5) Receiving PUSH_PROMISE in "closed"
The draft says that 'An endpoint might receive a PUSH_PROMISE frame after
it sends RST_STREAM. PUSH_PROMISE causes a stream to become "reserved".'

The same question above.
Is PUSH_PROMISE always leads the associted stream to be reserved(remote)
in the closed state? Or is it limited in the case after RST_STREAM was sent?

If any missings or mistakes are found in the table, I'm very glad to have feedbacks.

Regards,

---

From: Martin Thomson <[email-masked]>
Date: Wed, 17 Jul 2013 09:24:15 -0700

This is really valuable work.

I'm going to create a ticket to cover addressing these points:
https://github.com/http2/http2-spec/issues/175

That one, I'll mark as editorial, but I'll also create a couple of
extra issues (below).

> http://html5.ohtsu.org/HTTP2_Stream_State.pdf

Note that, in general, you will see a great deal of symmetry between
the two tables.  If it is a PROTOCOL_ERROR to receive, then it will be
a MUST NOT for send, aside from the boundary cases where races can
occur.

> Is it a stream error with PROTOCOL_ERROR or falled into "closed" state?

I believe that the right approach is to treat this as a *connection*
error of type PROTOCOL_ERROR.  Otherwise, an endpoint can be required
to maintain too much extra state.
-> https://github.com/http2/http2-spec/issues/176

> They are not necessary. So is it to be an error or ignored?

Both can be received in this state.  If you just sent END_STREAM, then
it would not be unexpected to receive either frame shortly thereafter.
 Ignoring them seems safe (providing that you apply the usual DoS
heuristics).

> No description about this case is in the draft. Is it prohibited?

No need to send it, but it's impossible to force compliance (see above answer).

> Is this ignored always in the closed state or only in the case

If you send RST_STREAM, then receiving RST_STREAM should be OK.  In my
opinion, an implementation could choose to use RST_STREAM as a signal
that they can stop ignoring frames on that streams (and transition to
a  hard connection-level PROTOCOL_ERROR for any other frames that
appear).

If a stream is closed, either because both peers sent END_STREAM, or
you *received* RST_STREAM, receiving RST_STREAM is a PROTOCOL_ERROR.
That, we should clarify.

> in the closed state? Or is it limited in the case after RST_STREAM was sent?

This is only valid if you send RST_STREAM.  If you reach "closed" in
any other way, the remote peer is aware of the close and should not be
sending junk.  In this case, perhaps we need to escalate the error to
a connection one, so that we can avoid the need to worry about the
promised stream.

That might be a general principle that can be applied to invalid
PUSH_PROMISE frames, lest we end up with streams that are sort-of
promised, but not promised in any valid way.
-> https://github.com/http2/http2-spec/issues/177

> If any missings or mistakes are found in the table, I'm very glad to have feedbacks.

I think that you have the PUSH_PROMISE a little wrong, depending on
which stream that you are talking about.

The stream that you are using here is the *promised* stream.  But the
frame header for PUSH_PROMISE includes the *associated* stream.
Perhaps you need to add another column for the effect that
PUSH_PROMISE has on the associated stream.

---

From: Shigeki Ohtsu <[email-masked]>
Date: Thu, 18 Jul 2013 15:38:47 +0900

Thanks for answers, they are very helpful for me.

Following comments, I've update the table in

Please review this if it is correct and I've also submitted a new PR of

https://github.com/http2/http2-spec/pull/179

which is related in receiving PUSH_PROMISE shown in the table as marked (*2)

Please review it too.

Regards,

---

From: Ilari Liusvaara <[email-masked]>
Date: Thu, 18 Jul 2013 11:08:38 +0300

> Please review this if it is correct and I've also submitted a new PR of

Eh, HEADERS in Reserved (remote) transitions to half closed (local)
regardless of END_STREAM? That looks bit suspicious.

Also, I think that anytime DATA can be successfully received,
WINDOW_UPDATE can be sent (half closed (local) seems to violate
that).

-Ilari

---

From: Shigeki Ohtsu <[email-masked]>
Date: Thu, 18 Jul 2013 17:32:58 +0900

> regardless of END_STREAM? That looks bit suspicious.

Yes, it can be an option that it is UNCHANGED to still remain in the reserved(remote)
when HEADERS without END_STREAM is received.

> WINDOW_UPDATE can be sent (half closed (local) seems to violate

PRIORITY can also be received in reserved(local/remote) accrding to the above model.

I'm not sure that there are pros and cons about this model. If not, I think it would be a design choice.

---

From: Martin Thomson <[email-masked]>
Date: Thu, 18 Jul 2013 09:35:40 -0700

> when HEADERS without END_STREAM is received.

It should be that HEADERS + END_STREAM from reserved (remote) goes to
closed.  This covers the case where a push only includes headers (a
push for a HEAD request might look like that).

---

From: Martin Thomson <[email-masked]>
Date: Thu, 18 Jul 2013 09:37:50 -0700

> PRIORITY can also be received in reserved(local/remote) accrding to the

No this is also incorrect in the table.  If you can receive DATA, then
the protocol requires that you be able to send WINDOW_UPDATE.

Another bug I noticed is that it should be possible to send
PUSH_PROMISE in half closed (remote) and to receive it in half closed
(local).

---

From: Shigeki Ohtsu <[email-masked]>
Date: Fri, 19 Jul 2013 19:50:23 +0900

Thanks Martin,

You're right. HEADER+END_STREAM goes like two step transitions and
PUSH_PRMISE can be sent in hald closed(remote).

The table was fixed and updated.

The transition flow of PUSH_PROMISE confused me much. I hope no more fix is needed.