From fbdab8ccb097d4ab16ad4ef472c57c27b46383d5 Mon Sep 17 00:00:00 2001 From: nielsandriesse Date: Wed, 29 Apr 2020 15:59:27 +1000 Subject: [PATCH 1/3] Handle slave device message send failures --- .../Multi Device/MultiDeviceProtocol.swift | 38 +++++++++++++++++-- .../src/Messages/OWSMessageSend.swift | 10 ----- 2 files changed, 34 insertions(+), 14 deletions(-) diff --git a/SignalServiceKit/src/Loki/Protocol/Multi Device/MultiDeviceProtocol.swift b/SignalServiceKit/src/Loki/Protocol/Multi Device/MultiDeviceProtocol.swift index 38ec825d1..cd60fa71b 100644 --- a/SignalServiceKit/src/Loki/Protocol/Multi Device/MultiDeviceProtocol.swift +++ b/SignalServiceKit/src/Loki/Protocol/Multi Device/MultiDeviceProtocol.swift @@ -41,7 +41,21 @@ public final class MultiDeviceProtocol : NSObject { return !(message is DeviceLinkMessage) && !message.thread.isGroupThread() } - private static func sendMessage(_ messageSend: OWSMessageSend, to destination: MultiDeviceDestination, in transaction: YapDatabaseReadTransaction) { + private static func copy(_ messageSend: OWSMessageSend, for destination: MultiDeviceDestination, with seal: Resolver) -> OWSMessageSend { + var recipient: SignalRecipient! + storage.dbReadConnection.read { transaction in + recipient = SignalRecipient.getOrBuildUnsavedRecipient(forRecipientId: destination.hexEncodedPublicKey, transaction: transaction) + } + // TODO: Apparently it's okay that the thread, sender certificate, etc. don't get changed? + return OWSMessageSend(message: messageSend.message, thread: messageSend.thread, recipient: recipient, + senderCertificate: messageSend.senderCertificate, udAccess: messageSend.udAccess, localNumber: messageSend.localNumber, success: { + seal.fulfill(messageSend.thread as! TSContactThread) + }, failure: { error in + seal.reject(error) + }) + } + + private static func sendMessage(_ messageSend: OWSMessageSend, to destination: MultiDeviceDestination, in transaction: YapDatabaseReadTransaction) -> Promise { let (promise, seal) = Promise.pending() let message = messageSend.message let messageSender = SSKEnvironment.shared.messageSender @@ -50,7 +64,7 @@ public final class MultiDeviceProtocol : NSObject { let shouldSendAutoGeneratedFR = !thread.isContactFriend && !(message is FriendRequestMessage) && !(message is SessionRequestMessage) && !isSessionResetMessage && !(message is TypingIndicatorMessage) if !shouldSendAutoGeneratedFR { - let messageSendCopy = messageSend.copy(with: destination) + let messageSendCopy = copy(messageSend, for: destination, with: seal) messageSender.sendMessage(messageSendCopy) } else { DispatchQueue.main.async { @@ -76,6 +90,7 @@ public final class MultiDeviceProtocol : NSObject { } } } + return promise.map { _ in } } @objc(sendMessageToDestinationAndLinkedDevices:in:) @@ -92,16 +107,31 @@ public final class MultiDeviceProtocol : NSObject { print("[Loki] Sending \(type(of: message)) message using multi device routing.") let recipientID = messageSend.recipient.recipientId() getMultiDeviceDestinations(for: recipientID, in: transaction).done(on: OWSDispatch.sendingQueue()) { destinations in + var promises: [Promise] = [] let masterDestination = destinations.first { $0.isMaster } if let masterDestination = masterDestination { storage.dbReadConnection.read { transaction in - sendMessage(messageSend, to: masterDestination, in: transaction) + promises.append(sendMessage(messageSend, to: masterDestination, in: transaction)) } } let slaveDestinations = destinations.filter { !$0.isMaster } slaveDestinations.forEach { slaveDestination in storage.dbReadConnection.read { transaction in - sendMessage(messageSend, to: slaveDestination, in: transaction) + promises.append(sendMessage(messageSend, to: slaveDestination, in: transaction)) + } + } + when(resolved: promises).done(on: OWSDispatch.sendingQueue()) { results in + let errors = results.compactMap { result -> Error? in + if case Result.rejected(let error) = result { + return error + } else { + return nil + } + } + if errors.isEmpty { + messageSend.success() + } else { + messageSend.failure(errors.first!) } } }.catch(on: OWSDispatch.sendingQueue()) { error in diff --git a/SignalServiceKit/src/Messages/OWSMessageSend.swift b/SignalServiceKit/src/Messages/OWSMessageSend.swift index 00cbf59c2..b9d186947 100644 --- a/SignalServiceKit/src/Messages/OWSMessageSend.swift +++ b/SignalServiceKit/src/Messages/OWSMessageSend.swift @@ -93,14 +93,4 @@ public class OWSMessageSend: NSObject { // We "fail over" to non-UD sends after auth errors sending via UD. disableUD() } - - public func copy(with destination: MultiDeviceProtocol.MultiDeviceDestination) -> OWSMessageSend { - var recipient: SignalRecipient! - OWSPrimaryStorage.shared().dbReadConnection.read { transaction in - recipient = SignalRecipient.getOrBuildUnsavedRecipient(forRecipientId: destination.hexEncodedPublicKey, transaction: transaction) - } - let success = destination.isMaster ? self.success : { } - let failure = destination.isMaster ? self.failure : { _ in } - return OWSMessageSend(message: message, thread: thread, recipient: recipient, senderCertificate: senderCertificate, udAccess: udAccess, localNumber: localNumber, success: success, failure: failure) - } } From 58c28ff674ddd80a4a3a95f2e81484ddfb869856 Mon Sep 17 00:00:00 2001 From: nielsandriesse Date: Wed, 29 Apr 2020 16:04:09 +1000 Subject: [PATCH 2/3] Revert "Fix message status bar updating issue" This reverts commit 739cb1b6ab4315b9028f030a00506609b69ebe9f. --- .../ConversationView/ConversationViewController.m | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Signal/src/ViewControllers/ConversationView/ConversationViewController.m b/Signal/src/ViewControllers/ConversationView/ConversationViewController.m index 775fe9db0..2cd43c5b5 100644 --- a/Signal/src/ViewControllers/ConversationView/ConversationViewController.m +++ b/Signal/src/ViewControllers/ConversationView/ConversationViewController.m @@ -5413,8 +5413,7 @@ typedef enum : NSUInteger { targetInteraction = interaction; } }]; - if (targetInteraction == nil || targetInteraction.interactionType != OWSInteractionType_OutgoingMessage - || [LKSessionProtocol isMessageNoteToSelf:self.thread]) { return; } + if (targetInteraction == nil || targetInteraction.interactionType != OWSInteractionType_OutgoingMessage) { return; } dispatch_async(dispatch_get_main_queue(), ^{ if (progress <= self.progressIndicatorView.progress) { return; } self.progressIndicatorView.alpha = 1; From a7f04cb95c42b2b4e53b93a187270b9bb7fd035b Mon Sep 17 00:00:00 2001 From: nielsandriesse Date: Wed, 29 Apr 2020 16:28:14 +1000 Subject: [PATCH 3/3] Fix crash --- .../src/Loki/Protocol/Multi Device/MultiDeviceProtocol.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SignalServiceKit/src/Loki/Protocol/Multi Device/MultiDeviceProtocol.swift b/SignalServiceKit/src/Loki/Protocol/Multi Device/MultiDeviceProtocol.swift index cd60fa71b..45f682092 100644 --- a/SignalServiceKit/src/Loki/Protocol/Multi Device/MultiDeviceProtocol.swift +++ b/SignalServiceKit/src/Loki/Protocol/Multi Device/MultiDeviceProtocol.swift @@ -49,7 +49,7 @@ public final class MultiDeviceProtocol : NSObject { // TODO: Apparently it's okay that the thread, sender certificate, etc. don't get changed? return OWSMessageSend(message: messageSend.message, thread: messageSend.thread, recipient: recipient, senderCertificate: messageSend.senderCertificate, udAccess: messageSend.udAccess, localNumber: messageSend.localNumber, success: { - seal.fulfill(messageSend.thread as! TSContactThread) + seal.fulfill(messageSend.message.thread as! TSContactThread) }, failure: { error in seal.reject(error) })