From 78fa9e08a5a809c0c6b3c838459077b5d44c8e01 Mon Sep 17 00:00:00 2001 From: Holger Weiss Date: Wed, 3 Aug 2016 02:28:46 +0200 Subject: [PATCH] XEP-0198: Handle timeouts during stream resumption If session resumption failed because requesting the #state from the old c2s process took too long, the new c2s process will usually receive the response. Let the new process handle that case gracefully. --- src/ejabberd_c2s.erl | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/ejabberd_c2s.erl b/src/ejabberd_c2s.erl index d69599485..74b78512a 100644 --- a/src/ejabberd_c2s.erl +++ b/src/ejabberd_c2s.erl @@ -1318,7 +1318,7 @@ handle_sync_event({resume_session, Time}, _From, _StateName, StateData#state.user, StateData#state.server, StateData#state.resource), - {stop, normal, {ok, StateData}, StateData#state{mgmt_state = resumed}}; + {stop, normal, {resume, StateData}, StateData#state{mgmt_state = resumed}}; handle_sync_event({resume_session, _Time}, _From, StateName, StateData) -> {reply, {error, <<"Previous session not found">>}, StateName, StateData}; @@ -1745,6 +1745,13 @@ handle_info({broadcast, Type, From, Packet}, StateName, StateData) -> fsm_next_state(StateName, StateData); handle_info(dont_ask_offline, StateName, StateData) -> fsm_next_state(StateName, StateData#state{ask_offline = false}); +handle_info({_Ref, {resume, OldStateData}}, StateName, StateData) -> + %% This happens if the resume_session/1 request timed out; the new session + %% now receives the late response. + ?DEBUG("Received old session state for ~s after failed resumption", + [jid:to_string(OldStateData#state.jid)]), + handle_unacked_stanzas(OldStateData#state{mgmt_resend = false}), + fsm_next_state(StateName, StateData); handle_info(Info, StateName, StateData) -> ?ERROR_MSG("Unexpected info: ~p", [Info]), fsm_next_state(StateName, StateData). @@ -3017,7 +3024,7 @@ inherit_session_state(#state{user = U, server = S} = StateData, ResumeID) -> OldPID -> OldSID = {Time, OldPID}, case catch resume_session(OldSID) of - {ok, OldStateData} -> + {resume, OldStateData} -> NewSID = {Time, self()}, % Old time, new PID Priority = case OldStateData#state.pres_last of undefined ->