From 6c834b6a6e3008ee66fdac36ef1f3480fe10e3a8 Mon Sep 17 00:00:00 2001 From: nielsandriesse Date: Thu, 23 Apr 2020 15:03:27 +1000 Subject: [PATCH] Re-order functions --- .../Messaging/SessionProtocol+Receiving.swift | 188 ++++++++++-------- 1 file changed, 104 insertions(+), 84 deletions(-) diff --git a/SignalServiceKit/src/Loki/Messaging/SessionProtocol+Receiving.swift b/SignalServiceKit/src/Loki/Messaging/SessionProtocol+Receiving.swift index e04a46748..6fa4cf4c0 100644 --- a/SignalServiceKit/src/Loki/Messaging/SessionProtocol+Receiving.swift +++ b/SignalServiceKit/src/Loki/Messaging/SessionProtocol+Receiving.swift @@ -27,24 +27,18 @@ public extension SessionProtocol { /// Only ever modified from the message processing queue (`OWSBatchMessageProcessor.processingQueue`). private static var syncMessageTimestamps: [String:Set] = [:] - @objc(isFriendRequestFromBeforeRestoration:) - public static func isFriendRequestFromBeforeRestoration(_ envelope: SSKProtoEnvelope) -> Bool { - // The envelope type is set during UD decryption - let restorationTimeInMs = UInt64(storage.getRestorationTime() * 1000) - return (envelope.type == .friendRequest && envelope.timestamp < restorationTimeInMs) + // MARK: - Session Handling + @objc(isSessionRestoreMessage:) + public static func isSessionRestoreMessage(_ dataMessage: SSKProtoDataMessage) -> Bool { + let sessionRestoreFlag = SSKProtoDataMessage.SSKProtoDataMessageFlags.sessionRestore + return dataMessage.flags & UInt32(sessionRestoreFlag.rawValue) != 0 } - // TODO: We should probably look at why sync messages are being duplicated rather than doing this - @objc(isDuplicateSyncMessage:fromHexEncodedPublicKey:) - public static func isDuplicateSyncMessage(_ protoContent: SSKProtoContent, from hexEncodedPublicKey: String) -> Bool { - guard let syncMessage = protoContent.syncMessage?.sent else { return false } - var timestamps: Set = syncMessageTimestamps[hexEncodedPublicKey] ?? [] - let hasTimestamp = syncMessage.timestamp != 0 - guard hasTimestamp else { return false } - let result = timestamps.contains(syncMessage.timestamp) - timestamps.insert(syncMessage.timestamp) - syncMessageTimestamps[hexEncodedPublicKey] = timestamps - return result + // TODO: Is this only ever used for closed groups? + @objc(isSessionRequestMessage:) + public static func isSessionRequestMessage(_ dataMessage: SSKProtoDataMessage) -> Bool { + let sessionRequestFlag = SSKProtoDataMessage.SSKProtoDataMessageFlags.sessionRequest + return dataMessage.flags & UInt32(sessionRequestFlag.rawValue) != 0 } // TODO: This seriously needs some explanation of when we expect pre key bundles to be attached @@ -89,76 +83,9 @@ public extension SessionProtocol { messageSenderJobQueue.add(message: ephemeralMessage, transaction: transaction) } - @objc(handleP2PAddressMessageIfNeeded:wrappedIn:) - public static func handleP2PAddressMessageIfNeeded(_ protoContent: SSKProtoContent, wrappedIn envelope: SSKProtoEnvelope) { - // The envelope source is set during UD decryption - let hexEncodedPublicKey = envelope.source! - guard let addressMessage = protoContent.lokiAddressMessage, let address = addressMessage.ptpAddress else { return } - let portAsUInt32 = addressMessage.ptpPort - guard portAsUInt32 != 0, portAsUInt32 < UInt16.max else { return } - let port = UInt16(portAsUInt32) - LokiP2PAPI.didReceiveLokiAddressMessage(forContact: hexEncodedPublicKey, address: address, port: port, receivedThroughP2P: envelope.isPtpMessage) - } - - @objc(handleDeviceLinkMessageIfNeeded:wrappedIn:using:) - public static func handleDeviceLinkMessageIfNeeded(_ protoContent: SSKProtoContent, wrappedIn envelope: SSKProtoEnvelope, using transaction: YapDatabaseReadWriteTransaction) { - // The envelope source is set during UD decryption - let hexEncodedPublicKey = envelope.source! - guard let deviceLinkMessage = protoContent.lokiDeviceLinkMessage, let master = deviceLinkMessage.masterHexEncodedPublicKey, - let slave = deviceLinkMessage.slaveHexEncodedPublicKey, let slaveSignature = deviceLinkMessage.slaveSignature else { - print("[Loki] Received an invalid device link message.") - return - } - let deviceLinkingSession = DeviceLinkingSession.current - if let masterSignature = deviceLinkMessage.masterSignature { // Authorization - print("[Loki] Received a device link authorization from: \(hexEncodedPublicKey).") // Intentionally not `master` - if let deviceLinkingSession = deviceLinkingSession { - deviceLinkingSession.processLinkingAuthorization(from: master, for: slave, masterSignature: masterSignature, slaveSignature: slaveSignature) - } else { - print("[Loki] Received a device link authorization without a session; ignoring.") - } - // Set any profile info (the device link authorization also includes the master device's profile info) - if let dataMessage = protoContent.dataMessage { - updateDisplayNameIfNeeded(for: master, using: dataMessage, appendingShortID: false, in: transaction) - updateProfileKeyIfNeeded(for: master, using: dataMessage) - } - } else { // Request - print("[Loki] Received a device link request from: \(hexEncodedPublicKey).") // Intentionally not `slave` - if let deviceLinkingSession = deviceLinkingSession { - deviceLinkingSession.processLinkingRequest(from: slave, to: master, with: slaveSignature) - } else { - NotificationCenter.default.post(name: .unexpectedDeviceLinkRequestReceived, object: nil) - } - } - } - - @objc(isSessionRequestMessage:) - public static func isSessionRequestMessage(_ dataMessage: SSKProtoDataMessage) -> Bool { - let sessionRequestFlag = SSKProtoDataMessage.SSKProtoDataMessageFlags.sessionRequest - return dataMessage.flags & UInt32(sessionRequestFlag.rawValue) != 0 - } - - @objc(isSessionRestoreMessage:) - public static func isSessionRestoreMessage(_ dataMessage: SSKProtoDataMessage) -> Bool { - let sessionRestoreFlag = SSKProtoDataMessage.SSKProtoDataMessageFlags.sessionRestore - return dataMessage.flags & UInt32(sessionRestoreFlag.rawValue) != 0 - } - - @objc(isUnlinkDeviceMessage:) - public static func isUnlinkDeviceMessage(_ dataMessage: SSKProtoDataMessage) -> Bool { - let unlinkDeviceFlag = SSKProtoDataMessage.SSKProtoDataMessageFlags.unlinkDevice - return dataMessage.flags & UInt32(unlinkDeviceFlag.rawValue) != 0 - } - @objc(shouldIgnoreClosedGroupMessage:inThread:wrappedIn:using:) - public static func shouldIgnoreClosedGroupMessage(_ dataMessage: SSKProtoDataMessage, in thread: TSThread, wrappedIn envelope: SSKProtoEnvelope, using transaction: YapDatabaseReadTransaction) -> Bool { - // The envelope source is set during UD decryption - let hexEncodedPublicKey = envelope.source! - guard let thread = thread as? TSGroupThread, thread.groupModel.groupType == .closedGroup, - dataMessage.group?.type == .deliver else { return false } - return thread.isUser(inGroup: hexEncodedPublicKey, transaction: transaction) - } + // MARK: - Sync Messages @objc(isValidSyncMessage:in:) public static func isValidSyncMessage(_ envelope: SSKProtoEnvelope, in transaction: YapDatabaseReadTransaction) -> Bool { // The envelope source is set during UD decryption @@ -167,6 +94,19 @@ public extension SessionProtocol { return linkedDeviceHexEncodedPublicKeys.contains(hexEncodedPublicKey) } + // TODO: We should probably look at why sync messages are being duplicated rather than doing this + @objc(isDuplicateSyncMessage:fromHexEncodedPublicKey:) + public static func isDuplicateSyncMessage(_ protoContent: SSKProtoContent, from hexEncodedPublicKey: String) -> Bool { + guard let syncMessage = protoContent.syncMessage?.sent else { return false } + var timestamps: Set = syncMessageTimestamps[hexEncodedPublicKey] ?? [] + let hasTimestamp = syncMessage.timestamp != 0 + guard hasTimestamp else { return false } + let result = timestamps.contains(syncMessage.timestamp) + timestamps.insert(syncMessage.timestamp) + syncMessageTimestamps[hexEncodedPublicKey] = timestamps + return result + } + @objc(updateProfileFromSyncMessageIfNeeded:wrappedIn:using:) public static func updateProfileFromSyncMessageIfNeeded(_ dataMessage: SSKProtoDataMessage, wrappedIn envelope: SSKProtoEnvelope, using transaction: YapDatabaseReadWriteTransaction) { // The envelope source is set during UD decryption @@ -284,6 +224,47 @@ public extension SessionProtocol { } } + + + // MARK: Multi Device + @objc(handleDeviceLinkMessageIfNeeded:wrappedIn:using:) + public static func handleDeviceLinkMessageIfNeeded(_ protoContent: SSKProtoContent, wrappedIn envelope: SSKProtoEnvelope, using transaction: YapDatabaseReadWriteTransaction) { + // The envelope source is set during UD decryption + let hexEncodedPublicKey = envelope.source! + guard let deviceLinkMessage = protoContent.lokiDeviceLinkMessage, let master = deviceLinkMessage.masterHexEncodedPublicKey, + let slave = deviceLinkMessage.slaveHexEncodedPublicKey, let slaveSignature = deviceLinkMessage.slaveSignature else { + print("[Loki] Received an invalid device link message.") + return + } + let deviceLinkingSession = DeviceLinkingSession.current + if let masterSignature = deviceLinkMessage.masterSignature { // Authorization + print("[Loki] Received a device link authorization from: \(hexEncodedPublicKey).") // Intentionally not `master` + if let deviceLinkingSession = deviceLinkingSession { + deviceLinkingSession.processLinkingAuthorization(from: master, for: slave, masterSignature: masterSignature, slaveSignature: slaveSignature) + } else { + print("[Loki] Received a device link authorization without a session; ignoring.") + } + // Set any profile info (the device link authorization also includes the master device's profile info) + if let dataMessage = protoContent.dataMessage { + updateDisplayNameIfNeeded(for: master, using: dataMessage, appendingShortID: false, in: transaction) + updateProfileKeyIfNeeded(for: master, using: dataMessage) + } + } else { // Request + print("[Loki] Received a device link request from: \(hexEncodedPublicKey).") // Intentionally not `slave` + if let deviceLinkingSession = deviceLinkingSession { + deviceLinkingSession.processLinkingRequest(from: slave, to: master, with: slaveSignature) + } else { + NotificationCenter.default.post(name: .unexpectedDeviceLinkRequestReceived, object: nil) + } + } + } + + @objc(isUnlinkDeviceMessage:) + public static func isUnlinkDeviceMessage(_ dataMessage: SSKProtoDataMessage) -> Bool { + let unlinkDeviceFlag = SSKProtoDataMessage.SSKProtoDataMessageFlags.unlinkDevice + return dataMessage.flags & UInt32(unlinkDeviceFlag.rawValue) != 0 + } + @objc(handleUnlinkDeviceMessage:wrappedIn:using:) public static func handleUnlinkDeviceMessage(_ dataMessage: SSKProtoDataMessage, wrappedIn envelope: SSKProtoEnvelope, using transaction: YapDatabaseReadWriteTransaction) { // The envelope source is set during UD decryption @@ -303,6 +284,18 @@ public extension SessionProtocol { } } + + + // MARK: - Closed Groups + @objc(shouldIgnoreClosedGroupMessage:inThread:wrappedIn:using:) + public static func shouldIgnoreClosedGroupMessage(_ dataMessage: SSKProtoDataMessage, in thread: TSThread, wrappedIn envelope: SSKProtoEnvelope, using transaction: YapDatabaseReadTransaction) -> Bool { + // The envelope source is set during UD decryption + let hexEncodedPublicKey = envelope.source! + guard let thread = thread as? TSGroupThread, thread.groupModel.groupType == .closedGroup, + dataMessage.group?.type == .deliver else { return false } + return thread.isUser(inGroup: hexEncodedPublicKey, transaction: transaction) + } + @objc(shouldIgnoreClosedGroupUpdateMessage:in:using:) public static func shouldIgnoreClosedGroupUpdateMessage(_ envelope: SSKProtoEnvelope, in thread: TSGroupThread?, using transaction: YapDatabaseReadTransaction) -> Bool { // The envelope source is set during UD decryption @@ -324,6 +317,9 @@ public extension SessionProtocol { } } + + + // MARK: - Profile Updating @objc(updateDisplayNameIfNeededForHexEncodedPublicKey:using:appendingShortID:in:) public static func updateDisplayNameIfNeeded(for hexEncodedPublicKey: String, using dataMessage: SSKProtoDataMessage, appendingShortID appendShortID: Bool, in transaction: YapDatabaseReadWriteTransaction) { guard let profile = dataMessage.profile, let rawDisplayName = profile.displayName else { return } @@ -351,6 +347,16 @@ public extension SessionProtocol { profileManager.setProfileKeyData(profileKey, forRecipientId: hexEncodedPublicKey, avatarURL: profilePictureURL) } + + + // MARK: - Friend Requests + @objc(isFriendRequestFromBeforeRestoration:) + public static func isFriendRequestFromBeforeRestoration(_ envelope: SSKProtoEnvelope) -> Bool { + // The envelope type is set during UD decryption + let restorationTimeInMs = UInt64(storage.getRestorationTime() * 1000) + return (envelope.type == .friendRequest && envelope.timestamp < restorationTimeInMs) + } + @objc(canFriendRequestBeAutoAcceptedForHexEncodedPublicKey:in:using:) public static func canFriendRequestBeAutoAccepted(for hexEncodedPublicKey: String, in thread: TSThread, using transaction: YapDatabaseReadTransaction) -> Bool { if thread.hasCurrentUserSentFriendRequest { @@ -447,4 +453,18 @@ public extension SessionProtocol { // Don't save yet. This is done in finalizeIncomingMessage:thread:masterThread:envelope:transaction. } } + + + + // MARK: - P2P + @objc(handleP2PAddressMessageIfNeeded:wrappedIn:) + public static func handleP2PAddressMessageIfNeeded(_ protoContent: SSKProtoContent, wrappedIn envelope: SSKProtoEnvelope) { + // The envelope source is set during UD decryption + let hexEncodedPublicKey = envelope.source! + guard let addressMessage = protoContent.lokiAddressMessage, let address = addressMessage.ptpAddress else { return } + let portAsUInt32 = addressMessage.ptpPort + guard portAsUInt32 != 0, portAsUInt32 < UInt16.max else { return } + let port = UInt16(portAsUInt32) + LokiP2PAPI.didReceiveLokiAddressMessage(forContact: hexEncodedPublicKey, address: address, port: port, receivedThroughP2P: envelope.isPtpMessage) + } }