]> nmode's Git Repositories - signal-cli/commitdiff
Retry failed messages after trusting a new identity
authorAsamK <asamk@gmx.de>
Mon, 20 Dec 2021 16:48:36 +0000 (17:48 +0100)
committerAsamK <asamk@gmx.de>
Mon, 20 Dec 2021 16:48:36 +0000 (17:48 +0100)
lib/src/main/java/org/asamk/signal/manager/ManagerImpl.java
lib/src/main/java/org/asamk/signal/manager/helper/IncomingMessageHandler.java
lib/src/main/java/org/asamk/signal/manager/storage/identities/IdentityKeyStore.java

index cb9e473052fbb0572f0315ad480146e7c11b6332..2fb3ae568cde6ad329762d0586553f89d35735dc 100644 (file)
@@ -151,6 +151,7 @@ public class ManagerImpl implements Manager {
     private final Set<ReceiveMessageHandler> messageHandlers = new HashSet<>();
     private final List<Runnable> closedListeners = new ArrayList<>();
     private boolean isReceivingSynchronous;
+    private boolean needsToRetryFailedMessages = false;
 
     ManagerImpl(
             SignalAccount account,
@@ -1102,7 +1103,7 @@ public class ManagerImpl implements Manager {
     private void receiveMessagesInternal(
             Duration timeout, boolean returnOnTimeout, ReceiveMessageHandler handler
     ) throws IOException {
-        retryFailedReceivedMessages(handler);
+        needsToRetryFailedMessages = true;
 
         // Use a Map here because java Set doesn't have a get method ...
         Map<HandleAction, HandleAction> queuedActions = new HashMap<>();
@@ -1121,6 +1122,10 @@ public class ManagerImpl implements Manager {
         final var MAX_BACKOFF_COUNTER = 9;
 
         while (!Thread.interrupted()) {
+            if (needsToRetryFailedMessages) {
+                retryFailedReceivedMessages(handler);
+                needsToRetryFailedMessages = false;
+            }
             SignalServiceEnvelope envelope;
             final CachedMessage[] cachedMessage = {null};
             final var nowMillis = System.currentTimeMillis();
@@ -1365,7 +1370,11 @@ public class ManagerImpl implements Manager {
         } catch (IOException e) {
             return false;
         }
-        return identityHelper.trustIdentityVerified(recipientId, fingerprint);
+        final var updated = identityHelper.trustIdentityVerified(recipientId, fingerprint);
+        if (updated && this.isReceiving()) {
+            needsToRetryFailedMessages = true;
+        }
+        return updated;
     }
 
     /**
@@ -1382,7 +1391,11 @@ public class ManagerImpl implements Manager {
         } catch (IOException e) {
             return false;
         }
-        return identityHelper.trustIdentityVerifiedSafetyNumber(recipientId, safetyNumber);
+        final var updated = identityHelper.trustIdentityVerifiedSafetyNumber(recipientId, safetyNumber);
+        if (updated && this.isReceiving()) {
+            needsToRetryFailedMessages = true;
+        }
+        return updated;
     }
 
     /**
@@ -1399,7 +1412,11 @@ public class ManagerImpl implements Manager {
         } catch (IOException e) {
             return false;
         }
-        return identityHelper.trustIdentityVerifiedSafetyNumber(recipientId, safetyNumber);
+        final var updated = identityHelper.trustIdentityVerifiedSafetyNumber(recipientId, safetyNumber);
+        if (updated && this.isReceiving()) {
+            needsToRetryFailedMessages = true;
+        }
+        return updated;
     }
 
     /**
@@ -1415,7 +1432,11 @@ public class ManagerImpl implements Manager {
         } catch (IOException e) {
             return false;
         }
-        return identityHelper.trustIdentityAllKeys(recipientId);
+        final var updated = identityHelper.trustIdentityAllKeys(recipientId);
+        if (updated && this.isReceiving()) {
+            needsToRetryFailedMessages = true;
+        }
+        return updated;
     }
 
     @Override
index 3fc040bc737d917dba057b74b7ef3f129bf9cd3e..db854ef6d6ba935b54c9a9702308c8d68e165e69 100644 (file)
@@ -106,6 +106,7 @@ public final class IncomingMessageHandler {
 
         SignalServiceContent content = null;
         if (!envelope.isReceipt()) {
+            account.getIdentityKeyStore().setRetryingDecryption(true);
             try {
                 content = dependencies.getCipher().decrypt(envelope);
             } catch (ProtocolUntrustedIdentityException e) {
@@ -115,6 +116,8 @@ public final class IncomingMessageHandler {
                 return new Pair<>(List.of(), exception);
             } catch (Exception e) {
                 return new Pair<>(List.of(), e);
+            } finally {
+                account.getIdentityKeyStore().setRetryingDecryption(false);
             }
         }
         actions.addAll(checkAndHandleMessage(envelope, content, ignoreAttachments, handler, null));
index d7b25d237a6c855baceef466526d71e4bfd4cffd..5a651eddb14f501d44165b0b9a8f45de876f12ff 100644 (file)
@@ -43,6 +43,8 @@ public class IdentityKeyStore implements org.whispersystems.libsignal.state.Iden
     private final int localRegistrationId;
     private final TrustNewIdentity trustNewIdentity;
 
+    private boolean isRetryingDecryption = false;
+
     public IdentityKeyStore(
             final File identitiesPath,
             final RecipientResolver resolver,
@@ -75,6 +77,9 @@ public class IdentityKeyStore implements org.whispersystems.libsignal.state.Iden
     }
 
     public boolean saveIdentity(final RecipientId recipientId, final IdentityKey identityKey, Date added) {
+        if (isRetryingDecryption) {
+            return false;
+        }
         synchronized (cachedIdentities) {
             final var identityInfo = loadIdentityLocked(recipientId);
             if (identityInfo != null && identityInfo.getIdentityKey().equals(identityKey)) {
@@ -92,13 +97,19 @@ public class IdentityKeyStore implements org.whispersystems.libsignal.state.Iden
         }
     }
 
+    public void setRetryingDecryption(final boolean retryingDecryption) {
+        isRetryingDecryption = retryingDecryption;
+    }
+
     public boolean setIdentityTrustLevel(
             RecipientId recipientId, IdentityKey identityKey, TrustLevel trustLevel
     ) {
         synchronized (cachedIdentities) {
             final var identityInfo = loadIdentityLocked(recipientId);
-            if (identityInfo == null || !identityInfo.getIdentityKey().equals(identityKey)) {
-                // Identity not found, not updating the trust level
+            if (identityInfo == null
+                    || !identityInfo.getIdentityKey().equals(identityKey)
+                    || identityInfo.getTrustLevel() == trustLevel) {
+                // Identity not found or trust not changed, not updating the trust level
                 return false;
             }