module Foreign.Erlang.Epmd
    ( -- * List registered nodes
      epmdNames
    , NamesResponse(..)
      -- * Looking up nodes
    , lookupNode
      -- * Registering nodes
    , registerNode
    , NodeRegistration(nr_creation)
    ) where

import           Data.Binary
import           Data.Binary.Get
import           Data.Binary.Put
import qualified Data.ByteString            as BS
import qualified Data.ByteString.Lazy.Char8 as CL
import           Data.Maybe

import           Foreign.Erlang.NodeData
import           Network.BufferedSocket
import           Util.Binary
import           Util.BufferedIOx
import           Util.IOExtra
import           Util.Socket

--------------------------------------------------------------------------------
epmdPort :: Word16
epmdPort :: Word16
epmdPort = Word16
4369

--------------------------------------------------------------------------------
names_req, port_please2_req, port_please2_resp, alive2_req, alive2_resp :: Word8
names_req :: Word8
names_req = Word8
110

port_please2_req :: Word8
port_please2_req = Word8
122

port_please2_resp :: Word8
port_please2_resp = Word8
119

alive2_req :: Word8
alive2_req = Word8
120

alive2_resp :: Word8
alive2_resp = Word8
121

--------------------------------------------------------------------------------
data NamesRequest = NamesRequest
    deriving (NamesRequest -> NamesRequest -> Bool
(NamesRequest -> NamesRequest -> Bool)
-> (NamesRequest -> NamesRequest -> Bool) -> Eq NamesRequest
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: NamesRequest -> NamesRequest -> Bool
$c/= :: NamesRequest -> NamesRequest -> Bool
== :: NamesRequest -> NamesRequest -> Bool
$c== :: NamesRequest -> NamesRequest -> Bool
Eq, Int -> NamesRequest -> ShowS
[NamesRequest] -> ShowS
NamesRequest -> String
(Int -> NamesRequest -> ShowS)
-> (NamesRequest -> String)
-> ([NamesRequest] -> ShowS)
-> Show NamesRequest
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [NamesRequest] -> ShowS
$cshowList :: [NamesRequest] -> ShowS
show :: NamesRequest -> String
$cshow :: NamesRequest -> String
showsPrec :: Int -> NamesRequest -> ShowS
$cshowsPrec :: Int -> NamesRequest -> ShowS
Show)

instance Binary NamesRequest where
    put :: NamesRequest -> Put
put NamesRequest
_ = HasCallStack => Put -> Put
Put -> Put
putWithLength16be (Put -> Put) -> Put -> Put
forall a b. (a -> b) -> a -> b
$
        Word8 -> Put
putWord8 Word8
names_req
    get :: Get NamesRequest
get = Get NamesRequest
forall a. HasCallStack => a
undefined

data NodeInfo = NodeInfo String Word16
    deriving (NodeInfo -> NodeInfo -> Bool
(NodeInfo -> NodeInfo -> Bool)
-> (NodeInfo -> NodeInfo -> Bool) -> Eq NodeInfo
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: NodeInfo -> NodeInfo -> Bool
$c/= :: NodeInfo -> NodeInfo -> Bool
== :: NodeInfo -> NodeInfo -> Bool
$c== :: NodeInfo -> NodeInfo -> Bool
Eq, Int -> NodeInfo -> ShowS
[NodeInfo] -> ShowS
NodeInfo -> String
(Int -> NodeInfo -> ShowS)
-> (NodeInfo -> String) -> ([NodeInfo] -> ShowS) -> Show NodeInfo
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [NodeInfo] -> ShowS
$cshowList :: [NodeInfo] -> ShowS
show :: NodeInfo -> String
$cshow :: NodeInfo -> String
showsPrec :: Int -> NodeInfo -> ShowS
$cshowsPrec :: Int -> NodeInfo -> ShowS
Show)

