Search in sources :

Example 6 with ServerRejectedException

use of org.whispersystems.signalservice.api.push.exceptions.ServerRejectedException in project Signal-Android by WhisperSystems.

the class PushServiceSocket method validateServiceResponse.

private Response validateServiceResponse(Response response) throws NonSuccessfulResponseCodeException, PushNetworkException, MalformedResponseException {
    int responseCode = response.code();
    String responseMessage = response.message();
    switch(responseCode) {
        case 413:
            throw new RateLimitException("Rate limit exceeded: " + responseCode);
        case 401:
        case 403:
            throw new AuthorizationFailedException(responseCode, "Authorization failed!");
        case 404:
            throw new NotFoundException("Not found");
        case 409:
            MismatchedDevices mismatchedDevices = readResponseJson(response, MismatchedDevices.class);
            throw new MismatchedDevicesException(mismatchedDevices);
        case 410:
            StaleDevices staleDevices = readResponseJson(response, StaleDevices.class);
            throw new StaleDevicesException(staleDevices);
        case 411:
            DeviceLimit deviceLimit = readResponseJson(response, DeviceLimit.class);
            throw new DeviceLimitExceededException(deviceLimit);
        case 417:
            throw new ExpectationFailedException();
        case 423:
            RegistrationLockFailure accountLockFailure = readResponseJson(response, RegistrationLockFailure.class);
            AuthCredentials credentials = accountLockFailure.backupCredentials;
            String basicStorageCredentials = credentials != null ? credentials.asBasic() : null;
            throw new LockedException(accountLockFailure.length, accountLockFailure.timeRemaining, basicStorageCredentials);
        case 428:
            ProofRequiredResponse proofRequiredResponse = readResponseJson(response, ProofRequiredResponse.class);
            String retryAfterRaw = response.header("Retry-After");
            long retryAfter = Util.parseInt(retryAfterRaw, -1);
            throw new ProofRequiredException(proofRequiredResponse, retryAfter);
        case 499:
            throw new DeprecatedVersionException();
        case 508:
            throw new ServerRejectedException();
    }
    if (responseCode != 200 && responseCode != 202 && responseCode != 204) {
        throw new NonSuccessfulResponseCodeException(responseCode, "Bad response: " + responseCode + " " + responseMessage);
    }
    return response;
}
Also used : RateLimitException(org.whispersystems.signalservice.api.push.exceptions.RateLimitException) DeprecatedVersionException(org.whispersystems.signalservice.api.push.exceptions.DeprecatedVersionException) ExpectationFailedException(org.whispersystems.signalservice.api.push.exceptions.ExpectationFailedException) GroupNotFoundException(org.whispersystems.signalservice.internal.push.exceptions.GroupNotFoundException) NotFoundException(org.whispersystems.signalservice.api.push.exceptions.NotFoundException) NonSuccessfulResponseCodeException(org.whispersystems.signalservice.api.push.exceptions.NonSuccessfulResponseCodeException) GroupStaleDevicesException(org.whispersystems.signalservice.internal.push.exceptions.GroupStaleDevicesException) StaleDevicesException(org.whispersystems.signalservice.internal.push.exceptions.StaleDevicesException) ProofRequiredException(org.whispersystems.signalservice.api.push.exceptions.ProofRequiredException) ServerRejectedException(org.whispersystems.signalservice.api.push.exceptions.ServerRejectedException) GroupsV2AuthorizationString(org.whispersystems.signalservice.api.groupsv2.GroupsV2AuthorizationString) AuthorizationFailedException(org.whispersystems.signalservice.api.push.exceptions.AuthorizationFailedException) GroupMismatchedDevicesException(org.whispersystems.signalservice.internal.push.exceptions.GroupMismatchedDevicesException) MismatchedDevicesException(org.whispersystems.signalservice.internal.push.exceptions.MismatchedDevicesException)

Example 7 with ServerRejectedException

use of org.whispersystems.signalservice.api.push.exceptions.ServerRejectedException in project Signal-Android by WhisperSystems.

the class DefaultErrorMapper method parseError.

