diff options
| -rw-r--r-- | ios/MullvadVPN/SimulatorTunnelProvider.swift | 2 | ||||
| -rw-r--r-- | ios/MullvadVPN/SimulatorTunnelProviderHost.swift | 139 |
2 files changed, 61 insertions, 80 deletions
diff --git a/ios/MullvadVPN/SimulatorTunnelProvider.swift b/ios/MullvadVPN/SimulatorTunnelProvider.swift index 3ee852299f..9e5ba30fdf 100644 --- a/ios/MullvadVPN/SimulatorTunnelProvider.swift +++ b/ios/MullvadVPN/SimulatorTunnelProvider.swift @@ -116,7 +116,7 @@ class SimulatorTunnelProviderDelegate { } } - func startTunnel(options: [String: Any]?, completionHandler: @escaping (Error?) -> Void) { + func startTunnel(options: [String: NSObject]?, completionHandler: @escaping (Error?) -> Void) { completionHandler(nil) } diff --git a/ios/MullvadVPN/SimulatorTunnelProviderHost.swift b/ios/MullvadVPN/SimulatorTunnelProviderHost.swift index 37ac1f38f3..2aa95403f7 100644 --- a/ios/MullvadVPN/SimulatorTunnelProviderHost.swift +++ b/ios/MullvadVPN/SimulatorTunnelProviderHost.swift @@ -15,26 +15,34 @@ import Logging class SimulatorTunnelProviderHost: SimulatorTunnelProviderDelegate { - private enum ExclusivityCategory { - case exclusive - } - private var connectionInfo: TunnelConnectionInfo? - private let logger = Logger(label: "SimulatorTunnelProviderHost") + private let providerLogger = Logger(label: "SimulatorTunnelProviderHost") + private let stateQueue = DispatchQueue(label: "SimulatorTunnelProviderHostQueue") - private let operationQueue = OperationQueue() - private lazy var exclusivityController = ExclusivityController<ExclusivityCategory>(operationQueue: operationQueue) + override func startTunnel(options: [String: NSObject]?, completionHandler: @escaping (Error?) -> Void) { + stateQueue.async { + let tunnelOptions = PacketTunnelOptions(rawOptions: options ?? [:]) + let appSelectorResult = Result { try tunnelOptions.getSelectorResult() } + + if let error = appSelectorResult.error { + self.providerLogger.error( + chainedError: AnyChainedError(error), + message: "Failed to decode relay selector result passed from the app. Will continue by picking new relay." + ) + } + + if let appSelectorResult = appSelectorResult.flattenValue { + self.connectionInfo = appSelectorResult.tunnelConnectionInfo + } else { + self.connectionInfo = self.pickRelay()?.tunnelConnectionInfo + } - override func startTunnel(options: [String: Any]?, completionHandler: @escaping (Error?) -> Void) { - let startOperation = makeStartOperation() - startOperation.addDidFinishBlockObserver(queue: .main) { _ in completionHandler(nil) } - exclusivityController.addOperation(startOperation, categories: [.exclusive]) } override func stopTunnel(with reason: NEProviderStopReason, completionHandler: @escaping () -> Void) { - DispatchQueue.main.async { + stateQueue.async { self.connectionInfo = nil completionHandler() @@ -42,85 +50,58 @@ class SimulatorTunnelProviderHost: SimulatorTunnelProviderDelegate { } override func handleAppMessage(_ messageData: Data, completionHandler: ((Data?) -> Void)?) { - DispatchQueue.main.async { - let result = PacketTunnelIpcHandler.decodeRequest(messageData: messageData) - switch result { - case .success(let request): + Result { try TunnelIPC.Coding.decodeRequest(messageData) } + .asPromise() + .receive(on: stateQueue) + .onFailure { error in + self.providerLogger.error(chainedError: AnyChainedError(error), message: "Failed to decode the IPC request.") + } + .success() + .mapThen(defaultValue: nil) { request in switch request { - case .reloadTunnelSettings: - let operationObserver = OperationBlockObserver<AsyncBlockOperation>( - queue: .main, - willExecute: { _ in - self.reasserting = true - }, - willFinish: { _ in - self.reasserting = false - }, - didFinish: { _ in - self.replyAppMessage(true, completionHandler: completionHandler) - }) + case .tunnelConnectionInfo: + return Result { try TunnelIPC.Coding.encodeResponse(self.connectionInfo) } + .asPromise() + .onFailure { error in + self.providerLogger.error(chainedError: AnyChainedError(error), message: "Failed to encode tunnel connection info IPC response.") + } + .success() - let startOperation = self.makeStartOperation() - startOperation.addObserver(operationObserver) - self.exclusivityController.addOperation(startOperation, categories: [.exclusive]) + case .reloadTunnelSettings: + self.reasserting = true + self.connectionInfo = self.pickRelay()?.tunnelConnectionInfo + self.reasserting = false - case .tunnelInformation: - self.replyAppMessage(self.connectionInfo, completionHandler: completionHandler) + return .resolved(nil) } - - case .failure: - completionHandler?(nil) } - } + .observe { completion in + completionHandler?(completion.unwrappedValue ?? nil) + } } - private func replyAppMessage<T: Codable>(_ response: T, completionHandler: ((Data?) -> Void)?) { - switch PacketTunnelIpcHandler.encodeResponse(response: response) { - case .success(let data): - completionHandler?(data) + private func pickRelay() -> RelaySelectorResult? { + guard let result = RelayCache.Tracker.shared.read().await().unwrappedValue else { return nil } - case .failure(let error): - self.logger.error(chainedError: error) - completionHandler?(nil) - } - } + switch result { + case .success(let cachedRelays): + let keychainReference = self.protocolConfiguration.passwordReference! - private func makeStartOperation() -> AsyncBlockOperation { - return AsyncBlockOperation { [weak self] (finish) in - guard let self = self else { - finish() - return - } + switch TunnelSettingsManager.load(searchTerm: .persistentReference(keychainReference)) { + case .success(let entry): + return RelaySelector.evaluate( + relays: cachedRelays.relays, + constraints: entry.tunnelSettings.relayConstraints + ) + case .failure(let error): + self.providerLogger.error(chainedError: error, message: "Failed to load tunnel settings when picking relay") - self.pickRelay { (selectorResult) in - DispatchQueue.main.async { - self.connectionInfo = selectorResult?.tunnelConnectionInfo - finish() - } + return nil } - } - } - - private func pickRelay(completion: @escaping (RelaySelectorResult?) -> Void) { - RelayCache.shared.read { (result) in - switch result { - case .success(let cachedRelays): - let keychainReference = self.protocolConfiguration.passwordReference! - switch TunnelSettingsManager.load(searchTerm: .persistentReference(keychainReference)) { - case .success(let entry): - let relayConstraints = entry.tunnelSettings.relayConstraints - let relaySelector = RelaySelector(relays: cachedRelays.relays) - let selectorResult = relaySelector.evaluate(with: relayConstraints) - completion(selectorResult) - case .failure(let error): - self.logger.error(chainedError: error) - completion(nil) - } - case .failure(let error): - self.logger.error(chainedError: error) - completion(nil) - } + case .failure(let error): + self.providerLogger.error(chainedError: error, message: "Failed to read relays when picking relay") + return nil } } |
