Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
chrzaszcz committed Jan 25, 2022
1 parent a0e9c6a commit c6554af
Show file tree
Hide file tree
Showing 6 changed files with 117 additions and 79 deletions.
97 changes: 58 additions & 39 deletions src/config/mongoose_config_spec.erl
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ host_config() ->
<<"modules">> => modules(),
<<"acl">> => acl(),
<<"access">> => access(),
<<"s2s">> => s2s()
<<"s2s">> => host_s2s()
},
wrap = none
}.
Expand Down Expand Up @@ -868,66 +868,85 @@ access_rule_item() ->
format_items = map
}.

%% path: (host_config[].)s2s
%% path: s2s
s2s() ->
#section{
items = #{<<"dns">> => s2s_dns(),
<<"outgoing">> => s2s_outgoing(),
<<"use_starttls">> => #option{type = atom,
validate = {enum, [false, optional, required,
required_trusted]},
wrap = {global_config, s2s_use_starttls}},
<<"certfile">> => #option{type = string,
validate = non_empty,
wrap = {global_config, s2s_certfile}},
<<"default_policy">> => #option{type = atom,
validate = {enum, [allow, deny]},
wrap = {host_config, s2s_default_policy}},
<<"host_policy">> => #list{items = s2s_host_policy(),
format_items = map,
wrap = {host_config, s2s_host_policy}},
<<"address">> => #list{items = s2s_address(),
format_items = map,
wrap = {global_config, s2s_address}},
<<"ciphers">> => #option{type = string,
wrap = {global_config, s2s_ciphers}},
<<"shared">> => #option{type = binary,
validate = non_empty,
wrap = {host_config, s2s_shared}},
<<"max_retry_delay">> => #option{type = integer,
validate = positive,
wrap = {host_config, s2s_max_retry_delay}}
},
items = maps:merge(s2s_global_items(), s2s_host_items()),
wrap = none,
include = always
}.

%% path: host_config[].s2s
host_s2s() ->
#section{
items = s2s_host_items(),
wrap = none
}.

s2s_host_items() ->
#{<<"default_policy">> => #option{type = atom,
validate = {enum, [allow, deny]},
wrap = {host_config, s2s_default_policy}},
<<"host_policy">> => #list{items = s2s_host_policy(),
format_items = map,
wrap = {host_config, s2s_host_policy}},
<<"shared">> => #option{type = binary,
validate = non_empty,
wrap = {host_config, s2s_shared}},
<<"max_retry_delay">> => #option{type = integer,
validate = positive,
wrap = {host_config, s2s_max_retry_delay}}
}.

s2s_global_items() ->
#{<<"dns">> => s2s_dns(),
<<"outgoing">> => s2s_outgoing(),
<<"use_starttls">> => #option{type = atom,
validate = {enum, [false, optional, required,
required_trusted]},
wrap = {global_config, s2s_use_starttls}},
<<"certfile">> => #option{type = string,
validate = non_empty,
wrap = {global_config, s2s_certfile}},
<<"address">> => #list{items = s2s_address(),
format_items = map,
wrap = {global_config, s2s_address}},
<<"ciphers">> => #option{type = string,
wrap = {global_config, s2s_ciphers}}
}.

%% path: (host_config[].)s2s.dns
s2s_dns() ->
#section{
items = #{<<"timeout">> => #option{type = integer,
validate = positive},
<<"retries">> => #option{type = integer,
validate = positive}},
wrap = {global_config, s2s_dns_options}
format_items = map,
include = always,
defaults = #{<<"timeout">> => 10,
<<"retries">> => 2},
wrap = {global_config, s2s_dns}
}.

%% path: (host_config[].)s2s.outgoing
s2s_outgoing() ->
#section{
items = #{<<"port">> => #option{type = integer,
validate = port,
wrap = {global_config, outgoing_s2s_port}},
validate = port},
<<"ip_versions">> =>
#list{items = #option{type = integer,
validate = {enum, [4, 6]},
process = fun ?MODULE:process_s2s_address_family/1},
validate = unique_non_empty,
wrap = {global_config, outgoing_s2s_families}},
validate = {enum, [4, 6]}},
validate = unique_non_empty},
<<"connection_timeout">> => #option{type = int_or_infinity,
validate = positive,
wrap = {global_config, outgoing_s2s_timeout}}
validate = positive}
},
wrap = none
format_items = map,
include = always,
defaults = #{<<"port">> => 5269,
<<"ip_versions">> => [4, 6],
<<"connection_timeout">> => 10000},
wrap = {global_config, s2s_outgoing}
}.

