From 3c4057ff553928d4e4ab40e410dbc6a478dd8206 Mon Sep 17 00:00:00 2001 From: Evgeniy Khramtsov Date: Wed, 22 Feb 2017 19:46:47 +0300 Subject: Reload modules when reloading configuration file --- src/mod_ping.erl | 122 +++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 78 insertions(+), 44 deletions(-) (limited to 'src/mod_ping.erl') diff --git a/src/mod_ping.erl b/src/mod_ping.erl index aa048e36e..0e2ccb9fa 100644 --- a/src/mod_ping.erl +++ b/src/mod_ping.erl @@ -48,7 +48,7 @@ -export([start_ping/2, stop_ping/2]). %% gen_mod callbacks --export([start/2, stop/1]). +-export([start/2, stop/1, reload/3]). %% gen_server callbacks -export([init/1, terminate/2, handle_call/3, @@ -87,64 +87,49 @@ start(Host, Opts) -> stop(Host) -> gen_mod:stop_child(?MODULE, Host). +reload(Host, NewOpts, OldOpts) -> + Proc = gen_mod:get_module_proc(Host, ?MODULE), + gen_server:cast(Proc, {reload, Host, NewOpts, OldOpts}). + %%==================================================================== %% gen_server callbacks %%==================================================================== init([Host, Opts]) -> process_flag(trap_exit, true), - SendPings = gen_mod:get_opt(send_pings, Opts, - fun(B) when is_boolean(B) -> B end, - ?DEFAULT_SEND_PINGS), - PingInterval = gen_mod:get_opt(ping_interval, Opts, - fun(I) when is_integer(I), I>0 -> I end, - ?DEFAULT_PING_INTERVAL), - PingAckTimeout = gen_mod:get_opt(ping_ack_timeout, Opts, - fun(I) when is_integer(I), I>0 -> I * 1000 end, - undefined), - TimeoutAction = gen_mod:get_opt(timeout_action, Opts, - fun(none) -> none; - (kill) -> kill - end, none), + State = init_state(Host, Opts), IQDisc = gen_mod:get_opt(iqdisc, Opts, fun gen_iq_handler:check_type/1, no_queue), - gen_iq_handler:add_iq_handler(ejabberd_sm, Host, - ?NS_PING, ?MODULE, iq_ping, IQDisc), - gen_iq_handler:add_iq_handler(ejabberd_local, Host, - ?NS_PING, ?MODULE, iq_ping, IQDisc), - case SendPings of - true -> - ejabberd_hooks:add(sm_register_connection_hook, Host, - ?MODULE, user_online, 100), - ejabberd_hooks:add(sm_remove_connection_hook, Host, - ?MODULE, user_offline, 100), - ejabberd_hooks:add(user_send_packet, Host, ?MODULE, - user_send, 100); - _ -> ok + register_iq_handlers(Host, IQDisc), + case State#state.send_pings of + true -> register_hooks(Host); + false -> ok end, - {ok, - #state{host = Host, send_pings = SendPings, - ping_interval = PingInterval, - timeout_action = TimeoutAction, - ping_ack_timeout = PingAckTimeout, - timers = maps:new()}}. + {ok, State}. terminate(_Reason, #state{host = Host}) -> - ejabberd_hooks:delete(sm_remove_connection_hook, Host, - ?MODULE, user_offline, 100), - ejabberd_hooks:delete(sm_register_connection_hook, Host, - ?MODULE, user_online, 100), - ejabberd_hooks:delete(user_send_packet, Host, ?MODULE, - user_send, 100), - gen_iq_handler:remove_iq_handler(ejabberd_local, Host, - ?NS_PING), - gen_iq_handler:remove_iq_handler(ejabberd_sm, Host, - ?NS_PING). + unregister_hooks(Host), + unregister_iq_handlers(Host). handle_call(stop, _From, State) -> {stop, normal, ok, State}; handle_call(_Req, _From, State) -> {reply, {error, badarg}, State}. +handle_cast({reload, Host, NewOpts, OldOpts}, + #state{timers = Timers} = OldState) -> + case gen_mod:is_equal_opt(iqdisc, NewOpts, OldOpts, + fun gen_iq_handler:check_type/1, + one_queue) of + {false, IQDisc, _} -> register_iq_handlers(Host, IQDisc); + true -> ok + end, + NewState = init_state(Host, NewOpts), + case {NewState#state.send_pings, OldState#state.send_pings} of + {true, false} -> register_hooks(Host); + {false, true} -> unregister_hooks(Host); + _ -> ok + end, + {noreply, NewState#state{timers = Timers}}; handle_cast({start_ping, JID}, State) -> Timers = add_timer(JID, State#state.ping_interval, State#state.timers), @@ -169,7 +154,9 @@ handle_cast({iq_pong, JID, timeout}, State) -> _ -> ok end, {noreply, State#state{timers = Timers}}; -handle_cast(_Msg, State) -> {noreply, State}. +handle_cast(Msg, State) -> + ?WARNING_MSG("unexpected cast: ~p", [Msg]), + {noreply, State}. handle_info({timeout, _TRef, {ping, JID}}, State) -> From = jid:make(State#state.host), @@ -212,6 +199,53 @@ user_send({Packet, #{jid := JID} = C2SState}) -> %%==================================================================== %% Internal functions %%==================================================================== +init_state(Host, Opts) -> + SendPings = gen_mod:get_opt(send_pings, Opts, + fun(B) when is_boolean(B) -> B end, + ?DEFAULT_SEND_PINGS), + PingInterval = gen_mod:get_opt(ping_interval, Opts, + fun(I) when is_integer(I), I>0 -> I end, + ?DEFAULT_PING_INTERVAL), + PingAckTimeout = gen_mod:get_opt(ping_ack_timeout, Opts, + fun(I) when is_integer(I), I>0 -> I * 1000 end, + undefined), + TimeoutAction = gen_mod:get_opt(timeout_action, Opts, + fun(none) -> none; + (kill) -> kill + end, none), + #state{host = Host, + send_pings = SendPings, + ping_interval = PingInterval, + timeout_action = TimeoutAction, + ping_ack_timeout = PingAckTimeout, + timers = maps:new()}. + +register_hooks(Host) -> + ejabberd_hooks:add(sm_register_connection_hook, Host, + ?MODULE, user_online, 100), + ejabberd_hooks:add(sm_remove_connection_hook, Host, + ?MODULE, user_offline, 100), + ejabberd_hooks:add(user_send_packet, Host, ?MODULE, + user_send, 100). + +unregister_hooks(Host) -> + ejabberd_hooks:delete(sm_remove_connection_hook, Host, + ?MODULE, user_offline, 100), + ejabberd_hooks:delete(sm_register_connection_hook, Host, + ?MODULE, user_online, 100), + ejabberd_hooks:delete(user_send_packet, Host, ?MODULE, + user_send, 100). + +register_iq_handlers(Host, IQDisc) -> + gen_iq_handler:add_iq_handler(ejabberd_sm, Host, ?NS_PING, + ?MODULE, iq_ping, IQDisc), + gen_iq_handler:add_iq_handler(ejabberd_local, Host, ?NS_PING, + ?MODULE, iq_ping, IQDisc). + +unregister_iq_handlers(Host) -> + gen_iq_handler:remove_iq_handler(ejabberd_local, Host, ?NS_PING), + gen_iq_handler:remove_iq_handler(ejabberd_sm, Host, ?NS_PING). + -spec add_timer(jid(), non_neg_integer(), map()) -> map(). add_timer(JID, Interval, Timers) -> LJID = jid:tolower(JID), -- cgit v1.2.3