warp 3.1.7 → 3.1.8
raw patch · 8 files changed
+53/−42 lines, 8 filesdep ~http2
Dependency ranges changed: http2
Files
- ChangeLog.md +4/−0
- Network/Wai/Handler/Warp/HTTP2/HPACK.hs +2/−1
- Network/Wai/Handler/Warp/HTTP2/Receiver.hs +20/−19
- Network/Wai/Handler/Warp/HTTP2/Sender.hs +9/−8
- Network/Wai/Handler/Warp/HTTP2/Types.hs +8/−4
- Network/Wai/Handler/Warp/HTTP2/Worker.hs +5/−4
- README.md +2/−3
- warp.cabal +3/−3
ChangeLog.md view
@@ -1,3 +1,7 @@+## 3.1.8++* Using the new priority queue based on PSQ provided by http2 lib.+ ## 3.1.7 * A concatenated Cookie header is prepended to the headers to ensure that it flows pseudo headers. [#454](https://github.com/yesodweb/wai/pull/454)
Network/Wai/Handler/Warp/HTTP2/HPACK.hs view
@@ -22,7 +22,8 @@ -- $setup -- >>> :set -XOverloadedStrings --- fixme: should we split "Set-Cookie:" headers?+-- Set-Cookie: contains only one cookie value.+-- So, we don't need to split it. hpackEncodeHeader :: Context -> InternalInfo -> S.Settings -> H.Status -> H.ResponseHeaders -> IO Builder hpackEncodeHeader ctx ii settings s h = do
Network/Wai/Handler/Warp/HTTP2/Receiver.hs view
@@ -41,17 +41,17 @@ | Just (ConnectionError err msg) <- E.fromException e = do csid <- readIORef currentStreamId let frame = goawayFrame csid err msg- enqueue outputQ (OGoaway frame) highestPriority+ enqueue outputQ 0 controlPriority $ OGoaway frame | otherwise = return () sendReset err sid = do let frame = resetFrame err sid- enqueue outputQ (OFrame frame) highestPriority+ enqueue outputQ 0 controlPriority $ OFrame frame loop = do hd <- recvN frameHeaderLength if BS.null hd then- enqueue outputQ OFinish highestPriority+ enqueue outputQ 0 controlPriority OFinish else do cont <- processStreamGuardingError $ decodeFrameHeader hd when cont loop@@ -186,7 +186,7 @@ unless (testAck flags) $ do modifyIORef http2settings $ \old -> updateSettings old alist let frame = settingsFrame setAck []- enqueue outputQ (OSettings frame alist) highestPriority+ enqueue outputQ 0 controlPriority $ OSettings frame alist return True control FramePing FrameHeader{flags} bs Context{outputQ} =@@ -194,11 +194,11 @@ E.throwIO $ ConnectionError ProtocolError "the ack flag of this ping frame must not be set" else do let frame = pingFrame bs- enqueue outputQ (OFrame frame) defaultPriority+ enqueue outputQ 0 controlPriority $ OFrame frame return True control FrameGoAway _ _ Context{outputQ} = do- enqueue outputQ OFinish highestPriority+ enqueue outputQ 0 controlPriority OFinish return False control FrameWindowUpdate header bs Context{connectionWindow} = do@@ -271,7 +271,7 @@ let frame1 = windowUpdateFrame 0 payloadLength frame2 = windowUpdateFrame streamNumber payloadLength frame = frame1 `BS.append` frame2- enqueue outputQ (OFrame frame) highestPriority+ enqueue outputQ 0 controlPriority $ OFrame frame atomically $ writeTQueue q body if endOfStream then do mcl <- readIORef streamContentLength@@ -310,24 +310,25 @@ atomically $ writeTVar streamWindow w return s -stream FrameRSTStream header bs _ _ strm = do+stream FrameRSTStream header bs ctx _ strm = do RSTStreamFrame e <- guardIt $ decoderstStreamFrame header bs let cc = Reset e- closed strm cc+ closed strm cc ctx return $ Closed cc -- will be written to streamState again stream FramePriority header bs Context{outputQ} s Stream{streamNumber,streamPriority} = do- PriorityFrame p <- guardIt $ decodePriorityFrame header bs- checkPriority p streamNumber- -- checkme: this should be tested- -- fixme: This works well when the priority gets lower because- -- the old higher priority value comes out from the queue quickly- -- and the new lower priority is used when enqueuing again.- -- But when the priority get higher, it takes time to use the new- -- priority.- writeIORef streamPriority p+ PriorityFrame newp <- guardIt $ decodePriorityFrame header bs+ checkPriority newp streamNumber -- checkme: this should be tested- when (isIdle s) $ prepare outputQ streamNumber p+ oldp <- readIORef streamPriority+ writeIORef streamPriority newp+ if isIdle s then+ prepare outputQ streamNumber newp+ else do+ mx <- delete outputQ streamNumber oldp+ case mx of+ Nothing -> return ()+ Just x -> enqueue outputQ streamNumber newp x return s -- this ordering is important
Network/Wai/Handler/Warp/HTTP2/Sender.hs view
@@ -60,15 +60,16 @@ -- | Run the given action if the stream is not closed; handle any exceptions by -- resetting the stream.-unlessClosed :: Connection -> Stream -> IO () -> IO Bool-unlessClosed Connection{connSendAll}+unlessClosed :: Context -> Connection -> Stream -> IO () -> IO Bool+unlessClosed ctx+ Connection{connSendAll} strm@Stream{streamState,streamNumber} body = E.handle resetStream $ do state <- readIORef streamState if (isClosed state) then return False else body >> return True where resetStream e = do- closed strm (ResetByMe e)+ closed strm (ResetByMe e) ctx let rst = resetFrame InternalError streamNumber connSendAll rst return False@@ -99,7 +100,7 @@ loop -- ignoring the old priority because the value might be changed.- loop = dequeue outputQ >>= \(out, _) -> switch out+ loop = dequeue outputQ >>= \(_sid,out) -> switch out ignore :: E.SomeException -> IO () ignore _ = return ()@@ -118,12 +119,12 @@ connSendAll frame loop switch (OResponse strm s h aux) = do- _ <- unlessClosed conn strm $+ _ <- unlessClosed ctx conn strm $ getWindowSize connectionWindow (streamWindow strm) >>= sendResponse strm s h aux loop switch (ONext strm curr) = do- _ <- unlessClosed conn strm $ do+ _ <- unlessClosed ctx conn strm $ do lim <- getWindowSize connectionWindow (streamWindow strm) -- Data frame payload Next datPayloadLen mnext <- curr lim@@ -131,7 +132,7 @@ dispatchNext strm mnext loop switch (OPush oldStrm push mvar strm s h aux) = do- pushed <- unlessClosed conn oldStrm $ do+ pushed <- unlessClosed ctx conn oldStrm $ do lim <- getWindowSize connectionWindow (streamWindow strm) -- Write and send the promise. builder <- hpackEncodeCIHeaders ctx $ promiseHeaders push@@ -183,7 +184,7 @@ -- 'closed' must be before 'flushN'. If not, the context would be -- switched to the receiver, resulting in the inconsistency of -- concurrency.- closed strm Finished+ closed strm Finished ctx flushN toFlush -- Flush the connection buffer to the socket, where the first 'n' bytes of
Network/Wai/Handler/Warp/HTTP2/Types.hs view
@@ -248,10 +248,14 @@ atomicModifyIORef' concurrencyRef (\x -> (x+1,())) writeIORef streamState (Open JustOpened) -closed :: Stream -> ClosedCode -> IO ()-closed Stream{concurrencyRef,streamState} cc = do+closed :: Stream -> ClosedCode -> Context -> IO ()+closed Stream{concurrencyRef,streamState,streamNumber,streamPriority}+ cc+ Context{outputQ} = do atomicModifyIORef' concurrencyRef (\x -> (x-1,())) writeIORef streamState (Closed cc)+ pri <- readIORef streamPriority+ clear outputQ streamNumber pri ---------------------------------------------------------------- @@ -297,7 +301,7 @@ x <- readTVar $ streamWindow strm check (x > 0) pri <- readIORef $ streamPriority strm- enqueue outQ out pri+ enqueue outQ (streamNumber strm) pri out enqueueOrSpawnTemporaryWaiter :: Stream -> PriorityTree Output -> Output -> IO () enqueueOrSpawnTemporaryWaiter strm outQ out = do@@ -307,4 +311,4 @@ void $ forkIO $ enqueueWhenWindowIsOpen outQ out else do pri <- readIORef $ streamPriority strm- enqueue outQ out pri+ enqueue outQ (streamNumber strm) pri out
Network/Wai/Handler/Warp/HTTP2/Worker.hs view
@@ -96,10 +96,11 @@ -- | Handle abnormal termination of a stream: mark it as closed, send a reset -- frame, and call the user's 'settingsOnException' handler if applicable. cleanupStream :: Context -> S.Settings -> Stream -> Maybe Request -> Maybe SomeException -> IO ()-cleanupStream Context{outputQ} set strm req me = do- closed strm Killed- let frame = resetFrame InternalError (streamNumber strm)- enqueue outputQ (OFrame frame) highestPriority+cleanupStream ctx@Context{outputQ} set strm req me = do+ closed strm Killed ctx+ let sid = streamNumber strm+ frame = resetFrame InternalError sid+ enqueue outputQ sid controlPriority $ OFrame frame case me of Nothing -> return () Just e -> S.settingsOnException set req e
README.md view
@@ -1,4 +1,3 @@-## warp+# Warp -The premier WAI handler. For more information, see [Warp: A Haskell Web-Server](http://steve.vinoski.net/blog/2011/05/01/warp-a-haskell-web-server/).+Warp is a server library for HTTP/1.x and HTTP/2 based WAI(Web Application Interface in Haskell). For more information, see [Warp](http://www.aosabook.org/en/posa/warp.html).
warp.cabal view
@@ -1,5 +1,5 @@ Name: warp-Version: 3.1.7+Version: 3.1.8 Synopsis: A fast, light-weight web server for WAI applications. License: MIT License-file: LICENSE@@ -42,7 +42,7 @@ , ghc-prim , http-types >= 0.8.5 , iproute >= 1.3.1- , http2 >= 1.1+ , http2 >= 1.2 , simple-sendfile >= 0.2.7 && < 0.3 , unix-compat >= 0.2 , wai >= 3.0.4 && < 3.1@@ -160,7 +160,7 @@ , directory , process , containers- , http2 >= 1.1+ , http2 >= 1.2 , word8 , hashable