Search in sources :

Example 6 with PushNetworkException

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

the class PushServiceSocket method sendGroupMessage.

public SendGroupMessageResponse sendGroupMessage(byte[] body, byte[] joinedUnidentifiedAccess, long timestamp, boolean online) throws IOException {
    ServiceConnectionHolder connectionHolder = (ServiceConnectionHolder) getRandom(serviceClients, random);
    String path = String.format(Locale.US, GROUP_MESSAGE_PATH, timestamp, online);
    Request.Builder requestBuilder = new Request.Builder();
    requestBuilder.url(String.format("%s%s", connectionHolder.getUrl(), path));
    requestBuilder.put(RequestBody.create(MediaType.get("application/vnd.signal-messenger.mrm"), body));
    requestBuilder.addHeader("Unidentified-Access-Key", Base64.encodeBytes(joinedUnidentifiedAccess));
    if (signalAgent != null) {
        requestBuilder.addHeader("X-Signal-Agent", signalAgent);
    }
    if (connectionHolder.getHostHeader().isPresent()) {
        requestBuilder.addHeader("Host", connectionHolder.getHostHeader().get());
    }
    Call call = connectionHolder.getUnidentifiedClient().newCall(requestBuilder.build());
    synchronized (connections) {
        connections.add(call);
    }
    Response response;
    try {
        response = call.execute();
    } catch (IOException e) {
        throw new PushNetworkException(e);
    } finally {
        synchronized (connections) {
            connections.remove(call);
        }
    }
    switch(response.code()) {
        case 200:
            return readBodyJson(response.body(), SendGroupMessageResponse.class);
        case 401:
            throw new InvalidUnidentifiedAccessHeaderException();
        case 404:
            throw new NotFoundException("At least one unregistered user in message send.");
        case 409:
            GroupMismatchedDevices[] mismatchedDevices = readBodyJson(response.body(), GroupMismatchedDevices[].class);
            throw new GroupMismatchedDevicesException(mismatchedDevices);
        case 410:
            GroupStaleDevices[] staleDevices = readBodyJson(response.body(), GroupStaleDevices[].class);
            throw new GroupStaleDevicesException(staleDevices);
        case 508:
            throw new ServerRejectedException();
        default:
            throw new NonSuccessfulResponseCodeException(response.code());
    }
}
Also used : Call(okhttp3.Call) PushNetworkException(org.whispersystems.signalservice.api.push.exceptions.PushNetworkException) GroupMismatchedDevicesException(org.whispersystems.signalservice.internal.push.exceptions.GroupMismatchedDevicesException) ReceiptCredentialRequest(org.signal.zkgroup.receipts.ReceiptCredentialRequest) Request(okhttp3.Request) ChangePhoneNumberRequest(org.whispersystems.signalservice.api.account.ChangePhoneNumberRequest) DiscoveryRequest(org.whispersystems.signalservice.internal.contacts.entities.DiscoveryRequest) KeyBackupRequest(org.whispersystems.signalservice.internal.contacts.entities.KeyBackupRequest) ProfileKeyCredentialRequest(org.signal.zkgroup.profiles.ProfileKeyCredentialRequest) GroupNotFoundException(org.whispersystems.signalservice.internal.push.exceptions.GroupNotFoundException) NotFoundException(org.whispersystems.signalservice.api.push.exceptions.NotFoundException) NonSuccessfulResponseCodeException(org.whispersystems.signalservice.api.push.exceptions.NonSuccessfulResponseCodeException) ServerRejectedException(org.whispersystems.signalservice.api.push.exceptions.ServerRejectedException) GroupsV2AuthorizationString(org.whispersystems.signalservice.api.groupsv2.GroupsV2AuthorizationString) IOException(java.io.IOException) GroupStaleDevicesException(org.whispersystems.signalservice.internal.push.exceptions.GroupStaleDevicesException) CallingResponse(org.whispersystems.signalservice.api.messages.calls.CallingResponse) Response(okhttp3.Response) KeyBackupResponse(org.whispersystems.signalservice.internal.contacts.entities.KeyBackupResponse) ReceiptCredentialResponse(org.signal.zkgroup.receipts.ReceiptCredentialResponse) CredentialResponse(org.whispersystems.signalservice.api.groupsv2.CredentialResponse) StorageAuthResponse(org.whispersystems.signalservice.api.storage.StorageAuthResponse) VerifyDeviceResponse(org.whispersystems.signalservice.api.messages.multidevice.VerifyDeviceResponse) DiscoveryResponse(org.whispersystems.signalservice.internal.contacts.entities.DiscoveryResponse) ProfileKeyCredentialResponse(org.signal.zkgroup.profiles.ProfileKeyCredentialResponse) TokenResponse(org.whispersystems.signalservice.internal.contacts.entities.TokenResponse) InvalidUnidentifiedAccessHeaderException(org.whispersystems.signalservice.internal.push.exceptions.InvalidUnidentifiedAccessHeaderException)

