Search in sources :

Example 1 with WebSocketRequestMessage

use of org.whispersystems.signalservice.internal.websocket.WebSocketProtos.WebSocketRequestMessage in project libsignal-service-java by signalapp.

the class SignalServiceMessagePipe method read.

/**
 * A blocking call that reads a message off the pipe (see {@link #read(long, java.util.concurrent.TimeUnit)}
 *
 * Unlike {@link #read(long, java.util.concurrent.TimeUnit)}, this method allows you
 * to specify a callback that will be called before the received message is acknowledged.
 * This allows you to write the received message to durable storage before acknowledging
 * receipt of it to the server.
 *
 * @param timeout The timeout to wait for.
 * @param unit The timeout time unit.
 * @param callback A callback that will be called before the message receipt is
 *                 acknowledged to the server.
 * @return The message read (same as the message sent through the callback).
 * @throws TimeoutException
 * @throws IOException
 * @throws InvalidVersionException
 */
public SignalServiceEnvelope read(long timeout, TimeUnit unit, MessagePipeCallback callback) throws TimeoutException, IOException, InvalidVersionException {
    while (true) {
        WebSocketRequestMessage request = websocket.readRequest(unit.toMillis(timeout));
        WebSocketResponseMessage response = createWebSocketResponse(request);
        try {
            if (isSignalServiceEnvelope(request)) {
                SignalServiceEnvelope envelope = new SignalServiceEnvelope(request.getBody().toByteArray(), credentialsProvider.getSignalingKey());
                callback.onMessage(envelope);
                return envelope;
            }
        } finally {
            websocket.sendResponse(response);
        }
    }
}
Also used : SignalServiceEnvelope(org.whispersystems.signalservice.api.messages.SignalServiceEnvelope) WebSocketRequestMessage(org.whispersystems.signalservice.internal.websocket.WebSocketProtos.WebSocketRequestMessage) WebSocketResponseMessage(org.whispersystems.signalservice.internal.websocket.WebSocketProtos.WebSocketResponseMessage)

Example 2 with WebSocketRequestMessage

use of org.whispersystems.signalservice.internal.websocket.WebSocketProtos.WebSocketRequestMessage 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 3 with WebSocketRequestMessage

use of org.whispersystems.signalservice.internal.websocket.WebSocketProtos.WebSocketRequestMessage in project libsignal-service-java by signalapp.

the class SignalServiceMessagePipe method getProfile.

public SignalServiceProfile getProfile(SignalServiceAddress address) throws IOException {
    try {
        WebSocketRequestMessage requestMessage = WebSocketRequestMessage.newBuilder().setId(SecureRandom.getInstance("SHA1PRNG").nextLong()).setVerb("GET").setPath(String.format("/v1/profile/%s", address.getNumber())).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());
        }
        return JsonUtil.fromJson(response.second(), SignalServiceProfile.class);
    } catch (NoSuchAlgorithmException nsae) {
        throw new AssertionError(nsae);
    } catch (InterruptedException | ExecutionException | TimeoutException e) {
        throw new IOException(e);
    }
}
Also used : 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 4 with WebSocketRequestMessage

use of org.whispersystems.signalservice.internal.websocket.WebSocketProtos.WebSocketRequestMessage in project Signal-Android by WhisperSystems.

the class SignalWebSocket method readOrEmpty.

/**
 * <p>
 * A blocking call that reads a message off the pipe. When this call returns, the message has been
 * acknowledged and will not be retransmitted. This will return {@link Optional#absent()} when an
 * empty response is hit, which indicates the WebSocket is empty.
 * <p>
 * You can specify a {@link MessageReceivedCallback} that will be called before the received message is acknowledged.
 * This allows you to write the received message to durable storage before acknowledging receipt of it to the
 * server.
 * <p>
 * Important: The empty response will only be hit once for each connection. That means if you get
 * an empty response and call readOrEmpty() again on the same instance, you will not get an empty
 * response, and instead will block until you get an actual message. This will, however, reset if
 * connection breaks (if, for instance, you lose and regain network).
 *
 * @param timeout  The timeout to wait for.
 * @param callback A callback that will be called before the message receipt is acknowledged to the server.
 * @return The message read (same as the message sent through the callback).
 */
