HTTP/2 client behaviour on receiving illegal PUSH_PROMISE frames

I'm a little unclear exactly how clients should behave upon receiving
PUSH_PROMISE frames in certain illegal states.  In particular,
sections 5.1 and 6.6 of RFC 7540 appear to state contradictory
requirements:

+------------------------------+-----------------+-----------------+
| Client state                 |   Section 5.1   |   Section 6.6   |
+------------------------------+-----------------+-----------------+
| half-closed(remote)          |       S:SC      |       C:PE      |
|                              |                 |                 |
| closed (RST_STREAM received) |       S:SC      |       C:PE      |
| closed (END_STREAM received) |       C:SC      |       C:PE      |
| closed (RST_STREAM sent)     |    Ignore/P:?   |   Handle/C:PE   |
+------------------------------+-----------------+-----------------+
KEY
S: = Stream error
C: = Connection error
P: = Reset promised stream (error type not stated)
:SC = STREAM_CLOSED
:PE = PROTOCOL_ERROR


So, which is correct?  And where RST_STREAM has been sent, should the
PUSH_PROMISE be ignored or handled (beyond sending RST_STREAM for the
promised stream, in which case what should be the error type)?


The relevant extracts from Section 5.1 are:

In "half-closed(remote)":

> If an endpoint receives additional frames, other than WINDOW_UPDATE,
> PRIORITY, or RST_STREAM, for a stream that is in this state, it MUST
> respond with a stream error (Section 5.4.2) of type STREAM_CLOSED.

In "closed":

> An endpoint that receives any frame other than PRIORITY after
> receiving a RST_STREAM MUST treat that as a stream error (Section
> 5.4.2) of type STREAM_CLOSED. Similarly, an endpoint that receives any
> frames after receiving a frame with the END_STREAM flag set MUST treat
> that as a connection error (Section 5.4.1) of type STREAM_CLOSED,
> unless the frame is permitted as described below.

and

> An endpoint MUST ignore frames that it receives on closed streams
> after it has sent a RST_STREAM frame.
>
> [deletia]
>
> An endpoint might receive a PUSH_PROMISE frame after it sends
> RST_STREAM. PUSH_PROMISE causes a stream to become "reserved" even if
> the associated stream has been reset. Therefore, a RST_STREAM is
> needed to close an unwanted promised stream.


And from Section 6.6 PUSH_PROMISE:

> A receiver MUST treat the receipt of a PUSH_PROMISE on a stream that
> is neither "open" nor "half-closed (local)" as a connection error
> (Section 5.4.1) of type PROTOCOL_ERROR. However, an endpoint that has
> sent RST_STREAM on the associated stream MUST handle PUSH_PROMISE
> frames that might have been created before the RST_STREAM frame is
> received and processed.

-- Alan

Received on Tuesday, 22 September 2020 17:27:16 UTC