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) -- FIXME return RegisteredNode Nothing -> do socketClose sock errorX alreadyExistsErrorType (show $ aliveName node) --------------------------------------------------------------------------------