diff options
| author | Andrej Mihajlov <and@mullvad.net> | 2023-02-28 16:29:44 +0100 |
|---|---|---|
| committer | Andrej Mihajlov <and@mullvad.net> | 2023-03-03 12:01:30 +0100 |
| commit | 5699b74692c162604186b0c70724e124cc68eae7 (patch) | |
| tree | a3077cf2bf7ac78a3a4fa8edd5c0388a91f1c1bb | |
| parent | 639e2da07be3be0a638379beb6cfd399ddb0c176 (diff) | |
| download | mullvadvpn-5699b74692c162604186b0c70724e124cc68eae7.tar.xz mullvadvpn-5699b74692c162604186b0c70724e124cc68eae7.zip | |
Serialize calls to reconnect tunnel
| -rw-r--r-- | ios/PacketTunnel/PacketTunnelProvider.swift | 40 |
1 files changed, 36 insertions, 4 deletions
diff --git a/ios/PacketTunnel/PacketTunnelProvider.swift b/ios/PacketTunnel/PacketTunnelProvider.swift index 8b59185b90..0bd3acef6a 100644 --- a/ios/PacketTunnel/PacketTunnelProvider.swift +++ b/ios/PacketTunnel/PacketTunnelProvider.swift @@ -83,6 +83,9 @@ class PacketTunnelProvider: NEPacketTunnelProvider, TunnelMonitorDelegate { /// Last device check task. private var checkDeviceStateTask: Cancellable? + /// Last task to reconnect the tunnel. + private var reconnectTunnelTask: Operation? + /// Internal operation queue. private let operationQueue = AsyncOperationQueue() @@ -207,7 +210,9 @@ class PacketTunnelProvider: NEPacketTunnelProvider, TunnelMonitorDelegate { configurationError = error startEmptyTunnel(completionHandler: completionHandler) - beginTunnelStartupFailureRecovery() + dispatchQueue.async { + self.beginTunnelStartupFailureRecovery() + } return } @@ -252,12 +257,12 @@ class PacketTunnelProvider: NEPacketTunnelProvider, TunnelMonitorDelegate { dispatchQueue.async { self.cancelTunnelStartupFailureRecovery() - self.tunnelMonitor.stop() - self.checkDeviceStateTask?.cancel() - self.checkDeviceStateTask = nil self.startTunnelCompletionHandler = nil } + tunnelMonitor.stop() + operationQueue.cancelAllOperations() + adapter.stop { error in self.dispatchQueue.async { if let error = error { @@ -402,6 +407,8 @@ class PacketTunnelProvider: NEPacketTunnelProvider, TunnelMonitorDelegate { // MARK: - Private private func beginTunnelStartupFailureRecovery() { + dispatchPrecondition(condition: .onQueue(dispatchQueue)) + let timer = DispatchSource.makeTimerSource(queue: dispatchQueue) timer.setEventHandler { [weak self] in guard let self = self else { return } @@ -425,6 +432,8 @@ class PacketTunnelProvider: NEPacketTunnelProvider, TunnelMonitorDelegate { } private func cancelTunnelStartupFailureRecovery() { + dispatchPrecondition(condition: .onQueue(dispatchQueue)) + tunnelStartupFailureRecoveryTimer?.cancel() tunnelStartupFailureRecoveryTimer = nil } @@ -495,6 +504,29 @@ class PacketTunnelProvider: NEPacketTunnelProvider, TunnelMonitorDelegate { ) { dispatchPrecondition(condition: .onQueue(dispatchQueue)) + let blockOperation = AsyncBlockOperation(dispatchQueue: dispatchQueue) { operation in + self.reconnectTunnelInner(to: nextRelay) { error in + completionHandler?(error) + operation.finish() + } + } + + if let reconnectTunnelTask = reconnectTunnelTask { + blockOperation.addDependency(reconnectTunnelTask) + } + + reconnectTunnelTask?.cancel() + reconnectTunnelTask = blockOperation + + operationQueue.addOperation(blockOperation) + } + + private func reconnectTunnelInner( + to nextRelay: NextRelay, + completionHandler: ((Error?) -> Void)? = nil + ) { + dispatchPrecondition(condition: .onQueue(dispatchQueue)) + // Read tunnel configuration. let tunnelConfiguration: PacketTunnelConfiguration do { |
