summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorAndrej Mihajlov <and@mullvad.net>2022-05-31 14:16:30 +0200
committerAndrej Mihajlov <and@mullvad.net>2022-06-08 12:31:16 +0200
commit8a3bc95854654a1c3758ca9dd1d8f85ea4ba3775 (patch)
tree724d7d8875738ff4b502b846c81421fa0f32d837
parent1cdc1610be9cd4e2f7913345955568bda0d67cd9 (diff)
downloadmullvadvpn-8a3bc95854654a1c3758ca9dd1d8f85ea4ba3775.tar.xz
mullvadvpn-8a3bc95854654a1c3758ca9dd1d8f85ea4ba3775.zip
Switch to mutually exclusive condition
-rw-r--r--ios/MullvadVPN.xcodeproj/project.pbxproj6
-rw-r--r--ios/MullvadVPN/AppStorePaymentManager/AppStorePaymentManager.swift14
-rw-r--r--ios/MullvadVPN/Operations/ExclusivityController.swift117
-rw-r--r--ios/MullvadVPN/TunnelManager/TunnelManager.swift77
4 files changed, 45 insertions, 169 deletions
diff --git a/ios/MullvadVPN.xcodeproj/project.pbxproj b/ios/MullvadVPN.xcodeproj/project.pbxproj
index 4056bbb17f..813d27349b 100644
--- a/ios/MullvadVPN.xcodeproj/project.pbxproj
+++ b/ios/MullvadVPN.xcodeproj/project.pbxproj
@@ -21,7 +21,6 @@
58095C552760F02500890776 /* UpdateAddressCacheOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58095C542760F02500890776 /* UpdateAddressCacheOperation.swift */; };
58095C572760F47900890776 /* api-ip-address.json in Resources */ = {isa = PBXBuildFile; fileRef = 58095C562760F47900890776 /* api-ip-address.json */; };
58095C592762155700890776 /* RESTRetryStrategy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58095C582762155700890776 /* RESTRetryStrategy.swift */; };
- 580EE20624B3222200F9D8A1 /* ExclusivityController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 580EE20524B3222200F9D8A1 /* ExclusivityController.swift */; };
580EE22424B3243100F9D8A1 /* AsyncBlockOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 580EE22324B3243100F9D8A1 /* AsyncBlockOperation.swift */; };
580F8B8328197881002E0998 /* TunnelSettingsV2.swift in Sources */ = {isa = PBXBuildFile; fileRef = 580F8B8228197881002E0998 /* TunnelSettingsV2.swift */; };
580F8B8428197884002E0998 /* TunnelSettingsV2.swift in Sources */ = {isa = PBXBuildFile; fileRef = 580F8B8228197881002E0998 /* TunnelSettingsV2.swift */; };
@@ -86,7 +85,6 @@
5846227126E229F20035F7C2 /* AppStoreSubscription.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5846227026E229F20035F7C2 /* AppStoreSubscription.swift */; };
5846227326E22A160035F7C2 /* AppStorePaymentObserver.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5846227226E22A160035F7C2 /* AppStorePaymentObserver.swift */; };
5846227726E22A7C0035F7C2 /* AppStorePaymentManagerDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5846227626E22A7C0035F7C2 /* AppStorePaymentManagerDelegate.swift */; };
- 5846227A26E24F1F0035F7C2 /* ExclusivityController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 580EE20524B3222200F9D8A1 /* ExclusivityController.swift */; };
584789BE264D4A2A000E45FB /* le_root_cert.cer in Resources */ = {isa = PBXBuildFile; fileRef = 584789B7264D4A2A000E45FB /* le_root_cert.cer */; };
584789E026529D72000E45FB /* SSLPinningURLSessionDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 584789DF26529D72000E45FB /* SSLPinningURLSessionDelegate.swift */; };
584789EC2652A1A2000E45FB /* Logging in Frameworks */ = {isa = PBXBuildFile; productRef = 584789EB2652A1A2000E45FB /* Logging */; };
@@ -346,7 +344,6 @@
58095C542760F02500890776 /* UpdateAddressCacheOperation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UpdateAddressCacheOperation.swift; sourceTree = "<group>"; };
58095C562760F47900890776 /* api-ip-address.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "api-ip-address.json"; sourceTree = "<group>"; };
58095C582762155700890776 /* RESTRetryStrategy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RESTRetryStrategy.swift; sourceTree = "<group>"; };
- 580EE20524B3222200F9D8A1 /* ExclusivityController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExclusivityController.swift; sourceTree = "<group>"; };
580EE22324B3243100F9D8A1 /* AsyncBlockOperation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AsyncBlockOperation.swift; sourceTree = "<group>"; };
580F8B8228197881002E0998 /* TunnelSettingsV2.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TunnelSettingsV2.swift; sourceTree = "<group>"; };
580F8B8528197958002E0998 /* DNSSettings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DNSSettings.swift; sourceTree = "<group>"; };
@@ -618,7 +615,6 @@
children = (
580EE22324B3243100F9D8A1 /* AsyncBlockOperation.swift */,
58E973DD24850EB600096F90 /* AsyncOperation.swift */,
- 580EE20524B3222200F9D8A1 /* ExclusivityController.swift */,
589D28782846250500F9A7B3 /* AsyncOperationQueue.swift */,
589D28812846306C00F9A7B3 /* GroupOperation.swift */,
5840BE34279EDB16002836BA /* OperationCompletion.swift */,
@@ -1227,7 +1223,6 @@
583E1E1B2848DE1C004838B3 /* ResultOperation+Fallible.swift in Sources */,
5857F23024C843ED00CF6F47 /* ChainedError.swift in Sources */,
58A8BE81239FBE62006B74AC /* IPEndpoint.swift in Sources */,
- 5846227A26E24F1F0035F7C2 /* ExclusivityController.swift in Sources */,
58871D2325D535D2002297FA /* IPAddressRange+Codable.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
@@ -1353,7 +1348,6 @@
584D26BF270C550B004EA533 /* AnyIPAddress.swift in Sources */,
5862805422428EF100F5A6E1 /* TranslucentButtonBlurView.swift in Sources */,
587EB66A270EFACB00123C75 /* CharacterSet+IPAddress.swift in Sources */,
- 580EE20624B3222200F9D8A1 /* ExclusivityController.swift in Sources */,
5888AD83227B11080051EB06 /* SelectLocationCell.swift in Sources */,
585DA89326B0323E00B8C587 /* TunnelIPCRequest.swift in Sources */,
5891BF1C25E3E3EB006D6FB0 /* Bundle+ProductVersion.swift in Sources */,
diff --git a/ios/MullvadVPN/AppStorePaymentManager/AppStorePaymentManager.swift b/ios/MullvadVPN/AppStorePaymentManager/AppStorePaymentManager.swift
index d035332eef..a8b56a8921 100644
--- a/ios/MullvadVPN/AppStorePaymentManager/AppStorePaymentManager.swift
+++ b/ios/MullvadVPN/AppStorePaymentManager/AppStorePaymentManager.swift
@@ -31,8 +31,6 @@ class AppStorePaymentManager: NSObject, SKPaymentTransactionObserver {
private let apiProxy = REST.ProxyFactory.shared.createAPIProxy()
private let accountsProxy = REST.ProxyFactory.shared.createAccountsProxy()
- private let exclusivityController = ExclusivityController()
-
private let paymentQueue: SKPaymentQueue
private var observerList = ObserverList<AppStorePaymentObserver>()
@@ -102,9 +100,11 @@ class AppStorePaymentManager: NSObject, SKPaymentTransactionObserver {
func requestProducts(with productIdentifiers: Set<AppStoreSubscription>, completionHandler: @escaping (OperationCompletion<SKProductsResponse, Swift.Error>) -> Void) -> Cancellable {
let productIdentifiers = productIdentifiers.productIdentifiersSet
- let operation = ProductsRequestOperation(productIdentifiers: productIdentifiers, completionHandler: completionHandler)
-
- exclusivityController.addOperation(operation, categories: [OperationCategory.productsRequest])
+ let operation = ProductsRequestOperation(
+ productIdentifiers: productIdentifiers,
+ completionHandler: completionHandler
+ )
+ operation.addCondition(MutuallyExclusive(category: OperationCategory.productsRequest))
operationQueue.addOperation(operation)
@@ -197,7 +197,9 @@ class AppStorePaymentManager: NSObject, SKPaymentTransactionObserver {
UIApplication.shared.endBackgroundTask(backgroundTaskIdentifier)
}
- exclusivityController.addOperation(operation, categories: [OperationCategory.sendAppStoreReceipt])
+ operation.addCondition(
+ MutuallyExclusive(category: OperationCategory.sendAppStoreReceipt)
+ )
operationQueue.addOperation(operation)
diff --git a/ios/MullvadVPN/Operations/ExclusivityController.swift b/ios/MullvadVPN/Operations/ExclusivityController.swift
deleted file mode 100644
index 5e8fdaf97f..0000000000
--- a/ios/MullvadVPN/Operations/ExclusivityController.swift
+++ /dev/null
@@ -1,117 +0,0 @@
-//
-// ExclusivityController.swift
-// MullvadVPN
-//
-// Created by pronebird on 06/07/2020.
-// Copyright © 2020 Mullvad VPN AB. All rights reserved.
-//
-
-import Foundation
-
-class ExclusivityController: NSObject {
- private let lock = NSLock()
- private var operations: [String: [Operation]] = [:]
- private var categoriesByOperation: [Operation: [String]] = [:]
-
- func addOperation(_ operation: Operation, categories: [String]) {
- lock.lock()
-
- categories.forEach { category in
- addOperation(operation, category: category)
- }
-
- addObserverIfNeeded(operation: operation, categories: categories)
-
- lock.unlock()
- }
-
- func removeOperation(_ operation: Operation, categories: [String]) {
- lock.lock()
-
- categories.forEach { category in
- removeOperation(operation, category: category)
- }
-
- removeObserverIfNeeded(operation: operation, categories: categories)
-
- lock.unlock()
- }
-
- override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
- if let operation = object as? Operation, keyPath == "isFinished" {
- operationDidFinish(operation)
- } else {
- super.observeValue(forKeyPath: keyPath, of: object, change: change, context: context)
- }
- }
-
- // MARK: - Private
-
- private func addOperation(_ operation: Operation, category: String) {
- var operationsWithThisCategory = operations[category] ?? []
-
- if let last = operationsWithThisCategory.last {
- operation.addDependency(last)
- }
-
- operationsWithThisCategory.append(operation)
-
- operations[category] = operationsWithThisCategory
- }
-
- private func removeOperation(_ operation: Operation, category: String) {
- guard var operationsWithThisCategory = operations[category],
- let index = operationsWithThisCategory.firstIndex(of: operation) else { return }
-
- operationsWithThisCategory.remove(at: index)
-
- if operationsWithThisCategory.isEmpty {
- operations.removeValue(forKey: category)
- } else {
- operations[category] = operationsWithThisCategory
- }
- }
-
- private func addObserverIfNeeded(operation: Operation, categories: [String]) {
- let existingCategories = categoriesByOperation[operation] ?? []
- let newCategories = existingCategories + categories
-
- if existingCategories.isEmpty && !newCategories.isEmpty {
- operation.addObserver(self, forKeyPath: "isFinished", options: .new, context: nil)
- }
-
- if !newCategories.isEmpty {
- categoriesByOperation[operation] = newCategories
- }
- }
-
- private func removeObserverIfNeeded(operation: Operation, categories: [String]) {
- guard var newCategories = categoriesByOperation[operation] else { return }
-
- newCategories.removeAll { s in
- categories.contains(s)
- }
-
- if newCategories.isEmpty {
- operation.removeObserver(self, forKeyPath: "isFinished", context: nil)
-
- categoriesByOperation.removeValue(forKey: operation)
- } else {
- categoriesByOperation[operation] = newCategories
- }
- }
-
- private func operationDidFinish(_ operation: Operation) {
- lock.lock()
-
- let operationCategories = categoriesByOperation[operation] ?? []
-
- removeObserverIfNeeded(operation: operation, categories: operationCategories)
-
- operationCategories.forEach { category in
- removeOperation(operation, category: category)
- }
-
- lock.unlock()
- }
-}
diff --git a/ios/MullvadVPN/TunnelManager/TunnelManager.swift b/ios/MullvadVPN/TunnelManager/TunnelManager.swift
index a0996867aa..f97c8da036 100644
--- a/ios/MullvadVPN/TunnelManager/TunnelManager.swift
+++ b/ios/MullvadVPN/TunnelManager/TunnelManager.swift
@@ -61,7 +61,6 @@ final class TunnelManager: TunnelManagerStateDelegate {
private let logger = Logger(label: "TunnelManager")
private let stateQueue = DispatchQueue(label: "TunnelManager.stateQueue")
- private let exclusivityController = ExclusivityController()
private let operationQueue = AsyncOperationQueue()
private var statusObserver: Tunnel.StatusBlockObserver?
@@ -223,32 +222,21 @@ final class TunnelManager: TunnelManagerStateDelegate {
completionHandler(completion.error)
}
}
+ loadTunnelOperation.addDependency(migrateSettingsOperation)
- let backgroundTaskIdentifier = UIApplication.shared.beginBackgroundTask(
- withName: "Load tunnel configuration"
- ) {
- // no-op
- }
-
- loadTunnelOperation.completionBlock = {
- UIApplication.shared.endBackgroundTask(backgroundTaskIdentifier)
- }
-
- exclusivityController.addOperation(migrateSettingsOperation, categories: [
- OperationCategory.changeTunnelSettings
+ let groupOperation = GroupOperation(operations: [
+ migrateSettingsOperation, loadTunnelOperation
])
- exclusivityController.addOperation(loadTunnelOperation, categories: [
- OperationCategory.manageTunnelProvider,
- OperationCategory.changeTunnelSettings
- ])
- loadTunnelOperation.addDependency(migrateSettingsOperation)
+ groupOperation.addCondition(
+ MutuallyExclusive(category: OperationCategory.manageTunnelProvider)
+ )
+ groupOperation.addCondition(
+ MutuallyExclusive(category: OperationCategory.changeTunnelSettings)
+ )
- operationQueue.addOperations([
- migrateSettingsOperation,
- loadTunnelOperation
- ], waitUntilFinished: false)
+ operationQueue.addOperation(groupOperation)
}
func startTunnel() {
@@ -280,8 +268,7 @@ final class TunnelManager: TunnelManagerStateDelegate {
operation.completionBlock = {
UIApplication.shared.endBackgroundTask(backgroundTaskIdentifier)
}
-
- exclusivityController.addOperation(operation, categories: [OperationCategory.manageTunnelProvider])
+ operation.addCondition(MutuallyExclusive(category: OperationCategory.manageTunnelProvider))
operationQueue.addOperation(operation)
}
@@ -313,7 +300,7 @@ final class TunnelManager: TunnelManagerStateDelegate {
UIApplication.shared.endBackgroundTask(backgroundTaskIdentifier)
}
- exclusivityController.addOperation(operation, categories: [OperationCategory.manageTunnelProvider])
+ operation.addCondition(MutuallyExclusive(category: OperationCategory.manageTunnelProvider))
operationQueue.addOperation(operation)
}
@@ -353,7 +340,9 @@ final class TunnelManager: TunnelManagerStateDelegate {
UIApplication.shared.endBackgroundTask(backgroundTaskIdentifier)
}
- exclusivityController.addOperation(operation, categories: [OperationCategory.manageTunnelProvider])
+ operation.addCondition(
+ MutuallyExclusive(category: OperationCategory.manageTunnelProvider)
+ )
operationQueue.addOperation(operation)
}
@@ -397,10 +386,12 @@ final class TunnelManager: TunnelManagerStateDelegate {
UIApplication.shared.endBackgroundTask(backgroundTaskIdentifier)
}
- exclusivityController.addOperation(operation, categories: [
- OperationCategory.manageTunnelProvider,
- OperationCategory.changeTunnelSettings
- ])
+ operation.addCondition(
+ MutuallyExclusive(category: OperationCategory.manageTunnelProvider)
+ )
+ operation.addCondition(
+ MutuallyExclusive(category: OperationCategory.changeTunnelSettings)
+ )
operationQueue.addOperation(operation)
}
@@ -431,9 +422,9 @@ final class TunnelManager: TunnelManagerStateDelegate {
UIApplication.shared.endBackgroundTask(backgroundTaskIdentifier)
}
- exclusivityController.addOperation(operation, categories: [
- OperationCategory.changeTunnelSettings
- ])
+ operation.addCondition(
+ MutuallyExclusive(category: OperationCategory.changeTunnelSettings)
+ )
operationQueue.addOperation(operation)
}
@@ -456,9 +447,9 @@ final class TunnelManager: TunnelManagerStateDelegate {
UIApplication.shared.endBackgroundTask(backgroundTaskIdentifier)
}
- exclusivityController.addOperation(operation, categories: [
- OperationCategory.changeTunnelSettings
- ])
+ operation.addCondition(
+ MutuallyExclusive(category: OperationCategory.changeTunnelSettings)
+ )
operationQueue.addOperation(operation)
@@ -501,7 +492,9 @@ final class TunnelManager: TunnelManagerStateDelegate {
UIApplication.shared.endBackgroundTask(backgroundTaskIdentifier)
}
- exclusivityController.addOperation(operation, categories: [OperationCategory.changeTunnelSettings])
+ operation.addCondition(
+ MutuallyExclusive(category: OperationCategory.changeTunnelSettings)
+ )
operationQueue.addOperation(operation)
}
@@ -545,7 +538,9 @@ final class TunnelManager: TunnelManagerStateDelegate {
UIApplication.shared.endBackgroundTask(backgroundTaskIdentifier)
}
- exclusivityController.addOperation(operation, categories: [OperationCategory.changeTunnelSettings])
+ operation.addCondition(
+ MutuallyExclusive(category: OperationCategory.changeTunnelSettings)
+ )
operationQueue.addOperation(operation)
@@ -678,7 +673,9 @@ final class TunnelManager: TunnelManagerStateDelegate {
self.startTunnel()
}
- exclusivityController.addOperation(operation, categories: [OperationCategory.tunnelStateUpdate])
+ operation.addCondition(
+ MutuallyExclusive(category: OperationCategory.tunnelStateUpdate)
+ )
// Cancel last VPN status mapping operation
lastMapConnectionStatusOperation?.cancel()
@@ -735,7 +732,7 @@ final class TunnelManager: TunnelManagerStateDelegate {
UIApplication.shared.endBackgroundTask(backgroundTaskIdentifier)
}
- exclusivityController.addOperation(operation, categories: [OperationCategory.changeTunnelSettings])
+ operation.addCondition(MutuallyExclusive(category: OperationCategory.changeTunnelSettings))
operationQueue.addOperation(operation)
}