Make first account "master" for directory purposes

This commit is contained in:
Matt Corallo 2014-01-09 11:44:20 -10:00
parent 591d26981e
commit 2473505d4e
6 changed files with 36 additions and 89 deletions

View File

@ -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<NumberData> numberList = accounts.getAllNumbers(offset, ACCOUNT_CHUNK_SIZE);
List<Account> numberList = accounts.getAllMasterAccounts(offset, ACCOUNT_CHUNK_SIZE);
List<ClientContact> 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);

View File

@ -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());
}
}

View File

@ -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<NumberData> 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<Account> getAllFirstAccounts(@Bind("offset") int offset, @Bind("limit") int length);
@Mapper(NumberDataMapper.class)
@SqlQuery(NUMBER_DATA_QUERY + " GROUP BY " + NUMBER)
public abstract Iterator<NumberData> 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<Account> 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<NumberData> {
@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})

View File

@ -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<NumberData> getAllNumbers(int offset, int length) {
return accounts.getAllNumbers(offset, length);
public List<Account> getAllMasterAccounts(int offset, int length) {
return accounts.getAllFirstAccounts(offset, length);
}
public Iterator<NumberData> getAllNumbers() {
return accounts.getAllNumbers();
public Iterator<Account> 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<Account> 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());

View File

@ -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;
}
}

View File

@ -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<NumberData> numbers = accountsManager.getAllNumbers();
Iterator<Account> 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 {