./ct_report/coverage/mongoose_epmd.COVER.html

1 %% EPMD implementation which redefines how name lookups work
2 %% There is no behaviour for erl_epmd
3 -module(mongoose_epmd).
4 -export([
5 start/0,
6 start_link/0,
7 stop/0,
8 port_please/2, port_please/3,
9 listen_port_please/2,
10 names/0, names/1,
11 register_node/2, register_node/3,
12 address_please/3,
13 open/0, open/1, open/2
14 ]).
15 -include_lib("kernel/include/logger.hrl").
16
17 %% For debugging
18 -export([lookup_ip/1]).
19 -export([match_node_name/2]).
20
21 -type lookup_error() ::
22 {no_ip_in_db, node()}
23 | {cannot_connect_to_epmd, node(), inet:ip_address()}
24 | {no_record_for_node, node()}
25 | mongoose_node_address_ets_table_not_found.
26
27 -ignore_xref([
28 start/0,
29 start_link/0,
30 stop/0,
31 port_please/2, port_please/3,
32 listen_port_please/2,
33 names/0, names/1,
34 register_node/2, register_node/3,
35 address_please/3,
36 open/0, open/1, open/2,
37 lookup_ip/1, match_node_name/2
38 ]).
39
40
:-(
start() -> erl_epmd:start().
41
:-(
start_link() -> erl_epmd:start_link().
42
:-(
stop() -> erl_epmd:stop().
43
:-(
port_please(A, B) -> erl_epmd:port_please(A, B).
44
:-(
port_please(A, B, C) -> erl_epmd:port_please(A, B, C).
45
:-(
listen_port_please(A, B) -> erl_epmd:listen_port_please(A, B).
46
:-(
names() -> erl_epmd:names().
47
:-(
names(A) -> erl_epmd:names(A).
48
:-(
register_node(A, B) -> erl_epmd:register_node(A, B).
49
:-(
register_node(A, B, C) -> erl_epmd:register_node(A, B, C).
50
:-(
open() -> erl_epmd:open().
51
:-(
open(A) -> erl_epmd:open(A).
52
:-(
open(A, B) -> erl_epmd:open(A, B).
53
54 address_please(Name, Host, AddressFamily) ->
55 4 Node = list_to_binary(Name ++ "@" ++ Host),
56 4 case lookup_ip(Node) of
57 {ok, _IP} = Res ->
58 2 Res;
59 _ ->
60 %% Fallback to the default behaviour
61 2 inet:getaddr(Host, AddressFamily)
62 end.
63
64 %% This function waits for the IP address to appear.
65 %% It only works well in case net_kernel does not contact a lot of
66 %% dead nodes.
67 %% Generally, we only expect calls for nodes that are alive
68 %% and the connect is issued by CETS (but CETS checks that node is
69 %% reachable first) or by connect_all feature in the global module of OTP.
70 -spec lookup_ip(binary()) -> {ok, inet:ip_address()} | {error, lookup_error()}.
71 lookup_ip(Node) ->
72 4 try
73 4 cets_discovery:wait_for_get_nodes(mongoose_cets_discovery, 3000),
74 3 cets_discovery:system_info(mongoose_cets_discovery)
75 of
76 #{backend_state := BackendState} ->
77 3 match_node_name(BackendState, Node)
78 catch _:_ ->
79 1 {error, failed_to_get_disco_state}
80 end.
81
82 match_node_name(#{address_pairs := Pairs}, Node) ->
83 7 case Pairs of
84 #{Node := <<>>} ->
85 %% The caller should try DNS.
86 1 {error, {no_ip_in_db, Node}};
87 #{Node := Bin} ->
88 5 inet:parse_address(binary_to_list(Bin));
89 #{} ->
90 1 {error, {no_record_for_node, Node}}
91 end;
92 match_node_name(BackendState, Node) ->
93 %% Could happen if CETS backend is not mongoose_cets_discovery_rdbms
94 1 ?LOG_ERROR(#{what => cets_no_address_pairs_set,
95 backend_state => BackendState,
96
:-(
remote_node => Node}),
97 1 {error, no_address_pairs_set}.
Line Hits Source