]> granicus.if.org Git - ejabberd/commitdiff
Don't broadcast last published PEP items
authorHolger Weiss <holger@zedat.fu-berlin.de>
Fri, 14 Nov 2014 00:03:26 +0000 (01:03 +0100)
committerHolger Weiss <holger@zedat.fu-berlin.de>
Fri, 14 Nov 2014 00:03:26 +0000 (01:03 +0100)
When a client becomes available, don't send the last published PEP items
of all his peers to all his other peers, but only to that client.

src/ejabberd_c2s.erl
src/mod_caps.erl
src/mod_pubsub.erl
src/mod_pubsub_odbc.erl

index 72ebdb5b0d474b05286472f09461d2d92a940877..bbde72745e8927338a27179b958231212a1e9cb3 100644 (file)
@@ -45,6 +45,7 @@
         set_aux_field/3,
         del_aux_field/2,
         get_subscription/2,
+        send_filtered/5,
         broadcast/4,
         get_subscribed/1,
          transform_listen_option/2]).
@@ -247,6 +248,9 @@ get_subscription(LFrom, StateData) ->
        true -> none
     end.
 
+send_filtered(FsmRef, Feature, From, To, Packet) ->
+    FsmRef ! {send_filtered, Feature, From, To, Packet}.
+
 broadcast(FsmRef, Type, From, Packet) ->
     FsmRef ! {broadcast, Type, From, Packet}.
 
@@ -1738,6 +1742,26 @@ handle_info({force_update_presence, LUser}, StateName,
                     _ -> StateData
                   end,
     fsm_next_state(StateName, NewStateData);
+handle_info({send_filtered, Feature, From, To, Packet}, StateName, StateData) ->
+    Drop = ejabberd_hooks:run_fold(c2s_filter_packet, StateData#state.server,
+                                  true, [StateData#state.server, StateData,
+                                         Feature, To, Packet]),
+    NewStateData = if Drop ->
+                         ?DEBUG("Dropping packet from ~p to ~p",
+                                [jlib:jid_to_string(From),
+                                 jlib:jid_to_string(To)]),
+                         StateData;
+                     true ->
+                         FinalPacket = jlib:replace_from_to(From, To, Packet),
+                         case StateData#state.jid of
+                           To ->
+                               send_packet(StateData, FinalPacket);
+                           _ ->
+                               ejabberd_router:route(From, To, FinalPacket),
+                               StateData
+                         end
+                  end,
+    fsm_next_state(StateName, NewStateData);
 handle_info({broadcast, Type, From, Packet}, StateName, StateData) ->
     Recipients = ejabberd_hooks:run_fold(
                   c2s_broadcast_recipients, StateData#state.server,
index bad949c1d2a08bf0ba707b7b5648fe4629774fde..1002df444e2822f3c50e736d486c691bd11cd5bb 100644 (file)
@@ -48,7 +48,8 @@
 
 %% hook handlers
 -export([user_send_packet/3, user_receive_packet/4,
-        c2s_presence_in/2, c2s_broadcast_recipients/6]).
+        c2s_presence_in/2, c2s_filter_packet/6,
+        c2s_broadcast_recipients/6]).
 
 -include("ejabberd.hrl").
 -include("logger.hrl").
