packages feed

quic-0.1.0: Network/QUIC/Connector.hs

module Network.QUIC.Connector where

import Data.IORef
import Network.QUIC.Types
import UnliftIO.STM

class Connector a where
    getRole            :: a -> Role
    getEncryptionLevel :: a -> IO EncryptionLevel
    getMaxPacketSize   :: a -> IO Int
    getConnectionState :: a -> IO ConnectionState
    getPacketNumber    :: a -> IO PacketNumber
    getAlive           :: a -> IO Bool

----------------------------------------------------------------

data ConnState = ConnState {
    role            :: Role
  , connectionState :: TVar ConnectionState
  , packetNumber    :: IORef PacketNumber   -- squeezing three to one
  , encryptionLevel :: TVar EncryptionLevel -- to synchronize
  , maxPacketSize   :: IORef Int
  -- Explicitly separated from 'ConnectionState'
  -- It seems that STM triggers a dead-lock if
  -- it is used in the close function of bracket.
  , connectionAlive :: IORef Bool
  }

newConnState :: Role -> IO ConnState
newConnState rl =
    ConnState rl <$> newTVarIO Handshaking
                 <*> newIORef 0
                 <*> newTVarIO InitialLevel
                 <*> newIORef defaultQUICPacketSize
                 <*> newIORef True

----------------------------------------------------------------

data Role = Client | Server deriving (Eq, Show)

isClient :: Connector a => a -> Bool
isClient conn = getRole conn == Client

isServer :: Connector a => a -> Bool
isServer conn = getRole conn == Server

----------------------------------------------------------------

data ConnectionState = Handshaking
                     | ReadyFor0RTT
                     | ReadyFor1RTT
                     | Established
                     deriving (Eq, Ord, Show)

isConnectionEstablished :: Connector a => a -> IO Bool
isConnectionEstablished conn = do
    st <- getConnectionState conn
    return $ case st of
      Established -> True
      _           -> False