From 974461fb23453108417a9f2c005ba46c0991440c Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Thu, 7 Nov 2024 17:18:13 +0100 Subject: [PATCH] track resumption id --- .../conversations/xmpp/XmppConnection.java | 33 +++++++++++++++---- .../android/xmpp/model/sm/Resumed.java | 4 +++ 2 files changed, 31 insertions(+), 6 deletions(-) diff --git a/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java b/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java index f6650abbfc6a84f866431ac3940e9ba68b526c24..5ba2dbe72a1ed078cf96588c3c4fb2dce30a5375 100644 --- a/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java +++ b/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java @@ -45,6 +45,7 @@ import eu.siacs.conversations.services.MemorizingTrustManager; import eu.siacs.conversations.services.MessageArchiveService; import eu.siacs.conversations.services.NotificationService; import eu.siacs.conversations.services.XmppConnectionService; +import eu.siacs.conversations.ui.util.PendingItem; import eu.siacs.conversations.utils.AccountUtils; import eu.siacs.conversations.utils.CryptoHelper; import eu.siacs.conversations.utils.Patterns; @@ -189,6 +190,7 @@ public class XmppConnection implements Runnable { private OnStatusChanged statusListener = null; private final Runnable bindListener; private OnMessageAcknowledged acknowledgedListener = null; + private final PendingItem pendingResumeId = new PendingItem<>(); private LoginInfo loginInfo; private HashedToken.Mechanism hashTokenRequest; private HttpUrl redirectionUrl = null; @@ -288,6 +290,7 @@ public class XmppConnection implements Runnable { mXmppConnectionService.resetSendingToWaiting(account); } Log.d(Config.LOGTAG, account.getJid().asBareJid().toString() + ": connecting"); + this.pendingResumeId.clear(); this.loginInfo = null; this.features.encryptionEnabled = false; this.inSmacksSession = false; @@ -1068,6 +1071,17 @@ public class XmppConnection implements Runnable { } private void processResumed(final Resumed resumed) throws StateChangingException { + final var pendingResumeId = this.pendingResumeId.pop(); + final var prevId = resumed.getPrevId(); + if (prevId == null || !prevId.equals(pendingResumeId)) { + Log.d( + Config.LOGTAG, + account.getJid().asBareJid() + + ": server tried resume with unknown id " + + prevId); + resetStreamId(); + throw new StateChangingException(Account.State.INCOMPATIBLE_SERVER); + } this.inSmacksSession = true; this.isBound = true; this.tagWriter.writeStanzaAsync(new Request()); @@ -1475,9 +1489,9 @@ public class XmppConnection implements Runnable { + ": resuming after stanza #" + stanzasReceived); } - final var resume = new Resume(this.streamId.id, stanzasReceived); - this.mSmCatchupMessageCounter.set(0); - this.mWaitingForSmCatchup.set(true); + final var streamId = this.streamId.id; + final var resume = new Resume(streamId, stanzasReceived); + prepareForResume(streamId); this.tagWriter.writeStanzaAsync(resume); } else if (needsBinding) { if (this.streamFeatures.hasChild("bind", Namespace.BIND) @@ -1705,9 +1719,9 @@ public class XmppConnection implements Runnable { authenticate.addChild(generateBindRequest(bind)); } if (inlineStreamManagement && streamId != null) { - final var resume = new Resume(this.streamId.id, stanzasReceived); - this.mSmCatchupMessageCounter.set(0); - this.mWaitingForSmCatchup.set(true); + final var streamId = this.streamId.id; + final var resume = new Resume(streamId, stanzasReceived); + prepareForResume(streamId); authenticate.addExtension(resume); } if (hashedTokenRequest != null) { @@ -1719,6 +1733,12 @@ public class XmppConnection implements Runnable { return authenticate; } + private void prepareForResume(final String streamId) { + this.mSmCatchupMessageCounter.set(0); + this.mWaitingForSmCatchup.set(true); + this.pendingResumeId.push(streamId); + } + private Bind generateBindRequest(final Collection bindFeatures) { Log.d(Config.LOGTAG, "inline bind features: " + bindFeatures); final var bind = new Bind(); @@ -2617,6 +2637,7 @@ public class XmppConnection implements Runnable { } private void resetStreamId() { + this.pendingResumeId.clear(); this.streamId = null; this.boundStreamFeatures = null; } diff --git a/src/main/java/im/conversations/android/xmpp/model/sm/Resumed.java b/src/main/java/im/conversations/android/xmpp/model/sm/Resumed.java index eb240745fd4b1402e96c838ef71a868f1d7dcf68..bcb36d4093f2cbe4f04423b6a1393a62c6aca28e 100644 --- a/src/main/java/im/conversations/android/xmpp/model/sm/Resumed.java +++ b/src/main/java/im/conversations/android/xmpp/model/sm/Resumed.java @@ -15,4 +15,8 @@ public class Resumed extends StreamElement { public Optional getHandled() { return this.getOptionalIntAttribute("h"); } + + public String getPrevId() { + return this.getAttribute("previd"); + } }