aboutsummaryrefslogtreecommitdiff
path: root/src/ejabberd_listener.erl
diff options
context:
space:
mode:
authorEvgeniy Khramtsov <ekhramtsov@process-one.net>2017-04-30 19:01:47 +0300
committerEvgeniy Khramtsov <ekhramtsov@process-one.net>2017-04-30 19:01:47 +0300
commitfddd6110e00df12c99a20a2cc9d074f5f4f1f965 (patch)
tree366575b855f1b2013db7eeb02ecb213f81c98c1f /src/ejabberd_listener.erl
parentMerge 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.erl63
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};