module Language.Erlang.Epmd ( epmdNames
, lookupNode
, registerNode
)
where
import qualified Data.ByteString as BS
import qualified Data.ByteString.Lazy as BL
import Data.Binary
import Data.Binary.Put
import Data.Binary.Get
import Util.IOx
import Util.BufferedSocket
import Util.Binary
import Util.Socket
import Util.Util
import Language.Erlang.NodeData
epmdPort :: Word16
epmdPort = 4369
names_req, port_please2_req, port_please2_resp, alive2_req, alive2_resp :: Word8
names_req = 110
port_please2_req = 122
port_please2_resp = 119
alive2_req = 120
alive2_resp = 121
putEpmdNamesRequest :: Put
putEpmdNamesRequest = do
putWord8 names_req
getEpmdNamesResponse :: Get (Word32, BS.ByteString)
getEpmdNamesResponse = do
epmdPortNo <- getWord32be
nodeInfos <- getRemainingLazyByteString
return (epmdPortNo, BL.toStrict nodeInfos)
epmdNames :: BS.ByteString -> IOx (Word32, BS.ByteString)
epmdNames hostName = do
sock <- connectSocket hostName epmdPort >>= makeBuffered
runPutSocket sock (putWithLength16be putEpmdNamesRequest)
(epmdPortNo, nodeInfos) <- runGetSocket sock getEpmdNamesResponse
socketClose sock
return (epmdPortNo, nodeInfos)
putLookupNodeRequest :: BS.ByteString -> Put
putLookupNodeRequest alive = do
putWord8 port_please2_req
putByteString alive
getLookupNodeResponse :: Get (Maybe NodeData)
getLookupNodeResponse = do
matchWord8 port_please2_resp
result <- getWord8
if result > 0 then do
return Nothing
else do
Just <$> get
lookupNode :: BS.ByteString -> BS.ByteString -> IOx NodeData
lookupNode alive hostName = do
sock <- connectSocket hostName epmdPort >>= makeBuffered
runPutSocket sock (putWithLength16be (putLookupNodeRequest alive))
r <- runGetSocket sock getLookupNodeResponse
socketClose sock
case r of
(Just n) -> return n
Nothing -> errorX doesNotExistErrorType (show alive)
putRegisterNodeRequest :: NodeData -> Put
putRegisterNodeRequest node = do
putWord8 alive2_req
put node
getRegisterNodeResponse :: Get (Maybe Word16)
getRegisterNodeResponse = do
matchWord8 alive2_resp
result <- getWord8
if result > 0 then do
return Nothing
else do
creation <- getWord16be
return (Just creation)
registerNode :: NodeData -> BS.ByteString -> IOx (BufferedSocket, Word16)
registerNode node hostName = do
sock <- connectSocket hostName epmdPort >>= makeBuffered
runPutSocket sock (putWithLength16be (putRegisterNodeRequest node))
r <- runGetSocket sock getRegisterNodeResponse
case r of
(Just creation) -> do
return (sock, creation)
Nothing -> do
socketClose sock
errorX alreadyExistsErrorType (show $ aliveName node)