module Control.Distributed.Process.Internal.Messaging
  ( sendPayload
  , sendBinary
  , sendMessage
  , disconnect
  , closeImplicitReconnections
  , impliesDeathOf
  , sendCtrlMsg
  ) where

import Data.Accessor ((^.), (^=))
import Data.Binary (Binary, encode)
import qualified Data.Map as Map (partitionWithKey, elems)
import qualified Data.ByteString.Lazy as BSL (toChunks)
import qualified Data.ByteString as BSS (ByteString)
import Control.Distributed.Process.Serializable ()

import Control.Concurrent (forkIO)
import Control.Concurrent.Chan (writeChan)
import Control.Exception (mask_)
import Control.Monad (unless)
import Control.Monad.IO.Class (liftIO)
import Control.Monad.Reader (ask)
import qualified Network.Transport as NT
  ( Connection
  , send
  , defaultConnectHints
  , connect
  , Reliability(ReliableOrdered)
  , close
  )
import Control.Distributed.Process.Internal.Types
  ( LocalNode(localEndPoint, localCtrlChan)
  , withValidLocalState
  , modifyValidLocalState
  , modifyValidLocalState_
  , Identifier
  , localConnections
  , localConnectionBetween
  , nodeAddress
  , nodeOf
  , messageToPayload
  , createMessage
  , NCMsg(..)
  , ProcessSignal(Died)
  , DiedReason(DiedDisconnect)
  , ImplicitReconnect(WithImplicitReconnect)
  , NodeId(..)
  , ProcessId(..)
  , LocalNode(..)
  , LocalProcess(..)
  , Process(..)
  , SendPortId(sendPortProcessId)
  , Identifier(NodeIdentifier, ProcessIdentifier, SendPortIdentifier)
  )
import Control.Distributed.Process.Serializable (Serializable)
import Data.Foldable (forM_)

--------------------------------------------------------------------------------
-- Message sending                                                            --
--------------------------------------------------------------------------------

sendPayload :: LocalNode
            -> Identifier
            -> Identifier
            -> ImplicitReconnect
            -> [BSS.ByteString]
            -> IO ()
sendPayload :: LocalNode
-> Identifier
-> Identifier
-> ImplicitReconnect
-> [ByteString]
-> IO ()
sendPayload LocalNode
node Identifier
from Identifier
to ImplicitReconnect
implicitReconnect [ByteString]
payload = do
  Maybe Connection
mConn <- LocalNode
-> Identifier
-> Identifier
-> ImplicitReconnect
-> IO (Maybe Connection)
connBetween LocalNode
node Identifier
from Identifier
to ImplicitReconnect
implicitReconnect
  Bool
didSend <- case Maybe Connection
mConn of
    Just Connection
conn -> do
      Either (TransportError SendErrorCode) ()
didSend <- Connection
-> [ByteString] -> IO (Either (TransportError SendErrorCode) ())
NT.send Connection
conn [ByteString]
payload
      case Either (TransportError SendErrorCode) ()
didSend of
        Left TransportError SendErrorCode
_err -> Bool -> IO Bool
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return Bool
False
        Right ()  -> Bool -> IO Bool
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return Bool
True
    Maybe Connection
Nothing -> Bool -> IO Bool
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return Bool
False
  Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless Bool
