mirror of
https://github.com/processone/ejabberd.git
synced 2024-12-22 17:28:25 +01:00
Use multicast routing for more packets generated by muc
This commit is contained in:
parent
2e2667bbd7
commit
0de6f1c538
@ -880,7 +880,7 @@ get_priority_from_presence(#presence{priority = Prio}) ->
|
||||
-spec route_multiple(state(), [jid()], stanza()) -> ok.
|
||||
route_multiple(#{lserver := LServer}, JIDs, Pkt) ->
|
||||
From = xmpp:get_from(Pkt),
|
||||
ejabberd_router_multicast:route_multicast(From, LServer, JIDs, Pkt).
|
||||
ejabberd_router_multicast:route_multicast(From, LServer, JIDs, Pkt, false).
|
||||
|
||||
get_subscription(#jid{luser = LUser, lserver = LServer}, JID) ->
|
||||
{Subscription, _, _} = ejabberd_hooks:run_fold(
|
||||
|
@ -30,7 +30,7 @@
|
||||
-behaviour(gen_server).
|
||||
|
||||
%% API
|
||||
-export([route_multicast/4,
|
||||
-export([route_multicast/5,
|
||||
register_route/1,
|
||||
unregister_route/1
|
||||
]).
|
||||
@ -58,9 +58,11 @@
|
||||
start_link() ->
|
||||
gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).
|
||||
|
||||
-spec route_multicast(jid(), binary(), [jid()], stanza()) -> ok.
|
||||
route_multicast(From, Domain, Destinations, Packet) ->
|
||||
case catch do_route(Domain, Destinations, xmpp:set_from(Packet, From)) of
|
||||
-spec route_multicast(jid(), binary(), [jid()], stanza(), boolean()) -> ok.
|
||||
route_multicast(From0, Domain0, Destinations0, Packet0, Wrapped0) ->
|
||||
{From, Domain, Destinations, Packet, Wrapped} =
|
||||
ejabberd_hooks:run_fold(multicast_route, {From0, Domain0, Destinations0, Packet0, Wrapped0}, []),
|
||||
case catch do_route(Domain, Destinations, xmpp:set_from(Packet, From), Wrapped) of
|
||||
{'EXIT', Reason} ->
|
||||
?ERROR_MSG("~p~nwhen processing: ~p",
|
||||
[Reason, {From, Domain, Destinations, Packet}]);
|
||||
@ -157,7 +159,7 @@ handle_cast(Msg, State) ->
|
||||
%% Description: Handling all non call/cast messages
|
||||
%%--------------------------------------------------------------------
|
||||
handle_info({route_multicast, Domain, Destinations, Packet}, State) ->
|
||||
case catch do_route(Domain, Destinations, Packet) of
|
||||
case catch do_route(Domain, Destinations, Packet, false) of
|
||||
{'EXIT', Reason} ->
|
||||
?ERROR_MSG("~p~nwhen processing: ~p",
|
||||
[Reason, {Domain, Destinations, Packet}]);
|
||||
@ -204,13 +206,41 @@ terminate(_Reason, _State) ->
|
||||
code_change(_OldVsn, State, _Extra) ->
|
||||
{ok, State}.
|
||||
|
||||
-spec update_to_in_wrapped(stanza(), jid()) -> stanza().
|
||||
update_to_in_wrapped(Packet, To) ->
|
||||
case Packet of
|
||||
#message{sub_els = [#ps_event{
|
||||
items = #ps_items{
|
||||
items = [#ps_item{
|
||||
sub_els = [Internal]
|
||||
} = PSItem]
|
||||
} = PSItems
|
||||
} = PSEvent]} ->
|
||||
Internal2 = xmpp:set_to(Internal, To),
|
||||
PSItem2 = PSItem#ps_item{sub_els = Internal2},
|
||||
PSItems2 = PSItems#ps_items{items = PSItem2},
|
||||
PSEvent2 = PSEvent#ps_event{items = PSItems2},
|
||||
Packet#message{sub_els = [PSEvent2]};
|
||||
_ ->
|
||||
Packet
|
||||
end.
|
||||
|
||||
%%--------------------------------------------------------------------
|
||||
%%% Internal functions
|
||||
%%--------------------------------------------------------------------
|
||||
%% From = #jid
|
||||
%% Destinations = [#jid]
|
||||
-spec do_route(binary(), [jid()], stanza()) -> any().
|
||||
do_route(Domain, Destinations, Packet) ->
|
||||
-spec do_route(binary(), [jid()], stanza(), boolean()) -> any().
|
||||
do_route(Domain, Destinations, Packet, true) ->
|
||||
?DEBUG("Route multicast:~n~ts~nDomain: ~ts~nDestinations: ~ts~n",
|
||||
[xmpp:pp(Packet), Domain,
|
||||
str:join([jid:encode(To) || To <- Destinations], <<", ">>)]),
|
||||
lists:foreach(
|
||||
fun(To) ->
|
||||
Packet2 = update_to_in_wrapped(Packet, To),
|
||||
ejabberd_router:route(Packet2)
|
||||
end, Destinations);
|
||||
do_route(Domain, Destinations, Packet, false) ->
|
||||
?DEBUG("Route multicast:~n~ts~nDomain: ~ts~nDestinations: ~ts~n",
|
||||
[xmpp:pp(Packet), Domain,
|
||||
str:join([jid:encode(To) || To <- Destinations], <<", ">>)]),
|
||||
@ -236,4 +266,7 @@ pick_multicast_pid(Rs) ->
|
||||
|
||||
-spec do_route_normal([jid()], stanza()) -> any().
|
||||
do_route_normal(Destinations, Packet) ->
|
||||
[ejabberd_router:route(xmpp:set_to(Packet, To)) || To <- Destinations].
|
||||
lists:foreach(
|
||||
fun(To) ->
|
||||
ejabberd_router:route(xmpp:set_to(Packet, To))
|
||||
end, Destinations).
|
||||
|
@ -4624,37 +4624,55 @@ store_room_no_checks(StateData, ChangesHints) ->
|
||||
|
||||
-spec send_subscriptions_change_notifications(jid(), binary(), subscribe|unsubscribe, state()) -> ok.
|
||||
send_subscriptions_change_notifications(From, Nick, Type, State) ->
|
||||
maps:fold(fun(_, #subscriber{nodes = Nodes, jid = JID}, _) ->
|
||||
case lists:member(?NS_MUCSUB_NODES_SUBSCRIBERS, Nodes) of
|
||||
{WJ, WN} =
|
||||
maps:fold(
|
||||
fun({WithJid, WithNick} = Res, #subscriber{nodes = Nodes, jid = JID}, _) ->
|
||||
case lists:member(?NS_MUCSUB_NODES_SUBSCRIBERS, Nodes) of
|
||||
true ->
|
||||
case (State#state.config)#config.anonymous == false orelse
|
||||
get_role(JID, State) == moderator orelse
|
||||
get_default_role(get_affiliation(JID, State), State) == moderator of
|
||||
true ->
|
||||
ShowJid = case (State#state.config)#config.anonymous == false orelse
|
||||
get_role(JID, State) == moderator orelse
|
||||
get_default_role(get_affiliation(JID, State), State) == moderator of
|
||||
true -> true;
|
||||
_ -> false
|
||||
end,
|
||||
Payload = case {Type, ShowJid} of
|
||||
{subscribe, true} ->
|
||||
#muc_subscribe{jid = From, nick = Nick};
|
||||
{subscribe, _} ->
|
||||
#muc_subscribe{nick = Nick};
|
||||
{unsubscribe, true} ->
|
||||
#muc_unsubscribe{jid = From, nick = Nick};
|
||||
{unsubscribe, _} ->
|
||||
#muc_unsubscribe{nick = Nick}
|
||||
end,
|
||||
Packet = #message{
|
||||
sub_els = [#ps_event{
|
||||
items = #ps_items{
|
||||
node = ?NS_MUCSUB_NODES_SUBSCRIBERS,
|
||||
items = [#ps_item{
|
||||
id = p1_rand:get_string(),
|
||||
sub_els = [Payload]}]}}]},
|
||||
ejabberd_router:route(xmpp:set_from_to(Packet, State#state.jid, JID));
|
||||
false ->
|
||||
ok
|
||||
end
|
||||
end, ok, State#state.subscribers).
|
||||
{[JID | WithJid], WithNick};
|
||||
_ ->
|
||||
{WithJid, [JID | WithNick]}
|
||||
end;
|
||||
false ->
|
||||
Res
|
||||
end
|
||||
end, ok, State#state.subscribers),
|
||||
if WJ /= [] ->
|
||||
Payload1 = case Type of
|
||||
subscribe -> #muc_subscribe{jid = From, nick = Nick};
|
||||
_ -> #muc_unsubscribe{jid = From, nick = Nick}
|
||||
end,
|
||||
Packet1 = #message{
|
||||
sub_els = [#ps_event{
|
||||
items = #ps_items{
|
||||
node = ?NS_MUCSUB_NODES_SUBSCRIBERS,
|
||||
items = [#ps_item{
|
||||
id = p1_rand:get_string(),
|
||||
sub_els = [Payload1]}]}}]},
|
||||
ejabberd_router_multicast:route_multicast(State#state.jid, State#state.server_host,
|
||||
WJ, Packet1, true);
|
||||
true -> ok
|
||||
end,
|
||||
if WN /= [] ->
|
||||
Payload2 = case Type of
|
||||
subscribe -> #muc_subscribe{nick = Nick};
|
||||
_ -> #muc_unsubscribe{nick = Nick}
|
||||
end,
|
||||
Packet2 = #message{
|
||||
sub_els = [#ps_event{
|
||||
items = #ps_items{
|
||||
node = ?NS_MUCSUB_NODES_SUBSCRIBERS,
|
||||
items = [#ps_item{
|
||||
id = p1_rand:get_string(),
|
||||
sub_els = [Payload2]}]}}]},
|
||||
ejabberd_router_multicast:route_multicast(State#state.jid, State#state.server_host,
|
||||
WN, Packet2, true);
|
||||
true -> ok
|
||||
end.
|
||||
|
||||
-spec send_wrapped(jid(), jid(), stanza(), binary(), state()) -> ok.
|
||||
send_wrapped(From, To, Packet, Node, State) ->
|
||||
@ -4727,10 +4745,70 @@ wrap(From, To, Packet, Node, Id) ->
|
||||
|
||||
-spec send_wrapped_multiple(jid(), users(), stanza(), binary(), state()) -> ok.
|
||||
send_wrapped_multiple(From, Users, Packet, Node, State) ->
|
||||
{Dir, Wra} =
|
||||
maps:fold(
|
||||
fun(_, #user{jid = To}, _) ->
|
||||
send_wrapped(From, To, Packet, Node, State)
|
||||
end, ok, Users).
|
||||
fun(_, #user{jid = To, last_presence = LP}, {Direct, Wrapped} = Res) ->
|
||||
IsOffline = LP == undefined,
|
||||
if IsOffline ->
|
||||
LBareTo = jid:tolower(jid:remove_resource(To)),
|
||||
case maps:find(LBareTo, State#state.subscribers) of
|
||||
{ok, #subscriber{nodes = Nodes}} ->
|
||||
case lists:member(Node, Nodes) of
|
||||
true ->
|
||||
{Direct, [To | Wrapped]};
|
||||
_ ->
|
||||
Res
|
||||
end;
|
||||
_ ->
|
||||
Res
|
||||
end;
|
||||
true ->
|
||||
{[To | Direct], Wrapped}
|
||||
end
|
||||
end, {[],[]}, Users),
|
||||
case Dir of
|
||||
[] -> ok;
|
||||
_ ->
|
||||
case Packet of
|
||||
#presence{type = unavailable} ->
|
||||
case xmpp:get_subtag(Packet, #muc_user{}) of
|
||||
#muc_user{destroy = Destroy,
|
||||
status_codes = Codes} ->
|
||||
case Destroy /= undefined orelse
|
||||
(lists:member(110,Codes) andalso
|
||||
not lists:member(303, Codes)) of
|
||||
true ->
|
||||
ejabberd_router_multicast:route_multicast(
|
||||
State#state.jid, State#state.server_host, Dir,
|
||||
#presence{id = p1_rand:get_string(),
|
||||
type = unavailable}, false);
|
||||
false ->
|
||||
ok
|
||||
end;
|
||||
_ ->
|
||||
false
|
||||
end;
|
||||
_ ->
|
||||
ok
|
||||
end,
|
||||
ejabberd_router_multicast:route_multicast(State#state.jid, State#state.server_host,
|
||||
Dir, Packet, false)
|
||||
end,
|
||||
case Wra of
|
||||
[] -> ok;
|
||||
_ ->
|
||||
MamEnabled = (State#state.config)#config.mam,
|
||||
Id = case xmpp:get_subtag(Packet, #stanza_id{by = #jid{}}) of
|
||||
#stanza_id{id = Id2} ->
|
||||
Id2;
|
||||
_ ->
|
||||
p1_rand:get_string()
|
||||
end,
|
||||
NewPacket = wrap(From, State#state.jid, Packet, Node, Id),
|
||||
NewPacket2 = xmpp:put_meta(NewPacket, in_muc_mam, MamEnabled),
|
||||
ejabberd_router_multicast:route_multicast(State#state.jid, State#state.server_host,
|
||||
Wra, NewPacket2, true)
|
||||
end.
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
%% Detect messange stanzas that don't have meaningful content
|
||||
|
Loading…
Reference in New Issue
Block a user