From 41dc1efde444b6911b36304442658cd9b5483e6d Mon Sep 17 00:00:00 2001 From: Holger Weiss Date: Wed, 5 Nov 2014 19:04:02 +0100 Subject: [PATCH] Avoid duplicates of carbon copies When multiple resources have the same (highest) priority, the session manager routes messages sent to their bare JID to each of these resources. When another resource has a lower priority but receives carbon copies, make sure it won't receive multiple copies of such messages. --- src/mod_carboncopy.erl | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/src/mod_carboncopy.erl b/src/mod_carboncopy.erl index a5cbd60d1..1313e341a 100644 --- a/src/mod_carboncopy.erl +++ b/src/mod_carboncopy.erl @@ -167,6 +167,10 @@ remove_connection(User, Server, Resource, _Status)-> send_copies(JID, To, Packet, Direction)-> {U, S, R} = jlib:jid_tolower(JID), PrioRes = ejabberd_sm:get_user_present_resources(U, S), + {MaxPrio, MaxRes} = case catch lists:max(PrioRes) of + {Prio, Res} -> {Prio, Res}; + _ -> {0, undefined} + end, IsBareTo = case {Direction, To} of {received, #jid{lresource = <<>>}} -> true; @@ -180,15 +184,19 @@ send_copies(JID, To, Packet, Direction)-> end, %% list of JIDs that should receive a carbon copy of this message (excluding the %% receiver(s) of the original message - TargetJIDs = if IsBareTo -> - MaxPrio = case catch lists:max(PrioRes) of - {Prio, _Res} -> Prio; - _ -> 0 - end, + TargetJIDs = case {IsBareTo, R} of + {true, MaxRes} -> OrigTo = fun(Res) -> lists:member({MaxPrio, Res}, PrioRes) end, [ {jlib:make_jid({U, S, CCRes}), CC_Version} || {CCRes, CC_Version} <- list(U, S), not OrigTo(CCRes) ]; - true -> + {true, _} -> + %% The message was sent to our bare JID, and we currently have + %% multiple resources with the same highest priority, so the session + %% manager routes the message to each of them. We create carbon + %% copies only from one of those resources (the one where R equals + %% MaxRes) in order to avoid duplicates. + []; + {false, _} -> [ {jlib:make_jid({U, S, CCRes}), CC_Version} || {CCRes, CC_Version} <- list(U, S), CCRes /= R ] %TargetJIDs = lists:delete(JID, [ jlib:make_jid({U, S, CCRes}) || CCRes <- list(U, S) ]),