data NamesResponse = NamesResponse Word16 [NodeInfo]
    deriving (NamesResponse -> NamesResponse -> Bool
(NamesResponse -> NamesResponse -> Bool)
-> (NamesResponse -> NamesResponse -> Bool) -> Eq NamesResponse
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: NamesResponse -> NamesResponse -> Bool
$c/= :: NamesResponse -> NamesResponse -> Bool
== :: NamesResponse -> NamesResponse -> Bool
$c== :: NamesResponse -> NamesResponse -> Bool
Eq, Int -> NamesResponse -> ShowS
[NamesResponse] -> ShowS
NamesResponse -> String
(Int -> NamesResponse -> ShowS)
-> (NamesResponse -> String)
-> ([NamesResponse] -> ShowS)
-> Show NamesResponse
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [NamesResponse] -> ShowS
$cshowList :: [NamesResponse] -> ShowS
show :: NamesResponse -> String
$cshow :: NamesResponse -> String
showsPrec :: Int -> NamesResponse -> ShowS
$cshowsPrec :: Int -> NamesResponse -> ShowS
Show)

instance Binary NamesResponse where
    put :: NamesResponse -> Put
put NamesResponse
_ = Put
forall a. HasCallStack => a
undefined
    get :: Get NamesResponse
get = do
        Word32
epmdPortNo <- Get Word32
getWord32be
        ByteString
nodeInfos <- Get ByteString
getRemainingLazyByteString
        NamesResponse -> Get NamesResponse
forall (m :: * -> *) a. Monad m => a -> m a
return (NamesResponse -> Get NamesResponse)
-> NamesResponse -> Get NamesResponse
forall a b. (a -> b) -> a -> b
$
            Word16 -> [NodeInfo] -> NamesResponse
NamesResponse (Word32 -> Word16
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word32
epmdPortNo)
                          ([Maybe NodeInfo] -> [NodeInfo]
forall a. [Maybe a] -> [a]
catMaybes ((ByteString -> Maybe NodeInfo) -> [ByteString] -> [Maybe NodeInfo]
forall a b. (a -> b) -> [a] -> [b]
map ByteString -> Maybe NodeInfo
nodeInfo (ByteString -> [ByteString]
CL.lines ByteString
nodeInfos)))
      where
        nodeInfo :: CL.ByteString -> Maybe NodeInfo
        nodeInfo :: ByteString -> Maybe NodeInfo
nodeInfo ByteString
cl = do
            [ ByteString
"name", ByteString
name, ByteString
"at", ByteString
"port", ByteString
portString ] <- [ByteString] -> Maybe [ByteString]
forall a. a -> Maybe a
Just ([ByteString] -> Maybe [ByteString])
-> [ByteString] -> Maybe [ByteString]
forall a b. (a -> b) -> a -> b
$ Char -> ByteString -> [ByteString]
CL.split Char
' ' ByteString
cl
            (Int
port, ByteString
"") <- ByteString -> Maybe (Int, ByteString)
CL.readInt ByteString
portString
            NodeInfo -> Maybe NodeInfo
forall (m :: * -> *) a. Monad m => a -> m a
return (NodeInfo -> Maybe NodeInfo) -> NodeInfo -> Maybe NodeInfo
forall a b. (a -> b) -> a -> b
$ String -> Word16 -> NodeInfo
NodeInfo (ByteString -> String
CL.unpack ByteString
name) (Int -> Word16
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
port)

-- | List all registered nodes
epmdNames :: (MonadMask m, MonadResource m, MonadLogger m)
          => BS.ByteString -- ^ hostname
          -> m NamesResponse
epmdNames :: ByteString -> m NamesResponse
epmdNames ByteString
hostName = ByteString
-> (BufferedSocket -> m NamesResponse) -> m NamesResponse
forall (m :: * -> *) b.
(MonadIO m, MonadMask m) =>
ByteString -> (BufferedSocket -> m b) -> m b
withBufferedSocket ByteString
hostName (NamesRequest -> BufferedSocket -> m NamesResponse
forall (m :: * -> *) s a b.
(MonadLogger m, MonadMask m, MonadIO m, BufferedIOx s, Binary a,
 Binary b) =>
a -> s -> m b
sendRequest NamesRequest
NamesRequest)

