Retry failed messages after trusting a new identity

This commit is contained in:
AsamK 2021-12-20 17:48:36 +01:00
parent 71e0c3f80c
commit 172011234b
3 changed files with 42 additions and 7 deletions

View file

@ -151,6 +151,7 @@ public class ManagerImpl implements Manager {
private final Set<ReceiveMessageHandler> messageHandlers = new HashSet<>(); private final Set<ReceiveMessageHandler> messageHandlers = new HashSet<>();
private final List<Runnable> closedListeners = new ArrayList<>(); private final List<Runnable> closedListeners = new ArrayList<>();
private boolean isReceivingSynchronous; private boolean isReceivingSynchronous;
private boolean needsToRetryFailedMessages = false;
ManagerImpl( ManagerImpl(
SignalAccount account, SignalAccount account,
@ -1102,7 +1103,7 @@ public class ManagerImpl implements Manager {
private void receiveMessagesInternal( private void receiveMessagesInternal(
Duration timeout, boolean returnOnTimeout, ReceiveMessageHandler handler Duration timeout, boolean returnOnTimeout, ReceiveMessageHandler handler
) throws IOException { ) throws IOException {
retryFailedReceivedMessages(handler); needsToRetryFailedMessages = true;
// Use a Map here because java Set doesn't have a get method ... // Use a Map here because java Set doesn't have a get method ...
Map<HandleAction, HandleAction> queuedActions = new HashMap<>(); Map<HandleAction, HandleAction> queuedActions = new HashMap<>();
@ -1121,6 +1122,10 @@ public class ManagerImpl implements Manager {
final var MAX_BACKOFF_COUNTER = 9; final var MAX_BACKOFF_COUNTER = 9;
while (!Thread.interrupted()) { while (!Thread.interrupted()) {
if (needsToRetryFailedMessages) {
retryFailedReceivedMessages(handler);
needsToRetryFailedMessages = false;
}
SignalServiceEnvelope envelope; SignalServiceEnvelope envelope;
final CachedMessage[] cachedMessage = {null}; final CachedMessage[] cachedMessage = {null};
final var nowMillis = System.currentTimeMillis(); final var nowMillis = System.currentTimeMillis();
@ -1365,7 +1370,11 @@ public class ManagerImpl implements Manager {
} catch (IOException e) { } catch (IOException e) {
return false; 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) { } catch (IOException e) {
return false; 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) { } catch (IOException e) {
return false; 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) { } catch (IOException e) {
return false; return false;
} }
return identityHelper.trustIdentityAllKeys(recipientId); final var updated = identityHelper.trustIdentityAllKeys(recipientId);
if (updated && this.isReceiving()) {
needsToRetryFailedMessages = true;
}
return updated;
} }
@Override @Override

View file

@ -106,6 +106,7 @@ public final class IncomingMessageHandler {
SignalServiceContent content = null; SignalServiceContent content = null;
if (!envelope.isReceipt()) { if (!envelope.isReceipt()) {
account.getIdentityKeyStore().setRetryingDecryption(true);
try { try {
content = dependencies.getCipher().decrypt(envelope); content = dependencies.getCipher().decrypt(envelope);
} catch (ProtocolUntrustedIdentityException e) { } catch (ProtocolUntrustedIdentityException e) {
@ -115,6 +116,8 @@ public final class IncomingMessageHandler {
return new Pair<>(List.of(), exception); return new Pair<>(List.of(), exception);
} catch (Exception e) { } catch (Exception e) {
return new Pair<>(List.of(), e); return new Pair<>(List.of(), e);
} finally {
account.getIdentityKeyStore().setRetryingDecryption(false);
} }
} }
actions.addAll(checkAndHandleMessage(envelope, content, ignoreAttachments, handler, null)); actions.addAll(checkAndHandleMessage(envelope, content, ignoreAttachments, handler, null));

View file

@ -43,6 +43,8 @@ public class IdentityKeyStore implements org.whispersystems.libsignal.state.Iden
private final int localRegistrationId; private final int localRegistrationId;
private final TrustNewIdentity trustNewIdentity; private final TrustNewIdentity trustNewIdentity;
private boolean isRetryingDecryption = false;
public IdentityKeyStore( public IdentityKeyStore(
final File identitiesPath, final File identitiesPath,
final RecipientResolver resolver, 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) { public boolean saveIdentity(final RecipientId recipientId, final IdentityKey identityKey, Date added) {
if (isRetryingDecryption) {
return false;
}
synchronized (cachedIdentities) { synchronized (cachedIdentities) {
final var identityInfo = loadIdentityLocked(recipientId); final var identityInfo = loadIdentityLocked(recipientId);
if (identityInfo != null && identityInfo.getIdentityKey().equals(identityKey)) { 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( public boolean setIdentityTrustLevel(
RecipientId recipientId, IdentityKey identityKey, TrustLevel trustLevel RecipientId recipientId, IdentityKey identityKey, TrustLevel trustLevel
) { ) {
synchronized (cachedIdentities) { synchronized (cachedIdentities) {
final var identityInfo = loadIdentityLocked(recipientId); final var identityInfo = loadIdentityLocked(recipientId);
if (identityInfo == null || !identityInfo.getIdentityKey().equals(identityKey)) { if (identityInfo == null
// Identity not found, not updating the trust level || !identityInfo.getIdentityKey().equals(identityKey)
|| identityInfo.getTrustLevel() == trustLevel) {
// Identity not found or trust not changed, not updating the trust level
return false; return false;
} }