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.
|
-spec route_multiple(state(), [jid()], stanza()) -> ok.
|
||||||
route_multiple(#{lserver := LServer}, JIDs, Pkt) ->
|
route_multiple(#{lserver := LServer}, JIDs, Pkt) ->
|
||||||
From = xmpp:get_from(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) ->
|
get_subscription(#jid{luser = LUser, lserver = LServer}, JID) ->
|
||||||
{Subscription, _, _} = ejabberd_hooks:run_fold(
|
{Subscription, _, _} = ejabberd_hooks:run_fold(
|
||||||
|
|
|
@ -30,7 +30,7 @@
|
||||||
-behaviour(gen_server).
|
-behaviour(gen_server).
|
||||||
|
|
||||||
%% API
|
%% API
|
||||||
-export([route_multicast/4,
|
-export([route_multicast/5,
|
||||||
register_route/1,
|
register_route/1,
|
||||||
unregister_route/1
|
unregister_route/1
|
||||||
]).
|
]).
|
||||||
|
@ -58,9 +58,11 @@
|
||||||
start_link() ->
|
start_link() ->
|
||||||
gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).
|
gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).
|
||||||
|
|
||||||
-spec route_multicast(jid(), binary(), [jid()], stanza()) -> ok.
|
-spec route_multicast(jid(), binary(), [jid()], stanza(), boolean()) -> ok.
|
||||||
route_multicast(From, Domain, Destinations, Packet) ->
|
route_multicast(From0, Domain0, Destinations0, Packet0, Wrapped0) ->
|
||||||
case catch do_route(Domain, Destinations, xmpp:set_from(Packet, From)) of
|
{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} ->
|
{'EXIT', Reason} ->
|
||||||
?ERROR_MSG("~p~nwhen processing: ~p",
|
?ERROR_MSG("~p~nwhen processing: ~p",
|
||||||
[Reason, {From, Domain, Destinations, Packet}]);
|
[Reason, {From, Domain, Destinations, Packet}]);
|
||||||
|
@ -157,7 +159,7 @@ handle_cast(Msg, State) ->
|
||||||
%% Description: Handling all non call/cast messages
|
%% Description: Handling all non call/cast messages
|
||||||
%%--------------------------------------------------------------------
|
%%--------------------------------------------------------------------
|
||||||
handle_info({route_multicast, Domain, Destinations, Packet}, State) ->
|
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} ->
|
{'EXIT', Reason} ->
|
||||||
?ERROR_MSG("~p~nwhen processing: ~p",
|
?ERROR_MSG("~p~nwhen processing: ~p",
|
||||||
[Reason, {Domain, Destinations, Packet}]);
|
[Reason, {Domain, Destinations, Packet}]);
|
||||||
|
@ -204,13 +206,41 @@ terminate(_Reason, _State) ->
|
||||||
code_change(_OldVsn, State, _Extra) ->
|
code_change(_OldVsn, State, _Extra) ->
|
||||||
{ok, State}.
|
{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
|
%%% Internal functions
|
||||||
%%--------------------------------------------------------------------
|
%%--------------------------------------------------------------------
|
||||||
%% From = #jid
|
%% From = #jid
|
||||||
%% Destinations = [#jid]
|
%% Destinations = [#jid]
|
||||||
-spec do_route(binary(), [jid()], stanza()) -> any().
|
-spec do_route(binary(), [jid()], stanza(), boolean()) -> any().
|
||||||
do_route(Domain, Destinations, Packet) ->
|
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",
|
?DEBUG("Route multicast:~n~ts~nDomain: ~ts~nDestinations: ~ts~n",
|
||||||
[xmpp:pp(Packet), Domain,
|
[xmpp:pp(Packet), Domain,
|
||||||
str:join([jid:encode(To) || To <- Destinations], <<", ">>)]),
|
str:join([jid:encode(To) || To <- Destinations], <<", ">>)]),
|
||||||
|
@ -236,4 +266,7 @@ pick_multicast_pid(Rs) ->
|
||||||
|
|
||||||
-spec do_route_normal([jid()], stanza()) -> any().
|
-spec do_route_normal([jid()], stanza()) -> any().
|
||||||
do_route_normal(Destinations, Packet) ->
|
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.
|
-spec send_subscriptions_change_notifications(jid(), binary(), subscribe|unsubscribe, state()) -> ok.
|
||||||
send_subscriptions_change_notifications(From, Nick, Type, State) ->
|
send_subscriptions_change_notifications(From, Nick, Type, State) ->
|
||||||
maps:fold(fun(_, #subscriber{nodes = Nodes, jid = JID}, _) ->
|
{WJ, WN} =
|
||||||
case lists:member(?NS_MUCSUB_NODES_SUBSCRIBERS, Nodes) of
|
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 ->
|
true ->
|
||||||
ShowJid = case (State#state.config)#config.anonymous == false orelse
|
{[JID | WithJid], WithNick};
|
||||||
get_role(JID, State) == moderator orelse
|
_ ->
|
||||||
get_default_role(get_affiliation(JID, State), State) == moderator of
|
{WithJid, [JID | WithNick]}
|
||||||
true -> true;
|
end;
|
||||||
_ -> false
|
false ->
|
||||||
end,
|
Res
|
||||||
Payload = case {Type, ShowJid} of
|
end
|
||||||
{subscribe, true} ->
|
end, ok, State#state.subscribers),
|
||||||
#muc_subscribe{jid = From, nick = Nick};
|
if WJ /= [] ->
|
||||||
{subscribe, _} ->
|
Payload1 = case Type of
|
||||||
#muc_subscribe{nick = Nick};
|
subscribe -> #muc_subscribe{jid = From, nick = Nick};
|
||||||
{unsubscribe, true} ->
|
_ -> #muc_unsubscribe{jid = From, nick = Nick}
|
||||||
#muc_unsubscribe{jid = From, nick = Nick};
|
end,
|
||||||
{unsubscribe, _} ->
|
Packet1 = #message{
|
||||||
#muc_unsubscribe{nick = Nick}
|
sub_els = [#ps_event{
|
||||||
end,
|
items = #ps_items{
|
||||||
Packet = #message{
|
node = ?NS_MUCSUB_NODES_SUBSCRIBERS,
|
||||||
sub_els = [#ps_event{
|
items = [#ps_item{
|
||||||
items = #ps_items{
|
id = p1_rand:get_string(),
|
||||||
node = ?NS_MUCSUB_NODES_SUBSCRIBERS,
|
sub_els = [Payload1]}]}}]},
|
||||||
items = [#ps_item{
|
ejabberd_router_multicast:route_multicast(State#state.jid, State#state.server_host,
|
||||||
id = p1_rand:get_string(),
|
WJ, Packet1, true);
|
||||||
sub_els = [Payload]}]}}]},
|
true -> ok
|
||||||
ejabberd_router:route(xmpp:set_from_to(Packet, State#state.jid, JID));
|
end,
|
||||||
false ->
|
if WN /= [] ->
|
||||||
ok
|
Payload2 = case Type of
|
||||||
end
|
subscribe -> #muc_subscribe{nick = Nick};
|
||||||
end, ok, State#state.subscribers).
|
_ -> #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.
|
-spec send_wrapped(jid(), jid(), stanza(), binary(), state()) -> ok.
|
||||||
send_wrapped(From, To, Packet, Node, State) ->
|
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.
|
-spec send_wrapped_multiple(jid(), users(), stanza(), binary(), state()) -> ok.
|
||||||
send_wrapped_multiple(From, Users, Packet, Node, State) ->
|
send_wrapped_multiple(From, Users, Packet, Node, State) ->
|
||||||
|
{Dir, Wra} =
|
||||||
maps:fold(
|
maps:fold(
|
||||||
fun(_, #user{jid = To}, _) ->
|
fun(_, #user{jid = To, last_presence = LP}, {Direct, Wrapped} = Res) ->
|
||||||
send_wrapped(From, To, Packet, Node, State)
|
IsOffline = LP == undefined,
|
||||||
end, ok, Users).
|
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
|
%% Detect messange stanzas that don't have meaningful content
|
||||||
|
|
Loading…
Reference in New Issue