@Override
public Throwable parseError(int status, String body, Function<String, String> getHeader) {
    if (customErrorMappers.containsKey(status)) {
        try {
            return customErrorMappers.get(status).parseError(status, body, getHeader);
        } catch (MalformedResponseException e) {
            return e;
        }
    }
    switch(status) {
        case 401:
        case 403:
            return new AuthorizationFailedException(status, "Authorization failed!");
        case 402:
            return new CaptchaRequiredException();
        case 404:
            return new NotFoundException("Not found");
        case 409:
            try {
                return new MismatchedDevicesException(JsonUtil.fromJsonResponse(body, MismatchedDevices.class));
            } catch (MalformedResponseException e) {
                return e;
            }
        case 410:
            try {
                return new StaleDevicesException(JsonUtil.fromJsonResponse(body, StaleDevices.class));
            } catch (MalformedResponseException e) {
                return e;
            }
        case 411:
            try {
                return new DeviceLimitExceededException(JsonUtil.fromJsonResponse(body, DeviceLimit.class));
            } catch (MalformedResponseException e) {
                return e;
            }
        case 413:
            return new RateLimitException("Rate limit exceeded: " + status);
        case 417:
            return new ExpectationFailedException();
        case 423:
            PushServiceSocket.RegistrationLockFailure accountLockFailure;
            try {
                accountLockFailure = JsonUtil.fromJsonResponse(body, PushServiceSocket.RegistrationLockFailure.class);
            } catch (MalformedResponseException e) {
                return e;
            }
            AuthCredentials credentials = accountLockFailure.backupCredentials;
            String basicStorageCredentials = credentials != null ? credentials.asBasic() : null;
            return new LockedException(accountLockFailure.length, accountLockFailure.timeRemaining, basicStorageCredentials);
        case 428:
            ProofRequiredResponse proofRequiredResponse;
            try {
                proofRequiredResponse = JsonUtil.fromJsonResponse(body, ProofRequiredResponse.class);
            } catch (MalformedResponseException e) {
                return e;
            }
            String retryAfterRaw = getHeader.apply("Retry-After");
            long retryAfter = Util.parseInt(retryAfterRaw, -1);
            return new ProofRequiredException(proofRequiredResponse, retryAfter);
        case 499:
            return new DeprecatedVersionException();
        case 508:
            return new ServerRejectedException();
    }
    if (status != 200 && status != 202 && status != 204) {
        return new NonSuccessfulResponseCodeException(status, "Bad response: " + status);
    }
    return null;
}
Also used : LockedException(org.whispersystems.signalservice.internal.push.LockedException) RateLimitException(org.whispersystems.signalservice.api.push.exceptions.RateLimitException) DeprecatedVersionException(org.whispersystems.signalservice.api.push.exceptions.DeprecatedVersionException) ExpectationFailedException(org.whispersystems.signalservice.api.push.exceptions.ExpectationFailedException) DeviceLimit(org.whispersystems.signalservice.internal.push.DeviceLimit) NotFoundException(org.whispersystems.signalservice.api.push.exceptions.NotFoundException) NonSuccessfulResponseCodeException(org.whispersystems.signalservice.api.push.exceptions.NonSuccessfulResponseCodeException) StaleDevicesException(org.whispersystems.signalservice.internal.push.exceptions.StaleDevicesException) ProofRequiredException(org.whispersystems.signalservice.api.push.exceptions.ProofRequiredException) ServerRejectedException(org.whispersystems.signalservice.api.push.exceptions.ServerRejectedException) MalformedResponseException(org.whispersystems.signalservice.api.push.exceptions.MalformedResponseException) MismatchedDevices(org.whispersystems.signalservice.internal.push.MismatchedDevices) StaleDevices(org.whispersystems.signalservice.internal.push.StaleDevices) DeviceLimitExceededException(org.whispersystems.signalservice.internal.push.DeviceLimitExceededException) AuthCredentials(org.whispersystems.signalservice.internal.push.AuthCredentials) AuthorizationFailedException(org.whispersystems.signalservice.api.push.exceptions.AuthorizationFailedException) MismatchedDevicesException(org.whispersystems.signalservice.internal.push.exceptions.MismatchedDevicesException) PushServiceSocket(org.whispersystems.signalservice.internal.push.PushServiceSocket) CaptchaRequiredException(org.whispersystems.signalservice.api.push.exceptions.CaptchaRequiredException) ProofRequiredResponse(org.whispersystems.signalservice.internal.push.ProofRequiredResponse)

Example 8 with ServerRejectedException

use of org.whispersystems.signalservice.api.push.exceptions.ServerRejectedException in project Signal-Android by WhisperSystems.

the class SignalServiceMessageSender method sendMessage.

