From 0a9212583dd59535432a10e88aeaec097ae1bd0a Mon Sep 17 00:00:00 2001 From: Holger Weiss Date: Tue, 16 Sep 2014 22:42:34 +0200 Subject: [PATCH] XEP-0198: Support "resend_on_timeout: if_offline" If "resend_on_timeout" is set to "if_offline", resend unacknowledged stanzas only if no other resource is online when the session times out. In other words, allow for sending them to offline storage, but nowhere else. --- doc/guide.tex | 10 +++++++--- src/ejabberd_c2s.erl | 16 ++++++++++++++-- 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/doc/guide.tex b/doc/guide.tex index 27fcfc181..efebc2521 100644 --- a/doc/guide.tex +++ b/doc/guide.tex @@ -1022,7 +1022,7 @@ request_handlers: /"a"/"b": mod_foo /"http-bind": mod_http_bind \end{verbatim} - \titem{resend\_on\_timeout: true|false} + \titem{resend\_on\_timeout: true|false|if\_offline} If \term{stream\_management} is enabled and this option is set to \term{true}, any stanzas that weren't acknowledged by the client will be resent on session timeout. This behavior might often be @@ -1030,8 +1030,12 @@ request_handlers: circumstances. For example, a message that was sent to two resources might get resent to one of them if the other one timed out. Therefore, the default value for this option is \term{false}, which - tells ejabberd to generate an error message instead. The option can - be specified for \term{ejabberd\_c2s} listeners. + tells ejabberd to generate an error message instead. As an + alternative, the option may be set to \term{if\_offline}. In this + case, unacknowledged stanzas are resent only if no other resource is + online when the session times out. Otherwise, error messages are + generated. The option can be specified for \term{ejabberd\_c2s} + listeners. \titem{resume\_timeout: Seconds} This option configures the number of seconds until a session times out if the connection is lost. During this period of time, a client diff --git a/src/ejabberd_c2s.erl b/src/ejabberd_c2s.erl index cb6f9e6d8..d0dfd2553 100644 --- a/src/ejabberd_c2s.erl +++ b/src/ejabberd_c2s.erl @@ -316,7 +316,11 @@ init([{SockMod, Socket}, Opts]) -> Timeout when is_integer(Timeout), Timeout >= 0 -> Timeout; _ -> 300 end, - ResendOnTimeout = proplists:get_bool(resend_on_timeout, Opts), + ResendOnTimeout = case proplists:get_value(resend_on_timeout, Opts) of + Resend when is_boolean(Resend) -> Resend; + if_offline -> if_offline; + _ -> false + end, IP = peerip(SockMod, Socket), Socket1 = if TLSEnabled andalso SockMod /= ejabberd_frontend_socket -> @@ -2879,7 +2883,15 @@ handle_unacked_stanzas(_StateData, _F) -> handle_unacked_stanzas(StateData) when StateData#state.mgmt_state == active; StateData#state.mgmt_state == pending -> - ReRoute = case StateData#state.mgmt_resend of + ResendOnTimeout = + case StateData#state.mgmt_resend of + Resend when is_boolean(Resend) -> + Resend; + if_offline -> + ejabberd_sm:get_user_resources(StateData#state.user, + StateData#state.server) == [] + end, + ReRoute = case ResendOnTimeout of true -> fun ejabberd_router:route/3; false ->