Include timestamps in all server-to-client websocket messages.

This commit is contained in:
Jon Chambers 2020-05-21 11:15:36 -04:00 committed by Jon Chambers
parent eb8b5e5c01
commit a25af36e32
4 changed files with 29 additions and 10 deletions

View File

@ -1,5 +1,7 @@
package org.whispersystems.textsecuregcm.filters;
import org.whispersystems.textsecuregcm.util.TimestampHeaderUtil;
import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.container.ContainerResponseContext;
import javax.ws.rs.container.ContainerResponseFilter;
@ -10,10 +12,8 @@ import java.util.Collections;
*/
public class TimestampResponseFilter implements ContainerResponseFilter {
private static final String TIMESTAMP_HEADER = "X-Signal-Timestamp";
@Override
public void filter(final ContainerRequestContext requestContext, final ContainerResponseContext responseContext) {
responseContext.getStringHeaders().put(TIMESTAMP_HEADER, Collections.singletonList(String.valueOf(System.currentTimeMillis())));
responseContext.getStringHeaders().put(TimestampHeaderUtil.TIMESTAMP_HEADER, Collections.singletonList(String.valueOf(System.currentTimeMillis())));
}
}

View File

@ -0,0 +1,13 @@
package org.whispersystems.textsecuregcm.util;
public class TimestampHeaderUtil {
public static final String TIMESTAMP_HEADER = "X-Signal-Timestamp";
private TimestampHeaderUtil() {
}
public static String getTimestampHeader() {
return TIMESTAMP_HEADER + ":" + System.currentTimeMillis();
}
}

View File

@ -6,8 +6,10 @@ import org.slf4j.LoggerFactory;
import org.whispersystems.dispatch.DispatchChannel;
import org.whispersystems.textsecuregcm.entities.MessageProtos.ProvisioningUuid;
import org.whispersystems.textsecuregcm.storage.PubSubProtos.PubSubMessage;
import org.whispersystems.textsecuregcm.util.TimestampHeaderUtil;
import org.whispersystems.websocket.WebSocketClient;
import java.util.Collections;
import java.util.Optional;
public class ProvisioningConnection implements DispatchChannel {
@ -28,7 +30,7 @@ public class ProvisioningConnection implements DispatchChannel {
if (outgoingMessage.getType() == PubSubMessage.Type.DELIVER) {
Optional<byte[]> body = Optional.of(outgoingMessage.getContent().toByteArray());
client.sendRequest("PUT", "/v1/message", null, body)
client.sendRequest("PUT", "/v1/message", Collections.singletonList(TimestampHeaderUtil.getTimestampHeader()), body)
.thenAccept(response -> client.close(1001, "All you get."))
.exceptionally(throwable -> {
client.close(1001, "That's all!");
@ -44,10 +46,12 @@ public class ProvisioningConnection implements DispatchChannel {
public void onDispatchSubscribed(String channel) {
try {
ProvisioningAddress address = new ProvisioningAddress(channel);
this.client.sendRequest("PUT", "/v1/address", null, Optional.of(ProvisioningUuid.newBuilder()
.setUuid(address.getAddress())
.build()
.toByteArray()));
this.client.sendRequest("PUT", "/v1/address", Collections.singletonList(TimestampHeaderUtil.getTimestampHeader()),
Optional.of(ProvisioningUuid.newBuilder()
.setUuid(address.getAddress())
.build()
.toByteArray()));
} catch (InvalidWebsocketAddressException e) {
logger.warn("Badly formatted address", e);
this.client.close(1001, "Server Error");

View File

@ -21,6 +21,7 @@ import org.whispersystems.textsecuregcm.storage.Account;
import org.whispersystems.textsecuregcm.storage.Device;
import org.whispersystems.textsecuregcm.storage.MessagesManager;
import org.whispersystems.textsecuregcm.util.Constants;
import org.whispersystems.textsecuregcm.util.TimestampHeaderUtil;
import org.whispersystems.textsecuregcm.util.Util;
import org.whispersystems.websocket.WebSocketClient;
import org.whispersystems.websocket.messages.WebSocketResponseMessage;
@ -28,6 +29,7 @@ import org.whispersystems.websocket.messages.WebSocketResponseMessage;
import javax.ws.rs.WebApplicationException;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Optional;
import static com.codahale.metrics.MetricRegistry.name;
@ -118,7 +120,7 @@ public class WebSocketConnection implements DispatchChannel {
body = Optional.ofNullable(new EncryptedOutgoingMessage(message, device.getSignalingKey()).toByteArray());
}
client.sendRequest("PUT", "/api/v1/message", Collections.singletonList(header), body)
client.sendRequest("PUT", "/api/v1/message", List.of(header, TimestampHeaderUtil.getTimestampHeader()), body)
.thenAccept(response -> {
boolean isReceipt = message.getType() == Envelope.Type.RECEIPT;
@ -201,7 +203,7 @@ public class WebSocketConnection implements DispatchChannel {
}
if (!messages.hasMore()) {
client.sendRequest("PUT", "/api/v1/queue/empty", null, Optional.empty());
client.sendRequest("PUT", "/api/v1/queue/empty", Collections.singletonList(TimestampHeaderUtil.getTimestampHeader()), Optional.empty());
}
}