From 2473505d4e45ded916957c7dfb630d055c223e6f Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Thu, 9 Jan 2014 11:44:20 -1000 Subject: [PATCH] Make first account "master" for directory purposes --- .../controllers/FederationController.java | 12 +++---- .../textsecuregcm/storage/Account.java | 5 +++ .../textsecuregcm/storage/Accounts.java | 34 ++++--------------- .../storage/AccountsManager.java | 32 +++++++---------- .../textsecuregcm/util/NumberData.java | 25 -------------- .../workers/DirectoryUpdater.java | 17 +++++----- 6 files changed, 36 insertions(+), 89 deletions(-) delete mode 100644 src/main/java/org/whispersystems/textsecuregcm/util/NumberData.java diff --git a/src/main/java/org/whispersystems/textsecuregcm/controllers/FederationController.java b/src/main/java/org/whispersystems/textsecuregcm/controllers/FederationController.java index bc31b4121..0682b290c 100644 --- a/src/main/java/org/whispersystems/textsecuregcm/controllers/FederationController.java +++ b/src/main/java/org/whispersystems/textsecuregcm/controllers/FederationController.java @@ -27,7 +27,6 @@ import org.whispersystems.textsecuregcm.entities.AttachmentUri; import org.whispersystems.textsecuregcm.entities.ClientContact; import org.whispersystems.textsecuregcm.entities.ClientContacts; import org.whispersystems.textsecuregcm.entities.MessageProtos.OutgoingMessageSignal; -import org.whispersystems.textsecuregcm.entities.PreKey; import org.whispersystems.textsecuregcm.entities.RelayMessage; import org.whispersystems.textsecuregcm.entities.UnstructuredPreKeyList; import org.whispersystems.textsecuregcm.federation.FederatedPeer; @@ -35,7 +34,6 @@ import org.whispersystems.textsecuregcm.push.PushSender; import org.whispersystems.textsecuregcm.storage.Account; import org.whispersystems.textsecuregcm.storage.AccountsManager; import org.whispersystems.textsecuregcm.storage.Keys; -import org.whispersystems.textsecuregcm.util.NumberData; import org.whispersystems.textsecuregcm.util.UrlSigner; import org.whispersystems.textsecuregcm.util.Util; @@ -138,14 +136,14 @@ public class FederationController { public ClientContacts getUserTokens(@Auth FederatedPeer peer, @PathParam("offset") int offset) { - List numberList = accounts.getAllNumbers(offset, ACCOUNT_CHUNK_SIZE); + List numberList = accounts.getAllMasterAccounts(offset, ACCOUNT_CHUNK_SIZE); List clientContacts = new LinkedList<>(); - for (NumberData number : numberList) { - byte[] token = Util.getContactToken(number.getNumber()); - ClientContact clientContact = new ClientContact(token, null, number.isSupportsSms()); + for (Account account : numberList) { + byte[] token = Util.getContactToken(account.getNumber()); + ClientContact clientContact = new ClientContact(token, null, account.getSupportsSms()); - if (!number.isActive()) + if (!account.isActive()) clientContact.setInactive(true); clientContacts.add(clientContact); diff --git a/src/main/java/org/whispersystems/textsecuregcm/storage/Account.java b/src/main/java/org/whispersystems/textsecuregcm/storage/Account.java index f16bc1d23..0e30f8165 100644 --- a/src/main/java/org/whispersystems/textsecuregcm/storage/Account.java +++ b/src/main/java/org/whispersystems/textsecuregcm/storage/Account.java @@ -18,6 +18,7 @@ package org.whispersystems.textsecuregcm.storage; import org.whispersystems.textsecuregcm.auth.AuthenticationCredentials; +import org.whispersystems.textsecuregcm.util.Util; import java.io.Serializable; @@ -131,4 +132,8 @@ public class Account implements Serializable { public boolean getFetchesMessages() { return fetchesMessages; } + + public boolean isActive() { + return getFetchesMessages() || !Util.isEmpty(getApnRegistrationId()) || !Util.isEmpty(getGcmRegistrationId()); + } } diff --git a/src/main/java/org/whispersystems/textsecuregcm/storage/Accounts.java b/src/main/java/org/whispersystems/textsecuregcm/storage/Accounts.java index e25769f3e..11263e6f0 100644 --- a/src/main/java/org/whispersystems/textsecuregcm/storage/Accounts.java +++ b/src/main/java/org/whispersystems/textsecuregcm/storage/Accounts.java @@ -29,7 +29,6 @@ import org.skife.jdbi.v2.sqlobject.SqlUpdate; import org.skife.jdbi.v2.sqlobject.Transaction; import org.skife.jdbi.v2.sqlobject.customizers.Mapper; import org.skife.jdbi.v2.tweak.ResultSetMapper; -import org.whispersystems.textsecuregcm.util.NumberData; import java.lang.annotation.Annotation; import java.lang.annotation.ElementType; @@ -54,13 +53,6 @@ public abstract class Accounts { public static final String FETCHES_MESSAGES = "fetches_messages"; public static final String SUPPORTS_SMS = "supports_sms"; - - private static final String NUMBER_DATA_QUERY = "SELECT number, COUNT(" + - "CASE WHEN (" + GCM_ID + " IS NOT NULL OR " + APN_ID + " IS NOT NULL OR " + FETCHES_MESSAGES + " = 1) " + - "THEN 1 ELSE 0 END) AS active, COUNT(" + - "CASE WHEN " + SUPPORTS_SMS + " = 1 THEN 1 ELSE 0 END) AS " + SUPPORTS_SMS + " " + - "FROM accounts"; - @SqlUpdate("INSERT INTO accounts (" + NUMBER + ", " + DEVICE_ID + ", " + AUTH_TOKEN + ", " + SALT + ", " + SIGNALING_KEY + ", " + FETCHES_MESSAGES + ", " + GCM_ID + ", " + APN_ID + ", " + SUPPORTS_SMS + ") " + @@ -93,17 +85,13 @@ public abstract class Accounts { @SqlQuery("SELECT COUNT(DISTINCT " + NUMBER + ") from accounts") abstract long getNumberCount(); - @Mapper(NumberDataMapper.class) - @SqlQuery(NUMBER_DATA_QUERY + " GROUP BY " + NUMBER + " OFFSET :offset LIMIT :limit") - abstract List getAllNumbers(@Bind("offset") int offset, @Bind("limit") int length); + @Mapper(AccountMapper.class) + @SqlQuery("SELECT * FROM accounts WHERE " + DEVICE_ID + " = 1 OFFSET :offset LIMIT :limit") + abstract List getAllFirstAccounts(@Bind("offset") int offset, @Bind("limit") int length); - @Mapper(NumberDataMapper.class) - @SqlQuery(NUMBER_DATA_QUERY + " GROUP BY " + NUMBER) - public abstract Iterator getAllNumbers(); - - @Mapper(NumberDataMapper.class) - @SqlQuery(NUMBER_DATA_QUERY + " WHERE " + NUMBER + " = :number GROUP BY " + NUMBER) - abstract NumberData getNumberData(@Bind("number") String number); + @Mapper(AccountMapper.class) + @SqlQuery("SELECT * FROM accounts WHERE " + DEVICE_ID + " = 1") + public abstract Iterator getAllFirstAccounts(); @Mapper(AccountMapper.class) @SqlQuery("SELECT * FROM accounts WHERE " + NUMBER + " = :number") @@ -130,16 +118,6 @@ public abstract class Accounts { } } - public static class NumberDataMapper implements ResultSetMapper { - - @Override - public NumberData map(int i, ResultSet resultSet, StatementContext statementContext) - throws SQLException - { - return new NumberData(resultSet.getString("number"), resultSet.getInt("active") != 0, resultSet.getInt(SUPPORTS_SMS) != 0); - } - } - @BindingAnnotation(AccountBinder.AccountBinderFactory.class) @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.PARAMETER}) diff --git a/src/main/java/org/whispersystems/textsecuregcm/storage/AccountsManager.java b/src/main/java/org/whispersystems/textsecuregcm/storage/AccountsManager.java index c21e9f180..e8d699255 100644 --- a/src/main/java/org/whispersystems/textsecuregcm/storage/AccountsManager.java +++ b/src/main/java/org/whispersystems/textsecuregcm/storage/AccountsManager.java @@ -20,7 +20,6 @@ package org.whispersystems.textsecuregcm.storage; import com.google.common.base.Optional; import net.spy.memcached.MemcachedClient; import org.whispersystems.textsecuregcm.entities.ClientContact; -import org.whispersystems.textsecuregcm.util.NumberData; import org.whispersystems.textsecuregcm.util.Util; import java.util.Iterator; @@ -45,12 +44,12 @@ public class AccountsManager { return accounts.getNumberCount(); } - public List getAllNumbers(int offset, int length) { - return accounts.getAllNumbers(offset, length); + public List getAllMasterAccounts(int offset, int length) { + return accounts.getAllFirstAccounts(offset, length); } - public Iterator getAllNumbers() { - return accounts.getAllNumbers(); + public Iterator getAllMasterAccounts() { + return accounts.getAllFirstAccounts(); } /** Creates a new Account and NumberData, clearing all existing accounts/data on the given number */ @@ -62,7 +61,7 @@ public class AccountsManager { memcachedClient.set(getKey(account.getNumber(), account.getDeviceId()), 0, account); } - updateDirectory(account, false); + updateDirectory(account); } /** Creates a new Account for an existing NumberData (setting the deviceId) */ @@ -74,7 +73,7 @@ public class AccountsManager { memcachedClient.set(getKey(account.getNumber(), account.getDeviceId()), 0, account); } - updateDirectory(account, true); + updateDirectory(account); } public void update(Account account) { @@ -83,7 +82,7 @@ public class AccountsManager { } accounts.update(account); - updateDirectory(account, true); + updateDirectory(account); } public Optional get(String number, long deviceId) { @@ -109,20 +108,13 @@ public class AccountsManager { return accounts.getAllByNumber(number); } - private void updateDirectory(Account account, boolean possiblyOtherAccounts) { - boolean active = account.getFetchesMessages() || - !Util.isEmpty(account.getApnRegistrationId()) || !Util.isEmpty(account.getGcmRegistrationId()); - boolean supportsSms = account.getSupportsSms(); + private void updateDirectory(Account account) { + if (account.getDeviceId() != 1) + return; - if (possiblyOtherAccounts && (!active || !supportsSms)) { - NumberData numberData = accounts.getNumberData(account.getNumber()); - active = numberData.isActive(); - supportsSms = numberData.isSupportsSms(); - } - - if (active) { + if (account.isActive()) { byte[] token = Util.getContactToken(account.getNumber()); - ClientContact clientContact = new ClientContact(token, null, supportsSms); + ClientContact clientContact = new ClientContact(token, null, account.getSupportsSms()); directory.add(clientContact); } else { directory.remove(account.getNumber()); diff --git a/src/main/java/org/whispersystems/textsecuregcm/util/NumberData.java b/src/main/java/org/whispersystems/textsecuregcm/util/NumberData.java deleted file mode 100644 index 8fd446e61..000000000 --- a/src/main/java/org/whispersystems/textsecuregcm/util/NumberData.java +++ /dev/null @@ -1,25 +0,0 @@ -package org.whispersystems.textsecuregcm.util; - -public class NumberData { - private String number; - private boolean active; - private boolean supportsSms; - - public NumberData(String number, boolean active, boolean supportsSms) { - this.number = number; - this.active = active; - this.supportsSms = supportsSms; - } - - public boolean isActive() { - return active; - } - - public boolean isSupportsSms() { - return supportsSms; - } - - public String getNumber() { - return number; - } -} diff --git a/src/main/java/org/whispersystems/textsecuregcm/workers/DirectoryUpdater.java b/src/main/java/org/whispersystems/textsecuregcm/workers/DirectoryUpdater.java index 916d70104..e2e294e54 100644 --- a/src/main/java/org/whispersystems/textsecuregcm/workers/DirectoryUpdater.java +++ b/src/main/java/org/whispersystems/textsecuregcm/workers/DirectoryUpdater.java @@ -27,7 +27,6 @@ import org.whispersystems.textsecuregcm.storage.AccountsManager; import org.whispersystems.textsecuregcm.storage.DirectoryManager; import org.whispersystems.textsecuregcm.storage.DirectoryManager.BatchOperationHandle; import org.whispersystems.textsecuregcm.util.Base64; -import org.whispersystems.textsecuregcm.util.NumberData; import org.whispersystems.textsecuregcm.util.Util; import java.util.Iterator; @@ -54,22 +53,22 @@ public class DirectoryUpdater { BatchOperationHandle batchOperation = directory.startBatchOperation(); try { - Iterator numbers = accountsManager.getAllNumbers(); + Iterator accounts = accountsManager.getAllMasterAccounts(); - if (numbers == null) + if (accounts == null) return; - while (numbers.hasNext()) { - NumberData number = numbers.next(); - if (number.isActive()) { - byte[] token = Util.getContactToken(number.getNumber()); - ClientContact clientContact = new ClientContact(token, null, number.isSupportsSms()); + while (accounts.hasNext()) { + Account account = accounts.next(); + if (account.isActive()) { + byte[] token = Util.getContactToken(account.getNumber()); + ClientContact clientContact = new ClientContact(token, null, account.getSupportsSms()); directory.add(batchOperation, clientContact); logger.debug("Adding local token: " + Base64.encodeBytesWithoutPadding(token)); } else { - directory.remove(batchOperation, number.getNumber()); + directory.remove(batchOperation, account.getNumber()); } } } finally {