warp 3.2.10 → 3.2.11
raw patch · 5 files changed
+41/−19 lines, 5 files
Files
- ChangeLog.md +4/−0
- Network/Wai/Handler/Warp/HTTP2/HPACK.hs +5/−2
- Network/Wai/Handler/Warp/HTTP2/Receiver.hs +25/−15
- Network/Wai/Handler/Warp/HTTP2/Types.hs +6/−1
- warp.cabal +1/−1
ChangeLog.md view
@@ -1,3 +1,7 @@+## 3.2.11++* Fixing 10 HTTP2 bugs pointed out by h2spec v2.+ ## 3.2.10 * Add `connFree` to `Connection`. Close socket connections on timeout triggered. Timeout exceptions extend from `SomeAsyncException`. [#602](https://github.com/yesodweb/wai/pull/602) [#605](https://github.com/yesodweb/wai/pull/605)
Network/Wai/Handler/Warp/HTTP2/HPACK.hs view
@@ -83,13 +83,16 @@ {-# INLINE checkRequestHeader #-} checkRequestHeader :: ValueTable -> Bool checkRequestHeader reqvt+ | just mMethod (== "CONNECT") = mPath == Nothing && mScheme == Nothing | mStatus /= Nothing = False | mMethod == Nothing = False+ | mScheme == Nothing = False+ | mPath == Nothing = False+ | mPath == Just "" = False | mAuthority == Nothing = False | mConnection /= Nothing = False | just mTE (/= "trailers") = False- | just mMethod (== "CONNECT") = mPath == Nothing && mScheme == Nothing- | otherwise = mPath /= Nothing+ | otherwise = True where mStatus = getHeaderValue tokenStatus reqvt mScheme = getHeaderValue tokenScheme reqvt
Network/Wai/Handler/Warp/HTTP2/Receiver.hs view
@@ -159,6 +159,8 @@ when (ftyp == FrameHeaders) $ do st <- readIORef $ streamState strm0 when (isHalfClosed st) $ E.throwIO $ ConnectionError StreamClosed "header must not be sent to half closed"+ -- Priority made an idele stream+ when (isIdle st) $ opened ctx strm0 return js Nothing | isResponse streamId -> return Nothing@@ -166,19 +168,23 @@ when (ftyp `notElem` [FrameHeaders,FramePriority]) $ E.throwIO $ ConnectionError ProtocolError "this frame is not allowed in an idel stream" csid <- readIORef clientStreamId- when (streamId <= csid) $- E.throwIO $ ConnectionError ProtocolError "stream identifier must not decrease"- when (ftyp == FrameHeaders) $ do- writeIORef clientStreamId streamId- cnt <- readIORef concurrency- -- Checking the limitation of concurrency- when (cnt >= maxConcurrency) $- E.throwIO $ StreamError RefusedStream streamId- ws <- initialWindowSize <$> readIORef http2settings- newstrm <- newStream streamId (fromIntegral ws)- when (ftyp == FrameHeaders) $ opened ctx newstrm- insert streamTable streamId newstrm- return $ Just newstrm+ if streamId <= csid then do+ if ftyp == FramePriority then+ return Nothing -- will be ignored+ else+ E.throwIO $ ConnectionError ProtocolError "stream identifier must not decrease"+ else do+ when (ftyp == FrameHeaders) $ do+ writeIORef clientStreamId streamId+ cnt <- readIORef concurrency+ -- Checking the limitation of concurrency+ when (cnt >= maxConcurrency) $+ E.throwIO $ StreamError RefusedStream streamId+ ws <- initialWindowSize <$> readIORef http2settings+ newstrm <- newStream streamId (fromIntegral ws)+ when (ftyp == FrameHeaders) $ opened ctx newstrm+ insert streamTable streamId newstrm+ return $ Just newstrm consume = void . recvN @@ -191,14 +197,18 @@ ---------------------------------------------------------------- control :: FrameTypeId -> FrameHeader -> ByteString -> Context -> IO Bool-control FrameSettings header@FrameHeader{flags} bs Context{http2settings, controlQ,firstSettings} = do+control FrameSettings header@FrameHeader{flags} bs Context{http2settings, controlQ, firstSettings, streamTable} = do SettingsFrame alist <- guardIt $ decodeSettingsFrame header bs case checkSettingsList alist of Just x -> E.throwIO x Nothing -> return () -- HTTP/2 Setting from a browser unless (testAck flags) $ do+ oldws <- initialWindowSize <$> readIORef http2settings modifyIORef' http2settings $ \old -> updateSettings old alist+ newws <- initialWindowSize <$> readIORef http2settings+ let diff = newws - oldws+ when (diff /= 0) $ updateAllStreamWindow (+ diff) streamTable let !frame = settingsFrame setAck [] sent <- readIORef firstSettings let !setframe@@ -210,7 +220,7 @@ control FramePing FrameHeader{flags} bs Context{controlQ} = if testAck flags then- E.throwIO $ ConnectionError ProtocolError "the ack flag of this ping frame must not be set"+ return True -- just ignore else do let !frame = pingFrame bs enqueueControl controlQ $ CFrame frame
Network/Wai/Handler/Warp/HTTP2/Types.hs view
@@ -11,7 +11,7 @@ import Control.Concurrent (forkIO) import Control.Concurrent.STM import Control.Exception (SomeException, bracket)-import Control.Monad (void)+import Control.Monad (void, forM_) import Data.ByteString (ByteString) import qualified Data.ByteString as BS import Data.IntMap.Strict (IntMap, IntMap)@@ -255,6 +255,11 @@ search :: StreamTable -> M.Key -> IO (Maybe Stream) search (StreamTable ref) k = M.lookup k <$> readIORef ref++updateAllStreamWindow :: (WindowSize -> WindowSize) -> StreamTable -> IO ()+updateAllStreamWindow adst (StreamTable ref) = do+ strms <- M.elems <$> readIORef ref+ forM_ strms $ \strm -> atomically $ modifyTVar (streamWindow strm) adst {-# INLINE forkAndEnqueueWhenReady #-} forkAndEnqueueWhenReady :: IO () -> PriorityTree Output -> Output -> Manager -> IO ()
warp.cabal view
@@ -1,5 +1,5 @@ Name: warp-Version: 3.2.10+Version: 3.2.11 Synopsis: A fast, light-weight web server for WAI applications. License: MIT License-file: LICENSE