mirror of
https://github.com/signalapp/Signal-Server
synced 2026-04-20 15:18:05 +01:00
Support for push preauth
This commit is contained in:
@@ -94,6 +94,8 @@ public class APNSender implements Managed {
|
||||
Futures.addCallback(future, new FutureCallback<ApnResult>() {
|
||||
@Override
|
||||
public void onSuccess(@Nullable ApnResult result) {
|
||||
if (message.getChallengeData().isPresent()) return;
|
||||
|
||||
if (result == null) {
|
||||
logger.warn("*** RECEIVED NULL APN RESULT ***");
|
||||
} else if (result.getStatus() == ApnResult.Status.NO_SUCH_USER) {
|
||||
|
||||
@@ -157,7 +157,7 @@ public class ApnFallbackManager implements Managed, Runnable {
|
||||
continue;
|
||||
}
|
||||
|
||||
apnSender.sendMessage(new ApnMessage(apnId, separated.get().first(), separated.get().second(), true));
|
||||
apnSender.sendMessage(new ApnMessage(apnId, separated.get().first(), separated.get().second(), true, Optional.empty()));
|
||||
retry.mark();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,20 +1,28 @@
|
||||
package org.whispersystems.textsecuregcm.push;
|
||||
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
@SuppressWarnings("OptionalUsedAsFieldOrParameterType")
|
||||
public class ApnMessage {
|
||||
|
||||
public static final String APN_PAYLOAD = "{\"aps\":{\"sound\":\"default\",\"alert\":{\"loc-key\":\"APN_Message\"}}}";
|
||||
public static final long MAX_EXPIRATION = Integer.MAX_VALUE * 1000L;
|
||||
public static final String APN_NOTIFICATION_PAYLOAD = "{\"aps\":{\"sound\":\"default\",\"alert\":{\"loc-key\":\"APN_Message\"}}}";
|
||||
public static final String APN_CHALLENGE_PAYLOAD = "{\"aps\":{\"sound\":\"default\",\"alert\":{\"loc-key\":\"APN_Message\"}}, \"challenge\" : \"%s\"}";
|
||||
public static final long MAX_EXPIRATION = Integer.MAX_VALUE * 1000L;
|
||||
|
||||
private final String apnId;
|
||||
private final String number;
|
||||
private final long deviceId;
|
||||
private final boolean isVoip;
|
||||
private final String apnId;
|
||||
private final String number;
|
||||
private final long deviceId;
|
||||
private final boolean isVoip;
|
||||
private final Optional<String> challengeData;
|
||||
|
||||
public ApnMessage(String apnId, String number, long deviceId, boolean isVoip) {
|
||||
this.apnId = apnId;
|
||||
this.number = number;
|
||||
this.deviceId = deviceId;
|
||||
this.isVoip = isVoip;
|
||||
public ApnMessage(String apnId, String number, long deviceId, boolean isVoip, Optional<String> challengeData) {
|
||||
this.apnId = apnId;
|
||||
this.number = number;
|
||||
this.deviceId = deviceId;
|
||||
this.isVoip = isVoip;
|
||||
this.challengeData = challengeData;
|
||||
}
|
||||
|
||||
public boolean isVoip() {
|
||||
@@ -26,7 +34,13 @@ public class ApnMessage {
|
||||
}
|
||||
|
||||
public String getMessage() {
|
||||
return APN_PAYLOAD;
|
||||
if (!challengeData.isPresent()) return APN_NOTIFICATION_PAYLOAD;
|
||||
else return String.format(APN_CHALLENGE_PAYLOAD, challengeData.get());
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
public Optional<String> getChallengeData() {
|
||||
return challengeData;
|
||||
}
|
||||
|
||||
public long getExpirationTime() {
|
||||
|
||||
@@ -66,14 +66,22 @@ public class GCMSender implements Managed {
|
||||
.withDestination(message.getGcmId())
|
||||
.withPriority("high");
|
||||
|
||||
String key = message.isReceipt() ? "receipt" : "notification";
|
||||
Message request = builder.withDataPart(key, "").build();
|
||||
String key;
|
||||
|
||||
switch (message.getType()) {
|
||||
case RECEIPT: key = "receipt"; break;
|
||||
case NOTIFICATION: key = "notification"; break;
|
||||
case CHALLENGE: key = "challenge"; break;
|
||||
default: throw new AssertionError();
|
||||
}
|
||||
|
||||
Message request = builder.withDataPart(key, message.getData().orElse("")).build();
|
||||
|
||||
CompletableFuture<Result> future = signalSender.send(request);
|
||||
markOutboundMeter(key);
|
||||
|
||||
future.handle((result, throwable) -> {
|
||||
if (result != null) {
|
||||
if (result != null && message.getType() != GcmMessage.Type.CHALLENGE) {
|
||||
if (result.isUnregistered() || result.isInvalidRegistrationId()) {
|
||||
executor.submit(() -> handleBadRegistration(message));
|
||||
} else if (result.hasCanonicalRegistrationId()) {
|
||||
|
||||
@@ -1,17 +1,27 @@
|
||||
package org.whispersystems.textsecuregcm.push;
|
||||
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
@SuppressWarnings("OptionalUsedAsFieldOrParameterType")
|
||||
public class GcmMessage {
|
||||
|
||||
private final String gcmId;
|
||||
private final String number;
|
||||
private final int deviceId;
|
||||
private final boolean receipt;
|
||||
public enum Type {
|
||||
RECEIPT, NOTIFICATION, CHALLENGE
|
||||
}
|
||||
|
||||
public GcmMessage(String gcmId, String number, int deviceId, boolean receipt) {
|
||||
this.gcmId = gcmId;
|
||||
this.number = number;
|
||||
this.deviceId = deviceId;
|
||||
this.receipt = receipt;
|
||||
private final String gcmId;
|
||||
private final String number;
|
||||
private final int deviceId;
|
||||
private final Type type;
|
||||
private final Optional<String> data;
|
||||
|
||||
public GcmMessage(String gcmId, String number, int deviceId, Type type, Optional<String> data) {
|
||||
this.gcmId = gcmId;
|
||||
this.number = number;
|
||||
this.deviceId = deviceId;
|
||||
this.type = type;
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
public String getGcmId() {
|
||||
@@ -22,11 +32,16 @@ public class GcmMessage {
|
||||
return number;
|
||||
}
|
||||
|
||||
public boolean isReceipt() {
|
||||
return receipt;
|
||||
public Type getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public int getDeviceId() {
|
||||
return deviceId;
|
||||
}
|
||||
|
||||
public Optional<String> getData() {
|
||||
return data;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -28,6 +28,7 @@ import org.whispersystems.textsecuregcm.util.BlockingThreadPoolExecutor;
|
||||
import org.whispersystems.textsecuregcm.util.Constants;
|
||||
import org.whispersystems.textsecuregcm.util.Util;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import static com.codahale.metrics.MetricRegistry.name;
|
||||
@@ -105,7 +106,7 @@ public class PushSender implements Managed {
|
||||
|
||||
private void sendGcmNotification(Account account, Device device) {
|
||||
GcmMessage gcmMessage = new GcmMessage(device.getGcmId(), account.getNumber(),
|
||||
(int)device.getId(), false);
|
||||
(int)device.getId(), GcmMessage.Type.NOTIFICATION, Optional.empty());
|
||||
|
||||
gcmSender.sendMessage(gcmMessage);
|
||||
}
|
||||
@@ -126,10 +127,10 @@ public class PushSender implements Managed {
|
||||
}
|
||||
|
||||
if (!Util.isEmpty(device.getVoipApnId())) {
|
||||
apnMessage = new ApnMessage(device.getVoipApnId(), account.getNumber(), device.getId(), true);
|
||||
apnMessage = new ApnMessage(device.getVoipApnId(), account.getNumber(), device.getId(), true, Optional.empty());
|
||||
RedisOperation.unchecked(() -> apnFallbackManager.schedule(account, device));
|
||||
} else {
|
||||
apnMessage = new ApnMessage(device.getApnId(), account.getNumber(), device.getId(), false);
|
||||
apnMessage = new ApnMessage(device.getApnId(), account.getNumber(), device.getId(), false, Optional.empty());
|
||||
}
|
||||
|
||||
apnSender.sendMessage(apnMessage);
|
||||
|
||||
Reference in New Issue
Block a user