Skip to content

Commit

Permalink
Merge pull request #3540 from esl/mod-bosh-config-map
Browse files Browse the repository at this point in the history
  • Loading branch information
gustawlippa committed Feb 17, 2022
2 parents 8005e53 + 0ceb574 commit 6ca2443
Show file tree
Hide file tree
Showing 19 changed files with 265 additions and 185 deletions.
2 changes: 1 addition & 1 deletion big_tests/rebar.config
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

{require_min_otp_vsn, "21"}.

{src_dirs, ["src", "tests"]}.
{src_dirs, ["src", "tests", "../test/common"]}.

%% We use https:// instead of git://
{deps, [
Expand Down
91 changes: 63 additions & 28 deletions big_tests/tests/bosh_SUITE.erl
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

-include_lib("escalus/include/escalus.hrl").
-include_lib("common_test/include/ct.hrl").
-include_lib("eunit/include/eunit.hrl").
-include_lib("exml/include/exml.hrl").

-import(distributed_helper, [mim/0,
Expand All @@ -36,6 +37,7 @@

all() ->
[
{group, without_bosh},
{group, essential},
{group, essential_https},
{group, chat},
Expand All @@ -48,6 +50,7 @@ all() ->

groups() ->
[
{without_bosh, [], [reject_connection_when_mod_bosh_is_disabled]},
{essential, [shuffle], essential_test_cases()},
{essential_https, [shuffle], essential_test_cases()},
{chat, [shuffle], chat_test_cases()},
Expand Down Expand Up @@ -104,8 +107,8 @@ acks_test_cases() ->
%%--------------------------------------------------------------------

init_per_suite(Config) ->
dynamic_modules:save_modules(host_type(), Config),
escalus:init_per_suite([{escalus_user_db, {module, escalus_ejabberd}} | Config]).
Config1 = dynamic_modules:save_modules(host_type(), Config),
escalus:init_per_suite([{escalus_user_db, {module, escalus_ejabberd}} | Config1]).

end_per_suite(Config) ->
dynamic_modules:restore_modules(Config),
Expand All @@ -115,8 +118,9 @@ end_per_suite(Config) ->
init_per_group(time, Config) ->
dynamic_modules:ensure_modules(host_type(), required_modules(time)),
Config;
init_per_group(essential, Config) ->
dynamic_modules:ensure_modules(host_type(), required_modules(essential)),
init_per_group(GroupName, Config) when GroupName =:= essential;
GroupName =:= without_bosh ->
dynamic_modules:ensure_modules(host_type(), required_modules(GroupName)),
[{user, carol} | Config];
init_per_group(essential_https, Config) ->
dynamic_modules:ensure_modules(host_type(), required_modules(essential_https)),
Expand All @@ -132,6 +136,7 @@ init_per_group(GroupName, Config) ->

end_per_group(GroupName, _Config) when GroupName =:= time;
GroupName =:= essential;
GroupName =:= without_bosh;
GroupName =:= essential_https ->
ok;
end_per_group(_GroupName, Config) ->
Expand All @@ -146,16 +151,18 @@ end_per_testcase(CaseName, Config) ->

%% Module configuration per group

required_modules(without_bosh) ->
[{mod_bosh, stopped}];
required_modules(GroupName) ->
[{mod_bosh, required_bosh_opts(GroupName)}].
[{mod_bosh, maps:merge(config_parser_helper:default_mod_config(mod_bosh),
required_bosh_opts(GroupName))}].

required_bosh_opts(time) ->
[{max_wait, ?MAX_WAIT},
{inactivity, ?INACTIVITY}];
#{max_wait => ?MAX_WAIT, inactivity => ?INACTIVITY};
required_bosh_opts(server_acks) ->
[{server_acks, true}];
#{server_acks => true};
required_bosh_opts(_Group) ->
[].
#{}.

%%--------------------------------------------------------------------
%% Tests
Expand Down Expand Up @@ -184,37 +191,65 @@ create_and_terminate_session(Config) ->
%% Assert the session was terminated.
wait_for_zero_bosh_sessions().

accept_higher_hold_value(Config) ->
#xmlel{attrs = RespAttrs} = send_specific_hold(Config, <<"2">>),
{<<"hold">>, <<"1">>} = lists:keyfind(<<"hold">>, 1, RespAttrs).
reject_connection_when_mod_bosh_is_disabled(Config) ->
{Domain, Path, Client} = get_fusco_connection(Config),
Rid = rand:uniform(1000000),
Body = escalus_bosh:session_creation_body(2, <<"1.0">>, <<"en">>, Rid, Domain, nil),
Result = fusco_request(Client, <<"POST">>, Path, exml:to_iolist(Body)),
{{<<"200">>, <<"OK">>}, _Headers, RespBody, _, _} = Result,
{ok, #xmlel{attrs = RespAttrs}} = exml:parse(RespBody),

?assertMatch(#{<<"type">> := <<"terminate">>}, maps:from_list(RespAttrs)),
?assertEqual([], get_bosh_sessions()),
fusco_cp:stop(Client).

do_not_accept_0_hold_value(Config) ->
#xmlel{attrs = RespAttrs} = send_specific_hold(Config, <<"0">>),
{<<"type">>, <<"terminate">>} = lists:keyfind(<<"type">>, 1, RespAttrs).
{Domain, Path, Client} = get_fusco_connection(Config),
Rid = rand:uniform(1000000),
Body0 = escalus_bosh:session_creation_body(2, <<"1.0">>, <<"en">>, Rid, Domain, nil),
#xmlel{attrs = Attrs0} = Body0,
Attrs = lists:keyreplace(<<"hold">>, 1, Attrs0, {<<"hold">>, <<"0">>}),
Body = Body0#xmlel{attrs = Attrs},
Result = fusco_request(Client, <<"POST">>, Path, exml:to_iolist(Body)),
{{<<"200">>, <<"OK">>}, _Headers, RespBody, _, _} = Result,
{ok, #xmlel{attrs = RespAttrs}} = exml:parse(RespBody),

?assertMatch(#{<<"type">> := <<"terminate">>}, maps:from_list(RespAttrs)),
?assertEqual([], get_bosh_sessions()),
fusco_cp:stop(Client).

send_specific_hold(Config, HoldValue) ->
accept_higher_hold_value(Config) ->
{Domain, Path, Client} = get_fusco_connection(Config),

Rid = rand:uniform(1000000),
Body0 = escalus_bosh:session_creation_body(2, <<"1.0">>, <<"en">>, Rid, Domain, nil),
#xmlel{attrs = Attrs0} = Body0,
Attrs = lists:keyreplace(<<"hold">>, 1, Attrs0, {<<"hold">>, HoldValue}),
Attrs = lists:keyreplace(<<"hold">>, 1, Attrs0, {<<"hold">>, <<"2">>}),
Body = Body0#xmlel{attrs = Attrs},

Result = fusco_request(Client, <<"POST">>, Path, exml:to_iolist(Body)),
{{<<"200">>, <<"OK">>}, _Headers, RespBody, _, _} = Result,

{ok, #xmlel{attrs = RespAttrs} = Resp} = exml:parse(RespBody),
case lists:keyfind(<<"sid">>, 1, RespAttrs) of
{<<"sid">>, SID} ->
TerminateBody = escalus_bosh:session_termination_body(Rid + 1, SID),
fusco_request(Client, <<"POST">>, Path, exml:to_iolist(TerminateBody));
_ ->
skip
{ok, #xmlel{attrs = RespAttrs}} = exml:parse(RespBody),

%% Server returns its hold value, which is 1
#{<<"hold">> := <<"1">>, <<"sid">> := SID} = maps:from_list(RespAttrs),
?assertMatch([_], get_bosh_sessions()),

TerminateBody = escalus_bosh:session_termination_body(Rid + 1, SID),
Res2 = fusco_request(Client, <<"POST">>, Path, exml:to_iolist(TerminateBody)),
{{<<"200">>, <<"OK">>}, _, RespBody2, _, _} = Res2,
{ok, #xmlel{attrs = RespAttrs2}} = exml:parse(RespBody2),
case maps:from_list(RespAttrs2) of
#{<<"type">> := <<"terminate">>} ->
ok;
#{<<"sid">> := SID} ->
%% Server sent stream features separately, one more request needed
EmptyBody = escalus_bosh:empty_body(Rid + 2, SID),
Res3 = fusco_request(Client, <<"POST">>, Path, exml:to_iolist(EmptyBody)),
{{<<"200">>, <<"OK">>}, _, RespBody3, _, _} = Res3,
{ok, #xmlel{attrs = RespAttrs3}} = exml:parse(RespBody3),
?assertMatch(#{<<"type">> := <<"terminate">>}, maps:from_list(RespAttrs3))
end,
fusco_cp:stop(Client),
Resp.
?assertEqual([], get_bosh_sessions()),
fusco_cp:stop(Client).

fusco_request(Client, Method, Path, Body) ->
fusco_request(Client, Method, Path, Body, []).
Expand Down
6 changes: 3 additions & 3 deletions big_tests/tests/oauth_SUITE.erl
Original file line number Diff line number Diff line change
Expand Up @@ -475,6 +475,6 @@ required_modules() ->
{mod_auth_token, auth_token_opts()}].

auth_token_opts() ->
#{iqdisc => no_queue,
validity_period => #{access => #{value => 60, unit => minutes},
refresh => #{value => 1, unit => days}}}.
Defaults = config_parser_helper:default_mod_config(mod_auth_token),
Defaults#{validity_period => #{access => #{value => 60, unit => minutes},
refresh => #{value => 1, unit => days}}}.
7 changes: 7 additions & 0 deletions doc/modules/mod_auth_token.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,13 @@ Generation of keys necessary to sign binary tokens is delegated to module `mod_k

## Options

### `modules.mod_auth_token.backend`
* **Syntax:** non-empty string
* **Default:** `"rdbms"`
* **Example:** `backend = "rdbms"`

Token storage backend. Currently only `"rdbms"` is supported.

### `modules.mod_auth_token.iqdisc.type`
* **Syntax:** string, one of `"one_queue"`, `"no_queue"`, `"queues"`, `"parallel"`
* **Default:** `"no_queue"`
Expand Down
9 changes: 8 additions & 1 deletion doc/modules/mod_bosh.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,19 @@ If you want to use BOSH, you must enable it both in the `listen` section of

## Options

### `modules.mod_bosh.backend`
* **Syntax:** non-empty string
* **Default:** `"mnesia"`
* **Example:** `backend = "mnesia"`

Backend to use for storing BOSH connections. Currently only `"mnesia"` is supported.

### `modules.mod_bosh.inactivity`
* **Syntax:** positive integer or the string `"infinity"`
* **Default:** `30`
* **Example:** `inactivity = 30`

Maximum allowed inactivity time for a BOSH connection.
Maximum allowed inactivity time (in seconds) for a BOSH connection.
Please note that a long-polling request is not considered to be an inactivity.

### `modules.mod_bosh.max_wait`
Expand Down
3 changes: 2 additions & 1 deletion rebar.config
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,8 @@
{fed1, [{relx, [ {overlay_vars, ["rel/vars-toml.config", "rel/fed1.vars-toml.config"]},
{overlay, [{template, "rel/files/mongooseim.toml", "etc/mongooseim.toml"}]} ]}]},
{reg1, [{relx, [ {overlay_vars, ["rel/vars-toml.config", "rel/reg1.vars-toml.config"]},
{overlay, [{template, "rel/files/mongooseim.toml", "etc/mongooseim.toml"}]} ]}]}
{overlay, [{template, "rel/files/mongooseim.toml", "etc/mongooseim.toml"}]} ]}]},
{test, [{extra_src_dirs, [{"test", [{recursive, true}]}]}]}
]}.

{plugins,
Expand Down
3 changes: 1 addition & 2 deletions src/gen_mod.erl
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,7 @@

-type service_deps_list() :: [atom()].

-export_type([deps_list/0,
module_opts/0]).
-export_type([deps_list/0, opt_key/0, opt_value/0, module_opts/0]).

-export([
% Modules start & stop, do NOT use in the tests, use mongoose_modules API instead
Expand Down
17 changes: 10 additions & 7 deletions src/mod_auth_token.erl
Original file line number Diff line number Diff line change
Expand Up @@ -76,8 +76,8 @@
%%

-spec start(mongooseim:host_type(), gen_mod:module_opts()) -> ok.
start(HostType, #{iqdisc := IQDisc}) ->
mod_auth_token_backend:start(HostType),
start(HostType, #{iqdisc := IQDisc} = Opts) ->
mod_auth_token_backend:start(HostType, Opts),
ejabberd_hooks:add(hooks(HostType)),
gen_iq_handler:add_iq_handler_for_domain(
HostType, ?NS_ESL_TOKEN_AUTH, ejabberd_sm,
Expand All @@ -102,9 +102,12 @@ supported_features() ->
-spec config_spec() -> mongoose_config_spec:config_section().
config_spec() ->
#section{
items = #{<<"validity_period">> => validity_periods_spec(),
items = #{<<"backend">> => #option{type = atom,
validate = {module, mod_auth_token}},
<<"validity_period">> => validity_periods_spec(),
<<"iqdisc">> => mongoose_config_spec:iqdisc()},
defaults = #{<<"iqdisc">> => no_queue},
defaults = #{<<"backend">> => rdbms,
<<"iqdisc">> => no_queue},
format_items = map
}.

Expand Down Expand Up @@ -450,9 +453,9 @@ clean_tokens(Acc, User, Server) ->
end,
Acc.

config_metrics(Host) ->
OptsToReport = [{backend, rdbms}], %list of tuples {option, default_value}
mongoose_module_metrics:opts_for_module(Host, ?MODULE, OptsToReport).
-spec config_metrics(mongooseim:host_type()) -> [{gen_mod:opt_key(), gen_mod:opt_value()}].
config_metrics(HostType) ->
mongoose_module_metrics:opts_for_module(HostType, ?MODULE, [backend]).

-spec disco_local_features(mongoose_disco:feature_acc()) -> mongoose_disco:feature_acc().
disco_local_features(Acc = #{node := <<>>}) ->
Expand Down
8 changes: 4 additions & 4 deletions src/mod_auth_token_backend.erl
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
%%% @end
%%%----------------------------------------------------------------------
-module(mod_auth_token_backend).
-export([start/1,
-export([start/2,
revoke/2,
get_valid_sequence_number/2,
clean_tokens/2]).
Expand All @@ -26,9 +26,9 @@
%% ----------------------------------------------------------------------
%% API Functions

-spec start(HostType :: mongooseim:host_type()) -> ok.
start(HostType) ->
mongoose_backend:init(HostType, ?MAIN_MODULE, [], #{backend => rdbms}),
-spec start(mongooseim:host_type(), gen_mod:module_opts()) -> ok.
start(HostType, Opts) ->
mongoose_backend:init(HostType, ?MAIN_MODULE, [], Opts),
Args = [HostType],
mongoose_backend:call(HostType, ?MAIN_MODULE, ?FUNCTION_NAME, Args).

Expand Down
Loading

0 comments on commit 6ca2443

Please sign in to comment.