{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RecordWildCards #-}

module Network.QUIC.Recovery.Types (
    SentPacket(..)
  , mkSentPacket
  , fixSentPacket
  , LostPacket(..)
  , SentPackets(..)
  , emptySentPackets
  , RTT(..)
  , initialRTT
  , CCMode(..)
  , CC(..)
  , initialCC
  , LossDetection(..)
  , initialLossDetection
  , MetricsDiff(..)
  , TimerType(..)
  , TimerInfo(..)
  , TimerInfoQ(..)
  , TimerCancelled
  , TimerExpired
  , makeSentPackets
  , makeLossDetection
  , LDCC(..)
  , newLDCC
  , qlogSent
  , qlogMetricsUpdated
  , qlogPacketLost
  , qlogContestionStateUpdated
  , qlogLossTimerUpdated
  , qlogLossTimerCancelled
  , qlogLossTimerExpired
  ) where

import Control.Concurrent.STM
import Data.IORef
import Data.List (intersperse)
import Data.Sequence (Seq)
import qualified Data.Sequence as Seq
import GHC.Event
import System.Log.FastLogger

import Network.QUIC.Connector
import Network.QUIC.Imports
import Network.QUIC.Qlog
import Network.QUIC.Types

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

data SentPacket = SentPacket {
    SentPacket -> PlainPacket
spPlainPacket       :: PlainPacket
  , SentPacket -> TimeMicrosecond
spTimeSent          :: TimeMicrosecond
  , SentPacket -> Int
spSentBytes         :: Int
  , SentPacket -> EncryptionLevel
spEncryptionLevel   :: EncryptionLevel
  , SentPacket -> Int
spPacketNumber      :: PacketNumber
  , SentPacket -> PeerPacketNumbers
spPeerPacketNumbers :: PeerPacketNumbers
  , SentPacket -> Bool
spAckEliciting      :: Bool
  } deriving (SentPacket -> SentPacket -> Bool
(SentPacket -> SentPacket -> Bool)
-> (SentPacket -> SentPacket -> Bool) -> Eq SentPacket
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: SentPacket -> SentPacket -> Bool
$c/= :: SentPacket -> SentPacket -> Bool
== :: SentPacket -> SentPacket -> Bool
$c== :: SentPacket -> SentPacket -> Bool
Eq, Int -> SentPacket -> ShowS
[SentPacket] -> ShowS
SentPacket -> String
(Int -> SentPacket -> ShowS)
-> (SentPacket -> String)
-> ([SentPacket] -> ShowS)
-> Show SentPacket
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [SentPacket] -> ShowS
$cshowList :: [SentPacket] -> ShowS
show :: SentPacket -> String
$cshow :: SentPacket -> String
showsPrec :: Int -> SentPacket -> ShowS
$cshowsPrec :: Int -> SentPacket -> ShowS
Show)

instance Ord SentPacket where
    SentPacket
x <= :: SentPacket -> SentPacket -> Bool
<= SentPacket
y = SentPacket -> Int
spPacketNumber SentPacket
x Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= SentPacket -> Int
spPacketNumber SentPacket
y

newtype LostPacket = LostPacket SentPacket

mkSentPacket :: PacketNumber -> EncryptionLevel -> PlainPacket -> PeerPacketNumbers -> Bool -> SentPacket
mkSentPacket :: Int
-> EncryptionLevel
-> PlainPacket
-> PeerPacketNumbers
-> Bool
-> SentPacket
mkSentPacket Int
mypn EncryptionLevel
lvl PlainPacket
ppkt PeerPacketNumbers
ppns Bool
ackeli = SentPacket :: PlainPacket
-> TimeMicrosecond
-> Int
-> EncryptionLevel
-> Int
-> PeerPacketNumbers
-> Bool
-> SentPacket
SentPacket {
    spPlainPacket :: PlainPacket
spPlainPacket       = PlainPacket
ppkt
  , spTimeSent :: TimeMicrosecond
spTimeSent          = TimeMicrosecond
timeMicrosecond0
  , spSentBytes :: Int
spSentBytes         = Int
0
  , spEncryptionLevel :: EncryptionLevel
spEncryptionLevel   = EncryptionLevel
lvl
  , spPacketNumber :: Int
spPacketNumber      = Int
mypn
  , spPeerPacketNumbers :: PeerPacketNumbers
spPeerPacketNumbers = PeerPacketNumbers
ppns
  , spAckEliciting :: Bool
spAckEliciting      = Bool
ackeli
  }

fixSentPacket :: SentPacket -> Int -> Int -> SentPacket
fixSentPacket :: SentPacket -> Int -> Int -> SentPacket
fixSentPacket SentPacket
spkt Int
bytes Int
padLen = SentPacket
spkt {
    spPlainPacket :: PlainPacket
spPlainPacket = if Int
padLen Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
/= Int
0 then Int -> PlainPacket -> PlainPacket
addPadding Int
padLen (PlainPacket -> PlainPacket) -> PlainPacket -> PlainPacket
forall a b. (a -> b) -> a -> b
$ SentPacket -> PlainPacket
spPlainPacket SentPacket
spkt
                                   else SentPacket -> PlainPacket
spPlainPacket SentPacket
spkt
  , spSentBytes :: Int
spSentBytes   = Int
bytes
  }

addPadding :: Int -> PlainPacket -> PlainPacket
addPadding :: Int -> PlainPacket -> PlainPacket
addPadding Int
n (PlainPacket Header
hdr Plain
plain) = Header -> Plain -> PlainPacket
PlainPacket Header
hdr Plain
plain'
  where
    plain' :: Plain
plain' = Plain
plain {
        plainFrames :: [Frame]
plainFrames = Plain -> [Frame]
plainFrames Plain
plain [Frame] -> [Frame] -> [Frame]
forall a. [a] -> [a] -> [a]
++ [Int -> Frame
Padding Int
n]
      }

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

newtype SentPackets = SentPackets (Seq SentPacket) deriving SentPackets -> SentPackets -> Bool
(SentPackets -> SentPackets -> Bool)
-> (SentPackets -> SentPackets -> Bool) -> Eq SentPackets
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: SentPackets -> SentPackets -> Bool
$c/= :: SentPackets -> SentPackets -> Bool
== :: SentPackets -> SentPackets -> Bool
$c== :: SentPackets -> SentPackets -> Bool
Eq

emptySentPackets :: SentPackets
emptySentPackets :: SentPackets
emptySentPackets = Seq SentPacket -> SentPackets
SentPackets Seq SentPacket
forall a. Seq a
Seq.empty

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

data RTT = RTT {
  -- | The most recent RTT measurement made when receiving an ack for
  --   a previously unacked packet.
    RTT -> Microseconds
latestRTT   :: Microseconds
  -- | The smoothed RTT of the connection.
  , RTT -> Microseconds
smoothedRTT :: Microseconds
  -- | The RTT variation.
  , RTT -> Microseconds
rttvar      :: Microseconds
  -- | The minimum RTT seen in the connection, ignoring ack delay.
  , RTT -> Microseconds
minRTT      :: Microseconds
  -- | The maximum amount of time by which the receiver intends to
  --   delay acknowledgments for packets in the ApplicationData packet
  --   number space.  The actual ack_delay in a received ACK frame may
  --   be larger due to late timers, reordering, or lost ACK frames.
  , RTT -> Microseconds
maxAckDelay1RTT :: Microseconds
  -- | The number of times a PTO has been sent without receiving
  --  an ack.
  , RTT -> Int
ptoCount :: Int
  } deriving Int -> RTT -> ShowS
[RTT] -> ShowS
RTT -> String
(Int -> RTT -> ShowS)
-> (RTT -> String) -> ([RTT] -> ShowS) -> Show RTT
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [RTT] -> ShowS
$cshowList :: [RTT] -> ShowS
show :: RTT -> String
$cshow :: RTT -> String
showsPrec :: Int -> RTT -> ShowS
$cshowsPrec :: Int -> RTT -> ShowS
Show

-- | The RTT used before an RTT sample is taken.
kInitialRTT :: Microseconds
kInitialRTT :: Microseconds
kInitialRTT = Int -> Microseconds
Microseconds Int
333000

initialRTT :: RTT
initialRTT :: RTT
initialRTT = RTT :: Microseconds
-> Microseconds
-> Microseconds
-> Microseconds
-> Microseconds
-> Int
-> RTT
RTT {
    latestRTT :: Microseconds
latestRTT       = Int -> Microseconds
Microseconds Int
0
  , smoothedRTT :: Microseconds
smoothedRTT     = Microseconds
kInitialRTT
  , rttvar :: Microseconds
rttvar          = Microseconds
kInitialRTT Microseconds -> Int -> Microseconds
forall a. Bits a => a -> Int -> a
.>>. Int
1
  , minRTT :: Microseconds
minRTT          = Int -> Microseconds
Microseconds Int
0
  , maxAckDelay1RTT :: Microseconds
maxAckDelay1RTT = Int -> Microseconds
Microseconds Int
0
  , ptoCount :: Int
ptoCount        = Int
0
  }

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

data CCMode = SlowStart
            | Avoidance
            | Recovery
            deriving (CCMode -> CCMode -> Bool
(CCMode -> CCMode -> Bool)
-> (CCMode -> CCMode -> Bool) -> Eq CCMode
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: CCMode -> CCMode -> Bool
$c/= :: CCMode -> CCMode -> Bool
== :: CCMode -> CCMode -> Bool
$c== :: CCMode -> CCMode -> Bool
Eq)

instance Show CCMode where
    show :: CCMode -> String
show CCMode
SlowStart = String
"slow_start"
    show CCMode
Avoidance = String
"avoidance"
    show CCMode
Recovery  = String
"recovery"

data CC = CC {
  -- | The sum of the size in bytes of all sent packets that contain
  --   at least one ack-eliciting or PADDING frame, and have not been
  --   acked or declared lost.  The size does not include IP or UDP
  --   overhead, but does include the QUIC header and AEAD overhead.
  --   Packets only containing ACK frames do not count towards
  --   bytes_in_flight to ensure congestion control does not impede
  --   congestion feedback.
    CC -> Int
bytesInFlight :: Int
  -- | Maximum number of bytes-in-flight that may be sent.
  , CC -> Int
congestionWindow :: Int
  -- | The time when QUIC first detects congestion due to loss or ECN,
  --   causing it to enter congestion recovery.  When a packet sent
  --   after this time is acknowledged, QUIC exits congestion
  --   recovery.
  , CC -> Maybe TimeMicrosecond
congestionRecoveryStartTime :: Maybe TimeMicrosecond
  -- | Slow start threshold in bytes.  When the congestion window is
  --   below ssthresh, the mode is slow start and the window grows by
  --   the number of bytes acknowledged.
  , CC -> Int
ssthresh :: Int
  -- | Records number of bytes acked, and used for incrementing
  --   the congestion window during congestion avoidance.
  , CC -> Int
bytesAcked :: Int
  , CC -> Int
numOfAckEliciting :: Int
  , CC -> CCMode
ccMode :: CCMode
  } deriving Int -> CC -> ShowS
[CC] -> ShowS
CC -> String
(Int -> CC -> ShowS)
-> (CC -> String) -> ([CC] -> ShowS) -> Show CC
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [CC] -> ShowS
$cshowList :: [CC] -> ShowS
show :: CC -> String
$cshow :: CC -> String
showsPrec :: Int -> CC -> ShowS
$cshowsPrec :: Int -> CC -> ShowS
Show

initialCC :: CC
initialCC :: CC
initialCC = CC :: Int
-> Int
-> Maybe TimeMicrosecond
-> Int
-> Int
-> Int
-> CCMode
-> CC
CC {
    bytesInFlight :: Int
bytesInFlight = Int
0
  , congestionWindow :: Int
congestionWindow = Int
0
  , congestionRecoveryStartTime :: Maybe TimeMicrosecond
congestionRecoveryStartTime = Maybe TimeMicrosecond
forall a. Maybe a
Nothing
  , ssthresh :: Int
ssthresh = Int
forall a. Bounded a => a
maxBound
  , bytesAcked :: Int
bytesAcked = Int
0
  , numOfAckEliciting :: Int
numOfAckEliciting = Int
0
  , ccMode :: CCMode
ccMode = CCMode
SlowStart
  }

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

data LossDetection = LossDetection {
    LossDetection -> Int
largestAckedPacket           :: PacketNumber
  , LossDetection -> AckInfo
previousAckInfo              :: AckInfo
  , LossDetection -> TimeMicrosecond
timeOfLastAckElicitingPacket :: TimeMicrosecond
  , LossDetection -> Maybe TimeMicrosecond
lossTime                     :: Maybe TimeMicrosecond
  } deriving Int -> LossDetection -> ShowS
[LossDetection] -> ShowS
LossDetection -> String
(Int -> LossDetection -> ShowS)
-> (LossDetection -> String)
-> ([LossDetection] -> ShowS)
-> Show LossDetection
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [LossDetection] -> ShowS
$cshowList :: [LossDetection] -> ShowS
show :: LossDetection -> String
$cshow :: LossDetection -> String
showsPrec :: Int -> LossDetection -> ShowS
$cshowsPrec :: Int -> LossDetection -> ShowS
Show

initialLossDetection :: LossDetection
initialLossDetection :: LossDetection
initialLossDetection = Int
-> AckInfo
-> TimeMicrosecond
-> Maybe TimeMicrosecond
-> LossDetection
LossDetection (-Int
1) AckInfo
ackInfo0 TimeMicrosecond
timeMicrosecond0 Maybe TimeMicrosecond
forall a. Maybe a
Nothing

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

newtype MetricsDiff = MetricsDiff [(String,Int)]

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

data TimerType = LossTime
               | PTO
               deriving TimerType -> TimerType -> Bool
(TimerType -> TimerType -> Bool)
-> (TimerType -> TimerType -> Bool) -> Eq TimerType
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: TimerType -> TimerType -> Bool
$c/= :: TimerType -> TimerType -> Bool
== :: TimerType -> TimerType -> Bool
$c== :: TimerType -> TimerType -> Bool
Eq

instance Show TimerType where
    show :: TimerType -> String
show TimerType
LossTime = String
"loss_time"
    show TimerType
PTO      = String
"pto"

data TimerExpired = TimerExpired

data TimerCancelled = TimerCancelled

data TimerInfo = TimerInfo {
    TimerInfo -> TimeMicrosecond
timerTime  :: TimeMicrosecond
  , TimerInfo -> EncryptionLevel
timerLevel :: EncryptionLevel
  , TimerInfo -> TimerType
timerType  :: TimerType
  } deriving (TimerInfo -> TimerInfo -> Bool
(TimerInfo -> TimerInfo -> Bool)
-> (TimerInfo -> TimerInfo -> Bool) -> Eq TimerInfo
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: TimerInfo -> TimerInfo -> Bool
$c/= :: TimerInfo -> TimerInfo -> Bool
== :: TimerInfo -> TimerInfo -> Bool
$c== :: TimerInfo -> TimerInfo -> Bool
Eq, Int -> TimerInfo -> ShowS
[TimerInfo] -> ShowS
TimerInfo -> String
(Int -> TimerInfo -> ShowS)
-> (TimerInfo -> String)
-> ([TimerInfo] -> ShowS)
-> Show TimerInfo
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [TimerInfo] -> ShowS
$cshowList :: [TimerInfo] -> ShowS
show :: TimerInfo -> String
$cshow :: TimerInfo -> String
showsPrec :: Int -> TimerInfo -> ShowS
$cshowsPrec :: Int -> TimerInfo -> ShowS
Show)

data TimerInfoQ = Empty
                | Next TimerInfo
                deriving (TimerInfoQ -> TimerInfoQ -> Bool
(TimerInfoQ -> TimerInfoQ -> Bool)
-> (TimerInfoQ -> TimerInfoQ -> Bool) -> Eq TimerInfoQ
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: TimerInfoQ -> TimerInfoQ -> Bool
$c/= :: TimerInfoQ -> TimerInfoQ -> Bool
== :: TimerInfoQ -> TimerInfoQ -> Bool
$c== :: TimerInfoQ -> TimerInfoQ -> Bool
Eq)

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

makeSpaceDiscarded :: IO (Array EncryptionLevel (IORef Bool))
makeSpaceDiscarded :: IO (Array EncryptionLevel (IORef Bool))
makeSpaceDiscarded = do
    IORef Bool
i1 <- Bool -> IO (IORef Bool)
forall a. a -> IO (IORef a)
newIORef Bool
False
    IORef Bool
i2 <- Bool -> IO (IORef Bool)
forall a. a -> IO (IORef a)
newIORef Bool
False
    IORef Bool
i3 <- Bool -> IO (IORef Bool)
forall a. a -> IO (IORef a)
newIORef Bool
False
    IORef Bool
i4 <- Bool -> IO (IORef Bool)
forall a. a -> IO (IORef a)
newIORef Bool
False
    let lst :: [(EncryptionLevel, IORef Bool)]
lst = [(EncryptionLevel
InitialLevel,IORef Bool
i1),(EncryptionLevel
RTT0Level,IORef Bool
i2),(EncryptionLevel
HandshakeLevel,IORef Bool
i3),(EncryptionLevel
RTT1Level,IORef Bool
i4)]
        arr :: Array EncryptionLevel (IORef Bool)
arr = (EncryptionLevel, EncryptionLevel)
-> [(EncryptionLevel, IORef Bool)]
-> Array EncryptionLevel (IORef Bool)
forall i e. Ix i => (i, i) -> [(i, e)] -> Array i e
array (EncryptionLevel
InitialLevel,EncryptionLevel
RTT1Level) [(EncryptionLevel, IORef Bool)]
lst
    Array EncryptionLevel (IORef Bool)
-> IO (Array EncryptionLevel (IORef Bool))
forall (m :: * -> *) a. Monad m => a -> m a
return Array EncryptionLevel (IORef Bool)
arr

makeSentPackets :: IO (Array EncryptionLevel (IORef SentPackets))
makeSentPackets :: IO (Array EncryptionLevel (IORef SentPackets))
makeSentPackets = do
    IORef SentPackets
i1 <- SentPackets -> IO (IORef SentPackets)
forall a. a -> IO (IORef a)
newIORef SentPackets
emptySentPackets
    IORef SentPackets
i2 <- SentPackets -> IO (IORef SentPackets)
forall a. a -> IO (IORef a)
newIORef SentPackets
emptySentPackets
    IORef SentPackets
i3 <- SentPackets -> IO (IORef SentPackets)
forall a. a -> IO (IORef a)
newIORef SentPackets
emptySentPackets
    let lst :: [(EncryptionLevel, IORef SentPackets)]
lst = [(EncryptionLevel
InitialLevel,IORef SentPackets
i1),(EncryptionLevel
HandshakeLevel,IORef SentPackets
i2),(EncryptionLevel
RTT1Level,IORef SentPackets
i3)]
        arr :: Array EncryptionLevel (IORef SentPackets)
arr = (EncryptionLevel, EncryptionLevel)
-> [(EncryptionLevel, IORef SentPackets)]
-> Array EncryptionLevel (IORef SentPackets)
forall i e. Ix i => (i, i) -> [(i, e)] -> Array i e
array (EncryptionLevel
InitialLevel,EncryptionLevel
RTT1Level) [(EncryptionLevel, IORef SentPackets)]
lst
    Array EncryptionLevel (IORef SentPackets)
-> IO (Array EncryptionLevel (IORef SentPackets))
forall (m :: * -> *) a. Monad m => a -> m a
return Array EncryptionLevel (IORef SentPackets)
arr

makeLossDetection :: IO (Array EncryptionLevel (IORef LossDetection))
makeLossDetection :: IO (Array EncryptionLevel (IORef LossDetection))
makeLossDetection = do
    IORef LossDetection
i1 <- LossDetection -> IO (IORef LossDetection)
forall a. a -> IO (IORef a)
newIORef LossDetection
initialLossDetection
    IORef LossDetection
i2 <- LossDetection -> IO (IORef LossDetection)
forall a. a -> IO (IORef a)
newIORef LossDetection
initialLossDetection
    IORef LossDetection
i3 <- LossDetection -> IO (IORef LossDetection)
forall a. a -> IO (IORef a)
newIORef LossDetection
initialLossDetection
    let lst :: [(EncryptionLevel, IORef LossDetection)]
lst = [(EncryptionLevel
InitialLevel,IORef LossDetection
i1),(EncryptionLevel
HandshakeLevel,IORef LossDetection
i2),(EncryptionLevel
RTT1Level,IORef LossDetection
i3)]
        arr :: Array EncryptionLevel (IORef LossDetection)
arr = (EncryptionLevel, EncryptionLevel)
-> [(EncryptionLevel, IORef LossDetection)]
-> Array EncryptionLevel (IORef LossDetection)
forall i e. Ix i => (i, i) -> [(i, e)] -> Array i e
array (EncryptionLevel
InitialLevel,EncryptionLevel
RTT1Level) [(EncryptionLevel, IORef LossDetection)]
lst
    Array EncryptionLevel (IORef LossDetection)
-> IO (Array EncryptionLevel (IORef LossDetection))
forall (m :: * -> *) a. Monad m => a -> m a
return Array EncryptionLevel (IORef LossDetection)
arr

data LDCC = LDCC {
    LDCC -> ConnState
ldccState         :: ConnState
  , LDCC -> QLogger
ldccQlogger       :: QLogger
  , LDCC -> PlainPacket -> IO ()
putRetrans        :: PlainPacket -> IO ()
  , LDCC -> IORef RTT
recoveryRTT       :: IORef RTT
  , LDCC -> TVar CC
recoveryCC        :: TVar CC
  , LDCC -> Array EncryptionLevel (IORef Bool)
spaceDiscarded    :: Array EncryptionLevel (IORef Bool)
  , LDCC -> Array EncryptionLevel (IORef SentPackets)
sentPackets       :: Array EncryptionLevel (IORef SentPackets)
  , LDCC -> Array EncryptionLevel (IORef LossDetection)
lossDetection     :: Array EncryptionLevel (IORef LossDetection)
  -- The current timer key
  , LDCC -> IORef (Maybe TimeoutKey)
timerKey          :: IORef (Maybe TimeoutKey)
  -- The current timer value
  , LDCC -> IORef (Maybe TimerInfo)
timerInfo         :: IORef (Maybe TimerInfo)
  , LDCC -> TVar SentPackets
lostCandidates    :: TVar SentPackets
  , LDCC -> TVar (Maybe EncryptionLevel)
ptoPing           :: TVar (Maybe EncryptionLevel)
  , LDCC -> IORef Bool
speedingUp        :: IORef Bool
  , LDCC -> IORef Int
pktNumPersistent  :: IORef PacketNumber
  , LDCC -> Array EncryptionLevel (IORef PeerPacketNumbers)
peerPacketNumbers :: Array EncryptionLevel (IORef PeerPacketNumbers)
  , LDCC -> IORef PeerPacketNumbers
previousRTT1PPNs  :: IORef PeerPacketNumbers -- for RTT1
  -- Pending timer value
  , LDCC -> TVar TimerInfoQ
timerInfoQ        :: TVar TimerInfoQ
  }

makePPN :: IO (Array EncryptionLevel (IORef PeerPacketNumbers))
makePPN :: IO (Array EncryptionLevel (IORef PeerPacketNumbers))
makePPN = do
    IORef PeerPacketNumbers
ref1 <- PeerPacketNumbers -> IO (IORef PeerPacketNumbers)
forall a. a -> IO (IORef a)
newIORef PeerPacketNumbers
emptyPeerPacketNumbers
    IORef PeerPacketNumbers
ref2 <- PeerPacketNumbers -> IO (IORef PeerPacketNumbers)
forall a. a -> IO (IORef a)
newIORef PeerPacketNumbers
emptyPeerPacketNumbers
    IORef PeerPacketNumbers
ref3 <- PeerPacketNumbers -> IO (IORef PeerPacketNumbers)
forall a. a -> IO (IORef a)
newIORef PeerPacketNumbers
emptyPeerPacketNumbers
    -- using the ref for RTT0Level and RTT1Level
    let lst :: [(EncryptionLevel, IORef PeerPacketNumbers)]
lst = [(EncryptionLevel
InitialLevel,   IORef PeerPacketNumbers
ref1)
              ,(EncryptionLevel
RTT0Level,      IORef PeerPacketNumbers
ref3)
              ,(EncryptionLevel
HandshakeLevel, IORef PeerPacketNumbers
ref2)
              ,(EncryptionLevel
RTT1Level,      IORef PeerPacketNumbers
ref3)]
        arr :: Array EncryptionLevel (IORef PeerPacketNumbers)
arr = (EncryptionLevel, EncryptionLevel)
-> [(EncryptionLevel, IORef PeerPacketNumbers)]
-> Array EncryptionLevel (IORef PeerPacketNumbers)
forall i e. Ix i => (i, i) -> [(i, e)] -> Array i e
array (EncryptionLevel
InitialLevel,EncryptionLevel
RTT1Level) [(EncryptionLevel, IORef PeerPacketNumbers)]
lst
    Array EncryptionLevel (IORef PeerPacketNumbers)
-> IO (Array EncryptionLevel (IORef PeerPacketNumbers))
forall (m :: * -> *) a. Monad m => a -> m a
return Array EncryptionLevel (IORef PeerPacketNumbers)
arr

newLDCC :: ConnState -> QLogger -> (PlainPacket -> IO ()) -> IO LDCC
newLDCC :: ConnState -> QLogger -> (PlainPacket -> IO ()) -> IO LDCC
newLDCC ConnState
cs QLogger
qLog PlainPacket -> IO ()
put = ConnState
-> QLogger
-> (PlainPacket -> IO ())
-> IORef RTT
-> TVar CC
-> Array EncryptionLevel (IORef Bool)
-> Array EncryptionLevel (IORef SentPackets)
-> Array EncryptionLevel (IORef LossDetection)
-> IORef (Maybe TimeoutKey)
-> IORef (Maybe TimerInfo)
-> TVar SentPackets
-> TVar (Maybe EncryptionLevel)
-> IORef Bool
-> IORef Int
-> Array EncryptionLevel (IORef PeerPacketNumbers)
-> IORef PeerPacketNumbers
-> TVar TimerInfoQ
-> LDCC
LDCC ConnState
cs QLogger
qLog PlainPacket -> IO ()
put
    (IORef RTT
 -> TVar CC
 -> Array EncryptionLevel (IORef Bool)
 -> Array EncryptionLevel (IORef SentPackets)
 -> Array EncryptionLevel (IORef LossDetection)
 -> IORef (Maybe TimeoutKey)
 -> IORef (Maybe TimerInfo)
 -> TVar SentPackets
 -> TVar (Maybe EncryptionLevel)
 -> IORef Bool
 -> IORef Int
 -> Array EncryptionLevel (IORef PeerPacketNumbers)
 -> IORef PeerPacketNumbers
 -> TVar TimerInfoQ
 -> LDCC)
-> IO (IORef RTT)
-> IO
     (TVar CC
      -> Array EncryptionLevel (IORef Bool)
      -> Array EncryptionLevel (IORef SentPackets)
      -> Array EncryptionLevel (IORef LossDetection)
      -> IORef (Maybe TimeoutKey)
      -> IORef (Maybe TimerInfo)
      -> TVar SentPackets
      -> TVar (Maybe EncryptionLevel)
      -> IORef Bool
      -> IORef Int
      -> Array EncryptionLevel (IORef PeerPacketNumbers)
      -> IORef PeerPacketNumbers
      -> TVar TimerInfoQ
      -> LDCC)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> RTT -> IO (IORef RTT)
forall a. a -> IO (IORef a)
newIORef RTT
initialRTT
    IO
  (TVar CC
   -> Array EncryptionLevel (IORef Bool)
   -> Array EncryptionLevel (IORef SentPackets)
   -> Array EncryptionLevel (IORef LossDetection)
   -> IORef (Maybe TimeoutKey)
   -> IORef (Maybe TimerInfo)
   -> TVar SentPackets
   -> TVar (Maybe EncryptionLevel)
   -> IORef Bool
   -> IORef Int
   -> Array EncryptionLevel (IORef PeerPacketNumbers)
   -> IORef PeerPacketNumbers
   -> TVar TimerInfoQ
   -> LDCC)
-> IO (TVar CC)
-> IO
     (Array EncryptionLevel (IORef Bool)
      -> Array EncryptionLevel (IORef SentPackets)
      -> Array EncryptionLevel (IORef LossDetection)
      -> IORef (Maybe TimeoutKey)
      -> IORef (Maybe TimerInfo)
      -> TVar SentPackets
      -> TVar (Maybe EncryptionLevel)
      -> IORef Bool
      -> IORef Int
      -> Array EncryptionLevel (IORef PeerPacketNumbers)
      -> IORef PeerPacketNumbers
      -> TVar TimerInfoQ
      -> LDCC)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> CC -> IO (TVar CC)
forall a. a -> IO (TVar a)
newTVarIO CC
initialCC
    IO
  (Array EncryptionLevel (IORef Bool)
   -> Array EncryptionLevel (IORef SentPackets)
   -> Array EncryptionLevel (IORef LossDetection)
   -> IORef (Maybe TimeoutKey)
   -> IORef (Maybe TimerInfo)
   -> TVar SentPackets
   -> TVar (Maybe EncryptionLevel)
   -> IORef Bool
   -> IORef Int
   -> Array EncryptionLevel (IORef PeerPacketNumbers)
   -> IORef PeerPacketNumbers
   -> TVar TimerInfoQ
   -> LDCC)
-> IO (Array EncryptionLevel (IORef Bool))
-> IO
     (Array EncryptionLevel (IORef SentPackets)
      -> Array EncryptionLevel (IORef LossDetection)
      -> IORef (Maybe TimeoutKey)
      -> IORef (Maybe TimerInfo)
      -> TVar SentPackets
      -> TVar (Maybe EncryptionLevel)
      -> IORef Bool
      -> IORef Int
      -> Array EncryptionLevel (IORef PeerPacketNumbers)
      -> IORef PeerPacketNumbers
      -> TVar TimerInfoQ
      -> LDCC)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> IO (Array EncryptionLevel (IORef Bool))
makeSpaceDiscarded
    IO
  (Array EncryptionLevel (IORef SentPackets)
   -> Array EncryptionLevel (IORef LossDetection)
   -> IORef (Maybe TimeoutKey)
   -> IORef (Maybe TimerInfo)
   -> TVar SentPackets
   -> TVar (Maybe EncryptionLevel)
   -> IORef Bool
   -> IORef Int
   -> Array EncryptionLevel (IORef PeerPacketNumbers)
   -> IORef PeerPacketNumbers
   -> TVar TimerInfoQ
   -> LDCC)
-> IO (Array EncryptionLevel (IORef SentPackets))
-> IO
     (Array EncryptionLevel (IORef LossDetection)
      -> IORef (Maybe TimeoutKey)
      -> IORef (Maybe TimerInfo)
      -> TVar SentPackets
      -> TVar (Maybe EncryptionLevel)
      -> IORef Bool
      -> IORef Int
      -> Array EncryptionLevel (IORef PeerPacketNumbers)
      -> IORef PeerPacketNumbers
      -> TVar TimerInfoQ
      -> LDCC)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> IO (Array EncryptionLevel (IORef SentPackets))
makeSentPackets
    IO
  (Array EncryptionLevel (IORef LossDetection)
   -> IORef (Maybe TimeoutKey)
   -> IORef (Maybe TimerInfo)
   -> TVar SentPackets
   -> TVar (Maybe EncryptionLevel)
   -> IORef Bool
   -> IORef Int
   -> Array EncryptionLevel (IORef PeerPacketNumbers)
   -> IORef PeerPacketNumbers
   -> TVar TimerInfoQ
   -> LDCC)
-> IO (Array EncryptionLevel (IORef LossDetection))
-> IO
     (IORef (Maybe TimeoutKey)
      -> IORef (Maybe TimerInfo)
      -> TVar SentPackets
      -> TVar (Maybe EncryptionLevel)
      -> IORef Bool
      -> IORef Int
      -> Array EncryptionLevel (IORef PeerPacketNumbers)
      -> IORef PeerPacketNumbers
      -> TVar TimerInfoQ
      -> LDCC)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> IO (Array EncryptionLevel (IORef LossDetection))
makeLossDetection
    IO
  (IORef (Maybe TimeoutKey)
   -> IORef (Maybe TimerInfo)
   -> TVar SentPackets
   -> TVar (Maybe EncryptionLevel)
   -> IORef Bool
   -> IORef Int
   -> Array EncryptionLevel (IORef PeerPacketNumbers)
   -> IORef PeerPacketNumbers
   -> TVar TimerInfoQ
   -> LDCC)
-> IO (IORef (Maybe TimeoutKey))
-> IO
     (IORef (Maybe TimerInfo)
      -> TVar SentPackets
      -> TVar (Maybe EncryptionLevel)
      -> IORef Bool
      -> IORef Int
      -> Array EncryptionLevel (IORef PeerPacketNumbers)
      -> IORef PeerPacketNumbers
      -> TVar TimerInfoQ
      -> LDCC)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Maybe TimeoutKey -> IO (IORef (Maybe TimeoutKey))
forall a. a -> IO (IORef a)
newIORef Maybe TimeoutKey
forall a. Maybe a
Nothing
    IO
  (IORef (Maybe TimerInfo)
   -> TVar SentPackets
   -> TVar (Maybe EncryptionLevel)
   -> IORef Bool
   -> IORef Int
   -> Array EncryptionLevel (IORef PeerPacketNumbers)
   -> IORef PeerPacketNumbers
   -> TVar TimerInfoQ
   -> LDCC)
-> IO (IORef (Maybe TimerInfo))
-> IO
     (TVar SentPackets
      -> TVar (Maybe EncryptionLevel)
      -> IORef Bool
      -> IORef Int
      -> Array EncryptionLevel (IORef PeerPacketNumbers)
      -> IORef PeerPacketNumbers
      -> TVar TimerInfoQ
      -> LDCC)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Maybe TimerInfo -> IO (IORef (Maybe TimerInfo))
forall a. a -> IO (IORef a)
newIORef Maybe TimerInfo
forall a. Maybe a
Nothing
    IO
  (TVar SentPackets
   -> TVar (Maybe EncryptionLevel)
   -> IORef Bool
   -> IORef Int
   -> Array EncryptionLevel (IORef PeerPacketNumbers)
   -> IORef PeerPacketNumbers
   -> TVar TimerInfoQ
   -> LDCC)
-> IO (TVar SentPackets)
-> IO
     (TVar (Maybe EncryptionLevel)
      -> IORef Bool
      -> IORef Int
      -> Array EncryptionLevel (IORef PeerPacketNumbers)
      -> IORef PeerPacketNumbers
      -> TVar TimerInfoQ
      -> LDCC)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> SentPackets -> IO (TVar SentPackets)
forall a. a -> IO (TVar a)
newTVarIO SentPackets
emptySentPackets
    IO
  (TVar (Maybe EncryptionLevel)
   -> IORef Bool
   -> IORef Int
   -> Array EncryptionLevel (IORef PeerPacketNumbers)
   -> IORef PeerPacketNumbers
   -> TVar TimerInfoQ
   -> LDCC)
-> IO (TVar (Maybe EncryptionLevel))
-> IO
     (IORef Bool
      -> IORef Int
      -> Array EncryptionLevel (IORef PeerPacketNumbers)
      -> IORef PeerPacketNumbers
      -> TVar TimerInfoQ
      -> LDCC)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Maybe EncryptionLevel -> IO (TVar (Maybe EncryptionLevel))
forall a. a -> IO (TVar a)
newTVarIO Maybe EncryptionLevel
forall a. Maybe a
Nothing
    IO
  (IORef Bool
   -> IORef Int
   -> Array EncryptionLevel (IORef PeerPacketNumbers)
   -> IORef PeerPacketNumbers
   -> TVar TimerInfoQ
   -> LDCC)
-> IO (IORef Bool)
-> IO
     (IORef Int
      -> Array EncryptionLevel (IORef PeerPacketNumbers)
      -> IORef PeerPacketNumbers
      -> TVar TimerInfoQ
      -> LDCC)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Bool -> IO (IORef Bool)
forall a. a -> IO (IORef a)
newIORef Bool
False
    IO
  (IORef Int
   -> Array EncryptionLevel (IORef PeerPacketNumbers)
   -> IORef PeerPacketNumbers
   -> TVar TimerInfoQ
   -> LDCC)
-> IO (IORef Int)
-> IO
     (Array EncryptionLevel (IORef PeerPacketNumbers)
      -> IORef PeerPacketNumbers -> TVar TimerInfoQ -> LDCC)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Int -> IO (IORef Int)
forall a. a -> IO (IORef a)
newIORef Int
forall a. Bounded a => a
maxBound
    IO
  (Array EncryptionLevel (IORef PeerPacketNumbers)
   -> IORef PeerPacketNumbers -> TVar TimerInfoQ -> LDCC)
-> IO (Array EncryptionLevel (IORef PeerPacketNumbers))
-> IO (IORef PeerPacketNumbers -> TVar TimerInfoQ -> LDCC)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> IO (Array EncryptionLevel (IORef PeerPacketNumbers))
makePPN
    IO (IORef PeerPacketNumbers -> TVar TimerInfoQ -> LDCC)
-> IO (IORef PeerPacketNumbers) -> IO (TVar TimerInfoQ -> LDCC)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> PeerPacketNumbers -> IO (IORef PeerPacketNumbers)
forall a. a -> IO (IORef a)
newIORef PeerPacketNumbers
emptyPeerPacketNumbers
    IO (TVar TimerInfoQ -> LDCC) -> IO (TVar TimerInfoQ) -> IO LDCC
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> TimerInfoQ -> IO (TVar TimerInfoQ)
forall a. a -> IO (TVar a)
newTVarIO TimerInfoQ
Empty

instance KeepQlog LDCC where
    keepQlog :: LDCC -> QLogger
keepQlog = LDCC -> QLogger
ldccQlogger

instance Connector LDCC where
    getRole :: LDCC -> Role
getRole            = ConnState -> Role
role (ConnState -> Role) -> (LDCC -> ConnState) -> LDCC -> Role
forall b c a. (b -> c) -> (a -> b) -> a -> c
. LDCC -> ConnState
ldccState
    getEncryptionLevel :: LDCC -> IO EncryptionLevel
getEncryptionLevel = TVar EncryptionLevel -> IO EncryptionLevel
forall a. TVar a -> IO a
readTVarIO (TVar EncryptionLevel -> IO EncryptionLevel)
-> (LDCC -> TVar EncryptionLevel) -> LDCC -> IO EncryptionLevel
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ConnState -> TVar EncryptionLevel
encryptionLevel (ConnState -> TVar EncryptionLevel)
-> (LDCC -> ConnState) -> LDCC -> TVar EncryptionLevel
forall b c a. (b -> c) -> (a -> b) -> a -> c
. LDCC -> ConnState
ldccState
    getMaxPacketSize :: LDCC -> IO Int
getMaxPacketSize   = IORef Int -> IO Int
forall a. IORef a -> IO a
readIORef  (IORef Int -> IO Int) -> (LDCC -> IORef Int) -> LDCC -> IO Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ConnState -> IORef Int
maxPacketSize   (ConnState -> IORef Int)
-> (LDCC -> ConnState) -> LDCC -> IORef Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. LDCC -> ConnState
ldccState
    getConnectionState :: LDCC -> IO ConnectionState
getConnectionState = TVar ConnectionState -> IO ConnectionState
forall a. TVar a -> IO a
readTVarIO (TVar ConnectionState -> IO ConnectionState)
-> (LDCC -> TVar ConnectionState) -> LDCC -> IO ConnectionState
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ConnState -> TVar ConnectionState
connectionState (ConnState -> TVar ConnectionState)
-> (LDCC -> ConnState) -> LDCC -> TVar ConnectionState
forall b c a. (b -> c) -> (a -> b) -> a -> c
. LDCC -> ConnState
ldccState
    getPacketNumber :: LDCC -> IO Int
getPacketNumber    = IORef Int -> IO Int
forall a. IORef a -> IO a
readIORef  (IORef Int -> IO Int) -> (LDCC -> IORef Int) -> LDCC -> IO Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ConnState -> IORef Int
packetNumber    (ConnState -> IORef Int)
-> (LDCC -> ConnState) -> LDCC -> IORef Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. LDCC -> ConnState
ldccState
    getAlive :: LDCC -> IO Bool
getAlive           = IORef Bool -> IO Bool
forall a. IORef a -> IO a
readIORef  (IORef Bool -> IO Bool) -> (LDCC -> IORef Bool) -> LDCC -> IO Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ConnState -> IORef Bool
connectionAlive (ConnState -> IORef Bool)
-> (LDCC -> ConnState) -> LDCC -> IORef Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. LDCC -> ConnState
ldccState

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

instance Qlog SentPacket where
    qlog :: SentPacket -> LogStr
qlog SentPacket{Bool
Int
TimeMicrosecond
PeerPacketNumbers
EncryptionLevel
PlainPacket
spAckEliciting :: Bool
spPeerPacketNumbers :: PeerPacketNumbers
spPacketNumber :: Int
spEncryptionLevel :: EncryptionLevel
spSentBytes :: Int
spTimeSent :: TimeMicrosecond
spPlainPacket :: PlainPacket
spAckEliciting :: SentPacket -> Bool
spPeerPacketNumbers :: SentPacket -> PeerPacketNumbers
spPacketNumber :: SentPacket -> Int
spEncryptionLevel :: SentPacket -> EncryptionLevel
spSentBytes :: SentPacket -> Int
spTimeSent :: SentPacket -> TimeMicrosecond
spPlainPacket :: SentPacket -> PlainPacket
..} = LogStr
"{\"raw\":{\"length\":" LogStr -> LogStr -> LogStr
forall a. Semigroup a => a -> a -> a
<> Int -> LogStr
forall a. Show a => a -> LogStr
sw Int
spSentBytes LogStr -> LogStr -> LogStr
forall a. Semigroup a => a -> a -> a
<> LogStr
"},\"header\":{\"packet_type\":\"" LogStr -> LogStr -> LogStr
forall a. Semigroup a => a -> a -> a
<> LogStr -> LogStr
forall msg. ToLogStr msg => msg -> LogStr
toLogStr (Header -> LogStr
packetType Header
hdr) LogStr -> LogStr -> LogStr
forall a. Semigroup a => a -> a -> a
<> LogStr
"\",\"packet_number\":\"" LogStr -> LogStr -> LogStr
forall a. Semigroup a => a -> a -> a
<> Int -> LogStr
forall a. Show a => a -> LogStr
sw Int
plainPacketNumber LogStr -> LogStr -> LogStr
forall a. Semigroup a => a -> a -> a
<> LogStr
"\",\"dcid\":\"" LogStr -> LogStr -> LogStr
forall a. Semigroup a => a -> a -> a
<> CID -> LogStr
forall a. Show a => a -> LogStr
sw (Header -> CID
headerMyCID Header
hdr) LogStr -> LogStr -> LogStr
forall a. Semigroup a => a -> a -> a
<> LogStr
"\"},\"frames\":" LogStr -> LogStr -> LogStr
forall a. Semigroup a => a -> a -> a
<> LogStr
"[" LogStr -> LogStr -> LogStr
forall a. Semigroup a => a -> a -> a
<> (LogStr -> LogStr -> LogStr) -> LogStr -> [LogStr] -> LogStr
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr LogStr -> LogStr -> LogStr
forall a. Semigroup a => a -> a -> a
(<>) LogStr
"" (LogStr -> [LogStr] -> [LogStr]
forall a. a -> [a] -> [a]
intersperse LogStr
"," ((Frame -> LogStr) -> [Frame] -> [LogStr]
forall a b. (a -> b) -> [a] -> [b]
map Frame -> LogStr
forall a. Qlog a => a -> LogStr
qlog [Frame]
plainFrames)) LogStr -> LogStr -> LogStr
forall a. Semigroup a => a -> a -> a
<> LogStr
"]" LogStr -> LogStr -> LogStr
forall a. Semigroup a => a -> a -> a
<> LogStr
"}"
      where
        PlainPacket Header
hdr Plain{Int
[Frame]
Flags Raw
plainMarks :: Plain -> Int
plainPacketNumber :: Plain -> Int
plainFlags :: Plain -> Flags Raw
plainMarks :: Int
plainFlags :: Flags Raw
plainFrames :: [Frame]
plainPacketNumber :: Int
plainFrames :: Plain -> [Frame]
..} = PlainPacket
spPlainPacket

instance Qlog LostPacket where
    qlog :: LostPacket -> LogStr
qlog (LostPacket SentPacket{Bool
Int
TimeMicrosecond
PeerPacketNumbers
EncryptionLevel
PlainPacket
spAckEliciting :: Bool
spPeerPacketNumbers :: PeerPacketNumbers
spPacketNumber :: Int
spEncryptionLevel :: EncryptionLevel
spSentBytes :: Int
spTimeSent :: TimeMicrosecond
spPlainPacket :: PlainPacket
spAckEliciting :: SentPacket -> Bool
spPeerPacketNumbers :: SentPacket -> PeerPacketNumbers
spPacketNumber :: SentPacket -> Int
spEncryptionLevel :: SentPacket -> EncryptionLevel
spSentBytes :: SentPacket -> Int
spTimeSent :: SentPacket -> TimeMicrosecond
spPlainPacket :: SentPacket -> PlainPacket
..}) =
        LogStr
"{\"header\":{\"packet_type\":\"" LogStr -> LogStr -> LogStr
forall a. Semigroup a => a -> a -> a
<> LogStr -> LogStr
forall msg. ToLogStr msg => msg -> LogStr
toLogStr (Header -> LogStr
packetType Header
hdr) LogStr -> LogStr -> LogStr
forall a. Semigroup a => a -> a -> a
<> LogStr
"\"" LogStr -> LogStr -> LogStr
forall a. Semigroup a => a -> a -> a
<>
        LogStr
",\"packet_number\":" LogStr -> LogStr -> LogStr
forall a. Semigroup a => a -> a -> a
<> Int -> LogStr
forall a. Show a => a -> LogStr
sw Int
spPacketNumber LogStr -> LogStr -> LogStr
forall a. Semigroup a => a -> a -> a
<>
        LogStr
"}}"
      where
        PlainPacket Header
hdr Plain
_ = PlainPacket
spPlainPacket

instance Qlog MetricsDiff where
    qlog :: MetricsDiff -> LogStr
qlog (MetricsDiff []) = LogStr
"{}"
    qlog (MetricsDiff ((String, Int)
x:[(String, Int)]
xs)) = LogStr
"{" LogStr -> LogStr -> LogStr
forall a. Semigroup a => a -> a -> a
<> (String, Int) -> LogStr
forall msg a. (ToLogStr msg, Show a) => (msg, a) -> LogStr
tv0 (String, Int)
x LogStr -> LogStr -> LogStr
forall a. Semigroup a => a -> a -> a
<> ((String, Int) -> LogStr -> LogStr)
-> LogStr -> [(String, Int)] -> LogStr
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr (String, Int) -> LogStr -> LogStr
forall msg a.
(ToLogStr msg, Show a) =>
(msg, a) -> LogStr -> LogStr
tv LogStr
"" [(String, Int)]
xs LogStr -> LogStr -> LogStr
forall a. Semigroup a => a -> a -> a
<> LogStr
"}"
      where
        tv0 :: (msg, a) -> LogStr
tv0 (msg
tag,a
val)    =  LogStr
"\"" LogStr -> LogStr -> LogStr
forall a. Semigroup a => a -> a -> a
<> msg -> LogStr
forall msg. ToLogStr msg => msg -> LogStr
toLogStr msg
tag LogStr -> LogStr -> LogStr
forall a. Semigroup a => a -> a -> a
<> LogStr
"\":" LogStr -> LogStr -> LogStr
forall a. Semigroup a => a -> a -> a
<> a -> LogStr
forall a. Show a => a -> LogStr
sw a
val
        tv :: (msg, a) -> LogStr -> LogStr
tv (msg
tag,a
val) LogStr
pre = LogStr
",\"" LogStr -> LogStr -> LogStr
forall a. Semigroup a => a -> a -> a
<> msg -> LogStr
forall msg. ToLogStr msg => msg -> LogStr
toLogStr msg
tag LogStr -> LogStr -> LogStr
forall a. Semigroup a => a -> a -> a
<> LogStr
"\":" LogStr -> LogStr -> LogStr
forall a. Semigroup a => a -> a -> a
<> a -> LogStr
forall a. Show a => a -> LogStr
sw a
val LogStr -> LogStr -> LogStr
forall a. Semigroup a => a -> a -> a
<> LogStr
pre

instance Qlog CCMode where
    qlog :: CCMode -> LogStr
qlog CCMode
mode = LogStr
"{\"new\":\"" LogStr -> LogStr -> LogStr
forall a. Semigroup a => a -> a -> a
<> CCMode -> LogStr
forall a. Show a => a -> LogStr
sw CCMode
mode LogStr -> LogStr -> LogStr
forall a. Semigroup a => a -> a -> a
<> LogStr
"\"}"

instance Qlog TimerCancelled where
    qlog :: TimerCancelled -> LogStr
qlog TimerCancelled
TimerCancelled = LogStr
"{\"event_type\":\"cancelled\"}"

instance Qlog TimerExpired where
    qlog :: TimerExpired -> LogStr
qlog TimerExpired
TimerExpired   = LogStr
"{\"event_type\":\"expired\"}"

instance Qlog (TimerInfo,Microseconds) where
    qlog :: (TimerInfo, Microseconds) -> LogStr
qlog (TimerInfo{TimeMicrosecond
EncryptionLevel
TimerType
timerType :: TimerType
timerLevel :: EncryptionLevel
timerTime :: TimeMicrosecond
timerType :: TimerInfo -> TimerType
timerLevel :: TimerInfo -> EncryptionLevel
timerTime :: TimerInfo -> TimeMicrosecond
..},Microseconds
us) = LogStr
"{\"event_type\":\"set\"" LogStr -> LogStr -> LogStr
forall a. Semigroup a => a -> a -> a
<>
                             LogStr
",\"timer_type\":\"" LogStr -> LogStr -> LogStr
forall a. Semigroup a => a -> a -> a
<> TimerType -> LogStr
forall a. Show a => a -> LogStr
sw TimerType
timerType LogStr -> LogStr -> LogStr
forall a. Semigroup a => a -> a -> a
<> LogStr
"\"" LogStr -> LogStr -> LogStr
forall a. Semigroup a => a -> a -> a
<>
                             LogStr
",\"packet_number_space\":\"" LogStr -> LogStr -> LogStr
forall a. Semigroup a => a -> a -> a
<> EncryptionLevel -> LogStr
packetNumberSpace EncryptionLevel
timerLevel LogStr -> LogStr -> LogStr
forall a. Semigroup a => a -> a -> a
<> LogStr
"\"" LogStr -> LogStr -> LogStr
forall a. Semigroup a => a -> a -> a
<>
                             LogStr
",\"delta\":" LogStr -> LogStr -> LogStr
forall a. Semigroup a => a -> a -> a
<> Microseconds -> LogStr
delta Microseconds
us LogStr -> LogStr -> LogStr
forall a. Semigroup a => a -> a -> a
<>
                             LogStr
"}"

packetNumberSpace :: EncryptionLevel -> LogStr
packetNumberSpace :: EncryptionLevel -> LogStr
packetNumberSpace EncryptionLevel
InitialLevel   = LogStr
"initial"
packetNumberSpace EncryptionLevel
RTT0Level      = LogStr
"application_data"
packetNumberSpace EncryptionLevel
HandshakeLevel = LogStr
"handshake"
packetNumberSpace EncryptionLevel
RTT1Level      = LogStr
"application_data"

delta :: Microseconds -> LogStr
delta :: Microseconds -> LogStr
delta (Microseconds Int
n) = Int -> LogStr
forall a. Show a => a -> LogStr
sw Int
n

qlogSent :: (KeepQlog q, Qlog pkt) => q -> pkt -> TimeMicrosecond -> IO ()
qlogSent :: q -> pkt -> TimeMicrosecond -> IO ()
qlogSent q
q pkt
pkt TimeMicrosecond
tim = q -> QLogger
forall a. KeepQlog a => a -> QLogger
keepQlog q
q QLogger -> QLogger
forall a b. (a -> b) -> a -> b
$ LogStr -> TimeMicrosecond -> QlogMsg
QSent (pkt -> LogStr
forall a. Qlog a => a -> LogStr
qlog pkt
pkt) TimeMicrosecond
tim

qlogMetricsUpdated :: KeepQlog q => q -> MetricsDiff -> IO ()
qlogMetricsUpdated :: q -> MetricsDiff -> IO ()
qlogMetricsUpdated q
q MetricsDiff
m = do
    TimeMicrosecond
tim <- IO TimeMicrosecond
getTimeMicrosecond
    q -> QLogger
forall a. KeepQlog a => a -> QLogger
keepQlog q
q QLogger -> QLogger
forall a b. (a -> b) -> a -> b
$ LogStr -> TimeMicrosecond -> QlogMsg
QMetricsUpdated (MetricsDiff -> LogStr
forall a. Qlog a => a -> LogStr
qlog MetricsDiff
m) TimeMicrosecond
tim

qlogPacketLost :: KeepQlog q => q -> LostPacket -> IO ()
qlogPacketLost :: q -> LostPacket -> IO ()
qlogPacketLost q
q LostPacket
lpkt = do
    TimeMicrosecond
tim <- IO TimeMicrosecond
getTimeMicrosecond
    q -> QLogger
forall a. KeepQlog a => a -> QLogger
keepQlog q
q QLogger -> QLogger
forall a b. (a -> b) -> a -> b
$ LogStr -> TimeMicrosecond -> QlogMsg
QPacketLost (LostPacket -> LogStr
forall a. Qlog a => a -> LogStr
qlog LostPacket
lpkt) TimeMicrosecond
tim

qlogContestionStateUpdated :: KeepQlog q => q -> CCMode -> IO ()
qlogContestionStateUpdated :: q -> CCMode -> IO ()
qlogContestionStateUpdated q
q CCMode
mode = do
    TimeMicrosecond
tim <- IO TimeMicrosecond
getTimeMicrosecond
    q -> QLogger
forall a. KeepQlog a => a -> QLogger
keepQlog q
q QLogger -> QLogger
forall a b. (a -> b) -> a -> b
$ LogStr -> TimeMicrosecond -> QlogMsg
QCongestionStateUpdated (CCMode -> LogStr
forall a. Qlog a => a -> LogStr
qlog CCMode
mode) TimeMicrosecond
tim

qlogLossTimerUpdated :: KeepQlog q => q -> (TimerInfo,Microseconds) -> IO ()
qlogLossTimerUpdated :: q -> (TimerInfo, Microseconds) -> IO ()
qlogLossTimerUpdated q
q (TimerInfo, Microseconds)
tmi = do
    TimeMicrosecond
tim <- IO TimeMicrosecond
getTimeMicrosecond
    q -> QLogger
forall a. KeepQlog a => a -> QLogger
keepQlog q
q QLogger -> QLogger
forall a b. (a -> b) -> a -> b
$ LogStr -> TimeMicrosecond -> QlogMsg
QLossTimerUpdated ((TimerInfo, Microseconds) -> LogStr
forall a. Qlog a => a -> LogStr
qlog (TimerInfo, Microseconds)
tmi) TimeMicrosecond
tim

qlogLossTimerCancelled :: KeepQlog q => q -> IO ()
qlogLossTimerCancelled :: q -> IO ()
qlogLossTimerCancelled q
q = do
    TimeMicrosecond
tim <- IO TimeMicrosecond
getTimeMicrosecond
    q -> QLogger
forall a. KeepQlog a => a -> QLogger
keepQlog q
q QLogger -> QLogger
forall a b. (a -> b) -> a -> b
$ LogStr -> TimeMicrosecond -> QlogMsg
QLossTimerUpdated (TimerCancelled -> LogStr
forall a. Qlog a => a -> LogStr
qlog TimerCancelled
TimerCancelled) TimeMicrosecond
tim

qlogLossTimerExpired :: KeepQlog q => q -> IO ()
qlogLossTimerExpired :: q -> IO ()
qlogLossTimerExpired q
q = do
    TimeMicrosecond
tim <- IO TimeMicrosecond
getTimeMicrosecond
    q -> QLogger
forall a. KeepQlog a => a -> QLogger
keepQlog q
q QLogger -> QLogger
forall a b. (a -> b) -> a -> b
$ LogStr -> TimeMicrosecond -> QlogMsg
QLossTimerUpdated (TimerExpired -> LogStr
forall a. Qlog a => a -> LogStr
qlog TimerExpired
TimerExpired) TimeMicrosecond
tim