%% path: (host_config[].)s2s.host_policy[]
Expand Down
39 changes: 16 additions & 23 deletions src/ejabberd_s2s_out.erl
Original file line number Diff line number Diff line change
Expand Up @@ -296,10 +296,10 @@ open_socket1({_, _, _, _, _, _, _, _} = Addr, Port) ->
open_socket2(inet6, Addr, Port);
%% Hostname
open_socket1(Host, Port) ->
lists:foldl(fun(_Family, {ok, _Socket} = R) ->
lists:foldl(fun(_IPVersion, {ok, _Socket} = R) ->
R;
(Family, _) ->
Addrs = get_addrs(Host, Family),
(IPVersion, _) ->
Addrs = get_addrs(Host, IPVersion),
lists:foldl(fun(_Addr, {ok, _Socket} = R) ->
R;
(Addr, _) ->
Expand Down Expand Up @@ -998,9 +998,7 @@ get_addr_port(Server) ->

-spec srv_lookup(jid:server()) -> {'error', atom()} | {'ok', inet:hostent()}.
srv_lookup(Server) ->
Options = mongoose_config:get_opt(s2s_dns_options, []),
TimeoutMs = timer:seconds(proplists:get_value(timeout, Options, 10)),
Retries = proplists:get_value(retries, Options, 2),
#{timeout := TimeoutMs, retries := Retries} = mongoose_config:get_opt(s2s_dns),
srv_lookup(Server, TimeoutMs, Retries).


Expand Down Expand Up @@ -1044,18 +1042,10 @@ test_get_addr_port(Server) ->
end, [], lists:seq(1, 100000)).


-spec get_addrs(Host :: atom() | binary() | string(),
Family :: 'inet4' | 'inet6' | 'ipv4' | 'ipv6'
) -> [inet:ip_address()].
get_addrs(Host, Family) when is_binary(Host) ->
get_addrs(binary_to_list(Host), Family);
get_addrs(Host, Family) ->
Type = case Family of
inet4 -> inet;
ipv4 -> inet;
inet6 -> inet6;
ipv6 -> inet6
end,
-spec get_addrs(Host :: atom() | binary() | string(), inet | inet6) -> [inet:ip_address()].
get_addrs(Host, Type) when is_binary(Host) ->
get_addrs(binary_to_list(Host), Type);
get_addrs(Host, Type) ->
case inet:gethostbyname(Host, Type) of
{ok, #hostent{h_addr_list = Addrs}} ->
?LOG_DEBUG(#{what => s2s_srv_resolve_success,
Expand All @@ -1068,12 +1058,12 @@ get_addrs(Host, Family) ->
end.


-spec outgoing_s2s_port() -> integer().
-spec outgoing_s2s_port() -> inet:port_number().
outgoing_s2s_port() ->
mongoose_config:get_opt(outgoing_s2s_port, 5269).
mongoose_config:get_opt([s2s_outgoing, port]).


-spec outgoing_s2s_families() -> ['ipv4' | 'ipv6', ...].
-spec outgoing_s2s_families() -> [inet:address_family(), ...].
outgoing_s2s_families() ->
%% DISCUSSION: Why prefer IPv4 first?
%%
Expand All @@ -1086,11 +1076,14 @@ outgoing_s2s_families() ->
%% AAAA records for their sites due to the mentioned
%% quality of current IPv6 connectivity. Making IPv6 the a
%% `fallback' may avoid these problems elegantly.
mongoose_config:get_opt(outgoing_s2s_families, [ipv4, ipv6]).
[ip_version_to_family(V) || V <- mongoose_config:get_opt([s2s_outgoing, ip_versions])].

ip_version_to_family(4) -> inet;
ip_version_to_family(6) -> inet6.

-spec outgoing_s2s_timeout() -> non_neg_integer() | infinity.
outgoing_s2s_timeout() ->
mongoose_config:get_opt(outgoing_s2s_timeout, 10000).
mongoose_config:get_opt([s2s_outgoing, connection_timeout], 10000).

%% @doc Human readable S2S logging: Log only new outgoing connections as INFO
%% Do not log dialback
Expand Down
21 changes: 12 additions & 9 deletions test/config_parser_SUITE.erl
Original file line number Diff line number Diff line change
Expand Up @@ -1431,27 +1431,32 @@ access_merge_host_and_global(_Config) ->
%% tests: s2s

s2s_dns_timeout(_Config) ->
?cfg(s2s_dns_options, [{timeout, 5}], #{<<"s2s">> => #{<<"dns">> => #{<<"timeout">> => 5}}}),
?cfg([s2s_dns, timeout], 10, #{}), % default
?cfg([s2s_dns, timeout], 5, #{<<"s2s">> => #{<<"dns">> => #{<<"timeout">> => 5}}}),
?err(#{<<"s2s">> => #{<<"dns">> => #{<<"timeout">> => 0}}}).

s2s_dns_retries(_Config) ->
?cfg(s2s_dns_options, [{retries, 1}], #{<<"s2s">> => #{<<"dns">> => #{<<"retries">> => 1}}}),
?cfg([s2s_dns, retries], 2, #{}), % default
?cfg([s2s_dns, retries], 1, #{<<"s2s">> => #{<<"dns">> => #{<<"retries">> => 1}}}),
?err(#{<<"s2s">> => #{<<"dns">> => #{<<"retries">> => 0}}}).

s2s_outgoing_port(_Config) ->
?cfg(outgoing_s2s_port, 5270, #{<<"s2s">> => #{<<"outgoing">> => #{<<"port">> => 5270}}}),
?cfg([s2s_outgoing, port], 5269, #{}), % default
?cfg([s2s_outgoing, port], 5270, #{<<"s2s">> => #{<<"outgoing">> => #{<<"port">> => 5270}}}),
?err(#{<<"s2s">> => #{<<"outgoing">> => #{<<"port">> => <<"http">>}}}).

s2s_outgoing_ip_versions(_Config) ->
?cfg(outgoing_s2s_families, [ipv6, ipv4],
?cfg([s2s_outgoing, ip_versions], [4, 6], #{}), % default
?cfg([s2s_outgoing, ip_versions], [6, 4],
#{<<"s2s">> => #{<<"outgoing">> => #{<<"ip_versions">> => [6, 4]}}}),
?err(#{<<"s2s">> => #{<<"outgoing">> => #{<<"ip_versions">> => []}}}),
?err(#{<<"s2s">> => #{<<"outgoing">> => #{<<"ip_versions">> => [<<"http">>]}}}).

s2s_outgoing_timeout(_Config) ->
?cfg(outgoing_s2s_timeout, 5,
#{<<"s2s">> => #{<<"outgoing">> => #{<<"connection_timeout">> => 5}}}),
?cfg(outgoing_s2s_timeout, infinity,
?cfg([s2s_outgoing, connection_timeout], 10000, #{}), % default
?cfg([s2s_outgoing, connection_timeout], 5000,
#{<<"s2s">> => #{<<"outgoing">> => #{<<"connection_timeout">> => 5000}}}),
?cfg([s2s_outgoing, connection_timeout], infinity,
#{<<"s2s">> => #{<<"outgoing">> => #{<<"connection_timeout">> => <<"infinity">>}}}),
?err(#{<<"s2s">> => #{<<"outgoing">> => #{<<"connection_timeout">> => 0}}}).

Expand Down Expand Up @@ -3218,8 +3223,6 @@ compare_nodes([{auth_method, _}], V1, V2) when is_atom(V1) ->
?eq([V1], V2);
compare_nodes([{s2s_addr, _}], {_, _, _, _} = IP1, IP2) ->
?eq(inet:ntoa(IP1), IP2);
compare_nodes([s2s_dns_options], V1, V2) ->
compare_unordered_lists(V1, V2);
compare_nodes([{modules, _}, mod_extdisco], V1, V2) ->
compare_ordered_lists(V1, V2, fun compare_unordered_lists/2);
compare_nodes([{modules, _}, _Module], V1, V2) ->
Expand Down
4 changes: 2 additions & 2 deletions test/config_parser_SUITE_data/s2s_only.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@
default_policy = "allow"
ciphers = "TLSv1.2:TLSv1.3"
outgoing.port = 5299
outgoing.connection_timeout = 10000
outgoing.ip_versions = [4, 6]
outgoing.connection_timeout = 4000
outgoing.ip_versions = [6, 4]
dns.timeout = 30
dns.retries = 1
shared = "shared secret"
Expand Down
31 changes: 25 additions & 6 deletions test/config_parser_helper.erl
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ options("host_types") ->
{registration_timeout, 600},
{routing_modules, mongoose_router:default_routing_modules()},
{sm_backend, {mnesia, []}},
{s2s_dns, #{retries => 2, timeout => 10}},
{s2s_outgoing, #{connection_timeout => 10000,
ip_versions => [4, 6],
port => 5269}},
{{auth, <<"another host type">>}, auth_with_methods(#{})},
{{auth, <<"localhost">>},
auth_with_methods(#{rdbms => #{users_number_estimate => false}})},
Expand Down Expand Up @@ -79,6 +83,10 @@ options("miscellaneous") ->
{periodic_report, 10800000},
report,
{tracking_id, "UA-123456789"}]}]},
{s2s_dns, #{retries => 2, timeout => 10}},
{s2s_outgoing, #{connection_timeout => 10000,
ip_versions => [4, 6],
port => 5269}},
{sm_backend, {mnesia, []}},
{{auth, <<"anonymous.localhost">>}, custom_auth()},
{{auth, <<"localhost">>}, custom_auth()},
Expand All @@ -101,6 +109,10 @@ options("modules") ->
{rdbms_server_type, generic},
{registration_timeout, 600},
{routing_modules, mongoose_router:default_routing_modules()},
{s2s_dns, #{retries => 2, timeout => 10}},
{s2s_outgoing, #{connection_timeout => 10000,
ip_versions => [4, 6],
port => 5269}},
{sm_backend, {mnesia, []}},
{{auth, <<"dummy_host">>}, default_auth()},
{{auth, <<"localhost">>}, default_auth()},
Expand Down Expand Up @@ -229,11 +241,15 @@ options("mongooseim-pgsql") ->
{server_name_indication, disable},
{verify, verify_peer}]}]}}]},
{redis, <<"localhost">>, global_distrib, [{workers, 10}], []}]},
{outgoing_s2s_port, 5299},
{rdbms_server_type, generic},
{registration_timeout, infinity},
{routing_modules, mongoose_router:default_routing_modules()},
{s2s_address, #{<<"fed1">> => "127.0.0.1"}},
{s2s_certfile, "tools/ssl/mongooseim/server.pem"},
{s2s_dns, #{retries => 2, timeout => 10}},
{s2s_outgoing, #{connection_timeout => 10000,
ip_versions => [4, 6],
port => 5299}},
{s2s_use_starttls, optional},
{services,
[{service_admin_extra,
Expand Down Expand Up @@ -265,7 +281,6 @@ options("mongooseim-pgsql") ->
{{replaced_wait_timeout, <<"anonymous.localhost">>}, 2000},
{{replaced_wait_timeout, <<"localhost">>}, 2000},
{{replaced_wait_timeout, <<"localhost.bis">>}, 2000},
{s2s_address, #{<<"fed1">> => "127.0.0.1"}},
{{s2s_default_policy, <<"anonymous.localhost">>}, allow},
{{s2s_default_policy, <<"localhost">>}, allow},
{{s2s_default_policy, <<"localhost.bis">>}, allow},
Expand Down Expand Up @@ -346,6 +361,10 @@ options("outgoing_pools") ->
{registration_timeout, 600},
{routing_modules, mongoose_router:default_routing_modules()},
{sm_backend, {mnesia, []}},
{s2s_dns, #{retries => 2, timeout => 10}},
{s2s_outgoing, #{connection_timeout => 10000,
ip_versions => [4, 6],
port => 5269}},
{{auth, <<"anonymous.localhost">>}, default_auth()},
{{auth, <<"localhost">>}, default_auth()},
{{auth, <<"localhost.bis">>}, default_auth()},
Expand All @@ -365,15 +384,11 @@ options("s2s_only") ->
{listen, []},
{loglevel, warning},
{mongooseimctl_access_commands, []},
{outgoing_s2s_families, [ipv4, ipv6]},
{outgoing_s2s_port, 5299},
{outgoing_s2s_timeout, 10000},
{rdbms_server_type, generic},
{registration_timeout, 600},
{routing_modules, mongoose_router:default_routing_modules()},
{s2s_certfile, "tools/ssl/mongooseim/server.pem"},
{s2s_ciphers, "TLSv1.2:TLSv1.3"},
{s2s_dns_options, [{retries, 1}, {timeout, 30}]},
{s2s_use_starttls, optional},
{sm_backend, {mnesia, []}},
{{auth, <<"dummy_host">>}, default_auth()},
Expand All @@ -384,6 +399,10 @@ options("s2s_only") ->
{{replaced_wait_timeout, <<"localhost">>}, 2000},
{s2s_address, #{<<"fed1">> => "127.0.0.1",
<<"fed2">> => {"127.0.0.1", 8765}}},
{s2s_dns, #{retries => 1, timeout => 30}},
{s2s_outgoing, #{connection_timeout => 4000,
ip_versions => [6, 4],
port => 5299}},
{{s2s_default_policy, <<"dummy_host">>}, allow},
{{s2s_default_policy, <<"localhost">>}, allow},
{{s2s_max_retry_delay, <<"dummy_host">>}, 30},
Expand Down
4 changes: 4 additions & 0 deletions test/mongoose_config_SUITE.erl
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,10 @@ minimal_config_opts() ->
{rdbms_server_type, generic},
{registration_timeout, 600},
{routing_modules, mongoose_router:default_routing_modules()},
{s2s_dns, #{retries => 2,timeout => 10}},
{s2s_outgoing, #{connection_timeout => 10000,
ip_versions => [4, 6],
port => 5269}},
{sm_backend, {mnesia, []}},
{{auth, <<"localhost">>}, config_parser_helper:default_auth()},
{{modules, <<"localhost">>}, #{}},
Expand Down

0 comments on commit c6554af

Please sign in to comment.