{-# LANGUAGE CPP #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE NamedFieldPuns #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
module Ouroboros.Network.Subscription.Ip
( SubscriptionParams (..)
, IPSubscriptionParams
, ipSubscriptionWorker
, subscriptionWorker
, IPSubscriptionTarget (..)
, ipSubscriptionTarget
, SubscriptionTrace (..)
, ErrorPolicyTrace (..)
, WithIPList (..)
, BeforeConnect
, runBeforeConnect
, beforeConnectTx
, completeApplicationTx
, socketStateChangeTx
, mainTx
, selectSockAddr
) where
import Control.Concurrent.Class.MonadSTM.Strict
import Control.Monad.Class.MonadThrow
import Control.Monad.Class.MonadTime.SI
import Control.Tracer
import Data.Void (Void)
import Network.Socket qualified as Socket
import Text.Printf
import Ouroboros.Network.ErrorPolicy
import Ouroboros.Network.Snocket (Snocket)
import Ouroboros.Network.Socket
import Ouroboros.Network.Subscription.PeerState
import Ouroboros.Network.Subscription.Subscriber
import Ouroboros.Network.Subscription.Worker
data IPSubscriptionTarget = IPSubscriptionTarget {
IPSubscriptionTarget -> [SockAddr]
ispIps :: ![Socket.SockAddr]
, IPSubscriptionTarget -> Int
ispValency :: !Int
} deriving (IPSubscriptionTarget -> IPSubscriptionTarget -> Bool
(IPSubscriptionTarget -> IPSubscriptionTarget -> Bool)
-> (IPSubscriptionTarget -> IPSubscriptionTarget -> Bool)
-> Eq IPSubscriptionTarget
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: IPSubscriptionTarget -> IPSubscriptionTarget -> Bool
== :: IPSubscriptionTarget -> IPSubscriptionTarget -> Bool
$c/= :: IPSubscriptionTarget -> IPSubscriptionTarget -> Bool
/= :: IPSubscriptionTarget -> IPSubscriptionTarget -> Bool
Eq, Int -> IPSubscriptionTarget -> ShowS
[IPSubscriptionTarget] -> ShowS
IPSubscriptionTarget -> String
(Int -> IPSubscriptionTarget -> ShowS)
-> (IPSubscriptionTarget -> String)
-> ([IPSubscriptionTarget] -> ShowS)
-> Show IPSubscriptionTarget
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> IPSubscriptionTarget -> ShowS
showsPrec :: Int -> IPSubscriptionTarget -> ShowS
$cshow :: IPSubscriptionTarget -> String
show :: IPSubscriptionTarget -> String
$cshowList :: [IPSubscriptionTarget] -> ShowS
showList :: [IPSubscriptionTarget] -> ShowS
Show)
data SubscriptionParams a target = SubscriptionParams
{ forall a target.
SubscriptionParams a target -> LocalAddresses SockAddr
spLocalAddresses :: LocalAddresses Socket.SockAddr
, forall a target.
SubscriptionParams a target -> SockAddr -> Maybe DiffTime
spConnectionAttemptDelay :: Socket.SockAddr -> Maybe DiffTime
, forall a target. SubscriptionParams a target -> ErrorPolicies
spErrorPolicies :: ErrorPolicies
, forall a target. SubscriptionParams a target -> target
spSubscriptionTarget :: target
}
type IPSubscriptionParams a = SubscriptionParams a IPSubscriptionTarget
ipSubscriptionWorker
:: forall a.
Snocket IO Socket.Socket Socket.SockAddr
-> Tracer IO (WithIPList (SubscriptionTrace Socket.SockAddr))
-> Tracer IO (WithAddr Socket.SockAddr ErrorPolicyTrace)
-> NetworkMutableState Socket.SockAddr
-> IPSubscriptionParams a
-> (Socket.Socket -> IO a)
-> IO Void
ipSubscriptionWorker :: forall a.
Snocket IO Socket SockAddr
-> Tracer IO (WithIPList (SubscriptionTrace SockAddr))
-> Tracer IO (WithAddr SockAddr ErrorPolicyTrace)
-> NetworkMutableState SockAddr
-> IPSubscriptionParams a
-> (Socket -> IO a)
-> IO Void
ipSubscriptionWorker Snocket IO Socket SockAddr
snocket Tracer IO (WithIPList (SubscriptionTrace SockAddr))
subscriptionTracer Tracer IO (WithAddr SockAddr ErrorPolicyTrace)
errorPolicyTracer
networkState :: NetworkMutableState SockAddr
networkState@NetworkMutableState { StrictTVar IO (PeerStates IO SockAddr)
nmsPeerStates :: StrictTVar IO (PeerStates IO SockAddr)
nmsPeerStates :: forall addr.
NetworkMutableState addr -> StrictTVar IO (PeerStates IO addr)
nmsPeerStates }
SubscriptionParams { LocalAddresses SockAddr
spLocalAddresses :: forall a target.
SubscriptionParams a target -> LocalAddresses SockAddr
spLocalAddresses :: LocalAddresses SockAddr
spLocalAddresses
, SockAddr -> Maybe DiffTime
spConnectionAttemptDelay :: forall a target.
SubscriptionParams a target -> SockAddr -> Maybe DiffTime
spConnectionAttemptDelay :: SockAddr -> Maybe DiffTime
spConnectionAttemptDelay
, IPSubscriptionTarget
spSubscriptionTarget :: forall a target. SubscriptionParams a target -> target
spSubscriptionTarget :: IPSubscriptionTarget
spSubscriptionTarget
, ErrorPolicies
spErrorPolicies :: forall a target. SubscriptionParams a target -> ErrorPolicies
spErrorPolicies :: ErrorPolicies
spErrorPolicies
}
Socket -> IO a
k =
Snocket IO Socket SockAddr
-> Tracer IO (SubscriptionTrace SockAddr)
-> Tracer IO (WithAddr SockAddr ErrorPolicyTrace)
-> NetworkMutableState SockAddr
-> WorkerParams IO LocalAddresses SockAddr
-> ErrorPolicies
-> Main IO (PeerStates IO SockAddr) Void
-> (Socket -> IO a)
-> IO Void
forall x a.
Snocket IO Socket SockAddr
-> Tracer IO (SubscriptionTrace SockAddr)
-> Tracer IO (WithAddr SockAddr ErrorPolicyTrace)
-> NetworkMutableState SockAddr
-> WorkerParams IO LocalAddresses SockAddr
-> ErrorPolicies
-> Main IO (PeerStates IO SockAddr) x
-> (Socket -> IO a)
-> IO x
subscriptionWorker Snocket IO Socket SockAddr
snocket
Tracer IO (SubscriptionTrace SockAddr)
subscriptionTracer'
Tracer IO (WithAddr SockAddr ErrorPolicyTrace)
errorPolicyTracer
NetworkMutableState SockAddr
networkState
WorkerParams IO LocalAddresses SockAddr
workerParams
ErrorPolicies
spErrorPolicies
Main IO (PeerStates IO SockAddr) Void
forall (m :: * -> *) addr.
(MonadThrow (STM m), MonadSTM m) =>
Main m (PeerStates m addr) Void
mainTx
Socket -> IO a
k
where
workerParams :: WorkerParams IO LocalAddresses SockAddr
workerParams = WorkerParams {
wpLocalAddresses :: LocalAddresses SockAddr
wpLocalAddresses = LocalAddresses SockAddr
spLocalAddresses,
wpConnectionAttemptDelay :: SockAddr -> Maybe DiffTime
wpConnectionAttemptDelay = SockAddr -> Maybe DiffTime
spConnectionAttemptDelay,
wpSubscriptionTarget :: IO (SubscriptionTarget IO SockAddr)
wpSubscriptionTarget =
SubscriptionTarget IO SockAddr
-> IO (SubscriptionTarget IO SockAddr)
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (SubscriptionTarget IO SockAddr
-> IO (SubscriptionTarget IO SockAddr))
-> SubscriptionTarget IO SockAddr
-> IO (SubscriptionTarget IO SockAddr)
forall a b. (a -> b) -> a -> b
$ Tracer IO (SubscriptionTrace SockAddr)
-> StrictTVar IO (PeerStates IO SockAddr)
-> [SockAddr]
-> SubscriptionTarget IO SockAddr
forall (m :: * -> *) addr.
(MonadMonotonicTime m, MonadSTM m, Ord addr) =>
Tracer m (SubscriptionTrace addr)
-> StrictTVar m (PeerStates m addr)
-> [addr]
-> SubscriptionTarget m addr
ipSubscriptionTarget Tracer IO (SubscriptionTrace SockAddr)
subscriptionTracer' StrictTVar IO (PeerStates IO SockAddr)
nmsPeerStates
(IPSubscriptionTarget -> [SockAddr]
ispIps IPSubscriptionTarget
spSubscriptionTarget),
wpValency :: Int
wpValency = IPSubscriptionTarget -> Int
ispValency IPSubscriptionTarget
spSubscriptionTarget,
wpSelectAddress :: SockAddr -> LocalAddresses SockAddr -> Maybe SockAddr
wpSelectAddress = SockAddr -> LocalAddresses SockAddr -> Maybe SockAddr
selectSockAddr
}
subscriptionTracer' :: Tracer IO (SubscriptionTrace SockAddr)
subscriptionTracer' = (LocalAddresses SockAddr
-> [SockAddr]
-> SubscriptionTrace SockAddr
-> WithIPList (SubscriptionTrace SockAddr)
forall a.
LocalAddresses SockAddr -> [SockAddr] -> a -> WithIPList a
WithIPList LocalAddresses SockAddr
spLocalAddresses (IPSubscriptionTarget -> [SockAddr]
ispIps IPSubscriptionTarget
spSubscriptionTarget)
(SubscriptionTrace SockAddr
-> WithIPList (SubscriptionTrace SockAddr))
-> Tracer IO (WithIPList (SubscriptionTrace SockAddr))
-> Tracer IO (SubscriptionTrace SockAddr)
forall a' a. (a' -> a) -> Tracer IO a -> Tracer IO a'
forall (f :: * -> *) a' a.
Contravariant f =>
(a' -> a) -> f a -> f a'
`contramap` Tracer IO (WithIPList (SubscriptionTrace SockAddr))
subscriptionTracer)
selectSockAddr :: Socket.SockAddr
-> LocalAddresses Socket.SockAddr
-> Maybe Socket.SockAddr
selectSockAddr :: SockAddr -> LocalAddresses SockAddr -> Maybe SockAddr
selectSockAddr Socket.SockAddrInet{} (LocalAddresses (Just SockAddr
localAddr) Maybe SockAddr
_ Maybe SockAddr
_ ) = SockAddr -> Maybe SockAddr
forall a. a -> Maybe a
Just SockAddr
localAddr
selectSockAddr Socket.SockAddrInet6{} (LocalAddresses Maybe SockAddr
_ (Just SockAddr
localAddr) Maybe SockAddr
_ ) = SockAddr -> Maybe SockAddr
forall a. a -> Maybe a
Just SockAddr
localAddr
selectSockAddr Socket.SockAddrUnix{} (LocalAddresses Maybe SockAddr
_ Maybe SockAddr
_ (Just SockAddr
localAddr) ) = SockAddr -> Maybe SockAddr
forall a. a -> Maybe a
Just SockAddr
localAddr
selectSockAddr SockAddr
_ LocalAddresses SockAddr
_ = Maybe SockAddr
forall a. Maybe a
Nothing
ipSubscriptionTarget :: forall m addr.
( MonadMonotonicTime m
, MonadSTM m
, Ord addr
)
=> Tracer m (SubscriptionTrace addr)
-> StrictTVar m (PeerStates m addr)
-> [addr]
-> SubscriptionTarget m addr
ipSubscriptionTarget :: forall (m :: * -> *) addr.
(MonadMonotonicTime m, MonadSTM m, Ord addr) =>
Tracer m (SubscriptionTrace addr)
-> StrictTVar m (PeerStates m addr)
-> [addr]
-> SubscriptionTarget m addr
ipSubscriptionTarget Tracer m (SubscriptionTrace addr)
tr StrictTVar m (PeerStates m addr)
peerStatesVar [addr]
ips = [addr] -> SubscriptionTarget m addr
go [addr]
ips
where
go :: [addr]
-> SubscriptionTarget m addr
go :: [addr] -> SubscriptionTarget m addr
go [] = m (Maybe (addr, SubscriptionTarget m addr))
-> SubscriptionTarget m addr
forall (m :: * -> *) target.
m (Maybe (target, SubscriptionTarget m target))
-> SubscriptionTarget m target
SubscriptionTarget (m (Maybe (addr, SubscriptionTarget m addr))
-> SubscriptionTarget m addr)
-> m (Maybe (addr, SubscriptionTarget m addr))
-> SubscriptionTarget m addr
forall a b. (a -> b) -> a -> b
$ Maybe (addr, SubscriptionTarget m addr)
-> m (Maybe (addr, SubscriptionTarget m addr))
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Maybe (addr, SubscriptionTarget m addr)
forall a. Maybe a
Nothing
go (addr
a : [addr]
as) = m (Maybe (addr, SubscriptionTarget m addr))
-> SubscriptionTarget m addr
forall (m :: * -> *) target.
m (Maybe (target, SubscriptionTarget m target))
-> SubscriptionTarget m target
SubscriptionTarget (m (Maybe (addr, SubscriptionTarget m addr))
-> SubscriptionTarget m addr)
-> m (Maybe (addr, SubscriptionTarget m addr))
-> SubscriptionTarget m addr
forall a b. (a -> b) -> a -> b
$ do
b <- StrictTVar m (PeerStates m addr)
-> BeforeConnect m (PeerStates m addr) addr -> addr -> m Bool
forall (m :: * -> *) s addr.
(MonadMonotonicTime m, MonadSTM m) =>
StrictTVar m s -> BeforeConnect m s addr -> addr -> m Bool
runBeforeConnect StrictTVar m (PeerStates m addr)
peerStatesVar BeforeConnect m (PeerStates m addr) addr
forall (m :: * -> *) addr.
(MonadSTM m, Ord addr) =>
BeforeConnect m (PeerStates m addr) addr
beforeConnectTx addr
a
if b
then do
traceWith tr $ SubscriptionTraceTryConnectToPeer a
pure $ Just (a, go as)
else do
traceWith tr $ SubscriptionTraceSkippingPeer a
getSubscriptionTarget $ go as
socketStateChangeTx
:: Ord addr
=> SocketStateChange IO
(PeerStates IO addr)
addr
socketStateChangeTx :: forall addr.
Ord addr =>
SocketStateChange IO (PeerStates IO addr) addr
socketStateChangeTx (CreatedSocket addr
addr Async IO ()
thread) PeerStates IO addr
ps =
PeerStates IO addr -> STM (PeerStates IO addr)
forall a. a -> STM a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (addr -> Async IO () -> PeerStates IO addr -> PeerStates IO addr
forall (m :: * -> *) addr.
(Ord addr, Ord (Async m ())) =>
addr -> Async m () -> PeerStates m addr -> PeerStates m addr
registerConsumer addr
addr Async IO ()
thread PeerStates IO addr
ps)
socketStateChangeTx ClosedSocket{} ps :: PeerStates IO addr
ps@ThrowException{} =
PeerStates IO addr -> STM (PeerStates IO addr)
forall a. a -> STM a
forall (f :: * -> *) a. Applicative f => a -> f a
pure PeerStates IO addr
ps
socketStateChangeTx (ClosedSocket addr
addr Async IO ()
thread) PeerStates IO addr
ps =
PeerStates IO addr -> STM IO (PeerStates IO addr)
forall a. a -> STM IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (PeerStates IO addr -> STM IO (PeerStates IO addr))
-> PeerStates IO addr -> STM IO (PeerStates IO addr)
forall a b. (a -> b) -> a -> b
$ addr -> Async IO () -> PeerStates IO addr -> PeerStates IO addr
forall (m :: * -> *) addr.
(Ord addr, Ord (Async m ())) =>
addr -> Async m () -> PeerStates m addr -> PeerStates m addr
unregisterConsumer addr
addr Async IO ()
thread PeerStates IO addr
ps
mainTx :: ( MonadThrow (STM m)
, MonadSTM m
)
=> Main m (PeerStates m addr) Void
mainTx :: forall (m :: * -> *) addr.
(MonadThrow (STM m), MonadSTM m) =>
Main m (PeerStates m addr) Void
mainTx (ThrowException e
e) = e -> STM m Void
forall e a. Exception e => e -> STM m a
forall (m :: * -> *) e a. (MonadThrow m, Exception e) => e -> m a
throwIO e
e
mainTx PeerStates{} = STM m Void
forall a. STM m a
forall (m :: * -> *) a. MonadSTM m => STM m a
retry
subscriptionWorker
:: Snocket IO Socket.Socket Socket.SockAddr
-> Tracer IO (SubscriptionTrace Socket.SockAddr)
-> Tracer IO (WithAddr Socket.SockAddr ErrorPolicyTrace)
-> NetworkMutableState Socket.SockAddr
-> WorkerParams IO LocalAddresses Socket.SockAddr
-> ErrorPolicies
-> Main IO (PeerStates IO Socket.SockAddr) x
-> (Socket.Socket -> IO a)
-> IO x
subscriptionWorker :: forall x a.
Snocket IO Socket SockAddr
-> Tracer IO (SubscriptionTrace SockAddr)
-> Tracer IO (WithAddr SockAddr ErrorPolicyTrace)
-> NetworkMutableState SockAddr
-> WorkerParams IO LocalAddresses SockAddr
-> ErrorPolicies
-> Main IO (PeerStates IO SockAddr) x
-> (Socket -> IO a)
-> IO x
subscriptionWorker Snocket IO Socket SockAddr
snocket
Tracer IO (SubscriptionTrace SockAddr)
tracer
Tracer IO (WithAddr SockAddr ErrorPolicyTrace)
errorPolicyTracer
NetworkMutableState { ConnectionTable IO SockAddr
nmsConnectionTable :: ConnectionTable IO SockAddr
nmsConnectionTable :: forall addr. NetworkMutableState addr -> ConnectionTable IO addr
nmsConnectionTable, StrictTVar IO (PeerStates IO SockAddr)
nmsPeerStates :: forall addr.
NetworkMutableState addr -> StrictTVar IO (PeerStates IO addr)
nmsPeerStates :: StrictTVar IO (PeerStates IO SockAddr)
nmsPeerStates }
WorkerParams IO LocalAddresses SockAddr
workerParams
ErrorPolicies
errorPolicies
Main IO (PeerStates IO SockAddr) x
main Socket -> IO a
k =
Tracer IO (SubscriptionTrace SockAddr)
-> Tracer IO (WithAddr SockAddr ErrorPolicyTrace)
-> ConnectionTable IO SockAddr
-> StrictTVar IO (PeerStates IO SockAddr)
-> Snocket IO Socket SockAddr
-> (Socket -> SockAddr -> IO ())
-> WorkerCallbacks IO (PeerStates IO SockAddr) SockAddr a x
-> WorkerParams IO LocalAddresses SockAddr
-> (Socket -> IO a)
-> IO x
forall s sock (localAddrs :: * -> *) addr a x.
Ord addr =>
Tracer IO (SubscriptionTrace addr)
-> Tracer IO (WithAddr addr ErrorPolicyTrace)
-> ConnectionTable IO addr
-> StateVar IO s
-> Snocket IO sock addr
-> (sock -> addr -> IO ())
-> WorkerCallbacks IO s addr a x
-> WorkerParams IO localAddrs addr
-> (sock -> IO a)
-> IO x
worker Tracer IO (SubscriptionTrace SockAddr)
tracer
Tracer IO (WithAddr SockAddr ErrorPolicyTrace)
errorPolicyTracer
ConnectionTable IO SockAddr
nmsConnectionTable
StrictTVar IO (PeerStates IO SockAddr)
nmsPeerStates
Snocket IO Socket SockAddr
snocket
(((Maybe SockAddr -> IO ())
-> (SockAddr -> Maybe SockAddr) -> SockAddr -> IO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. SockAddr -> Maybe SockAddr
forall a. a -> Maybe a
Just) ((Maybe SockAddr -> IO ()) -> SockAddr -> IO ())
-> (Socket -> Maybe SockAddr -> IO ())
-> Socket
-> SockAddr
-> IO ()
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Socket -> Maybe SockAddr -> IO ()
configureSocket)
WorkerCallbacks
{ wcSocketStateChangeTx :: SocketStateChange IO (PeerStates IO SockAddr) SockAddr
wcSocketStateChangeTx = SocketStateChange IO (PeerStates IO SockAddr) SockAddr
forall addr.
Ord addr =>
SocketStateChange IO (PeerStates IO addr) addr
socketStateChangeTx
, wcCompleteApplicationTx :: CompleteApplication IO (PeerStates IO SockAddr) SockAddr a
wcCompleteApplicationTx = ErrorPolicies
-> CompleteApplication IO (PeerStates IO SockAddr) SockAddr a
forall (m :: * -> *) addr a.
(MonadAsync m, Ord addr, Ord (Async m ())) =>
ErrorPolicies -> CompleteApplication m (PeerStates m addr) addr a
completeApplicationTx ErrorPolicies
errorPolicies
, wcMainTx :: Main IO (PeerStates IO SockAddr) x
wcMainTx = Main IO (PeerStates IO SockAddr) x
main
}
WorkerParams IO LocalAddresses SockAddr
workerParams
Socket -> IO a
k
data WithIPList a = WithIPList {
forall a. WithIPList a -> LocalAddresses SockAddr
wilSrc :: (LocalAddresses Socket.SockAddr)
, forall a. WithIPList a -> [SockAddr]
wilDsts :: [Socket.SockAddr]
, forall a. WithIPList a -> a
wilEvent :: a
}
instance (Show a) => Show (WithIPList a) where
show :: WithIPList a -> String
show (WithIPList (LocalAddresses Maybe SockAddr
Nothing (Just SockAddr
ipv6) Maybe SockAddr
Nothing) [SockAddr]
wilDsts a
wilEvent) =
String -> String -> String -> ShowS
forall r. PrintfType r => String -> r
printf String
"IPs: %s %s %s" (SockAddr -> String
forall a. Show a => a -> String
show SockAddr
ipv6) ([SockAddr] -> String
forall a. Show a => a -> String
show [SockAddr]
wilDsts) (a -> String
forall a. Show a => a -> String
show a
wilEvent)
show (WithIPList (LocalAddresses (Just SockAddr
ipv4) Maybe SockAddr
Nothing Maybe SockAddr
Nothing) [SockAddr]
wilDsts a
wilEvent) =
String -> String -> String -> ShowS
forall r. PrintfType r => String -> r
printf String
"IPs: %s %s %s" (SockAddr -> String
forall a. Show a => a -> String
show SockAddr
ipv4) ([SockAddr] -> String
forall a. Show a => a -> String
show [SockAddr]
wilDsts) (a -> String
forall a. Show a => a -> String
show a
wilEvent)
show (WithIPList (LocalAddresses Maybe SockAddr
Nothing Maybe SockAddr
Nothing (Just SockAddr
unix)) [SockAddr]
wilDsts a
wilEvent) =
String -> String -> String -> ShowS
forall r. PrintfType r => String -> r
printf String
"IPs: %s %s %s" (SockAddr -> String
forall a. Show a => a -> String
show SockAddr
unix) ([SockAddr] -> String
forall a. Show a => a -> String
show [SockAddr]
wilDsts) (a -> String
forall a. Show a => a -> String
show a
wilEvent)
show (WithIPList (LocalAddresses (Just SockAddr
ipv4) (Just SockAddr
ipv6) Maybe SockAddr
Nothing) [SockAddr]
wilDsts a
wilEvent) =
String -> String -> String -> String -> ShowS
forall r. PrintfType r => String -> r
printf String
"IPs: %s %s %s %s" (SockAddr -> String
forall a. Show a => a -> String
show SockAddr
ipv4) (SockAddr -> String
forall a. Show a => a -> String
show SockAddr
ipv6)
([SockAddr] -> String
forall a. Show a => a -> String
show [SockAddr]
wilDsts) (a -> String
forall a. Show a => a -> String
show a
wilEvent)
show WithIPList {LocalAddresses SockAddr
wilSrc :: forall a. WithIPList a -> LocalAddresses SockAddr
wilSrc :: LocalAddresses SockAddr
wilSrc, [SockAddr]
wilDsts :: forall a. WithIPList a -> [SockAddr]
wilDsts :: [SockAddr]
wilDsts, a
wilEvent :: forall a. WithIPList a -> a
wilEvent :: a
wilEvent} =
String -> String -> String -> ShowS
forall r. PrintfType r => String -> r
printf String
"IPs: %s %s %s" (LocalAddresses SockAddr -> String
forall a. Show a => a -> String
show LocalAddresses SockAddr
wilSrc) ([SockAddr] -> String
forall a. Show a => a -> String
show [SockAddr]
wilDsts) (a -> String
forall a. Show a => a -> String
show a
wilEvent)