module Network.GRPC.Util.HTTP2 (
fromHeaderTable
, withConfigForInsecure
, withConfigForSecure
, mkServerConfig
, mkTlsSettings
, withTimeManager
) where
import Control.Exception
import Data.Bifunctor
import Data.ByteString qualified as Strict (ByteString)
import Foreign (mallocBytes, free)
import Network.HPACK (BufferSize)
import Network.HPACK qualified as HPACK
import Network.HPACK.Token qualified as HPACK
import Network.HTTP.Types qualified as HTTP
import Network.HTTP2.Server qualified as Server
import Network.HTTP2.TLS.Server qualified as Server.TLS
import Network.Socket (Socket, SockAddr)
import Network.Socket qualified as Socket
import Network.Socket.BufferPool (Recv)
import Network.Socket.BufferPool qualified as Recv
import Network.Socket.ByteString qualified as Socket
import System.TimeManager qualified as Time (Manager)
import System.TimeManager qualified as TimeManager
import Network.GRPC.Common.HTTP2Settings
fromHeaderTable :: HPACK.TokenHeaderTable -> [HTTP.Header]
= ((Token, ByteString) -> Header)
-> [(Token, ByteString)] -> [Header]
forall a b. (a -> b) -> [a] -> [b]
map ((Token -> HeaderName) -> (Token, ByteString) -> Header
forall a b c. (a -> b) -> (a, c) -> (b, c)
forall (p :: * -> * -> *) a b c.
Bifunctor p =>
(a -> b) -> p a c -> p b c
first Token -> HeaderName
HPACK.tokenKey) ([(Token, ByteString)] -> [Header])
-> (TokenHeaderTable -> [(Token, ByteString)])
-> TokenHeaderTable
-> [Header]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. TokenHeaderTable -> [(Token, ByteString)]
forall a b. (a, b) -> a
fst
withConfigForInsecure ::
Time.Manager
-> Socket
-> (Server.Config -> IO a)
-> IO a
withConfigForInsecure :: forall a. Manager -> Socket -> (Config -> IO a) -> IO a
withConfigForInsecure Manager
mgr Socket
sock Config -> IO a
k = do
pool <- Int -> Int -> IO BufferPool
Recv.newBufferPool Int
readBufferLowerLimit Int
readBufferSize
mysa <- Socket.getSocketName sock
peersa <- Socket.getPeerName sock
withConfig
mgr
(Socket.sendAll sock)
(Recv.receive sock pool)
mysa
peersa
k
where
def :: Server.TLS.Settings
def :: Settings
def = Settings
Server.TLS.defaultSettings
readBufferLowerLimit, readBufferSize :: Int
readBufferLowerLimit :: Int
readBufferLowerLimit = Settings -> Int
Server.TLS.settingsReadBufferLowerLimit Settings
def
readBufferSize :: Int
readBufferSize = Settings -> Int
Server.TLS.settingsReadBufferSize Settings
def
withConfigForSecure ::
Time.Manager
-> Server.TLS.IOBackend
-> (Server.Config -> IO a)
-> IO a
withConfigForSecure :: forall a. Manager -> IOBackend -> (Config -> IO a) -> IO a
withConfigForSecure Manager
mgr IOBackend
backend =
Manager
-> (ByteString -> IO ())
-> Recv
-> SockAddr
-> SockAddr
-> (Config -> IO a)
-> IO a
forall a.
Manager
-> (ByteString -> IO ())
-> Recv
-> SockAddr
-> SockAddr
-> (Config -> IO a)
-> IO a
withConfig
Manager
mgr
(IOBackend -> ByteString -> IO ()
Server.TLS.send IOBackend
backend)
(IOBackend -> Recv
Server.TLS.recv IOBackend
backend)
(IOBackend -> SockAddr
Server.TLS.mySockAddr IOBackend
backend)
(IOBackend -> SockAddr
Server.TLS.peerSockAddr IOBackend
backend)
withConfig ::
Time.Manager
-> (Strict.ByteString -> IO ())
-> Recv
-> SockAddr
-> SockAddr
-> (Server.Config -> IO a)
-> IO a
withConfig :: forall a.
Manager
-> (ByteString -> IO ())
-> Recv
-> SockAddr
-> SockAddr
-> (Config -> IO a)
-> IO a
withConfig Manager
mgr ByteString -> IO ()
send Recv
recv SockAddr
mysa SockAddr
peersa Config -> IO a
k =
IO (Ptr Word8)
-> (Ptr Word8 -> IO ()) -> (Ptr Word8 -> IO a) -> IO a
forall a b c. IO a -> (a -> IO b) -> (a -> IO c) -> IO c
bracket (Int -> IO (Ptr Word8)
forall a. Int -> IO (Ptr a)
mallocBytes Int
writeBufferSize) Ptr Word8 -> IO ()
forall a. Ptr a -> IO ()
free ((Ptr Word8 -> IO a) -> IO a) -> (Ptr Word8 -> IO a) -> IO a
forall a b. (a -> b) -> a -> b
$ \Ptr Word8
buf -> do
recvN <- ByteString -> Recv -> IO RecvN
Recv.makeRecvN ByteString
forall a. Monoid a => a
mempty Recv
recv
k Server.Config {
confWriteBuffer = buf
, confBufferSize = writeBufferSize
, confSendAll = send
, confReadN = recvN
, confPositionReadMaker = Server.defaultPositionReadMaker
, confTimeoutManager = mgr
, confMySockAddr = mysa
, confPeerSockAddr = peersa
}
where
writeBufferSize :: BufferSize
writeBufferSize :: Int
writeBufferSize = Int
4096
mkServerConfig :: HTTP2Settings -> Server.ServerConfig
mkServerConfig :: HTTP2Settings -> ServerConfig
mkServerConfig HTTP2Settings
http2Settings =
ServerConfig
Server.defaultServerConfig {
Server.connectionWindowSize = fromIntegral $
http2ConnectionWindowSize http2Settings
, Server.settings =
Server.defaultSettings {
Server.initialWindowSize = fromIntegral $
http2StreamWindowSize http2Settings
, Server.maxConcurrentStreams = Just . fromIntegral $
http2MaxConcurrentStreams http2Settings
, Server.pingRateLimit =
case http2OverridePingRateLimit http2Settings of
Maybe Int
Nothing -> Settings -> Int
Server.pingRateLimit Settings
Server.defaultSettings
Just Int
limit -> Int
limit
, Server.emptyFrameRateLimit =
case http2OverrideEmptyFrameRateLimit http2Settings of
Maybe Int
Nothing -> Settings -> Int
Server.emptyFrameRateLimit Settings
Server.defaultSettings
Just Int
limit -> Int
limit
, Server.settingsRateLimit =
case http2OverrideSettingsRateLimit http2Settings of
Maybe Int
Nothing -> Settings -> Int
Server.settingsRateLimit Settings
Server.defaultSettings
Just Int
limit -> Int
limit
, Server.rstRateLimit =
case http2OverrideRstRateLimit http2Settings of
Maybe Int
Nothing -> Settings -> Int
Server.rstRateLimit Settings
Server.defaultSettings
Just Int
limit -> Int
limit
}
}
mkTlsSettings ::
HTTP2Settings
-> (String -> IO ())
-> Server.TLS.Settings
mkTlsSettings :: HTTP2Settings -> (String -> IO ()) -> Settings
mkTlsSettings HTTP2Settings
http2Settings String -> IO ()
keyLogger =
Settings
Server.TLS.defaultSettings {
Server.TLS.settingsKeyLogger =
keyLogger
, Server.TLS.settingsTimeout =
disableTimeout
, Server.TLS.settingsConnectionWindowSize = fromIntegral $
http2ConnectionWindowSize http2Settings
, Server.TLS.settingsStreamWindowSize = fromIntegral $
http2StreamWindowSize http2Settings
, Server.TLS.settingsConcurrentStreams = fromIntegral $
http2MaxConcurrentStreams http2Settings
, Server.TLS.settingsPingRateLimit =
case http2OverridePingRateLimit http2Settings of
Maybe Int
Nothing -> Settings -> Int
Server.pingRateLimit Settings
Server.defaultSettings
Just Int
limit -> Int
limit
, Server.TLS.settingsEmptyFrameRateLimit =
case http2OverrideEmptyFrameRateLimit http2Settings of
Maybe Int
Nothing -> Settings -> Int
Server.emptyFrameRateLimit Settings
Server.defaultSettings
Just Int
limit -> Int
limit
, Server.TLS.settingsSettingsRateLimit =
case http2OverrideSettingsRateLimit http2Settings of
Maybe Int
Nothing -> Settings -> Int
Server.settingsRateLimit Settings
Server.defaultSettings
Just Int
limit -> Int
limit
, Server.TLS.settingsRstRateLimit =
case http2OverrideRstRateLimit http2Settings of
Maybe Int
Nothing -> Settings -> Int
Server.rstRateLimit Settings
Server.defaultSettings
Just Int
limit -> Int
limit
}
withTimeManager :: (Time.Manager -> IO a) -> IO a
withTimeManager :: forall a. (Manager -> IO a) -> IO a
withTimeManager = Int -> (Manager -> IO a) -> IO a
forall a. Int -> (Manager -> IO a) -> IO a
TimeManager.withManager (Int
disableTimeout Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
1_000_000)
disableTimeout :: Int
disableTimeout :: Int
disableTimeout = Int
0