didSend (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$ do
    Chan NCMsg -> NCMsg -> IO ()
forall a. Chan a -> a -> IO ()
writeChan (LocalNode -> Chan NCMsg
localCtrlChan LocalNode
node) NCMsg
      { ctrlMsgSender :: Identifier
ctrlMsgSender = Identifier
to
      , ctrlMsgSignal :: ProcessSignal
ctrlMsgSignal = Identifier -> DiedReason -> ProcessSignal
Died (NodeId -> Identifier
NodeIdentifier (NodeId -> Identifier) -> NodeId -> Identifier
forall a b. (a -> b) -> a -> b
$ Identifier -> NodeId
nodeOf Identifier
to) DiedReason
DiedDisconnect
      }

sendBinary :: Binary a
           => LocalNode
           -> Identifier
           -> Identifier
           -> ImplicitReconnect
           -> a
           -> IO ()
sendBinary :: forall a.
Binary a =>
LocalNode
-> Identifier -> Identifier -> ImplicitReconnect -> a -> IO ()
sendBinary LocalNode
node Identifier
from Identifier
to ImplicitReconnect
implicitReconnect
  = LocalNode
-> Identifier
-> Identifier
-> ImplicitReconnect
-> [ByteString]
-> IO ()
sendPayload LocalNode
node Identifier
from Identifier
to ImplicitReconnect
implicitReconnect ([ByteString] -> IO ()) -> (a -> [ByteString]) -> a -> IO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. LazyByteString -> [ByteString]
BSL.toChunks (LazyByteString -> [ByteString])
-> (a -> LazyByteString) -> a -> [ByteString]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> LazyByteString
forall a. Binary a => a -> LazyByteString
encode

sendMessage :: Serializable a
            => LocalNode
            -> Identifier
            -> Identifier
            -> ImplicitReconnect
            -> a
            -> IO ()
sendMessage :: forall a.
Serializable a =>
LocalNode
-> Identifier -> Identifier -> ImplicitReconnect -> a -> IO ()
sendMessage LocalNode
node Identifier
from Identifier
to ImplicitReconnect
implicitReconnect =
  LocalNode
-> Identifier
-> Identifier
-> ImplicitReconnect
-> [ByteString]
-> IO ()
sendPayload LocalNode
node Identifier
from Identifier
to ImplicitReconnect
implicitReconnect ([ByteString] -> IO ()) -> (a -> [ByteString]) -> a -> IO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Message -> [ByteString]
messageToPayload (Message -> [ByteString]) -> (a -> Message) -> a -> [ByteString]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> Message
forall a. Serializable a => a -> Message
createMessage

setupConnBetween :: LocalNode
                 -> Identifier
                 -> Identifier
                 -> ImplicitReconnect
                 -> IO (Maybe NT.Connection)
setupConnBetween :: LocalNode
-> Identifier
-> Identifier
-> ImplicitReconnect
-> IO (Maybe Connection)
setupConnBetween LocalNode
node Identifier
from Identifier
to ImplicitReconnect
implicitReconnect = do
    Either (TransportError ConnectErrorCode) Connection
mConn <- EndPoint
-> EndPointAddress
-> Reliability
-> ConnectHints
-> IO (Either (TransportError ConnectErrorCode) Connection)
NT.connect (LocalNode -> EndPoint
localEndPoint LocalNode
node)
                        (NodeId -> EndPointAddress
nodeAddress (NodeId -> EndPointAddress)
-> (Identifier -> NodeId) -> Identifier -> EndPointAddress
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Identifier -> NodeId
nodeOf (Identifier -> EndPointAddress) -> Identifier -> EndPointAddress
forall a b. (a -> b) -> a -> b
$ Identifier
to)
                        Reliability
NT.ReliableOrdered
                        ConnectHints
NT.defaultConnectHints
    case Either (TransportError ConnectErrorCode) Connection
mConn of
      Right Connection
conn -> do
        Either (TransportError SendErrorCode) ()
didSend <- Connection
-> [ByteString] -> IO (Either (TransportError SendErrorCode) ())
NT.send Connection
conn (LazyByteString -> [ByteString]
BSL.toChunks (LazyByteString -> [ByteString])
-> (Identifier -> LazyByteString) -> Identifier -> [ByteString]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Identifier -> LazyByteString
forall a. Binary a => a -> LazyByteString
encode (Identifier -> [ByteString]) -> Identifier -> [ByteString]
forall a b. (a -> b) -> a -> b
$ Identifier
to)
        case Either (TransportError SendErrorCode) ()
didSend of
          Left TransportError SendErrorCode
_ ->
            Maybe Connection -> IO (Maybe Connection)
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe Connection
forall a. Maybe a
Nothing
          Right () -> do
            LocalNode
-> (ValidLocalNodeState -> IO ValidLocalNodeState) -> IO ()
modifyValidLocalState_ LocalNode
node ((ValidLocalNodeState -> IO ValidLocalNodeState) -> IO ())
-> (ValidLocalNodeState -> IO ValidLocalNodeState) -> IO ()
forall a b. (a -> b) -> a -> b
$
              ValidLocalNodeState -> IO ValidLocalNodeState
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (ValidLocalNodeState -> IO ValidLocalNodeState)
-> (ValidLocalNodeState -> ValidLocalNodeState)
-> ValidLocalNodeState
-> IO ValidLocalNodeState
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Identifier
-> Identifier
-> Accessor
     ValidLocalNodeState (Maybe (Connection, ImplicitReconnect))
localConnectionBetween Identifier
from Identifier
to Accessor
  ValidLocalNodeState (Maybe (Connection, ImplicitReconnect))
-> Maybe (Connection, ImplicitReconnect)
-> ValidLocalNodeState
-> ValidLocalNodeState
forall r a. T r a -> a -> r -> r
^= (Connection, ImplicitReconnect)
-> Maybe (Connection, ImplicitReconnect)
forall a. a -> Maybe a
Just (Connection
conn, ImplicitReconnect
implicitReconnect))
            Maybe Connection -> IO (Maybe Connection)
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (Maybe Connection -> IO (Maybe Connection))
-> Maybe Connection -> IO (Maybe Connection)
forall a b. (a -> b) -> a -> b
$ Connection -> Maybe Connection
forall a. a -> Maybe a
Just Connection
conn
      Left TransportError ConnectErrorCode
