]> granicus.if.org Git - ejabberd/commitdiff
Avoid duplicates of carbon copies
authorHolger Weiss <holger@zedat.fu-berlin.de>
Wed, 5 Nov 2014 18:04:02 +0000 (19:04 +0100)
committerHolger Weiss <holger@zedat.fu-berlin.de>
Wed, 5 Nov 2014 18:04:02 +0000 (19:04 +0100)
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

index a5cbd60d1dc97e17fb1c687916ae2f809171d9a4..1313e341a9fa5dbcb80e8b1d57b7e39fe7b1a0fd 100644 (file)
@@ -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) ]),