Support for server federation.

This commit is contained in:
Moxie Marlinspike
2013-10-18 22:45:27 -07:00
parent 25a2ad7289
commit fa5ccc3f8a
15 changed files with 372 additions and 116 deletions

View File

@@ -10,6 +10,8 @@ import org.thoughtcrime.securesms.service.SendReceiveService;
import org.thoughtcrime.securesms.util.TextSecurePreferences;
import org.whispersystems.textsecure.crypto.InvalidVersionException;
import org.whispersystems.textsecure.directory.Directory;
import org.whispersystems.textsecure.directory.NotInDirectoryException;
import org.whispersystems.textsecure.push.ContactTokenDetails;
import org.whispersystems.textsecure.push.IncomingEncryptedPushMessage;
import org.whispersystems.textsecure.push.IncomingPushMessage;
import org.whispersystems.textsecure.push.PushServiceSocket;
@@ -59,13 +61,16 @@ public class GcmIntentService extends GCMBaseIntentService {
IncomingEncryptedPushMessage encryptedMessage = new IncomingEncryptedPushMessage(data, sessionKey);
IncomingPushMessage message = encryptedMessage.getIncomingPushMessage();
if (!isActiveNumber(context, message.getSource())) {
Directory directory = Directory.getInstance(context);
String contactToken = directory.getToken(message.getSource());
ContactTokenDetails contactTokenDetails = new ContactTokenDetails(contactToken, message.getRelay());
directory.setToken(contactTokenDetails, true);
}
Intent service = new Intent(context, SendReceiveService.class);
service.setAction(SendReceiveService.RECEIVE_PUSH_ACTION);
service.putExtra("message", message);
Directory directory = Directory.getInstance(context);
directory.setToken(directory.getToken(message.getSource()), true);
context.startService(service);
} catch (IOException e) {
Log.w("GcmIntentService", e);
@@ -84,4 +89,16 @@ public class GcmIntentService extends GCMBaseIntentService {
String password = TextSecurePreferences.getPushServerPassword(context);
return new PushServiceSocket(context, localNumber, password);
}
private boolean isActiveNumber(Context context, String e164number) {
boolean isActiveNumber;
try {
isActiveNumber = Directory.getInstance(context).isActiveNumber(e164number);
} catch (NotInDirectoryException e) {
isActiveNumber = false;
}
return isActiveNumber;
}
}

View File