_ ->
        Maybe Connection -> IO (Maybe Connection)
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe Connection
forall a. Maybe a
Nothing

connBetween :: LocalNode
            -> Identifier
            -> Identifier
            -> ImplicitReconnect
            -> IO (Maybe NT.Connection)
connBetween :: LocalNode
-> Identifier
-> Identifier
-> ImplicitReconnect
-> IO (Maybe Connection)
connBetween LocalNode
node Identifier
from Identifier
to ImplicitReconnect
implicitReconnect = do
    Maybe (Connection, ImplicitReconnect)
mConn <- LocalNode
-> (ValidLocalNodeState
    -> IO (Maybe (Connection, ImplicitReconnect)))
-> IO (Maybe (Connection, ImplicitReconnect))
forall r. LocalNode -> (ValidLocalNodeState -> IO r) -> IO r
withValidLocalState LocalNode
node ((ValidLocalNodeState
  -> IO (Maybe (Connection, ImplicitReconnect)))
 -> IO (Maybe (Connection, ImplicitReconnect)))
-> (ValidLocalNodeState
    -> IO (Maybe (Connection, ImplicitReconnect)))
-> IO (Maybe (Connection, ImplicitReconnect))
forall a b. (a -> b) -> a -> b
$
      Maybe (Connection, ImplicitReconnect)
-> IO (Maybe (Connection, ImplicitReconnect))
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (Maybe (Connection, ImplicitReconnect)
 -> IO (Maybe (Connection, ImplicitReconnect)))
-> (ValidLocalNodeState -> Maybe (Connection, ImplicitReconnect))
-> ValidLocalNodeState
-> IO (Maybe (Connection, ImplicitReconnect))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (ValidLocalNodeState
-> Accessor
     ValidLocalNodeState (Maybe (Connection, ImplicitReconnect))
-> Maybe (Connection, ImplicitReconnect)
forall r a. r -> T r a -> a
^. Identifier
-> Identifier
-> Accessor
     ValidLocalNodeState (Maybe (Connection, ImplicitReconnect))
localConnectionBetween Identifier
from Identifier
to)
    case Maybe (Connection, ImplicitReconnect)
mConn of
      Just (Connection
conn, ImplicitReconnect
_) ->
        Maybe Connection -> IO (Maybe Connection)
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (Maybe Connection -> IO (Maybe Connection))
-> Maybe Connection -> IO (Maybe Connection)
forall a b. (a -> b) -> a -> b
$ Connection -> Maybe Connection
forall a. a -> Maybe a
Just Connection
conn
      Maybe (Connection, ImplicitReconnect)
Nothing ->
        LocalNode
-> Identifier
-> Identifier
-> ImplicitReconnect
-> IO (Maybe Connection)
setupConnBetween LocalNode
node Identifier
from Identifier
to ImplicitReconnect
implicitReconnect

