From 9768de2d5eecfb107ad2a842cb94c0188f00f8bb Mon Sep 17 00:00:00 2001 From: Moxie Marlinspike Date: Wed, 22 Oct 2014 18:28:03 -0700 Subject: [PATCH] Short circuit self-send. // FREEBIE --- .../securesms/database/MmsDatabase.java | 14 +++ .../securesms/database/SmsDatabase.java | 26 ++++++ .../securesms/gcm/GcmBroadcastReceiver.java | 4 +- .../securesms/sms/MessageSender.java | 85 +++++++++++++++---- 4 files changed, 109 insertions(+), 20 deletions(-) diff --git a/src/org/thoughtcrime/securesms/database/MmsDatabase.java b/src/org/thoughtcrime/securesms/database/MmsDatabase.java index c2e8dbe716..216a31b76e 100644 --- a/src/org/thoughtcrime/securesms/database/MmsDatabase.java +++ b/src/org/thoughtcrime/securesms/database/MmsDatabase.java @@ -499,6 +499,20 @@ public class MmsDatabase extends Database implements MmsSmsColumns { return new Reader(masterSecret, cursor); } + public long copyMessageInbox(MasterSecret masterSecret, long messageId) throws MmsException { + SendReq[] request = getOutgoingMessages(masterSecret, messageId); + + ContentValues contentValues = getContentValuesFromHeader(request[0].getPduHeaders()); + + contentValues.put(MESSAGE_BOX, Types.BASE_INBOX_TYPE | Types.SECURE_MESSAGE_BIT | Types.ENCRYPTION_SYMMETRIC_BIT); + contentValues.put(THREAD_ID, getThreadIdForMessage(messageId)); + contentValues.put(READ, 1); + contentValues.put(DATE_RECEIVED, contentValues.getAsLong(DATE_SENT)); + + return insertMediaMessage(masterSecret, request[0].getPduHeaders(), + request[0].getBody(), contentValues); + } + private Pair insertMessageInbox(MasterSecret masterSecret, IncomingMediaMessage retrieved, String contentLocation, long threadId, long mailbox) throws MmsException diff --git a/src/org/thoughtcrime/securesms/database/SmsDatabase.java b/src/org/thoughtcrime/securesms/database/SmsDatabase.java index 3f90709041..3c98afc82e 100644 --- a/src/org/thoughtcrime/securesms/database/SmsDatabase.java +++ b/src/org/thoughtcrime/securesms/database/SmsDatabase.java @@ -311,6 +311,32 @@ public class SmsDatabase extends Database implements MmsSmsColumns { notifyConversationListListeners(); } + public Pair copyMessageInbox(long messageId) { + Reader reader = readerFor(getMessage(messageId)); + SmsMessageRecord record = reader.getNext(); + + ContentValues contentValues = new ContentValues(); + contentValues.put(TYPE, (record.getType() & ~Types.BASE_TYPE_MASK) | Types.BASE_INBOX_TYPE); + contentValues.put(ADDRESS, record.getIndividualRecipient().getNumber()); + contentValues.put(ADDRESS_DEVICE_ID, record.getRecipientDeviceId()); + contentValues.put(DATE_RECEIVED, System.currentTimeMillis()); + contentValues.put(DATE_SENT, record.getDateSent()); + contentValues.put(PROTOCOL, 31337); + contentValues.put(READ, 0); + contentValues.put(BODY, record.getBody().getBody()); + contentValues.put(THREAD_ID, record.getThreadId()); + + SQLiteDatabase db = databaseHelper.getWritableDatabase(); + long newMessageId = db.insert(TABLE_NAME, null, contentValues); + + DatabaseFactory.getThreadDatabase(context).update(record.getThreadId()); + notifyConversationListeners(record.getThreadId()); + Trimmer.trimThread(context, record.getThreadId()); + reader.close(); + + return new Pair<>(newMessageId, record.getThreadId()); + } + protected Pair insertMessageInbox(IncomingTextMessage message, long type) { if (message.isKeyExchange()) { type |= Types.KEY_EXCHANGE_BIT; diff --git a/src/org/thoughtcrime/securesms/gcm/GcmBroadcastReceiver.java b/src/org/thoughtcrime/securesms/gcm/GcmBroadcastReceiver.java index d6028127c6..f9bb4d3615 100644 --- a/src/org/thoughtcrime/securesms/gcm/GcmBroadcastReceiver.java +++ b/src/org/thoughtcrime/securesms/gcm/GcmBroadcastReceiver.java @@ -72,9 +72,7 @@ public class GcmBroadcastReceiver extends BroadcastReceiver { message.getTimestampMillis(), message.getRelay())); } - } catch (IOException e) { - Log.w(TAG, e); - } catch (InvalidVersionException e) { + } catch (IOException | InvalidVersionException e) { Log.w(TAG, e); } } diff --git a/src/org/thoughtcrime/securesms/sms/MessageSender.java b/src/org/thoughtcrime/securesms/sms/MessageSender.java index b9ccf36540..3e006601eb 100644 --- a/src/org/thoughtcrime/securesms/sms/MessageSender.java +++ b/src/org/thoughtcrime/securesms/sms/MessageSender.java @@ -19,15 +19,27 @@ package org.thoughtcrime.securesms.sms; import android.content.Context; import android.content.Intent; import android.util.Log; +import android.util.Pair; +import org.thoughtcrime.securesms.database.EncryptingSmsDatabase; +import org.thoughtcrime.securesms.database.MmsDatabase; +import org.thoughtcrime.securesms.database.MmsSmsColumns; +import org.thoughtcrime.securesms.mms.IncomingMediaMessage; import org.thoughtcrime.securesms.mms.OutgoingMediaMessage; +import org.thoughtcrime.securesms.recipients.Recipients; +import org.thoughtcrime.securesms.util.TextSecurePreferences; +import org.thoughtcrime.securesms.util.Util; import org.whispersystems.textsecure.crypto.MasterSecret; import org.thoughtcrime.securesms.database.DatabaseFactory; import org.thoughtcrime.securesms.service.SendReceiveService; +import org.whispersystems.textsecure.push.IncomingPushMessage; +import org.whispersystems.textsecure.push.PushMessageProtos; +import org.whispersystems.textsecure.util.InvalidNumberException; import java.util.List; import ws.com.google.android.mms.MmsException; +import ws.com.google.android.mms.pdu.RetrieveConf; public class MessageSender { @@ -35,19 +47,31 @@ public class MessageSender { OutgoingTextMessage message, long threadId, boolean forceSms) { - if (threadId == -1) + EncryptingSmsDatabase database = DatabaseFactory.getEncryptingSmsDatabase(context); + + if (threadId == -1) { threadId = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(message.getRecipients()); + } - List messageIds = DatabaseFactory.getEncryptingSmsDatabase(context) - .insertMessageOutbox(masterSecret, threadId, message, forceSms); + List messageIds = database.insertMessageOutbox(masterSecret, threadId, message, forceSms); - for (long messageId : messageIds) { - Log.w("SMSSender", "Got message id for new message: " + messageId); + if (!forceSms && isSelfSend(context, message.getRecipients())) { + for (long messageId : messageIds) { + database.markAsSent(messageId); + database.markAsPush(messageId); - Intent intent = new Intent(SendReceiveService.SEND_SMS_ACTION, null, - context, SendReceiveService.class); - intent.putExtra("message_id", messageId); - context.startService(intent); + Pair messageAndThreadId = database.copyMessageInbox(messageId); + database.markAsPush(messageAndThreadId.first); + } + } else { + for (long messageId : messageIds) { + Log.w("SMSSender", "Got message id for new message: " + messageId); + + Intent intent = new Intent(SendReceiveService.SEND_SMS_ACTION, null, + context, SendReceiveService.class); + intent.putExtra("message_id", messageId); + context.startService(intent); + } } return threadId; @@ -58,18 +82,27 @@ public class MessageSender { long threadId, boolean forceSms) throws MmsException { - if (threadId == -1) + MmsDatabase database = DatabaseFactory.getMmsDatabase(context); + + if (threadId == -1) { threadId = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(message.getRecipients(), message.getDistributionType()); + } - long messageId = DatabaseFactory.getMmsDatabase(context) - .insertMessageOutbox(masterSecret, message, threadId, forceSms); + long messageId = database.insertMessageOutbox(masterSecret, message, threadId, forceSms); - Intent intent = new Intent(SendReceiveService.SEND_MMS_ACTION, null, - context, SendReceiveService.class); - intent.putExtra("message_id", messageId); - intent.putExtra("thread_id", threadId); + if (!forceSms && isSelfSend(context, message.getRecipients())) { + database.markAsSent(messageId, "self-send".getBytes(), 0); + database.markAsPush(messageId); + long newMessageId = database.copyMessageInbox(masterSecret, messageId); + database.markAsPush(newMessageId); + } else { + Intent intent = new Intent(SendReceiveService.SEND_MMS_ACTION, null, + context, SendReceiveService.class); + intent.putExtra("message_id", messageId); + intent.putExtra("thread_id", threadId); - context.startService(intent); + context.startService(intent); + } return threadId; } @@ -91,4 +124,22 @@ public class MessageSender { context.startService(intent); } + private static boolean isSelfSend(Context context, Recipients recipients) { + try { + if (!TextSecurePreferences.isPushRegistered(context)) { + return false; + } + + if (!recipients.isSingleRecipient()) { + return false; + } + + String e164number = Util.canonicalizeNumber(context, recipients.getPrimaryRecipient().getNumber()); + return TextSecurePreferences.getLocalNumber(context).equals(e164number); + } catch (InvalidNumberException e) { + Log.w("MessageSender", e); + return false; + } + } + }