From 53803630d4c38765b1b81eb9620a49e7a8638ddd Mon Sep 17 00:00:00 2001 From: Moxie Marlinspike Date: Fri, 12 Jul 2013 17:40:41 -0700 Subject: [PATCH] Enable TextSecure universal transport. --- ...mMessage.java => OutgoingPushMessage.java} | 12 +-- .../textsecure/push/PushServiceSocket.java | 3 +- .../securesms/gcm/OptimizingTransport.java | 85 ------------------- .../securesms/transport/BaseTransport.java | 32 +++++++ .../securesms/transport/GcmTransport.java | 24 ------ .../securesms/transport/PushTransport.java | 43 ++++++++++ .../securesms/transport/SmsTransport.java | 20 ++--- .../transport/UniversalTransport.java | 56 +++++++----- 8 files changed, 126 insertions(+), 149 deletions(-) rename library/src/org/whispersystems/textsecure/push/{OutgoingGcmMessage.java => OutgoingPushMessage.java} (74%) delete mode 100644 src/org/thoughtcrime/securesms/gcm/OptimizingTransport.java create mode 100644 src/org/thoughtcrime/securesms/transport/BaseTransport.java delete mode 100644 src/org/thoughtcrime/securesms/transport/GcmTransport.java create mode 100644 src/org/thoughtcrime/securesms/transport/PushTransport.java diff --git a/library/src/org/whispersystems/textsecure/push/OutgoingGcmMessage.java b/library/src/org/whispersystems/textsecure/push/OutgoingPushMessage.java similarity index 74% rename from library/src/org/whispersystems/textsecure/push/OutgoingGcmMessage.java rename to library/src/org/whispersystems/textsecure/push/OutgoingPushMessage.java index 83da71393a..f350a9529c 100644 --- a/library/src/org/whispersystems/textsecure/push/OutgoingGcmMessage.java +++ b/library/src/org/whispersystems/textsecure/push/OutgoingPushMessage.java @@ -3,23 +3,25 @@ package org.whispersystems.textsecure.push; import java.util.LinkedList; import java.util.List; -public class OutgoingGcmMessage { +public class OutgoingPushMessage { private List destinations; private String messageText; private List attachments; - public OutgoingGcmMessage(List destinations, String messageText, List attachments) { + public OutgoingPushMessage(List destinations, String messageText, + List attachments) + { this.destinations = destinations; this.messageText = messageText; this.attachments = attachments; } - public OutgoingGcmMessage(String destination, String messageText) { + public OutgoingPushMessage(String destination, String messageText) { this.destinations = new LinkedList(); - this.destinations.add(destination); - this.messageText = messageText; this.attachments = new LinkedList(); + this.messageText = messageText; + this.destinations.add(destination); } public List getDestinations() { diff --git a/library/src/org/whispersystems/textsecure/push/PushServiceSocket.java b/library/src/org/whispersystems/textsecure/push/PushServiceSocket.java index a59bc5fd58..b071de349f 100644 --- a/library/src/org/whispersystems/textsecure/push/PushServiceSocket.java +++ b/library/src/org/whispersystems/textsecure/push/PushServiceSocket.java @@ -1,7 +1,6 @@ package org.whispersystems.textsecure.push; import android.content.Context; -import android.content.res.AssetManager; import android.util.Base64; import android.util.Log; @@ -72,7 +71,7 @@ public class PushServiceSocket { public void sendMessage(String recipient, String messageText) throws IOException, RateLimitException { - OutgoingGcmMessage message = new OutgoingGcmMessage(recipient, messageText); + OutgoingPushMessage message = new OutgoingPushMessage(recipient, messageText); String responseText = makeRequest(MESSAGE_PATH, "POST", new Gson().toJson(message)); GcmMessageResponse response = new Gson().fromJson(responseText, GcmMessageResponse.class); diff --git a/src/org/thoughtcrime/securesms/gcm/OptimizingTransport.java b/src/org/thoughtcrime/securesms/gcm/OptimizingTransport.java deleted file mode 100644 index b621bb5916..0000000000 --- a/src/org/thoughtcrime/securesms/gcm/OptimizingTransport.java +++ /dev/null @@ -1,85 +0,0 @@ -package org.thoughtcrime.securesms.gcm; - -import android.app.Activity; -import android.app.PendingIntent; -import android.content.Context; -import android.telephony.SmsManager; -import android.util.Log; - -import org.whispersystems.textsecure.directory.NumberFilter; -import org.thoughtcrime.securesms.util.TextSecurePreferences; -import org.whispersystems.textsecure.push.PushServiceSocket; -import org.whispersystems.textsecure.push.RateLimitException; -import org.whispersystems.textsecure.util.PhoneNumberFormatter; - -import java.io.IOException; -import java.util.ArrayList; - -public class OptimizingTransport { - - public static void sendTextMessage(Context context, String destinationAddress, String message, - PendingIntent sentIntent, PendingIntent deliveredIntent) - { - String localNumber = TextSecurePreferences.getLocalNumber(context); - String canonicalizedDestinationAddress = PhoneNumberFormatter.formatNumber(destinationAddress, localNumber); - NumberFilter filter = NumberFilter.getInstance(context); - - Log.w("OptimzingTransport", "Outgoing message: " + canonicalizedDestinationAddress); - - if (filter.containsNumber(canonicalizedDestinationAddress)) { - Log.w("OptimzingTransport", "In the filter, sending GCM..."); - sendGcmTextMessage(context, destinationAddress, message, sentIntent, deliveredIntent); - } else { - Log.w("OptimzingTransport", "Not in the filter, sending SMS..."); - sendSmsTextMessage(destinationAddress, message, sentIntent, deliveredIntent); - } - } - - public static void sendMultipartTextMessage(Context context, - String recipient, - ArrayList messages, - ArrayList sentIntents, - ArrayList deliveredIntents) - { - // FIXME - - sendTextMessage(context, recipient, messages.get(0), sentIntents.get(0), deliveredIntents == null ? null : deliveredIntents.get(0)); - } - - - private static void sendGcmTextMessage(Context context, String recipient, String messageText, - PendingIntent sentIntent, PendingIntent deliveredIntent) - { - try { - String localNumber = TextSecurePreferences.getLocalNumber(context); - String password = TextSecurePreferences.getPushServerPassword(context); - - if (localNumber == null || password == null) { - Log.w("OptimzingTransport", "No credentials, falling back to SMS..."); - sendSmsTextMessage(recipient, messageText, sentIntent, deliveredIntent); - return; - } - - PushServiceSocket pushServiceSocket = new PushServiceSocket(context, localNumber, password); - pushServiceSocket.sendMessage(PhoneNumberFormatter.formatNumber(recipient, localNumber), messageText); - sentIntent.send(Activity.RESULT_OK); - } catch (IOException ioe) { - Log.w("OptimizingTransport", ioe); - Log.w("OptimzingTransport", "IOException, falling back to SMS..."); - sendSmsTextMessage(recipient, messageText, sentIntent, deliveredIntent); - } catch (PendingIntent.CanceledException e) { - Log.w("OptimizingTransport", e); - } catch (RateLimitException e) { - Log.w("OptimzingTransport", e); - Log.w("OptimzingTransport", "Rate Limit Exceeded, falling back to SMS..."); - sendSmsTextMessage(recipient, messageText, sentIntent, deliveredIntent); - } - } - - private static void sendSmsTextMessage(String recipient, String message, - PendingIntent sentIntent, PendingIntent deliveredIntent) - { - SmsManager.getDefault().sendTextMessage(recipient, null, message, sentIntent, deliveredIntent); - } - -} diff --git a/src/org/thoughtcrime/securesms/transport/BaseTransport.java b/src/org/thoughtcrime/securesms/transport/BaseTransport.java new file mode 100644 index 0000000000..9dc469ae08 --- /dev/null +++ b/src/org/thoughtcrime/securesms/transport/BaseTransport.java @@ -0,0 +1,32 @@ +package org.thoughtcrime.securesms.transport; + +import android.content.Context; +import android.content.Intent; +import android.net.Uri; + +import org.thoughtcrime.securesms.service.SendReceiveService; +import org.thoughtcrime.securesms.service.SmsListener; + +public abstract class BaseTransport { + + protected Intent constructSentIntent(Context context, long messageId, long type) { + Intent pending = new Intent(SendReceiveService.SENT_SMS_ACTION, + Uri.parse("custom://" + messageId + System.currentTimeMillis()), + context, SmsListener.class); + + pending.putExtra("type", type); + pending.putExtra("message_id", messageId); + + return pending; + } + + protected Intent constructDeliveredIntent(Context context, long messageId, long type) { + Intent pending = new Intent(SendReceiveService.DELIVERED_SMS_ACTION, + Uri.parse("custom://" + messageId + System.currentTimeMillis()), + context, SmsListener.class); + pending.putExtra("type", type); + pending.putExtra("message_id", messageId); + + return pending; + } +} diff --git a/src/org/thoughtcrime/securesms/transport/GcmTransport.java b/src/org/thoughtcrime/securesms/transport/GcmTransport.java deleted file mode 100644 index a53d0f991b..0000000000 --- a/src/org/thoughtcrime/securesms/transport/GcmTransport.java +++ /dev/null @@ -1,24 +0,0 @@ -package org.thoughtcrime.securesms.transport; - -import android.content.Context; - -import org.thoughtcrime.securesms.crypto.MasterSecret; -import org.thoughtcrime.securesms.database.model.SmsMessageRecord; - -import java.io.IOException; - -public class GcmTransport { - - private final Context context; - private final MasterSecret masterSecret; - - public GcmTransport(Context context, MasterSecret masterSecret) { - this.context = context.getApplicationContext(); - this.masterSecret = masterSecret; - } - - public void deliver(SmsMessageRecord message) throws IOException { - - } - -} diff --git a/src/org/thoughtcrime/securesms/transport/PushTransport.java b/src/org/thoughtcrime/securesms/transport/PushTransport.java new file mode 100644 index 0000000000..a030c00b71 --- /dev/null +++ b/src/org/thoughtcrime/securesms/transport/PushTransport.java @@ -0,0 +1,43 @@ +package org.thoughtcrime.securesms.transport; + +import android.content.Context; +import android.util.Log; + +import org.thoughtcrime.securesms.crypto.MasterSecret; +import org.thoughtcrime.securesms.database.model.SmsMessageRecord; +import org.thoughtcrime.securesms.util.TextSecurePreferences; +import org.whispersystems.textsecure.push.PushServiceSocket; +import org.whispersystems.textsecure.push.RateLimitException; +import org.whispersystems.textsecure.util.PhoneNumberFormatter; + +import java.io.IOException; + +public class PushTransport extends BaseTransport { + + private final Context context; + private final MasterSecret masterSecret; + + public PushTransport(Context context, MasterSecret masterSecret) { + this.context = context.getApplicationContext(); + this.masterSecret = masterSecret; + } + + public void deliver(SmsMessageRecord message) throws IOException { + try { + String localNumber = TextSecurePreferences.getLocalNumber(context); + String password = TextSecurePreferences.getPushServerPassword(context); + PushServiceSocket socket = new PushServiceSocket(context, localNumber, password); + + String recipientNumber = message.getIndividualRecipient().getNumber(); + String recipientCanonicalNumber = PhoneNumberFormatter.formatNumber(recipientNumber, + localNumber); + + socket.sendMessage(recipientCanonicalNumber, message.getBody().getBody()); + + context.sendBroadcast(constructSentIntent(context, message.getId(), message.getType())); + } catch (RateLimitException e) { + Log.w("PushTransport", e); + throw new IOException("Rate limit exceeded."); + } + } +} diff --git a/src/org/thoughtcrime/securesms/transport/SmsTransport.java b/src/org/thoughtcrime/securesms/transport/SmsTransport.java index b0caf789e7..3da72406eb 100644 --- a/src/org/thoughtcrime/securesms/transport/SmsTransport.java +++ b/src/org/thoughtcrime/securesms/transport/SmsTransport.java @@ -20,7 +20,7 @@ import org.thoughtcrime.securesms.util.TextSecurePreferences; import java.util.ArrayList; -public class SmsTransport { +public class SmsTransport extends BaseTransport { private final Context context; private final MasterSecret masterSecret; @@ -114,11 +114,10 @@ public class SmsTransport { private ArrayList constructSentIntents(long messageId, long type, ArrayList messages) { ArrayList sentIntents = new ArrayList(messages.size()); - for (int i=0;i deliveredIntents = new ArrayList(messages.size()); - for (int i=0;i