From 830fdccd21c3a4b25b319ba0c33a14d14c42a25e Mon Sep 17 00:00:00 2001 From: Holger Weiss Date: Fri, 14 Nov 2014 01:03:26 +0100 Subject: [PATCH] Don't broadcast last published PEP items 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 | 24 ++++++++++++++++++++++++ src/mod_caps.erl | 22 +++++++++++++++++++++- src/mod_pubsub.erl | 11 ++++++----- src/mod_pubsub_odbc.erl | 11 ++++++----- 4 files changed, 57 insertions(+), 11 deletions(-) diff --git a/src/ejabberd_c2s.erl b/src/ejabberd_c2s.erl index 72ebdb5b0..bbde72745 100644 --- a/src/ejabberd_c2s.erl +++ b/src/ejabberd_c2s.erl @@ -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, diff --git a/src/mod_caps.erl b/src/mod_caps.erl index bad949c1d..1002df444 100644 --- a/src/mod_caps.erl +++ b/src/mod_caps.erl @@ -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, diff --git a/src/mod_pubsub.erl b/src/mod_pubsub.erl index 0cd84fd2f..c34b1583c 100644 --- a/src/mod_pubsub.erl +++ b/src/mod_pubsub.erl @@ -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, <>}, + service_jid(From), jlib:make_jid(To), + Stanza) _ -> ok end; dispatch_items(From, To, _Node, Stanza) -> diff --git a/src/mod_pubsub_odbc.erl b/src/mod_pubsub_odbc.erl index 821add288..8edd1250b 100644 --- a/src/mod_pubsub_odbc.erl +++ b/src/mod_pubsub_odbc.erl @@ -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, <>}, + service_jid(From), jlib:make_jid(To), + Stanza) _ -> ok end; dispatch_items(From, To, _Node, Stanza) -> -- 2.50.1