diff --git a/ChangeLog.md b/ChangeLog.md index 9360a29d..bd77ea60 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -2,6 +2,9 @@ ## Unreleased changes +- Change `waitStream` so that it automatically credits the connection. This + is a breaking change due to function signature change. + ## v0.10.0.0 - Export frameHttp2RawConnection to convert an RawHttp2Connection into an Http2FrameConnection. diff --git a/examples/SimpleGet.lhs b/examples/SimpleGet.lhs index 47b00e47..3e1351b7 100644 --- a/examples/SimpleGet.lhs +++ b/examples/SimpleGet.lhs @@ -85,7 +85,7 @@ client-originated streams (however with its own flow-control context). > resetPushPromises _ pps _ _ _ = _rst pps RefusedStream > > handler sfc _ = do -> waitStream stream sfc resetPushPromises >>= print . fromStreamResult +> waitStream conn stream sfc resetPushPromises >>= print . fromStreamResult We've defined an initializer and a handler so far. diff --git a/src/Network/HTTP2/Client/Helpers.hs b/src/Network/HTTP2/Client/Helpers.hs index 56497cf3..66192ec3 100644 --- a/src/Network/HTTP2/Client/Helpers.hs +++ b/src/Network/HTTP2/Client/Helpers.hs @@ -115,12 +115,16 @@ upload dat flagmod conn connectionFlowControl stream streamFlowControl = do -- -- This function is fine if you don't want to consume results in chunks. See -- 'fromStreamResult' to collect the complicated 'StreamResult' into a simpler --- 'StramResponse'. -waitStream :: Http2Stream +-- 'StreamResponse'. +waitStream :: Http2Client + -- ^The connection. + -> Http2Stream + -- ^The stream to wait on. This stream must be part of the connection. -> IncomingFlowControl + -- ^Incoming flow control for the __stream__. -> PushPromiseHandler -> ClientIO StreamResult -waitStream stream streamFlowControl ppHandler = do +waitStream conn stream streamFlowControl ppHandler = do ev <- _waitEvent stream case ev of StreamHeadersEvent fH hdrs @@ -131,10 +135,11 @@ waitStream stream streamFlowControl ppHandler = do return (Right hdrs, reverse dfrms, trls) StreamPushPromiseEvent _ ppSid ppHdrs -> do _handlePushPromise stream ppSid ppHdrs ppHandler - waitStream stream streamFlowControl ppHandler + waitStream conn stream streamFlowControl ppHandler _ -> error $ "expecting StreamHeadersEvent but got " ++ show ev where + connFlowControl = _incomingFlowControl conn waitDataFrames xs = do ev <- _waitEvent stream case ev of @@ -142,9 +147,19 @@ waitStream stream streamFlowControl ppHandler = do | HTTP2.testEndStream (HTTP2.flags fh) -> return ((Right x):xs, Nothing) | otherwise -> do - _ <- lift $ _consumeCredit streamFlowControl (HTTP2.payloadLength fh) - lift $ _addCredit streamFlowControl (HTTP2.payloadLength fh) + let size = HTTP2.payloadLength fh + _ <- lift $ _consumeCredit streamFlowControl size + lift $ _addCredit streamFlowControl size _ <- _updateWindow $ streamFlowControl + -- We also send a WINDOW_UPDATE for the connection in order + -- to not rely on external updateWindow calls. This reduces + -- latency and makes the function less error-prone to use. + -- Note that the main loop (dispatchLoop) already credits + -- the connection for received data frames, but it does not + -- send the WINDOW_UPDATE frames.. That is why we only send + -- those frames here, and we do not credit the connection + -- as we do the stream in the preceding lines. + _ <- _updateWindow $ connFlowControl waitDataFrames ((Right x):xs) StreamPushPromiseEvent _ ppSid ppHdrs -> do _handlePushPromise stream ppSid ppHdrs ppHandler