on master help sign in
Wrap recvN in HTTP2 to tickle the timer.

This patch addresses a bug preventing long HTTP2 connections. See #593 for an initial report, as well as https://github.com/yesodweb/wai/issues/593#issuecomment-304382746 for a reproducible example -- which this patch addresses (the actual root cause for #593 might differ but seem closely related).

commit9dc578ae90be229a11c9b6520013e07bc3fc691a authorLucas DiCioccio <lucas@dicioccio.fr> dateTue 30 May 2017, 20:30 (9 years ago) parent241a83c
1 file changed+16−2
warp/Network/Wai/Handler/Warp/Run.hs+16−2
warp/Network/Wai/Handler/Warp/Run.hs+16−2
@@ -331,12 +331,13 @@ serveConnection conn ii1 origAddr transport settings app = do
331331 return (True, bs0)
332332 else
333333 return (False, bs0)
334+ istatus <- newIORef False
334335 if settingsHTTP2Enabled settings && h2 then do
335− recvN <- makeReceiveN bs (connRecv conn) (connRecvBuf conn)
336+ rawRecvN <- makeReceiveN bs (connRecv conn) (connRecvBuf conn)
337+ let recvN = wrappedRecvN th istatus (settingsSlowlorisSize settings) rawRecvN
336338 -- fixme: origAddr
337339 http2 conn ii1 origAddr transport settings recvN app
338340 else do
339− istatus <- newIORef False
340341 src <- mkSource (wrappedRecv conn th istatus (settingsSlowlorisSize settings))
341342 writeIORef istatus True
342343 leftoverSource src bs
@@ -512,6 +513,19 @@ wrappedRecv Connection { connRecv = recv } th istatus slowlorisSize = do
512513 when (S.length bs >= slowlorisSize) $ T.tickle th
513514 return bs
514515
516+wrappedRecvN :: T.Handle -> IORef Bool -> Int -> (BufSize -> IO ByteString) -> (BufSize -> IO ByteString)
517+wrappedRecvN th istatus slowlorisSize readN bufsize = do
518+ bs <- readN bufsize
519+ unless (S.null bs) $ do
520+ writeIORef istatus True
521+ -- TODO: think about the slowloris protection in HTTP2: current code
522+ -- might open a slow-loris attack vector. Rather than timing we should
523+ -- consider limiting the per-client connections assuming that in HTTP2
524+ -- we should allow only few connections per host (real-world
525+ -- deployments with large NATs may be trickier).
526+ when (S.length bs >= slowlorisSize || bufsize <= slowlorisSize) $ T.tickle th
527+ return bs
528+
515529-- Copied from: https://github.com/mzero/plush/blob/master/src/Plush/Server/Warp.hs
516530setSocketCloseOnExec :: Socket -> IO ()
517531#if WINDOWS