private List<SendMessageResult> sendMessage(List<SignalServiceAddress> recipients, List<Optional<UnidentifiedAccess>> unidentifiedAccess, long timestamp, EnvelopeContent content, boolean online, PartialSendCompleteListener partialListener, CancelationSignal cancelationSignal) throws IOException {
    Log.d(TAG, "[" + timestamp + "] Sending to " + recipients.size() + " recipients.");
    enforceMaxContentSize(content);
    long startTime = System.currentTimeMillis();
    List<Future<SendMessageResult>> futureResults = new LinkedList<>();
    Iterator<SignalServiceAddress> recipientIterator = recipients.iterator();
    Iterator<Optional<UnidentifiedAccess>> unidentifiedAccessIterator = unidentifiedAccess.iterator();
    while (recipientIterator.hasNext()) {
        SignalServiceAddress recipient = recipientIterator.next();
        Optional<UnidentifiedAccess> access = unidentifiedAccessIterator.next();
        futureResults.add(executor.submit(() -> {
            SendMessageResult result = sendMessage(recipient, access, timestamp, content, online, cancelationSignal);
            if (partialListener != null) {
                partialListener.onPartialSendComplete(result);
            }
            return result;
        }));
    }
    List<SendMessageResult> results = new ArrayList<>(futureResults.size());
    recipientIterator = recipients.iterator();
    for (Future<SendMessageResult> futureResult : futureResults) {
        SignalServiceAddress recipient = recipientIterator.next();
        try {
            results.add(futureResult.get());
        } catch (ExecutionException e) {
            if (e.getCause() instanceof UntrustedIdentityException) {
                Log.w(TAG, e);
                results.add(SendMessageResult.identityFailure(recipient, ((UntrustedIdentityException) e.getCause()).getIdentityKey()));
            } else if (e.getCause() instanceof UnregisteredUserException) {
                Log.w(TAG, "[" + timestamp + "] Found unregistered user.");
                results.add(SendMessageResult.unregisteredFailure(recipient));
            } 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 if (e.getCause() instanceof ProofRequiredException) {
                Log.w(TAG, e);
                results.add(SendMessageResult.proofRequiredFailure(recipient, (ProofRequiredException) e.getCause()));
            } else {
                throw new IOException(e);
            }
        } catch (InterruptedException e) {
            throw new IOException(e);
        }
    }
    double sendsForAverage = 0;
    for (SendMessageResult result : results) {
        if (result.getSuccess() != null && result.getSuccess().getDuration() != -1) {
            sendsForAverage++;
        }
    }
    double average = 0;
    if (sendsForAverage > 0) {
        for (SendMessageResult result : results) {
            if (result.getSuccess() != null && result.getSuccess().getDuration() != -1) {
                average += result.getSuccess().getDuration() / sendsForAverage;
            }
        }
    }
    Log.d(TAG, "[" + timestamp + "] Completed send to " + recipients.size() + " recipients in " + (System.currentTimeMillis() - startTime) + " ms, with an average time of " + Math.round(average) + " ms per send.");
    return results;
}
Also used : UntrustedIdentityException(org.whispersystems.signalservice.api.crypto.UntrustedIdentityException) UnregisteredUserException(org.whispersystems.signalservice.api.push.exceptions.UnregisteredUserException) PushNetworkException(org.whispersystems.signalservice.api.push.exceptions.PushNetworkException) Optional(org.whispersystems.libsignal.util.guava.Optional) ArrayList(java.util.ArrayList) ServerRejectedException(org.whispersystems.signalservice.api.push.exceptions.ServerRejectedException) ProofRequiredException(org.whispersystems.signalservice.api.push.exceptions.ProofRequiredException) IOException(java.io.IOException) LinkedList(java.util.LinkedList) SendMessageResult(org.whispersystems.signalservice.api.messages.SendMessageResult) UnidentifiedAccess(org.whispersystems.signalservice.api.crypto.UnidentifiedAccess) Future(java.util.concurrent.Future) SignalServiceAddress(org.whispersystems.signalservice.api.push.SignalServiceAddress) ExecutionException(java.util.concurrent.ExecutionException)

Example 9 with ServerRejectedException

use of org.whispersystems.signalservice.api.push.exceptions.ServerRejectedException in project Signal-Android by WhisperSystems.

the class PushGroupSendJob method deliver.

