|
|
@ -1,6 +1,7 @@
|
|
|
|
import SessionUtilitiesKit
|
|
|
|
import SessionUtilitiesKit
|
|
|
|
|
|
|
|
|
|
|
|
public enum MessageReceiver {
|
|
|
|
public enum MessageReceiver {
|
|
|
|
|
|
|
|
private static var lastEncryptionKeyPairRequest: [String:Date] = [:]
|
|
|
|
|
|
|
|
|
|
|
|
public enum Error : LocalizedError {
|
|
|
|
public enum Error : LocalizedError {
|
|
|
|
case duplicateMessage
|
|
|
|
case duplicateMessage
|
|
|
@ -18,7 +19,6 @@ public enum MessageReceiver {
|
|
|
|
// Shared sender keys
|
|
|
|
// Shared sender keys
|
|
|
|
case invalidGroupPublicKey
|
|
|
|
case invalidGroupPublicKey
|
|
|
|
case noGroupKeyPair
|
|
|
|
case noGroupKeyPair
|
|
|
|
case sharedSecretGenerationFailed
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public var isRetryable: Bool {
|
|
|
|
public var isRetryable: Bool {
|
|
|
|
switch self {
|
|
|
|
switch self {
|
|
|
@ -44,18 +44,20 @@ public enum MessageReceiver {
|
|
|
|
// Shared sender keys
|
|
|
|
// Shared sender keys
|
|
|
|
case .invalidGroupPublicKey: return "Invalid group public key."
|
|
|
|
case .invalidGroupPublicKey: return "Invalid group public key."
|
|
|
|
case .noGroupKeyPair: return "Missing group key pair."
|
|
|
|
case .noGroupKeyPair: return "Missing group key pair."
|
|
|
|
case .sharedSecretGenerationFailed: return "Couldn't generate a shared secret."
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public static func parse(_ data: Data, openGroupMessageServerID: UInt64?, using transaction: Any) throws -> (Message, SNProtoContent) {
|
|
|
|
public static func parse(_ data: Data, openGroupMessageServerID: UInt64?, isRetry: Bool = false, using transaction: Any) throws -> (Message, SNProtoContent) {
|
|
|
|
let userPublicKey = SNMessagingKitConfiguration.shared.storage.getUserPublicKey()
|
|
|
|
let userPublicKey = SNMessagingKitConfiguration.shared.storage.getUserPublicKey()
|
|
|
|
let isOpenGroupMessage = (openGroupMessageServerID != nil)
|
|
|
|
let isOpenGroupMessage = (openGroupMessageServerID != nil)
|
|
|
|
// Parse the envelope
|
|
|
|
// Parse the envelope
|
|
|
|
let envelope = try SNProtoEnvelope.parseData(data)
|
|
|
|
let envelope = try SNProtoEnvelope.parseData(data)
|
|
|
|
let storage = SNMessagingKitConfiguration.shared.storage
|
|
|
|
let storage = SNMessagingKitConfiguration.shared.storage
|
|
|
|
guard !Set(storage.getReceivedMessageTimestamps(using: transaction)).contains(envelope.timestamp) else { throw Error.duplicateMessage }
|
|
|
|
// If the message failed to process the first time around we retry it later (if the error is retryable). In this case the timestamp
|
|
|
|
|
|
|
|
// will already be in the database but we don't want to treat the message as a duplicate. The isRetry flag is a simple workaround
|
|
|
|
|
|
|
|
// for this issue.
|
|
|
|
|
|
|
|
guard !Set(storage.getReceivedMessageTimestamps(using: transaction)).contains(envelope.timestamp) || isRetry else { throw Error.duplicateMessage }
|
|
|
|
storage.addReceivedMessageTimestamp(envelope.timestamp, using: transaction)
|
|
|
|
storage.addReceivedMessageTimestamp(envelope.timestamp, using: transaction)
|
|
|
|
// Decrypt the contents
|
|
|
|
// Decrypt the contents
|
|
|
|
guard let ciphertext = envelope.content else { throw Error.noData }
|
|
|
|
guard let ciphertext = envelope.content else { throw Error.noData }
|
|
|
@ -93,9 +95,13 @@ public enum MessageReceiver {
|
|
|
|
try decrypt()
|
|
|
|
try decrypt()
|
|
|
|
} catch {
|
|
|
|
} catch {
|
|
|
|
do {
|
|
|
|
do {
|
|
|
|
try MessageSender.requestEncryptionKeyPair(for: groupPublicKey!, using: transaction as! YapDatabaseReadWriteTransaction)
|
|
|
|
let now = Date()
|
|
|
|
} catch {
|
|
|
|
// Don't spam encryption key pair requests
|
|
|
|
// Do nothing
|
|
|
|
let shouldRequestEncryptionKeyPair = given(lastEncryptionKeyPairRequest[groupPublicKey!]) { now.timeIntervalSince($0) > 30 } ?? true
|
|
|
|
|
|
|
|
if shouldRequestEncryptionKeyPair {
|
|
|
|
|
|
|
|
try MessageSender.requestEncryptionKeyPair(for: groupPublicKey!, using: transaction as! YapDatabaseReadWriteTransaction)
|
|
|
|
|
|
|
|
lastEncryptionKeyPairRequest[groupPublicKey!] = now
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
throw error // Throw the * decryption * error and not the error generated by requestEncryptionKeyPair (if it generated one)
|
|
|
|
throw error // Throw the * decryption * error and not the error generated by requestEncryptionKeyPair (if it generated one)
|
|
|
|
}
|
|
|
|
}
|
|
|
|