Skip to content

Commit

Permalink
Merge pull request #107 from edsko/edsko/rst-stream-in-half-closed-local
Browse files Browse the repository at this point in the history
Deal with `RST_STREAM` in `HalfClosedLocal` state
  • Loading branch information
kazu-yamamoto authored Feb 6, 2024
2 parents 0962096 + 0b63888 commit 4c1dfdd
Showing 1 changed file with 19 additions and 8 deletions.
27 changes: 19 additions & 8 deletions Network/HTTP2/H2/Receiver.hs
Original file line number Diff line number Diff line change
Expand Up @@ -557,21 +557,32 @@ stream FrameRSTStream header@FrameHeader{streamId} bs ctx s strm = do
ConnectionErrorIsSent EnhanceYourCalm streamId "too many rst_stream"
RSTStreamFrame err <- guardIt $ decodeRSTStreamFrame header bs
let cc = Reset err
closed ctx strm cc

-- The spec mandates (section 8.1):
-- HTTP2 spec, section 5.1, "Stream States":
--
-- > A stream in the "open" state may be used by both peers to send frames
-- > of any type. (..) From this state, either endpoint can send a frame
-- > with an END_STREAM flag set, which causes the stream to transition into
-- > one of the "half-closed" states. An endpoint sending an END_STREAM
-- > flag causes the stream state to become "half-closed (local)"; an
-- > endpoint receiving an END_STREAM flag causes the stream state to become
-- > "half-closed (remote)".
--
-- > When this is true, a server MAY request that the client abort
-- > transmission of a request without error by sending a RST_STREAM with an
-- > error code of NO_ERROR after sending a complete response (i.e., a frame
-- > with the END_STREAM flag).
-- Crucially (for the specific case we're dealing with here), it continues:
--
-- We check the first part ("after sending a complete response") by checking
-- the current stream state.
-- > /Either endpoint/ can send a RST_STREAM frame from this state, causing
-- > it to transition immediately to "closed".
--
-- (emphasis not in original). This justifies the two non-error cases,
-- below. (Section 8.1 of the spec is also relevant, but it is less explicit
-- about the /either endpoint/ part.)
case (s, err) of
(Open (Just _) _, NoError) -> -- HalfClosedLocal
return (Closed cc)
(HalfClosedRemote, NoError) ->
return (Closed cc)
_otherwise -> do
closed ctx strm cc
E.throwIO $ StreamErrorIsReceived err streamId

-- (No state transition)
Expand Down

0 comments on commit 4c1dfdd

Please sign in to comment.