Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
chrzaszcz committed Feb 7, 2022
1 parent 6a008ef commit 3e286cf
Show file tree
Hide file tree
Showing 17 changed files with 265 additions and 256 deletions.
41 changes: 20 additions & 21 deletions big_tests/tests/extdisco_SUITE.erl
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,10 @@ all() ->
{group, extdisco_required_elements_configured}].

groups() ->
G = [{extdisco_not_configured, [sequence], extdisco_not_configured_tests()},
{extdisco_configured, [sequence], extdisco_configured_tests()},
{multiple_extdisco_configured, [sequence], multiple_extdisco_configured_tests()},
{extdisco_required_elements_configured, [sequence], extdisco_required_elements_configured_tests()}],
ct_helper:repeat_all_until_all_ok(G).
[{extdisco_not_configured, [sequence], extdisco_not_configured_tests()},
{extdisco_configured, [sequence], extdisco_configured_tests()},
{multiple_extdisco_configured, [sequence], multiple_extdisco_configured_tests()},
{extdisco_required_elements_configured, [sequence], extdisco_required_elements_configured_tests()}].

extdisco_not_configured_tests() ->
[external_services_discovery_not_supported,
Expand Down Expand Up @@ -75,7 +74,7 @@ init_per_group(multiple_extdisco_configured, Config) ->
ExternalServices = [stun_service(), stun_service(), turn_service()],
set_external_services(ExternalServices, Config);
init_per_group(extdisco_required_elements_configured, Config) ->
ExternalServices = [[{type, ftp},{host, "3.3.3.3"}]],
ExternalServices = [#{type => ftp, host => <<"3.3.3.3">>}],
set_external_services(ExternalServices, Config);
init_per_group(_GroupName, Config) ->
Config.
Expand Down Expand Up @@ -299,23 +298,23 @@ external_service_required_elements_configured(Config) ->
%%-----------------------------------------------------------------

stun_service() ->
[{type, stun},
{host, "1.1.1.1"},
{port, 3478},
{transport, "udp"},
{username, "username"},
{password, "secret"}].
#{type => stun,
host => <<"1.1.1.1">>,
port => 3478,
transport => <<"udp">>,
username => <<"username">>,
password => <<"secret">>}.

turn_service() ->
[{type, turn},
{host, "2.2.2.2"},
{port, 3478},
{transport, "tcp"},
{username, "username"},
{password, "secret"}].

set_external_services(Opts, Config) ->
Module = [{mod_extdisco, Opts}],
#{type => turn,
host => <<"2.2.2.2">>,
port => 3478,
transport => <<"tcp">>,
username => <<"username">>,
password => <<"secret">>}.

