Support XEP-0198 pings
If stream management is enabled, let mod_ping trigger XEP-0198 <r/>equests rather than sending XEP-0199 pings. This avoids the overhead of the ping IQ stanzas, which, if stream management is enabled, are accompanied by XEP-0198 elements anyway. Thanks to MoyaApp (<https://moya.app>) for sponsoring this work.
This commit is contained in:
parent
74cb2e054f
commit
6c691a73bd
|
@ -49,14 +49,13 @@
|
||||||
-export([init/1, terminate/2, handle_call/3,
|
-export([init/1, terminate/2, handle_call/3,
|
||||||
handle_cast/2, handle_info/2, code_change/3]).
|
handle_cast/2, handle_info/2, code_change/3]).
|
||||||
|
|
||||||
-export([iq_ping/1, user_online/3, user_offline/3, mod_doc/0,
|
-export([iq_ping/1, user_online/3, user_offline/3, mod_doc/0, user_send/1,
|
||||||
user_send/1, mod_opt_type/1, mod_options/1, depends/2]).
|
c2s_handle_cast/2, mod_opt_type/1, mod_options/1, depends/2]).
|
||||||
|
|
||||||
-record(state,
|
-record(state,
|
||||||
{host :: binary(),
|
{host :: binary(),
|
||||||
send_pings :: boolean(),
|
send_pings :: boolean(),
|
||||||
ping_interval :: pos_integer(),
|
ping_interval :: pos_integer(),
|
||||||
ping_ack_timeout :: undefined | non_neg_integer(),
|
|
||||||
timeout_action :: none | kill,
|
timeout_action :: none | kill,
|
||||||
timers :: timers()}).
|
timers :: timers()}).
|
||||||
|
|
||||||
|
@ -167,13 +166,8 @@ handle_info({timeout, _TRef, {ping, JID}}, State) ->
|
||||||
JID#jid.lresource) of
|
JID#jid.lresource) of
|
||||||
none ->
|
none ->
|
||||||
del_timer(JID, State#state.timers);
|
del_timer(JID, State#state.timers);
|
||||||
_ ->
|
Pid ->
|
||||||
Host = State#state.host,
|
ejabberd_c2s:cast(Pid, send_ping),
|
||||||
From = jid:make(Host),
|
|
||||||
IQ = #iq{from = From, to = JID, type = get, sub_els = [#ping{}]},
|
|
||||||
ejabberd_router:route_iq(IQ, JID,
|
|
||||||
gen_mod:get_module_proc(Host, ?MODULE),
|
|
||||||
State#state.ping_ack_timeout),
|
|
||||||
add_timer(JID, State#state.ping_interval,
|
add_timer(JID, State#state.ping_interval,
|
||||||
State#state.timers)
|
State#state.timers)
|
||||||
end,
|
end,
|
||||||
|
@ -214,19 +208,29 @@ user_send({Packet, #{jid := JID} = C2SState}) ->
|
||||||
start_ping(JID#jid.lserver, JID),
|
start_ping(JID#jid.lserver, JID),
|
||||||
{Packet, C2SState}.
|
{Packet, C2SState}.
|
||||||
|
|
||||||
|
-spec c2s_handle_cast(ejabberd_c2s:state(), send_ping | term())
|
||||||
|
-> ejabberd_c2s:state() | {stop, ejabberd_c2s:state()}.
|
||||||
|
c2s_handle_cast(#{lserver := Host, jid := JID} = C2SState, send_ping) ->
|
||||||
|
From = jid:make(Host),
|
||||||
|
IQ = #iq{from = From, to = JID, type = get, sub_els = [#ping{}]},
|
||||||
|
Proc = gen_mod:get_module_proc(Host, ?MODULE),
|
||||||
|
PingAckTimeout = mod_ping_opt:ping_ack_timeout(Host),
|
||||||
|
ejabberd_router:route_iq(IQ, JID, Proc, PingAckTimeout),
|
||||||
|
{stop, C2SState};
|
||||||
|
c2s_handle_cast(C2SState, _Msg) ->
|
||||||
|
C2SState.
|
||||||
|
|
||||||
%%====================================================================
|
%%====================================================================
|
||||||
%% Internal functions
|
%% Internal functions
|
||||||
%%====================================================================
|
%%====================================================================
|
||||||
init_state(Host, Opts) ->
|
init_state(Host, Opts) ->
|
||||||
SendPings = mod_ping_opt:send_pings(Opts),
|
SendPings = mod_ping_opt:send_pings(Opts),
|
||||||
PingInterval = mod_ping_opt:ping_interval(Opts),
|
PingInterval = mod_ping_opt:ping_interval(Opts),
|
||||||
PingAckTimeout = mod_ping_opt:ping_ack_timeout(Opts),
|
|
||||||
TimeoutAction = mod_ping_opt:timeout_action(Opts),
|
TimeoutAction = mod_ping_opt:timeout_action(Opts),
|
||||||
#state{host = Host,
|
#state{host = Host,
|
||||||
send_pings = SendPings,
|
send_pings = SendPings,
|
||||||
ping_interval = PingInterval,
|
ping_interval = PingInterval,
|
||||||
timeout_action = TimeoutAction,
|
timeout_action = TimeoutAction,
|
||||||
ping_ack_timeout = PingAckTimeout,
|
|
||||||
timers = #{}}.
|
timers = #{}}.
|
||||||
|
|
||||||
register_hooks(Host) ->
|
register_hooks(Host) ->
|
||||||
|
@ -235,7 +239,9 @@ register_hooks(Host) ->
|
||||||
ejabberd_hooks:add(sm_remove_connection_hook, Host,
|
ejabberd_hooks:add(sm_remove_connection_hook, Host,
|
||||||
?MODULE, user_offline, 100),
|
?MODULE, user_offline, 100),
|
||||||
ejabberd_hooks:add(user_send_packet, Host, ?MODULE,
|
ejabberd_hooks:add(user_send_packet, Host, ?MODULE,
|
||||||
user_send, 100).
|
user_send, 100),
|
||||||
|
ejabberd_hooks:add(c2s_handle_cast, Host, ?MODULE,
|
||||||
|
c2s_handle_cast, 99).
|
||||||
|
|
||||||
unregister_hooks(Host) ->
|
unregister_hooks(Host) ->
|
||||||
ejabberd_hooks:delete(sm_remove_connection_hook, Host,
|
ejabberd_hooks:delete(sm_remove_connection_hook, Host,
|
||||||
|
@ -243,7 +249,9 @@ unregister_hooks(Host) ->
|
||||||
ejabberd_hooks:delete(sm_register_connection_hook, Host,
|
ejabberd_hooks:delete(sm_register_connection_hook, Host,
|
||||||
?MODULE, user_online, 100),
|
?MODULE, user_online, 100),
|
||||||
ejabberd_hooks:delete(user_send_packet, Host, ?MODULE,
|
ejabberd_hooks:delete(user_send_packet, Host, ?MODULE,
|
||||||
user_send, 100).
|
user_send, 100),
|
||||||
|
ejabberd_hooks:delete(c2s_handle_cast, Host, ?MODULE,
|
||||||
|
c2s_handle_cast, 99).
|
||||||
|
|
||||||
register_iq_handlers(Host) ->
|
register_iq_handlers(Host) ->
|
||||||
gen_iq_handler:add_iq_handler(ejabberd_sm, Host, ?NS_PING,
|
gen_iq_handler:add_iq_handler(ejabberd_sm, Host, ?NS_PING,
|
||||||
|
@ -315,7 +323,10 @@ mod_doc() ->
|
||||||
#{value => "timeout()",
|
#{value => "timeout()",
|
||||||
desc =>
|
desc =>
|
||||||
?T("How long to wait before deeming that a client "
|
?T("How long to wait before deeming that a client "
|
||||||
"has not answered a given server ping request. "
|
"has not answered a given server ping request. NOTE: when "
|
||||||
|
"_`mod_stream_mgmt`_ is loaded and stream management is "
|
||||||
|
"enabled by a client, this value is ignored, and the "
|
||||||
|
"`ack_timeout` applies instead. "
|
||||||
"The default value is 'undefined'.")}},
|
"The default value is 'undefined'.")}},
|
||||||
{send_pings,
|
{send_pings,
|
||||||
#{value => "true | false",
|
#{value => "true | false",
|
||||||
|
|
|
@ -32,8 +32,8 @@
|
||||||
-export([c2s_stream_started/2, c2s_stream_features/2,
|
-export([c2s_stream_started/2, c2s_stream_features/2,
|
||||||
c2s_authenticated_packet/2, c2s_unauthenticated_packet/2,
|
c2s_authenticated_packet/2, c2s_unauthenticated_packet/2,
|
||||||
c2s_unbinded_packet/2, c2s_closed/2, c2s_terminated/2,
|
c2s_unbinded_packet/2, c2s_closed/2, c2s_terminated/2,
|
||||||
c2s_handle_send/3, c2s_handle_info/2, c2s_handle_call/3,
|
c2s_handle_send/3, c2s_handle_info/2, c2s_handle_cast/2,
|
||||||
c2s_handle_recv/3, c2s_inline_features/2,
|
c2s_handle_call/3, c2s_handle_recv/3, c2s_inline_features/2,
|
||||||
c2s_handle_sasl2_inline/1, c2s_handle_sasl2_inline_post/3,
|
c2s_handle_sasl2_inline/1, c2s_handle_sasl2_inline_post/3,
|
||||||
c2s_handle_bind2_inline/1]).
|
c2s_handle_bind2_inline/1]).
|
||||||
%% adjust pending session timeout / access queue
|
%% adjust pending session timeout / access queue
|
||||||
|
@ -77,6 +77,7 @@ start(_Host, Opts) ->
|
||||||
{hook, c2s_handle_send, c2s_handle_send, 50},
|
{hook, c2s_handle_send, c2s_handle_send, 50},
|
||||||
{hook, c2s_handle_recv, c2s_handle_recv, 50},
|
{hook, c2s_handle_recv, c2s_handle_recv, 50},
|
||||||
{hook, c2s_handle_info, c2s_handle_info, 50},
|
{hook, c2s_handle_info, c2s_handle_info, 50},
|
||||||
|
{hook, c2s_handle_cast, c2s_handle_cast, 50},
|
||||||
{hook, c2s_handle_call, c2s_handle_call, 50},
|
{hook, c2s_handle_call, c2s_handle_call, 50},
|
||||||
{hook, c2s_handle_sasl2_inline, c2s_handle_sasl2_inline, 50},
|
{hook, c2s_handle_sasl2_inline, c2s_handle_sasl2_inline, 50},
|
||||||
{hook, c2s_handle_sasl2_inline_post, c2s_handle_sasl2_inline_post, 50},
|
{hook, c2s_handle_sasl2_inline_post, c2s_handle_sasl2_inline_post, 50},
|
||||||
|
@ -258,6 +259,13 @@ c2s_handle_send(#{mgmt_state := MgmtState, mod := Mod,
|
||||||
c2s_handle_send(State, _Pkt, _Result) ->
|
c2s_handle_send(State, _Pkt, _Result) ->
|
||||||
State.
|
State.
|
||||||
|
|
||||||
|
c2s_handle_cast(#{mgmt_state := active} = State, send_ping) ->
|
||||||
|
{stop, send_rack(State)};
|
||||||
|
c2s_handle_cast(#{mgmt_state := pending} = State, send_ping) ->
|
||||||
|
{stop, State};
|
||||||
|
c2s_handle_cast(State, _Msg) ->
|
||||||
|
State.
|
||||||
|
|
||||||
c2s_handle_call(#{mgmt_id := MgmtID, mgmt_queue := Queue, mod := Mod} = State,
|
c2s_handle_call(#{mgmt_id := MgmtID, mgmt_queue := Queue, mod := Mod} = State,
|
||||||
{resume_session, MgmtID}, From) ->
|
{resume_session, MgmtID}, From) ->
|
||||||
State1 = State#{mgmt_queue => p1_queue:file_to_ram(Queue)},
|
State1 = State#{mgmt_queue => p1_queue:file_to_ram(Queue)},
|
||||||
|
|
Loading…
Reference in New Issue