@@ -266,6 +267,21 @@ c2s_presence_in(C2SState,
        true -> C2SState
     end.
 
+c2s_filter_packet(InAcc, Host, C2SState, {pep_message, Feature}, To, _Packet) ->
+    case ejabberd_c2s:get_aux_field(caps_resources, C2SState) of
+      {ok, Rs} ->
+         LTo = jlib:jid_tolower(To),
+         case gb_trees:lookup(LTo, Rs) of
+           {value, Caps} ->
+               Drop = not lists:member(Feature, get_features(Host, Caps)),
+               {stop, Drop};
+           none ->
+               {stop, true}
+         end;
+      _ -> InAcc
+    end;
+c2s_filter_packet(Acc, _, _, _, _, _) -> Acc.
+
 c2s_broadcast_recipients(InAcc, Host, C2SState,
                         {pep_message, Feature}, _From, _Packet) ->
     case ejabberd_c2s:get_aux_field(caps_resources,
@@ -317,6 +333,8 @@ init([Host, Opts]) ->
                  [{max_size, MaxSize}, {life_time, LifeTime}]),
     ejabberd_hooks:add(c2s_presence_in, Host, ?MODULE,
                       c2s_presence_in, 75),
+    ejabberd_hooks:add(c2s_filter_packet, Host, ?MODULE,
+                      c2s_filter_packet, 75),
     ejabberd_hooks:add(c2s_broadcast_recipients, Host,
                       ?MODULE, c2s_broadcast_recipients, 75),
     ejabberd_hooks:add(user_send_packet, Host, ?MODULE,
@@ -348,6 +366,8 @@ terminate(_Reason, State) ->
     Host = State#state.host,
     ejabberd_hooks:delete(c2s_presence_in, Host, ?MODULE,
                          c2s_presence_in, 75),
+    ejabberd_hooks:delete(c2s_filter_packet, Host, ?MODULE,
+                         c2s_filter_packet, 75),
     ejabberd_hooks:delete(c2s_broadcast_recipients, Host,
                          ?MODULE, c2s_broadcast_recipients, 75),
     ejabberd_hooks:delete(user_send_packet, Host, ?MODULE,
index 0cd84fd2f476fa0ddbe82d9d1eed56971d0c671b..c34b1583c5acec3a3204feeaf2ae7fd3de1889dd 100644 (file)
@@ -3367,12 +3367,13 @@ send_items(Host, Node, NodeId, Type, LJID, Number) ->
 ).
 
 dispatch_items(_From, _To, _Node, _Stanza = undefined) -> ok;
-dispatch_items(From, {U, S, R}, Node, Stanza) when is_tuple(From) ->
-    case ejabberd_sm:get_session_pid(U, S, R) of
+dispatch_items(From, {ToU, ToS, ToR} = To, Node, Stanza) ->
+    case ejabberd_sm:get_session_pid(ToU, ToS, ToR) of
       C2SPid when is_pid(C2SPid) ->
-         ejabberd_c2s:broadcast(C2SPid,
-                                {pep_message, <<((Node))/binary, "+notify">>},
-                                service_jid(From), Stanza);
+         ejabberd_c2s:send_filtered(C2SPid,
+                                    {pep_message, <<Node/binary, "+notify">>},
+                                    service_jid(From), jlib:make_jid(To),
+                                    Stanza)
       _ -> ok
     end;
 dispatch_items(From, To, _Node, Stanza) ->
index 821add288039d8a76be619afafb5d5a5d7824399..8edd1250ba200c17e4f32c4c5221d2a3f2a1d025 100644 (file)
@@ -3052,12 +3052,13 @@ send_items(Host, Node, NodeId, Type, LJID, Number) ->
 ).
 
 dispatch_items(_From, _To, _Node, _Stanza = undefined) -> ok;
-dispatch_items(From, {U, S, R}, Node, Stanza) when is_tuple(From) ->
-    case ejabberd_sm:get_session_pid(U, S, R) of
+dispatch_items(From, {ToU, ToS, ToR} = To, Node, Stanza) ->
+    case ejabberd_sm:get_session_pid(ToU, ToS, ToR) of
       C2SPid when is_pid(C2SPid) ->
-         ejabberd_c2s:broadcast(C2SPid,
-                                {pep_message, <<((Node))/binary, "+notify">>},
-                                service_jid(From), Stanza);
+         ejabberd_c2s:send_filtered(C2SPid,
+                                    {pep_message, <<Node/binary, "+notify">>},
+                                    service_jid(From), jlib:make_jid(To),
+                                    Stanza)
       _ -> ok
     end;
 dispatch_items(From, To, _Node, Stanza) ->