disconnect :: LocalNode -> Identifier -> Identifier -> IO ()
disconnect :: LocalNode -> Identifier -> Identifier -> IO ()
disconnect LocalNode
node Identifier
from Identifier
to = IO () -> IO ()
forall a. IO a -> IO a
mask_ (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$ do
  Maybe (IO ())
mio <- LocalNode
-> (ValidLocalNodeState -> IO (ValidLocalNodeState, IO ()))
-> IO (Maybe (IO ()))
forall a.
LocalNode
-> (ValidLocalNodeState -> IO (ValidLocalNodeState, a))
-> IO (Maybe a)
modifyValidLocalState LocalNode
node ((ValidLocalNodeState -> IO (ValidLocalNodeState, IO ()))
 -> IO (Maybe (IO ())))
-> (ValidLocalNodeState -> IO (ValidLocalNodeState, IO ()))
-> IO (Maybe (IO ()))
forall a b. (a -> b) -> a -> b
$ \ValidLocalNodeState
vst ->
    case ValidLocalNodeState
vst ValidLocalNodeState
-> Accessor
     ValidLocalNodeState (Maybe (Connection, ImplicitReconnect))
-> Maybe (Connection, ImplicitReconnect)
forall r a. r -> T r a -> a
^. Identifier
-> Identifier
-> Accessor
     ValidLocalNodeState (Maybe (Connection, ImplicitReconnect))
localConnectionBetween Identifier
from Identifier
to of
      Maybe (Connection, ImplicitReconnect)
Nothing ->
        (ValidLocalNodeState, IO ()) -> IO (ValidLocalNodeState, IO ())
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (ValidLocalNodeState
vst, () -> IO ()
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return ())
      Just (Connection
conn, ImplicitReconnect
_) -> do
        (ValidLocalNodeState, IO ()) -> IO (ValidLocalNodeState, IO ())
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return ( Identifier
-> Identifier
-> Accessor
     ValidLocalNodeState (Maybe (Connection, ImplicitReconnect))
localConnectionBetween Identifier
from Identifier
to Accessor
  ValidLocalNodeState (Maybe (Connection, ImplicitReconnect))
-> Maybe (Connection, ImplicitReconnect)
-> ValidLocalNodeState
-> ValidLocalNodeState
forall r a. T r a -> a -> r -> r
^= Maybe (Connection, ImplicitReconnect)
forall a. Maybe a
Nothing (ValidLocalNodeState -> ValidLocalNodeState)
-> ValidLocalNodeState -> ValidLocalNodeState
forall a b. (a -> b) -> a -> b
$ ValidLocalNodeState
vst
               , Connection -> IO ()
NT.close Connection
conn
               )
  Maybe (IO ()) -> (IO () -> IO ThreadId) -> IO ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ Maybe (IO ())
mio IO () -> IO ThreadId
forkIO

closeImplicitReconnections :: LocalNode -> Identifier -> IO ()
closeImplicitReconnections :: LocalNode -> Identifier -> IO ()
closeImplicitReconnections LocalNode
node Identifier
to = IO () -> IO ()
forall a. IO a -> IO a
mask_ (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$ do
  Maybe [Connection]
mconns <- LocalNode
-> (ValidLocalNodeState -> IO (ValidLocalNodeState, [Connection]))
-> IO (Maybe [Connection])
forall a.
LocalNode
-> (ValidLocalNodeState -> IO (ValidLocalNodeState, a))
-> IO (Maybe a)
modifyValidLocalState LocalNode
node ((ValidLocalNodeState -> IO (ValidLocalNodeState, [Connection]))
 -> IO (Maybe [Connection]))
-> (ValidLocalNodeState -> IO (ValidLocalNodeState, [Connection]))
-> IO (Maybe [Connection])
forall a b. (a -> b) -> a -> b
$ \ValidLocalNodeState
vst -> do
    let shouldClose :: (a, Identifier) -> (a, ImplicitReconnect) -> Bool
shouldClose (a
_, Identifier
to') (a
_, ImplicitReconnect
WithImplicitReconnect) = Identifier
to Identifier -> Identifier -> Bool
`impliesDeathOf` Identifier
to'
        shouldClose (a, Identifier)
_ (a, ImplicitReconnect)
_ = Bool
False
    let (Map (Identifier, Identifier) (Connection, ImplicitReconnect)
affected, Map (Identifier, Identifier) (Connection, ImplicitReconnect)
unaffected) =
          ((Identifier, Identifier)
 -> (Connection, ImplicitReconnect) -> Bool)
-> Map (Identifier, Identifier) (Connection, ImplicitReconnect)
-> (Map (Identifier, Identifier) (Connection, ImplicitReconnect),
    Map (Identifier, Identifier) (Connection, ImplicitReconnect))
forall k a. (k -> a -> Bool) -> Map k a -> (Map k a, Map k a)
Map.partitionWithKey (Identifier, Identifier) -> (Connection, ImplicitReconnect) -> Bool
forall {a} {a}. (a, Identifier) -> (a, ImplicitReconnect) -> Bool
shouldClose (ValidLocalNodeState
vst ValidLocalNodeState
-> T ValidLocalNodeState
     (Map (Identifier, Identifier) (Connection, ImplicitReconnect))
-> Map (Identifier, Identifier) (Connection, ImplicitReconnect)
forall r a. r -> T r a -> a
^. T ValidLocalNodeState
  (Map (Identifier, Identifier) (Connection, ImplicitReconnect))
localConnections)
    (ValidLocalNodeState, [Connection])
-> IO (ValidLocalNodeState, [Connection])
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return ( T ValidLocalNodeState
  (Map (Identifier, Identifier) (Connection, ImplicitReconnect))
localConnections T ValidLocalNodeState
  (Map (Identifier, Identifier) (Connection, ImplicitReconnect))
-> Map (Identifier, Identifier) (Connection, ImplicitReconnect)
-> ValidLocalNodeState
-> ValidLocalNodeState
forall r a. T r a -> a -> r -> r
^= Map (Identifier, Identifier) (Connection, ImplicitReconnect)
unaffected (ValidLocalNodeState -> ValidLocalNodeState)
-> ValidLocalNodeState -> ValidLocalNodeState
forall a b. (a -> b) -> a -> b
$ ValidLocalNodeState
vst
           , ((Connection, ImplicitReconnect) -> Connection)
-> [(Connection, ImplicitReconnect)] -> [Connection]
forall a b. (a -> b) -> [a] -> [b]
map (Connection, ImplicitReconnect) -> Connection
forall a b. (a, b) -> a
fst ([(Connection, ImplicitReconnect)] -> [Connection])
-> [(Connection, ImplicitReconnect)] -> [Connection]
forall a b. (a -> b) -> a -> b
$ Map (Identifier, Identifier) (Connection, ImplicitReconnect)
-> [(Connection, ImplicitReconnect)]
forall k a. Map k a -> [a]
Map.elems Map (Identifier, Identifier) (Connection, ImplicitReconnect)
affected
           )
  Maybe [Connection] -> ([Connection] -> IO ThreadId) -> IO ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ Maybe [Connection]
mconns (([Connection] -> IO ThreadId) -> IO ())
-> ([Connection] -> IO ThreadId) -> IO ()
forall a b. (a -> b) -> a -> b
$ IO () -> IO ThreadId
forkIO (IO () -> IO ThreadId)
-> ([Connection] -> IO ()) -> [Connection] -> IO ThreadId
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Connection -> IO ()) -> [Connection] -> IO ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ Connection -> IO ()
NT.close

-- | @a `impliesDeathOf` b@ is true if the death of @a@ (for instance, a node)
-- implies the death of @b@ (for instance, a process on that node)
impliesDeathOf :: Identifier
               -> Identifier
               -> Bool
NodeIdentifier NodeId
nid impliesDeathOf :: Identifier -> Identifier -> Bool
`impliesDeathOf` NodeIdentifier NodeId
nid' =
  NodeId
nid' NodeId -> NodeId -> Bool
forall a. Eq a => a -> a -> Bool
== NodeId
nid
NodeIdentifier NodeId
nid `impliesDeathOf` ProcessIdentifier ProcessId
pid =
  ProcessId -> NodeId
processNodeId ProcessId
pid NodeId -> NodeId -> Bool
forall a. Eq a => a -> a -> Bool
== NodeId
nid
NodeIdentifier NodeId
nid `impliesDeathOf` SendPortIdentifier SendPortId
cid =
  ProcessId -> NodeId
processNodeId (SendPortId -> ProcessId
sendPortProcessId SendPortId
cid) NodeId -> NodeId -> Bool
forall a. Eq a => a -> a -> Bool
== NodeId
nid
ProcessIdentifier ProcessId
pid `impliesDeathOf` ProcessIdentifier ProcessId
pid' =
  ProcessId
pid' ProcessId -> ProcessId -> Bool
forall a. Eq a => a -> a -> Bool
== ProcessId
pid
ProcessIdentifier ProcessId
pid `impliesDeathOf` SendPortIdentifier SendPortId
cid =
  SendPortId -> ProcessId
sendPortProcessId SendPortId
cid ProcessId -> ProcessId -> Bool
forall a. Eq a => a -> a -> Bool
== ProcessId
pid
SendPortIdentifier SendPortId
cid `impliesDeathOf` SendPortIdentifier SendPortId
cid' =
  SendPortId
cid' SendPortId -> SendPortId -> Bool
forall a. Eq a => a -> a -> Bool
== SendPortId
cid
Identifier
_ `impliesDeathOf` Identifier
_ =
  Bool
False


-- Send a control message. Evaluates the message to HNF before sending it.
--
-- The message shouldn't produce more errors when further evaluated. If
-- evaluation threw errors the node controller or the receiver would crash when
-- inspecting it.
sendCtrlMsg :: Maybe NodeId  -- ^ Nothing for the local node
            -> ProcessSignal -- ^ Message to send
            -> Process ()
sendCtrlMsg :: Maybe NodeId -> ProcessSignal -> Process ()
sendCtrlMsg Maybe NodeId
mNid ProcessSignal
signal = do
  LocalProcess
proc <- Process LocalProcess
forall r (m :: * -> *). MonadReader r m => m r
ask
  let msg :: NCMsg
msg = NCMsg { ctrlMsgSender :: Identifier
ctrlMsgSender = ProcessId -> Identifier
ProcessIdentifier (LocalProcess -> ProcessId
processId LocalProcess
proc)
                  , ctrlMsgSignal :: ProcessSignal
ctrlMsgSignal = ProcessSignal
signal
                  }
  case Maybe NodeId
mNid of
    Maybe NodeId
Nothing -> do
      IO () -> Process ()
forall a. IO a -> Process a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> Process ()) -> IO () -> Process ()
forall a b. (a -> b) -> a -> b
$ Chan NCMsg -> NCMsg -> IO ()
forall a. Chan a -> a -> IO ()
writeChan (LocalNode -> Chan NCMsg
localCtrlChan (LocalProcess -> LocalNode
processNode LocalProcess
proc)) (NCMsg -> IO ()) -> NCMsg -> IO ()
forall a b. (a -> b) -> a -> b
$! NCMsg
msg
    Just NodeId
nid ->
      IO () -> Process ()
forall a. IO a -> Process a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> Process ()) -> IO () -> Process ()
forall a b. (a -> b) -> a -> b
$ LocalNode
-> Identifier -> Identifier -> ImplicitReconnect -> NCMsg -> IO ()
forall a.
Binary a =>
LocalNode
-> Identifier -> Identifier -> ImplicitReconnect -> a -> IO ()
sendBinary (LocalProcess -> LocalNode
processNode LocalProcess
proc)
                          (NodeId -> Identifier
NodeIdentifier (ProcessId -> NodeId
processNodeId (ProcessId -> NodeId) -> ProcessId -> NodeId
forall a b. (a -> b) -> a -> b
$ LocalProcess -> ProcessId
processId LocalProcess
proc))
                          (NodeId -> Identifier
NodeIdentifier NodeId
nid)
                          ImplicitReconnect
WithImplicitReconnect
                          NCMsg
msg