From 246cd10454e76b73c899875f3548984d331cc6c8 Mon Sep 17 00:00:00 2001 From: Moxie Marlinspike Date: Sat, 19 Oct 2013 16:42:25 -0700 Subject: [PATCH] Bundle e164 and relay into PushDestination --- .../textsecure/push/PushDestination.java | 35 ++++++++++++ .../textsecure/push/PushServiceSocket.java | 33 +++++------ .../securesms/transport/PushTransport.java | 55 ++++++++++--------- .../transport/UniversalTransport.java | 20 ++++--- 4 files changed, 92 insertions(+), 51 deletions(-) create mode 100644 library/src/org/whispersystems/textsecure/push/PushDestination.java diff --git a/library/src/org/whispersystems/textsecure/push/PushDestination.java b/library/src/org/whispersystems/textsecure/push/PushDestination.java new file mode 100644 index 0000000000..59e5e2ca88 --- /dev/null +++ b/library/src/org/whispersystems/textsecure/push/PushDestination.java @@ -0,0 +1,35 @@ +package org.whispersystems.textsecure.push; + +import android.content.Context; + +import org.whispersystems.textsecure.directory.Directory; +import org.whispersystems.textsecure.util.PhoneNumberFormatter; + +public class PushDestination { + + private final String e164number; + private final String relay; + + private PushDestination(String e164number, String relay) { + this.e164number = e164number; + this.relay = relay; + } + + public String getNumber() { + return e164number; + } + + public String getRelay() { + return relay; + } + + public static PushDestination getInstance(Context context, + PushServiceSocket.PushCredentials credentials, + String destinationNumber) + { + String e164destination = PhoneNumberFormatter.formatNumber(destinationNumber, credentials.getLocalNumber(context)); + String relay = Directory.getInstance(context).getRelay(e164destination); + + return new PushDestination(e164destination, relay); + } +} diff --git a/library/src/org/whispersystems/textsecure/push/PushServiceSocket.java b/library/src/org/whispersystems/textsecure/push/PushServiceSocket.java index dea2e580de..350c77a5ed 100644 --- a/library/src/org/whispersystems/textsecure/push/PushServiceSocket.java +++ b/library/src/org/whispersystems/textsecure/push/PushServiceSocket.java @@ -84,31 +84,32 @@ public class PushServiceSocket { makeRequest(REGISTER_GCM_PATH, "DELETE", null); } - public void sendMessage(String relay, String recipient, byte[] body, int type) + public void sendMessage(PushDestination recipient, byte[] body, int type) throws IOException { - OutgoingPushMessage message = new OutgoingPushMessage(relay, recipient, body, type); + OutgoingPushMessage message = new OutgoingPushMessage(recipient.getRelay(), + recipient.getNumber(), + body, type); + sendMessage(new OutgoingPushMessageList(message)); } - public void sendMessage(List relays, List recipients, + public void sendMessage(List recipients, List bodies, List types) throws IOException { List messages = new LinkedList(); - Iterator relaysIterator = relays.iterator(); - Iterator recipientsIterator = recipients.iterator(); - Iterator bodiesIterator = bodies.iterator(); - Iterator typesIterator = types.iterator(); + Iterator recipientsIterator = recipients.iterator(); + Iterator bodiesIterator = bodies.iterator(); + Iterator typesIterator = types.iterator(); while (recipientsIterator.hasNext()) { - String relay = relaysIterator.next(); - String recipient = recipientsIterator.next(); - byte[] body = bodiesIterator.next(); - int type = typesIterator.next(); + PushDestination recipient = recipientsIterator.next(); + byte[] body = bodiesIterator.next(); + int type = typesIterator.next(); - messages.add(new OutgoingPushMessage(relay, recipient, body, type)); + messages.add(new OutgoingPushMessage(recipient.getRelay(), recipient.getNumber(), body, type)); } sendMessage(new OutgoingPushMessageList(messages)); @@ -143,11 +144,11 @@ public class PushServiceSocket { makeRequest(String.format(PREKEY_PATH, ""), "PUT", PreKeyList.toJson(new PreKeyList(lastResortEntity, entities))); } - public PreKeyEntity getPreKey(String relay, String number) throws IOException { - String path = String.format(PREKEY_PATH, number); + public PreKeyEntity getPreKey(PushDestination destination) throws IOException { + String path = String.format(PREKEY_PATH, destination.getNumber()); - if (relay != null) { - path = path + "?relay=" + relay; + if (destination.getRelay() != null) { + path = path + "?relay=" + destination.getRelay(); } String responseText = makeRequest(path, "GET", null); diff --git a/src/org/thoughtcrime/securesms/transport/PushTransport.java b/src/org/thoughtcrime/securesms/transport/PushTransport.java index eae8d0ead8..ad900e98fa 100644 --- a/src/org/thoughtcrime/securesms/transport/PushTransport.java +++ b/src/org/thoughtcrime/securesms/transport/PushTransport.java @@ -28,6 +28,7 @@ import org.whispersystems.textsecure.push.OutgoingPushMessage; import org.whispersystems.textsecure.push.PreKeyEntity; import org.whispersystems.textsecure.push.PushAttachmentData; import org.whispersystems.textsecure.push.PushAttachmentPointer; +import org.whispersystems.textsecure.push.PushDestination; import org.whispersystems.textsecure.push.PushMessageProtos.PushMessageContent; import org.whispersystems.textsecure.push.PushServiceSocket; import org.whispersystems.textsecure.push.PushTransportDetails; @@ -55,19 +56,20 @@ public class PushTransport extends BaseTransport { public void deliver(SmsMessageRecord message) throws IOException { try { - PushServiceSocket socket = new PushServiceSocket(context, TextSecurePushCredentials.getInstance()); + TextSecurePushCredentials credentials = TextSecurePushCredentials.getInstance(); + Recipient recipient = message.getIndividualRecipient(); + PushServiceSocket socket = new PushServiceSocket(context, credentials); + PushDestination destination = PushDestination.getInstance(context, credentials, + recipient.getNumber()); - String localNumber = TextSecurePreferences.getLocalNumber(context); - Recipient recipient = message.getIndividualRecipient(); - 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 relay = Directory.getInstance(context).getRelay(recipientCanonicalNumber); + String plaintextBody = message.getBody().getBody(); + byte[] plaintext = PushMessageContent.newBuilder() + .setBody(plaintextBody) + .build().toByteArray(); - Pair typeAndCiphertext = getEncryptedMessage(socket, recipient, recipientCanonicalNumber, plaintext); + Pair typeAndCiphertext = getEncryptedMessage(socket, recipient, destination, plaintext); - socket.sendMessage(relay, recipientCanonicalNumber, typeAndCiphertext.second, typeAndCiphertext.first); + socket.sendMessage(destination, typeAndCiphertext.second, typeAndCiphertext.first); context.sendBroadcast(constructSentIntent(context, message.getId(), message.getType())); } catch (RateLimitException e) { @@ -76,16 +78,17 @@ public class PushTransport extends BaseTransport { } } - public void deliver(SendReq message, List destinations) throws IOException { + public void deliver(SendReq message, List destinations) throws IOException { try { - PushServiceSocket socket = new PushServiceSocket(context, TextSecurePushCredentials.getInstance()); - String messageBody = PartParser.getMessageText(message.getBody()); - List relays = new LinkedList(); - List ciphertext = new LinkedList(); - List types = new LinkedList(); + TextSecurePushCredentials credentials = TextSecurePushCredentials.getInstance(); + PushServiceSocket socket = new PushServiceSocket(context, credentials); + String messageBody = PartParser.getMessageText(message.getBody()); - for (String destination : destinations) { - Recipients recipients = RecipientFactory.getRecipientsFromString(context, destination, false); + List ciphertext = new LinkedList(); + List types = new LinkedList(); + + for (PushDestination destination : destinations) { + Recipients recipients = RecipientFactory.getRecipientsFromString(context, destination.getNumber(), false); List attachments = getPushAttachmentPointers(socket, message.getBody()); PushMessageContent.Builder builder = PushMessageContent.newBuilder(); @@ -108,12 +111,11 @@ public class PushTransport extends BaseTransport { Pair typeAndCiphertext = getEncryptedMessage(socket, recipients.getPrimaryRecipient(), destination, plaintext); - relays.add(Directory.getInstance(context).getRelay(destination)); types.add(typeAndCiphertext.first); ciphertext.add(typeAndCiphertext.second); } - socket.sendMessage(relays, destinations, ciphertext, types); + socket.sendMessage(destinations, ciphertext, types); } catch (RateLimitException e) { Log.w("PushTransport", e); @@ -148,8 +150,10 @@ public class PushTransport extends BaseTransport { return attachments; } - private Pair getEncryptedMessage(PushServiceSocket socket, Recipient recipient, - String canonicalRecipientNumber, byte[] plaintext) + private Pair getEncryptedMessage(PushServiceSocket socket, + Recipient recipient, + PushDestination pushDestination, + byte[] plaintext) throws IOException { if (KeyUtil.isNonPrekeySessionFor(context, masterSecret, recipient)) { @@ -162,7 +166,7 @@ public class PushTransport extends BaseTransport { return new Pair(OutgoingPushMessage.TYPE_MESSAGE_PREKEY_BUNDLE, ciphertext); } else { Log.w("PushTransport", "Sending prekeybundle ciphertext message for new session..."); - byte[] ciphertext = getEncryptedPrekeyBundleMessageForNewSession(socket, recipient, canonicalRecipientNumber, plaintext); + byte[] ciphertext = getEncryptedPrekeyBundleMessageForNewSession(socket, recipient, pushDestination, plaintext); return new Pair(OutgoingPushMessage.TYPE_MESSAGE_PREKEY_BUNDLE, ciphertext); } } @@ -182,14 +186,13 @@ public class PushTransport extends BaseTransport { private byte[] getEncryptedPrekeyBundleMessageForNewSession(PushServiceSocket socket, Recipient recipient, - String canonicalRecipientNumber, + PushDestination pushDestination, byte[] plaintext) throws IOException { IdentityKeyPair identityKeyPair = IdentityKeyUtil.getIdentityKeyPair(context, masterSecret); IdentityKey identityKey = identityKeyPair.getPublicKey(); - String relay = Directory.getInstance(context).getRelay(canonicalRecipientNumber); - PreKeyEntity preKey = socket.getPreKey(relay, canonicalRecipientNumber); + PreKeyEntity preKey = socket.getPreKey(pushDestination); KeyExchangeProcessor processor = new KeyExchangeProcessor(context, masterSecret, recipient); processor.processKeyExchangeMessage(preKey); diff --git a/src/org/thoughtcrime/securesms/transport/UniversalTransport.java b/src/org/thoughtcrime/securesms/transport/UniversalTransport.java index 7beff2a0ba..064143d987 100644 --- a/src/org/thoughtcrime/securesms/transport/UniversalTransport.java +++ b/src/org/thoughtcrime/securesms/transport/UniversalTransport.java @@ -29,6 +29,7 @@ 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.PushDestination; import org.whispersystems.textsecure.push.PushServiceSocket; import java.io.IOException; @@ -80,7 +81,7 @@ public class UniversalTransport { return mmsTransport.deliver(mediaMessage); } - List destinations = getMediaDestinations(mediaMessage); + List destinations = getMediaDestinations(mediaMessage); if (isPushTransport(destinations)) { try { @@ -97,24 +98,25 @@ public class UniversalTransport { } } - private List getMediaDestinations(SendReq mediaMessage) { - LinkedList destinations = new LinkedList(); + private List getMediaDestinations(SendReq mediaMessage) { + TextSecurePushCredentials credentials = TextSecurePushCredentials.getInstance(); + LinkedList destinations = new LinkedList(); if (mediaMessage.getTo() != null) { for (EncodedStringValue to : mediaMessage.getTo()) { - destinations.add(Util.canonicalizeNumber(context, to.getString())); + destinations.add(PushDestination.getInstance(context, credentials, to.getString())); } } if (mediaMessage.getCc() != null) { for (EncodedStringValue cc : mediaMessage.getCc()) { - destinations.add(Util.canonicalizeNumber(context, cc.getString())); + destinations.add(PushDestination.getInstance(context, credentials, cc.getString())); } } if (mediaMessage.getBcc() != null) { for (EncodedStringValue bcc : mediaMessage.getBcc()) { - destinations.add(Util.canonicalizeNumber(context, bcc.getString())); + destinations.add(PushDestination.getInstance(context, credentials, bcc.getString())); } } @@ -147,9 +149,9 @@ public class UniversalTransport { } } - private boolean isPushTransport(List destinations) { - for (String destination : destinations) { - if (!isPushTransport(destination)) { + private boolean isPushTransport(List destinations) { + for (PushDestination destination : destinations) { + if (!isPushTransport(destination.getNumber())) { return false; } }