--------------------------------------------------------------------------------
newtype LookupNodeRequest = LookupNodeRequest BS.ByteString
    deriving (LookupNodeRequest -> LookupNodeRequest -> Bool
(LookupNodeRequest -> LookupNodeRequest -> Bool)
-> (LookupNodeRequest -> LookupNodeRequest -> Bool)
-> Eq LookupNodeRequest
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: LookupNodeRequest -> LookupNodeRequest -> Bool
$c/= :: LookupNodeRequest -> LookupNodeRequest -> Bool
== :: LookupNodeRequest -> LookupNodeRequest -> Bool
$c== :: LookupNodeRequest -> LookupNodeRequest -> Bool
Eq, Int -> LookupNodeRequest -> ShowS
[LookupNodeRequest] -> ShowS
LookupNodeRequest -> String
(Int -> LookupNodeRequest -> ShowS)
-> (LookupNodeRequest -> String)
-> ([LookupNodeRequest] -> ShowS)
-> Show LookupNodeRequest
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [LookupNodeRequest] -> ShowS
$cshowList :: [LookupNodeRequest] -> ShowS
show :: LookupNodeRequest -> String
$cshow :: LookupNodeRequest -> String
showsPrec :: Int -> LookupNodeRequest -> ShowS
$cshowsPrec :: Int -> LookupNodeRequest -> ShowS
Show)

instance Binary LookupNodeRequest where
    put :: LookupNodeRequest -> Put
put (LookupNodeRequest ByteString
alive) =
        HasCallStack => Put -> Put
Put -> Put
putWithLength16be (Put -> Put) -> Put -> Put
forall a b. (a -> b) -> a -> b
$ do
            Word8 -> Put
putWord8 Word8
port_please2_req
            ByteString -> Put
putByteString ByteString
alive
    get :: Get LookupNodeRequest
get = Get LookupNodeRequest
forall a. HasCallStack => a
undefined

newtype LookupNodeResponse =
      LookupNodeResponse { LookupNodeResponse -> Maybe NodeData
fromLookupNodeResponse :: Maybe NodeData }
    deriving (LookupNodeResponse -> LookupNodeResponse -> Bool
(LookupNodeResponse -> LookupNodeResponse -> Bool)
-> (LookupNodeResponse -> LookupNodeResponse -> Bool)
-> Eq LookupNodeResponse
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: LookupNodeResponse -> LookupNodeResponse -> Bool
$c/= :: LookupNodeResponse -> LookupNodeResponse -> Bool
== :: LookupNodeResponse -> LookupNodeResponse -> Bool
$c== :: LookupNodeResponse -> LookupNodeResponse -> Bool
Eq, Int -> LookupNodeResponse -> ShowS
[LookupNodeResponse] -> ShowS
LookupNodeResponse -> String
(Int -> LookupNodeResponse -> ShowS)
-> (LookupNodeResponse -> String)
-> ([LookupNodeResponse] -> ShowS)
-> Show LookupNodeResponse
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [LookupNodeResponse] -> ShowS
$cshowList :: [LookupNodeResponse] -> ShowS
show :: LookupNodeResponse -> String
$cshow :: LookupNodeResponse -> String
showsPrec :: Int -> LookupNodeResponse -> ShowS
$cshowsPrec :: Int -> LookupNodeResponse -> ShowS
Show)

instance Binary LookupNodeResponse where
    put :: LookupNodeResponse -> Put
put LookupNodeResponse
_ = Put
forall a. HasCallStack => a
undefined
    get :: Get LookupNodeResponse
get = Maybe NodeData -> LookupNodeResponse
LookupNodeResponse (Maybe NodeData -> LookupNodeResponse)
-> Get (Maybe NodeData) -> Get LookupNodeResponse
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> do
                                 HasCallStack => Word8 -> Get ()
Word8 -> Get ()
matchWord8 Word8
port_please2_resp
                                 Word8
result <- Get Word8
getWord8
                                 if Word8
