packages feed

http3 0.0.16 → 0.0.17

raw patch · 3 files changed

+91/−21 lines, 3 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

+ Network.HTTP3.Server: ServerIO :: SockAddr -> SockAddr -> IO (a, Request) -> (a -> Response -> IO ()) -> ServerIO a
+ Network.HTTP3.Server: [sioMySockAddr] :: ServerIO a -> SockAddr
+ Network.HTTP3.Server: [sioPeerSockAddr] :: ServerIO a -> SockAddr
+ Network.HTTP3.Server: [sioReadRequest] :: ServerIO a -> IO (a, Request)
+ Network.HTTP3.Server: [sioWriteResponse] :: ServerIO a -> a -> Response -> IO ()
+ Network.HTTP3.Server: data () => ServerIO a
+ Network.HTTP3.Server: runIO :: Connection -> Config -> (ServerIO Stream -> IO (IO ())) -> IO ()

Files

ChangeLog.md view
@@ -1,5 +1,9 @@ # Revision history for http3 +## 0.0.17++* Providing ServerIO API+ ## 0.0.16  * Using quic v0.2
Network/HTTP3/Server.hs view
@@ -13,14 +13,21 @@     Hooks (..),     defaultHooks,     module Network.HTTP.Semantics.Server,++    -- * Internal+    runIO,+    ServerIO (..), ) where  import Control.Concurrent+import Control.Concurrent.Async+import Control.Concurrent.STM import Data.IORef import Network.HTTP.Semantics import Network.HTTP.Semantics.Server import Network.HTTP.Semantics.Server.Internal-import Network.QUIC (Connection, Stream)+import Network.HTTP2.Server.Internal (ServerIO (..))+import Network.QUIC (Connection, ConnectionInfo (..), Stream, getConnectionInfo) import qualified Network.QUIC as QUIC import qualified System.TimeManager as T import qualified UnliftIO.Exception as E@@ -40,16 +47,42 @@ run conn conf server = E.bracket open close $ \ctx -> do     tid <- forkIO $ setupUnidirectional conn conf     addThreadId ctx tid-    readerServer ctx server+    readerServer ctx $ \strm ->+        void $+            forkFinally+                (processRequest ctx server strm)+                (\_ -> closeStream strm)   where     open = do         ref <- newIORef IInit         newContext conn conf (controlStream conn ref)     close = clearContext -readerServer :: Context -> Server -> IO ()-readerServer ctx server = loop+runIO :: Connection -> Config -> (ServerIO Stream -> IO (IO ())) -> IO ()+runIO conn conf action = E.bracket open close $ \ctx -> do+    tid <- forkIO $ setupUnidirectional conn conf+    info <- getConnectionInfo conn+    addThreadId ctx tid+    reqq <- newTQueueIO+    let sio =+            ServerIO+                { sioMySockAddr = localSockAddr info+                , sioPeerSockAddr = remoteSockAddr info+                , sioReadRequest = atomically $ readTQueue reqq+                , sioWriteResponse = sendResponseIO ctx+                }+        put strmreq = atomically $ writeTQueue reqq strmreq+    io <- action sio+    concurrently_ io (readerServer ctx $ processRequestIO ctx put)   where+    open = do+        ref <- newIORef IInit+        newContext conn conf (controlStream conn ref)+    close = clearContext++readerServer :: Context -> (Stream -> IO ()) -> IO ()+readerServer ctx action = loop+  where     loop = do         accept ctx >>= process         loop@@ -57,8 +90,7 @@         | QUIC.isClientInitiatedUnidirectional sid = do             tid <- forkIO $ unidirectional ctx strm             addThreadId ctx tid-        | QUIC.isClientInitiatedBidirectional sid =-            void $ forkFinally (processRequest ctx server strm) (\_ -> closeStream strm)+        | QUIC.isClientInitiatedBidirectional sid = action strm         | QUIC.isServerInitiatedUnidirectional sid = return () -- error         | otherwise = return ()       where@@ -71,20 +103,8 @@     mvt <- recvHeader ctx src     case mvt of         Nothing -> QUIC.resetStream strm H3MessageError-        Just ht@(_, vt) -> do-            let mMethod = getFieldValue tokenMethod vt-                mScheme = getFieldValue tokenScheme vt-                mAuthority = getFieldValue tokenAuthority vt-                mPath = getFieldValue tokenPath vt-            case (mMethod, mScheme, mAuthority, mPath) of-                (Just "CONNECT", _, Just _, _) -> return ()-                (Just _, Just _, Just _, Just _) -> return ()-                _ -> QUIC.resetStream strm H3MessageError-            -- fixme: Content-Length-            refI <- newIORef IInit-            refH <- newIORef Nothing-            let readB = recvBody ctx src refI refH-                req = Request $ InpObj ht Nothing readB refH+        Just ht -> do+            req <- mkRequest ctx strm src ht             let aux = Aux th (getMySockAddr ctx) (getPeerSockAddr ctx)             server req aux $ sendResponse ctx strm th   where@@ -93,9 +113,54 @@             abort ctx QpackDecompressionFailed         | otherwise = QUIC.resetStream strm H3MessageError +processRequestIO :: Context -> ((Stream, Request) -> IO ()) -> Stream -> IO ()+processRequestIO ctx put strm = E.handleAny reset $ do+    src <- newSource strm+    mvt <- recvHeader ctx src+    case mvt of+        Nothing -> QUIC.resetStream strm H3MessageError+        Just ht -> do+            req <- mkRequest ctx strm src ht+            put (strm, req)+  where+    reset se+        | Just (_ :: DecodeError) <- E.fromException se =+            abort ctx QpackDecompressionFailed+        | otherwise = QUIC.resetStream strm H3MessageError++mkRequest+    :: Context+    -> Stream+    -> Source+    -> (TokenHeaderList, ValueTable)+    -> IO Request+mkRequest ctx strm src ht@(_, vt) = do+    let mMethod = getFieldValue tokenMethod vt+        mScheme = getFieldValue tokenScheme vt+        mAuthority = getFieldValue tokenAuthority vt+        mPath = getFieldValue tokenPath vt+    case (mMethod, mScheme, mAuthority, mPath) of+        (Just "CONNECT", _, Just _, _) -> return ()+        (Just _, Just _, Just _, Just _) -> return ()+        _ -> QUIC.resetStream strm H3MessageError+    -- fixme: Content-Length+    refI <- newIORef IInit+    refH <- newIORef Nothing+    let readB = recvBody ctx src refI refH+        req = Request $ InpObj ht Nothing readB refH+    return req+ sendResponse     :: Context -> Stream -> T.Handle -> Response -> [PushPromise] -> IO () sendResponse ctx strm th (Response outobj) _pp = do     sendHeader ctx strm th $ outObjHeaders outobj     sendBody ctx strm th outobj     QUIC.shutdownStream strm++sendResponseIO+    :: Context -> Stream -> Response -> IO ()+sendResponseIO ctx strm (Response outobj) = do+    th <- registerThread ctx -- fixme+    sendHeader ctx strm th $ outObjHeaders outobj+    sendBody ctx strm th outobj+    QUIC.closeStream strm
http3.cabal view
@@ -1,6 +1,6 @@ cabal-version:      2.4 name:               http3-version:            0.0.16+version:            0.0.17 license:            BSD-3-Clause license-file:       LICENSE maintainer:         Kazu Yamamoto <kazu@iij.ad.jp>@@ -77,6 +77,7 @@     ghc-options:        -Wall     build-depends:         base >=4.9 && <5,+        async,         array,         bytestring,         case-insensitive,