-module(epmd_extra). -compile(export_all). -include_lib("eunit/include/eunit.hrl"). -define(epmd_msg(Bin), <<(size(Bin)):16, Bin/binary>>). -define(alive2_req(PortNum, NodeType, Prot, LVsn, HVsn, NodeName, Extra), ?epmd_msg(<<120, PortNum:16, NodeType, Prot, LVsn:16, HVsn:16, (size(NodeName)):16, NodeName/binary, (size(Extra)):16, Extra/binary>>)). -define(alive2_resp(Res, Creation), <<121, Res, Creation:16>>). -define(port_please2_req(NodeName), ?epmd_msg(<<122, NodeName/binary>>)). -define(port2_resp_err(Res), <<119, Res>>). -define(port2_resp_ok(Res, PortNum, NodeType, Prot, HVsn, LVsn, NodeName, Rest), <<119, Res, PortNum:16, NodeType, Prot, HVsn:16, LVsn:16, NLen:16, NodeName:NLen/binary, Rest/binary>>). -record(node_info, {res, port, node_type, prot, lvsn, hvsn, node_name, rest}). port_please(NodeName) -> {ok, S} = gen_tcp:connect("localhost", 4369, [binary, {active, true}]), ok = gen_tcp:send(S, ?port_please2_req(NodeName)), case recv(S) of ?port2_resp_err(Res) -> {error, {port_please2_failed, Res}}; ?port2_resp_ok(Res, PortNum, NodeType, Prot, HVsn, LVsn, NodeName, Rest) -> {ok, #node_info{res=Res, port=PortNum, node_type=NodeType, prot=Prot, lvsn=LVsn, hvsn=HVsn, node_name=NodeName, rest=Rest}} end. recv(S) -> receive {tcp, S, Data} -> <>; {tcp_closed, S} -> <<>> end. register_node(PortNum, NodeName, Extra) -> {ok, S} = gen_tcp:connect("localhost", 4369, [binary, {active, true}]), ok = gen_tcp:send(S, ?alive2_req(PortNum, 72, 0, 5, 5, NodeName, Extra)), receive {tcp, S, ?alive2_resp(0, _Creation)} -> {ok, S}; {tcp, S, ?alive2_resp(Res, _Creation)} -> gen_tcp:close(S), {error, {failed_to_reg, Res}} end. returns_a_valid_empty_extra_test() -> {ok, S} = register_node(4711, <<"foo">>, <<>>), try {ok, NodeInfo} = port_please(<<"foo">>), <<0, 0>> = NodeInfo#node_info.rest after gen_tcp:close(S) end. returns_a_valid_populated_extra_test() -> {ok, S} = register_node(4711, <<"foo">>, <<"ABCD">>), try {ok, NodeInfo} = port_please(<<"foo">>), <<0, 4, "ABCD">> = NodeInfo#node_info.rest after gen_tcp:close(S) end. returns_an_extra_containing_null_test() -> {ok, S} = register_node(4711, <<"foo">>, <<$A, 0, 0>>), try {ok, NodeInfo} = port_please(<<"foo">>), <<0, 3, $A, 0, 0>> = NodeInfo#node_info.rest after gen_tcp:close(S) end.