Are HTTP/2 state changes atomic with respect to SETTINGS_MAX_CONCURRENT_STREAMS?

Hey folks,

While implementing (yet another) HTTP/2 stack, I have bumped into an
edge case that I hadn't noticed before and wanted to get feedback from
the WG about what the consensus interpretation is.

Here's the text of RFC 7540 § 5.1.2:

>  Streams that are in the "open" state or in either of the "half-
> closed" states count toward the maximum number of streams that an
> endpoint is permitted to open.  Streams in any of these three states
> count toward the limit advertised in the
> SETTINGS_MAX_CONCURRENT_STREAMS setting.  Streams in either of the
> "reserved" states do not count toward the stream limit.

So far so clear. My question is this: if a server reserves a stream,
and then on the reserved stream sends a HEADERS frame with END_STREAM
set, does the reserved stream ever count against

This can be thought about through this thought experiment. Imagine a
client sets SETTINGS_MAX_CONCURRENT_STREAMS to 5. The server sends six
PUSH_PROMISE frames, and then opens 5 streams with
HEADERS(END_HEADERS). Then, the server sends
HEADERS(END_HEADERS,END_STREAM) on the sixth reserved stream. Does
this trigger a violation of SETTINGS_MAX_CONCURRENT_STREAMS?

RFC 7540 never quite says whether or not HEADERS + END_STREAM triggers
atomic or sequential state transitions. § 5.1 says (while describing
the idle state):

> Sending or receiving a HEADERS frame causes the stream to
> become "open".  The stream identifier is selected as described
>  in Section 5.1.1.  The same HEADERS frame can also cause a
> stream to immediately become "half-closed".

This says "immediately", without defining the semantics of immediacy.
This text stands in contrast to the text describing the reserved
states, which says:

> The endpoint can send a HEADERS frame.  This causes the stream
> to open in a "half-closed (remote)" state.

This does not say "immediately transition" but instead "open in".

This is made more complex by the stream state diagram, which implies
that the END_STREAM transition occurs separately from the HEADERS

My instinct is to say that these streams do not count against
SETTINGS_MAX_CONCURRENT_STREAMS. This instinct is largely informed by
Martin's previous characterisation of RFC 7540 as being written "as
though headers were free". In a model where headers cost nothing, a
stream guaranteed to be made only of headers never counts against

That said, I'm interested in knowing what other implementations do. We
should also consider whether it is worth drafting an erratum to
attempt to clarify the state transitions of END_STREAM.



Received on Friday, 8 February 2019 16:43:18 UTC