aboutsummaryrefslogtreecommitdiff
path: root/src/ejabberd_c2s.erl
diff options
context:
space:
mode:
authorHolger Weiss <holger@zedat.fu-berlin.de>2014-03-25 23:23:38 +0100
committerHolger Weiß <holger@zedat.fu-berlin.de>2014-03-25 23:23:38 +0100
commita97c716352c3baec1416f5e0ee303c996bb5900c (patch)
tree5467e575056ef37863369efaca0fa6384f934419 /src/ejabberd_c2s.erl
parentRemove "fun" element from c2s #state (diff)
XEP-0198: Bounce unacked stanzas by default
If the new "resend_on_timeout" option is set to false (which it is by default), bounce any unacknowledged stanzas instead of re-routing them.
Diffstat (limited to 'src/ejabberd_c2s.erl')
-rw-r--r--src/ejabberd_c2s.erl36
1 files changed, 23 insertions, 13 deletions
diff --git a/src/ejabberd_c2s.erl b/src/ejabberd_c2s.erl
index 4955f6e42..0051266c7 100644
--- a/src/ejabberd_c2s.erl
+++ b/src/ejabberd_c2s.erl
@@ -115,6 +115,7 @@
max_ack_queue,
pending_since,
resume_timeout,
+ resend_on_timeout,
n_stanzas_in = 0,
n_stanzas_out = 0,
lang}).
@@ -304,6 +305,7 @@ init([{SockMod, Socket}, Opts]) ->
Timeout when is_integer(Timeout), Timeout >= 0 -> Timeout;
_ -> 300
end,
+ ResendOnTimeout = proplists:get_bool(resend_on_timeout, Opts),
IP = peerip(SockMod, Socket),
%% Check if IP is blacklisted:
case is_ip_blacklisted(IP) of
@@ -328,7 +330,8 @@ init([{SockMod, Socket}, Opts]) ->
access = Access, shaper = Shaper, ip = IP,
sm_state = StreamMgmtState,
max_ack_queue = MaxAckQueue,
- resume_timeout = ResumeTimeout},
+ resume_timeout = ResumeTimeout,
+ resend_on_timeout = ResendOnTimeout},
{ok, wait_for_stream, StateData, ?C2S_OPEN_TIMEOUT}
end.
@@ -1757,7 +1760,7 @@ terminate(_Reason, StateName, StateData) ->
StateData#state.pres_a, Packet),
presence_broadcast(StateData, From,
StateData#state.pres_i, Packet),
- resend_unacked_stanzas(StateData);
+ handle_unacked_stanzas(StateData);
_ ->
?INFO_MSG("(~w) Close session for ~s",
[StateData#state.socket,
@@ -1787,7 +1790,7 @@ terminate(_Reason, StateName, StateData) ->
presence_broadcast(StateData, From,
StateData#state.pres_i, Packet)
end,
- resend_unacked_stanzas(StateData)
+ handle_unacked_stanzas(StateData)
end,
bounce_messages();
true ->
@@ -2714,7 +2717,7 @@ handle_resume(StateData, Attrs) ->
{<<"previd">>, AttrId}],
children = []}),
SendFun = fun(_F, _T, El) -> send_element(NewState, El) end,
- resend_unacked_stanzas(NewState, SendFun),
+ handle_unacked_stanzas(NewState, SendFun),
send_element(NewState,
#xmlel{name = <<"r">>,
attrs = [{<<"xmlns">>, AttrXmlns}],
@@ -2782,33 +2785,40 @@ limit_queue_length(#state{jid = JID,
StateData
end.
-resend_unacked_stanzas(StateData, F) when StateData#state.sm_state == active;
+handle_unacked_stanzas(StateData, F) when StateData#state.sm_state == active;
StateData#state.sm_state == pending ->
Queue = StateData#state.ack_queue,
case queue:len(Queue) of
0 ->
ok;
N ->
- ?INFO_MSG("Resending ~B unacknowledged stanzas to ~s",
+ ?INFO_MSG("~B stanzas were not acknowledged by ~s",
[N, jlib:jid_to_string(StateData#state.jid)]),
lists:foreach(
- fun({Num, #xmlel{attrs = Attrs} = El}) ->
+ fun({_, #xmlel{attrs = Attrs} = El}) ->
From_s = xml:get_attr_s(<<"from">>, Attrs),
From = jlib:string_to_jid(From_s),
To_s = xml:get_attr_s(<<"to">>, Attrs),
To = jlib:string_to_jid(To_s),
- ?DEBUG("Resending unacknowledged stanza #~B from ~s to ~s",
- [Num, From_s, To_s]),
F(From, To, El)
end, queue:to_list(Queue))
end;
-resend_unacked_stanzas(_StateData, _F) ->
+handle_unacked_stanzas(_StateData, _F) ->
ok.
-resend_unacked_stanzas(StateData) when StateData#state.sm_state == active;
+handle_unacked_stanzas(StateData) when StateData#state.sm_state == active;
StateData#state.sm_state == pending ->
- resend_unacked_stanzas(StateData, fun ejabberd_router:route/3);
-resend_unacked_stanzas(_StateData) ->
+ F = case StateData#state.resend_on_timeout of
+ true ->
+ fun ejabberd_router:route/3;
+ false ->
+ fun(From, To, El) ->
+ Err = jlib:make_error_reply(El, ?ERR_SERVICE_UNAVAILABLE),
+ ejabberd_router:route(To, From, Err)
+ end
+ end,
+ handle_unacked_stanzas(StateData, F);
+handle_unacked_stanzas(_StateData) ->
ok.
inherit_session_state(#state{user = U, server = S} = StateData, ResumeID) ->