Make APN fallback behave well in multi-server environments.

// FREEBIE
This commit is contained in:
Moxie Marlinspike
2015-07-29 15:02:44 -07:00
parent 8d0d934249
commit d4e618893c
13 changed files with 179 additions and 49 deletions

View File

@@ -13,6 +13,8 @@ import org.whispersystems.textsecuregcm.storage.AccountsManager;
import org.whispersystems.textsecuregcm.storage.Device;
import org.whispersystems.textsecuregcm.storage.MessagesManager;
import org.whispersystems.textsecuregcm.storage.PubSubManager;
import org.whispersystems.textsecuregcm.storage.PubSubProtos;
import org.whispersystems.textsecuregcm.storage.PubSubProtos.PubSubMessage;
import org.whispersystems.textsecuregcm.util.Constants;
import org.whispersystems.textsecuregcm.util.Util;
import org.whispersystems.websocket.session.WebSocketSessionContext;
@@ -47,15 +49,16 @@ public class AuthenticatedConnectListener implements WebSocketConnectListener {
@Override
public void onWebSocketConnect(WebSocketSessionContext context) {
final Account account = context.getAuthenticated(Account.class);
final Device device = account.getAuthenticatedDevice().get();
final long connectTime = System.currentTimeMillis();
final WebsocketAddress address = new WebsocketAddress(account.getNumber(), device.getId());
final WebSocketConnection connection = new WebSocketConnection(pushSender, receiptSender,
messagesManager, account, device,
context.getClient());
final Account account = context.getAuthenticated(Account.class);
final Device device = account.getAuthenticatedDevice().get();
final long connectTime = System.currentTimeMillis();
final WebsocketAddress address = new WebsocketAddress(account.getNumber(), device.getId());
final WebSocketConnectionInfo info = new WebSocketConnectionInfo(address);
final WebSocketConnection connection = new WebSocketConnection(pushSender, receiptSender,
messagesManager, account, device,
context.getClient());
apnFallbackManager.cancel(address);
pubSubManager.publish(info, PubSubMessage.newBuilder().setType(PubSubMessage.Type.CONNECTED).build());
updateLastSeen(account, device);
pubSubManager.subscribe(address, connection);

View File

@@ -0,0 +1,58 @@
package org.whispersystems.textsecuregcm.websocket;
import org.whispersystems.textsecuregcm.storage.PubSubAddress;
import org.whispersystems.textsecuregcm.util.Util;
public class WebSocketConnectionInfo implements PubSubAddress {
private final WebsocketAddress address;
public WebSocketConnectionInfo(WebsocketAddress address) {
this.address = address;
}
public WebSocketConnectionInfo(String serialized) throws FormattingException {
String[] parts = serialized.split("[:]", 3);
if (parts.length != 3 || !"c".equals(parts[2])) {
throw new FormattingException("Bad address: " + serialized);
}
try {
this.address = new WebsocketAddress(parts[0], Long.parseLong(parts[1]));
} catch (NumberFormatException e) {
throw new FormattingException(e);
}
}
public String serialize() {
return address.serialize() + ":c";
}
public WebsocketAddress getWebsocketAddress() {
return address;
}
@Override
public boolean equals(Object other) {
return
other != null &&
other instanceof WebSocketConnectionInfo
&& ((WebSocketConnectionInfo)other).address.equals(address);
}
@Override
public int hashCode() {
return Util.hashCode(address, "c");
}
public static class FormattingException extends Exception {
public FormattingException(String message) {
super(message);
}
public FormattingException(Exception e) {
super(e);
}
}
}

View File

@@ -1,6 +1,8 @@
package org.whispersystems.textsecuregcm.websocket;
public class WebsocketAddress {
import org.whispersystems.textsecuregcm.storage.PubSubAddress;
public class WebsocketAddress implements PubSubAddress {
private final String number;
private final long deviceId;