]> granicus.if.org Git - ejabberd/commitdiff
Carbons: Also forward messages sent to bare JIDs
authorHolger Weiss <holger@zedat.fu-berlin.de>
Mon, 7 Apr 2014 20:10:08 +0000 (22:10 +0200)
committerHolger Weiss <holger@zedat.fu-berlin.de>
Mon, 7 Apr 2014 20:10:08 +0000 (22:10 +0200)
Don't ignore messages sent to bare JIDs, but forward them to all
carbon-copy-enabled resources that don't have the highest priority.

src/ejabberd_sm.erl
src/mod_carboncopy.erl

index 2b704d999dfdc711de0321b9f4c670f281b83a5d..a8038a280167ab82efe988b88a2cebeedc4f5028 100644 (file)
@@ -38,6 +38,7 @@
         bounce_offline_message/3,
         disconnect_removed_user/2,
         get_user_resources/2,
+        get_user_present_resources/2,
         set_presence/7,
         unset_presence/6,
         close_session_unset_presence/5,
@@ -167,6 +168,20 @@ get_user_resources(User, Server) ->
            [element(3, S#session.usr) || S <- clean_session_list(Ss)]
     end.
 
+-spec get_user_present_resources(binary(), binary()) -> [tuple()].
+
+get_user_present_resources(LUser, LServer) ->
+    US = {LUser, LServer},
+    case catch mnesia:dirty_index_read(session, US,
+                                      #session.us)
+       of
+      {'EXIT', _Reason} -> [];
+      Ss ->
+         [{S#session.priority, element(3, S#session.usr)}
+          || S <- clean_session_list(Ss),
+             is_integer(S#session.priority)]
+    end.
+
 -spec get_user_ip(binary(), binary(), binary()) -> ip().
 
 get_user_ip(User, Server, Resource) ->
@@ -670,20 +685,6 @@ clean_session_list([S1, S2 | Rest], Res) ->
 
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
-get_user_present_resources(LUser, LServer) ->
-    US = {LUser, LServer},
-    case catch mnesia:dirty_index_read(session, US,
-                                      #session.us)
-       of
-      {'EXIT', _Reason} -> [];
-      Ss ->
-         [{S#session.priority, element(3, S#session.usr)}
-          || S <- clean_session_list(Ss),
-             is_integer(S#session.priority)]
-    end.
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
 %% On new session, check if some existing connections need to be replace
 check_for_sessions_to_replace(User, Server, Resource) ->
     LUser = jlib:nodeprep(User),
index d31791cd59c84c9e15ccd67aa2eeed8a40a7092d..6a5c8870670a09ed44f113e6e01b2c732bcdec20 100644 (file)
@@ -128,23 +128,18 @@ iq_handler(From, _To,  #iq{type=set, sub_el = #xmlel{name = Operation, children
 iq_handler(_From, _To, IQ, _CC)->
     IQ#iq{type=error, sub_el = [?ERR_NOT_ALLOWED]}.
 
-user_send_packet(From, _To, Packet) ->
-    check_and_forward(From, Packet, sent).
+user_send_packet(From, To, Packet) ->
+    check_and_forward(From, To, Packet, sent).
 
-%% Only make carbon copies if the original destination was not a bare jid. 
-%% If the original destination was a bare jid, the message is going to be delivered to all
-%% connected resources anyway. Avoid duplicate delivery. "XEP-0280 : 3.5 Receiving Messages"
-user_receive_packet(JID, _From, #jid{resource=Resource} = _To, Packet) when Resource /= <<>> ->
-    check_and_forward(JID, Packet, received);
-user_receive_packet(_JID, _From, _To, _Packet) ->
-       ok.
+user_receive_packet(JID, _From, To, Packet) ->
+    check_and_forward(JID, To, Packet, received).
     
 % verifier si le trafic est local
 % Modified from original version: 
 %    - registered to the user_send_packet hook, to be called only once even for multicast
 %    - do not support "private" message mode, and do not modify the original packet in any way
 %    - we also replicate "read" notifications
-check_and_forward(JID, #xmlel{name = <<"message">>, attrs = Attrs} = Packet, Direction)->
+check_and_forward(JID, To, #xmlel{name = <<"message">>, attrs = Attrs} = Packet, Direction)->
     case xml:get_attr_s(<<"type">>, Attrs) of 
       <<"chat">> ->
        case xml:get_subtag(Packet, <<"private">>) of
@@ -155,11 +150,11 @@ check_and_forward(JID, #xmlel{name = <<"message">>, attrs = Attrs} = Packet, Dir
                        %% receiving message back to original sender.
                        SubTag = xml:get_subtag(Packet,<<"sent">>),
                        if SubTag == false ->
-                            send_copies(JID, Packet, Direction);
+                            send_copies(JID, To, Packet, Direction);
                                   true ->
                             case xml:get_subtag(SubTag,<<"forwarded">>) of
                                 false->
-                                    send_copies(JID, Packet, Direction);
+                                    send_copies(JID, To, Packet, Direction);
                                 _ ->
                                     stop
                             end
@@ -175,7 +170,7 @@ check_and_forward(JID, #xmlel{name = <<"message">>, attrs = Attrs} = Packet, Dir
        ok
     end;
  
-check_and_forward(_JID, _Packet, _)-> ok.
+check_and_forward(_JID, _To, _Packet, _)-> ok.
 
 remove_connection(User, Server, Resource, _Status)->
     disable(Server, User, Resource),
@@ -184,14 +179,26 @@ remove_connection(User, Server, Resource, _Status)->
 
 %%% Internal
 %% Direction = received | sent <received xmlns='urn:xmpp:carbons:1'/>
-send_copies(JID, Packet, Direction)->
+send_copies(JID, To, Packet, Direction)->
     {U, S, R} = jlib:jid_tolower(JID),
 
     %% list of JIDs that should receive a carbon copy of this message (excluding the
-    %% receiver of the original message
-    TargetJIDs = [ {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) ]),
-
+    %% receiver(s) of the original message
+    TargetJIDs = case {Direction, To} of
+       {received, #jid{resource = <<>>}} ->
+           PrioRes = ejabberd_sm:get_user_present_resources(U, S),
+           MaxPrio = case catch lists:max(PrioRes) of
+               {Prio, _Res} -> Prio;
+               _ -> 0
+           end,
+           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) ];
+       _ ->
+           [ {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) ]),
+    end,
 
     lists:map(fun({Dest,Version}) ->
                    {_, _, Resource} = jlib:jid_tolower(Dest),