aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEvgeniy Khramtsov <ekhramtsov@process-one.net>2017-02-22 19:46:47 +0300
committerEvgeniy Khramtsov <ekhramtsov@process-one.net>2017-02-22 19:46:47 +0300
commit3c4057ff553928d4e4ab40e410dbc6a478dd8206 (patch)
treea0272f84a1221db928cfd4c9f44d9bed6e196bc8
parentMake sure all hooks are called with proper host (diff)
Reload modules when reloading configuration file
-rw-r--r--src/ejabberd_config.erl5
-rw-r--r--src/gen_iq_handler.erl2
-rw-r--r--src/gen_mod.erl111
-rw-r--r--src/mod_adhoc.erl15
-rw-r--r--src/mod_admin_extra.erl5
-rw-r--r--src/mod_announce.erl12
-rw-r--r--src/mod_block_strangers.erl5
-rw-r--r--src/mod_blocking.erl13
-rw-r--r--src/mod_bosh.erl8
-rw-r--r--src/mod_caps.erl27
-rw-r--r--src/mod_carboncopy.erl21
-rw-r--r--src/mod_client_state.erl100
-rw-r--r--src/mod_configure.erl11
-rw-r--r--src/mod_delegation.erl5
-rw-r--r--src/mod_disco.erl43
-rw-r--r--src/mod_echo.erl22
-rw-r--r--src/mod_fail2ban.erl5
-rw-r--r--src/mod_http_api.erl6
-rw-r--r--src/mod_http_fileserver.erl43
-rw-r--r--src/mod_irc.erl81
-rw-r--r--src/mod_last.erl22
-rw-r--r--src/mod_legacy_auth.erl5
-rw-r--r--src/mod_mam.erl92
-rw-r--r--src/mod_metrics.erl5
-rw-r--r--src/mod_muc.erl218
-rw-r--r--src/mod_muc_admin.erl5
-rw-r--r--src/mod_muc_log.erl72
-rw-r--r--src/mod_multicast.erl30
-rw-r--r--src/mod_offline.erl36
-rw-r--r--src/mod_ping.erl122
-rw-r--r--src/mod_pres_counter.erl5
-rw-r--r--src/mod_privacy.erl20
-rw-r--r--src/mod_private.erl20
-rw-r--r--src/mod_privilege.erl5
-rw-r--r--src/mod_proxy65.erl7
-rw-r--r--src/mod_proxy65_service.erl42
-rw-r--r--src/mod_register.erl15
-rw-r--r--src/mod_register_web.erl5
-rw-r--r--src/mod_roster.erl20
-rw-r--r--src/mod_s2s_dialback.erl10
-rw-r--r--src/mod_shared_roster.erl14
-rw-r--r--src/mod_sic.erl19
-rw-r--r--src/mod_sip.erl6
-rw-r--r--src/mod_stats.erl5
-rw-r--r--src/mod_stream_mgmt.erl6
-rw-r--r--src/mod_time.erl13
-rw-r--r--src/mod_vcard_xupdate.erl12
-rw-r--r--src/mod_version.erl13
48 files changed, 1085 insertions, 299 deletions
diff --git a/src/ejabberd_config.erl b/src/ejabberd_config.erl
index 89cd67cad..ff0f7b3e8 100644
--- a/src/ejabberd_config.erl
+++ b/src/ejabberd_config.erl
@@ -138,7 +138,7 @@ get_ejabberd_config_path() ->
-spec get_env_config() -> {ok, string()} | undefined.
get_env_config() ->
%% First case: the filename can be specified with: erl -config "/path/to/ejabberd.yml".
- case application:get_env(config) of
+ case application:get_env(ejabberd, config) of
R = {ok, _Path} -> R;
undefined ->
%% Second case for embbeding ejabberd in another app, for example for Elixir:
@@ -194,7 +194,8 @@ load_file(File) ->
reload_file() ->
Config = get_ejabberd_config_path(),
- load_file(Config).
+ load_file(Config),
+ ejabberd_hooks:run(config_reloaded, []).
-spec convert_to_yaml(file:filename()) -> ok | {error, any()}.
diff --git a/src/gen_iq_handler.erl b/src/gen_iq_handler.erl
index 62874c4f4..ebf056ebb 100644
--- a/src/gen_iq_handler.erl
+++ b/src/gen_iq_handler.erl
@@ -50,7 +50,7 @@
-type component() :: ejabberd_sm | ejabberd_local.
-type type() :: no_queue | one_queue | pos_integer() | parallel.
-type opts() :: no_queue | {one_queue, pid()} | {queues, [pid()]} | parallel.
--export_type([opts/0]).
+-export_type([opts/0, type/0]).
%%====================================================================
%% API
diff --git a/src/gen_mod.erl b/src/gen_mod.erl
index 68a5aeb5b..b74d1555d 100644
--- a/src/gen_mod.erl
+++ b/src/gen_mod.erl
@@ -31,10 +31,10 @@
-author('alexey@process-one.net').
-export([init/1, start_link/0, start_child/3, start_child/4,
- stop_child/1, stop_child/2]).
+ stop_child/1, stop_child/2, config_reloaded/0]).
-export([start/0, start_module/2, start_module/3,
stop_module/2, stop_module_keep_config/2, get_opt/3,
- get_opt/4, get_opt_host/3, opt_type/1,
+ get_opt/4, get_opt_host/3, opt_type/1, is_equal_opt/5,
get_module_opt/4, get_module_opt/5, get_module_opt_host/3,
loaded_modules/1, loaded_modules_with_opts/1,
get_hosts/2, get_module_proc/2, is_loaded/2,
@@ -46,6 +46,7 @@
-include("ejabberd.hrl").
-include("logger.hrl").
+-include_lib("stdlib/include/ms_transform.hrl").
-record(ejabberd_module,
{module_host = {undefined, <<"">>} :: {atom(), binary()},
@@ -56,9 +57,12 @@
-callback start(binary(), opts()) -> ok | {ok, pid()}.
-callback stop(binary()) -> any().
+-callback reload(binary(), opts(), opts()) -> ok | {ok, pid()}.
-callback mod_opt_type(atom()) -> fun((term()) -> term()) | [atom()].
-callback depends(binary(), opts()) -> [{module(), hard | soft}].
+-optional_callbacks([reload/3]).
+
-export_type([opts/0]).
-export_type([db_type/0]).
@@ -75,6 +79,7 @@ start_link() ->
supervisor:start_link({local, ejabberd_gen_mod_sup}, ?MODULE, []).
init([]) ->
+ ejabberd_hooks:add(config_reloaded, ?MODULE, config_reloaded, 50),
ets:new(ejabberd_modules,
[named_table, public,
{keypos, #ejabberd_module.module_host}]),
@@ -182,9 +187,7 @@ start_module(Host, Module) ->
start_module(Host, Module, Opts0) ->
?DEBUG("loading ~s at ~s", [Module, Host]),
Opts = validate_opts(Module, Opts0),
- ets:insert(ejabberd_modules,
- #ejabberd_module{module_host = {Module, Host},
- opts = Opts}),
+ store_options(Host, Module, Opts),
try case Module:start(Host, Opts) of
ok -> ok;
{ok, Pid} when is_pid(Pid) -> {ok, Pid};
@@ -202,6 +205,77 @@ start_module(Host, Module, Opts0) ->
erlang:raise(Class, Reason, erlang:get_stacktrace())
end.
+-spec reload_modules(binary()) -> ok.
+reload_modules(Host) ->
+ NewMods = ejabberd_config:get_option(
+ {modules, Host}, opt_type(modules), []),
+ OldMods = ets:select(
+ ejabberd_modules,
+ ets:fun2ms(
+ fun(#ejabberd_module{module_host = {M, H}, opts = O})
+ when H == Host -> {M, O}
+ end)),
+ lists:foreach(
+ fun({Mod, _Opts}) ->
+ case lists:keymember(Mod, 1, NewMods) of
+ false ->
+ stop_module(Host, Mod);
+ true ->
+ ok
+ end
+ end, OldMods),
+ lists:foreach(
+ fun({Mod, Opts}) ->
+ case lists:keymember(Mod, 1, OldMods) of
+ false ->
+ start_module(Host, Mod, Opts);
+ true ->
+ ok
+ end
+ end, NewMods),
+ lists:foreach(
+ fun({Mod, OldOpts}) ->
+ case lists:keyfind(Mod, 1, NewMods) of
+ {_, NewOpts} when NewOpts /= OldOpts ->
+ reload_module(Host, Mod, NewOpts, OldOpts);
+ _ ->
+ ok
+ end
+ end, OldMods).
+
+-spec reload_module(binary(), module(), opts(), opts()) -> ok | {ok, pid()}.
+reload_module(Host, Module, NewOpts0, OldOpts) ->
+ case erlang:function_exported(Module, reload, 3) of
+ true ->
+ ?DEBUG("reloading ~s at ~s", [Module, Host]),
+ NewOpts = validate_opts(Module, NewOpts0),
+ store_options(Host, Module, NewOpts),
+ try case Module:reload(Host, NewOpts, OldOpts) of
+ ok -> ok;
+ {ok, Pid} when is_pid(Pid) -> {ok, Pid};
+ Err -> erlang:error(Err)
+ end
+ catch Class:Reason ->
+ StackTrace = erlang:get_stacktrace(),
+ ?CRITICAL_MSG("failed to reload module ~s at ~s:~n"
+ "** Reason = ~p",
+ [Module, Host,
+ {Class, {Reason, StackTrace}}]),
+ erlang:raise(Class, Reason, StackTrace)
+ end;
+ false ->
+ ?WARNING_MSG("module ~s doesn't support reloading "
+ "and will be restarted", [Module]),
+ stop_module(Host, Module),
+ start_module(Host, Module, NewOpts0)
+ end.
+
+-spec store_options(binary(), module(), opts()) -> true.
+store_options(Host, Module, Opts) ->
+ ets:insert(ejabberd_modules,
+ #ejabberd_module{module_host = {Module, Host},
+ opts = Opts}).
+
maybe_halt_ejabberd(ErrorText) ->
case is_app_running(ejabberd) of
false ->
@@ -239,6 +313,7 @@ stop_modules(Host) ->
-spec stop_module(binary(), atom()) -> error | {aborted, any()} | {atomic, any()}.
stop_module(Host, Module) ->
+ ?DEBUG("stopping ~s at ~s", [Module, Host]),
case stop_module_keep_config(Host, Module) of
error -> error;
ok -> ok
@@ -544,5 +619,29 @@ get_module_proc(Host, Base) ->
is_loaded(Host, Module) ->
ets:member(ejabberd_modules, {Module, Host}).
-opt_type(modules) -> fun (L) when is_list(L) -> L end;
+-spec config_reloaded() -> ok.
+config_reloaded() ->
+ lists:foreach(
+ fun(Host) ->
+ reload_modules(Host)
+ end, ?MYHOSTS).
+
+-spec is_equal_opt(atom(), opts(), opts(), check_fun(), any()) ->
+ true | {false, any(), any()}.
+is_equal_opt(Opt, NewOpts, OldOpts, VFun, Default) ->
+ NewVal = get_opt(Opt, NewOpts, VFun, Default),
+ OldVal = get_opt(Opt, OldOpts, VFun, Default),
+ if NewVal /= OldVal ->
+ {false, NewVal, OldVal};
+ true ->
+ true
+ end.
+
+opt_type(modules) ->
+ fun(Mods) ->
+ lists:map(
+ fun({M, A}) when is_atom(M), is_list(A) ->
+ {M, A}
+ end, Mods)
+ end;
opt_type(_) -> [modules].
diff --git a/src/mod_adhoc.erl b/src/mod_adhoc.erl
index fc0c62831..a0090aba9 100644
--- a/src/mod_adhoc.erl
+++ b/src/mod_adhoc.erl
@@ -31,7 +31,7 @@
-behaviour(gen_mod).
--export([start/2, stop/1, process_local_iq/1,
+-export([start/2, stop/1, reload/3, process_local_iq/1,
process_sm_iq/1, get_local_commands/5,
get_local_identity/5, get_local_features/5,
get_sm_commands/5, get_sm_identity/5, get_sm_features/5,
@@ -88,6 +88,19 @@ stop(Host) ->
gen_iq_handler:remove_iq_handler(ejabberd_local, Host,
?NS_COMMANDS).
+reload(Host, NewOpts, OldOpts) ->
+ case gen_mod:is_equal_opt(iqdisc, NewOpts, OldOpts,
+ fun gen_iq_handler:check_type/1,
+ one_queue) of
+ {false, IQDisc, _} ->
+ gen_iq_handler:add_iq_handler(ejabberd_local, Host, ?NS_COMMANDS,
+ ?MODULE, process_local_iq, IQDisc),
+ gen_iq_handler:add_iq_handler(ejabberd_sm, Host, ?NS_COMMANDS,
+ ?MODULE, process_sm_iq, IQDisc);
+ true ->
+ ok
+ end.
+
%-------------------------------------------------------------------------
get_local_commands(Acc, _From,
diff --git a/src/mod_admin_extra.erl b/src/mod_admin_extra.erl
index fc07faacb..317d0406f 100644
--- a/src/mod_admin_extra.erl
+++ b/src/mod_admin_extra.erl
@@ -30,7 +30,7 @@
-include("logger.hrl").
--export([start/2, stop/1, mod_opt_type/1,
+-export([start/2, stop/1, reload/3, mod_opt_type/1,
get_commands_spec/0, depends/2]).
% Commands API
@@ -96,6 +96,9 @@ start(_Host, _Opts) ->
stop(_Host) ->
ejabberd_commands:unregister_commands(get_commands_spec()).
+reload(_Host, _NewOpts, _OldOpts) ->
+ ok.
+
depends(_Host, _Opts) ->
[].
diff --git a/src/mod_announce.erl b/src/mod_announce.erl
index 29def8378..f1da3802b 100644
--- a/src/mod_announce.erl
+++ b/src/mod_announce.erl
@@ -32,7 +32,7 @@
-behaviour(gen_server).
-behaviour(gen_mod).
--export([start/2, stop/1, export/1, import_info/0,
+-export([start/2, stop/1, reload/3, export/1, import_info/0,
import_start/2, import/5, announce/1, send_motd/1, disco_identity/5,
disco_features/5, disco_items/5, depends/2,
send_announcement_to_all/3, announce_commands/4,
@@ -80,6 +80,16 @@ start(Host, Opts) ->
stop(Host) ->
gen_mod:stop_child(?MODULE, Host).
+reload(Host, NewOpts, OldOpts) ->
+ NewMod = gen_mod:db_mod(Host, NewOpts, ?MODULE),
+ OldMod = gen_mod:db_mod(Host, OldOpts, ?MODULE),
+ if NewMod /= OldMod ->
+ NewMod:init(Host, NewOpts);
+ true ->
+ ok
+ end,
+ ok.
+
depends(_Host, _Opts) ->
[{mod_adhoc, hard}].
diff --git a/src/mod_block_strangers.erl b/src/mod_block_strangers.erl
index 56fddd093..dfc9f9b74 100644
--- a/src/mod_block_strangers.erl
+++ b/src/mod_block_strangers.erl
@@ -29,7 +29,7 @@
-behaviour(gen_mod).
%% API
--export([start/2, stop/1,
+-export([start/2, stop/1, reload/3,
depends/2, mod_opt_type/1]).
-export([filter_packet/1]).
@@ -50,6 +50,9 @@ stop(Host) ->
?MODULE, filter_packet, 25),
ok.
+reload(_Host, _NewOpts, _OldOpts) ->
+ ok.
+
filter_packet({#message{} = Msg, State} = Acc) ->
From = xmpp:get_from(Msg),
LFrom = jid:tolower(From),
diff --git a/src/mod_blocking.erl b/src/mod_blocking.erl
index dd1f8f741..97c2e8b16 100644
--- a/src/mod_blocking.erl
+++ b/src/mod_blocking.erl
@@ -29,7 +29,7 @@
-protocol({xep, 191, '1.2'}).
--export([start/2, stop/1, process_iq/1, mod_opt_type/1, depends/2,
+-export([start/2, stop/1, reload/3, process_iq/1, mod_opt_type/1, depends/2,
disco_features/5]).
-include("ejabberd.hrl").
@@ -56,6 +56,17 @@ stop(Host) ->
ejabberd_hooks:delete(disco_local_features, Host, ?MODULE, disco_features, 50),
gen_iq_handler:remove_iq_handler(ejabberd_sm, Host, ?NS_BLOCKING).
+reload(Host, NewOpts, OldOpts) ->
+ case gen_mod:is_equal_opt(iqdisc, NewOpts, OldOpts,
+ fun gen_iq_handler:check_type/1,
+ one_queue) of
+ {false, IQDisc, _} ->
+ gen_iq_handler:add_iq_handler(ejabberd_sm, Host, ?NS_BLOCKING,
+ ?MODULE, process_iq, IQDisc);
+ true ->
+ ok
+ end.
+
depends(_Host, _Opts) ->
[{mod_privacy, hard}].
diff --git a/src/mod_bosh.erl b/src/mod_bosh.erl
index 04fb7f557..049504ee4 100644
--- a/src/mod_bosh.erl
+++ b/src/mod_bosh.erl
@@ -33,7 +33,7 @@
-behaviour(gen_mod).
-export([start_link/0]).
--export([start/2, stop/1, process/2, open_session/2,
+-export([start/2, stop/1, reload/3, process/2, open_session/2,
close_session/1, find_session/1]).
-export([depends/2, mod_opt_type/1]).
@@ -103,6 +103,12 @@ stop(Host) ->
supervisor:terminate_child(ejabberd_sup, TmpSup),
supervisor:delete_child(ejabberd_sup, TmpSup).
+reload(_Host, NewOpts, _OldOpts) ->
+ start_jiffy(NewOpts),
+ Mod = gen_mod:ram_db_mod(global, ?MODULE),
+ Mod:init(),
+ ok.
+
%%%===================================================================
%%% Internal functions
%%%===================================================================
diff --git a/src/mod_caps.erl b/src/mod_caps.erl
index e23b66895..42a5d94df 100644
--- a/src/mod_caps.erl
+++ b/src/mod_caps.erl
@@ -41,7 +41,7 @@
get_user_caps/2, import_start/2, import_stop/2]).
%% gen_mod callbacks
--export([start/2, stop/1, depends/2]).
+-export([start/2, stop/1, reload/3, depends/2]).
%% gen_server callbacks
-export([init/1, handle_info/2, handle_call/3,
@@ -238,6 +238,31 @@ c2s_presence_in(C2SState,
depends(_Host, _Opts) ->
[].
+reload(Host, NewOpts, OldOpts) ->
+ NewMod = gen_mod:db_mod(Host, NewOpts, ?MODULE),
+ OldMod = gen_mod:db_mod(Host, OldOpts, ?MODULE),
+ if OldMod /= NewMod ->
+ NewMod:init(Host, NewOpts);
+ true ->
+ ok
+ end,
+ case gen_mod:is_equal_opt(cache_size, NewOpts, OldOpts,
+ fun(I) when is_integer(I), I>0 -> I end,
+ 1000) of
+ {false, MaxSize, _} ->
+ cache_tab:setopts(caps_features, [{max_size, MaxSize}]);
+ true ->
+ ok
+ end,
+ case gen_mod:is_equal_opt(cache_life_time, NewOpts, OldOpts,
+ fun(I) when is_integer(I), I>0 -> I end,
+ timer:hours(24) div 1000) of
+ {false, LifeTime, _} ->
+ cache_tab:setopts(caps_features, [{life_time, LifeTime}]);
+ true ->
+ ok
+ end.
+
init([Host, Opts]) ->
process_flag(trap_exit, true),
Mod = gen_mod:db_mod(Host, Opts, ?MODULE),
diff --git a/src/mod_carboncopy.erl b/src/mod_carboncopy.erl
index 0071b68b5..03fe475f2 100644
--- a/src/mod_carboncopy.erl
+++ b/src/mod_carboncopy.erl
@@ -32,8 +32,7 @@
-behavior(gen_mod).
%% API:
--export([start/2,
- stop/1]).
+-export([start/2, stop/1, reload/3]).
-export([user_send_packet/1, user_receive_packet/1,
iq_handler/1, remove_connection/4, disco_features/5,
@@ -75,6 +74,24 @@ stop(Host) ->
ejabberd_hooks:delete(user_receive_packet,Host, ?MODULE, user_receive_packet, 89),
ejabberd_hooks:delete(unset_presence_hook,Host, ?MODULE, remove_connection, 10).
+reload(Host, NewOpts, OldOpts) ->
+ NewMod = gen_mod:db_mod(Host, NewOpts, ?MODULE),
+ OldMod = gen_mod:db_mod(Host, OldOpts, ?MODULE),
+ if NewMod /= OldMod ->
+ NewMod:init(Host, NewOpts);
+ true ->
+ ok
+ end,
+ case gen_mod:is_equal_opt(iqdisc, NewOpts, OldOpts,
+ fun gen_iq_handler:check_type/1,
+ one_queue) of
+ {false, IQDisc, _} ->
+ gen_iq_handler:add_iq_handler(ejabberd_sm, Host, ?NS_CARBONS_2,
+ ?MODULE, iq_handler, IQDisc);
+ true ->
+ ok
+ end.
+
-spec disco_features({error, stanza_error()} | {result, [binary()]} | empty,
jid(), jid(), binary(), binary()) ->
{error, stanza_error()} | {result, [binary()]}.
diff --git a/src/mod_client_state.erl b/src/mod_client_state.erl
index d912bef50..f6d7292b5 100644
--- a/src/mod_client_state.erl
+++ b/src/mod_client_state.erl
@@ -31,7 +31,7 @@
-behavior(gen_mod).
%% gen_mod callbacks.
--export([start/2, stop/1, mod_opt_type/1, depends/2]).
+-export([start/2, stop/1, reload/3, mod_opt_type/1, depends/2]).
%% ejabberd_hooks callbacks.
-export([filter_presence/1, filter_chat_states/1,
@@ -72,16 +72,7 @@ start(Host, Opts) ->
fun(B) when is_boolean(B) -> B end,
true),
if QueuePresence; QueueChatStates; QueuePEP ->
- ejabberd_hooks:add(c2s_stream_started, Host, ?MODULE,
- c2s_stream_started, 50),
- ejabberd_hooks:add(c2s_post_auth_features, Host, ?MODULE,
- add_stream_feature, 50),
- ejabberd_hooks:add(c2s_authenticated_packet, Host, ?MODULE,
- c2s_authenticated_packet, 50),
- ejabberd_hooks:add(c2s_copy_session, Host, ?MODULE,
- c2s_copy_session, 50),
- ejabberd_hooks:add(c2s_session_resumed, Host, ?MODULE,
- c2s_session_resumed, 50),
+ register_hooks(Host),
if QueuePresence ->
ejabberd_hooks:add(c2s_filter_send, Host, ?MODULE,
filter_presence, 50);
@@ -96,9 +87,7 @@ start(Host, Opts) ->
ejabberd_hooks:add(c2s_filter_send, Host, ?MODULE,
filter_pep, 50);
true -> ok
- end,
- ejabberd_hooks:add(c2s_filter_send, Host, ?MODULE,
- filter_other, 75);
+ end;
true -> ok
end.
@@ -118,16 +107,7 @@ stop(Host) ->
fun(B) when is_boolean(B) -> B end,
true),
if QueuePresence; QueueChatStates; QueuePEP ->
- ejabberd_hooks:delete(c2s_stream_started, Host, ?MODULE,
- c2s_stream_started, 50),
- ejabberd_hooks:delete(c2s_post_auth_features, Host, ?MODULE,
- add_stream_feature, 50),
- ejabberd_hooks:delete(c2s_authenticated_packet, Host, ?MODULE,
- c2s_authenticated_packet, 50),
- ejabberd_hooks:delete(c2s_copy_session, Host, ?MODULE,
- c2s_copy_session, 50),
- ejabberd_hooks:delete(c2s_session_resumed, Host, ?MODULE,
- c2s_session_resumed, 50),
+ unregister_hooks(Host),
if QueuePresence ->
ejabberd_hooks:delete(c2s_filter_send, Host, ?MODULE,
filter_presence, 50);
@@ -142,12 +122,48 @@ stop(Host) ->
ejabberd_hooks:delete(c2s_filter_send, Host, ?MODULE,
filter_pep, 50);
true -> ok
- end,
- ejabberd_hooks:delete(c2s_filter_send, Host, ?MODULE,
- filter_other, 75);
+ end;
true -> ok
end.
+-spec reload(binary(), gen_mod:opts(), gen_mod:opts()) -> ok.
+reload(Host, NewOpts, _OldOpts) ->
+ QueuePresence = gen_mod:get_opt(queue_presence, NewOpts,
+ fun(B) when is_boolean(B) -> B end,
+ true),
+ QueueChatStates = gen_mod:get_opt(queue_chat_states, NewOpts,
+ fun(B) when is_boolean(B) -> B end,
+ true),
+ QueuePEP = gen_mod:get_opt(queue_pep, NewOpts,
+ fun(B) when is_boolean(B) -> B end,
+ true),
+ if QueuePresence; QueueChatStates; QueuePEP ->
+ register_hooks(Host);
+ true ->
+ unregister_hooks(Host)
+ end,
+ if QueuePresence ->
+ ejabberd_hooks:add(c2s_filter_send, Host, ?MODULE,
+ filter_presence, 50);
+ true ->
+ ejabberd_hooks:delete(c2s_filter_send, Host, ?MODULE,
+ filter_presence, 50)
+ end,
+ if QueueChatStates ->
+ ejabberd_hooks:add(c2s_filter_send, Host, ?MODULE,
+ filter_chat_states, 50);
+ true ->
+ ejabberd_hooks:delete(c2s_filter_send, Host, ?MODULE,
+ filter_chat_states, 50)
+ end,
+ if QueuePEP ->
+ ejabberd_hooks:add(c2s_filter_send, Host, ?MODULE,
+ filter_pep, 50);
+ true ->
+ ejabberd_hooks:delete(c2s_filter_send, Host, ?MODULE,
+ filter_pep, 50)
+ end.
+
-spec mod_opt_type(atom()) -> fun((term()) -> term()) | [atom()].
mod_opt_type(queue_presence) ->
@@ -163,6 +179,36 @@ mod_opt_type(_) -> [queue_presence, queue_chat_states, queue_pep].
depends(_Host, _Opts) ->
[].
+-spec register_hooks(binary()) -> ok.
+register_hooks(Host) ->
+ ejabberd_hooks:add(c2s_stream_started, Host, ?MODULE,
+ c2s_stream_started, 50),
+ ejabberd_hooks:add(c2s_post_auth_features, Host, ?MODULE,
+ add_stream_feature, 50),
+ ejabberd_hooks:add(c2s_authenticated_packet, Host, ?MODULE,
+ c2s_authenticated_packet, 50),
+ ejabberd_hooks:add(c2s_copy_session, Host, ?MODULE,
+ c2s_copy_session, 50),
+ ejabberd_hooks:add(c2s_session_resumed, Host, ?MODULE,
+ c2s_session_resumed, 50),
+ ejabberd_hooks:add(c2s_filter_send, Host, ?MODULE,
+ filter_other, 75).
+
+-spec unregister_hooks(binary()) -> ok.
+unregister_hooks(Host) ->
+ ejabberd_hooks:delete(c2s_stream_started, Host, ?MODULE,
+ c2s_stream_started, 50),
+ ejabberd_hooks:delete(c2s_post_auth_features, Host, ?MODULE,
+ add_stream_feature, 50),
+ ejabberd_hooks:delete(c2s_authenticated_packet, Host, ?MODULE,
+ c2s_authenticated_packet, 50),
+ ejabberd_hooks:delete(c2s_copy_session, Host, ?MODULE,
+ c2s_copy_session, 50),
+ ejabberd_hooks:delete(c2s_session_resumed, Host, ?MODULE,
+ c2s_session_resumed, 50),
+ ejabberd_hooks:delete(c2s_filter_send, Host, ?MODULE,
+ filter_other, 75).
+
%%--------------------------------------------------------------------
%% ejabberd_hooks callbacks.
%%--------------------------------------------------------------------
diff --git a/src/mod_configure.erl b/src/mod_configure.erl
index b1827be05..1af8bf6ff 100644
--- a/src/mod_configure.erl
+++ b/src/mod_configure.erl
@@ -31,7 +31,7 @@
-behaviour(gen_mod).
--export([start/2, stop/1, get_local_identity/5,
+-export([start/2, stop/1, reload/3, get_local_identity/5,
get_local_features/5, get_local_items/5,
adhoc_local_items/4, adhoc_local_commands/4,
get_sm_identity/5, get_sm_features/5, get_sm_items/5,
@@ -89,11 +89,10 @@ stop(Host) ->
ejabberd_hooks:delete(disco_local_features, Host,
?MODULE, get_local_features, 50),
ejabberd_hooks:delete(disco_local_items, Host, ?MODULE,
- get_local_items, 50),
- gen_iq_handler:remove_iq_handler(ejabberd_local, Host,
- ?NS_COMMANDS),
- gen_iq_handler:remove_iq_handler(ejabberd_sm, Host,
- ?NS_COMMANDS).
+ get_local_items, 50).
+
+reload(_Host, _NewOpts, _OldOpts) ->
+ ok.
depends(_Host, _Opts) ->
[{mod_adhoc, hard}, {mod_last, soft}].
diff --git a/src/mod_delegation.erl b/src/mod_delegation.erl
index b3377fe75..baad79af3 100644
--- a/src/mod_delegation.erl
+++ b/src/mod_delegation.erl
@@ -31,7 +31,7 @@
-behaviour(gen_mod).
%% API
--export([start/2, stop/1, mod_opt_type/1, depends/2]).
+-export([start/2, stop/1, reload/3, mod_opt_type/1, depends/2]).
%% gen_server callbacks
-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
terminate/2, code_change/3]).
@@ -57,6 +57,9 @@ start(Host, Opts) ->
stop(Host) ->
gen_mod:stop_child(?MODULE, Host).
+reload(_Host, _NewOpts, _OldOpts) ->
+ ok.
+
mod_opt_type(iqdisc) -> fun gen_iq_handler:check_type/1;
mod_opt_type(namespaces) -> validate_fun();
mod_opt_type(_) ->
diff --git a/src/mod_disco.erl b/src/mod_disco.erl
index 2de8679ee..88c06c543 100644
--- a/src/mod_disco.erl
+++ b/src/mod_disco.erl
@@ -32,7 +32,7 @@
-behaviour(gen_mod).
--export([start/2, stop/1, process_local_iq_items/1,
+-export([start/2, stop/1, reload/3, process_local_iq_items/1,
process_local_iq_info/1, get_local_identity/5,
get_local_features/5, get_local_services/5,
process_sm_iq_items/1, process_sm_iq_info/1,
@@ -118,10 +118,51 @@ stop(Host) ->
{{'_', Host}}),
ok.
+reload(Host, NewOpts, OldOpts) ->
+ case gen_mod:is_equal_opt(extra_domains, NewOpts, OldOpts,
+ fun(Hs) ->
+ [iolist_to_binary(H) || H <- Hs]
+ end, []) of
+ {false, NewDomains, OldDomains} ->
+ lists:foreach(
+ fun(Domain) ->
+ register_extra_domain(Host, Domain)
+ end, NewDomains -- OldDomains),
+ lists:foreach(
+ fun(Domain) ->
+ unregister_extra_domain(Host, Domain)
+ end, OldDomains -- NewDomains);
+ true ->
+ ok
+ end,
+ case gen_mod:is_equal_opt(iqdisc, NewOpts, OldOpts,
+ fun gen_iq_handler:check_type/1,
+ one_queue) of
+ {false, IQDisc, _} ->
+ gen_iq_handler:add_iq_handler(ejabberd_local, Host,
+ ?NS_DISCO_ITEMS, ?MODULE,
+ process_local_iq_items, IQDisc),
+ gen_iq_handler:add_iq_handler(ejabberd_local, Host,
+ ?NS_DISCO_INFO, ?MODULE,
+ process_local_iq_info, IQDisc),
+ gen_iq_handler:add_iq_handler(ejabberd_sm, Host,
+ ?NS_DISCO_ITEMS, ?MODULE, process_sm_iq_items,
+ IQDisc),
+ gen_iq_handler:add_iq_handler(ejabberd_sm, Host,
+ ?NS_DISCO_INFO, ?MODULE, process_sm_iq_info,
+ IQDisc);
+ true ->
+ ok
+ end.
+
-spec register_extra_domain(binary(), binary()) -> true.
register_extra_domain(Host, Domain) ->
ets:insert(disco_extra_domains, {{Domain, Host}}).
+-spec unregister_extra_domain(binary(), binary()) -> true.
+unregister_extra_domain(Host, Domain) ->
+ ets:delete_object(disco_extra_domains, {{Domain, Host}}).
+
-spec process_local_iq_items(iq()) -> iq().
process_local_iq_items(#iq{type = set, lang = Lang} = IQ) ->
Txt = <<"Value 'set' of 'type' attribute is not allowed">>,
diff --git a/src/mod_echo.erl b/src/mod_echo.erl
index 5db5d49ce..7eeb8d4e9 100644
--- a/src/mod_echo.erl
+++ b/src/mod_echo.erl
@@ -32,7 +32,7 @@
-behaviour(gen_mod).
%% API
--export([start/2, stop/1, do_client_version/3]).
+-export([start/2, stop/1, reload/3, do_client_version/3]).
-export([init/1, handle_call/3, handle_cast/2,
handle_info/2, terminate/2, code_change/3,
@@ -54,6 +54,10 @@ start(Host, Opts) ->
stop(Host) ->
gen_mod:stop_child(?MODULE, Host).
+reload(Host, NewOpts, OldOpts) ->
+ Proc = gen_mod:get_module_proc(Host, ?MODULE),
+ gen_server:cast(Proc, {reload, Host, NewOpts, OldOpts}).
+
depends(_Host, _Opts) ->
[].
@@ -96,7 +100,21 @@ handle_call(stop, _From, State) ->
%% {stop, Reason, State}
%% Description: Handling cast messages
%%--------------------------------------------------------------------
-handle_cast(_Msg, State) -> {noreply, State}.
+handle_cast({reload, Host, NewOpts, OldOpts}, State) ->
+ NewMyHost = gen_mod:get_opt_host(Host, NewOpts,
+ <<"echo.@HOST@">>),
+ OldMyHost = gen_mod:get_opt_host(Host, OldOpts,
+ <<"echo.@HOST@">>),
+ if NewMyHost /= OldMyHost ->
+ ejabberd_router:register_route(NewMyHost, Host),
+ ejabberd_router:unregister_route(OldMyHost);
+ true ->
+ ok
+ end,
+ {noreply, State#state{host = NewMyHost}};
+handle_cast(Msg, State) ->
+ ?WARNING_MSG("unexpected cast: ~p", [Msg]),
+ {noreply, State}.
%%--------------------------------------------------------------------
%% Function: handle_info(Info, State) -> {noreply, State} |
diff --git a/src/mod_fail2ban.erl b/src/mod_fail2ban.erl
index 7f404d846..b6f889fc9 100644
--- a/src/mod_fail2ban.erl
+++ b/src/mod_fail2ban.erl
@@ -28,7 +28,7 @@
-behaviour(gen_server).
%% API
--export([start/2, stop/1, c2s_auth_result/3,
+-export([start/2, stop/1, reload/3, c2s_auth_result/3,
c2s_stream_started/2]).
-export([init/1, handle_call/3, handle_cast/2,
@@ -111,6 +111,9 @@ start(Host, Opts) ->
stop(Host) ->
gen_mod:stop_child(?MODULE, Host).
+reload(_Host, _NewOpts, _OldOpts) ->
+ ok.
+
depends(_Host, _Opts) ->
[].
diff --git a/src/mod_http_api.erl b/src/mod_http_api.erl
index d962aaefe..4956f2f62 100644
--- a/src/mod_http_api.erl
+++ b/src/mod_http_api.erl
@@ -74,7 +74,7 @@
-behaviour(gen_mod).
--export([start/2, stop/1, process/2, mod_opt_type/1, depends/2]).
+-export([start/2, stop/1, reload/3, process/2, mod_opt_type/1, depends/2]).
-include("ejabberd.hrl").
-include("xmpp.hrl").
@@ -125,6 +125,10 @@ stop(_Host) ->
ejabberd_access_permissions:unregister_permission_addon(?MODULE),
ok.
+reload(Host, NewOpts, _OldOpts) ->
+ stop(Host),
+ start(Host, NewOpts).
+
depends(_Host, _Opts) ->
[].
diff --git a/src/mod_http_fileserver.erl b/src/mod_http_fileserver.erl
index 143ab03f5..79eeed5ac 100644
--- a/src/mod_http_fileserver.erl
+++ b/src/mod_http_fileserver.erl
@@ -31,7 +31,7 @@
-behaviour(gen_server).
%% gen_mod callbacks
--export([start/2, stop/1]).
+-export([start/2, stop/1, reload/3]).
%% gen_server callbacks
-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
@@ -90,6 +90,10 @@ start(Host, Opts) ->
stop(Host) ->
gen_mod:stop_child(?MODULE, Host).
+reload(Host, NewOpts, OldOpts) ->
+ Proc = get_proc_name(Host),
+ gen_server:cast(Proc, {reload, Host, NewOpts, OldOpts}).
+
depends(_Host, _Opts) ->
[].
@@ -105,19 +109,9 @@ depends(_Host, _Opts) ->
%%--------------------------------------------------------------------
init([Host, Opts]) ->
try initialize(Host, Opts) of
- {DocRoot, AccessLog, AccessLogFD, DirectoryIndices,
- CustomHeaders, DefaultContentType, ContentTypes,
- UserAccess} ->
+ State ->
process_flag(trap_exit, true),
- {ok, #state{host = Host,
- accesslog = AccessLog,
- accesslogfd = AccessLogFD,
- docroot = DocRoot,
- directory_indices = DirectoryIndices,
- custom_headers = CustomHeaders,
- default_content_type = DefaultContentType,
- content_types = ContentTypes,
- user_access = UserAccess}}
+ {ok, State}
catch
throw:Reason ->
{stop, Reason}
@@ -163,9 +157,15 @@ initialize(Host, Opts) ->
?INFO_MSG("known content types: ~s",
[str:join([[$*, K, " -> ", V] || {K, V} <- ContentTypes],
<<", ">>)]),
- {DocRoot, AccessLog, AccessLogFD, DirectoryIndices,
- CustomHeaders, DefaultContentType, ContentTypes, UserAccess}.
-
+ #state{host = Host,
+ accesslog = AccessLog,
+ accesslogfd = AccessLogFD,
+ docroot = DocRoot,
+ directory_indices = DirectoryIndices,
+ custom_headers = CustomHeaders,
+ default_content_type = DefaultContentType,
+ content_types = ContentTypes,
+ user_access = UserAccess}.
%% @spec (AdminCTs::[CT], Default::[CT]) -> [CT]
%% where CT = {Extension::string(), Value}
@@ -251,7 +251,16 @@ handle_cast({add_to_log, FileSize, Code, Request}, State) ->
handle_cast(reopen_log, State) ->
FD2 = reopen_log(State#state.accesslog, State#state.accesslogfd),
{noreply, State#state{accesslogfd = FD2}};
-handle_cast(_Msg, State) ->
+handle_cast({reload, Host, NewOpts, _OldOpts}, OldState) ->
+ try initialize(Host, NewOpts) of
+ NewState ->
+ FD = reopen_log(NewState#state.accesslog, OldState#state.accesslogfd),
+ {noreply, NewState#state{accesslogfd = FD}}
+ catch throw:_ ->
+ {noreply, OldState}
+ end;
+handle_cast(Msg, State) ->
+ ?WARNING_MSG("unexpected cast: ~p", [Msg]),
{noreply, State}.
%%--------------------------------------------------------------------
diff --git a/src/mod_irc.erl b/src/mod_irc.erl
index 68f31dfde..37d54954b 100644
--- a/src/mod_irc.erl
+++ b/src/mod_irc.erl
@@ -32,7 +32,7 @@
-behaviour(gen_mod).
%% API
--export([start/2, stop/1, export/1, import/1,
+-export([start/2, stop/1, reload/3, export/1, import/1,
import/3, closed_connection/3, get_connection_params/3,
data_to_binary/2, process_disco_info/1, process_disco_items/1,
process_register/1, process_vcard/1, process_command/1]).
@@ -78,6 +78,10 @@ stop(Host) ->
stop_supervisor(Host),
gen_mod:stop_child(?MODULE, Host).
+reload(Host, NewOpts, OldOpts) ->
+ Proc = gen_mod:get_module_proc(Host, ?MODULE),
+ gen_server:cast(Proc, {reload, Host, NewOpts, OldOpts}).
+
depends(_Host, _Opts) ->
[].
@@ -107,16 +111,7 @@ init([Host, Opts]) ->
{keypos, #irc_connection.jid_server_host}]),
IQDisc = gen_mod:get_opt(iqdisc, Opts, fun gen_iq_handler:check_type/1,
one_queue),
- gen_iq_handler:add_iq_handler(ejabberd_local, MyHost, ?NS_DISCO_INFO,
- ?MODULE, process_disco_info, IQDisc),
- gen_iq_handler:add_iq_handler(ejabberd_local, MyHost, ?NS_DISCO_ITEMS,
- ?MODULE, process_disco_items, IQDisc),
- gen_iq_handler:add_iq_handler(ejabberd_local, MyHost, ?NS_REGISTER,
- ?MODULE, process_register, IQDisc),
- gen_iq_handler:add_iq_handler(ejabberd_local, MyHost, ?NS_VCARD,
- ?MODULE, process_vcard, IQDisc),
- gen_iq_handler:add_iq_handler(ejabberd_local, MyHost, ?NS_COMMANDS,
- ?MODULE, process_command, IQDisc),
+ register_hooks(MyHost, IQDisc),
ejabberd_router:register_route(MyHost, Host),
{ok,
#state{host = MyHost, server_host = Host,
@@ -140,7 +135,44 @@ handle_call(stop, _From, State) ->
%% {stop, Reason, State}
%% Description: Handling cast messages
%%--------------------------------------------------------------------
-handle_cast(_Msg, State) -> {noreply, State}.
+handle_cast({reload, ServerHost, NewOpts, OldOpts}, State) ->
+ NewHost = gen_mod:get_opt_host(ServerHost, NewOpts, <<"irc.@HOST@">>),
+ OldHost = gen_mod:get_opt_host(ServerHost, OldOpts, <<"irc.@HOST@">>),
+ NewIQDisc = gen_mod:get_opt(iqdisc, NewOpts,
+ fun gen_iq_handler:check_type/1,
+ one_queue),
+ OldIQDisc = gen_mod:get_opt(iqdisc, OldOpts,
+ fun gen_iq_handler:check_type/1,
+ one_queue),
+ NewMod = gen_mod:db_mod(ServerHost, NewOpts, ?MODULE),
+ OldMod = gen_mod:db_mod(ServerHost, OldOpts, ?MODULE),
+ Access = gen_mod:get_opt(access, NewOpts,
+ fun acl:access_rules_validator/1,
+ all),
+ if NewMod /= OldMod ->
+ NewMod:init(ServerHost, NewOpts);
+ true ->
+ ok
+ end,
+ if (NewIQDisc /= OldIQDisc) or (NewHost /= OldHost) ->
+ register_hooks(NewHost, NewIQDisc);
+ true ->
+ ok
+ end,
+ if NewHost /= OldHost ->
+ ejabberd_router:register_route(NewHost, ServerHost),
+ ejabberd_router:unregister_route(OldHost),
+ unregister_hooks(OldHost);
+ true ->
+ ok
+ end,
+ Access = gen_mod:get_opt(access, NewOpts,
+ fun acl:access_rules_validator/1,
+ all),
+ {noreply, State#state{host = NewHost, access = Access}};
+handle_cast(Msg, State) ->
+ ?WARNING_MSG("unexpected cast: ~p", [Msg]),
+ {noreply, State}.
%%--------------------------------------------------------------------
%% Function: handle_info(Info, State) -> {noreply, State} |
@@ -168,11 +200,7 @@ handle_info(_Info, State) -> {noreply, State}.
%%--------------------------------------------------------------------
terminate(_Reason, #state{host = MyHost}) ->
ejabberd_router:unregister_route(MyHost),
- gen_iq_handler:remove_iq_handler(ejabberd_local, MyHost, ?NS_DISCO_INFO),
- gen_iq_handler:remove_iq_handler(ejabberd_local, MyHost, ?NS_DISCO_ITEMS),
- gen_iq_handler:remove_iq_handler(ejabberd_local, MyHost, ?NS_REGISTER),
- gen_iq_handler:remove_iq_handler(ejabberd_local, MyHost, ?NS_VCARD),
- gen_iq_handler:remove_iq_handler(ejabberd_local, MyHost, ?NS_COMMANDS).
+ unregister_hooks(MyHost).
%%--------------------------------------------------------------------
%% Func: code_change(OldVsn, State, Extra) -> {ok, NewState}
@@ -183,6 +211,25 @@ code_change(_OldVsn, State, _Extra) -> {ok, State}.
%%--------------------------------------------------------------------
%%% Internal functions
%%--------------------------------------------------------------------
+register_hooks(Host, IQDisc) ->
+ gen_iq_handler:add_iq_handler(ejabberd_local, Host, ?NS_DISCO_INFO,
+ ?MODULE, process_disco_info, IQDisc),
+ gen_iq_handler:add_iq_handler(ejabberd_local, Host, ?NS_DISCO_ITEMS,
+ ?MODULE, process_disco_items, IQDisc),
+ gen_iq_handler:add_iq_handler(ejabberd_local, Host, ?NS_REGISTER,
+ ?MODULE, process_register, IQDisc),
+ gen_iq_handler:add_iq_handler(ejabberd_local, Host, ?NS_VCARD,
+ ?MODULE, process_vcard, IQDisc),
+ gen_iq_handler:add_iq_handler(ejabberd_local, Host, ?NS_COMMANDS,
+ ?MODULE, process_command, IQDisc).
+
+unregister_hooks(Host) ->
+ gen_iq_handler:remove_iq_handler(ejabberd_local, Host, ?NS_DISCO_INFO),
+ gen_iq_handler:remove_iq_handler(ejabberd_local, Host, ?NS_DISCO_ITEMS),
+ gen_iq_handler:remove_iq_handler(ejabberd_local, Host, ?NS_REGISTER),
+ gen_iq_handler:remove_iq_handler(ejabberd_local, Host, ?NS_VCARD),
+ gen_iq_handler:remove_iq_handler(ejabberd_local, Host, ?NS_COMMANDS).
+
start_supervisor(Host) ->
Proc = gen_mod:get_module_proc(Host,
ejabberd_mod_irc_sup),
diff --git a/src/mod_last.erl b/src/mod_last.erl
index f60005163..e20c1524d 100644
--- a/src/mod_last.erl
+++ b/src/mod_last.erl
@@ -33,7 +33,7 @@
-behaviour(gen_mod).
--export([start/2, stop/1, process_local_iq/1, export/1,
+-export([start/2, stop/1, reload/3, process_local_iq/1, export/1,
process_sm_iq/1, on_presence_update/4, import_info/0,
import/5, import_start/2, store_last_info/4, get_last_info/2,
remove_user/2, transform_options/1, mod_opt_type/1,
@@ -86,6 +86,26 @@ stop(Host) ->
gen_iq_handler:remove_iq_handler(ejabberd_sm, Host,
?NS_LAST).
+reload(Host, NewOpts, OldOpts) ->
+ NewMod = gen_mod:db_mod(Host, NewOpts, ?MODULE),
+ OldMod = gen_mod:db_mod(Host, OldOpts, ?MODULE),
+ if NewMod /= OldMod ->
+ NewMod:init(Host, NewOpts);
+ true ->
+ ok
+ end,
+ case gen_mod:is_equal_opt(iqdisc, NewOpts, OldOpts,
+ fun gen_iq_handler:check_type/1,
+ one_queue) of
+ {false, IQDisc, _} ->
+ gen_iq_handler:add_iq_handler(ejabberd_local, Host, ?NS_LAST,
+ ?MODULE, process_local_iq, IQDisc),
+ gen_iq_handler:add_iq_handler(ejabberd_sm, Host, ?NS_LAST,
+ ?MODULE, process_sm_iq, IQDisc);
+ true ->
+ ok
+ end.
+
%%%
%%% Uptime of ejabberd node
%%%
diff --git a/src/mod_legacy_auth.erl b/src/mod_legacy_auth.erl
index 723c47f85..49e210ec6 100644
--- a/src/mod_legacy_auth.erl
+++ b/src/mod_legacy_auth.erl
@@ -25,7 +25,7 @@
-protocol({xep, 78, '2.5'}).
%% gen_mod API
--export([start/2, stop/1, depends/2, mod_opt_type/1]).
+-export([start/2, stop/1, reload/3, depends/2, mod_opt_type/1]).
%% hooks
-export([c2s_unauthenticated_packet/2, c2s_stream_features/2]).
@@ -48,6 +48,9 @@ stop(Host) ->
ejabberd_hooks:delete(c2s_pre_auth_features, Host, ?MODULE,
c2s_stream_features, 50).
+reload(_Host, _NewOpts, _OldOpts) ->
+ ok.
+
depends(_Host, _Opts) ->
[].
diff --git a/src/mod_mam.erl b/src/mod_mam.erl
index 553c90f94..a10c3a382 100644
--- a/src/mod_mam.erl
+++ b/src/mod_mam.erl
@@ -30,7 +30,7 @@
-behaviour(gen_mod).
%% API
--export([start/2, stop/1, depends/2]).
+-export([start/2, stop/1, reload/3, depends/2]).
-export([user_send_packet/1, user_send_packet_strip_tag/1, user_receive_packet/1,
process_iq_v0_2/1, process_iq_v0_3/1, disco_sm_features/5,
@@ -74,18 +74,7 @@ start(Host, Opts) ->
Mod = gen_mod:db_mod(Host, Opts, ?MODULE),
Mod:init(Host, Opts),
init_cache(Opts),
- gen_iq_handler:add_iq_handler(ejabberd_local, Host,
- ?NS_MAM_TMP, ?MODULE, process_iq_v0_2, IQDisc),
- gen_iq_handler:add_iq_handler(ejabberd_sm, Host,
- ?NS_MAM_TMP, ?MODULE, process_iq_v0_2, IQDisc),
- gen_iq_handler:add_iq_handler(ejabberd_local, Host,
- ?NS_MAM_0, ?MODULE, process_iq_v0_3, IQDisc),
- gen_iq_handler:add_iq_handler(ejabberd_sm, Host,
- ?NS_MAM_0, ?MODULE, process_iq_v0_3, IQDisc),
- gen_iq_handler:add_iq_handler(ejabberd_local, Host,
- ?NS_MAM_1, ?MODULE, process_iq_v0_3, IQDisc),
- gen_iq_handler:add_iq_handler(ejabberd_sm, Host,
- ?NS_MAM_1, ?MODULE, process_iq_v0_3, IQDisc),
+ register_iq_handlers(Host, IQDisc),
ejabberd_hooks:add(user_receive_packet, Host, ?MODULE,
user_receive_packet, 88),
ejabberd_hooks:add(user_send_packet, Host, ?MODULE,
@@ -130,24 +119,19 @@ init_cache(Opts) ->
{life_time, LifeTime}]).
stop(Host) ->
+ unregister_iq_handlers(Host),
ejabberd_hooks:delete(user_send_packet, Host, ?MODULE,
user_send_packet, 88),
ejabberd_hooks:delete(user_receive_packet, Host, ?MODULE,
user_receive_packet, 88),
ejabberd_hooks:delete(user_send_packet, Host, ?MODULE,
- user_send_packet_strip_tag, 500),
+ user_send_packet_strip_tag, 500),
ejabberd_hooks:delete(offline_message_hook, Host, ?MODULE,
offline_message, 50),
ejabberd_hooks:delete(muc_filter_message, Host, ?MODULE,
muc_filter_message, 50),
ejabberd_hooks:delete(muc_process_iq, Host, ?MODULE,
muc_process_iq, 50),
- gen_iq_handler:remove_iq_handler(ejabberd_local, Host, ?NS_MAM_TMP),
- gen_iq_handler:remove_iq_handler(ejabberd_sm, Host, ?NS_MAM_TMP),
- gen_iq_handler:remove_iq_handler(ejabberd_local, Host, ?NS_MAM_0),
- gen_iq_handler:remove_iq_handler(ejabberd_sm, Host, ?NS_MAM_0),
- gen_iq_handler:remove_iq_handler(ejabberd_local, Host, ?NS_MAM_1),
- gen_iq_handler:remove_iq_handler(ejabberd_sm, Host, ?NS_MAM_1),
ejabberd_hooks:delete(disco_sm_features, Host, ?MODULE,
disco_sm_features, 50),
ejabberd_hooks:delete(remove_user, Host, ?MODULE,
@@ -169,9 +153,77 @@ stop(Host) ->
ejabberd_commands:unregister_commands(get_commands_spec()),
ok.
+reload(Host, NewOpts, OldOpts) ->
+ NewMod = gen_mod:db_mod(Host, NewOpts, ?MODULE),
+ OldMod = gen_mod:db_mod(Host, OldOpts, ?MODULE),
+ if NewMod /= OldMod ->
+ NewMod:init(Host, NewOpts);
+ true ->
+ ok
+ end,
+ case gen_mod:is_equal_opt(cache_size, NewOpts, OldOpts,
+ fun(I) when is_integer(I), I>0 -> I end,
+ 1000) of
+ {false, MaxSize, _} ->
+ cache_tab:setopts(archive_prefs, [{max_size, MaxSize}]);
+ true ->
+ ok
+ end,
+ case gen_mod:is_equal_opt(cache_life_time, NewOpts, OldOpts,
+ fun(I) when is_integer(I), I>0 -> I end,
+ timer:hours(1) div 1000) of
+ {false, LifeTime, _} ->
+ cache_tab:setopts(archive_prefs, [{life_time, LifeTime}]);
+ true ->
+ ok
+ end,
+ case gen_mod:is_equal_opt(iqdisc, NewOpts, OldOpts,
+ fun gen_iq_handler:check_type/1,
+ one_queue) of
+ {false, IQDisc, _} ->
+ register_iq_handlers(Host, IQDisc);
+ true ->
+ ok
+ end,
+ case gen_mod:is_equal_opt(assume_mam_usage, NewOpts, OldOpts,
+ fun(B) when is_boolean(B) -> B end, false) of
+ {false, true, _} ->
+ ejabberd_hooks:add(message_is_archived, Host, ?MODULE,
+ message_is_archived, 50);
+ {false, false, _} ->
+ ejabberd_hooks:delete(message_is_archived, Host, ?MODULE,
+ message_is_archived, 50);
+ true ->
+ ok
+ end.
+
depends(_Host, _Opts) ->
[].
+-spec register_iq_handlers(binary(), gen_iq_handler:type()) -> ok.
+register_iq_handlers(Host, IQDisc) ->
+ gen_iq_handler:add_iq_handler(ejabberd_local, Host, ?NS_MAM_TMP,
+ ?MODULE, process_iq_v0_2, IQDisc),
+ gen_iq_handler:add_iq_handler(ejabberd_sm, Host, ?NS_MAM_TMP,
+ ?MODULE, process_iq_v0_2, IQDisc),
+ gen_iq_handler:add_iq_handler(ejabberd_local, Host, ?NS_MAM_0,
+ ?MODULE, process_iq_v0_3, IQDisc),
+ gen_iq_handler:add_iq_handler(ejabberd_sm, Host, ?NS_MAM_0, ?MODULE,
+ process_iq_v0_3, IQDisc),
+ gen_iq_handler:add_iq_handler(ejabberd_local, Host, ?NS_MAM_1,
+ ?MODULE, process_iq_v0_3, IQDisc),
+ gen_iq_handler:add_iq_handler(ejabberd_sm, Host, ?NS_MAM_1,
+ ?MODULE, process_iq_v0_3, IQDisc).
+
+-spec unregister_iq_handlers(binary()) -> ok.
+unregister_iq_handlers(Host) ->
+ gen_iq_handler:remove_iq_handler(ejabberd_local, Host, ?NS_MAM_TMP),
+ gen_iq_handler:remove_iq_handler(ejabberd_sm, Host, ?NS_MAM_TMP),
+ gen_iq_handler:remove_iq_handler(ejabberd_local, Host, ?NS_MAM_0),
+ gen_iq_handler:remove_iq_handler(ejabberd_sm, Host, ?NS_MAM_0),
+ gen_iq_handler:remove_iq_handler(ejabberd_local, Host, ?NS_MAM_1),
+ gen_iq_handler:remove_iq_handler(ejabberd_sm, Host, ?NS_MAM_1).
+
-spec remove_user(binary(), binary()) -> ok.
remove_user(User, Server) ->
LUser = jid:nodeprep(User),
diff --git a/src/mod_metrics.erl b/src/mod_metrics.erl
index 849f8ee0c..d9fc586f9 100644
--- a/src/mod_metrics.erl
+++ b/src/mod_metrics.erl
@@ -34,7 +34,7 @@
-include("xmpp.hrl").
-export([start/2, stop/1, send_metrics/4, opt_type/1, mod_opt_type/1,
- depends/2]).
+ depends/2, reload/3]).
-export([offline_message_hook/2,
sm_register_connection_hook/3, sm_remove_connection_hook/3,
@@ -68,6 +68,9 @@ stop(Host) ->
ejabberd_hooks:delete(remove_user, Host, ?MODULE, remove_user, 20),
ejabberd_hooks:delete(register_user, Host, ?MODULE, register_user, 20).
+reload(_Host, _NewOpts, _OldOpts) ->
+ ok.
+
depends(_Host, _Opts) ->
[].
diff --git a/src/mod_muc.erl b/src/mod_muc.erl
index a15dd3789..563f4c68a 100644
--- a/src/mod_muc.erl
+++ b/src/mod_muc.erl
@@ -36,6 +36,7 @@
%% API
-export([start/2,
stop/1,
+ reload/3,
room_destroyed/4,
store_room/4,
restore_room/3,
@@ -114,6 +115,10 @@ stop(Host) ->
gen_mod:stop_child(?MODULE, Host),
{wait, Rooms}.
+reload(Host, NewOpts, OldOpts) ->
+ Proc = gen_mod:get_module_proc(Host, ?MODULE),
+ gen_server:cast(Proc, {reload, Host, NewOpts, OldOpts}).
+
depends(_Host, _Opts) ->
[{mod_mam, soft}].
@@ -220,12 +225,115 @@ init([Host, Opts]) ->
process_flag(trap_exit, true),
IQDisc = gen_mod:get_opt(iqdisc, Opts, fun gen_iq_handler:check_type/1,
one_queue),
- MyHost = gen_mod:get_opt_host(Host, Opts,
- <<"conference.@HOST@">>),
+ #state{access = Access, host = MyHost,
+ history_size = HistorySize,
+ room_shaper = RoomShaper} = State = init_state(Host, Opts),
Mod = gen_mod:db_mod(Host, Opts, ?MODULE),
RMod = gen_mod:ram_db_mod(Host, Opts, ?MODULE),
Mod:init(Host, [{host, MyHost}|Opts]),
RMod:init(Host, [{host, MyHost}|Opts]),
+ register_iq_handlers(MyHost, IQDisc),
+ ejabberd_router:register_route(MyHost, Host),
+ load_permanent_rooms(MyHost, Host, Access, HistorySize, RoomShaper),
+ {ok, State}.
+
+handle_call(stop, _From, State) ->
+ {stop, normal, ok, State};
+handle_call({create, Room, From, Nick, Opts}, _From,
+ #state{host = Host, server_host = ServerHost,
+ access = Access, default_room_opts = DefOpts,
+ history_size = HistorySize,
+ room_shaper = RoomShaper} = State) ->
+ ?DEBUG("MUC: create new room '~s'~n", [Room]),
+ NewOpts = case Opts of
+ default -> DefOpts;
+ _ -> Opts
+ end,
+ {ok, Pid} = mod_muc_room:start(
+ Host, ServerHost, Access,
+ Room, HistorySize,
+ RoomShaper, From,
+ Nick, NewOpts),
+ RMod = gen_mod:ram_db_mod(ServerHost, ?MODULE),
+ RMod:register_online_room(Room, Host, Pid),
+ {reply, ok, State}.
+
+handle_cast({reload, ServerHost, NewOpts, OldOpts}, #state{host = OldHost}) ->
+ NewIQDisc = gen_mod:get_opt(iqdisc, NewOpts,
+ fun gen_iq_handler:check_type/1,
+ one_queue),
+ OldIQDisc = gen_mod:get_opt(iqdisc, OldOpts,
+ fun gen_iq_handler:check_type/1,
+ one_queue),
+ NewMod = gen_mod:db_mod(ServerHost, NewOpts, ?MODULE),
+ NewRMod = gen_mod:ram_db_mod(ServerHost, NewOpts, ?MODULE),
+ OldMod = gen_mod:db_mod(ServerHost, OldOpts, ?MODULE),
+ OldRMod = gen_mod:ram_db_mod(ServerHost, OldOpts, ?MODULE),
+ #state{host = NewHost} = NewState = init_state(ServerHost, NewOpts),
+ if NewMod /= OldMod ->
+ NewMod:init(ServerHost, [{host, NewHost}|NewOpts]);
+ true ->
+ ok
+ end,
+ if NewRMod /= OldRMod ->
+ NewRMod:init(ServerHost, [{host, NewHost}|NewOpts]);
+ true ->
+ ok
+ end,
+ if (NewIQDisc /= OldIQDisc) or (NewHost /= OldHost) ->
+ register_iq_handlers(NewHost, NewIQDisc);
+ true ->
+ ok
+ end,
+ if NewHost /= OldHost ->
+ ejabberd_router:register_route(NewHost, ServerHost),
+ ejabberd_router:unregister_route(OldHost),
+ unregister_iq_handlers(OldHost);
+ true ->
+ ok
+ end,
+ {noreply, NewState};
+handle_cast(Msg, State) ->
+ ?WARNING_MSG("unexpected cast: ~p", [Msg]),
+ {noreply, State}.
+
+handle_info({route, Packet},
+ #state{host = Host, server_host = ServerHost,
+ access = Access, default_room_opts = DefRoomOpts,
+ history_size = HistorySize,
+ max_rooms_discoitems = MaxRoomsDiscoItems,
+ room_shaper = RoomShaper} = State) ->
+ From = xmpp:get_from(Packet),
+ To = xmpp:get_to(Packet),
+ case catch do_route(Host, ServerHost, Access, HistorySize, RoomShaper,
+ From, To, Packet, DefRoomOpts, MaxRoomsDiscoItems) of
+ {'EXIT', Reason} ->
+ ?ERROR_MSG("~p", [Reason]);
+ _ ->
+ ok
+ end,
+ {noreply, State};
+handle_info({room_destroyed, {Room, Host}, Pid}, State) ->
+ ServerHost = State#state.server_host,
+ RMod = gen_mod:ram_db_mod(ServerHost, ?MODULE),
+ RMod:unregister_online_room(Room, Host, Pid),
+ {noreply, State};
+handle_info(Info, State) ->
+ ?ERROR_MSG("unexpected info: ~p", [Info]),
+ {noreply, State}.
+
+terminate(_Reason, #state{host = MyHost}) ->
+ ejabberd_router:unregister_route(MyHost),
+ unregister_iq_handlers(MyHost).
+
+code_change(_OldVsn, State, _Extra) -> {ok, State}.
+
+%%--------------------------------------------------------------------
+%%% Internal functions
+%%--------------------------------------------------------------------
+init_state(Host, Opts) ->
+ MyHost = gen_mod:get_opt_host(Host, Opts,
+ <<"conference.@HOST@">>),
Access = gen_mod:get_opt(access, Opts,
fun acl:access_rules_validator/1, all),
AccessCreate = gen_mod:get_opt(access_create, Opts,
@@ -298,93 +406,35 @@ init([Host, Opts]) ->
RoomShaper = gen_mod:get_opt(room_shaper, Opts,
fun(A) when is_atom(A) -> A end,
none),
- gen_iq_handler:add_iq_handler(ejabberd_local, MyHost, ?NS_REGISTER,
+ #state{host = MyHost,
+ server_host = Host,
+ access = {Access, AccessCreate, AccessAdmin, AccessPersistent},
+ default_room_opts = DefRoomOpts,
+ history_size = HistorySize,
+ max_rooms_discoitems = MaxRoomsDiscoItems,
+ room_shaper = RoomShaper}.
+
+register_iq_handlers(Host, IQDisc) ->
+ gen_iq_handler:add_iq_handler(ejabberd_local, Host, ?NS_REGISTER,
?MODULE, process_register, IQDisc),
- gen_iq_handler:add_iq_handler(ejabberd_local, MyHost, ?NS_VCARD,
+ gen_iq_handler:add_iq_handler(ejabberd_local, Host, ?NS_VCARD,
?MODULE, process_vcard, IQDisc),
- gen_iq_handler:add_iq_handler(ejabberd_local, MyHost, ?NS_MUCSUB,
+ gen_iq_handler:add_iq_handler(ejabberd_local, Host, ?NS_MUCSUB,
?MODULE, process_mucsub, IQDisc),
- gen_iq_handler:add_iq_handler(ejabberd_local, MyHost, ?NS_MUC_UNIQUE,
+ gen_iq_handler:add_iq_handler(ejabberd_local, Host, ?NS_MUC_UNIQUE,
?MODULE, process_muc_unique, IQDisc),
- gen_iq_handler:add_iq_handler(ejabberd_local, MyHost, ?NS_DISCO_INFO,
+ gen_iq_handler:add_iq_handler(ejabberd_local, Host, ?NS_DISCO_INFO,
?MODULE, process_disco_info, IQDisc),
- gen_iq_handler:add_iq_handler(ejabberd_local, MyHost, ?NS_DISCO_ITEMS,
- ?MODULE, process_disco_items, IQDisc),
- ejabberd_router:register_route(MyHost, Host),
- load_permanent_rooms(MyHost, Host,
- {Access, AccessCreate, AccessAdmin, AccessPersistent},
- HistorySize, RoomShaper),
- {ok, #state{host = MyHost,
- server_host = Host,
- access = {Access, AccessCreate, AccessAdmin, AccessPersistent},
- default_room_opts = DefRoomOpts,
- history_size = HistorySize,
- max_rooms_discoitems = MaxRoomsDiscoItems,
- room_shaper = RoomShaper}}.
-
-handle_call(stop, _From, State) ->
- {stop, normal, ok, State};
-handle_call({create, Room, From, Nick, Opts}, _From,
- #state{host = Host, server_host = ServerHost,
- access = Access, default_room_opts = DefOpts,
- history_size = HistorySize,
- room_shaper = RoomShaper} = State) ->
- ?DEBUG("MUC: create new room '~s'~n", [Room]),
- NewOpts = case Opts of
- default -> DefOpts;
- _ -> Opts
- end,
- {ok, Pid} = mod_muc_room:start(
- Host, ServerHost, Access,
- Room, HistorySize,
- RoomShaper, From,
- Nick, NewOpts),
- RMod = gen_mod:ram_db_mod(ServerHost, ?MODULE),
- RMod:register_online_room(Room, Host, Pid),
- {reply, ok, State}.
-
-handle_cast(_Msg, State) -> {noreply, State}.
-
-handle_info({route, Packet},
- #state{host = Host, server_host = ServerHost,
- access = Access, default_room_opts = DefRoomOpts,
- history_size = HistorySize,
- max_rooms_discoitems = MaxRoomsDiscoItems,
- room_shaper = RoomShaper} = State) ->
- From = xmpp:get_from(Packet),
- To = xmpp:get_to(Packet),
- case catch do_route(Host, ServerHost, Access, HistorySize, RoomShaper,
- From, To, Packet, DefRoomOpts, MaxRoomsDiscoItems) of
- {'EXIT', Reason} ->
- ?ERROR_MSG("~p", [Reason]);
- _ ->
- ok
- end,
- {noreply, State};
-handle_info({room_destroyed, {Room, Host}, Pid}, State) ->
- ServerHost = State#state.server_host,
- RMod = gen_mod:ram_db_mod(ServerHost, ?MODULE),
- RMod:unregister_online_room(Room, Host, Pid),
- {noreply, State};
-handle_info(Info, State) ->
- ?ERROR_MSG("unexpected info: ~p", [Info]),
- {noreply, State}.
-
-terminate(_Reason, #state{host = MyHost}) ->
- ejabberd_router:unregister_route(MyHost),
- gen_iq_handler:remove_iq_handler(ejabberd_local, MyHost, ?NS_REGISTER),
- gen_iq_handler:remove_iq_handler(ejabberd_local, MyHost, ?NS_VCARD),
- gen_iq_handler:remove_iq_handler(ejabberd_local, MyHost, ?NS_MUCSUB),
- gen_iq_handler:remove_iq_handler(ejabberd_local, MyHost, ?NS_MUC_UNIQUE),
- gen_iq_handler:remove_iq_handler(ejabberd_local, MyHost, ?NS_DISCO_INFO),
- gen_iq_handler:remove_iq_handler(ejabberd_local, MyHost, ?NS_DISCO_ITEMS),
- ok.
-
-code_change(_OldVsn, State, _Extra) -> {ok, State}.
-
-%%--------------------------------------------------------------------
-%%% Internal functions
-%%--------------------------------------------------------------------
+ gen_iq_handler:add_iq_handler(ejabberd_local, Host, ?NS_DISCO_ITEMS,
+ ?MODULE, process_disco_items, IQDisc).
+
+unregister_iq_handlers(Host) ->
+ gen_iq_handler:remove_iq_handler(ejabberd_local, Host, ?NS_REGISTER),
+ gen_iq_handler:remove_iq_handler(ejabberd_local, Host, ?NS_VCARD),
+ gen_iq_handler:remove_iq_handler(ejabberd_local, Host, ?NS_MUCSUB),
+ gen_iq_handler:remove_iq_handler(ejabberd_local, Host, ?NS_MUC_UNIQUE),
+ gen_iq_handler:remove_iq_handler(ejabberd_local, Host, ?NS_DISCO_INFO),
+ gen_iq_handler:remove_iq_handler(ejabberd_local, Host, ?NS_DISCO_ITEMS).
do_route(Host, ServerHost, Access, HistorySize, RoomShaper,
From, To, Packet, DefRoomOpts, _MaxRoomsDiscoItems) ->
diff --git a/src/mod_muc_admin.erl b/src/mod_muc_admin.erl
index 2a6a0bb81..21a1d90c6 100644
--- a/src/mod_muc_admin.erl
+++ b/src/mod_muc_admin.erl
@@ -28,7 +28,7 @@
-behaviour(gen_mod).
--export([start/2, stop/1, depends/2, muc_online_rooms/1,
+-export([start/2, stop/1, reload/3, depends/2, muc_online_rooms/1,
muc_unregister_nick/1, create_room/3, destroy_room/2,
create_room_with_opts/4,
create_rooms_file/1, destroy_rooms_file/1,
@@ -67,6 +67,9 @@ stop(Host) ->
ejabberd_hooks:delete(webadmin_page_main, ?MODULE, web_page_main, 50),
ejabberd_hooks:delete(webadmin_page_host, Host, ?MODULE, web_page_host, 50).
+reload(_Host, _NewOpts, _OldOpts) ->
+ ok.
+
depends(_Host, _Opts) ->
[{mod_muc, hard}].
diff --git a/src/mod_muc_log.erl b/src/mod_muc_log.erl
index 916deef24..13f0efdfe 100644
--- a/src/mod_muc_log.erl
+++ b/src/mod_muc_log.erl
@@ -36,7 +36,7 @@
-behaviour(gen_mod).
%% API
--export([start/2, stop/1, transform_module_options/1,
+-export([start/2, stop/1, reload/3, transform_module_options/1,
check_access_log/2, add_to_log/5]).
-export([init/1, handle_call/3, handle_cast/2,
@@ -78,6 +78,10 @@ start(Host, Opts) ->
stop(Host) ->
gen_mod:stop_child(?MODULE, Host).
+reload(Host, NewOpts, _OldOpts) ->
+ Proc = get_proc_name(Host),
+ gen_server:cast(Proc, {reload, NewOpts}).
+
add_to_log(Host, Type, Data, Room, Opts) ->
gen_server:cast(get_proc_name(Host),
{add_to_log, Type, Data, Room, Opts}).
@@ -106,6 +110,36 @@ depends(_Host, _Opts) ->
%%====================================================================
init([Host, Opts]) ->
process_flag(trap_exit, true),
+ {ok, init_state(Host, Opts)}.
+
+handle_call({check_access_log, ServerHost, FromJID}, _From, State) ->
+ Reply = acl:match_rule(ServerHost, State#logstate.access, FromJID),
+ {reply, Reply, State};
+handle_call(stop, _From, State) ->
+ {stop, normal, ok, State}.
+
+handle_cast({reload, Opts}, #logstate{host = Host}) ->
+ {noreply, init_state(Host, Opts)};
+handle_cast({add_to_log, Type, Data, Room, Opts}, State) ->
+ case catch add_to_log2(Type, Data, Room, Opts, State) of
+ {'EXIT', Reason} -> ?ERROR_MSG("~p", [Reason]);
+ _ -> ok
+ end,
+ {noreply, State};
+handle_cast(Msg, State) ->
+ ?WARNING_MSG("unexpected cast: ~p", [Msg]),
+ {noreply, State}.
+
+handle_info(_Info, State) -> {noreply, State}.
+
+terminate(_Reason, _State) -> ok.
+
+code_change(_OldVsn, State, _Extra) -> {ok, State}.
+
+%%--------------------------------------------------------------------
+%%% Internal functions
+%%--------------------------------------------------------------------
+init_state(Host, Opts) ->
OutDir = gen_mod:get_opt(outdir, Opts,
fun iolist_to_binary/1,
<<"www/muc">>),
@@ -152,37 +186,13 @@ init([Host, Opts]) ->
{language, Host},
fun iolist_to_binary/1,
?MYLANG),
- {ok,
- #logstate{host = Host, out_dir = OutDir,
- dir_type = DirType, dir_name = DirName,
- file_format = FileFormat, css_file = CSSFile,
- file_permissions = FilePermissions,
- access = AccessLog, lang = Lang, timezone = Timezone,
- spam_prevention = NoFollow, top_link = Top_link}}.
-
-handle_call({check_access_log, ServerHost, FromJID}, _From, State) ->
- Reply = acl:match_rule(ServerHost, State#logstate.access, FromJID),
- {reply, Reply, State};
-handle_call(stop, _From, State) ->
- {stop, normal, ok, State}.
-
-handle_cast({add_to_log, Type, Data, Room, Opts}, State) ->
- case catch add_to_log2(Type, Data, Room, Opts, State) of
- {'EXIT', Reason} -> ?ERROR_MSG("~p", [Reason]);
- _ -> ok
- end,
- {noreply, State};
-handle_cast(_Msg, State) -> {noreply, State}.
-
-handle_info(_Info, State) -> {noreply, State}.
-
-terminate(_Reason, _State) -> ok.
-
-code_change(_OldVsn, State, _Extra) -> {ok, State}.
+ #logstate{host = Host, out_dir = OutDir,
+ dir_type = DirType, dir_name = DirName,
+ file_format = FileFormat, css_file = CSSFile,
+ file_permissions = FilePermissions,
+ access = AccessLog, lang = Lang, timezone = Timezone,
+ spam_prevention = NoFollow, top_link = Top_link}.
-%%--------------------------------------------------------------------
-%%% Internal functions
-%%--------------------------------------------------------------------
add_to_log2(text, {Nick, Packet}, Room, Opts, State) ->
case has_no_permanent_store_hint(Packet) of
false ->
diff --git a/src/mod_multicast.erl b/src/mod_multicast.erl
index 81fe50c9d..48a2b5962 100644
--- a/src/mod_multicast.erl
+++ b/src/mod_multicast.erl
@@ -34,7 +34,7 @@
-behaviour(gen_mod).
%% API
--export([start/2, stop/1]).
+-export([start/2, stop/1, reload/3]).
%% gen_server callbacks
-export([init/1, handle_info/2, handle_call/3,
@@ -122,6 +122,10 @@ start(LServerS, Opts) ->
stop(LServerS) ->
gen_mod:stop_child(?MODULE, LServerS).
+reload(LServerS, NewOpts, OldOpts) ->
+ Proc = gen_mod:get_module_proc(LServerS, ?MODULE),
+ gen_server:cast(Proc, {reload, NewOpts, OldOpts}).
+
%%====================================================================
%% gen_server callbacks
%%====================================================================
@@ -150,7 +154,29 @@ init([LServerS, Opts]) ->
handle_call(stop, _From, State) ->
try_stop_loop(), {stop, normal, ok, State}.
-handle_cast(_Msg, State) -> {noreply, State}.
+handle_cast({reload, NewOpts, NewOpts},
+ #state{lserver = LServerS, lservice = OldLServiceS} = State) ->
+ Access = gen_mod:get_opt(access, NewOpts,
+ fun acl:access_rules_validator/1, all),
+ SLimits =
+ build_service_limit_record(gen_mod:get_opt(limits, NewOpts,
+ fun (A) when is_list(A) ->
+ A
+ end,
+ [])),
+ NewLServiceS = gen_mod:get_opt_host(LServerS, NewOpts,
+ <<"multicast.@HOST@">>),
+ if NewLServiceS /= OldLServiceS ->
+ ejabberd_router:register_route(NewLServiceS, LServerS),
+ ejabberd_router:unregister_route(OldLServiceS);
+ true ->
+ ok
+ end,
+ {noreply, State#state{lservice = NewLServiceS,
+ access = Access, service_limits = SLimits}};
+handle_cast(Msg, State) ->
+ ?WARNING_MSG("unexpected cast: ~p", [Msg]),
+ {noreply, State}.
%%--------------------------------------------------------------------
%% Function: handle_info(Info, State) -> {noreply, State} |
diff --git a/src/mod_offline.erl b/src/mod_offline.erl
index 846d7c783..552b49cd9 100644
--- a/src/mod_offline.erl
+++ b/src/mod_offline.erl
@@ -38,6 +38,7 @@
-export([start/2,
stop/1,
+ reload/3,
store_packet/2,
store_offline_msg/5,
c2s_self_presence/1,
@@ -113,6 +114,10 @@ start(Host, Opts) ->
stop(Host) ->
gen_mod:stop_child(?MODULE, Host).
+reload(Host, NewOpts, OldOpts) ->
+ Proc = gen_mod:get_module_proc(Host, ?MODULE),
+ gen_server:cast(Proc, {reload, NewOpts, OldOpts}).
+
depends(_Host, _Opts) ->
[].
@@ -162,8 +167,35 @@ init([Host, Opts]) ->
handle_call(stop, _From, State) ->
{stop, normal, ok, State}.
-
-handle_cast(_Msg, State) -> {noreply, State}.
+handle_cast({reload, NewOpts, OldOpts}, #state{host = Host} = State) ->
+ NewMod = gen_mod:db_mod(Host, NewOpts, ?MODULE),
+ OldMod = gen_mod:db_mod(Host, OldOpts, ?MODULE),
+ if NewMod /= OldMod ->
+ NewMod:init(Host, NewOpts);
+ true ->
+ ok
+ end,
+ case gen_mod:is_equal_opt(iqdisc, NewOpts, OldOpts,
+ fun gen_iq_handler:check_type/1,
+ one_queue) of
+ {false, IQDisc, _} ->
+ gen_iq_handler:add_iq_handler(ejabberd_sm, Host, ?NS_FLEX_OFFLINE,
+ ?MODULE, handle_offline_query, IQDisc);
+ true ->
+ ok
+ end,
+ case gen_mod:is_equal_opt(access_max_user_messages, NewOpts, OldOpts,
+ fun acl:shaper_rules_validator/1,
+ max_user_offline_messages) of
+ {false, AccessMaxOfflineMsgs, _} ->
+ {noreply,
+ State#state{access_max_offline_messages = AccessMaxOfflineMsgs}};
+ true ->
+ {noreply, State}
+ end;
+handle_cast(Msg, State) ->
+ ?WARNING_MSG("unexpected cast: ~p", [Msg]),
+ {noreply, State}.
handle_info(#offline_msg{us = UserServer} = Msg, State) ->
diff --git a/src/mod_ping.erl b/src/mod_ping.erl
index aa048e36e..0e2ccb9fa 100644
--- a/src/mod_ping.erl
+++ b/src/mod_ping.erl
@@ -48,7 +48,7 @@
-export([start_ping/2, stop_ping/2]).
%% gen_mod callbacks
--export([start/2, stop/1]).
+-export([start/2, stop/1, reload/3]).
%% gen_server callbacks
-export([init/1, terminate/2, handle_call/3,
@@ -87,64 +87,49 @@ start(Host, Opts) ->
stop(Host) ->
gen_mod:stop_child(?MODULE, Host).
+reload(Host, NewOpts, OldOpts) ->
+ Proc = gen_mod:get_module_proc(Host, ?MODULE),
+ gen_server:cast(Proc, {reload, Host, NewOpts, OldOpts}).
+
%%====================================================================
%% gen_server callbacks
%%====================================================================
init([Host, Opts]) ->
process_flag(trap_exit, true),
- SendPings = gen_mod:get_opt(send_pings, Opts,
- fun(B) when is_boolean(B) -> B end,
- ?DEFAULT_SEND_PINGS),
- PingInterval = gen_mod:get_opt(ping_interval, Opts,
- fun(I) when is_integer(I), I>0 -> I end,
- ?DEFAULT_PING_INTERVAL),
- PingAckTimeout = gen_mod:get_opt(ping_ack_timeout, Opts,
- fun(I) when is_integer(I), I>0 -> I * 1000 end,
- undefined),
- TimeoutAction = gen_mod:get_opt(timeout_action, Opts,
- fun(none) -> none;
- (kill) -> kill
- end, none),
+ State = init_state(Host, Opts),
IQDisc = gen_mod:get_opt(iqdisc, Opts, fun gen_iq_handler:check_type/1,
no_queue),
- gen_iq_handler:add_iq_handler(ejabberd_sm, Host,
- ?NS_PING, ?MODULE, iq_ping, IQDisc),
- gen_iq_handler:add_iq_handler(ejabberd_local, Host,
- ?NS_PING, ?MODULE, iq_ping, IQDisc),
- case SendPings of
- true ->
- ejabberd_hooks:add(sm_register_connection_hook, Host,
- ?MODULE, user_online, 100),
- ejabberd_hooks:add(sm_remove_connection_hook, Host,
- ?MODULE, user_offline, 100),
- ejabberd_hooks:add(user_send_packet, Host, ?MODULE,
- user_send, 100);
- _ -> ok
+ register_iq_handlers(Host, IQDisc),
+ case State#state.send_pings of
+ true -> register_hooks(Host);
+ false -> ok
end,
- {ok,
- #state{host = Host, send_pings = SendPings,
- ping_interval = PingInterval,
- timeout_action = TimeoutAction,
- ping_ack_timeout = PingAckTimeout,
- timers = maps:new()}}.
+ {ok, State}.
terminate(_Reason, #state{host = Host}) ->
- ejabberd_hooks:delete(sm_remove_connection_hook, Host,
- ?MODULE, user_offline, 100),
- ejabberd_hooks:delete(sm_register_connection_hook, Host,
- ?MODULE, user_online, 100),
- ejabberd_hooks:delete(user_send_packet, Host, ?MODULE,
- user_send, 100),
- gen_iq_handler:remove_iq_handler(ejabberd_local, Host,
- ?NS_PING),
- gen_iq_handler:remove_iq_handler(ejabberd_sm, Host,
- ?NS_PING).
+ unregister_hooks(Host),
+ unregister_iq_handlers(Host).
handle_call(stop, _From, State) ->
{stop, normal, ok, State};
handle_call(_Req, _From, State) ->
{reply, {error, badarg}, State}.
+handle_cast({reload, Host, NewOpts, OldOpts},
+ #state{timers = Timers} = OldState) ->
+ case gen_mod:is_equal_opt(iqdisc, NewOpts, OldOpts,
+ fun gen_iq_handler:check_type/1,
+ one_queue) of
+ {false, IQDisc, _} -> register_iq_handlers(Host, IQDisc);
+ true -> ok
+ end,
+ NewState = init_state(Host, NewOpts),
+ case {NewState#state.send_pings, OldState#state.send_pings} of
+ {true, false} -> register_hooks(Host);
+ {false, true} -> unregister_hooks(Host);
+ _ -> ok
+ end,
+ {noreply, NewState#state{timers = Timers}};
handle_cast({start_ping, JID}, State) ->
Timers = add_timer(JID, State#state.ping_interval,
State#state.timers),
@@ -169,7 +154,9 @@ handle_cast({iq_pong, JID, timeout}, State) ->
_ -> ok
end,
{noreply, State#state{timers = Timers}};
-handle_cast(_Msg, State) -> {noreply, State}.
+handle_cast(Msg, State) ->
+ ?WARNING_MSG("unexpected cast: ~p", [Msg]),
+ {noreply, State}.
handle_info({timeout, _TRef, {ping, JID}}, State) ->
From = jid:make(State#state.host),
@@ -212,6 +199,53 @@ user_send({Packet, #{jid := JID} = C2SState}) ->
%%====================================================================
%% Internal functions
%%====================================================================
+init_state(Host, Opts) ->
+ SendPings = gen_mod:get_opt(send_pings, Opts,
+ fun(B) when is_boolean(B) -> B end,
+ ?DEFAULT_SEND_PINGS),
+ PingInterval = gen_mod:get_opt(ping_interval, Opts,
+ fun(I) when is_integer(I), I>0 -> I end,
+ ?DEFAULT_PING_INTERVAL),
+ PingAckTimeout = gen_mod:get_opt(ping_ack_timeout, Opts,
+ fun(I) when is_integer(I), I>0 -> I * 1000 end,
+ undefined),
+ TimeoutAction = gen_mod:get_opt(timeout_action, Opts,
+ fun(none) -> none;
+ (kill) -> kill
+ end, none),
+ #state{host = Host,
+ send_pings = SendPings,
+ ping_interval = PingInterval,
+ timeout_action = TimeoutAction,
+ ping_ack_timeout = PingAckTimeout,
+ timers = maps:new()}.
+
+register_hooks(Host) ->
+ ejabberd_hooks:add(sm_register_connection_hook, Host,
+ ?MODULE, user_online, 100),
+ ejabberd_hooks:add(sm_remove_connection_hook, Host,
+ ?MODULE, user_offline, 100),
+ ejabberd_hooks:add(user_send_packet, Host, ?MODULE,
+ user_send, 100).
+
+unregister_hooks(Host) ->
+ ejabberd_hooks:delete(sm_remove_connection_hook, Host,
+ ?MODULE, user_offline, 100),
+ ejabberd_hooks:delete(sm_register_connection_hook, Host,
+ ?MODULE, user_online, 100),
+ ejabberd_hooks:delete(user_send_packet, Host, ?MODULE,
+ user_send, 100).
+
+register_iq_handlers(Host, IQDisc) ->
+ gen_iq_handler:add_iq_handler(ejabberd_sm, Host, ?NS_PING,
+ ?MODULE, iq_ping, IQDisc),
+ gen_iq_handler:add_iq_handler(ejabberd_local, Host, ?NS_PING,
+ ?MODULE, iq_ping, IQDisc).
+
+unregister_iq_handlers(Host) ->
+ gen_iq_handler:remove_iq_handler(ejabberd_local, Host, ?NS_PING),
+ gen_iq_handler:remove_iq_handler(ejabberd_sm, Host, ?NS_PING).
+
-spec add_timer(jid(), non_neg_integer(), map()) -> map().
add_timer(JID, Interval, Timers) ->
LJID = jid:tolower(JID),
diff --git a/src/mod_pres_counter.erl b/src/mod_pres_counter.erl
index c22562a11..f70e2d9f0 100644
--- a/src/mod_pres_counter.erl
+++ b/src/mod_pres_counter.erl
@@ -27,7 +27,7 @@
-behavior(gen_mod).
--export([start/2, stop/1, check_packet/4,
+-export([start/2, stop/1, reload/3, check_packet/4,
mod_opt_type/1, depends/2]).
-include("ejabberd.hrl").
@@ -48,6 +48,9 @@ stop(Host) ->
?MODULE, check_packet, 25),
ok.
+reload(_Host, _NewOpts, _OldOpts) ->
+ ok.
+
depends(_Host, _Opts) ->
[].
diff --git a/src/mod_privacy.erl b/src/mod_privacy.erl
index 50008053e..5aa816975 100644
--- a/src/mod_privacy.erl
+++ b/src/mod_privacy.erl
@@ -31,7 +31,7 @@
-behaviour(gen_mod).
--export([start/2, stop/1, process_iq/1, export/1, import_info/0,
+-export([start/2, stop/1, reload/3, process_iq/1, export/1, import_info/0,
c2s_session_opened/1, c2s_copy_session/2, push_list_update/3,
user_send_packet/1, user_receive_packet/1, disco_features/5,
check_packet/4, remove_user/2, encode_list_item/1,
@@ -99,6 +99,24 @@ stop(Host) ->
gen_iq_handler:remove_iq_handler(ejabberd_sm, Host,
?NS_PRIVACY).
+reload(Host, NewOpts, OldOpts) ->
+ NewMod = gen_mod:db_mod(Host, NewOpts, ?MODULE),
+ OldMod = gen_mod:db_mod(Host, OldOpts, ?MODULE),
+ if NewMod /= OldMod ->
+ NewMod:init(Host, NewOpts);
+ true ->
+ ok
+ end,
+ case gen_mod:is_equal_opt(iqdisc, NewOpts, OldOpts,
+ fun gen_iq_handler:check_type/1,
+ one_queue) of
+ {false, IQDisc, _} ->
+ gen_iq_handler:add_iq_handler(ejabberd_sm, Host, ?NS_PRIVACY,
+ ?MODULE, process_iq, IQDisc);
+ true ->
+ ok
+ end.
+
-spec disco_features({error, stanza_error()} | {result, [binary()]} | empty,
jid(), jid(), binary(), binary()) ->
{error, stanza_error()} | {result, [binary()]}.
diff --git a/src/mod_private.erl b/src/mod_private.erl
index 87172b744..dc33af7f8 100644
--- a/src/mod_private.erl
+++ b/src/mod_private.erl
@@ -31,7 +31,7 @@
-behaviour(gen_mod).
--export([start/2, stop/1, process_sm_iq/1, import_info/0,
+-export([start/2, stop/1, reload/3, process_sm_iq/1, import_info/0,
remove_user/2, get_data/2, get_data/3, export/1,
import/5, import_start/2, mod_opt_type/1, set_data/3, depends/2]).
@@ -64,6 +64,24 @@ stop(Host) ->
gen_iq_handler:remove_iq_handler(ejabberd_sm, Host,
?NS_PRIVATE).
+reload(Host, NewOpts, OldOpts) ->
+ NewMod = gen_mod:db_mod(Host, NewOpts, ?MODULE),
+ OldMod = gen_mod:db_mod(Host, OldOpts, ?MODULE),
+ if NewMod /= OldMod ->
+ NewMod:init(Host, NewOpts);
+ true ->
+ ok
+ end,
+ case gen_mod:is_equal_opt(iqdisc, NewOpts, OldOpts,
+ fun gen_iq_handler:check_type/1,
+ one_queue) of
+ {false, IQDisc, _} ->
+ gen_iq_handler:add_iq_handler(ejabberd_sm, Host, ?NS_PRIVATE,
+ ?MODULE, process_sm_iq, IQDisc);
+ true ->
+ ok
+ end.
+
-spec process_sm_iq(iq()) -> iq().
process_sm_iq(#iq{type = Type, lang = Lang,
from = #jid{luser = LUser, lserver = LServer},
diff --git a/src/mod_privilege.erl b/src/mod_privilege.erl
index c320afd57..1547d53ad 100644
--- a/src/mod_privilege.erl
+++ b/src/mod_privilege.erl
@@ -31,7 +31,7 @@
-behaviour(gen_mod).
%% API
--export([start/2, stop/1, mod_opt_type/1, depends/2]).
+-export([start/2, stop/1, reload/3, mod_opt_type/1, depends/2]).
%% gen_server callbacks
-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
terminate/2, code_change/3]).
@@ -55,6 +55,9 @@ start(Host, Opts) ->
stop(Host) ->
gen_mod:stop_child(?MODULE, Host).
+reload(_Host, _NewOpts, _OldOpts) ->
+ ok.
+
mod_opt_type(roster) -> v_roster();
mod_opt_type(message) -> v_message();
mod_opt_type(presence) -> v_presence();
diff --git a/src/mod_proxy65.erl b/src/mod_proxy65.erl
index 4bb754d84..e8183b21f 100644
--- a/src/mod_proxy65.erl
+++ b/src/mod_proxy65.erl
@@ -34,7 +34,7 @@
-behaviour(supervisor).
%% gen_mod callbacks.
--export([start/2, stop/1, transform_module_options/1]).
+-export([start/2, stop/1, reload/3, transform_module_options/1]).
%% supervisor callbacks.
-export([init/1]).
@@ -68,6 +68,11 @@ stop(Host) ->
supervisor:terminate_child(ejabberd_sup, Proc),
supervisor:delete_child(ejabberd_sup, Proc).
+reload(Host, NewOpts, OldOpts) ->
+ Mod = gen_mod:ram_db_mod(global, ?MODULE),
+ Mod:init(),
+ mod_proxy65_service:reload(Host, NewOpts, OldOpts).
+
start_link(Host, Opts) ->
Proc = gen_mod:get_module_proc(Host, ?PROCNAME),
supervisor:start_link({local, Proc}, ?MODULE,
diff --git a/src/mod_proxy65_service.erl b/src/mod_proxy65_service.erl
index bdcd677fb..b9a96ca71 100644
--- a/src/mod_proxy65_service.erl
+++ b/src/mod_proxy65_service.erl
@@ -33,7 +33,7 @@
-export([init/1, handle_info/2, handle_call/3,
handle_cast/2, terminate/2, code_change/3]).
--export([start_link/2, add_listener/2, process_disco_info/1,
+-export([start_link/2, reload/3, add_listener/2, process_disco_info/1,
process_disco_items/1, process_vcard/1, process_bytestreams/1,
transform_module_options/1, delete_listener/1]).
@@ -54,6 +54,10 @@ start_link(Host, Opts) ->
gen_server:start_link({local, Proc}, ?MODULE,
[Host, Opts], []).
+reload(Host, NewOpts, OldOpts) ->
+ Proc = gen_mod:get_module_proc(Host, ?PROCNAME),
+ gen_server:cast(Proc, {reload, Host, NewOpts, OldOpts}).
+
init([Host, Opts]) ->
process_flag(trap_exit, true),
IQDisc = gen_mod:get_opt(iqdisc, Opts, fun gen_iq_handler:check_type/1,
@@ -85,7 +89,41 @@ handle_info(_Info, State) -> {noreply, State}.
handle_call(_Request, _From, State) ->
{reply, ok, State}.
-handle_cast(_Request, State) -> {noreply, State}.
+handle_cast({reload, ServerHost, NewOpts, OldOpts}, State) ->
+ NewHost = gen_mod:get_opt_host(ServerHost, NewOpts, <<"proxy.@HOST@">>),
+ OldHost = gen_mod:get_opt_host(ServerHost, OldOpts, <<"proxy.@HOST@">>),
+ NewIQDisc = gen_mod:get_opt(iqdisc, NewOpts,
+ fun gen_iq_handler:check_type/1,
+ one_queue),
+ OldIQDisc = gen_mod:get_opt(iqdisc, OldOpts,
+ fun gen_iq_handler:check_type/1,
+ one_queue),
+ if (NewIQDisc /= OldIQDisc) or (NewHost /= OldHost) ->
+ gen_iq_handler:add_iq_handler(ejabberd_local, NewHost, ?NS_DISCO_INFO,
+ ?MODULE, process_disco_info, NewIQDisc),
+ gen_iq_handler:add_iq_handler(ejabberd_local, NewHost, ?NS_DISCO_ITEMS,
+ ?MODULE, process_disco_items, NewIQDisc),
+ gen_iq_handler:add_iq_handler(ejabberd_local, NewHost, ?NS_VCARD,
+ ?MODULE, process_vcard, NewIQDisc),
+ gen_iq_handler:add_iq_handler(ejabberd_local, NewHost, ?NS_BYTESTREAMS,
+ ?MODULE, process_bytestreams, NewIQDisc);
+ true ->
+ ok
+ end,
+ if NewHost /= OldHost ->
+ ejabberd_router:register_route(NewHost, ServerHost),
+ ejabberd_router:unregister_route(OldHost),
+ gen_iq_handler:remove_iq_handler(ejabberd_local, OldHost, ?NS_DISCO_INFO),
+ gen_iq_handler:remove_iq_handler(ejabberd_local, OldHost, ?NS_DISCO_ITEMS),
+ gen_iq_handler:remove_iq_handler(ejabberd_local, OldHost, ?NS_VCARD),
+ gen_iq_handler:remove_iq_handler(ejabberd_local, OldHost, ?NS_BYTESTREAMS);
+ true ->
+ ok
+ end,
+ {noreply, State#state{myhost = NewHost}};
+handle_cast(Msg, State) ->
+ ?WARNING_MSG("unexpected cast: ~p", [Msg]),
+ {noreply, State}.
code_change(_OldVsn, State, _Extra) -> {ok, State}.
diff --git a/src/mod_register.erl b/src/mod_register.erl
index 55ce3ff00..7269d21cb 100644
--- a/src/mod_register.erl
+++ b/src/mod_register.erl
@@ -33,7 +33,7 @@
-behaviour(gen_mod).
--export([start/2, stop/1, stream_feature_register/2,
+-export([start/2, stop/1, reload/3, stream_feature_register/2,
c2s_unauthenticated_packet/2, try_register/5,
process_iq/1, send_registration_notifications/3,
transform_options/1, transform_module_options/1,
@@ -71,6 +71,19 @@ stop(Host) ->
gen_iq_handler:remove_iq_handler(ejabberd_sm, Host,
?NS_REGISTER).
+reload(Host, NewOpts, OldOpts) ->
+ case gen_mod:is_equal_opt(iqdisc, NewOpts, OldOpts,
+ fun gen_iq_handler:check_type/1,
+ one_queue) of
+ {false, IQDisc, _} ->
+ gen_iq_handler:add_iq_handler(ejabberd_local, Host, ?NS_REGISTER,
+ ?MODULE, process_iq, IQDisc),
+ gen_iq_handler:add_iq_handler(ejabberd_sm, Host, ?NS_REGISTER,
+ ?MODULE, process_iq, IQDisc);
+ true ->
+ ok
+ end.
+
depends(_Host, _Opts) ->
[].
diff --git a/src/mod_register_web.erl b/src/mod_register_web.erl
index 21db76b46..237a905b7 100644
--- a/src/mod_register_web.erl
+++ b/src/mod_register_web.erl
@@ -55,7 +55,7 @@
-behaviour(gen_mod).
--export([start/2, stop/1, process/2, mod_opt_type/1, depends/2]).
+-export([start/2, stop/1, reload/3, process/2, mod_opt_type/1, depends/2]).
-include("ejabberd.hrl").
-include("logger.hrl").
@@ -76,6 +76,9 @@ start(_Host, _Opts) ->
stop(_Host) -> ok.
+reload(_Host, _NewOpts, _OldOpts) ->
+ ok.
+
depends(_Host, _Opts) ->
[{mod_register, hard}].
diff --git a/src/mod_roster.erl b/src/mod_roster.erl
index 86a9ab8bc..30b4269f1 100644
--- a/src/mod_roster.erl
+++ b/src/mod_roster.erl
@@ -41,7 +41,7 @@
-behaviour(gen_mod).
--export([start/2, stop/1, process_iq/1, export/1,
+-export([start/2, stop/1, reload/3, process_iq/1, export/1,
import_info/0, process_local_iq/1, get_user_roster/2,
import/5, c2s_session_opened/1, get_roster/2,
import_start/2, import_stop/2, user_receive_packet/1,
@@ -139,6 +139,24 @@ stop(Host) ->
gen_iq_handler:remove_iq_handler(ejabberd_sm, Host,
?NS_ROSTER).
+reload(Host, NewOpts, OldOpts) ->
+ NewMod = gen_mod:db_mod(Host, NewOpts, ?MODULE),
+ OldMod = gen_mod:db_mod(Host, OldOpts, ?MODULE),
+ if NewMod /= OldMod ->
+ NewMod:init(Host, NewOpts);
+ true ->
+ ok
+ end,
+ case gen_mod:is_equal_opt(iqdisc, NewOpts, OldOpts,
+ fun gen_iq_handler:check_type/1,
+ one_queue) of
+ {false, IQDisc, _} ->
+ gen_iq_handler:add_iq_handler(ejabberd_sm, Host, ?NS_ROSTER,
+ ?MODULE, process_iq, IQDisc);
+ true ->
+ ok
+ end.
+
depends(_Host, _Opts) ->
[].
diff --git a/src/mod_s2s_dialback.erl b/src/mod_s2s_dialback.erl
index 7c7a0e8d5..d48bda2d9 100644
--- a/src/mod_s2s_dialback.erl
+++ b/src/mod_s2s_dialback.erl
@@ -26,7 +26,7 @@
-protocol({xep, 185, '1.0'}).
%% gen_mod API
--export([start/2, stop/1, depends/2, mod_opt_type/1]).
+-export([start/2, stop/1, reload/3, depends/2, mod_opt_type/1]).
%% Hooks
-export([s2s_out_auth_result/2, s2s_out_downgraded/2,
s2s_in_packet/2, s2s_out_packet/2, s2s_in_recv/3,
@@ -86,6 +86,14 @@ stop(Host) ->
ejabberd_hooks:delete(s2s_out_auth_result, Host, ?MODULE,
s2s_out_auth_result, 50).
+reload(Host, NewOpts, _OldOpts) ->
+ case ejabberd_s2s:tls_verify(Host) of
+ false ->
+ start(Host, NewOpts);
+ true ->
+ stop(Host)
+ end.
+
depends(_Host, _Opts) ->
[].
diff --git a/src/mod_shared_roster.erl b/src/mod_shared_roster.erl
index 214035147..7929b21ab 100644
--- a/src/mod_shared_roster.erl
+++ b/src/mod_shared_roster.erl
@@ -29,7 +29,7 @@
-behaviour(gen_mod).
--export([start/2, stop/1, export/1,
+-export([start/2, stop/1, reload/3, export/1,
import_info/0, webadmin_menu/3, webadmin_page/3,
get_user_roster/2, c2s_session_opened/1,
get_jid_info/4, import/5, process_item/2, import_start/2,
@@ -127,8 +127,16 @@ stop(Host) ->
ejabberd_hooks:delete(remove_user, Host, ?MODULE,
remove_user,
50).
- %%ejabberd_hooks:delete(remove_user, Host,
- %% ?MODULE, remove_user, 50),
+
+reload(Host, NewOpts, OldOpts) ->
+ NewMod = gen_mod:db_mod(Host, NewOpts, ?MODULE),
+ OldMod = gen_mod:db_mod(Host, OldOpts, ?MODULE),
+ if NewMod /= OldMod ->
+ NewMod:init(Host, NewOpts);
+ true ->
+ ok
+ end,
+ ok.
depends(_Host, _Opts) ->
[].
diff --git a/src/mod_sic.erl b/src/mod_sic.erl
index fe8d8aa0f..bca662fcd 100644
--- a/src/mod_sic.erl
+++ b/src/mod_sic.erl
@@ -31,7 +31,7 @@
-behaviour(gen_mod).
--export([start/2, stop/1, process_local_iq/1,
+-export([start/2, stop/1, reload/3, process_local_iq/1,
process_sm_iq/1, mod_opt_type/1, depends/2]).
-include("ejabberd.hrl").
@@ -56,6 +56,23 @@ stop(Host) ->
gen_iq_handler:remove_iq_handler(ejabberd_local, Host, ?NS_SIC_1),
gen_iq_handler:remove_iq_handler(ejabberd_sm, Host, ?NS_SIC_1).
+reload(Host, NewOpts, OldOpts) ->
+ case gen_mod:is_equal_opt(iqdisc, NewOpts, OldOpts,
+ fun gen_iq_handler:check_type/1,
+ one_queue) of
+ {false, IQDisc, _} ->
+ gen_iq_handler:add_iq_handler(ejabberd_local, Host, ?NS_SIC_0,
+ ?MODULE, process_local_iq, IQDisc),
+ gen_iq_handler:add_iq_handler(ejabberd_sm, Host, ?NS_SIC_0,
+ ?MODULE, process_sm_iq, IQDisc),
+ gen_iq_handler:add_iq_handler(ejabberd_local, Host, ?NS_SIC_1,
+ ?MODULE, process_local_iq, IQDisc),
+ gen_iq_handler:add_iq_handler(ejabberd_sm, Host, ?NS_SIC_1,
+ ?MODULE, process_sm_iq, IQDisc);
+ true ->
+ ok
+ end.
+
depends(_Host, _Opts) ->
[].
diff --git a/src/mod_sip.erl b/src/mod_sip.erl
index 7d62bdfc3..c34a90795 100644
--- a/src/mod_sip.erl
+++ b/src/mod_sip.erl
@@ -29,7 +29,8 @@
-behaviour(esip).
%% API
--export([start/2, stop/1, make_response/2, is_my_host/1, at_my_host/1]).
+-export([start/2, stop/1, reload/3,
+ make_response/2, is_my_host/1, at_my_host/1]).
-export([data_in/2, data_out/2, message_in/2,
message_out/2, request/2, request/3, response/2,
@@ -61,6 +62,9 @@ start(_Host, _Opts) ->
stop(_Host) ->
ok.
+reload(_Host, _NewOpts, _OldOpts) ->
+ ok.
+
depends(_Host, _Opts) ->
[].
diff --git a/src/mod_stats.erl b/src/mod_stats.erl
index 6cafdf732..124b21d50 100644
--- a/src/mod_stats.erl
+++ b/src/mod_stats.erl
@@ -31,7 +31,7 @@
-behaviour(gen_mod).
--export([start/2, stop/1, process_iq/1, mod_opt_type/1, depends/2]).
+-export([start/2, stop/1, reload/3, process_iq/1, mod_opt_type/1, depends/2]).
-include("ejabberd.hrl").
-include("logger.hrl").
@@ -46,6 +46,9 @@ start(Host, Opts) ->
stop(Host) ->
gen_iq_handler:remove_iq_handler(ejabberd_local, Host, ?NS_STATS).
+reload(Host, NewOpts, _OldOpts) ->
+ start(Host, NewOpts).
+
depends(_Host, _Opts) ->
[].
diff --git a/src/mod_stream_mgmt.erl b/src/mod_stream_mgmt.erl
index 981b357b7..6420c257b 100644
--- a/src/mod_stream_mgmt.erl
+++ b/src/mod_stream_mgmt.erl
@@ -26,7 +26,7 @@
-protocol({xep, 198, '1.5.2'}).
%% gen_mod API
--export([start/2, stop/1, depends/2, mod_opt_type/1]).
+-export([start/2, stop/1, reload/3, depends/2, mod_opt_type/1]).
%% hooks
-export([c2s_stream_init/2, c2s_stream_started/2, c2s_stream_features/2,
c2s_authenticated_packet/2, c2s_unauthenticated_packet/2,
@@ -87,6 +87,10 @@ stop(Host) ->
ejabberd_hooks:delete(c2s_closed, Host, ?MODULE, c2s_closed, 50),
ejabberd_hooks:delete(c2s_terminated, Host, ?MODULE, c2s_terminated, 50).
+reload(_Host, _NewOpts, _OldOpts) ->
+ ?WARNING_MSG("module ~s is reloaded, but new configuration will take "
+ "effect for newly created client connections only", []).
+
depends(_Host, _Opts) ->
[].
diff --git a/src/mod_time.erl b/src/mod_time.erl
index 883fd4b1a..0b5264889 100644
--- a/src/mod_time.erl
+++ b/src/mod_time.erl
@@ -32,7 +32,7 @@
-behaviour(gen_mod).
--export([start/2, stop/1, process_local_iq/1,
+-export([start/2, stop/1, reload/3, process_local_iq/1,
mod_opt_type/1, depends/2]).
-include("ejabberd.hrl").
@@ -50,6 +50,17 @@ stop(Host) ->
gen_iq_handler:remove_iq_handler(ejabberd_local, Host,
?NS_TIME).
+reload(Host, NewOpts, OldOpts) ->
+ case gen_mod:is_equal_opt(iqdisc, NewOpts, OldOpts,
+ fun gen_iq_handler:check_type/1,
+ one_queue) of
+ {false, IQDisc, _} ->
+ gen_iq_handler:add_iq_handler(ejabberd_local, Host, ?NS_TIME,
+ ?MODULE, process_local_iq, IQDisc);
+ true ->
+ ok
+ end.
+
process_local_iq(#iq{type = set, lang = Lang} = IQ) ->
Txt = <<"Value 'set' of 'type' attribute is not allowed">>,
xmpp:make_error(IQ, xmpp:err_not_allowed(Txt, Lang));
diff --git a/src/mod_vcard_xupdate.erl b/src/mod_vcard_xupdate.erl
index 12e31b8dc..2a754d408 100644
--- a/src/mod_vcard_xupdate.erl
+++ b/src/mod_vcard_xupdate.erl
@@ -28,7 +28,7 @@
-behaviour(gen_mod).
%% gen_mod callbacks
--export([start/2, stop/1]).
+-export([start/2, stop/1, reload/3]).
-export([update_presence/1, vcard_set/3, export/1,
import_info/0, import/5, import_start/2,
@@ -64,6 +64,16 @@ stop(Host) ->
vcard_set, 100),
ok.
+reload(Host, NewOpts, OldOpts) ->
+ NewMod = gen_mod:db_mod(Host, NewOpts, ?MODULE),
+ OldMod = gen_mod:db_mod(Host, OldOpts, ?MODULE),
+ if NewMod /= OldMod ->
+ NewMod:init(Host, NewOpts);
+ true ->
+ ok
+ end,
+ ok.
+
depends(_Host, _Opts) ->
[].
diff --git a/src/mod_version.erl b/src/mod_version.erl
index ee35a3c41..2ec713c17 100644
--- a/src/mod_version.erl
+++ b/src/mod_version.erl
@@ -31,7 +31,7 @@
-behaviour(gen_mod).
--export([start/2, stop/1, process_local_iq/1,
+-export([start/2, stop/1, reload/3, process_local_iq/1,
mod_opt_type/1, depends/2]).
-include("ejabberd.hrl").
@@ -50,6 +50,17 @@ stop(Host) ->
gen_iq_handler:remove_iq_handler(ejabberd_local, Host,
?NS_VERSION).
+reload(Host, NewOpts, OldOpts) ->
+ case gen_mod:is_equal_opt(iqdisc, NewOpts, OldOpts,
+ fun gen_iq_handler:check_type/1,
+ one_queue) of
+ {false, IQDisc, _} ->
+ gen_iq_handler:add_iq_handler(ejabberd_local, Host, ?NS_VERSION,
+ ?MODULE, process_local_iq, IQDisc);
+ true ->
+ ok
+ end.
+
process_local_iq(#iq{type = set, lang = Lang} = IQ) ->
Txt = <<"Value 'set' of 'type' attribute is not allowed">>,
xmpp:make_error(IQ, xmpp:err_not_allowed(Txt, Lang));