private List<SendMessageResult> deliver(OutgoingMediaMessage message, @NonNull Recipient groupRecipient, @NonNull List<Recipient> destinations) throws IOException, UntrustedIdentityException, UndeliverableMessageException {
    try {
        rotateSenderCertificateIfNecessary();
        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<Attachment> attachments = Stream.of(message.getAttachments()).filterNot(Attachment::isSticker).toList();
        List<SignalServiceAttachment> attachmentPointers = getAttachmentPointersFor(attachments);
        boolean isRecipientUpdate = Stream.of(SignalDatabase.groupReceipts().getGroupReceiptInfo(messageId)).anyMatch(info -> info.getStatus() > GroupReceiptDatabase.STATUS_UNDELIVERED);
        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());
                ByteString groupChange = groupContext.getGroupChange();
                if (groupChange != null) {
                    builder.withSignedGroupChange(groupChange.toByteArray());
                }
                SignalServiceGroupV2 group = builder.build();
                SignalServiceDataMessage groupDataMessage = SignalServiceDataMessage.newBuilder().withTimestamp(message.getSentTimeMillis()).withExpiration(groupRecipient.getExpiresInSeconds()).asGroupMessage(group).build();
                return GroupSendUtil.sendResendableDataMessage(context, groupRecipient.requireGroupId().requireV2(), destinations, isRecipientUpdate, ContentHint.IMPLICIT, new MessageId(messageId, true), groupDataMessage);
            } else {
                throw new UndeliverableMessageException("Messages can no longer be sent to V1 groups!");
            }
        } else {
            Optional<GroupDatabase.GroupRecord> groupRecord = SignalDatabase.groups().getGroup(groupRecipient.requireGroupId());
            if (groupRecord.isPresent() && groupRecord.get().isAnnouncementGroup() && !groupRecord.get().isAdmin(Recipient.self())) {
                throw new UndeliverableMessageException("Non-admins cannot send messages in announcement groups!");
            }
            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 GroupSendUtil.sendResendableDataMessage(context, groupRecipient.getGroupId().transform(GroupId::requireV2).orNull(), destinations, isRecipientUpdate, ContentHint.RESENDABLE, new MessageId(messageId, true), groupMessage);
        }
    } catch (ServerRejectedException e) {
        throw new UndeliverableMessageException(e);
    }
}
Also used : ByteString(com.google.protobuf.ByteString) SignalServiceAttachment(org.whispersystems.signalservice.api.messages.SignalServiceAttachment) Attachment(org.thoughtcrime.securesms.attachments.Attachment) OutgoingGroupUpdateMessage(org.thoughtcrime.securesms.mms.OutgoingGroupUpdateMessage) GroupContextV2(org.whispersystems.signalservice.internal.push.SignalServiceProtos.GroupContextV2) MessageGroupContext(org.thoughtcrime.securesms.mms.MessageGroupContext) UndeliverableMessageException(org.thoughtcrime.securesms.transport.UndeliverableMessageException) Preview(org.whispersystems.signalservice.api.messages.SignalServiceDataMessage.Preview) ServerRejectedException(org.whispersystems.signalservice.api.push.exceptions.ServerRejectedException) SignalServiceGroupV2(org.whispersystems.signalservice.api.messages.SignalServiceGroupV2) GroupId(org.thoughtcrime.securesms.groups.GroupId) Quote(org.whispersystems.signalservice.api.messages.SignalServiceDataMessage.Quote) SignalServiceAttachment(org.whispersystems.signalservice.api.messages.SignalServiceAttachment) SignalServiceDataMessage(org.whispersystems.signalservice.api.messages.SignalServiceDataMessage) SharedContact(org.whispersystems.signalservice.api.messages.shared.SharedContact) MessageId(org.thoughtcrime.securesms.database.model.MessageId)

Example 10 with ServerRejectedException

use of org.whispersystems.signalservice.api.push.exceptions.ServerRejectedException in project Signal-Android by WhisperSystems.

the class PushTextSendJob method deliver.

