Update message sending logic for new multi device API

pull/55/head
Niels Andriesse 6 years ago
parent 9a9cefd4ec
commit f88a0f3c1f

@ -2,6 +2,7 @@ import PromiseKit
@objc(LKAPI)
public final class LokiAPI : NSObject {
private static var lastDeviceLinkUpdate: [String:Date] = [:] // Hex encoded public key to date
internal static let storage = OWSPrimaryStorage.shared()
// MARK: Convenience
@ -14,6 +15,7 @@ public final class LokiAPI : NSObject {
private static let maxRetryCount: UInt = 8
private static let defaultTimeout: TimeInterval = 20
private static let longPollingTimeout: TimeInterval = 40
private static let deviceLinkUpdateInterval: TimeInterval = 8 * 60
public static let defaultMessageTTL: UInt64 = 24 * 60 * 60 * 1000
internal static var powDifficulty: UInt = 40
@ -33,6 +35,13 @@ public final class LokiAPI : NSObject {
}
}
internal struct Destination {
internal let hexEncodedPublicKey: String
internal let kind: Kind
enum Kind { case master, slave }
}
public typealias MessageListPromise = Promise<[SSKProtoEnvelope]>
public typealias RawResponsePromise = Promise<RawResponse>
@ -109,6 +118,37 @@ public final class LokiAPI : NSObject {
}
}
internal static func getDestinations(for hexEncodedPublicKey: String) -> Promise<[Destination]> {
let (promise, seal) = Promise<[Destination]>.pending()
func getDestinations() {
storage.dbReadConnection.read { transaction in
var destinations: [Destination] = []
let masterHexEncodedPublicKey = storage.getMasterHexEncodedPublicKey(for: hexEncodedPublicKey, in: transaction) ?? hexEncodedPublicKey
let masterDestination = Destination(hexEncodedPublicKey: masterHexEncodedPublicKey, kind: .master)
destinations.append(masterDestination)
let deviceLinks = storage.getDeviceLinks(for: masterHexEncodedPublicKey, in: transaction)
let slaveDestinations = deviceLinks.map { Destination(hexEncodedPublicKey: $0.slave.hexEncodedPublicKey, kind: .slave) }
destinations.append(contentsOf: slaveDestinations)
seal.fulfill(destinations)
}
}
let timeSinceLastUpdate: TimeInterval
if let lastDeviceLinkUpdate = lastDeviceLinkUpdate[hexEncodedPublicKey] {
timeSinceLastUpdate = Date().timeIntervalSince(lastDeviceLinkUpdate)
} else {
timeSinceLastUpdate = .infinity
}
if timeSinceLastUpdate > deviceLinkUpdateInterval {
storage.dbReadConnection.read { transaction in
let masterHexEncodedPublicKey = storage.getMasterHexEncodedPublicKey(for: hexEncodedPublicKey, in: transaction) ?? hexEncodedPublicKey
LokiStorageAPI.getDeviceLinks(associatedWith: masterHexEncodedPublicKey).done { _ in getDestinations() }.catch { seal.reject($0) }
}
} else {
getDestinations()
}
return promise
}
// MARK: Public API
public static func getMessages() -> Promise<Set<MessageListPromise>> {
return getTargetSnodes(for: userHexEncodedPublicKey).mapValues { targetSnode in
@ -117,17 +157,17 @@ public final class LokiAPI : NSObject {
}
public static func sendSignalMessage(_ signalMessage: SignalMessage, onP2PSuccess: @escaping () -> Void) -> Promise<Set<RawResponsePromise>> {
let result = internalSendSignalMessage(signalMessage, onP2PSuccess: onP2PSuccess)
// Use a best attempt approach for multi device for now
// TODO: Caching & get master links if this is a slave
LokiStorageAPI.getDeviceLinks(associatedWith: signalMessage.recipientID).done { deviceLinks in
let associatedHexEncodedPublicKeys = Set(deviceLinks.flatMap { [ $0.master.hexEncodedPublicKey, $0.slave.hexEncodedPublicKey ] }).subtracting([ signalMessage.recipientID ])
associatedHexEncodedPublicKeys.forEach { hexEncodedPublicKey in
let signalMessageCopy = signalMessage.copy(with: hexEncodedPublicKey)
return getDestinations(for: signalMessage.recipientID).then { destinations -> Promise<Set<RawResponsePromise>> in
// Use a best attempt approach for multi device for now
let slaveDestinations = destinations.filter { $0.kind == .slave }
slaveDestinations.forEach { destination in
let signalMessageCopy = signalMessage.copy(with: destination.hexEncodedPublicKey)
internalSendSignalMessage(signalMessageCopy) { }
}
let masterDestination = destinations.first { $0.kind == .master }!
let signalMessageCopy = signalMessage.copy(with: masterDestination.hexEncodedPublicKey)
return internalSendSignalMessage(signalMessage, onP2PSuccess: onP2PSuccess)
}
return result
}
// MARK: Public API (Obj-C)

Loading…
Cancel
Save