Fix processing of early messages.

1. Eliminated any possibility of infinite recursion.
2. Handle the fact that you can have multiple 'early contents' for a
   single message.
This commit is contained in:
Greyson Parrelli 2020-05-09 12:18:09 -04:00
parent 618b1b5ace
commit a83ccc18bb
2 changed files with 26 additions and 11 deletions

View File

@ -240,6 +240,17 @@ public final class PushProcessMessageJob extends BaseJob {
if (messageState == MessageState.DECRYPTED_OK) {
SignalServiceContent content = SignalServiceContent.deserialize(serializedPlaintextContent);
handleMessage(content, optionalSmsMessageId);
Optional<List<SignalServiceContent>> earlyContent = ApplicationDependencies.getEarlyMessageCache()
.retrieve(Recipient.externalPush(context, content.getSender()).getId(),
content.getTimestamp());
if (earlyContent.isPresent()) {
Log.i(TAG, "Found " + earlyContent.get().size() + " dependent item(s) that were retrieved earlier. Processing.");
for (SignalServiceContent earlyItem : earlyContent.get()) {
handleMessage(earlyItem, Optional.absent());
}
}
} else {
//noinspection ConstantConditions
handleExceptionMessage(exceptionMetadata, optionalSmsMessageId);
@ -332,14 +343,6 @@ public final class PushProcessMessageJob extends BaseJob {
}
resetRecipientToPush(Recipient.externalPush(context, content.getSender()));
Optional<SignalServiceContent> earlyContent = ApplicationDependencies.getEarlyMessageCache()
.retrieve(Recipient.externalPush(context, content.getSender()).getId(),
content.getTimestamp());
if (earlyContent.isPresent()) {
Log.i(TAG, "Found dependent content that was retrieved earlier. Processing.");
handleMessage(earlyContent.get(), Optional.absent());
}
} catch (StorageFailedException e) {
Log.w(TAG, e);
handleCorruptMessage(e.getSender(), e.getSenderDevice(), timestamp, smsMessageId);
@ -1363,6 +1366,7 @@ public final class PushProcessMessageJob extends BaseJob {
.incrementReadReceiptCount(id, content.getTimestamp());
if (!handled) {
Log.w(TAG, "[handleReadReceipt] Could not find matching message! timestamp: " + timestamp + " author: " + sender.getId());
ApplicationDependencies.getEarlyMessageCache().store(sender.getId(), timestamp, content);
}
}

View File

@ -6,6 +6,8 @@ import org.thoughtcrime.securesms.recipients.RecipientId;
import org.whispersystems.libsignal.util.guava.Optional;
import org.whispersystems.signalservice.api.messages.SignalServiceContent;
import java.util.LinkedList;
import java.util.List;
import java.util.Objects;
/**
@ -15,14 +17,23 @@ import java.util.Objects;
*/
public final class EarlyMessageCache {
private final LRUCache<MessageId, SignalServiceContent> cache = new LRUCache<>(100);
private final LRUCache<MessageId, List<SignalServiceContent>> cache = new LRUCache<>(100);
/**
* @param targetSender The sender of the message this message depends on.
* @param targetSentTimestamp The sent timestamp of the message this message depends on.
*/
public void store(@NonNull RecipientId targetSender, long targetSentTimestamp, @NonNull SignalServiceContent content) {
cache.put(new MessageId(targetSender, targetSentTimestamp), content);
MessageId messageId = new MessageId(targetSender, targetSentTimestamp);
List<SignalServiceContent> contentList = cache.get(messageId);
if (contentList == null) {
contentList = new LinkedList<>();
}
contentList.add(content);
cache.put(messageId, contentList);
}
/**
@ -30,7 +41,7 @@ public final class EarlyMessageCache {
* @param sender The sender of the message in question.
* @param sentTimestamp The sent timestamp of the message in question.
*/
public Optional<SignalServiceContent> retrieve(@NonNull RecipientId sender, long sentTimestamp) {
public Optional<List<SignalServiceContent>> retrieve(@NonNull RecipientId sender, long sentTimestamp) {
return Optional.fromNullable(cache.remove(new MessageId(sender, sentTimestamp)));
}