Partially implement message syncing

This commit is contained in:
Niels Andriesse 2021-01-14 10:40:58 +11:00
parent c1cba59a75
commit 74fd3eb812
9 changed files with 35 additions and 24 deletions

View File

@ -519,7 +519,7 @@
C3471ED42555386B00297E91 /* AESGCM.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3C2A5D72553860B00C340D1 /* AESGCM.swift */; };
C3471F4C25553AB000297E91 /* MessageReceiver+Decryption.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3471F4B25553AB000297E91 /* MessageReceiver+Decryption.swift */; };
C3471FA42555439E00297E91 /* Notification+MessageSender.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3471FA32555439E00297E91 /* Notification+MessageSender.swift */; };
C34A977425A3E34A00852C71 /* ClosedGroupUpdateV2.swift in Sources */ = {isa = PBXBuildFile; fileRef = C34A977325A3E34A00852C71 /* ClosedGroupUpdateV2.swift */; };
C34A977425A3E34A00852C71 /* ClosedGroupUpdate.swift in Sources */ = {isa = PBXBuildFile; fileRef = C34A977325A3E34A00852C71 /* ClosedGroupUpdate.swift */; };
C34C8F7423A7830B00D82669 /* SpaceMono-Bold.ttf in Resources */ = {isa = PBXBuildFile; fileRef = C34C8F7323A7830A00D82669 /* SpaceMono-Bold.ttf */; };
C352A2F525574B4700338F3E /* Job.swift in Sources */ = {isa = PBXBuildFile; fileRef = C352A2F425574B4700338F3E /* Job.swift */; };
C352A2FF25574B6300338F3E /* MessageSendJob.swift in Sources */ = {isa = PBXBuildFile; fileRef = C352A2FE25574B6300338F3E /* MessageSendJob.swift */; };
@ -1523,7 +1523,7 @@
C3471ECA2555356A00297E91 /* MessageSender+Encryption.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "MessageSender+Encryption.swift"; sourceTree = "<group>"; };
C3471F4B25553AB000297E91 /* MessageReceiver+Decryption.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "MessageReceiver+Decryption.swift"; sourceTree = "<group>"; };
C3471FA32555439E00297E91 /* Notification+MessageSender.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Notification+MessageSender.swift"; sourceTree = "<group>"; };
C34A977325A3E34A00852C71 /* ClosedGroupUpdateV2.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ClosedGroupUpdateV2.swift; sourceTree = "<group>"; };
C34A977325A3E34A00852C71 /* ClosedGroupUpdate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ClosedGroupUpdate.swift; sourceTree = "<group>"; };
C34C8F7323A7830A00D82669 /* SpaceMono-Bold.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "SpaceMono-Bold.ttf"; sourceTree = "<group>"; };
C352A2F425574B4700338F3E /* Job.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Job.swift; sourceTree = "<group>"; };
C352A2FE25574B6300338F3E /* MessageSendJob.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessageSendJob.swift; sourceTree = "<group>"; };
@ -2368,7 +2368,7 @@
C3C2A7702553A41E00C340D1 /* ControlMessage.swift */,
C300A5BC2554B00D00555489 /* ReadReceipt.swift */,
C300A5D22554B05A00555489 /* TypingIndicator.swift */,
C34A977325A3E34A00852C71 /* ClosedGroupUpdateV2.swift */,
C34A977325A3E34A00852C71 /* ClosedGroupUpdate.swift */,
C300A5E62554B07300555489 /* ExpirationTimerUpdate.swift */,
C3DA9C0625AE7396008F7C7E /* ConfigurationMessage.swift */,
);
@ -4933,7 +4933,7 @@
C3471FA42555439E00297E91 /* Notification+MessageSender.swift in Sources */,
C32C5BEF256DC8EE003C73A2 /* OWSDisappearingMessagesJob.m in Sources */,
C3A7222A2558C1E40043A11F /* DotNetAPI.swift in Sources */,
C34A977425A3E34A00852C71 /* ClosedGroupUpdateV2.swift in Sources */,
C34A977425A3E34A00852C71 /* ClosedGroupUpdate.swift in Sources */,
C32C5E97256DE0CB003C73A2 /* OWSPrimaryStorage.m in Sources */,
C32C5EB9256DE130003C73A2 /* OWSQuotedReplyModel+Conversion.swift in Sources */,
C3A71D1F25589AC30043A11F /* WebSocketResources.pb.swift in Sources */,