result Word8 -> Word8 -> Bool
forall a. Ord a => a -> a -> Bool
> Word8
0
                                     then Maybe NodeData -> Get (Maybe NodeData)
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe NodeData
forall a. Maybe a
Nothing
                                     else NodeData -> Maybe NodeData
forall a. a -> Maybe a
Just (NodeData -> Maybe NodeData)
-> Get NodeData -> Get (Maybe NodeData)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Get NodeData
forall t. Binary t => Get t
get

-- | Lookup a node
lookupNode :: (MonadMask m, MonadResource m, MonadLogger m)
           => BS.ByteString -- ^ alive
           -> BS.ByteString -- ^ hostname
           -> m (Maybe NodeData)
lookupNode :: ByteString -> ByteString -> m (Maybe NodeData)
lookupNode ByteString
alive ByteString
hostName =
    LookupNodeResponse -> Maybe NodeData
fromLookupNodeResponse (LookupNodeResponse -> Maybe NodeData)
-> m LookupNodeResponse -> m (Maybe NodeData)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ByteString
-> (BufferedSocket -> m LookupNodeResponse) -> m LookupNodeResponse
forall (m :: * -> *) b.
(MonadIO m, MonadMask m) =>
ByteString -> (BufferedSocket -> m b) -> m b
withBufferedSocket ByteString
hostName
                                                  (LookupNodeRequest -> BufferedSocket -> m LookupNodeResponse
forall (m :: * -> *) s a b.
(MonadLogger m, MonadMask m, MonadIO m, BufferedIOx s, Binary a,
 Binary b) =>
a -> s -> m b
sendRequest
                                                       (ByteString -> LookupNodeRequest
LookupNodeRequest ByteString
alive))

--------------------------------------------------------------------------------
data RegisterNodeRequest = RegisterNodeRequest NodeData
    deriving (RegisterNodeRequest -> RegisterNodeRequest -> Bool
(RegisterNodeRequest -> RegisterNodeRequest -> Bool)
-> (RegisterNodeRequest -> RegisterNodeRequest -> Bool)
-> Eq RegisterNodeRequest
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: RegisterNodeRequest -> RegisterNodeRequest -> Bool
$c/= :: RegisterNodeRequest -> RegisterNodeRequest -> Bool
== :: RegisterNodeRequest -> RegisterNodeRequest -> Bool
$c== :: RegisterNodeRequest -> RegisterNodeRequest -> Bool
Eq, Int -> RegisterNodeRequest -> ShowS
[RegisterNodeRequest] -> ShowS
RegisterNodeRequest -> String
(Int -> RegisterNodeRequest -> ShowS)
-> (RegisterNodeRequest -> String)
-> ([RegisterNodeRequest] -> ShowS)
-> Show RegisterNodeRequest
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [RegisterNodeRequest] -> ShowS
$cshowList :: [RegisterNodeRequest] -> ShowS
show :: RegisterNodeRequest -> String
$cshow :: RegisterNodeRequest -> String
showsPrec :: Int -> RegisterNodeRequest -> ShowS
$cshowsPrec :: Int -> RegisterNodeRequest -> ShowS
Show)

instance Binary RegisterNodeRequest where
    put :: RegisterNodeRequest -> Put
put (RegisterNodeRequest NodeData
node) =
        HasCallStack => Put -> Put
Put -> Put
putWithLength16be (Put -> Put) -> Put -> Put
forall a b. (a -> b) -> a -> b
$ do
            Word8 -> Put
putWord8 Word8
alive2_req
            NodeData -> Put
forall t. Binary t => t -> Put
put NodeData
node
    get :: Get RegisterNodeRequest
get = Get RegisterNodeRequest
forall a. HasCallStack => a
undefined

