Search in sources :

Example 1 with SendMessageResponse

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

the class SignalServiceMessagePipe method send.

public SendMessageResponse send(OutgoingPushMessageList list) throws IOException {
    try {
        WebSocketRequestMessage requestMessage = WebSocketRequestMessage.newBuilder().setId(SecureRandom.getInstance("SHA1PRNG").nextLong()).setVerb("PUT").setPath(String.format("/v1/messages/%s", list.getDestination())).addHeaders("content-type:application/json").setBody(ByteString.copyFrom(JsonUtil.toJson(list).getBytes())).build();
        Pair<Integer, String> response = websocket.sendRequest(requestMessage).get(10, TimeUnit.SECONDS);
        if (response.first() < 200 || response.first() >= 300) {
            throw new IOException("Non-successful response: " + response.first());
        }
        if (Util.isEmpty(response.second()))
            return new SendMessageResponse(false);
        else
            return JsonUtil.fromJson(response.second(), SendMessageResponse.class);
    } catch (NoSuchAlgorithmException e) {
        throw new AssertionError(e);
    } catch (InterruptedException | ExecutionException | TimeoutException e) {
        throw new IOException(e);
    }
}
Also used : SendMessageResponse(org.whispersystems.signalservice.internal.push.SendMessageResponse) WebSocketRequestMessage(org.whispersystems.signalservice.internal.websocket.WebSocketProtos.WebSocketRequestMessage) ByteString(com.google.protobuf.ByteString) IOException(java.io.IOException) NoSuchAlgorithmException(java.security.NoSuchAlgorithmException) ExecutionException(java.util.concurrent.ExecutionException) TimeoutException(java.util.concurrent.TimeoutException)

Example 2 with SendMessageResponse

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

the class SignalServiceMessageSender method sendMessage.

/**
 * Send a message to a single recipient.
 *
 * @param recipient The message's destination.
 * @param message The message.
 * @throws UntrustedIdentityException
 * @throws IOException
 */
public void sendMessage(SignalServiceAddress recipient, SignalServiceDataMessage message) throws UntrustedIdentityException, IOException {
    byte[] content = createMessageContent(message);
    long timestamp = message.getTimestamp();
    boolean silent = message.getGroupInfo().isPresent() && message.getGroupInfo().get().getType() == SignalServiceGroup.Type.REQUEST_INFO;
    SendMessageResponse response = sendMessage(recipient, timestamp, content, silent);
    if (response != null && response.getNeedsSync()) {
        byte[] syncMessage = createMultiDeviceSentTranscriptContent(content, Optional.of(recipient), timestamp);
        sendMessage(localAddress, timestamp, syncMessage, false);
    }
    if (message.isEndSession()) {
        store.deleteAllSessions(recipient.getNumber());
        if (eventListener.isPresent()) {
            eventListener.get().onSecurityEvent(recipient);
        }
    }
}
Also used : SendMessageResponse(org.whispersystems.signalservice.internal.push.SendMessageResponse)

Example 3 with SendMessageResponse

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

the class SignalServiceMessageSender method sendMessage.

private void sendMessage(VerifiedMessage message) throws IOException, UntrustedIdentityException {
    byte[] nullMessageBody = DataMessage.newBuilder().setBody(Base64.encodeBytes(Util.getRandomLengthBytes(140))).build().toByteArray();
    NullMessage nullMessage = NullMessage.newBuilder().setPadding(ByteString.copyFrom(nullMessageBody)).build();
    byte[] content = Content.newBuilder().setNullMessage(nullMessage).build().toByteArray();
    SendMessageResponse response = sendMessage(new SignalServiceAddress(message.getDestination()), message.getTimestamp(), content, false);
    if (response != null && response.getNeedsSync()) {
        byte[] syncMessage = createMultiDeviceVerifiedContent(message, nullMessage.toByteArray());
        sendMessage(localAddress, message.getTimestamp(), syncMessage, false);
    }
}
Also used : NullMessage(org.whispersystems.signalservice.internal.push.SignalServiceProtos.NullMessage) SendMessageResponse(org.whispersystems.signalservice.internal.push.SendMessageResponse) SignalServiceAddress(org.whispersystems.signalservice.api.push.SignalServiceAddress)

Example 4 with SendMessageResponse

use of org.whispersystems.signalservice.internal.push.SendMessageResponse 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 SendMessageResponse

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

the class SignalServiceMessageSender method sendMessage.

private SendMessageResponseList sendMessage(List<SignalServiceAddress> recipients, long timestamp, byte[] content) throws IOException {
    SendMessageResponseList responseList = new SendMessageResponseList();
    for (SignalServiceAddress recipient : recipients) {
        try {
            SendMessageResponse response = sendMessage(recipient, timestamp, content, false);
            responseList.addResponse(response);
        } catch (UntrustedIdentityException e) {
            Log.w(TAG, e);
            responseList.addException(e);
        } catch (UnregisteredUserException e) {
            Log.w(TAG, e);
            responseList.addException(e);
        } catch (PushNetworkException e) {
            Log.w(TAG, e);
            responseList.addException(new NetworkFailureException(recipient.getNumber(), e));
        }
    }
    return responseList;
}
Also used : SendMessageResponse(org.whispersystems.signalservice.internal.push.SendMessageResponse) SendMessageResponseList(org.whispersystems.signalservice.internal.push.SendMessageResponseList) UntrustedIdentityException(org.whispersystems.signalservice.api.crypto.UntrustedIdentityException) UnregisteredUserException(org.whispersystems.signalservice.api.push.exceptions.UnregisteredUserException) PushNetworkException(org.whispersystems.signalservice.api.push.exceptions.PushNetworkException) SignalServiceAddress(org.whispersystems.signalservice.api.push.SignalServiceAddress) NetworkFailureException(org.whispersystems.signalservice.api.push.exceptions.NetworkFailureException)

Aggregations

SendMessageResponse (org.whispersystems.signalservice.internal.push.SendMessageResponse)6 UnregisteredUserException (org.whispersystems.signalservice.api.push.exceptions.UnregisteredUserException)3 ByteString (com.google.protobuf.ByteString)2 IOException (java.io.IOException)2 SignalServiceAddress (org.whispersystems.signalservice.api.push.SignalServiceAddress)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 InvalidUnidentifiedAccessHeaderException (org.whispersystems.signalservice.internal.push.exceptions.InvalidUnidentifiedAccessHeaderException)2 WebSocketRequestMessage (org.whispersystems.signalservice.internal.websocket.WebSocketProtos.WebSocketRequestMessage)2 Single (io.reactivex.rxjava3.core.Single)1 NoSuchAlgorithmException (java.security.NoSuchAlgorithmException)1 SecureRandom (java.security.SecureRandom)1 LinkedList (java.util.LinkedList)1 List (java.util.List)1 Locale (java.util.Locale)1 ExecutionException (java.util.concurrent.ExecutionException)1 TimeoutException (java.util.concurrent.TimeoutException)1 InvalidKeyException (org.whispersystems.libsignal.InvalidKeyException)1 Optional (org.whispersystems.libsignal.util.guava.Optional)1