diff --git a/protobuf/OutgoingMessageSignal.proto b/protobuf/OutgoingMessageSignal.proto index 15339d6b4..4278a2855 100644 --- a/protobuf/OutgoingMessageSignal.proto +++ b/protobuf/OutgoingMessageSignal.proto @@ -25,7 +25,7 @@ message OutgoingMessageSignal { CIPHERTEXT = 1; KEY_EXCHANGE = 2; PREKEY_BUNDLE = 3; - PLAINTEXT = 4; +// PLAINTEXT = 4; RECEIPT = 5; } diff --git a/src/main/java/org/whispersystems/textsecuregcm/entities/ApnMessage.java b/src/main/java/org/whispersystems/textsecuregcm/entities/ApnMessage.java index b66db39c8..60763d271 100644 --- a/src/main/java/org/whispersystems/textsecuregcm/entities/ApnMessage.java +++ b/src/main/java/org/whispersystems/textsecuregcm/entities/ApnMessage.java @@ -8,6 +8,9 @@ import javax.validation.constraints.Min; import javax.validation.constraints.NotNull; public class ApnMessage { + + public static long MAX_EXPIRATION = Integer.MAX_VALUE * 1000L; + @JsonProperty @NotEmpty private String apnId; @@ -28,22 +31,27 @@ public class ApnMessage { @NotNull private boolean voip; + @JsonProperty + private long expirationTime; + public ApnMessage() {} - public ApnMessage(String apnId, String number, int deviceId, String message, boolean voip) { - this.apnId = apnId; - this.number = number; - this.deviceId = deviceId; - this.message = message; - this.voip = voip; + public ApnMessage(String apnId, String number, int deviceId, String message, boolean voip, long expirationTime) { + this.apnId = apnId; + this.number = number; + this.deviceId = deviceId; + this.message = message; + this.voip = voip; + this.expirationTime = expirationTime; } - public ApnMessage(ApnMessage copy, String apnId, boolean voip) { - this.apnId = apnId; - this.number = copy.number; - this.deviceId = copy.deviceId; - this.message = copy.message; - this.voip = voip; + public ApnMessage(ApnMessage copy, String apnId, boolean voip, long expirationTime) { + this.apnId = apnId; + this.number = copy.number; + this.deviceId = copy.deviceId; + this.message = copy.message; + this.voip = voip; + this.expirationTime = expirationTime; } @VisibleForTesting @@ -60,4 +68,9 @@ public class ApnMessage { public String getMessage() { return message; } + + @VisibleForTesting + public long getExpirationTime() { + return expirationTime; + } } diff --git a/src/main/java/org/whispersystems/textsecuregcm/push/ApnFallbackManager.java b/src/main/java/org/whispersystems/textsecuregcm/push/ApnFallbackManager.java index bda485b2d..4c0d49f2f 100644 --- a/src/main/java/org/whispersystems/textsecuregcm/push/ApnFallbackManager.java +++ b/src/main/java/org/whispersystems/textsecuregcm/push/ApnFallbackManager.java @@ -71,7 +71,9 @@ public class ApnFallbackManager implements Managed, Runnable { try { Entry taskEntry = taskQueue.get(); ApnFallbackTask task = taskEntry.getValue(); - pushServiceClient.send(new ApnMessage(task.getMessage(), task.getApnId(), false)); + + pushServiceClient.send(new ApnMessage(task.getMessage(), task.getApnId(), + false, ApnMessage.MAX_EXPIRATION)); } catch (Throwable e) { logger.warn("ApnFallbackThread", e); } diff --git a/src/main/java/org/whispersystems/textsecuregcm/push/PushSender.java b/src/main/java/org/whispersystems/textsecuregcm/push/PushSender.java index 9f5485e7c..887070827 100644 --- a/src/main/java/org/whispersystems/textsecuregcm/push/PushSender.java +++ b/src/main/java/org/whispersystems/textsecuregcm/push/PushSender.java @@ -30,6 +30,7 @@ import org.whispersystems.textsecuregcm.util.Util; import org.whispersystems.textsecuregcm.websocket.WebsocketAddress; import java.util.LinkedHashMap; +import java.util.concurrent.TimeUnit; import io.dropwizard.lifecycle.Managed; import static org.whispersystems.textsecuregcm.entities.MessageProtos.OutgoingMessageSignal; @@ -107,16 +108,19 @@ public class PushSender { DeliveryStatus deliveryStatus = webSocketSender.sendMessage(account, device, outgoingMessage, WebsocketSender.Type.APN); if (!deliveryStatus.isDelivered() && outgoingMessage.getType() != OutgoingMessageSignal.Type.RECEIPT_VALUE) { - String apnId = Util.isEmpty(device.getVoipApnId()) ? device.getApnId() : device.getVoipApnId(); - boolean isVoip = !Util.isEmpty(device.getVoipApnId()); + ApnMessage apnMessage; - ApnMessage apnMessage = new ApnMessage(apnId, account.getNumber(), (int)device.getId(), - String.format(APN_PAYLOAD, deliveryStatus.getMessageQueueDepth()), - isVoip); + if (!Util.isEmpty(device.getVoipApnId())) { + apnMessage = new ApnMessage(device.getVoipApnId(), account.getNumber(), (int)device.getId(), + String.format(APN_PAYLOAD, deliveryStatus.getMessageQueueDepth()), + true, System.currentTimeMillis() + TimeUnit.SECONDS.toMillis(30)); - if (isVoip) { apnFallbackManager.schedule(new WebsocketAddress(account.getNumber(), device.getId()), new ApnFallbackTask(device.getApnId(), apnMessage)); + } else { + apnMessage = new ApnMessage(device.getApnId(), account.getNumber(), (int)device.getId(), + String.format(APN_PAYLOAD, deliveryStatus.getMessageQueueDepth()), + false, ApnMessage.MAX_EXPIRATION); } pushServiceClient.send(apnMessage); diff --git a/src/test/java/org/whispersystems/textsecuregcm/tests/push/ApnFallbackManagerTest.java b/src/test/java/org/whispersystems/textsecuregcm/tests/push/ApnFallbackManagerTest.java index ea21cd085..67e611b91 100644 --- a/src/test/java/org/whispersystems/textsecuregcm/tests/push/ApnFallbackManagerTest.java +++ b/src/test/java/org/whispersystems/textsecuregcm/tests/push/ApnFallbackManagerTest.java @@ -19,7 +19,7 @@ public class ApnFallbackManagerTest { public void testFullFallback() throws Exception { PushServiceClient pushServiceClient = mock(PushServiceClient.class); WebsocketAddress address = mock(WebsocketAddress.class ); - ApnMessage message = new ApnMessage("bar", "123", 1, "hmm", true); + ApnMessage message = new ApnMessage("bar", "123", 1, "hmm", true, 1111); ApnFallbackTask task = new ApnFallbackTask("foo", message, 500); ApnFallbackManager apnFallbackManager = new ApnFallbackManager(pushServiceClient); @@ -35,13 +35,14 @@ public class ApnFallbackManagerTest { assertEquals(captor.getValue().getMessage(), message.getMessage()); assertEquals(captor.getValue().getApnId(), task.getApnId()); assertFalse(captor.getValue().isVoip()); + assertEquals(captor.getValue().getExpirationTime(), Integer.MAX_VALUE * 1000L); } @Test public void testNoFallback() throws Exception { PushServiceClient pushServiceClient = mock(PushServiceClient.class); WebsocketAddress address = mock(WebsocketAddress.class ); - ApnMessage message = new ApnMessage("bar", "123", 1, "hmm", true); + ApnMessage message = new ApnMessage("bar", "123", 1, "hmm", true, 5555); ApnFallbackTask task = new ApnFallbackTask ("foo", message, 500); ApnFallbackManager apnFallbackManager = new ApnFallbackManager(pushServiceClient);