mirror of
https://github.com/processone/ejabberd.git
synced 2024-12-22 17:28:25 +01:00
Reload modules when reloading configuration file
This commit is contained in:
parent
ff67860cdb
commit
3c4057ff55
@ -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()}.
|
||||
|
||||
|
@ -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
|
||||
|
111
src/gen_mod.erl
111
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].
|
||||
|
@ -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,
|
||||
|
@ -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) ->
|
||||
[].
|
||||
|
||||
|
@ -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}].
|
||||
|
||||
|
@ -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),
|
||||
|
@ -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}].
|
||||
|
||||
|
@ -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
|
||||
%%%===================================================================
|
||||
|
@ -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),
|
||||
|
@ -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()]}.
|
||||
|
@ -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.
|
||||
%%--------------------------------------------------------------------
|
||||
|
@ -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}].
|
||||
|
@ -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(_) ->
|
||||
|
@ -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">>,
|
||||
|
@ -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} |
|
||||
|
@ -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) ->
|
||||
[].
|
||||
|
||||
|
@ -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) ->
|
||||
[].
|
||||
|
||||
|
@ -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}.
|
||||
|
||||
%%--------------------------------------------------------------------
|
||||
|
@ -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),
|
||||
|
@ -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
|
||||
%%%
|
||||
|
@ -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) ->
|
||||
[].
|
||||
|
||||
|
@ -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),
|
||||
|
@ -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) ->
|
||||
[].
|
||||
|
||||
|
216
src/mod_muc.erl
216
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}}.
|
||||
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) ->
|
||||
|
@ -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}].
|
||||
|
||||
|
@ -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 ->
|
||||
|
@ -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} |
|
||||
|
@ -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) ->
|
||||
|
122
src/mod_ping.erl
122
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),
|
||||
|
@ -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) ->
|
||||
[].
|
||||
|
||||
|
@ -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()]}.
|
||||
|
@ -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},
|
||||
|
@ -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();
|
||||
|
@ -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,
|
||||
|
@ -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}.
|
||||
|
||||
|
@ -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) ->
|
||||
[].
|
||||
|
||||
|
@ -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}].
|
||||
|
||||
|
@ -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) ->
|
||||
[].
|
||||
|
||||
|
@ -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) ->
|
||||
[].
|
||||
|
||||
|
@ -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) ->
|
||||
[].
|
||||
|
@ -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) ->
|
||||
[].
|
||||
|
||||
|
@ -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) ->
|
||||
[].
|
||||
|
||||
|
@ -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) ->
|
||||
[].
|
||||
|
||||
|
@ -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) ->
|
||||
[].
|
||||
|
||||
|
@ -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));
|
||||
|
@ -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) ->
|
||||
[].
|
||||
|
||||
|
@ -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));
|
||||
|
Loading…
Reference in New Issue
Block a user