Search in sources :

Example 1 with MismatchedDevicesException

use of org.whispersystems.signalservice.internal.push.exceptions.MismatchedDevicesException in project libsignal-service-java by signalapp.

the class PushServiceSocket method makeServiceRequest.

private String makeServiceRequest(String urlFragment, String method, String body) throws NonSuccessfulResponseCodeException, PushNetworkException {
    Response response = getServiceConnection(urlFragment, method, body);
    int responseCode;
    String responseMessage;
    String responseBody;
    try {
        responseCode = response.code();
        responseMessage = response.message();
        responseBody = response.body().string();
    } catch (IOException ioe) {
        throw new PushNetworkException(ioe);
    }
    switch(responseCode) {
        case 413:
            throw new RateLimitException("Rate limit exceeded: " + responseCode);
        case 401:
        case 403:
            throw new AuthorizationFailedException("Authorization failed!");
        case 404:
            throw new NotFoundException("Not found");
        case 409:
            MismatchedDevices mismatchedDevices;
            try {
                mismatchedDevices = JsonUtil.fromJson(responseBody, MismatchedDevices.class);
            } catch (JsonProcessingException e) {
                Log.w(TAG, e);
                throw new NonSuccessfulResponseCodeException("Bad response: " + responseCode + " " + responseMessage);
            } catch (IOException e) {
                throw new PushNetworkException(e);
            }
            throw new MismatchedDevicesException(mismatchedDevices);
        case 410:
            StaleDevices staleDevices;
            try {
                staleDevices = JsonUtil.fromJson(responseBody, StaleDevices.class);
            } catch (JsonProcessingException e) {
                throw new NonSuccessfulResponseCodeException("Bad response: " + responseCode + " " + responseMessage);
            } catch (IOException e) {
                throw new PushNetworkException(e);
            }
            throw new StaleDevicesException(staleDevices);
        case 411:
            DeviceLimit deviceLimit;
            try {
                deviceLimit = JsonUtil.fromJson(responseBody, DeviceLimit.class);
            } catch (JsonProcessingException e) {
                throw new NonSuccessfulResponseCodeException("Bad response: " + responseCode + " " + responseMessage);
            } catch (IOException e) {
                throw new PushNetworkException(e);
            }
            throw new DeviceLimitExceededException(deviceLimit);
        case 417:
            throw new ExpectationFailedException();
        case 423:
            RegistrationLockFailure accountLockFailure;
            try {
                accountLockFailure = JsonUtil.fromJson(responseBody, RegistrationLockFailure.class);
            } catch (JsonProcessingException e) {
                Log.w(TAG, e);
                throw new NonSuccessfulResponseCodeException("Bad response: " + responseCode + " " + responseMessage);
            } catch (IOException e) {
                throw new PushNetworkException(e);
            }
            throw new LockedException(accountLockFailure.length, accountLockFailure.timeRemaining);
    }
    if (responseCode != 200 && responseCode != 204) {
        throw new NonSuccessfulResponseCodeException("Bad response: " + responseCode + " " + responseMessage);
    }
    return responseBody;
}
Also used : PushNetworkException(org.whispersystems.signalservice.api.push.exceptions.PushNetworkException) RateLimitException(org.whispersystems.signalservice.api.push.exceptions.RateLimitException) ExpectationFailedException(org.whispersystems.signalservice.api.push.exceptions.ExpectationFailedException) NotFoundException(org.whispersystems.signalservice.api.push.exceptions.NotFoundException) NonSuccessfulResponseCodeException(org.whispersystems.signalservice.api.push.exceptions.NonSuccessfulResponseCodeException) StaleDevicesException(org.whispersystems.signalservice.internal.push.exceptions.StaleDevicesException) IOException(java.io.IOException) Response(okhttp3.Response) AuthorizationFailedException(org.whispersystems.signalservice.api.push.exceptions.AuthorizationFailedException) MismatchedDevicesException(org.whispersystems.signalservice.internal.push.exceptions.MismatchedDevicesException) JsonProcessingException(com.fasterxml.jackson.core.JsonProcessingException)

Example 2 with MismatchedDevicesException

use of org.whispersystems.signalservice.internal.push.exceptions.MismatchedDevicesException 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 3 with MismatchedDevicesException

use of org.whispersystems.signalservice.internal.push.exceptions.MismatchedDevicesException 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 4 with MismatchedDevicesException

use of org.whispersystems.signalservice.internal.push.exceptions.MismatchedDevicesException in project Signal-Android by WhisperSystems.

the class SignalServiceMessageSender method sendMessage.

