Use a custom redis pubsub implementation rather than Jedis.

// FREEBIE
This commit is contained in:
Moxie Marlinspike
2015-03-16 15:05:33 -07:00
parent e79861c30a
commit c7e0cc1158
26 changed files with 1254 additions and 292 deletions

View File

@@ -4,58 +4,62 @@ import com.google.common.base.Optional;
import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.protobuf.InvalidProtocolBufferException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.whispersystems.dispatch.DispatchChannel;
import org.whispersystems.textsecuregcm.entities.MessageProtos.ProvisioningUuid;
import org.whispersystems.textsecuregcm.storage.PubSubListener;
import org.whispersystems.textsecuregcm.storage.PubSubManager;
import org.whispersystems.textsecuregcm.storage.PubSubProtos.PubSubMessage;
import org.whispersystems.websocket.WebSocketClient;
import org.whispersystems.websocket.messages.WebSocketResponseMessage;
public class ProvisioningConnection implements PubSubListener {
public class ProvisioningConnection implements DispatchChannel {
private final PubSubManager pubSubManager;
private final ProvisioningAddress provisioningAddress;
private final WebSocketClient client;
private final Logger logger = LoggerFactory.getLogger(ProvisioningConnection.class);
public ProvisioningConnection(PubSubManager pubSubManager, WebSocketClient client) {
this.pubSubManager = pubSubManager;
this.client = client;
this.provisioningAddress = ProvisioningAddress.generate();
private final WebSocketClient client;
public ProvisioningConnection(WebSocketClient client) {
this.client = client;
}
@Override
public void onPubSubMessage(PubSubMessage outgoingMessage) {
if (outgoingMessage.getType() == PubSubMessage.Type.DELIVER) {
Optional<byte[]> body = Optional.of(outgoingMessage.getContent().toByteArray());
public void onDispatchMessage(String channel, byte[] message) {
try {
PubSubMessage outgoingMessage = PubSubMessage.parseFrom(message);
ListenableFuture<WebSocketResponseMessage> response = client.sendRequest("PUT", "/v1/message", body);
if (outgoingMessage.getType() == PubSubMessage.Type.DELIVER) {
Optional<byte[]> body = Optional.of(outgoingMessage.getContent().toByteArray());
Futures.addCallback(response, new FutureCallback<WebSocketResponseMessage>() {
@Override
public void onSuccess(WebSocketResponseMessage webSocketResponseMessage) {
pubSubManager.unsubscribe(provisioningAddress, ProvisioningConnection.this);
client.close(1001, "All you get.");
}
ListenableFuture<WebSocketResponseMessage> response = client.sendRequest("PUT", "/v1/message", body);
@Override
public void onFailure(Throwable throwable) {
pubSubManager.unsubscribe(provisioningAddress, ProvisioningConnection.this);
client.close(1001, "That's all!");
}
});
Futures.addCallback(response, new FutureCallback<WebSocketResponseMessage>() {
@Override
public void onSuccess(WebSocketResponseMessage webSocketResponseMessage) {
client.close(1001, "All you get.");
}
@Override
public void onFailure(Throwable throwable) {
client.close(1001, "That's all!");
}
});
}
} catch (InvalidProtocolBufferException e) {
logger.warn("Protobuf Error: ", e);
}
}
public void onConnected() {
this.pubSubManager.subscribe(provisioningAddress, this);
@Override
public void onDispatchSubscribed(String channel) {
this.client.sendRequest("PUT", "/v1/address", Optional.of(ProvisioningUuid.newBuilder()
.setUuid(provisioningAddress.getAddress())
.setUuid(channel)
.build()
.toByteArray()));
}
public void onConnectionLost() {
this.pubSubManager.unsubscribe(provisioningAddress, this);
this.client.close(1001, "Done");
@Override
public void onDispatchUnsubscribed(String channel) {
this.client.close(1001, "Closed");
}
}