data RegisterNodeResponse = RegisterNodeResponse (Maybe Word16)
    deriving (RegisterNodeResponse -> RegisterNodeResponse -> Bool
(RegisterNodeResponse -> RegisterNodeResponse -> Bool)
-> (RegisterNodeResponse -> RegisterNodeResponse -> Bool)
-> Eq RegisterNodeResponse
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: RegisterNodeResponse -> RegisterNodeResponse -> Bool
$c/= :: RegisterNodeResponse -> RegisterNodeResponse -> Bool
== :: RegisterNodeResponse -> RegisterNodeResponse -> Bool
$c== :: RegisterNodeResponse -> RegisterNodeResponse -> Bool
Eq, Int -> RegisterNodeResponse -> ShowS
[RegisterNodeResponse] -> ShowS
RegisterNodeResponse -> String
(Int -> RegisterNodeResponse -> ShowS)
-> (RegisterNodeResponse -> String)
-> ([RegisterNodeResponse] -> ShowS)
-> Show RegisterNodeResponse
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [RegisterNodeResponse] -> ShowS
$cshowList :: [RegisterNodeResponse] -> ShowS
show :: RegisterNodeResponse -> String
$cshow :: RegisterNodeResponse -> String
showsPrec :: Int -> RegisterNodeResponse -> ShowS
$cshowsPrec :: Int -> RegisterNodeResponse -> ShowS
Show)

instance Binary RegisterNodeResponse where
    put :: RegisterNodeResponse -> Put
put RegisterNodeResponse
_ = Put
forall a. HasCallStack => a
undefined
    get :: Get RegisterNodeResponse
get = Maybe Word16 -> RegisterNodeResponse
RegisterNodeResponse (Maybe Word16 -> RegisterNodeResponse)
-> Get (Maybe Word16) -> Get RegisterNodeResponse
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> do
                                   HasCallStack => Word8 -> Get ()
Word8 -> Get ()
matchWord8 Word8
alive2_resp
                                   Word8
result <- Get Word8
getWord8
                                   if Word8
result Word8 -> Word8 -> Bool
forall a. Ord a => a -> a -> Bool
> Word8
0
                                       then Maybe Word16 -> Get (Maybe Word16)
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe Word16
forall a. Maybe a
Nothing
                                       else Word16 -> Maybe Word16
forall a. a -> Maybe a
Just (Word16 -> Maybe Word16) -> Get Word16 -> Get (Maybe Word16)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Get Word16
getWord16be

newtype NodeRegistration = NodeRegistration { NodeRegistration -> Word16
nr_creation :: Word16 }

newtype NodeAlreadyRegistered = NodeAlreadyRegistered NodeData
    deriving (Int -> NodeAlreadyRegistered -> ShowS
[NodeAlreadyRegistered] -> ShowS
NodeAlreadyRegistered -> String
(Int -> NodeAlreadyRegistered -> ShowS)
-> (NodeAlreadyRegistered -> String)
-> ([NodeAlreadyRegistered] -> ShowS)
-> Show NodeAlreadyRegistered
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [NodeAlreadyRegistered] -> ShowS
$cshowList :: [NodeAlreadyRegistered] -> ShowS
show :: NodeAlreadyRegistered -> String
$cshow :: NodeAlreadyRegistered -> String
showsPrec :: Int -> NodeAlreadyRegistered -> ShowS
$cshowsPrec :: Int -> NodeAlreadyRegistered -> ShowS
Show)

instance Exception NodeAlreadyRegistered

-- | Register a node with an epmd; as long as the TCP connection is open, the
-- registration is considered valid.
registerNode :: (MonadResource m, MonadLogger m, MonadMask m)
             => NodeData -- ^ node
             -> BS.ByteString -- ^ hostName
             -> (NodeRegistration -> m a) -- ^ action to execute while the TCP connection is alive
             -> m a
registerNode :: NodeData -> ByteString -> (NodeRegistration -> m a) -> m a
registerNode NodeData
node ByteString
hostName NodeRegistration -> m a
action =
    ByteString -> (BufferedSocket -> m a) -> m a
forall (m :: * -> *) b.
(MonadIO m, MonadMask m) =>
ByteString -> (BufferedSocket -> m b) -> m b
withBufferedSocket ByteString
hostName BufferedSocket -> m a
forall s. BufferedIOx s => s -> m a
go
  where
    go :: s -> m a
