From 950c20931004dcdf830324901e1b81e793c46b85 Mon Sep 17 00:00:00 2001 From: Evgeny Khramtsov Date: Tue, 6 Aug 2019 16:18:04 +0300 Subject: [PATCH] Report connection error before waiting for resumption In other words don't hide the reason why c2s connection has failed --- src/ejabberd_c2s.erl | 2 +- src/mod_stream_mgmt.erl | 33 ++++++++++++++++++++++----------- 2 files changed, 23 insertions(+), 12 deletions(-) diff --git a/src/ejabberd_c2s.erl b/src/ejabberd_c2s.erl index f0c609eb7..22b723041 100644 --- a/src/ejabberd_c2s.erl +++ b/src/ejabberd_c2s.erl @@ -44,7 +44,7 @@ %% API -export([get_presence/1, set_presence/2, resend_presence/1, resend_presence/2, open_session/1, call/3, cast/2, send/2, close/1, close/2, stop/1, - reply/2, copy_state/2, set_timeout/2, route/2, + reply/2, copy_state/2, set_timeout/2, route/2, format_reason/2, host_up/1, host_down/1, send_ws_ping/1, bounce_message_queue/2]). -include("xmpp.hrl"). diff --git a/src/mod_stream_mgmt.erl b/src/mod_stream_mgmt.erl index ced5424a8..042efc249 100644 --- a/src/mod_stream_mgmt.erl +++ b/src/mod_stream_mgmt.erl @@ -239,8 +239,8 @@ c2s_handle_info(#{mgmt_ack_timer := TRef, jid := JID, mod := Mod} = State, {timeout, TRef, ack_timeout}) -> ?DEBUG("Timed out waiting for stream management acknowledgement of ~s", [jid:encode(JID)]), - State1 = Mod:close(State), - {stop, transition_to_pending(State1)}; + State1 = Mod:close(State, ack_timeout), + {stop, transition_to_pending(State1, ack_timeout)}; c2s_handle_info(#{mgmt_state := pending, lang := Lang, mgmt_pending_timer := TRef, jid := JID, mod := Mod} = State, {timeout, TRef, pending_timeout}) -> @@ -268,8 +268,8 @@ c2s_handle_info(State, _) -> c2s_closed(State, {stream, _}) -> State; -c2s_closed(#{mgmt_state := active} = State, _Reason) -> - {stop, transition_to_pending(State)}; +c2s_closed(#{mgmt_state := active} = State, Reason) -> + {stop, transition_to_pending(State, Reason)}; c2s_closed(State, _Reason) -> State. @@ -439,19 +439,22 @@ handle_resume(#{user := User, lserver := LServer, {error, send(State, El)} end. --spec transition_to_pending(state()) -> state(). +-spec transition_to_pending(state(), _) -> state(). transition_to_pending(#{mgmt_state := active, mod := Mod, - mgmt_timeout := 0} = State) -> + mgmt_timeout := 0} = State, _Reason) -> Mod:stop(State); -transition_to_pending(#{mgmt_state := active, jid := JID, - lserver := LServer, mgmt_timeout := Timeout} = State) -> +transition_to_pending(#{mgmt_state := active, jid := JID, socket := Socket, + lserver := LServer, mgmt_timeout := Timeout} = State, + Reason) -> State1 = cancel_ack_timer(State), - ?INFO_MSG("Waiting ~B seconds for resumption of stream for ~s", - [Timeout div 1000, jid:encode(JID)]), + ?INFO_MSG("(~s) Closing c2s connection for ~s: ~s; " + "waiting ~B seconds for stream resumption", + [xmpp_socket:pp(Socket), jid:encode(JID), + format_reason(State, Reason), Timeout div 1000]), TRef = erlang:start_timer(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) -> +transition_to_pending(State, _Reason) -> State. -spec check_h_attribute(state(), non_neg_integer()) -> state(). @@ -744,6 +747,14 @@ format_error(session_copy_timed_out) -> format_error(invalid_previd) -> ?T("Invalid 'previd' value"). +-spec format_reason(state(), term()) -> binary(). +format_reason(_, ack_timeout) -> + <<"Timed out waiting for stream acknowledgement">>; +format_reason(#{stop_reason := {socket, ack_timeout}} = State, _) -> + format_reason(State, ack_timeout); +format_reason(State, Reason) -> + ejabberd_c2s:format_reason(State, Reason). + -spec log_resumption_error(binary(), binary(), error_reason()) -> ok. log_resumption_error(User, Server, Reason) when Reason == invalid_previd ->