packages feed

http2-tls 0.0.1 → 0.1.0

raw patch · 9 files changed

+212/−85 lines, 9 filesdep +crypton-x509-storedep +crypton-x509-validationdep ~http2PVP ok

version bump matches the API change (PVP)

Dependencies added: crypton-x509-store, crypton-x509-validation

Dependency ranges changed: http2

API changes (from Hackage documentation)

- Network.HTTP2.TLS.Client: type Client a = Request -> Response -> IO a -> IO a -> IO a
- Network.HTTP2.TLS.Server: settingReadBufferLowerLimit :: Settings -> Int
- Network.HTTP2.TLS.Server: settingReadBufferSize :: Settings -> Int
+ Network.HTTP2.TLS.Client: data Settings
+ Network.HTTP2.TLS.Client: defaultSettings :: Settings
+ Network.HTTP2.TLS.Client: settingsAddrInfoFlags :: Settings -> [AddrInfoFlag]
+ Network.HTTP2.TLS.Client: settingsCAStore :: Settings -> CertificateStore
+ Network.HTTP2.TLS.Client: settingsKeyLogger :: Settings -> String -> IO ()
+ Network.HTTP2.TLS.Client: settingsValidateCert :: Settings -> Bool
+ Network.HTTP2.TLS.Client: type Client a = forall b. () => Request -> Response -> IO b -> IO b -> IO a
+ Network.HTTP2.TLS.Internal: [mySockAddr] :: IOBackend -> SockAddr
+ Network.HTTP2.TLS.Internal: [peerSockAddr] :: IOBackend -> SockAddr
+ Network.HTTP2.TLS.Internal: gclose :: Socket -> IO ()
+ Network.HTTP2.TLS.Server: mySockAddr :: IOBackend -> SockAddr
+ Network.HTTP2.TLS.Server: peerSockAddr :: IOBackend -> SockAddr
+ Network.HTTP2.TLS.Server: settingsKeyLogger :: Settings -> String -> IO ()
+ Network.HTTP2.TLS.Server: settingsReadBufferLowerLimit :: Settings -> Int
+ Network.HTTP2.TLS.Server: settingsReadBufferSize :: Settings -> Int
- Network.HTTP2.TLS.Client: run :: HostName -> PortNumber -> Client a -> IO a
+ Network.HTTP2.TLS.Client: run :: Settings -> HostName -> PortNumber -> Client a -> IO a
- Network.HTTP2.TLS.Client: runTLS :: HostName -> PortNumber -> ByteString -> (Context -> IO a) -> IO a
+ Network.HTTP2.TLS.Client: runTLS :: Settings -> HostName -> PortNumber -> ByteString -> (Context -> SockAddr -> SockAddr -> IO a) -> IO a
- Network.HTTP2.TLS.Internal: IOBackend :: (ByteString -> IO ()) -> ([ByteString] -> IO ()) -> IO ByteString -> IOBackend
+ Network.HTTP2.TLS.Internal: IOBackend :: (ByteString -> IO ()) -> ([ByteString] -> IO ()) -> IO ByteString -> SockAddr -> SockAddr -> IOBackend
- Network.HTTP2.TLS.Internal: tlsIOBackend :: Context -> IOBackend
+ Network.HTTP2.TLS.Internal: tlsIOBackend :: Context -> Socket -> IO IOBackend

Files

