diff options
author | Holger Weiss <holger@zedat.fu-berlin.de> | 2014-04-07 21:21:11 +0200 |
---|---|---|
committer | Holger Weiß <holger@zedat.fu-berlin.de> | 2014-04-07 21:21:11 +0200 |
commit | c114eb373650d270082e81406f13db035de33385 (patch) | |
tree | 17eb593f3b11eac2466e93edcbe23b872ea1a1df /src/ejabberd_c2s.erl | |
parent | XEP-0198: Bounce unacked stanzas by default (diff) |
XEP-0198: Don't bounce/resend forwarded messages
On connection timeout, drop any messages that were forwarded by some
encapsulating protocol, such as XEP-0280 carbon copies or XEP-0313
archive messages. Bouncing or resending them could easily lead to
unexpected results.
Diffstat (limited to 'src/ejabberd_c2s.erl')
-rw-r--r-- | src/ejabberd_c2s.erl | 60 |
1 files changed, 52 insertions, 8 deletions
diff --git a/src/ejabberd_c2s.erl b/src/ejabberd_c2s.erl index 0051266c7..17b54e3c5 100644 --- a/src/ejabberd_c2s.erl +++ b/src/ejabberd_c2s.erl @@ -2808,19 +2808,63 @@ handle_unacked_stanzas(_StateData, _F) -> handle_unacked_stanzas(StateData) when StateData#state.sm_state == active; StateData#state.sm_state == pending -> - 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 + ReRoute = 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, + F = fun(From, To, El) -> + %% We'll drop the stanza if it was <forwarded/> by some + %% encapsulating protocol as per XEP-0297. One such protocol is + %% XEP-0280, which says: "When a receiving server attempts to + %% deliver a forked message, and that message bounces with an + %% error for any reason, the receiving server MUST NOT forward + %% that error back to the original sender." Resending such a + %% stanza could easily lead to unexpected results as well. + case is_encapsulated_forward(El) of + true -> + ?DEBUG("Dropping forwarded stanza from ~s", + [xml:get_attr_s(<<"from">>, El#xmlel.attrs)]); + false -> + ReRoute(From, To, El) + end end, handle_unacked_stanzas(StateData, F); handle_unacked_stanzas(_StateData) -> ok. +is_encapsulated_forward(#xmlel{name = <<"message">>} = El) -> + SubTag = case {xml:get_subtag(El, <<"sent">>), + xml:get_subtag(El, <<"received">>), + xml:get_subtag(El, <<"result">>)} of + {false, false, false} -> + false; + {Tag, false, false} -> + Tag; + {false, Tag, false} -> + Tag; + {_, _, Tag} -> + Tag + end, + if SubTag == false -> + false; + true -> + case xml:get_subtag(SubTag, <<"forwarded">>) of + false -> + false; + _ -> + true + end + end; +is_encapsulated_forward(_El) -> + false. + inherit_session_state(#state{user = U, server = S} = StateData, ResumeID) -> case jlib:base64_to_term(ResumeID) of {term, {U, S, R, Time}} -> |