{-# LANGUAGE DerivingStrategies         #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE LambdaCase                 #-}
{-# LANGUAGE NamedFieldPuns             #-}
{-# LANGUAGE ScopedTypeVariables        #-}
{-# LANGUAGE TypeApplications           #-}
-- Undecidable instances are need for 'Show' instance of 'ConnectionState'.
{-# LANGUAGE QuantifiedConstraints      #-}

module Ouroboros.Network.ConnectionManager.State
  ( -- * ConnectionManagerState API
    ConnectionManagerState
  , module ConnMap
    -- ** Monadic API
  , readConnectionStates
  , readAbstractStateMap
    -- * MutableConnState
  , MutableConnState (..)
  , ConnStateIdSupply
  , ConnStateId (..)
  , ConnectionTransitionTrace
  , newConnStateIdSupply
  , newMutableConnState
    -- * ConnectionState
  , ConnectionState (..)
  , abstractState
  , connectionTerminated
  ) where

import Control.Concurrent.Class.MonadSTM.Strict
import Control.Monad.Class.MonadAsync
import Data.Function (on)
import Data.Proxy (Proxy (..))
import Data.Typeable (Typeable)
import Prelude hiding (lookup)

import Ouroboros.Network.ConnectionId
import Ouroboros.Network.ConnectionManager.ConnMap as ConnMap
import Ouroboros.Network.ConnectionManager.Types

import Test.Ouroboros.Network.Utils (WithName (..))

-- | 'ConnectionManager' state: for each peer we keep a 'ConnectionState' in
-- a mutable variable, which reduces congestion on the 'TMVar' which keeps
-- 'ConnectionManagerState'.
--
type ConnectionManagerState peerAddr handle handleError version m =
    ConnMap peerAddr (MutableConnState peerAddr handle handleError version m)


readConnectionStates
  :: MonadSTM m
  => ConnectionManagerState peerAddr handle handleError version m
  -> STM m (ConnMap peerAddr (ConnectionState peerAddr handle handleError version m))
readConnectionStates :: forall (m :: * -> *) peerAddr handle handleError version.
MonadSTM m =>
ConnectionManagerState peerAddr handle handleError version m
-> STM
     m
     (ConnMap
        peerAddr (ConnectionState peerAddr handle handleError version m))
readConnectionStates = (MutableConnState peerAddr handle handleError version m
 -> STM m (ConnectionState peerAddr handle handleError version m))
-> ConnMap
     peerAddr (MutableConnState peerAddr handle handleError version m)
-> STM
     m
     (ConnMap
        peerAddr (ConnectionState peerAddr handle handleError version m))
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
forall (f :: * -> *) a b.
Applicative f =>
(a -> f b) -> ConnMap peerAddr a -> f (ConnMap peerAddr b)
traverse (StrictTVar
  m (ConnectionState peerAddr handle handleError version m)
-> STM m (ConnectionState peerAddr handle handleError version m)
forall (m :: * -> *) a. MonadSTM m => StrictTVar m a -> STM m a
readTVar (StrictTVar
   m (ConnectionState peerAddr handle handleError version m)
 -> STM m (ConnectionState peerAddr handle handleError version m))
-> (MutableConnState peerAddr handle handleError version m
    -> StrictTVar
         m (ConnectionState peerAddr handle handleError version m))
-> MutableConnState peerAddr handle handleError version m
-> STM m (ConnectionState peerAddr handle handleError version m)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. MutableConnState peerAddr handle handleError version m
-> StrictTVar
     m (ConnectionState peerAddr handle handleError version m)
forall peerAddr handle handleError version (m :: * -> *).
MutableConnState peerAddr handle handleError version m
-> StrictTVar
     m (ConnectionState peerAddr handle handleError version m)
connVar)


readAbstractStateMap
  :: MonadSTM m
  => ConnectionManagerState peerAddr handle handleError version m
  -> STM m (ConnMap peerAddr AbstractState)
readAbstractStateMap :: forall (m :: * -> *) peerAddr handle handleError version.
MonadSTM m =>
ConnectionManagerState peerAddr handle handleError version m
-> STM m (ConnMap peerAddr AbstractState)
readAbstractStateMap = (MutableConnState peerAddr handle handleError version m
 -> STM m AbstractState)
-> ConnMap
     peerAddr (MutableConnState peerAddr handle handleError version m)
-> STM m (ConnMap peerAddr AbstractState)
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
forall (f :: * -> *) a b.
Applicative f =>
(a -> f b) -> ConnMap peerAddr a -> f (ConnMap peerAddr b)
traverse ((ConnectionState peerAddr handle handleError version m
 -> AbstractState)
-> STM m (ConnectionState peerAddr handle handleError version m)
-> STM m AbstractState
forall a b. (a -> b) -> STM m a -> STM m b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (MaybeUnknown
  (ConnectionState peerAddr handle handleError version m)
-> AbstractState
forall muxMode peerAddr m a (b :: * -> *).
MaybeUnknown (ConnectionState muxMode peerAddr m a b)
-> AbstractState
abstractState (MaybeUnknown
   (ConnectionState peerAddr handle handleError version m)
 -> AbstractState)
-> (ConnectionState peerAddr handle handleError version m
    -> MaybeUnknown
         (ConnectionState peerAddr handle handleError version m))
-> ConnectionState peerAddr handle handleError version m
-> AbstractState
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ConnectionState peerAddr handle handleError version m
-> MaybeUnknown
     (ConnectionState peerAddr handle handleError version m)
forall state. state -> MaybeUnknown state
Known) (STM m (ConnectionState peerAddr handle handleError version m)
 -> STM m AbstractState)
-> (MutableConnState peerAddr handle handleError version m
    -> STM m (ConnectionState peerAddr handle handleError version m))
-> MutableConnState peerAddr handle handleError version m
-> STM m AbstractState
forall b c a. (b -> c) -> (a -> b) -> a -> c
. StrictTVar
  m (ConnectionState peerAddr handle handleError version m)
-> STM m (ConnectionState peerAddr handle handleError version m)
forall (m :: * -> *) a. MonadSTM m => StrictTVar m a -> STM m a
readTVar (StrictTVar
   m (ConnectionState peerAddr handle handleError version m)
 -> STM m (ConnectionState peerAddr handle handleError version m))
-> (MutableConnState peerAddr handle handleError version m
    -> StrictTVar
         m (ConnectionState peerAddr handle handleError version m))
-> MutableConnState peerAddr handle handleError version m
-> STM m (ConnectionState peerAddr handle handleError version m)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. MutableConnState peerAddr handle handleError version m
-> StrictTVar
     m (ConnectionState peerAddr handle handleError version m)
forall peerAddr handle handleError version (m :: * -> *).
MutableConnState peerAddr handle handleError version m
-> StrictTVar
     m (ConnectionState peerAddr handle handleError version m)
connVar)

-- | A unique identifier of a connection.
--
-- It's used even when we don't yet know `ConnectionId`.
--
newtype ConnStateId = ConnStateId Int
  deriving stock (ConnStateId -> ConnStateId -> Bool
(ConnStateId -> ConnStateId -> Bool)
-> (ConnStateId -> ConnStateId -> Bool) -> Eq ConnStateId
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: ConnStateId -> ConnStateId -> Bool
== :: ConnStateId -> ConnStateId -> Bool
$c/= :: ConnStateId -> ConnStateId -> Bool
/= :: ConnStateId -> ConnStateId -> Bool
Eq, Eq ConnStateId
Eq ConnStateId =>
(ConnStateId -> ConnStateId -> Ordering)
-> (ConnStateId -> ConnStateId -> Bool)
-> (ConnStateId -> ConnStateId -> Bool)
-> (ConnStateId -> ConnStateId -> Bool)
-> (ConnStateId -> ConnStateId -> Bool)
-> (ConnStateId -> ConnStateId -> ConnStateId)
-> (ConnStateId -> ConnStateId -> ConnStateId)
-> Ord ConnStateId
ConnStateId -> ConnStateId -> Bool
ConnStateId -> ConnStateId -> Ordering
ConnStateId -> ConnStateId -> ConnStateId
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
$ccompare :: ConnStateId -> ConnStateId -> Ordering
compare :: ConnStateId -> ConnStateId -> Ordering
$c< :: ConnStateId -> ConnStateId -> Bool
< :: ConnStateId -> ConnStateId -> Bool
$c<= :: ConnStateId -> ConnStateId -> Bool
<= :: ConnStateId -> ConnStateId -> Bool
$c> :: ConnStateId -> ConnStateId -> Bool
> :: ConnStateId -> ConnStateId -> Bool
$c>= :: ConnStateId -> ConnStateId -> Bool
>= :: ConnStateId -> ConnStateId -> Bool
$cmax :: ConnStateId -> ConnStateId -> ConnStateId
max :: ConnStateId -> ConnStateId -> ConnStateId
$cmin :: ConnStateId -> ConnStateId -> ConnStateId
min :: ConnStateId -> ConnStateId -> ConnStateId
Ord, Int -> ConnStateId -> ShowS
[ConnStateId] -> ShowS
ConnStateId -> String
(Int -> ConnStateId -> ShowS)
-> (ConnStateId -> String)
-> ([ConnStateId] -> ShowS)
-> Show ConnStateId
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> ConnStateId -> ShowS
showsPrec :: Int -> ConnStateId -> ShowS
$cshow :: ConnStateId -> String
show :: ConnStateId -> String
$cshowList :: [ConnStateId] -> ShowS
showList :: [ConnStateId] -> ShowS
Show)
  deriving newtype Int -> ConnStateId
ConnStateId -> Int
ConnStateId -> [ConnStateId]
ConnStateId -> ConnStateId
ConnStateId -> ConnStateId -> [ConnStateId]
ConnStateId -> ConnStateId -> ConnStateId -> [ConnStateId]
(ConnStateId -> ConnStateId)
-> (ConnStateId -> ConnStateId)
-> (Int -> ConnStateId)
-> (ConnStateId -> Int)
-> (ConnStateId -> [ConnStateId])
-> (ConnStateId -> ConnStateId -> [ConnStateId])
-> (ConnStateId -> ConnStateId -> [ConnStateId])
-> (ConnStateId -> ConnStateId -> ConnStateId -> [ConnStateId])
-> Enum ConnStateId
forall a.
(a -> a)
-> (a -> a)
-> (Int -> a)
-> (a -> Int)
-> (a -> [a])
-> (a -> a -> [a])
-> (a -> a -> [a])
-> (a -> a -> a -> [a])
-> Enum a
$csucc :: ConnStateId -> ConnStateId
succ :: ConnStateId -> ConnStateId
$cpred :: ConnStateId -> ConnStateId
pred :: ConnStateId -> ConnStateId
$ctoEnum :: Int -> ConnStateId
toEnum :: Int -> ConnStateId
$cfromEnum :: ConnStateId -> Int
fromEnum :: ConnStateId -> Int
$cenumFrom :: ConnStateId -> [ConnStateId]
enumFrom :: ConnStateId -> [ConnStateId]
$cenumFromThen :: ConnStateId -> ConnStateId -> [ConnStateId]
enumFromThen :: ConnStateId -> ConnStateId -> [ConnStateId]
$cenumFromTo :: ConnStateId -> ConnStateId -> [ConnStateId]
enumFromTo :: ConnStateId -> ConnStateId -> [ConnStateId]
$cenumFromThenTo :: ConnStateId -> ConnStateId -> ConnStateId -> [ConnStateId]
enumFromThenTo :: ConnStateId -> ConnStateId -> ConnStateId -> [ConnStateId]
Enum

-- | 'MutableConnState', which supplies a unique identifier.
--
-- TODO: We can get away without id, by tracking connections in
-- `TerminatingState` using a separate priority search queue.
--
data MutableConnState peerAddr handle handleError version m = MutableConnState {
    -- | A unique identifier
    --
    forall peerAddr handle handleError version (m :: * -> *).
MutableConnState peerAddr handle handleError version m
-> ConnStateId
connStateId  :: !ConnStateId

  , -- | Mutable state
    --
    forall peerAddr handle handleError version (m :: * -> *).
MutableConnState peerAddr handle handleError version m
-> StrictTVar
     m (ConnectionState peerAddr handle handleError version m)
connVar      :: !(StrictTVar m (ConnectionState peerAddr handle handleError
                                                    version m))
  }


instance Eq (MutableConnState peerAddr handle handleError version m) where
    == :: MutableConnState peerAddr handle handleError version m
-> MutableConnState peerAddr handle handleError version m -> Bool
(==) =  ConnStateId -> ConnStateId -> Bool
forall a. Eq a => a -> a -> Bool
(==) (ConnStateId -> ConnStateId -> Bool)
-> (MutableConnState peerAddr handle handleError version m
    -> ConnStateId)
-> MutableConnState peerAddr handle handleError version m
-> MutableConnState peerAddr handle handleError version m
-> Bool
forall b c a. (b -> b -> c) -> (a -> b) -> a -> a -> c
`on` MutableConnState peerAddr handle handleError version m
-> ConnStateId
forall peerAddr handle handleError version (m :: * -> *).
MutableConnState peerAddr handle handleError version m
-> ConnStateId
connStateId


-- | A supply of fresh id's.
--
-- We use a fresh ids for 'MutableConnState'.
--
newtype ConnStateIdSupply m = ConnStateIdSupply { forall (m :: * -> *). ConnStateIdSupply m -> STM m ConnStateId
getConnStateId :: STM m ConnStateId }


-- | Create a 'FreshIdSupply' inside an 'STM' monad.
--
newConnStateIdSupply :: forall m. MonadSTM m
                     => Proxy m
                     -> STM m (ConnStateIdSupply m)
newConnStateIdSupply :: forall (m :: * -> *).
MonadSTM m =>
Proxy m -> STM m (ConnStateIdSupply m)
newConnStateIdSupply Proxy m
_ = do
    (v :: StrictTVar m ConnStateId) <- ConnStateId -> STM m (StrictTVar m ConnStateId)
forall (m :: * -> *) a. MonadSTM m => a -> STM m (StrictTVar m a)
newTVar (Int -> ConnStateId
ConnStateId Int
0)
    let getConnStateId :: STM m ConnStateId
        getConnStateId = do
          c <- StrictTVar m ConnStateId -> STM m ConnStateId
forall (m :: * -> *) a. MonadSTM m => StrictTVar m a -> STM m a
readTVar StrictTVar m ConnStateId
v
          writeTVar v (succ c)
          return c
    return $ ConnStateIdSupply { getConnStateId }


type ConnectionTransitionTrace peerAddr = WithName peerAddr (AbstractTransitionTrace ConnStateId)


newMutableConnState :: forall peerAddr handle handleError version m.
                      ( MonadTraceSTM m
                      , Typeable peerAddr
                      )
                    => peerAddr
                    -> ConnStateIdSupply m
                    -> ConnectionState peerAddr handle handleError
                                       version m
                    -> STM m (MutableConnState peerAddr handle handleError
                                               version m)
newMutableConnState :: forall peerAddr handle handleError version (m :: * -> *).
(MonadTraceSTM m, Typeable peerAddr) =>
peerAddr
-> ConnStateIdSupply m
-> ConnectionState peerAddr handle handleError version m
-> STM m (MutableConnState peerAddr handle handleError version m)
newMutableConnState peerAddr
peerAddr ConnStateIdSupply m
freshIdSupply ConnectionState peerAddr handle handleError version m
connState = do
      connStateId <- ConnStateIdSupply m -> STM m ConnStateId
forall (m :: * -> *). ConnStateIdSupply m -> STM m ConnStateId
getConnStateId ConnStateIdSupply m
freshIdSupply
      connVar <- newTVar connState
      -- This tracing is a no op in IO.
      --
      -- We need this for IOSimPOR testing of connection manager state
      -- transition tests. It can happen that the transitions happen
      -- correctly but IOSimPOR reorders the threads that log the transitions.
      -- This is a false positive and we don't want that to happen.
      --
      -- The simplest way to do so is to leverage the `traceTVar` IOSim
      -- capabilities. These trace messages won't be reordered by IOSimPOR
      -- since these happen atomically in STM.
      --
      traceTVar
        (Proxy @m) connVar
        (\Maybe (ConnectionState peerAddr handle handleError version m)
mbPrev ConnectionState peerAddr handle handleError version m
curr ->
          let currAbs :: AbstractState
currAbs = MaybeUnknown
  (ConnectionState peerAddr handle handleError version m)
-> AbstractState
forall muxMode peerAddr m a (b :: * -> *).
MaybeUnknown (ConnectionState muxMode peerAddr m a b)
-> AbstractState
abstractState (ConnectionState peerAddr handle handleError version m
-> MaybeUnknown
     (ConnectionState peerAddr handle handleError version m)
forall state. state -> MaybeUnknown state
Known ConnectionState peerAddr handle handleError version m
curr)
           in case Maybe (ConnectionState peerAddr handle handleError version m)
mbPrev of
                Just ConnectionState peerAddr handle handleError version m
prev |
                    let prevAbs :: AbstractState
prevAbs = MaybeUnknown
  (ConnectionState peerAddr handle handleError version m)
-> AbstractState
forall muxMode peerAddr m a (b :: * -> *).
MaybeUnknown (ConnectionState muxMode peerAddr m a b)
-> AbstractState
abstractState (ConnectionState peerAddr handle handleError version m
-> MaybeUnknown
     (ConnectionState peerAddr handle handleError version m)
forall state. state -> MaybeUnknown state
Known ConnectionState peerAddr handle handleError version m
prev)
                  , AbstractState
prevAbs AbstractState -> AbstractState -> Bool
forall a. Eq a => a -> a -> Bool
/= AbstractState
currAbs -> TraceValue -> InspectMonad m TraceValue
forall a. a -> InspectMonad m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure
                                       (TraceValue -> InspectMonad m TraceValue)
-> TraceValue -> InspectMonad m TraceValue
forall a b. (a -> b) -> a -> b
$ ConnectionTransitionTrace peerAddr -> TraceValue
forall tr. Typeable tr => tr -> TraceValue
TraceDynamic
                                       ( peerAddr
-> AbstractTransitionTrace ConnStateId
-> ConnectionTransitionTrace peerAddr
forall name event. name -> event -> WithName name event
WithName peerAddr
peerAddr
                                                  (ConnStateId
-> Transition' AbstractState -> AbstractTransitionTrace ConnStateId
forall id state.
id -> Transition' state -> TransitionTrace' id state
TransitionTrace ConnStateId
connStateId (Transition' AbstractState -> AbstractTransitionTrace ConnStateId)
-> Transition' AbstractState -> AbstractTransitionTrace ConnStateId
forall a b. (a -> b) -> a -> b
$ AbstractState -> AbstractState -> Transition' AbstractState
mkAbsTransition AbstractState
prevAbs AbstractState
currAbs)
                                       :: ConnectionTransitionTrace peerAddr)
                Maybe (ConnectionState peerAddr handle handleError version m)
Nothing                -> TraceValue -> InspectMonad m TraceValue
forall a. a -> InspectMonad m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure
                                       (TraceValue -> InspectMonad m TraceValue)
-> TraceValue -> InspectMonad m TraceValue
forall a b. (a -> b) -> a -> b
$ ConnectionTransitionTrace peerAddr -> TraceValue
forall tr. Typeable tr => tr -> TraceValue
TraceDynamic
                                       ( peerAddr
-> AbstractTransitionTrace ConnStateId
-> ConnectionTransitionTrace peerAddr
forall name event. name -> event -> WithName name event
WithName peerAddr
peerAddr
                                       (AbstractTransitionTrace ConnStateId
 -> ConnectionTransitionTrace peerAddr)
-> AbstractTransitionTrace ConnStateId
-> ConnectionTransitionTrace peerAddr
forall a b. (a -> b) -> a -> b
$ ConnStateId
-> Transition' AbstractState -> AbstractTransitionTrace ConnStateId
forall id state.
id -> Transition' state -> TransitionTrace' id state
TransitionTrace ConnStateId
connStateId
                                       (Transition' AbstractState -> AbstractTransitionTrace ConnStateId)
-> Transition' AbstractState -> AbstractTransitionTrace ConnStateId
forall a b. (a -> b) -> a -> b
$ AbstractState -> AbstractState -> Transition' AbstractState
mkAbsTransition AbstractState
TerminatedSt
                                                         AbstractState
currAbs
                                       :: ConnectionTransitionTrace peerAddr)
                Maybe (ConnectionState peerAddr handle handleError version m)
_                      -> TraceValue -> InspectMonad m TraceValue
forall a. a -> InspectMonad m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure TraceValue
DontTrace
        )
      return $ MutableConnState { connStateId, connVar }

abstractState :: MaybeUnknown (ConnectionState muxMode peerAddr m a b)
              -> AbstractState
abstractState :: forall muxMode peerAddr m a (b :: * -> *).
MaybeUnknown (ConnectionState muxMode peerAddr m a b)
-> AbstractState
abstractState = \case
    MaybeUnknown (ConnectionState muxMode peerAddr m a b)
Unknown  -> AbstractState
UnknownConnectionSt
    Race ConnectionState muxMode peerAddr m a b
s'  -> ConnectionState muxMode peerAddr m a b -> AbstractState
forall muxMode peerAddr m a (b :: * -> *).
ConnectionState muxMode peerAddr m a b -> AbstractState
go ConnectionState muxMode peerAddr m a b
s'
    Known ConnectionState muxMode peerAddr m a b
s' -> ConnectionState muxMode peerAddr m a b -> AbstractState
forall muxMode peerAddr m a (b :: * -> *).
ConnectionState muxMode peerAddr m a b -> AbstractState
go ConnectionState muxMode peerAddr m a b
s'
  where
    go :: ConnectionState muxMode peerAddr m a b -> AbstractState
    go :: forall muxMode peerAddr m a (b :: * -> *).
ConnectionState muxMode peerAddr m a b -> AbstractState
go ReservedOutboundState {}       = AbstractState
ReservedOutboundSt
    go (UnnegotiatedState Provenance
pr ConnectionId muxMode
_ Async b ()
_)     = Provenance -> AbstractState
UnnegotiatedSt Provenance
pr
    go OutboundUniState {}            = AbstractState
OutboundUniSt
    go (OutboundDupState    ConnectionId muxMode
_ Async b ()
_ peerAddr
_ TimeoutExpired
te) = TimeoutExpired -> AbstractState
OutboundDupSt TimeoutExpired
te
    go (OutboundIdleState ConnectionId muxMode
_ Async b ()
_ peerAddr
_ DataFlow
df)   = DataFlow -> AbstractState
OutboundIdleSt DataFlow
df
    go (InboundIdleState ConnectionId muxMode
_ Async b ()
_ peerAddr
_ DataFlow
df)    = DataFlow -> AbstractState
InboundIdleSt DataFlow
df
    go (InboundState     ConnectionId muxMode
_ Async b ()
_ peerAddr
_ DataFlow
df)    = DataFlow -> AbstractState
InboundSt DataFlow
df
    go DuplexState {}                 = AbstractState
DuplexSt
    go TerminatingState {}            = AbstractState
TerminatingSt
    go TerminatedState {}             = AbstractState
TerminatedSt


-- | State of a connection.
--
data ConnectionState peerAddr handle handleError version m =
    -- | Each outbound connections starts in this state.
    ReservedOutboundState

    -- | Each inbound connection starts in this state, outbound connection
    -- reach this state once `connect` call returns.
    --
    -- note: the async handle is lazy, because it's passed with 'mfix'.
  | UnnegotiatedState   !Provenance
                        !(ConnectionId peerAddr)
                         (Async m ())

    -- | @OutboundState Unidirectional@ state.
  | OutboundUniState    !(ConnectionId peerAddr) !(Async m ()) !handle

    -- | Either @OutboundState Duplex@ or @OutboundState^\tau Duplex@.
  | OutboundDupState    !(ConnectionId peerAddr) !(Async m ()) !handle !TimeoutExpired

    -- | Before connection is reset it is put in 'OutboundIdleState' for the
    -- duration of 'outboundIdleTimeout'.
    --
  | OutboundIdleState   !(ConnectionId peerAddr) !(Async m ()) !handle !DataFlow
  | InboundIdleState    !(ConnectionId peerAddr) !(Async m ()) !handle !DataFlow
  | InboundState        !(ConnectionId peerAddr) !(Async m ()) !handle !DataFlow
  | DuplexState         !(ConnectionId peerAddr) !(Async m ()) !handle
  | TerminatingState    !(ConnectionId peerAddr) !(Async m ()) !(Maybe handleError)
  | TerminatedState                              !(Maybe handleError)


instance ( Show peerAddr
         -- , Show handleError
         , MonadAsync m
         )
      => Show (ConnectionState peerAddr handle handleError version m) where
    show :: ConnectionState peerAddr handle handleError version m -> String
show ConnectionState peerAddr handle handleError version m
ReservedOutboundState = String
"ReservedOutboundState"
    show (UnnegotiatedState Provenance
pr ConnectionId peerAddr
connId Async m ()
connThread) =
      [String] -> String
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat [String
"UnnegotiatedState "
             , Provenance -> String
forall a. Show a => a -> String
show Provenance
pr
             , String
" "
             , ConnectionId peerAddr -> String
forall a. Show a => a -> String
show ConnectionId peerAddr
connId
             , String
" "
             , ThreadId m -> String
forall a. Show a => a -> String
show (Async m () -> ThreadId m
forall a. Async m a -> ThreadId m
forall (m :: * -> *) a. MonadAsync m => Async m a -> ThreadId m
asyncThreadId Async m ()
connThread)
             ]
    show (OutboundUniState ConnectionId peerAddr
connId Async m ()
connThread handle
_handle) =
      [String] -> String
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat [ String
"OutboundState Unidirectional "
             , ConnectionId peerAddr -> String
forall a. Show a => a -> String
show ConnectionId peerAddr
connId
             , String
" "
             , ThreadId m -> String
forall a. Show a => a -> String
show (Async m () -> ThreadId m
forall a. Async m a -> ThreadId m
forall (m :: * -> *) a. MonadAsync m => Async m a -> ThreadId m
asyncThreadId Async m ()
connThread)
             ]
    show (OutboundDupState ConnectionId peerAddr
connId Async m ()
connThread handle
_handle TimeoutExpired
expired) =
      [String] -> String
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat [ String
"OutboundState "
             , ConnectionId peerAddr -> String
forall a. Show a => a -> String
show ConnectionId peerAddr
connId
             , String
" "
             , ThreadId m -> String
forall a. Show a => a -> String
show (Async m () -> ThreadId m
forall a. Async m a -> ThreadId m
forall (m :: * -> *) a. MonadAsync m => Async m a -> ThreadId m
asyncThreadId Async m ()
connThread)
             , String
" "
             , TimeoutExpired -> String
forall a. Show a => a -> String
show TimeoutExpired
expired
             ]
    show (OutboundIdleState ConnectionId peerAddr
connId Async m ()
connThread handle
_handle DataFlow
df) =
      [String] -> String
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat [ String
"OutboundIdleState "
             , ConnectionId peerAddr -> String
forall a. Show a => a -> String
show ConnectionId peerAddr
connId
             , String
" "
             , ThreadId m -> String
forall a. Show a => a -> String
show (Async m () -> ThreadId m
forall a. Async m a -> ThreadId m
forall (m :: * -> *) a. MonadAsync m => Async m a -> ThreadId m
asyncThreadId Async m ()
connThread)
             , String
" "
             , DataFlow -> String
forall a. Show a => a -> String
show DataFlow
df
             ]
    show (InboundIdleState ConnectionId peerAddr
connId Async m ()
connThread handle
_handle DataFlow
df) =
      [String] -> String
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat [ String
"InboundIdleState "
             , ConnectionId peerAddr -> String
forall a. Show a => a -> String
show ConnectionId peerAddr
connId
             , String
" "
             , ThreadId m -> String
forall a. Show a => a -> String
show (Async m () -> ThreadId m
forall a. Async m a -> ThreadId m
forall (m :: * -> *) a. MonadAsync m => Async m a -> ThreadId m
asyncThreadId Async m ()
connThread)
             , String
" "
             , DataFlow -> String
forall a. Show a => a -> String
show DataFlow
df
             ]
    show (InboundState  ConnectionId peerAddr
connId Async m ()
connThread handle
_handle DataFlow
df) =
      [String] -> String
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat [ String
"InboundState "
             , ConnectionId peerAddr -> String
forall a. Show a => a -> String
show ConnectionId peerAddr
connId
             , String
" "
             , ThreadId m -> String
forall a. Show a => a -> String
show (Async m () -> ThreadId m
forall a. Async m a -> ThreadId m
forall (m :: * -> *) a. MonadAsync m => Async m a -> ThreadId m
asyncThreadId Async m ()
connThread)
             , String
" "
             , DataFlow -> String
forall a. Show a => a -> String
show DataFlow
df
             ]
    show (DuplexState   ConnectionId peerAddr
connId Async m ()
connThread handle
_handle) =
      [String] -> String
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat [ String
"DuplexState "
             , ConnectionId peerAddr -> String
forall a. Show a => a -> String
show ConnectionId peerAddr
connId
             , String
" "
             , ThreadId m -> String
forall a. Show a => a -> String
show (Async m () -> ThreadId m
forall a. Async m a -> ThreadId m
forall (m :: * -> *) a. MonadAsync m => Async m a -> ThreadId m
asyncThreadId Async m ()
connThread)
             ]
    show (TerminatingState ConnectionId peerAddr
connId Async m ()
connThread Maybe handleError
_handleError) =
      [String] -> String
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat ([ String
"TerminatingState "
              , ConnectionId peerAddr -> String
forall a. Show a => a -> String
show ConnectionId peerAddr
connId
              , String
" "
              , ThreadId m -> String
forall a. Show a => a -> String
show (Async m () -> ThreadId m
forall a. Async m a -> ThreadId m
forall (m :: * -> *) a. MonadAsync m => Async m a -> ThreadId m
asyncThreadId Async m ()
connThread)
              ]
              )-- ++ maybeToList ((' ' :) . show <$> handleError))
    show (TerminatedState Maybe handleError
_handleError) =
      [String] -> String
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat ([String
"TerminatedState"]
              )-- ++ maybeToList ((' ' :) . show <$> handleError))


-- | Return 'True' for states in which the connection was already closed.
--
connectionTerminated :: ConnectionState peerAddr handle handleError version m
                     -> Bool
connectionTerminated :: forall peerAddr handle handleError version (m :: * -> *).
ConnectionState peerAddr handle handleError version m -> Bool
connectionTerminated TerminatingState {} = Bool
True
connectionTerminated TerminatedState  {} = Bool
True
connectionTerminated ConnectionState peerAddr handle handleError version m
_                   = Bool
False