@@ -10,6 +10,7 @@ import android.util.Log;
import org.thoughtcrime.securesms.util.TextSecurePreferences;
import org.whispersystems.textsecure.directory.Directory;
import org.whispersystems.textsecure.push.ContactTokenDetails;
import org.whispersystems.textsecure.push.PushServiceSocket;
import java.util.List;
@@ -61,11 +62,14 @@ public class DirectoryRefreshService extends Service {
String password = TextSecurePreferences.getPushServerPassword(context);
PushServiceSocket socket = new PushServiceSocket(context, localNumber, password);
Set<String> eligibleContactTokens = directory.getPushEligibleContactTokens(localNumber);
List<String> activeTokens = socket.retrieveDirectory(eligibleContactTokens);
Set<String> eligibleContactTokens = directory.getPushEligibleContactTokens(localNumber);
List<ContactTokenDetails> activeTokens = socket.retrieveDirectory(eligibleContactTokens);
if (activeTokens != null) {
eligibleContactTokens.removeAll(activeTokens);
for (ContactTokenDetails activeToken : activeTokens) {
eligibleContactTokens.remove(activeToken.getToken());
}
directory.setTokens(activeTokens, eligibleContactTokens);
}

View File

@@ -20,6 +20,7 @@ import org.whispersystems.textsecure.crypto.IdentityKey;
import org.whispersystems.textsecure.crypto.MasterSecret;
import org.whispersystems.textsecure.crypto.PreKeyUtil;
import org.whispersystems.textsecure.directory.Directory;
import org.whispersystems.textsecure.push.ContactTokenDetails;
import org.whispersystems.textsecure.push.PushServiceSocket;
import org.whispersystems.textsecure.storage.PreKeyRecord;
import org.whispersystems.textsecure.util.Util;
@@ -282,11 +283,13 @@ public class RegistrationService extends Service {
String gcmRegistrationId = waitForGcmRegistrationId();
socket.registerGcmId(gcmRegistrationId);
Set<String> contactTokens = Directory.getInstance(this).getPushEligibleContactTokens(number);
List<String> activeTokens = socket.retrieveDirectory(contactTokens);
Set<String> contactTokens = Directory.getInstance(this).getPushEligibleContactTokens(number);
List<ContactTokenDetails> activeTokens = socket.retrieveDirectory(contactTokens);
if (activeTokens != null) {
contactTokens.removeAll(activeTokens);
for (ContactTokenDetails activeToken : activeTokens) {
contactTokens.remove(activeToken.getToken());
}
Directory.getInstance(this).setTokens(activeTokens, contactTokens);
}

View File

@@ -22,6 +22,7 @@ import org.whispersystems.textsecure.crypto.KeyUtil;
import org.whispersystems.textsecure.crypto.MasterSecret;
import org.whispersystems.textsecure.crypto.MessageCipher;
import org.whispersystems.textsecure.crypto.protocol.PreKeyBundleMessage;
import org.whispersystems.textsecure.directory.Directory;
import org.whispersystems.textsecure.push.OutgoingPushMessage;
import org.whispersystems.textsecure.push.PreKeyEntity;
import org.whispersystems.textsecure.push.PushAttachmentData;
@@ -61,12 +62,12 @@ public class PushTransport extends BaseTransport {
String plaintextBody = message.getBody().getBody();
PushMessageContent.Builder builder = PushMessageContent.newBuilder();
byte[] plaintext = builder.setBody(plaintextBody).build().toByteArray();
String recipientCanonicalNumber = PhoneNumberFormatter.formatNumber(recipient.getNumber(),
localNumber);
String recipientCanonicalNumber = PhoneNumberFormatter.formatNumber(recipient.getNumber(), localNumber);
String relay = Directory.getInstance(context).getRelay(recipientCanonicalNumber);
Pair<Integer, byte[]> typeAndCiphertext = getEncryptedMessage(socket, recipient, recipientCanonicalNumber, plaintext);
socket.sendMessage(recipientCanonicalNumber, typeAndCiphertext.second, typeAndCiphertext.first);
socket.sendMessage(relay, recipientCanonicalNumber, typeAndCiphertext.second, typeAndCiphertext.first);
context.sendBroadcast(constructSentIntent(context, message.getId(), message.getType()));
} catch (RateLimitException e) {
@@ -81,7 +82,8 @@ public class PushTransport extends BaseTransport {
String password = TextSecurePreferences.getPushServerPassword(context);
PushServiceSocket socket = new PushServiceSocket(context, localNumber, password);
String messageBody = PartParser.getMessageText(message.getBody());
List<byte[]> ciphertext = new LinkedList<byte[]> ();
List<String> relays = new LinkedList<String>();
List<byte[]> ciphertext = new LinkedList<byte[]>();
List<Integer> types = new LinkedList<Integer>();
for (String destination : destinations) {
@@ -108,11 +110,12 @@ public class PushTransport extends BaseTransport {
Pair<Integer, byte[]> typeAndCiphertext = getEncryptedMessage(socket, recipients.getPrimaryRecipient(),
destination, plaintext);
relays.add(Directory.getInstance(context).getRelay(destination));
types.add(typeAndCiphertext.first);
ciphertext.add(typeAndCiphertext.second);
}
socket.sendMessage(destinations, ciphertext, types);
socket.sendMessage(relays, destinations, ciphertext, types);
} catch (RateLimitException e) {
Log.w("PushTransport", e);
@@ -187,7 +190,8 @@ public class PushTransport extends BaseTransport {
{
IdentityKeyPair identityKeyPair = IdentityKeyUtil.getIdentityKeyPair(context, masterSecret);
IdentityKey identityKey = identityKeyPair.getPublicKey();
PreKeyEntity preKey = socket.getPreKey(canonicalRecipientNumber);
String relay = Directory.getInstance(context).getRelay(canonicalRecipientNumber);
PreKeyEntity preKey = socket.getPreKey(canonicalRecipientNumber, relay);
KeyExchangeProcessor processor = new KeyExchangeProcessor(context, masterSecret, recipient);
processor.processKeyExchangeMessage(preKey);

View File

@@ -27,6 +27,7 @@ import org.thoughtcrime.securesms.util.Util;
import org.whispersystems.textsecure.crypto.MasterSecret;
import org.whispersystems.textsecure.directory.Directory;
import org.whispersystems.textsecure.directory.NotInDirectoryException;
import org.whispersystems.textsecure.push.ContactTokenDetails;
import org.whispersystems.textsecure.push.PushServiceSocket;
import java.io.IOException;
@@ -126,15 +127,20 @@ public class UniversalTransport {
return directory.isActiveNumber(destination);
} catch (NotInDirectoryException e) {
try {
String localNumber = TextSecurePreferences.getLocalNumber(context);
String pushPassword = TextSecurePreferences.getPushServerPassword(context);
String contactToken = directory.getToken(destination);
PushServiceSocket socket = new PushServiceSocket(context, localNumber, pushPassword);
boolean registeredUser = socket.isRegisteredUser(contactToken);
String localNumber = TextSecurePreferences.getLocalNumber(context);
String pushPassword = TextSecurePreferences.getPushServerPassword(context);
String contactToken = directory.getToken(destination);
PushServiceSocket socket = new PushServiceSocket(context, localNumber, pushPassword);
ContactTokenDetails registeredUser = socket.getContactTokenDetails(contactToken);
directory.setToken(contactToken, registeredUser);
return registeredUser;
if (registeredUser == null) {
registeredUser = new ContactTokenDetails(contactToken);
directory.setToken(registeredUser, false);
return false;
} else {
directory.setToken(registeredUser, true);
return true;
}
} catch (IOException e1) {
Log.w("UniversalTransport", e1);
return false;