diff options
author | Evgeniy Khramtsov <ekhramtsov@process-one.net> | 2017-04-30 19:01:47 +0300 |
---|---|---|
committer | Evgeniy Khramtsov <ekhramtsov@process-one.net> | 2017-04-30 19:01:47 +0300 |
commit | fddd6110e00df12c99a20a2cc9d074f5f4f1f965 (patch) | |
tree | 366575b855f1b2013db7eeb02ecb213f81c98c1f /src/ejabberd_listener.erl | |
parent | Merge branch 'new-option-validation' (diff) |
Don't validate an option in gen_mod:get*opt() functions
The changes are very similar to those from previous commit:
* Now there is no need to pass validating function in
gen_mod:get_opt() and gen_mod:get_module_opt() functions,
because the modules' configuration keeps already validated values.
* New functions gen_mod:get_opt/2 and gen_mod:get_module_opt/3 are
introduced.
* Functions gen_mod:get_opt/4 and get_module_opt/5 are deprecated.
If the functions are still called, the "function" argument is
simply ignored.
* Validating callback Mod:listen_opt_type/1 is introduced to validate
listening options at startup.
Diffstat (limited to 'src/ejabberd_listener.erl')
-rw-r--r-- | src/ejabberd_listener.erl | 63 |
1 files changed, 45 insertions, 18 deletions
diff --git a/src/ejabberd_listener.erl b/src/ejabberd_listener.erl index 64e7f83b0..653ad931a 100644 --- a/src/ejabberd_listener.erl +++ b/src/ejabberd_listener.erl @@ -52,7 +52,6 @@ listeners_childspec() -> Ls = ejabberd_config:get_option(listen, []), Specs = lists:map( fun({Port, Module, Opts}) -> - maybe_start_sip(Module), ets:insert(?MODULE, {Port, Module, Opts}), {Port, {?MODULE, start, [Port, Module, Opts]}, @@ -82,10 +81,11 @@ report_duplicated_portips(L) -> end. start(Port, Module, Opts) -> + NewOpts = validate_module_options(Module, Opts), %% Check if the module is an ejabberd listener or an independent listener case Module:socket_type() of - independent -> Module:start_listener(Port, Opts); - _ -> start_dependent(Port, Module, Opts) + independent -> Module:start_listener(Port, NewOpts); + _ -> start_dependent(Port, Module, NewOpts) end. %% @spec(Port, Module, Opts) -> {ok, Pid} | {error, ErrorMessage} @@ -356,7 +356,6 @@ start_listener2(Port, Module, Opts) -> %% It is only required to start the supervisor in some cases. %% But it doesn't hurt to attempt to start it for any listener. %% So, it's normal (and harmless) that in most cases this call returns: {error, {already_started, pid()}} - maybe_start_sip(Module), start_listener_sup(Port, Module, Opts). start_module_sup(_Port, Module) -> @@ -427,12 +426,6 @@ delete_listener(PortIP, Module, Opts) -> PortIP1 = {Port, IPT, Proto}, stop_listener(PortIP1, Module). - -maybe_start_sip(esip_socket) -> - ejabberd:start_app(esip); -maybe_start_sip(_) -> - ok. - config_reloaded() -> New = ejabberd_config:get_option(listen, []), Old = ets:tab2list(?MODULE), @@ -626,6 +619,47 @@ transform_options({listen, LOpts}, Opts) -> transform_options(Opt, Opts) -> [Opt|Opts]. +-spec validate_module_options(module(), [{atom(), any()}]) -> [{atom(), any()}]. +validate_module_options(Module, Opts) -> + try Module:listen_opt_type('') of + _ -> + lists:filtermap( + fun({Opt, Val}) -> + case validate_module_option(Module, Opt, Val) of + {ok, NewVal} -> {true, {Opt, NewVal}}; + error -> false + end + end, Opts) + catch _:undef -> + ?WARNING_MSG("module '~s' doesn't export listen_opt_type/1", + [Module]), + Opts + end. + +-spec validate_module_option(module(), atom(), any()) -> {ok, any()} | error. +validate_module_option(Module, Opt, Val) -> + case Module:listen_opt_type(Opt) of + VFun when is_function(VFun) -> + try VFun(Val) of + NewVal -> {ok, NewVal} + catch {invalid_syntax, Error} -> + ?ERROR_MSG("ignoring listen option '~s' with " + "invalid value: ~p: ~s", + [Opt, Val, Error]), + error; + _:_ -> + ?ERROR_MSG("ignoring listen option '~s' with " + "invalid value: ~p", + [Opt, Val]), + error + end; + KnownOpts when is_list(KnownOpts) -> + ?ERROR_MSG("unknown listen option '~s' for '~s' will be likely " + "ignored, available options are: ~s", + [Opt, Module, misc:join_atoms(KnownOpts, <<", ">>)]), + {ok, Val} + end. + -type transport() :: udp | tcp. -type port_ip_transport() :: inet:port_number() | {inet:port_number(), transport()} | @@ -647,7 +681,7 @@ validate_cfg(L) -> true = ?IS_TRANSPORT(T), {{Port, IP, T}, Mod, Opts}; ({module, Mod}, {Port, _, Opts}) -> - {Port, prepare_mod(Mod), Opts}; + {Port, Mod, Opts}; (Opt, {Port, Mod, Opts}) -> {Port, Mod, [Opt|Opts]} end, {{5222, all_zero_ip(LOpts), tcp}, ejabberd_c2s, []}, LOpts) @@ -666,13 +700,6 @@ prepare_ip(IP) when is_list(IP) -> prepare_ip(IP) when is_binary(IP) -> prepare_ip(binary_to_list(IP)). -prepare_mod(ejabberd_sip) -> - prepare_mod(sip); -prepare_mod(sip) -> - esip_socket; -prepare_mod(Mod) when is_atom(Mod) -> - Mod. - all_zero_ip(Opts) -> case proplists:get_bool(inet6, Opts) of true -> {0,0,0,0,0,0,0,0}; |