diff --git a/pom.xml b/pom.xml index 32e4a7a96..3523a6c81 100644 --- a/pom.xml +++ b/pom.xml @@ -91,11 +91,6 @@ gcm-server 1.0.2 - - com.google.code.gson - gson - 2.2.2 - net.spy spymemcached diff --git a/src/main/java/org/whispersystems/textsecuregcm/configuration/FederationConfiguration.java b/src/main/java/org/whispersystems/textsecuregcm/configuration/FederationConfiguration.java index c4f3484a6..6bc5ec802 100644 --- a/src/main/java/org/whispersystems/textsecuregcm/configuration/FederationConfiguration.java +++ b/src/main/java/org/whispersystems/textsecuregcm/configuration/FederationConfiguration.java @@ -18,12 +18,8 @@ package org.whispersystems.textsecuregcm.configuration; import com.fasterxml.jackson.annotation.JsonProperty; -import com.google.gson.JsonArray; -import com.google.gson.JsonElement; -import com.google.gson.JsonParser; import org.whispersystems.textsecuregcm.federation.FederatedPeer; -import java.util.LinkedList; import java.util.List; public class FederationConfiguration { @@ -34,31 +30,7 @@ public class FederationConfiguration { @JsonProperty private String name; - @JsonProperty - private String herokuPeers; - public List getPeers() { - if (peers != null) { - return peers; - } - - if (herokuPeers != null) { - List peers = new LinkedList<>(); - JsonElement root = new JsonParser().parse(herokuPeers); - JsonArray peerElements = root.getAsJsonArray(); - - for (JsonElement peer : peerElements) { - String name = peer.getAsJsonObject().get("name").getAsString(); - String url = peer.getAsJsonObject().get("url").getAsString(); - String authenticationToken = peer.getAsJsonObject().get("authenticationToken").getAsString(); - String certificate = peer.getAsJsonObject().get("certificate").getAsString(); - - peers.add(new FederatedPeer(name, url, authenticationToken, certificate)); - } - - return peers; - } - return peers; } diff --git a/src/main/java/org/whispersystems/textsecuregcm/entities/ClientContact.java b/src/main/java/org/whispersystems/textsecuregcm/entities/ClientContact.java index 99ec3235c..14b2a5912 100644 --- a/src/main/java/org/whispersystems/textsecuregcm/entities/ClientContact.java +++ b/src/main/java/org/whispersystems/textsecuregcm/entities/ClientContact.java @@ -18,15 +18,10 @@ package org.whispersystems.textsecuregcm.entities; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; -import com.fasterxml.jackson.annotation.JsonValue; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.fasterxml.jackson.databind.annotation.JsonSerialize; -import com.google.gson.Gson; -import org.whispersystems.textsecuregcm.util.Base64; import org.whispersystems.textsecuregcm.util.ByteArrayAdapter; -import javax.xml.bind.annotation.XmlRootElement; -import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; import java.util.Arrays; @JsonInclude(JsonInclude.Include.NON_DEFAULT) @@ -73,9 +68,9 @@ public class ClientContact { this.inactive = inactive; } - public String toString() { - return new Gson().toJson(this); - } +// public String toString() { +// return new Gson().toJson(this); +// } @Override public boolean equals(Object other) { diff --git a/src/main/java/org/whispersystems/textsecuregcm/storage/DirectoryManager.java b/src/main/java/org/whispersystems/textsecuregcm/storage/DirectoryManager.java index baf30fee6..1c0c2f950 100644 --- a/src/main/java/org/whispersystems/textsecuregcm/storage/DirectoryManager.java +++ b/src/main/java/org/whispersystems/textsecuregcm/storage/DirectoryManager.java @@ -16,14 +16,19 @@ */ package org.whispersystems.textsecuregcm.storage; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.ObjectMapper; import com.google.common.base.Optional; -import com.google.gson.Gson; -import com.google.gson.annotations.SerializedName; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.whispersystems.textsecuregcm.entities.ClientContact; import org.whispersystems.textsecuregcm.util.IterablePair; import org.whispersystems.textsecuregcm.util.Pair; import org.whispersystems.textsecuregcm.util.Util; +import java.io.IOException; import java.util.LinkedList; import java.util.List; @@ -34,12 +39,17 @@ import redis.clients.jedis.Response; public class DirectoryManager { + private final Logger logger = LoggerFactory.getLogger(DirectoryManager.class); + private static final byte[] DIRECTORY_KEY = {'d', 'i', 'r', 'e', 'c', 't', 'o', 'r', 'y'}; + private final ObjectMapper objectMapper; private final JedisPool redisPool; public DirectoryManager(JedisPool redisPool) { - this.redisPool = redisPool; + this.redisPool = redisPool; + this.objectMapper = new ObjectMapper(); + this.objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); } public void remove(String number) { @@ -63,45 +73,48 @@ public class DirectoryManager { public void add(ClientContact contact) { TokenValue tokenValue = new TokenValue(contact.getRelay(), contact.isSupportsSms()); - Jedis jedis = redisPool.getResource(); - jedis.hset(DIRECTORY_KEY, contact.getToken(), new Gson().toJson(tokenValue).getBytes()); - redisPool.returnResource(jedis); + try (Jedis jedis = redisPool.getResource()) { + jedis.hset(DIRECTORY_KEY, contact.getToken(), objectMapper.writeValueAsBytes(tokenValue)); + } catch (JsonProcessingException e) { + logger.warn("JSON Serialization", e); + } } public void add(BatchOperationHandle handle, ClientContact contact) { - Pipeline pipeline = handle.pipeline; - TokenValue tokenValue = new TokenValue(contact.getRelay(), contact.isSupportsSms()); + try { + Pipeline pipeline = handle.pipeline; + TokenValue tokenValue = new TokenValue(contact.getRelay(), contact.isSupportsSms()); - pipeline.hset(DIRECTORY_KEY, contact.getToken(), new Gson().toJson(tokenValue).getBytes()); + pipeline.hset(DIRECTORY_KEY, contact.getToken(), objectMapper.writeValueAsBytes(tokenValue)); + } catch (JsonProcessingException e) { + logger.warn("JSON Serialization", e); + } } public PendingClientContact get(BatchOperationHandle handle, byte[] token) { Pipeline pipeline = handle.pipeline; - return new PendingClientContact(token, pipeline.hget(DIRECTORY_KEY, token)); + return new PendingClientContact(objectMapper, token, pipeline.hget(DIRECTORY_KEY, token)); } public Optional get(byte[] token) { - Jedis jedis = redisPool.getResource(); - - try { + try (Jedis jedis = redisPool.getResource()) { byte[] result = jedis.hget(DIRECTORY_KEY, token); if (result == null) { return Optional.absent(); } - TokenValue tokenValue = new Gson().fromJson(new String(result), TokenValue.class); + TokenValue tokenValue = objectMapper.readValue(result, TokenValue.class); return Optional.of(new ClientContact(token, tokenValue.relay, tokenValue.supportsSms)); - } finally { - redisPool.returnResource(jedis); + } catch (IOException e) { + logger.warn("JSON Error", e); + return Optional.absent(); } } public List get(List tokens) { - Jedis jedis = redisPool.getResource(); - - try { + try (Jedis jedis = redisPool.getResource()) { Pipeline pipeline = jedis.pipelined(); List> futures = new LinkedList<>(); List results = new LinkedList<>(); @@ -117,17 +130,19 @@ public class DirectoryManager { IterablePair> lists = new IterablePair<>(tokens, futures); for (Pair> pair : lists) { - if (pair.second().get() != null) { - TokenValue tokenValue = new Gson().fromJson(new String(pair.second().get()), TokenValue.class); - ClientContact clientContact = new ClientContact(pair.first(), tokenValue.relay, tokenValue.supportsSms); + try { + if (pair.second().get() != null) { + TokenValue tokenValue = objectMapper.readValue(pair.second().get(), TokenValue.class); + ClientContact clientContact = new ClientContact(pair.first(), tokenValue.relay, tokenValue.supportsSms); - results.add(clientContact); + results.add(clientContact); + } + } catch (IOException e) { + logger.warn("Deserialization Problem: ", e); } } return results; - } finally { - redisPool.returnResource(jedis); } } @@ -156,10 +171,10 @@ public class DirectoryManager { } private static class TokenValue { - @SerializedName("r") + @JsonProperty(value = "r") private String relay; - @SerializedName("s") + @JsonProperty(value = "s") private boolean supportsSms; public TokenValue(String relay, boolean supportsSms) { @@ -169,22 +184,24 @@ public class DirectoryManager { } public static class PendingClientContact { + private final ObjectMapper objectMapper; private final byte[] token; private final Response response; - PendingClientContact(byte[] token, Response response) { - this.token = token; - this.response = response; + PendingClientContact(ObjectMapper objectMapper, byte[] token, Response response) { + this.objectMapper = objectMapper; + this.token = token; + this.response = response; } - public Optional get() { + public Optional get() throws IOException { byte[] result = response.get(); if (result == null) { return Optional.absent(); } - TokenValue tokenValue = new Gson().fromJson(new String(result), TokenValue.class); + TokenValue tokenValue = objectMapper.readValue(result, TokenValue.class); return Optional.of(new ClientContact(token, tokenValue.relay, tokenValue.supportsSms)); } diff --git a/src/main/java/org/whispersystems/textsecuregcm/workers/DirectoryUpdater.java b/src/main/java/org/whispersystems/textsecuregcm/workers/DirectoryUpdater.java index 45b4ecd5c..2348e0500 100644 --- a/src/main/java/org/whispersystems/textsecuregcm/workers/DirectoryUpdater.java +++ b/src/main/java/org/whispersystems/textsecuregcm/workers/DirectoryUpdater.java @@ -29,6 +29,7 @@ import org.whispersystems.textsecuregcm.storage.DirectoryManager.BatchOperationH import org.whispersystems.textsecuregcm.util.Base64; import org.whispersystems.textsecuregcm.util.Util; +import java.io.IOException; import java.util.Iterator; import java.util.LinkedList; import java.util.List; @@ -53,9 +54,12 @@ public class DirectoryUpdater { } public void updateFromLocalDatabase() { - BatchOperationHandle batchOperation = directory.startBatchOperation(); + int contactsAdded = 0; + int contactsRemoved = 0; + BatchOperationHandle batchOperation = directory.startBatchOperation(); try { + logger.info("Updating from local DB."); Iterator accounts = accountsManager.getAll(); if (accounts == null) @@ -69,17 +73,17 @@ public class DirectoryUpdater { ClientContact clientContact = new ClientContact(token, null, account.getSupportsSms()); directory.add(batchOperation, clientContact); - - logger.debug("Adding local token: " + Base64.encodeBytesWithoutPadding(token)); + contactsAdded++; } else { directory.remove(batchOperation, account.getNumber()); + contactsRemoved++; } } } finally { directory.stopBatchOperation(batchOperation); } - logger.info("Local directory is updated."); + logger.info(String.format("Local directory is updated (%d added, %d removed).", contactsAdded, contactsRemoved)); } public void updateFromPeers() { @@ -121,19 +125,23 @@ public class DirectoryUpdater { Iterator localContactIterator = localContacts.iterator(); while (remoteContactIterator.hasNext() && localContactIterator.hasNext()) { - ClientContact remoteContact = remoteContactIterator.next(); - Optional localContact = localContactIterator.next().get(); + try { + ClientContact remoteContact = remoteContactIterator.next(); + Optional localContact = localContactIterator.next().get(); - remoteContact.setRelay(client.getPeerName()); + remoteContact.setRelay(client.getPeerName()); - if (!remoteContact.isInactive() && (!localContact.isPresent() || client.getPeerName().equals(localContact.get().getRelay()))) { - contactsAdded++; - directory.add(handle, remoteContact); - } else { - if (localContact.isPresent() && client.getPeerName().equals(localContact.get().getRelay())) { - contactsRemoved++; - directory.remove(handle, remoteContact.getToken()); + if (!remoteContact.isInactive() && (!localContact.isPresent() || client.getPeerName().equals(localContact.get().getRelay()))) { + contactsAdded++; + directory.add(handle, remoteContact); + } else { + if (localContact.isPresent() && client.getPeerName().equals(localContact.get().getRelay())) { + contactsRemoved++; + directory.remove(handle, remoteContact.getToken()); + } } + } catch (IOException e) { + logger.warn("JSON Serialization Failed: ", e); } }