diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobs/GroupCallUpdateSendJob.java b/app/src/main/java/org/thoughtcrime/securesms/jobs/GroupCallUpdateSendJob.java index f3eaf8822..ade00459e 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/jobs/GroupCallUpdateSendJob.java +++ b/app/src/main/java/org/thoughtcrime/securesms/jobs/GroupCallUpdateSendJob.java @@ -23,6 +23,7 @@ import org.whispersystems.signalservice.api.crypto.UntrustedIdentityException; import org.whispersystems.signalservice.api.messages.SendMessageResult; import org.whispersystems.signalservice.api.messages.SignalServiceDataMessage; import org.whispersystems.signalservice.api.push.SignalServiceAddress; +import org.whispersystems.signalservice.api.push.exceptions.ServerRejectedException; import java.io.IOException; import java.util.List; @@ -126,6 +127,7 @@ public class GroupCallUpdateSendJob extends BaseJob { @Override protected boolean onShouldRetry(@NonNull Exception e) { + if (e instanceof ServerRejectedException) return false; return e instanceof IOException || e instanceof RetryLaterException; } diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobs/ProfileKeySendJob.java b/app/src/main/java/org/thoughtcrime/securesms/jobs/ProfileKeySendJob.java index e4ea79de6..3d18ab80b 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/jobs/ProfileKeySendJob.java +++ b/app/src/main/java/org/thoughtcrime/securesms/jobs/ProfileKeySendJob.java @@ -25,6 +25,7 @@ import org.whispersystems.signalservice.api.messages.SendMessageResult; import org.whispersystems.signalservice.api.messages.SignalServiceDataMessage; import org.whispersystems.signalservice.api.messages.SignalServiceGroup; import org.whispersystems.signalservice.api.push.SignalServiceAddress; +import org.whispersystems.signalservice.api.push.exceptions.ServerRejectedException; import java.io.IOException; import java.util.List; @@ -100,6 +101,7 @@ public class ProfileKeySendJob extends BaseJob { @Override protected boolean onShouldRetry(@NonNull Exception e) { + if (e instanceof ServerRejectedException) return false; return e instanceof IOException || e instanceof RetryLaterException; } diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobs/PushGroupSendJob.java b/app/src/main/java/org/thoughtcrime/securesms/jobs/PushGroupSendJob.java index e514ff8a8..cb925e210 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/jobs/PushGroupSendJob.java +++ b/app/src/main/java/org/thoughtcrime/securesms/jobs/PushGroupSendJob.java @@ -55,6 +55,7 @@ import org.whispersystems.signalservice.api.messages.SignalServiceGroup; import org.whispersystems.signalservice.api.messages.SignalServiceGroupV2; import org.whispersystems.signalservice.api.messages.shared.SharedContact; import org.whispersystems.signalservice.api.push.SignalServiceAddress; +import org.whispersystems.signalservice.api.push.exceptions.ServerRejectedException; import org.whispersystems.signalservice.internal.push.SignalServiceProtos.GroupContext; import org.whispersystems.signalservice.internal.push.SignalServiceProtos.GroupContextV2; @@ -288,87 +289,91 @@ public final class PushGroupSendJob extends PushSendJob { } private List deliver(OutgoingMediaMessage message, @NonNull Recipient groupRecipient, @NonNull List destinations) - throws IOException, UntrustedIdentityException, UndeliverableMessageException { - rotateSenderCertificateIfNecessary(); + throws IOException, UntrustedIdentityException, UndeliverableMessageException + { + try { + rotateSenderCertificateIfNecessary(); - SignalServiceMessageSender messageSender = ApplicationDependencies.getSignalServiceMessageSender(); - GroupId.Push groupId = groupRecipient.requireGroupId().requirePush(); - Optional profileKey = getProfileKey(groupRecipient); - Optional quote = getQuoteFor(message); - Optional sticker = getStickerFor(message); - List sharedContacts = getSharedContactsFor(message); - List previews = getPreviewsFor(message); - List mentions = getMentionsFor(message.getMentions()); - List addresses = RecipientUtil.toSignalServiceAddressesFromResolved(context, destinations); - List attachments = Stream.of(message.getAttachments()).filterNot(Attachment::isSticker).toList(); - List attachmentPointers = getAttachmentPointersFor(attachments); - boolean isRecipientUpdate = Stream.of(DatabaseFactory.getGroupReceiptDatabase(context).getGroupReceiptInfo(messageId)) - .anyMatch(info -> info.getStatus() > GroupReceiptDatabase.STATUS_UNDELIVERED); + SignalServiceMessageSender messageSender = ApplicationDependencies.getSignalServiceMessageSender(); + GroupId.Push groupId = groupRecipient.requireGroupId().requirePush(); + Optional profileKey = getProfileKey(groupRecipient); + Optional quote = getQuoteFor(message); + Optional sticker = getStickerFor(message); + List sharedContacts = getSharedContactsFor(message); + List previews = getPreviewsFor(message); + List mentions = getMentionsFor(message.getMentions()); + List addresses = RecipientUtil.toSignalServiceAddressesFromResolved(context, destinations); + List attachments = Stream.of(message.getAttachments()).filterNot(Attachment::isSticker).toList(); + List attachmentPointers = getAttachmentPointersFor(attachments); + boolean isRecipientUpdate = Stream.of(DatabaseFactory.getGroupReceiptDatabase(context).getGroupReceiptInfo(messageId)) + .anyMatch(info -> info.getStatus() > GroupReceiptDatabase.STATUS_UNDELIVERED); - List> unidentifiedAccess = UnidentifiedAccessUtil.getAccessFor(context, destinations); + List> unidentifiedAccess = UnidentifiedAccessUtil.getAccessFor(context, destinations); - if (message.isGroup()) { - OutgoingGroupUpdateMessage groupMessage = (OutgoingGroupUpdateMessage) message; + if (message.isGroup()) { + OutgoingGroupUpdateMessage groupMessage = (OutgoingGroupUpdateMessage) message; - if (groupMessage.isV2Group()) { - MessageGroupContext.GroupV2Properties properties = groupMessage.requireGroupV2Properties(); - GroupContextV2 groupContext = properties.getGroupContext(); - SignalServiceGroupV2.Builder builder = SignalServiceGroupV2.newBuilder(properties.getGroupMasterKey()) - .withRevision(groupContext.getRevision()); + if (groupMessage.isV2Group()) { + MessageGroupContext.GroupV2Properties properties = groupMessage.requireGroupV2Properties(); + GroupContextV2 groupContext = properties.getGroupContext(); + SignalServiceGroupV2.Builder builder = SignalServiceGroupV2.newBuilder(properties.getGroupMasterKey()) + .withRevision(groupContext.getRevision()); - ByteString groupChange = groupContext.getGroupChange(); - if (groupChange != null) { - builder.withSignedGroupChange(groupChange.toByteArray()); - } + ByteString groupChange = groupContext.getGroupChange(); + if (groupChange != null) { + builder.withSignedGroupChange(groupChange.toByteArray()); + } - SignalServiceGroupV2 group = builder.build(); - SignalServiceDataMessage groupDataMessage = SignalServiceDataMessage.newBuilder() - .withTimestamp(message.getSentTimeMillis()) - .withExpiration(groupRecipient.getExpireMessages()) - .asGroupMessage(group) - .build(); - - return messageSender.sendMessage(addresses, unidentifiedAccess, isRecipientUpdate, groupDataMessage); - } else { - MessageGroupContext.GroupV1Properties properties = groupMessage.requireGroupV1Properties(); - - GroupContext groupContext = properties.getGroupContext(); - SignalServiceAttachment avatar = attachmentPointers.isEmpty() ? null : attachmentPointers.get(0); - SignalServiceGroup.Type type = properties.isQuit() ? SignalServiceGroup.Type.QUIT : SignalServiceGroup.Type.UPDATE; - List members = Stream.of(groupContext.getMembersE164List()) - .map(e164 -> new SignalServiceAddress(null, e164)) - .toList(); - SignalServiceGroup group = new SignalServiceGroup(type, groupId.getDecodedId(), groupContext.getName(), members, avatar); - SignalServiceDataMessage groupDataMessage = SignalServiceDataMessage.newBuilder() + SignalServiceGroupV2 group = builder.build(); + SignalServiceDataMessage groupDataMessage = SignalServiceDataMessage.newBuilder() .withTimestamp(message.getSentTimeMillis()) - .withExpiration(message.getRecipient().getExpireMessages()) + .withExpiration(groupRecipient.getExpireMessages()) .asGroupMessage(group) .build(); + return messageSender.sendMessage(addresses, unidentifiedAccess, isRecipientUpdate, groupDataMessage); + } else { + MessageGroupContext.GroupV1Properties properties = groupMessage.requireGroupV1Properties(); - Log.i(TAG, JobLogger.format(this, "Beginning update send.")); - return messageSender.sendMessage(addresses, unidentifiedAccess, isRecipientUpdate, groupDataMessage); + GroupContext groupContext = properties.getGroupContext(); + SignalServiceAttachment avatar = attachmentPointers.isEmpty() ? null : attachmentPointers.get(0); + SignalServiceGroup.Type type = properties.isQuit() ? SignalServiceGroup.Type.QUIT : SignalServiceGroup.Type.UPDATE; + List members = Stream.of(groupContext.getMembersE164List()) + .map(e164 -> new SignalServiceAddress(null, e164)) + .toList(); + SignalServiceGroup group = new SignalServiceGroup(type, groupId.getDecodedId(), groupContext.getName(), members, avatar); + SignalServiceDataMessage groupDataMessage = SignalServiceDataMessage.newBuilder() + .withTimestamp(message.getSentTimeMillis()) + .withExpiration(message.getRecipient().getExpireMessages()) + .asGroupMessage(group) + .build(); + + Log.i(TAG, JobLogger.format(this, "Beginning update send.")); + return messageSender.sendMessage(addresses, unidentifiedAccess, isRecipientUpdate, groupDataMessage); + } + } else { + SignalServiceDataMessage.Builder builder = SignalServiceDataMessage.newBuilder() + .withTimestamp(message.getSentTimeMillis()); + + GroupUtil.setDataMessageGroupContext(context, builder, groupId); + + SignalServiceDataMessage groupMessage = builder.withAttachments(attachmentPointers) + .withBody(message.getBody()) + .withExpiration((int)(message.getExpiresIn() / 1000)) + .withViewOnce(message.isViewOnce()) + .asExpirationUpdate(message.isExpirationUpdate()) + .withProfileKey(profileKey.orNull()) + .withQuote(quote.orNull()) + .withSticker(sticker.orNull()) + .withSharedContacts(sharedContacts) + .withPreviews(previews) + .withMentions(mentions) + .build(); + + Log.i(TAG, JobLogger.format(this, "Beginning message send.")); + return messageSender.sendMessage(addresses, unidentifiedAccess, isRecipientUpdate, groupMessage); } - } else { - SignalServiceDataMessage.Builder builder = SignalServiceDataMessage.newBuilder() - .withTimestamp(message.getSentTimeMillis()); - - GroupUtil.setDataMessageGroupContext(context, builder, groupId); - - SignalServiceDataMessage groupMessage = builder.withAttachments(attachmentPointers) - .withBody(message.getBody()) - .withExpiration((int)(message.getExpiresIn() / 1000)) - .withViewOnce(message.isViewOnce()) - .asExpirationUpdate(message.isExpirationUpdate()) - .withProfileKey(profileKey.orNull()) - .withQuote(quote.orNull()) - .withSticker(sticker.orNull()) - .withSharedContacts(sharedContacts) - .withPreviews(previews) - .withMentions(mentions) - .build(); - - Log.i(TAG, JobLogger.format(this, "Beginning message send.")); - return messageSender.sendMessage(addresses, unidentifiedAccess, isRecipientUpdate, groupMessage); + } catch (ServerRejectedException e) { + throw new UndeliverableMessageException(e); } } diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobs/PushGroupSilentUpdateSendJob.java b/app/src/main/java/org/thoughtcrime/securesms/jobs/PushGroupSilentUpdateSendJob.java index dc3689a4d..928785cb1 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/jobs/PushGroupSilentUpdateSendJob.java +++ b/app/src/main/java/org/thoughtcrime/securesms/jobs/PushGroupSilentUpdateSendJob.java @@ -33,6 +33,7 @@ import org.whispersystems.signalservice.api.messages.SendMessageResult; import org.whispersystems.signalservice.api.messages.SignalServiceDataMessage; import org.whispersystems.signalservice.api.messages.SignalServiceGroupV2; import org.whispersystems.signalservice.api.push.SignalServiceAddress; +import org.whispersystems.signalservice.api.push.exceptions.ServerRejectedException; import org.whispersystems.signalservice.api.util.UuidUtil; import org.whispersystems.signalservice.internal.push.SignalServiceProtos; @@ -144,6 +145,7 @@ public final class PushGroupSilentUpdateSendJob extends BaseJob { @Override protected boolean onShouldRetry(@NonNull Exception e) { + if (e instanceof ServerRejectedException) return false; return e instanceof IOException || e instanceof RetryLaterException; } 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 ed1223d28..243801e92 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/jobs/PushMediaSendJob.java +++ b/app/src/main/java/org/thoughtcrime/securesms/jobs/PushMediaSendJob.java @@ -41,6 +41,7 @@ import org.whispersystems.signalservice.api.messages.SignalServiceDataMessage.Pr import org.whispersystems.signalservice.api.messages.multidevice.SignalServiceSyncMessage; import org.whispersystems.signalservice.api.messages.shared.SharedContact; import org.whispersystems.signalservice.api.push.SignalServiceAddress; +import org.whispersystems.signalservice.api.push.exceptions.ServerRejectedException; import org.whispersystems.signalservice.api.push.exceptions.UnregisteredUserException; import java.io.FileNotFoundException; @@ -236,6 +237,8 @@ public class PushMediaSendJob extends PushSendJob { } catch (FileNotFoundException e) { warn(TAG, String.valueOf(message.getSentTimeMillis()), e); throw new UndeliverableMessageException(e); + } catch (ServerRejectedException e) { + throw new UndeliverableMessageException(e); } catch (IOException e) { warn(TAG, String.valueOf(message.getSentTimeMillis()), e); throw new RetryLaterException(e); 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 eedaf9658..95c16fbae 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/jobs/PushTextSendJob.java +++ b/app/src/main/java/org/thoughtcrime/securesms/jobs/PushTextSendJob.java @@ -19,6 +19,7 @@ import org.thoughtcrime.securesms.recipients.RecipientUtil; import org.thoughtcrime.securesms.service.ExpiringMessageManager; import org.thoughtcrime.securesms.transport.InsecureFallbackApprovalException; import org.thoughtcrime.securesms.transport.RetryLaterException; +import org.thoughtcrime.securesms.transport.UndeliverableMessageException; import org.thoughtcrime.securesms.util.TextSecurePreferences; import org.thoughtcrime.securesms.util.Util; import org.whispersystems.libsignal.util.guava.Optional; @@ -28,6 +29,7 @@ import org.whispersystems.signalservice.api.crypto.UntrustedIdentityException; import org.whispersystems.signalservice.api.messages.SignalServiceDataMessage; import org.whispersystems.signalservice.api.messages.multidevice.SignalServiceSyncMessage; import org.whispersystems.signalservice.api.push.SignalServiceAddress; +import org.whispersystems.signalservice.api.push.exceptions.ServerRejectedException; import org.whispersystems.signalservice.api.push.exceptions.UnregisteredUserException; import java.io.IOException; @@ -67,7 +69,7 @@ public class PushTextSendJob extends PushSendJob { } @Override - public void onPushSend() throws NoSuchMessageException, RetryLaterException { + public void onPushSend() throws NoSuchMessageException, RetryLaterException, UndeliverableMessageException { ExpiringMessageManager expirationManager = ApplicationContext.getInstance(context).getExpiringMessageManager(); MessageDatabase database = DatabaseFactory.getSmsDatabase(context); SmsMessageRecord record = database.getSmsMessage(messageId); @@ -150,7 +152,7 @@ public class PushTextSendJob extends PushSendJob { } private boolean deliver(SmsMessageRecord message) - throws UntrustedIdentityException, InsecureFallbackApprovalException, RetryLaterException + throws UntrustedIdentityException, InsecureFallbackApprovalException, RetryLaterException, UndeliverableMessageException { try { rotateSenderCertificateIfNecessary(); @@ -183,6 +185,8 @@ public class PushTextSendJob extends PushSendJob { } catch (UnregisteredUserException e) { warn(TAG, "Failure", e); throw new InsecureFallbackApprovalException(e); + } catch (ServerRejectedException e) { + throw new UndeliverableMessageException(e); } catch (IOException e) { warn(TAG, "Failure", e); throw new RetryLaterException(e); 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 8221d57a3..bec6170ca 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/jobs/ReactionSendJob.java +++ b/app/src/main/java/org/thoughtcrime/securesms/jobs/ReactionSendJob.java @@ -29,6 +29,7 @@ import org.whispersystems.signalservice.api.crypto.UntrustedIdentityException; import org.whispersystems.signalservice.api.messages.SendMessageResult; import org.whispersystems.signalservice.api.messages.SignalServiceDataMessage; import org.whispersystems.signalservice.api.push.SignalServiceAddress; +import org.whispersystems.signalservice.api.push.exceptions.ServerRejectedException; import java.io.IOException; import java.util.List; @@ -179,6 +180,7 @@ public class ReactionSendJob extends BaseJob { @Override protected boolean onShouldRetry(@NonNull Exception e) { + if (e instanceof ServerRejectedException) return false; return e instanceof IOException || e instanceof RetryLaterException; } @@ -219,7 +221,6 @@ public class ReactionSendJob extends BaseJob { GroupUtil.setDataMessageGroupContext(context, dataMessage, conversationRecipient.requireGroupId().requirePush()); } - List results = messageSender.sendMessage(addresses, unidentifiedAccess, false, dataMessage.build()); return GroupSendJobHelper.getCompletedSends(context, results); diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobs/RemoteDeleteSendJob.java b/app/src/main/java/org/thoughtcrime/securesms/jobs/RemoteDeleteSendJob.java index 876c600cc..234cc84da 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/jobs/RemoteDeleteSendJob.java +++ b/app/src/main/java/org/thoughtcrime/securesms/jobs/RemoteDeleteSendJob.java @@ -28,6 +28,7 @@ import org.whispersystems.signalservice.api.crypto.UntrustedIdentityException; import org.whispersystems.signalservice.api.messages.SendMessageResult; import org.whispersystems.signalservice.api.messages.SignalServiceDataMessage; import org.whispersystems.signalservice.api.push.SignalServiceAddress; +import org.whispersystems.signalservice.api.push.exceptions.ServerRejectedException; import java.io.IOException; import java.util.List; @@ -152,6 +153,7 @@ public class RemoteDeleteSendJob extends BaseJob { @Override protected boolean onShouldRetry(@NonNull Exception e) { + if (e instanceof ServerRejectedException) return false; return e instanceof IOException || e instanceof RetryLaterException; } 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 4d8c559bf..df7a7bb28 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/jobs/SendDeliveryReceiptJob.java +++ b/app/src/main/java/org/thoughtcrime/securesms/jobs/SendDeliveryReceiptJob.java @@ -12,11 +12,13 @@ import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraint; import org.thoughtcrime.securesms.recipients.Recipient; import org.thoughtcrime.securesms.recipients.RecipientId; import org.thoughtcrime.securesms.recipients.RecipientUtil; +import org.thoughtcrime.securesms.transport.UndeliverableMessageException; import org.whispersystems.signalservice.api.SignalServiceMessageSender; import org.whispersystems.signalservice.api.crypto.UntrustedIdentityException; import org.whispersystems.signalservice.api.messages.SignalServiceReceiptMessage; import org.whispersystems.signalservice.api.push.SignalServiceAddress; import org.whispersystems.signalservice.api.push.exceptions.PushNetworkException; +import org.whispersystems.signalservice.api.push.exceptions.ServerRejectedException; import java.io.IOException; import java.util.Collections; @@ -73,7 +75,7 @@ public class SendDeliveryReceiptJob extends BaseJob { } @Override - public void onRun() throws IOException, UntrustedIdentityException { + public void onRun() throws IOException, UntrustedIdentityException, UndeliverableMessageException { SignalServiceMessageSender messageSender = ApplicationDependencies.getSignalServiceMessageSender(); Recipient recipient = Recipient.resolved(recipientId); SignalServiceAddress remoteAddress = RecipientUtil.toSignalServiceAddress(context, recipient); @@ -88,6 +90,7 @@ public class SendDeliveryReceiptJob extends BaseJob { @Override public boolean onShouldRetry(@NonNull Exception e) { + if (e instanceof ServerRejectedException) return false; if (e instanceof PushNetworkException) return true; return false; } 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 d3ba4e663..61714089b 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/jobs/SendReadReceiptJob.java +++ b/app/src/main/java/org/thoughtcrime/securesms/jobs/SendReadReceiptJob.java @@ -15,6 +15,7 @@ import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraint; import org.thoughtcrime.securesms.recipients.Recipient; import org.thoughtcrime.securesms.recipients.RecipientId; import org.thoughtcrime.securesms.recipients.RecipientUtil; +import org.thoughtcrime.securesms.transport.UndeliverableMessageException; import org.thoughtcrime.securesms.util.TextSecurePreferences; import org.thoughtcrime.securesms.util.Util; import org.whispersystems.signalservice.api.SignalServiceMessageSender; @@ -22,6 +23,7 @@ import org.whispersystems.signalservice.api.crypto.UntrustedIdentityException; import org.whispersystems.signalservice.api.messages.SignalServiceReceiptMessage; import org.whispersystems.signalservice.api.push.SignalServiceAddress; import org.whispersystems.signalservice.api.push.exceptions.PushNetworkException; +import org.whispersystems.signalservice.api.push.exceptions.ServerRejectedException; import java.io.IOException; import java.util.ArrayList; @@ -110,7 +112,7 @@ public class SendReadReceiptJob extends BaseJob { } @Override - public void onRun() throws IOException, UntrustedIdentityException { + public void onRun() throws IOException, UntrustedIdentityException, UndeliverableMessageException { if (!TextSecurePreferences.isReadReceiptsEnabled(context) || messageIds.isEmpty()) return; if (!RecipientUtil.isMessageRequestAccepted(context, threadId)) { @@ -140,6 +142,7 @@ public class SendReadReceiptJob extends BaseJob { @Override public boolean onShouldRetry(@NonNull Exception e) { + if (e instanceof ServerRejectedException) return false; if (e instanceof PushNetworkException) return true; return false; } 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 44dff8dfb..d99ab79c7 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/jobs/SendViewedReceiptJob.java +++ b/app/src/main/java/org/thoughtcrime/securesms/jobs/SendViewedReceiptJob.java @@ -21,6 +21,7 @@ import org.whispersystems.signalservice.api.crypto.UntrustedIdentityException; import org.whispersystems.signalservice.api.messages.SignalServiceReceiptMessage; import org.whispersystems.signalservice.api.push.SignalServiceAddress; import org.whispersystems.signalservice.api.push.exceptions.PushNetworkException; +import org.whispersystems.signalservice.api.push.exceptions.ServerRejectedException; import java.io.IOException; import java.util.Collections; @@ -121,6 +122,7 @@ public class SendViewedReceiptJob extends BaseJob { @Override public boolean onShouldRetry(@NonNull Exception e) { + if (e instanceof ServerRejectedException) return false; if (e instanceof PushNetworkException) return true; return false; } diff --git a/libsignal/service/src/main/java/org/whispersystems/signalservice/api/SignalServiceMessagePipe.java b/libsignal/service/src/main/java/org/whispersystems/signalservice/api/SignalServiceMessagePipe.java index a1ea81d97..c7dea7a21 100644 --- a/libsignal/service/src/main/java/org/whispersystems/signalservice/api/SignalServiceMessagePipe.java +++ b/libsignal/service/src/main/java/org/whispersystems/signalservice/api/SignalServiceMessagePipe.java @@ -26,6 +26,7 @@ import org.whispersystems.signalservice.api.profiles.SignalServiceProfile; import org.whispersystems.signalservice.api.push.SignalServiceAddress; import org.whispersystems.signalservice.api.push.exceptions.NonSuccessfulResponseCodeException; import org.whispersystems.signalservice.api.push.exceptions.NotFoundException; +import org.whispersystems.signalservice.api.push.exceptions.ServerRejectedException; import org.whispersystems.signalservice.api.push.exceptions.UnregisteredUserException; import org.whispersystems.signalservice.api.util.CredentialsProvider; import org.whispersystems.signalservice.internal.push.AttachmentV2UploadAttributes; @@ -200,6 +201,8 @@ public class SignalServiceMessagePipe { return FutureTransformers.map(response, value -> { if (value.getStatus() == 404) { throw new UnregisteredUserException(list.getDestination(), new NotFoundException("not found")); + } else if (value.getStatus() == 508) { + throw new ServerRejectedException(); } else if (value.getStatus() < 200 || value.getStatus() >= 300) { throw new IOException("Non-successful response: " + value.getStatus()); } diff --git a/libsignal/service/src/main/java/org/whispersystems/signalservice/api/SignalServiceMessageSender.java b/libsignal/service/src/main/java/org/whispersystems/signalservice/api/SignalServiceMessageSender.java index edeff33a8..79c589882 100644 --- a/libsignal/service/src/main/java/org/whispersystems/signalservice/api/SignalServiceMessageSender.java +++ b/libsignal/service/src/main/java/org/whispersystems/signalservice/api/SignalServiceMessageSender.java @@ -53,6 +53,7 @@ import org.whispersystems.signalservice.api.push.SignalServiceAddress; import org.whispersystems.signalservice.api.push.exceptions.AuthorizationFailedException; import org.whispersystems.signalservice.api.push.exceptions.NonSuccessfulResponseCodeException; import org.whispersystems.signalservice.api.push.exceptions.PushNetworkException; +import org.whispersystems.signalservice.api.push.exceptions.ServerRejectedException; import org.whispersystems.signalservice.api.push.exceptions.UnregisteredUserException; import org.whispersystems.signalservice.api.util.CredentialsProvider; import org.whispersystems.signalservice.internal.configuration.SignalServiceConfiguration; @@ -1312,6 +1313,9 @@ public class SignalServiceMessageSender { } else if (e.getCause() instanceof PushNetworkException) { Log.w(TAG, e); results.add(SendMessageResult.networkFailure(recipient)); + } else if (e.getCause() instanceof ServerRejectedException) { + Log.w(TAG, e); + throw ((ServerRejectedException) e.getCause()); } else { throw new IOException(e); } diff --git a/libsignal/service/src/main/java/org/whispersystems/signalservice/api/push/exceptions/ServerRejectedException.java b/libsignal/service/src/main/java/org/whispersystems/signalservice/api/push/exceptions/ServerRejectedException.java new file mode 100644 index 000000000..2b26c9c6e --- /dev/null +++ b/libsignal/service/src/main/java/org/whispersystems/signalservice/api/push/exceptions/ServerRejectedException.java @@ -0,0 +1,7 @@ +package org.whispersystems.signalservice.api.push.exceptions; + +/** + * Indicates the server has rejected the request and we should stop retrying. + */ +public class ServerRejectedException extends NonSuccessfulResponseCodeException { +} diff --git a/libsignal/service/src/main/java/org/whispersystems/signalservice/internal/push/PushServiceSocket.java b/libsignal/service/src/main/java/org/whispersystems/signalservice/internal/push/PushServiceSocket.java index a700081a7..e61b6d948 100644 --- a/libsignal/service/src/main/java/org/whispersystems/signalservice/internal/push/PushServiceSocket.java +++ b/libsignal/service/src/main/java/org/whispersystems/signalservice/internal/push/PushServiceSocket.java @@ -63,6 +63,7 @@ import org.whispersystems.signalservice.api.push.exceptions.RangeException; import org.whispersystems.signalservice.api.push.exceptions.RateLimitException; import org.whispersystems.signalservice.api.push.exceptions.RemoteAttestationResponseExpiredException; import org.whispersystems.signalservice.api.push.exceptions.ResumeLocationInvalidException; +import org.whispersystems.signalservice.api.push.exceptions.ServerRejectedException; import org.whispersystems.signalservice.api.push.exceptions.UnregisteredUserException; import org.whispersystems.signalservice.api.push.exceptions.UsernameMalformedException; import org.whispersystems.signalservice.api.push.exceptions.UsernameTakenException; @@ -1434,6 +1435,9 @@ public class PushServiceSocket { basicStorageCredentials); case 499: throw new DeprecatedVersionException(); + + case 508: + throw new ServerRejectedException(); } if (responseCode != 200 && responseCode != 204) {