{-# LANGUAGE CPP                       #-}
{-# LANGUAGE DeriveFunctor             #-}
{-# LANGUAGE DeriveGeneric             #-}
{-# LANGUAGE DerivingVia               #-}
{-# LANGUAGE ExistentialQuantification #-}
{-# LANGUAGE LambdaCase                #-}
{-# LANGUAGE NamedFieldPuns            #-}

module Network.Mux.Trace
  ( Error (..)
  , handleIOException
  , Trace (..)
  , BearerState (..)
  , WithBearer (..)
  , TraceLabelPeer (..)
  ) where

import Prelude hiding (read)

import Text.Printf

import Control.Exception hiding (throwIO)
import Control.Monad.Class.MonadThrow
import Control.Monad.Class.MonadTime.SI
import Data.Bifunctor (Bifunctor (..))
import Data.Word
import GHC.Generics (Generic (..))
import Quiet (Quiet (..))

import Network.Mux.TCPInfo
import Network.Mux.Types


--
-- Errors
--

-- | Enumeration of error conditions.
--
data Error = UnknownMiniProtocol MiniProtocolNum
           -- ^ returned by 'decodeSDUHeader', thrown by 'Bearer'.
           | BearerClosed String
           -- ^ thrown by 'Bearer' when received a null byte.
           | IngressQueueOverRun MiniProtocolNum MiniProtocolDir
           -- ^ thrown by 'demux' when violating 'maximumIngressQueue'
           -- byte limit.
           | InitiatorOnly MiniProtocolNum
           -- ^ thrown when data arrives on a responder channel when the
           -- mux was set up as an 'InitiatorApp'.
           | IOException IOException String
           -- ^ 'IOException' thrown by

           | SDUDecodeError String
           -- ^ return by 'decodeSDUHeader', thrown by 'Bearer'.
           | SDUReadTimeout
           -- ^ thrown when reading of a single SDU takes too long
           | SDUWriteTimeout
           -- ^ thrown when writing a single SDU takes too long

           | Shutdown (Maybe SomeException) Status
           -- ^ Result of runMiniProtocol's completionAction in case of
           -- an error or mux being closed while a mini-protocol was
           -- still running, this is not a clean exit.
           deriving Int -> Error -> ShowS
[Error] -> ShowS
Error -> String
(Int -> Error -> ShowS)
-> (Error -> String) -> ([Error] -> ShowS) -> Show Error
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> Error -> ShowS
showsPrec :: Int -> Error -> ShowS
$cshow :: Error -> String
show :: Error -> String
$cshowList :: [Error] -> ShowS
showList :: [Error] -> ShowS
Show

instance Exception Error where
  displayException :: Error -> String
displayException = \case
    UnknownMiniProtocol MiniProtocolNum
pnum      -> String -> ShowS
forall r. PrintfType r => String -> r
printf String
"unknown mini-protocol %s" (MiniProtocolNum -> String
forall a. Show a => a -> String
show MiniProtocolNum
pnum)
    BearerClosed String
msg              -> String -> ShowS
forall r. PrintfType r => String -> r
printf String
"bearer closed: %s" (ShowS
forall a. Show a => a -> String
show String
msg)
    IngressQueueOverRun MiniProtocolNum
pnum MiniProtocolDir
pdir -> String -> String -> ShowS
forall r. PrintfType r => String -> r
printf String
"ingress queue overrun for %s %s " (MiniProtocolNum -> String
forall a. Show a => a -> String
show MiniProtocolNum
pnum) (MiniProtocolDir -> String
forall a. Show a => a -> String
show MiniProtocolDir
pdir)
    InitiatorOnly MiniProtocolNum
pnum            -> String -> ShowS
forall r. PrintfType r => String -> r
printf String
"received data on initiator only protocol %s" (MiniProtocolNum -> String
forall a. Show a => a -> String
show MiniProtocolNum
pnum)
    IOException IOException
e String
msg             -> IOException -> String
forall e. Exception e => e -> String
displayException IOException
e String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
": " String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
msg
    SDUDecodeError String
msg            -> String -> ShowS
forall r. PrintfType r => String -> r
printf String
"SDU decode error: %s" String
msg
    Error
SDUReadTimeout                -> String
"SDU read timeout expired"
    Error
SDUWriteTimeout               -> String
"SDU write timeout expired"
    Shutdown Maybe SomeException
Nothing Status
st           -> String -> ShowS
forall r. PrintfType r => String -> r
printf String
"mux shutdown error in state %s" (Status -> String
forall a. Show a => a -> String
show Status
st)
    Shutdown (Just SomeException
e) Status
st          -> String -> String -> ShowS
forall r. PrintfType r => String -> r
printf String
"mux shutdown error (%s) in state %s " (SomeException -> String
forall e. Exception e => e -> String
displayException SomeException
e) (Status -> String
forall a. Show a => a -> String
show Status
st)

-- | Handler for 'IOException's which wraps them in 'Error'.
--
-- It is used various 'Bearer' implementations:
-- * 'socketAsBearer'
-- * 'pipeAsBearer'
--
handleIOException :: MonadThrow m => String -> IOException -> m a
handleIOException :: forall (m :: * -> *) a.
MonadThrow m =>
String -> IOException -> m a
handleIOException String
msg IOException
e = Error -> m a
forall e a. Exception e => e -> m a
forall (m :: * -> *) e a. (MonadThrow m, Exception e) => e -> m a
throwIO (IOException -> String -> Error
IOException IOException
e String
msg)


--
-- Tracing
--

-- | A peer label for use in 'Tracer's. This annotates tracer output as being
-- associated with a given peer identifier.
--
data TraceLabelPeer peerid a = TraceLabelPeer peerid a
  deriving (TraceLabelPeer peerid a -> TraceLabelPeer peerid a -> Bool
(TraceLabelPeer peerid a -> TraceLabelPeer peerid a -> Bool)
-> (TraceLabelPeer peerid a -> TraceLabelPeer peerid a -> Bool)
-> Eq (TraceLabelPeer peerid a)
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
forall peerid a.
(Eq peerid, Eq a) =>
TraceLabelPeer peerid a -> TraceLabelPeer peerid a -> Bool
$c== :: forall peerid a.
(Eq peerid, Eq a) =>
TraceLabelPeer peerid a -> TraceLabelPeer peerid a -> Bool
== :: TraceLabelPeer peerid a -> TraceLabelPeer peerid a -> Bool
$c/= :: forall peerid a.
(Eq peerid, Eq a) =>
TraceLabelPeer peerid a -> TraceLabelPeer peerid a -> Bool
/= :: TraceLabelPeer peerid a -> TraceLabelPeer peerid a -> Bool
Eq, (forall a b.
 (a -> b) -> TraceLabelPeer peerid a -> TraceLabelPeer peerid b)
-> (forall a b.
    a -> TraceLabelPeer peerid b -> TraceLabelPeer peerid a)
-> Functor (TraceLabelPeer peerid)
forall a b. a -> TraceLabelPeer peerid b -> TraceLabelPeer peerid a
forall a b.
(a -> b) -> TraceLabelPeer peerid a -> TraceLabelPeer peerid b
forall peerid a b.
a -> TraceLabelPeer peerid b -> TraceLabelPeer peerid a
forall peerid a b.
(a -> b) -> TraceLabelPeer peerid a -> TraceLabelPeer peerid b
forall (f :: * -> *).
(forall a b. (a -> b) -> f a -> f b)
-> (forall a b. a -> f b -> f a) -> Functor f
$cfmap :: forall peerid a b.
(a -> b) -> TraceLabelPeer peerid a -> TraceLabelPeer peerid b
fmap :: forall a b.
(a -> b) -> TraceLabelPeer peerid a -> TraceLabelPeer peerid b
$c<$ :: forall peerid a b.
a -> TraceLabelPeer peerid b -> TraceLabelPeer peerid a
<$ :: forall a b. a -> TraceLabelPeer peerid b -> TraceLabelPeer peerid a
Functor, Int -> TraceLabelPeer peerid a -> ShowS
[TraceLabelPeer peerid a] -> ShowS
TraceLabelPeer peerid a -> String
(Int -> TraceLabelPeer peerid a -> ShowS)
-> (TraceLabelPeer peerid a -> String)
-> ([TraceLabelPeer peerid a] -> ShowS)
-> Show (TraceLabelPeer peerid a)
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
forall peerid a.
(Show peerid, Show a) =>
Int -> TraceLabelPeer peerid a -> ShowS
forall peerid a.
(Show peerid, Show a) =>
[TraceLabelPeer peerid a] -> ShowS
forall peerid a.
(Show peerid, Show a) =>
TraceLabelPeer peerid a -> String
$cshowsPrec :: forall peerid a.
(Show peerid, Show a) =>
Int -> TraceLabelPeer peerid a -> ShowS
showsPrec :: Int -> TraceLabelPeer peerid a -> ShowS
$cshow :: forall peerid a.
(Show peerid, Show a) =>
TraceLabelPeer peerid a -> String
show :: TraceLabelPeer peerid a -> String
$cshowList :: forall peerid a.
(Show peerid, Show a) =>
[TraceLabelPeer peerid a] -> ShowS
showList :: [TraceLabelPeer peerid a] -> ShowS
Show)

instance Bifunctor TraceLabelPeer where
  bimap :: forall a b c d.
(a -> b) -> (c -> d) -> TraceLabelPeer a c -> TraceLabelPeer b d
bimap a -> b
f c -> d
g (TraceLabelPeer a
a c
b) = b -> d -> TraceLabelPeer b d
forall peerid a. peerid -> a -> TraceLabelPeer peerid a
TraceLabelPeer (a -> b
f a
a) (c -> d
g c
b)

-- | Type used for tracing mux events.
--
data WithBearer peerid a = WithBearer {
      forall peerid a. WithBearer peerid a -> peerid
wbPeerId :: !peerid
      -- ^ A tag that should identify a specific mux bearer.
    , forall peerid a. WithBearer peerid a -> a
wbEvent  :: !a
  }
  deriving ((forall x. WithBearer peerid a -> Rep (WithBearer peerid a) x)
-> (forall x. Rep (WithBearer peerid a) x -> WithBearer peerid a)
-> Generic (WithBearer peerid a)
forall x. Rep (WithBearer peerid a) x -> WithBearer peerid a
forall x. WithBearer peerid a -> Rep (WithBearer peerid a) x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
forall peerid a x.
Rep (WithBearer peerid a) x -> WithBearer peerid a
forall peerid a x.
WithBearer peerid a -> Rep (WithBearer peerid a) x
$cfrom :: forall peerid a x.
WithBearer peerid a -> Rep (WithBearer peerid a) x
from :: forall x. WithBearer peerid a -> Rep (WithBearer peerid a) x
$cto :: forall peerid a x.
Rep (WithBearer peerid a) x -> WithBearer peerid a
to :: forall x. Rep (WithBearer peerid a) x -> WithBearer peerid a
Generic)
  deriving Int -> WithBearer peerid a -> ShowS
[WithBearer peerid a] -> ShowS
WithBearer peerid a -> String
(Int -> WithBearer peerid a -> ShowS)
-> (WithBearer peerid a -> String)
-> ([WithBearer peerid a] -> ShowS)
-> Show (WithBearer peerid a)
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
forall peerid a.
(Show peerid, Show a) =>
Int -> WithBearer peerid a -> ShowS
forall peerid a.
(Show peerid, Show a) =>
[WithBearer peerid a] -> ShowS
forall peerid a.
(Show peerid, Show a) =>
WithBearer peerid a -> String
$cshowsPrec :: forall peerid a.
(Show peerid, Show a) =>
Int -> WithBearer peerid a -> ShowS
showsPrec :: Int -> WithBearer peerid a -> ShowS
$cshow :: forall peerid a.
(Show peerid, Show a) =>
WithBearer peerid a -> String
show :: WithBearer peerid a -> String
$cshowList :: forall peerid a.
(Show peerid, Show a) =>
[WithBearer peerid a] -> ShowS
showList :: [WithBearer peerid a] -> ShowS
Show via (Quiet (WithBearer peerid a))
--TODO: probably remove this type


data BearerState = Mature
                 -- ^ `Bearer` has successfully completed the handshake.
                 | Dead
                 -- ^ `Bearer` is dead and the underlying bearer has been
                 -- closed.
                 deriving (BearerState -> BearerState -> Bool
(BearerState -> BearerState -> Bool)
-> (BearerState -> BearerState -> Bool) -> Eq BearerState
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: BearerState -> BearerState -> Bool
== :: BearerState -> BearerState -> Bool
$c/= :: BearerState -> BearerState -> Bool
/= :: BearerState -> BearerState -> Bool
Eq, Int -> BearerState -> ShowS
[BearerState] -> ShowS
BearerState -> String
(Int -> BearerState -> ShowS)
-> (BearerState -> String)
-> ([BearerState] -> ShowS)
-> Show BearerState
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> BearerState -> ShowS
showsPrec :: Int -> BearerState -> ShowS
$cshow :: BearerState -> String
show :: BearerState -> String
$cshowList :: [BearerState] -> ShowS
showList :: [BearerState] -> ShowS
Show)

-- | Enumeration of Mux events that can be traced.
--
data Trace =
      TraceRecvHeaderStart
    | TraceRecvHeaderEnd SDUHeader
    | TraceRecvDeltaQObservation SDUHeader Time
    | TraceRecvDeltaQSample Double Int Int Double Double Double Double String
    | TraceRecvStart Int
    | TraceRecvEnd Int
    | TraceSendStart SDUHeader
    | TraceSendEnd
    | TraceState BearerState
    | TraceCleanExit MiniProtocolNum MiniProtocolDir
    | TraceExceptionExit MiniProtocolNum MiniProtocolDir SomeException
    | TraceChannelRecvStart MiniProtocolNum
    | TraceChannelRecvEnd MiniProtocolNum Int
    | TraceChannelSendStart MiniProtocolNum Int
    | TraceChannelSendEnd MiniProtocolNum
    | TraceHandshakeStart
    | TraceHandshakeClientEnd DiffTime
    | TraceHandshakeServerEnd
    | forall e. Exception e => TraceHandshakeClientError e DiffTime
    | forall e. Exception e => TraceHandshakeServerError e
    | TraceSDUReadTimeoutException
    | TraceSDUWriteTimeoutException
    | TraceStartEagerly MiniProtocolNum MiniProtocolDir
    | TraceStartOnDemand MiniProtocolNum MiniProtocolDir
    | TraceStartedOnDemand MiniProtocolNum MiniProtocolDir
    | TraceTerminating MiniProtocolNum MiniProtocolDir
    | TraceStopping
    | TraceStopped
    | TraceTCPInfo StructTCPInfo Word16

instance Show Trace where
    show :: Trace -> String
show Trace
TraceRecvHeaderStart = ShowS
forall r. PrintfType r => String -> r
printf String
"Bearer Receive Header Start"
    show (TraceRecvHeaderEnd SDUHeader { RemoteClockModel
mhTimestamp :: RemoteClockModel
mhTimestamp :: SDUHeader -> RemoteClockModel
mhTimestamp, MiniProtocolNum
mhNum :: MiniProtocolNum
mhNum :: SDUHeader -> MiniProtocolNum
mhNum, MiniProtocolDir
mhDir :: MiniProtocolDir
mhDir :: SDUHeader -> MiniProtocolDir
mhDir, Word16
mhLength :: Word16
mhLength :: SDUHeader -> Word16
mhLength }) = String -> Word32 -> String -> String -> Word16 -> String
forall r. PrintfType r => String -> r
printf String
"Bearer Receive Header End: ts: 0x%08x (%s) %s len %d"
        (RemoteClockModel -> Word32
unRemoteClockModel RemoteClockModel
mhTimestamp) (MiniProtocolNum -> String
forall a. Show a => a -> String
show MiniProtocolNum
mhNum) (MiniProtocolDir -> String
forall a. Show a => a -> String
show MiniProtocolDir
mhDir) Word16
mhLength
    show (TraceRecvDeltaQObservation SDUHeader { RemoteClockModel
mhTimestamp :: SDUHeader -> RemoteClockModel
mhTimestamp :: RemoteClockModel
mhTimestamp, Word16
mhLength :: SDUHeader -> Word16
mhLength :: Word16
mhLength } Time
ts) = String -> Word32 -> String -> Word16 -> String
forall r. PrintfType r => String -> r
printf String
"Bearer DeltaQ observation: remote ts %d local ts %s length %d"
        (RemoteClockModel -> Word32
unRemoteClockModel RemoteClockModel
mhTimestamp) (Time -> String
forall a. Show a => a -> String
show Time
ts) Word16
mhLength
    show (TraceRecvDeltaQSample Double
d Int
sp Int
so Double
dqs Double
dqvm Double
dqvs Double
estR String
sdud) = String
-> Double
-> Int
-> Int
-> Double
-> Double
-> Double
-> Double
-> ShowS
forall r. PrintfType r => String -> r
printf String
"Bearer DeltaQ Sample: duration %.3e packets %d sumBytes %d DeltaQ_S %.3e DeltaQ_VMean %.3e DeltaQ_VVar %.3e DeltaQ_estR %.3e sizeDist %s"
         Double
d Int
sp Int
so Double
dqs Double
dqvm Double
dqvs Double
estR String
sdud
    show (TraceRecvStart Int
len) = String -> Int -> String
forall r. PrintfType r => String -> r
printf String
"Bearer Receive Start: length %d" Int
len
    show (TraceRecvEnd Int
len) = String -> Int -> String
forall r. PrintfType r => String -> r
printf String
"Bearer Receive End: length %d" Int
len
    show (TraceSendStart SDUHeader { RemoteClockModel
mhTimestamp :: SDUHeader -> RemoteClockModel
mhTimestamp :: RemoteClockModel
mhTimestamp, MiniProtocolNum
mhNum :: SDUHeader -> MiniProtocolNum
mhNum :: MiniProtocolNum
mhNum, MiniProtocolDir
mhDir :: SDUHeader -> MiniProtocolDir
mhDir :: MiniProtocolDir
mhDir, Word16
mhLength :: SDUHeader -> Word16
mhLength :: Word16
mhLength }) = String -> Word32 -> String -> String -> Word16 -> String
forall r. PrintfType r => String -> r
printf String
"Bearer Send Start: ts: 0x%08x (%s) %s length %d"
        (RemoteClockModel -> Word32
unRemoteClockModel RemoteClockModel
mhTimestamp) (MiniProtocolNum -> String
forall a. Show a => a -> String
show MiniProtocolNum
mhNum) (MiniProtocolDir -> String
forall a. Show a => a -> String
show MiniProtocolDir
mhDir) Word16
mhLength
    show Trace
TraceSendEnd = ShowS
forall r. PrintfType r => String -> r
printf String
"Bearer Send End"
    show (TraceState BearerState
new) = String -> ShowS
forall r. PrintfType r => String -> r
printf String
"State: %s" (BearerState -> String
forall a. Show a => a -> String
show BearerState
new)
    show (TraceCleanExit MiniProtocolNum
mid MiniProtocolDir
dir) = String -> String -> ShowS
forall r. PrintfType r => String -> r
printf String
"Miniprotocol (%s) %s terminated cleanly" (MiniProtocolNum -> String
forall a. Show a => a -> String
show MiniProtocolNum
mid) (MiniProtocolDir -> String
forall a. Show a => a -> String
show MiniProtocolDir
dir)
    show (TraceExceptionExit MiniProtocolNum
mid MiniProtocolDir
dir SomeException
e) = String -> String -> String -> ShowS
forall r. PrintfType r => String -> r
printf String
"Miniprotocol %s %s terminated with exception %s" (MiniProtocolNum -> String
forall a. Show a => a -> String
show MiniProtocolNum
mid) (MiniProtocolDir -> String
forall a. Show a => a -> String
show MiniProtocolDir
dir) (SomeException -> String
forall a. Show a => a -> String
show SomeException
e)
    show (TraceChannelRecvStart MiniProtocolNum
mid) = String -> ShowS
forall r. PrintfType r => String -> r
printf String
"Channel Receive Start on %s" (MiniProtocolNum -> String
forall a. Show a => a -> String
show MiniProtocolNum
mid)
    show (TraceChannelRecvEnd MiniProtocolNum
mid Int
len) = String -> String -> Int -> String
forall r. PrintfType r => String -> r
printf String
"Channel Receive End on (%s) %d" (MiniProtocolNum -> String
forall a. Show a => a -> String
show MiniProtocolNum
mid)
        Int
len
    show (TraceChannelSendStart MiniProtocolNum
mid Int
len) = String -> String -> Int -> String
forall r. PrintfType r => String -> r
printf String
"Channel Send Start on (%s) %d" (MiniProtocolNum -> String
forall a. Show a => a -> String
show MiniProtocolNum
mid)
        Int
len
    show (TraceChannelSendEnd MiniProtocolNum
mid) = String -> ShowS
forall r. PrintfType r => String -> r
printf String
"Channel Send End on %s" (MiniProtocolNum -> String
forall a. Show a => a -> String
show MiniProtocolNum
mid)
    show Trace
TraceHandshakeStart = String
"Handshake start"
    show (TraceHandshakeClientEnd DiffTime
duration) = String -> ShowS
forall r. PrintfType r => String -> r
printf String
"Handshake Client end, duration %s" (DiffTime -> String
forall a. Show a => a -> String
show DiffTime
duration)
    show Trace
TraceHandshakeServerEnd = String
"Handshake Server end"
    show (TraceHandshakeClientError e
e DiffTime
duration) =
         -- Client Error can include an error string from the peer which could be very large.
        String -> String -> ShowS
forall r. PrintfType r => String -> r
printf String
"Handshake Client Error %s duration %s" (Int -> ShowS
forall a. Int -> [a] -> [a]
take Int
256 ShowS -> ShowS
forall a b. (a -> b) -> a -> b
$ e -> String
forall a. Show a => a -> String
show e
e) (DiffTime -> String
forall a. Show a => a -> String
show DiffTime
duration)
    show (TraceHandshakeServerError e
e) = String -> ShowS
forall r. PrintfType r => String -> r
printf String
"Handshake Server Error %s" (e -> String
forall a. Show a => a -> String
show e
e)
    show Trace
TraceSDUReadTimeoutException = String
"Timed out reading SDU"
    show Trace
TraceSDUWriteTimeoutException = String
"Timed out writing SDU"
    show (TraceStartEagerly MiniProtocolNum
mid MiniProtocolDir
dir) = String -> String -> ShowS
forall r. PrintfType r => String -> r
printf String
"Eagerly started (%s) in %s" (MiniProtocolNum -> String
forall a. Show a => a -> String
show MiniProtocolNum
mid) (MiniProtocolDir -> String
forall a. Show a => a -> String
show MiniProtocolDir
dir)
    show (TraceStartOnDemand MiniProtocolNum
mid MiniProtocolDir
dir) = String -> String -> ShowS
forall r. PrintfType r => String -> r
printf String
"Preparing to start (%s) in %s" (MiniProtocolNum -> String
forall a. Show a => a -> String
show MiniProtocolNum
mid) (MiniProtocolDir -> String
forall a. Show a => a -> String
show MiniProtocolDir
dir)
    show (TraceStartedOnDemand MiniProtocolNum
mid MiniProtocolDir
dir) = String -> String -> ShowS
forall r. PrintfType r => String -> r
printf String
"Started on demand (%s) in %s" (MiniProtocolNum -> String
forall a. Show a => a -> String
show MiniProtocolNum
mid) (MiniProtocolDir -> String
forall a. Show a => a -> String
show MiniProtocolDir
dir)
    show (TraceTerminating MiniProtocolNum
mid MiniProtocolDir
dir) = String -> String -> ShowS
forall r. PrintfType r => String -> r
printf String
"Terminating (%s) in %s" (MiniProtocolNum -> String
forall a. Show a => a -> String
show MiniProtocolNum
mid) (MiniProtocolDir -> String
forall a. Show a => a -> String
show MiniProtocolDir
dir)
    show Trace
TraceStopping = String
"Mux stopping"
    show Trace
TraceStopped  = String
"Mux stoppped"
#ifdef linux_HOST_OS
    show (TraceTCPInfo StructTCPInfo
            { CUInt
tcpi_snd_mss :: CUInt
tcpi_snd_mss :: StructTCPInfo -> CUInt
tcpi_snd_mss, CUInt
tcpi_rcv_mss :: CUInt
tcpi_rcv_mss :: StructTCPInfo -> CUInt
tcpi_rcv_mss, CUInt
tcpi_lost :: CUInt
tcpi_lost :: StructTCPInfo -> CUInt
tcpi_lost, CUInt
tcpi_retrans :: CUInt
tcpi_retrans :: StructTCPInfo -> CUInt
tcpi_retrans
            , CUInt
tcpi_rtt :: CUInt
tcpi_rtt :: StructTCPInfo -> CUInt
tcpi_rtt, CUInt
tcpi_rttvar :: CUInt
tcpi_rttvar :: StructTCPInfo -> CUInt
tcpi_rttvar, CUInt
tcpi_snd_cwnd :: CUInt
tcpi_snd_cwnd :: StructTCPInfo -> CUInt
tcpi_snd_cwnd }
            Word16
len)
                                     =
      String
-> Word
-> Word
-> Word
-> Word
-> Word
-> Word
-> Word
-> Word16
-> String
forall r. PrintfType r => String -> r
printf String
"TCPInfo rtt %d rttvar %d cwnd %d smss %d rmss %d lost %d retrans %d len %d"
        (CUInt -> Word
forall a b. (Integral a, Num b) => a -> b
fromIntegral CUInt
tcpi_rtt :: Word) (CUInt -> Word
forall a b. (Integral a, Num b) => a -> b
fromIntegral CUInt
tcpi_rttvar :: Word)
        (CUInt -> Word
forall a b. (Integral a, Num b) => a -> b
fromIntegral CUInt
tcpi_snd_cwnd :: Word) (CUInt -> Word
forall a b. (Integral a, Num b) => a -> b
fromIntegral CUInt
tcpi_snd_mss :: Word)
        (CUInt -> Word
forall a b. (Integral a, Num b) => a -> b
fromIntegral CUInt
tcpi_rcv_mss :: Word) (CUInt -> Word
forall a b. (Integral a, Num b) => a -> b
fromIntegral CUInt
tcpi_lost :: Word)
        (CUInt -> Word
forall a b. (Integral a, Num b) => a -> b
fromIntegral CUInt
tcpi_retrans :: Word)
        Word16
len
#else
    show (TraceTCPInfo _ len) = printf "TCPInfo len %d" len
#endif