private SendMessageResult sendMessage(SignalServiceAddress recipient, Optional<UnidentifiedAccess> unidentifiedAccess, long timestamp, EnvelopeContent content, boolean online, CancelationSignal cancelationSignal) throws UntrustedIdentityException, IOException {
    enforceMaxContentSize(content);
    long startTime = System.currentTimeMillis();
    for (int i = 0; i < RETRY_COUNT; i++) {
        if (cancelationSignal != null && cancelationSignal.isCanceled()) {
            throw new CancelationException();
        }
        try {
            OutgoingPushMessageList messages = getEncryptedMessages(socket, recipient, unidentifiedAccess, timestamp, content, online);
            if (content.getContent().isPresent() && content.getContent().get().getSyncMessage() != null && content.getContent().get().getSyncMessage().hasSent()) {
                Log.d(TAG, "[sendMessage][" + timestamp + "] Sending a sent sync message to devices: " + messages.getDevices());
            } else if (content.getContent().isPresent() && content.getContent().get().hasSenderKeyDistributionMessage()) {
                Log.d(TAG, "[sendMessage][" + timestamp + "] Sending a SKDM to " + messages.getDestination() + " for devices: " + messages.getDevices());
            }
            if (cancelationSignal != null && cancelationSignal.isCanceled()) {
                throw new CancelationException();
            }
            if (!unidentifiedAccess.isPresent()) {
                try {
                    SendMessageResponse response = new MessagingService.SendResponseProcessor<>(messagingService.send(messages, Optional.absent()).blockingGet()).getResultOrThrow();
                    return SendMessageResult.success(recipient, messages.getDevices(), response.sentUnidentified(), response.getNeedsSync() || store.isMultiDevice(), System.currentTimeMillis() - startTime, content.getContent());
                } catch (InvalidUnidentifiedAccessHeaderException | UnregisteredUserException | MismatchedDevicesException | StaleDevicesException e) {
                    // Non-technical failures shouldn't be retried with socket
                    throw e;
                } catch (WebSocketUnavailableException e) {
                    Log.i(TAG, "[sendMessage][" + timestamp + "] Pipe unavailable, falling back... (" + e.getClass().getSimpleName() + ": " + e.getMessage() + ")");
                } catch (IOException e) {
                    Log.w(TAG, e);
                    Log.w(TAG, "[sendMessage][" + timestamp + "] Pipe failed, falling back... (" + e.getClass().getSimpleName() + ": " + e.getMessage() + ")");
                }
            } else if (unidentifiedAccess.isPresent()) {
                try {
                    SendMessageResponse response = new MessagingService.SendResponseProcessor<>(messagingService.send(messages, unidentifiedAccess).blockingGet()).getResultOrThrow();
                    return SendMessageResult.success(recipient, messages.getDevices(), response.sentUnidentified(), response.getNeedsSync() || store.isMultiDevice(), System.currentTimeMillis() - startTime, content.getContent());
                } catch (InvalidUnidentifiedAccessHeaderException | UnregisteredUserException | MismatchedDevicesException | StaleDevicesException e) {
                    // Non-technical failures shouldn't be retried with socket
                    throw e;
                } catch (WebSocketUnavailableException e) {
                    Log.i(TAG, "[sendMessage][" + timestamp + "] Unidentified pipe unavailable, falling back... (" + e.getClass().getSimpleName() + ": " + e.getMessage() + ")");
                } catch (IOException e) {
                    Log.w(TAG, e);
                    Log.w(TAG, "[sendMessage][" + timestamp + "] Unidentified pipe failed, falling back...");
                }
            }
            if (cancelationSignal != null && cancelationSignal.isCanceled()) {
                throw new CancelationException();
            }
            SendMessageResponse response = socket.sendMessage(messages, unidentifiedAccess);
            return SendMessageResult.success(recipient, messages.getDevices(), response.sentUnidentified(), response.getNeedsSync() || store.isMultiDevice(), System.currentTimeMillis() - startTime, content.getContent());
        } catch (InvalidKeyException ike) {
            Log.w(TAG, ike);
            unidentifiedAccess = Optional.absent();
        } catch (AuthorizationFailedException afe) {
            Log.w(TAG, afe);
            if (unidentifiedAccess.isPresent()) {
                unidentifiedAccess = Optional.absent();
            } else {
                throw afe;
            }
        } catch (MismatchedDevicesException mde) {
            Log.w(TAG, "[sendMessage][" + timestamp + "] Handling mismatched devices. (" + mde.getMessage() + ")");
            handleMismatchedDevices(socket, recipient, mde.getMismatchedDevices());
        } catch (StaleDevicesException ste) {
            Log.w(TAG, "[sendMessage][" + timestamp + "] Handling stale devices. (" + ste.getMessage() + ")");
            handleStaleDevices(recipient, ste.getStaleDevices());
        }
    }
    throw new IOException("Failed to resolve conflicts after " + RETRY_COUNT + " attempts!");
}
Also used : UnregisteredUserException(org.whispersystems.signalservice.api.push.exceptions.UnregisteredUserException) GroupStaleDevicesException(org.whispersystems.signalservice.internal.push.exceptions.GroupStaleDevicesException) StaleDevicesException(org.whispersystems.signalservice.internal.push.exceptions.StaleDevicesException) WebSocketUnavailableException(org.whispersystems.signalservice.api.websocket.WebSocketUnavailableException) IOException(java.io.IOException) InvalidKeyException(org.whispersystems.libsignal.InvalidKeyException) ContentHint(org.whispersystems.signalservice.api.crypto.ContentHint) MessagingService(org.whispersystems.signalservice.api.services.MessagingService) OutgoingPushMessageList(org.whispersystems.signalservice.internal.push.OutgoingPushMessageList) SendMessageResponse(org.whispersystems.signalservice.internal.push.SendMessageResponse) AuthorizationFailedException(org.whispersystems.signalservice.api.push.exceptions.AuthorizationFailedException) GroupMismatchedDevicesException(org.whispersystems.signalservice.internal.push.exceptions.GroupMismatchedDevicesException) MismatchedDevicesException(org.whispersystems.signalservice.internal.push.exceptions.MismatchedDevicesException) InvalidUnidentifiedAccessHeaderException(org.whispersystems.signalservice.internal.push.exceptions.InvalidUnidentifiedAccessHeaderException)

