@@ -109,8 +109,8 @@ frameReceiver ctx mkreq recvN = loop 0 `E.catch` sendGoaway
109109 PriorityFrame newpri <- guardIt $ decodePriorityFrame header pl
110110 checkPriority newpri streamId
111111 return True -- just ignore this frame
112− Just strm@Stream{streamState,streamPrecedence} -> do
113− state <- readIORef streamState
112+ Just strm@Stream{streamPrecedence} -> do
113+ state <- readStreamState strm
114114 state' <- stream ftyp header pl ctx state strm
115115 case state' of
116116 Open (NoBody tbl@(_,reqvt) pri) -> do
@@ -119,7 +119,7 @@ frameReceiver ctx mkreq recvN = loop 0 `E.catch` sendGoaway
119119 when (just mcl (/= (0 :: Int))) $
120120 E.throwIO $ StreamError ProtocolError streamId
121121 writeIORef streamPrecedence $ toPrecedence pri
122− writeIORef streamState HalfClosed
122+ halfClosedRemote ctx strm
123123 (!req, !ii) <- mkreq tbl (Just 0, return "")
124124 atomically $ writeTQueue inputQ $ Input strm req reqvt ii
125125 Open (HasBody tbl@(_,reqvt) pri) -> do
@@ -128,17 +128,20 @@ frameReceiver ctx mkreq recvN = loop 0 `E.catch` sendGoaway
128128 let !mcl = readInt <$> getHeaderValue tokenContentLength reqvt
129129 writeIORef streamPrecedence $ toPrecedence pri
130130 bodyLength <- newIORef 0
131− writeIORef streamState $ Open (Body q mcl bodyLength)
131+ setStreamState ctx strm $ Open (Body q mcl bodyLength)
132132 readQ <- newReadBody q
133133 bodySource <- mkSource readQ
134134 (!req, !ii) <- mkreq tbl (mcl, readSource bodySource)
135135 atomically $ writeTQueue inputQ $ Input strm req reqvt ii
136136 s@(Open Continued{}) -> do
137137 setContinued
138− writeIORef streamState s
139− s -> do -- Idle, Open Body, HalfClosed, Closed
138+ setStreamState ctx strm s
139+ HalfClosedRemote -> do
140140 resetContinued
141− writeIORef streamState s
141+ halfClosedRemote ctx strm
142+ s -> do -- Idle, Open Body, Closed
143+ resetContinued
144+ setStreamState ctx strm s
142145 return True
143146 where
144147 setContinued = writeIORef continued (Just streamId)
@@ -155,8 +158,8 @@ frameReceiver ctx mkreq recvN = loop 0 `E.catch` sendGoaway
155158 case mstrm0 of
156159 js@(Just strm0) -> do
157160 when (ftyp == FrameHeaders) $ do
158− st <- readIORef $ streamState strm0
159− when (isHalfClosed st) $ E.throwIO $ ConnectionError StreamClosed "header must not be sent to half closed"
161+ st <- readStreamState strm0
162+ when (isHalfClosedRemote st) $ E.throwIO $ ConnectionError StreamClosed "header must not be sent to half or fully closed stream"
160163 -- Priority made an idele stream
161164 when (isIdle st) $ opened ctx strm0
162165 return js
@@ -286,11 +289,28 @@ stream FrameHeaders header@FrameHeader{flags} bs _ (Open (Body q _ _)) _ = do
286289 let !endOfStream = testEndStream flags
287290 if endOfStream then do
288291 atomically $ writeTQueue q ""
289− return HalfClosed
292+ return HalfClosedRemote
290293 else
291294 -- we don't support continuation here.
292295 E.throwIO $ ConnectionError ProtocolError "continuation in trailer is not supported"
293296
297+-- ignore data-frame except for flow-control when we're done locally
298+stream FrameData
299+ FrameHeader{flags,payloadLength}
300+ _bs
301+ Context{controlQ} s@(HalfClosedLocal _)
302+ Stream{streamNumber} = do
303+ let !endOfStream = testEndStream flags
304+ when (payloadLength /= 0) $ do
305+ let !frame1 = windowUpdateFrame 0 payloadLength
306+ !frame2 = windowUpdateFrame streamNumber payloadLength
307+ !frame = frame1 `BS.append` frame2
308+ enqueueControl controlQ $ CFrame frame
309+ if endOfStream then do
310+ return HalfClosedRemote
311+ else
312+ return s
313+
294314stream FrameData
295315 header@FrameHeader{flags,payloadLength,streamId}
296316 bs
@@ -312,7 +332,7 @@ stream FrameData
312332 Nothing -> return ()
313333 Just cl -> when (cl /= len) $ E.throwIO $ StreamError ProtocolError streamId
314334 atomically $ writeTQueue q ""
315− return HalfClosed
335+ return HalfClosedRemote
316336 else
317337 return s
318338