summaryrefslogtreecommitdiff
path: root/src/mod_mam.erl
diff options
context:
space:
mode:
authorEvgeniy Khramtsov <ekhramtsov@process-one.net>2015-08-12 16:58:56 +0300
committerChristophe Romain <christophe.romain@process-one.net>2015-10-02 16:09:55 +0200
commit6378c673df75ad05932e9029d3ccc965df43c810 (patch)
treeaba1fcb77e78c5033aced089d5b8f30312f1d2f1 /src/mod_mam.erl
parentFix force_update_presence (diff)
Avoid MAM dups when routing to multiple resources
Diffstat (limited to 'src/mod_mam.erl')
-rw-r--r--src/mod_mam.erl39
1 files changed, 36 insertions, 3 deletions
diff --git a/src/mod_mam.erl b/src/mod_mam.erl
index 3e3e0873..0c85e701 100644
--- a/src/mod_mam.erl
+++ b/src/mod_mam.erl
@@ -157,11 +157,12 @@ remove_user(LUser, LServer, odbc) ->
LServer,
[<<"delete from archive_prefs where username='">>, SUser, <<"';">>]).
-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) of
- true ->
+ true when not IsBareCopy ->
NewPkt = strip_my_archived_tag(Pkt, LServer),
case store_msg(C2SState, NewPkt, LUser, LServer, Peer, recv) of
{ok, ID} ->
@@ -178,7 +179,7 @@ user_receive_packet(Pkt, C2SState, JID, Peer, _To) ->
_ ->
NewPkt
end;
- false ->
+ _ ->
Pkt
end.
@@ -726,6 +727,38 @@ maybe_update_from_to(#xmlel{children = Els} = Pkt, JidRequestor,
Pkt2 = jlib:replace_from(jlib:jid_replace_resource(JidRequestor, Nick), Pkt1),
jlib:remove_attr(<<"to">>, Pkt2).
+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.
+
send(From, To, Msgs, RSM, Count, IsComplete, #iq{sub_el = SubEl} = IQ) ->
QID = xml:get_tag_attr_s(<<"queryid">>, SubEl),
NS = xml:get_tag_attr_s(<<"xmlns">>, SubEl),