diff --git a/SessionMessagingKit/Sending & Receiving/MessageSender.swift b/SessionMessagingKit/Sending & Receiving/MessageSender.swift index cc8bac427..1f518bf75 100644 --- a/SessionMessagingKit/Sending & Receiving/MessageSender.swift +++ b/SessionMessagingKit/Sending & Receiving/MessageSender.swift @@ -38,6 +38,7 @@ public final class MessageSender : NSObject { } internal static func sendToSnodeDestination(_ destination: Message.Destination, message: Message, using transaction: Any) -> Promise { + let (promise, seal) = Promise.pending() let storage = Configuration.shared.storage if message.sentTimestamp == nil { // Visible messages will already have the sent timestamp set message.sentTimestamp = NSDate.millisecondTimestamp() @@ -48,17 +49,27 @@ public final class MessageSender : NSObject { case .closedGroup(let groupPublicKey): message.recipient = groupPublicKey case .openGroup(_, _): preconditionFailure() } + // Set the failure handler + let _ = promise.catch(on: DispatchQueue.main) { error in + storage.withAsync({ transaction in + Configuration.shared.messageSenderDelegate.handleFailedMessageSend(message, with: error, using: transaction) + }, completion: { }) + if case .contact(_) = destination { + NotificationCenter.default.post(name: .messageSendingFailed, object: NSNumber(value: message.sentTimestamp!)) + } + } // Validate the message - guard message.isValid else { return Promise(error: Error.invalidMessage) } + guard message.isValid else { seal.reject(Error.invalidMessage); return promise } // Convert it to protobuf - guard let proto = message.toProto() else { return Promise(error: Error.protoConversionFailed) } + guard let proto = message.toProto() else { seal.reject(Error.protoConversionFailed); return promise } // Serialize the protobuf let plaintext: Data do { plaintext = try proto.serializedData() } catch { SNLog("Couldn't serialize proto due to error: \(error).") - return Promise(error: error) + seal.reject(error) + return promise } // Encrypt the serialized protobuf if case .contact(_) = destination { @@ -75,7 +86,8 @@ public final class MessageSender : NSObject { } } catch { SNLog("Couldn't encrypt message for destination: \(destination) due to error: \(error).") - return Promise(error: error) + seal.reject(error) + return promise } // Wrap the result let kind: SNProtoEnvelope.SNProtoEnvelopeType @@ -95,7 +107,8 @@ public final class MessageSender : NSObject { senderPublicKey: senderPublicKey, base64EncodedContent: ciphertext.base64EncodedString()) } catch { SNLog("Couldn't wrap message due to error: \(error).") - return Promise(error: error) + seal.reject(error) + return promise } // Calculate proof of work if case .contact(_) = destination { @@ -107,7 +120,8 @@ public final class MessageSender : NSObject { let base64EncodedData = wrappedMessage.base64EncodedString() guard let (timestamp, nonce) = ProofOfWork.calculate(ttl: type(of: message).ttl, publicKey: recipient, data: base64EncodedData) else { SNLog("Proof of work calculation failed.") - return Promise(error: Error.proofOfWorkCalculationFailed) + seal.reject(Error.proofOfWorkCalculationFailed) + return promise } // Send the result if case .contact(_) = destination { @@ -116,7 +130,6 @@ public final class MessageSender : NSObject { } } let snodeMessage = SnodeMessage(recipient: recipient, data: base64EncodedData, ttl: type(of: message).ttl, timestamp: timestamp, nonce: nonce) - let (promise, seal) = Promise.pending() SnodeAPI.sendMessage(snodeMessage).done(on: Threading.workQueue) { promises in var isSuccess = false let promiseCount = promises.count @@ -149,18 +162,11 @@ public final class MessageSender : NSObject { JobQueue.shared.add(notifyPNServerJob, using: transaction) }, completion: { }) } - let _ = promise.catch(on: DispatchQueue.main) { error in - storage.withAsync({ transaction in - Configuration.shared.messageSenderDelegate.handleFailedMessageSend(message, with: error, using: transaction) - }, completion: { }) - if case .contact(_) = destination { - NotificationCenter.default.post(name: .messageSendingFailed, object: NSNumber(value: message.sentTimestamp!)) - } - } return promise } internal static func sendToOpenGroupDestination(_ destination: Message.Destination, message: Message, using transaction: Any) -> Promise { + let (promise, seal) = Promise.pending() let storage = Configuration.shared.storage message.sentTimestamp = NSDate.millisecondTimestamp() switch destination { @@ -168,7 +174,12 @@ public final class MessageSender : NSObject { case .closedGroup(_): preconditionFailure() case .openGroup(let channel, let server): message.recipient = "\(server).\(channel)" } - guard message.isValid else { return Promise(error: Error.invalidMessage) } + let _ = promise.catch(on: DispatchQueue.global(qos: .userInitiated)) { error in + storage.withAsync({ transaction in + Configuration.shared.messageSenderDelegate.handleFailedMessageSend(message, with: error, using: transaction) + }, completion: { }) + } + guard message.isValid else { seal.reject(Error.invalidMessage); return promise } let (channel, server) = { () -> (UInt64, String) in switch destination { case .openGroup(let channel, let server): return (channel, server) @@ -176,19 +187,18 @@ public final class MessageSender : NSObject { } }() guard let message = message as? VisibleMessage, - let openGroupMessage = OpenGroupMessage.from(message, for: server) else { return Promise(error: Error.invalidMessage) } - let promise = OpenGroupAPI.sendMessage(openGroupMessage, to: channel, on: server) - let _ = promise.done(on: DispatchQueue.global(qos: .userInitiated)) { openGroupMessage in + let openGroupMessage = OpenGroupMessage.from(message, for: server) else { seal.reject(Error.invalidMessage); return promise } + OpenGroupAPI.sendMessage(openGroupMessage, to: channel, on: server).done(on: DispatchQueue.global(qos: .userInitiated)) { openGroupMessage in message.openGroupServerMessageID = openGroupMessage.serverID - storage.withAsync({ transaction in - Configuration.shared.messageSenderDelegate.handleSuccessfulMessageSend(message, using: transaction) - }, completion: { }) + seal.fulfill(()) + }.catch(on: DispatchQueue.global(qos: .userInitiated)) { error in + seal.reject(error) } - promise.catch(on: DispatchQueue.global(qos: .userInitiated)) { error in + let _ = promise.done(on: DispatchQueue.global(qos: .userInitiated)) { storage.withAsync({ transaction in - Configuration.shared.messageSenderDelegate.handleFailedMessageSend(message, with: error, using: transaction) + Configuration.shared.messageSenderDelegate.handleSuccessfulMessageSend(message, using: transaction) }, completion: { }) } - return promise.map { _ in } + return promise } } diff --git a/SignalUtilitiesKit/Messaging/Core Messages/TSIncomingMessage+Conversion.swift b/SignalUtilitiesKit/Messaging/Core Messages/TSIncomingMessage+Conversion.swift index 6917b7235..05762914d 100644 --- a/SignalUtilitiesKit/Messaging/Core Messages/TSIncomingMessage+Conversion.swift +++ b/SignalUtilitiesKit/Messaging/Core Messages/TSIncomingMessage+Conversion.swift @@ -17,6 +17,7 @@ public extension TSIncomingMessage { wasReceivedByUD: true ) result.openGroupServerMessageID = visibleMessage.openGroupServerMessageID ?? 0 + result.isOpenGroupMessage = result.openGroupServerMessageID != 0 return result } } diff --git a/SignalUtilitiesKit/Messaging/Core Messages/TSInteraction.h b/SignalUtilitiesKit/Messaging/Core Messages/TSInteraction.h index e8010e70e..983103a49 100644 --- a/SignalUtilitiesKit/Messaging/Core Messages/TSInteraction.h +++ b/SignalUtilitiesKit/Messaging/Core Messages/TSInteraction.h @@ -40,7 +40,7 @@ NSString *NSStringFromOWSInteractionType(OWSInteractionType value); @property (nonatomic, readonly) uint64_t sortId; @property (nonatomic, readonly) uint64_t receivedAtTimestamp; @property (nonatomic, readonly) BOOL shouldUseServerTime; -@property (nonatomic, readonly) BOOL isOpenGroupMessage; +@property (nonatomic) BOOL isOpenGroupMessage; - (void)setServerTimestampToReceivedTimestamp:(uint64_t)receivedAtTimestamp; diff --git a/SignalUtilitiesKit/Messaging/Core Messages/TSMessage.h b/SignalUtilitiesKit/Messaging/Core Messages/TSMessage.h index 6b5a1d660..436780bfe 100644 --- a/SignalUtilitiesKit/Messaging/Core Messages/TSMessage.h +++ b/SignalUtilitiesKit/Messaging/Core Messages/TSMessage.h @@ -27,9 +27,7 @@ NS_ASSUME_NONNULL_BEGIN @property (nonatomic, readonly) BOOL isExpiringMessage; @property (nonatomic, readonly, nullable) TSQuotedMessage *quotedMessage; @property (nonatomic, nullable) OWSLinkPreview *linkPreview; -// Open groups @property (nonatomic) uint64_t openGroupServerMessageID; -@property (nonatomic, readonly) BOOL isOpenGroupMessage; - (instancetype)initInteractionWithTimestamp:(uint64_t)timestamp inThread:(TSThread *)thread NS_UNAVAILABLE; diff --git a/SignalUtilitiesKit/Messaging/Core Messages/TSMessage.m b/SignalUtilitiesKit/Messaging/Core Messages/TSMessage.m index 6d7c2575c..53ab3c0b5 100644 --- a/SignalUtilitiesKit/Messaging/Core Messages/TSMessage.m +++ b/SignalUtilitiesKit/Messaging/Core Messages/TSMessage.m @@ -432,12 +432,6 @@ static const NSUInteger OWSMessageSchemaVersion = 4; }]; } -#pragma mark - Open Groups - -- (BOOL)isOpenGroupMessage { - return self.openGroupServerMessageID > 0; -} - @end NS_ASSUME_NONNULL_END diff --git a/SignalUtilitiesKit/Messaging/Core Messages/TSOutgoingMessage.m b/SignalUtilitiesKit/Messaging/Core Messages/TSOutgoingMessage.m index 5b2449b23..35fe9dd7c 100644 --- a/SignalUtilitiesKit/Messaging/Core Messages/TSOutgoingMessage.m +++ b/SignalUtilitiesKit/Messaging/Core Messages/TSOutgoingMessage.m @@ -602,8 +602,7 @@ NSString *NSStringForOutgoingMessageRecipientState(OWSOutgoingMessageRecipientSt [self applyChangeToSelfAndLatestCopy:transaction changeBlock:^(TSOutgoingMessage *message) { // Mark any "sending" recipients as "failed." - for (TSOutgoingMessageRecipientState *recipientState in message.recipientStateMap - .allValues) { + for (TSOutgoingMessageRecipientState *recipientState in message.recipientStateMap.allValues) { if (recipientState.state == OWSOutgoingMessageRecipientStateSending) { recipientState.state = OWSOutgoingMessageRecipientStateFailed; } diff --git a/SignalUtilitiesKit/Messaging/Sending & Receiving/MessageSenderDelegate.swift b/SignalUtilitiesKit/Messaging/Sending & Receiving/MessageSenderDelegate.swift index e720bcfa1..bf9d2b33a 100644 --- a/SignalUtilitiesKit/Messaging/Sending & Receiving/MessageSenderDelegate.swift +++ b/SignalUtilitiesKit/Messaging/Sending & Receiving/MessageSenderDelegate.swift @@ -26,9 +26,8 @@ public final class MessageSenderDelegate : NSObject, SessionMessagingKit.Message // MARK: Sending public func handleSuccessfulMessageSend(_ message: Message, using transaction: Any) { guard let tsMessage = TSOutgoingMessage.find(withTimestamp: message.sentTimestamp!) else { return } - if let openGroupServerMessageID = message.openGroupServerMessageID { - tsMessage.openGroupServerMessageID = openGroupServerMessageID - } + tsMessage.openGroupServerMessageID = message.openGroupServerMessageID ?? 0 + tsMessage.isOpenGroupMessage = tsMessage.openGroupServerMessageID != 0 tsMessage.update(withSentRecipient: message.recipient!, wasSentByUD: true, transaction: transaction as! YapDatabaseReadWriteTransaction) }