on master help sign in
Guarantee atomicity of WINDOW_UPDATE increments.

The current code may lead to over-estimating the window size. The over-estimation occurs as follows: - the initial window state is W - the receiver observes a window update and computes W+K in a first transaction - the sender decrease the window by the payload size P, hence the window state is set to W-P - the receiver writes W+K in the second transaction This over-estimation carries over and may lead to unexpected GOAWAYs.

commit2b97428ca7187e469c0dbe6044913c3d741b361e authorLucas DiCioccio <lucas@dicioccio.fr> dateThu 25 May 2017, 21:38 (9 years ago) parent3a1c271
1 file changed+10−4
warp/Network/Wai/Handler/Warp/HTTP2/Receiver.hs+10−4
warp/Network/Wai/Handler/Warp/HTTP2/Receiver.hs+10−4
@@ -232,9 +232,12 @@ control FrameGoAway _ _ Context{controlQ} = do
232232
233233control FrameWindowUpdate header bs Context{connectionWindow} = do
234234 WindowUpdateFrame n <- guardIt $ decodeWindowUpdateFrame header bs
235− !w <- (n +) <$> atomically (readTVar connectionWindow)
235+ !w <- atomically $ do
236+ w0 <- readTVar connectionWindow
237+ let w1 = w0 + n
238+ writeTVar connectionWindow w1
239+ return w1
236240 when (isWindowOverflow w) $ E.throwIO $ ConnectionError FlowControlError "control window should be less than 2^31"
237− atomically $ writeTVar connectionWindow w
238241 return True
239242
240243control _ _ _ _ =
@@ -336,10 +339,13 @@ stream FrameContinuation FrameHeader{flags} frag ctx (Open (Continued rfrags siz
336339
337340stream FrameWindowUpdate header@FrameHeader{streamId} bs _ s Stream{streamWindow} = do
338341 WindowUpdateFrame n <- guardIt $ decodeWindowUpdateFrame header bs
339− !w <- (n +) <$> atomically (readTVar streamWindow)
342+ !w <- atomically $ do
343+ w0 <- readTVar streamWindow
344+ let w1 = w0 + n
345+ writeTVar streamWindow w1
346+ return w1
340347 when (isWindowOverflow w) $
341348 E.throwIO $ StreamError FlowControlError streamId
342− atomically $ writeTVar streamWindow w
343349 return s
344350
345351stream FrameRSTStream header bs ctx _ strm = do