mirror of
https://github.com/processone/ejabberd.git
synced 2024-11-22 16:20:52 +01:00
Let ejabberd_sm mark copied messages
When multiple resources have the same (highest) priority, ejabberd_sm dispatches messages addressed to the bare JID (or to an unavailable resource) to each of these resources. Such messages are now marked with an 'sm_copy' flag for all but one of the resources. This makes it easier for other modules to identify those duplicates. Resolves #1356.
This commit is contained in:
parent
ee8cc1dac2
commit
114ca786ee
@ -570,9 +570,9 @@ route_message(From, To, Packet, Type) ->
|
||||
LServer = To#jid.lserver,
|
||||
PrioRes = get_user_present_resources(LUser, LServer),
|
||||
case catch lists:max(PrioRes) of
|
||||
{Priority, _R}
|
||||
when is_integer(Priority), Priority >= 0 ->
|
||||
lists:foreach(fun ({P, R}) when P == Priority;
|
||||
{MaxPrio, MaxRes}
|
||||
when is_integer(MaxPrio), MaxPrio >= 0 ->
|
||||
lists:foreach(fun ({P, R}) when P == MaxPrio;
|
||||
(P >= 0) and (Type == headline) ->
|
||||
LResource = jid:resourceprep(R),
|
||||
Mod = get_sm_backend(LServer),
|
||||
@ -584,7 +584,12 @@ route_message(From, To, Packet, Type) ->
|
||||
Session = lists:max(Ss),
|
||||
Pid = element(2, Session#session.sid),
|
||||
?DEBUG("sending to process ~p~n", [Pid]),
|
||||
Pid ! {route, From, To, Packet}
|
||||
LMaxRes = jid:resourceprep(MaxRes),
|
||||
Packet1 = maybe_mark_as_copy(Packet,
|
||||
LResource,
|
||||
LMaxRes,
|
||||
P, MaxPrio),
|
||||
Pid ! {route, From, To, Packet1}
|
||||
end;
|
||||
%% Ignore other priority:
|
||||
({_Prio, _Res}) -> ok
|
||||
@ -603,6 +608,16 @@ route_message(From, To, Packet, Type) ->
|
||||
end
|
||||
end.
|
||||
|
||||
-spec maybe_mark_as_copy(message(), binary(), binary(), integer(), integer())
|
||||
-> message().
|
||||
maybe_mark_as_copy(Packet, R, R, P, P) ->
|
||||
Packet;
|
||||
maybe_mark_as_copy(Packet, _, _, P, P) ->
|
||||
Meta = Packet#message.meta,
|
||||
Packet#message{meta = Meta#{sm_copy => true}};
|
||||
maybe_mark_as_copy(Packet, _, _, _, _) ->
|
||||
Packet.
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
-spec clean_session_list([#session{}]) -> [#session{}].
|
||||
clean_session_list(Ss) ->
|
||||
|
@ -153,7 +153,7 @@ send_copies(JID, To, Packet, Direction)->
|
||||
{U, S, R} = jid:tolower(JID),
|
||||
PrioRes = ejabberd_sm:get_user_present_resources(U, S),
|
||||
{_, AvailRs} = lists:unzip(PrioRes),
|
||||
{MaxPrio, MaxRes} = case catch lists:max(PrioRes) of
|
||||
{MaxPrio, _MaxRes} = case catch lists:max(PrioRes) of
|
||||
{Prio, Res} -> {Prio, Res};
|
||||
_ -> {0, undefined}
|
||||
end,
|
||||
@ -166,19 +166,19 @@ send_copies(JID, To, Packet, Direction)->
|
||||
end,
|
||||
%% list of JIDs that should receive a carbon copy of this message (excluding the
|
||||
%% receiver(s) of the original message
|
||||
TargetJIDs = case {IsBareTo, R} of
|
||||
{true, MaxRes} ->
|
||||
TargetJIDs = case {IsBareTo, Packet} of
|
||||
{true, #message{meta = #{sm_copy := true}}} ->
|
||||
%% The message was sent to our bare JID, and we currently have
|
||||
%% multiple resources with the same highest priority, so the session
|
||||
%% manager routes the message to each of them. We create carbon
|
||||
%% copies only from one of those resources in order to avoid
|
||||
%% duplicates.
|
||||
[];
|
||||
{true, _} ->
|
||||
OrigTo = fun(Res) -> lists:member({MaxPrio, Res}, PrioRes) end,
|
||||
[ {jid:make({U, S, CCRes}), CC_Version}
|
||||
|| {CCRes, CC_Version} <- list(U, S),
|
||||
lists:member(CCRes, AvailRs), not OrigTo(CCRes) ];
|
||||
{true, _} ->
|
||||
%% The message was sent to our bare JID, and we currently have
|
||||
%% multiple resources with the same highest priority, so the session
|
||||
%% manager routes the message to each of them. We create carbon
|
||||
%% copies only from one of those resources (the one where R equals
|
||||
%% MaxRes) in order to avoid duplicates.
|
||||
[];
|
||||
{false, _} ->
|
||||
[ {jid:make({U, S, CCRes}), CC_Version}
|
||||
|| {CCRes, CC_Version} <- list(U, S),
|
||||
|
@ -200,12 +200,11 @@ set_room_option(Acc, _Property, _Lang) ->
|
||||
Acc.
|
||||
|
||||
-spec user_receive_packet(stanza(), ejabberd_c2s:state(), jid(), jid(), jid()) -> stanza().
|
||||
user_receive_packet(Pkt, C2SState, JID, Peer, To) ->
|
||||
user_receive_packet(Pkt, C2SState, JID, Peer, _To) ->
|
||||
LUser = JID#jid.luser,
|
||||
LServer = JID#jid.lserver,
|
||||
IsBareCopy = is_bare_copy(JID, To),
|
||||
case should_archive(Pkt, LServer) of
|
||||
true when not IsBareCopy ->
|
||||
true ->
|
||||
NewPkt = strip_my_archived_tag(Pkt, LServer),
|
||||
case store_msg(C2SState, NewPkt, LUser, LServer, Peer, recv) of
|
||||
{ok, ID} ->
|
||||
@ -454,6 +453,8 @@ process_iq(LServer, #iq{from = #jid{luser = LUser}, lang = Lang,
|
||||
|
||||
should_archive(#message{type = error}, _LServer) ->
|
||||
false;
|
||||
should_archive(#message{meta = #{sm_copy := true}}, _LServer) ->
|
||||
false;
|
||||
should_archive(#message{body = Body, subject = Subject,
|
||||
type = Type} = Pkt, LServer) ->
|
||||
case is_resent(Pkt, LServer) of
|
||||
@ -812,38 +813,6 @@ maybe_update_from_to(#message{sub_els = Els} = Pkt, JidRequestor, JidArchive,
|
||||
maybe_update_from_to(Pkt, _JidRequestor, _JidArchive, _Peer, chat, _Nick) ->
|
||||
Pkt.
|
||||
|
||||
is_bare_copy(#jid{luser = U, lserver = S, lresource = R}, To) ->
|
||||
PrioRes = ejabberd_sm:get_user_present_resources(U, S),
|
||||
MaxRes = case catch lists:max(PrioRes) of
|
||||
{_Prio, Res} when is_binary(Res) ->
|
||||
Res;
|
||||
_ ->
|
||||
undefined
|
||||
end,
|
||||
IsBareTo = case To of
|
||||
#jid{lresource = <<"">>} ->
|
||||
true;
|
||||
#jid{lresource = LRes} ->
|
||||
%% Unavailable resources are handled like bare JIDs.
|
||||
lists:keyfind(LRes, 2, PrioRes) =:= false
|
||||
end,
|
||||
case {IsBareTo, R} of
|
||||
{true, MaxRes} ->
|
||||
?DEBUG("Recipient of message to bare JID has top priority: ~s@~s/~s",
|
||||
[U, S, R]),
|
||||
false;
|
||||
{true, _R} ->
|
||||
%% The message was sent to our bare JID, and we currently have
|
||||
%% multiple resources with the same highest priority, so the session
|
||||
%% manager routes the message to each of them. We store the message
|
||||
%% only from the resource where R equals MaxRes.
|
||||
?DEBUG("Additional recipient of message to bare JID: ~s@~s/~s",
|
||||
[U, S, R]),
|
||||
true;
|
||||
{false, _R} ->
|
||||
false
|
||||
end.
|
||||
|
||||
-spec send([{binary(), integer(), xmlel()}],
|
||||
non_neg_integer(), boolean(), iq()) -> iq() | ignore.
|
||||
send(Msgs, Count, IsComplete,
|
||||
|
Loading…
Reference in New Issue
Block a user