From 0ecdb43be6b8e2184432f277dbc7eca8cbb1c024 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Sun, 30 Jun 2019 19:54:07 +0200 Subject: [PATCH] rate limit muc pings / joins. never run two pings at same time --- .../siacs/conversations/entities/Account.java | 1 + .../services/XmppConnectionService.java | 30 ++++++++++++++++--- 2 files changed, 27 insertions(+), 4 deletions(-) diff --git a/src/main/java/eu/siacs/conversations/entities/Account.java b/src/main/java/eu/siacs/conversations/entities/Account.java index 29d66fd08..a60ee83c7 100644 --- a/src/main/java/eu/siacs/conversations/entities/Account.java +++ b/src/main/java/eu/siacs/conversations/entities/Account.java @@ -67,6 +67,7 @@ public class Account extends AbstractEntity implements AvatarService.Avatarable public List pendingConferenceJoins = new CopyOnWriteArrayList<>(); public List pendingConferenceLeaves = new CopyOnWriteArrayList<>(); public final Set inProgressConferenceJoins = new HashSet<>(); + public final Set inProgressConferencePings = new HashSet<>(); protected Jid jid; protected String password; protected int options = 0; diff --git a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java index df4f198aa..b5e33a4fd 100644 --- a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java +++ b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java @@ -314,6 +314,12 @@ public class XmppConnectionService extends Service { } account.getRoster().clearPresences(); + synchronized (account.inProgressConferenceJoins) { + account.inProgressConferenceJoins.clear(); + } + synchronized (account.inProgressConferencePings) { + account.inProgressConferencePings.clear(); + } mJingleConnectionManager.cancelInTransmission(); mQuickConversationsService.considerSyncBackground(false); fetchRosterFromServer(account); @@ -2464,21 +2470,37 @@ public class XmppConnectionService extends Service { } public void mucSelfPingAndRejoin(final Conversation conversation) { + final Account account = conversation.getAccount(); + synchronized (account.inProgressConferenceJoins) { + if (account.inProgressConferenceJoins.contains(conversation)) { + Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": canceling muc self ping because join is already under way"); + return; + } + } + synchronized (account.inProgressConferencePings) { + if (!account.inProgressConferencePings.add(conversation)) { + Log.d(Config.LOGTAG, account.getJid().asBareJid()+": canceling muc self ping because ping is already under way"); + return; + } + } final Jid self = conversation.getMucOptions().getSelf().getFullJid(); final IqPacket ping = new IqPacket(IqPacket.TYPE.GET); ping.setTo(self); ping.addChild("ping", Namespace.PING); - sendIqPacket(conversation.getAccount(), ping, (account, response) -> { + sendIqPacket(conversation.getAccount(), ping, (a, response) -> { if (response.getType() == IqPacket.TYPE.ERROR) { Element error = response.findChild("error"); if (error == null || error.hasChild("service-unavailable") || error.hasChild("feature-not-implemented") || error.hasChild("item-not-found")) { - Log.d(Config.LOGTAG,account.getJid().asBareJid()+": ping to "+self+" came back as ignorable error"); + Log.d(Config.LOGTAG,a.getJid().asBareJid()+": ping to "+self+" came back as ignorable error"); } else { - Log.d(Config.LOGTAG,account.getJid().asBareJid()+": ping to "+self+" failed. attempting rejoin"); + Log.d(Config.LOGTAG,a.getJid().asBareJid()+": ping to "+self+" failed. attempting rejoin"); joinMuc(conversation); } } else if (response.getType() == IqPacket.TYPE.RESULT) { - Log.d(Config.LOGTAG,account.getJid().asBareJid()+": ping to "+self+" came back fine"); + Log.d(Config.LOGTAG,a.getJid().asBareJid()+": ping to "+self+" came back fine"); + } + synchronized (account.inProgressConferencePings) { + account.inProgressConferencePings.remove(conversation); } }); }