Example 7 with PushNetworkException

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

the class PushServiceSocket method makeServiceRequest.

private Response makeServiceRequest(String urlFragment, String method, RequestBody body, Map<String, String> headers, ResponseCodeHandler responseCodeHandler, Optional<UnidentifiedAccess> unidentifiedAccessKey, boolean doNotAddAuthenticationOrUnidentifiedAccessKey) throws NonSuccessfulResponseCodeException, PushNetworkException, MalformedResponseException {
    Response response = getServiceConnection(urlFragment, method, body, headers, unidentifiedAccessKey, doNotAddAuthenticationOrUnidentifiedAccessKey);
    ResponseBody responseBody = response.body();
    try {
        responseCodeHandler.handle(response.code(), responseBody);
        return validateServiceResponse(response);
    } catch (NonSuccessfulResponseCodeException | PushNetworkException | MalformedResponseException e) {
        if (responseBody != null) {
            responseBody.close();
        }
        throw e;
    }
}
Also used : CallingResponse(org.whispersystems.signalservice.api.messages.calls.CallingResponse) Response(okhttp3.Response) KeyBackupResponse(org.whispersystems.signalservice.internal.contacts.entities.KeyBackupResponse) ReceiptCredentialResponse(org.signal.zkgroup.receipts.ReceiptCredentialResponse) CredentialResponse(org.whispersystems.signalservice.api.groupsv2.CredentialResponse) StorageAuthResponse(org.whispersystems.signalservice.api.storage.StorageAuthResponse) VerifyDeviceResponse(org.whispersystems.signalservice.api.messages.multidevice.VerifyDeviceResponse) DiscoveryResponse(org.whispersystems.signalservice.internal.contacts.entities.DiscoveryResponse) ProfileKeyCredentialResponse(org.signal.zkgroup.profiles.ProfileKeyCredentialResponse) TokenResponse(org.whispersystems.signalservice.internal.contacts.entities.TokenResponse) PushNetworkException(org.whispersystems.signalservice.api.push.exceptions.PushNetworkException) NonSuccessfulResponseCodeException(org.whispersystems.signalservice.api.push.exceptions.NonSuccessfulResponseCodeException) MalformedResponseException(org.whispersystems.signalservice.api.push.exceptions.MalformedResponseException) ResponseBody(okhttp3.ResponseBody)

Example 8 with PushNetworkException

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

the class PushServiceSocket method uploadToCdn2.

private byte[] uploadToCdn2(String resumableUrl, InputStream data, String contentType, long length, OutputStreamFactory outputStreamFactory, ProgressListener progressListener, CancelationSignal cancelationSignal) throws IOException {
    ConnectionHolder connectionHolder = getRandom(cdnClientsMap.get(2), random);
    OkHttpClient okHttpClient = connectionHolder.getClient().newBuilder().connectTimeout(soTimeoutMillis, TimeUnit.MILLISECONDS).readTimeout(soTimeoutMillis, TimeUnit.MILLISECONDS).build();
    ResumeInfo resumeInfo = getResumeInfo(resumableUrl, length);
    DigestingRequestBody file = new DigestingRequestBody(data, outputStreamFactory, contentType, length, progressListener, cancelationSignal, resumeInfo.contentStart);
    if (resumeInfo.contentStart == length) {
        Log.w(TAG, "Resume start point == content length");
        try (NowhereBufferedSink buffer = new NowhereBufferedSink()) {
            file.writeTo(buffer);
        }
        return file.getTransmittedDigest();
    }
    Request.Builder request = new Request.Builder().url(buildConfiguredUrl(connectionHolder, resumableUrl)).put(file).addHeader("Content-Range", resumeInfo.contentRange);
    if (connectionHolder.getHostHeader().isPresent()) {
        request.header("host", connectionHolder.getHostHeader().get());
    }
    Call call = okHttpClient.newCall(request.build());
    synchronized (connections) {
        connections.add(call);
    }
    try {
        Response response;
        try {
            response = call.execute();
        } catch (IOException e) {
            throw new PushNetworkException(e);
        }
        if (response.isSuccessful())
            return file.getTransmittedDigest();
        else
            throw new NonSuccessfulResponseCodeException(response.code(), "Response: " + response);
    } finally {
        synchronized (connections) {
            connections.remove(call);
        }
    }
}
Also used : CallingResponse(org.whispersystems.signalservice.api.messages.calls.CallingResponse) Response(okhttp3.Response) KeyBackupResponse(org.whispersystems.signalservice.internal.contacts.entities.KeyBackupResponse) ReceiptCredentialResponse(org.signal.zkgroup.receipts.ReceiptCredentialResponse) CredentialResponse(org.whispersystems.signalservice.api.groupsv2.CredentialResponse) StorageAuthResponse(org.whispersystems.signalservice.api.storage.StorageAuthResponse) VerifyDeviceResponse(org.whispersystems.signalservice.api.messages.multidevice.VerifyDeviceResponse) DiscoveryResponse(org.whispersystems.signalservice.internal.contacts.entities.DiscoveryResponse) ProfileKeyCredentialResponse(org.signal.zkgroup.profiles.ProfileKeyCredentialResponse) TokenResponse(org.whispersystems.signalservice.internal.contacts.entities.TokenResponse) Call(okhttp3.Call) OkHttpClient(okhttp3.OkHttpClient) PushNetworkException(org.whispersystems.signalservice.api.push.exceptions.PushNetworkException) DigestingRequestBody(org.whispersystems.signalservice.internal.push.http.DigestingRequestBody) ReceiptCredentialRequest(org.signal.zkgroup.receipts.ReceiptCredentialRequest) Request(okhttp3.Request) ChangePhoneNumberRequest(org.whispersystems.signalservice.api.account.ChangePhoneNumberRequest) DiscoveryRequest(org.whispersystems.signalservice.internal.contacts.entities.DiscoveryRequest) KeyBackupRequest(org.whispersystems.signalservice.internal.contacts.entities.KeyBackupRequest) ProfileKeyCredentialRequest(org.signal.zkgroup.profiles.ProfileKeyCredentialRequest) NonSuccessfulResponseCodeException(org.whispersystems.signalservice.api.push.exceptions.NonSuccessfulResponseCodeException) IOException(java.io.IOException)

