aboutsummaryrefslogtreecommitdiff
path: root/src/mod_stream_mgmt.erl
diff options
context:
space:
mode:
Diffstat (limited to 'src/mod_stream_mgmt.erl')
-rw-r--r--src/mod_stream_mgmt.erl63
1 files changed, 48 insertions, 15 deletions
diff --git a/src/mod_stream_mgmt.erl b/src/mod_stream_mgmt.erl
index 127eea3e8..2f6b0fc71 100644
--- a/src/mod_stream_mgmt.erl
+++ b/src/mod_stream_mgmt.erl
@@ -33,6 +33,8 @@
c2s_unbinded_packet/2, c2s_closed/2, c2s_terminated/2,
c2s_handle_send/3, c2s_handle_info/2, c2s_handle_call/3,
c2s_handle_recv/3]).
+%% adjust pending session timeout
+-export([get_resume_timeout/1, set_resume_timeout/2]).
-include("xmpp.hrl").
-include("logger.hrl").
@@ -69,7 +71,12 @@ start(Host, _Opts) ->
ejabberd_hooks:add(c2s_terminated, Host, ?MODULE, c2s_terminated, 50).
stop(Host) ->
- %% TODO: do something with global 'c2s_init' hook
+ case gen_mod:is_loaded_elsewhere(Host, ?MODULE) of
+ true ->
+ ok;
+ false ->
+ ejabberd_hooks:delete(c2s_init, ?MODULE, c2s_stream_init, 50)
+ end,
ejabberd_hooks:delete(c2s_stream_started, Host, ?MODULE,
c2s_stream_started, 50),
ejabberd_hooks:delete(c2s_post_auth_features, Host, ?MODULE,
@@ -235,8 +242,9 @@ c2s_handle_info(#{mgmt_ack_timer := TRef, jid := JID, mod := Mod} = State,
[jid:encode(JID)]),
State1 = Mod:close(State),
{stop, transition_to_pending(State1)};
-c2s_handle_info(#{mgmt_state := pending, jid := JID, mod := Mod} = State,
- {timeout, _, pending_timeout}) ->
+c2s_handle_info(#{mgmt_state := pending,
+ mgmt_pending_timer := TRef, jid := JID, mod := Mod} = State,
+ {timeout, TRef, pending_timeout}) ->
?DEBUG("Timed out waiting for resumption of stream for ~s",
[jid:encode(JID)]),
Mod:stop(State#{mgmt_state => timeout});
@@ -283,6 +291,20 @@ c2s_terminated(State, _Reason) ->
State.
%%%===================================================================
+%%% Adjust pending session timeout
+%%%===================================================================
+-spec get_resume_timeout(state()) -> non_neg_integer().
+get_resume_timeout(#{mgmt_timeout := Timeout}) ->
+ Timeout.
+
+-spec set_resume_timeout(state(), non_neg_integer()) -> state().
+set_resume_timeout(#{mgmt_timeout := Timeout} = State, Timeout) ->
+ State;
+set_resume_timeout(State, Timeout) ->
+ State1 = restart_pending_timer(State, Timeout),
+ State1#{mgmt_timeout => Timeout}.
+
+%%%===================================================================
%%% Internal functions
%%%===================================================================
-spec negotiate_stream_mgmt(xmpp_element(), state()) -> state().
@@ -388,8 +410,6 @@ handle_resume(#{user := User, lserver := LServer, sockmod := SockMod,
previd = AttrId}),
State3 = resend_unacked_stanzas(State2),
State4 = send(State3, #sm_r{xmlns = AttrXmlns}),
- %% TODO: move this to mod_client_state
- %% csi_flush_queue(State4),
State5 = ejabberd_hooks:run_fold(c2s_session_resumed, LServer, State4, []),
?INFO_MSG("(~s) Resumed session for ~s",
[SockMod:pp(Socket), jid:encode(JID)]),
@@ -408,8 +428,8 @@ transition_to_pending(#{mgmt_state := active, jid := JID,
lserver := LServer, mgmt_timeout := Timeout} = State) ->
State1 = cancel_ack_timer(State),
?INFO_MSG("Waiting for resumption of stream for ~s", [jid:encode(JID)]),
- erlang:start_timer(timer:seconds(Timeout), self(), pending_timeout),
- State2 = State1#{mgmt_state => pending},
+ TRef = erlang:start_timer(timer:seconds(Timeout), self(), pending_timeout),
+ State2 = State1#{mgmt_state => pending, mgmt_pending_timer => TRef},
ejabberd_hooks:run_fold(c2s_session_pending, LServer, State2, []);
transition_to_pending(State) ->
State.
@@ -648,20 +668,33 @@ add_resent_delay_info(_State, El, _Time) ->
send(#{mod := Mod} = State, Pkt) ->
Mod:send(State, Pkt).
+-spec restart_pending_timer(state(), non_neg_integer()) -> state().
+restart_pending_timer(#{mgmt_pending_timer := TRef} = State, NewTimeout) ->
+ cancel_timer(TRef),
+ NewTRef = erlang:start_timer(timer:seconds(NewTimeout), self(),
+ pending_timeout),
+ State#{mgmt_pending_timer => NewTRef};
+restart_pending_timer(State, _NewTimeout) ->
+ State.
+
-spec cancel_ack_timer(state()) -> state().
cancel_ack_timer(#{mgmt_ack_timer := TRef} = State) ->
- case erlang:cancel_timer(TRef) of
- false ->
- receive {timeout, TRef, _} -> ok
- after 0 -> ok
- end;
- _ ->
- ok
- end,
+ cancel_timer(TRef),
maps:remove(mgmt_ack_timer, State);
cancel_ack_timer(State) ->
State.
+-spec cancel_timer(reference()) -> ok.
+cancel_timer(TRef) ->
+ case erlang:cancel_timer(TRef) of
+ false ->
+ receive {timeout, TRef, _} -> ok
+ after 0 -> ok
+ end;
+ _ ->
+ ok
+ end.
+
-spec bounce_message_queue() -> ok.
bounce_message_queue() ->
receive {route, Pkt} ->