From 807f13ddc435bc8591fc9c9f88a6de6fec5b8eb2 Mon Sep 17 00:00:00 2001 From: Moxie Marlinspike Date: Wed, 15 Apr 2015 16:46:03 -0700 Subject: [PATCH] Support for retrieving messages via REST. Support for retrieving messages via HTTP rather than websockets. // FREEBIE --- .../api/TextSecureMessageReceiver.java | 38 ++++++++++++++ .../internal/push/PushServiceSocket.java | 10 ++++ .../push/TextSecureEnvelopeEntity.java | 50 +++++++++++++++++++ .../push/TextSecureEnvelopeEntityList.java | 16 ++++++ 4 files changed, 114 insertions(+) create mode 100644 java/src/main/java/org/whispersystems/textsecure/internal/push/TextSecureEnvelopeEntity.java create mode 100644 java/src/main/java/org/whispersystems/textsecure/internal/push/TextSecureEnvelopeEntityList.java diff --git a/java/src/main/java/org/whispersystems/textsecure/api/TextSecureMessageReceiver.java b/java/src/main/java/org/whispersystems/textsecure/api/TextSecureMessageReceiver.java index ecbd8eba92..bb3b46b454 100644 --- a/java/src/main/java/org/whispersystems/textsecure/api/TextSecureMessageReceiver.java +++ b/java/src/main/java/org/whispersystems/textsecure/api/TextSecureMessageReceiver.java @@ -19,15 +19,19 @@ package org.whispersystems.textsecure.api; import org.whispersystems.libaxolotl.InvalidMessageException; import org.whispersystems.textsecure.api.crypto.AttachmentCipherInputStream; import org.whispersystems.textsecure.api.messages.TextSecureAttachmentPointer; +import org.whispersystems.textsecure.api.messages.TextSecureEnvelope; import org.whispersystems.textsecure.api.push.TrustStore; import org.whispersystems.textsecure.api.util.CredentialsProvider; import org.whispersystems.textsecure.internal.push.PushServiceSocket; +import org.whispersystems.textsecure.internal.push.TextSecureEnvelopeEntity; import org.whispersystems.textsecure.internal.util.StaticCredentialsProvider; import org.whispersystems.textsecure.internal.websocket.WebSocketConnection; import java.io.File; import java.io.IOException; import java.io.InputStream; +import java.util.LinkedList; +import java.util.List; /** * The primary interface for receiving TextSecure messages. @@ -102,4 +106,38 @@ public class TextSecureMessageReceiver { return new TextSecureMessagePipe(webSocket, credentialsProvider); } + public List retrieveMessages() throws IOException { + return retrieveMessages(new NullMessageReceivedCallback()); + } + + public List retrieveMessages(MessageReceivedCallback callback) + throws IOException + { + List results = new LinkedList<>(); + List entities = socket.getMessages(); + + for (TextSecureEnvelopeEntity entity : entities) { + TextSecureEnvelope envelope = new TextSecureEnvelope(entity.getType(), entity.getSource(), + entity.getSourceDevice(), entity.getRelay(), + entity.getTimestamp(), entity.getMessage()); + + callback.onMessage(envelope); + results.add(envelope); + + socket.acknowledgeMessage(entity.getSource(), entity.getTimestamp()); + } + + return results; + } + + + public interface MessageReceivedCallback { + public void onMessage(TextSecureEnvelope envelope); + } + + public static class NullMessageReceivedCallback implements MessageReceivedCallback { + @Override + public void onMessage(TextSecureEnvelope envelope) {} + } + } diff --git a/java/src/main/java/org/whispersystems/textsecure/internal/push/PushServiceSocket.java b/java/src/main/java/org/whispersystems/textsecure/internal/push/PushServiceSocket.java index d8532a38df..eafd850048 100644 --- a/java/src/main/java/org/whispersystems/textsecure/internal/push/PushServiceSocket.java +++ b/java/src/main/java/org/whispersystems/textsecure/internal/push/PushServiceSocket.java @@ -90,6 +90,7 @@ public class PushServiceSocket { private static final String DIRECTORY_TOKENS_PATH = "/v1/directory/tokens"; private static final String DIRECTORY_VERIFY_PATH = "/v1/directory/%s"; private static final String MESSAGE_PATH = "/v1/messages/%s"; + private static final String ACKNOWLEDGE_MESSAGE_PATH = "/v1/messages/%s/%d"; private static final String RECEIPT_PATH = "/v1/receipt/%s/%d"; private static final String ATTACHMENT_PATH = "/v1/attachments/%s"; @@ -162,6 +163,15 @@ public class PushServiceSocket { } } + public List getMessages() throws IOException { + String responseText = makeRequest(String.format(MESSAGE_PATH, ""), "GET", null); + return JsonUtil.fromJson(responseText, TextSecureEnvelopeEntityList.class).getMessages(); + } + + public void acknowledgeMessage(String sender, long timestamp) throws IOException { + makeRequest(String.format(ACKNOWLEDGE_MESSAGE_PATH, sender, timestamp), "DELETE", null); + } + public void registerPreKeys(IdentityKey identityKey, PreKeyRecord lastResortKey, SignedPreKeyRecord signedPreKey, diff --git a/java/src/main/java/org/whispersystems/textsecure/internal/push/TextSecureEnvelopeEntity.java b/java/src/main/java/org/whispersystems/textsecure/internal/push/TextSecureEnvelopeEntity.java new file mode 100644 index 0000000000..6d1a33c392 --- /dev/null +++ b/java/src/main/java/org/whispersystems/textsecure/internal/push/TextSecureEnvelopeEntity.java @@ -0,0 +1,50 @@ +package org.whispersystems.textsecure.internal.push; + +import com.fasterxml.jackson.annotation.JsonProperty; + +public class TextSecureEnvelopeEntity { + + @JsonProperty + private int type; + + @JsonProperty + private String relay; + + @JsonProperty + private long timestamp; + + @JsonProperty + private String source; + + @JsonProperty + private int sourceDevice; + + @JsonProperty + private byte[] message; + + public TextSecureEnvelopeEntity() {} + + public int getType() { + return type; + } + + public String getRelay() { + return relay; + } + + public long getTimestamp() { + return timestamp; + } + + public String getSource() { + return source; + } + + public int getSourceDevice() { + return sourceDevice; + } + + public byte[] getMessage() { + return message; + } +} diff --git a/java/src/main/java/org/whispersystems/textsecure/internal/push/TextSecureEnvelopeEntityList.java b/java/src/main/java/org/whispersystems/textsecure/internal/push/TextSecureEnvelopeEntityList.java new file mode 100644 index 0000000000..c2e7189b0f --- /dev/null +++ b/java/src/main/java/org/whispersystems/textsecure/internal/push/TextSecureEnvelopeEntityList.java @@ -0,0 +1,16 @@ +package org.whispersystems.textsecure.internal.push; + +import org.whispersystems.textsecure.api.messages.TextSecureEnvelope; + +import java.util.List; + +public class TextSecureEnvelopeEntityList { + + private List messages; + + public TextSecureEnvelopeEntityList() {} + + public List getMessages() { + return messages; + } +}