summaryrefslogtreecommitdiffhomepage
path: root/ios
diff options
context:
space:
mode:
authorAndrej Mihajlov <and@mullvad.net>2022-03-28 14:57:24 +0200
committerAndrej Mihajlov <and@mullvad.net>2022-04-05 09:12:56 +0200
commit455cd2b79885cfd1c71ee0ef3c49a6ddb3bf0555 (patch)
treed0adb59a2722f3c3ebaa6461639af82bf07c7ed6 /ios
parenteaeb54da9c31ae3de738980ec04a9f2b40204b21 (diff)
downloadmullvadvpn-455cd2b79885cfd1c71ee0ef3c49a6ddb3bf0555.tar.xz
mullvadvpn-455cd2b79885cfd1c71ee0ef3c49a6ddb3bf0555.zip
Subclass from ResultOperation
Diffstat (limited to 'ios')
-rw-r--r--ios/MullvadVPN/AppStorePaymentManager/AppStorePaymentManager.swift47
-rw-r--r--ios/MullvadVPN/AppStoreReceipt.swift22
-rw-r--r--ios/MullvadVPN/Operations/ProductsRequestOperation.swift21
-rw-r--r--ios/MullvadVPN/RelayCache/RelayCacheTracker.swift16
-rw-r--r--ios/MullvadVPN/TunnelIPC/TunnelIPCRequestOperation.swift41
-rw-r--r--ios/MullvadVPN/TunnelManager/LoadTunnelOperation.swift13
-rw-r--r--ios/MullvadVPN/TunnelManager/ReloadTunnelOperation.swift29
-rw-r--r--ios/MullvadVPN/TunnelManager/ReplaceKeyOperation.swift11
-rw-r--r--ios/MullvadVPN/TunnelManager/SetAccountOperation.swift13
-rw-r--r--ios/MullvadVPN/TunnelManager/SetTunnelSettingsOperation.swift52
-rw-r--r--ios/MullvadVPN/TunnelManager/StartTunnelOperation.swift79
-rw-r--r--ios/MullvadVPN/TunnelManager/StopTunnelOperation.swift67
12 files changed, 157 insertions, 254 deletions
diff --git a/ios/MullvadVPN/AppStorePaymentManager/AppStorePaymentManager.swift b/ios/MullvadVPN/AppStorePaymentManager/AppStorePaymentManager.swift
index 9d4b56cf99..fab80ea9de 100644
--- a/ios/MullvadVPN/AppStorePaymentManager/AppStorePaymentManager.swift
+++ b/ios/MullvadVPN/AppStorePaymentManager/AppStorePaymentManager.swift
@@ -133,6 +133,17 @@ class AppStorePaymentManager: NSObject, SKPaymentTransactionObserver {
didFailWithError: .validateAccount(error)
)
}
+
+ case .cancelled:
+ self.observerList.forEach { observer in
+ observer.appStorePaymentManager(
+ self,
+ transaction: nil,
+ payment: payment,
+ accountToken: accountToken,
+ didFailWithError: .validateAccount(.network(URLError(.cancelled)))
+ )
+ }
}
UIApplication.shared.endBackgroundTask(backgroundTaskIdentifier)
@@ -285,16 +296,13 @@ class AppStorePaymentManager: NSObject, SKPaymentTransactionObserver {
}
-private class SendAppStoreReceiptOperation: AsyncOperation {
- typealias CompletionHandler = (OperationCompletion<REST.CreateApplePaymentResponse, AppStorePaymentManager.Error>) -> Void
-
+private class SendAppStoreReceiptOperation: ResultOperation<REST.CreateApplePaymentResponse, AppStorePaymentManager.Error> {
private let restClient: REST.Client
private let accountToken: String
private let forceRefresh: Bool
private let receiptProperties: [String: Any]?
- private var completionHandler: CompletionHandler?
- private var fetchReceiptCancellable: Cancellable?
- private var submitReceiptCancellable: Cancellable?
+ private var fetchReceiptTask: Cancellable?
+ private var submitReceiptTask: Cancellable?
private let logger = Logger(label: "AppStorePaymentManager.SendAppStoreReceiptOperation")
@@ -303,18 +311,19 @@ private class SendAppStoreReceiptOperation: AsyncOperation {
self.accountToken = accountToken
self.forceRefresh = forceRefresh
self.receiptProperties = receiptProperties
- self.completionHandler = completionHandler
+
+ super.init(completionQueue: .main, completionHandler: completionHandler)
}
override func cancel() {
super.cancel()
DispatchQueue.main.async {
- self.fetchReceiptCancellable?.cancel()
- self.fetchReceiptCancellable = nil
+ self.fetchReceiptTask?.cancel()
+ self.fetchReceiptTask = nil
- self.submitReceiptCancellable?.cancel()
- self.submitReceiptCancellable = nil
+ self.submitReceiptTask?.cancel()
+ self.submitReceiptTask = nil
}
}
@@ -325,7 +334,7 @@ private class SendAppStoreReceiptOperation: AsyncOperation {
return
}
- self.fetchReceiptCancellable = AppStoreReceipt.fetch(forceRefresh: self.forceRefresh, receiptProperties: self.receiptProperties) { completion in
+ self.fetchReceiptTask = AppStoreReceipt.fetch(forceRefresh: self.forceRefresh, receiptProperties: self.receiptProperties) { completion in
switch completion {
case .success(let receiptData):
self.sendReceipt(receiptData)
@@ -342,7 +351,7 @@ private class SendAppStoreReceiptOperation: AsyncOperation {
}
private func sendReceipt(_ receiptData: Data) {
- submitReceiptCancellable = restClient.createApplePayment(
+ submitReceiptTask = restClient.createApplePayment(
token: self.accountToken,
receiptString: receiptData,
retryStrategy: .noRetry) { result in
@@ -354,15 +363,11 @@ private class SendAppStoreReceiptOperation: AsyncOperation {
case .failure(let error):
self.logger.error(chainedError: error, message: "Failed to send the AppStore receipt.")
self.finish(completion: .failure(.sendReceipt(error)))
+
+ case .cancelled:
+ self.logger.debug("Receipt submission cancelled.")
+ self.finish(completion: .cancelled)
}
}
}
-
- private func finish(completion: OperationCompletion<REST.CreateApplePaymentResponse, AppStorePaymentManager.Error>) {
- let block = completionHandler
- completionHandler = nil
-
- block?(completion)
- finish()
- }
}
diff --git a/ios/MullvadVPN/AppStoreReceipt.swift b/ios/MullvadVPN/AppStoreReceipt.swift
index ff61ffd281..849ef7ed0c 100644
--- a/ios/MullvadVPN/AppStoreReceipt.swift
+++ b/ios/MullvadVPN/AppStoreReceipt.swift
@@ -67,19 +67,18 @@ enum AppStoreReceipt {
}
}
-fileprivate class FetchAppStoreReceiptOperation: AsyncOperation, SKRequestDelegate {
+fileprivate class FetchAppStoreReceiptOperation: ResultOperation<Data, AppStoreReceipt.Error>, SKRequestDelegate {
+ private let dispatchQueue: DispatchQueue
private var request: SKReceiptRefreshRequest?
private let receiptProperties: [String: Any]?
private let forceRefresh: Bool
- private let dispatchQueue: DispatchQueue
- private var completionHandler: ((OperationCompletion<Data, AppStoreReceipt.Error>) -> Void)?
-
- init(dispatchQueue: DispatchQueue, forceRefresh: Bool, receiptProperties: [String: Any]?, completionHandler: @escaping (OperationCompletion<Data, AppStoreReceipt.Error>) -> Void) {
+ init(dispatchQueue: DispatchQueue, forceRefresh: Bool, receiptProperties: [String: Any]?, completionHandler: @escaping (Completion) -> Void) {
self.dispatchQueue = dispatchQueue
self.forceRefresh = forceRefresh
self.receiptProperties = receiptProperties
- self.completionHandler = completionHandler
+
+ super.init(completionQueue: .main, completionHandler: completionHandler)
}
override func main() {
@@ -172,15 +171,4 @@ fileprivate class FetchAppStoreReceiptOperation: AsyncOperation, SKRequestDelega
}
}
- private func finish(completion: OperationCompletion<Data, AppStoreReceipt.Error>) {
- let block = completionHandler
- completionHandler = nil
-
- DispatchQueue.main.async {
- block?(completion)
- }
-
- finish()
- }
-
}
diff --git a/ios/MullvadVPN/Operations/ProductsRequestOperation.swift b/ios/MullvadVPN/Operations/ProductsRequestOperation.swift
index 953fc28dab..ea1269c49b 100644
--- a/ios/MullvadVPN/Operations/ProductsRequestOperation.swift
+++ b/ios/MullvadVPN/Operations/ProductsRequestOperation.swift
@@ -9,9 +9,8 @@
import Foundation
import StoreKit
-class ProductsRequestOperation: AsyncOperation, SKProductsRequestDelegate {
+class ProductsRequestOperation: ResultOperation<SKProductsResponse, Error>, SKProductsRequestDelegate {
private let productIdentifiers: Set<String>
- private var completionHandler: ((OperationCompletion<SKProductsResponse, Error>) -> Void)?
private let maxRetryCount = 10
private let retryDelay: DispatchTimeInterval = .seconds(2)
@@ -20,11 +19,10 @@ class ProductsRequestOperation: AsyncOperation, SKProductsRequestDelegate {
private var retryTimer: DispatchSourceTimer?
private var request: SKProductsRequest?
- init(productIdentifiers: Set<String>, completionHandler: @escaping (OperationCompletion<SKProductsResponse, Error>) -> Void) {
+ init(productIdentifiers: Set<String>, completionHandler: @escaping CompletionHandler) {
self.productIdentifiers = productIdentifiers
- self.completionHandler = completionHandler
- super.init()
+ super.init(completionQueue: .main, completionHandler: completionHandler)
}
override func main() {
@@ -65,9 +63,7 @@ class ProductsRequestOperation: AsyncOperation, SKProductsRequestDelegate {
}
func productsRequest(_ request: SKProductsRequest, didReceive response: SKProductsResponse) {
- DispatchQueue.main.async {
- self.finish(completion: .success(response))
- }
+ finish(completion: .success(response))
}
// MARK: - Private
@@ -92,13 +88,4 @@ class ProductsRequestOperation: AsyncOperation, SKProductsRequestDelegate {
retryTimer?.schedule(wallDeadline: .now() + self.retryDelay)
retryTimer?.activate()
}
-
- private func finish(completion: OperationCompletion<SKProductsResponse, Error>) {
- assert(Thread.isMainThread)
-
- completionHandler?(completion)
- completionHandler = nil
-
- finish()
- }
}
diff --git a/ios/MullvadVPN/RelayCache/RelayCacheTracker.swift b/ios/MullvadVPN/RelayCache/RelayCacheTracker.swift
index b5e9d87a44..9495c0adeb 100644
--- a/ios/MullvadVPN/RelayCache/RelayCacheTracker.swift
+++ b/ios/MullvadVPN/RelayCache/RelayCacheTracker.swift
@@ -303,9 +303,8 @@ extension RelayCache.Tracker {
}
}
-fileprivate class UpdateRelaysOperation: AsyncOperation {
+fileprivate class UpdateRelaysOperation: ResultOperation<RelayCache.FetchResult, RelayCache.Error> {
typealias UpdateHandler = (RelayCache.CachedRelays) -> Void
- typealias CompletionHandler = (OperationCompletion<RelayCache.FetchResult, RelayCache.Error>) -> Void
private let dispatchQueue: DispatchQueue
private let restClient: REST.Client
@@ -315,7 +314,6 @@ fileprivate class UpdateRelaysOperation: AsyncOperation {
private let logger = Logger(label: "RelayCacheTracker.UpdateRelaysOperation")
private let updateHandler: UpdateHandler
- private var completionHandler: CompletionHandler?
private var downloadCancellable: Cancellable?
init(dispatchQueue: DispatchQueue,
@@ -329,7 +327,8 @@ fileprivate class UpdateRelaysOperation: AsyncOperation {
self.cacheFileURL = cacheFileURL
self.relayUpdateInterval = relayUpdateInterval
self.updateHandler = updateHandler
- self.completionHandler = completionHandler
+
+ super.init(completionQueue: dispatchQueue, completionHandler: completionHandler)
}
override func main() {
@@ -370,15 +369,6 @@ fileprivate class UpdateRelaysOperation: AsyncOperation {
}
}
- private func finish(completion: OperationCompletion<RelayCache.FetchResult, RelayCache.Error>) {
- let block = completionHandler
- completionHandler = nil
-
- block?(completion)
-
- finish()
- }
-
private func didReceiveNewRelays(etag: String?, relays: REST.ServerRelaysResponse) {
let numRelays = relays.wireguard.relays.count
diff --git a/ios/MullvadVPN/TunnelIPC/TunnelIPCRequestOperation.swift b/ios/MullvadVPN/TunnelIPC/TunnelIPCRequestOperation.swift
index c634b679e6..cb48e414d7 100644
--- a/ios/MullvadVPN/TunnelIPC/TunnelIPCRequestOperation.swift
+++ b/ios/MullvadVPN/TunnelIPC/TunnelIPCRequestOperation.swift
@@ -20,9 +20,8 @@ extension TunnelIPC {
var timeout: TimeInterval = 5
}
- final class RequestOperation<Output>: AsyncOperation {
+ final class RequestOperation<Output>: ResultOperation<Output, TunnelIPC.Error> {
typealias DecoderHandler = (Data?) -> Result<Output, TunnelIPC.Error>
- typealias CompletionHandler = (OperationCompletion<Output, TunnelIPC.Error>) -> Void
private let queue: DispatchQueue
@@ -31,7 +30,6 @@ extension TunnelIPC {
private let options: RequestOptions
private let decoderHandler: DecoderHandler
- private var completionHandler: CompletionHandler?
private var statusObserver: Tunnel.StatusBlockObserver?
private var timeoutWork: DispatchWorkItem?
@@ -53,12 +51,24 @@ extension TunnelIPC {
self.options = options
self.decoderHandler = decoderHandler
- self.completionHandler = completionHandler
+
+ super.init(completionQueue: queue, completionHandler: completionHandler)
}
override func main() {
queue.async {
- self.execute()
+ guard !self.isCancelled else {
+ self.completeOperation(completion: .cancelled)
+ return
+ }
+
+ self.setTimeoutTimer(connectingStateWaitDelay: 0)
+
+ self.statusObserver = self.tunnel.addBlockObserver(queue: self.queue) { [weak self] tunnel, status in
+ self?.handleVPNStatus(status)
+ }
+
+ self.handleVPNStatus(self.tunnel.status)
}
}
@@ -72,21 +82,6 @@ extension TunnelIPC {
}
}
- private func execute() {
- guard !isCancelled else {
- completeOperation(completion: .cancelled)
- return
- }
-
- setTimeoutTimer(connectingStateWaitDelay: 0)
-
- statusObserver = tunnel.addBlockObserver(queue: queue) { [weak self] tunnel, status in
- self?.handleVPNStatus(status)
- }
-
- handleVPNStatus(tunnel.status)
- }
-
private func removeVPNStatusObserver() {
statusObserver?.invalidate()
statusObserver = nil
@@ -211,12 +206,8 @@ extension TunnelIPC {
timeoutWork?.cancel()
waitForConnectingStateWork?.cancel()
- // Call completion handler.
- completionHandler?(completion)
- completionHandler = nil
-
// Finish operation.
- finish()
+ finish(completion: completion)
}
}
}
diff --git a/ios/MullvadVPN/TunnelManager/LoadTunnelOperation.swift b/ios/MullvadVPN/TunnelManager/LoadTunnelOperation.swift
index fc393b7494..83946f02bf 100644
--- a/ios/MullvadVPN/TunnelManager/LoadTunnelOperation.swift
+++ b/ios/MullvadVPN/TunnelManager/LoadTunnelOperation.swift
@@ -9,13 +9,10 @@
import Foundation
import Logging
-class LoadTunnelOperation: AsyncOperation {
- typealias CompletionHandler = (OperationCompletion<(), TunnelManager.Error>) -> Void
-
+class LoadTunnelOperation: ResultOperation<(), TunnelManager.Error> {
private let queue: DispatchQueue
private let accountToken: String?
private let state: TunnelManager.State
- private var completionHandler: CompletionHandler?
private let logger = Logger(label: "TunnelManager.LoadTunnelOperation")
@@ -23,16 +20,14 @@ class LoadTunnelOperation: AsyncOperation {
self.queue = queue
self.state = state
self.accountToken = accountToken
- self.completionHandler = completionHandler
+
+ super.init(completionQueue: queue, completionHandler: completionHandler)
}
override func main() {
queue.async {
self.execute { completion in
- self.completionHandler?(completion)
- self.completionHandler = nil
-
- self.finish()
+ self.finish(completion: completion)
}
}
}
diff --git a/ios/MullvadVPN/TunnelManager/ReloadTunnelOperation.swift b/ios/MullvadVPN/TunnelManager/ReloadTunnelOperation.swift
index 090a29f59f..48308b7e77 100644
--- a/ios/MullvadVPN/TunnelManager/ReloadTunnelOperation.swift
+++ b/ios/MullvadVPN/TunnelManager/ReloadTunnelOperation.swift
@@ -8,39 +8,37 @@
import Foundation
-class ReloadTunnelOperation: AsyncOperation {
- typealias CompletionHandler = (OperationCompletion<(), TunnelManager.Error>) -> Void
-
+class ReloadTunnelOperation: ResultOperation<(), TunnelManager.Error> {
private let queue: DispatchQueue
private let state: TunnelManager.State
- private var request: Cancellable?
- private var completionHandler: CompletionHandler?
+ private var cancellableTask: Cancellable?
init(queue: DispatchQueue, state: TunnelManager.State, completionHandler: @escaping CompletionHandler) {
self.queue = queue
self.state = state
- self.completionHandler = completionHandler
+
+ super.init(completionQueue: queue, completionHandler: completionHandler)
}
override func main() {
queue.async {
guard !self.isCancelled else {
- self.completeOperation(completion: .cancelled)
+ self.finish(completion: .cancelled)
return
}
guard let tunnel = self.state.tunnel else {
- self.completeOperation(completion: .failure(.unsetAccount))
+ self.finish(completion: .failure(.unsetAccount))
return
}
let session = TunnelIPC.Session(tunnel: tunnel)
- self.request = session.reloadTunnelSettings { [weak self] completion in
+ self.cancellableTask = session.reloadTunnelSettings { [weak self] completion in
guard let self = self else { return }
self.queue.async {
- self.completeOperation(completion: completion.mapError { .reloadTunnel($0) })
+ self.finish(completion: completion.mapError { .reloadTunnel($0) })
}
}
}
@@ -50,15 +48,8 @@ class ReloadTunnelOperation: AsyncOperation {
super.cancel()
queue.async {
- self.request?.cancel()
+ self.cancellableTask?.cancel()
+ self.cancellableTask = nil
}
}
-
- private func completeOperation(completion: OperationCompletion<(), TunnelManager.Error>) {
- completionHandler?(completion)
- completionHandler = nil
-
- finish()
- }
-
}
diff --git a/ios/MullvadVPN/TunnelManager/ReplaceKeyOperation.swift b/ios/MullvadVPN/TunnelManager/ReplaceKeyOperation.swift
index 7d610c5e6f..ff4849e741 100644
--- a/ios/MullvadVPN/TunnelManager/ReplaceKeyOperation.swift
+++ b/ios/MullvadVPN/TunnelManager/ReplaceKeyOperation.swift
@@ -9,9 +9,7 @@
import Foundation
import Logging
-class ReplaceKeyOperation: AsyncOperation {
- typealias CompletionHandler = (OperationCompletion<TunnelManager.KeyRotationResult, TunnelManager.Error>) -> Void
-
+class ReplaceKeyOperation: ResultOperation<TunnelManager.KeyRotationResult, TunnelManager.Error> {
private let queue: DispatchQueue
private let state: TunnelManager.State
@@ -77,16 +75,13 @@ class ReplaceKeyOperation: AsyncOperation {
self.restClient = restClient
self.rotationInterval = rotationInterval
- self.completionHandler = completionHandler
+ super.init(completionQueue: queue, completionHandler: completionHandler)
}
override func main() {
queue.async {
self.execute { completion in
- self.completionHandler?(completion)
- self.completionHandler = nil
-
- self.finish()
+ self.finish(completion: completion)
}
}
}
diff --git a/ios/MullvadVPN/TunnelManager/SetAccountOperation.swift b/ios/MullvadVPN/TunnelManager/SetAccountOperation.swift
index 90b7cd3779..228bdee460 100644
--- a/ios/MullvadVPN/TunnelManager/SetAccountOperation.swift
+++ b/ios/MullvadVPN/TunnelManager/SetAccountOperation.swift
@@ -10,9 +10,8 @@ import Foundation
import class WireGuardKitTypes.PublicKey
import Logging
-class SetAccountOperation: AsyncOperation {
+class SetAccountOperation: ResultOperation<(), TunnelManager.Error> {
typealias WillDeleteVPNConfigurationHandler = () -> Void
- typealias CompletionHandler = (OperationCompletion<(), TunnelManager.Error>) -> Void
private let queue: DispatchQueue
private let state: TunnelManager.State
@@ -20,8 +19,6 @@ class SetAccountOperation: AsyncOperation {
private let accountToken: String?
private var willDeleteVPNConfigurationHandler: WillDeleteVPNConfigurationHandler?
- private var completionHandler: CompletionHandler?
-
private let logger = Logger(label: "TunnelManager.SetAccountOperation")
init(queue: DispatchQueue, state: TunnelManager.State, restClient: REST.Client, accountToken: String?, willDeleteVPNConfigurationHandler: @escaping WillDeleteVPNConfigurationHandler, completionHandler: @escaping CompletionHandler) {
@@ -30,16 +27,14 @@ class SetAccountOperation: AsyncOperation {
self.restClient = restClient
self.accountToken = accountToken
self.willDeleteVPNConfigurationHandler = willDeleteVPNConfigurationHandler
- self.completionHandler = completionHandler
+
+ super.init(completionQueue: queue, completionHandler: completionHandler)
}
override func main() {
queue.async {
self.execute { completion in
- self.completionHandler?(completion)
- self.completionHandler = nil
-
- self.finish()
+ self.finish(completion: completion)
}
}
}
diff --git a/ios/MullvadVPN/TunnelManager/SetTunnelSettingsOperation.swift b/ios/MullvadVPN/TunnelManager/SetTunnelSettingsOperation.swift
index 86e6c1a4ff..e818474f60 100644
--- a/ios/MullvadVPN/TunnelManager/SetTunnelSettingsOperation.swift
+++ b/ios/MullvadVPN/TunnelManager/SetTunnelSettingsOperation.swift
@@ -8,57 +8,45 @@
import Foundation
-class SetTunnelSettingsOperation: AsyncOperation {
+class SetTunnelSettingsOperation: ResultOperation<(), TunnelManager.Error> {
typealias ModificationHandler = (inout TunnelSettings) -> Void
- typealias CompletionHandler = (OperationCompletion<(), TunnelManager.Error>) -> Void
private let queue: DispatchQueue
private let state: TunnelManager.State
private let modificationBlock: ModificationHandler
- private var completionHandler: CompletionHandler?
init(queue: DispatchQueue, state: TunnelManager.State, modificationBlock: @escaping ModificationHandler, completionHandler: @escaping CompletionHandler) {
self.queue = queue
self.state = state
self.modificationBlock = modificationBlock
- self.completionHandler = completionHandler
+
+ super.init(completionQueue: queue, completionHandler: completionHandler)
}
override func main() {
queue.async {
- self.execute { completion in
- self.completionHandler?(completion)
- self.completionHandler = nil
-
- self.finish()
+ guard !self.isCancelled else {
+ self.finish(completion: .cancelled)
+ return
}
- }
- }
- private func execute(completionHandler: CompletionHandler) {
- guard !isCancelled else {
- completionHandler(.cancelled)
- return
- }
-
- guard let accountToken = state.tunnelInfo?.token else {
- completionHandler(.failure(.unsetAccount))
- return
- }
-
- let result = TunnelSettingsManager.update(searchTerm: .accountToken(accountToken)) { tunnelSettings in
- self.modificationBlock(&tunnelSettings)
- }
-
- switch result {
- case .success(let newTunnelSettings):
- state.tunnelInfo?.tunnelSettings = newTunnelSettings
+ guard let accountToken = self.state.tunnelInfo?.token else {
+ self.finish(completion: .failure(.unsetAccount))
+ return
+ }
- completionHandler(.success(()))
+ let result = TunnelSettingsManager.update(searchTerm: .accountToken(accountToken)) { tunnelSettings in
+ self.modificationBlock(&tunnelSettings)
+ }
- case .failure(let error):
- completionHandler(.failure(.updateTunnelSettings(error)))
+ switch result {
+ case .success(let newTunnelSettings):
+ self.state.tunnelInfo?.tunnelSettings = newTunnelSettings
+ self.finish(completion: .success(()))
+ case .failure(let error):
+ self.finish(completion: .failure(.updateTunnelSettings(error)))
+ }
}
}
}
diff --git a/ios/MullvadVPN/TunnelManager/StartTunnelOperation.swift b/ios/MullvadVPN/TunnelManager/StartTunnelOperation.swift
index ac8223f963..43bcb9241b 100644
--- a/ios/MullvadVPN/TunnelManager/StartTunnelOperation.swift
+++ b/ios/MullvadVPN/TunnelManager/StartTunnelOperation.swift
@@ -9,82 +9,71 @@
import Foundation
import NetworkExtension
-class StartTunnelOperation: AsyncOperation {
+class StartTunnelOperation: ResultOperation<(), TunnelManager.Error> {
typealias EncodeErrorHandler = (Error) -> Void
- typealias CompletionHandler = (OperationCompletion<(), TunnelManager.Error>) -> Void
private let queue: DispatchQueue
private let state: TunnelManager.State
private var encodeErrorHandler: EncodeErrorHandler?
- private var completionHandler: CompletionHandler?
init(queue: DispatchQueue, state: TunnelManager.State, encodeErrorHandler: @escaping EncodeErrorHandler, completionHandler: @escaping CompletionHandler) {
self.queue = queue
self.state = state
self.encodeErrorHandler = encodeErrorHandler
- self.completionHandler = completionHandler
+
+ super.init(completionQueue: queue, completionHandler: completionHandler)
}
override func main() {
queue.async {
- self.execute { completion in
- self.completionHandler?(completion)
- self.completionHandler = nil
-
- self.finish()
+ guard !self.isCancelled else {
+ self.finish(completion: .cancelled)
+ return
}
- }
- }
-
- private func execute(completionHandler: @escaping CompletionHandler) {
- guard !self.isCancelled else {
- completionHandler(.cancelled)
- return
- }
- guard let tunnelInfo = self.state.tunnelInfo else {
- completionHandler(.failure(.unsetAccount))
- return
- }
+ guard let tunnelInfo = self.state.tunnelInfo else {
+ self.finish(completion: .failure(.unsetAccount))
+ return
+ }
- switch self.state.tunnelStatus.state {
- case .disconnecting(.nothing):
- self.state.tunnelStatus.state = .disconnecting(.reconnect)
+ switch self.state.tunnelStatus.state {
+ case .disconnecting(.nothing):
+ self.state.tunnelStatus.state = .disconnecting(.reconnect)
- completionHandler(.success(()))
+ self.finish(completion: .success(()))
- case .disconnected, .pendingReconnect:
- RelayCache.Tracker.shared.read { readResult in
- self.queue.async {
- switch readResult {
- case .success(let cachedRelays):
- self.didReceiveRelays(
- tunnelInfo: tunnelInfo,
- cachedRelays: cachedRelays,
- completionHandler: completionHandler
- )
+ case .disconnected, .pendingReconnect:
+ RelayCache.Tracker.shared.read { readResult in
+ self.queue.async {
+ switch readResult {
+ case .success(let cachedRelays):
+ self.didReceiveRelays(
+ tunnelInfo: tunnelInfo,
+ cachedRelays: cachedRelays
+ )
- case .failure(let error):
- completionHandler(.failure(.readRelays(error)))
+ case .failure(let error):
+ self.finish(completion: .failure(.readRelays(error)))
+ }
}
}
- }
- default:
- // Do not attempt to start the tunnel in all other cases.
- completionHandler(.success(()))
+ default:
+ // Do not attempt to start the tunnel in all other cases.
+ self.finish(completion: .success(()))
+ }
}
}
- private func didReceiveRelays(tunnelInfo: TunnelInfo, cachedRelays: RelayCache.CachedRelays, completionHandler: @escaping (OperationCompletion<(), TunnelManager.Error>) -> Void) {
+ private func didReceiveRelays(tunnelInfo: TunnelInfo, cachedRelays: RelayCache.CachedRelays) {
let selectorResult = RelaySelector.evaluate(
relays: cachedRelays.relays,
constraints: tunnelInfo.tunnelSettings.relayConstraints
)
guard let selectorResult = selectorResult else {
- completionHandler(.failure(.cannotSatisfyRelayConstraints))
+ finish(completion: .failure(.cannotSatisfyRelayConstraints))
return
}
@@ -94,10 +83,10 @@ class StartTunnelOperation: AsyncOperation {
case .success(let tunnelProvider):
let startTunnelResult = Result { try self.startTunnel(tunnelProvider: tunnelProvider, selectorResult: selectorResult) }
- completionHandler(OperationCompletion(result: startTunnelResult.mapError { .startVPNTunnel($0) }))
+ self.finish(completion: OperationCompletion(result: startTunnelResult.mapError { .startVPNTunnel($0) }))
case .failure(let error):
- completionHandler(.failure(error))
+ self.finish(completion: .failure(error))
}
}
}
diff --git a/ios/MullvadVPN/TunnelManager/StopTunnelOperation.swift b/ios/MullvadVPN/TunnelManager/StopTunnelOperation.swift
index 377d946399..39b6833716 100644
--- a/ios/MullvadVPN/TunnelManager/StopTunnelOperation.swift
+++ b/ios/MullvadVPN/TunnelManager/StopTunnelOperation.swift
@@ -8,64 +8,53 @@
import Foundation
-class StopTunnelOperation: AsyncOperation {
- typealias CompletionHandler = (OperationCompletion<(), TunnelManager.Error>) -> Void
-
+class StopTunnelOperation: ResultOperation<(), TunnelManager.Error> {
private let queue: DispatchQueue
private let state: TunnelManager.State
- private var completionHandler: CompletionHandler?
init(queue: DispatchQueue, state: TunnelManager.State, completionHandler: @escaping CompletionHandler) {
self.queue = queue
self.state = state
- self.completionHandler = completionHandler
+
+ super.init(completionQueue: queue, completionHandler: completionHandler)
}
override func main() {
queue.async {
- self.execute { completion in
- self.completionHandler?(completion)
- self.completionHandler = nil
-
- self.finish()
+ guard !self.isCancelled else {
+ self.finish(completion: .cancelled)
+ return
}
- }
- }
- private func execute(completionHandler: @escaping CompletionHandler) {
- guard !isCancelled else {
- completionHandler(.cancelled)
- return
- }
-
- guard let tunnel = state.tunnel else {
- completionHandler(.failure(.unsetAccount))
- return
- }
+ guard let tunnel = self.state.tunnel else {
+ self.finish(completion: .failure(.unsetAccount))
+ return
+ }
- switch self.state.tunnelStatus.state {
- case .disconnecting(.reconnect):
- state.tunnelStatus.state = .disconnecting(.nothing)
+ switch self.state.tunnelStatus.state {
+ case .disconnecting(.reconnect):
+ self.state.tunnelStatus.state = .disconnecting(.nothing)
- completionHandler(.success(()))
+ self.finish(completion: .success(()))
- case .connected, .connecting, .reconnecting:
- // Disable on-demand when stopping the tunnel to prevent it from coming back up
- tunnel.isOnDemandEnabled = false
+ case .connected, .connecting, .reconnecting:
+ // Disable on-demand when stopping the tunnel to prevent it from coming back up
+ tunnel.isOnDemandEnabled = false
- tunnel.saveToPreferences { error in
- self.queue.async {
- if let error = error {
- completionHandler(.failure(.saveVPNConfiguration(error)))
- } else {
- tunnel.stop()
- completionHandler(.success(()))
+ tunnel.saveToPreferences { error in
+ self.queue.async {
+ if let error = error {
+ self.finish(completion: .failure(.saveVPNConfiguration(error)))
+ } else {
+ tunnel.stop()
+ self.finish(completion: .success(()))
+ }
}
}
- }
- default:
- completionHandler(.success(()))
+ default:
+ self.finish(completion: .success(()))
+ }
}
}
}