quic-simple-0.1.0.0: src/Network/QUIC/Simple.hs
{-# LANGUAGE CPP #-}
module Network.QUIC.Simple
( -- * Basic wrappers
runServer
, runClient
-- * CBOR/Serialise wrappers
, Serialise
, runServerSimple
, startClientSimple
-- * The rest of the QUIC API
, module Network.QUIC
) where
import Network.QUIC
import Network.QUIC.Simple.Stream
import Control.Monad (forever)
import Control.Concurrent (forkIO, killThread)
import Control.Concurrent.STM (atomically, readTBQueue, writeTBQueue, newTBQueueIO)
import Control.Concurrent.MVar (newEmptyMVar, putMVar, takeMVar)
import Codec.Serialise (Serialise)
import Data.IP (IP(..))
import Network.QUIC.Client (ClientConfig(..), defaultClientConfig)
import Network.QUIC.Client qualified as Client
import Network.QUIC.Server (ServerConfig(..), defaultServerConfig)
import Network.QUIC.Server qualified as Server
import Network.QUIC.Simple.Credentials (genCredentials)
import Network.Socket (HostName, PortNumber, ServiceName)
runServer :: [(IP, PortNumber)] -> (Connection -> Stream -> IO ()) -> IO ()
runServer scAddresses action = do
scCredentials <- genCredentials
let
sc = defaultServerConfig
{ scCredentials
, scAddresses
}
Server.run sc \conn -> do
defaultStream <- acceptStream conn
action conn defaultStream
runServerSimple
:: (Serialise q, Serialise r)
=> IP
-> PortNumber
-> (q -> IO r)
-> IO ()
runServerSimple host port action =
runServer [(host, port)] \_conn stream0 -> do
(writeQ, readQ) <- streamSerialise stream0
forever do
query <- atomically (readTBQueue readQ)
reply <- action query
atomically $ writeTBQueue writeQ reply
runClient :: HostName -> ServiceName -> (Connection -> Stream -> IO ()) -> IO ()
runClient ccServerName ccPortName action = do
Client.run cc \conn -> do
defaultStream <- stream conn
action conn defaultStream
where
cc = defaultClientConfig
{ ccServerName
, ccPortName
, ccValidate = False
#if MIN_VERSION_quic(0,2,10)
, ccSockConnected = True
, ccWatchDog = True
#endif
}
startClientSimple
:: (Serialise q, Serialise r)
=> HostName
-> ServiceName
-> IO (IO (), q -> IO r)
startClientSimple host port = do
client <- newEmptyMVar
tid <- forkIO $ runClient host port \_conn stream0 -> do
requests <- newTBQueueIO 16
putMVar client requests
(writeQ, readQ) <- streamSerialise stream0
forever do
(query, handler) <- atomically $ readTBQueue requests
atomically $ writeTBQueue writeQ query
reply <- atomically $ readTBQueue readQ
handler reply
requests <- takeMVar client
pure
( killThread tid
, \query -> do
reply <- newEmptyMVar
atomically $ writeTBQueue requests (query, putMVar reply)
takeMVar reply
)