module Foreign.Erlang.Epmd
(
epmdNames
, NamesResponse(..)
, lookupNode
, 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)
epmdNames :: (MonadMask m, MonadResource m, MonadLogger m)
=> BS.ByteString
-> 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
lookupNode :: (MonadMask m, MonadResource m, MonadLogger m)
=> BS.ByteString
-> BS.ByteString
-> 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
registerNode :: (MonadResource m, MonadLogger m, MonadMask m)
=> NodeData
-> BS.ByteString
-> (NodeRegistration -> m a)
-> 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
-> (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
-> 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