Example 5 with MismatchedDevicesException

use of org.whispersystems.signalservice.internal.push.exceptions.MismatchedDevicesException in project libsignal-service-java by signalapp.

the class SignalServiceMessageSender method sendMessage.

private SendMessageResponse sendMessage(SignalServiceAddress recipient, long timestamp, byte[] content, boolean silent) throws UntrustedIdentityException, IOException {
    for (int i = 0; i < 3; i++) {
        try {
            OutgoingPushMessageList messages = getEncryptedMessages(socket, recipient, timestamp, content, silent);
            Optional<SignalServiceMessagePipe> pipe = this.pipe.get();
            if (pipe.isPresent()) {
                try {
                    Log.w(TAG, "Transmitting over pipe...");
                    return pipe.get().send(messages);
                } catch (IOException e) {
                    Log.w(TAG, e);
                    Log.w(TAG, "Falling back to new connection...");
                }
            }
            Log.w(TAG, "Not transmitting over pipe...");
            return socket.sendMessage(messages);
        } catch (MismatchedDevicesException mde) {
            Log.w(TAG, mde);
            handleMismatchedDevices(socket, recipient, mde.getMismatchedDevices());
        } catch (StaleDevicesException ste) {
            Log.w(TAG, ste);
            handleStaleDevices(recipient, ste.getStaleDevices());
        }
    }
    throw new IOException("Failed to resolve conflicts after 3 attempts!");
}
Also used : OutgoingPushMessageList(org.whispersystems.signalservice.internal.push.OutgoingPushMessageList) MismatchedDevicesException(org.whispersystems.signalservice.internal.push.exceptions.MismatchedDevicesException) StaleDevicesException(org.whispersystems.signalservice.internal.push.exceptions.StaleDevicesException) IOException(java.io.IOException)

Aggregations

MismatchedDevicesException (org.whispersystems.signalservice.internal.push.exceptions.MismatchedDevicesException)5 StaleDevicesException (org.whispersystems.signalservice.internal.push.exceptions.StaleDevicesException)5 AuthorizationFailedException (org.whispersystems.signalservice.api.push.exceptions.AuthorizationFailedException)4 IOException (java.io.IOException)3 ExpectationFailedException (org.whispersystems.signalservice.api.push.exceptions.ExpectationFailedException)3 NonSuccessfulResponseCodeException (org.whispersystems.signalservice.api.push.exceptions.NonSuccessfulResponseCodeException)3 NotFoundException (org.whispersystems.signalservice.api.push.exceptions.NotFoundException)3 RateLimitException (org.whispersystems.signalservice.api.push.exceptions.RateLimitException)3 DeprecatedVersionException (org.whispersystems.signalservice.api.push.exceptions.DeprecatedVersionException)2 ProofRequiredException (org.whispersystems.signalservice.api.push.exceptions.ProofRequiredException)2 ServerRejectedException (org.whispersystems.signalservice.api.push.exceptions.ServerRejectedException)2 OutgoingPushMessageList (org.whispersystems.signalservice.internal.push.OutgoingPushMessageList)2 GroupMismatchedDevicesException (org.whispersystems.signalservice.internal.push.exceptions.GroupMismatchedDevicesException)2 GroupStaleDevicesException (org.whispersystems.signalservice.internal.push.exceptions.GroupStaleDevicesException)2 JsonProcessingException (com.fasterxml.jackson.core.JsonProcessingException)1 Response (okhttp3.Response)1 InvalidKeyException (org.whispersystems.libsignal.InvalidKeyException)1 ContentHint (org.whispersystems.signalservice.api.crypto.ContentHint)1 GroupsV2AuthorizationString (org.whispersystems.signalservice.api.groupsv2.GroupsV2AuthorizationString)1 CaptchaRequiredException (org.whispersystems.signalservice.api.push.exceptions.CaptchaRequiredException)1