diff --git a/Session/Utilities/BackgroundPoller.swift b/Session/Utilities/BackgroundPoller.swift index 5d84d359c..c7d1b3c28 100644 --- a/Session/Utilities/BackgroundPoller.swift +++ b/Session/Utilities/BackgroundPoller.swift @@ -28,19 +28,19 @@ public final class BackgroundPoller : NSObject { private static func pollForMessages() -> Promise { let userPublicKey = getUserHexEncodedPublicKey() - return getMessages(for: userPublicKey) + return getMessages(for: userPublicKey, authenticated: true) } private static func pollForClosedGroupMessages() -> [Promise] { let publicKeys = Storage.shared.getUserClosedGroupPublicKeys() - return publicKeys.map { getMessages(for: $0) } + return publicKeys.map { getMessages(for: $0, authenticated: false) } } - private static func getMessages(for publicKey: String) -> Promise { + private static func getMessages(for publicKey: String, authenticated: Bool) -> Promise { return SnodeAPI.getSwarm(for: publicKey).then(on: DispatchQueue.main) { swarm -> Promise in guard let snode = swarm.randomElement() else { throw SnodeAPI.Error.generic } return attempt(maxRetryCount: 4, recoveringOn: DispatchQueue.main) { - return SnodeAPI.getRawMessages(from: snode, associatedWith: publicKey).then(on: DispatchQueue.main) { rawResponse -> Promise in + return SnodeAPI.getRawMessages(from: snode, associatedWith: publicKey, authenticated: authenticated).then(on: DispatchQueue.main) { rawResponse -> Promise in let (messages, lastRawMessage) = SnodeAPI.parseRawMessagesResponse(rawResponse, from: snode, associatedWith: publicKey) let promises = messages.compactMap { json -> Promise? in // Use a best attempt approach here; we don't want to fail the entire process if one of the @@ -50,9 +50,9 @@ public final class BackgroundPoller : NSObject { let job = MessageReceiveJob(data: data, serverHash: json["hash"] as? String, isBackgroundPoll: true) return job.execute() } - + let namespace = authenticated ? SnodeAPI.defaultNamespace : SnodeAPI.unauthenticatedNamespace // Now that the MessageReceiveJob's have been created we can update the `lastMessageHash` value - SnodeAPI.updateLastMessageHashValueIfPossible(for: snode, associatedWith: publicKey, from: lastRawMessage) + SnodeAPI.updateLastMessageHashValueIfPossible(for: snode, namespace: namespace, associatedWith: publicKey, from: lastRawMessage) return when(fulfilled: promises) // The promise returned by MessageReceiveJob never rejects } diff --git a/SessionMessagingKit/Sending & Receiving/Pollers/ClosedGroupPoller.swift b/SessionMessagingKit/Sending & Receiving/Pollers/ClosedGroupPoller.swift index 7ea185b16..c2667e1eb 100644 --- a/SessionMessagingKit/Sending & Receiving/Pollers/ClosedGroupPoller.swift +++ b/SessionMessagingKit/Sending & Receiving/Pollers/ClosedGroupPoller.swift @@ -128,7 +128,7 @@ public final class ClosedGroupPoller : NSObject { } // Now that the MessageReceiveJob's have been created we can update the `lastMessageHash` value - SnodeAPI.updateLastMessageHashValueIfPossible(for: snode, associatedWith: groupPublicKey, from: lastRawMessage) + SnodeAPI.updateLastMessageHashValueIfPossible(for: snode, namespace: SnodeAPI.unauthenticatedNamespace, associatedWith: groupPublicKey, from: lastRawMessage) } promise.catch2 { error in SNLog("Polling failed for closed group with public key: \(groupPublicKey) due to error: \(error).") diff --git a/SessionMessagingKit/Sending & Receiving/Pollers/Poller.swift b/SessionMessagingKit/Sending & Receiving/Pollers/Poller.swift index 5c9e66561..7c50725fb 100644 --- a/SessionMessagingKit/Sending & Receiving/Pollers/Poller.swift +++ b/SessionMessagingKit/Sending & Receiving/Pollers/Poller.swift @@ -112,7 +112,7 @@ public final class Poller : NSObject { } // Now that the MessageReceiveJob's have been created we can update the `lastMessageHash` value - SnodeAPI.updateLastMessageHashValueIfPossible(for: snode, associatedWith: userPublicKey, from: lastRawMessage) + SnodeAPI.updateLastMessageHashValueIfPossible(for: snode, namespace: SnodeAPI.defaultNamespace, associatedWith: userPublicKey, from: lastRawMessage) strongSelf.pollCount += 1 if strongSelf.pollCount == Poller.maxPollCount { diff --git a/SessionSnodeKit/SnodeAPI.swift b/SessionSnodeKit/SnodeAPI.swift index c7e08b069..dea03b4cc 100644 --- a/SessionSnodeKit/SnodeAPI.swift +++ b/SessionSnodeKit/SnodeAPI.swift @@ -24,9 +24,9 @@ public final class SnodeAPI : NSObject { public static var swarmCache: [String:Set] = [:] // MARK: Namespaces - private static let defaultNamespace = 0 - private static let unauthenticatedNamespace = -10 - private static let configNamespace = 5 + public static let defaultNamespace = 0 + public static let unauthenticatedNamespace = -10 + public static let configNamespace = 5 // MARK: Hardfork version private static var hardfork = UserDefaults.standard[.hardfork] @@ -451,8 +451,8 @@ public final class SnodeAPI : NSObject { guard let userED25519KeyPair = storage.getUserED25519KeyPair() else { return Promise(error: Error.noKeyPair) } // Get last message hash - storage.pruneLastMessageHashInfoIfExpired(for: snode, associatedWith: publicKey) - let lastHash = storage.getLastMessageHash(for: snode, associatedWith: publicKey) ?? "" + storage.pruneLastMessageHashInfoIfExpired(for: snode, namespace: namespace, associatedWith: publicKey) + let lastHash = storage.getLastMessageHash(for: snode, namespace: namespace, associatedWith: publicKey) ?? "" // Construct signature let timestamp = UInt64(Int64(NSDate.millisecondTimestamp()) + SnodeAPI.clockOffset) let ed25519PublicKey = userED25519KeyPair.publicKey.toHexString() @@ -475,8 +475,8 @@ public final class SnodeAPI : NSObject { let storage = SNSnodeKitConfiguration.shared.storage // Get last message hash - storage.pruneLastMessageHashInfoIfExpired(for: snode, associatedWith: publicKey) - let lastHash = storage.getLastMessageHash(for: snode, associatedWith: publicKey) ?? "" + storage.pruneLastMessageHashInfoIfExpired(for: snode, namespace: namespace, associatedWith: publicKey) + let lastHash = storage.getLastMessageHash(for: snode, namespace: namespace, associatedWith: publicKey) ?? "" // Make the request let parameters: JSON = [ @@ -673,10 +673,10 @@ public final class SnodeAPI : NSObject { ) } - public static func updateLastMessageHashValueIfPossible(for snode: Snode, associatedWith publicKey: String, from lastRawMessage: JSON?) { + public static func updateLastMessageHashValueIfPossible(for snode: Snode, namespace: Int, associatedWith publicKey: String, from lastRawMessage: JSON?) { if let lastMessage = lastRawMessage, let lastHash = lastMessage["hash"] as? String, let expirationDate = lastMessage["expiration"] as? UInt64 { SNSnodeKitConfiguration.shared.storage.writeSync { transaction in - SNSnodeKitConfiguration.shared.storage.setLastMessageHashInfo(for: snode, associatedWith: publicKey, + SNSnodeKitConfiguration.shared.storage.setLastMessageHashInfo(for: snode, namespace: namespace, associatedWith: publicKey, to: [ "hash" : lastHash, "expirationDate" : NSNumber(value: expirationDate) ], using: transaction) } } else if (lastRawMessage != nil) { diff --git a/SessionSnodeKit/Storage+SnodeAPI.swift b/SessionSnodeKit/Storage+SnodeAPI.swift index 24b36365f..cbccbc0a6 100644 --- a/SessionSnodeKit/Storage+SnodeAPI.swift +++ b/SessionSnodeKit/Storage+SnodeAPI.swift @@ -80,8 +80,8 @@ extension Storage { private static let lastMessageHashCollection = "LokiLastMessageHashCollection" - public func getLastMessageHashInfo(for snode: Snode, associatedWith publicKey: String) -> JSON? { - let key = "\(snode.address):\(snode.port).\(publicKey)" + public func getLastMessageHashInfo(for snode: Snode, namespace: Int, associatedWith publicKey: String) -> JSON? { + let key = namespace == SnodeAPI.defaultNamespace ? "\(snode.address):\(snode.port).\(publicKey)" : "\(snode.address):\(snode.port).\(publicKey).\(namespace)" var result: JSON? Storage.read { transaction in result = transaction.object(forKey: key, inCollection: Storage.lastMessageHashCollection) as? JSON @@ -93,29 +93,29 @@ extension Storage { return result } - public func getLastMessageHash(for snode: Snode, associatedWith publicKey: String) -> String? { - return getLastMessageHashInfo(for: snode, associatedWith: publicKey)?["hash"] as? String + public func getLastMessageHash(for snode: Snode, namespace: Int, associatedWith publicKey: String) -> String? { + return getLastMessageHashInfo(for: snode, namespace: namespace, associatedWith: publicKey)?["hash"] as? String } - public func setLastMessageHashInfo(for snode: Snode, associatedWith publicKey: String, to lastMessageHashInfo: JSON, using transaction: Any) { - let key = "\(snode.address):\(snode.port).\(publicKey)" + public func setLastMessageHashInfo(for snode: Snode, namespace: Int, associatedWith publicKey: String, to lastMessageHashInfo: JSON, using transaction: Any) { + let key = namespace == SnodeAPI.defaultNamespace ? "\(snode.address):\(snode.port).\(publicKey)" : "\(snode.address):\(snode.port).\(publicKey).\(namespace)" guard lastMessageHashInfo.count == 2 && lastMessageHashInfo["hash"] as? String != nil && lastMessageHashInfo["expirationDate"] as? NSNumber != nil else { return } (transaction as! YapDatabaseReadWriteTransaction).setObject(lastMessageHashInfo, forKey: key, inCollection: Storage.lastMessageHashCollection) } - public func pruneLastMessageHashInfoIfExpired(for snode: Snode, associatedWith publicKey: String) { - guard let lastMessageHashInfo = getLastMessageHashInfo(for: snode, associatedWith: publicKey), + public func pruneLastMessageHashInfoIfExpired(for snode: Snode, namespace: Int, associatedWith publicKey: String) { + guard let lastMessageHashInfo = getLastMessageHashInfo(for: snode, namespace: namespace, associatedWith: publicKey), (lastMessageHashInfo["hash"] as? String) != nil, let expirationDate = (lastMessageHashInfo["expirationDate"] as? NSNumber)?.uint64Value else { return } let now = NSDate.millisecondTimestamp() if now >= expirationDate { Storage.writeSync { transaction in - self.removeLastMessageHashInfo(for: snode, associatedWith: publicKey, using: transaction) + self.removeLastMessageHashInfo(for: snode, namespace: namespace, associatedWith: publicKey, using: transaction) } } } - public func removeLastMessageHashInfo(for snode: Snode, associatedWith publicKey: String, using transaction: Any) { - let key = "\(snode.address):\(snode.port).\(publicKey)" + public func removeLastMessageHashInfo(for snode: Snode, namespace: Int, associatedWith publicKey: String, using transaction: Any) { + let key = namespace == SnodeAPI.defaultNamespace ? "\(snode.address):\(snode.port).\(publicKey)" : "\(snode.address):\(snode.port).\(publicKey).\(namespace)" (transaction as! YapDatabaseReadWriteTransaction).removeObject(forKey: key, inCollection: Storage.lastMessageHashCollection) } diff --git a/SessionSnodeKit/Storage.swift b/SessionSnodeKit/Storage.swift index ce0a90f81..04367a847 100644 --- a/SessionSnodeKit/Storage.swift +++ b/SessionSnodeKit/Storage.swift @@ -20,9 +20,9 @@ public protocol SessionSnodeKitStorageProtocol { func setLastSnodePoolRefreshDate(to date: Date, using transaction: Any) func getSwarm(for publicKey: String) -> Set func setSwarm(to swarm: Set, for publicKey: String, using transaction: Any) - func getLastMessageHash(for snode: Snode, associatedWith publicKey: String) -> String? - func setLastMessageHashInfo(for snode: Snode, associatedWith publicKey: String, to lastMessageHashInfo: JSON, using transaction: Any) - func pruneLastMessageHashInfoIfExpired(for snode: Snode, associatedWith publicKey: String) + func getLastMessageHash(for snode: Snode, namespace: Int, associatedWith publicKey: String) -> String? + func setLastMessageHashInfo(for snode: Snode, namespace: Int, associatedWith publicKey: String, to lastMessageHashInfo: JSON, using transaction: Any) + func pruneLastMessageHashInfoIfExpired(for snode: Snode, namespace: Int, associatedWith publicKey: String) func getReceivedMessages(for publicKey: String) -> Set func setReceivedMessages(to receivedMessages: Set, for publicKey: String, using transaction: Any) }