summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorAndrej Mihajlov <and@mullvad.net>2023-02-28 16:29:44 +0100
committerAndrej Mihajlov <and@mullvad.net>2023-03-03 12:01:30 +0100
commit5699b74692c162604186b0c70724e124cc68eae7 (patch)
treea3077cf2bf7ac78a3a4fa8edd5c0388a91f1c1bb
parent639e2da07be3be0a638379beb6cfd399ddb0c176 (diff)
downloadmullvadvpn-5699b74692c162604186b0c70724e124cc68eae7.tar.xz
mullvadvpn-5699b74692c162604186b0c70724e124cc68eae7.zip
Serialize calls to reconnect tunnel
-rw-r--r--ios/PacketTunnel/PacketTunnelProvider.swift40
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 {