private final Set<ReceiveMessageHandler> messageHandlers = new HashSet<>();
private final List<Runnable> closedListeners = new ArrayList<>();
private boolean isReceivingSynchronous;
+ private boolean needsToRetryFailedMessages = false;
ManagerImpl(
SignalAccount account,
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<>();
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();
} 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;
}
/**
} 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;
}
/**
} 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;
}
/**
} catch (IOException e) {
return false;
}
- return identityHelper.trustIdentityAllKeys(recipientId);
+ final var updated = identityHelper.trustIdentityAllKeys(recipientId);
+ if (updated && this.isReceiving()) {
+ needsToRetryFailedMessages = true;
+ }
+ return updated;
}
@Override
SignalServiceContent content = null;
if (!envelope.isReceipt()) {
+ account.getIdentityKeyStore().setRetryingDecryption(true);
try {
content = dependencies.getCipher().decrypt(envelope);
} catch (ProtocolUntrustedIdentityException e) {
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));
private final int localRegistrationId;
private final TrustNewIdentity trustNewIdentity;
+ private boolean isRetryingDecryption = false;
+
public IdentityKeyStore(
final File identitiesPath,
final RecipientResolver resolver,
}
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)) {
}
}
+ 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;
}