set_external_services(Services, Config) ->
Module = [{mod_extdisco, #{iqdisc => no_queue, service => Services}}],
ok = dynamic_modules:ensure_modules(domain(), Module),
Config.

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

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

## Options

### `modules.mod_auth_token.iqdisc.type`
* **Syntax:** string, one of `"one_queue"`, `"no_queue"`, `"queues"`, `"parallel"`
* **Default:** `"no_queue"`

Strategy to handle incoming IQ stanzas. For details, please refer to
[IQ processing policies](../configuration/Modules.md#iq-processing-policies).

### `modules.mod_auth_token.validity_period`
* **Syntax:** Array of TOML tables with the following keys: `token`, `value`, `unit` and following values: {token = `values: "access", "refresh", "provision"`, value = `non-negative integer`, unit = `values: "days", "hours", "minutes", "seconds"`}.
* **Default:** `[{token = "access", value = 1, unit = "hours"}, {token = "refresh", value = 25, unit = "days"}]`
* **Example:** `[{token = "access", value = 13, unit = "minutes"}, {token = "refresh", value = 13, unit = "days"}]`
* **Syntax:** TOML table. Each key is either `access` or `refresh`. Each value is a nested TOML table with the following mandatory keys: `value` (non-negative integer) and `unit` (`"days"`, `"hours"`, `"minutes"` or `"seconds"`).
* **Default:** `{access = {value = 1, unit = "hours"}, refresh = {value = 1, unit = "hours"}}`
* **Example:** `validity_period.access = {value = 30, unit = "minutes"}`

Validity periods of access and refresh tokens can be defined independently.
Validity periods of access and refresh tokens can be defined independently - specifying one of them does not change the default value for the other one.
Validity period configuration for provision tokens happens outside the module since the server does not generate provision tokens - it only validates them.

### Required keys
Expand Down Expand Up @@ -156,8 +163,6 @@ Access token validity can't be sidestepped right now.

```toml
[modules.mod_auth_token]
validity_period = [
{token = "access", value = 13, unit = "minutes"},
{token = "refresh", value = 13, unit = "days"}
]
validity_period.access = {value = 13, unit = "minutes"}
validity_period.refresh = {value = 13, unit = "days"}
```
30 changes: 24 additions & 6 deletions doc/modules/mod_extdisco.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,42 +7,57 @@ The main use-case is to help discover STUN/TURN servers to allow for negotiating

## Options

### `modules.mod_extdisco.service.type`
### `modules.mod_extdisco.iqdisc.type`
* **Syntax:** string, one of `"one_queue"`, `"no_queue"`, `"queues"`, `"parallel"`
* **Default:** `"no_queue"`

Strategy to handle incoming IQ stanzas. For details, please refer to
[IQ processing policies](../configuration/Modules.md#iq-processing-policies).

### `modules.mod_extdisco.service`
* **Syntax:** TOML array with one table for each advertised service - see below for details.
* **Default:** `[]` - no services advertised

### Service options

Each advertised service is specified as a TOML table containing the following options listed below.

#### `modules.mod_extdisco.service.type`
* **Syntax:** string
* **Default:** none, this option is required
* **Example:** `type = "stun"`

Service type, common values are `"stun"`, `"turn"`, `"ftp"`.

### `modules.mod_extdisco.service.host`
#### `modules.mod_extdisco.service.host`
* **Syntax:** string
* **Default:** none, this option is required
* **Example:** `host = "192.168.0.2"`

Hostname or an IP address where the service is hosted.

### `modules.mod_extdisco.service.port`
#### `modules.mod_extdisco.service.port`
* **Syntax:** string
* **Default:** none, this option is recommended
* **Example:** `port = "3478"`

The communications port to be used at the host.

### `modules.mod_extdisco.service.transport`
#### `modules.mod_extdisco.service.transport`
* **Syntax:** string, one of `"udp"`, `"tcp"`
* **Default:** none, this option is optional
* **Example:** `transport = "udp"`

The underlying transport protocol to be used when communicating with the service.

### `modules.mod_extdisco.service.username`
#### `modules.mod_extdisco.service.username`
* **Syntax:** string
* **Default:** none, this option is optional
* **Example:** `username = "username"`

A service-generated username for use at the service.

### `modules.mod_extdisco.service.password`
#### `modules.mod_extdisco.service.password`
* **Syntax:** string
* **Default:** none, this option is optional
* **Example:** `password = "password"`
Expand All @@ -53,20 +68,23 @@ A service-generated password for use at the service.

```toml
[modules.mod_extdisco]

[[modules.mod_extdisco.service]]
type = "stun"
host = "127.0.0.1"
port = 3478
transport = "udp"
username = "username"
password = "password"

[[modules.mod_extdisco.service]]
type = "stun"
host = "stun.host.com"
port = 3478
transport = "tcp"
username = "username2"
password = "password2"

[[modules.mod_extdisco.service]]
type = "turn"
host = "turn.host.com"
Expand Down
2 changes: 1 addition & 1 deletion src/config/mongoose_config_parser.erl
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ post_process_modules_opt(Other) ->
Other.

unfold_opts(Modules) ->
maps:map(fun(_Mod, Opts) -> proplists:unfold(Opts) end, Modules).
maps:map(fun(_Mod, Opts) -> mongoose_modules:unfold_opts(Opts) end, Modules).

%% local functions

Expand Down
43 changes: 29 additions & 14 deletions src/gen_mod.erl
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@
get_opt/4,
set_opt/3,
get_module_opt/4,
get_module_opt/3,
get_module_opts/2,
get_loaded_module_opts/2,
get_opt_subhost/3,
Expand All @@ -82,7 +83,11 @@
-type module_feature() :: atom().
-type domain_name() :: mongooseim:domain_name().
-type host_type() :: mongooseim:host_type().
-type module_opts() :: list().
-type key_path() :: mongoose_config:key_path().
-type opt_key() :: term(). %% top-level module options have atoms as keys
-type opt_value() :: mongoose_config:value().
-type module_opts() :: [{opt_key(), opt_value()}] % deprecated, will be removed
| #{opt_key() => opt_value()}. % new format

%% -export([behaviour_info/1]).
%% behaviour_info(callbacks) ->
Expand Down Expand Up @@ -265,6 +270,11 @@ wait_for_stop(MonitorReference) ->
timeout
end.

-spec get_opt(opt_key() | key_path(), module_opts()) -> opt_value().
get_opt(Path, Opts) when is_list(Path), is_map(Opts) ->
lists:foldl(fun maps:get/2, Opts, Path);
get_opt(Opt, Opts) when is_map(Opts) ->
maps:get(Opt, Opts);
get_opt(Opt, Opts) ->
case lists:keysearch(Opt, 1, Opts) of
false ->
Expand All @@ -273,14 +283,16 @@ get_opt(Opt, Opts) ->
Val
end.

get_opt(Opt, Opts, Default) ->
case lists:keysearch(Opt, 1, Opts) of
false ->
Default;
{value, {_, Val}} ->
Val
-spec get_opt(opt_key() | key_path(), module_opts(), opt_value()) -> opt_value().
get_opt(Path, Opts, Default) ->
try
get_opt(Path, Opts)
catch
error:{badkey, _} -> Default;
throw:{undefined_option, _} -> Default
end.

%% @deprecated Processing should be done in the config spec
get_opt(Opt, Opts, F, Default) ->
case lists:keysearch(Opt, 1, Opts) of
false ->
Expand All @@ -289,16 +301,12 @@ get_opt(Opt, Opts, F, Default) ->
F(Val)
end.

-spec set_opt(_, [tuple()], _) -> [tuple(), ...].
%% @deprecated Options shouldn't be modified
set_opt(Opt, Opts, Value) ->
lists:keystore(Opt, 1, Opts, {Opt, Value}).


%%% TODO Make Opt an atom. Fix in mod_auth_token:
%%% 374: The call gen_mod:get_module_opt(Domain::any(), 'mod_auth_token',
%%% {'validity_period','access' | 'refresh'}, {1 | 25,'days' | 'hours'})
%%% breaks the contract (mongooseim:host_type(), module(), atom(), term()) -> term()
-spec get_module_opt(mongooseim:host_type(), module(), term(), term()) -> term().
-spec get_module_opt(mongooseim:host_type(), module(), opt_key() | key_path(), opt_value()) ->
opt_value().
get_module_opt(HostType, Module, Opt, Default) ->
%% Fail in dev builds.
%% It protects against passing something weird as a Module argument
Expand All @@ -307,10 +315,17 @@ get_module_opt(HostType, Module, Opt, Default) ->
ModuleOpts = get_module_opts(HostType, Module),
get_opt(Opt, ModuleOpts, Default).

-spec get_module_opt(mongooseim:host_type(), module(), opt_key() | key_path()) -> opt_value().
get_module_opt(HostType, Module, Opt) ->
?ASSERT_MODULE(Module),
ModuleOpts = get_loaded_module_opts(HostType, Module),
get_opt(Opt, ModuleOpts).

-spec get_module_opts(mongooseim:host_type(), module()) -> module_opts().
get_module_opts(HostType, Module) ->
mongoose_config:get_opt([{modules, HostType}, Module], []).

-spec get_loaded_module_opts(mongooseim:host_type(), module()) -> module_opts().
get_loaded_module_opts(HostType, Module) ->
mongoose_config:get_opt([{modules, HostType}, Module]).

Expand Down
20 changes: 10 additions & 10 deletions src/mam/mod_mam_rdbms_arch_async.erl
Original file line number Diff line number Diff line change
Expand Up @@ -64,18 +64,20 @@ supported_features() ->
-spec start_pool(mongooseim:host_type(), {writer_type(), gen_mod:module_opts()}) ->
supervisor:startchild_ret().
start_pool(HostType, {Type, Opts}) ->
{Opts1, Extra} = extend_opts(Type, Opts),
{PoolOpts, Extra} = make_pool_opts(Type, Opts),
prepare_insert_queries(Type, Extra),
ensure_metrics(Type, HostType),
register_hooks(Type, HostType),
start_pool(Type, HostType, Opts1).
start_pool(Type, HostType, PoolOpts).

extend_opts(Type, Opts) ->
-spec make_pool_opts(writer_type(), gen_mod:module_opts()) ->
{mongoose_async_pools:pool_opts(), mongoose_async_pools:pool_extra()}.
make_pool_opts(Type, Opts) ->
Merge = maps:merge(defaults(), maps:from_list(Opts)),
Extra = add_batch_name(Type, Merge),
Opts1 = maps:to_list(Extra),
Opts2 = gen_mod:set_opt(flush_extra, Opts1, Extra),
{add_callback(Type, Opts2), Extra}.
PoolOpts = Extra#{flush_callback => flush_callback(Type),
flush_extra => Extra},
{PoolOpts, Extra}.

%% Put batch_size into a statement name, so we could survive the module restarts
%% with different batch sizes
Expand All @@ -84,10 +86,8 @@ add_batch_name(pm, #{batch_size := MaxSize} = Opts) ->
add_batch_name(muc, #{batch_size := MaxSize} = Opts) ->
Opts#{batch_name => multi_name(insert_mam_muc_messages, MaxSize)}.

add_callback(pm, Opts) ->
gen_mod:set_opt(flush_callback, Opts, fun ?MODULE:flush_pm/2);
add_callback(muc, Opts) ->
gen_mod:set_opt(flush_callback, Opts, fun ?MODULE:flush_muc/2).
flush_callback(pm) -> fun ?MODULE:flush_pm/2;
flush_callback(muc) -> fun ?MODULE:flush_muc/2.

defaults() ->
#{flush_interval => 2000,
Expand Down
Loading

0 comments on commit 3e286cf

Please sign in to comment.