View File

@ -1,7 +1,7 @@
import SessionProtocolKit
import SessionUtilitiesKit
public final class ClosedGroupUpdateV2 : ControlMessage {
public final class ClosedGroupUpdate : ControlMessage {
public var kind: Kind?
public override var ttl: UInt64 {
@ -11,6 +11,13 @@ public final class ClosedGroupUpdateV2 : ControlMessage {
}
}
public override var isSelfSendValid: Bool {
switch kind {
case .update, .encryptionKeyPair: return true
default: return false
}
}
// MARK: Kind
public enum Kind : CustomStringConvertible {
case new(publicKey: Data, name: String, encryptionKeyPair: ECKeyPair, members: [Data], admins: [Data])
@ -131,7 +138,7 @@ public final class ClosedGroupUpdateV2 : ControlMessage {
}
// MARK: Proto Conversion
public override class func fromProto(_ proto: SNProtoContent) -> ClosedGroupUpdateV2? {
public override class func fromProto(_ proto: SNProtoContent) -> ClosedGroupUpdate? {
guard let closedGroupUpdateProto = proto.dataMessage?.closedGroupUpdateV2 else { return nil }
let kind: Kind
switch closedGroupUpdateProto.type {
@ -153,7 +160,7 @@ public final class ClosedGroupUpdateV2 : ControlMessage {
let wrappers = closedGroupUpdateProto.wrappers.compactMap { KeyPairWrapper.fromProto($0) }
kind = .encryptionKeyPair(wrappers)
}
return ClosedGroupUpdateV2(kind: kind)
return ClosedGroupUpdate(kind: kind)
}
public override func toProto(using transaction: YapDatabaseReadWriteTransaction) -> SNProtoContent? {

View File

@ -5,6 +5,8 @@ public final class ConfigurationMessage : ControlMessage {
public var closedGroups: Set<ClosedGroup> = []
public var openGroups: Set<String> = []
public override var isSelfSendValid: Bool { true }
// MARK: Initialization
public override init() { super.init() }

View File

@ -12,6 +12,7 @@ public class Message : NSObject, NSCoding { // NSObject/NSCoding conformance is
public var openGroupServerMessageID: UInt64?
public var ttl: UInt64 { 2 * 24 * 60 * 60 * 1000 }
public var isSelfSendValid: Bool { false }
public override init() { }

View File

@ -11,7 +11,7 @@ extension MessageReceiver {
switch message {
case let message as ReadReceipt: handleReadReceipt(message, using: transaction)
case let message as TypingIndicator: handleTypingIndicator(message, using: transaction)
case let message as ClosedGroupUpdateV2: handleClosedGroupUpdateV2(message, using: transaction)
case let message as ClosedGroupUpdate: handleClosedGroupUpdateV2(message, using: transaction)
case let message as ExpirationTimerUpdate: handleExpirationTimerUpdate(message, using: transaction)
case let message as ConfigurationMessage: handleConfigurationMessage(message, using: transaction)
case let message as VisibleMessage: try handleVisibleMessage(message, associatedWithProto: proto, openGroupID: openGroupID, isBackgroundPoll: isBackgroundPoll, using: transaction)
@ -233,7 +233,7 @@ extension MessageReceiver {
return tsIncomingMessageID
}
private static func handleClosedGroupUpdateV2(_ message: ClosedGroupUpdateV2, using transaction: Any) {
private static func handleClosedGroupUpdateV2(_ message: ClosedGroupUpdate, using transaction: Any) {
switch message.kind! {
case .new: handleNewClosedGroup(message, using: transaction)
case .update: handleClosedGroupUpdate(message, using: transaction)
@ -241,7 +241,7 @@ extension MessageReceiver {
}
}
private static func handleNewClosedGroup(_ message: ClosedGroupUpdateV2, using transaction: Any) {
private static func handleNewClosedGroup(_ message: ClosedGroupUpdate, using transaction: Any) {
guard case let .new(publicKeyAsData, name, encryptionKeyPair, membersAsData, adminsAsData) = message.kind else { return }
let groupPublicKey = publicKeyAsData.toHexString()
let members = membersAsData.map { $0.toHexString() }
@ -273,7 +273,7 @@ extension MessageReceiver {
infoMessage.save(with: transaction)
}
private static func handleClosedGroupUpdate(_ message: ClosedGroupUpdateV2, using transaction: Any) {
private static func handleClosedGroupUpdate(_ message: ClosedGroupUpdate, using transaction: Any) {
// Prepare
guard case let .update(name, membersAsData) = message.kind else { return }
let transaction = transaction as! YapDatabaseReadWriteTransaction
@ -332,7 +332,7 @@ extension MessageReceiver {
}
}
private static func handleClosedGroupEncryptionKeyPair(_ message: ClosedGroupUpdateV2, using transaction: Any) {
private static func handleClosedGroupEncryptionKeyPair(_ message: ClosedGroupUpdate, using transaction: Any) {
// Prepare
guard case let .encryptionKeyPair(wrappers) = message.kind, let groupPublicKey = message.groupPublicKey else { return }
let transaction = transaction as! YapDatabaseReadWriteTransaction

View File

@ -107,7 +107,7 @@ public enum MessageReceiver {
let message: Message? = {
if let readReceipt = ReadReceipt.fromProto(proto) { return readReceipt }
if let typingIndicator = TypingIndicator.fromProto(proto) { return typingIndicator }
if let closedGroupUpdate = ClosedGroupUpdateV2.fromProto(proto) { return closedGroupUpdate }
if let closedGroupUpdate = ClosedGroupUpdate.fromProto(proto) { return closedGroupUpdate }
if let expirationTimerUpdate = ExpirationTimerUpdate.fromProto(proto) { return expirationTimerUpdate }
if let configurationMessage = ConfigurationMessage.fromProto(proto) { return configurationMessage }
if let visibleMessage = VisibleMessage.fromProto(proto) { return visibleMessage }
@ -115,7 +115,7 @@ public enum MessageReceiver {
}()
if let message = message {
// Ignore self sends if needed
if !(message is ConfigurationMessage) {
if !message.isSelfSendValid {
guard sender != userPublicKey else { throw Error.selfSend }
}
// Guard against control messages in open groups

View File

@ -27,9 +27,9 @@ extension MessageSender {
guard member != userPublicKey else { continue }
let thread = TSContactThread.getOrCreateThread(withContactId: member, transaction: transaction)
thread.save(with: transaction)
let closedGroupUpdateKind = ClosedGroupUpdateV2.Kind.new(publicKey: Data(hex: groupPublicKey), name: name,
let closedGroupUpdateKind = ClosedGroupUpdate.Kind.new(publicKey: Data(hex: groupPublicKey), name: name,
encryptionKeyPair: encryptionKeyPair, members: membersAsData, admins: adminsAsData)
let closedGroupUpdate = ClosedGroupUpdateV2(kind: closedGroupUpdateKind)
let closedGroupUpdate = ClosedGroupUpdate(kind: closedGroupUpdateKind)
let promise = MessageSender.sendNonDurably(closedGroupUpdate, in: thread, using: transaction)
promises.append(promise)
}
@ -81,7 +81,7 @@ extension MessageSender {
}
}
// Send the update to the group
let mainClosedGroupUpdate = ClosedGroupUpdateV2(kind: .update(name: name, members: membersAsData))
let mainClosedGroupUpdate = ClosedGroupUpdate(kind: .update(name: name, members: membersAsData))
if isUserLeaving {
let _ = MessageSender.sendNonDurably(mainClosedGroupUpdate, in: thread, using: transaction).done {
SNMessagingKitConfiguration.shared.storage.write { transaction in
@ -101,9 +101,9 @@ extension MessageSender {
for member in newMembers {
let thread = TSContactThread.getOrCreateThread(withContactId: member, transaction: transaction)
thread.save(with: transaction)
let closedGroupUpdateKind = ClosedGroupUpdateV2.Kind.new(publicKey: Data(hex: groupPublicKey), name: name,
let closedGroupUpdateKind = ClosedGroupUpdate.Kind.new(publicKey: Data(hex: groupPublicKey), name: name,
encryptionKeyPair: encryptionKeyPair, members: membersAsData, admins: adminsAsData)
let closedGroupUpdate = ClosedGroupUpdateV2(kind: closedGroupUpdateKind)
let closedGroupUpdate = ClosedGroupUpdate(kind: closedGroupUpdateKind)
MessageSender.send(closedGroupUpdate, in: thread, using: transaction)
}
}
@ -155,11 +155,11 @@ extension MessageSender {
let proto = try SNProtoKeyPair.builder(publicKey: newKeyPair.publicKey,
privateKey: newKeyPair.privateKey).build()
let plaintext = try proto.serializedData()
let wrappers = try targetMembers.compactMap { publicKey -> ClosedGroupUpdateV2.KeyPairWrapper in
let wrappers = try targetMembers.compactMap { publicKey -> ClosedGroupUpdate.KeyPairWrapper in
let ciphertext = try MessageSender.encryptWithSessionProtocol(plaintext, for: publicKey)
return ClosedGroupUpdateV2.KeyPairWrapper(publicKey: publicKey, encryptedKeyPair: ciphertext)
return ClosedGroupUpdate.KeyPairWrapper(publicKey: publicKey, encryptedKeyPair: ciphertext)
}
let closedGroupUpdate = ClosedGroupUpdateV2(kind: .encryptionKeyPair(wrappers))
let closedGroupUpdate = ClosedGroupUpdate(kind: .encryptionKeyPair(wrappers))
let _ = MessageSender.sendNonDurably(closedGroupUpdate, in: thread, using: transaction).done { // FIXME: It'd be great if we could make this a durable operation
// Store it * after * having sent out the message to the group
SNMessagingKitConfiguration.shared.storage.write { transaction in

View File

@ -242,7 +242,7 @@ public final class MessageSender : NSObject {
storage.write(with: { transaction in
MessageSender.handleSuccessfulMessageSend(message, to: destination, using: transaction)
var shouldNotify = (message is VisibleMessage)
if let closedGroupUpdate = message as? ClosedGroupUpdateV2, case .new = closedGroupUpdate.kind {
if let closedGroupUpdate = message as? ClosedGroupUpdate, case .new = closedGroupUpdate.kind {
shouldNotify = true
}
if shouldNotify {
@ -340,6 +340,7 @@ public final class MessageSender : NSObject {
// MARK: Success & Failure Handling
public static func handleSuccessfulMessageSend(_ message: Message, to destination: Message.Destination, using transaction: Any) {
Storage.shared.addReceivedMessageTimestamp(message.sentTimestamp!, using: transaction) // To later ignore self-sends in a multi device context
guard let tsMessage = TSOutgoingMessage.find(withTimestamp: message.sentTimestamp!) else { return }
tsMessage.openGroupServerMessageID = message.openGroupServerMessageID ?? 0
var recipients = [ message.recipient! ]

View File

@ -55,7 +55,7 @@ public final class NotificationServiceExtension : UNNotificationServiceExtension
group.groupModel.groupType == .closedGroup { // Should always be true because we don't get PNs for open groups
senderDisplayName = String(format: NotificationStrings.incomingGroupMessageTitleFormat, senderDisplayName, group.groupModel.groupName ?? MessageStrings.newGroupDefaultTitle)
}
case let closedGroupUpdate as ClosedGroupUpdateV2:
case let closedGroupUpdate as ClosedGroupUpdate:
// TODO: We could consider actually handling the update here. Not sure if there's enough time though, seeing as though
// in some cases we need to send messages (e.g. our sender key) to a number of other users.
switch closedGroupUpdate.kind {