Handle ServerRejectedException.

Handle an exception that indicates we should halt retries.
This commit is contained in:
Greyson Parrelli 2021-01-16 00:54:33 -05:00
parent a3c7e7e552
commit c95f0fce6e
15 changed files with 122 additions and 75 deletions

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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<SendMessageResult> deliver(OutgoingMediaMessage message, @NonNull Recipient groupRecipient, @NonNull List<Recipient> destinations)
throws IOException, UntrustedIdentityException, UndeliverableMessageException {
rotateSenderCertificateIfNecessary();
throws IOException, UntrustedIdentityException, UndeliverableMessageException
{
try {
rotateSenderCertificateIfNecessary();
SignalServiceMessageSender messageSender = ApplicationDependencies.getSignalServiceMessageSender();
GroupId.Push groupId = groupRecipient.requireGroupId().requirePush();
Optional<byte[]> profileKey = getProfileKey(groupRecipient);
Optional<Quote> quote = getQuoteFor(message);
Optional<SignalServiceDataMessage.Sticker> sticker = getStickerFor(message);
List<SharedContact> sharedContacts = getSharedContactsFor(message);
List<Preview> previews = getPreviewsFor(message);
List<SignalServiceDataMessage.Mention> mentions = getMentionsFor(message.getMentions());
List<SignalServiceAddress> addresses = RecipientUtil.toSignalServiceAddressesFromResolved(context, destinations);
List<Attachment> attachments = Stream.of(message.getAttachments()).filterNot(Attachment::isSticker).toList();
List<SignalServiceAttachment> 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<byte[]> profileKey = getProfileKey(groupRecipient);
Optional<Quote> quote = getQuoteFor(message);
Optional<SignalServiceDataMessage.Sticker> sticker = getStickerFor(message);
List<SharedContact> sharedContacts = getSharedContactsFor(message);
List<Preview> previews = getPreviewsFor(message);
List<SignalServiceDataMessage.Mention> mentions = getMentionsFor(message.getMentions());
List<SignalServiceAddress> addresses = RecipientUtil.toSignalServiceAddressesFromResolved(context, destinations);
List<Attachment> attachments = Stream.of(message.getAttachments()).filterNot(Attachment::isSticker).toList();
List<SignalServiceAttachment> attachmentPointers = getAttachmentPointersFor(attachments);
boolean isRecipientUpdate = Stream.of(DatabaseFactory.getGroupReceiptDatabase(context).getGroupReceiptInfo(messageId))
.anyMatch(info -> info.getStatus() > GroupReceiptDatabase.STATUS_UNDELIVERED);
List<Optional<UnidentifiedAccessPair>> unidentifiedAccess = UnidentifiedAccessUtil.getAccessFor(context, destinations);
List<Optional<UnidentifiedAccessPair>> 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<SignalServiceAddress> 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<SignalServiceAddress> 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);
}
}

View file

@ -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;
}

View file

@ -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);

View file

@ -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);

View file

@ -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<SendMessageResult> results = messageSender.sendMessage(addresses, unidentifiedAccess, false, dataMessage.build());
return GroupSendJobHelper.getCompletedSends(context, results);

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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());
}

View file

@ -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);
}

View file

@ -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 {
}

View file

@ -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) {