@SuppressWarnings("DuplicateThrows")
public Optional<SignalServiceEnvelope> readOrEmpty(long timeout, MessageReceivedCallback callback) throws TimeoutException, WebSocketUnavailableException, IOException {
    while (true) {
        WebSocketRequestMessage request = getWebSocket().readRequest(timeout);
        WebSocketResponseMessage response = createWebSocketResponse(request);
        try {
            if (isSignalServiceEnvelope(request)) {
                Optional<String> timestampHeader = findHeader(request);
                long timestamp = 0;
                if (timestampHeader.isPresent()) {
                    try {
                        timestamp = Long.parseLong(timestampHeader.get());
                    } catch (NumberFormatException e) {
                        Log.w(TAG, "Failed to parse " + SERVER_DELIVERED_TIMESTAMP_HEADER);
                    }
                }
                SignalServiceEnvelope envelope = new SignalServiceEnvelope(request.getBody().toByteArray(), timestamp);
                callback.onMessage(envelope);
                return Optional.of(envelope);
            } else if (isSocketEmptyRequest(request)) {
                return Optional.absent();
            }
        } finally {
            getWebSocket().sendResponse(response);
        }
    }
}
Also used : SignalServiceEnvelope(org.whispersystems.signalservice.api.messages.SignalServiceEnvelope) WebSocketRequestMessage(org.whispersystems.signalservice.internal.websocket.WebSocketProtos.WebSocketRequestMessage) WebSocketResponseMessage(org.whispersystems.signalservice.internal.websocket.WebSocketProtos.WebSocketResponseMessage)

Example 5 with WebSocketRequestMessage

use of org.whispersystems.signalservice.internal.websocket.WebSocketProtos.WebSocketRequestMessage in project Signal-Android by WhisperSystems.

the class MessagingService method sendToGroup.