go s
sock = do
        r :: RegisterNodeResponse
r@(RegisterNodeResponse Maybe Word16
mr) <- RegisterNodeRequest -> s -> m RegisterNodeResponse
forall (m :: * -> *) s a b.
(MonadLogger m, MonadMask m, MonadIO m, BufferedIOx s, Binary a,
 Binary b) =>
a -> s -> m b
sendRequest (NodeData -> RegisterNodeRequest
RegisterNodeRequest NodeData
node)
                                                   s
sock
        RegisterNodeResponse -> m ()
forall s (m :: * -> *).
(HasCallStack, Show s, MonadLogger m) =>
s -> m ()
logInfoShow RegisterNodeResponse
r
        Bool -> m () -> m ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Maybe Word16 -> Bool
forall a. Maybe a -> Bool
isNothing Maybe Word16
mr) (NodeAlreadyRegistered -> m ()
forall (m :: * -> *) e a. (MonadThrow m, Exception e) => e -> m a
throwM (NodeData -> NodeAlreadyRegistered
NodeAlreadyRegistered NodeData
node))
        NodeRegistration -> m a
action (Word16 -> NodeRegistration
NodeRegistration (Maybe Word16 -> Word16
forall a. HasCallStack => Maybe a -> a
fromJust Maybe Word16
mr))

sendRequest :: (MonadLogger m, MonadMask m, MonadIO m, BufferedIOx s, Binary a, Binary b)
            => a
            -> s
            -> m b
sendRequest :: a -> s -> m b
sendRequest a
req s
sock = do
    IO () -> m ()
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> m ()) -> IO () -> m ()
forall a b. (a -> b) -> a -> b
$ s -> a -> IO ()
forall (m :: * -> *) s a.
(MonadIO m, BufferedIOx s, Binary a) =>
s -> a -> m ()
runPutBuffered s
sock a
req
    s -> m b
forall (m :: * -> *) s a.
(MonadIO m, BufferedIOx s, Binary a, MonadMask m, MonadLogger m) =>
s -> m a
runGetBuffered s
sock

withBufferedSocket :: (MonadIO m, MonadMask m)
                   => BS.ByteString -- ^ hostName
                   -> (BufferedSocket -> m b)
                   -> m b
withBufferedSocket :: ByteString -> (BufferedSocket -> m b) -> m b
withBufferedSocket ByteString
hostName =
    m BufferedSocket
-> (BufferedSocket -> m ()) -> (BufferedSocket -> m b) -> m b
forall (m :: * -> *) a c b.
MonadMask m =>
m a -> (a -> m c) -> (a -> m b) -> m b
bracket (IO BufferedSocket -> m BufferedSocket
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO BufferedSocket -> m BufferedSocket)
-> IO BufferedSocket -> m BufferedSocket
forall a b. (a -> b) -> a -> b
$ ByteString -> IO BufferedSocket
forall (m :: * -> *). MonadIO m => ByteString -> m BufferedSocket
connectBufferedSocket ByteString
hostName) (IO () -> m ()
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> m ())
-> (BufferedSocket -> IO ()) -> BufferedSocket -> m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. BufferedSocket -> IO ()
forall a (m :: * -> *). (BufferedIOx a, MonadIO m) => a -> m ()
closeBuffered)

connectBufferedSocket :: (MonadIO m)
                      => BS.ByteString -- ^ hostName
                      -> m BufferedSocket
connectBufferedSocket :: ByteString -> m BufferedSocket
connectBufferedSocket ByteString
hostName =
    IO BufferedSocket -> m BufferedSocket
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO BufferedSocket -> m BufferedSocket)
-> IO BufferedSocket -> m BufferedSocket
forall a b. (a -> b) -> a -> b
$
        ByteString -> Word16 -> IO Socket
connectSocket ByteString
hostName Word16
epmdPort IO Socket -> (Socket -> IO BufferedSocket) -> IO BufferedSocket
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Socket -> IO BufferedSocket
makeBuffered