private boolean deliver(SmsMessageRecord message) throws UntrustedIdentityException, InsecureFallbackApprovalException, UndeliverableMessageException, IOException {
    try {
        rotateSenderCertificateIfNecessary();
        Recipient messageRecipient = message.getIndividualRecipient().resolve();
        if (messageRecipient.isUnregistered()) {
            throw new UndeliverableMessageException(messageRecipient.getId() + " not registered!");
        }
        SignalServiceMessageSender messageSender = ApplicationDependencies.getSignalServiceMessageSender();
        SignalServiceAddress address = RecipientUtil.toSignalServiceAddress(context, messageRecipient);
        Optional<byte[]> profileKey = getProfileKey(messageRecipient);
        Optional<UnidentifiedAccessPair> unidentifiedAccess = UnidentifiedAccessUtil.getAccessFor(context, messageRecipient);
        log(TAG, String.valueOf(message.getDateSent()), "Have access key to use: " + unidentifiedAccess.isPresent());
        SignalServiceDataMessage textSecureMessage = SignalServiceDataMessage.newBuilder().withTimestamp(message.getDateSent()).withBody(message.getBody()).withExpiration((int) (message.getExpiresIn() / 1000)).withProfileKey(profileKey.orNull()).asEndSessionMessage(message.isEndSession()).build();
        if (Util.equals(SignalStore.account().getAci(), address.getServiceId())) {
            Optional<UnidentifiedAccessPair> syncAccess = UnidentifiedAccessUtil.getAccessForSync(context);
            SignalLocalMetrics.IndividualMessageSend.onDeliveryStarted(messageId);
            SendMessageResult result = messageSender.sendSyncMessage(textSecureMessage);
            SignalDatabase.messageLog().insertIfPossible(messageRecipient.getId(), message.getDateSent(), result, ContentHint.RESENDABLE, new MessageId(messageId, false));
            return syncAccess.isPresent();
        } else {
            SignalLocalMetrics.IndividualMessageSend.onDeliveryStarted(messageId);
            SendMessageResult result = messageSender.sendDataMessage(address, unidentifiedAccess, ContentHint.RESENDABLE, textSecureMessage, new MetricEventListener(messageId));
            SignalDatabase.messageLog().insertIfPossible(messageRecipient.getId(), message.getDateSent(), result, ContentHint.RESENDABLE, new MessageId(messageId, false));
            return result.getSuccess().isUnidentified();
        }
    } catch (UnregisteredUserException e) {
        warn(TAG, "Failure", e);
        throw new InsecureFallbackApprovalException(e);
    } catch (ServerRejectedException e) {
        throw new UndeliverableMessageException(e);
    }
}
Also used : UnregisteredUserException(org.whispersystems.signalservice.api.push.exceptions.UnregisteredUserException) SignalServiceMessageSender(org.whispersystems.signalservice.api.SignalServiceMessageSender) Recipient(org.thoughtcrime.securesms.recipients.Recipient) UnidentifiedAccessPair(org.whispersystems.signalservice.api.crypto.UnidentifiedAccessPair) ServerRejectedException(org.whispersystems.signalservice.api.push.exceptions.ServerRejectedException) InsecureFallbackApprovalException(org.thoughtcrime.securesms.transport.InsecureFallbackApprovalException) SendMessageResult(org.whispersystems.signalservice.api.messages.SendMessageResult) SignalServiceDataMessage(org.whispersystems.signalservice.api.messages.SignalServiceDataMessage) UndeliverableMessageException(org.thoughtcrime.securesms.transport.UndeliverableMessageException) SignalServiceAddress(org.whispersystems.signalservice.api.push.SignalServiceAddress) MessageId(org.thoughtcrime.securesms.database.model.MessageId) SyncMessageId(org.thoughtcrime.securesms.database.MessageDatabase.SyncMessageId)

Aggregations

ServerRejectedException (org.whispersystems.signalservice.api.push.exceptions.ServerRejectedException)14 SendMessageResult (org.whispersystems.signalservice.api.messages.SendMessageResult)6 SignalServiceAddress (org.whispersystems.signalservice.api.push.SignalServiceAddress)6 NonSuccessfulResponseCodeException (org.whispersystems.signalservice.api.push.exceptions.NonSuccessfulResponseCodeException)6 NotFoundException (org.whispersystems.signalservice.api.push.exceptions.NotFoundException)6 ProofRequiredException (org.whispersystems.signalservice.api.push.exceptions.ProofRequiredException)6 UnregisteredUserException (org.whispersystems.signalservice.api.push.exceptions.UnregisteredUserException)6 MessageId (org.thoughtcrime.securesms.database.model.MessageId)5 UndeliverableMessageException (org.thoughtcrime.securesms.transport.UndeliverableMessageException)5 SignalServiceDataMessage (org.whispersystems.signalservice.api.messages.SignalServiceDataMessage)5 IOException (java.io.IOException)4 Attachment (org.thoughtcrime.securesms.attachments.Attachment)4 GroupsV2AuthorizationString (org.whispersystems.signalservice.api.groupsv2.GroupsV2AuthorizationString)4 SignalServiceAttachment (org.whispersystems.signalservice.api.messages.SignalServiceAttachment)4 Preview (org.whispersystems.signalservice.api.messages.SignalServiceDataMessage.Preview)4 SharedContact (org.whispersystems.signalservice.api.messages.shared.SharedContact)4 AuthorizationFailedException (org.whispersystems.signalservice.api.push.exceptions.AuthorizationFailedException)4 DeprecatedVersionException (org.whispersystems.signalservice.api.push.exceptions.DeprecatedVersionException)4 ExpectationFailedException (org.whispersystems.signalservice.api.push.exceptions.ExpectationFailedException)4 PushNetworkException (org.whispersystems.signalservice.api.push.exceptions.PushNetworkException)4