public Single<ServiceResponse<SendGroupMessageResponse>> sendToGroup(byte[] body, byte[] joinedUnidentifiedAccess, long timestamp, boolean online) {
    List<String> headers = new LinkedList<String>() {

        {
            add("content-type:application/vnd.signal-messenger.mrm");
            add("Unidentified-Access-Key:" + Base64.encodeBytes(joinedUnidentifiedAccess));
        }
    };
    String path = String.format(Locale.US, "/v1/messages/multi_recipient?ts=%s&online=%s", timestamp, online);
    WebSocketRequestMessage requestMessage = WebSocketRequestMessage.newBuilder().setId(new SecureRandom().nextLong()).setVerb("PUT").setPath(path).addAllHeaders(headers).setBody(ByteString.copyFrom(body)).build();
    return signalWebSocket.request(requestMessage).map(DefaultResponseMapper.extend(SendGroupMessageResponse.class).withCustomError(401, (status, errorBody, getHeader) -> new InvalidUnidentifiedAccessHeaderException()).withCustomError(404, (status, errorBody, getHeader) -> new NotFoundException("At least one unregistered user in message send.")).withCustomError(409, (status, errorBody, getHeader) -> {
        GroupMismatchedDevices[] mismatchedDevices = JsonUtil.fromJsonResponse(errorBody, GroupMismatchedDevices[].class);
        return new GroupMismatchedDevicesException(mismatchedDevices);
    }).withCustomError(410, (status, errorBody, getHeader) -> {
        GroupStaleDevices[] staleDevices = JsonUtil.fromJsonResponse(errorBody, GroupStaleDevices[].class);
        return new GroupStaleDevicesException(staleDevices);
    }).build()::map).onErrorReturn(ServiceResponse::forUnknownError);
}
Also used : Single(io.reactivex.rxjava3.core.Single) SignalWebSocket(org.whispersystems.signalservice.api.SignalWebSocket) Util(org.whispersystems.signalservice.internal.util.Util) SecureRandom(java.security.SecureRandom) UnidentifiedAccess(org.whispersystems.signalservice.api.crypto.UnidentifiedAccess) NotFoundException(org.whispersystems.signalservice.api.push.exceptions.NotFoundException) GroupMismatchedDevicesException(org.whispersystems.signalservice.internal.push.exceptions.GroupMismatchedDevicesException) Locale(java.util.Locale) GroupStaleDevicesException(org.whispersystems.signalservice.internal.push.exceptions.GroupStaleDevicesException) LinkedList(java.util.LinkedList) GroupMismatchedDevices(org.whispersystems.signalservice.internal.push.GroupMismatchedDevices) DefaultResponseMapper(org.whispersystems.signalservice.internal.websocket.DefaultResponseMapper) SendMessageResponse(org.whispersystems.signalservice.internal.push.SendMessageResponse) InvalidUnidentifiedAccessHeaderException(org.whispersystems.signalservice.internal.push.exceptions.InvalidUnidentifiedAccessHeaderException) WebSocketRequestMessage(org.whispersystems.signalservice.internal.websocket.WebSocketProtos.WebSocketRequestMessage) ServiceResponse(org.whispersystems.signalservice.internal.ServiceResponse) JsonUtil(org.whispersystems.signalservice.internal.util.JsonUtil) OutgoingPushMessageList(org.whispersystems.signalservice.internal.push.OutgoingPushMessageList) Optional(org.whispersystems.libsignal.util.guava.Optional) UnregisteredUserException(org.whispersystems.signalservice.api.push.exceptions.UnregisteredUserException) ByteString(com.google.protobuf.ByteString) List(java.util.List) GroupStaleDevices(org.whispersystems.signalservice.internal.push.GroupStaleDevices) Base64(org.whispersystems.util.Base64) SendGroupMessageResponse(org.whispersystems.signalservice.internal.push.SendGroupMessageResponse) ResponseMapper(org.whispersystems.signalservice.internal.websocket.ResponseMapper) ServiceResponseProcessor(org.whispersystems.signalservice.internal.ServiceResponseProcessor) GroupMismatchedDevicesException(org.whispersystems.signalservice.internal.push.exceptions.GroupMismatchedDevicesException) WebSocketRequestMessage(org.whispersystems.signalservice.internal.websocket.WebSocketProtos.WebSocketRequestMessage) SecureRandom(java.security.SecureRandom) NotFoundException(org.whispersystems.signalservice.api.push.exceptions.NotFoundException) ByteString(com.google.protobuf.ByteString) LinkedList(java.util.LinkedList) GroupStaleDevicesException(org.whispersystems.signalservice.internal.push.exceptions.GroupStaleDevicesException) ServiceResponse(org.whispersystems.signalservice.internal.ServiceResponse) GroupStaleDevices(org.whispersystems.signalservice.internal.push.GroupStaleDevices) InvalidUnidentifiedAccessHeaderException(org.whispersystems.signalservice.internal.push.exceptions.InvalidUnidentifiedAccessHeaderException)

Aggregations

WebSocketRequestMessage (org.whispersystems.signalservice.internal.websocket.WebSocketProtos.WebSocketRequestMessage)6 ByteString (com.google.protobuf.ByteString)4 SendMessageResponse (org.whispersystems.signalservice.internal.push.SendMessageResponse)3 Single (io.reactivex.rxjava3.core.Single)2 IOException (java.io.IOException)2 NoSuchAlgorithmException (java.security.NoSuchAlgorithmException)2 SecureRandom (java.security.SecureRandom)2 LinkedList (java.util.LinkedList)2 List (java.util.List)2 Locale (java.util.Locale)2 ExecutionException (java.util.concurrent.ExecutionException)2 TimeoutException (java.util.concurrent.TimeoutException)2 Optional (org.whispersystems.libsignal.util.guava.Optional)2 SignalWebSocket (org.whispersystems.signalservice.api.SignalWebSocket)2 UnidentifiedAccess (org.whispersystems.signalservice.api.crypto.UnidentifiedAccess)2 SignalServiceEnvelope (org.whispersystems.signalservice.api.messages.SignalServiceEnvelope)2 NotFoundException (org.whispersystems.signalservice.api.push.exceptions.NotFoundException)2 UnregisteredUserException (org.whispersystems.signalservice.api.push.exceptions.UnregisteredUserException)2 ServiceResponse (org.whispersystems.signalservice.internal.ServiceResponse)2 ServiceResponseProcessor (org.whispersystems.signalservice.internal.ServiceResponseProcessor)2