Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactored hook handlers in mod_ping #3821

Merged
merged 2 commits into from
Oct 26, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
98 changes: 57 additions & 41 deletions src/mod_ping.erl
Original file line number Diff line number Diff line change
Expand Up @@ -26,17 +26,14 @@

%% Hook callbacks
-export([iq_ping/5,
user_online/5,
user_offline/5,
user_send/4,
user_ping_response/5,
user_keep_alive/2]).
user_online/3,
user_offline/3,
user_send/3,
user_ping_response/3,
user_keep_alive/3]).

%% Remote hook callback
-export([handle_remote_hook/4]).

-ignore_xref([handle_remote_hook/4, user_keep_alive/2, user_offline/5, user_online/5,
user_ping_response/5, user_ping_response/5, user_send/4]).
-export([handle_remote_hook/3]).

%%====================================================================
%% Info Handler
Expand Down Expand Up @@ -75,12 +72,12 @@ route_ping_iq(JID, Server, HostType) ->
%%====================================================================

hooks(HostType) ->
[{sm_register_connection_hook, HostType, ?MODULE, user_online, 100},
{sm_remove_connection_hook, HostType, ?MODULE, user_offline, 100},
{user_send_packet, HostType, ?MODULE, user_send, 100},
{user_sent_keep_alive, HostType, ?MODULE, user_keep_alive, 100},
{user_ping_response, HostType, ?MODULE, user_ping_response, 100},
{c2s_remote_hook, HostType, ?MODULE, handle_remote_hook, 100}].
[{sm_register_connection_hook, HostType, fun ?MODULE:user_online/3, #{}, 100},
{sm_remove_connection_hook, HostType, fun ?MODULE:user_offline/3, #{}, 100},
{user_send_packet, HostType, fun ?MODULE:user_send/3, #{}, 100},
{user_sent_keep_alive, HostType, fun ?MODULE:user_keep_alive/3, #{}, 100},
{user_ping_response, HostType, fun ?MODULE:user_ping_response/3, #{}, 100},
{c2s_remote_hook, HostType, fun ?MODULE:handle_remote_hook/3, #{}, 100}].

ensure_metrics(HostType) ->
mongoose_metrics:ensure_metric(HostType, [mod_ping, ping_response], spiral),
Expand All @@ -102,15 +99,15 @@ start(HostType, #{send_pings := SendPings, iqdisc := IQDisc}) ->

-spec maybe_add_hooks_handlers(mongooseim:host_type(), boolean()) -> ok.
maybe_add_hooks_handlers(Host, true) ->
ejabberd_hooks:add(hooks(Host));
gen_hook:add_handlers(hooks(Host));
maybe_add_hooks_handlers(_, _) ->
ok.

-spec stop(mongooseim:host_type()) -> ok.
stop(HostType) ->
%% a word of warning: timers are installed in c2s processes, so stopping mod_ping
%% won't stop currently running timers. They'll run one more time, and then stop.
ejabberd_hooks:delete(hooks(HostType)),
gen_hook:delete_handlers(hooks(HostType)),
gen_iq_handler:remove_iq_handler_for_domain(HostType, ?NS_PING, ejabberd_local),
gen_iq_handler:remove_iq_handler_for_domain(HostType, ?NS_PING, ejabberd_sm),
ok.
Expand Down Expand Up @@ -152,43 +149,62 @@ iq_ping(Acc, _From, _To, #iq{sub_el = SubEl} = IQ, _) ->
%% Hook callbacks
%%====================================================================

handle_remote_hook(HandlerState, mod_ping, Args, C2SState) ->
handle_remote_call(Args,
-spec handle_remote_hook(Acc, Params, Extra) -> {ok, Acc} when
Acc :: term(),
Params :: #{tag := atom(), args := term(), c2s_state := ejabberd_c2s:state()},
Extra :: map().
handle_remote_hook(HandlerState, #{tag := mod_ping, hook_args := Args, c2s_state := C2SState}, _) ->
{ok, handle_remote_call(Args,
ejabberd_c2s_state:jid(C2SState),
ejabberd_c2s_state:server(C2SState),
ejabberd_c2s_state:host_type(C2SState),
HandlerState);
handle_remote_hook(HandlerState, _, _, _) ->
HandlerState.

user_online(Acc, _HostType, {_, Pid} = _SID, _Jid, _Info) ->
HandlerState)};
handle_remote_hook(HandlerState, _, _) ->
{ok, HandlerState}.

-spec user_online(Acc, Params, Extra) -> {ok, Acc} when
Acc :: ok,
Params :: #{sid := ejabberd_sm:sid()},
Extra :: map().
user_online(Acc, #{sid := {_, Pid}}, _) ->
ejabberd_c2s:run_remote_hook(Pid, mod_ping, init),
Acc.
{ok, Acc}.

user_offline(Acc, {_, Pid} = _SID, _JID, _Info, _Reason) ->
-spec user_offline(Acc, Params, Extra) -> {ok, Acc} when
Acc :: mongoose_acc:t(),
Params :: #{sid := ejabberd_sm:sid()},
Extra :: map().
user_offline(Acc, #{sid := {_, Pid}}, _) ->
ejabberd_c2s:run_remote_hook(Pid, mod_ping, remove_timer),
Acc.
{ok, Acc}.

user_send(Acc, _JID, _From, _Packet) ->
-spec user_send(Acc, Params, Extra) -> {ok, Acc} when
Acc :: mongoose_acc:t(),
Params :: map(),
Extra :: map().
user_send(Acc, _, _) ->
ejabberd_c2s:run_remote_hook(self(), mod_ping, init),
Acc.
{ok, Acc}.

user_keep_alive(Acc, _JID) ->
-spec user_keep_alive(Acc, Params, Extra) -> {ok, Acc} when
Acc :: mongoose_acc:t(),
Params :: map(),
Extra :: map().
user_keep_alive(Acc, _, _) ->
ejabberd_c2s:run_remote_hook(self(), mod_ping, init),
Acc.

-spec user_ping_response(Acc :: mongoose_acc:t(),
HostType :: mongooseim:host_type(),
JID :: jid:jid(),
Response :: timeout | jlib:iq(),
TDelta :: pos_integer()) -> mongoose_acc:t().
user_ping_response(Acc, HostType, _JID, timeout, _TDelta) ->
{ok, Acc}.

-spec user_ping_response(Acc, Params, Extra) -> {ok, Acc} when
Acc :: mongoose_acc:t(),
Params :: #{response := timeout | jlib:iq(), time_delta := non_neg_integer()},
Extra :: #{host_type := mongooseim:host_type()}.
user_ping_response(Acc, #{response := timeout}, #{host_type := HostType}) ->
mongoose_metrics:update(HostType, [mod_ping, ping_response_timeout], 1),
Acc;
user_ping_response(Acc, HostType, _JID, _Response, TDelta) ->
{ok, Acc};
user_ping_response(Acc, #{time_delta := TDelta}, #{host_type := HostType}) ->
mongoose_metrics:update(HostType, [mod_ping, ping_response_time], TDelta),
mongoose_metrics:update(HostType, [mod_ping, ping_response], 1),
Acc.
{ok, Acc}.

%%====================================================================
%% Implementation
Expand Down
10 changes: 8 additions & 2 deletions src/mongoose_hooks.erl
Original file line number Diff line number Diff line change
Expand Up @@ -180,8 +180,11 @@
C2SState :: ejabberd_c2s:state(),
Result :: term(). % ok | empty_state | HandlerState
c2s_remote_hook(HostType, Tag, Args, HandlerState, C2SState) ->
Params = #{tag => Tag, hook_args => Args, c2s_state => C2SState},
LegacyArgs = [Tag, Args, C2SState],
ParamsWithLegacyArgs = ejabberd_hooks:add_args(Params, LegacyArgs),
run_hook_for_host_type(c2s_remote_hook, HostType, HandlerState,
[Tag, Args, C2SState]).
ParamsWithLegacyArgs).

-spec adhoc_local_commands(HostType, From, To, AdhocRequest) -> Result when
HostType :: mongooseim:host_type(),
Expand Down Expand Up @@ -493,7 +496,10 @@ user_receive_packet(HostType, Acc, JID, From, To, El) ->
JID :: jid:jid(),
Result :: any().
user_sent_keep_alive(HostType, JID) ->
run_hook_for_host_type(user_sent_keep_alive, HostType, ok, [JID]).
Params = #{jid => JID},
Args = [JID],
ParamsWithLegacyArgs = ejabberd_hooks:add_args(Params, Args),
run_hook_for_host_type(user_sent_keep_alive, HostType, ok, ParamsWithLegacyArgs).

%%% @doc A hook called when a user sends an XMPP stanza.
%%% The hook's handler is expected to accept four parameters:
Expand Down