Packages
otpbp
7.3.2
7.18.0
7.16.1
7.15.0
7.14.0
7.13.0
7.12.0
7.11.0
7.10.2
7.9.3
7.9.2
7.9.1
7.8.7
7.8.6
7.8.5
7.8.4
7.7.1
7.7.0
7.6.3
7.6.2
7.6.1
7.6.0
7.5.1
7.5.0
7.4.0
7.3.4
7.3.3
7.3.2
7.3.1
7.3.0
7.2.0
7.1.1
7.1.0
7.0.4
7.0.3
7.0.2
7.0.1
6.26.0
6.25.0
6.24.0
6.23.0
6.22.2
6.21.3
6.21.2
6.21.1
6.20.2
6.19.1
6.19.0
6.18.3
6.18.2
6.18.1
6.18.0
6.17.1
6.17.0
6.16.0
6.15.4
6.15.3
6.15.2
6.15.1
6.15.0
6.14.0
6.13.5
6.13.4
6.13.3
6.13.2
6.13.1
6.13.0
6.12.0
6.11.2
6.11.1
6.10.0
6.9.2
6.9.1
6.9.0
6.8.0
6.7.1
6.7.0
6.6.4
6.6.3
6.6.2
6.6.1
6.6.0
6.5.0
6.4.0
6.3.3
6.3.2
6.3.1
6.3.0
6.2.1
6.2.0
6.1.0
6.0.0
5.39.0
5.38.0
5.37.0
5.36.0
5.35.2
5.34.3
5.34.2
5.34.1
5.33.1
5.32.1
5.32.0
5.31.3
5.31.2
5.31.1
5.31.0
5.30.1
5.30.0
5.29.0
5.28.4
5.28.3
5.28.2
5.28.1
5.28.0
5.27.0
5.26.5
5.26.4
5.26.3
5.26.2
5.26.1
5.26.0
5.25.0
5.24.2
5.24.1
5.23.0
5.22.2
5.22.1
5.22.0
5.21.0
5.20.1
5.20.0
5.19.4
5.19.3
5.19.2
5.19.1
5.19.0
5.18.0
5.17.0
5.16.3
5.16.1
5.16.0
5.15.1
5.15.0
5.14.0
5.13.1
5.13.0
5.12.1
5.12.0
5.11.2
5.11.1
5.10.1
5.10.0
5.9.0
5.8.0
5.7.0
5.6.1
5.6.0
5.5.0
5.4.2
5.4.1
5.4.0
5.3.0
5.2.2
5.2.1
5.2.0
5.1.2
5.1.1
4.79.0
4.78.0
4.77.0
4.76.2
4.75.3
4.75.2
4.75.1
4.74.0
4.73.1
4.73.0
4.72.3
4.72.2
4.72.1
4.72.0
4.71.1
4.71.0
4.70.0
4.69.4
4.69.3
4.69.2
4.69.1
4.69.0
4.68.0
4.67.5
4.67.4
4.67.3
4.67.2
4.67.0
4.66.0
4.65.2
4.65.1
4.64.0
4.63.2
4.63.1
4.63.0
4.62.0
4.61.1
4.61.0
4.60.4
4.60.3
4.60.2
4.60.1
4.60.0
4.59.0
4.58.0
4.57.2
4.57.1
4.57.0
4.56.2
4.56.1
4.56.0
4.55.0
4.54.0
4.53.0
4.52.1
4.52.0
4.51.3
4.51.2
4.51.0
4.50.0
4.49.3
4.49.2
OTP backports
Current section
Files
Jump to
Current section
Files
src/otpbp_erl_epmd.erl
-module(otpbp_erl_epmd).
-ifndef(HAVE_erl_epmd__listen_port_please_2).
% OTP 21.0
-export([listen_port_please/2]).
-endif.
-ifndef(HAVE_erl_epmd__port_please_2).
% OTP 21.0
-export([port_please/2]).
-endif.
-ifndef(HAVE_erl_epmd__port_please_3).
% OTP 21.0
-export([port_please/3]).
-include_lib("kernel/include/dist.hrl").
-include_lib("kernel/include/inet.hrl").
-endif.
-ifndef(HAVE_erl_epmd__port_please_2).
-ifdef(HAVE_erl_epmd__port_please_3).
-import(erl_epmd, [port_please/3]).
-endif.
-endif.
-ifndef(HAVE_erl_epmd__port_please_3).
-ifdef(HAVE_erl_epmd__listen_port_please_2).
-import(erl_epmd, [listen_port_please/2]).
-endif.
-endif.
-ifndef(HAVE_erl_epmd__listen_port_please_2).
listen_port_please(_Name, _Host) ->
{ok,
case init:get_argument(erl_epmd_port) of
{ok, [[StringPort]]} -> list_to_integer(StringPort);
_ -> 0
end}.
-endif.
-ifndef(HAVE_erl_epmd__port_please_2).
port_please(Node, HostName) -> port_please(Node, HostName, infinity).
-endif.
-ifndef(HAVE_erl_epmd__port_please_3).
-ifdef(ERL_DIST_VER_HIGH).
-define(epmd_dist_high, ?ERL_DIST_VER_HIGH).
-else.
-define(epmd_dist_high, 5).
-endif.
-ifdef(ERL_DIST_VER_LOW).
-define(epmd_dist_low, ?ERL_DIST_VER_LOW).
-else.
-define(epmd_dist_low, 5).
-endif.
port_please(Node, HostName, Timeout) ->
case listen_port_please(Node, HostName) of
{ok, 0} ->
case getepmdbyname(HostName, Timeout) of
{ok, EpmdAddr} -> get_port(Node, EpmdAddr, Timeout);
_Error -> noport
end;
{ok, Prt} -> {port, Prt, ?epmd_dist_low}
end.
getepmdbyname(HostName, Timeout) when is_list(HostName) ->
case inet:gethostbyname(HostName,
case inet_db:res_option(inet6) of
true -> inet6;
false -> inet
end,
Timeout) of
{ok, #hostent{h_addr_list = [EpmdAddr|_]}} -> {ok, EpmdAddr};
Else -> Else
end;
getepmdbyname(HostName, Timeout) when is_atom(HostName) -> getepmdbyname(atom_to_list(HostName), Timeout);
getepmdbyname(HostName, _Timeout) -> {ok, HostName}.
-define(int16(X), [((X) bsr 8) band 16#FF, (X) band 16#FF]).
-define(EPMD_PORT_PLEASE2_REQ, $z).
get_port(Node, EpmdAddress, Timeout) ->
case erl_epmd:open(EpmdAddress, Timeout) of
{ok, Socket} ->
Name = to_string(Node),
case gen_tcp:send(Socket, [?int16(length(Name) + 1), ?EPMD_PORT_PLEASE2_REQ, Name]) of
ok -> wait_for_port_reply(Socket, []);
_Error -> noport
end;
_Error -> noport
end.
to_string(S) when is_list(S) -> S;
to_string(S) when is_atom(S) -> atom_to_list(S).
-define(u16(X1, X0), (((X1) bsl 8) bor (X0))).
wait_for_port_reply(Socket, SoFar) ->
receive
{tcp, Socket, Data0} ->
case SoFar ++ Data0 of
[$w, 0|Rest] -> wait_for_port_reply_cont(Socket, Rest);
[$w, _|_] -> wait_for_close(Socket, noport);
[_, _|_] = Garbage -> {error, {garbage_from_epmd, Garbage}};
Data -> wait_for_port_reply(Socket, Data)
end;
{tcp_closed, Socket} -> closed
after 10000 ->
gen_tcp:close(Socket),
noport
end.
wait_for_port_reply_cont(Socket, SoFar) when length(SoFar) >= 10 -> wait_for_port_reply_cont2(Socket, SoFar);
wait_for_port_reply_cont(Socket, SoFar) ->
receive
{tcp, Socket, Data0} ->
case SoFar ++ Data0 of
Data when length(Data) >= 10 -> wait_for_port_reply_cont2(Socket, Data);
Data -> wait_for_port_reply_cont(Socket, Data)
end;
{tcp_closed, Socket} -> noport
after 10000 ->
gen_tcp:close(Socket),
noport
end.
wait_for_port_reply_cont2(Socket, [A, B, _Type, _Proto, HighA, HighB, LowA, LowB, NLenA, NLenB|Rest]) ->
wait_for_port_reply_name(Socket, ?u16(NLenA, NLenB), Rest),
{port, ?u16(A, B), best_version(?u16(LowA, LowB), ?u16(HighA, HighB))}.
wait_for_port_reply_name(Socket, Len, Sofar) ->
receive
{tcp, Socket, _Data} -> wait_for_port_reply_name(Socket, Len, Sofar);
{tcp_closed, Socket} -> ok
end.
best_version(Low, High) -> select_best_version(epmd_dist_low(), epmd_dist_high(), Low, High).
select_best_version(L1, H1, L2, H2) when L1 > H2; L2 > H1 -> 0;
select_best_version(_L1, H1, _L2, H2) -> min(H1, H2).
wait_for_close(Socket, Reply) ->
receive
{tcp_closed, Socket} -> Reply
after 10000 ->
gen_tcp:close(Socket),
Reply
end.
epmd_dist_high() ->
case os:getenv("ERL_EPMD_DIST_HIGH") of
false -> ?epmd_dist_high;
Version ->
try list_to_integer(Version) of
N when N < ?epmd_dist_high -> N;
_ -> ?epmd_dist_high
catch
_:_ -> ?epmd_dist_high
end
end.
epmd_dist_low() ->
case os:getenv("ERL_EPMD_DIST_LOW") of
false -> ?epmd_dist_low;
Version ->
try list_to_integer(Version) of
N when N > ?epmd_dist_low -> N;
_ -> ?epmd_dist_low
catch
_:_ -> ?epmd_dist_low
end
end.
-endif.