From 5787a5f68a51db200281d04ffeace82718b0e3a0 Mon Sep 17 00:00:00 2001 From: Greyson Parrelli Date: Tue, 24 Aug 2021 09:56:26 -0400 Subject: [PATCH] Improve conversion of Recipient to SignalServiceAddress. --- .../jobs/AutomaticSessionResetJob.java | 8 ++++++- .../jobs/MultiDeviceBlockedUpdateJob.java | 2 +- .../jobs/MultiDeviceContactUpdateJob.java | 11 +++++++-- .../MultiDeviceMessageRequestResponseJob.java | 13 ++++++++--- .../jobs/MultiDeviceReadUpdateJob.java | 3 ++- .../jobs/MultiDeviceVerifiedUpdateJob.java | 17 ++++++++++---- .../jobs/MultiDeviceViewOnceOpenJob.java | 9 +++++++- .../jobs/MultiDeviceViewedUpdateJob.java | 3 ++- .../securesms/jobs/NullMessageSendJob.java | 5 ++++ .../jobs/PaymentNotificationSendJob.java | 10 ++++++-- .../securesms/jobs/PushGroupUpdateJob.java | 17 ++++++++++---- .../securesms/jobs/PushMediaSendJob.java | 7 +++++- .../securesms/jobs/PushSendJob.java | 11 ++++++--- .../securesms/jobs/PushTextSendJob.java | 7 +++++- .../securesms/jobs/ReactionSendJob.java | 12 ++++++---- .../securesms/jobs/RequestGroupInfoJob.java | 5 ++++ .../securesms/jobs/ResendMessageJob.java | 10 ++++++-- .../jobs/SendDeliveryReceiptJob.java | 6 +++++ .../securesms/jobs/SendReadReceiptJob.java | 6 +++++ .../securesms/jobs/SendRetryReceiptJob.java | 8 ++++++- .../securesms/jobs/SendViewedReceiptJob.java | 6 +++++ .../jobs/SenderKeyDistributionSendJob.java | 5 ++++ .../securesms/messages/GroupSendUtil.java | 23 +++++++++++++++++-- .../securesms/recipients/Recipient.java | 8 +++++++ .../securesms/recipients/RecipientUtil.java | 18 +++++++++++++-- .../securesms/util/ProfileUtil.java | 6 ++++- 26 files changed, 197 insertions(+), 39 deletions(-) diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobs/AutomaticSessionResetJob.java b/app/src/main/java/org/thoughtcrime/securesms/jobs/AutomaticSessionResetJob.java index f91d8c470..729bbe312 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/jobs/AutomaticSessionResetJob.java +++ b/app/src/main/java/org/thoughtcrime/securesms/jobs/AutomaticSessionResetJob.java @@ -126,7 +126,13 @@ public class AutomaticSessionResetJob extends BaseJob { } private void sendNullMessage() throws IOException { - Recipient recipient = Recipient.resolved(recipientId); + Recipient recipient = Recipient.resolved(recipientId); + + if (recipient.isUnregistered()) { + Log.w(TAG, recipient.getId() + " not registered!"); + return; + } + SignalServiceMessageSender messageSender = ApplicationDependencies.getSignalServiceMessageSender(); SignalServiceAddress address = RecipientUtil.toSignalServiceAddress(context, recipient); Optional unidentifiedAccess = UnidentifiedAccessUtil.getAccessFor(context, recipient); diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobs/MultiDeviceBlockedUpdateJob.java b/app/src/main/java/org/thoughtcrime/securesms/jobs/MultiDeviceBlockedUpdateJob.java index b8b03b17c..428082fe8 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/jobs/MultiDeviceBlockedUpdateJob.java +++ b/app/src/main/java/org/thoughtcrime/securesms/jobs/MultiDeviceBlockedUpdateJob.java @@ -82,7 +82,7 @@ public class MultiDeviceBlockedUpdateJob extends BaseJob { while ((recipient = reader.getNext()) != null) { if (recipient.isPushGroup()) { blockedGroups.add(recipient.requireGroupId().getDecodedId()); - } else if (recipient.hasServiceIdentifier()) { + } else if (recipient.isMaybeRegistered()) { blockedIndividuals.add(RecipientUtil.toSignalServiceAddress(context, recipient)); } } diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobs/MultiDeviceContactUpdateJob.java b/app/src/main/java/org/thoughtcrime/securesms/jobs/MultiDeviceContactUpdateJob.java index e72811b0d..ac61f06cf 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/jobs/MultiDeviceContactUpdateJob.java +++ b/app/src/main/java/org/thoughtcrime/securesms/jobs/MultiDeviceContactUpdateJob.java @@ -17,6 +17,7 @@ import org.thoughtcrime.securesms.crypto.ProfileKeyUtil; import org.thoughtcrime.securesms.crypto.UnidentifiedAccessUtil; import org.thoughtcrime.securesms.database.DatabaseFactory; import org.thoughtcrime.securesms.database.IdentityDatabase; +import org.thoughtcrime.securesms.database.RecipientDatabase; import org.thoughtcrime.securesms.dependencies.ApplicationDependencies; import org.thoughtcrime.securesms.jobmanager.Data; import org.thoughtcrime.securesms.jobmanager.Job; @@ -135,8 +136,14 @@ public class MultiDeviceContactUpdateJob extends BaseJob { WriteDetails writeDetails = createTempFile(); try { - DeviceContactsOutputStream out = new DeviceContactsOutputStream(writeDetails.outputStream); - Recipient recipient = Recipient.resolved(recipientId); + DeviceContactsOutputStream out = new DeviceContactsOutputStream(writeDetails.outputStream); + Recipient recipient = Recipient.resolved(recipientId); + + if (recipient.getRegistered() == RecipientDatabase.RegisteredState.NOT_REGISTERED) { + Log.w(TAG, recipientId + " not registered!"); + return; + } + Optional identityRecord = DatabaseFactory.getIdentityDatabase(context).getIdentity(recipient.getId()); Optional verifiedMessage = getVerifiedMessage(recipient, identityRecord); Map inboxPositions = DatabaseFactory.getThreadDatabase(context).getInboxPositions(); diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobs/MultiDeviceMessageRequestResponseJob.java b/app/src/main/java/org/thoughtcrime/securesms/jobs/MultiDeviceMessageRequestResponseJob.java index 539818054..0c47ec831 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/jobs/MultiDeviceMessageRequestResponseJob.java +++ b/app/src/main/java/org/thoughtcrime/securesms/jobs/MultiDeviceMessageRequestResponseJob.java @@ -5,6 +5,7 @@ import androidx.annotation.NonNull; import org.signal.core.util.logging.Log; import org.thoughtcrime.securesms.crypto.UnidentifiedAccessUtil; +import org.thoughtcrime.securesms.database.RecipientDatabase; import org.thoughtcrime.securesms.dependencies.ApplicationDependencies; import org.thoughtcrime.securesms.jobmanager.Data; import org.thoughtcrime.securesms.jobmanager.Job; @@ -110,12 +111,18 @@ public class MultiDeviceMessageRequestResponseJob extends BaseJob { if (recipient.isGroup()) { response = MessageRequestResponseMessage.forGroup(recipient.getGroupId().get().getDecodedId(), localToRemoteType(type)); - } else { + } else if (recipient.isMaybeRegistered()) { response = MessageRequestResponseMessage.forIndividual(RecipientUtil.toSignalServiceAddress(context, recipient), localToRemoteType(type)); + } else { + response = null; } - messageSender.sendSyncMessage(SignalServiceSyncMessage.forMessageRequestResponse(response), - UnidentifiedAccessUtil.getAccessForSync(context)); + if (response != null) { + messageSender.sendSyncMessage(SignalServiceSyncMessage.forMessageRequestResponse(response), + UnidentifiedAccessUtil.getAccessForSync(context)); + } else { + Log.w(TAG, recipient.getId() + " not registered!"); + } } private static MessageRequestResponseMessage.Type localToRemoteType(@NonNull Type type) { diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobs/MultiDeviceReadUpdateJob.java b/app/src/main/java/org/thoughtcrime/securesms/jobs/MultiDeviceReadUpdateJob.java index f7eaf78b7..54b78a7f6 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/jobs/MultiDeviceReadUpdateJob.java +++ b/app/src/main/java/org/thoughtcrime/securesms/jobs/MultiDeviceReadUpdateJob.java @@ -8,6 +8,7 @@ import com.fasterxml.jackson.annotation.JsonProperty; import org.signal.core.util.logging.Log; import org.thoughtcrime.securesms.crypto.UnidentifiedAccessUtil; import org.thoughtcrime.securesms.database.MessageDatabase.SyncMessageId; +import org.thoughtcrime.securesms.database.RecipientDatabase; import org.thoughtcrime.securesms.dependencies.ApplicationDependencies; import org.thoughtcrime.securesms.jobmanager.Data; import org.thoughtcrime.securesms.jobmanager.Job; @@ -114,7 +115,7 @@ public class MultiDeviceReadUpdateJob extends BaseJob { for (SerializableSyncMessageId messageId : messageIds) { Recipient recipient = Recipient.resolved(RecipientId.from(messageId.recipientId)); - if (!recipient.isGroup()) { + if (!recipient.isGroup() && recipient.isMaybeRegistered()) { readMessages.add(new ReadMessage(RecipientUtil.toSignalServiceAddress(context, recipient), messageId.timestamp)); } } diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobs/MultiDeviceVerifiedUpdateJob.java b/app/src/main/java/org/thoughtcrime/securesms/jobs/MultiDeviceVerifiedUpdateJob.java index 6b3eede0e..0373a4096 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/jobs/MultiDeviceVerifiedUpdateJob.java +++ b/app/src/main/java/org/thoughtcrime/securesms/jobs/MultiDeviceVerifiedUpdateJob.java @@ -6,6 +6,7 @@ import androidx.annotation.NonNull; import org.signal.core.util.logging.Log; import org.thoughtcrime.securesms.crypto.UnidentifiedAccessUtil; import org.thoughtcrime.securesms.database.IdentityDatabase.VerifiedStatus; +import org.thoughtcrime.securesms.database.RecipientDatabase; import org.thoughtcrime.securesms.dependencies.ApplicationDependencies; import org.thoughtcrime.securesms.jobmanager.Data; import org.thoughtcrime.securesms.jobmanager.Job; @@ -103,11 +104,17 @@ public class MultiDeviceVerifiedUpdateJob extends BaseJob { return; } - SignalServiceMessageSender messageSender = ApplicationDependencies.getSignalServiceMessageSender(); - Recipient recipient = Recipient.resolved(destination); - VerifiedMessage.VerifiedState verifiedState = getVerifiedState(verifiedStatus); - SignalServiceAddress verifiedAddress = RecipientUtil.toSignalServiceAddress(context, recipient); - VerifiedMessage verifiedMessage = new VerifiedMessage(verifiedAddress, new IdentityKey(identityKey, 0), verifiedState, timestamp); + SignalServiceMessageSender messageSender = ApplicationDependencies.getSignalServiceMessageSender(); + Recipient recipient = Recipient.resolved(destination); + + if (recipient.isUnregistered()) { + Log.w(TAG, recipient.getId() + " not registered!"); + return; + } + + VerifiedMessage.VerifiedState verifiedState = getVerifiedState(verifiedStatus); + SignalServiceAddress verifiedAddress = RecipientUtil.toSignalServiceAddress(context, recipient); + VerifiedMessage verifiedMessage = new VerifiedMessage(verifiedAddress, new IdentityKey(identityKey, 0), verifiedState, timestamp); messageSender.sendSyncMessage(SignalServiceSyncMessage.forVerified(verifiedMessage), UnidentifiedAccessUtil.getAccessFor(context, recipient)); diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobs/MultiDeviceViewOnceOpenJob.java b/app/src/main/java/org/thoughtcrime/securesms/jobs/MultiDeviceViewOnceOpenJob.java index 269ded31c..faa8316a4 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/jobs/MultiDeviceViewOnceOpenJob.java +++ b/app/src/main/java/org/thoughtcrime/securesms/jobs/MultiDeviceViewOnceOpenJob.java @@ -7,6 +7,7 @@ import com.fasterxml.jackson.annotation.JsonProperty; import org.signal.core.util.logging.Log; import org.thoughtcrime.securesms.crypto.UnidentifiedAccessUtil; import org.thoughtcrime.securesms.database.MessageDatabase.SyncMessageId; +import org.thoughtcrime.securesms.database.RecipientDatabase; import org.thoughtcrime.securesms.dependencies.ApplicationDependencies; import org.thoughtcrime.securesms.jobmanager.Data; import org.thoughtcrime.securesms.jobmanager.Job; @@ -83,7 +84,13 @@ public class MultiDeviceViewOnceOpenJob extends BaseJob { SignalServiceMessageSender messageSender = ApplicationDependencies.getSignalServiceMessageSender(); Recipient recipient = Recipient.resolved(RecipientId.from(messageId.recipientId)); - ViewOnceOpenMessage openMessage = new ViewOnceOpenMessage(RecipientUtil.toSignalServiceAddress(context, recipient), messageId.timestamp); + + if (recipient.isUnregistered()) { + Log.w(TAG, recipient.getId() + " not registered!"); + return; + } + + ViewOnceOpenMessage openMessage = new ViewOnceOpenMessage(RecipientUtil.toSignalServiceAddress(context, recipient), messageId.timestamp); messageSender.sendSyncMessage(SignalServiceSyncMessage.forViewOnceOpen(openMessage), UnidentifiedAccessUtil.getAccessForSync(context)); } diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobs/MultiDeviceViewedUpdateJob.java b/app/src/main/java/org/thoughtcrime/securesms/jobs/MultiDeviceViewedUpdateJob.java index bca65d88b..5c0951849 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/jobs/MultiDeviceViewedUpdateJob.java +++ b/app/src/main/java/org/thoughtcrime/securesms/jobs/MultiDeviceViewedUpdateJob.java @@ -8,6 +8,7 @@ import com.fasterxml.jackson.annotation.JsonProperty; import org.signal.core.util.logging.Log; import org.thoughtcrime.securesms.crypto.UnidentifiedAccessUtil; import org.thoughtcrime.securesms.database.MessageDatabase.SyncMessageId; +import org.thoughtcrime.securesms.database.RecipientDatabase; import org.thoughtcrime.securesms.dependencies.ApplicationDependencies; import org.thoughtcrime.securesms.jobmanager.Data; import org.thoughtcrime.securesms.jobmanager.Job; @@ -114,7 +115,7 @@ public class MultiDeviceViewedUpdateJob extends BaseJob { for (SerializableSyncMessageId messageId : messageIds) { Recipient recipient = Recipient.resolved(RecipientId.from(messageId.recipientId)); - if (!recipient.isGroup()) { + if (!recipient.isGroup() && recipient.isMaybeRegistered()) { viewedMessages.add(new ViewedMessage(RecipientUtil.toSignalServiceAddress(context, recipient), messageId.timestamp)); } } diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobs/NullMessageSendJob.java b/app/src/main/java/org/thoughtcrime/securesms/jobs/NullMessageSendJob.java index ad5b07331..82cadc60d 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/jobs/NullMessageSendJob.java +++ b/app/src/main/java/org/thoughtcrime/securesms/jobs/NullMessageSendJob.java @@ -4,6 +4,7 @@ import androidx.annotation.NonNull; import org.signal.core.util.logging.Log; import org.thoughtcrime.securesms.crypto.UnidentifiedAccessUtil; +import org.thoughtcrime.securesms.database.RecipientDatabase; import org.thoughtcrime.securesms.dependencies.ApplicationDependencies; import org.thoughtcrime.securesms.jobmanager.Data; import org.thoughtcrime.securesms.jobmanager.Job; @@ -67,6 +68,10 @@ public class NullMessageSendJob extends BaseJob { return; } + if (recipient.isUnregistered()) { + Log.w(TAG, recipient.getId() + " not registered!"); + } + SignalServiceMessageSender messageSender = ApplicationDependencies.getSignalServiceMessageSender(); SignalServiceAddress address = RecipientUtil.toSignalServiceAddress(context, recipient); Optional unidentifiedAccess = UnidentifiedAccessUtil.getAccessFor(context, recipient); diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobs/PaymentNotificationSendJob.java b/app/src/main/java/org/thoughtcrime/securesms/jobs/PaymentNotificationSendJob.java index 7c72008b2..0d159d8c1 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/jobs/PaymentNotificationSendJob.java +++ b/app/src/main/java/org/thoughtcrime/securesms/jobs/PaymentNotificationSendJob.java @@ -81,8 +81,14 @@ public final class PaymentNotificationSendJob extends BaseJob { throw new NotPushRegisteredException(); } - PaymentDatabase paymentDatabase = DatabaseFactory.getPaymentDatabase(context); - Recipient recipient = Recipient.resolved(recipientId); + PaymentDatabase paymentDatabase = DatabaseFactory.getPaymentDatabase(context); + Recipient recipient = Recipient.resolved(recipientId); + + if (recipient.isUnregistered()) { + Log.w(TAG, recipientId + " not registered!"); + return; + } + SignalServiceMessageSender messageSender = ApplicationDependencies.getSignalServiceMessageSender(); SignalServiceAddress address = RecipientUtil.toSignalServiceAddress(context, recipient); Optional unidentifiedAccess = UnidentifiedAccessUtil.getAccessFor(context, recipient); diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobs/PushGroupUpdateJob.java b/app/src/main/java/org/thoughtcrime/securesms/jobs/PushGroupUpdateJob.java index 3ae92bbaf..58d9a2ec6 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/jobs/PushGroupUpdateJob.java +++ b/app/src/main/java/org/thoughtcrime/securesms/jobs/PushGroupUpdateJob.java @@ -82,6 +82,13 @@ public class PushGroupUpdateJob extends BaseJob { throw new NotPushRegisteredException(); } + Recipient sourceRecipient = Recipient.resolved(source); + + if (sourceRecipient.isUnregistered()) { + Log.w(TAG, sourceRecipient.getId() + " not registered!"); + return; + } + GroupDatabase groupDatabase = DatabaseFactory.getGroupDatabase(context); Optional record = groupDatabase.getGroup(groupId); SignalServiceAttachment avatar = null; @@ -103,7 +110,10 @@ public class PushGroupUpdateJob extends BaseJob { for (RecipientId member : record.get().getMembers()) { Recipient recipient = Recipient.resolved(member); - members.add(RecipientUtil.toSignalServiceAddress(context, recipient)); + + if (recipient.isMaybeRegistered()) { + members.add(RecipientUtil.toSignalServiceAddress(context, recipient)); + } } SignalServiceGroup groupContext = SignalServiceGroup.newBuilder(Type.UPDATE) @@ -123,10 +133,9 @@ public class PushGroupUpdateJob extends BaseJob { .build(); SignalServiceMessageSender messageSender = ApplicationDependencies.getSignalServiceMessageSender(); - Recipient recipient = Recipient.resolved(source); - messageSender.sendDataMessage(RecipientUtil.toSignalServiceAddress(context, recipient), - UnidentifiedAccessUtil.getAccessFor(context, recipient), + messageSender.sendDataMessage(RecipientUtil.toSignalServiceAddress(context, sourceRecipient), + UnidentifiedAccessUtil.getAccessFor(context, sourceRecipient), ContentHint.DEFAULT, message); } diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobs/PushMediaSendJob.java b/app/src/main/java/org/thoughtcrime/securesms/jobs/PushMediaSendJob.java index 8b10ca374..98bcff806 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/jobs/PushMediaSendJob.java +++ b/app/src/main/java/org/thoughtcrime/securesms/jobs/PushMediaSendJob.java @@ -196,7 +196,12 @@ public class PushMediaSendJob extends PushSendJob { try { rotateSenderCertificateIfNecessary(); - Recipient messageRecipient = message.getRecipient().fresh(); + Recipient messageRecipient = message.getRecipient().fresh(); + + if (messageRecipient.isUnregistered()) { + throw new UndeliverableMessageException(messageRecipient.getId() + " not registered!"); + } + SignalServiceMessageSender messageSender = ApplicationDependencies.getSignalServiceMessageSender(); SignalServiceAddress address = RecipientUtil.toSignalServiceAddress(context, messageRecipient); List attachments = Stream.of(message.getAttachments()).filterNot(Attachment::isSticker).toList(); diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobs/PushSendJob.java b/app/src/main/java/org/thoughtcrime/securesms/jobs/PushSendJob.java index 0bdf453b7..e6e3c8b5e 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/jobs/PushSendJob.java +++ b/app/src/main/java/org/thoughtcrime/securesms/jobs/PushSendJob.java @@ -355,9 +355,14 @@ public abstract class PushSendJob extends SendJob { } } - Recipient quoteAuthorRecipient = Recipient.resolved(quoteAuthor); - SignalServiceAddress quoteAddress = RecipientUtil.toSignalServiceAddress(context, quoteAuthorRecipient); - return Optional.of(new SignalServiceDataMessage.Quote(quoteId, quoteAddress, quoteBody, quoteAttachments, quoteMentions)); + Recipient quoteAuthorRecipient = Recipient.resolved(quoteAuthor); + + if (quoteAuthorRecipient.isMaybeRegistered()) { + SignalServiceAddress quoteAddress = RecipientUtil.toSignalServiceAddress(context, quoteAuthorRecipient); + return Optional.of(new SignalServiceDataMessage.Quote(quoteId, quoteAddress, quoteBody, quoteAttachments, quoteMentions)); + } else { + return Optional.absent(); + } } protected Optional getStickerFor(OutgoingMediaMessage message) { diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobs/PushTextSendJob.java b/app/src/main/java/org/thoughtcrime/securesms/jobs/PushTextSendJob.java index 1f851db33..534c605ae 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/jobs/PushTextSendJob.java +++ b/app/src/main/java/org/thoughtcrime/securesms/jobs/PushTextSendJob.java @@ -167,7 +167,12 @@ public class PushTextSendJob extends PushSendJob { try { rotateSenderCertificateIfNecessary(); - Recipient messageRecipient = message.getIndividualRecipient().fresh(); + Recipient messageRecipient = message.getIndividualRecipient().fresh(); + + if (messageRecipient.isUnregistered()) { + throw new UndeliverableMessageException(messageRecipient.getId() + " not registered!"); + } + SignalServiceMessageSender messageSender = ApplicationDependencies.getSignalServiceMessageSender(); SignalServiceAddress address = RecipientUtil.toSignalServiceAddress(context, messageRecipient); Optional profileKey = getProfileKey(messageRecipient); diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobs/ReactionSendJob.java b/app/src/main/java/org/thoughtcrime/securesms/jobs/ReactionSendJob.java index 8345db03f..10d4d67a7 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/jobs/ReactionSendJob.java +++ b/app/src/main/java/org/thoughtcrime/securesms/jobs/ReactionSendJob.java @@ -39,6 +39,7 @@ import org.whispersystems.signalservice.api.push.exceptions.ServerRejectedExcept import java.io.IOException; import java.util.List; import java.util.concurrent.TimeUnit; +import java.util.stream.Collectors; public class ReactionSendJob extends BaseJob { @@ -177,12 +178,13 @@ public class ReactionSendJob extends BaseJob { return; } - List destinations = Stream.of(recipients).map(Recipient::resolved).toList(); - List completions = deliver(conversationRecipient, destinations, targetAuthor, targetSentTimestamp); + List resolved = Stream.of(recipients).map(Recipient::resolved).toList(); + List unregistered = resolved.stream().filter(Recipient::isUnregistered).map(Recipient::getId).collect(Collectors.toList()); + List destinations = resolved.stream().filter(Recipient::isMaybeRegistered).collect(Collectors.toList()); + List completions = deliver(conversationRecipient, destinations, targetAuthor, targetSentTimestamp); - for (Recipient completion : completions) { - recipients.remove(completion.getId()); - } + recipients.removeAll(unregistered); + recipients.removeAll(completions.stream().map(Recipient::getId).collect(Collectors.toList())); Log.i(TAG, "Completed now: " + completions.size() + ", Remaining: " + recipients.size()); diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobs/RequestGroupInfoJob.java b/app/src/main/java/org/thoughtcrime/securesms/jobs/RequestGroupInfoJob.java index 8e1c6a2bd..1aaf4781f 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/jobs/RequestGroupInfoJob.java +++ b/app/src/main/java/org/thoughtcrime/securesms/jobs/RequestGroupInfoJob.java @@ -86,6 +86,11 @@ public class RequestGroupInfoJob extends BaseJob { SignalServiceMessageSender messageSender = ApplicationDependencies.getSignalServiceMessageSender(); Recipient recipient = Recipient.resolved(source); + if (recipient.isUnregistered()) { + Log.w(TAG, recipient.getId() + " is unregistered!"); + return; + } + messageSender.sendDataMessage(RecipientUtil.toSignalServiceAddress(context, recipient), UnidentifiedAccessUtil.getAccessFor(context, recipient), ContentHint.IMPLICIT, diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobs/ResendMessageJob.java b/app/src/main/java/org/thoughtcrime/securesms/jobs/ResendMessageJob.java index d8042f84c..bb74b40f1 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/jobs/ResendMessageJob.java +++ b/app/src/main/java/org/thoughtcrime/securesms/jobs/ResendMessageJob.java @@ -125,8 +125,14 @@ public class ResendMessageJob extends BaseJob { ThreadUtil.sleep(10000); } - SignalServiceMessageSender messageSender = ApplicationDependencies.getSignalServiceMessageSender(); - Recipient recipient = Recipient.resolved(recipientId); + SignalServiceMessageSender messageSender = ApplicationDependencies.getSignalServiceMessageSender(); + Recipient recipient = Recipient.resolved(recipientId); + + if (recipient.isUnregistered()) { + Log.w(TAG, recipient.getId() + " is unregistered!"); + return; + } + SignalServiceAddress address = RecipientUtil.toSignalServiceAddress(context, recipient); Optional access = UnidentifiedAccessUtil.getAccessFor(context, recipient); Content contentToSend = content; diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobs/SendDeliveryReceiptJob.java b/app/src/main/java/org/thoughtcrime/securesms/jobs/SendDeliveryReceiptJob.java index 02e0efa4e..4acdf2057 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/jobs/SendDeliveryReceiptJob.java +++ b/app/src/main/java/org/thoughtcrime/securesms/jobs/SendDeliveryReceiptJob.java @@ -101,6 +101,12 @@ public class SendDeliveryReceiptJob extends BaseJob { SignalServiceMessageSender messageSender = ApplicationDependencies.getSignalServiceMessageSender(); Recipient recipient = Recipient.resolved(recipientId); + + if (recipient.isUnregistered()) { + Log.w(TAG, recipient.getId() + " is unregistered!"); + return; + } + SignalServiceAddress remoteAddress = RecipientUtil.toSignalServiceAddress(context, recipient); SignalServiceReceiptMessage receiptMessage = new SignalServiceReceiptMessage(SignalServiceReceiptMessage.Type.DELIVERY, Collections.singletonList(messageSentTimestamp), diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobs/SendReadReceiptJob.java b/app/src/main/java/org/thoughtcrime/securesms/jobs/SendReadReceiptJob.java index 953506524..9f7d675f4 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/jobs/SendReadReceiptJob.java +++ b/app/src/main/java/org/thoughtcrime/securesms/jobs/SendReadReceiptJob.java @@ -148,6 +148,7 @@ public class SendReadReceiptJob extends BaseJob { } Recipient recipient = Recipient.resolved(recipientId); + if (recipient.isBlocked()) { Log.w(TAG, "Refusing to send receipts to blocked recipient"); return; @@ -158,6 +159,11 @@ public class SendReadReceiptJob extends BaseJob { return; } + if (recipient.isUnregistered()) { + Log.w(TAG, recipient.getId() + " not registered!"); + return; + } + SignalServiceMessageSender messageSender = ApplicationDependencies.getSignalServiceMessageSender(); SignalServiceAddress remoteAddress = RecipientUtil.toSignalServiceAddress(context, recipient); SignalServiceReceiptMessage receiptMessage = new SignalServiceReceiptMessage(SignalServiceReceiptMessage.Type.READ, messageSentTimestamps, timestamp); diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobs/SendRetryReceiptJob.java b/app/src/main/java/org/thoughtcrime/securesms/jobs/SendRetryReceiptJob.java index d3c237250..ab03b6cd1 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/jobs/SendRetryReceiptJob.java +++ b/app/src/main/java/org/thoughtcrime/securesms/jobs/SendRetryReceiptJob.java @@ -80,7 +80,13 @@ public final class SendRetryReceiptJob extends BaseJob { @Override protected void onRun() throws Exception { - Recipient recipient = Recipient.resolved(recipientId); + Recipient recipient = Recipient.resolved(recipientId); + + if (recipient.isUnregistered()) { + Log.w(TAG, recipient.getId() + " not registered!"); + return; + } + SignalServiceAddress address = RecipientUtil.toSignalServiceAddress(context, recipient); Optional access = UnidentifiedAccessUtil.getAccessFor(context, recipient); Optional group = groupId.transform(GroupId::getDecodedId); diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobs/SendViewedReceiptJob.java b/app/src/main/java/org/thoughtcrime/securesms/jobs/SendViewedReceiptJob.java index 4d9dfb2b3..8d7c2bbf0 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/jobs/SendViewedReceiptJob.java +++ b/app/src/main/java/org/thoughtcrime/securesms/jobs/SendViewedReceiptJob.java @@ -149,6 +149,7 @@ public class SendViewedReceiptJob extends BaseJob { } Recipient recipient = Recipient.resolved(recipientId); + if (recipient.isBlocked()) { Log.w(TAG, "Refusing to send receipts to blocked recipient"); return; @@ -159,6 +160,11 @@ public class SendViewedReceiptJob extends BaseJob { return; } + if (recipient.isUnregistered()) { + Log.w(TAG, recipient.getId() + " not registered!"); + return; + } + SignalServiceMessageSender messageSender = ApplicationDependencies.getSignalServiceMessageSender(); SignalServiceAddress remoteAddress = RecipientUtil.toSignalServiceAddress(context, recipient); SignalServiceReceiptMessage receiptMessage = new SignalServiceReceiptMessage(SignalServiceReceiptMessage.Type.VIEWED, diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobs/SenderKeyDistributionSendJob.java b/app/src/main/java/org/thoughtcrime/securesms/jobs/SenderKeyDistributionSendJob.java index a79721dda..367f9f8ff 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/jobs/SenderKeyDistributionSendJob.java +++ b/app/src/main/java/org/thoughtcrime/securesms/jobs/SenderKeyDistributionSendJob.java @@ -91,6 +91,11 @@ public final class SenderKeyDistributionSendJob extends BaseJob { return; } + if (recipient.isUnregistered()) { + Log.w(TAG, recipient.getId() + " not registered!"); + return; + } + SignalServiceMessageSender messageSender = ApplicationDependencies.getSignalServiceMessageSender(); List address = Collections.singletonList(RecipientUtil.toSignalServiceAddress(context, recipient)); DistributionId distributionId = groupDatabase.getOrCreateDistributionId(groupId); diff --git a/app/src/main/java/org/thoughtcrime/securesms/messages/GroupSendUtil.java b/app/src/main/java/org/thoughtcrime/securesms/messages/GroupSendUtil.java index 79c355d7d..ba07e3b09 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/messages/GroupSendUtil.java +++ b/app/src/main/java/org/thoughtcrime/securesms/messages/GroupSendUtil.java @@ -49,6 +49,7 @@ import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Objects; +import java.util.Set; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicLong; import java.util.stream.Collectors; @@ -137,13 +138,16 @@ public final class GroupSendUtil { @Nullable CancelationSignal cancelationSignal) throws IOException, UntrustedIdentityException { - RecipientData recipients = new RecipientData(context, allTargets); + Set unregisteredTargets = allTargets.stream().filter(Recipient::isUnregistered).collect(Collectors.toSet()); + List registeredTargets = allTargets.stream().filter(r -> !unregisteredTargets.contains(r)).collect(Collectors.toList()); + + RecipientData recipients = new RecipientData(context, registeredTargets); Optional groupRecord = groupId != null ? DatabaseFactory.getGroupDatabase(context).getGroup(groupId) : Optional.absent(); List senderKeyTargets = new LinkedList<>(); List legacyTargets = new LinkedList<>(); - for (Recipient recipient : allTargets) { + for (Recipient recipient : registeredTargets) { Optional access = recipients.getAccessPair(recipient.getId()); boolean validMembership = groupRecord.isPresent() && groupRecord.get().getMembers().contains(recipient.getId()); @@ -262,6 +266,21 @@ public final class GroupSendUtil { Log.d(TAG, "Successfully sent using 1:1 to " + successCount + "/" + targets.size() + " legacy targets."); } + if (unregisteredTargets.size() > 0) { + Log.w(TAG, "There are " + unregisteredTargets.size() + " unregistered targets. Including failure results."); + + List unregisteredResults = unregisteredTargets.stream() + .filter(Recipient::hasUuid) + .map(t -> SendMessageResult.unregisteredFailure(new SignalServiceAddress(t.requireUuid(), t.getE164().orNull()))) + .collect(Collectors.toList()); + + if (unregisteredResults.size() < unregisteredTargets.size()) { + Log.w(TAG, "There are " + (unregisteredTargets.size() - unregisteredResults.size()) + " targets that have no UUID! Cannot report a failure for them."); + } + + allResults.addAll(unregisteredResults); + } + return allResults; } diff --git a/app/src/main/java/org/thoughtcrime/securesms/recipients/Recipient.java b/app/src/main/java/org/thoughtcrime/securesms/recipients/Recipient.java index 29b7003ae..726700690 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/recipients/Recipient.java +++ b/app/src/main/java/org/thoughtcrime/securesms/recipients/Recipient.java @@ -886,6 +886,14 @@ public class Recipient { return registered == RegisteredState.REGISTERED || isPushGroup(); } + public boolean isMaybeRegistered() { + return registered != RegisteredState.NOT_REGISTERED || isPushGroup(); + } + + public boolean isUnregistered() { + return registered == RegisteredState.NOT_REGISTERED && !isPushGroup(); + } + public @Nullable String getNotificationChannel() { return !NotificationChannels.supported() ? null : notificationChannel; } diff --git a/app/src/main/java/org/thoughtcrime/securesms/recipients/RecipientUtil.java b/app/src/main/java/org/thoughtcrime/securesms/recipients/RecipientUtil.java index 197ecd419..03f1938d9 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/recipients/RecipientUtil.java +++ b/app/src/main/java/org/thoughtcrime/securesms/recipients/RecipientUtil.java @@ -28,10 +28,12 @@ import org.thoughtcrime.securesms.sms.MessageSender; import org.thoughtcrime.securesms.storage.StorageSyncHelper; import org.whispersystems.libsignal.util.guava.Optional; import org.whispersystems.signalservice.api.push.SignalServiceAddress; +import org.whispersystems.signalservice.api.push.exceptions.NotFoundException; import java.io.IOException; import java.util.Collection; import java.util.List; +import java.util.stream.Collectors; public class RecipientUtil { @@ -40,7 +42,7 @@ public class RecipientUtil { /** * This method will do it's best to craft a fully-populated {@link SignalServiceAddress} based on * the provided recipient. This includes performing a possible network request if no UUID is - * available. If the request to get a UUID fails, an IOException is thrown. + * available. If the request to get a UUID fails or the user is not registered, an IOException is thrown. */ @WorkerThread public static @NonNull SignalServiceAddress toSignalServiceAddress(@NonNull Context context, @NonNull Recipient recipient) @@ -60,7 +62,11 @@ public class RecipientUtil { Log.i(TAG, "Successfully performed a UUID fetch for " + recipient.getId() + ". Registered: " + state); } - return new SignalServiceAddress(recipient.requireUuid(), Optional.fromNullable(recipient.resolve().getE164().orNull())); + if (recipient.hasUuid()) { + return new SignalServiceAddress(recipient.requireUuid(), Optional.fromNullable(recipient.resolve().getE164().orNull())); + } else { + throw new NotFoundException(recipient.getId() + " is not registered!"); + } } public static @NonNull List toSignalServiceAddresses(@NonNull Context context, @NonNull List recipients) @@ -80,6 +86,9 @@ public class RecipientUtil { .toList(); } + /** + * Ensures that UUIDs are available. If a UUID cannot be retrieved or a user is found to be unregistered, an exception is thrown. + */ public static boolean ensureUuidsAreAvailable(@NonNull Context context, @NonNull Collection recipients) throws IOException { @@ -90,6 +99,11 @@ public class RecipientUtil { if (recipientsWithoutUuids.size() > 0) { DirectoryHelper.refreshDirectoryFor(context, recipientsWithoutUuids, false); + + if (recipients.stream().map(Recipient::resolve).anyMatch(Recipient::isUnregistered)) { + throw new NotFoundException("1 or more recipients are not registered!"); + } + return true; } else { return false; diff --git a/app/src/main/java/org/thoughtcrime/securesms/util/ProfileUtil.java b/app/src/main/java/org/thoughtcrime/securesms/util/ProfileUtil.java index 5c7e36ade..57bdf0dc7 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/util/ProfileUtil.java +++ b/app/src/main/java/org/thoughtcrime/securesms/util/ProfileUtil.java @@ -268,7 +268,11 @@ public final class ProfileUtil { private static @NonNull SignalServiceAddress toSignalServiceAddress(@NonNull Context context, @NonNull Recipient recipient) throws IOException { if (recipient.getRegistered() == RecipientDatabase.RegisteredState.NOT_REGISTERED) { - return new SignalServiceAddress(recipient.getUuid().orNull(), recipient.getE164().orNull()); + if (recipient.hasUuid()) { + return new SignalServiceAddress(recipient.requireUuid(), recipient.getE164().orNull()); + } else { + throw new IOException(recipient.getId() + " not registered!"); + } } else { return RecipientUtil.toSignalServiceAddress(context, recipient); }