|
|
|
|
@ -22,6 +22,11 @@ public final class SnodeAPI : NSObject {
|
|
|
|
|
public static var clockOffset: Int64 = 0
|
|
|
|
|
/// - Note: Should only be accessed from `Threading.workQueue` to avoid race conditions.
|
|
|
|
|
public static var swarmCache: [String:Set<Snode>] = [:]
|
|
|
|
|
|
|
|
|
|
// MARK: Namespaces
|
|
|
|
|
private static let defaultNamespace = 0
|
|
|
|
|
private static let unauthenticatedNamespace = -10
|
|
|
|
|
private static let configNamespace = 5
|
|
|
|
|
|
|
|
|
|
// MARK: Settings
|
|
|
|
|
private static let maxRetryCount: UInt = 8
|
|
|
|
|
@ -391,36 +396,61 @@ public final class SnodeAPI : NSObject {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static func getRawMessages(from snode: Snode, associatedWith publicKey: String) -> RawResponsePromise {
|
|
|
|
|
let (promise, seal) = RawResponsePromise.pending()
|
|
|
|
|
Threading.workQueue.async {
|
|
|
|
|
getMessagesWithAuthentication(from: snode, associatedWith: publicKey).done2 { seal.fulfill($0) }.catch2 { seal.reject($0) }
|
|
|
|
|
}
|
|
|
|
|
return promise
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static func getRawMessagesUnauthenticated(from snode: Snode, associatedWith publicKey: String) -> RawResponsePromise {
|
|
|
|
|
let (promise, seal) = RawResponsePromise.pending()
|
|
|
|
|
Threading.workQueue.async {
|
|
|
|
|
getMessagesInternal(from: snode, associatedWith: publicKey).done2 { seal.fulfill($0) }.catch2 { seal.reject($0) }
|
|
|
|
|
}
|
|
|
|
|
return promise
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static func getMessagesInternal(from snode: Snode, associatedWith publicKey: String) -> RawResponsePromise {
|
|
|
|
|
|
|
|
|
|
private static func getMessagesWithAuthentication(from snode: Snode, associatedWith publicKey: String) -> RawResponsePromise {
|
|
|
|
|
let storage = SNSnodeKitConfiguration.shared.storage
|
|
|
|
|
|
|
|
|
|
// NOTE: All authentication logic is currently commented out, the reason being that we can't currently support
|
|
|
|
|
// NOTE: All authentication logic is only apply to 1-1 chats, the reason being that we can't currently support
|
|
|
|
|
// it yet for closed groups. The Storage Server requires an ed25519 key pair, but we don't have that for our
|
|
|
|
|
// closed groups.
|
|
|
|
|
|
|
|
|
|
// guard let userED25519KeyPair = storage.getUserED25519KeyPair() else { return Promise(error: Error.noKeyPair) }
|
|
|
|
|
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) ?? ""
|
|
|
|
|
// Construct signature
|
|
|
|
|
// let timestamp = UInt64(Int64(NSDate.millisecondTimestamp()) + SnodeAPI.clockOffset)
|
|
|
|
|
// let ed25519PublicKey = userED25519KeyPair.publicKey.toHexString()
|
|
|
|
|
// let verificationData = ("retrieve" + String(timestamp)).data(using: String.Encoding.utf8)!
|
|
|
|
|
// let signature = sodium.sign.signature(message: Bytes(verificationData), secretKey: userED25519KeyPair.secretKey)!
|
|
|
|
|
let timestamp = UInt64(Int64(NSDate.millisecondTimestamp()) + SnodeAPI.clockOffset)
|
|
|
|
|
let ed25519PublicKey = userED25519KeyPair.publicKey.toHexString()
|
|
|
|
|
let verificationData = ("retrieve" + String(timestamp)).data(using: String.Encoding.utf8)!
|
|
|
|
|
let signature = sodium.sign.signature(message: Bytes(verificationData), secretKey: userED25519KeyPair.secretKey)!
|
|
|
|
|
// Make the request
|
|
|
|
|
let parameters: JSON = [
|
|
|
|
|
"pubKey" : Features.useTestnet ? publicKey.removing05PrefixIfNeeded() : publicKey,
|
|
|
|
|
"namespace": defaultNamespace,
|
|
|
|
|
"lastHash" : lastHash,
|
|
|
|
|
"timestamp" : timestamp,
|
|
|
|
|
"pubkey_ed25519" : ed25519PublicKey,
|
|
|
|
|
"signature" : signature.toBase64()
|
|
|
|
|
]
|
|
|
|
|
return invoke(.getMessages, on: snode, associatedWith: publicKey, parameters: parameters)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static func getMessagesInternal(from snode: Snode, associatedWith publicKey: String) -> RawResponsePromise {
|
|
|
|
|
let storage = SNSnodeKitConfiguration.shared.storage
|
|
|
|
|
|
|
|
|
|
// Get last message hash
|
|
|
|
|
storage.pruneLastMessageHashInfoIfExpired(for: snode, associatedWith: publicKey)
|
|
|
|
|
let lastHash = storage.getLastMessageHash(for: snode, associatedWith: publicKey) ?? ""
|
|
|
|
|
|
|
|
|
|
// Make the request
|
|
|
|
|
let parameters: JSON = [
|
|
|
|
|
"pubKey" : Features.useTestnet ? publicKey.removing05PrefixIfNeeded() : publicKey,
|
|
|
|
|
"namespace": unauthenticatedNamespace,
|
|
|
|
|
"lastHash" : lastHash,
|
|
|
|
|
// "timestamp" : timestamp,
|
|
|
|
|
// "pubkey_ed25519" : ed25519PublicKey,
|
|
|
|
|
// "signature" : signature.toBase64()!
|
|
|
|
|
]
|
|
|
|
|
return invoke(.getMessages, on: snode, associatedWith: publicKey, parameters: parameters)
|
|
|
|
|
}
|
|
|
|
|
|