Example 9 with PushNetworkException

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

the class PushServiceSocket method getServiceConnection.

private Response getServiceConnection(String urlFragment, String method, RequestBody body, Map<String, String> headers, Optional<UnidentifiedAccess> unidentifiedAccess, boolean doNotAddAuthenticationOrUnidentifiedAccessKey) throws PushNetworkException {
    try {
        OkHttpClient okHttpClient = buildOkHttpClient(unidentifiedAccess.isPresent());
        Call call = okHttpClient.newCall(buildServiceRequest(urlFragment, method, body, headers, unidentifiedAccess, doNotAddAuthenticationOrUnidentifiedAccessKey));
        synchronized (connections) {
            connections.add(call);
        }
        try {
            return call.execute();
        } finally {
            synchronized (connections) {
                connections.remove(call);
            }
        }
    } catch (IOException e) {
        throw new PushNetworkException(e);
    }
}
Also used : Call(okhttp3.Call) OkHttpClient(okhttp3.OkHttpClient) PushNetworkException(org.whispersystems.signalservice.api.push.exceptions.PushNetworkException) IOException(java.io.IOException)

Example 10 with PushNetworkException

use of org.whispersystems.signalservice.api.push.exceptions.PushNetworkException 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)

Aggregations

PushNetworkException (org.whispersystems.signalservice.api.push.exceptions.PushNetworkException)22 IOException (java.io.IOException)19 Response (okhttp3.Response)13 NonSuccessfulResponseCodeException (org.whispersystems.signalservice.api.push.exceptions.NonSuccessfulResponseCodeException)13 Call (okhttp3.Call)12 OkHttpClient (okhttp3.OkHttpClient)11 Request (okhttp3.Request)11 ProfileKeyCredentialResponse (org.signal.zkgroup.profiles.ProfileKeyCredentialResponse)10 ReceiptCredentialResponse (org.signal.zkgroup.receipts.ReceiptCredentialResponse)10 CredentialResponse (org.whispersystems.signalservice.api.groupsv2.CredentialResponse)10 CallingResponse (org.whispersystems.signalservice.api.messages.calls.CallingResponse)10 VerifyDeviceResponse (org.whispersystems.signalservice.api.messages.multidevice.VerifyDeviceResponse)10 StorageAuthResponse (org.whispersystems.signalservice.api.storage.StorageAuthResponse)10 DiscoveryResponse (org.whispersystems.signalservice.internal.contacts.entities.DiscoveryResponse)10 KeyBackupResponse (org.whispersystems.signalservice.internal.contacts.entities.KeyBackupResponse)10 TokenResponse (org.whispersystems.signalservice.internal.contacts.entities.TokenResponse)10 ProfileKeyCredentialRequest (org.signal.zkgroup.profiles.ProfileKeyCredentialRequest)8 ReceiptCredentialRequest (org.signal.zkgroup.receipts.ReceiptCredentialRequest)8 ChangePhoneNumberRequest (org.whispersystems.signalservice.api.account.ChangePhoneNumberRequest)8 DiscoveryRequest (org.whispersystems.signalservice.internal.contacts.entities.DiscoveryRequest)8