Reload modules when reloading configuration file

This commit is contained in:
Evgeniy Khramtsov 2017-02-22 19:46:47 +03:00
parent ff67860cdb
commit 3c4057ff55
48 changed files with 1084 additions and 298 deletions

View File

@ -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()}.

View File

@ -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

View File

@ -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].

View File

@ -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,

View File

@ -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) ->
[].

View File

@ -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}].

View File

@ -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),

View File

@ -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}].

View File

@ -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
%%%===================================================================

View File

@ -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),

View File

@ -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()]}.

View File

@ -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.
%%--------------------------------------------------------------------

View File

@ -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}].

View File

@ -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(_) ->

View File

@ -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">>,

View File

@ -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} |

View File

@ -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) ->
[].

View File

@ -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) ->
[].

View File

@ -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}.
%%--------------------------------------------------------------------

View File

@ -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),

View File

@ -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
%%%

View File

@ -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) ->
[].

View File

@ -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),

View File

@ -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) ->
[].

View File

@ -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}}.
gen_iq_handler:add_iq_handler(ejabberd_local, Host, ?NS_DISCO_ITEMS,
?MODULE, process_disco_items, IQDisc).
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
%%--------------------------------------------------------------------
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) ->

View File

@ -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}].

View File

@ -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}}.
#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}.
%%--------------------------------------------------------------------
%%% Internal functions
%%--------------------------------------------------------------------
add_to_log2(text, {Nick, Packet}, Room, Opts, State) ->
case has_no_permanent_store_hint(Packet) of
false ->

View File

@ -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} |

View File

@ -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) ->

View File

@ -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),

View File

@ -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) ->
[].

View File

@ -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()]}.

View File

@ -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},

View File

@ -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();

View File

@ -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,

View File

@ -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}.

View File

@ -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) ->
[].

View File

@ -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}].

View File

@ -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) ->
[].

View File

@ -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) ->
[].

View File

@ -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) ->
[].

View File

@ -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) ->
[].

View File

@ -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) ->
[].

View File

@ -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) ->
[].

View File

@ -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) ->
[].

View File

@ -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));

View File

@ -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) ->
[].

View File

@ -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));