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

Two reasons, I think....

Separation of PUSH_PROMISE and stream concurrency was used as a predecessor to 103 -- if a client permitted push but set the max streams to zero, then the sequence of promises just becomes a stream of suggested dependent resources that can be delivered at any point during the response rather than only at the beginning.

The attack we were concerned about at the time was giving you a partial response and forcing you to buffer state for it, then another, then another, and never actually finish anything.  If you have fully consumed a push, you can flush the state, either by delivering it to the application or by discarding it entirely.  Since the TCP bytestream enforces consuming everything in order, you'll be done with one push before you begin consuming another -- from the HTTP layer's perspective, you *do* only have 5 outstanding no matter how many are in the pipe.  If the responses are coming faster than you can keep up, then TCP will generate backpressure.  If the server doesn't want that, it needs to moderate how much it pushes to how much it can send.

The DoS this permits is blocking the actual response behind lots of pushes -- something the server can do anyway by simply withholding the response.  The true cost is in HPACK processing all the promises and responses -- we chose to implement a "fast path" in the HPACK processor which updates table state and discards all output to mitigate this.

-----Original Message-----
From: Willy Tarreau <> 
Sent: Friday, February 8, 2019 10:58 PM
To: Mike Bishop <>
Cc: Cory Benfield <>;
Subject: Re: Are HTTP/2 state changes atomic with respect to SETTINGS_MAX_CONCURRENT_STREAMS?

On Fri, Feb 08, 2019 at 11:40:46PM +0000, Mike Bishop wrote:
> >From 5.1:  "For the purpose of state transitions, the END_STREAM flag 
> >is
>    processed as a separate event to the frame that bears it; a HEADERS
>    frame with the END_STREAM flag set can cause two state transitions."
> This means that the frame causes two events -- increasing the number 
> of concurrent streams, then decreasing it again.

I was surprised by this assertion, until I found that streams in the reserved state are not counted. Do you have an idea why it's done this way ? This means that a server can trivially DoS a client or intermediary by pushing 1 billion streams that must be memorized and are not accounted for :-/


Received on Monday, 11 February 2019 17:58:37 UTC