ignore IQ result when MAM query had been killed

Daniel Gultsch created

Change summary

src/main/java/eu/siacs/conversations/services/MessageArchiveService.java | 30 
1 file changed, 22 insertions(+), 8 deletions(-)

Detailed changes

src/main/java/eu/siacs/conversations/services/MessageArchiveService.java 🔗

@@ -225,19 +225,31 @@ public class MessageArchiveService implements OnAdvancedStreamFeaturesLoaded {
 	private void execute(final Query query) {
 		final Account account = query.getAccount();
 		if (account.getStatus() == Account.State.ONLINE) {
+			final Conversation conversation = query.getConversation();
+			if (conversation != null && conversation.getStatus() == Conversation.STATUS_ARCHIVED) {
+				throw new IllegalStateException("Attempted to run MAM query for archived conversation");
+			}
 			Log.d(Config.LOGTAG, account.getJid().asBareJid().toString() + ": running mam query " + query.toString());
-			IqPacket packet = this.mXmppConnectionService.getIqGenerator().queryMessageArchiveManagement(query);
+			final IqPacket packet = this.mXmppConnectionService.getIqGenerator().queryMessageArchiveManagement(query);
 			this.mXmppConnectionService.sendIqPacket(account, packet, (a, p) -> {
-				Element fin = p.findChild("fin", query.version.namespace);
+				final Element fin = p.findChild("fin", query.version.namespace);
 				if (p.getType() == IqPacket.TYPE.TIMEOUT) {
-					synchronized (MessageArchiveService.this.queries) {
-						MessageArchiveService.this.queries.remove(query);
+					synchronized (this.queries) {
+						this.queries.remove(query);
 						if (query.hasCallback()) {
 							query.callback(false);
 						}
 					}
 				} else if (p.getType() == IqPacket.TYPE.RESULT && fin != null) {
-					processFin(query, fin);
+					final boolean running;
+					synchronized (this.queries) {
+						running = this.queries.contains(query);
+					}
+					if (running) {
+						processFin(query, fin);
+					} else {
+						Log.d(Config.LOGTAG,account.getJid().asBareJid()+": ignoring MAM iq result because query had been killed");
+					}
 				} else if (p.getType() == IqPacket.TYPE.RESULT && query.isLegacy()) {
 					//do nothing
 				} else {
@@ -252,9 +264,11 @@ public class MessageArchiveService implements OnAdvancedStreamFeaturesLoaded {
 		}
 	}
 
-	private void finalizeQuery(Query query, boolean done) {
+	private void finalizeQuery(final Query query, boolean done) {
 		synchronized (this.queries) {
-			this.queries.remove(query);
+			if (!this.queries.remove(query)) {
+				throw new IllegalStateException("Unable to remove query from queries");
+			}
 		}
 		final Conversation conversation = query.getConversation();
 		if (conversation != null) {
@@ -377,7 +391,7 @@ public class MessageArchiveService implements OnAdvancedStreamFeaturesLoaded {
 	void kill(Conversation conversation) {
 		final ArrayList<Query> toBeKilled = new ArrayList<>();
 		synchronized (this.queries) {
-			for (Query q : queries) {
+			for (final Query q : queries) {
 				if (q.conversation == conversation) {
 					toBeKilled.add(q);
 				}