Network/HTTP2/TLS/Client.hs view
@@ -1,4 +1,5 @@ {-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE RankNTypes #-} {-# LANGUAGE RecordWildCards #-}  -- | Running an HTTP\/2 client over TLS.@@ -10,11 +11,20 @@     HostName,     PortNumber,     runTLS,++    -- * Settings+    Settings,+    defaultSettings,+    settingsKeyLogger,+    settingsValidateCert,+    settingsCAStore,+    settingsAddrInfoFlags, ) where  import Data.ByteString (ByteString) import qualified Data.ByteString.Char8 as C8 import Data.Default.Class (def)+import Data.X509.Validation (validateDefault) import Network.HTTP2.Client (     Client,     ClientConfig (..),@@ -24,55 +34,64 @@ import Network.TLS hiding (HostName) import qualified UnliftIO.Exception as E +import Network.HTTP2.TLS.Client.Settings import Network.HTTP2.TLS.Config import Network.HTTP2.TLS.IO-import Network.HTTP2.TLS.Settings+import Network.HTTP2.TLS.Internal (gclose)+import qualified Network.HTTP2.TLS.Server.Settings as Server import Network.HTTP2.TLS.Supported  ----------------------------------------------------------------  -- | Running a TLS client. runTLS-    :: HostName+    :: Settings+    -> HostName     -> PortNumber     -> ByteString     -- ^ ALPN-    -> (Context -> IO a)+    -> (Context -> SockAddr -> SockAddr -> IO a)     -> IO a-runTLS serverName port alpn action =-    E.bracket open close $ \sock -> do+runTLS settings serverName port alpn action =+    E.bracket open gclose $ \sock -> do+        mysa <- getSocketName sock+        peersa <- getPeerName sock         E.bracket (contextNew sock params) bye $ \ctx -> do             handshake ctx-            action ctx+            action ctx mysa peersa   where-    open = openTCP serverName port-    params = getClientParams serverName alpn False+    open = openTCP (settingsAddrInfoFlags settings) serverName port+    params = getClientParams settings serverName alpn  -- | Running an HTTP\/2 client over TLS (over TCP).-run :: HostName -> PortNumber -> Client a -> IO a-run serverName port client =-    runTLS serverName port "h2" $ \ctx ->-        run' "https" serverName (sendTLS ctx) (recvTLS ctx) client+run :: Settings -> HostName -> PortNumber -> Client a -> IO a+run settings serverName port client =+    runTLS settings serverName port "h2" $ \ctx mysa peersa ->+        run' "https" serverName (sendTLS ctx) (recvTLS ctx) mysa peersa client  -- | Running an HTTP\/2 client over TCP. runH2C :: HostName -> PortNumber -> Client a -> IO a runH2C serverName port client =     E.bracket open close $ \sock -> do-        recv <- mkRecvTCP defaultSettings sock-        run' "http" serverName (sendTCP sock) recv client+        mysa <- getSocketName sock+        peersa <- getPeerName sock+        recv <- mkRecvTCP Server.defaultSettings sock+        run' "http" serverName (sendTCP sock) recv mysa peersa client   where-    open = openTCP serverName port+    open = openTCP (settingsAddrInfoFlags defaultSettings) serverName port  run'     :: ByteString     -> HostName     -> (ByteString -> IO ())     -> IO ByteString+    -> SockAddr+    -> SockAddr     -> Client a     -> IO a-run' schm serverName send recv client =+run' schm serverName send recv mysa peersa client =     E.bracket-        (allocConfigForClient send recv)+        (allocConfigForClient send recv mysa peersa)         freeConfigForClient         (\conf -> H2Client.run cliconf conf client)   where@@ -83,18 +102,18 @@             , cacheLimit = 20             } -openTCP :: HostName -> PortNumber -> IO Socket-openTCP h p = do-    ai <- makeAddrInfo h p+openTCP :: [AddrInfoFlag] -> HostName -> PortNumber -> IO Socket+openTCP flags h p = do+    ai <- makeAddrInfo flags h p     sock <- openSocket ai     connect sock $ addrAddress ai     return sock -makeAddrInfo :: HostName -> PortNumber -> IO AddrInfo-makeAddrInfo nh p = do+makeAddrInfo :: [AddrInfoFlag] -> HostName -> PortNumber -> IO AddrInfo+makeAddrInfo flags nh p = do     let hints =             defaultHints-                { addrFlags = [AI_ADDRCONFIG, AI_NUMERICHOST, AI_NUMERICSERV]+                { addrFlags = flags                 , addrSocketType = Stream                 }     let np = show p@@ -103,33 +122,42 @@ ----------------------------------------------------------------  getClientParams-    :: HostName+    :: Settings+    -> HostName     -> ByteString     -- ^ ALPN-    -> Bool-    -- ^ Checking server certificates     -> ClientParams-getClientParams serverName alpn validate =+getClientParams Settings{..} serverName alpn =     (defaultParamsClient serverName "")         { clientSupported = supported         , clientWantSessionResume = Nothing         , clientUseServerNameIndication = True         , clientShared = shared         , clientHooks = hooks+        , clientDebug = debug         }   where     shared =         def             { sharedValidationCache = validateCache+            , sharedCAStore = settingsCAStore             }     supported = strongSupported     hooks =         def             { onSuggestALPN = return $ Just [alpn]+            , onServerCertificate = validateCert             }     validateCache-        | validate = def+        | settingsValidateCert = def         | otherwise =             ValidationCache                 (\_ _ _ -> return ValidationCachePass)                 (\_ _ _ -> return ())+    validateCert+        | settingsValidateCert = validateDefault+        | otherwise = \_ _ _ _ -> return []+    debug =+        def+            { debugKeyLogger = settingsKeyLogger+            }
+ Network/HTTP2/TLS/Client/Settings.hs view
@@ -0,0 +1,34 @@+module Network.HTTP2.TLS.Client.Settings where++import Data.X509.CertificateStore (CertificateStore)+import Network.Socket++-- Client settings type.+data Settings = Settings+    { settingsKeyLogger :: String -> IO ()+    -- ^ Key logger+    --+    -- Applications may wish to set this depending on the SSLKEYLOGFILE environment variable. Default is do nothing.+    , settingsValidateCert :: Bool+    -- ^ Should we validate TLS certificates?+    --+    -- >>> settingsValidateCert defaultSettings+    -- True+    , settingsCAStore :: CertificateStore+    -- ^ Certificate store used for validation. The default is 'mempty'.+    , settingsAddrInfoFlags :: [AddrInfoFlag]+    -- ^ Flags that control the querying behaviour of @getAddrInfo@.+    --+    -- >>> settingsAddrInfoFlags defaultSettings+    -- []+    }++-- | Default settings.+defaultSettings :: Settings+defaultSettings =+    Settings+        { settingsKeyLogger = \_ -> return ()+        , settingsValidateCert = True+        , settingsCAStore = mempty+        , settingsAddrInfoFlags = []+        }
Network/HTTP2/TLS/Config.hs view
@@ -9,14 +9,21 @@     Config (..),     defaultPositionReadMaker,  )+import Network.Socket (SockAddr) import Network.Socket.BufferPool import qualified System.TimeManager as T -import Network.HTTP2.TLS.Settings+import Network.HTTP2.TLS.Server.Settings  allocConfigForServer-    :: Settings -> T.Manager -> (ByteString -> IO ()) -> IO ByteString -> IO Config-allocConfigForServer Settings{..} mgr send recv = do+    :: Settings+    -> T.Manager+    -> (ByteString -> IO ())+    -> IO ByteString+    -> SockAddr+    -> SockAddr+    -> IO Config+allocConfigForServer Settings{..} mgr send recv mysa peersa = do     buf <- mallocBytes settingsSendBufferSize     recvN <- makeRecvN "" recv     let config =@@ -27,6 +34,8 @@                 , confReadN = recvN                 , confPositionReadMaker = defaultPositionReadMaker                 , confTimeoutManager = mgr+                , confMySockAddr = mysa+                , confPeerSockAddr = peersa                 }     return config @@ -34,9 +43,9 @@ freeConfigForServer :: Config -> IO () freeConfigForServer conf = free $ confWriteBuffer conf --allocConfigForClient :: (ByteString -> IO ()) -> IO ByteString -> IO Config-allocConfigForClient send recv = do+allocConfigForClient+    :: (ByteString -> IO ()) -> IO ByteString -> SockAddr -> SockAddr -> IO Config+allocConfigForClient send recv mysa peersa = do     let wbufsiz = 4096 -- fixme     buf <- mallocBytes wbufsiz     recvN <- makeRecvN "" recv@@ -51,6 +60,8 @@                 , confReadN = recvN                 , confPositionReadMaker = defaultPositionReadMaker                 , confTimeoutManager = mgr+                , confMySockAddr = mysa+                , confPeerSockAddr = peersa                 }     return config 
Network/HTTP2/TLS/IO.hs view
@@ -16,7 +16,7 @@ import qualified System.TimeManager as T import qualified UnliftIO.Exception as E -import Network.HTTP2.TLS.Settings+import Network.HTTP2.TLS.Server.Settings  ---------------------------------------------------------------- @@ -27,7 +27,7 @@  mkRecvTCP :: Settings -> Socket -> IO (IO ByteString) mkRecvTCP Settings{..} sock = do-    pool <- newBufferPool settingReadBufferLowerLimit settingReadBufferSize+    pool <- newBufferPool settingsReadBufferLowerLimit settingsReadBufferSize     return $ receive sock pool  sendTCP :: Socket -> ByteString -> IO ()@@ -46,11 +46,13 @@     -- ^ Sending many.     , recv :: IO ByteString     -- ^ Receiving.+    , mySockAddr :: SockAddr+    , peerSockAddr :: SockAddr     }  timeoutIOBackend :: T.Handle -> Settings -> IOBackend -> IOBackend timeoutIOBackend th Settings{..} IOBackend{..} =-    IOBackend send' sendMany' recv'+    IOBackend send' sendMany' recv' mySockAddr peerSockAddr   where     send' bs = send bs >> T.tickle th     sendMany' bss = sendMany bss >> T.tickle th@@ -59,22 +61,31 @@         when (BS.length bs > settingsSlowlorisSize) $ T.tickle th         return bs -tlsIOBackend :: Context -> IOBackend-tlsIOBackend ctx =-    IOBackend-        { send = sendTLS ctx-        , sendMany = sendManyTLS ctx-        , recv = recvTLS ctx-        }+tlsIOBackend :: Context -> Socket -> IO IOBackend+tlsIOBackend ctx sock = do+    mysa <- getSocketName sock+    peersa <- getPeerName sock+    return $+        IOBackend+            { send = sendTLS ctx+            , sendMany = sendManyTLS ctx+            , recv = recvTLS ctx+            , mySockAddr = mysa+            , peerSockAddr = peersa+            }  tcpIOBackend :: Settings -> Socket -> IO IOBackend tcpIOBackend settings sock = do     recv' <- mkRecvTCP settings sock+    mysa <- getSocketName sock+    peersa <- getPeerName sock     return $         IOBackend             { send = void . NSB.send sock             , sendMany = \_ -> return ()             , recv = recv'+            , mySockAddr = mysa+            , peerSockAddr = peersa             }  ----------------------------------------------------------------@@ -85,6 +96,7 @@ sendManyTLS :: Context -> [ByteString] -> IO () sendManyTLS ctx = sendData ctx . LBS.fromChunks +{- FOURMOLU_DISABLE -} -- TLS version of recv (decrypting) without a cache. recvTLS :: Context -> IO ByteString recvTLS ctx = E.handle onEOF $ recvData ctx@@ -97,6 +109,7 @@ #endif         | Just ioe <- E.fromException e, isEOFError ioe = return ""         | otherwise = E.throwIO e+{- FOURMOLU_ENABLE -}  ---------------------------------------------------------------- 
Network/HTTP2/TLS/Internal.hs view
@@ -1,5 +1,17 @@+{-# LANGUAGE CPP #-}+ module Network.HTTP2.TLS.Internal (     module Network.HTTP2.TLS.IO,+    gclose, ) where +import Network.Socket+ import Network.HTTP2.TLS.IO++gclose :: Socket -> IO ()+#if MIN_VERSION_network(3,1,1)+gclose sock = gracefulClose sock 5000+#else+gclose = close+#endif
Network/HTTP2/TLS/Server.hs view
@@ -16,14 +16,17 @@     settingsTimeout,     settingsSendBufferSize,     settingsSlowlorisSize,-    settingReadBufferSize,-    settingReadBufferLowerLimit,+    settingsReadBufferSize,+    settingsReadBufferLowerLimit,+    settingsKeyLogger,      -- * IO backend     IOBackend,     send,     sendMany,     recv,+    mySockAddr,+    peerSockAddr, ) where  import Data.ByteString (ByteString)@@ -41,7 +44,7 @@  import Network.HTTP2.TLS.Config import Network.HTTP2.TLS.IO-import Network.HTTP2.TLS.Settings+import Network.HTTP2.TLS.Server.Settings import Network.HTTP2.TLS.Supported  -- | Running a TLS client.@@ -61,10 +64,10 @@         backend <- mkBackend settings sock         E.bracket (contextNew backend params) bye $ \ctx -> do             handshake ctx-            let iobackend = timeoutIOBackend th settings $ tlsIOBackend ctx+            iobackend <- timeoutIOBackend th settings <$> tlsIOBackend ctx sock             action mgr iobackend   where-    params = getServerParams creds alpn+    params = getServerParams creds alpn settingsKeyLogger  -- | Running an HTTP\/2 client over TLS (over TCP). --   ALPN is "h2".@@ -83,7 +86,7 @@ run' :: Settings -> Server -> T.Manager -> IOBackend -> IO () run' settings server mgr IOBackend{..} =     E.bracket-        (allocConfigForServer settings mgr send recv)+        (allocConfigForServer settings mgr send recv mySockAddr peerSockAddr)         freeConfigForServer         (\conf -> H2Server.run conf server) @@ -92,12 +95,14 @@ getServerParams     :: Credentials     -> ByteString+    -> (String -> IO ())     -> ServerParams-getServerParams creds alpn =+getServerParams creds alpn keyLogger =     def         { serverSupported = supported         , serverShared = shared         , serverHooks = hooks+        , serverDebug = debug         }   where     shared =@@ -109,6 +114,10 @@     hooks =         def             { onALPNClientSuggest = Just $ selectALPN alpn+            }+    debug =+        def+            { debugKeyLogger = keyLogger             }  selectALPN :: ByteString -> [ByteString] -> IO ByteString
+ Network/HTTP2/TLS/Server/Settings.hs view
@@ -0,0 +1,48 @@+module Network.HTTP2.TLS.Server.Settings where++-- Server settings type.+data Settings = Settings+    { settingsTimeout :: Int+    -- ^ Timeout in seconds. (All)+    --+    -- >>> settingsTimeout defaultSettings+    -- 30+    , settingsSendBufferSize :: Int+    -- ^ Send buffer size. (H2 and H2c)+    --+    -- >>> settingsSendBufferSize defaultSettings+    -- 4096+    , settingsSlowlorisSize :: Int+    -- ^ If the size of receiving data is less than or equal,+    --   the timeout is not reset.+    --   (All)+    --+    -- >>> settingsSlowlorisSize defaultSettings+    -- 50+    , settingsReadBufferSize :: Int+    -- ^ When the size of a read buffer is lower than this limit, the buffer is thrown awany (and is eventually freed). Then a new buffer is allocated. (All)+    --+    -- >>> settingsReadBufferSize defaultSettings+    -- 16384+    , settingsReadBufferLowerLimit :: Int+    -- ^  The allocation size for a read buffer.  (All)+    --+    -- >>> settingsReadBufferLowerLimit defaultSettings+    -- 2048+    , settingsKeyLogger :: String -> IO ()+    -- ^ Key logger (defaults to none)+    --+    -- Applications may wish to set this depending on the SSLKEYLOGFILE environment variable. The default is do nothing.+    }++-- | Default settings.+defaultSettings :: Settings+defaultSettings =+    Settings+        { settingsTimeout = 30+        , settingsSendBufferSize = 4096+        , settingsSlowlorisSize = 50+        , settingsReadBufferSize = 16384+        , settingsReadBufferLowerLimit = 2048+        , settingsKeyLogger = \_ -> return ()+        }
− Network/HTTP2/TLS/Settings.hs
@@ -1,31 +0,0 @@-module Network.HTTP2.TLS.Settings where---- Settings type.-data Settings = Settings-    { settingsTimeout :: Int-    -- ^ Timeout in seconds. (All)-    , settingsSendBufferSize :: Int-    -- ^ Send buffer size. (H2 and H2c)-    , settingsSlowlorisSize :: Int-    -- ^ If the size of receiving data is less than or equal,-    --   the timeout is not reset.-    --   (All)-    , settingReadBufferSize :: Int-    -- ^ When the size of a read buffer is lower than this limit, the buffer is thrown awany (and is eventually freed). Then a new buffer is allocated. (All)-    , settingReadBufferLowerLimit :: Int-    -- ^  The allocation size for a read buffer.  (All)-    } deriving (Eq, Show)---- | Default settings.------ >>> defaultSettings--- Settings {settingsTimeout = 30, settingsSendBufferSize = 4096, settingsSlowlorisSize = 50, settingReadBufferSize = 16384, settingReadBufferLowerLimit = 2048}-defaultSettings :: Settings-defaultSettings =-    Settings-        { settingsTimeout = 30-        , settingsSendBufferSize = 4096-        , settingsSlowlorisSize = 50-        , settingReadBufferSize = 16384-        , settingReadBufferLowerLimit = 2048-        }
http2-tls.cabal view
@@ -1,6 +1,6 @@ cabal-version:      >=1.10 name:               http2-tls-version:            0.0.1+version:            0.1.0 license:            BSD3 license-file:       LICENSE maintainer:         Kazu Yamamoto <kazu@iij.ad.jp>@@ -24,9 +24,10 @@         Network.HTTP2.TLS.Server      other-modules:+        Network.HTTP2.TLS.Client.Settings         Network.HTTP2.TLS.Config         Network.HTTP2.TLS.IO-        Network.HTTP2.TLS.Settings+        Network.HTTP2.TLS.Server.Settings         Network.HTTP2.TLS.Supported      default-language:   Haskell2010@@ -35,8 +36,10 @@     build-depends:         base >=4.9 && <5,         bytestring,+        crypton-x509-store,+        crypton-x509-validation,         data-default-class,-        http2,+        http2 >= 4.2.0,         network,         network-run >=0.2.6,         recv,