{-# LANGUAGE BangPatterns         #-}
{-# LANGUAGE DataKinds            #-}
{-# LANGUAGE FlexibleContexts     #-}
{-# LANGUAGE GADTs                #-}
{-# LANGUAGE KindSignatures       #-}
{-# LANGUAGE NamedFieldPuns       #-}
{-# LANGUAGE RankNTypes           #-}
{-# LANGUAGE ScopedTypeVariables  #-}
{-# LANGUAGE TupleSections        #-}
{-# LANGUAGE UndecidableInstances #-}

-- | The implementation of connection manager.
--
-- The module should be imported qualified.
--
module Ouroboros.Network.ConnectionManager.Core
  ( Arguments (..)
  , Trace (..)
  , with
  , defaultTimeWaitTimeout
  , defaultProtocolIdleTimeout
  , defaultResetTimeout
  , ConnectionState (..)
  , State.abstractState
  ) where

import Control.Applicative (Alternative)
import Control.Concurrent.Class.MonadSTM qualified as LazySTM
import Control.Concurrent.Class.MonadSTM.Strict
import Control.Exception (assert)
import Control.Monad (forM_, guard, unless, when, (>=>))
import Control.Monad.Class.MonadAsync
import Control.Monad.Class.MonadFork (throwTo)
import Control.Monad.Class.MonadThrow hiding (handle)
import Control.Monad.Class.MonadTime.SI
import Control.Monad.Class.MonadTimer.SI
import Control.Monad.Fix
import Control.Tracer (Tracer, contramap, traceWith)
import Data.Foldable (foldMap', traverse_)
import Data.Functor (void, ($>))
import Data.Proxy (Proxy (..))
import Data.Typeable (Typeable)
import GHC.Stack (CallStack, HasCallStack, callStack)
import System.Random (StdGen, split)

import Data.Map.Strict (Map)
import Data.Map.Strict qualified as Map
import Data.Set qualified as Set

import Data.Monoid.Synchronisation
import Data.Set (Set)
import Data.Tuple (swap)
import Data.Wedge
import Data.Word (Word32)

import Network.Mux.Trace qualified as Mx
import Network.Mux.Types qualified as Mx

import Ouroboros.Network.ConnectionId
import Ouroboros.Network.ConnectionManager.InformationChannel
           (InformationChannel)
import Ouroboros.Network.ConnectionManager.InformationChannel qualified as InfoChannel
import Ouroboros.Network.ConnectionManager.State (ConnStateIdSupply,
           ConnectionManagerState, ConnectionState (..), MutableConnState (..))
import Ouroboros.Network.ConnectionManager.State qualified as State
import Ouroboros.Network.ConnectionManager.Types
import Ouroboros.Network.InboundGovernor.Event (NewConnectionInfo (..))
import Ouroboros.Network.MuxMode
import Ouroboros.Network.NodeToNode.Version (DiffusionMode (..))
import Ouroboros.Network.Server.RateLimiting (AcceptedConnectionsLimit (..))
import Ouroboros.Network.Snocket


-- | Arguments for a 'ConnectionManager' which are independent of 'MuxMode'.
--
data Arguments handlerTrace socket peerAddr handle handleError versionNumber versionData m =
    Arguments {
        -- | Connection manager tracer.
        --
        forall handlerTrace socket peerAddr handle handleError
       versionNumber versionData (m :: * -> *).
Arguments
  handlerTrace
  socket
  peerAddr
  handle
  handleError
  versionNumber
  versionData
  m
-> Tracer m (Trace peerAddr handlerTrace)
tracer              :: Tracer m (Trace peerAddr handlerTrace),

        -- | Trace state transitions.
        --
        -- TODO: do we need this tracer?  In some tests we relay on `traceTVar` in
        -- `newNetworkMutableState` instead.
        forall handlerTrace socket peerAddr handle handleError
       versionNumber versionData (m :: * -> *).
Arguments
  handlerTrace
  socket
  peerAddr
  handle
  handleError
  versionNumber
  versionData
  m
-> Tracer
     m
     (TransitionTrace
        ConnStateId
        (ConnectionState peerAddr handle handleError versionNumber m))
trTracer            :: Tracer m (TransitionTrace State.ConnStateId
                                            (ConnectionState peerAddr handle handleError versionNumber m)),

        -- | Mux trace.
        --
        forall handlerTrace socket peerAddr handle handleError
       versionNumber versionData (m :: * -> *).
Arguments
  handlerTrace
  socket
  peerAddr
  handle
  handleError
  versionNumber
  versionData
  m
-> Tracer m (WithBearer (ConnectionId peerAddr) Trace)
muxTracer           :: Tracer m (Mx.WithBearer (ConnectionId peerAddr) Mx.Trace),

        -- | @IPv4@ address of the connection manager.  If given, outbound
        -- connections to an @IPv4@ address will bound to it.  To use
        -- bidirectional @TCP@ connections, it must be the same as the server
        -- listening @IPv4@ address.
        --
        forall handlerTrace socket peerAddr handle handleError
       versionNumber versionData (m :: * -> *).
Arguments
  handlerTrace
  socket
  peerAddr
  handle
  handleError
  versionNumber
  versionData
  m
-> Maybe peerAddr
ipv4Address         :: Maybe peerAddr,

        -- | @IPv6@ address of the connection manager.  If given, outbound
        -- connections to an @IPv6@ address will bound to it.  To use
        -- bidirectional @TCP@ connections, it must be the same as the server
        -- listening @IPv6@ address.
        --
        forall handlerTrace socket peerAddr handle handleError
       versionNumber versionData (m :: * -> *).
Arguments
  handlerTrace
  socket
  peerAddr
  handle
  handleError
  versionNumber
  versionData
  m
-> Maybe peerAddr
ipv6Address         :: Maybe peerAddr,

        forall handlerTrace socket peerAddr handle handleError
       versionNumber versionData (m :: * -> *).
Arguments
  handlerTrace
  socket
  peerAddr
  handle
  handleError
  versionNumber
  versionData
  m
-> peerAddr -> Maybe AddressType
addressType         :: peerAddr -> Maybe AddressType,

        -- | Snocket for the 'socket' type.
        --
        forall handlerTrace socket peerAddr handle handleError
       versionNumber versionData (m :: * -> *).
Arguments
  handlerTrace
  socket
  peerAddr
  handle
  handleError
  versionNumber
  versionData
  m
-> Snocket m socket peerAddr
snocket             :: Snocket m socket peerAddr,

        -- | Make MuxBearer.
        --
        forall handlerTrace socket peerAddr handle handleError
       versionNumber versionData (m :: * -> *).
Arguments
  handlerTrace
  socket
  peerAddr
  handle
  handleError
  versionNumber
  versionData
  m
-> MakeBearer m socket
makeBearer          :: MakeBearer m socket,

        -- | Socket configuration.
        --
        forall handlerTrace socket peerAddr handle handleError
       versionNumber versionData (m :: * -> *).
Arguments
  handlerTrace
  socket
  peerAddr
  handle
  handleError
  versionNumber
  versionData
  m
-> socket -> Maybe peerAddr -> m ()
configureSocket     :: socket -> Maybe peerAddr -> m (),

        -- | @TCP@ will held connections in @TIME_WAIT@ state for up to two MSL
        -- (maximum segment time).  On Linux this is set to '60' seconds on
        -- other system this might be up to four minutes.
        --
        -- This is configurable, so we can set different value in tests.
        --
        -- When this timeout expires a connection will transition from
        -- 'TerminatingState' to 'TerminatedState'.
        --
        forall handlerTrace socket peerAddr handle handleError
       versionNumber versionData (m :: * -> *).
Arguments
  handlerTrace
  socket
  peerAddr
  handle
  handleError
  versionNumber
  versionData
  m
-> DiffTime
timeWaitTimeout     :: DiffTime,

        -- | Inactivity timeout before the connection will be reset.  It is the
        -- timeout attached to the 'OutboundIdleState'.
        --
        forall handlerTrace socket peerAddr handle handleError
       versionNumber versionData (m :: * -> *).
Arguments
  handlerTrace
  socket
  peerAddr
  handle
  handleError
  versionNumber
  versionData
  m
-> DiffTime
outboundIdleTimeout :: DiffTime,

        -- | Given a version number and respective version data, get the
        -- 'DataFlow'.
        --
        forall handlerTrace socket peerAddr handle handleError
       versionNumber versionData (m :: * -> *).
Arguments
  handlerTrace
  socket
  peerAddr
  handle
  handleError
  versionNumber
  versionData
  m
-> versionData -> DataFlow
connectionDataFlow    :: versionData -> DataFlow,

        -- | Prune policy
        --
        forall handlerTrace socket peerAddr handle handleError
       versionNumber versionData (m :: * -> *).
Arguments
  handlerTrace
  socket
  peerAddr
  handle
  handleError
  versionNumber
  versionData
  m
-> PrunePolicy peerAddr
prunePolicy         :: PrunePolicy peerAddr,

        -- | StdGen used by the `PrunePolicy`
        --
        forall handlerTrace socket peerAddr handle handleError
       versionNumber versionData (m :: * -> *).
Arguments
  handlerTrace
  socket
  peerAddr
  handle
  handleError
  versionNumber
  versionData
  m
-> StdGen
stdGen              :: StdGen,

        forall handlerTrace socket peerAddr handle handleError
       versionNumber versionData (m :: * -> *).
Arguments
  handlerTrace
  socket
  peerAddr
  handle
  handleError
  versionNumber
  versionData
  m
-> AcceptedConnectionsLimit
connectionsLimits   :: AcceptedConnectionsLimit,

        forall handlerTrace socket peerAddr handle handleError
       versionNumber versionData (m :: * -> *).
Arguments
  handlerTrace
  socket
  peerAddr
  handle
  handleError
  versionNumber
  versionData
  m
-> versionData -> DiffusionMode -> versionData
updateVersionData   :: versionData -> DiffusionMode -> versionData,

        -- | Supply for `ConnStateId`-s.
        --
        forall handlerTrace socket peerAddr handle handleError
       versionNumber versionData (m :: * -> *).
Arguments
  handlerTrace
  socket
  peerAddr
  handle
  handleError
  versionNumber
  versionData
  m
-> ConnStateIdSupply m
connStateIdSupply   :: ConnStateIdSupply m
      }



connectionManagerStateToCounters
  :: State.ConnMap peerAddr (ConnectionState peerAddr handle handleError version m)
  -> ConnectionManagerCounters
connectionManagerStateToCounters :: forall peerAddr handle handleError version (m :: * -> *).
ConnMap
  peerAddr (ConnectionState peerAddr handle handleError version m)
-> ConnectionManagerCounters
connectionManagerStateToCounters = (ConnectionState peerAddr handle handleError version m
 -> ConnectionManagerCounters)
-> ConnMap
     peerAddr (ConnectionState peerAddr handle handleError version m)
-> ConnectionManagerCounters
forall m a. Monoid m => (a -> m) -> ConnMap peerAddr a -> m
forall (t :: * -> *) m a.
(Foldable t, Monoid m) =>
(a -> m) -> t a -> m
foldMap' ConnectionState peerAddr handle handleError version m
-> ConnectionManagerCounters
forall peerAddr handle handleError version (m :: * -> *).
ConnectionState peerAddr handle handleError version m
-> ConnectionManagerCounters
connectionStateToCounters



-- | Perform counting from an 'AbstractState'
connectionStateToCounters
    :: ConnectionState peerAddr handle handleError version m
    -> ConnectionManagerCounters
connectionStateToCounters :: forall peerAddr handle handleError version (m :: * -> *).
ConnectionState peerAddr handle handleError version m
-> ConnectionManagerCounters
connectionStateToCounters ConnectionState peerAddr handle handleError version m
state =
    case ConnectionState peerAddr handle handleError version m
state of
      ConnectionState peerAddr handle handleError version m
ReservedOutboundState                 -> ConnectionManagerCounters
forall a. Monoid a => a
mempty

      UnnegotiatedState Provenance
Inbound ConnectionId peerAddr
_ Async m ()
_         -> ConnectionManagerCounters
inboundConn

      UnnegotiatedState Provenance
Outbound ConnectionId peerAddr
_ Async m ()
_        -> ConnectionManagerCounters
outboundConn

      OutboundUniState {}                   -> ConnectionManagerCounters
unidirectionalConn
                                            ConnectionManagerCounters
-> ConnectionManagerCounters -> ConnectionManagerCounters
forall a. Semigroup a => a -> a -> a
<> ConnectionManagerCounters
outboundConn

      OutboundDupState  {}                  -> ConnectionManagerCounters
duplexConn
                                            ConnectionManagerCounters
-> ConnectionManagerCounters -> ConnectionManagerCounters
forall a. Semigroup a => a -> a -> a
<> ConnectionManagerCounters
outboundConn

      OutboundIdleState ConnectionId peerAddr
_ Async m ()
_ handle
_ DataFlow
Unidirectional -> ConnectionManagerCounters
unidirectionalConn
                                             ConnectionManagerCounters
-> ConnectionManagerCounters -> ConnectionManagerCounters
forall a. Semigroup a => a -> a -> a
<> ConnectionManagerCounters
outboundConn

      OutboundIdleState ConnectionId peerAddr
_ Async m ()
_ handle
_ DataFlow
Duplex         -> ConnectionManagerCounters
duplexConn
                                             ConnectionManagerCounters
-> ConnectionManagerCounters -> ConnectionManagerCounters
forall a. Semigroup a => a -> a -> a
<> ConnectionManagerCounters
outboundConn

      InboundIdleState ConnectionId peerAddr
_ Async m ()
_ handle
_ DataFlow
Unidirectional -> ConnectionManagerCounters
unidirectionalConn
                                            ConnectionManagerCounters
-> ConnectionManagerCounters -> ConnectionManagerCounters
forall a. Semigroup a => a -> a -> a
<> ConnectionManagerCounters
inboundConn

      InboundIdleState ConnectionId peerAddr
_ Async m ()
_ handle
_ DataFlow
Duplex         -> ConnectionManagerCounters
duplexConn
                                            ConnectionManagerCounters
-> ConnectionManagerCounters -> ConnectionManagerCounters
forall a. Semigroup a => a -> a -> a
<> ConnectionManagerCounters
inboundConn

      InboundState ConnectionId peerAddr
_ Async m ()
_ handle
_ DataFlow
Unidirectional     -> ConnectionManagerCounters
unidirectionalConn
                                            ConnectionManagerCounters
-> ConnectionManagerCounters -> ConnectionManagerCounters
forall a. Semigroup a => a -> a -> a
<> ConnectionManagerCounters
inboundConn

      InboundState ConnectionId peerAddr
_ Async m ()
_ handle
_ DataFlow
Duplex             -> ConnectionManagerCounters
duplexConn
                                            ConnectionManagerCounters
-> ConnectionManagerCounters -> ConnectionManagerCounters
forall a. Semigroup a => a -> a -> a
<> ConnectionManagerCounters
inboundConn

      DuplexState {}                        -> ConnectionManagerCounters
fullDuplexConn
                                            ConnectionManagerCounters
-> ConnectionManagerCounters -> ConnectionManagerCounters
forall a. Semigroup a => a -> a -> a
<> ConnectionManagerCounters
duplexConn
                                             ConnectionManagerCounters
-> ConnectionManagerCounters -> ConnectionManagerCounters
forall a. Semigroup a => a -> a -> a
<> ConnectionManagerCounters
inboundConn
                                            ConnectionManagerCounters
-> ConnectionManagerCounters -> ConnectionManagerCounters
forall a. Semigroup a => a -> a -> a
<> ConnectionManagerCounters
outboundConn

      TerminatingState {}                   -> ConnectionManagerCounters
forall a. Monoid a => a
mempty
      TerminatedState {}                    -> ConnectionManagerCounters
forall a. Monoid a => a
mempty
  where
    fullDuplexConn :: ConnectionManagerCounters
fullDuplexConn     = Int -> Int -> Int -> Int -> Int -> ConnectionManagerCounters
ConnectionManagerCounters Int
1 Int
0 Int
0 Int
0 Int
0
    duplexConn :: ConnectionManagerCounters
duplexConn         = Int -> Int -> Int -> Int -> Int -> ConnectionManagerCounters
ConnectionManagerCounters Int
0 Int
1 Int
0 Int
0 Int
0
    unidirectionalConn :: ConnectionManagerCounters
unidirectionalConn = Int -> Int -> Int -> Int -> Int -> ConnectionManagerCounters
ConnectionManagerCounters Int
0 Int
0 Int
1 Int
0 Int
0
    inboundConn :: ConnectionManagerCounters
inboundConn        = Int -> Int -> Int -> Int -> Int -> ConnectionManagerCounters
ConnectionManagerCounters Int
0 Int
0 Int
0 Int
1 Int
0
    outboundConn :: ConnectionManagerCounters
outboundConn       = Int -> Int -> Int -> Int -> Int -> ConnectionManagerCounters
ConnectionManagerCounters Int
0 Int
0 Int
0 Int
0 Int
1


getConnThread :: ConnectionState peerAddr handle handleError version m
              -> Maybe (Async m ())
getConnThread :: forall peerAddr handle handleError version (m :: * -> *).
ConnectionState peerAddr handle handleError version m
-> Maybe (Async m ())
getConnThread ConnectionState peerAddr handle handleError version m
ReservedOutboundState                                     = Maybe (Async m ())
forall a. Maybe a
Nothing
getConnThread (UnnegotiatedState Provenance
_pr   ConnectionId peerAddr
_connId Async m ()
connThread)              = Async m () -> Maybe (Async m ())
forall a. a -> Maybe a
Just Async m ()
connThread
getConnThread (OutboundUniState        ConnectionId peerAddr
_connId Async m ()
connThread handle
_handle )     = Async m () -> Maybe (Async m ())
forall a. a -> Maybe a
Just Async m ()
connThread
getConnThread (OutboundDupState        ConnectionId peerAddr
_connId Async m ()
connThread handle
_handle TimeoutExpired
_te)  = Async m () -> Maybe (Async m ())
forall a. a -> Maybe a
Just Async m ()
connThread
getConnThread (OutboundIdleState       ConnectionId peerAddr
_connId Async m ()
connThread handle
_handle DataFlow
_df)  = Async m () -> Maybe (Async m ())
forall a. a -> Maybe a
Just Async m ()
connThread
getConnThread (InboundIdleState        ConnectionId peerAddr
_connId Async m ()
connThread handle
_handle DataFlow
_df)  = Async m () -> Maybe (Async m ())
forall a. a -> Maybe a
Just Async m ()
connThread
getConnThread (InboundState            ConnectionId peerAddr
_connId Async m ()
connThread handle
_handle DataFlow
_df)  = Async m () -> Maybe (Async m ())
forall a. a -> Maybe a
Just Async m ()
connThread
getConnThread (DuplexState             ConnectionId peerAddr
_connId Async m ()
connThread handle
_handle)      = Async m () -> Maybe (Async m ())
forall a. a -> Maybe a
Just Async m ()
connThread
getConnThread (TerminatingState        ConnectionId peerAddr
_connId Async m ()
connThread Maybe handleError
_handleError) = Async m () -> Maybe (Async m ())
forall a. a -> Maybe a
Just Async m ()
connThread
getConnThread TerminatedState {}                                        = Maybe (Async m ())
forall a. Maybe a
Nothing

-- | Get 'DataFlow' for a connection.  It returns 'Nowhere' if that connection
-- is either not yet created or in terminating state, 'There' for  unnegotiated
-- connections and 'Here' if the data flow is known.
--
getConnType :: ConnectionState peerAddr handle handleError version m
            -> Maybe ConnectionType
getConnType :: forall peerAddr handle handleError version (m :: * -> *).
ConnectionState peerAddr handle handleError version m
-> Maybe ConnectionType
getConnType ConnectionState peerAddr handle handleError version m
ReservedOutboundState                                    = Maybe ConnectionType
forall a. Maybe a
Nothing
getConnType (UnnegotiatedState Provenance
pr  ConnectionId peerAddr
_connId Async m ()
_connThread)              = ConnectionType -> Maybe ConnectionType
forall a. a -> Maybe a
Just (Provenance -> ConnectionType
UnnegotiatedConn Provenance
pr)
getConnType (OutboundUniState      ConnectionId peerAddr
_connId Async m ()
_connThread handle
_handle)      = ConnectionType -> Maybe ConnectionType
forall a. a -> Maybe a
Just (Provenance -> DataFlow -> ConnectionType
NegotiatedConn Provenance
Outbound DataFlow
Unidirectional)
getConnType (OutboundDupState      ConnectionId peerAddr
_connId Async m ()
_connThread handle
_handle TimeoutExpired
_te)  = ConnectionType -> Maybe ConnectionType
forall a. a -> Maybe a
Just (Provenance -> DataFlow -> ConnectionType
NegotiatedConn Provenance
Outbound DataFlow
Duplex)
getConnType (OutboundIdleState     ConnectionId peerAddr
_connId Async m ()
_connThread handle
_handle DataFlow
df)   = ConnectionType -> Maybe ConnectionType
forall a. a -> Maybe a
Just (DataFlow -> ConnectionType
OutboundIdleConn DataFlow
df)
getConnType (InboundIdleState      ConnectionId peerAddr
_connId Async m ()
_connThread handle
_handle DataFlow
df)   = ConnectionType -> Maybe ConnectionType
forall a. a -> Maybe a
Just (DataFlow -> ConnectionType
InboundIdleConn DataFlow
df)
getConnType (InboundState          ConnectionId peerAddr
_connId Async m ()
_connThread handle
_handle DataFlow
df)   = ConnectionType -> Maybe ConnectionType
forall a. a -> Maybe a
Just (Provenance -> DataFlow -> ConnectionType
NegotiatedConn Provenance
Inbound DataFlow
df)
getConnType (DuplexState           ConnectionId peerAddr
_connId Async m ()
_connThread handle
_handle)      = ConnectionType -> Maybe ConnectionType
forall a. a -> Maybe a
Just ConnectionType
DuplexConn
getConnType (TerminatingState      ConnectionId peerAddr
_connId Async m ()
_connThread Maybe handleError
_handleError) = Maybe ConnectionType
forall a. Maybe a
Nothing
getConnType TerminatedState {}                                       = Maybe ConnectionType
forall a. Maybe a
Nothing


-- | Return 'True' if a connection is inbound.  This must agree with
-- 'connectionStateToCounters'.  Both are used for pruning.
--
isInboundConn :: ConnectionState peerAddr handle handleError version m -> Bool
isInboundConn :: forall peerAddr handle handleError version (m :: * -> *).
ConnectionState peerAddr handle handleError version m -> Bool
isInboundConn ConnectionState peerAddr handle handleError version m
ReservedOutboundState                      = Bool
False
isInboundConn (UnnegotiatedState Provenance
pr ConnectionId peerAddr
_connId Async m ()
_connThread) = Provenance
pr Provenance -> Provenance -> Bool
forall a. Eq a => a -> a -> Bool
== Provenance
Inbound
isInboundConn OutboundUniState {}                        = Bool
False
isInboundConn OutboundDupState {}                        = Bool
False
isInboundConn OutboundIdleState {}                       = Bool
False
isInboundConn InboundIdleState {}                        = Bool
True
isInboundConn InboundState {}                            = Bool
True
isInboundConn DuplexState {}                             = Bool
True
isInboundConn TerminatingState {}                        = Bool
False
isInboundConn TerminatedState {}                         = Bool
False

-- | The default value for 'timeWaitTimeout'.
--
defaultTimeWaitTimeout :: DiffTime
defaultTimeWaitTimeout :: DiffTime
defaultTimeWaitTimeout = DiffTime
60

-- | Inactivity timeout.  It configures how long to wait since the local side
-- demoted remote peer to /cold/, before closing the connection.
--
defaultProtocolIdleTimeout :: DiffTime
defaultProtocolIdleTimeout :: DiffTime
defaultProtocolIdleTimeout = DiffTime
5

defaultResetTimeout :: DiffTime
defaultResetTimeout :: DiffTime
defaultResetTimeout = DiffTime
5


newtype PruneAction m = PruneAction { forall (m :: * -> *). PruneAction m -> m ()
runPruneAction :: m () }

-- | Instruction used internally in @releaseOutboundConnectionImpl@, e.g. in
-- the implementation of one of the two  @DemotedToCold^{dataFlow}_{Local}@
-- transitions.
--
data DemoteToColdLocal peerAddr handlerTrace handle handleError version m
    -- | Any @DemotedToCold@ transition which terminates the connection:
    -- @
    --   DemotedToCold^{Duplex}_{Local} : * -> TerminatingState
    -- @
    -- from the spec.
    --
    = DemotedToColdLocal      (ConnectionId peerAddr)
                              (Async m ())
                              (StrictTVar m (ConnectionState
                                              peerAddr handle
                                              handleError version m))
                             !(TransitionTrace State.ConnStateId
                                              (ConnectionState
                                                peerAddr handle
                                                handleError version m))

    -- | Any @DemoteToCold@ transition which does not terminate the connection, i.e.
    -- @
    --   DemotedToCold^{Duplex}_{Local} : OutboundState^\tau Duplex
    --                                  → InboundIdleState^\tau
    -- @
    -- or the case where the connection is already in 'TerminatingState' or
    -- 'TerminatedState'.
    --
    | DemoteToColdLocalNoop !(Maybe (TransitionTrace State.ConnStateId
                                                     (ConnectionState
                                                        peerAddr handle
                                                        handleError version m)))
                            !AbstractState

    -- | Duplex connection was demoted, prune connections.
    --
    | PruneConnections       (PruneAction m)
                             -- ^ prune action

                            !(Either
                               (ConnectionState
                                 peerAddr handle
                                 handleError version m)
                               (TransitionTrace State.ConnStateId
                                                (ConnectionState
                                                   peerAddr handle
                                                   handleError version m))
                             )

                             -- ^ Left case is for when the connection which
                             -- triggered pruning is pruned in this case we do
                             -- not want to trace a new transition.
                             --
                             -- Right case is for when the connection which
                             -- triggered pruning isn't pruned. In this case
                             -- we do want to trace a new transition.


    -- | Demote error.
    | DemoteToColdLocalError  (Trace peerAddr handlerTrace)
                             !AbstractState


-- | Entry point for using the connection manager.  This is a classic @with@ style
-- combinator, which cleans resources on exit of the callback (whether cleanly
-- or through an exception).
--
-- Including a connection (either inbound or outbound) is an idempotent
-- operation on connection manager state.  The connection manager will always
-- return the handle that was first to be included in its state.
--
-- Once an inbound connection is passed to the 'ConnectionManager', the manager
-- is responsible for the resource.
--
with
    :: forall (muxMode :: Mx.Mode) peerAddr socket handlerTrace handle handleError version versionData m a.
       ( Alternative (STM m)
       , MonadLabelledSTM   m
       , MonadTraceSTM      m
       -- 'MonadFork' is only to get access to 'throwTo'
       , MonadFork          m
       , MonadAsync         m
       , MonadDelay         m
       , MonadEvaluate      m
       , MonadFix           m
       , MonadMask          m
       , MonadThrow    (STM m)
       , MonadTimer         m

       , Ord      peerAddr
       , Show     peerAddr
       , Typeable peerAddr
       )
    => Arguments handlerTrace socket peerAddr handle handleError version versionData m
    -> ConnectionHandler  muxMode handlerTrace socket peerAddr handle handleError version versionData m
    -- ^ Callback which runs in a thread dedicated for a given connection.
    -> (handleError -> HandleErrorType)
    -- ^ classify 'handleError's
    -> InResponderMode muxMode (InformationChannel (NewConnectionInfo peerAddr handle) m)
    -- ^ On outbound duplex connections we need to notify the server about
    -- a new connection.
    -> (ConnectionManager muxMode socket peerAddr handle handleError m -> m a)
    -- ^ Continuation which receives the 'ConnectionManager'.  It must not leak
    -- outside of scope of this callback.  Once it returns all resources
    -- will be closed.
    -> m a
with :: forall (muxMode :: Mode) peerAddr socket handlerTrace handle
       handleError version versionData (m :: * -> *) a.
(Alternative (STM m), MonadLabelledSTM m, MonadTraceSTM m,
 MonadFork m, MonadAsync m, MonadDelay m, MonadEvaluate m,
 MonadFix m, MonadMask m, MonadThrow (STM m), MonadTimer m,
 Ord peerAddr, Show peerAddr, Typeable peerAddr) =>
Arguments
  handlerTrace
  socket
  peerAddr
  handle
  handleError
  version
  versionData
  m
-> ConnectionHandler
     muxMode
     handlerTrace
     socket
     peerAddr
     handle
     handleError
     version
     versionData
     m
-> (handleError -> HandleErrorType)
-> InResponderMode
     muxMode (InformationChannel (NewConnectionInfo peerAddr handle) m)
-> (ConnectionManager muxMode socket peerAddr handle handleError m
    -> m a)
-> m a
with args :: Arguments
  handlerTrace
  socket
  peerAddr
  handle
  handleError
  version
  versionData
  m
args@Arguments {
         Tracer m (Trace peerAddr handlerTrace)
tracer :: forall handlerTrace socket peerAddr handle handleError
       versionNumber versionData (m :: * -> *).
Arguments
  handlerTrace
  socket
  peerAddr
  handle
  handleError
  versionNumber
  versionData
  m
-> Tracer m (Trace peerAddr handlerTrace)
tracer :: Tracer m (Trace peerAddr handlerTrace)
tracer,
         Tracer
  m
  (TransitionTrace
     ConnStateId
     (ConnectionState peerAddr handle handleError version m))
trTracer :: forall handlerTrace socket peerAddr handle handleError
       versionNumber versionData (m :: * -> *).
Arguments
  handlerTrace
  socket
  peerAddr
  handle
  handleError
  versionNumber
  versionData
  m
-> Tracer
     m
     (TransitionTrace
        ConnStateId
        (ConnectionState peerAddr handle handleError versionNumber m))
trTracer :: Tracer
  m
  (TransitionTrace
     ConnStateId
     (ConnectionState peerAddr handle handleError version m))
trTracer,
         Tracer m (WithBearer (ConnectionId peerAddr) Trace)
muxTracer :: forall handlerTrace socket peerAddr handle handleError
       versionNumber versionData (m :: * -> *).
Arguments
  handlerTrace
  socket
  peerAddr
  handle
  handleError
  versionNumber
  versionData
  m
-> Tracer m (WithBearer (ConnectionId peerAddr) Trace)
muxTracer :: Tracer m (WithBearer (ConnectionId peerAddr) Trace)
muxTracer,
         Maybe peerAddr
ipv4Address :: forall handlerTrace socket peerAddr handle handleError
       versionNumber versionData (m :: * -> *).
Arguments
  handlerTrace
  socket
  peerAddr
  handle
  handleError
  versionNumber
  versionData
  m
-> Maybe peerAddr
ipv4Address :: Maybe peerAddr
ipv4Address,
         Maybe peerAddr
ipv6Address :: forall handlerTrace socket peerAddr handle handleError
       versionNumber versionData (m :: * -> *).
Arguments
  handlerTrace
  socket
  peerAddr
  handle
  handleError
  versionNumber
  versionData
  m
-> Maybe peerAddr
ipv6Address :: Maybe peerAddr
ipv6Address,
         peerAddr -> Maybe AddressType
addressType :: forall handlerTrace socket peerAddr handle handleError
       versionNumber versionData (m :: * -> *).
Arguments
  handlerTrace
  socket
  peerAddr
  handle
  handleError
  versionNumber
  versionData
  m
-> peerAddr -> Maybe AddressType
addressType :: peerAddr -> Maybe AddressType
addressType,
         Snocket m socket peerAddr
snocket :: forall handlerTrace socket peerAddr handle handleError
       versionNumber versionData (m :: * -> *).
Arguments
  handlerTrace
  socket
  peerAddr
  handle
  handleError
  versionNumber
  versionData
  m
-> Snocket m socket peerAddr
snocket :: Snocket m socket peerAddr
snocket,
         MakeBearer m socket
makeBearer :: forall handlerTrace socket peerAddr handle handleError
       versionNumber versionData (m :: * -> *).
Arguments
  handlerTrace
  socket
  peerAddr
  handle
  handleError
  versionNumber
  versionData
  m
-> MakeBearer m socket
makeBearer :: MakeBearer m socket
makeBearer,
         socket -> Maybe peerAddr -> m ()
configureSocket :: forall handlerTrace socket peerAddr handle handleError
       versionNumber versionData (m :: * -> *).
Arguments
  handlerTrace
  socket
  peerAddr
  handle
  handleError
  versionNumber
  versionData
  m
-> socket -> Maybe peerAddr -> m ()
configureSocket :: socket -> Maybe peerAddr -> m ()
configureSocket,
         DiffTime
timeWaitTimeout :: forall handlerTrace socket peerAddr handle handleError
       versionNumber versionData (m :: * -> *).
Arguments
  handlerTrace
  socket
  peerAddr
  handle
  handleError
  versionNumber
  versionData
  m
-> DiffTime
timeWaitTimeout :: DiffTime
timeWaitTimeout,
         DiffTime
outboundIdleTimeout :: forall handlerTrace socket peerAddr handle handleError
       versionNumber versionData (m :: * -> *).
Arguments
  handlerTrace
  socket
  peerAddr
  handle
  handleError
  versionNumber
  versionData
  m
-> DiffTime
outboundIdleTimeout :: DiffTime
outboundIdleTimeout,
         versionData -> DataFlow
connectionDataFlow :: forall handlerTrace socket peerAddr handle handleError
       versionNumber versionData (m :: * -> *).
Arguments
  handlerTrace
  socket
  peerAddr
  handle
  handleError
  versionNumber
  versionData
  m
-> versionData -> DataFlow
connectionDataFlow :: versionData -> DataFlow
connectionDataFlow,
         PrunePolicy peerAddr
prunePolicy :: forall handlerTrace socket peerAddr handle handleError
       versionNumber versionData (m :: * -> *).
Arguments
  handlerTrace
  socket
  peerAddr
  handle
  handleError
  versionNumber
  versionData
  m
-> PrunePolicy peerAddr
prunePolicy :: PrunePolicy peerAddr
prunePolicy,
         AcceptedConnectionsLimit
connectionsLimits :: forall handlerTrace socket peerAddr handle handleError
       versionNumber versionData (m :: * -> *).
Arguments
  handlerTrace
  socket
  peerAddr
  handle
  handleError
  versionNumber
  versionData
  m
-> AcceptedConnectionsLimit
connectionsLimits :: AcceptedConnectionsLimit
connectionsLimits,
         versionData -> DiffusionMode -> versionData
updateVersionData :: forall handlerTrace socket peerAddr handle handleError
       versionNumber versionData (m :: * -> *).
Arguments
  handlerTrace
  socket
  peerAddr
  handle
  handleError
  versionNumber
  versionData
  m
-> versionData -> DiffusionMode -> versionData
updateVersionData :: versionData -> DiffusionMode -> versionData
updateVersionData,
         ConnStateIdSupply m
connStateIdSupply :: forall handlerTrace socket peerAddr handle handleError
       versionNumber versionData (m :: * -> *).
Arguments
  handlerTrace
  socket
  peerAddr
  handle
  handleError
  versionNumber
  versionData
  m
-> ConnStateIdSupply m
connStateIdSupply :: ConnStateIdSupply m
connStateIdSupply
       }
     ConnectionHandler {
         WithMuxTuple
  muxMode
  (ConnectionHandlerFn
     handlerTrace
     socket
     peerAddr
     handle
     handleError
     version
     versionData
     m)
connectionHandler :: WithMuxTuple
  muxMode
  (ConnectionHandlerFn
     handlerTrace
     socket
     peerAddr
     handle
     handleError
     version
     versionData
     m)
connectionHandler :: forall (muxMode :: Mode) handlerTrace socket peerAddr handle
       handleError versionNumber versionData (m :: * -> *).
ConnectionHandler
  muxMode
  handlerTrace
  socket
  peerAddr
  handle
  handleError
  versionNumber
  versionData
  m
-> WithMuxTuple
     muxMode
     (ConnectionHandlerFn
        handlerTrace
        socket
        peerAddr
        handle
        handleError
        versionNumber
        versionData
        m)
connectionHandler
       }
     handleError -> HandleErrorType
classifyHandleError
     InResponderMode
  muxMode (InformationChannel (NewConnectionInfo peerAddr handle) m)
inboundGovernorInfoChannel
     ConnectionManager muxMode socket peerAddr handle handleError m
-> m a
k = do
    ((stateVar, stdGenVar)
       ::  ( StrictTMVar m (ConnectionManagerState peerAddr handle handleError
                                                   version m)
           , StrictTVar m StdGen
           ))
      <- STM
  m
  (StrictTMVar
     m (ConnectionManagerState peerAddr handle handleError version m),
   StrictTVar m StdGen)
-> m (StrictTMVar
        m (ConnectionManagerState peerAddr handle handleError version m),
      StrictTVar m StdGen)
forall a. (?callStack::CallStack) => STM m a -> m a
forall (m :: * -> *) a.
(MonadSTM m, ?callStack::CallStack) =>
STM m a -> m a
atomically (STM
   m
   (StrictTMVar
      m (ConnectionManagerState peerAddr handle handleError version m),
    StrictTVar m StdGen)
 -> m (StrictTMVar
         m (ConnectionManagerState peerAddr handle handleError version m),
       StrictTVar m StdGen))
-> STM
     m
     (StrictTMVar
        m (ConnectionManagerState peerAddr handle handleError version m),
      StrictTVar m StdGen)
-> m (StrictTMVar
        m (ConnectionManagerState peerAddr handle handleError version m),
      StrictTVar m StdGen)
forall a b. (a -> b) -> a -> b
$  do
          v  <- ConnectionManagerState peerAddr handle handleError version m
-> STM
     m
     (StrictTMVar
        m (ConnectionManagerState peerAddr handle handleError version m))
forall (m :: * -> *) a. MonadSTM m => a -> STM m (StrictTMVar m a)
newTMVar ConnectionManagerState peerAddr handle handleError version m
forall peerAddr a. ConnMap peerAddr a
State.empty
          labelTMVar v "cm-state"
          traceTMVar (Proxy :: Proxy m) v $ \Maybe
  (Maybe
     (ConnectionManagerState peerAddr handle handleError version m))
_ Maybe
  (ConnectionManagerState peerAddr handle handleError version m)
mbst -> do
            st' <- case Maybe
  (ConnectionManagerState peerAddr handle handleError version m)
mbst of
              Maybe
  (ConnectionManagerState peerAddr handle handleError version m)
Nothing -> Maybe
  (ConnMap
     peerAddr (ConnectionState peerAddr handle handleError version m))
-> InspectMonad
     m
     (Maybe
        (ConnMap
           peerAddr (ConnectionState peerAddr handle handleError version m)))
forall a. a -> InspectMonad m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Maybe
  (ConnMap
     peerAddr (ConnectionState peerAddr handle handleError version m))
forall a. Maybe a
Nothing
              Just ConnectionManagerState peerAddr handle handleError version m
st -> ConnMap
  peerAddr (ConnectionState peerAddr handle handleError version m)
-> Maybe
     (ConnMap
        peerAddr (ConnectionState peerAddr handle handleError version m))
forall a. a -> Maybe a
Just (ConnMap
   peerAddr (ConnectionState peerAddr handle handleError version m)
 -> Maybe
      (ConnMap
         peerAddr (ConnectionState peerAddr handle handleError version m)))
-> InspectMonad
     m
     (ConnMap
        peerAddr (ConnectionState peerAddr handle handleError version m))
-> InspectMonad
     m
     (Maybe
        (ConnMap
           peerAddr (ConnectionState peerAddr handle handleError version m)))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (MutableConnState peerAddr handle handleError version m
 -> InspectMonad
      m (ConnectionState peerAddr handle handleError version m))
-> ConnectionManagerState peerAddr handle handleError version m
-> InspectMonad
     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 (Proxy m
-> TVar m (ConnectionState peerAddr handle handleError version m)
-> InspectMonad
     m (ConnectionState peerAddr handle handleError version m)
forall (m :: * -> *) (proxy :: (* -> *) -> *) a.
MonadInspectSTM m =>
proxy m -> TVar m a -> InspectMonad m a
forall (proxy :: (* -> *) -> *) a.
proxy m -> TVar m a -> InspectMonad m a
inspectTVar (Proxy m
forall {k} (t :: k). Proxy t
Proxy :: Proxy m) (TVar m (ConnectionState peerAddr handle handleError version m)
 -> InspectMonad
      m (ConnectionState peerAddr handle handleError version m))
-> (MutableConnState peerAddr handle handleError version m
    -> TVar m (ConnectionState peerAddr handle handleError version m))
-> MutableConnState peerAddr handle handleError version m
-> InspectMonad
     m (ConnectionState peerAddr handle handleError version m)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. StrictTVar
  m (ConnectionState peerAddr handle handleError version m)
-> TVar m (ConnectionState peerAddr handle handleError version m)
forall (m :: * -> *) a. StrictTVar m a -> LazyTVar m a
toLazyTVar (StrictTVar
   m (ConnectionState peerAddr handle handleError version m)
 -> TVar 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
-> TVar 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) ConnectionManagerState peerAddr handle handleError version m
st
            return (TraceString (show st'))

          stdGenVar <- newTVar (stdGen args)
          return (v, stdGenVar)

    let readState
          :: STM m (State.ConnMap peerAddr AbstractState)
        readState = StrictTMVar
  m (ConnectionManagerState peerAddr handle handleError version m)
-> STM
     m (ConnectionManagerState peerAddr handle handleError version m)
forall (m :: * -> *) a. MonadSTM m => StrictTMVar m a -> STM m a
readTMVar StrictTMVar
  m (ConnectionManagerState peerAddr handle handleError version m)
stateVar STM
  m (ConnectionManagerState peerAddr handle handleError version m)
-> (ConnectionManagerState peerAddr handle handleError version m
    -> STM m (ConnMap peerAddr AbstractState))
-> STM m (ConnMap peerAddr AbstractState)
forall a b. STM m a -> (a -> STM m b) -> STM m b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= ConnectionManagerState peerAddr handle handleError version m
-> STM m (ConnMap peerAddr AbstractState)
forall (m :: * -> *) peerAddr handle handleError version.
MonadSTM m =>
ConnectionManagerState peerAddr handle handleError version m
-> STM m (ConnMap peerAddr AbstractState)
State.readAbstractStateMap

        waitForOutboundDemotion
          :: ConnectionId peerAddr
          -> STM m ()
        waitForOutboundDemotion ConnectionId peerAddr
connId = do
          state <- STM m (ConnMap peerAddr AbstractState)
readState
          case State.lookup connId state of
            Maybe AbstractState
Nothing                        -> () -> STM m ()
forall a. a -> STM m a
forall (m :: * -> *) a. Monad m => a -> m a
return ()
            Just AbstractState
UnknownConnectionSt       -> () -> STM m ()
forall a. a -> STM m a
forall (m :: * -> *) a. Monad m => a -> m a
return ()
            Just InboundIdleSt {}          -> () -> STM m ()
forall a. a -> STM m a
forall (m :: * -> *) a. Monad m => a -> m a
return ()
            Just InboundSt {}              -> () -> STM m ()
forall a. a -> STM m a
forall (m :: * -> *) a. Monad m => a -> m a
return ()
            Just AbstractState
WaitRemoteIdleSt          -> () -> STM m ()
forall a. a -> STM m a
forall (m :: * -> *) a. Monad m => a -> m a
return ()
            Just AbstractState
TerminatedSt              -> () -> STM m ()
forall a. a -> STM m a
forall (m :: * -> *) a. Monad m => a -> m a
return ()
            Just (UnnegotiatedSt Provenance
Inbound)  -> () -> STM m ()
forall a. a -> STM m a
forall (m :: * -> *) a. Monad m => a -> m a
return ()
            Just (UnnegotiatedSt Provenance
Outbound) -> STM m ()
forall a. STM m a
forall (m :: * -> *) a. MonadSTM m => STM m a
retry
            Just AbstractState
ReservedOutboundSt        -> STM m ()
forall a. STM m a
forall (m :: * -> *) a. MonadSTM m => STM m a
retry
            Just AbstractState
OutboundUniSt             -> STM m ()
forall a. STM m a
forall (m :: * -> *) a. MonadSTM m => STM m a
retry
            Just OutboundIdleSt {}         -> STM m ()
forall a. STM m a
forall (m :: * -> *) a. MonadSTM m => STM m a
retry
            Just OutboundDupSt {}          -> STM m ()
forall a. STM m a
forall (m :: * -> *) a. MonadSTM m => STM m a
retry
            Just AbstractState
DuplexSt                  -> STM m ()
forall a. STM m a
forall (m :: * -> *) a. MonadSTM m => STM m a
retry
            Just AbstractState
TerminatingSt             -> STM m ()
forall a. STM m a
forall (m :: * -> *) a. MonadSTM m => STM m a
retry

        connectionManager :: ConnectionManager muxMode socket peerAddr
                                               handle handleError m
        connectionManager =
          case WithMuxTuple
  muxMode
  (ConnectionHandlerFn
     handlerTrace
     socket
     peerAddr
     handle
     handleError
     version
     versionData
     m)
connectionHandler of
            WithInitiatorMode ConnectionHandlerFn
  handlerTrace
  socket
  peerAddr
  handle
  handleError
  version
  versionData
  m
outboundHandler ->
              ConnectionManager {
                getConnectionManager :: WithMuxMode
  'InitiatorMode
  (OutboundConnectionManager
     'InitiatorMode socket peerAddr handle handleError m)
  (InboundConnectionManager
     'InitiatorMode socket peerAddr handle handleError m)
getConnectionManager =
                  OutboundConnectionManager
  'InitiatorMode socket peerAddr handle handleError m
-> WithMuxMode
     'InitiatorMode
     (OutboundConnectionManager
        'InitiatorMode socket peerAddr handle handleError m)
     (InboundConnectionManager
        'InitiatorMode socket peerAddr handle handleError m)
forall a b. a -> WithMuxMode 'InitiatorMode a b
WithInitiatorMode
                    OutboundConnectionManager {
                        ocmAcquireConnection :: AcquireOutboundConnection peerAddr handle handleError m
ocmAcquireConnection =
                          (?callStack::CallStack) =>
StrictTMVar
  m (ConnectionManagerState peerAddr handle handleError version m)
-> StrictTVar m StdGen
-> ConnectionHandlerFn
     handlerTrace
     socket
     peerAddr
     handle
     handleError
     version
     versionData
     m
-> AcquireOutboundConnection peerAddr handle handleError m
StrictTMVar
  m (ConnectionManagerState peerAddr handle handleError version m)
-> StrictTVar m StdGen
-> ConnectionHandlerFn
     handlerTrace
     socket
     peerAddr
     handle
     handleError
     version
     versionData
     m
-> AcquireOutboundConnection peerAddr handle handleError m
acquireOutboundConnectionImpl StrictTMVar
  m (ConnectionManagerState peerAddr handle handleError version m)
stateVar StrictTVar m StdGen
stdGenVar ConnectionHandlerFn
  handlerTrace
  socket
  peerAddr
  handle
  handleError
  version
  versionData
  m
outboundHandler,
                        ocmReleaseConnection :: ConnectionId peerAddr -> m (OperationResult AbstractState)
ocmReleaseConnection =
                          StrictTMVar
  m (ConnectionManagerState peerAddr handle handleError version m)
-> StrictTVar m StdGen
-> ConnectionId peerAddr
-> m (OperationResult AbstractState)
releaseOutboundConnectionImpl StrictTMVar
  m (ConnectionManagerState peerAddr handle handleError version m)
stateVar StrictTVar m StdGen
stdGenVar
                      },
                STM m (ConnMap peerAddr AbstractState)
readState :: STM m (ConnMap peerAddr AbstractState)
readState :: STM m (ConnMap peerAddr AbstractState)
readState,
                ConnectionId peerAddr -> STM m ()
waitForOutboundDemotion :: ConnectionId peerAddr -> STM m ()
waitForOutboundDemotion :: ConnectionId peerAddr -> STM m ()
waitForOutboundDemotion
              }

            WithResponderMode ConnectionHandlerFn
  handlerTrace
  socket
  peerAddr
  handle
  handleError
  version
  versionData
  m
inboundHandler ->
              ConnectionManager {
                getConnectionManager :: WithMuxMode
  'ResponderMode
  (OutboundConnectionManager
     'ResponderMode socket peerAddr handle handleError m)
  (InboundConnectionManager
     'ResponderMode socket peerAddr handle handleError m)
getConnectionManager =
                  InboundConnectionManager
  'ResponderMode socket peerAddr handle handleError m
-> WithMuxMode
     'ResponderMode
     (OutboundConnectionManager
        'ResponderMode socket peerAddr handle handleError m)
     (InboundConnectionManager
        'ResponderMode socket peerAddr handle handleError m)
forall b a. b -> WithMuxMode 'ResponderMode a b
WithResponderMode
                    InboundConnectionManager {
                        icmIncludeConnection :: IncludeInboundConnection socket peerAddr handle handleError m
icmIncludeConnection =
                          (?callStack::CallStack) =>
StrictTMVar
  m (ConnectionManagerState peerAddr handle handleError version m)
-> ConnectionHandlerFn
     handlerTrace
     socket
     peerAddr
     handle
     handleError
     version
     versionData
     m
-> IncludeInboundConnection socket peerAddr handle handleError m
StrictTMVar
  m (ConnectionManagerState peerAddr handle handleError version m)
-> ConnectionHandlerFn
     handlerTrace
     socket
     peerAddr
     handle
     handleError
     version
     versionData
     m
-> IncludeInboundConnection socket peerAddr handle handleError m
includeInboundConnectionImpl StrictTMVar
  m (ConnectionManagerState peerAddr handle handleError version m)
stateVar ConnectionHandlerFn
  handlerTrace
  socket
  peerAddr
  handle
  handleError
  version
  versionData
  m
inboundHandler,
                        icmReleaseConnection :: ConnectionId peerAddr -> m (OperationResult DemotedToColdRemoteTr)
icmReleaseConnection =
                          StrictTMVar
  m (ConnectionManagerState peerAddr handle handleError version m)
-> ConnectionId peerAddr
-> m (OperationResult DemotedToColdRemoteTr)
releaseInboundConnectionImpl StrictTMVar
  m (ConnectionManagerState peerAddr handle handleError version m)
stateVar,
                        icmPromotedToWarmRemote :: ConnectionId peerAddr -> m (OperationResult AbstractState)
icmPromotedToWarmRemote =
                          StrictTMVar
  m (ConnectionManagerState peerAddr handle handleError version m)
-> StrictTVar m StdGen
-> ConnectionId peerAddr
-> m (OperationResult AbstractState)
promotedToWarmRemoteImpl StrictTMVar
  m (ConnectionManagerState peerAddr handle handleError version m)
stateVar StrictTVar m StdGen
stdGenVar,
                        icmDemotedToColdRemote :: ConnectionId peerAddr -> m (OperationResult AbstractState)
icmDemotedToColdRemote =
                          StrictTMVar
  m (ConnectionManagerState peerAddr handle handleError version m)
-> ConnectionId peerAddr -> m (OperationResult AbstractState)
demotedToColdRemoteImpl StrictTMVar
  m (ConnectionManagerState peerAddr handle handleError version m)
stateVar,
                        icmNumberOfConnections :: STM m Int
icmNumberOfConnections =
                          StrictTMVar
  m (ConnectionManagerState peerAddr handle handleError version m)
-> STM
     m (ConnectionManagerState peerAddr handle handleError version m)
forall (m :: * -> *) a. MonadSTM m => StrictTMVar m a -> STM m a
readTMVar StrictTMVar
  m (ConnectionManagerState peerAddr handle handleError version m)
stateVar STM
  m (ConnectionManagerState peerAddr handle handleError version m)
-> (ConnectionManagerState peerAddr handle handleError version m
    -> STM m Int)
-> STM m Int
forall a b. STM m a -> (a -> STM m b) -> STM m b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= ConnectionManagerState peerAddr handle handleError version m
-> STM m Int
countIncomingConnections
                      },
                STM m (ConnMap peerAddr AbstractState)
readState :: STM m (ConnMap peerAddr AbstractState)
readState :: STM m (ConnMap peerAddr AbstractState)
readState,
                ConnectionId peerAddr -> STM m ()
waitForOutboundDemotion :: ConnectionId peerAddr -> STM m ()
waitForOutboundDemotion :: ConnectionId peerAddr -> STM m ()
waitForOutboundDemotion
              }

            WithInitiatorResponderMode ConnectionHandlerFn
  handlerTrace
  socket
  peerAddr
  handle
  handleError
  version
  versionData
  m
outboundHandler ConnectionHandlerFn
  handlerTrace
  socket
  peerAddr
  handle
  handleError
  version
  versionData
  m
inboundHandler ->
              ConnectionManager {
                getConnectionManager :: WithMuxMode
  'InitiatorResponderMode
  (OutboundConnectionManager
     'InitiatorResponderMode socket peerAddr handle handleError m)
  (InboundConnectionManager
     'InitiatorResponderMode socket peerAddr handle handleError m)
getConnectionManager =
                  OutboundConnectionManager
  'InitiatorResponderMode socket peerAddr handle handleError m
-> InboundConnectionManager
     'InitiatorResponderMode socket peerAddr handle handleError m
-> WithMuxMode
     'InitiatorResponderMode
     (OutboundConnectionManager
        'InitiatorResponderMode socket peerAddr handle handleError m)
     (InboundConnectionManager
        'InitiatorResponderMode socket peerAddr handle handleError m)
forall a b. a -> b -> WithMuxMode 'InitiatorResponderMode a b
WithInitiatorResponderMode
                    OutboundConnectionManager {
                        ocmAcquireConnection :: AcquireOutboundConnection peerAddr handle handleError m
ocmAcquireConnection =
                          (?callStack::CallStack) =>
StrictTMVar
  m (ConnectionManagerState peerAddr handle handleError version m)
-> StrictTVar m StdGen
-> ConnectionHandlerFn
     handlerTrace
     socket
     peerAddr
     handle
     handleError
     version
     versionData
     m
-> AcquireOutboundConnection peerAddr handle handleError m
StrictTMVar
  m (ConnectionManagerState peerAddr handle handleError version m)
-> StrictTVar m StdGen
-> ConnectionHandlerFn
     handlerTrace
     socket
     peerAddr
     handle
     handleError
     version
     versionData
     m
-> AcquireOutboundConnection peerAddr handle handleError m
acquireOutboundConnectionImpl StrictTMVar
  m (ConnectionManagerState peerAddr handle handleError version m)
stateVar StrictTVar m StdGen
stdGenVar ConnectionHandlerFn
  handlerTrace
  socket
  peerAddr
  handle
  handleError
  version
  versionData
  m
outboundHandler,
                        ocmReleaseConnection :: ConnectionId peerAddr -> m (OperationResult AbstractState)
ocmReleaseConnection =
                          StrictTMVar
  m (ConnectionManagerState peerAddr handle handleError version m)
-> StrictTVar m StdGen
-> ConnectionId peerAddr
-> m (OperationResult AbstractState)
releaseOutboundConnectionImpl StrictTMVar
  m (ConnectionManagerState peerAddr handle handleError version m)
stateVar StrictTVar m StdGen
stdGenVar
                      }
                    InboundConnectionManager {
                        icmIncludeConnection :: IncludeInboundConnection socket peerAddr handle handleError m
icmIncludeConnection =
                          (?callStack::CallStack) =>
StrictTMVar
  m (ConnectionManagerState peerAddr handle handleError version m)
-> ConnectionHandlerFn
     handlerTrace
     socket
     peerAddr
     handle
     handleError
     version
     versionData
     m
-> IncludeInboundConnection socket peerAddr handle handleError m
StrictTMVar
  m (ConnectionManagerState peerAddr handle handleError version m)
-> ConnectionHandlerFn
     handlerTrace
     socket
     peerAddr
     handle
     handleError
     version
     versionData
     m
-> IncludeInboundConnection socket peerAddr handle handleError m
includeInboundConnectionImpl StrictTMVar
  m (ConnectionManagerState peerAddr handle handleError version m)
stateVar ConnectionHandlerFn
  handlerTrace
  socket
  peerAddr
  handle
  handleError
  version
  versionData
  m
inboundHandler,
                        icmReleaseConnection :: ConnectionId peerAddr -> m (OperationResult DemotedToColdRemoteTr)
icmReleaseConnection =
                          StrictTMVar
  m (ConnectionManagerState peerAddr handle handleError version m)
-> ConnectionId peerAddr
-> m (OperationResult DemotedToColdRemoteTr)
releaseInboundConnectionImpl StrictTMVar
  m (ConnectionManagerState peerAddr handle handleError version m)
stateVar,
                        icmPromotedToWarmRemote :: ConnectionId peerAddr -> m (OperationResult AbstractState)
icmPromotedToWarmRemote =
                          StrictTMVar
  m (ConnectionManagerState peerAddr handle handleError version m)
-> StrictTVar m StdGen
-> ConnectionId peerAddr
-> m (OperationResult AbstractState)
promotedToWarmRemoteImpl StrictTMVar
  m (ConnectionManagerState peerAddr handle handleError version m)
stateVar StrictTVar m StdGen
stdGenVar,
                        icmDemotedToColdRemote :: ConnectionId peerAddr -> m (OperationResult AbstractState)
icmDemotedToColdRemote =
                          StrictTMVar
  m (ConnectionManagerState peerAddr handle handleError version m)
-> ConnectionId peerAddr -> m (OperationResult AbstractState)
demotedToColdRemoteImpl StrictTMVar
  m (ConnectionManagerState peerAddr handle handleError version m)
stateVar,
                        icmNumberOfConnections :: STM m Int
icmNumberOfConnections =
                          StrictTMVar
  m (ConnectionManagerState peerAddr handle handleError version m)
-> STM
     m (ConnectionManagerState peerAddr handle handleError version m)
forall (m :: * -> *) a. MonadSTM m => StrictTMVar m a -> STM m a
readTMVar StrictTMVar
  m (ConnectionManagerState peerAddr handle handleError version m)
stateVar STM
  m (ConnectionManagerState peerAddr handle handleError version m)
-> (ConnectionManagerState peerAddr handle handleError version m
    -> STM m Int)
-> STM m Int
forall a b. STM m a -> (a -> STM m b) -> STM m b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= ConnectionManagerState peerAddr handle handleError version m
-> STM m Int
countIncomingConnections
                      },
                STM m (ConnMap peerAddr AbstractState)
readState :: STM m (ConnMap peerAddr AbstractState)
readState :: STM m (ConnMap peerAddr AbstractState)
readState,
                ConnectionId peerAddr -> STM m ()
waitForOutboundDemotion :: ConnectionId peerAddr -> STM m ()
waitForOutboundDemotion :: ConnectionId peerAddr -> STM m ()
waitForOutboundDemotion
              }

    k connectionManager
      -- Since this exception handler is blocking it might receive exceptions
      -- during its execution, which we want to avoid, so we wrap it around
      -- uninterruptibleMask_.
      `finally` uninterruptibleMask_ (do
        traceWith tracer TrShutdown

        state <- atomically $ readTMVar stateVar
        -- Spawning one thread for each connection cleanup avoids spending time
        -- waiting for locks and cleanup logic that could delay closing the
        -- connections and making us not respecting certain timeouts.
        asyncs <- State.traverseMaybe
          (\MutableConnState { ConnStateId
connStateId :: ConnStateId
connStateId :: forall peerAddr handle handleError version (m :: * -> *).
MutableConnState peerAddr handle handleError version m
-> ConnStateId
connStateId, StrictTVar
  m (ConnectionState peerAddr handle handleError version m)
connVar :: 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)
connVar } -> do
            -- cleanup handler for that thread will close socket associated
            -- with the thread.  We put each connection in 'TerminatedState' to
            -- try that none of the connection threads will enter
            -- 'TerminatingState' (and thus delay shutdown for 'tcp_WAIT_TIME'
            -- seconds) when receiving the 'AsyncCancelled' exception. However,
            -- we can have a race between the finally handler and the `cleanup`
            -- callback. If the finally block loses the race, the received
            -- 'AsyncCancelled' should interrupt the 'threadDelay'.
            --
            (connState, trT, trU , shouldTraceTerminated, shouldTraceUnknown)
              <- STM
  m
  (ConnectionState peerAddr handle handleError version m,
   TransitionTrace
     ConnStateId
     (ConnectionState peerAddr handle handleError version m),
   TransitionTrace
     ConnStateId
     (ConnectionState peerAddr handle handleError version m),
   Bool, Bool)
-> m (ConnectionState peerAddr handle handleError version m,
      TransitionTrace
        ConnStateId
        (ConnectionState peerAddr handle handleError version m),
      TransitionTrace
        ConnStateId
        (ConnectionState peerAddr handle handleError version m),
      Bool, Bool)
forall a. (?callStack::CallStack) => STM m a -> m a
forall (m :: * -> *) a.
(MonadSTM m, ?callStack::CallStack) =>
STM m a -> m a
atomically (STM
   m
   (ConnectionState peerAddr handle handleError version m,
    TransitionTrace
      ConnStateId
      (ConnectionState peerAddr handle handleError version m),
    TransitionTrace
      ConnStateId
      (ConnectionState peerAddr handle handleError version m),
    Bool, Bool)
 -> m (ConnectionState peerAddr handle handleError version m,
       TransitionTrace
         ConnStateId
         (ConnectionState peerAddr handle handleError version m),
       TransitionTrace
         ConnStateId
         (ConnectionState peerAddr handle handleError version m),
       Bool, Bool))
-> STM
     m
     (ConnectionState peerAddr handle handleError version m,
      TransitionTrace
        ConnStateId
        (ConnectionState peerAddr handle handleError version m),
      TransitionTrace
        ConnStateId
        (ConnectionState peerAddr handle handleError version m),
      Bool, Bool)
-> m (ConnectionState peerAddr handle handleError version m,
      TransitionTrace
        ConnStateId
        (ConnectionState peerAddr handle handleError version m),
      TransitionTrace
        ConnStateId
        (ConnectionState peerAddr handle handleError version m),
      Bool, Bool)
forall a b. (a -> b) -> a -> b
$ do
                  connState <- 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)
connVar
                  let connState'            = Maybe handleError
-> ConnectionState peerAddr handle handleError version m
forall peerAddr handle handleError version (m :: * -> *).
Maybe handleError
-> ConnectionState peerAddr handle handleError version m
TerminatedState Maybe handleError
forall a. Maybe a
Nothing
                      trT                   =
                        ConnStateId
-> Transition'
     (MaybeUnknown
        (ConnectionState peerAddr handle handleError version m))
-> TransitionTrace
     ConnStateId (ConnectionState peerAddr handle handleError version m)
forall id state.
id -> Transition' state -> TransitionTrace' id state
TransitionTrace ConnStateId
connStateId (ConnectionState peerAddr handle handleError version m
-> ConnectionState peerAddr handle handleError version m
-> Transition'
     (MaybeUnknown
        (ConnectionState peerAddr handle handleError version m))
forall state. state -> state -> Transition state
mkTransition ConnectionState peerAddr handle handleError version m
connState ConnectionState peerAddr handle handleError version m
forall {peerAddr} {handle} {handleError} {version} {m :: * -> *}.
ConnectionState peerAddr handle handleError version m
connState')
                      absConnState          = MaybeUnknown
  (ConnectionState peerAddr handle handleError version m)
-> AbstractState
forall muxMode peerAddr m a (b :: * -> *).
MaybeUnknown (ConnectionState muxMode peerAddr m a b)
-> AbstractState
State.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
connState)
                      shouldTraceTerminated = AbstractState
absConnState AbstractState -> AbstractState -> Bool
forall a. Eq a => a -> a -> Bool
/= AbstractState
TerminatedSt
                      shouldTraceUnknown    = AbstractState
absConnState AbstractState -> AbstractState -> Bool
forall a. Eq a => a -> a -> Bool
== AbstractState
ReservedOutboundSt
                      trU = ConnStateId
-> Transition'
     (MaybeUnknown
        (ConnectionState peerAddr handle handleError version m))
-> TransitionTrace
     ConnStateId (ConnectionState peerAddr handle handleError version m)
forall id state.
id -> Transition' state -> TransitionTrace' id state
TransitionTrace
                              ConnStateId
connStateId
                              (Transition { fromState :: MaybeUnknown
  (ConnectionState peerAddr handle handleError version m)
fromState = 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
forall {peerAddr} {handle} {handleError} {version} {m :: * -> *}.
ConnectionState peerAddr handle handleError version m
connState'
                                          , toState :: MaybeUnknown
  (ConnectionState peerAddr handle handleError version m)
toState   = MaybeUnknown
  (ConnectionState peerAddr handle handleError version m)
forall state. MaybeUnknown state
Unknown
                                          })

                  writeTVar connVar connState'
                  return (connState, trT, trU
                         , shouldTraceTerminated, shouldTraceUnknown)

            when shouldTraceTerminated $ do
              traceWith trTracer trT

              -- If an Async exception is received after a connection gets set
              -- to ReservedOutboundSt, BUT after a connect call is made and,
              -- therefore still does not have a connection handler thread, we
              -- should trace the unknown transition as well.
              when shouldTraceUnknown $
                traceWith trTracer trU

            -- using 'throwTo' here, since we want to block only until connection
            -- handler thread receives an exception so as to not take up extra
            -- time and making us go above timeout schedules.
            traverse
              (\Async m ()
thread -> do
                ThreadId m -> AsyncCancelled -> m ()
forall e. Exception e => ThreadId m -> e -> m ()
forall (m :: * -> *) e.
(MonadFork m, Exception e) =>
ThreadId m -> e -> m ()
throwTo (Async m () -> ThreadId m
forall a. Async m a -> ThreadId m
forall (m :: * -> *) a. MonadAsync m => Async m a -> ThreadId m
asyncThreadId Async m ()
thread) AsyncCancelled
AsyncCancelled
                Async m () -> m (Async m ())
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Async m ()
thread
              )
              (getConnThread connState)
          ) state

        atomically $ runLastToFinishM
                   $ foldMap (LastToFinishM . void <$> waitCatchSTM) asyncs
      )
  where
    traceCounters :: StrictTMVar m (ConnectionManagerState peerAddr handle handleError version m) -> m ()
    traceCounters :: StrictTMVar
  m (ConnectionManagerState peerAddr handle handleError version m)
-> m ()
traceCounters StrictTMVar
  m (ConnectionManagerState peerAddr handle handleError version m)
stateVar = do
      state <- STM
  m
  (ConnMap
     peerAddr (ConnectionState peerAddr handle handleError version m))
-> m (ConnMap
        peerAddr (ConnectionState peerAddr handle handleError version m))
forall a. (?callStack::CallStack) => STM m a -> m a
forall (m :: * -> *) a.
(MonadSTM m, ?callStack::CallStack) =>
STM m a -> m a
atomically (STM
   m
   (ConnMap
      peerAddr (ConnectionState peerAddr handle handleError version m))
 -> m (ConnMap
         peerAddr (ConnectionState peerAddr handle handleError version m)))
-> STM
     m
     (ConnMap
        peerAddr (ConnectionState peerAddr handle handleError version m))
-> m (ConnMap
        peerAddr (ConnectionState peerAddr handle handleError version m))
forall a b. (a -> b) -> a -> b
$ StrictTMVar
  m (ConnectionManagerState peerAddr handle handleError version m)
-> STM
     m (ConnectionManagerState peerAddr handle handleError version m)
forall (m :: * -> *) a. MonadSTM m => StrictTMVar m a -> STM m a
readTMVar StrictTMVar
  m (ConnectionManagerState peerAddr handle handleError version m)
stateVar STM
  m (ConnectionManagerState peerAddr handle handleError version m)
-> (ConnectionManagerState peerAddr handle handleError version m
    -> STM
         m
         (ConnMap
            peerAddr (ConnectionState peerAddr handle handleError version m)))
-> STM
     m
     (ConnMap
        peerAddr (ConnectionState peerAddr handle handleError version m))
forall a b. STM m a -> (a -> STM m b) -> STM m b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= ConnectionManagerState peerAddr handle handleError version m
-> STM
     m
     (ConnMap
        peerAddr (ConnectionState peerAddr handle handleError version m))
forall (m :: * -> *) peerAddr handle handleError version.
MonadSTM m =>
ConnectionManagerState peerAddr handle handleError version m
-> STM
     m
     (ConnMap
        peerAddr (ConnectionState peerAddr handle handleError version m))
State.readConnectionStates
      traceWith tracer (TrConnectionManagerCounters (connectionManagerStateToCounters state))

    countIncomingConnections
        :: ConnectionManagerState peerAddr handle handleError version m
        -> STM m Int
    countIncomingConnections :: ConnectionManagerState peerAddr handle handleError version m
-> STM m Int
countIncomingConnections ConnectionManagerState peerAddr handle handleError version m
st =
          ConnectionManagerCounters -> Int
inboundConns
        (ConnectionManagerCounters -> Int)
-> (ConnMap
      peerAddr (ConnectionState peerAddr handle handleError version m)
    -> ConnectionManagerCounters)
-> ConnMap
     peerAddr (ConnectionState peerAddr handle handleError version m)
-> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ConnMap
  peerAddr (ConnectionState peerAddr handle handleError version m)
-> ConnectionManagerCounters
forall peerAddr handle handleError version (m :: * -> *).
ConnMap
  peerAddr (ConnectionState peerAddr handle handleError version m)
-> ConnectionManagerCounters
connectionManagerStateToCounters
      (ConnMap
   peerAddr (ConnectionState peerAddr handle handleError version m)
 -> Int)
-> STM
     m
     (ConnMap
        peerAddr (ConnectionState peerAddr handle handleError version m))
-> STM m Int
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ConnectionManagerState peerAddr handle handleError version m
-> STM
     m
     (ConnMap
        peerAddr (ConnectionState peerAddr handle handleError version m))
forall (m :: * -> *) peerAddr handle handleError version.
MonadSTM m =>
ConnectionManagerState peerAddr handle handleError version m
-> STM
     m
     (ConnMap
        peerAddr (ConnectionState peerAddr handle handleError version m))
State.readConnectionStates ConnectionManagerState peerAddr handle handleError version m
st


    -- Fork connection thread.
    --
    -- TODO: We could probably elegantly eliminate 'PromiseWriter', now that we use
    -- MonadFix.
    forkConnectionHandler
      :: (versionData -> versionData)
      -> StrictTMVar m (ConnectionManagerState peerAddr handle handleError version m)
      -> MutableConnState peerAddr handle handleError version m
      -> socket
      -> ConnectionId peerAddr
      -> PromiseWriter m (Either handleError (HandshakeConnectionResult handle (version, versionData)))
      -> ConnectionHandlerFn handlerTrace socket peerAddr handle handleError version versionData m
      -> m (Async m ())
    forkConnectionHandler :: (versionData -> versionData)
-> StrictTMVar
     m (ConnectionManagerState peerAddr handle handleError version m)
-> MutableConnState peerAddr handle handleError version m
-> socket
-> ConnectionId peerAddr
-> PromiseWriter
     m
     (Either
        handleError
        (HandshakeConnectionResult handle (version, versionData)))
-> ConnectionHandlerFn
     handlerTrace
     socket
     peerAddr
     handle
     handleError
     version
     versionData
     m
-> m (Async m ())
forkConnectionHandler versionData -> versionData
updateVersionDataFn StrictTMVar
  m (ConnectionManagerState peerAddr handle handleError version m)
stateVar
                          mutableConnState :: MutableConnState peerAddr handle handleError version m
mutableConnState@MutableConnState { ConnStateId
connStateId :: forall peerAddr handle handleError version (m :: * -> *).
MutableConnState peerAddr handle handleError version m
-> ConnStateId
connStateId :: ConnStateId
connStateId, StrictTVar
  m (ConnectionState peerAddr handle handleError version m)
connVar :: 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)
connVar }
                          socket
socket
                          ConnectionId peerAddr
connId
                          PromiseWriter
  m
  (Either
     handleError
     (HandshakeConnectionResult handle (version, versionData)))
writer
                          ConnectionHandlerFn
  handlerTrace
  socket
  peerAddr
  handle
  handleError
  version
  versionData
  m
handler =
        ((forall a. m a -> m a) -> m (Async m ())) -> m (Async m ())
forall b. ((forall a. m a -> m a) -> m b) -> m b
forall (m :: * -> *) b.
MonadMask m =>
((forall a. m a -> m a) -> m b) -> m b
mask (((forall a. m a -> m a) -> m (Async m ())) -> m (Async m ()))
-> ((forall a. m a -> m a) -> m (Async m ())) -> m (Async m ())
forall a b. (a -> b) -> a -> b
$ \forall a. m a -> m a
unmask -> m () -> m (Async m ())
forall a. m a -> m (Async m a)
forall (m :: * -> *) a. MonadAsync m => m a -> m (Async m a)
async (m () -> m (Async m ())) -> m () -> m (Async m ())
forall a b. (a -> b) -> a -> b
$ do
          MaskedAction m () -> (forall a. m a -> m a) -> m ()
forall (m :: * -> *) a.
MaskedAction m a -> (forall x. m x -> m x) -> m a
runWithUnmask
            (ConnectionHandlerFn
  handlerTrace
  socket
  peerAddr
  handle
  handleError
  version
  versionData
  m
handler versionData -> versionData
updateVersionDataFn socket
socket PromiseWriter
  m
  (Either
     handleError
     (HandshakeConnectionResult handle (version, versionData)))
writer
                     (ConnectionId peerAddr
-> handlerTrace -> Trace peerAddr handlerTrace
forall peerAddr handlerTrace.
ConnectionId peerAddr
-> handlerTrace -> Trace peerAddr handlerTrace
TrConnectionHandler ConnectionId peerAddr
connId (handlerTrace -> Trace peerAddr handlerTrace)
-> Tracer m (Trace peerAddr handlerTrace) -> Tracer m handlerTrace
forall a' a. (a' -> a) -> Tracer m a -> Tracer m a'
forall (f :: * -> *) a' a.
Contravariant f =>
(a' -> a) -> f a -> f a'
`contramap` Tracer m (Trace peerAddr handlerTrace)
tracer)
                     ConnectionId peerAddr
connId
                     (\DiffTime
bearerTimeout ->
                       MakeBearer m socket
-> DiffTime -> Tracer m Trace -> socket -> m (Bearer m)
forall (m :: * -> *) fd.
MakeBearer m fd -> DiffTime -> Tracer m Trace -> fd -> m (Bearer m)
getBearer MakeBearer m socket
makeBearer
                         DiffTime
bearerTimeout
                         (ConnectionId peerAddr
-> Trace -> WithBearer (ConnectionId peerAddr) Trace
forall peerid a. peerid -> a -> WithBearer peerid a
Mx.WithBearer ConnectionId peerAddr
connId (Trace -> WithBearer (ConnectionId peerAddr) Trace)
-> Tracer m (WithBearer (ConnectionId peerAddr) Trace)
-> Tracer m Trace
forall a' a. (a' -> a) -> Tracer m a -> Tracer m a'
forall (f :: * -> *) a' a.
Contravariant f =>
(a' -> a) -> f a -> f a'
`contramap` Tracer m (WithBearer (ConnectionId peerAddr) Trace)
muxTracer)))
            m x -> m x
forall a. m a -> m a
unmask
          m () -> m () -> m ()
forall a b. m a -> m b -> m a
forall (m :: * -> *) a b. MonadThrow m => m a -> m b -> m a
`finally` m ()
cleanup
      where
        cleanup :: m ()
        cleanup :: m ()
cleanup =
          -- We must ensure that we update 'connVar',
          -- `acquireOutboundConnection` might be blocked on it awaiting for:
          -- - handshake negotiation; or
          -- - `Terminate: TerminatingState → TerminatedState` transition.
          -- That's why we use 'uninterruptibleMask'. Note that this cleanup
          -- function after all is interruptible, because we unmask async
          -- exceptions around 'threadDelay', but even if an async exception
          -- hits there we will update `connVar`.
          ((forall a. m a -> m a) -> m ()) -> m ()
forall b. ((forall a. m a -> m a) -> m b) -> m b
forall (m :: * -> *) b.
MonadMask m =>
((forall a. m a -> m a) -> m b) -> m b
uninterruptibleMask (((forall a. m a -> m a) -> m ()) -> m ())
-> ((forall a. m a -> m a) -> m ()) -> m ()
forall a b. (a -> b) -> a -> b
$ \forall a. m a -> m a
unmask -> do
            Tracer m (Trace peerAddr handlerTrace)
-> Trace peerAddr handlerTrace -> m ()
forall (m :: * -> *) a. Tracer m a -> a -> m ()
traceWith Tracer m (Trace peerAddr handlerTrace)
tracer (ConnectionId peerAddr -> Trace peerAddr handlerTrace
forall peerAddr handlerTrace.
ConnectionId peerAddr -> Trace peerAddr handlerTrace
TrConnectionCleanup ConnectionId peerAddr
connId)
            mbTransition <- StrictTMVar
  m (ConnectionManagerState peerAddr handle handleError version m)
-> (ConnectionManagerState peerAddr handle handleError version m
    -> m (ConnectionManagerState peerAddr handle handleError version m,
          Maybe
            (Transition'
               (MaybeUnknown
                  (ConnectionState peerAddr handle handleError version m)))))
-> m (Maybe
        (Transition'
           (MaybeUnknown
              (ConnectionState peerAddr handle handleError version m))))
forall (m :: * -> *) a b.
(MonadEvaluate m, MonadMask m, MonadSTM m) =>
StrictTMVar m a -> (a -> m (a, b)) -> m b
modifyTMVar StrictTMVar
  m (ConnectionManagerState peerAddr handle handleError version m)
stateVar ((ConnectionManagerState peerAddr handle handleError version m
  -> m (ConnectionManagerState peerAddr handle handleError version m,
        Maybe
          (Transition'
             (MaybeUnknown
                (ConnectionState peerAddr handle handleError version m)))))
 -> m (Maybe
         (Transition'
            (MaybeUnknown
               (ConnectionState peerAddr handle handleError version m)))))
-> (ConnectionManagerState peerAddr handle handleError version m
    -> m (ConnectionManagerState peerAddr handle handleError version m,
          Maybe
            (Transition'
               (MaybeUnknown
                  (ConnectionState peerAddr handle handleError version m)))))
-> m (Maybe
        (Transition'
           (MaybeUnknown
              (ConnectionState peerAddr handle handleError version m))))
forall a b. (a -> b) -> a -> b
$ \ConnectionManagerState peerAddr handle handleError version m
state -> do
              eTransition <- STM
  m
  (Either
     (Maybe
        (TransitionTrace
           ConnStateId
           (ConnectionState peerAddr handle handleError version m)))
     (Transition'
        (MaybeUnknown
           (ConnectionState peerAddr handle handleError version m))))
-> m (Either
        (Maybe
           (TransitionTrace
              ConnStateId
              (ConnectionState peerAddr handle handleError version m)))
        (Transition'
           (MaybeUnknown
              (ConnectionState peerAddr handle handleError version m))))
forall a. (?callStack::CallStack) => STM m a -> m a
forall (m :: * -> *) a.
(MonadSTM m, ?callStack::CallStack) =>
STM m a -> m a
atomically (STM
   m
   (Either
      (Maybe
         (TransitionTrace
            ConnStateId
            (ConnectionState peerAddr handle handleError version m)))
      (Transition'
         (MaybeUnknown
            (ConnectionState peerAddr handle handleError version m))))
 -> m (Either
         (Maybe
            (TransitionTrace
               ConnStateId
               (ConnectionState peerAddr handle handleError version m)))
         (Transition'
            (MaybeUnknown
               (ConnectionState peerAddr handle handleError version m)))))
-> STM
     m
     (Either
        (Maybe
           (TransitionTrace
              ConnStateId
              (ConnectionState peerAddr handle handleError version m)))
        (Transition'
           (MaybeUnknown
              (ConnectionState peerAddr handle handleError version m))))
-> m (Either
        (Maybe
           (TransitionTrace
              ConnStateId
              (ConnectionState peerAddr handle handleError version m)))
        (Transition'
           (MaybeUnknown
              (ConnectionState peerAddr handle handleError version m))))
forall a b. (a -> b) -> a -> b
$ do
                connState <- 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)
connVar
                let connState' = Maybe handleError
-> ConnectionState peerAddr handle handleError version m
forall peerAddr handle handleError version (m :: * -> *).
Maybe handleError
-> ConnectionState peerAddr handle handleError version m
TerminatedState Maybe handleError
forall a. Maybe a
Nothing
                    transition = ConnectionState peerAddr handle handleError version m
-> ConnectionState peerAddr handle handleError version m
-> Transition'
     (MaybeUnknown
        (ConnectionState peerAddr handle handleError version m))
forall state. state -> state -> Transition state
mkTransition ConnectionState peerAddr handle handleError version m
connState ConnectionState peerAddr handle handleError version m
forall {peerAddr} {handle} {handleError} {version} {m :: * -> *}.
ConnectionState peerAddr handle handleError version m
connState'
                    transitionTrace = ConnStateId
-> Transition'
     (MaybeUnknown
        (ConnectionState peerAddr handle handleError version m))
-> TransitionTrace
     ConnStateId (ConnectionState peerAddr handle handleError version m)
forall id state.
id -> Transition' state -> TransitionTrace' id state
TransitionTrace ConnStateId
connStateId Transition'
  (MaybeUnknown
     (ConnectionState peerAddr handle handleError version m))
transition
                case connState of
                  ConnectionState peerAddr handle handleError version m
ReservedOutboundState -> do
                    StrictTVar
  m (ConnectionState peerAddr handle handleError version m)
-> ConnectionState peerAddr handle handleError version m
-> STM m ()
forall (m :: * -> *) a.
MonadSTM m =>
StrictTVar m a -> a -> STM m ()
writeTVar StrictTVar
  m (ConnectionState peerAddr handle handleError version m)
connVar ConnectionState peerAddr handle handleError version m
forall {peerAddr} {handle} {handleError} {version} {m :: * -> *}.
ConnectionState peerAddr handle handleError version m
connState'
                    Either
  (Maybe
     (TransitionTrace
        ConnStateId
        (ConnectionState peerAddr handle handleError version m)))
  (Transition'
     (MaybeUnknown
        (ConnectionState peerAddr handle handleError version m)))
-> STM
     m
     (Either
        (Maybe
           (TransitionTrace
              ConnStateId
              (ConnectionState peerAddr handle handleError version m)))
        (Transition'
           (MaybeUnknown
              (ConnectionState peerAddr handle handleError version m))))
forall a. a -> STM m a
forall (m :: * -> *) a. Monad m => a -> m a
return (Either
   (Maybe
      (TransitionTrace
         ConnStateId
         (ConnectionState peerAddr handle handleError version m)))
   (Transition'
      (MaybeUnknown
         (ConnectionState peerAddr handle handleError version m)))
 -> STM
      m
      (Either
         (Maybe
            (TransitionTrace
               ConnStateId
               (ConnectionState peerAddr handle handleError version m)))
         (Transition'
            (MaybeUnknown
               (ConnectionState peerAddr handle handleError version m)))))
-> Either
     (Maybe
        (TransitionTrace
           ConnStateId
           (ConnectionState peerAddr handle handleError version m)))
     (Transition'
        (MaybeUnknown
           (ConnectionState peerAddr handle handleError version m)))
-> STM
     m
     (Either
        (Maybe
           (TransitionTrace
              ConnStateId
              (ConnectionState peerAddr handle handleError version m)))
        (Transition'
           (MaybeUnknown
              (ConnectionState peerAddr handle handleError version m))))
forall a b. (a -> b) -> a -> b
$ Maybe
  (TransitionTrace
     ConnStateId
     (ConnectionState peerAddr handle handleError version m))
-> Either
     (Maybe
        (TransitionTrace
           ConnStateId
           (ConnectionState peerAddr handle handleError version m)))
     (Transition'
        (MaybeUnknown
           (ConnectionState peerAddr handle handleError version m)))
forall a b. a -> Either a b
Left (TransitionTrace
  ConnStateId (ConnectionState peerAddr handle handleError version m)
-> Maybe
     (TransitionTrace
        ConnStateId
        (ConnectionState peerAddr handle handleError version m))
forall a. a -> Maybe a
Just TransitionTrace
  ConnStateId (ConnectionState peerAddr handle handleError version m)
transitionTrace)
                  UnnegotiatedState {} -> do
                    StrictTVar
  m (ConnectionState peerAddr handle handleError version m)
-> ConnectionState peerAddr handle handleError version m
-> STM m ()
forall (m :: * -> *) a.
MonadSTM m =>
StrictTVar m a -> a -> STM m ()
writeTVar StrictTVar
  m (ConnectionState peerAddr handle handleError version m)
connVar ConnectionState peerAddr handle handleError version m
forall {peerAddr} {handle} {handleError} {version} {m :: * -> *}.
ConnectionState peerAddr handle handleError version m
connState'
                    Either
  (Maybe
     (TransitionTrace
        ConnStateId
        (ConnectionState peerAddr handle handleError version m)))
  (Transition'
     (MaybeUnknown
        (ConnectionState peerAddr handle handleError version m)))
-> STM
     m
     (Either
        (Maybe
           (TransitionTrace
              ConnStateId
              (ConnectionState peerAddr handle handleError version m)))
        (Transition'
           (MaybeUnknown
              (ConnectionState peerAddr handle handleError version m))))
forall a. a -> STM m a
forall (m :: * -> *) a. Monad m => a -> m a
return (Either
   (Maybe
      (TransitionTrace
         ConnStateId
         (ConnectionState peerAddr handle handleError version m)))
   (Transition'
      (MaybeUnknown
         (ConnectionState peerAddr handle handleError version m)))
 -> STM
      m
      (Either
         (Maybe
            (TransitionTrace
               ConnStateId
               (ConnectionState peerAddr handle handleError version m)))
         (Transition'
            (MaybeUnknown
               (ConnectionState peerAddr handle handleError version m)))))
-> Either
     (Maybe
        (TransitionTrace
           ConnStateId
           (ConnectionState peerAddr handle handleError version m)))
     (Transition'
        (MaybeUnknown
           (ConnectionState peerAddr handle handleError version m)))
-> STM
     m
     (Either
        (Maybe
           (TransitionTrace
              ConnStateId
              (ConnectionState peerAddr handle handleError version m)))
        (Transition'
           (MaybeUnknown
              (ConnectionState peerAddr handle handleError version m))))
forall a b. (a -> b) -> a -> b
$ Maybe
  (TransitionTrace
     ConnStateId
     (ConnectionState peerAddr handle handleError version m))
-> Either
     (Maybe
        (TransitionTrace
           ConnStateId
           (ConnectionState peerAddr handle handleError version m)))
     (Transition'
        (MaybeUnknown
           (ConnectionState peerAddr handle handleError version m)))
forall a b. a -> Either a b
Left (TransitionTrace
  ConnStateId (ConnectionState peerAddr handle handleError version m)
-> Maybe
     (TransitionTrace
        ConnStateId
        (ConnectionState peerAddr handle handleError version m))
forall a. a -> Maybe a
Just TransitionTrace
  ConnStateId (ConnectionState peerAddr handle handleError version m)
transitionTrace)
                  OutboundUniState {} -> do
                    StrictTVar
  m (ConnectionState peerAddr handle handleError version m)
-> ConnectionState peerAddr handle handleError version m
-> STM m ()
forall (m :: * -> *) a.
MonadSTM m =>
StrictTVar m a -> a -> STM m ()
writeTVar StrictTVar
  m (ConnectionState peerAddr handle handleError version m)
connVar ConnectionState peerAddr handle handleError version m
forall {peerAddr} {handle} {handleError} {version} {m :: * -> *}.
ConnectionState peerAddr handle handleError version m
connState'
                    Either
  (Maybe
     (TransitionTrace
        ConnStateId
        (ConnectionState peerAddr handle handleError version m)))
  (Transition'
     (MaybeUnknown
        (ConnectionState peerAddr handle handleError version m)))
-> STM
     m
     (Either
        (Maybe
           (TransitionTrace
              ConnStateId
              (ConnectionState peerAddr handle handleError version m)))
        (Transition'
           (MaybeUnknown
              (ConnectionState peerAddr handle handleError version m))))
forall a. a -> STM m a
forall (m :: * -> *) a. Monad m => a -> m a
return (Either
   (Maybe
      (TransitionTrace
         ConnStateId
         (ConnectionState peerAddr handle handleError version m)))
   (Transition'
      (MaybeUnknown
         (ConnectionState peerAddr handle handleError version m)))
 -> STM
      m
      (Either
         (Maybe
            (TransitionTrace
               ConnStateId
               (ConnectionState peerAddr handle handleError version m)))
         (Transition'
            (MaybeUnknown
               (ConnectionState peerAddr handle handleError version m)))))
-> Either
     (Maybe
        (TransitionTrace
           ConnStateId
           (ConnectionState peerAddr handle handleError version m)))
     (Transition'
        (MaybeUnknown
           (ConnectionState peerAddr handle handleError version m)))
-> STM
     m
     (Either
        (Maybe
           (TransitionTrace
              ConnStateId
              (ConnectionState peerAddr handle handleError version m)))
        (Transition'
           (MaybeUnknown
              (ConnectionState peerAddr handle handleError version m))))
forall a b. (a -> b) -> a -> b
$ Maybe
  (TransitionTrace
     ConnStateId
     (ConnectionState peerAddr handle handleError version m))
-> Either
     (Maybe
        (TransitionTrace
           ConnStateId
           (ConnectionState peerAddr handle handleError version m)))
     (Transition'
        (MaybeUnknown
           (ConnectionState peerAddr handle handleError version m)))
forall a b. a -> Either a b
Left (TransitionTrace
  ConnStateId (ConnectionState peerAddr handle handleError version m)
-> Maybe
     (TransitionTrace
        ConnStateId
        (ConnectionState peerAddr handle handleError version m))
forall a. a -> Maybe a
Just TransitionTrace
  ConnStateId (ConnectionState peerAddr handle handleError version m)
transitionTrace)
                  OutboundDupState {} -> do
                    StrictTVar
  m (ConnectionState peerAddr handle handleError version m)
-> ConnectionState peerAddr handle handleError version m
-> STM m ()
forall (m :: * -> *) a.
MonadSTM m =>
StrictTVar m a -> a -> STM m ()
writeTVar StrictTVar
  m (ConnectionState peerAddr handle handleError version m)
connVar ConnectionState peerAddr handle handleError version m
forall {peerAddr} {handle} {handleError} {version} {m :: * -> *}.
ConnectionState peerAddr handle handleError version m
connState'
                    Either
  (Maybe
     (TransitionTrace
        ConnStateId
        (ConnectionState peerAddr handle handleError version m)))
  (Transition'
     (MaybeUnknown
        (ConnectionState peerAddr handle handleError version m)))
-> STM
     m
     (Either
        (Maybe
           (TransitionTrace
              ConnStateId
              (ConnectionState peerAddr handle handleError version m)))
        (Transition'
           (MaybeUnknown
              (ConnectionState peerAddr handle handleError version m))))
forall a. a -> STM m a
forall (m :: * -> *) a. Monad m => a -> m a
return (Either
   (Maybe
      (TransitionTrace
         ConnStateId
         (ConnectionState peerAddr handle handleError version m)))
   (Transition'
      (MaybeUnknown
         (ConnectionState peerAddr handle handleError version m)))
 -> STM
      m
      (Either
         (Maybe
            (TransitionTrace
               ConnStateId
               (ConnectionState peerAddr handle handleError version m)))
         (Transition'
            (MaybeUnknown
               (ConnectionState peerAddr handle handleError version m)))))
-> Either
     (Maybe
        (TransitionTrace
           ConnStateId
           (ConnectionState peerAddr handle handleError version m)))
     (Transition'
        (MaybeUnknown
           (ConnectionState peerAddr handle handleError version m)))
-> STM
     m
     (Either
        (Maybe
           (TransitionTrace
              ConnStateId
              (ConnectionState peerAddr handle handleError version m)))
        (Transition'
           (MaybeUnknown
              (ConnectionState peerAddr handle handleError version m))))
forall a b. (a -> b) -> a -> b
$ Maybe
  (TransitionTrace
     ConnStateId
     (ConnectionState peerAddr handle handleError version m))
-> Either
     (Maybe
        (TransitionTrace
           ConnStateId
           (ConnectionState peerAddr handle handleError version m)))
     (Transition'
        (MaybeUnknown
           (ConnectionState peerAddr handle handleError version m)))
forall a b. a -> Either a b
Left (TransitionTrace
  ConnStateId (ConnectionState peerAddr handle handleError version m)
-> Maybe
     (TransitionTrace
        ConnStateId
        (ConnectionState peerAddr handle handleError version m))
forall a. a -> Maybe a
Just TransitionTrace
  ConnStateId (ConnectionState peerAddr handle handleError version m)
transitionTrace)
                  OutboundIdleState {} -> do
                    StrictTVar
  m (ConnectionState peerAddr handle handleError version m)
-> ConnectionState peerAddr handle handleError version m
-> STM m ()
forall (m :: * -> *) a.
MonadSTM m =>
StrictTVar m a -> a -> STM m ()
writeTVar StrictTVar
  m (ConnectionState peerAddr handle handleError version m)
connVar ConnectionState peerAddr handle handleError version m
forall {peerAddr} {handle} {handleError} {version} {m :: * -> *}.
ConnectionState peerAddr handle handleError version m
connState'
                    Either
  (Maybe
     (TransitionTrace
        ConnStateId
        (ConnectionState peerAddr handle handleError version m)))
  (Transition'
     (MaybeUnknown
        (ConnectionState peerAddr handle handleError version m)))
-> STM
     m
     (Either
        (Maybe
           (TransitionTrace
              ConnStateId
              (ConnectionState peerAddr handle handleError version m)))
        (Transition'
           (MaybeUnknown
              (ConnectionState peerAddr handle handleError version m))))
forall a. a -> STM m a
forall (m :: * -> *) a. Monad m => a -> m a
return (Either
   (Maybe
      (TransitionTrace
         ConnStateId
         (ConnectionState peerAddr handle handleError version m)))
   (Transition'
      (MaybeUnknown
         (ConnectionState peerAddr handle handleError version m)))
 -> STM
      m
      (Either
         (Maybe
            (TransitionTrace
               ConnStateId
               (ConnectionState peerAddr handle handleError version m)))
         (Transition'
            (MaybeUnknown
               (ConnectionState peerAddr handle handleError version m)))))
-> Either
     (Maybe
        (TransitionTrace
           ConnStateId
           (ConnectionState peerAddr handle handleError version m)))
     (Transition'
        (MaybeUnknown
           (ConnectionState peerAddr handle handleError version m)))
-> STM
     m
     (Either
        (Maybe
           (TransitionTrace
              ConnStateId
              (ConnectionState peerAddr handle handleError version m)))
        (Transition'
           (MaybeUnknown
              (ConnectionState peerAddr handle handleError version m))))
forall a b. (a -> b) -> a -> b
$ Maybe
  (TransitionTrace
     ConnStateId
     (ConnectionState peerAddr handle handleError version m))
-> Either
     (Maybe
        (TransitionTrace
           ConnStateId
           (ConnectionState peerAddr handle handleError version m)))
     (Transition'
        (MaybeUnknown
           (ConnectionState peerAddr handle handleError version m)))
forall a b. a -> Either a b
Left (TransitionTrace
  ConnStateId (ConnectionState peerAddr handle handleError version m)
-> Maybe
     (TransitionTrace
        ConnStateId
        (ConnectionState peerAddr handle handleError version m))
forall a. a -> Maybe a
Just TransitionTrace
  ConnStateId (ConnectionState peerAddr handle handleError version m)
transitionTrace)
                  InboundIdleState {} -> do
                    StrictTVar
  m (ConnectionState peerAddr handle handleError version m)
-> ConnectionState peerAddr handle handleError version m
-> STM m ()
forall (m :: * -> *) a.
MonadSTM m =>
StrictTVar m a -> a -> STM m ()
writeTVar StrictTVar
  m (ConnectionState peerAddr handle handleError version m)
connVar ConnectionState peerAddr handle handleError version m
forall {peerAddr} {handle} {handleError} {version} {m :: * -> *}.
ConnectionState peerAddr handle handleError version m
connState'
                    Either
  (Maybe
     (TransitionTrace
        ConnStateId
        (ConnectionState peerAddr handle handleError version m)))
  (Transition'
     (MaybeUnknown
        (ConnectionState peerAddr handle handleError version m)))
-> STM
     m
     (Either
        (Maybe
           (TransitionTrace
              ConnStateId
              (ConnectionState peerAddr handle handleError version m)))
        (Transition'
           (MaybeUnknown
              (ConnectionState peerAddr handle handleError version m))))
forall a. a -> STM m a
forall (m :: * -> *) a. Monad m => a -> m a
return (Either
   (Maybe
      (TransitionTrace
         ConnStateId
         (ConnectionState peerAddr handle handleError version m)))
   (Transition'
      (MaybeUnknown
         (ConnectionState peerAddr handle handleError version m)))
 -> STM
      m
      (Either
         (Maybe
            (TransitionTrace
               ConnStateId
               (ConnectionState peerAddr handle handleError version m)))
         (Transition'
            (MaybeUnknown
               (ConnectionState peerAddr handle handleError version m)))))
-> Either
     (Maybe
        (TransitionTrace
           ConnStateId
           (ConnectionState peerAddr handle handleError version m)))
     (Transition'
        (MaybeUnknown
           (ConnectionState peerAddr handle handleError version m)))
-> STM
     m
     (Either
        (Maybe
           (TransitionTrace
              ConnStateId
              (ConnectionState peerAddr handle handleError version m)))
        (Transition'
           (MaybeUnknown
              (ConnectionState peerAddr handle handleError version m))))
forall a b. (a -> b) -> a -> b
$ Maybe
  (TransitionTrace
     ConnStateId
     (ConnectionState peerAddr handle handleError version m))
-> Either
     (Maybe
        (TransitionTrace
           ConnStateId
           (ConnectionState peerAddr handle handleError version m)))
     (Transition'
        (MaybeUnknown
           (ConnectionState peerAddr handle handleError version m)))
forall a b. a -> Either a b
Left (TransitionTrace
  ConnStateId (ConnectionState peerAddr handle handleError version m)
-> Maybe
     (TransitionTrace
        ConnStateId
        (ConnectionState peerAddr handle handleError version m))
forall a. a -> Maybe a
Just TransitionTrace
  ConnStateId (ConnectionState peerAddr handle handleError version m)
transitionTrace)
                  InboundState {} -> do
                    StrictTVar
  m (ConnectionState peerAddr handle handleError version m)
-> ConnectionState peerAddr handle handleError version m
-> STM m ()
forall (m :: * -> *) a.
MonadSTM m =>
StrictTVar m a -> a -> STM m ()
writeTVar StrictTVar
  m (ConnectionState peerAddr handle handleError version m)
connVar ConnectionState peerAddr handle handleError version m
forall {peerAddr} {handle} {handleError} {version} {m :: * -> *}.
ConnectionState peerAddr handle handleError version m
connState'
                    Either
  (Maybe
     (TransitionTrace
        ConnStateId
        (ConnectionState peerAddr handle handleError version m)))
  (Transition'
     (MaybeUnknown
        (ConnectionState peerAddr handle handleError version m)))
-> STM
     m
     (Either
        (Maybe
           (TransitionTrace
              ConnStateId
              (ConnectionState peerAddr handle handleError version m)))
        (Transition'
           (MaybeUnknown
              (ConnectionState peerAddr handle handleError version m))))
forall a. a -> STM m a
forall (m :: * -> *) a. Monad m => a -> m a
return (Either
   (Maybe
      (TransitionTrace
         ConnStateId
         (ConnectionState peerAddr handle handleError version m)))
   (Transition'
      (MaybeUnknown
         (ConnectionState peerAddr handle handleError version m)))
 -> STM
      m
      (Either
         (Maybe
            (TransitionTrace
               ConnStateId
               (ConnectionState peerAddr handle handleError version m)))
         (Transition'
            (MaybeUnknown
               (ConnectionState peerAddr handle handleError version m)))))
-> Either
     (Maybe
        (TransitionTrace
           ConnStateId
           (ConnectionState peerAddr handle handleError version m)))
     (Transition'
        (MaybeUnknown
           (ConnectionState peerAddr handle handleError version m)))
-> STM
     m
     (Either
        (Maybe
           (TransitionTrace
              ConnStateId
              (ConnectionState peerAddr handle handleError version m)))
        (Transition'
           (MaybeUnknown
              (ConnectionState peerAddr handle handleError version m))))
forall a b. (a -> b) -> a -> b
$ Maybe
  (TransitionTrace
     ConnStateId
     (ConnectionState peerAddr handle handleError version m))
-> Either
     (Maybe
        (TransitionTrace
           ConnStateId
           (ConnectionState peerAddr handle handleError version m)))
     (Transition'
        (MaybeUnknown
           (ConnectionState peerAddr handle handleError version m)))
forall a b. a -> Either a b
Left (TransitionTrace
  ConnStateId (ConnectionState peerAddr handle handleError version m)
-> Maybe
     (TransitionTrace
        ConnStateId
        (ConnectionState peerAddr handle handleError version m))
forall a. a -> Maybe a
Just TransitionTrace
  ConnStateId (ConnectionState peerAddr handle handleError version m)
transitionTrace)
                  DuplexState {} -> do
                    StrictTVar
  m (ConnectionState peerAddr handle handleError version m)
-> ConnectionState peerAddr handle handleError version m
-> STM m ()
forall (m :: * -> *) a.
MonadSTM m =>
StrictTVar m a -> a -> STM m ()
writeTVar StrictTVar
  m (ConnectionState peerAddr handle handleError version m)
connVar ConnectionState peerAddr handle handleError version m
forall {peerAddr} {handle} {handleError} {version} {m :: * -> *}.
ConnectionState peerAddr handle handleError version m
connState'
                    Either
  (Maybe
     (TransitionTrace
        ConnStateId
        (ConnectionState peerAddr handle handleError version m)))
  (Transition'
     (MaybeUnknown
        (ConnectionState peerAddr handle handleError version m)))
-> STM
     m
     (Either
        (Maybe
           (TransitionTrace
              ConnStateId
              (ConnectionState peerAddr handle handleError version m)))
        (Transition'
           (MaybeUnknown
              (ConnectionState peerAddr handle handleError version m))))
forall a. a -> STM m a
forall (m :: * -> *) a. Monad m => a -> m a
return (Either
   (Maybe
      (TransitionTrace
         ConnStateId
         (ConnectionState peerAddr handle handleError version m)))
   (Transition'
      (MaybeUnknown
         (ConnectionState peerAddr handle handleError version m)))
 -> STM
      m
      (Either
         (Maybe
            (TransitionTrace
               ConnStateId
               (ConnectionState peerAddr handle handleError version m)))
         (Transition'
            (MaybeUnknown
               (ConnectionState peerAddr handle handleError version m)))))
-> Either
     (Maybe
        (TransitionTrace
           ConnStateId
           (ConnectionState peerAddr handle handleError version m)))
     (Transition'
        (MaybeUnknown
           (ConnectionState peerAddr handle handleError version m)))
-> STM
     m
     (Either
        (Maybe
           (TransitionTrace
              ConnStateId
              (ConnectionState peerAddr handle handleError version m)))
        (Transition'
           (MaybeUnknown
              (ConnectionState peerAddr handle handleError version m))))
forall a b. (a -> b) -> a -> b
$ Maybe
  (TransitionTrace
     ConnStateId
     (ConnectionState peerAddr handle handleError version m))
-> Either
     (Maybe
        (TransitionTrace
           ConnStateId
           (ConnectionState peerAddr handle handleError version m)))
     (Transition'
        (MaybeUnknown
           (ConnectionState peerAddr handle handleError version m)))
forall a b. a -> Either a b
Left (TransitionTrace
  ConnStateId (ConnectionState peerAddr handle handleError version m)
-> Maybe
     (TransitionTrace
        ConnStateId
        (ConnectionState peerAddr handle handleError version m))
forall a. a -> Maybe a
Just TransitionTrace
  ConnStateId (ConnectionState peerAddr handle handleError version m)
transitionTrace)
                  TerminatingState {} -> do
                    Either
  (Maybe
     (TransitionTrace
        ConnStateId
        (ConnectionState peerAddr handle handleError version m)))
  (Transition'
     (MaybeUnknown
        (ConnectionState peerAddr handle handleError version m)))
-> STM
     m
     (Either
        (Maybe
           (TransitionTrace
              ConnStateId
              (ConnectionState peerAddr handle handleError version m)))
        (Transition'
           (MaybeUnknown
              (ConnectionState peerAddr handle handleError version m))))
forall a. a -> STM m a
forall (m :: * -> *) a. Monad m => a -> m a
return (Either
   (Maybe
      (TransitionTrace
         ConnStateId
         (ConnectionState peerAddr handle handleError version m)))
   (Transition'
      (MaybeUnknown
         (ConnectionState peerAddr handle handleError version m)))
 -> STM
      m
      (Either
         (Maybe
            (TransitionTrace
               ConnStateId
               (ConnectionState peerAddr handle handleError version m)))
         (Transition'
            (MaybeUnknown
               (ConnectionState peerAddr handle handleError version m)))))
-> Either
     (Maybe
        (TransitionTrace
           ConnStateId
           (ConnectionState peerAddr handle handleError version m)))
     (Transition'
        (MaybeUnknown
           (ConnectionState peerAddr handle handleError version m)))
-> STM
     m
     (Either
        (Maybe
           (TransitionTrace
              ConnStateId
              (ConnectionState peerAddr handle handleError version m)))
        (Transition'
           (MaybeUnknown
              (ConnectionState peerAddr handle handleError version m))))
forall a b. (a -> b) -> a -> b
$ Transition'
  (MaybeUnknown
     (ConnectionState peerAddr handle handleError version m))
-> Either
     (Maybe
        (TransitionTrace
           ConnStateId
           (ConnectionState peerAddr handle handleError version m)))
     (Transition'
        (MaybeUnknown
           (ConnectionState peerAddr handle handleError version m)))
forall a b. b -> Either a b
Right Transition'
  (MaybeUnknown
     (ConnectionState peerAddr handle handleError version m))
transition
                  TerminatedState {} ->
                    Either
  (Maybe
     (TransitionTrace
        ConnStateId
        (ConnectionState peerAddr handle handleError version m)))
  (Transition'
     (MaybeUnknown
        (ConnectionState peerAddr handle handleError version m)))
-> STM
     m
     (Either
        (Maybe
           (TransitionTrace
              ConnStateId
              (ConnectionState peerAddr handle handleError version m)))
        (Transition'
           (MaybeUnknown
              (ConnectionState peerAddr handle handleError version m))))
forall a. a -> STM m a
forall (m :: * -> *) a. Monad m => a -> m a
return (Either
   (Maybe
      (TransitionTrace
         ConnStateId
         (ConnectionState peerAddr handle handleError version m)))
   (Transition'
      (MaybeUnknown
         (ConnectionState peerAddr handle handleError version m)))
 -> STM
      m
      (Either
         (Maybe
            (TransitionTrace
               ConnStateId
               (ConnectionState peerAddr handle handleError version m)))
         (Transition'
            (MaybeUnknown
               (ConnectionState peerAddr handle handleError version m)))))
-> Either
     (Maybe
        (TransitionTrace
           ConnStateId
           (ConnectionState peerAddr handle handleError version m)))
     (Transition'
        (MaybeUnknown
           (ConnectionState peerAddr handle handleError version m)))
-> STM
     m
     (Either
        (Maybe
           (TransitionTrace
              ConnStateId
              (ConnectionState peerAddr handle handleError version m)))
        (Transition'
           (MaybeUnknown
              (ConnectionState peerAddr handle handleError version m))))
forall a b. (a -> b) -> a -> b
$ Maybe
  (TransitionTrace
     ConnStateId
     (ConnectionState peerAddr handle handleError version m))
-> Either
     (Maybe
        (TransitionTrace
           ConnStateId
           (ConnectionState peerAddr handle handleError version m)))
     (Transition'
        (MaybeUnknown
           (ConnectionState peerAddr handle handleError version m)))
forall a b. a -> Either a b
Left Maybe
  (TransitionTrace
     ConnStateId
     (ConnectionState peerAddr handle handleError version m))
forall a. Maybe a
Nothing

              case eTransition of
                Left Maybe
  (TransitionTrace
     ConnStateId
     (ConnectionState peerAddr handle handleError version m))
mbTransition -> do
                  (TransitionTrace
   ConnStateId (ConnectionState peerAddr handle handleError version m)
 -> m ())
-> Maybe
     (TransitionTrace
        ConnStateId
        (ConnectionState peerAddr handle handleError version m))
-> m ()
forall (t :: * -> *) (f :: * -> *) a b.
(Foldable t, Applicative f) =>
(a -> f b) -> t a -> f ()
traverse_ (Tracer
  m
  (TransitionTrace
     ConnStateId
     (ConnectionState peerAddr handle handleError version m))
-> TransitionTrace
     ConnStateId (ConnectionState peerAddr handle handleError version m)
-> m ()
forall (m :: * -> *) a. Tracer m a -> a -> m ()
traceWith Tracer
  m
  (TransitionTrace
     ConnStateId
     (ConnectionState peerAddr handle handleError version m))
trTracer) Maybe
  (TransitionTrace
     ConnStateId
     (ConnectionState peerAddr handle handleError version m))
mbTransition
                  Snocket m socket peerAddr -> socket -> m ()
forall (m :: * -> *) fd addr. Snocket m fd addr -> fd -> m ()
close Snocket m socket peerAddr
snocket socket
socket
                  (ConnectionManagerState peerAddr handle handleError version m,
 Maybe
   (Transition'
      (MaybeUnknown
         (ConnectionState peerAddr handle handleError version m))))
-> m (ConnectionManagerState peerAddr handle handleError version m,
      Maybe
        (Transition'
           (MaybeUnknown
              (ConnectionState peerAddr handle handleError version m))))
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return ( ConnectionManagerState peerAddr handle handleError version m
state
                         , Maybe
  (Transition'
     (MaybeUnknown
        (ConnectionState peerAddr handle handleError version m)))
forall a. Maybe a
Nothing
                         )
                Right Transition'
  (MaybeUnknown
     (ConnectionState peerAddr handle handleError version m))
transition -> do
                  Snocket m socket peerAddr -> socket -> m ()
forall (m :: * -> *) fd addr. Snocket m fd addr -> fd -> m ()
close Snocket m socket peerAddr
snocket socket
socket
                  (ConnectionManagerState peerAddr handle handleError version m,
 Maybe
   (Transition'
      (MaybeUnknown
         (ConnectionState peerAddr handle handleError version m))))
-> m (ConnectionManagerState peerAddr handle handleError version m,
      Maybe
        (Transition'
           (MaybeUnknown
              (ConnectionState peerAddr handle handleError version m))))
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return ( ConnectionManagerState peerAddr handle handleError version m
state
                         , Transition'
  (MaybeUnknown
     (ConnectionState peerAddr handle handleError version m))
-> Maybe
     (Transition'
        (MaybeUnknown
           (ConnectionState peerAddr handle handleError version m)))
forall a. a -> Maybe a
Just Transition'
  (MaybeUnknown
     (ConnectionState peerAddr handle handleError version m))
transition
                         )

            case mbTransition of
              Maybe
  (Transition'
     (MaybeUnknown
        (ConnectionState peerAddr handle handleError version m)))
Nothing -> do
                let transition :: TransitionTrace
  ConnStateId (ConnectionState peerAddr handle handleError version m)
transition =
                      ConnStateId
-> Transition'
     (MaybeUnknown
        (ConnectionState peerAddr handle handleError version m))
-> TransitionTrace
     ConnStateId (ConnectionState peerAddr handle handleError version m)
forall id state.
id -> Transition' state -> TransitionTrace' id state
TransitionTrace
                        ConnStateId
connStateId
                        Transition
                           { fromState :: MaybeUnknown
  (ConnectionState peerAddr handle handleError version m)
fromState = ConnectionState peerAddr handle handleError version m
-> MaybeUnknown
     (ConnectionState peerAddr handle handleError version m)
forall state. state -> MaybeUnknown state
Known (Maybe handleError
-> ConnectionState peerAddr handle handleError version m
forall peerAddr handle handleError version (m :: * -> *).
Maybe handleError
-> ConnectionState peerAddr handle handleError version m
TerminatedState Maybe handleError
forall a. Maybe a
Nothing)
                           , toState :: MaybeUnknown
  (ConnectionState peerAddr handle handleError version m)
toState   = MaybeUnknown
  (ConnectionState peerAddr handle handleError version m)
forall state. MaybeUnknown state
Unknown
                           }
                mbTransition' <- StrictTMVar
  m (ConnectionManagerState peerAddr handle handleError version m)
-> (ConnectionManagerState peerAddr handle handleError version m
    -> m (ConnectionManagerState peerAddr handle handleError version m,
          Maybe
            (TransitionTrace
               ConnStateId
               (ConnectionState peerAddr handle handleError version m))))
-> m (Maybe
        (TransitionTrace
           ConnStateId
           (ConnectionState peerAddr handle handleError version m)))
forall (m :: * -> *) a b.
(MonadEvaluate m, MonadMask m, MonadSTM m) =>
StrictTMVar m a -> (a -> m (a, b)) -> m b
modifyTMVar StrictTMVar
  m (ConnectionManagerState peerAddr handle handleError version m)
stateVar ((ConnectionManagerState peerAddr handle handleError version m
  -> m (ConnectionManagerState peerAddr handle handleError version m,
        Maybe
          (TransitionTrace
             ConnStateId
             (ConnectionState peerAddr handle handleError version m))))
 -> m (Maybe
         (TransitionTrace
            ConnStateId
            (ConnectionState peerAddr handle handleError version m))))
-> (ConnectionManagerState peerAddr handle handleError version m
    -> m (ConnectionManagerState peerAddr handle handleError version m,
          Maybe
            (TransitionTrace
               ConnStateId
               (ConnectionState peerAddr handle handleError version m))))
-> m (Maybe
        (TransitionTrace
           ConnStateId
           (ConnectionState peerAddr handle handleError version m)))
forall a b. (a -> b) -> a -> b
$ \ConnectionManagerState peerAddr handle handleError version m
state ->
                  case ConnectionId peerAddr
-> ConnectionManagerState peerAddr handle handleError version m
-> Maybe (MutableConnState peerAddr handle handleError version m)
forall peerAddr a.
Ord peerAddr =>
ConnectionId peerAddr -> ConnMap peerAddr a -> Maybe a
State.lookup ConnectionId peerAddr
connId ConnectionManagerState peerAddr handle handleError version m
state of
                    Maybe (MutableConnState peerAddr handle handleError version m)
Nothing -> (ConnectionManagerState peerAddr handle handleError version m,
 Maybe
   (TransitionTrace
      ConnStateId
      (ConnectionState peerAddr handle handleError version m)))
-> m (ConnectionManagerState peerAddr handle handleError version m,
      Maybe
        (TransitionTrace
           ConnStateId
           (ConnectionState peerAddr handle handleError version m)))
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (ConnectionManagerState peerAddr handle handleError version m
state, Maybe
  (TransitionTrace
     ConnStateId
     (ConnectionState peerAddr handle handleError version m))
forall a. Maybe a
Nothing)
                    Just MutableConnState peerAddr handle handleError version m
v  ->
                      if MutableConnState peerAddr handle handleError version m
mutableConnState MutableConnState peerAddr handle handleError version m
-> MutableConnState peerAddr handle handleError version m -> Bool
forall a. Eq a => a -> a -> Bool
== MutableConnState peerAddr handle handleError version m
v
                         then (ConnectionManagerState peerAddr handle handleError version m,
 Maybe
   (TransitionTrace
      ConnStateId
      (ConnectionState peerAddr handle handleError version m)))
-> m (ConnectionManagerState peerAddr handle handleError version m,
      Maybe
        (TransitionTrace
           ConnStateId
           (ConnectionState peerAddr handle handleError version m)))
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (ConnectionId peerAddr
-> ConnectionManagerState peerAddr handle handleError version m
-> ConnectionManagerState peerAddr handle handleError version m
forall peerAddr a.
Ord peerAddr =>
ConnectionId peerAddr -> ConnMap peerAddr a -> ConnMap peerAddr a
State.delete ConnectionId peerAddr
connId ConnectionManagerState peerAddr handle handleError version m
state , TransitionTrace
  ConnStateId (ConnectionState peerAddr handle handleError version m)
-> Maybe
     (TransitionTrace
        ConnStateId
        (ConnectionState peerAddr handle handleError version m))
forall a. a -> Maybe a
Just TransitionTrace
  ConnStateId (ConnectionState peerAddr handle handleError version m)
transition)
                         else (ConnectionManagerState peerAddr handle handleError version m,
 Maybe
   (TransitionTrace
      ConnStateId
      (ConnectionState peerAddr handle handleError version m)))
-> m (ConnectionManagerState peerAddr handle handleError version m,
      Maybe
        (TransitionTrace
           ConnStateId
           (ConnectionState peerAddr handle handleError version m)))
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (ConnectionManagerState peerAddr handle handleError version m
state                     , Maybe
  (TransitionTrace
     ConnStateId
     (ConnectionState peerAddr handle handleError version m))
forall a. Maybe a
Nothing)

                traverse_ (traceWith trTracer) mbTransition'
                traceCounters stateVar

              Just Transition'
  (MaybeUnknown
     (ConnectionState peerAddr handle handleError version m))
transition ->
                do Tracer m (Trace peerAddr handlerTrace)
-> Trace peerAddr handlerTrace -> m ()
forall (m :: * -> *) a. Tracer m a -> a -> m ()
traceWith Tracer m (Trace peerAddr handlerTrace)
tracer (ConnectionId peerAddr -> Trace peerAddr handlerTrace
forall peerAddr handlerTrace.
ConnectionId peerAddr -> Trace peerAddr handlerTrace
TrConnectionTimeWait ConnectionId peerAddr
connId)
                   Bool -> m () -> m ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (DiffTime
timeWaitTimeout DiffTime -> DiffTime -> Bool
forall a. Ord a => a -> a -> Bool
> DiffTime
0) (m () -> m ()) -> m () -> m ()
forall a b. (a -> b) -> a -> b
$
                     let -- make sure we wait at least 'timeWaitTimeout', we
                         -- ignore all 'AsyncCancelled' exceptions.
                         forceThreadDelay :: DiffTime -> m ()
forceThreadDelay DiffTime
delay | DiffTime
delay DiffTime -> DiffTime -> Bool
forall a. Ord a => a -> a -> Bool
<= DiffTime
0 = () -> m ()
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()
                         forceThreadDelay DiffTime
delay = do
                           t <- m Time
forall (m :: * -> *). MonadMonotonicTime m => m Time
getMonotonicTime
                           unmask (threadDelay delay)
                             `catch` \SomeException
e ->
                                case SomeException -> Maybe AsyncCancelled
forall e. Exception e => SomeException -> Maybe e
fromException SomeException
e
                                of Just AsyncCancelled
AsyncCancelled -> do
                                     t' <- m Time
forall (m :: * -> *). MonadMonotonicTime m => m Time
getMonotonicTime
                                     forceThreadDelay (delay - t' `diffTime` t)
                                   Maybe AsyncCancelled
_ -> SomeException -> m ()
forall e a. Exception e => e -> m a
forall (m :: * -> *) e a. (MonadThrow m, Exception e) => e -> m a
throwIO SomeException
e
                     in DiffTime -> m ()
forceThreadDelay DiffTime
timeWaitTimeout
                m () -> m () -> m ()
forall a b. m a -> m b -> m a
forall (m :: * -> *) a b. MonadThrow m => m a -> m b -> m a
`finally` do
                  -- We must ensure that we update 'connVar',
                  -- `acquireOutboundConnection` might be blocked on it awaiting for:
                  -- - handshake negotiation; or
                  -- - `Terminate: TerminatingState → TerminatedState` transition.
                  Tracer m (Trace peerAddr handlerTrace)
-> Trace peerAddr handlerTrace -> m ()
forall (m :: * -> *) a. Tracer m a -> a -> m ()
traceWith Tracer m (Trace peerAddr handlerTrace)
tracer (ConnectionId peerAddr -> Trace peerAddr handlerTrace
forall peerAddr handlerTrace.
ConnectionId peerAddr -> Trace peerAddr handlerTrace
TrConnectionTimeWaitDone ConnectionId peerAddr
connId)

                  trs <- STM
  m
  [Transition'
     (MaybeUnknown
        (ConnectionState peerAddr handle handleError version m))]
-> m [Transition'
        (MaybeUnknown
           (ConnectionState peerAddr handle handleError version m))]
forall a. (?callStack::CallStack) => STM m a -> m a
forall (m :: * -> *) a.
(MonadSTM m, ?callStack::CallStack) =>
STM m a -> m a
atomically (STM
   m
   [Transition'
      (MaybeUnknown
         (ConnectionState peerAddr handle handleError version m))]
 -> m [Transition'
         (MaybeUnknown
            (ConnectionState peerAddr handle handleError version m))])
-> STM
     m
     [Transition'
        (MaybeUnknown
           (ConnectionState peerAddr handle handleError version m))]
-> m [Transition'
        (MaybeUnknown
           (ConnectionState peerAddr handle handleError version m))]
forall a b. (a -> b) -> a -> b
$ do
                    connState <- 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)
connVar
                    let transition' = Transition'
  (MaybeUnknown
     (ConnectionState peerAddr handle handleError version m))
transition { fromState = Known connState }
                        shouldTrace = MaybeUnknown
  (ConnectionState peerAddr handle handleError version m)
-> AbstractState
forall muxMode peerAddr m a (b :: * -> *).
MaybeUnknown (ConnectionState muxMode peerAddr m a b)
-> AbstractState
State.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
connState)
                                   AbstractState -> AbstractState -> Bool
forall a. Eq a => a -> a -> Bool
/= AbstractState
TerminatedSt
                    writeTVar connVar (TerminatedState Nothing)
                    --  We have to be careful when deleting it from
                    --  'ConnectionManagerState'.
                    updated <-
                      modifyTMVarPure
                        stateVar
                        ( \ConnectionManagerState peerAddr handle handleError version m
state ->
                          case ConnectionId peerAddr
-> ConnectionManagerState peerAddr handle handleError version m
-> Maybe (MutableConnState peerAddr handle handleError version m)
forall peerAddr a.
Ord peerAddr =>
ConnectionId peerAddr -> ConnMap peerAddr a -> Maybe a
State.lookup ConnectionId peerAddr
connId ConnectionManagerState peerAddr handle handleError version m
state of
                            Maybe (MutableConnState peerAddr handle handleError version m)
Nothing -> (ConnectionManagerState peerAddr handle handleError version m
state, Bool
False)
                            Just MutableConnState peerAddr handle handleError version m
v  ->
                              if MutableConnState peerAddr handle handleError version m
mutableConnState MutableConnState peerAddr handle handleError version m
-> MutableConnState peerAddr handle handleError version m -> Bool
forall a. Eq a => a -> a -> Bool
== MutableConnState peerAddr handle handleError version m
v
                                then (ConnectionId peerAddr
-> ConnectionManagerState peerAddr handle handleError version m
-> ConnectionManagerState peerAddr handle handleError version m
forall peerAddr a.
Ord peerAddr =>
ConnectionId peerAddr -> ConnMap peerAddr a -> ConnMap peerAddr a
State.delete ConnectionId peerAddr
connId ConnectionManagerState peerAddr handle handleError version m
state, Bool
True)
                                else (ConnectionManagerState peerAddr handle handleError version m
state                    , Bool
False)
                        )

                    if updated
                       then do
                      -- Key was present in the dictionary (stateVar) and
                      -- removed so we trace the removal.
                        let trs = [ Transition
                                     { fromState :: MaybeUnknown
  (ConnectionState peerAddr handle handleError version m)
fromState = ConnectionState peerAddr handle handleError version m
-> MaybeUnknown
     (ConnectionState peerAddr handle handleError version m)
forall state. state -> MaybeUnknown state
Known (Maybe handleError
-> ConnectionState peerAddr handle handleError version m
forall peerAddr handle handleError version (m :: * -> *).
Maybe handleError
-> ConnectionState peerAddr handle handleError version m
TerminatedState Maybe handleError
forall a. Maybe a
Nothing)
                                     , toState :: MaybeUnknown
  (ConnectionState peerAddr handle handleError version m)
toState   = MaybeUnknown
  (ConnectionState peerAddr handle handleError version m)
forall state. MaybeUnknown state
Unknown
                                     }
                                  ]
                        return $
                          if shouldTrace
                             then transition' : trs
                             else trs
                      -- Key was not present in the dictionary (stateVar),
                      -- so we do not trace anything as it was already traced upon
                      -- deletion.
                      --
                      -- OR
                      --
                      -- Key was overwritten in the dictionary (stateVar),
                      -- so we do not trace anything as it was already traced upon
                      -- overwriting.
                       else return [ ]

                  traverse_ (traceWith trTracer . TransitionTrace connStateId) trs
                  traceCounters stateVar

    -- Pruning is done in two stages:
    -- * an STM transaction which selects which connections to prune, and sets
    --   their state to 'TerminatedState';
    -- * an io action which logs and cancels all the connection handler
    --   threads.
    mkPruneAction :: ConnectionId peerAddr
                  -> Int
                  -- ^ number of connections to prune
                  -> ConnectionManagerState peerAddr handle handleError version m
                  -> ConnectionState peerAddr handle handleError version  m
                  -- ^ next connection state, if it will not be pruned.
                  -> StrictTVar m (ConnectionState peerAddr handle handleError version m)
                  -> StrictTVar m StdGen
                  -> Async m ()
                  -> STM m (Bool, PruneAction m)
                  -- ^ return if the connection was choose to be pruned and the
                  -- 'PruneAction'
    mkPruneAction :: ConnectionId peerAddr
-> Int
-> ConnectionManagerState peerAddr handle handleError version m
-> ConnectionState peerAddr handle handleError version m
-> StrictTVar
     m (ConnectionState peerAddr handle handleError version m)
-> StrictTVar m StdGen
-> Async m ()
-> STM m (Bool, PruneAction m)
mkPruneAction ConnectionId peerAddr
connId Int
numberToPrune ConnectionManagerState peerAddr handle handleError version m
state ConnectionState peerAddr handle handleError version m
connState' StrictTVar
  m (ConnectionState peerAddr handle handleError version m)
connVar StrictTVar m StdGen
stdGenVar Async m ()
connThread = do
      choiceMap'
          <- (ConnectionId peerAddr
 -> MutableConnState peerAddr handle handleError version m
 -> STM
      m
      (Maybe
         (ConnectionType, Async m (),
          StrictTVar
            m (ConnectionState peerAddr handle handleError version m))))
-> Map
     (ConnectionId peerAddr)
     (MutableConnState peerAddr handle handleError version m)
-> STM
     m
     (Map
        (ConnectionId peerAddr)
        (ConnectionType, Async m (),
         StrictTVar
           m (ConnectionState peerAddr handle handleError version m)))
forall (f :: * -> *) k a b.
Applicative f =>
(k -> a -> f (Maybe b)) -> Map k a -> f (Map k b)
Map.traverseMaybeWithKey
                (\ConnectionId peerAddr
_ MutableConnState { connVar :: 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)
connVar' } ->
                      (\ConnectionState peerAddr handle handleError version m
cs -> do
                          -- this expression returns @Maybe (connType, connThread)@;
                          -- 'traverseMaybeWithKey' collects all 'Just' cases.
                          Bool -> Maybe ()
forall (f :: * -> *). Alternative f => Bool -> f ()
guard (ConnectionState peerAddr handle handleError version m -> Bool
forall peerAddr handle handleError version (m :: * -> *).
ConnectionState peerAddr handle handleError version m -> Bool
isInboundConn ConnectionState peerAddr handle handleError version m
cs)
                          (,,StrictTVar
  m (ConnectionState peerAddr handle handleError version m)
connVar') (ConnectionType
 -> Async m ()
 -> (ConnectionType, Async m (),
     StrictTVar
       m (ConnectionState peerAddr handle handleError version m)))
-> Maybe ConnectionType
-> Maybe
     (Async m ()
      -> (ConnectionType, Async m (),
          StrictTVar
            m (ConnectionState peerAddr handle handleError version m)))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ConnectionState peerAddr handle handleError version m
-> Maybe ConnectionType
forall peerAddr handle handleError version (m :: * -> *).
ConnectionState peerAddr handle handleError version m
-> Maybe ConnectionType
getConnType ConnectionState peerAddr handle handleError version m
cs
                                       Maybe
  (Async m ()
   -> (ConnectionType, Async m (),
       StrictTVar
         m (ConnectionState peerAddr handle handleError version m)))
-> Maybe (Async m ())
-> Maybe
     (ConnectionType, Async m (),
      StrictTVar
        m (ConnectionState peerAddr handle handleError version m))
forall a b. Maybe (a -> b) -> Maybe a -> Maybe b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> ConnectionState peerAddr handle handleError version m
-> Maybe (Async m ())
forall peerAddr handle handleError version (m :: * -> *).
ConnectionState peerAddr handle handleError version m
-> Maybe (Async m ())
getConnThread ConnectionState peerAddr handle handleError version m
cs)
                  (ConnectionState peerAddr handle handleError version m
 -> Maybe
      (ConnectionType, Async m (),
       StrictTVar
         m (ConnectionState peerAddr handle handleError version m)))
-> STM m (ConnectionState peerAddr handle handleError version m)
-> STM
     m
     (Maybe
        (ConnectionType, Async m (),
         StrictTVar
           m (ConnectionState peerAddr handle handleError version m)))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> 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)
connVar'
                )
                (ConnectionManagerState peerAddr handle handleError version m
-> Map
     (ConnectionId peerAddr)
     (MutableConnState peerAddr handle handleError version m)
forall peerAddr a.
Ord peerAddr =>
ConnMap peerAddr a -> Map (ConnectionId peerAddr) a
State.toMap ConnectionManagerState peerAddr handle handleError version m
state)
      let choiceMap :: Map (ConnectionId peerAddr)
                           ( ConnectionType
                           , Async m ()
                           , StrictTVar m (ConnectionState peerAddr handle handleError version m)
                           )
          choiceMap =
            case ConnectionState peerAddr handle handleError version m
-> Maybe ConnectionType
forall peerAddr handle handleError version (m :: * -> *).
ConnectionState peerAddr handle handleError version m
-> Maybe ConnectionType
getConnType ConnectionState peerAddr handle handleError version m
connState' of
              Maybe ConnectionType
Nothing -> Bool
-> Map
     (ConnectionId peerAddr)
     (ConnectionType, Async m (),
      StrictTVar
        m (ConnectionState peerAddr handle handleError version m))
-> Map
     (ConnectionId peerAddr)
     (ConnectionType, Async m (),
      StrictTVar
        m (ConnectionState peerAddr handle handleError version m))
forall a. (?callStack::CallStack) => Bool -> a -> a
assert Bool
False Map
  (ConnectionId peerAddr)
  (ConnectionType, Async m (),
   StrictTVar
     m (ConnectionState peerAddr handle handleError version m))
choiceMap'
              Just ConnectionType
a  -> ConnectionId peerAddr
-> (ConnectionType, Async m (),
    StrictTVar
      m (ConnectionState peerAddr handle handleError version m))
-> Map
     (ConnectionId peerAddr)
     (ConnectionType, Async m (),
      StrictTVar
        m (ConnectionState peerAddr handle handleError version m))
-> Map
     (ConnectionId peerAddr)
     (ConnectionType, Async m (),
      StrictTVar
        m (ConnectionState peerAddr handle handleError version m))
forall k a. Ord k => k -> a -> Map k a -> Map k a
Map.insert ConnectionId peerAddr
connId (ConnectionType
a, Async m ()
connThread, StrictTVar
  m (ConnectionState peerAddr handle handleError version m)
connVar)
                                    Map
  (ConnectionId peerAddr)
  (ConnectionType, Async m (),
   StrictTVar
     m (ConnectionState peerAddr handle handleError version m))
choiceMap'

      stdGen <- stateTVar stdGenVar split
      let pruneSet = PrunePolicy peerAddr
prunePolicy
                       StdGen
stdGen
                       ((\(ConnectionType
a,Async m ()
_,StrictTVar
  m (ConnectionState peerAddr handle handleError version m)
_) -> ConnectionType
a) ((ConnectionType, Async m (),
  StrictTVar
    m (ConnectionState peerAddr handle handleError version m))
 -> ConnectionType)
-> Map
     (ConnectionId peerAddr)
     (ConnectionType, Async m (),
      StrictTVar
        m (ConnectionState peerAddr handle handleError version m))
-> Map (ConnectionId peerAddr) ConnectionType
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Map
  (ConnectionId peerAddr)
  (ConnectionType, Async m (),
   StrictTVar
     m (ConnectionState peerAddr handle handleError version m))
choiceMap)
                       Int
numberToPrune

      let pruneMap = Map
  (ConnectionId peerAddr)
  (ConnectionType, Async m (),
   StrictTVar
     m (ConnectionState peerAddr handle handleError version m))
choiceMap Map
  (ConnectionId peerAddr)
  (ConnectionType, Async m (),
   StrictTVar
     m (ConnectionState peerAddr handle handleError version m))
-> Set (ConnectionId peerAddr)
-> Map
     (ConnectionId peerAddr)
     (ConnectionType, Async m (),
      StrictTVar
        m (ConnectionState peerAddr handle handleError version m))
forall k a. Ord k => Map k a -> Set k -> Map k a
`Map.restrictKeys` Set (ConnectionId peerAddr)
pruneSet
      forM_ pruneMap $ \(ConnectionType
_, Async m ()
_, StrictTVar
  m (ConnectionState peerAddr handle handleError version m)
connVar') ->
        StrictTVar
  m (ConnectionState peerAddr handle handleError version m)
-> ConnectionState peerAddr handle handleError version m
-> STM m ()
forall (m :: * -> *) a.
MonadSTM m =>
StrictTVar m a -> a -> STM m ()
writeTVar StrictTVar
  m (ConnectionState peerAddr handle handleError version m)
connVar' (Maybe handleError
-> ConnectionState peerAddr handle handleError version m
forall peerAddr handle handleError version (m :: * -> *).
Maybe handleError
-> ConnectionState peerAddr handle handleError version m
TerminatedState Maybe handleError
forall a. Maybe a
Nothing)

      return ( connId `Set.member` pruneSet
             , PruneAction $ do
                 traceWith tracer (TrPruneConnections (Map.keysSet pruneMap)
                                                      numberToPrune
                                                      (Map.keysSet choiceMap))
                 -- we don't block until the thread terminates, delivering the
                 -- async exception is enough (although in this case, there's no
                 -- difference, since we put the connection in 'TerminatedState'
                 -- which avoids the 'timeWaitTimeout').
                 forM_ pruneMap $ \(ConnectionType
_, Async m ()
connThread', StrictTVar
  m (ConnectionState peerAddr handle handleError version m)
_) ->
                                   ThreadId m -> AsyncCancelled -> m ()
forall e. Exception e => ThreadId m -> e -> m ()
forall (m :: * -> *) e.
(MonadFork m, Exception e) =>
ThreadId m -> e -> m ()
throwTo (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')
                                           AsyncCancelled
AsyncCancelled
             )

    includeInboundConnectionImpl
        :: HasCallStack
        => StrictTMVar m (ConnectionManagerState peerAddr handle handleError version m)
        -> ConnectionHandlerFn handlerTrace socket peerAddr handle handleError version versionData m
        -> Word32
        -- ^ inbound connections hard limit
        -- TODO: This is needed because the accept loop can not guarantee that
        -- includeInboundConnection can run safely without going above the
        -- hard limit.  We have to check if we are not above the hard limit
        -- after locking the connection manager state `TMVar` and  then decide
        -- whether we can include the connection or not.
        -> socket
        -- ^ resource to include in the state
        -> ConnectionId peerAddr
        -- ^ connection id used as an identifier of the resource
        -> m (Connected peerAddr handle handleError)
    includeInboundConnectionImpl :: (?callStack::CallStack) =>
StrictTMVar
  m (ConnectionManagerState peerAddr handle handleError version m)
-> ConnectionHandlerFn
     handlerTrace
     socket
     peerAddr
     handle
     handleError
     version
     versionData
     m
-> IncludeInboundConnection socket peerAddr handle handleError m
includeInboundConnectionImpl StrictTMVar
  m (ConnectionManagerState peerAddr handle handleError version m)
stateVar
                                 ConnectionHandlerFn
  handlerTrace
  socket
  peerAddr
  handle
  handleError
  version
  versionData
  m
handler
                                 Word32
hardLimit
                                 socket
socket
                                 ConnectionId peerAddr
connId = do
        r <- StrictTMVar
  m (ConnectionManagerState peerAddr handle handleError version m)
-> (ConnectionManagerState peerAddr handle handleError version m
    -> m (ConnectionManagerState peerAddr handle handleError version m,
          Maybe
            (MutableConnState peerAddr handle handleError version m,
             Async m (),
             PromiseReader
               m
               (Either
                  handleError
                  (HandshakeConnectionResult handle (version, versionData))))))
-> m (Maybe
        (MutableConnState peerAddr handle handleError version m,
         Async m (),
         PromiseReader
           m
           (Either
              handleError
              (HandshakeConnectionResult handle (version, versionData)))))
forall (m :: * -> *) a b.
(MonadEvaluate m, MonadMask m, MonadSTM m) =>
StrictTMVar m a -> (a -> m (a, b)) -> m b
modifyTMVar StrictTMVar
  m (ConnectionManagerState peerAddr handle handleError version m)
stateVar ((ConnectionManagerState peerAddr handle handleError version m
  -> m (ConnectionManagerState peerAddr handle handleError version m,
        Maybe
          (MutableConnState peerAddr handle handleError version m,
           Async m (),
           PromiseReader
             m
             (Either
                handleError
                (HandshakeConnectionResult handle (version, versionData))))))
 -> m (Maybe
         (MutableConnState peerAddr handle handleError version m,
          Async m (),
          PromiseReader
            m
            (Either
               handleError
               (HandshakeConnectionResult handle (version, versionData))))))
-> (ConnectionManagerState peerAddr handle handleError version m
    -> m (ConnectionManagerState peerAddr handle handleError version m,
          Maybe
            (MutableConnState peerAddr handle handleError version m,
             Async m (),
             PromiseReader
               m
               (Either
                  handleError
                  (HandshakeConnectionResult handle (version, versionData))))))
-> m (Maybe
        (MutableConnState peerAddr handle handleError version m,
         Async m (),
         PromiseReader
           m
           (Either
              handleError
              (HandshakeConnectionResult handle (version, versionData)))))
forall a b. (a -> b) -> a -> b
$ \ConnectionManagerState peerAddr handle handleError version m
state -> do
          numberOfCons <- STM m Int -> m Int
forall a. (?callStack::CallStack) => STM m a -> m a
forall (m :: * -> *) a.
(MonadSTM m, ?callStack::CallStack) =>
STM m a -> m a
atomically (STM m Int -> m Int) -> STM m Int -> m Int
forall a b. (a -> b) -> a -> b
$ ConnectionManagerState peerAddr handle handleError version m
-> STM m Int
countIncomingConnections ConnectionManagerState peerAddr handle handleError version m
state

          let -- Check if after accepting this connection we get above the
              -- hard limit
              canAccept = Int
numberOfCons Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1 Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Word32 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word32
hardLimit

          if canAccept
          then do
            let provenance = Provenance
Inbound
            traceWith tracer (TrIncludeConnection provenance (remoteAddress connId))
            (reader, writer) <- newEmptyPromiseIO
            (connThread, connVar, connState0, connState) <-
              mfix $ \ ~(Async m ()
connThread, MutableConnState peerAddr handle handleError version m
_mutableConnVar, Maybe (ConnectionState peerAddr handle handleError version m)
_connState0, ConnectionState peerAddr handle handleError version m
_connState) -> do
                -- Either
                -- @
                --   Accepted    : ● → UnnegotiatedState Inbound
                --   Overwritten : ● → UnnegotiatedState Inbound
                --   SelfConn    : UnnegotiatedState Outbound
                --               → UnnegotiatedState Inbound
                -- @
                --
                -- This is subtle part, which needs to handle a near simultaneous
                -- open.  We cannot rely on 'ReservedOutboundState' state as
                -- a lock.  It may happen that the `acquireOutboundConnection`
                -- will put 'ReservedOutboundState', but before it will call `connect`
                -- the `accept` call will return.  We overwrite the state and
                -- replace the connection state 'TVar' with a fresh one.  Nothing
                -- is blocked on the replaced 'TVar'.
                --
                -- The `SelfConn` transition can happen when the node tries to
                -- connect to itself (and inbound & outbound addresses are the
                -- same).
                let connState' :: ConnectionState peerAddr handle handleError version m
connState' = Provenance
-> ConnectionId peerAddr
-> Async m ()
-> ConnectionState peerAddr handle handleError version m
forall peerAddr handle handleError version (m :: * -> *).
Provenance
-> ConnectionId peerAddr
-> Async m ()
-> ConnectionState peerAddr handle handleError version m
UnnegotiatedState Provenance
provenance ConnectionId peerAddr
connId Async m ()
connThread
                (mutableConnVar', connState0') <-
                  STM
  m
  (MutableConnState peerAddr handle handleError version m,
   Maybe (ConnectionState peerAddr handle handleError version m))
-> m (MutableConnState peerAddr handle handleError version m,
      Maybe (ConnectionState peerAddr handle handleError version m))
forall a. (?callStack::CallStack) => STM m a -> m a
forall (m :: * -> *) a.
(MonadSTM m, ?callStack::CallStack) =>
STM m a -> m a
atomically (STM
   m
   (MutableConnState peerAddr handle handleError version m,
    Maybe (ConnectionState peerAddr handle handleError version m))
 -> m (MutableConnState peerAddr handle handleError version m,
       Maybe (ConnectionState peerAddr handle handleError version m)))
-> STM
     m
     (MutableConnState peerAddr handle handleError version m,
      Maybe (ConnectionState peerAddr handle handleError version m))
-> m (MutableConnState peerAddr handle handleError version m,
      Maybe (ConnectionState peerAddr handle handleError version m))
forall a b. (a -> b) -> a -> b
$ do
                    let v0 :: Maybe (MutableConnState peerAddr handle handleError version m)
v0 = ConnectionId peerAddr
-> ConnectionManagerState peerAddr handle handleError version m
-> Maybe (MutableConnState peerAddr handle handleError version m)
forall peerAddr a.
Ord peerAddr =>
ConnectionId peerAddr -> ConnMap peerAddr a -> Maybe a
State.lookup ConnectionId peerAddr
connId ConnectionManagerState peerAddr handle handleError version m
state
                    case Maybe (MutableConnState peerAddr handle handleError version m)
v0 of
                      Maybe (MutableConnState peerAddr handle handleError version m)
Nothing -> do
                        -- 'Accepted'
                        v <- peerAddr
-> ConnStateIdSupply m
-> ConnectionState peerAddr handle handleError version m
-> STM m (MutableConnState peerAddr handle handleError version m)
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)
State.newMutableConnState (ConnectionId peerAddr -> peerAddr
forall addr. ConnectionId addr -> addr
remoteAddress ConnectionId peerAddr
connId) ConnStateIdSupply m
connStateIdSupply ConnectionState peerAddr handle handleError version m
connState'
                        labelTVar (connVar v) ("conn-state-" ++ show connId)
                        return (v, Nothing)
                      Just MutableConnState peerAddr handle handleError version m
v -> do
                        -- 'Overwritten', 'SelfConn' or accepting a new
                        -- connection while the old one is terminating.
                        connState0' <- 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 (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 MutableConnState peerAddr handle handleError version m
v)
                        !v' <- case connState0' of
                           -- Overwritten
                           ReservedOutboundState {} -> StrictTVar
  m (ConnectionState peerAddr handle handleError version m)
-> ConnectionState peerAddr handle handleError version m
-> STM m ()
forall (m :: * -> *) a.
MonadSTM m =>
StrictTVar m a -> a -> STM m ()
writeTVar (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 MutableConnState peerAddr handle handleError version m
v) ConnectionState peerAddr handle handleError version m
connState'
                                                    STM m ()
-> MutableConnState peerAddr handle handleError version m
-> STM m (MutableConnState peerAddr handle handleError version m)
forall (f :: * -> *) a b. Functor f => f a -> b -> f b
$> MutableConnState peerAddr handle handleError version m
v
                           -- SelfConn
                           UnnegotiatedState     {} -> StrictTVar
  m (ConnectionState peerAddr handle handleError version m)
-> ConnectionState peerAddr handle handleError version m
-> STM m ()
forall (m :: * -> *) a.
MonadSTM m =>
StrictTVar m a -> a -> STM m ()
writeTVar (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 MutableConnState peerAddr handle handleError version m
v) ConnectionState peerAddr handle handleError version m
connState'
                                                    STM m ()
-> MutableConnState peerAddr handle handleError version m
-> STM m (MutableConnState peerAddr handle handleError version m)
forall (f :: * -> *) a b. Functor f => f a -> b -> f b
$> MutableConnState peerAddr handle handleError version m
v

                           OutboundUniState      {} -> StrictTVar
  m (ConnectionState peerAddr handle handleError version m)
-> ConnectionState peerAddr handle handleError version m
-> STM m ()
forall (m :: * -> *) a.
MonadSTM m =>
StrictTVar m a -> a -> STM m ()
writeTVar (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 MutableConnState peerAddr handle handleError version m
v) ConnectionState peerAddr handle handleError version m
connState'
                                                    STM m ()
-> MutableConnState peerAddr handle handleError version m
-> STM m (MutableConnState peerAddr handle handleError version m)
forall (f :: * -> *) a b. Functor f => f a -> b -> f b
$> Bool
-> MutableConnState peerAddr handle handleError version m
-> MutableConnState peerAddr handle handleError version m
forall a. (?callStack::CallStack) => Bool -> a -> a
assert Bool
False MutableConnState peerAddr handle handleError version m
v
                           OutboundDupState      {} -> StrictTVar
  m (ConnectionState peerAddr handle handleError version m)
-> ConnectionState peerAddr handle handleError version m
-> STM m ()
forall (m :: * -> *) a.
MonadSTM m =>
StrictTVar m a -> a -> STM m ()
writeTVar (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 MutableConnState peerAddr handle handleError version m
v) ConnectionState peerAddr handle handleError version m
connState'
                                                    STM m ()
-> MutableConnState peerAddr handle handleError version m
-> STM m (MutableConnState peerAddr handle handleError version m)
forall (f :: * -> *) a b. Functor f => f a -> b -> f b
$> Bool
-> MutableConnState peerAddr handle handleError version m
-> MutableConnState peerAddr handle handleError version m
forall a. (?callStack::CallStack) => Bool -> a -> a
assert Bool
False MutableConnState peerAddr handle handleError version m
v
                           OutboundIdleState     {} -> StrictTVar
  m (ConnectionState peerAddr handle handleError version m)
-> ConnectionState peerAddr handle handleError version m
-> STM m ()
forall (m :: * -> *) a.
MonadSTM m =>
StrictTVar m a -> a -> STM m ()
writeTVar (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 MutableConnState peerAddr handle handleError version m
v) ConnectionState peerAddr handle handleError version m
connState'
                                                    STM m ()
-> MutableConnState peerAddr handle handleError version m
-> STM m (MutableConnState peerAddr handle handleError version m)
forall (f :: * -> *) a b. Functor f => f a -> b -> f b
$> Bool
-> MutableConnState peerAddr handle handleError version m
-> MutableConnState peerAddr handle handleError version m
forall a. (?callStack::CallStack) => Bool -> a -> a
assert Bool
False MutableConnState peerAddr handle handleError version m
v
                           DuplexState           {} -> StrictTVar
  m (ConnectionState peerAddr handle handleError version m)
-> ConnectionState peerAddr handle handleError version m
-> STM m ()
forall (m :: * -> *) a.
MonadSTM m =>
StrictTVar m a -> a -> STM m ()
writeTVar (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 MutableConnState peerAddr handle handleError version m
v) ConnectionState peerAddr handle handleError version m
connState'
                                                    STM m ()
-> MutableConnState peerAddr handle handleError version m
-> STM m (MutableConnState peerAddr handle handleError version m)
forall (f :: * -> *) a b. Functor f => f a -> b -> f b
$> Bool
-> MutableConnState peerAddr handle handleError version m
-> MutableConnState peerAddr handle handleError version m
forall a. (?callStack::CallStack) => Bool -> a -> a
assert Bool
False MutableConnState peerAddr handle handleError version m
v
                           InboundIdleState      {} -> StrictTVar
  m (ConnectionState peerAddr handle handleError version m)
-> ConnectionState peerAddr handle handleError version m
-> STM m ()
forall (m :: * -> *) a.
MonadSTM m =>
StrictTVar m a -> a -> STM m ()
writeTVar (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 MutableConnState peerAddr handle handleError version m
v) ConnectionState peerAddr handle handleError version m
connState'
                                                    STM m ()
-> MutableConnState peerAddr handle handleError version m
-> STM m (MutableConnState peerAddr handle handleError version m)
forall (f :: * -> *) a b. Functor f => f a -> b -> f b
$> Bool
-> MutableConnState peerAddr handle handleError version m
-> MutableConnState peerAddr handle handleError version m
forall a. (?callStack::CallStack) => Bool -> a -> a
assert Bool
False MutableConnState peerAddr handle handleError version m
v
                           InboundState          {} -> StrictTVar
  m (ConnectionState peerAddr handle handleError version m)
-> ConnectionState peerAddr handle handleError version m
-> STM m ()
forall (m :: * -> *) a.
MonadSTM m =>
StrictTVar m a -> a -> STM m ()
writeTVar (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 MutableConnState peerAddr handle handleError version m
v) ConnectionState peerAddr handle handleError version m
connState'
                                                    STM m ()
-> MutableConnState peerAddr handle handleError version m
-> STM m (MutableConnState peerAddr handle handleError version m)
forall (f :: * -> *) a b. Functor f => f a -> b -> f b
$> Bool
-> MutableConnState peerAddr handle handleError version m
-> MutableConnState peerAddr handle handleError version m
forall a. (?callStack::CallStack) => Bool -> a -> a
assert Bool
False MutableConnState peerAddr handle handleError version m
v

                           TerminatingState      {} -> peerAddr
-> ConnStateIdSupply m
-> ConnectionState peerAddr handle handleError version m
-> STM m (MutableConnState peerAddr handle handleError version m)
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)
State.newMutableConnState (ConnectionId peerAddr -> peerAddr
forall addr. ConnectionId addr -> addr
remoteAddress ConnectionId peerAddr
connId) ConnStateIdSupply m
connStateIdSupply ConnectionState peerAddr handle handleError version m
connState'
                           TerminatedState       {} -> peerAddr
-> ConnStateIdSupply m
-> ConnectionState peerAddr handle handleError version m
-> STM m (MutableConnState peerAddr handle handleError version m)
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)
State.newMutableConnState (ConnectionId peerAddr -> peerAddr
forall addr. ConnectionId addr -> addr
remoteAddress ConnectionId peerAddr
connId) ConnStateIdSupply m
connStateIdSupply ConnectionState peerAddr handle handleError version m
connState'

                        labelTVar (connVar v') ("conn-state-" ++ show connId)
                        return (v', Just connState0')

                connThread' <-
                  forkConnectionHandler
                     id stateVar mutableConnVar' socket connId writer handler
                return (connThread', mutableConnVar', connState0', connState')

            traceWith trTracer (TransitionTrace (connStateId connVar)
                                 Transition { fromState = maybe Unknown Known connState0
                                            , toState   = Known connState
                                            })
            return ( State.insert connId connVar state
                   , Just (connVar, connThread, reader)
                   )
          else
            return ( state
                   , Nothing
                   )

        case r of
          Maybe
  (MutableConnState peerAddr handle handleError version m,
   Async m (),
   PromiseReader
     m
     (Either
        handleError
        (HandshakeConnectionResult handle (version, versionData))))
Nothing ->
            Connected peerAddr handle handleError
-> m (Connected peerAddr handle handleError)
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (ConnectionId peerAddr
-> Maybe handleError -> Connected peerAddr handle handleError
forall peerAddr handle handleError.
ConnectionId peerAddr
-> Maybe handleError -> Connected peerAddr handle handleError
Disconnected ConnectionId peerAddr
connId Maybe handleError
forall a. Maybe a
Nothing)

          Just (mutableConnState :: MutableConnState peerAddr handle handleError version m
mutableConnState@MutableConnState { StrictTVar
  m (ConnectionState peerAddr handle handleError version m)
connVar :: 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)
connVar, ConnStateId
connStateId :: forall peerAddr handle handleError version (m :: * -> *).
MutableConnState peerAddr handle handleError version m
-> ConnStateId
connStateId :: ConnStateId
connStateId }
               , Async m ()
connThread, PromiseReader
  m
  (Either
     handleError
     (HandshakeConnectionResult handle (version, versionData)))
reader) -> do
            StrictTMVar
  m (ConnectionManagerState peerAddr handle handleError version m)
-> m ()
traceCounters StrictTMVar
  m (ConnectionManagerState peerAddr handle handleError version m)
stateVar

            res <- STM
  m
  (Either
     handleError
     (HandshakeConnectionResult handle (version, versionData)))
-> m (Either
        handleError
        (HandshakeConnectionResult handle (version, versionData)))
forall a. (?callStack::CallStack) => STM m a -> m a
forall (m :: * -> *) a.
(MonadSTM m, ?callStack::CallStack) =>
STM m a -> m a
atomically (STM
   m
   (Either
      handleError
      (HandshakeConnectionResult handle (version, versionData)))
 -> m (Either
         handleError
         (HandshakeConnectionResult handle (version, versionData))))
-> STM
     m
     (Either
        handleError
        (HandshakeConnectionResult handle (version, versionData)))
-> m (Either
        handleError
        (HandshakeConnectionResult handle (version, versionData)))
forall a b. (a -> b) -> a -> b
$ PromiseReader
  m
  (Either
     handleError
     (HandshakeConnectionResult handle (version, versionData)))
-> STM
     m
     (Either
        handleError
        (HandshakeConnectionResult handle (version, versionData)))
forall (m :: * -> *) a. PromiseReader m a -> STM m a
readPromise PromiseReader
  m
  (Either
     handleError
     (HandshakeConnectionResult handle (version, versionData)))
reader
            case res of
              Left handleError
handleError -> do
                ConnectionId peerAddr
-> ConnStateId
-> StrictTVar
     m (ConnectionState peerAddr handle handleError version m)
-> Async m ()
-> StrictTMVar
     m (ConnectionManagerState peerAddr handle handleError version m)
-> MutableConnState peerAddr handle handleError version m
-> Maybe handleError
-> m (Connected peerAddr handle handleError)
forall handle1.
ConnectionId peerAddr
-> ConnStateId
-> StrictTVar
     m (ConnectionState peerAddr handle handleError version m)
-> Async m ()
-> StrictTMVar
     m (ConnectionManagerState peerAddr handle handleError version m)
-> MutableConnState peerAddr handle handleError version m
-> Maybe handleError
-> m (Connected peerAddr handle1 handleError)
terminateInboundWithErrorOrQuery ConnectionId peerAddr
connId ConnStateId
connStateId StrictTVar
  m (ConnectionState peerAddr handle handleError version m)
connVar Async m ()
connThread StrictTMVar
  m (ConnectionManagerState peerAddr handle handleError version m)
stateVar MutableConnState peerAddr handle handleError version m
mutableConnState (Maybe handleError -> m (Connected peerAddr handle handleError))
-> Maybe handleError -> m (Connected peerAddr handle handleError)
forall a b. (a -> b) -> a -> b
$ handleError -> Maybe handleError
forall a. a -> Maybe a
Just handleError
handleError

              Right HandshakeConnectionResult handle (version, versionData)
HandshakeConnectionQuery -> do
                ConnectionId peerAddr
-> ConnStateId
-> StrictTVar
     m (ConnectionState peerAddr handle handleError version m)
-> Async m ()
-> StrictTMVar
     m (ConnectionManagerState peerAddr handle handleError version m)
-> MutableConnState peerAddr handle handleError version m
-> Maybe handleError
-> m (Connected peerAddr handle handleError)
forall handle1.
ConnectionId peerAddr
-> ConnStateId
-> StrictTVar
     m (ConnectionState peerAddr handle handleError version m)
-> Async m ()
-> StrictTMVar
     m (ConnectionManagerState peerAddr handle handleError version m)
-> MutableConnState peerAddr handle handleError version m
-> Maybe handleError
-> m (Connected peerAddr handle1 handleError)
terminateInboundWithErrorOrQuery ConnectionId peerAddr
connId ConnStateId
connStateId StrictTVar
  m (ConnectionState peerAddr handle handleError version m)
connVar Async m ()
connThread StrictTMVar
  m (ConnectionManagerState peerAddr handle handleError version m)
stateVar MutableConnState peerAddr handle handleError version m
mutableConnState Maybe handleError
forall a. Maybe a
Nothing

              Right (HandshakeConnectionResult handle
handle (version
_version, versionData
versionData)) -> do
                let dataFlow :: DataFlow
dataFlow = versionData -> DataFlow
connectionDataFlow versionData
versionData
                (connected, mbTransition, provenance) <- STM
  m
  (Bool,
   Maybe
     (Transition'
        (MaybeUnknown
           (ConnectionState peerAddr handle handleError version m))),
   Provenance)
-> m (Bool,
      Maybe
        (Transition'
           (MaybeUnknown
              (ConnectionState peerAddr handle handleError version m))),
      Provenance)
forall a. (?callStack::CallStack) => STM m a -> m a
forall (m :: * -> *) a.
(MonadSTM m, ?callStack::CallStack) =>
STM m a -> m a
atomically (STM
   m
   (Bool,
    Maybe
      (Transition'
         (MaybeUnknown
            (ConnectionState peerAddr handle handleError version m))),
    Provenance)
 -> m (Bool,
       Maybe
         (Transition'
            (MaybeUnknown
               (ConnectionState peerAddr handle handleError version m))),
       Provenance))
-> STM
     m
     (Bool,
      Maybe
        (Transition'
           (MaybeUnknown
              (ConnectionState peerAddr handle handleError version m))),
      Provenance)
-> m (Bool,
      Maybe
        (Transition'
           (MaybeUnknown
              (ConnectionState peerAddr handle handleError version m))),
      Provenance)
forall a b. (a -> b) -> a -> b
$ do
                  connState <- 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)
connVar
                  case connState of
                    -- Inbound connections cannot be found in this state at this
                    -- stage.
                    ConnectionState peerAddr handle handleError version m
ReservedOutboundState ->
                      ConnectionManagerError peerAddr
-> STM
     m
     (Bool,
      Maybe
        (Transition'
           (MaybeUnknown
              (ConnectionState peerAddr handle handleError version m))),
      Provenance)
forall (m :: * -> *) e a.
(MonadSTM m, MonadThrow (STM m), Exception e) =>
e -> STM m a
throwSTM ((CallStack -> ConnectionManagerError peerAddr)
-> ConnectionManagerError peerAddr
forall a. (?callStack::CallStack) => (CallStack -> a) -> a
withCallStack (peerAddr -> CallStack -> ConnectionManagerError peerAddr
forall peerAddr.
peerAddr -> CallStack -> ConnectionManagerError peerAddr
ImpossibleState (ConnectionId peerAddr -> peerAddr
forall addr. ConnectionId addr -> addr
remoteAddress ConnectionId peerAddr
connId)))

                    --
                    -- The common case.
                    --
                    -- Note: we don't set an explicit timeout here.  The
                    -- server will set a timeout and call
                    -- 'releaseInboundConnection' when it expires.
                    --
                    UnnegotiatedState {} -> do
                      let connState' :: ConnectionState peerAddr handle handleError version m
connState' = ConnectionId peerAddr
-> Async m ()
-> handle
-> DataFlow
-> ConnectionState peerAddr handle handleError version m
forall peerAddr handle handleError version (m :: * -> *).
ConnectionId peerAddr
-> Async m ()
-> handle
-> DataFlow
-> ConnectionState peerAddr handle handleError version m
InboundIdleState
                                         ConnectionId peerAddr
connId Async m ()
connThread handle
handle DataFlow
dataFlow
                      StrictTVar
  m (ConnectionState peerAddr handle handleError version m)
-> ConnectionState peerAddr handle handleError version m
-> STM m ()
forall (m :: * -> *) a.
MonadSTM m =>
StrictTVar m a -> a -> STM m ()
writeTVar StrictTVar
  m (ConnectionState peerAddr handle handleError version m)
connVar ConnectionState peerAddr handle handleError version m
connState'
                      (Bool,
 Maybe
   (Transition'
      (MaybeUnknown
         (ConnectionState peerAddr handle handleError version m))),
 Provenance)
-> STM
     m
     (Bool,
      Maybe
        (Transition'
           (MaybeUnknown
              (ConnectionState peerAddr handle handleError version m))),
      Provenance)
forall a. a -> STM m a
forall (m :: * -> *) a. Monad m => a -> m a
return ( Bool
True
                             , Transition'
  (MaybeUnknown
     (ConnectionState peerAddr handle handleError version m))
-> Maybe
     (Transition'
        (MaybeUnknown
           (ConnectionState peerAddr handle handleError version m)))
forall a. a -> Maybe a
Just (Transition'
   (MaybeUnknown
      (ConnectionState peerAddr handle handleError version m))
 -> Maybe
      (Transition'
         (MaybeUnknown
            (ConnectionState peerAddr handle handleError version m))))
-> Transition'
     (MaybeUnknown
        (ConnectionState peerAddr handle handleError version m))
-> Maybe
     (Transition'
        (MaybeUnknown
           (ConnectionState peerAddr handle handleError version m)))
forall a b. (a -> b) -> a -> b
$ ConnectionState peerAddr handle handleError version m
-> ConnectionState peerAddr handle handleError version m
-> Transition'
     (MaybeUnknown
        (ConnectionState peerAddr handle handleError version m))
forall state. state -> state -> Transition state
mkTransition ConnectionState peerAddr handle handleError version m
connState ConnectionState peerAddr handle handleError version m
connState'
                             , Provenance
Inbound
                             )

                    -- Self connection: the inbound side lost the race to update
                    -- the state after negotiating the connection.
                    OutboundUniState {} -> (Bool,
 Maybe
   (Transition'
      (MaybeUnknown
         (ConnectionState peerAddr handle handleError version m))),
 Provenance)
-> STM
     m
     (Bool,
      Maybe
        (Transition'
           (MaybeUnknown
              (ConnectionState peerAddr handle handleError version m))),
      Provenance)
forall a. a -> STM m a
forall (m :: * -> *) a. Monad m => a -> m a
return (Bool
True, Maybe
  (Transition'
     (MaybeUnknown
        (ConnectionState peerAddr handle handleError version m)))
forall a. Maybe a
Nothing, Provenance
Outbound)
                    OutboundDupState {} -> (Bool,
 Maybe
   (Transition'
      (MaybeUnknown
         (ConnectionState peerAddr handle handleError version m))),
 Provenance)
-> STM
     m
     (Bool,
      Maybe
        (Transition'
           (MaybeUnknown
              (ConnectionState peerAddr handle handleError version m))),
      Provenance)
forall a. a -> STM m a
forall (m :: * -> *) a. Monad m => a -> m a
return (Bool
True, Maybe
  (Transition'
     (MaybeUnknown
        (ConnectionState peerAddr handle handleError version m)))
forall a. Maybe a
Nothing, Provenance
Outbound)

                    OutboundIdleState ConnectionId peerAddr
_ Async m ()
_ handle
_ DataFlow
dataFlow' -> do
                      let connState' :: ConnectionState peerAddr handle handleError version m
connState' = ConnectionId peerAddr
-> Async m ()
-> handle
-> DataFlow
-> ConnectionState peerAddr handle handleError version m
forall peerAddr handle handleError version (m :: * -> *).
ConnectionId peerAddr
-> Async m ()
-> handle
-> DataFlow
-> ConnectionState peerAddr handle handleError version m
InboundIdleState
                                         ConnectionId peerAddr
connId Async m ()
connThread handle
handle
                                         DataFlow
dataFlow'
                      StrictTVar
  m (ConnectionState peerAddr handle handleError version m)
-> ConnectionState peerAddr handle handleError version m
-> STM m ()
forall (m :: * -> *) a.
MonadSTM m =>
StrictTVar m a -> a -> STM m ()
writeTVar StrictTVar
  m (ConnectionState peerAddr handle handleError version m)
connVar ConnectionState peerAddr handle handleError version m
connState'
                      (Bool,
 Maybe
   (Transition'
      (MaybeUnknown
         (ConnectionState peerAddr handle handleError version m))),
 Provenance)
-> STM
     m
     (Bool,
      Maybe
        (Transition'
           (MaybeUnknown
              (ConnectionState peerAddr handle handleError version m))),
      Provenance)
forall a. a -> STM m a
forall (m :: * -> *) a. Monad m => a -> m a
return ( Bool
True
                             , Transition'
  (MaybeUnknown
     (ConnectionState peerAddr handle handleError version m))
-> Maybe
     (Transition'
        (MaybeUnknown
           (ConnectionState peerAddr handle handleError version m)))
forall a. a -> Maybe a
Just (Transition'
   (MaybeUnknown
      (ConnectionState peerAddr handle handleError version m))
 -> Maybe
      (Transition'
         (MaybeUnknown
            (ConnectionState peerAddr handle handleError version m))))
-> Transition'
     (MaybeUnknown
        (ConnectionState peerAddr handle handleError version m))
-> Maybe
     (Transition'
        (MaybeUnknown
           (ConnectionState peerAddr handle handleError version m)))
forall a b. (a -> b) -> a -> b
$ ConnectionState peerAddr handle handleError version m
-> ConnectionState peerAddr handle handleError version m
-> Transition'
     (MaybeUnknown
        (ConnectionState peerAddr handle handleError version m))
forall state. state -> state -> Transition state
mkTransition ConnectionState peerAddr handle handleError version m
connState ConnectionState peerAddr handle handleError version m
connState'
                             , Provenance
Outbound
                             )

                    InboundIdleState {} ->
                      ConnectionManagerError peerAddr
-> STM
     m
     (Bool,
      Maybe
        (Transition'
           (MaybeUnknown
              (ConnectionState peerAddr handle handleError version m))),
      Provenance)
forall (m :: * -> *) e a.
(MonadSTM m, MonadThrow (STM m), Exception e) =>
e -> STM m a
throwSTM ((CallStack -> ConnectionManagerError peerAddr)
-> ConnectionManagerError peerAddr
forall a. (?callStack::CallStack) => (CallStack -> a) -> a
withCallStack (peerAddr -> CallStack -> ConnectionManagerError peerAddr
forall peerAddr.
peerAddr -> CallStack -> ConnectionManagerError peerAddr
ImpossibleState (ConnectionId peerAddr -> peerAddr
forall addr. ConnectionId addr -> addr
remoteAddress ConnectionId peerAddr
connId)))

                    -- At this stage the inbound connection cannot be in
                    -- 'InboundState', it would mean that there was another thread
                    -- that included that connection, but this would violate @TCP@
                    -- constraints.
                    InboundState {} ->
                      ConnectionManagerError peerAddr
-> STM
     m
     (Bool,
      Maybe
        (Transition'
           (MaybeUnknown
              (ConnectionState peerAddr handle handleError version m))),
      Provenance)
forall (m :: * -> *) e a.
(MonadSTM m, MonadThrow (STM m), Exception e) =>
e -> STM m a
throwSTM ((CallStack -> ConnectionManagerError peerAddr)
-> ConnectionManagerError peerAddr
forall a. (?callStack::CallStack) => (CallStack -> a) -> a
withCallStack (peerAddr -> CallStack -> ConnectionManagerError peerAddr
forall peerAddr.
peerAddr -> CallStack -> ConnectionManagerError peerAddr
ImpossibleState (ConnectionId peerAddr -> peerAddr
forall addr. ConnectionId addr -> addr
remoteAddress ConnectionId peerAddr
connId)))

                    DuplexState {} ->
                      ConnectionManagerError peerAddr
-> STM
     m
     (Bool,
      Maybe
        (Transition'
           (MaybeUnknown
              (ConnectionState peerAddr handle handleError version m))),
      Provenance)
forall (m :: * -> *) e a.
(MonadSTM m, MonadThrow (STM m), Exception e) =>
e -> STM m a
throwSTM ((CallStack -> ConnectionManagerError peerAddr)
-> ConnectionManagerError peerAddr
forall a. (?callStack::CallStack) => (CallStack -> a) -> a
withCallStack (peerAddr -> CallStack -> ConnectionManagerError peerAddr
forall peerAddr.
peerAddr -> CallStack -> ConnectionManagerError peerAddr
ImpossibleState (ConnectionId peerAddr -> peerAddr
forall addr. ConnectionId addr -> addr
remoteAddress ConnectionId peerAddr
connId)))

                    TerminatingState {} -> (Bool,
 Maybe
   (Transition'
      (MaybeUnknown
         (ConnectionState peerAddr handle handleError version m))),
 Provenance)
-> STM
     m
     (Bool,
      Maybe
        (Transition'
           (MaybeUnknown
              (ConnectionState peerAddr handle handleError version m))),
      Provenance)
forall a. a -> STM m a
forall (m :: * -> *) a. Monad m => a -> m a
return (Bool
False, Maybe
  (Transition'
     (MaybeUnknown
        (ConnectionState peerAddr handle handleError version m)))
forall a. Maybe a
Nothing, Provenance
Inbound)

                    TerminatedState {} -> (Bool,
 Maybe
   (Transition'
      (MaybeUnknown
         (ConnectionState peerAddr handle handleError version m))),
 Provenance)
-> STM
     m
     (Bool,
      Maybe
        (Transition'
           (MaybeUnknown
              (ConnectionState peerAddr handle handleError version m))),
      Provenance)
forall a. a -> STM m a
forall (m :: * -> *) a. Monad m => a -> m a
return (Bool
False, Maybe
  (Transition'
     (MaybeUnknown
        (ConnectionState peerAddr handle handleError version m)))
forall a. Maybe a
Nothing, Provenance
Inbound)

                traverse_ (traceWith trTracer . TransitionTrace connStateId) mbTransition
                traceCounters stateVar

                -- Note that we don't set a timeout thread here which would
                -- perform:
                -- @
                --   Commit^{dataFlow}
                --     : InboundIdleState dataFlow
                --     → TerminatingState
                -- @
                -- This is not needed!  When we return from this call, the inbound
                -- protocol governor will monitor the connection.  Once it becomes
                -- idle, it will call 'releaseInboundConnection' which will
                -- perform the aforementioned @Commit@ transition.

                if connected
                  then do
                    case inboundGovernorInfoChannel of
                      InResponderMode InformationChannel (NewConnectionInfo peerAddr handle) m
infoChannel ->
                        STM m () -> m ()
forall a. (?callStack::CallStack) => STM m a -> m a
forall (m :: * -> *) a.
(MonadSTM m, ?callStack::CallStack) =>
STM m a -> m a
atomically (STM m () -> m ()) -> STM m () -> m ()
forall a b. (a -> b) -> a -> b
$ InformationChannel (NewConnectionInfo peerAddr handle) m
-> NewConnectionInfo peerAddr handle -> STM m ()
forall a (m :: * -> *). InformationChannel a m -> a -> STM m ()
InfoChannel.writeMessage
                                       InformationChannel (NewConnectionInfo peerAddr handle) m
infoChannel
                                       (Provenance
-> ConnectionId peerAddr
-> DataFlow
-> handle
-> NewConnectionInfo peerAddr handle
forall peerAddr handle.
Provenance
-> ConnectionId peerAddr
-> DataFlow
-> handle
-> NewConnectionInfo peerAddr handle
NewConnectionInfo Provenance
provenance ConnectionId peerAddr
connId DataFlow
dataFlow handle
handle)
                      InResponderMode
  muxMode (InformationChannel (NewConnectionInfo peerAddr handle) m)
_ -> () -> m ()
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return ()
                    return $ Connected connId dataFlow handle

                  -- the connection is in `TerminatingState` or
                  -- `TerminatedState`.
                  else
                    return $ Disconnected connId Nothing

    terminateInboundWithErrorOrQuery
      :: ConnectionId peerAddr
      -> State.ConnStateId
      -> StrictTVar m (ConnectionState peerAddr handle handleError version m)
      -> Async m ()
      -> StrictTMVar
           m (ConnectionManagerState peerAddr handle handleError version m)
      -> MutableConnState peerAddr handle handleError version m
      -> Maybe handleError
      -> m (Connected peerAddr handle1 handleError)
    terminateInboundWithErrorOrQuery :: forall handle1.
ConnectionId peerAddr
-> ConnStateId
-> StrictTVar
     m (ConnectionState peerAddr handle handleError version m)
-> Async m ()
-> StrictTMVar
     m (ConnectionManagerState peerAddr handle handleError version m)
-> MutableConnState peerAddr handle handleError version m
-> Maybe handleError
-> m (Connected peerAddr handle1 handleError)
terminateInboundWithErrorOrQuery ConnectionId peerAddr
connId ConnStateId
connStateId StrictTVar
  m (ConnectionState peerAddr handle handleError version m)
connVar Async m ()
connThread StrictTMVar
  m (ConnectionManagerState peerAddr handle handleError version m)
stateVar MutableConnState peerAddr handle handleError version m
mutableConnState Maybe handleError
handleErrorM = do
        transitions <- STM
  m
  [Transition'
     (MaybeUnknown
        (ConnectionState peerAddr handle handleError version m))]
-> m [Transition'
        (MaybeUnknown
           (ConnectionState peerAddr handle handleError version m))]
forall a. (?callStack::CallStack) => STM m a -> m a
forall (m :: * -> *) a.
(MonadSTM m, ?callStack::CallStack) =>
STM m a -> m a
atomically (STM
   m
   [Transition'
      (MaybeUnknown
         (ConnectionState peerAddr handle handleError version m))]
 -> m [Transition'
         (MaybeUnknown
            (ConnectionState peerAddr handle handleError version m))])
-> STM
     m
     [Transition'
        (MaybeUnknown
           (ConnectionState peerAddr handle handleError version m))]
-> m [Transition'
        (MaybeUnknown
           (ConnectionState peerAddr handle handleError version m))]
forall a b. (a -> b) -> a -> b
$ do
          connState <- 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)
connVar

          let connState' =
                case handleError -> HandleErrorType
classifyHandleError (handleError -> HandleErrorType)
-> Maybe handleError -> Maybe HandleErrorType
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Maybe handleError
handleErrorM of
                  Just HandleErrorType
HandshakeFailure ->
                    ConnectionId peerAddr
-> Async m ()
-> Maybe handleError
-> ConnectionState peerAddr handle handleError version m
forall peerAddr handle handleError version (m :: * -> *).
ConnectionId peerAddr
-> Async m ()
-> Maybe handleError
-> ConnectionState peerAddr handle handleError version m
TerminatingState ConnectionId peerAddr
connId Async m ()
connThread
                                     Maybe handleError
handleErrorM
                  Just HandleErrorType
HandshakeProtocolViolation ->
                    Maybe handleError
-> ConnectionState peerAddr handle handleError version m
forall peerAddr handle handleError version (m :: * -> *).
Maybe handleError
-> ConnectionState peerAddr handle handleError version m
TerminatedState Maybe handleError
handleErrorM
                  -- On inbound query, connection is terminating.
                  Maybe HandleErrorType
Nothing ->
                    ConnectionId peerAddr
-> Async m ()
-> Maybe handleError
-> ConnectionState peerAddr handle handleError version m
forall peerAddr handle handleError version (m :: * -> *).
ConnectionId peerAddr
-> Async m ()
-> Maybe handleError
-> ConnectionState peerAddr handle handleError version m
TerminatingState ConnectionId peerAddr
connId Async m ()
connThread
                                     Maybe handleError
handleErrorM
              transition = ConnectionState peerAddr handle handleError version m
-> ConnectionState peerAddr handle handleError version m
-> Transition'
     (MaybeUnknown
        (ConnectionState peerAddr handle handleError version m))
forall state. state -> state -> Transition state
mkTransition ConnectionState peerAddr handle handleError version m
connState ConnectionState peerAddr handle handleError version m
connState'
              absConnState = MaybeUnknown
  (ConnectionState peerAddr handle handleError version m)
-> AbstractState
forall muxMode peerAddr m a (b :: * -> *).
MaybeUnknown (ConnectionState muxMode peerAddr m a b)
-> AbstractState
State.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
connState)
              shouldTrace = AbstractState
absConnState AbstractState -> AbstractState -> Bool
forall a. Eq a => a -> a -> Bool
/= AbstractState
TerminatedSt

          updated <-
            modifyTMVarSTM
              stateVar
              ( \ConnectionManagerState peerAddr handle handleError version m
state ->
                case ConnectionId peerAddr
-> ConnectionManagerState peerAddr handle handleError version m
-> Maybe (MutableConnState peerAddr handle handleError version m)
forall peerAddr a.
Ord peerAddr =>
ConnectionId peerAddr -> ConnMap peerAddr a -> Maybe a
State.lookup ConnectionId peerAddr
connId ConnectionManagerState peerAddr handle handleError version m
state of
                  Maybe (MutableConnState peerAddr handle handleError version m)
Nothing -> (ConnectionManagerState peerAddr handle handleError version m,
 Bool)
-> STM
     m
     (ConnectionManagerState peerAddr handle handleError version m,
      Bool)
forall a. a -> STM m a
forall (m :: * -> *) a. Monad m => a -> m a
return (ConnectionManagerState peerAddr handle handleError version m
state, Bool
False)
                  Just MutableConnState peerAddr handle handleError version m
mutableConnState'  ->
                    if MutableConnState peerAddr handle handleError version m
mutableConnState' MutableConnState peerAddr handle handleError version m
-> MutableConnState peerAddr handle handleError version m -> Bool
forall a. Eq a => a -> a -> Bool
== MutableConnState peerAddr handle handleError version m
mutableConnState
                      then do
                        -- 'handleError' might be either a handshake
                        -- negotiation a protocol failure (an IO
                        -- exception, a timeout or codec failure).  In
                        -- the first case we should not reset the
                        -- connection as this is not a protocol error.
                        --
                        -- If we are deleting the connState from the
                        -- state then connState' can be TerminatingSt in
                        -- which case we are going to transition
                        -- TerminatingSt -> TerminatedSt. Otherwise,
                        -- Connection Manager cleanup will take care of
                        -- tracing accordingly.
                        StrictTVar
  m (ConnectionState peerAddr handle handleError version m)
-> ConnectionState peerAddr handle handleError version m
-> STM m ()
forall (m :: * -> *) a.
MonadSTM m =>
StrictTVar m a -> a -> STM m ()
writeTVar StrictTVar
  m (ConnectionState peerAddr handle handleError version m)
connVar ConnectionState peerAddr handle handleError version m
connState'

                        (ConnectionManagerState peerAddr handle handleError version m,
 Bool)
-> STM
     m
     (ConnectionManagerState peerAddr handle handleError version m,
      Bool)
forall a. a -> STM m a
forall (m :: * -> *) a. Monad m => a -> m a
return (ConnectionId peerAddr
-> ConnectionManagerState peerAddr handle handleError version m
-> ConnectionManagerState peerAddr handle handleError version m
forall peerAddr a.
Ord peerAddr =>
ConnectionId peerAddr -> ConnMap peerAddr a -> ConnMap peerAddr a
State.delete ConnectionId peerAddr
connId ConnectionManagerState peerAddr handle handleError version m
state, Bool
True)
                      else
                        (ConnectionManagerState peerAddr handle handleError version m,
 Bool)
-> STM
     m
     (ConnectionManagerState peerAddr handle handleError version m,
      Bool)
forall a. a -> STM m a
forall (m :: * -> *) a. Monad m => a -> m a
return (ConnectionManagerState peerAddr handle handleError version m
state                    , Bool
False)
              )

          if updated
             then
            -- Key was present in the dictionary (stateVar) and
            -- removed so we trace the removal.
              return $
                if shouldTrace
                   then [ transition
                        , Transition
                           { fromState = Known (TerminatedState Nothing)
                           , toState   = Unknown
                           }
                        ]
                   else [ Transition
                           { fromState = Known (TerminatedState Nothing)
                           , toState   = Unknown
                           }
                        ]
            -- Key was not present in the dictionary (stateVar),
            -- so we do not trace anything as it was already traced upon
            -- deletion.
            --
            -- OR
            --
            -- Key was overwritten in the dictionary (stateVar),
            -- so we do not trace anything as it was already traced upon
            -- overwriting.
             else return [ ]

        traverse_ (traceWith trTracer . TransitionTrace connStateId) transitions
        traceCounters stateVar

        return (Disconnected connId handleErrorM)

    -- We need 'mask' in order to guarantee that the traces are logged if an
    -- async exception lands between the successful STM action and the logging
    -- action.
    releaseInboundConnectionImpl
        :: StrictTMVar m (ConnectionManagerState peerAddr handle handleError version m)
        -> ConnectionId peerAddr
        -> m (OperationResult DemotedToColdRemoteTr)
    releaseInboundConnectionImpl :: StrictTMVar
  m (ConnectionManagerState peerAddr handle handleError version m)
-> ConnectionId peerAddr
-> m (OperationResult DemotedToColdRemoteTr)
releaseInboundConnectionImpl StrictTMVar
  m (ConnectionManagerState peerAddr handle handleError version m)
stateVar ConnectionId peerAddr
connId = m (OperationResult DemotedToColdRemoteTr)
-> m (OperationResult DemotedToColdRemoteTr)
forall a. m a -> m a
forall (m :: * -> *) a. MonadMask m => m a -> m a
mask_ (m (OperationResult DemotedToColdRemoteTr)
 -> m (OperationResult DemotedToColdRemoteTr))
-> m (OperationResult DemotedToColdRemoteTr)
-> m (OperationResult DemotedToColdRemoteTr)
forall a b. (a -> b) -> a -> b
$ do
      Tracer m (Trace peerAddr handlerTrace)
-> Trace peerAddr handlerTrace -> m ()
forall (m :: * -> *) a. Tracer m a -> a -> m ()
traceWith Tracer m (Trace peerAddr handlerTrace)
tracer (Provenance -> ConnectionId peerAddr -> Trace peerAddr handlerTrace
forall peerAddr handlerTrace.
Provenance -> ConnectionId peerAddr -> Trace peerAddr handlerTrace
TrReleaseConnection Provenance
Inbound ConnectionId peerAddr
connId)
      (mbThread, mbTransitionTrace, result, mbAssertion) <- STM
  m
  (Maybe (Async m ()),
   Maybe
     (TransitionTrace
        ConnStateId
        (ConnectionState peerAddr handle handleError version m)),
   OperationResult DemotedToColdRemoteTr,
   Maybe (Trace peerAddr handlerTrace))
-> m (Maybe (Async m ()),
      Maybe
        (TransitionTrace
           ConnStateId
           (ConnectionState peerAddr handle handleError version m)),
      OperationResult DemotedToColdRemoteTr,
      Maybe (Trace peerAddr handlerTrace))
forall a. (?callStack::CallStack) => STM m a -> m a
forall (m :: * -> *) a.
(MonadSTM m, ?callStack::CallStack) =>
STM m a -> m a
atomically (STM
   m
   (Maybe (Async m ()),
    Maybe
      (TransitionTrace
         ConnStateId
         (ConnectionState peerAddr handle handleError version m)),
    OperationResult DemotedToColdRemoteTr,
    Maybe (Trace peerAddr handlerTrace))
 -> m (Maybe (Async m ()),
       Maybe
         (TransitionTrace
            ConnStateId
            (ConnectionState peerAddr handle handleError version m)),
       OperationResult DemotedToColdRemoteTr,
       Maybe (Trace peerAddr handlerTrace)))
-> STM
     m
     (Maybe (Async m ()),
      Maybe
        (TransitionTrace
           ConnStateId
           (ConnectionState peerAddr handle handleError version m)),
      OperationResult DemotedToColdRemoteTr,
      Maybe (Trace peerAddr handlerTrace))
-> m (Maybe (Async m ()),
      Maybe
        (TransitionTrace
           ConnStateId
           (ConnectionState peerAddr handle handleError version m)),
      OperationResult DemotedToColdRemoteTr,
      Maybe (Trace peerAddr handlerTrace))
forall a b. (a -> b) -> a -> b
$ do
        state <- StrictTMVar
  m (ConnectionManagerState peerAddr handle handleError version m)
-> STM
     m (ConnectionManagerState peerAddr handle handleError version m)
forall (m :: * -> *) a. MonadSTM m => StrictTMVar m a -> STM m a
readTMVar StrictTMVar
  m (ConnectionManagerState peerAddr handle handleError version m)
stateVar
        case State.lookup connId state of
          Maybe (MutableConnState peerAddr handle handleError version m)
Nothing -> do
            -- Note: this can happen if the inbound connection manager is
            -- notified late about the connection which has already terminated
            -- at this point.
            (Maybe (Async m ()),
 Maybe
   (TransitionTrace
      ConnStateId
      (ConnectionState peerAddr handle handleError version m)),
 OperationResult DemotedToColdRemoteTr,
 Maybe (Trace peerAddr handlerTrace))
-> STM
     m
     (Maybe (Async m ()),
      Maybe
        (TransitionTrace
           ConnStateId
           (ConnectionState peerAddr handle handleError version m)),
      OperationResult DemotedToColdRemoteTr,
      Maybe (Trace peerAddr handlerTrace))
forall a. a -> STM m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ( Maybe (Async m ())
forall a. Maybe a
Nothing
                 , Maybe
  (TransitionTrace
     ConnStateId
     (ConnectionState peerAddr handle handleError version m))
forall a. Maybe a
Nothing
                 , DemotedToColdRemoteTr -> OperationResult DemotedToColdRemoteTr
forall a. a -> OperationResult a
OperationSuccess DemotedToColdRemoteTr
CommitTr
                 , Maybe (Trace peerAddr handlerTrace)
forall a. Maybe a
Nothing
                 )
          Just MutableConnState { StrictTVar
  m (ConnectionState peerAddr handle handleError version m)
connVar :: 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)
connVar, ConnStateId
connStateId :: forall peerAddr handle handleError version (m :: * -> *).
MutableConnState peerAddr handle handleError version m
-> ConnStateId
connStateId :: ConnStateId
connStateId } -> do
            connState <- 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)
connVar
            let st = MaybeUnknown
  (ConnectionState peerAddr handle handleError version m)
-> AbstractState
forall muxMode peerAddr m a (b :: * -> *).
MaybeUnknown (ConnectionState muxMode peerAddr m a b)
-> AbstractState
State.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
connState)
            case connState of
              -- In any of the following two states releasing is not
              -- supported.  'includeInboundConnection' is a synchronous
              -- operation which returns only once the connection is
              -- negotiated.
              ConnectionState peerAddr handle handleError version m
ReservedOutboundState ->
                (Maybe (Async m ()),
 Maybe
   (TransitionTrace
      ConnStateId
      (ConnectionState peerAddr handle handleError version m)),
 OperationResult DemotedToColdRemoteTr,
 Maybe (Trace peerAddr handlerTrace))
-> STM
     m
     (Maybe (Async m ()),
      Maybe
        (TransitionTrace
           ConnStateId
           (ConnectionState peerAddr handle handleError version m)),
      OperationResult DemotedToColdRemoteTr,
      Maybe (Trace peerAddr handlerTrace))
forall a. a -> STM m a
forall (m :: * -> *) a. Monad m => a -> m a
return ( Maybe (Async m ())
forall a. Maybe a
Nothing
                       , Maybe
  (TransitionTrace
     ConnStateId
     (ConnectionState peerAddr handle handleError version m))
forall a. Maybe a
Nothing
                       , AbstractState -> OperationResult DemotedToColdRemoteTr
forall a. AbstractState -> OperationResult a
UnsupportedState AbstractState
st
                       , Maybe (Trace peerAddr handlerTrace)
forall a. Maybe a
Nothing
                       )
              UnnegotiatedState {} ->
                (Maybe (Async m ()),
 Maybe
   (TransitionTrace
      ConnStateId
      (ConnectionState peerAddr handle handleError version m)),
 OperationResult DemotedToColdRemoteTr,
 Maybe (Trace peerAddr handlerTrace))
-> STM
     m
     (Maybe (Async m ()),
      Maybe
        (TransitionTrace
           ConnStateId
           (ConnectionState peerAddr handle handleError version m)),
      OperationResult DemotedToColdRemoteTr,
      Maybe (Trace peerAddr handlerTrace))
forall a. a -> STM m a
forall (m :: * -> *) a. Monad m => a -> m a
return ( Maybe (Async m ())
forall a. Maybe a
Nothing
                       , Maybe
  (TransitionTrace
     ConnStateId
     (ConnectionState peerAddr handle handleError version m))
forall a. Maybe a
Nothing
                       , AbstractState -> OperationResult DemotedToColdRemoteTr
forall a. AbstractState -> OperationResult a
UnsupportedState AbstractState
st
                       , Maybe (Trace peerAddr handlerTrace)
forall a. Maybe a
Nothing
                       )

              -- @
              --   TimeoutExpired : OutboundState^\tau Duplex
              --                  → OutboundState      Duplex
              -- @
              OutboundDupState ConnectionId peerAddr
_connId Async m ()
connThread handle
handle TimeoutExpired
Ticking -> do
                let connState' :: ConnectionState peerAddr handle handleError version m
connState' = ConnectionId peerAddr
-> Async m ()
-> handle
-> TimeoutExpired
-> ConnectionState peerAddr handle handleError version m
forall peerAddr handle handleError version (m :: * -> *).
ConnectionId peerAddr
-> Async m ()
-> handle
-> TimeoutExpired
-> ConnectionState peerAddr handle handleError version m
OutboundDupState ConnectionId peerAddr
connId Async m ()
connThread handle
handle TimeoutExpired
Expired
                StrictTVar
  m (ConnectionState peerAddr handle handleError version m)
-> ConnectionState peerAddr handle handleError version m
-> STM m ()
forall (m :: * -> *) a.
MonadSTM m =>
StrictTVar m a -> a -> STM m ()
writeTVar StrictTVar
  m (ConnectionState peerAddr handle handleError version m)
connVar ConnectionState peerAddr handle handleError version m
connState'
                (Maybe (Async m ()),
 Maybe
   (TransitionTrace
      ConnStateId
      (ConnectionState peerAddr handle handleError version m)),
 OperationResult DemotedToColdRemoteTr,
 Maybe (Trace peerAddr handlerTrace))
-> STM
     m
     (Maybe (Async m ()),
      Maybe
        (TransitionTrace
           ConnStateId
           (ConnectionState peerAddr handle handleError version m)),
      OperationResult DemotedToColdRemoteTr,
      Maybe (Trace peerAddr handlerTrace))
forall a. a -> STM m a
forall (m :: * -> *) a. Monad m => a -> m a
return ( Maybe (Async m ())
forall a. Maybe a
Nothing
                       , TransitionTrace
  ConnStateId (ConnectionState peerAddr handle handleError version m)
-> Maybe
     (TransitionTrace
        ConnStateId
        (ConnectionState peerAddr handle handleError version m))
forall a. a -> Maybe a
Just (ConnStateId
-> Transition'
     (MaybeUnknown
        (ConnectionState peerAddr handle handleError version m))
-> TransitionTrace
     ConnStateId (ConnectionState peerAddr handle handleError version m)
forall id state.
id -> Transition' state -> TransitionTrace' id state
TransitionTrace ConnStateId
connStateId (ConnectionState peerAddr handle handleError version m
-> ConnectionState peerAddr handle handleError version m
-> Transition'
     (MaybeUnknown
        (ConnectionState peerAddr handle handleError version m))
forall state. state -> state -> Transition state
mkTransition ConnectionState peerAddr handle handleError version m
connState ConnectionState peerAddr handle handleError version m
connState'))
                       , DemotedToColdRemoteTr -> OperationResult DemotedToColdRemoteTr
forall a. a -> OperationResult a
OperationSuccess DemotedToColdRemoteTr
KeepTr
                       , Maybe (Trace peerAddr handlerTrace)
forall a. Maybe a
Nothing
                       )
              OutboundDupState ConnectionId peerAddr
_connId Async m ()
_connThread handle
_handle TimeoutExpired
Expired ->
                Bool
-> STM
     m
     (Maybe (Async m ()),
      Maybe
        (TransitionTrace
           ConnStateId
           (ConnectionState peerAddr handle handleError version m)),
      OperationResult DemotedToColdRemoteTr,
      Maybe (Trace peerAddr handlerTrace))
-> STM
     m
     (Maybe (Async m ()),
      Maybe
        (TransitionTrace
           ConnStateId
           (ConnectionState peerAddr handle handleError version m)),
      OperationResult DemotedToColdRemoteTr,
      Maybe (Trace peerAddr handlerTrace))
forall a. (?callStack::CallStack) => Bool -> a -> a
assert Bool
False (STM
   m
   (Maybe (Async m ()),
    Maybe
      (TransitionTrace
         ConnStateId
         (ConnectionState peerAddr handle handleError version m)),
    OperationResult DemotedToColdRemoteTr,
    Maybe (Trace peerAddr handlerTrace))
 -> STM
      m
      (Maybe (Async m ()),
       Maybe
         (TransitionTrace
            ConnStateId
            (ConnectionState peerAddr handle handleError version m)),
       OperationResult DemotedToColdRemoteTr,
       Maybe (Trace peerAddr handlerTrace)))
-> STM
     m
     (Maybe (Async m ()),
      Maybe
        (TransitionTrace
           ConnStateId
           (ConnectionState peerAddr handle handleError version m)),
      OperationResult DemotedToColdRemoteTr,
      Maybe (Trace peerAddr handlerTrace))
-> STM
     m
     (Maybe (Async m ()),
      Maybe
        (TransitionTrace
           ConnStateId
           (ConnectionState peerAddr handle handleError version m)),
      OperationResult DemotedToColdRemoteTr,
      Maybe (Trace peerAddr handlerTrace))
forall a b. (a -> b) -> a -> b
$
                (Maybe (Async m ()),
 Maybe
   (TransitionTrace
      ConnStateId
      (ConnectionState peerAddr handle handleError version m)),
 OperationResult DemotedToColdRemoteTr,
 Maybe (Trace peerAddr handlerTrace))
-> STM
     m
     (Maybe (Async m ()),
      Maybe
        (TransitionTrace
           ConnStateId
           (ConnectionState peerAddr handle handleError version m)),
      OperationResult DemotedToColdRemoteTr,
      Maybe (Trace peerAddr handlerTrace))
forall a. a -> STM m a
forall (m :: * -> *) a. Monad m => a -> m a
return ( Maybe (Async m ())
forall a. Maybe a
Nothing
                       , Maybe
  (TransitionTrace
     ConnStateId
     (ConnectionState peerAddr handle handleError version m))
forall a. Maybe a
Nothing
                       , DemotedToColdRemoteTr -> OperationResult DemotedToColdRemoteTr
forall a. a -> OperationResult a
OperationSuccess DemotedToColdRemoteTr
KeepTr
                       , Trace peerAddr handlerTrace -> Maybe (Trace peerAddr handlerTrace)
forall a. a -> Maybe a
Just (AssertionLocation peerAddr -> Trace peerAddr handlerTrace
forall peerAddr handlerTrace.
AssertionLocation peerAddr -> Trace peerAddr handlerTrace
TrUnexpectedlyFalseAssertion
                                 (Maybe (ConnectionId peerAddr)
-> AbstractState -> AssertionLocation peerAddr
forall peerAddr.
Maybe (ConnectionId peerAddr)
-> AbstractState -> AssertionLocation peerAddr
ReleaseInboundConnection (ConnectionId peerAddr -> Maybe (ConnectionId peerAddr)
forall a. a -> Maybe a
Just ConnectionId peerAddr
connId)
                                                           AbstractState
st)
                                 )
                       )

              OutboundUniState ConnectionId peerAddr
_connId Async m ()
_connThread handle
_handle ->
                (Maybe (Async m ()),
 Maybe
   (TransitionTrace
      ConnStateId
      (ConnectionState peerAddr handle handleError version m)),
 OperationResult DemotedToColdRemoteTr,
 Maybe (Trace peerAddr handlerTrace))
-> STM
     m
     (Maybe (Async m ()),
      Maybe
        (TransitionTrace
           ConnStateId
           (ConnectionState peerAddr handle handleError version m)),
      OperationResult DemotedToColdRemoteTr,
      Maybe (Trace peerAddr handlerTrace))
forall a. a -> STM m a
forall (m :: * -> *) a. Monad m => a -> m a
return ( Maybe (Async m ())
forall a. Maybe a
Nothing
                       , Maybe
  (TransitionTrace
     ConnStateId
     (ConnectionState peerAddr handle handleError version m))
forall a. Maybe a
Nothing
                       , AbstractState -> OperationResult DemotedToColdRemoteTr
forall a. AbstractState -> OperationResult a
UnsupportedState AbstractState
st
                       , Maybe (Trace peerAddr handlerTrace)
forall a. Maybe a
Nothing
                       )

              -- unexpected state, this state is reachable only from outbound
              -- states
              OutboundIdleState ConnectionId peerAddr
_connId Async m ()
_connThread handle
_handle DataFlow
_dataFlow ->
                (Maybe (Async m ()),
 Maybe
   (TransitionTrace
      ConnStateId
      (ConnectionState peerAddr handle handleError version m)),
 OperationResult DemotedToColdRemoteTr,
 Maybe (Trace peerAddr handlerTrace))
-> STM
     m
     (Maybe (Async m ()),
      Maybe
        (TransitionTrace
           ConnStateId
           (ConnectionState peerAddr handle handleError version m)),
      OperationResult DemotedToColdRemoteTr,
      Maybe (Trace peerAddr handlerTrace))
forall a. a -> STM m a
forall (m :: * -> *) a. Monad m => a -> m a
return ( Maybe (Async m ())
forall a. Maybe a
Nothing
                       , Maybe
  (TransitionTrace
     ConnStateId
     (ConnectionState peerAddr handle handleError version m))
forall a. Maybe a
Nothing
                       , DemotedToColdRemoteTr -> OperationResult DemotedToColdRemoteTr
forall a. a -> OperationResult a
OperationSuccess DemotedToColdRemoteTr
CommitTr
                       , Trace peerAddr handlerTrace -> Maybe (Trace peerAddr handlerTrace)
forall a. a -> Maybe a
Just (AssertionLocation peerAddr -> Trace peerAddr handlerTrace
forall peerAddr handlerTrace.
AssertionLocation peerAddr -> Trace peerAddr handlerTrace
TrUnexpectedlyFalseAssertion
                                 (Maybe (ConnectionId peerAddr)
-> AbstractState -> AssertionLocation peerAddr
forall peerAddr.
Maybe (ConnectionId peerAddr)
-> AbstractState -> AssertionLocation peerAddr
ReleaseInboundConnection (ConnectionId peerAddr -> Maybe (ConnectionId peerAddr)
forall a. a -> Maybe a
Just ConnectionId peerAddr
connId)
                                                           AbstractState
st)
                                 )
                       )

              -- @
              --   Commit^{dataFlow} : InboundIdleState dataFlow
              --                     → TerminatingState
              -- @
              --
              -- Note: the 'TrDemotedToColdRemote' is logged by the server.
              InboundIdleState ConnectionId peerAddr
_connId Async m ()
connThread handle
_handle DataFlow
_dataFlow -> do
                let connState' :: ConnectionState peerAddr handle handleError version m
connState' = ConnectionId peerAddr
-> Async m ()
-> Maybe handleError
-> ConnectionState peerAddr handle handleError version m
forall peerAddr handle handleError version (m :: * -> *).
ConnectionId peerAddr
-> Async m ()
-> Maybe handleError
-> ConnectionState peerAddr handle handleError version m
TerminatingState ConnectionId peerAddr
connId Async m ()
connThread Maybe handleError
forall a. Maybe a
Nothing
                StrictTVar
  m (ConnectionState peerAddr handle handleError version m)
-> ConnectionState peerAddr handle handleError version m
-> STM m ()
forall (m :: * -> *) a.
MonadSTM m =>
StrictTVar m a -> a -> STM m ()
writeTVar StrictTVar
  m (ConnectionState peerAddr handle handleError version m)
connVar ConnectionState peerAddr handle handleError version m
connState'
                (Maybe (Async m ()),
 Maybe
   (TransitionTrace
      ConnStateId
      (ConnectionState peerAddr handle handleError version m)),
 OperationResult DemotedToColdRemoteTr,
 Maybe (Trace peerAddr handlerTrace))
-> STM
     m
     (Maybe (Async m ()),
      Maybe
        (TransitionTrace
           ConnStateId
           (ConnectionState peerAddr handle handleError version m)),
      OperationResult DemotedToColdRemoteTr,
      Maybe (Trace peerAddr handlerTrace))
forall a. a -> STM m a
forall (m :: * -> *) a. Monad m => a -> m a
return ( Async m () -> Maybe (Async m ())
forall a. a -> Maybe a
Just Async m ()
connThread
                       , TransitionTrace
  ConnStateId (ConnectionState peerAddr handle handleError version m)
-> Maybe
     (TransitionTrace
        ConnStateId
        (ConnectionState peerAddr handle handleError version m))
forall a. a -> Maybe a
Just (ConnStateId
-> Transition'
     (MaybeUnknown
        (ConnectionState peerAddr handle handleError version m))
-> TransitionTrace
     ConnStateId (ConnectionState peerAddr handle handleError version m)
forall id state.
id -> Transition' state -> TransitionTrace' id state
TransitionTrace ConnStateId
connStateId (ConnectionState peerAddr handle handleError version m
-> ConnectionState peerAddr handle handleError version m
-> Transition'
     (MaybeUnknown
        (ConnectionState peerAddr handle handleError version m))
forall state. state -> state -> Transition state
mkTransition ConnectionState peerAddr handle handleError version m
connState ConnectionState peerAddr handle handleError version m
connState'))
                       , DemotedToColdRemoteTr -> OperationResult DemotedToColdRemoteTr
forall a. a -> OperationResult a
OperationSuccess DemotedToColdRemoteTr
CommitTr
                       , Maybe (Trace peerAddr handlerTrace)
forall a. Maybe a
Nothing
                       )

              -- the inbound protocol governor was supposed to call
              -- 'demotedToColdRemote' first.
              InboundState ConnectionId peerAddr
_connId Async m ()
connThread handle
_handle DataFlow
_dataFlow -> do
                let connState' :: ConnectionState peerAddr handle handleError version m
connState' = ConnectionId peerAddr
-> Async m ()
-> Maybe handleError
-> ConnectionState peerAddr handle handleError version m
forall peerAddr handle handleError version (m :: * -> *).
ConnectionId peerAddr
-> Async m ()
-> Maybe handleError
-> ConnectionState peerAddr handle handleError version m
TerminatingState ConnectionId peerAddr
connId Async m ()
connThread Maybe handleError
forall a. Maybe a
Nothing
                StrictTVar
  m (ConnectionState peerAddr handle handleError version m)
-> ConnectionState peerAddr handle handleError version m
-> STM m ()
forall (m :: * -> *) a.
MonadSTM m =>
StrictTVar m a -> a -> STM m ()
writeTVar StrictTVar
  m (ConnectionState peerAddr handle handleError version m)
connVar ConnectionState peerAddr handle handleError version m
connState'
                (Maybe (Async m ()),
 Maybe
   (TransitionTrace
      ConnStateId
      (ConnectionState peerAddr handle handleError version m)),
 OperationResult DemotedToColdRemoteTr,
 Maybe (Trace peerAddr handlerTrace))
-> STM
     m
     (Maybe (Async m ()),
      Maybe
        (TransitionTrace
           ConnStateId
           (ConnectionState peerAddr handle handleError version m)),
      OperationResult DemotedToColdRemoteTr,
      Maybe (Trace peerAddr handlerTrace))
forall a. a -> STM m a
forall (m :: * -> *) a. Monad m => a -> m a
return ( Async m () -> Maybe (Async m ())
forall a. a -> Maybe a
Just Async m ()
connThread
                       , TransitionTrace
  ConnStateId (ConnectionState peerAddr handle handleError version m)
-> Maybe
     (TransitionTrace
        ConnStateId
        (ConnectionState peerAddr handle handleError version m))
forall a. a -> Maybe a
Just (ConnStateId
-> Transition'
     (MaybeUnknown
        (ConnectionState peerAddr handle handleError version m))
-> TransitionTrace
     ConnStateId (ConnectionState peerAddr handle handleError version m)
forall id state.
id -> Transition' state -> TransitionTrace' id state
TransitionTrace ConnStateId
connStateId (ConnectionState peerAddr handle handleError version m
-> ConnectionState peerAddr handle handleError version m
-> Transition'
     (MaybeUnknown
        (ConnectionState peerAddr handle handleError version m))
forall state. state -> state -> Transition state
mkTransition ConnectionState peerAddr handle handleError version m
connState ConnectionState peerAddr handle handleError version m
connState'))
                       , AbstractState -> OperationResult DemotedToColdRemoteTr
forall a. AbstractState -> OperationResult a
UnsupportedState AbstractState
st
                       , Trace peerAddr handlerTrace -> Maybe (Trace peerAddr handlerTrace)
forall a. a -> Maybe a
Just (AssertionLocation peerAddr -> Trace peerAddr handlerTrace
forall peerAddr handlerTrace.
AssertionLocation peerAddr -> Trace peerAddr handlerTrace
TrUnexpectedlyFalseAssertion
                                 (Maybe (ConnectionId peerAddr)
-> AbstractState -> AssertionLocation peerAddr
forall peerAddr.
Maybe (ConnectionId peerAddr)
-> AbstractState -> AssertionLocation peerAddr
ReleaseInboundConnection (ConnectionId peerAddr -> Maybe (ConnectionId peerAddr)
forall a. a -> Maybe a
Just ConnectionId peerAddr
connId)
                                                           AbstractState
st)
                                 )
                       )

              -- the inbound connection governor ought to call
              -- 'demotedToColdRemote' first.
              DuplexState ConnectionId peerAddr
_connId Async m ()
connThread handle
handle -> do
                let connState' :: ConnectionState peerAddr handle handleError version m
connState' = ConnectionId peerAddr
-> Async m ()
-> handle
-> TimeoutExpired
-> ConnectionState peerAddr handle handleError version m
forall peerAddr handle handleError version (m :: * -> *).
ConnectionId peerAddr
-> Async m ()
-> handle
-> TimeoutExpired
-> ConnectionState peerAddr handle handleError version m
OutboundDupState ConnectionId peerAddr
connId Async m ()
connThread handle
handle TimeoutExpired
Ticking
                StrictTVar
  m (ConnectionState peerAddr handle handleError version m)
-> ConnectionState peerAddr handle handleError version m
-> STM m ()
forall (m :: * -> *) a.
MonadSTM m =>
StrictTVar m a -> a -> STM m ()
writeTVar StrictTVar
  m (ConnectionState peerAddr handle handleError version m)
connVar ConnectionState peerAddr handle handleError version m
connState'
                (Maybe (Async m ()),
 Maybe
   (TransitionTrace
      ConnStateId
      (ConnectionState peerAddr handle handleError version m)),
 OperationResult DemotedToColdRemoteTr,
 Maybe (Trace peerAddr handlerTrace))
-> STM
     m
     (Maybe (Async m ()),
      Maybe
        (TransitionTrace
           ConnStateId
           (ConnectionState peerAddr handle handleError version m)),
      OperationResult DemotedToColdRemoteTr,
      Maybe (Trace peerAddr handlerTrace))
forall a. a -> STM m a
forall (m :: * -> *) a. Monad m => a -> m a
return ( Maybe (Async m ())
forall a. Maybe a
Nothing
                       , TransitionTrace
  ConnStateId (ConnectionState peerAddr handle handleError version m)
-> Maybe
     (TransitionTrace
        ConnStateId
        (ConnectionState peerAddr handle handleError version m))
forall a. a -> Maybe a
Just (ConnStateId
-> Transition'
     (MaybeUnknown
        (ConnectionState peerAddr handle handleError version m))
-> TransitionTrace
     ConnStateId (ConnectionState peerAddr handle handleError version m)
forall id state.
id -> Transition' state -> TransitionTrace' id state
TransitionTrace ConnStateId
connStateId (ConnectionState peerAddr handle handleError version m
-> ConnectionState peerAddr handle handleError version m
-> Transition'
     (MaybeUnknown
        (ConnectionState peerAddr handle handleError version m))
forall state. state -> state -> Transition state
mkTransition ConnectionState peerAddr handle handleError version m
connState ConnectionState peerAddr handle handleError version m
connState'))
                       , AbstractState -> OperationResult DemotedToColdRemoteTr
forall a. AbstractState -> OperationResult a
UnsupportedState AbstractState
st
                       , Trace peerAddr handlerTrace -> Maybe (Trace peerAddr handlerTrace)
forall a. a -> Maybe a
Just (AssertionLocation peerAddr -> Trace peerAddr handlerTrace
forall peerAddr handlerTrace.
AssertionLocation peerAddr -> Trace peerAddr handlerTrace
TrUnexpectedlyFalseAssertion
                                 (Maybe (ConnectionId peerAddr)
-> AbstractState -> AssertionLocation peerAddr
forall peerAddr.
Maybe (ConnectionId peerAddr)
-> AbstractState -> AssertionLocation peerAddr
ReleaseInboundConnection (ConnectionId peerAddr -> Maybe (ConnectionId peerAddr)
forall a. a -> Maybe a
Just ConnectionId peerAddr
connId)
                                                           AbstractState
st)
                                 )
                       )

              -- If 'releaseOutboundConnection' is called just before
              -- 'releaseInboundConnection', the latter one might observe
              -- 'TerminatingState'.
              TerminatingState ConnectionId peerAddr
_connId Async m ()
_connThread Maybe handleError
_handleError ->
                (Maybe (Async m ()),
 Maybe
   (TransitionTrace
      ConnStateId
      (ConnectionState peerAddr handle handleError version m)),
 OperationResult DemotedToColdRemoteTr,
 Maybe (Trace peerAddr handlerTrace))
-> STM
     m
     (Maybe (Async m ()),
      Maybe
        (TransitionTrace
           ConnStateId
           (ConnectionState peerAddr handle handleError version m)),
      OperationResult DemotedToColdRemoteTr,
      Maybe (Trace peerAddr handlerTrace))
forall a. a -> STM m a
forall (m :: * -> *) a. Monad m => a -> m a
return ( Maybe (Async m ())
forall a. Maybe a
Nothing
                       , Maybe
  (TransitionTrace
     ConnStateId
     (ConnectionState peerAddr handle handleError version m))
forall a. Maybe a
Nothing
                       , DemotedToColdRemoteTr -> OperationResult DemotedToColdRemoteTr
forall a. a -> OperationResult a
OperationSuccess DemotedToColdRemoteTr
CommitTr
                       , Maybe (Trace peerAddr handlerTrace)
forall a. Maybe a
Nothing
                       )
              -- However, 'TerminatedState' should not be observable by
              -- 'releaseInboundConnection', unless 'timeWaitTimeout' is
              -- close to 'serverProtocolIdleTimeout'.
              TerminatedState Maybe handleError
_handleError ->
                (Maybe (Async m ()),
 Maybe
   (TransitionTrace
      ConnStateId
      (ConnectionState peerAddr handle handleError version m)),
 OperationResult DemotedToColdRemoteTr,
 Maybe (Trace peerAddr handlerTrace))
-> STM
     m
     (Maybe (Async m ()),
      Maybe
        (TransitionTrace
           ConnStateId
           (ConnectionState peerAddr handle handleError version m)),
      OperationResult DemotedToColdRemoteTr,
      Maybe (Trace peerAddr handlerTrace))
forall a. a -> STM m a
forall (m :: * -> *) a. Monad m => a -> m a
return ( Maybe (Async m ())
forall a. Maybe a
Nothing
                       , Maybe
  (TransitionTrace
     ConnStateId
     (ConnectionState peerAddr handle handleError version m))
forall a. Maybe a
Nothing
                       , AbstractState -> OperationResult DemotedToColdRemoteTr
forall a. AbstractState -> OperationResult a
UnsupportedState AbstractState
TerminatedSt
                       , Maybe (Trace peerAddr handlerTrace)
forall a. Maybe a
Nothing
                       )

      traverse_ (traceWith trTracer) mbTransitionTrace
      traceCounters stateVar

      -- 'throwTo' avoids blocking until 'timeWaitTimeout' expires.
      traverse_ (flip throwTo AsyncCancelled . asyncThreadId)
                mbThread

      whenJust mbAssertion $ \Trace peerAddr handlerTrace
tr -> do
        Tracer m (Trace peerAddr handlerTrace)
-> Trace peerAddr handlerTrace -> m ()
forall (m :: * -> *) a. Tracer m a -> a -> m ()
traceWith Tracer m (Trace peerAddr handlerTrace)
tracer Trace peerAddr handlerTrace
tr
        _ <- (Any -> Any) -> m (Any -> Any)
forall a. a -> m a
forall (m :: * -> *) a. MonadEvaluate m => a -> m a
evaluate (Bool -> Any -> Any
forall a. (?callStack::CallStack) => Bool -> a -> a
assert Bool
False)
        pure ()

      return result

    acquireOutboundConnectionImpl
        :: HasCallStack
        => StrictTMVar m (ConnectionManagerState peerAddr handle handleError version m)
        -> StrictTVar m StdGen
        -> ConnectionHandlerFn handlerTrace socket peerAddr handle handleError version versionData m
        -> DiffusionMode
        -> peerAddr
        -> m (Connected peerAddr handle handleError)
    acquireOutboundConnectionImpl :: (?callStack::CallStack) =>
StrictTMVar
  m (ConnectionManagerState peerAddr handle handleError version m)
-> StrictTVar m StdGen
-> ConnectionHandlerFn
     handlerTrace
     socket
     peerAddr
     handle
     handleError
     version
     versionData
     m
-> AcquireOutboundConnection peerAddr handle handleError m
acquireOutboundConnectionImpl StrictTMVar
  m (ConnectionManagerState peerAddr handle handleError version m)
stateVar StrictTVar m StdGen
stdGenVar ConnectionHandlerFn
  handlerTrace
  socket
  peerAddr
  handle
  handleError
  version
  versionData
  m
handler DiffusionMode
diffusionMode peerAddr
peerAddr = do
        let provenance :: Provenance
provenance = Provenance
Outbound
        Tracer m (Trace peerAddr handlerTrace)
-> Trace peerAddr handlerTrace -> m ()
forall (m :: * -> *) a. Tracer m a -> a -> m ()
traceWith Tracer m (Trace peerAddr handlerTrace)
tracer (Provenance -> peerAddr -> Trace peerAddr handlerTrace
forall peerAddr handlerTrace.
Provenance -> peerAddr -> Trace peerAddr handlerTrace
TrIncludeConnection Provenance
provenance peerAddr
peerAddr)
        (trace, mutableConnState@MutableConnState { connVar, connStateId }
              , eHandleWedge) <- STM
  m
  (Maybe
     (Either
        (TransitionTrace
           ConnStateId
           (ConnectionState peerAddr handle handleError version m))
        (Trace peerAddr handlerTrace)),
   MutableConnState peerAddr handle handleError version m,
   Either
     (ConnectionManagerError peerAddr)
     (Wedge
        (Connected peerAddr handle handleError) (ConnectionId peerAddr)))
-> m (Maybe
        (Either
           (TransitionTrace
              ConnStateId
              (ConnectionState peerAddr handle handleError version m))
           (Trace peerAddr handlerTrace)),
      MutableConnState peerAddr handle handleError version m,
      Either
        (ConnectionManagerError peerAddr)
        (Wedge
           (Connected peerAddr handle handleError) (ConnectionId peerAddr)))
forall a. (?callStack::CallStack) => STM m a -> m a
forall (m :: * -> *) a.
(MonadSTM m, ?callStack::CallStack) =>
STM m a -> m a
atomically (STM
   m
   (Maybe
      (Either
         (TransitionTrace
            ConnStateId
            (ConnectionState peerAddr handle handleError version m))
         (Trace peerAddr handlerTrace)),
    MutableConnState peerAddr handle handleError version m,
    Either
      (ConnectionManagerError peerAddr)
      (Wedge
         (Connected peerAddr handle handleError) (ConnectionId peerAddr)))
 -> m (Maybe
         (Either
            (TransitionTrace
               ConnStateId
               (ConnectionState peerAddr handle handleError version m))
            (Trace peerAddr handlerTrace)),
       MutableConnState peerAddr handle handleError version m,
       Either
         (ConnectionManagerError peerAddr)
         (Wedge
            (Connected peerAddr handle handleError) (ConnectionId peerAddr))))
-> STM
     m
     (Maybe
        (Either
           (TransitionTrace
              ConnStateId
              (ConnectionState peerAddr handle handleError version m))
           (Trace peerAddr handlerTrace)),
      MutableConnState peerAddr handle handleError version m,
      Either
        (ConnectionManagerError peerAddr)
        (Wedge
           (Connected peerAddr handle handleError) (ConnectionId peerAddr)))
-> m (Maybe
        (Either
           (TransitionTrace
              ConnStateId
              (ConnectionState peerAddr handle handleError version m))
           (Trace peerAddr handlerTrace)),
      MutableConnState peerAddr handle handleError version m,
      Either
        (ConnectionManagerError peerAddr)
        (Wedge
           (Connected peerAddr handle handleError) (ConnectionId peerAddr)))
forall a b. (a -> b) -> a -> b
$ do
          state <- StrictTMVar
  m (ConnectionManagerState peerAddr handle handleError version m)
-> STM
     m (ConnectionManagerState peerAddr handle handleError version m)
forall (m :: * -> *) a. MonadSTM m => StrictTMVar m a -> STM m a
readTMVar StrictTMVar
  m (ConnectionManagerState peerAddr handle handleError version m)
stateVar
          stdGen <- stateTVar stdGenVar split
          case State.lookupByRemoteAddr stdGen peerAddr state of
            Just mutableConnState :: MutableConnState peerAddr handle handleError version m
mutableConnState@MutableConnState { StrictTVar
  m (ConnectionState peerAddr handle handleError version m)
connVar :: 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)
connVar, ConnStateId
connStateId :: forall peerAddr handle handleError version (m :: * -> *).
MutableConnState peerAddr handle handleError version m
-> ConnStateId
connStateId :: ConnStateId
connStateId } -> do
              connState <- 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)
connVar
              let st = MaybeUnknown
  (ConnectionState peerAddr handle handleError version m)
-> AbstractState
forall muxMode peerAddr m a (b :: * -> *).
MaybeUnknown (ConnectionState muxMode peerAddr m a b)
-> AbstractState
State.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
connState)
              case connState of
                ConnectionState peerAddr handle handleError version m
ReservedOutboundState ->
                  (Maybe
   (Either
      (TransitionTrace
         ConnStateId
         (ConnectionState peerAddr handle handleError version m))
      (Trace peerAddr handlerTrace)),
 MutableConnState peerAddr handle handleError version m,
 Either
   (ConnectionManagerError peerAddr)
   (Wedge
      (Connected peerAddr handle handleError) (ConnectionId peerAddr)))
-> STM
     m
     (Maybe
        (Either
           (TransitionTrace
              ConnStateId
              (ConnectionState peerAddr handle handleError version m))
           (Trace peerAddr handlerTrace)),
      MutableConnState peerAddr handle handleError version m,
      Either
        (ConnectionManagerError peerAddr)
        (Wedge
           (Connected peerAddr handle handleError) (ConnectionId peerAddr)))
forall a. a -> STM m a
forall (m :: * -> *) a. Monad m => a -> m a
return ( Either
  (TransitionTrace
     ConnStateId
     (ConnectionState peerAddr handle handleError version m))
  (Trace peerAddr handlerTrace)
-> Maybe
     (Either
        (TransitionTrace
           ConnStateId
           (ConnectionState peerAddr handle handleError version m))
        (Trace peerAddr handlerTrace))
forall a. a -> Maybe a
Just (Trace peerAddr handlerTrace
-> Either
     (TransitionTrace
        ConnStateId
        (ConnectionState peerAddr handle handleError version m))
     (Trace peerAddr handlerTrace)
forall a b. b -> Either a b
Right (Provenance
-> peerAddr -> AbstractState -> Trace peerAddr handlerTrace
forall peerAddr handlerTrace.
Provenance
-> peerAddr -> AbstractState -> Trace peerAddr handlerTrace
TrConnectionExists Provenance
provenance peerAddr
peerAddr AbstractState
st))
                         , MutableConnState peerAddr handle handleError version m
mutableConnState
                         , ConnectionManagerError peerAddr
-> Either
     (ConnectionManagerError peerAddr)
     (Wedge
        (Connected peerAddr handle handleError) (ConnectionId peerAddr))
forall a b. a -> Either a b
Left ((CallStack -> ConnectionManagerError peerAddr)
-> ConnectionManagerError peerAddr
forall a. (?callStack::CallStack) => (CallStack -> a) -> a
withCallStack
                                  (Provenance
-> peerAddr -> CallStack -> ConnectionManagerError peerAddr
forall peerAddr.
Provenance
-> peerAddr -> CallStack -> ConnectionManagerError peerAddr
ConnectionExists Provenance
provenance peerAddr
peerAddr))
                         )

                UnnegotiatedState Provenance
Outbound ConnectionId peerAddr
_connId Async m ()
_connThread -> do
                  (Maybe
   (Either
      (TransitionTrace
         ConnStateId
         (ConnectionState peerAddr handle handleError version m))
      (Trace peerAddr handlerTrace)),
 MutableConnState peerAddr handle handleError version m,
 Either
   (ConnectionManagerError peerAddr)
   (Wedge
      (Connected peerAddr handle handleError) (ConnectionId peerAddr)))
-> STM
     m
     (Maybe
        (Either
           (TransitionTrace
              ConnStateId
              (ConnectionState peerAddr handle handleError version m))
           (Trace peerAddr handlerTrace)),
      MutableConnState peerAddr handle handleError version m,
      Either
        (ConnectionManagerError peerAddr)
        (Wedge
           (Connected peerAddr handle handleError) (ConnectionId peerAddr)))
forall a. a -> STM m a
forall (m :: * -> *) a. Monad m => a -> m a
return ( Either
  (TransitionTrace
     ConnStateId
     (ConnectionState peerAddr handle handleError version m))
  (Trace peerAddr handlerTrace)
-> Maybe
     (Either
        (TransitionTrace
           ConnStateId
           (ConnectionState peerAddr handle handleError version m))
        (Trace peerAddr handlerTrace))
forall a. a -> Maybe a
Just (Trace peerAddr handlerTrace
-> Either
     (TransitionTrace
        ConnStateId
        (ConnectionState peerAddr handle handleError version m))
     (Trace peerAddr handlerTrace)
forall a b. b -> Either a b
Right (Provenance
-> peerAddr -> AbstractState -> Trace peerAddr handlerTrace
forall peerAddr handlerTrace.
Provenance
-> peerAddr -> AbstractState -> Trace peerAddr handlerTrace
TrConnectionExists Provenance
provenance peerAddr
peerAddr AbstractState
st))
                         , MutableConnState peerAddr handle handleError version m
mutableConnState
                         , ConnectionManagerError peerAddr
-> Either
     (ConnectionManagerError peerAddr)
     (Wedge
        (Connected peerAddr handle handleError) (ConnectionId peerAddr))
forall a b. a -> Either a b
Left ((CallStack -> ConnectionManagerError peerAddr)
-> ConnectionManagerError peerAddr
forall a. (?callStack::CallStack) => (CallStack -> a) -> a
withCallStack
                                  (Provenance
-> peerAddr -> CallStack -> ConnectionManagerError peerAddr
forall peerAddr.
Provenance
-> peerAddr -> CallStack -> ConnectionManagerError peerAddr
ConnectionExists Provenance
provenance peerAddr
peerAddr))
                         )

                UnnegotiatedState Provenance
Inbound ConnectionId peerAddr
connId Async m ()
_connThread ->
                  -- we must not block inside @modifyTVar stateVar@, we
                  -- return 'There' to indicate that we need to block on
                  -- the connection state.
                  (Maybe
   (Either
      (TransitionTrace
         ConnStateId
         (ConnectionState peerAddr handle handleError version m))
      (Trace peerAddr handlerTrace)),
 MutableConnState peerAddr handle handleError version m,
 Either
   (ConnectionManagerError peerAddr)
   (Wedge
      (Connected peerAddr handle handleError) (ConnectionId peerAddr)))
-> STM
     m
     (Maybe
        (Either
           (TransitionTrace
              ConnStateId
              (ConnectionState peerAddr handle handleError version m))
           (Trace peerAddr handlerTrace)),
      MutableConnState peerAddr handle handleError version m,
      Either
        (ConnectionManagerError peerAddr)
        (Wedge
           (Connected peerAddr handle handleError) (ConnectionId peerAddr)))
forall a. a -> STM m a
forall (m :: * -> *) a. Monad m => a -> m a
return ( Maybe
  (Either
     (TransitionTrace
        ConnStateId
        (ConnectionState peerAddr handle handleError version m))
     (Trace peerAddr handlerTrace))
forall a. Maybe a
Nothing
                         , MutableConnState peerAddr handle handleError version m
mutableConnState
                         , Wedge
  (Connected peerAddr handle handleError) (ConnectionId peerAddr)
-> Either
     (ConnectionManagerError peerAddr)
     (Wedge
        (Connected peerAddr handle handleError) (ConnectionId peerAddr))
forall a b. b -> Either a b
Right (ConnectionId peerAddr
-> Wedge
     (Connected peerAddr handle handleError) (ConnectionId peerAddr)
forall a b. b -> Wedge a b
There ConnectionId peerAddr
connId)
                         )

                OutboundUniState {} -> do
                  (Maybe
   (Either
      (TransitionTrace
         ConnStateId
         (ConnectionState peerAddr handle handleError version m))
      (Trace peerAddr handlerTrace)),
 MutableConnState peerAddr handle handleError version m,
 Either
   (ConnectionManagerError peerAddr)
   (Wedge
      (Connected peerAddr handle handleError) (ConnectionId peerAddr)))
-> STM
     m
     (Maybe
        (Either
           (TransitionTrace
              ConnStateId
              (ConnectionState peerAddr handle handleError version m))
           (Trace peerAddr handlerTrace)),
      MutableConnState peerAddr handle handleError version m,
      Either
        (ConnectionManagerError peerAddr)
        (Wedge
           (Connected peerAddr handle handleError) (ConnectionId peerAddr)))
forall a. a -> STM m a
forall (m :: * -> *) a. Monad m => a -> m a
return ( Either
  (TransitionTrace
     ConnStateId
     (ConnectionState peerAddr handle handleError version m))
  (Trace peerAddr handlerTrace)
-> Maybe
     (Either
        (TransitionTrace
           ConnStateId
           (ConnectionState peerAddr handle handleError version m))
        (Trace peerAddr handlerTrace))
forall a. a -> Maybe a
Just (Trace peerAddr handlerTrace
-> Either
     (TransitionTrace
        ConnStateId
        (ConnectionState peerAddr handle handleError version m))
     (Trace peerAddr handlerTrace)
forall a b. b -> Either a b
Right (Provenance
-> peerAddr -> AbstractState -> Trace peerAddr handlerTrace
forall peerAddr handlerTrace.
Provenance
-> peerAddr -> AbstractState -> Trace peerAddr handlerTrace
TrConnectionExists Provenance
provenance peerAddr
peerAddr AbstractState
st))
                         , MutableConnState peerAddr handle handleError version m
mutableConnState
                         , ConnectionManagerError peerAddr
-> Either
     (ConnectionManagerError peerAddr)
     (Wedge
        (Connected peerAddr handle handleError) (ConnectionId peerAddr))
forall a b. a -> Either a b
Left ((CallStack -> ConnectionManagerError peerAddr)
-> ConnectionManagerError peerAddr
forall a. (?callStack::CallStack) => (CallStack -> a) -> a
withCallStack
                                  (Provenance
-> peerAddr -> CallStack -> ConnectionManagerError peerAddr
forall peerAddr.
Provenance
-> peerAddr -> CallStack -> ConnectionManagerError peerAddr
ConnectionExists Provenance
provenance peerAddr
peerAddr))
                         )

                OutboundDupState {} -> do
                  (Maybe
   (Either
      (TransitionTrace
         ConnStateId
         (ConnectionState peerAddr handle handleError version m))
      (Trace peerAddr handlerTrace)),
 MutableConnState peerAddr handle handleError version m,
 Either
   (ConnectionManagerError peerAddr)
   (Wedge
      (Connected peerAddr handle handleError) (ConnectionId peerAddr)))
-> STM
     m
     (Maybe
        (Either
           (TransitionTrace
              ConnStateId
              (ConnectionState peerAddr handle handleError version m))
           (Trace peerAddr handlerTrace)),
      MutableConnState peerAddr handle handleError version m,
      Either
        (ConnectionManagerError peerAddr)
        (Wedge
           (Connected peerAddr handle handleError) (ConnectionId peerAddr)))
forall a. a -> STM m a
forall (m :: * -> *) a. Monad m => a -> m a
return ( Either
  (TransitionTrace
     ConnStateId
     (ConnectionState peerAddr handle handleError version m))
  (Trace peerAddr handlerTrace)
-> Maybe
     (Either
        (TransitionTrace
           ConnStateId
           (ConnectionState peerAddr handle handleError version m))
        (Trace peerAddr handlerTrace))
forall a. a -> Maybe a
Just (Trace peerAddr handlerTrace
-> Either
     (TransitionTrace
        ConnStateId
        (ConnectionState peerAddr handle handleError version m))
     (Trace peerAddr handlerTrace)
forall a b. b -> Either a b
Right (Provenance
-> peerAddr -> AbstractState -> Trace peerAddr handlerTrace
forall peerAddr handlerTrace.
Provenance
-> peerAddr -> AbstractState -> Trace peerAddr handlerTrace
TrConnectionExists Provenance
provenance peerAddr
peerAddr AbstractState
st))
                         , MutableConnState peerAddr handle handleError version m
mutableConnState
                         , ConnectionManagerError peerAddr
-> Either
     (ConnectionManagerError peerAddr)
     (Wedge
        (Connected peerAddr handle handleError) (ConnectionId peerAddr))
forall a b. a -> Either a b
Left ((CallStack -> ConnectionManagerError peerAddr)
-> ConnectionManagerError peerAddr
forall a. (?callStack::CallStack) => (CallStack -> a) -> a
withCallStack
                                  (Provenance
-> peerAddr -> CallStack -> ConnectionManagerError peerAddr
forall peerAddr.
Provenance
-> peerAddr -> CallStack -> ConnectionManagerError peerAddr
ConnectionExists Provenance
provenance peerAddr
peerAddr))
                         )

                OutboundIdleState ConnectionId peerAddr
_connId Async m ()
_connThread handle
_handle DataFlow
_dataFlow ->
                  let tr :: AbstractState
tr = MaybeUnknown
  (ConnectionState peerAddr handle handleError version m)
-> AbstractState
forall muxMode peerAddr m a (b :: * -> *).
MaybeUnknown (ConnectionState muxMode peerAddr m a b)
-> AbstractState
State.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
connState) in
                  (Maybe
   (Either
      (TransitionTrace
         ConnStateId
         (ConnectionState peerAddr handle handleError version m))
      (Trace peerAddr handlerTrace)),
 MutableConnState peerAddr handle handleError version m,
 Either
   (ConnectionManagerError peerAddr)
   (Wedge
      (Connected peerAddr handle handleError) (ConnectionId peerAddr)))
-> STM
     m
     (Maybe
        (Either
           (TransitionTrace
              ConnStateId
              (ConnectionState peerAddr handle handleError version m))
           (Trace peerAddr handlerTrace)),
      MutableConnState peerAddr handle handleError version m,
      Either
        (ConnectionManagerError peerAddr)
        (Wedge
           (Connected peerAddr handle handleError) (ConnectionId peerAddr)))
forall a. a -> STM m a
forall (m :: * -> *) a. Monad m => a -> m a
return ( Either
  (TransitionTrace
     ConnStateId
     (ConnectionState peerAddr handle handleError version m))
  (Trace peerAddr handlerTrace)
-> Maybe
     (Either
        (TransitionTrace
           ConnStateId
           (ConnectionState peerAddr handle handleError version m))
        (Trace peerAddr handlerTrace))
forall a. a -> Maybe a
Just (Trace peerAddr handlerTrace
-> Either
     (TransitionTrace
        ConnStateId
        (ConnectionState peerAddr handle handleError version m))
     (Trace peerAddr handlerTrace)
forall a b. b -> Either a b
Right (peerAddr -> AbstractState -> Trace peerAddr handlerTrace
forall peerAddr handlerTrace.
peerAddr -> AbstractState -> Trace peerAddr handlerTrace
TrForbiddenOperation peerAddr
peerAddr AbstractState
tr))
                         , MutableConnState peerAddr handle handleError version m
mutableConnState
                         , ConnectionManagerError peerAddr
-> Either
     (ConnectionManagerError peerAddr)
     (Wedge
        (Connected peerAddr handle handleError) (ConnectionId peerAddr))
forall a b. a -> Either a b
Left ((CallStack -> ConnectionManagerError peerAddr)
-> ConnectionManagerError peerAddr
forall a. (?callStack::CallStack) => (CallStack -> a) -> a
withCallStack (peerAddr
-> AbstractState -> CallStack -> ConnectionManagerError peerAddr
forall peerAddr.
peerAddr
-> AbstractState -> CallStack -> ConnectionManagerError peerAddr
ForbiddenOperation peerAddr
peerAddr AbstractState
tr))
                         )

                InboundIdleState ConnectionId peerAddr
connId Async m ()
_connThread handle
_handle DataFlow
Unidirectional -> do
                  (Maybe
   (Either
      (TransitionTrace
         ConnStateId
         (ConnectionState peerAddr handle handleError version m))
      (Trace peerAddr handlerTrace)),
 MutableConnState peerAddr handle handleError version m,
 Either
   (ConnectionManagerError peerAddr)
   (Wedge
      (Connected peerAddr handle handleError) (ConnectionId peerAddr)))
-> STM
     m
     (Maybe
        (Either
           (TransitionTrace
              ConnStateId
              (ConnectionState peerAddr handle handleError version m))
           (Trace peerAddr handlerTrace)),
      MutableConnState peerAddr handle handleError version m,
      Either
        (ConnectionManagerError peerAddr)
        (Wedge
           (Connected peerAddr handle handleError) (ConnectionId peerAddr)))
forall a. a -> STM m a
forall (m :: * -> *) a. Monad m => a -> m a
return ( Either
  (TransitionTrace
     ConnStateId
     (ConnectionState peerAddr handle handleError version m))
  (Trace peerAddr handlerTrace)
-> Maybe
     (Either
        (TransitionTrace
           ConnStateId
           (ConnectionState peerAddr handle handleError version m))
        (Trace peerAddr handlerTrace))
forall a. a -> Maybe a
Just (Trace peerAddr handlerTrace
-> Either
     (TransitionTrace
        ConnStateId
        (ConnectionState peerAddr handle handleError version m))
     (Trace peerAddr handlerTrace)
forall a b. b -> Either a b
Right (ConnectionId peerAddr -> Trace peerAddr handlerTrace
forall peerAddr handlerTrace.
ConnectionId peerAddr -> Trace peerAddr handlerTrace
TrForbiddenConnection ConnectionId peerAddr
connId))
                         , MutableConnState peerAddr handle handleError version m
mutableConnState
                         , ConnectionManagerError peerAddr
-> Either
     (ConnectionManagerError peerAddr)
     (Wedge
        (Connected peerAddr handle handleError) (ConnectionId peerAddr))
forall a b. a -> Either a b
Left ((CallStack -> ConnectionManagerError peerAddr)
-> ConnectionManagerError peerAddr
forall a. (?callStack::CallStack) => (CallStack -> a) -> a
withCallStack
                                  (ConnectionId peerAddr
-> CallStack -> ConnectionManagerError peerAddr
forall peerAddr.
ConnectionId peerAddr
-> CallStack -> ConnectionManagerError peerAddr
ForbiddenConnection ConnectionId peerAddr
connId))
                         )

                InboundIdleState ConnectionId peerAddr
connId Async m ()
connThread handle
handle dataFlow :: DataFlow
dataFlow@DataFlow
Duplex -> do
                  -- @
                  --   Awake^{Duplex}_{Local} : InboundIdleState Duplex
                  --                          → OutboundState^\tau Duplex
                  -- @
                  let connState' :: ConnectionState peerAddr handle handleError version m
connState' = ConnectionId peerAddr
-> Async m ()
-> handle
-> TimeoutExpired
-> ConnectionState peerAddr handle handleError version m
forall peerAddr handle handleError version (m :: * -> *).
ConnectionId peerAddr
-> Async m ()
-> handle
-> TimeoutExpired
-> ConnectionState peerAddr handle handleError version m
OutboundDupState ConnectionId peerAddr
connId Async m ()
connThread handle
handle TimeoutExpired
Ticking
                  StrictTVar
  m (ConnectionState peerAddr handle handleError version m)
-> ConnectionState peerAddr handle handleError version m
-> STM m ()
forall (m :: * -> *) a.
MonadSTM m =>
StrictTVar m a -> a -> STM m ()
writeTVar StrictTVar
  m (ConnectionState peerAddr handle handleError version m)
connVar ConnectionState peerAddr handle handleError version m
connState'
                  (Maybe
   (Either
      (TransitionTrace
         ConnStateId
         (ConnectionState peerAddr handle handleError version m))
      (Trace peerAddr handlerTrace)),
 MutableConnState peerAddr handle handleError version m,
 Either
   (ConnectionManagerError peerAddr)
   (Wedge
      (Connected peerAddr handle handleError) (ConnectionId peerAddr)))
-> STM
     m
     (Maybe
        (Either
           (TransitionTrace
              ConnStateId
              (ConnectionState peerAddr handle handleError version m))
           (Trace peerAddr handlerTrace)),
      MutableConnState peerAddr handle handleError version m,
      Either
        (ConnectionManagerError peerAddr)
        (Wedge
           (Connected peerAddr handle handleError) (ConnectionId peerAddr)))
forall a. a -> STM m a
forall (m :: * -> *) a. Monad m => a -> m a
return ( Either
  (TransitionTrace
     ConnStateId
     (ConnectionState peerAddr handle handleError version m))
  (Trace peerAddr handlerTrace)
-> Maybe
     (Either
        (TransitionTrace
           ConnStateId
           (ConnectionState peerAddr handle handleError version m))
        (Trace peerAddr handlerTrace))
forall a. a -> Maybe a
Just (TransitionTrace
  ConnStateId (ConnectionState peerAddr handle handleError version m)
-> Either
     (TransitionTrace
        ConnStateId
        (ConnectionState peerAddr handle handleError version m))
     (Trace peerAddr handlerTrace)
forall a b. a -> Either a b
Left (ConnStateId
-> Transition'
     (MaybeUnknown
        (ConnectionState peerAddr handle handleError version m))
-> TransitionTrace
     ConnStateId (ConnectionState peerAddr handle handleError version m)
forall id state.
id -> Transition' state -> TransitionTrace' id state
TransitionTrace
                                         ConnStateId
connStateId
                                         (ConnectionState peerAddr handle handleError version m
-> ConnectionState peerAddr handle handleError version m
-> Transition'
     (MaybeUnknown
        (ConnectionState peerAddr handle handleError version m))
forall state. state -> state -> Transition state
mkTransition ConnectionState peerAddr handle handleError version m
connState ConnectionState peerAddr handle handleError version m
connState')))
                         , MutableConnState peerAddr handle handleError version m
mutableConnState
                         , Wedge
  (Connected peerAddr handle handleError) (ConnectionId peerAddr)
-> Either
     (ConnectionManagerError peerAddr)
     (Wedge
        (Connected peerAddr handle handleError) (ConnectionId peerAddr))
forall a b. b -> Either a b
Right (Connected peerAddr handle handleError
-> Wedge
     (Connected peerAddr handle handleError) (ConnectionId peerAddr)
forall a b. a -> Wedge a b
Here (ConnectionId peerAddr
-> DataFlow -> handle -> Connected peerAddr handle handleError
forall peerAddr handle handleError.
ConnectionId peerAddr
-> DataFlow -> handle -> Connected peerAddr handle handleError
Connected ConnectionId peerAddr
connId DataFlow
dataFlow handle
handle))
                         )

                InboundState ConnectionId peerAddr
connId Async m ()
_connThread handle
_handle DataFlow
Unidirectional -> do
                  -- the remote side negotiated unidirectional connection, we
                  -- cannot re-use it.
                  (Maybe
   (Either
      (TransitionTrace
         ConnStateId
         (ConnectionState peerAddr handle handleError version m))
      (Trace peerAddr handlerTrace)),
 MutableConnState peerAddr handle handleError version m,
 Either
   (ConnectionManagerError peerAddr)
   (Wedge
      (Connected peerAddr handle handleError) (ConnectionId peerAddr)))
-> STM
     m
     (Maybe
        (Either
           (TransitionTrace
              ConnStateId
              (ConnectionState peerAddr handle handleError version m))
           (Trace peerAddr handlerTrace)),
      MutableConnState peerAddr handle handleError version m,
      Either
        (ConnectionManagerError peerAddr)
        (Wedge
           (Connected peerAddr handle handleError) (ConnectionId peerAddr)))
forall a. a -> STM m a
forall (m :: * -> *) a. Monad m => a -> m a
return ( Either
  (TransitionTrace
     ConnStateId
     (ConnectionState peerAddr handle handleError version m))
  (Trace peerAddr handlerTrace)
-> Maybe
     (Either
        (TransitionTrace
           ConnStateId
           (ConnectionState peerAddr handle handleError version m))
        (Trace peerAddr handlerTrace))
forall a. a -> Maybe a
Just (Trace peerAddr handlerTrace
-> Either
     (TransitionTrace
        ConnStateId
        (ConnectionState peerAddr handle handleError version m))
     (Trace peerAddr handlerTrace)
forall a b. b -> Either a b
Right (ConnectionId peerAddr -> Trace peerAddr handlerTrace
forall peerAddr handlerTrace.
ConnectionId peerAddr -> Trace peerAddr handlerTrace
TrForbiddenConnection ConnectionId peerAddr
connId))
                         , MutableConnState peerAddr handle handleError version m
mutableConnState
                         , ConnectionManagerError peerAddr
-> Either
     (ConnectionManagerError peerAddr)
     (Wedge
        (Connected peerAddr handle handleError) (ConnectionId peerAddr))
forall a b. a -> Either a b
Left ((CallStack -> ConnectionManagerError peerAddr)
-> ConnectionManagerError peerAddr
forall a. (?callStack::CallStack) => (CallStack -> a) -> a
withCallStack
                                  (ConnectionId peerAddr
-> CallStack -> ConnectionManagerError peerAddr
forall peerAddr.
ConnectionId peerAddr
-> CallStack -> ConnectionManagerError peerAddr
ForbiddenConnection ConnectionId peerAddr
connId))
                         )

                InboundState ConnectionId peerAddr
connId Async m ()
connThread handle
handle dataFlow :: DataFlow
dataFlow@DataFlow
Duplex -> do
                  -- @
                  --   PromotedToWarm^{Duplex}_{Local} : InboundState Duplex
                  --                                   → DuplexState
                  -- @
                  let connState' :: ConnectionState peerAddr handle handleError version m
connState' = ConnectionId peerAddr
-> Async m ()
-> handle
-> ConnectionState peerAddr handle handleError version m
forall peerAddr handle handleError version (m :: * -> *).
ConnectionId peerAddr
-> Async m ()
-> handle
-> ConnectionState peerAddr handle handleError version m
DuplexState ConnectionId peerAddr
connId Async m ()
connThread handle
handle
                  StrictTVar
  m (ConnectionState peerAddr handle handleError version m)
-> ConnectionState peerAddr handle handleError version m
-> STM m ()
forall (m :: * -> *) a.
MonadSTM m =>
StrictTVar m a -> a -> STM m ()
writeTVar StrictTVar
  m (ConnectionState peerAddr handle handleError version m)
connVar ConnectionState peerAddr handle handleError version m
connState'
                  (Maybe
   (Either
      (TransitionTrace
         ConnStateId
         (ConnectionState peerAddr handle handleError version m))
      (Trace peerAddr handlerTrace)),
 MutableConnState peerAddr handle handleError version m,
 Either
   (ConnectionManagerError peerAddr)
   (Wedge
      (Connected peerAddr handle handleError) (ConnectionId peerAddr)))
-> STM
     m
     (Maybe
        (Either
           (TransitionTrace
              ConnStateId
              (ConnectionState peerAddr handle handleError version m))
           (Trace peerAddr handlerTrace)),
      MutableConnState peerAddr handle handleError version m,
      Either
        (ConnectionManagerError peerAddr)
        (Wedge
           (Connected peerAddr handle handleError) (ConnectionId peerAddr)))
forall a. a -> STM m a
forall (m :: * -> *) a. Monad m => a -> m a
return ( Either
  (TransitionTrace
     ConnStateId
     (ConnectionState peerAddr handle handleError version m))
  (Trace peerAddr handlerTrace)
-> Maybe
     (Either
        (TransitionTrace
           ConnStateId
           (ConnectionState peerAddr handle handleError version m))
        (Trace peerAddr handlerTrace))
forall a. a -> Maybe a
Just (TransitionTrace
  ConnStateId (ConnectionState peerAddr handle handleError version m)
-> Either
     (TransitionTrace
        ConnStateId
        (ConnectionState peerAddr handle handleError version m))
     (Trace peerAddr handlerTrace)
forall a b. a -> Either a b
Left (ConnStateId
-> Transition'
     (MaybeUnknown
        (ConnectionState peerAddr handle handleError version m))
-> TransitionTrace
     ConnStateId (ConnectionState peerAddr handle handleError version m)
forall id state.
id -> Transition' state -> TransitionTrace' id state
TransitionTrace
                                        ConnStateId
connStateId
                                        (ConnectionState peerAddr handle handleError version m
-> ConnectionState peerAddr handle handleError version m
-> Transition'
     (MaybeUnknown
        (ConnectionState peerAddr handle handleError version m))
forall state. state -> state -> Transition state
mkTransition ConnectionState peerAddr handle handleError version m
connState ConnectionState peerAddr handle handleError version m
connState')))
                         , MutableConnState peerAddr handle handleError version m
mutableConnState
                         , Wedge
  (Connected peerAddr handle handleError) (ConnectionId peerAddr)
-> Either
     (ConnectionManagerError peerAddr)
     (Wedge
        (Connected peerAddr handle handleError) (ConnectionId peerAddr))
forall a b. b -> Either a b
Right (Connected peerAddr handle handleError
-> Wedge
     (Connected peerAddr handle handleError) (ConnectionId peerAddr)
forall a b. a -> Wedge a b
Here (ConnectionId peerAddr
-> DataFlow -> handle -> Connected peerAddr handle handleError
forall peerAddr handle handleError.
ConnectionId peerAddr
-> DataFlow -> handle -> Connected peerAddr handle handleError
Connected ConnectionId peerAddr
connId DataFlow
dataFlow handle
handle))
                         )

                DuplexState ConnectionId peerAddr
_connId Async m ()
_connThread  handle
_handle ->
                  (Maybe
   (Either
      (TransitionTrace
         ConnStateId
         (ConnectionState peerAddr handle handleError version m))
      (Trace peerAddr handlerTrace)),
 MutableConnState peerAddr handle handleError version m,
 Either
   (ConnectionManagerError peerAddr)
   (Wedge
      (Connected peerAddr handle handleError) (ConnectionId peerAddr)))
-> STM
     m
     (Maybe
        (Either
           (TransitionTrace
              ConnStateId
              (ConnectionState peerAddr handle handleError version m))
           (Trace peerAddr handlerTrace)),
      MutableConnState peerAddr handle handleError version m,
      Either
        (ConnectionManagerError peerAddr)
        (Wedge
           (Connected peerAddr handle handleError) (ConnectionId peerAddr)))
forall a. a -> STM m a
forall (m :: * -> *) a. Monad m => a -> m a
return ( Either
  (TransitionTrace
     ConnStateId
     (ConnectionState peerAddr handle handleError version m))
  (Trace peerAddr handlerTrace)
-> Maybe
     (Either
        (TransitionTrace
           ConnStateId
           (ConnectionState peerAddr handle handleError version m))
        (Trace peerAddr handlerTrace))
forall a. a -> Maybe a
Just (Trace peerAddr handlerTrace
-> Either
     (TransitionTrace
        ConnStateId
        (ConnectionState peerAddr handle handleError version m))
     (Trace peerAddr handlerTrace)
forall a b. b -> Either a b
Right (Provenance
-> peerAddr -> AbstractState -> Trace peerAddr handlerTrace
forall peerAddr handlerTrace.
Provenance
-> peerAddr -> AbstractState -> Trace peerAddr handlerTrace
TrConnectionExists Provenance
provenance peerAddr
peerAddr AbstractState
st))
                         , MutableConnState peerAddr handle handleError version m
mutableConnState
                         , ConnectionManagerError peerAddr
-> Either
     (ConnectionManagerError peerAddr)
     (Wedge
        (Connected peerAddr handle handleError) (ConnectionId peerAddr))
forall a b. a -> Either a b
Left ((CallStack -> ConnectionManagerError peerAddr)
-> ConnectionManagerError peerAddr
forall a. (?callStack::CallStack) => (CallStack -> a) -> a
withCallStack
                                  (Provenance
-> peerAddr -> CallStack -> ConnectionManagerError peerAddr
forall peerAddr.
Provenance
-> peerAddr -> CallStack -> ConnectionManagerError peerAddr
ConnectionExists Provenance
provenance peerAddr
peerAddr))
                         )

                TerminatingState ConnectionId peerAddr
_connId Async m ()
_connThread Maybe handleError
_handleError ->
                  -- await for 'TerminatedState' or for removal of the
                  -- connection from the state.
                  STM
  m
  (Maybe
     (Either
        (TransitionTrace
           ConnStateId
           (ConnectionState peerAddr handle handleError version m))
        (Trace peerAddr handlerTrace)),
   MutableConnState peerAddr handle handleError version m,
   Either
     (ConnectionManagerError peerAddr)
     (Wedge
        (Connected peerAddr handle handleError) (ConnectionId peerAddr)))
forall a. STM m a
forall (m :: * -> *) a. MonadSTM m => STM m a
retry

                TerminatedState Maybe handleError
_handleError -> do
                  -- the connection terminated; we can not reset 'connVar' and
                  -- start afresh. We should wait for the removal of the
                  -- connection from the state.
                  retry

            Maybe (MutableConnState peerAddr handle handleError version m)
Nothing -> do
              let connState' :: ConnectionState peerAddr handle handleError version m
connState' = ConnectionState peerAddr handle handleError version m
forall {peerAddr} {handle} {handleError} {version} {m :: * -> *}.
ConnectionState peerAddr handle handleError version m
ReservedOutboundState
              (mutableConnState@MutableConnState { connVar, connStateId }
                :: MutableConnState peerAddr handle handleError
                                    version m)
                <- peerAddr
-> ConnStateIdSupply m
-> ConnectionState peerAddr handle handleError version m
-> STM m (MutableConnState peerAddr handle handleError version m)
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)
State.newMutableConnState peerAddr
peerAddr ConnStateIdSupply m
connStateIdSupply ConnectionState peerAddr handle handleError version m
forall {peerAddr} {handle} {handleError} {version} {m :: * -> *}.
ConnectionState peerAddr handle handleError version m
connState'
              -- TODO: label `connVar` using 'ConnectionId'
              labelTVar connVar ("conn-state-" ++ show peerAddr)

              writeTMVar stateVar
                        (State.insertUnknownLocalAddr peerAddr mutableConnState state)
              return ( Just (Left (TransitionTrace
                                    connStateId
                                    Transition {
                                        fromState = Unknown,
                                        toState   = Known connState'
                                      }))
                     , mutableConnState
                     , Right Nowhere
                     )

        traverse_ (either (traceWith trTracer) (traceWith tracer)) trace
        traceCounters stateVar
        case eHandleWedge of
          Left ConnectionManagerError peerAddr
e ->
            ConnectionManagerError peerAddr
-> m (Connected peerAddr handle handleError)
forall e a. Exception e => e -> m a
forall (m :: * -> *) e a. (MonadThrow m, Exception e) => e -> m a
throwIO ConnectionManagerError peerAddr
e

          -- connection manager does not have a connection with @peerAddr@.
          Right Wedge
  (Connected peerAddr handle handleError) (ConnectionId peerAddr)
Nowhere -> do
            (reader, writer) <- m (PromiseReader
     m
     (Either
        handleError
        (HandshakeConnectionResult handle (version, versionData))),
   PromiseWriter
     m
     (Either
        handleError
        (HandshakeConnectionResult handle (version, versionData))))
forall (m :: * -> *) a.
(MonadSTM m, MonadThrow (STM m)) =>
m (PromiseReader m a, PromiseWriter m a)
newEmptyPromiseIO

            (connId, connThread) <-
              -- This section of code passes the control over socket from
              -- `bracketOnError` which is responsible for:
              --
              --    * creating socket
              --    * connecting to remote host
              --    * obtaining local address of the connection
              --
              -- to the connection handler and its resource cleanup.
              -- Both the 'bracketOnError''s resource handler and the
              -- connection handler cleanup function are responsible for:
              --
              --  * closing the socket
              --  * freeing the slot in connection manager state map
              --
              mask $ \forall a. m a -> m a
unmask -> do

                --
                -- connect
                --

                (socket, connId) <-
                  m (socket, ConnectionId peerAddr)
-> m (socket, ConnectionId peerAddr)
forall a. m a -> m a
unmask (m (socket, ConnectionId peerAddr)
 -> m (socket, ConnectionId peerAddr))
-> m (socket, ConnectionId peerAddr)
-> m (socket, ConnectionId peerAddr)
forall a b. (a -> b) -> a -> b
$ m socket
-> (socket -> m ())
-> (socket -> m (socket, ConnectionId peerAddr))
-> m (socket, ConnectionId peerAddr)
forall a b c. m a -> (a -> m b) -> (a -> m c) -> m c
forall (m :: * -> *) a b c.
MonadCatch m =>
m a -> (a -> m b) -> (a -> m c) -> m c
bracketOnError
                    (Snocket m socket peerAddr -> peerAddr -> m socket
forall (m :: * -> *) fd addr. Snocket m fd addr -> addr -> m fd
openToConnect Snocket m socket peerAddr
snocket peerAddr
peerAddr)
                    (\socket
socket -> m () -> m ()
forall a. m a -> m a
forall (m :: * -> *) a. MonadMask m => m a -> m a
uninterruptibleMask_ (m () -> m ()) -> m () -> m ()
forall a b. (a -> b) -> a -> b
$ do
                      Snocket m socket peerAddr -> socket -> m ()
forall (m :: * -> *) fd addr. Snocket m fd addr -> fd -> m ()
close Snocket m socket peerAddr
snocket socket
socket
                      trs <- STM
  m
  [Transition'
     (MaybeUnknown
        (ConnectionState peerAddr handle handleError version m))]
-> m [Transition'
        (MaybeUnknown
           (ConnectionState peerAddr handle handleError version m))]
forall a. (?callStack::CallStack) => STM m a -> m a
forall (m :: * -> *) a.
(MonadSTM m, ?callStack::CallStack) =>
STM m a -> m a
atomically (STM
   m
   [Transition'
      (MaybeUnknown
         (ConnectionState peerAddr handle handleError version m))]
 -> m [Transition'
         (MaybeUnknown
            (ConnectionState peerAddr handle handleError version m))])
-> STM
     m
     [Transition'
        (MaybeUnknown
           (ConnectionState peerAddr handle handleError version m))]
-> m [Transition'
        (MaybeUnknown
           (ConnectionState peerAddr handle handleError version m))]
forall a b. (a -> b) -> a -> b
$ StrictTMVar
  m (ConnectionManagerState peerAddr handle handleError version m)
-> (ConnectionManagerState peerAddr handle handleError version m
    -> STM
         m
         (ConnectionManagerState peerAddr handle handleError version m,
          [Transition'
             (MaybeUnknown
                (ConnectionState peerAddr handle handleError version m))]))
-> STM
     m
     [Transition'
        (MaybeUnknown
           (ConnectionState peerAddr handle handleError version m))]
forall (m :: * -> *) a b.
MonadSTM m =>
StrictTMVar m a -> (a -> STM m (a, b)) -> STM m b
modifyTMVarSTM StrictTMVar
  m (ConnectionManagerState peerAddr handle handleError version m)
stateVar ((ConnectionManagerState peerAddr handle handleError version m
  -> STM
       m
       (ConnectionManagerState peerAddr handle handleError version m,
        [Transition'
           (MaybeUnknown
              (ConnectionState peerAddr handle handleError version m))]))
 -> STM
      m
      [Transition'
         (MaybeUnknown
            (ConnectionState peerAddr handle handleError version m))])
-> (ConnectionManagerState peerAddr handle handleError version m
    -> STM
         m
         (ConnectionManagerState peerAddr handle handleError version m,
          [Transition'
             (MaybeUnknown
                (ConnectionState peerAddr handle handleError version m))]))
-> STM
     m
     [Transition'
        (MaybeUnknown
           (ConnectionState peerAddr handle handleError version m))]
forall a b. (a -> b) -> a -> b
$ \ConnectionManagerState peerAddr handle handleError version m
state -> do
                        connState <- 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)
connVar
                        let state' = peerAddr
-> MutableConnState peerAddr handle handleError version m
-> ConnectionManagerState peerAddr handle handleError version m
-> ConnectionManagerState peerAddr handle handleError version m
forall peerAddr a.
(Ord peerAddr, Eq a) =>
peerAddr -> a -> ConnMap peerAddr a -> ConnMap peerAddr a
State.deleteAtRemoteAddr peerAddr
peerAddr MutableConnState peerAddr handle handleError version m
mutableConnState ConnectionManagerState peerAddr handle handleError version m
state
                            connState' = Maybe handleError
-> ConnectionState peerAddr handle handleError version m
forall peerAddr handle handleError version (m :: * -> *).
Maybe handleError
-> ConnectionState peerAddr handle handleError version m
TerminatedState Maybe handleError
forall a. Maybe a
Nothing
                        writeTVar connVar connState'
                        return
                          ( state'
                          , [ mkTransition connState connState'
                            , Transition (Known connState')
                                         Unknown
                            ]
                          )

                      traverse_ (traceWith trTracer . TransitionTrace connStateId) trs
                      traceCounters stateVar
                    )
                    ((socket -> m (socket, ConnectionId peerAddr))
 -> m (socket, ConnectionId peerAddr))
-> (socket -> m (socket, ConnectionId peerAddr))
-> m (socket, ConnectionId peerAddr)
forall a b. (a -> b) -> a -> b
$ \socket
socket -> do
                      Tracer m (Trace peerAddr handlerTrace)
-> Trace peerAddr handlerTrace -> m ()
forall (m :: * -> *) a. Tracer m a -> a -> m ()
traceWith Tracer m (Trace peerAddr handlerTrace)
tracer (Provenance -> peerAddr -> Trace peerAddr handlerTrace
forall peerAddr handlerTrace.
Provenance -> peerAddr -> Trace peerAddr handlerTrace
TrConnectionNotFound Provenance
provenance peerAddr
peerAddr)
                      let addr :: Maybe peerAddr
addr = case peerAddr -> Maybe AddressType
addressType peerAddr
peerAddr of
                                   Maybe AddressType
Nothing          -> Maybe peerAddr
forall a. Maybe a
Nothing
                                   Just AddressType
IPv4Address -> Maybe peerAddr
ipv4Address
                                   Just AddressType
IPv6Address -> Maybe peerAddr
ipv6Address
                      socket -> Maybe peerAddr -> m ()
configureSocket socket
socket Maybe peerAddr
addr
                      -- only bind to the ip address if:
                      -- * the diffusion is given `ipv4/6` addresses;
                      -- * `diffusionMode` for this connection is
                      --   `InitiatorAndResponderMode`.
                      case peerAddr -> Maybe AddressType
addressType peerAddr
peerAddr of
                        Just AddressType
IPv4Address | DiffusionMode
InitiatorAndResponderDiffusionMode
                                           <- DiffusionMode
diffusionMode ->
                             (peerAddr -> m ()) -> Maybe peerAddr -> m ()
forall (t :: * -> *) (f :: * -> *) a b.
(Foldable t, Applicative f) =>
(a -> f b) -> t a -> f ()
traverse_ (Snocket m socket peerAddr -> socket -> peerAddr -> m ()
forall (m :: * -> *) fd addr.
Snocket m fd addr -> fd -> addr -> m ()
bind Snocket m socket peerAddr
snocket socket
socket)
                                       Maybe peerAddr
ipv4Address
                        Just AddressType
IPv6Address | DiffusionMode
InitiatorAndResponderDiffusionMode
                                           <- DiffusionMode
diffusionMode ->
                             (peerAddr -> m ()) -> Maybe peerAddr -> m ()
forall (t :: * -> *) (f :: * -> *) a b.
(Foldable t, Applicative f) =>
(a -> f b) -> t a -> f ()
traverse_ (Snocket m socket peerAddr -> socket -> peerAddr -> m ()
forall (m :: * -> *) fd addr.
Snocket m fd addr -> fd -> addr -> m ()
bind Snocket m socket peerAddr
snocket socket
socket)
                                       Maybe peerAddr
ipv6Address
                        Maybe AddressType
_ -> () -> m ()
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()

                      Tracer m (Trace peerAddr handlerTrace)
-> Trace peerAddr handlerTrace -> m ()
forall (m :: * -> *) a. Tracer m a -> a -> m ()
traceWith Tracer m (Trace peerAddr handlerTrace)
tracer (Maybe peerAddr
-> peerAddr -> DiffusionMode -> Trace peerAddr handlerTrace
forall peerAddr handlerTrace.
Maybe peerAddr
-> peerAddr -> DiffusionMode -> Trace peerAddr handlerTrace
TrConnect Maybe peerAddr
addr peerAddr
peerAddr DiffusionMode
diffusionMode)
                      Snocket m socket peerAddr -> socket -> peerAddr -> m ()
forall (m :: * -> *) fd addr.
Snocket m fd addr -> fd -> addr -> m ()
connect Snocket m socket peerAddr
snocket socket
socket peerAddr
peerAddr
                        m () -> (SomeException -> m ()) -> m ()
forall e a. Exception e => m a -> (e -> m a) -> m a
forall (m :: * -> *) e a.
(MonadCatch m, Exception e) =>
m a -> (e -> m a) -> m a
`catch` \SomeException
e -> do
                          Tracer m (Trace peerAddr handlerTrace)
-> Trace peerAddr handlerTrace -> m ()
forall (m :: * -> *) a. Tracer m a -> a -> m ()
traceWith Tracer m (Trace peerAddr handlerTrace)
tracer (Maybe peerAddr
-> peerAddr -> SomeException -> Trace peerAddr handlerTrace
forall peerAddr handlerTrace.
Maybe peerAddr
-> peerAddr -> SomeException -> Trace peerAddr handlerTrace
TrConnectError Maybe peerAddr
addr peerAddr
peerAddr SomeException
e)
                          -- the handler attached by `bracketOnError` will
                          -- reset the state
                          SomeException -> m ()
forall e a. Exception e => e -> m a
forall (m :: * -> *) e a. (MonadThrow m, Exception e) => e -> m a
throwIO SomeException
e
                      localAddress <- Snocket m socket peerAddr -> socket -> m peerAddr
forall (m :: * -> *) fd addr. Snocket m fd addr -> fd -> m addr
getLocalAddr Snocket m socket peerAddr
snocket socket
socket
                      let connId = ConnectionId { peerAddr
localAddress :: peerAddr
localAddress :: peerAddr
localAddress
                                                , remoteAddress :: peerAddr
remoteAddress = peerAddr
peerAddr
                                                }
                      updated <- atomically $ modifyTMVarPure stateVar (swap . State.updateLocalAddr connId)
                      unless updated $
                        -- there exists a connection with exact same
                        -- `ConnectionId`
                        --
                        -- NOTE:
                        -- When we are connecting from our own `(ip, port)` to
                        -- itself.  In this case on linux, the `connect`
                        -- returns, while `accept` doesn't.  The outbound
                        -- socket is connected to itself (simultaneuos TCP
                        -- open?).  Since the `accept` call never returns, the
                        -- `connId` slot must have been available, and thus
                        -- `State.updateLocalAddr` must have returned `True`.
                        throwIO (withCallStack $ ConnectionExists provenance peerAddr)

                      return (socket, connId)

                --
                -- fork connection handler; it will unmask exceptions
                --

                connThread <-
                  forkConnectionHandler
                    (`updateVersionData` diffusionMode) stateVar mutableConnState socket connId writer handler
                return (connId, connThread)

            (trans, mbAssertion) <- atomically $ do
              connState <- readTVar connVar

              -- @
              --  Connected : ReservedOutboundState
              --            → UnnegotiatedState Outbound
              -- @
              case connState of
                ConnectionState peerAddr handle handleError version m
ReservedOutboundState -> do
                  let connState' :: ConnectionState peerAddr handle handleError version m
connState' = Provenance
-> ConnectionId peerAddr
-> Async m ()
-> ConnectionState peerAddr handle handleError version m
forall peerAddr handle handleError version (m :: * -> *).
Provenance
-> ConnectionId peerAddr
-> Async m ()
-> ConnectionState peerAddr handle handleError version m
UnnegotiatedState Provenance
provenance ConnectionId peerAddr
connId Async m ()
connThread
                  StrictTVar
  m (ConnectionState peerAddr handle handleError version m)
-> ConnectionState peerAddr handle handleError version m
-> STM m ()
forall (m :: * -> *) a.
MonadSTM m =>
StrictTVar m a -> a -> STM m ()
writeTVar StrictTVar
  m (ConnectionState peerAddr handle handleError version m)
connVar ConnectionState peerAddr handle handleError version m
connState'
                  (Maybe
   (Transition'
      (MaybeUnknown
         (ConnectionState peerAddr handle handleError version m))),
 Maybe (Trace peerAddr handlerTrace))
-> STM
     m
     (Maybe
        (Transition'
           (MaybeUnknown
              (ConnectionState peerAddr handle handleError version m))),
      Maybe (Trace peerAddr handlerTrace))
forall a. a -> STM m a
forall (m :: * -> *) a. Monad m => a -> m a
return ( Transition'
  (MaybeUnknown
     (ConnectionState peerAddr handle handleError version m))
-> Maybe
     (Transition'
        (MaybeUnknown
           (ConnectionState peerAddr handle handleError version m)))
forall a. a -> Maybe a
Just (Transition'
   (MaybeUnknown
      (ConnectionState peerAddr handle handleError version m))
 -> Maybe
      (Transition'
         (MaybeUnknown
            (ConnectionState peerAddr handle handleError version m))))
-> Transition'
     (MaybeUnknown
        (ConnectionState peerAddr handle handleError version m))
-> Maybe
     (Transition'
        (MaybeUnknown
           (ConnectionState peerAddr handle handleError version m)))
forall a b. (a -> b) -> a -> b
$ ConnectionState peerAddr handle handleError version m
-> ConnectionState peerAddr handle handleError version m
-> Transition'
     (MaybeUnknown
        (ConnectionState peerAddr handle handleError version m))
forall state. state -> state -> Transition state
mkTransition ConnectionState peerAddr handle handleError version m
connState ConnectionState peerAddr handle handleError version m
connState'
                         , Maybe (Trace peerAddr handlerTrace)
forall a. Maybe a
Nothing
                         )

                -- @
                --  SelfConn⁻¹ : UnnegotiatedState Inbound
                --             → UnnegotiatedState Outbound
                -- @
                --
                UnnegotiatedState Provenance
Inbound ConnectionId peerAddr
_connId Async m ()
_connThread -> do
                  let connState' :: ConnectionState peerAddr handle handleError version m
connState' = Provenance
-> ConnectionId peerAddr
-> Async m ()
-> ConnectionState peerAddr handle handleError version m
forall peerAddr handle handleError version (m :: * -> *).
Provenance
-> ConnectionId peerAddr
-> Async m ()
-> ConnectionState peerAddr handle handleError version m
UnnegotiatedState Provenance
Outbound ConnectionId peerAddr
connId Async m ()
connThread
                  StrictTVar
  m (ConnectionState peerAddr handle handleError version m)
-> ConnectionState peerAddr handle handleError version m
-> STM m ()
forall (m :: * -> *) a.
MonadSTM m =>
StrictTVar m a -> a -> STM m ()
writeTVar StrictTVar
  m (ConnectionState peerAddr handle handleError version m)
connVar ConnectionState peerAddr handle handleError version m
connState'
                  (Maybe
   (Transition'
      (MaybeUnknown
         (ConnectionState peerAddr handle handleError version m))),
 Maybe (Trace peerAddr handlerTrace))
-> STM
     m
     (Maybe
        (Transition'
           (MaybeUnknown
              (ConnectionState peerAddr handle handleError version m))),
      Maybe (Trace peerAddr handlerTrace))
forall a. a -> STM m a
forall (m :: * -> *) a. Monad m => a -> m a
return ( Transition'
  (MaybeUnknown
     (ConnectionState peerAddr handle handleError version m))
-> Maybe
     (Transition'
        (MaybeUnknown
           (ConnectionState peerAddr handle handleError version m)))
forall a. a -> Maybe a
Just (Transition'
   (MaybeUnknown
      (ConnectionState peerAddr handle handleError version m))
 -> Maybe
      (Transition'
         (MaybeUnknown
            (ConnectionState peerAddr handle handleError version m))))
-> Transition'
     (MaybeUnknown
        (ConnectionState peerAddr handle handleError version m))
-> Maybe
     (Transition'
        (MaybeUnknown
           (ConnectionState peerAddr handle handleError version m)))
forall a b. (a -> b) -> a -> b
$ ConnectionState peerAddr handle handleError version m
-> ConnectionState peerAddr handle handleError version m
-> Transition'
     (MaybeUnknown
        (ConnectionState peerAddr handle handleError version m))
forall state. state -> state -> Transition state
mkTransition ConnectionState peerAddr handle handleError version m
connState ConnectionState peerAddr handle handleError version m
connState'
                         , Maybe (Trace peerAddr handlerTrace)
forall a. Maybe a
Nothing
                         )


                TerminatingState {} ->
                  (Maybe
   (Transition'
      (MaybeUnknown
         (ConnectionState peerAddr handle handleError version m))),
 Maybe (Trace peerAddr handlerTrace))
-> STM
     m
     (Maybe
        (Transition'
           (MaybeUnknown
              (ConnectionState peerAddr handle handleError version m))),
      Maybe (Trace peerAddr handlerTrace))
forall a. a -> STM m a
forall (m :: * -> *) a. Monad m => a -> m a
return (Maybe
  (Transition'
     (MaybeUnknown
        (ConnectionState peerAddr handle handleError version m)))
forall a. Maybe a
Nothing, Maybe (Trace peerAddr handlerTrace)
forall a. Maybe a
Nothing)
                TerminatedState {} ->
                  (Maybe
   (Transition'
      (MaybeUnknown
         (ConnectionState peerAddr handle handleError version m))),
 Maybe (Trace peerAddr handlerTrace))
-> STM
     m
     (Maybe
        (Transition'
           (MaybeUnknown
              (ConnectionState peerAddr handle handleError version m))),
      Maybe (Trace peerAddr handlerTrace))
forall a. a -> STM m a
forall (m :: * -> *) a. Monad m => a -> m a
return (Maybe
  (Transition'
     (MaybeUnknown
        (ConnectionState peerAddr handle handleError version m)))
forall a. Maybe a
Nothing, Maybe (Trace peerAddr handlerTrace)
forall a. Maybe a
Nothing)
                ConnectionState peerAddr handle handleError version m
_ ->
                  (Maybe
   (Transition'
      (MaybeUnknown
         (ConnectionState peerAddr handle handleError version m))),
 Maybe (Trace peerAddr handlerTrace))
-> STM
     m
     (Maybe
        (Transition'
           (MaybeUnknown
              (ConnectionState peerAddr handle handleError version m))),
      Maybe (Trace peerAddr handlerTrace))
forall a. a -> STM m a
forall (m :: * -> *) a. Monad m => a -> m a
return ( Maybe
  (Transition'
     (MaybeUnknown
        (ConnectionState peerAddr handle handleError version m)))
forall a. Maybe a
Nothing
                         , Trace peerAddr handlerTrace -> Maybe (Trace peerAddr handlerTrace)
forall a. a -> Maybe a
Just (AssertionLocation peerAddr -> Trace peerAddr handlerTrace
forall peerAddr handlerTrace.
AssertionLocation peerAddr -> Trace peerAddr handlerTrace
TrUnexpectedlyFalseAssertion
                                   (Maybe (ConnectionId peerAddr)
-> AbstractState -> AssertionLocation peerAddr
forall peerAddr.
Maybe (ConnectionId peerAddr)
-> AbstractState -> AssertionLocation peerAddr
AcquireOutboundConnection
                                     (ConnectionId peerAddr -> Maybe (ConnectionId peerAddr)
forall a. a -> Maybe a
Just ConnectionId peerAddr
connId)
                                     (MaybeUnknown
  (ConnectionState peerAddr handle handleError version m)
-> AbstractState
forall muxMode peerAddr m a (b :: * -> *).
MaybeUnknown (ConnectionState muxMode peerAddr m a b)
-> AbstractState
State.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
connState))
                                   )
                                )
                         )

            traverse_ (traceWith trTracer . TransitionTrace connStateId) trans
            traverse_ (traceWith tracer >=> evaluate . assert True)
                      mbAssertion
            traceCounters stateVar

            res <- atomically (readPromise reader)
            case res of
              Left handleError
handleError -> do
                ConnectionId peerAddr
-> ConnStateId
-> StrictTVar
     m (ConnectionState peerAddr handle handleError version m)
-> Async m ()
-> StrictTMVar
     m (ConnectionManagerState peerAddr handle handleError version m)
-> MutableConnState peerAddr handle handleError version m
-> Maybe handleError
-> m (Connected peerAddr handle handleError)
terminateOutboundWithErrorOrQuery ConnectionId peerAddr
connId ConnStateId
connStateId StrictTVar
  m (ConnectionState peerAddr handle handleError version m)
connVar Async m ()
connThread StrictTMVar
  m (ConnectionManagerState peerAddr handle handleError version m)
stateVar MutableConnState peerAddr handle handleError version m
mutableConnState (Maybe handleError -> m (Connected peerAddr handle handleError))
-> Maybe handleError -> m (Connected peerAddr handle handleError)
forall a b. (a -> b) -> a -> b
$ handleError -> Maybe handleError
forall a. a -> Maybe a
Just handleError
handleError

              Right HandshakeConnectionResult handle (version, versionData)
HandshakeConnectionQuery -> do
                ConnectionId peerAddr
-> ConnStateId
-> StrictTVar
     m (ConnectionState peerAddr handle handleError version m)
-> Async m ()
-> StrictTMVar
     m (ConnectionManagerState peerAddr handle handleError version m)
-> MutableConnState peerAddr handle handleError version m
-> Maybe handleError
-> m (Connected peerAddr handle handleError)
terminateOutboundWithErrorOrQuery ConnectionId peerAddr
connId ConnStateId
connStateId StrictTVar
  m (ConnectionState peerAddr handle handleError version m)
connVar Async m ()
connThread StrictTMVar
  m (ConnectionManagerState peerAddr handle handleError version m)
stateVar MutableConnState peerAddr handle handleError version m
mutableConnState Maybe handleError
forall a. Maybe a
Nothing

              Right (HandshakeConnectionResult handle
handle (version
_version, versionData
versionData)) -> do
                let dataFlow :: DataFlow
dataFlow = versionData -> DataFlow
connectionDataFlow versionData
versionData
                -- We can safely overwrite the state: after successful
                -- `connect` it's not possible to have a race condition
                -- with any other inbound thread.  We are also guaranteed
                -- to have exclusive access as an outbound thread.
                mbTransition <- STM
  m
  (Maybe
     (Transition'
        (MaybeUnknown
           (ConnectionState peerAddr handle handleError version m))))
-> m (Maybe
        (Transition'
           (MaybeUnknown
              (ConnectionState peerAddr handle handleError version m))))
forall a. (?callStack::CallStack) => STM m a -> m a
forall (m :: * -> *) a.
(MonadSTM m, ?callStack::CallStack) =>
STM m a -> m a
atomically (STM
   m
   (Maybe
      (Transition'
         (MaybeUnknown
            (ConnectionState peerAddr handle handleError version m))))
 -> m (Maybe
         (Transition'
            (MaybeUnknown
               (ConnectionState peerAddr handle handleError version m)))))
-> STM
     m
     (Maybe
        (Transition'
           (MaybeUnknown
              (ConnectionState peerAddr handle handleError version m))))
-> m (Maybe
        (Transition'
           (MaybeUnknown
              (ConnectionState peerAddr handle handleError version m))))
forall a b. (a -> b) -> a -> b
$ do
                  connState <- 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)
connVar
                  case connState of
                    UnnegotiatedState Provenance
provenance' ConnectionId peerAddr
_ Async m ()
_ ->
                      case DataFlow
dataFlow of
                        DataFlow
Unidirectional -> do
                          -- @
                          --  Negotiated^{Unidirectional}_{Outbound}
                          --    : UnnegotiatedState Outbound
                          --    → OutboundUniState Outbound
                          -- @
                          let connState' :: ConnectionState peerAddr handle handleError version m
connState' = ConnectionId peerAddr
-> Async m ()
-> handle
-> ConnectionState peerAddr handle handleError version m
forall peerAddr handle handleError version (m :: * -> *).
ConnectionId peerAddr
-> Async m ()
-> handle
-> ConnectionState peerAddr handle handleError version m
OutboundUniState ConnectionId peerAddr
connId Async m ()
connThread handle
handle
                          StrictTVar
  m (ConnectionState peerAddr handle handleError version m)
-> ConnectionState peerAddr handle handleError version m
-> STM m ()
forall (m :: * -> *) a.
MonadSTM m =>
StrictTVar m a -> a -> STM m ()
writeTVar StrictTVar
  m (ConnectionState peerAddr handle handleError version m)
connVar ConnectionState peerAddr handle handleError version m
connState'
                          Maybe
  (Transition'
     (MaybeUnknown
        (ConnectionState peerAddr handle handleError version m)))
-> STM
     m
     (Maybe
        (Transition'
           (MaybeUnknown
              (ConnectionState peerAddr handle handleError version m))))
forall a. a -> STM m a
forall (m :: * -> *) a. Monad m => a -> m a
return (Transition'
  (MaybeUnknown
     (ConnectionState peerAddr handle handleError version m))
-> Maybe
     (Transition'
        (MaybeUnknown
           (ConnectionState peerAddr handle handleError version m)))
forall a. a -> Maybe a
Just (Transition'
   (MaybeUnknown
      (ConnectionState peerAddr handle handleError version m))
 -> Maybe
      (Transition'
         (MaybeUnknown
            (ConnectionState peerAddr handle handleError version m))))
-> Transition'
     (MaybeUnknown
        (ConnectionState peerAddr handle handleError version m))
-> Maybe
     (Transition'
        (MaybeUnknown
           (ConnectionState peerAddr handle handleError version m)))
forall a b. (a -> b) -> a -> b
$ ConnectionState peerAddr handle handleError version m
-> ConnectionState peerAddr handle handleError version m
-> Transition'
     (MaybeUnknown
        (ConnectionState peerAddr handle handleError version m))
forall state. state -> state -> Transition state
mkTransition ConnectionState peerAddr handle handleError version m
connState ConnectionState peerAddr handle handleError version m
connState')
                        DataFlow
Duplex -> do
                          -- @
                          --  Negotiated^{Duplex}_{Outbound}
                          --    : UnnegotiatedState Outbound
                          --    → OutboundDupState^\tau Outbound
                          -- @
                          let connState' :: ConnectionState peerAddr handle handleError version m
connState' = ConnectionId peerAddr
-> Async m ()
-> handle
-> TimeoutExpired
-> ConnectionState peerAddr handle handleError version m
forall peerAddr handle handleError version (m :: * -> *).
ConnectionId peerAddr
-> Async m ()
-> handle
-> TimeoutExpired
-> ConnectionState peerAddr handle handleError version m
OutboundDupState ConnectionId peerAddr
connId Async m ()
connThread handle
handle TimeoutExpired
Ticking
                              notifyInboundGov :: Bool
notifyInboundGov =
                                case Provenance
provenance' of
                                  Provenance
Inbound  -> Bool
False
                                  -- This is a connection to oneself; We don't
                                  -- need to notify the inbound governor, as
                                  -- it's already done by
                                  -- `includeInboundConnectionImpl`
                                  Provenance
Outbound -> Bool
True
                          StrictTVar
  m (ConnectionState peerAddr handle handleError version m)
-> ConnectionState peerAddr handle handleError version m
-> STM m ()
forall (m :: * -> *) a.
MonadSTM m =>
StrictTVar m a -> a -> STM m ()
writeTVar StrictTVar
  m (ConnectionState peerAddr handle handleError version m)
connVar ConnectionState peerAddr handle handleError version m
connState'
                          case InResponderMode
  muxMode (InformationChannel (NewConnectionInfo peerAddr handle) m)
inboundGovernorInfoChannel of
                            InResponderMode InformationChannel (NewConnectionInfo peerAddr handle) m
infoChannel | Bool
notifyInboundGov ->
                              InformationChannel (NewConnectionInfo peerAddr handle) m
-> NewConnectionInfo peerAddr handle -> STM m ()
forall a (m :: * -> *). InformationChannel a m -> a -> STM m ()
InfoChannel.writeMessage
                                InformationChannel (NewConnectionInfo peerAddr handle) m
infoChannel
                                (Provenance
-> ConnectionId peerAddr
-> DataFlow
-> handle
-> NewConnectionInfo peerAddr handle
forall peerAddr handle.
Provenance
-> ConnectionId peerAddr
-> DataFlow
-> handle
-> NewConnectionInfo peerAddr handle
NewConnectionInfo Provenance
provenance' ConnectionId peerAddr
connId DataFlow
dataFlow handle
handle)
                            InResponderMode
  muxMode (InformationChannel (NewConnectionInfo peerAddr handle) m)
_ -> () -> STM m ()
forall a. a -> STM m a
forall (m :: * -> *) a. Monad m => a -> m a
return ()
                          Maybe
  (Transition'
     (MaybeUnknown
        (ConnectionState peerAddr handle handleError version m)))
-> STM
     m
     (Maybe
        (Transition'
           (MaybeUnknown
              (ConnectionState peerAddr handle handleError version m))))
forall a. a -> STM m a
forall (m :: * -> *) a. Monad m => a -> m a
return (Transition'
  (MaybeUnknown
     (ConnectionState peerAddr handle handleError version m))
-> Maybe
     (Transition'
        (MaybeUnknown
           (ConnectionState peerAddr handle handleError version m)))
forall a. a -> Maybe a
Just (Transition'
   (MaybeUnknown
      (ConnectionState peerAddr handle handleError version m))
 -> Maybe
      (Transition'
         (MaybeUnknown
            (ConnectionState peerAddr handle handleError version m))))
-> Transition'
     (MaybeUnknown
        (ConnectionState peerAddr handle handleError version m))
-> Maybe
     (Transition'
        (MaybeUnknown
           (ConnectionState peerAddr handle handleError version m)))
forall a b. (a -> b) -> a -> b
$ ConnectionState peerAddr handle handleError version m
-> ConnectionState peerAddr handle handleError version m
-> Transition'
     (MaybeUnknown
        (ConnectionState peerAddr handle handleError version m))
forall state. state -> state -> Transition state
mkTransition ConnectionState peerAddr handle handleError version m
connState ConnectionState peerAddr handle handleError version m
connState')

                    -- @
                    --   SelfConn'^{-1}
                    --     : InboundIdleState Unidirectional
                    --     → OutboundUniState
                    -- @
                    InboundIdleState ConnectionId peerAddr
connId' Async m ()
connThread' handle
handle' DataFlow
Unidirectional -> do
                      let connState' :: ConnectionState peerAddr handle handleError version m
connState' = ConnectionId peerAddr
-> Async m ()
-> handle
-> ConnectionState peerAddr handle handleError version m
forall peerAddr handle handleError version (m :: * -> *).
ConnectionId peerAddr
-> Async m ()
-> handle
-> ConnectionState peerAddr handle handleError version m
OutboundUniState ConnectionId peerAddr
connId' Async m ()
connThread' handle
handle'
                      StrictTVar
  m (ConnectionState peerAddr handle handleError version m)
-> ConnectionState peerAddr handle handleError version m
-> STM m ()
forall (m :: * -> *) a.
MonadSTM m =>
StrictTVar m a -> a -> STM m ()
writeTVar StrictTVar
  m (ConnectionState peerAddr handle handleError version m)
connVar ConnectionState peerAddr handle handleError version m
connState'
                      Maybe
  (Transition'
     (MaybeUnknown
        (ConnectionState peerAddr handle handleError version m)))
-> STM
     m
     (Maybe
        (Transition'
           (MaybeUnknown
              (ConnectionState peerAddr handle handleError version m))))
forall a. a -> STM m a
forall (m :: * -> *) a. Monad m => a -> m a
return (Transition'
  (MaybeUnknown
     (ConnectionState peerAddr handle handleError version m))
-> Maybe
     (Transition'
        (MaybeUnknown
           (ConnectionState peerAddr handle handleError version m)))
forall a. a -> Maybe a
Just (Transition'
   (MaybeUnknown
      (ConnectionState peerAddr handle handleError version m))
 -> Maybe
      (Transition'
         (MaybeUnknown
            (ConnectionState peerAddr handle handleError version m))))
-> Transition'
     (MaybeUnknown
        (ConnectionState peerAddr handle handleError version m))
-> Maybe
     (Transition'
        (MaybeUnknown
           (ConnectionState peerAddr handle handleError version m)))
forall a b. (a -> b) -> a -> b
$ ConnectionState peerAddr handle handleError version m
-> ConnectionState peerAddr handle handleError version m
-> Transition'
     (MaybeUnknown
        (ConnectionState peerAddr handle handleError version m))
forall state. state -> state -> Transition state
mkTransition ConnectionState peerAddr handle handleError version m
connState ConnectionState peerAddr handle handleError version m
connState')

                    -- @
                    --   SelfConn'^{-1}
                    --     : InboundIdleState Duplex
                    --     → OutboundDupState
                    -- @
                    InboundIdleState ConnectionId peerAddr
connId' Async m ()
connThread' handle
handle' DataFlow
Duplex -> do
                      let connState' :: ConnectionState peerAddr handle handleError version m
connState' = ConnectionId peerAddr
-> Async m ()
-> handle
-> TimeoutExpired
-> ConnectionState peerAddr handle handleError version m
forall peerAddr handle handleError version (m :: * -> *).
ConnectionId peerAddr
-> Async m ()
-> handle
-> TimeoutExpired
-> ConnectionState peerAddr handle handleError version m
OutboundDupState ConnectionId peerAddr
connId' Async m ()
connThread' handle
handle' TimeoutExpired
Ticking
                      StrictTVar
  m (ConnectionState peerAddr handle handleError version m)
-> ConnectionState peerAddr handle handleError version m
-> STM m ()
forall (m :: * -> *) a.
MonadSTM m =>
StrictTVar m a -> a -> STM m ()
writeTVar StrictTVar
  m (ConnectionState peerAddr handle handleError version m)
connVar ConnectionState peerAddr handle handleError version m
connState'
                      Maybe
  (Transition'
     (MaybeUnknown
        (ConnectionState peerAddr handle handleError version m)))
-> STM
     m
     (Maybe
        (Transition'
           (MaybeUnknown
              (ConnectionState peerAddr handle handleError version m))))
forall a. a -> STM m a
forall (m :: * -> *) a. Monad m => a -> m a
return (Transition'
  (MaybeUnknown
     (ConnectionState peerAddr handle handleError version m))
-> Maybe
     (Transition'
        (MaybeUnknown
           (ConnectionState peerAddr handle handleError version m)))
forall a. a -> Maybe a
Just (Transition'
   (MaybeUnknown
      (ConnectionState peerAddr handle handleError version m))
 -> Maybe
      (Transition'
         (MaybeUnknown
            (ConnectionState peerAddr handle handleError version m))))
-> Transition'
     (MaybeUnknown
        (ConnectionState peerAddr handle handleError version m))
-> Maybe
     (Transition'
        (MaybeUnknown
           (ConnectionState peerAddr handle handleError version m)))
forall a b. (a -> b) -> a -> b
$ ConnectionState peerAddr handle handleError version m
-> ConnectionState peerAddr handle handleError version m
-> Transition'
     (MaybeUnknown
        (ConnectionState peerAddr handle handleError version m))
forall state. state -> state -> Transition state
mkTransition ConnectionState peerAddr handle handleError version m
connState ConnectionState peerAddr handle handleError version m
connState')

                    TerminatedState Maybe handleError
_ ->
                      Maybe
  (Transition'
     (MaybeUnknown
        (ConnectionState peerAddr handle handleError version m)))
-> STM
     m
     (Maybe
        (Transition'
           (MaybeUnknown
              (ConnectionState peerAddr handle handleError version m))))
forall a. a -> STM m a
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe
  (Transition'
     (MaybeUnknown
        (ConnectionState peerAddr handle handleError version m)))
forall a. Maybe a
Nothing
                    ConnectionState peerAddr handle handleError version m
_ ->
                      let st :: AbstractState
st = MaybeUnknown
  (ConnectionState peerAddr handle handleError version m)
-> AbstractState
forall muxMode peerAddr m a (b :: * -> *).
MaybeUnknown (ConnectionState muxMode peerAddr m a b)
-> AbstractState
State.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
connState) in
                      ConnectionManagerError peerAddr
-> STM
     m
     (Maybe
        (Transition'
           (MaybeUnknown
              (ConnectionState peerAddr handle handleError version m))))
forall (m :: * -> *) e a.
(MonadSTM m, MonadThrow (STM m), Exception e) =>
e -> STM m a
throwSTM ((CallStack -> ConnectionManagerError peerAddr)
-> ConnectionManagerError peerAddr
forall a. (?callStack::CallStack) => (CallStack -> a) -> a
withCallStack (peerAddr
-> AbstractState -> CallStack -> ConnectionManagerError peerAddr
forall peerAddr.
peerAddr
-> AbstractState -> CallStack -> ConnectionManagerError peerAddr
ForbiddenOperation peerAddr
peerAddr AbstractState
st))
                traverse_ (traceWith trTracer .  TransitionTrace connStateId)
                          mbTransition
                traceCounters stateVar
                return $ case mbTransition of
                  Just Transition'
  (MaybeUnknown
     (ConnectionState peerAddr handle handleError version m))
_  -> ConnectionId peerAddr
-> DataFlow -> handle -> Connected peerAddr handle handleError
forall peerAddr handle handleError.
ConnectionId peerAddr
-> DataFlow -> handle -> Connected peerAddr handle handleError
Connected    ConnectionId peerAddr
connId DataFlow
dataFlow handle
handle
                  Maybe
  (Transition'
     (MaybeUnknown
        (ConnectionState peerAddr handle handleError version m)))
Nothing -> ConnectionId peerAddr
-> Maybe handleError -> Connected peerAddr handle handleError
forall peerAddr handle handleError.
ConnectionId peerAddr
-> Maybe handleError -> Connected peerAddr handle handleError
Disconnected ConnectionId peerAddr
connId Maybe handleError
forall a. Maybe a
Nothing

          Right (There ConnectionId peerAddr
connId) -> do
            -- We can only enter the 'There' case if there is an inbound
            -- connection, and we are about to reuse it, but we need to wait
            -- for handshake.
            (etr, connected) <- STM
  m
  (Either
     (TransitionTrace
        ConnStateId
        (ConnectionState peerAddr handle handleError version m))
     (Trace peerAddr handlerTrace),
   Connected peerAddr handle handleError)
-> m (Either
        (TransitionTrace
           ConnStateId
           (ConnectionState peerAddr handle handleError version m))
        (Trace peerAddr handlerTrace),
      Connected peerAddr handle handleError)
forall a. (?callStack::CallStack) => STM m a -> m a
forall (m :: * -> *) a.
(MonadSTM m, ?callStack::CallStack) =>
STM m a -> m a
atomically (STM
   m
   (Either
      (TransitionTrace
         ConnStateId
         (ConnectionState peerAddr handle handleError version m))
      (Trace peerAddr handlerTrace),
    Connected peerAddr handle handleError)
 -> m (Either
         (TransitionTrace
            ConnStateId
            (ConnectionState peerAddr handle handleError version m))
         (Trace peerAddr handlerTrace),
       Connected peerAddr handle handleError))
-> STM
     m
     (Either
        (TransitionTrace
           ConnStateId
           (ConnectionState peerAddr handle handleError version m))
        (Trace peerAddr handlerTrace),
      Connected peerAddr handle handleError)
-> m (Either
        (TransitionTrace
           ConnStateId
           (ConnectionState peerAddr handle handleError version m))
        (Trace peerAddr handlerTrace),
      Connected peerAddr handle handleError)
forall a b. (a -> b) -> a -> b
$ do
              connState <- 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)
connVar
              case connState of
                ReservedOutboundState {} ->
                  ConnectionManagerError peerAddr
-> STM
     m
     (Either
        (TransitionTrace
           ConnStateId
           (ConnectionState peerAddr handle handleError version m))
        (Trace peerAddr handlerTrace),
      Connected peerAddr handle handleError)
forall (m :: * -> *) e a.
(MonadSTM m, MonadThrow (STM m), Exception e) =>
e -> STM m a
throwSTM
                    ((CallStack -> ConnectionManagerError peerAddr)
-> ConnectionManagerError peerAddr
forall a. (?callStack::CallStack) => (CallStack -> a) -> a
withCallStack (peerAddr -> CallStack -> ConnectionManagerError peerAddr
forall peerAddr.
peerAddr -> CallStack -> ConnectionManagerError peerAddr
ImpossibleState (ConnectionId peerAddr -> peerAddr
forall addr. ConnectionId addr -> addr
remoteAddress ConnectionId peerAddr
connId)))
                UnnegotiatedState Provenance
Outbound ConnectionId peerAddr
_ Async m ()
_ ->
                  ConnectionManagerError (ConnectionId peerAddr)
-> STM
     m
     (Either
        (TransitionTrace
           ConnStateId
           (ConnectionState peerAddr handle handleError version m))
        (Trace peerAddr handlerTrace),
      Connected peerAddr handle handleError)
forall (m :: * -> *) e a.
(MonadSTM m, MonadThrow (STM m), Exception e) =>
e -> STM m a
throwSTM
                    ((CallStack -> ConnectionManagerError (ConnectionId peerAddr))
-> ConnectionManagerError (ConnectionId peerAddr)
forall a. (?callStack::CallStack) => (CallStack -> a) -> a
withCallStack (Provenance
-> ConnectionId peerAddr
-> CallStack
-> ConnectionManagerError (ConnectionId peerAddr)
forall peerAddr.
Provenance
-> peerAddr -> CallStack -> ConnectionManagerError peerAddr
ConnectionExists Provenance
provenance ConnectionId peerAddr
connId))

                UnnegotiatedState Provenance
Inbound ConnectionId peerAddr
_ Async m ()
_ ->
                  -- await for connection negotiation
                  STM
  m
  (Either
     (TransitionTrace
        ConnStateId
        (ConnectionState peerAddr handle handleError version m))
     (Trace peerAddr handlerTrace),
   Connected peerAddr handle handleError)
forall a. STM m a
forall (m :: * -> *) a. MonadSTM m => STM m a
retry

                OutboundUniState {} ->
                  ConnectionManagerError (ConnectionId peerAddr)
-> STM
     m
     (Either
        (TransitionTrace
           ConnStateId
           (ConnectionState peerAddr handle handleError version m))
        (Trace peerAddr handlerTrace),
      Connected peerAddr handle handleError)
forall (m :: * -> *) e a.
(MonadSTM m, MonadThrow (STM m), Exception e) =>
e -> STM m a
throwSTM ((CallStack -> ConnectionManagerError (ConnectionId peerAddr))
-> ConnectionManagerError (ConnectionId peerAddr)
forall a. (?callStack::CallStack) => (CallStack -> a) -> a
withCallStack (Provenance
-> ConnectionId peerAddr
-> CallStack
-> ConnectionManagerError (ConnectionId peerAddr)
forall peerAddr.
Provenance
-> peerAddr -> CallStack -> ConnectionManagerError peerAddr
ConnectionExists Provenance
provenance ConnectionId peerAddr
connId))

                OutboundDupState {} ->
                  ConnectionManagerError (ConnectionId peerAddr)
-> STM
     m
     (Either
        (TransitionTrace
           ConnStateId
           (ConnectionState peerAddr handle handleError version m))
        (Trace peerAddr handlerTrace),
      Connected peerAddr handle handleError)
forall (m :: * -> *) e a.
(MonadSTM m, MonadThrow (STM m), Exception e) =>
e -> STM m a
throwSTM ((CallStack -> ConnectionManagerError (ConnectionId peerAddr))
-> ConnectionManagerError (ConnectionId peerAddr)
forall a. (?callStack::CallStack) => (CallStack -> a) -> a
withCallStack (Provenance
-> ConnectionId peerAddr
-> CallStack
-> ConnectionManagerError (ConnectionId peerAddr)
forall peerAddr.
Provenance
-> peerAddr -> CallStack -> ConnectionManagerError peerAddr
ConnectionExists Provenance
provenance ConnectionId peerAddr
connId))

                OutboundIdleState ConnectionId peerAddr
_connId Async m ()
_connThread handle
_handle DataFlow
_dataFlow ->
                  let tr :: AbstractState
tr = MaybeUnknown
  (ConnectionState peerAddr handle handleError version m)
-> AbstractState
forall muxMode peerAddr m a (b :: * -> *).
MaybeUnknown (ConnectionState muxMode peerAddr m a b)
-> AbstractState
State.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
connState) in
                  ConnectionManagerError peerAddr
-> STM
     m
     (Either
        (TransitionTrace
           ConnStateId
           (ConnectionState peerAddr handle handleError version m))
        (Trace peerAddr handlerTrace),
      Connected peerAddr handle handleError)
forall (m :: * -> *) e a.
(MonadSTM m, MonadThrow (STM m), Exception e) =>
e -> STM m a
throwSTM ((CallStack -> ConnectionManagerError peerAddr)
-> ConnectionManagerError peerAddr
forall a. (?callStack::CallStack) => (CallStack -> a) -> a
withCallStack (peerAddr
-> AbstractState -> CallStack -> ConnectionManagerError peerAddr
forall peerAddr.
peerAddr
-> AbstractState -> CallStack -> ConnectionManagerError peerAddr
ForbiddenOperation peerAddr
peerAddr AbstractState
tr))

                InboundIdleState ConnectionId peerAddr
_connId Async m ()
connThread handle
handle dataFlow :: DataFlow
dataFlow@DataFlow
Duplex -> do
                  -- @
                  --   Awake^{Duplex}_{Local} : InboundIdleState Duplex
                  --                          → OutboundState^\tau Duplex
                  -- @
                  -- This transition can happen if there are concurrent
                  -- `includeInboundConnection` and `acquireOutboundConnection`
                  -- calls.
                  let connState' :: ConnectionState peerAddr handle handleError version m
connState' = ConnectionId peerAddr
-> Async m ()
-> handle
-> TimeoutExpired
-> ConnectionState peerAddr handle handleError version m
forall peerAddr handle handleError version (m :: * -> *).
ConnectionId peerAddr
-> Async m ()
-> handle
-> TimeoutExpired
-> ConnectionState peerAddr handle handleError version m
OutboundDupState ConnectionId peerAddr
connId Async m ()
connThread handle
handle TimeoutExpired
Ticking
                  StrictTVar
  m (ConnectionState peerAddr handle handleError version m)
-> ConnectionState peerAddr handle handleError version m
-> STM m ()
forall (m :: * -> *) a.
MonadSTM m =>
StrictTVar m a -> a -> STM m ()
writeTVar StrictTVar
  m (ConnectionState peerAddr handle handleError version m)
connVar ConnectionState peerAddr handle handleError version m
connState'
                  (Either
   (TransitionTrace
      ConnStateId
      (ConnectionState peerAddr handle handleError version m))
   (Trace peerAddr handlerTrace),
 Connected peerAddr handle handleError)
-> STM
     m
     (Either
        (TransitionTrace
           ConnStateId
           (ConnectionState peerAddr handle handleError version m))
        (Trace peerAddr handlerTrace),
      Connected peerAddr handle handleError)
forall a. a -> STM m a
forall (m :: * -> *) a. Monad m => a -> m a
return ( TransitionTrace
  ConnStateId (ConnectionState peerAddr handle handleError version m)
-> Either
     (TransitionTrace
        ConnStateId
        (ConnectionState peerAddr handle handleError version m))
     (Trace peerAddr handlerTrace)
forall a b. a -> Either a b
Left (ConnStateId
-> Transition'
     (MaybeUnknown
        (ConnectionState peerAddr handle handleError version m))
-> TransitionTrace
     ConnStateId (ConnectionState peerAddr handle handleError version m)
forall id state.
id -> Transition' state -> TransitionTrace' id state
TransitionTrace
                                  ConnStateId
connStateId
                                  (ConnectionState peerAddr handle handleError version m
-> ConnectionState peerAddr handle handleError version m
-> Transition'
     (MaybeUnknown
        (ConnectionState peerAddr handle handleError version m))
forall state. state -> state -> Transition state
mkTransition ConnectionState peerAddr handle handleError version m
connState ConnectionState peerAddr handle handleError version m
connState'))
                         , ConnectionId peerAddr
-> DataFlow -> handle -> Connected peerAddr handle handleError
forall peerAddr handle handleError.
ConnectionId peerAddr
-> DataFlow -> handle -> Connected peerAddr handle handleError
Connected ConnectionId peerAddr
connId DataFlow
dataFlow handle
handle
                         )

                InboundIdleState ConnectionId peerAddr
_connId Async m ()
_connThread handle
_handle DataFlow
Unidirectional ->
                  ConnectionManagerError peerAddr
-> STM
     m
     (Either
        (TransitionTrace
           ConnStateId
           (ConnectionState peerAddr handle handleError version m))
        (Trace peerAddr handlerTrace),
      Connected peerAddr handle handleError)
forall (m :: * -> *) e a.
(MonadSTM m, MonadThrow (STM m), Exception e) =>
e -> STM m a
throwSTM
                    ((CallStack -> ConnectionManagerError peerAddr)
-> ConnectionManagerError peerAddr
forall a. (?callStack::CallStack) => (CallStack -> a) -> a
withCallStack (ConnectionId peerAddr
-> CallStack -> ConnectionManagerError peerAddr
forall peerAddr.
ConnectionId peerAddr
-> CallStack -> ConnectionManagerError peerAddr
ForbiddenConnection ConnectionId peerAddr
connId))

                InboundState ConnectionId peerAddr
_connId Async m ()
connThread handle
handle dataFlow :: DataFlow
dataFlow@DataFlow
Duplex -> do
                  -- @
                  --   PromotedToWarm^{Duplex}_{Local} : InboundState Duplex
                  --                                   → DuplexState
                  -- @
                  --
                  -- Note: this is unlikely to observe: @There connId@ only
                  -- appears if an inbound connection is unnegotiated, it is
                  -- more likely to observe the
                  -- @
                  --    InboundIdleState Duplex -> OutboundDupState
                  -- @
                  -- transition.
                  let connState' :: ConnectionState peerAddr handle handleError version m
connState' = ConnectionId peerAddr
-> Async m ()
-> handle
-> ConnectionState peerAddr handle handleError version m
forall peerAddr handle handleError version (m :: * -> *).
ConnectionId peerAddr
-> Async m ()
-> handle
-> ConnectionState peerAddr handle handleError version m
DuplexState ConnectionId peerAddr
connId Async m ()
connThread handle
handle
                  StrictTVar
  m (ConnectionState peerAddr handle handleError version m)
-> ConnectionState peerAddr handle handleError version m
-> STM m ()
forall (m :: * -> *) a.
MonadSTM m =>
StrictTVar m a -> a -> STM m ()
writeTVar StrictTVar
  m (ConnectionState peerAddr handle handleError version m)
connVar ConnectionState peerAddr handle handleError version m
connState'
                  (Either
   (TransitionTrace
      ConnStateId
      (ConnectionState peerAddr handle handleError version m))
   (Trace peerAddr handlerTrace),
 Connected peerAddr handle handleError)
-> STM
     m
     (Either
        (TransitionTrace
           ConnStateId
           (ConnectionState peerAddr handle handleError version m))
        (Trace peerAddr handlerTrace),
      Connected peerAddr handle handleError)
forall a. a -> STM m a
forall (m :: * -> *) a. Monad m => a -> m a
return ( TransitionTrace
  ConnStateId (ConnectionState peerAddr handle handleError version m)
-> Either
     (TransitionTrace
        ConnStateId
        (ConnectionState peerAddr handle handleError version m))
     (Trace peerAddr handlerTrace)
forall a b. a -> Either a b
Left (ConnStateId
-> Transition'
     (MaybeUnknown
        (ConnectionState peerAddr handle handleError version m))
-> TransitionTrace
     ConnStateId (ConnectionState peerAddr handle handleError version m)
forall id state.
id -> Transition' state -> TransitionTrace' id state
TransitionTrace
                                  ConnStateId
connStateId
                                  (ConnectionState peerAddr handle handleError version m
-> ConnectionState peerAddr handle handleError version m
-> Transition'
     (MaybeUnknown
        (ConnectionState peerAddr handle handleError version m))
forall state. state -> state -> Transition state
mkTransition ConnectionState peerAddr handle handleError version m
connState ConnectionState peerAddr handle handleError version m
connState'))
                         , ConnectionId peerAddr
-> DataFlow -> handle -> Connected peerAddr handle handleError
forall peerAddr handle handleError.
ConnectionId peerAddr
-> DataFlow -> handle -> Connected peerAddr handle handleError
Connected ConnectionId peerAddr
connId DataFlow
dataFlow handle
handle
                         )

                InboundState ConnectionId peerAddr
_ Async m ()
_ handle
_ DataFlow
Unidirectional ->
                  ConnectionManagerError peerAddr
-> STM
     m
     (Either
        (TransitionTrace
           ConnStateId
           (ConnectionState peerAddr handle handleError version m))
        (Trace peerAddr handlerTrace),
      Connected peerAddr handle handleError)
forall (m :: * -> *) e a.
(MonadSTM m, MonadThrow (STM m), Exception e) =>
e -> STM m a
throwSTM ((CallStack -> ConnectionManagerError peerAddr)
-> ConnectionManagerError peerAddr
forall a. (?callStack::CallStack) => (CallStack -> a) -> a
withCallStack (ConnectionId peerAddr
-> CallStack -> ConnectionManagerError peerAddr
forall peerAddr.
ConnectionId peerAddr
-> CallStack -> ConnectionManagerError peerAddr
ForbiddenConnection ConnectionId peerAddr
connId))

                DuplexState {} ->
                  ConnectionManagerError (ConnectionId peerAddr)
-> STM
     m
     (Either
        (TransitionTrace
           ConnStateId
           (ConnectionState peerAddr handle handleError version m))
        (Trace peerAddr handlerTrace),
      Connected peerAddr handle handleError)
forall (m :: * -> *) e a.
(MonadSTM m, MonadThrow (STM m), Exception e) =>
e -> STM m a
throwSTM ((CallStack -> ConnectionManagerError (ConnectionId peerAddr))
-> ConnectionManagerError (ConnectionId peerAddr)
forall a. (?callStack::CallStack) => (CallStack -> a) -> a
withCallStack (Provenance
-> ConnectionId peerAddr
-> CallStack
-> ConnectionManagerError (ConnectionId peerAddr)
forall peerAddr.
Provenance
-> peerAddr -> CallStack -> ConnectionManagerError peerAddr
ConnectionExists Provenance
provenance ConnectionId peerAddr
connId))

                TerminatingState ConnectionId peerAddr
_connId Async m ()
_connThread Maybe handleError
handleError ->
                  (Either
   (TransitionTrace
      ConnStateId
      (ConnectionState peerAddr handle handleError version m))
   (Trace peerAddr handlerTrace),
 Connected peerAddr handle handleError)
-> STM
     m
     (Either
        (TransitionTrace
           ConnStateId
           (ConnectionState peerAddr handle handleError version m))
        (Trace peerAddr handlerTrace),
      Connected peerAddr handle handleError)
forall a. a -> STM m a
forall (m :: * -> *) a. Monad m => a -> m a
return ( Trace peerAddr handlerTrace
-> Either
     (TransitionTrace
        ConnStateId
        (ConnectionState peerAddr handle handleError version m))
     (Trace peerAddr handlerTrace)
forall a b. b -> Either a b
Right (Provenance -> ConnectionId peerAddr -> Trace peerAddr handlerTrace
forall peerAddr handlerTrace.
Provenance -> ConnectionId peerAddr -> Trace peerAddr handlerTrace
TrTerminatingConnection Provenance
provenance ConnectionId peerAddr
connId)
                         , ConnectionId peerAddr
-> Maybe handleError -> Connected peerAddr handle handleError
forall peerAddr handle handleError.
ConnectionId peerAddr
-> Maybe handleError -> Connected peerAddr handle handleError
Disconnected ConnectionId peerAddr
connId Maybe handleError
handleError
                         )
                TerminatedState Maybe handleError
handleError ->
                  (Either
   (TransitionTrace
      ConnStateId
      (ConnectionState peerAddr handle handleError version m))
   (Trace peerAddr handlerTrace),
 Connected peerAddr handle handleError)
-> STM
     m
     (Either
        (TransitionTrace
           ConnStateId
           (ConnectionState peerAddr handle handleError version m))
        (Trace peerAddr handlerTrace),
      Connected peerAddr handle handleError)
forall a. a -> STM m a
forall (m :: * -> *) a. Monad m => a -> m a
return ( Trace peerAddr handlerTrace
-> Either
     (TransitionTrace
        ConnStateId
        (ConnectionState peerAddr handle handleError version m))
     (Trace peerAddr handlerTrace)
forall a b. b -> Either a b
Right (Provenance -> peerAddr -> Trace peerAddr handlerTrace
forall peerAddr handlerTrace.
Provenance -> peerAddr -> Trace peerAddr handlerTrace
TrTerminatedConnection Provenance
provenance
                                                         (ConnectionId peerAddr -> peerAddr
forall addr. ConnectionId addr -> addr
remoteAddress ConnectionId peerAddr
connId))
                         , ConnectionId peerAddr
-> Maybe handleError -> Connected peerAddr handle handleError
forall peerAddr handle handleError.
ConnectionId peerAddr
-> Maybe handleError -> Connected peerAddr handle handleError
Disconnected ConnectionId peerAddr
connId Maybe handleError
handleError
                         )

            case etr of
              Left TransitionTrace
  ConnStateId (ConnectionState peerAddr handle handleError version m)
tr'  -> Tracer
  m
  (TransitionTrace
     ConnStateId
     (ConnectionState peerAddr handle handleError version m))
-> TransitionTrace
     ConnStateId (ConnectionState peerAddr handle handleError version m)
-> m ()
forall (m :: * -> *) a. Tracer m a -> a -> m ()
traceWith Tracer
  m
  (TransitionTrace
     ConnStateId
     (ConnectionState peerAddr handle handleError version m))
trTracer TransitionTrace
  ConnStateId (ConnectionState peerAddr handle handleError version m)
tr'
              Right Trace peerAddr handlerTrace
tr' -> Tracer m (Trace peerAddr handlerTrace)
-> Trace peerAddr handlerTrace -> m ()
forall (m :: * -> *) a. Tracer m a -> a -> m ()
traceWith Tracer m (Trace peerAddr handlerTrace)
tracer   Trace peerAddr handlerTrace
tr'
            traceCounters stateVar
            return connected

          -- Connection manager has a connection which can be reused.
          Right (Here Connected peerAddr handle handleError
connected) -> do
            StrictTMVar
  m (ConnectionManagerState peerAddr handle handleError version m)
-> m ()
traceCounters StrictTMVar
  m (ConnectionManagerState peerAddr handle handleError version m)
stateVar
            Connected peerAddr handle handleError
-> m (Connected peerAddr handle handleError)
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return Connected peerAddr handle handleError
connected

    terminateOutboundWithErrorOrQuery
        :: ConnectionId peerAddr
        -> State.ConnStateId
        -> StrictTVar m (ConnectionState peerAddr handle handleError version m)
        -> Async m ()
        -> StrictTMVar m (ConnectionManagerState peerAddr handle handleError version m)
        -> MutableConnState peerAddr handle handleError version m
        -> Maybe handleError
        -> m (Connected peerAddr handle handleError)
    terminateOutboundWithErrorOrQuery :: ConnectionId peerAddr
-> ConnStateId
-> StrictTVar
     m (ConnectionState peerAddr handle handleError version m)
-> Async m ()
-> StrictTMVar
     m (ConnectionManagerState peerAddr handle handleError version m)
-> MutableConnState peerAddr handle handleError version m
-> Maybe handleError
-> m (Connected peerAddr handle handleError)
terminateOutboundWithErrorOrQuery ConnectionId peerAddr
connId ConnStateId
connStateId StrictTVar
  m (ConnectionState peerAddr handle handleError version m)
connVar Async m ()
connThread StrictTMVar
  m (ConnectionManagerState peerAddr handle handleError version m)
stateVar MutableConnState peerAddr handle handleError version m
mutableConnState Maybe handleError
handleErrorM = do
        transitions <- STM
  m
  [Transition'
     (MaybeUnknown
        (ConnectionState peerAddr handle handleError version m))]
-> m [Transition'
        (MaybeUnknown
           (ConnectionState peerAddr handle handleError version m))]
forall a. (?callStack::CallStack) => STM m a -> m a
forall (m :: * -> *) a.
(MonadSTM m, ?callStack::CallStack) =>
STM m a -> m a
atomically (STM
   m
   [Transition'
      (MaybeUnknown
         (ConnectionState peerAddr handle handleError version m))]
 -> m [Transition'
         (MaybeUnknown
            (ConnectionState peerAddr handle handleError version m))])
-> STM
     m
     [Transition'
        (MaybeUnknown
           (ConnectionState peerAddr handle handleError version m))]
-> m [Transition'
        (MaybeUnknown
           (ConnectionState peerAddr handle handleError version m))]
forall a b. (a -> b) -> a -> b
$ do
          connState <- 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)
connVar

          let connState' =
                case handleError -> HandleErrorType
classifyHandleError (handleError -> HandleErrorType)
-> Maybe handleError -> Maybe HandleErrorType
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Maybe handleError
handleErrorM of
                  Just HandleErrorType
HandshakeFailure ->
                    ConnectionId peerAddr
-> Async m ()
-> Maybe handleError
-> ConnectionState peerAddr handle handleError version m
forall peerAddr handle handleError version (m :: * -> *).
ConnectionId peerAddr
-> Async m ()
-> Maybe handleError
-> ConnectionState peerAddr handle handleError version m
TerminatingState ConnectionId peerAddr
connId Async m ()
connThread
                                     Maybe handleError
handleErrorM
                  Just HandleErrorType
HandshakeProtocolViolation ->
                    Maybe handleError
-> ConnectionState peerAddr handle handleError version m
forall peerAddr handle handleError version (m :: * -> *).
Maybe handleError
-> ConnectionState peerAddr handle handleError version m
TerminatedState Maybe handleError
handleErrorM
                  -- On outbound query, connection is terminated.
                  Maybe HandleErrorType
Nothing ->
                    Maybe handleError
-> ConnectionState peerAddr handle handleError version m
forall peerAddr handle handleError version (m :: * -> *).
Maybe handleError
-> ConnectionState peerAddr handle handleError version m
TerminatedState Maybe handleError
handleErrorM
              transition = ConnectionState peerAddr handle handleError version m
-> ConnectionState peerAddr handle handleError version m
-> Transition'
     (MaybeUnknown
        (ConnectionState peerAddr handle handleError version m))
forall state. state -> state -> Transition state
mkTransition ConnectionState peerAddr handle handleError version m
connState ConnectionState peerAddr handle handleError version m
connState'
              absConnState = MaybeUnknown
  (ConnectionState peerAddr handle handleError version m)
-> AbstractState
forall muxMode peerAddr m a (b :: * -> *).
MaybeUnknown (ConnectionState muxMode peerAddr m a b)
-> AbstractState
State.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
connState)
              shouldTransition = AbstractState
absConnState AbstractState -> AbstractState -> Bool
forall a. Eq a => a -> a -> Bool
/= AbstractState
TerminatedSt

          -- 'handleError' might be either a handshake negotiation
          -- a protocol failure (an IO exception, a timeout or
          -- codec failure).  In the first case we should not reset
          -- the connection as this is not a protocol error.
          when shouldTransition $ do
            writeTVar connVar connState'

          updated <-
            modifyTMVarPure
              stateVar
              ( \ConnectionManagerState peerAddr handle handleError version m
state ->
                case ConnectionId peerAddr
-> ConnectionManagerState peerAddr handle handleError version m
-> Maybe (MutableConnState peerAddr handle handleError version m)
forall peerAddr a.
Ord peerAddr =>
ConnectionId peerAddr -> ConnMap peerAddr a -> Maybe a
State.lookup ConnectionId peerAddr
connId ConnectionManagerState peerAddr handle handleError version m
state of
                  Maybe (MutableConnState peerAddr handle handleError version m)
Nothing -> (ConnectionManagerState peerAddr handle handleError version m
state, Bool
False)
                  Just MutableConnState peerAddr handle handleError version m
mutableConnState'  ->
                    if MutableConnState peerAddr handle handleError version m
mutableConnState' MutableConnState peerAddr handle handleError version m
-> MutableConnState peerAddr handle handleError version m -> Bool
forall a. Eq a => a -> a -> Bool
== MutableConnState peerAddr handle handleError version m
mutableConnState
                      then (ConnectionId peerAddr
-> ConnectionManagerState peerAddr handle handleError version m
-> ConnectionManagerState peerAddr handle handleError version m
forall peerAddr a.
Ord peerAddr =>
ConnectionId peerAddr -> ConnMap peerAddr a -> ConnMap peerAddr a
State.delete ConnectionId peerAddr
connId ConnectionManagerState peerAddr handle handleError version m
state, Bool
True)
                      else (ConnectionManagerState peerAddr handle handleError version m
state                    , Bool
False)
              )

          if updated
             then
            -- Key was present in the dictionary (stateVar) and
            -- removed so we trace the removal.
              return $
                if shouldTransition
                   then [ transition
                        , Transition
                           { fromState = Known (TerminatedState Nothing)
                           , toState   = Unknown
                           }
                        ]
                   else [ Transition
                           { fromState = Known (TerminatedState Nothing)
                           , toState   = Unknown
                           }
                        ]
            -- Key was not present in the dictionary (stateVar),
            -- so we do not trace anything as it was already traced upon
            -- deletion.
            --
            -- OR
            --
            -- Key was overwritten in the dictionary (stateVar),
            -- so we do not trace anything as it was already traced upon
            -- overwriting.
             else return [ ]


        traverse_ (traceWith trTracer . TransitionTrace connStateId) transitions
        traceCounters stateVar

        return (Disconnected connId handleErrorM)


    releaseOutboundConnectionImpl
        :: StrictTMVar m
            (ConnectionManagerState peerAddr handle handleError version m)
        -> StrictTVar m StdGen
        -> ConnectionId peerAddr
        -> m (OperationResult AbstractState)
    releaseOutboundConnectionImpl :: StrictTMVar
  m (ConnectionManagerState peerAddr handle handleError version m)
-> StrictTVar m StdGen
-> ConnectionId peerAddr
-> m (OperationResult AbstractState)
releaseOutboundConnectionImpl StrictTMVar
  m (ConnectionManagerState peerAddr handle handleError version m)
stateVar StrictTVar m StdGen
stdGenVar ConnectionId peerAddr
connId = do
      Tracer m (Trace peerAddr handlerTrace)
-> Trace peerAddr handlerTrace -> m ()
forall (m :: * -> *) a. Tracer m a -> a -> m ()
traceWith Tracer m (Trace peerAddr handlerTrace)
tracer (Provenance -> ConnectionId peerAddr -> Trace peerAddr handlerTrace
forall peerAddr handlerTrace.
Provenance -> ConnectionId peerAddr -> Trace peerAddr handlerTrace
TrReleaseConnection Provenance
Outbound ConnectionId peerAddr
connId)
      (transition, mbAssertion)
        <- STM
  m
  (DemoteToColdLocal
     peerAddr handlerTrace handle handleError version m,
   Maybe (Trace peerAddr handlerTrace))
-> m (DemoteToColdLocal
        peerAddr handlerTrace handle handleError version m,
      Maybe (Trace peerAddr handlerTrace))
forall a. (?callStack::CallStack) => STM m a -> m a
forall (m :: * -> *) a.
(MonadSTM m, ?callStack::CallStack) =>
STM m a -> m a
atomically (STM
   m
   (DemoteToColdLocal
      peerAddr handlerTrace handle handleError version m,
    Maybe (Trace peerAddr handlerTrace))
 -> m (DemoteToColdLocal
         peerAddr handlerTrace handle handleError version m,
       Maybe (Trace peerAddr handlerTrace)))
-> STM
     m
     (DemoteToColdLocal
        peerAddr handlerTrace handle handleError version m,
      Maybe (Trace peerAddr handlerTrace))
-> m (DemoteToColdLocal
        peerAddr handlerTrace handle handleError version m,
      Maybe (Trace peerAddr handlerTrace))
forall a b. (a -> b) -> a -> b
$ do
        state <- StrictTMVar
  m (ConnectionManagerState peerAddr handle handleError version m)
-> STM
     m (ConnectionManagerState peerAddr handle handleError version m)
forall (m :: * -> *) a. MonadSTM m => StrictTMVar m a -> STM m a
readTMVar StrictTMVar
  m (ConnectionManagerState peerAddr handle handleError version m)
stateVar
        case State.lookup connId state of
          -- if the connection errored, it will remove itself from the state.
          -- Calling 'releaseOutboundConnection' is a no-op in this case.
          Maybe (MutableConnState peerAddr handle handleError version m)
Nothing -> (DemoteToColdLocal
   peerAddr handlerTrace handle handleError version m,
 Maybe (Trace peerAddr handlerTrace))
-> STM
     m
     (DemoteToColdLocal
        peerAddr handlerTrace handle handleError version m,
      Maybe (Trace peerAddr handlerTrace))
forall a. a -> STM m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ( Maybe
  (TransitionTrace
     ConnStateId
     (ConnectionState peerAddr handle handleError version m))
-> AbstractState
-> DemoteToColdLocal
     peerAddr handlerTrace handle handleError version m
forall peerAddr handlerTrace handle handleError version
       (m :: * -> *).
Maybe
  (TransitionTrace
     ConnStateId
     (ConnectionState peerAddr handle handleError version m))
-> AbstractState
-> DemoteToColdLocal
     peerAddr handlerTrace handle handleError version m
DemoteToColdLocalNoop Maybe
  (TransitionTrace
     ConnStateId
     (ConnectionState peerAddr handle handleError version m))
forall a. Maybe a
Nothing AbstractState
UnknownConnectionSt
                          , Maybe (Trace peerAddr handlerTrace)
forall a. Maybe a
Nothing)

          Just MutableConnState { StrictTVar
  m (ConnectionState peerAddr handle handleError version m)
connVar :: 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)
connVar, ConnStateId
connStateId :: forall peerAddr handle handleError version (m :: * -> *).
MutableConnState peerAddr handle handleError version m
-> ConnStateId
connStateId :: ConnStateId
connStateId } -> do
            connState <- 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)
connVar
            let st = MaybeUnknown
  (ConnectionState peerAddr handle handleError version m)
-> AbstractState
forall muxMode peerAddr m a (b :: * -> *).
MaybeUnknown (ConnectionState muxMode peerAddr m a b)
-> AbstractState
State.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
connState)
            case connState of
              -- In any of the following three states releaseing is not
              -- supported.  'acquireOutboundConnection' is a synchronous
              -- operation which returns only once the connection is
              -- negotiated.
              ConnectionState peerAddr handle handleError version m
ReservedOutboundState ->
                (DemoteToColdLocal
   peerAddr handlerTrace handle handleError version m,
 Maybe (Trace peerAddr handlerTrace))
-> STM
     m
     (DemoteToColdLocal
        peerAddr handlerTrace handle handleError version m,
      Maybe (Trace peerAddr handlerTrace))
forall a. a -> STM m a
forall (m :: * -> *) a. Monad m => a -> m a
return
                  ( Trace peerAddr handlerTrace
-> AbstractState
-> DemoteToColdLocal
     peerAddr handlerTrace handle handleError version m
forall peerAddr handlerTrace handle handleError version
       (m :: * -> *).
Trace peerAddr handlerTrace
-> AbstractState
-> DemoteToColdLocal
     peerAddr handlerTrace handle handleError version m
DemoteToColdLocalError
                     (peerAddr -> AbstractState -> Trace peerAddr handlerTrace
forall peerAddr handlerTrace.
peerAddr -> AbstractState -> Trace peerAddr handlerTrace
TrForbiddenOperation (ConnectionId peerAddr -> peerAddr
forall addr. ConnectionId addr -> addr
remoteAddress ConnectionId peerAddr
connId) AbstractState
st)
                     AbstractState
st
                  , Maybe (Trace peerAddr handlerTrace)
forall a. Maybe a
Nothing
                  )

              UnnegotiatedState {} ->
                (DemoteToColdLocal
   peerAddr handlerTrace handle handleError version m,
 Maybe (Trace peerAddr handlerTrace))
-> STM
     m
     (DemoteToColdLocal
        peerAddr handlerTrace handle handleError version m,
      Maybe (Trace peerAddr handlerTrace))
forall a. a -> STM m a
forall (m :: * -> *) a. Monad m => a -> m a
return
                  ( Trace peerAddr handlerTrace
-> AbstractState
-> DemoteToColdLocal
     peerAddr handlerTrace handle handleError version m
forall peerAddr handlerTrace handle handleError version
       (m :: * -> *).
Trace peerAddr handlerTrace
-> AbstractState
-> DemoteToColdLocal
     peerAddr handlerTrace handle handleError version m
DemoteToColdLocalError
                     (peerAddr -> AbstractState -> Trace peerAddr handlerTrace
forall peerAddr handlerTrace.
peerAddr -> AbstractState -> Trace peerAddr handlerTrace
TrForbiddenOperation (ConnectionId peerAddr -> peerAddr
forall addr. ConnectionId addr -> addr
remoteAddress ConnectionId peerAddr
connId) AbstractState
st)
                     AbstractState
st
                  , Maybe (Trace peerAddr handlerTrace)
forall a. Maybe a
Nothing
                  )

              OutboundUniState ConnectionId peerAddr
_connId Async m ()
connThread handle
handle -> do
                -- @
                --   DemotedToCold^{Unidirectional}_{Local}
                --     : OutboundState Unidirectional
                --     → OutboundIdleState Unidirectional
                -- @
                let connState' :: ConnectionState peerAddr handle handleError version m
connState' = ConnectionId peerAddr
-> Async m ()
-> handle
-> DataFlow
-> ConnectionState peerAddr handle handleError version m
forall peerAddr handle handleError version (m :: * -> *).
ConnectionId peerAddr
-> Async m ()
-> handle
-> DataFlow
-> ConnectionState peerAddr handle handleError version m
OutboundIdleState ConnectionId peerAddr
connId Async m ()
connThread handle
handle
                                                   DataFlow
Unidirectional
                StrictTVar
  m (ConnectionState peerAddr handle handleError version m)
-> ConnectionState peerAddr handle handleError version m
-> STM m ()
forall (m :: * -> *) a.
MonadSTM m =>
StrictTVar m a -> a -> STM m ()
writeTVar StrictTVar
  m (ConnectionState peerAddr handle handleError version m)
connVar ConnectionState peerAddr handle handleError version m
connState'
                (DemoteToColdLocal
   peerAddr handlerTrace handle handleError version m,
 Maybe (Trace peerAddr handlerTrace))
-> STM
     m
     (DemoteToColdLocal
        peerAddr handlerTrace handle handleError version m,
      Maybe (Trace peerAddr handlerTrace))
forall a. a -> STM m a
forall (m :: * -> *) a. Monad m => a -> m a
return ( ConnectionId peerAddr
-> Async m ()
-> StrictTVar
     m (ConnectionState peerAddr handle handleError version m)
-> TransitionTrace
     ConnStateId (ConnectionState peerAddr handle handleError version m)
-> DemoteToColdLocal
     peerAddr handlerTrace handle handleError version m
forall peerAddr handlerTrace handle handleError version
       (m :: * -> *).
ConnectionId peerAddr
-> Async m ()
-> StrictTVar
     m (ConnectionState peerAddr handle handleError version m)
-> TransitionTrace
     ConnStateId (ConnectionState peerAddr handle handleError version m)
-> DemoteToColdLocal
     peerAddr handlerTrace handle handleError version m
DemotedToColdLocal ConnectionId peerAddr
connId Async m ()
connThread StrictTVar
  m (ConnectionState peerAddr handle handleError version m)
connVar
                          (ConnStateId
-> Transition'
     (MaybeUnknown
        (ConnectionState peerAddr handle handleError version m))
-> TransitionTrace
     ConnStateId (ConnectionState peerAddr handle handleError version m)
forall id state.
id -> Transition' state -> TransitionTrace' id state
TransitionTrace ConnStateId
connStateId (Transition'
   (MaybeUnknown
      (ConnectionState peerAddr handle handleError version m))
 -> TransitionTrace
      ConnStateId
      (ConnectionState peerAddr handle handleError version m))
-> Transition'
     (MaybeUnknown
        (ConnectionState peerAddr handle handleError version m))
-> TransitionTrace
     ConnStateId (ConnectionState peerAddr handle handleError version m)
forall a b. (a -> b) -> a -> b
$ ConnectionState peerAddr handle handleError version m
-> ConnectionState peerAddr handle handleError version m
-> Transition'
     (MaybeUnknown
        (ConnectionState peerAddr handle handleError version m))
forall state. state -> state -> Transition state
mkTransition ConnectionState peerAddr handle handleError version m
connState ConnectionState peerAddr handle handleError version m
connState')
                       , Maybe (Trace peerAddr handlerTrace)
forall a. Maybe a
Nothing
                       )

              OutboundDupState ConnectionId peerAddr
_connId Async m ()
connThread handle
handle TimeoutExpired
Expired -> do
                -- @
                --   DemotedToCold^{Duplex}_{Local}
                --     : OutboundState Duplex
                --     → OutboundIdleState^\tau
                -- @
                let connState' :: ConnectionState peerAddr handle handleError version m
connState' = ConnectionId peerAddr
-> Async m ()
-> handle
-> DataFlow
-> ConnectionState peerAddr handle handleError version m
forall peerAddr handle handleError version (m :: * -> *).
ConnectionId peerAddr
-> Async m ()
-> handle
-> DataFlow
-> ConnectionState peerAddr handle handleError version m
OutboundIdleState ConnectionId peerAddr
connId Async m ()
connThread handle
handle
                                                   DataFlow
Duplex
                StrictTVar
  m (ConnectionState peerAddr handle handleError version m)
-> ConnectionState peerAddr handle handleError version m
-> STM m ()
forall (m :: * -> *) a.
MonadSTM m =>
StrictTVar m a -> a -> STM m ()
writeTVar StrictTVar
  m (ConnectionState peerAddr handle handleError version m)
connVar ConnectionState peerAddr handle handleError version m
connState'
                (DemoteToColdLocal
   peerAddr handlerTrace handle handleError version m,
 Maybe (Trace peerAddr handlerTrace))
-> STM
     m
     (DemoteToColdLocal
        peerAddr handlerTrace handle handleError version m,
      Maybe (Trace peerAddr handlerTrace))
forall a. a -> STM m a
forall (m :: * -> *) a. Monad m => a -> m a
return ( ConnectionId peerAddr
-> Async m ()
-> StrictTVar
     m (ConnectionState peerAddr handle handleError version m)
-> TransitionTrace
     ConnStateId (ConnectionState peerAddr handle handleError version m)
-> DemoteToColdLocal
     peerAddr handlerTrace handle handleError version m
forall peerAddr handlerTrace handle handleError version
       (m :: * -> *).
ConnectionId peerAddr
-> Async m ()
-> StrictTVar
     m (ConnectionState peerAddr handle handleError version m)
-> TransitionTrace
     ConnStateId (ConnectionState peerAddr handle handleError version m)
-> DemoteToColdLocal
     peerAddr handlerTrace handle handleError version m
DemotedToColdLocal ConnectionId peerAddr
connId Async m ()
connThread StrictTVar
  m (ConnectionState peerAddr handle handleError version m)
connVar
                          (ConnStateId
-> Transition'
     (MaybeUnknown
        (ConnectionState peerAddr handle handleError version m))
-> TransitionTrace
     ConnStateId (ConnectionState peerAddr handle handleError version m)
forall id state.
id -> Transition' state -> TransitionTrace' id state
TransitionTrace ConnStateId
connStateId (Transition'
   (MaybeUnknown
      (ConnectionState peerAddr handle handleError version m))
 -> TransitionTrace
      ConnStateId
      (ConnectionState peerAddr handle handleError version m))
-> Transition'
     (MaybeUnknown
        (ConnectionState peerAddr handle handleError version m))
-> TransitionTrace
     ConnStateId (ConnectionState peerAddr handle handleError version m)
forall a b. (a -> b) -> a -> b
$ ConnectionState peerAddr handle handleError version m
-> ConnectionState peerAddr handle handleError version m
-> Transition'
     (MaybeUnknown
        (ConnectionState peerAddr handle handleError version m))
forall state. state -> state -> Transition state
mkTransition ConnectionState peerAddr handle handleError version m
connState ConnectionState peerAddr handle handleError version m
connState')
                       , Maybe (Trace peerAddr handlerTrace)
forall a. Maybe a
Nothing
                       )

              OutboundDupState ConnectionId peerAddr
_connId Async m ()
connThread handle
handle TimeoutExpired
Ticking -> do
                let connState' :: ConnectionState peerAddr handle handleError version m
connState' = ConnectionId peerAddr
-> Async m ()
-> handle
-> DataFlow
-> ConnectionState peerAddr handle handleError version m
forall peerAddr handle handleError version (m :: * -> *).
ConnectionId peerAddr
-> Async m ()
-> handle
-> DataFlow
-> ConnectionState peerAddr handle handleError version m
InboundIdleState ConnectionId peerAddr
connId Async m ()
connThread handle
handle DataFlow
Duplex
                    tr :: TransitionTrace
  ConnStateId (ConnectionState peerAddr handle handleError version m)
tr = ConnStateId
-> Transition'
     (MaybeUnknown
        (ConnectionState peerAddr handle handleError version m))
-> TransitionTrace
     ConnStateId (ConnectionState peerAddr handle handleError version m)
forall id state.
id -> Transition' state -> TransitionTrace' id state
TransitionTrace ConnStateId
connStateId (Transition'
   (MaybeUnknown
      (ConnectionState peerAddr handle handleError version m))
 -> TransitionTrace
      ConnStateId
      (ConnectionState peerAddr handle handleError version m))
-> Transition'
     (MaybeUnknown
        (ConnectionState peerAddr handle handleError version m))
-> TransitionTrace
     ConnStateId (ConnectionState peerAddr handle handleError version m)
forall a b. (a -> b) -> a -> b
$ ConnectionState peerAddr handle handleError version m
-> ConnectionState peerAddr handle handleError version m
-> Transition'
     (MaybeUnknown
        (ConnectionState peerAddr handle handleError version m))
forall state. state -> state -> Transition state
mkTransition ConnectionState peerAddr handle handleError version m
connState ConnectionState peerAddr handle handleError version m
connState'

                numberOfConns <- ConnectionManagerState peerAddr handle handleError version m
-> STM m Int
countIncomingConnections ConnectionManagerState peerAddr handle handleError version m
state

                -- use 'numberOfConns + 1' because we want to know if we
                -- actually let this connection evolve or if we need to make
                -- room for it by pruning.  This is because
                -- 'countIncomingConnections' does not count 'OutboundDupState'
                -- as an inbound connection, but does so for 'InboundIdleState'.
                let numberToPrune =
                      Int
numberOfConns Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1
                      Int -> Int -> Int
forall a. Num a => a -> a -> a
- Word32 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral
                          (AcceptedConnectionsLimit -> Word32
acceptedConnectionsHardLimit AcceptedConnectionsLimit
connectionsLimits)
                if numberToPrune > 0
                then do
                  (_, prune)
                    <- mkPruneAction connId numberToPrune state connState' connVar stdGenVar connThread
                  return
                    ( PruneConnections prune (Left connState)
                    , Nothing
                    )

                else do
                  -- @
                  --   DemotedToCold^{Duplex}_{Local}
                  --     : OutboundState^\tau Duplex
                  --     → InboundIdleState^\tau Duplex
                  -- @
                  -- does not require to perform any additional io action (we
                  -- already updated 'connVar').
                  writeTVar connVar connState'
                  return ( DemoteToColdLocalNoop (Just tr) st
                         , Nothing
                         )

              OutboundIdleState ConnectionId peerAddr
_connId Async m ()
_connThread handle
_handleError DataFlow
_dataFlow ->
                (DemoteToColdLocal
   peerAddr handlerTrace handle handleError version m,
 Maybe (Trace peerAddr handlerTrace))
-> STM
     m
     (DemoteToColdLocal
        peerAddr handlerTrace handle handleError version m,
      Maybe (Trace peerAddr handlerTrace))
forall a. a -> STM m a
forall (m :: * -> *) a. Monad m => a -> m a
return ( Maybe
  (TransitionTrace
     ConnStateId
     (ConnectionState peerAddr handle handleError version m))
-> AbstractState
-> DemoteToColdLocal
     peerAddr handlerTrace handle handleError version m
forall peerAddr handlerTrace handle handleError version
       (m :: * -> *).
Maybe
  (TransitionTrace
     ConnStateId
     (ConnectionState peerAddr handle handleError version m))
-> AbstractState
-> DemoteToColdLocal
     peerAddr handlerTrace handle handleError version m
DemoteToColdLocalNoop Maybe
  (TransitionTrace
     ConnStateId
     (ConnectionState peerAddr handle handleError version m))
forall a. Maybe a
Nothing AbstractState
st
                       , Maybe (Trace peerAddr handlerTrace)
forall a. Maybe a
Nothing
                       )

              -- TODO: This assertion is benign and also hit rarely (once per
              -- 100_000 simulations)
              InboundIdleState ConnectionId peerAddr
_connId Async m ()
_connThread handle
_handle DataFlow
_dataFlow ->
                -- assert (dataFlow == Duplex) $
                (DemoteToColdLocal
   peerAddr handlerTrace handle handleError version m,
 Maybe (Trace peerAddr handlerTrace))
-> STM
     m
     (DemoteToColdLocal
        peerAddr handlerTrace handle handleError version m,
      Maybe (Trace peerAddr handlerTrace))
forall a. a -> STM m a
forall (m :: * -> *) a. Monad m => a -> m a
return ( Maybe
  (TransitionTrace
     ConnStateId
     (ConnectionState peerAddr handle handleError version m))
-> AbstractState
-> DemoteToColdLocal
     peerAddr handlerTrace handle handleError version m
forall peerAddr handlerTrace handle handleError version
       (m :: * -> *).
Maybe
  (TransitionTrace
     ConnStateId
     (ConnectionState peerAddr handle handleError version m))
-> AbstractState
-> DemoteToColdLocal
     peerAddr handlerTrace handle handleError version m
DemoteToColdLocalNoop Maybe
  (TransitionTrace
     ConnStateId
     (ConnectionState peerAddr handle handleError version m))
forall a. Maybe a
Nothing AbstractState
st
                       , Maybe (Trace peerAddr handlerTrace)
forall a. Maybe a
Nothing
                       )
              InboundState ConnectionId peerAddr
_connId Async m ()
_connThread handle
_handle DataFlow
dataFlow -> do
                let mbAssertion :: Maybe (Trace peerAddr handlerTrace)
mbAssertion =
                      if DataFlow
dataFlow DataFlow -> DataFlow -> Bool
forall a. Eq a => a -> a -> Bool
== DataFlow
Duplex
                         then Maybe (Trace peerAddr handlerTrace)
forall a. Maybe a
Nothing
                         else Trace peerAddr handlerTrace -> Maybe (Trace peerAddr handlerTrace)
forall a. a -> Maybe a
Just (AssertionLocation peerAddr -> Trace peerAddr handlerTrace
forall peerAddr handlerTrace.
AssertionLocation peerAddr -> Trace peerAddr handlerTrace
TrUnexpectedlyFalseAssertion
                                      (Maybe (ConnectionId peerAddr)
-> AbstractState -> AssertionLocation peerAddr
forall peerAddr.
Maybe (ConnectionId peerAddr)
-> AbstractState -> AssertionLocation peerAddr
ReleaseOutboundConnection
                                        (ConnectionId peerAddr -> Maybe (ConnectionId peerAddr)
forall a. a -> Maybe a
Just ConnectionId peerAddr
connId)
                                        AbstractState
st)
                                   )
                (DemoteToColdLocal
   peerAddr handlerTrace handle handleError version m,
 Maybe (Trace peerAddr handlerTrace))
-> STM
     m
     (DemoteToColdLocal
        peerAddr handlerTrace handle handleError version m,
      Maybe (Trace peerAddr handlerTrace))
forall a. a -> STM m a
forall (m :: * -> *) a. Monad m => a -> m a
return
                  ( Trace peerAddr handlerTrace
-> AbstractState
-> DemoteToColdLocal
     peerAddr handlerTrace handle handleError version m
forall peerAddr handlerTrace handle handleError version
       (m :: * -> *).
Trace peerAddr handlerTrace
-> AbstractState
-> DemoteToColdLocal
     peerAddr handlerTrace handle handleError version m
DemoteToColdLocalError
                     (peerAddr -> AbstractState -> Trace peerAddr handlerTrace
forall peerAddr handlerTrace.
peerAddr -> AbstractState -> Trace peerAddr handlerTrace
TrForbiddenOperation (ConnectionId peerAddr -> peerAddr
forall addr. ConnectionId addr -> addr
remoteAddress ConnectionId peerAddr
connId) AbstractState
st)
                     AbstractState
st
                  , Maybe (Trace peerAddr handlerTrace)
mbAssertion
                  )

              DuplexState ConnectionId peerAddr
_connId Async m ()
connThread handle
handle -> do
                -- @
                --   DemotedToCold^{Duplex}_{Local} : DuplexState
                --                                  → InboundState Duplex
                -- @
                --
                let connState' :: ConnectionState peerAddr handle handleError version m
connState' = ConnectionId peerAddr
-> Async m ()
-> handle
-> DataFlow
-> ConnectionState peerAddr handle handleError version m
forall peerAddr handle handleError version (m :: * -> *).
ConnectionId peerAddr
-> Async m ()
-> handle
-> DataFlow
-> ConnectionState peerAddr handle handleError version m
InboundState ConnectionId peerAddr
connId Async m ()
connThread handle
handle DataFlow
Duplex
                    tr :: TransitionTrace
  ConnStateId (ConnectionState peerAddr handle handleError version m)
tr = ConnStateId
-> Transition'
     (MaybeUnknown
        (ConnectionState peerAddr handle handleError version m))
-> TransitionTrace
     ConnStateId (ConnectionState peerAddr handle handleError version m)
forall id state.
id -> Transition' state -> TransitionTrace' id state
TransitionTrace ConnStateId
connStateId (Transition'
   (MaybeUnknown
      (ConnectionState peerAddr handle handleError version m))
 -> TransitionTrace
      ConnStateId
      (ConnectionState peerAddr handle handleError version m))
-> Transition'
     (MaybeUnknown
        (ConnectionState peerAddr handle handleError version m))
-> TransitionTrace
     ConnStateId (ConnectionState peerAddr handle handleError version m)
forall a b. (a -> b) -> a -> b
$ ConnectionState peerAddr handle handleError version m
-> ConnectionState peerAddr handle handleError version m
-> Transition'
     (MaybeUnknown
        (ConnectionState peerAddr handle handleError version m))
forall state. state -> state -> Transition state
mkTransition ConnectionState peerAddr handle handleError version m
connState ConnectionState peerAddr handle handleError version m
connState'

                -- @
                -- DemotedToCold^{Duplex}_{Local} : DuplexState
                --                                → InboundState Duplex
                -- @
                -- does not require to perform any additional io action (we
                -- already updated 'connVar').
                StrictTVar
  m (ConnectionState peerAddr handle handleError version m)
-> ConnectionState peerAddr handle handleError version m
-> STM m ()
forall (m :: * -> *) a.
MonadSTM m =>
StrictTVar m a -> a -> STM m ()
writeTVar StrictTVar
  m (ConnectionState peerAddr handle handleError version m)
connVar ConnectionState peerAddr handle handleError version m
connState'
                (DemoteToColdLocal
   peerAddr handlerTrace handle handleError version m,
 Maybe (Trace peerAddr handlerTrace))
-> STM
     m
     (DemoteToColdLocal
        peerAddr handlerTrace handle handleError version m,
      Maybe (Trace peerAddr handlerTrace))
forall a. a -> STM m a
forall (m :: * -> *) a. Monad m => a -> m a
return ( Maybe
  (TransitionTrace
     ConnStateId
     (ConnectionState peerAddr handle handleError version m))
-> AbstractState
-> DemoteToColdLocal
     peerAddr handlerTrace handle handleError version m
forall peerAddr handlerTrace handle handleError version
       (m :: * -> *).
Maybe
  (TransitionTrace
     ConnStateId
     (ConnectionState peerAddr handle handleError version m))
-> AbstractState
-> DemoteToColdLocal
     peerAddr handlerTrace handle handleError version m
DemoteToColdLocalNoop (TransitionTrace
  ConnStateId (ConnectionState peerAddr handle handleError version m)
-> Maybe
     (TransitionTrace
        ConnStateId
        (ConnectionState peerAddr handle handleError version m))
forall a. a -> Maybe a
Just TransitionTrace
  ConnStateId (ConnectionState peerAddr handle handleError version m)
tr) AbstractState
st
                       , Maybe (Trace peerAddr handlerTrace)
forall a. Maybe a
Nothing
                       )

              TerminatingState ConnectionId peerAddr
_connId Async m ()
_connThread Maybe handleError
_handleError ->
                (DemoteToColdLocal
   peerAddr handlerTrace handle handleError version m,
 Maybe (Trace peerAddr handlerTrace))
-> STM
     m
     (DemoteToColdLocal
        peerAddr handlerTrace handle handleError version m,
      Maybe (Trace peerAddr handlerTrace))
forall a. a -> STM m a
forall (m :: * -> *) a. Monad m => a -> m a
return (Maybe
  (TransitionTrace
     ConnStateId
     (ConnectionState peerAddr handle handleError version m))
-> AbstractState
-> DemoteToColdLocal
     peerAddr handlerTrace handle handleError version m
forall peerAddr handlerTrace handle handleError version
       (m :: * -> *).
Maybe
  (TransitionTrace
     ConnStateId
     (ConnectionState peerAddr handle handleError version m))
-> AbstractState
-> DemoteToColdLocal
     peerAddr handlerTrace handle handleError version m
DemoteToColdLocalNoop Maybe
  (TransitionTrace
     ConnStateId
     (ConnectionState peerAddr handle handleError version m))
forall a. Maybe a
Nothing AbstractState
st
                       , Maybe (Trace peerAddr handlerTrace)
forall a. Maybe a
Nothing
                       )
              TerminatedState Maybe handleError
_handleError ->
                (DemoteToColdLocal
   peerAddr handlerTrace handle handleError version m,
 Maybe (Trace peerAddr handlerTrace))
-> STM
     m
     (DemoteToColdLocal
        peerAddr handlerTrace handle handleError version m,
      Maybe (Trace peerAddr handlerTrace))
forall a. a -> STM m a
forall (m :: * -> *) a. Monad m => a -> m a
return ( Maybe
  (TransitionTrace
     ConnStateId
     (ConnectionState peerAddr handle handleError version m))
-> AbstractState
-> DemoteToColdLocal
     peerAddr handlerTrace handle handleError version m
forall peerAddr handlerTrace handle handleError version
       (m :: * -> *).
Maybe
  (TransitionTrace
     ConnStateId
     (ConnectionState peerAddr handle handleError version m))
-> AbstractState
-> DemoteToColdLocal
     peerAddr handlerTrace handle handleError version m
DemoteToColdLocalNoop Maybe
  (TransitionTrace
     ConnStateId
     (ConnectionState peerAddr handle handleError version m))
forall a. Maybe a
Nothing AbstractState
st
                       , Maybe (Trace peerAddr handlerTrace)
forall a. Maybe a
Nothing
                       )

      whenJust mbAssertion $ \Trace peerAddr handlerTrace
tr' -> do
        Tracer m (Trace peerAddr handlerTrace)
-> Trace peerAddr handlerTrace -> m ()
forall (m :: * -> *) a. Tracer m a -> a -> m ()
traceWith Tracer m (Trace peerAddr handlerTrace)
tracer Trace peerAddr handlerTrace
tr'
        _ <- (Any -> Any) -> m (Any -> Any)
forall a. a -> m a
forall (m :: * -> *) a. MonadEvaluate m => a -> m a
evaluate (Bool -> Any -> Any
forall a. (?callStack::CallStack) => Bool -> a -> a
assert Bool
False)
        pure ()

      case transition of
        DemotedToColdLocal ConnectionId peerAddr
_connId Async m ()
connThread StrictTVar
  m (ConnectionState peerAddr handle handleError version m)
connVar
                           tr :: TransitionTrace
  ConnStateId (ConnectionState peerAddr handle handleError version m)
tr@TransitionTrace { ttPeerAddr :: forall id state. TransitionTrace' id state -> id
ttPeerAddr = ConnStateId
connStateId } -> do
          Tracer
  m
  (TransitionTrace
     ConnStateId
     (ConnectionState peerAddr handle handleError version m))
-> TransitionTrace
     ConnStateId (ConnectionState peerAddr handle handleError version m)
-> m ()
forall (m :: * -> *) a. Tracer m a -> a -> m ()
traceWith Tracer
  m
  (TransitionTrace
     ConnStateId
     (ConnectionState peerAddr handle handleError version m))
trTracer TransitionTrace
  ConnStateId (ConnectionState peerAddr handle handleError version m)
tr
          StrictTMVar
  m (ConnectionManagerState peerAddr handle handleError version m)
-> m ()
traceCounters StrictTMVar
  m (ConnectionManagerState peerAddr handle handleError version m)
stateVar
          timeoutVar <- DiffTime -> m (TVar m Bool)
forall (m :: * -> *). MonadTimer m => DiffTime -> m (TVar m Bool)
registerDelay DiffTime
outboundIdleTimeout
          r <- atomically $ runFirstToFinish $
               FirstToFinish (do connState <- readTVar connVar
                                 check (case connState of
                                          OutboundIdleState {} -> Bool
False
                                          ConnectionState peerAddr handle handleError version m
_                    -> Bool
True
                                       )
                                 return (Left connState)
                             )
            <> FirstToFinish (do b <- LazySTM.readTVar timeoutVar
                                 check b
                                 Right <$> readTVar connVar
                             )
          case r of
            Right ConnectionState peerAddr handle handleError version m
connState -> do
              let connState' :: ConnectionState peerAddr handle handleError version m
connState' = ConnectionId peerAddr
-> Async m ()
-> Maybe handleError
-> ConnectionState peerAddr handle handleError version m
forall peerAddr handle handleError version (m :: * -> *).
ConnectionId peerAddr
-> Async m ()
-> Maybe handleError
-> ConnectionState peerAddr handle handleError version m
TerminatingState ConnectionId peerAddr
connId Async m ()
connThread Maybe handleError
forall a. Maybe a
Nothing
              STM m () -> m ()
forall a. (?callStack::CallStack) => STM m a -> m a
forall (m :: * -> *) a.
(MonadSTM m, ?callStack::CallStack) =>
STM m a -> m a
atomically (STM m () -> m ()) -> STM m () -> m ()
forall a b. (a -> b) -> a -> b
$ StrictTVar
  m (ConnectionState peerAddr handle handleError version m)
-> ConnectionState peerAddr handle handleError version m
-> STM m ()
forall (m :: * -> *) a.
MonadSTM m =>
StrictTVar m a -> a -> STM m ()
writeTVar StrictTVar
  m (ConnectionState peerAddr handle handleError version m)
connVar ConnectionState peerAddr handle handleError version m
connState'
              Tracer
  m
  (TransitionTrace
     ConnStateId
     (ConnectionState peerAddr handle handleError version m))
-> TransitionTrace
     ConnStateId (ConnectionState peerAddr handle handleError version m)
-> m ()
forall (m :: * -> *) a. Tracer m a -> a -> m ()
traceWith Tracer
  m
  (TransitionTrace
     ConnStateId
     (ConnectionState peerAddr handle handleError version m))
trTracer (ConnStateId
-> Transition'
     (MaybeUnknown
        (ConnectionState peerAddr handle handleError version m))
-> TransitionTrace
     ConnStateId (ConnectionState peerAddr handle handleError version m)
forall id state.
id -> Transition' state -> TransitionTrace' id state
TransitionTrace ConnStateId
connStateId
                                   (ConnectionState peerAddr handle handleError version m
-> ConnectionState peerAddr handle handleError version m
-> Transition'
     (MaybeUnknown
        (ConnectionState peerAddr handle handleError version m))
forall state. state -> state -> Transition state
mkTransition ConnectionState peerAddr handle handleError version m
connState ConnectionState peerAddr handle handleError version m
connState'))
              StrictTMVar
  m (ConnectionManagerState peerAddr handle handleError version m)
-> m ()
traceCounters StrictTMVar
  m (ConnectionManagerState peerAddr handle handleError version m)
stateVar
              -- We rely on the `finally` handler of connection thread to:
              --
              -- - close the socket,
              -- - set the state to 'TerminatedState'
              -- - 'throwTo' avoids blocking until 'timeWaitTimeout' expires.
              ThreadId m -> AsyncCancelled -> m ()
forall e. Exception e => ThreadId m -> e -> m ()
forall (m :: * -> *) e.
(MonadFork m, Exception e) =>
ThreadId m -> e -> m ()
throwTo (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)
                      AsyncCancelled
AsyncCancelled
              OperationResult AbstractState -> m (OperationResult AbstractState)
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (AbstractState -> OperationResult AbstractState
forall a. a -> OperationResult a
OperationSuccess (MaybeUnknown
  (ConnectionState peerAddr handle handleError version m)
-> AbstractState
forall muxMode peerAddr m a (b :: * -> *).
MaybeUnknown (ConnectionState muxMode peerAddr m a b)
-> AbstractState
State.abstractState (MaybeUnknown
   (ConnectionState peerAddr handle handleError version m)
 -> AbstractState)
-> MaybeUnknown
     (ConnectionState peerAddr handle handleError version m)
-> AbstractState
forall a b. (a -> b) -> a -> b
$ 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
connState'))

            Left ConnectionState peerAddr handle handleError version m
connState  | ConnectionState peerAddr handle handleError version m -> Bool
forall peerAddr handle handleError version (m :: * -> *).
ConnectionState peerAddr handle handleError version m -> Bool
State.connectionTerminated ConnectionState peerAddr handle handleError version m
connState
                           ->
              OperationResult AbstractState -> m (OperationResult AbstractState)
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (AbstractState -> OperationResult AbstractState
forall a. a -> OperationResult a
OperationSuccess (MaybeUnknown
  (ConnectionState peerAddr handle handleError version m)
-> AbstractState
forall muxMode peerAddr m a (b :: * -> *).
MaybeUnknown (ConnectionState muxMode peerAddr m a b)
-> AbstractState
State.abstractState (MaybeUnknown
   (ConnectionState peerAddr handle handleError version m)
 -> AbstractState)
-> MaybeUnknown
     (ConnectionState peerAddr handle handleError version m)
-> AbstractState
forall a b. (a -> b) -> a -> b
$ 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
connState))
            Left ConnectionState peerAddr handle handleError version m
connState ->
              OperationResult AbstractState -> m (OperationResult AbstractState)
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (AbstractState -> OperationResult AbstractState
forall a. AbstractState -> OperationResult a
UnsupportedState (MaybeUnknown
  (ConnectionState peerAddr handle handleError version m)
-> AbstractState
forall muxMode peerAddr m a (b :: * -> *).
MaybeUnknown (ConnectionState muxMode peerAddr m a b)
-> AbstractState
State.abstractState (MaybeUnknown
   (ConnectionState peerAddr handle handleError version m)
 -> AbstractState)
-> MaybeUnknown
     (ConnectionState peerAddr handle handleError version m)
-> AbstractState
forall a b. (a -> b) -> a -> b
$ 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
connState))

        PruneConnections PruneAction m
prune Either
  (ConnectionState peerAddr handle handleError version m)
  (TransitionTrace
     ConnStateId
     (ConnectionState peerAddr handle handleError version m))
eTr -> do
          (TransitionTrace
   ConnStateId (ConnectionState peerAddr handle handleError version m)
 -> m ())
-> Either
     (ConnectionState peerAddr handle handleError version m)
     (TransitionTrace
        ConnStateId
        (ConnectionState peerAddr handle handleError version m))
-> m ()
forall (t :: * -> *) (f :: * -> *) a b.
(Foldable t, Applicative f) =>
(a -> f b) -> t a -> f ()
traverse_ (Tracer
  m
  (TransitionTrace
     ConnStateId
     (ConnectionState peerAddr handle handleError version m))
-> TransitionTrace
     ConnStateId (ConnectionState peerAddr handle handleError version m)
-> m ()
forall (m :: * -> *) a. Tracer m a -> a -> m ()
traceWith Tracer
  m
  (TransitionTrace
     ConnStateId
     (ConnectionState peerAddr handle handleError version m))
trTracer) Either
  (ConnectionState peerAddr handle handleError version m)
  (TransitionTrace
     ConnStateId
     (ConnectionState peerAddr handle handleError version m))
eTr
          PruneAction m -> m ()
forall (m :: * -> *). PruneAction m -> m ()
runPruneAction PruneAction m
prune
          StrictTMVar
  m (ConnectionManagerState peerAddr handle handleError version m)
-> m ()
traceCounters StrictTMVar
  m (ConnectionManagerState peerAddr handle handleError version m)
stateVar
          OperationResult AbstractState -> m (OperationResult AbstractState)
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (AbstractState -> OperationResult AbstractState
forall a. a -> OperationResult a
OperationSuccess (MaybeUnknown
  (ConnectionState peerAddr handle handleError version m)
-> AbstractState
forall muxMode peerAddr m a (b :: * -> *).
MaybeUnknown (ConnectionState muxMode peerAddr m a b)
-> AbstractState
State.abstractState ((ConnectionState peerAddr handle handleError version m
 -> MaybeUnknown
      (ConnectionState peerAddr handle handleError version m))
-> (TransitionTrace
      ConnStateId (ConnectionState peerAddr handle handleError version m)
    -> MaybeUnknown
         (ConnectionState peerAddr handle handleError version m))
-> Either
     (ConnectionState peerAddr handle handleError version m)
     (TransitionTrace
        ConnStateId
        (ConnectionState peerAddr handle handleError version m))
-> MaybeUnknown
     (ConnectionState peerAddr handle handleError version m)
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either ConnectionState peerAddr handle handleError version m
-> MaybeUnknown
     (ConnectionState peerAddr handle handleError version m)
forall state. state -> MaybeUnknown state
Known (Transition'
  (MaybeUnknown
     (ConnectionState peerAddr handle handleError version m))
-> MaybeUnknown
     (ConnectionState peerAddr handle handleError version m)
forall state. Transition' state -> state
fromState (Transition'
   (MaybeUnknown
      (ConnectionState peerAddr handle handleError version m))
 -> MaybeUnknown
      (ConnectionState peerAddr handle handleError version m))
-> (TransitionTrace
      ConnStateId (ConnectionState peerAddr handle handleError version m)
    -> Transition'
         (MaybeUnknown
            (ConnectionState peerAddr handle handleError version m)))
-> TransitionTrace
     ConnStateId (ConnectionState peerAddr handle handleError version m)
-> MaybeUnknown
     (ConnectionState peerAddr handle handleError version m)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. TransitionTrace
  ConnStateId (ConnectionState peerAddr handle handleError version m)
-> Transition'
     (MaybeUnknown
        (ConnectionState peerAddr handle handleError version m))
forall id state. TransitionTrace' id state -> Transition' state
ttTransition) Either
  (ConnectionState peerAddr handle handleError version m)
  (TransitionTrace
     ConnStateId
     (ConnectionState peerAddr handle handleError version m))
eTr)))

        DemoteToColdLocalError Trace peerAddr handlerTrace
trace AbstractState
st -> do
          Tracer m (Trace peerAddr handlerTrace)
-> Trace peerAddr handlerTrace -> m ()
forall (m :: * -> *) a. Tracer m a -> a -> m ()
traceWith Tracer m (Trace peerAddr handlerTrace)
tracer Trace peerAddr handlerTrace
trace
          OperationResult AbstractState -> m (OperationResult AbstractState)
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (AbstractState -> OperationResult AbstractState
forall a. AbstractState -> OperationResult a
UnsupportedState AbstractState
st)

        DemoteToColdLocalNoop Maybe
  (TransitionTrace
     ConnStateId
     (ConnectionState peerAddr handle handleError version m))
tr AbstractState
a -> do
          (TransitionTrace
   ConnStateId (ConnectionState peerAddr handle handleError version m)
 -> m ())
-> Maybe
     (TransitionTrace
        ConnStateId
        (ConnectionState peerAddr handle handleError version m))
-> m ()
forall (t :: * -> *) (f :: * -> *) a b.
(Foldable t, Applicative f) =>
(a -> f b) -> t a -> f ()
traverse_ (Tracer
  m
  (TransitionTrace
     ConnStateId
     (ConnectionState peerAddr handle handleError version m))
-> TransitionTrace
     ConnStateId (ConnectionState peerAddr handle handleError version m)
-> m ()
forall (m :: * -> *) a. Tracer m a -> a -> m ()
traceWith Tracer
  m
  (TransitionTrace
     ConnStateId
     (ConnectionState peerAddr handle handleError version m))
trTracer) Maybe
  (TransitionTrace
     ConnStateId
     (ConnectionState peerAddr handle handleError version m))
tr
          StrictTMVar
  m (ConnectionManagerState peerAddr handle handleError version m)
-> m ()
traceCounters StrictTMVar
  m (ConnectionManagerState peerAddr handle handleError version m)
stateVar
          OperationResult AbstractState -> m (OperationResult AbstractState)
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (AbstractState -> OperationResult AbstractState
forall a. a -> OperationResult a
OperationSuccess AbstractState
a)


    -- Needs to mask the STM action and the tracing for the case of an async
    -- exception falls right between the STM commit and the IO tracing. This
    -- guarantees that the same order of transitions and its trace.
    promotedToWarmRemoteImpl
        :: StrictTMVar m (ConnectionManagerState peerAddr handle handleError version m)
        -> StrictTVar m StdGen
        -> ConnectionId peerAddr
        -> m (OperationResult AbstractState)
    promotedToWarmRemoteImpl :: StrictTMVar
  m (ConnectionManagerState peerAddr handle handleError version m)
-> StrictTVar m StdGen
-> ConnectionId peerAddr
-> m (OperationResult AbstractState)
promotedToWarmRemoteImpl StrictTMVar
  m (ConnectionManagerState peerAddr handle handleError version m)
stateVar StrictTVar m StdGen
stdGenVar ConnectionId peerAddr
connId = m (OperationResult AbstractState)
-> m (OperationResult AbstractState)
forall a. m a -> m a
forall (m :: * -> *) a. MonadMask m => m a -> m a
mask_ (m (OperationResult AbstractState)
 -> m (OperationResult AbstractState))
-> m (OperationResult AbstractState)
-> m (OperationResult AbstractState)
forall a b. (a -> b) -> a -> b
$ do
      (result, pruneTr, mbAssertion) <- STM
  m
  (OperationResult
     (TransitionTrace
        ConnStateId
        (ConnectionState peerAddr handle handleError version m)),
   Maybe (PruneAction m), Maybe (Trace peerAddr handlerTrace))
-> m (OperationResult
        (TransitionTrace
           ConnStateId
           (ConnectionState peerAddr handle handleError version m)),
      Maybe (PruneAction m), Maybe (Trace peerAddr handlerTrace))
forall a. (?callStack::CallStack) => STM m a -> m a
forall (m :: * -> *) a.
(MonadSTM m, ?callStack::CallStack) =>
STM m a -> m a
atomically (STM
   m
   (OperationResult
      (TransitionTrace
         ConnStateId
         (ConnectionState peerAddr handle handleError version m)),
    Maybe (PruneAction m), Maybe (Trace peerAddr handlerTrace))
 -> m (OperationResult
         (TransitionTrace
            ConnStateId
            (ConnectionState peerAddr handle handleError version m)),
       Maybe (PruneAction m), Maybe (Trace peerAddr handlerTrace)))
-> STM
     m
     (OperationResult
        (TransitionTrace
           ConnStateId
           (ConnectionState peerAddr handle handleError version m)),
      Maybe (PruneAction m), Maybe (Trace peerAddr handlerTrace))
-> m (OperationResult
        (TransitionTrace
           ConnStateId
           (ConnectionState peerAddr handle handleError version m)),
      Maybe (PruneAction m), Maybe (Trace peerAddr handlerTrace))
forall a b. (a -> b) -> a -> b
$ do
        state <- StrictTMVar
  m (ConnectionManagerState peerAddr handle handleError version m)
-> STM
     m (ConnectionManagerState peerAddr handle handleError version m)
forall (m :: * -> *) a. MonadSTM m => StrictTMVar m a -> STM m a
readTMVar StrictTMVar
  m (ConnectionManagerState peerAddr handle handleError version m)
stateVar
        let mbConnVar = ConnectionId peerAddr
-> ConnectionManagerState peerAddr handle handleError version m
-> Maybe (MutableConnState peerAddr handle handleError version m)
forall peerAddr a.
Ord peerAddr =>
ConnectionId peerAddr -> ConnMap peerAddr a -> Maybe a
State.lookup ConnectionId peerAddr
connId ConnectionManagerState peerAddr handle handleError version m
state
        case mbConnVar of
          Maybe (MutableConnState peerAddr handle handleError version m)
Nothing -> (OperationResult
   (TransitionTrace
      ConnStateId
      (ConnectionState peerAddr handle handleError version m)),
 Maybe (PruneAction m), Maybe (Trace peerAddr handlerTrace))
-> STM
     m
     (OperationResult
        (TransitionTrace
           ConnStateId
           (ConnectionState peerAddr handle handleError version m)),
      Maybe (PruneAction m), Maybe (Trace peerAddr handlerTrace))
forall a. a -> STM m a
forall (m :: * -> *) a. Monad m => a -> m a
return ( AbstractState
-> OperationResult
     (TransitionTrace
        ConnStateId
        (ConnectionState peerAddr handle handleError version m))
forall a. AbstractState -> OperationResult a
UnsupportedState AbstractState
UnknownConnectionSt
                            , Maybe (PruneAction m)
forall a. Maybe a
Nothing
                            , Maybe (Trace peerAddr handlerTrace)
forall a. Maybe a
Nothing
                            )
          Just MutableConnState { StrictTVar
  m (ConnectionState peerAddr handle handleError version m)
connVar :: 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)
connVar, ConnStateId
connStateId :: forall peerAddr handle handleError version (m :: * -> *).
MutableConnState peerAddr handle handleError version m
-> ConnStateId
connStateId :: ConnStateId
connStateId } -> do
            connState <- 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)
connVar
            let st = MaybeUnknown
  (ConnectionState peerAddr handle handleError version m)
-> AbstractState
forall muxMode peerAddr m a (b :: * -> *).
MaybeUnknown (ConnectionState muxMode peerAddr m a b)
-> AbstractState
State.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
connState)
            case connState of
              ReservedOutboundState {} -> do
                (OperationResult
   (TransitionTrace
      ConnStateId
      (ConnectionState peerAddr handle handleError version m)),
 Maybe (PruneAction m), Maybe (Trace peerAddr handlerTrace))
-> STM
     m
     (OperationResult
        (TransitionTrace
           ConnStateId
           (ConnectionState peerAddr handle handleError version m)),
      Maybe (PruneAction m), Maybe (Trace peerAddr handlerTrace))
forall a. a -> STM m a
forall (m :: * -> *) a. Monad m => a -> m a
return ( AbstractState
-> OperationResult
     (TransitionTrace
        ConnStateId
        (ConnectionState peerAddr handle handleError version m))
forall a. AbstractState -> OperationResult a
UnsupportedState AbstractState
st
                       , Maybe (PruneAction m)
forall a. Maybe a
Nothing
                       , Trace peerAddr handlerTrace -> Maybe (Trace peerAddr handlerTrace)
forall a. a -> Maybe a
Just (AssertionLocation peerAddr -> Trace peerAddr handlerTrace
forall peerAddr handlerTrace.
AssertionLocation peerAddr -> Trace peerAddr handlerTrace
TrUnexpectedlyFalseAssertion
                                (Maybe (ConnectionId peerAddr)
-> AbstractState -> AssertionLocation peerAddr
forall peerAddr.
Maybe (ConnectionId peerAddr)
-> AbstractState -> AssertionLocation peerAddr
PromotedToWarmRemote
                                  Maybe (ConnectionId peerAddr)
forall a. Maybe a
Nothing
                                  AbstractState
st)
                              )
                       )
              UnnegotiatedState Provenance
_ ConnectionId peerAddr
_connId Async m ()
_ ->
                (OperationResult
   (TransitionTrace
      ConnStateId
      (ConnectionState peerAddr handle handleError version m)),
 Maybe (PruneAction m), Maybe (Trace peerAddr handlerTrace))
-> STM
     m
     (OperationResult
        (TransitionTrace
           ConnStateId
           (ConnectionState peerAddr handle handleError version m)),
      Maybe (PruneAction m), Maybe (Trace peerAddr handlerTrace))
forall a. a -> STM m a
forall (m :: * -> *) a. Monad m => a -> m a
return ( AbstractState
-> OperationResult
     (TransitionTrace
        ConnStateId
        (ConnectionState peerAddr handle handleError version m))
forall a. AbstractState -> OperationResult a
UnsupportedState AbstractState
st
                       , Maybe (PruneAction m)
forall a. Maybe a
Nothing
                       , Trace peerAddr handlerTrace -> Maybe (Trace peerAddr handlerTrace)
forall a. a -> Maybe a
Just (AssertionLocation peerAddr -> Trace peerAddr handlerTrace
forall peerAddr handlerTrace.
AssertionLocation peerAddr -> Trace peerAddr handlerTrace
TrUnexpectedlyFalseAssertion
                                (Maybe (ConnectionId peerAddr)
-> AbstractState -> AssertionLocation peerAddr
forall peerAddr.
Maybe (ConnectionId peerAddr)
-> AbstractState -> AssertionLocation peerAddr
PromotedToWarmRemote
                                  (ConnectionId peerAddr -> Maybe (ConnectionId peerAddr)
forall a. a -> Maybe a
Just ConnectionId peerAddr
connId)
                                  AbstractState
st)
                              )
                       )
              OutboundUniState ConnectionId peerAddr
_connId Async m ()
_connThread handle
_handle ->
                (OperationResult
   (TransitionTrace
      ConnStateId
      (ConnectionState peerAddr handle handleError version m)),
 Maybe (PruneAction m), Maybe (Trace peerAddr handlerTrace))
-> STM
     m
     (OperationResult
        (TransitionTrace
           ConnStateId
           (ConnectionState peerAddr handle handleError version m)),
      Maybe (PruneAction m), Maybe (Trace peerAddr handlerTrace))
forall a. a -> STM m a
forall (m :: * -> *) a. Monad m => a -> m a
return ( AbstractState
-> OperationResult
     (TransitionTrace
        ConnStateId
        (ConnectionState peerAddr handle handleError version m))
forall a. AbstractState -> OperationResult a
UnsupportedState AbstractState
st
                       , Maybe (PruneAction m)
forall a. Maybe a
Nothing
                       , Trace peerAddr handlerTrace -> Maybe (Trace peerAddr handlerTrace)
forall a. a -> Maybe a
Just (AssertionLocation peerAddr -> Trace peerAddr handlerTrace
forall peerAddr handlerTrace.
AssertionLocation peerAddr -> Trace peerAddr handlerTrace
TrUnexpectedlyFalseAssertion
                                (Maybe (ConnectionId peerAddr)
-> AbstractState -> AssertionLocation peerAddr
forall peerAddr.
Maybe (ConnectionId peerAddr)
-> AbstractState -> AssertionLocation peerAddr
PromotedToWarmRemote
                                  (ConnectionId peerAddr -> Maybe (ConnectionId peerAddr)
forall a. a -> Maybe a
Just ConnectionId peerAddr
connId)
                                  AbstractState
st)
                              )
                       )
              OutboundDupState ConnectionId peerAddr
_connId Async m ()
connThread handle
handle TimeoutExpired
_expired -> do
                -- @
                --   PromotedToWarm^{Duplex}_{Remote} : OutboundState Duplex
                --                                    → DuplexState
                -- @
                --
                -- For connections that reach DuplexState we are not sure if
                -- this was due to a connection that was established due to TCP
                -- simultaneous open or normal connect/accept. If it was
                -- established due to TCP simultaneous open a DuplexState can
                -- make us go above the Server number of connections hard limit,
                -- hence we need to prune connections.
                --
                let connState' :: ConnectionState peerAddr handle handleError version m
connState' = ConnectionId peerAddr
-> Async m ()
-> handle
-> ConnectionState peerAddr handle handleError version m
forall peerAddr handle handleError version (m :: * -> *).
ConnectionId peerAddr
-> Async m ()
-> handle
-> ConnectionState peerAddr handle handleError version m
DuplexState ConnectionId peerAddr
connId Async m ()
connThread handle
handle
                    tr :: Transition'
  (MaybeUnknown
     (ConnectionState peerAddr handle handleError version m))
tr = ConnectionState peerAddr handle handleError version m
-> ConnectionState peerAddr handle handleError version m
-> Transition'
     (MaybeUnknown
        (ConnectionState peerAddr handle handleError version m))
forall state. state -> state -> Transition state
mkTransition ConnectionState peerAddr handle handleError version m
connState ConnectionState peerAddr handle handleError version m
connState'

                numberOfConns <- ConnectionManagerState peerAddr handle handleError version m
-> STM m Int
countIncomingConnections ConnectionManagerState peerAddr handle handleError version m
state

                -- use 'numberOfConns + 1' because we want to know if we
                -- actually let this connection evolve if we need to make
                -- room for them by pruning.
                let numberToPrune =
                      Int
numberOfConns Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1
                      Int -> Int -> Int
forall a. Num a => a -> a -> a
- Word32 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral
                          (AcceptedConnectionsLimit -> Word32
acceptedConnectionsHardLimit AcceptedConnectionsLimit
connectionsLimits)

                -- Are we above the hard limit?
                if numberToPrune > 0
                then do
                  (pruneSelf, prune)
                    <- mkPruneAction connId numberToPrune state connState' connVar stdGenVar connThread

                  when (not pruneSelf)
                    $ writeTVar connVar connState'

                  return
                    ( OperationSuccess (TransitionTrace connStateId tr)
                    , Just prune
                    , Nothing
                    )

                else do
                  writeTVar connVar connState'
                  return ( OperationSuccess (TransitionTrace connStateId tr)
                         , Nothing
                         , Nothing
                         )
              OutboundIdleState ConnectionId peerAddr
_connId Async m ()
connThread handle
handle dataFlow :: DataFlow
dataFlow@DataFlow
Duplex -> do
                -- @
                --   Awake^{Duplex}_{Remote} : OutboundIdleState^\tau Duplex
                --                           → InboundState Duplex
                -- @
                let connState' :: ConnectionState peerAddr handle handleError version m
connState' = ConnectionId peerAddr
-> Async m ()
-> handle
-> DataFlow
-> ConnectionState peerAddr handle handleError version m
forall peerAddr handle handleError version (m :: * -> *).
ConnectionId peerAddr
-> Async m ()
-> handle
-> DataFlow
-> ConnectionState peerAddr handle handleError version m
InboundState ConnectionId peerAddr
connId Async m ()
connThread handle
handle DataFlow
dataFlow
                    tr :: Transition'
  (MaybeUnknown
     (ConnectionState peerAddr handle handleError version m))
tr = ConnectionState peerAddr handle handleError version m
-> ConnectionState peerAddr handle handleError version m
-> Transition'
     (MaybeUnknown
        (ConnectionState peerAddr handle handleError version m))
forall state. state -> state -> Transition state
mkTransition ConnectionState peerAddr handle handleError version m
connState ConnectionState peerAddr handle handleError version m
connState'

                numberOfConns <- ConnectionManagerState peerAddr handle handleError version m
-> STM m Int
countIncomingConnections ConnectionManagerState peerAddr handle handleError version m
state

                -- use 'numberOfConns + 1' because we want to know if we
                -- actually let this connection evolve if we need to make
                -- room for it by pruning.
                let numberToPrune =
                      Int
numberOfConns Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1
                      Int -> Int -> Int
forall a. Num a => a -> a -> a
- Word32 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral
                          (AcceptedConnectionsLimit -> Word32
acceptedConnectionsHardLimit AcceptedConnectionsLimit
connectionsLimits)

                -- Are we above the hard limit?
                if numberToPrune > 0
                then do
                  (pruneSelf, prune)
                    <- mkPruneAction connId numberToPrune state connState' connVar stdGenVar connThread
                  when (not pruneSelf)
                     $ writeTVar connVar connState'

                  return
                    ( OperationSuccess (TransitionTrace connStateId $ mkTransition connState (TerminatedState Nothing))
                    , Just prune
                    , Nothing
                    )

                else do
                  writeTVar connVar connState'
                  return ( OperationSuccess (TransitionTrace connStateId tr)
                         , Nothing
                         , Nothing
                         )
              OutboundIdleState ConnectionId peerAddr
_connId Async m ()
_connThread handle
_handle DataFlow
Unidirectional ->
                (OperationResult
   (TransitionTrace
      ConnStateId
      (ConnectionState peerAddr handle handleError version m)),
 Maybe (PruneAction m), Maybe (Trace peerAddr handlerTrace))
-> STM
     m
     (OperationResult
        (TransitionTrace
           ConnStateId
           (ConnectionState peerAddr handle handleError version m)),
      Maybe (PruneAction m), Maybe (Trace peerAddr handlerTrace))
forall a. a -> STM m a
forall (m :: * -> *) a. Monad m => a -> m a
return ( AbstractState
-> OperationResult
     (TransitionTrace
        ConnStateId
        (ConnectionState peerAddr handle handleError version m))
forall a. AbstractState -> OperationResult a
UnsupportedState AbstractState
st
                       , Maybe (PruneAction m)
forall a. Maybe a
Nothing
                       , Maybe (Trace peerAddr handlerTrace)
forall a. Maybe a
Nothing
                       )
              InboundIdleState ConnectionId peerAddr
_connId Async m ()
connThread handle
handle DataFlow
dataFlow -> do
                -- @
                --   Awake^{dataFlow}_{Remote} : InboundIdleState Duplex
                --                             → InboundState Duplex
                -- @
                let connState' :: ConnectionState peerAddr handle handleError version m
connState' = ConnectionId peerAddr
-> Async m ()
-> handle
-> DataFlow
-> ConnectionState peerAddr handle handleError version m
forall peerAddr handle handleError version (m :: * -> *).
ConnectionId peerAddr
-> Async m ()
-> handle
-> DataFlow
-> ConnectionState peerAddr handle handleError version m
InboundState ConnectionId peerAddr
connId Async m ()
connThread handle
handle DataFlow
dataFlow
                StrictTVar
  m (ConnectionState peerAddr handle handleError version m)
-> ConnectionState peerAddr handle handleError version m
-> STM m ()
forall (m :: * -> *) a.
MonadSTM m =>
StrictTVar m a -> a -> STM m ()
writeTVar StrictTVar
  m (ConnectionState peerAddr handle handleError version m)
connVar ConnectionState peerAddr handle handleError version m
connState'
                (OperationResult
   (TransitionTrace
      ConnStateId
      (ConnectionState peerAddr handle handleError version m)),
 Maybe (PruneAction m), Maybe (Trace peerAddr handlerTrace))
-> STM
     m
     (OperationResult
        (TransitionTrace
           ConnStateId
           (ConnectionState peerAddr handle handleError version m)),
      Maybe (PruneAction m), Maybe (Trace peerAddr handlerTrace))
forall a. a -> STM m a
forall (m :: * -> *) a. Monad m => a -> m a
return ( TransitionTrace
  ConnStateId (ConnectionState peerAddr handle handleError version m)
-> OperationResult
     (TransitionTrace
        ConnStateId
        (ConnectionState peerAddr handle handleError version m))
forall a. a -> OperationResult a
OperationSuccess (ConnStateId
-> Transition'
     (MaybeUnknown
        (ConnectionState peerAddr handle handleError version m))
-> TransitionTrace
     ConnStateId (ConnectionState peerAddr handle handleError version m)
forall id state.
id -> Transition' state -> TransitionTrace' id state
TransitionTrace ConnStateId
connStateId (Transition'
   (MaybeUnknown
      (ConnectionState peerAddr handle handleError version m))
 -> TransitionTrace
      ConnStateId
      (ConnectionState peerAddr handle handleError version m))
-> Transition'
     (MaybeUnknown
        (ConnectionState peerAddr handle handleError version m))
-> TransitionTrace
     ConnStateId (ConnectionState peerAddr handle handleError version m)
forall a b. (a -> b) -> a -> b
$ ConnectionState peerAddr handle handleError version m
-> ConnectionState peerAddr handle handleError version m
-> Transition'
     (MaybeUnknown
        (ConnectionState peerAddr handle handleError version m))
forall state. state -> state -> Transition state
mkTransition ConnectionState peerAddr handle handleError version m
connState ConnectionState peerAddr handle handleError version m
connState')
                       , Maybe (PruneAction m)
forall a. Maybe a
Nothing
                       , Maybe (Trace peerAddr handlerTrace)
forall a. Maybe a
Nothing
                       )
              InboundState ConnectionId peerAddr
_connId Async m ()
_ handle
_ DataFlow
_ ->
                (OperationResult
   (TransitionTrace
      ConnStateId
      (ConnectionState peerAddr handle handleError version m)),
 Maybe (PruneAction m), Maybe (Trace peerAddr handlerTrace))
-> STM
     m
     (OperationResult
        (TransitionTrace
           ConnStateId
           (ConnectionState peerAddr handle handleError version m)),
      Maybe (PruneAction m), Maybe (Trace peerAddr handlerTrace))
forall a. a -> STM m a
forall (m :: * -> *) a. Monad m => a -> m a
return ( TransitionTrace
  ConnStateId (ConnectionState peerAddr handle handleError version m)
-> OperationResult
     (TransitionTrace
        ConnStateId
        (ConnectionState peerAddr handle handleError version m))
forall a. a -> OperationResult a
OperationSuccess (ConnStateId
-> Transition'
     (MaybeUnknown
        (ConnectionState peerAddr handle handleError version m))
-> TransitionTrace
     ConnStateId (ConnectionState peerAddr handle handleError version m)
forall id state.
id -> Transition' state -> TransitionTrace' id state
TransitionTrace ConnStateId
connStateId (Transition'
   (MaybeUnknown
      (ConnectionState peerAddr handle handleError version m))
 -> TransitionTrace
      ConnStateId
      (ConnectionState peerAddr handle handleError version m))
-> Transition'
     (MaybeUnknown
        (ConnectionState peerAddr handle handleError version m))
-> TransitionTrace
     ConnStateId (ConnectionState peerAddr handle handleError version m)
forall a b. (a -> b) -> a -> b
$ ConnectionState peerAddr handle handleError version m
-> ConnectionState peerAddr handle handleError version m
-> Transition'
     (MaybeUnknown
        (ConnectionState peerAddr handle handleError version m))
forall state. state -> state -> Transition state
mkTransition ConnectionState peerAddr handle handleError version m
connState ConnectionState peerAddr handle handleError version m
connState)
                       , Maybe (PruneAction m)
forall a. Maybe a
Nothing
                       -- already in 'InboundState'?
                       , Trace peerAddr handlerTrace -> Maybe (Trace peerAddr handlerTrace)
forall a. a -> Maybe a
Just (AssertionLocation peerAddr -> Trace peerAddr handlerTrace
forall peerAddr handlerTrace.
AssertionLocation peerAddr -> Trace peerAddr handlerTrace
TrUnexpectedlyFalseAssertion
                                (Maybe (ConnectionId peerAddr)
-> AbstractState -> AssertionLocation peerAddr
forall peerAddr.
Maybe (ConnectionId peerAddr)
-> AbstractState -> AssertionLocation peerAddr
PromotedToWarmRemote
                                  (ConnectionId peerAddr -> Maybe (ConnectionId peerAddr)
forall a. a -> Maybe a
Just ConnectionId peerAddr
connId)
                                  AbstractState
st)
                              )
                       )
              DuplexState {} ->
                (OperationResult
   (TransitionTrace
      ConnStateId
      (ConnectionState peerAddr handle handleError version m)),
 Maybe (PruneAction m), Maybe (Trace peerAddr handlerTrace))
-> STM
     m
     (OperationResult
        (TransitionTrace
           ConnStateId
           (ConnectionState peerAddr handle handleError version m)),
      Maybe (PruneAction m), Maybe (Trace peerAddr handlerTrace))
forall a. a -> STM m a
forall (m :: * -> *) a. Monad m => a -> m a
return ( TransitionTrace
  ConnStateId (ConnectionState peerAddr handle handleError version m)
-> OperationResult
     (TransitionTrace
        ConnStateId
        (ConnectionState peerAddr handle handleError version m))
forall a. a -> OperationResult a
OperationSuccess (ConnStateId
-> Transition'
     (MaybeUnknown
        (ConnectionState peerAddr handle handleError version m))
-> TransitionTrace
     ConnStateId (ConnectionState peerAddr handle handleError version m)
forall id state.
id -> Transition' state -> TransitionTrace' id state
TransitionTrace ConnStateId
connStateId (Transition'
   (MaybeUnknown
      (ConnectionState peerAddr handle handleError version m))
 -> TransitionTrace
      ConnStateId
      (ConnectionState peerAddr handle handleError version m))
-> Transition'
     (MaybeUnknown
        (ConnectionState peerAddr handle handleError version m))
-> TransitionTrace
     ConnStateId (ConnectionState peerAddr handle handleError version m)
forall a b. (a -> b) -> a -> b
$ ConnectionState peerAddr handle handleError version m
-> ConnectionState peerAddr handle handleError version m
-> Transition'
     (MaybeUnknown
        (ConnectionState peerAddr handle handleError version m))
forall state. state -> state -> Transition state
mkTransition ConnectionState peerAddr handle handleError version m
connState ConnectionState peerAddr handle handleError version m
connState)
                       , Maybe (PruneAction m)
forall a. Maybe a
Nothing
                       , Maybe (Trace peerAddr handlerTrace)
forall a. Maybe a
Nothing
                       )
              TerminatingState {} ->
                (OperationResult
   (TransitionTrace
      ConnStateId
      (ConnectionState peerAddr handle handleError version m)),
 Maybe (PruneAction m), Maybe (Trace peerAddr handlerTrace))
-> STM
     m
     (OperationResult
        (TransitionTrace
           ConnStateId
           (ConnectionState peerAddr handle handleError version m)),
      Maybe (PruneAction m), Maybe (Trace peerAddr handlerTrace))
forall a. a -> STM m a
forall (m :: * -> *) a. Monad m => a -> m a
return ( AbstractState
-> OperationResult
     (TransitionTrace
        ConnStateId
        (ConnectionState peerAddr handle handleError version m))
forall a. AbstractState -> OperationResult a
UnsupportedState AbstractState
TerminatingSt
                       , Maybe (PruneAction m)
forall a. Maybe a
Nothing
                       , Maybe (Trace peerAddr handlerTrace)
forall a. Maybe a
Nothing
                       )
              TerminatedState {} ->
                (OperationResult
   (TransitionTrace
      ConnStateId
      (ConnectionState peerAddr handle handleError version m)),
 Maybe (PruneAction m), Maybe (Trace peerAddr handlerTrace))
-> STM
     m
     (OperationResult
        (TransitionTrace
           ConnStateId
           (ConnectionState peerAddr handle handleError version m)),
      Maybe (PruneAction m), Maybe (Trace peerAddr handlerTrace))
forall a. a -> STM m a
forall (m :: * -> *) a. Monad m => a -> m a
return ( AbstractState
-> OperationResult
     (TransitionTrace
        ConnStateId
        (ConnectionState peerAddr handle handleError version m))
forall a. AbstractState -> OperationResult a
UnsupportedState AbstractState
TerminatedSt
                       , Maybe (PruneAction m)
forall a. Maybe a
Nothing
                       , Maybe (Trace peerAddr handlerTrace)
forall a. Maybe a
Nothing
                       )

      whenJust mbAssertion $ \Trace peerAddr handlerTrace
tr' -> do
        Tracer m (Trace peerAddr handlerTrace)
-> Trace peerAddr handlerTrace -> m ()
forall (m :: * -> *) a. Tracer m a -> a -> m ()
traceWith Tracer m (Trace peerAddr handlerTrace)
tracer Trace peerAddr handlerTrace
tr'
        _ <- (Any -> Any) -> m (Any -> Any)
forall a. a -> m a
forall (m :: * -> *) a. MonadEvaluate m => a -> m a
evaluate (Bool -> Any -> Any
forall a. (?callStack::CallStack) => Bool -> a -> a
assert Bool
False)
        pure ()

      -- trace transition
      case (result, pruneTr) of
        (OperationSuccess TransitionTrace
  ConnStateId (ConnectionState peerAddr handle handleError version m)
tr, Maybe (PruneAction m)
Nothing) -> do
          Tracer
  m
  (TransitionTrace
     ConnStateId
     (ConnectionState peerAddr handle handleError version m))
-> TransitionTrace
     ConnStateId (ConnectionState peerAddr handle handleError version m)
-> m ()
forall (m :: * -> *) a. Tracer m a -> a -> m ()
traceWith Tracer
  m
  (TransitionTrace
     ConnStateId
     (ConnectionState peerAddr handle handleError version m))
trTracer TransitionTrace
  ConnStateId (ConnectionState peerAddr handle handleError version m)
tr
          StrictTMVar
  m (ConnectionManagerState peerAddr handle handleError version m)
-> m ()
traceCounters StrictTMVar
  m (ConnectionManagerState peerAddr handle handleError version m)
stateVar

        (OperationSuccess TransitionTrace
  ConnStateId (ConnectionState peerAddr handle handleError version m)
tr, Just PruneAction m
prune) -> do
          Tracer
  m
  (TransitionTrace
     ConnStateId
     (ConnectionState peerAddr handle handleError version m))
-> TransitionTrace
     ConnStateId (ConnectionState peerAddr handle handleError version m)
-> m ()
forall (m :: * -> *) a. Tracer m a -> a -> m ()
traceWith Tracer
  m
  (TransitionTrace
     ConnStateId
     (ConnectionState peerAddr handle handleError version m))
trTracer TransitionTrace
  ConnStateId (ConnectionState peerAddr handle handleError version m)
tr
          PruneAction m -> m ()
forall (m :: * -> *). PruneAction m -> m ()
runPruneAction PruneAction m
prune
          StrictTMVar
  m (ConnectionManagerState peerAddr handle handleError version m)
-> m ()
traceCounters StrictTMVar
  m (ConnectionManagerState peerAddr handle handleError version m)
stateVar

        (OperationResult
   (TransitionTrace
      ConnStateId
      (ConnectionState peerAddr handle handleError version m)),
 Maybe (PruneAction m))
_ -> () -> m ()
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return ()
      return (State.abstractState . fromState . ttTransition <$> result)


    demotedToColdRemoteImpl
        :: StrictTMVar m (ConnectionManagerState peerAddr handle handleError version m)
        -> ConnectionId peerAddr
        -> m (OperationResult AbstractState)
    demotedToColdRemoteImpl :: StrictTMVar
  m (ConnectionManagerState peerAddr handle handleError version m)
-> ConnectionId peerAddr -> m (OperationResult AbstractState)
demotedToColdRemoteImpl StrictTMVar
  m (ConnectionManagerState peerAddr handle handleError version m)
stateVar ConnectionId peerAddr
connId = do
      (result, mbAssertion) <- STM
  m
  (OperationResult
     (TransitionTrace
        ConnStateId
        (ConnectionState peerAddr handle handleError version m)),
   Maybe (Trace peerAddr handlerTrace))
-> m (OperationResult
        (TransitionTrace
           ConnStateId
           (ConnectionState peerAddr handle handleError version m)),
      Maybe (Trace peerAddr handlerTrace))
forall a. (?callStack::CallStack) => STM m a -> m a
forall (m :: * -> *) a.
(MonadSTM m, ?callStack::CallStack) =>
STM m a -> m a
atomically (STM
   m
   (OperationResult
      (TransitionTrace
         ConnStateId
         (ConnectionState peerAddr handle handleError version m)),
    Maybe (Trace peerAddr handlerTrace))
 -> m (OperationResult
         (TransitionTrace
            ConnStateId
            (ConnectionState peerAddr handle handleError version m)),
       Maybe (Trace peerAddr handlerTrace)))
-> STM
     m
     (OperationResult
        (TransitionTrace
           ConnStateId
           (ConnectionState peerAddr handle handleError version m)),
      Maybe (Trace peerAddr handlerTrace))
-> m (OperationResult
        (TransitionTrace
           ConnStateId
           (ConnectionState peerAddr handle handleError version m)),
      Maybe (Trace peerAddr handlerTrace))
forall a b. (a -> b) -> a -> b
$ do
        mbConnVar <- ConnectionId peerAddr
-> ConnectionManagerState peerAddr handle handleError version m
-> Maybe (MutableConnState peerAddr handle handleError version m)
forall peerAddr a.
Ord peerAddr =>
ConnectionId peerAddr -> ConnMap peerAddr a -> Maybe a
State.lookup ConnectionId peerAddr
connId (ConnectionManagerState peerAddr handle handleError version m
 -> Maybe (MutableConnState peerAddr handle handleError version m))
-> STM
     m (ConnectionManagerState peerAddr handle handleError version m)
-> STM
     m (Maybe (MutableConnState peerAddr handle handleError version m))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> StrictTMVar
  m (ConnectionManagerState peerAddr handle handleError version m)
-> STM
     m (ConnectionManagerState peerAddr handle handleError version m)
forall (m :: * -> *) a. MonadSTM m => StrictTMVar m a -> STM m a
readTMVar StrictTMVar
  m (ConnectionManagerState peerAddr handle handleError version m)
stateVar
        case mbConnVar of
          Maybe (MutableConnState peerAddr handle handleError version m)
Nothing -> (OperationResult
   (TransitionTrace
      ConnStateId
      (ConnectionState peerAddr handle handleError version m)),
 Maybe (Trace peerAddr handlerTrace))
-> STM
     m
     (OperationResult
        (TransitionTrace
           ConnStateId
           (ConnectionState peerAddr handle handleError version m)),
      Maybe (Trace peerAddr handlerTrace))
forall a. a -> STM m a
forall (m :: * -> *) a. Monad m => a -> m a
return ( AbstractState
-> OperationResult
     (TransitionTrace
        ConnStateId
        (ConnectionState peerAddr handle handleError version m))
forall a. AbstractState -> OperationResult a
UnsupportedState AbstractState
UnknownConnectionSt
                            , Maybe (Trace peerAddr handlerTrace)
forall a. Maybe a
Nothing
                            )
          Just MutableConnState { StrictTVar
  m (ConnectionState peerAddr handle handleError version m)
connVar :: 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)
connVar, ConnStateId
connStateId :: forall peerAddr handle handleError version (m :: * -> *).
MutableConnState peerAddr handle handleError version m
-> ConnStateId
connStateId :: ConnStateId
connStateId } -> do
            connState <- 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)
connVar
            let st = MaybeUnknown
  (ConnectionState peerAddr handle handleError version m)
-> AbstractState
forall muxMode peerAddr m a (b :: * -> *).
MaybeUnknown (ConnectionState muxMode peerAddr m a b)
-> AbstractState
State.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
connState)
            case connState of
              ReservedOutboundState {} -> do
                (OperationResult
   (TransitionTrace
      ConnStateId
      (ConnectionState peerAddr handle handleError version m)),
 Maybe (Trace peerAddr handlerTrace))
-> STM
     m
     (OperationResult
        (TransitionTrace
           ConnStateId
           (ConnectionState peerAddr handle handleError version m)),
      Maybe (Trace peerAddr handlerTrace))
forall a. a -> STM m a
forall (m :: * -> *) a. Monad m => a -> m a
return ( AbstractState
-> OperationResult
     (TransitionTrace
        ConnStateId
        (ConnectionState peerAddr handle handleError version m))
forall a. AbstractState -> OperationResult a
UnsupportedState AbstractState
st
                       , Trace peerAddr handlerTrace -> Maybe (Trace peerAddr handlerTrace)
forall a. a -> Maybe a
Just (AssertionLocation peerAddr -> Trace peerAddr handlerTrace
forall peerAddr handlerTrace.
AssertionLocation peerAddr -> Trace peerAddr handlerTrace
TrUnexpectedlyFalseAssertion
                                (Maybe (ConnectionId peerAddr)
-> AbstractState -> AssertionLocation peerAddr
forall peerAddr.
Maybe (ConnectionId peerAddr)
-> AbstractState -> AssertionLocation peerAddr
DemotedToColdRemote
                                  Maybe (ConnectionId peerAddr)
forall a. Maybe a
Nothing
                                  AbstractState
st)
                              )
                       )
              UnnegotiatedState Provenance
_ ConnectionId peerAddr
_connId Async m ()
_ ->
                (OperationResult
   (TransitionTrace
      ConnStateId
      (ConnectionState peerAddr handle handleError version m)),
 Maybe (Trace peerAddr handlerTrace))
-> STM
     m
     (OperationResult
        (TransitionTrace
           ConnStateId
           (ConnectionState peerAddr handle handleError version m)),
      Maybe (Trace peerAddr handlerTrace))
forall a. a -> STM m a
forall (m :: * -> *) a. Monad m => a -> m a
return ( AbstractState
-> OperationResult
     (TransitionTrace
        ConnStateId
        (ConnectionState peerAddr handle handleError version m))
forall a. AbstractState -> OperationResult a
UnsupportedState AbstractState
st
                       , Trace peerAddr handlerTrace -> Maybe (Trace peerAddr handlerTrace)
forall a. a -> Maybe a
Just (AssertionLocation peerAddr -> Trace peerAddr handlerTrace
forall peerAddr handlerTrace.
AssertionLocation peerAddr -> Trace peerAddr handlerTrace
TrUnexpectedlyFalseAssertion
                                (Maybe (ConnectionId peerAddr)
-> AbstractState -> AssertionLocation peerAddr
forall peerAddr.
Maybe (ConnectionId peerAddr)
-> AbstractState -> AssertionLocation peerAddr
DemotedToColdRemote
                                  (ConnectionId peerAddr -> Maybe (ConnectionId peerAddr)
forall a. a -> Maybe a
Just ConnectionId peerAddr
connId)
                                  AbstractState
st)
                              )
                       )
              OutboundUniState ConnectionId peerAddr
_connId Async m ()
_connThread handle
_handle ->
                (OperationResult
   (TransitionTrace
      ConnStateId
      (ConnectionState peerAddr handle handleError version m)),
 Maybe (Trace peerAddr handlerTrace))
-> STM
     m
     (OperationResult
        (TransitionTrace
           ConnStateId
           (ConnectionState peerAddr handle handleError version m)),
      Maybe (Trace peerAddr handlerTrace))
forall a. a -> STM m a
forall (m :: * -> *) a. Monad m => a -> m a
return ( AbstractState
-> OperationResult
     (TransitionTrace
        ConnStateId
        (ConnectionState peerAddr handle handleError version m))
forall a. AbstractState -> OperationResult a
UnsupportedState AbstractState
st
                       , Trace peerAddr handlerTrace -> Maybe (Trace peerAddr handlerTrace)
forall a. a -> Maybe a
Just (AssertionLocation peerAddr -> Trace peerAddr handlerTrace
forall peerAddr handlerTrace.
AssertionLocation peerAddr -> Trace peerAddr handlerTrace
TrUnexpectedlyFalseAssertion
                                (Maybe (ConnectionId peerAddr)
-> AbstractState -> AssertionLocation peerAddr
forall peerAddr.
Maybe (ConnectionId peerAddr)
-> AbstractState -> AssertionLocation peerAddr
DemotedToColdRemote
                                  (ConnectionId peerAddr -> Maybe (ConnectionId peerAddr)
forall a. a -> Maybe a
Just ConnectionId peerAddr
connId)
                                  AbstractState
st)
                              )
                       )
              OutboundDupState ConnectionId peerAddr
_connId Async m ()
_connThread handle
_handle TimeoutExpired
_expired ->
                (OperationResult
   (TransitionTrace
      ConnStateId
      (ConnectionState peerAddr handle handleError version m)),
 Maybe (Trace peerAddr handlerTrace))
-> STM
     m
     (OperationResult
        (TransitionTrace
           ConnStateId
           (ConnectionState peerAddr handle handleError version m)),
      Maybe (Trace peerAddr handlerTrace))
forall a. a -> STM m a
forall (m :: * -> *) a. Monad m => a -> m a
return ( TransitionTrace
  ConnStateId (ConnectionState peerAddr handle handleError version m)
-> OperationResult
     (TransitionTrace
        ConnStateId
        (ConnectionState peerAddr handle handleError version m))
forall a. a -> OperationResult a
OperationSuccess (ConnStateId
-> Transition'
     (MaybeUnknown
        (ConnectionState peerAddr handle handleError version m))
-> TransitionTrace
     ConnStateId (ConnectionState peerAddr handle handleError version m)
forall id state.
id -> Transition' state -> TransitionTrace' id state
TransitionTrace ConnStateId
connStateId (Transition'
   (MaybeUnknown
      (ConnectionState peerAddr handle handleError version m))
 -> TransitionTrace
      ConnStateId
      (ConnectionState peerAddr handle handleError version m))
-> Transition'
     (MaybeUnknown
        (ConnectionState peerAddr handle handleError version m))
-> TransitionTrace
     ConnStateId (ConnectionState peerAddr handle handleError version m)
forall a b. (a -> b) -> a -> b
$ ConnectionState peerAddr handle handleError version m
-> ConnectionState peerAddr handle handleError version m
-> Transition'
     (MaybeUnknown
        (ConnectionState peerAddr handle handleError version m))
forall state. state -> state -> Transition state
mkTransition ConnectionState peerAddr handle handleError version m
connState ConnectionState peerAddr handle handleError version m
connState)
                       , Maybe (Trace peerAddr handlerTrace)
forall a. Maybe a
Nothing
                       )
              -- one can only enter 'OutboundIdleState' if remote state is
              -- already cold.
              OutboundIdleState ConnectionId peerAddr
_connId Async m ()
_connThread handle
_handle DataFlow
_dataFlow ->
                (OperationResult
   (TransitionTrace
      ConnStateId
      (ConnectionState peerAddr handle handleError version m)),
 Maybe (Trace peerAddr handlerTrace))
-> STM
     m
     (OperationResult
        (TransitionTrace
           ConnStateId
           (ConnectionState peerAddr handle handleError version m)),
      Maybe (Trace peerAddr handlerTrace))
forall a. a -> STM m a
forall (m :: * -> *) a. Monad m => a -> m a
return ( TransitionTrace
  ConnStateId (ConnectionState peerAddr handle handleError version m)
-> OperationResult
     (TransitionTrace
        ConnStateId
        (ConnectionState peerAddr handle handleError version m))
forall a. a -> OperationResult a
OperationSuccess (ConnStateId
-> Transition'
     (MaybeUnknown
        (ConnectionState peerAddr handle handleError version m))
-> TransitionTrace
     ConnStateId (ConnectionState peerAddr handle handleError version m)
forall id state.
id -> Transition' state -> TransitionTrace' id state
TransitionTrace ConnStateId
connStateId (Transition'
   (MaybeUnknown
      (ConnectionState peerAddr handle handleError version m))
 -> TransitionTrace
      ConnStateId
      (ConnectionState peerAddr handle handleError version m))
-> Transition'
     (MaybeUnknown
        (ConnectionState peerAddr handle handleError version m))
-> TransitionTrace
     ConnStateId (ConnectionState peerAddr handle handleError version m)
forall a b. (a -> b) -> a -> b
$ ConnectionState peerAddr handle handleError version m
-> ConnectionState peerAddr handle handleError version m
-> Transition'
     (MaybeUnknown
        (ConnectionState peerAddr handle handleError version m))
forall state. state -> state -> Transition state
mkTransition ConnectionState peerAddr handle handleError version m
connState ConnectionState peerAddr handle handleError version m
connState)
                       , Maybe (Trace peerAddr handlerTrace)
forall a. Maybe a
Nothing
                       )
              InboundIdleState ConnectionId peerAddr
_connId Async m ()
_connThread handle
_handle DataFlow
_dataFlow ->
                (OperationResult
   (TransitionTrace
      ConnStateId
      (ConnectionState peerAddr handle handleError version m)),
 Maybe (Trace peerAddr handlerTrace))
-> STM
     m
     (OperationResult
        (TransitionTrace
           ConnStateId
           (ConnectionState peerAddr handle handleError version m)),
      Maybe (Trace peerAddr handlerTrace))
forall a. a -> STM m a
forall (m :: * -> *) a. Monad m => a -> m a
return ( TransitionTrace
  ConnStateId (ConnectionState peerAddr handle handleError version m)
-> OperationResult
     (TransitionTrace
        ConnStateId
        (ConnectionState peerAddr handle handleError version m))
forall a. a -> OperationResult a
OperationSuccess (ConnStateId
-> Transition'
     (MaybeUnknown
        (ConnectionState peerAddr handle handleError version m))
-> TransitionTrace
     ConnStateId (ConnectionState peerAddr handle handleError version m)
forall id state.
id -> Transition' state -> TransitionTrace' id state
TransitionTrace ConnStateId
connStateId (Transition'
   (MaybeUnknown
      (ConnectionState peerAddr handle handleError version m))
 -> TransitionTrace
      ConnStateId
      (ConnectionState peerAddr handle handleError version m))
-> Transition'
     (MaybeUnknown
        (ConnectionState peerAddr handle handleError version m))
-> TransitionTrace
     ConnStateId (ConnectionState peerAddr handle handleError version m)
forall a b. (a -> b) -> a -> b
$ ConnectionState peerAddr handle handleError version m
-> ConnectionState peerAddr handle handleError version m
-> Transition'
     (MaybeUnknown
        (ConnectionState peerAddr handle handleError version m))
forall state. state -> state -> Transition state
mkTransition ConnectionState peerAddr handle handleError version m
connState ConnectionState peerAddr handle handleError version m
connState)
                       , Maybe (Trace peerAddr handlerTrace)
forall a. Maybe a
Nothing
                       )

              -- @
              --   DemotedToCold^{dataFlow}_{Remote}
              --     : InboundState dataFlow
              --     → InboundIdleState^\tau dataFlow
              -- @
              InboundState ConnectionId peerAddr
_connId Async m ()
connThread handle
handle DataFlow
dataFlow -> do
                let connState' :: ConnectionState peerAddr handle handleError version m
connState' = ConnectionId peerAddr
-> Async m ()
-> handle
-> DataFlow
-> ConnectionState peerAddr handle handleError version m
forall peerAddr handle handleError version (m :: * -> *).
ConnectionId peerAddr
-> Async m ()
-> handle
-> DataFlow
-> ConnectionState peerAddr handle handleError version m
InboundIdleState ConnectionId peerAddr
connId Async m ()
connThread handle
handle DataFlow
dataFlow
                StrictTVar
  m (ConnectionState peerAddr handle handleError version m)
-> ConnectionState peerAddr handle handleError version m
-> STM m ()
forall (m :: * -> *) a.
MonadSTM m =>
StrictTVar m a -> a -> STM m ()
writeTVar StrictTVar
  m (ConnectionState peerAddr handle handleError version m)
connVar ConnectionState peerAddr handle handleError version m
connState'
                (OperationResult
   (TransitionTrace
      ConnStateId
      (ConnectionState peerAddr handle handleError version m)),
 Maybe (Trace peerAddr handlerTrace))
-> STM
     m
     (OperationResult
        (TransitionTrace
           ConnStateId
           (ConnectionState peerAddr handle handleError version m)),
      Maybe (Trace peerAddr handlerTrace))
forall a. a -> STM m a
forall (m :: * -> *) a. Monad m => a -> m a
return ( TransitionTrace
  ConnStateId (ConnectionState peerAddr handle handleError version m)
-> OperationResult
     (TransitionTrace
        ConnStateId
        (ConnectionState peerAddr handle handleError version m))
forall a. a -> OperationResult a
OperationSuccess (ConnStateId
-> Transition'
     (MaybeUnknown
        (ConnectionState peerAddr handle handleError version m))
-> TransitionTrace
     ConnStateId (ConnectionState peerAddr handle handleError version m)
forall id state.
id -> Transition' state -> TransitionTrace' id state
TransitionTrace ConnStateId
connStateId (Transition'
   (MaybeUnknown
      (ConnectionState peerAddr handle handleError version m))
 -> TransitionTrace
      ConnStateId
      (ConnectionState peerAddr handle handleError version m))
-> Transition'
     (MaybeUnknown
        (ConnectionState peerAddr handle handleError version m))
-> TransitionTrace
     ConnStateId (ConnectionState peerAddr handle handleError version m)
forall a b. (a -> b) -> a -> b
$ ConnectionState peerAddr handle handleError version m
-> ConnectionState peerAddr handle handleError version m
-> Transition'
     (MaybeUnknown
        (ConnectionState peerAddr handle handleError version m))
forall state. state -> state -> Transition state
mkTransition ConnectionState peerAddr handle handleError version m
connState ConnectionState peerAddr handle handleError version m
connState')
                       , Maybe (Trace peerAddr handlerTrace)
forall a. Maybe a
Nothing
                       )

              -- @
              --   DemotedToCold^{dataFlow}_{Remote}
              --     : DuplexState
              --     → OutboundState^\tau Duplex
              -- @
              DuplexState ConnectionId peerAddr
_connId Async m ()
connThread handle
handle -> do
                let connState' :: ConnectionState peerAddr handle handleError version m
connState' = ConnectionId peerAddr
-> Async m ()
-> handle
-> TimeoutExpired
-> ConnectionState peerAddr handle handleError version m
forall peerAddr handle handleError version (m :: * -> *).
ConnectionId peerAddr
-> Async m ()
-> handle
-> TimeoutExpired
-> ConnectionState peerAddr handle handleError version m
OutboundDupState ConnectionId peerAddr
connId Async m ()
connThread handle
handle TimeoutExpired
Ticking
                StrictTVar
  m (ConnectionState peerAddr handle handleError version m)
-> ConnectionState peerAddr handle handleError version m
-> STM m ()
forall (m :: * -> *) a.
MonadSTM m =>
StrictTVar m a -> a -> STM m ()
writeTVar StrictTVar
  m (ConnectionState peerAddr handle handleError version m)
connVar ConnectionState peerAddr handle handleError version m
connState'
                (OperationResult
   (TransitionTrace
      ConnStateId
      (ConnectionState peerAddr handle handleError version m)),
 Maybe (Trace peerAddr handlerTrace))
-> STM
     m
     (OperationResult
        (TransitionTrace
           ConnStateId
           (ConnectionState peerAddr handle handleError version m)),
      Maybe (Trace peerAddr handlerTrace))
forall a. a -> STM m a
forall (m :: * -> *) a. Monad m => a -> m a
return ( TransitionTrace
  ConnStateId (ConnectionState peerAddr handle handleError version m)
-> OperationResult
     (TransitionTrace
        ConnStateId
        (ConnectionState peerAddr handle handleError version m))
forall a. a -> OperationResult a
OperationSuccess (ConnStateId
-> Transition'
     (MaybeUnknown
        (ConnectionState peerAddr handle handleError version m))
-> TransitionTrace
     ConnStateId (ConnectionState peerAddr handle handleError version m)
forall id state.
id -> Transition' state -> TransitionTrace' id state
TransitionTrace ConnStateId
connStateId (Transition'
   (MaybeUnknown
      (ConnectionState peerAddr handle handleError version m))
 -> TransitionTrace
      ConnStateId
      (ConnectionState peerAddr handle handleError version m))
-> Transition'
     (MaybeUnknown
        (ConnectionState peerAddr handle handleError version m))
-> TransitionTrace
     ConnStateId (ConnectionState peerAddr handle handleError version m)
forall a b. (a -> b) -> a -> b
$ ConnectionState peerAddr handle handleError version m
-> ConnectionState peerAddr handle handleError version m
-> Transition'
     (MaybeUnknown
        (ConnectionState peerAddr handle handleError version m))
forall state. state -> state -> Transition state
mkTransition ConnectionState peerAddr handle handleError version m
connState ConnectionState peerAddr handle handleError version m
connState')
                       , Maybe (Trace peerAddr handlerTrace)
forall a. Maybe a
Nothing
                       )

              TerminatingState {} ->
                (OperationResult
   (TransitionTrace
      ConnStateId
      (ConnectionState peerAddr handle handleError version m)),
 Maybe (Trace peerAddr handlerTrace))
-> STM
     m
     (OperationResult
        (TransitionTrace
           ConnStateId
           (ConnectionState peerAddr handle handleError version m)),
      Maybe (Trace peerAddr handlerTrace))
forall a. a -> STM m a
forall (m :: * -> *) a. Monad m => a -> m a
return ( AbstractState
-> OperationResult
     (TransitionTrace
        ConnStateId
        (ConnectionState peerAddr handle handleError version m))
forall a. AbstractState -> OperationResult a
TerminatedConnection AbstractState
st
                       , Maybe (Trace peerAddr handlerTrace)
forall a. Maybe a
Nothing
                       )
              TerminatedState {} ->
                (OperationResult
   (TransitionTrace
      ConnStateId
      (ConnectionState peerAddr handle handleError version m)),
 Maybe (Trace peerAddr handlerTrace))
-> STM
     m
     (OperationResult
        (TransitionTrace
           ConnStateId
           (ConnectionState peerAddr handle handleError version m)),
      Maybe (Trace peerAddr handlerTrace))
forall a. a -> STM m a
forall (m :: * -> *) a. Monad m => a -> m a
return ( AbstractState
-> OperationResult
     (TransitionTrace
        ConnStateId
        (ConnectionState peerAddr handle handleError version m))
forall a. AbstractState -> OperationResult a
TerminatedConnection AbstractState
st
                       , Maybe (Trace peerAddr handlerTrace)
forall a. Maybe a
Nothing
                       )

      whenJust mbAssertion $ \Trace peerAddr handlerTrace
tr' -> do
        Tracer m (Trace peerAddr handlerTrace)
-> Trace peerAddr handlerTrace -> m ()
forall (m :: * -> *) a. Tracer m a -> a -> m ()
traceWith Tracer m (Trace peerAddr handlerTrace)
tracer Trace peerAddr handlerTrace
tr'
        _ <- (Any -> Any) -> m (Any -> Any)
forall a. a -> m a
forall (m :: * -> *) a. MonadEvaluate m => a -> m a
evaluate (Bool -> Any -> Any
forall a. (?callStack::CallStack) => Bool -> a -> a
assert Bool
False)
        pure ()

      -- trace transition
      case result of
        OperationSuccess TransitionTrace
  ConnStateId (ConnectionState peerAddr handle handleError version m)
tr ->
          Tracer
  m
  (TransitionTrace
     ConnStateId
     (ConnectionState peerAddr handle handleError version m))
-> TransitionTrace
     ConnStateId (ConnectionState peerAddr handle handleError version m)
-> m ()
forall (m :: * -> *) a. Tracer m a -> a -> m ()
traceWith Tracer
  m
  (TransitionTrace
     ConnStateId
     (ConnectionState peerAddr handle handleError version m))
trTracer TransitionTrace
  ConnStateId (ConnectionState peerAddr handle handleError version m)
tr
        OperationResult
  (TransitionTrace
     ConnStateId
     (ConnectionState peerAddr handle handleError version m))
_ -> () -> m ()
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return ()

      traceCounters stateVar
      return (State.abstractState . fromState . ttTransition <$> result)


--
-- Utilities
--

-- | Perform some operation on 'Just', given the field inside the 'Just'.
--
whenJust :: Applicative m => Maybe a -> (a -> m ()) -> m ()
whenJust :: forall (m :: * -> *) a.
Applicative m =>
Maybe a -> (a -> m ()) -> m ()
whenJust Maybe a
mg a -> m ()
f = m () -> (a -> m ()) -> Maybe a -> m ()
forall b a. b -> (a -> b) -> Maybe a -> b
maybe (() -> m ()
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()) a -> m ()
f Maybe a
mg

-- | Like 'modifyMVar' but strict in @a@ and for 'TMVar's
--
modifyTMVar :: ( MonadEvaluate m
               , MonadMask     m
               , MonadSTM      m
               )
            => StrictTMVar m a
            -> (a -> m (a, b))
            -> m b
modifyTMVar :: forall (m :: * -> *) a b.
(MonadEvaluate m, MonadMask m, MonadSTM m) =>
StrictTMVar m a -> (a -> m (a, b)) -> m b
modifyTMVar StrictTMVar m a
v a -> m (a, b)
k =
  ((forall a. m a -> m a) -> m b) -> m b
forall b. ((forall a. m a -> m a) -> m b) -> m b
forall (m :: * -> *) b.
MonadMask m =>
((forall a. m a -> m a) -> m b) -> m b
mask (((forall a. m a -> m a) -> m b) -> m b)
-> ((forall a. m a -> m a) -> m b) -> m b
forall a b. (a -> b) -> a -> b
$ \forall a. m a -> m a
restore -> do
    a <- STM m a -> m a
forall a. (?callStack::CallStack) => STM m a -> m a
forall (m :: * -> *) a.
(MonadSTM m, ?callStack::CallStack) =>
STM m a -> m a
atomically (StrictTMVar m a -> STM m a
forall (m :: * -> *) a. MonadSTM m => StrictTMVar m a -> STM m a
takeTMVar StrictTMVar m a
v)
    (a',b) <- restore (k a >>= evaluate)
      `onException`
        atomically (putTMVar v a)
    atomically (putTMVar v a')
    return b

modifyTMVarSTM :: MonadSTM m => StrictTMVar m a -> (a -> STM m (a, b)) -> STM m b
modifyTMVarSTM :: forall (m :: * -> *) a b.
MonadSTM m =>
StrictTMVar m a -> (a -> STM m (a, b)) -> STM m b
modifyTMVarSTM StrictTMVar m a
v a -> STM m (a, b)
k = do
    a <- StrictTMVar m a -> STM m a
forall (m :: * -> *) a. MonadSTM m => StrictTMVar m a -> STM m a
takeTMVar StrictTMVar m a
v
    (a',b) <- k a
    putTMVar v a'
    return b

-- | Like 'modifyMVar' but pure.
--
modifyTMVarPure :: MonadSTM m
                => StrictTMVar m a
                -> (a -> (a, b))
                -> STM m b
modifyTMVarPure :: forall (m :: * -> *) a b.
MonadSTM m =>
StrictTMVar m a -> (a -> (a, b)) -> STM m b
modifyTMVarPure StrictTMVar m a
v a -> (a, b)
k = do
    a <- StrictTMVar m a -> STM m a
forall (m :: * -> *) a. MonadSTM m => StrictTMVar m a -> STM m a
takeTMVar StrictTMVar m a
v
    let (a', b) = k a
    putTMVar v a'
    return b

--
-- Exceptions
--

-- | Useful to attach 'CallStack' to 'ConnectionManagerError'.
--
withCallStack :: HasCallStack => (CallStack -> a) -> a
withCallStack :: forall a. (?callStack::CallStack) => (CallStack -> a) -> a
withCallStack CallStack -> a
k = CallStack -> a
k CallStack
(?callStack::CallStack) => CallStack
callStack

-- | 'ConnectionManagerTrace' contains a hole for a trace of single connection
-- which is filled with 'ConnectionHandlerTrace'.
--
data Trace peerAddr handlerTrace
  = TrIncludeConnection            Provenance peerAddr
  | TrReleaseConnection            Provenance (ConnectionId peerAddr)
  | TrConnect                      (Maybe peerAddr) -- ^ local address
                                   peerAddr         -- ^ remote address
                                   DiffusionMode
  | TrConnectError                 (Maybe peerAddr) -- ^ local address
                                   peerAddr         -- ^ remote address
                                   SomeException
  | TrTerminatingConnection        Provenance (ConnectionId peerAddr)
  | TrTerminatedConnection         Provenance peerAddr
  | TrConnectionHandler            (ConnectionId peerAddr) handlerTrace
  | TrShutdown
  | TrConnectionExists             Provenance peerAddr    AbstractState
  | TrForbiddenConnection          (ConnectionId peerAddr)
  | TrConnectionFailure            (ConnectionId peerAddr)
  | TrConnectionNotFound           Provenance peerAddr
  | TrForbiddenOperation           peerAddr                AbstractState
  | TrPruneConnections             (Set (ConnectionId peerAddr)) -- ^ pruning set
                                   Int            -- ^ number connections that must be pruned
                                   (Set (ConnectionId peerAddr)) -- ^ choice set
  | TrConnectionCleanup            (ConnectionId peerAddr)
  | TrConnectionTimeWait           (ConnectionId peerAddr)
  | TrConnectionTimeWaitDone       (ConnectionId peerAddr)
  | TrConnectionManagerCounters    ConnectionManagerCounters
  | TrState                        (State.ConnMap peerAddr AbstractState)
  -- ^ traced on SIGUSR1 signal, installed in 'runDataDiffusion'
  | TrUnexpectedlyFalseAssertion   (AssertionLocation peerAddr)
  -- ^ This case is unexpected at call site.
  deriving Int -> Trace peerAddr handlerTrace -> String -> String
[Trace peerAddr handlerTrace] -> String -> String
Trace peerAddr handlerTrace -> String
(Int -> Trace peerAddr handlerTrace -> String -> String)
-> (Trace peerAddr handlerTrace -> String)
-> ([Trace peerAddr handlerTrace] -> String -> String)
-> Show (Trace peerAddr handlerTrace)
forall a.
(Int -> a -> String -> String)
-> (a -> String) -> ([a] -> String -> String) -> Show a
forall peerAddr handlerTrace.
(Show handlerTrace, Show peerAddr) =>
Int -> Trace peerAddr handlerTrace -> String -> String
forall peerAddr handlerTrace.
(Show handlerTrace, Show peerAddr) =>
[Trace peerAddr handlerTrace] -> String -> String
forall peerAddr handlerTrace.
(Show handlerTrace, Show peerAddr) =>
Trace peerAddr handlerTrace -> String
$cshowsPrec :: forall peerAddr handlerTrace.
(Show handlerTrace, Show peerAddr) =>
Int -> Trace peerAddr handlerTrace -> String -> String
showsPrec :: Int -> Trace peerAddr handlerTrace -> String -> String
$cshow :: forall peerAddr handlerTrace.
(Show handlerTrace, Show peerAddr) =>
Trace peerAddr handlerTrace -> String
show :: Trace peerAddr handlerTrace -> String
$cshowList :: forall peerAddr handlerTrace.
(Show handlerTrace, Show peerAddr) =>
[Trace peerAddr handlerTrace] -> String -> String
showList :: [Trace peerAddr handlerTrace] -> String -> String
Show