From b3351d7297e2338ad8288bff9387875e58e51041 Mon Sep 17 00:00:00 2001 From: nielsandriesse Date: Fri, 10 Jul 2020 11:09:00 +1000 Subject: [PATCH] Update for desktop protocol changes --- .../securesms/jobs/PushDecryptJob.java | 70 ++++++---------- .../loki/protocol/PushNullMessageSendJob.kt | 84 +++++++++++++++++++ 2 files changed, 110 insertions(+), 44 deletions(-) create mode 100644 src/org/thoughtcrime/securesms/loki/protocol/PushNullMessageSendJob.kt diff --git a/src/org/thoughtcrime/securesms/jobs/PushDecryptJob.java b/src/org/thoughtcrime/securesms/jobs/PushDecryptJob.java index 3a5a0be5df..04e7b50762 100644 --- a/src/org/thoughtcrime/securesms/jobs/PushDecryptJob.java +++ b/src/org/thoughtcrime/securesms/jobs/PushDecryptJob.java @@ -73,6 +73,7 @@ import org.thoughtcrime.securesms.loki.protocol.FriendRequestProtocol; import org.thoughtcrime.securesms.loki.protocol.LokiSessionResetImplementation; import org.thoughtcrime.securesms.loki.protocol.MultiDeviceProtocol; import org.thoughtcrime.securesms.loki.protocol.PushEphemeralMessageSendJob; +import org.thoughtcrime.securesms.loki.protocol.PushNullMessageSendJob; import org.thoughtcrime.securesms.loki.protocol.SessionManagementProtocol; import org.thoughtcrime.securesms.loki.protocol.SessionMetaProtocol; import org.thoughtcrime.securesms.loki.protocol.SyncMessagesProtocol; @@ -162,7 +163,6 @@ public class PushDecryptJob extends BaseJob implements InjectableType { private MessageNotifier messageNotifier; @Inject SignalServiceMessageSender messageSender; - private Address author; public PushDecryptJob(Context context) { this(context, -1); @@ -316,51 +316,13 @@ public class PushDecryptJob extends BaseJob implements InjectableType { } else if (isMediaMessage) { handleMediaMessage(content, message, smsMessageId, Optional.absent()); - // Loki - This is needed for compatibility with refactored desktop clients - if (!message.isGroupMessage()) { - Recipient recipient = recipient(context, content.getSender()); - long threadID = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(recipient); - LokiThreadDatabase threadDB = DatabaseFactory.getLokiThreadDatabase(context); - LokiThreadFriendRequestStatus threadFriendRequestStatus = threadDB.getFriendRequestStatus(threadID); - if (threadFriendRequestStatus == LokiThreadFriendRequestStatus.NONE || threadFriendRequestStatus == LokiThreadFriendRequestStatus.REQUEST_EXPIRED) { - threadDB.setFriendRequestStatus(threadID, LokiThreadFriendRequestStatus.REQUEST_RECEIVED); - } else if (threadFriendRequestStatus == LokiThreadFriendRequestStatus.REQUEST_SENT) { - threadDB.setFriendRequestStatus(threadID, LokiThreadFriendRequestStatus.FRIENDS); - EphemeralMessage ephemeralMessage = EphemeralMessage.create(content.getSender()); - ApplicationContext.getInstance(context).getJobManager().add(new PushEphemeralMessageSendJob(ephemeralMessage)); - SyncMessagesProtocol.syncContact(context, Address.fromSerialized(content.getSender())); - } - - // Loki - Handle friend request message if needed - FriendRequestProtocol.handleFriendRequestMessageIfNeeded(context, content.getSender(), content); - } + // Loki - Handle friend request message if needed + FriendRequestProtocol.handleFriendRequestMessageIfNeeded(context, content.getSender(), content); } else if (message.getBody().isPresent()) { handleTextMessage(content, message, smsMessageId, Optional.absent()); - // Loki - This is needed for compatibility with refactored desktop clients - if (!message.isGroupMessage()) { - Recipient recipient = recipient(context, content.getSender()); - long threadID = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(recipient); - LokiThreadDatabase threadDB = DatabaseFactory.getLokiThreadDatabase(context); - LokiThreadFriendRequestStatus threadFriendRequestStatus = threadDB.getFriendRequestStatus(threadID); - if (threadFriendRequestStatus == LokiThreadFriendRequestStatus.NONE || threadFriendRequestStatus == LokiThreadFriendRequestStatus.REQUEST_EXPIRED) { - threadDB.setFriendRequestStatus(threadID, LokiThreadFriendRequestStatus.REQUEST_RECEIVED); - } else if (threadFriendRequestStatus == LokiThreadFriendRequestStatus.REQUEST_SENT) { - threadDB.setFriendRequestStatus(threadID, LokiThreadFriendRequestStatus.FRIENDS); - EphemeralMessage ephemeralMessage = EphemeralMessage.create(content.getSender()); - ApplicationContext.getInstance(context).getJobManager().add(new PushEphemeralMessageSendJob(ephemeralMessage)); - SyncMessagesProtocol.syncContact(context, Address.fromSerialized(content.getSender())); - } - - // Loki - Handle friend request message if needed - FriendRequestProtocol.handleFriendRequestMessageIfNeeded(context, content.getSender(), content); - } - } else { - // Loki - This is needed for compatibility with refactored desktop clients - if (envelope.isFriendRequest()) { - EphemeralMessage ephemeralMessage = EphemeralMessage.create(content.getSender()); - ApplicationContext.getInstance(context).getJobManager().add(new PushEphemeralMessageSendJob(ephemeralMessage)); - } + // Loki - Handle friend request message if needed + FriendRequestProtocol.handleFriendRequestMessageIfNeeded(context, content.getSender(), content); } if (message.getGroupInfo().isPresent() && groupDatabase.isUnknownGroup(GroupUtil.getEncodedId(message.getGroupInfo().get()))) { @@ -406,7 +368,27 @@ public class PushDecryptJob extends BaseJob implements InjectableType { } else if (content.getTypingMessage().isPresent()) { handleTypingMessage(content, content.getTypingMessage().get()); } else { - Log.w(TAG, "Got unrecognized message..."); + + // Loki - This is needed for compatibility with refactored desktop clients + // ======== + if (envelope.isFriendRequest()) { + ApplicationContext.getInstance(context).getJobManager().add(new PushNullMessageSendJob(content.getSender())); + } else { + Log.w(TAG, "Got unrecognized message..."); + } + Recipient recipient = recipient(context, content.getSender()); + long threadID = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(recipient); + LokiThreadDatabase threadDB = DatabaseFactory.getLokiThreadDatabase(context); + LokiThreadFriendRequestStatus threadFriendRequestStatus = threadDB.getFriendRequestStatus(threadID); + if (threadFriendRequestStatus == LokiThreadFriendRequestStatus.NONE || threadFriendRequestStatus == LokiThreadFriendRequestStatus.REQUEST_EXPIRED) { + threadDB.setFriendRequestStatus(threadID, LokiThreadFriendRequestStatus.REQUEST_RECEIVED); + } else if (threadFriendRequestStatus == LokiThreadFriendRequestStatus.REQUEST_SENT) { + threadDB.setFriendRequestStatus(threadID, LokiThreadFriendRequestStatus.FRIENDS); + EphemeralMessage ephemeralMessage = EphemeralMessage.create(content.getSender()); + ApplicationContext.getInstance(context).getJobManager().add(new PushEphemeralMessageSendJob(ephemeralMessage)); + SyncMessagesProtocol.syncContact(context, Address.fromSerialized(content.getSender())); + } + // ======== } resetRecipientToPush(Recipient.from(context, Address.fromSerialized(content.getSender()), false)); diff --git a/src/org/thoughtcrime/securesms/loki/protocol/PushNullMessageSendJob.kt b/src/org/thoughtcrime/securesms/loki/protocol/PushNullMessageSendJob.kt new file mode 100644 index 0000000000..a0e745b626 --- /dev/null +++ b/src/org/thoughtcrime/securesms/loki/protocol/PushNullMessageSendJob.kt @@ -0,0 +1,84 @@ +package org.thoughtcrime.securesms.loki.protocol + +import com.google.protobuf.ByteString +import org.thoughtcrime.securesms.ApplicationContext +import org.thoughtcrime.securesms.crypto.UnidentifiedAccessUtil +import org.thoughtcrime.securesms.database.Address +import org.thoughtcrime.securesms.jobmanager.Data +import org.thoughtcrime.securesms.jobmanager.Job +import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraint +import org.thoughtcrime.securesms.jobs.BaseJob +import org.thoughtcrime.securesms.logging.Log +import org.thoughtcrime.securesms.recipients.Recipient +import org.whispersystems.signalservice.api.push.SignalServiceAddress +import org.whispersystems.signalservice.internal.push.SignalServiceProtos +import org.whispersystems.signalservice.loki.protocol.meta.TTLUtilities +import java.io.IOException +import java.security.SecureRandom +import java.util.* +import java.util.concurrent.TimeUnit + +class PushNullMessageSendJob private constructor(parameters: Parameters, private val publicKey: String) : BaseJob(parameters) { + + companion object { + const val KEY = "PushNullMessageSendJob" + } + + constructor(publicKey: String) : this(Parameters.Builder() + .addConstraint(NetworkConstraint.KEY) + .setQueue(KEY) + .setLifespan(TimeUnit.DAYS.toMillis(1)) + .setMaxAttempts(1) + .build(), + publicKey) + + override fun serialize(): Data { + return Data.Builder().putString("publicKey", publicKey).build() + } + + override fun getFactoryKey(): String { return KEY } + + public override fun onRun() { + val contentMessage = SignalServiceProtos.Content.newBuilder() + val nullMessage = SignalServiceProtos.NullMessage.newBuilder() + val sr = SecureRandom() + val paddingSize = sr.nextInt(512) + val padding = ByteArray(paddingSize) + sr.nextBytes(padding) + nullMessage.padding = ByteString.copyFrom(padding) + contentMessage.nullMessage = nullMessage.build() + val serializedContentMessage = contentMessage.build().toByteArray() + val messageSender = ApplicationContext.getInstance(context).communicationModule.provideSignalMessageSender() + val address = SignalServiceAddress(publicKey) + val recipient = Recipient.from(context, Address.fromSerialized(publicKey), false) + val udAccess = UnidentifiedAccessUtil.getAccessFor(context, recipient) + val ttl = TTLUtilities.getTTL(TTLUtilities.MessageType.Ephemeral) + try { + messageSender.sendMessage(0, address, udAccess.get().targetUnidentifiedAccess, + Date().time, serializedContentMessage, false, ttl, false, + false, false, false, false) + } catch (e: Exception) { + Log.d("Loki", "Failed to send null message to: $publicKey due to error: $e.") + throw e + } + } + + public override fun onShouldRetry(e: Exception): Boolean { + // Disable since we have our own retrying + return false + } + + override fun onCanceled() { } + + class Factory : Job.Factory { + + override fun create(parameters: Parameters, data: Data): PushNullMessageSendJob { + try { + val publicKey = data.getString("publicKey") + return PushNullMessageSendJob(parameters, publicKey) + } catch (e: IOException) { + throw AssertionError(e) + } + } + } +}