summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorAndrej Mihajlov <and@mullvad.net>2023-03-08 09:07:28 +0100
committerAndrej Mihajlov <and@mullvad.net>2023-03-08 09:07:28 +0100
commit94d6c46ee738637f7ff8a9385bb7b476481f89d3 (patch)
treeba2041dd079f8f00c43e70635a1f8ba576bffd4f
parentee456a021353bd08b31861e31698065c8a509312 (diff)
parentfe143949cbb6ec4d04571990ac63d6dc6ab17884 (diff)
downloadmullvadvpn-94d6c46ee738637f7ff8a9385bb7b476481f89d3.tar.xz
mullvadvpn-94d6c46ee738637f7ff8a9385bb7b476481f89d3.zip
Merge branch 'tunnel-wrap-start-stop-in-queue'
-rw-r--r--ios/PacketTunnel/PacketTunnelProvider.swift160
1 files changed, 81 insertions, 79 deletions
diff --git a/ios/PacketTunnel/PacketTunnelProvider.swift b/ios/PacketTunnel/PacketTunnelProvider.swift
index c388b1519d..b33b013fe6 100644
--- a/ios/PacketTunnel/PacketTunnelProvider.swift
+++ b/ios/PacketTunnel/PacketTunnelProvider.swift
@@ -172,86 +172,84 @@ class PacketTunnelProvider: NEPacketTunnelProvider, TunnelMonitorDelegate {
options: [String: NSObject]?,
completionHandler: @escaping (Error?) -> Void
) {
- let tunnelOptions = PacketTunnelOptions(rawOptions: options ?? [:])
- var appSelectorResult: RelaySelectorResult?
+ dispatchQueue.async {
+ let tunnelOptions = PacketTunnelOptions(rawOptions: options ?? [:])
+ var appSelectorResult: RelaySelectorResult?
- // Parse relay selector from tunnel options.
- do {
- appSelectorResult = try tunnelOptions.getSelectorResult()
+ // Parse relay selector from tunnel options.
+ do {
+ appSelectorResult = try tunnelOptions.getSelectorResult()
- switch appSelectorResult {
- case let .some(selectorResult):
- providerLogger.debug(
- "Start the tunnel via app, connect to \(selectorResult.relay.hostname)."
- )
+ switch appSelectorResult {
+ case let .some(selectorResult):
+ self.providerLogger.debug(
+ "Start the tunnel via app, connect to \(selectorResult.relay.hostname)."
+ )
- case .none:
- if tunnelOptions.isOnDemand() {
- providerLogger.debug("Start the tunnel via on-demand rule.")
- } else {
- providerLogger.debug("Start the tunnel via system.")
+ case .none:
+ if tunnelOptions.isOnDemand() {
+ self.providerLogger.debug("Start the tunnel via on-demand rule.")
+ } else {
+ self.providerLogger.debug("Start the tunnel via system.")
+ }
}
+ } catch {
+ self.providerLogger.debug("Start the tunnel via app.")
+ self.providerLogger.error(
+ error: error,
+ message: """
+ Failed to decode relay selector result passed from the app. \
+ Will continue by picking new relay.
+ """
+ )
}
- } catch {
- providerLogger.debug("Start the tunnel via app.")
- providerLogger.error(
- error: error,
- message: """
- Failed to decode relay selector result passed from the app. \
- Will continue by picking new relay.
- """
- )
- }
- // Read tunnel configuration.
- let tunnelConfiguration: PacketTunnelConfiguration
- do {
- let initialRelay: NextRelay = appSelectorResult.map { .set($0) } ?? .automatic
+ // Read tunnel configuration.
+ let tunnelConfiguration: PacketTunnelConfiguration
+ do {
+ let initialRelay: NextRelay = appSelectorResult.map { .set($0) } ?? .automatic
- tunnelConfiguration = try makeConfiguration(initialRelay)
- } catch {
- providerLogger.error(
- error: error,
- message: "Failed to read tunnel configuration when starting the tunnel."
- )
+ tunnelConfiguration = try self.makeConfiguration(initialRelay)
+ } catch {
+ self.providerLogger.error(
+ error: error,
+ message: "Failed to read tunnel configuration when starting the tunnel."
+ )
- configurationError = error
+ self.configurationError = error
- startEmptyTunnel(completionHandler: completionHandler)
- dispatchQueue.async {
+ self.startEmptyTunnel(completionHandler: completionHandler)
self.beginTunnelStartupFailureRecovery()
+ return
}
- return
- }
- // Set tunnel status.
- dispatchQueue.async {
+ // Set tunnel status.
let selectorResult = tunnelConfiguration.selectorResult
self.selectorResult = selectorResult
self.providerLogger.debug("Set tunnel relay to \(selectorResult.relay.hostname).")
- }
- // Start tunnel.
- adapter.start(tunnelConfiguration: tunnelConfiguration.wgTunnelConfig) { error in
- self.dispatchQueue.async {
- if let error = error {
- self.providerLogger.error(
- error: error,
- message: "Failed to start the tunnel."
- )
+ // Start tunnel.
+ self.adapter.start(tunnelConfiguration: tunnelConfiguration.wgTunnelConfig) { error in
+ self.dispatchQueue.async {
+ if let error = error {
+ self.providerLogger.error(
+ error: error,
+ message: "Failed to start the tunnel."
+ )
- completionHandler(error)
- } else {
- self.providerLogger.debug("Started the tunnel.")
+ completionHandler(error)
+ } else {
+ self.providerLogger.debug("Started the tunnel.")
- self.startTunnelCompletionHandler = { [weak self] in
- self?.isConnected = true
- completionHandler(nil)
- }
+ self.startTunnelCompletionHandler = { [weak self] in
+ self?.isConnected = true
+ completionHandler(nil)
+ }
- self.tunnelMonitor.start(
- probeAddress: tunnelConfiguration.selectorResult.endpoint.ipv4Gateway
- )
+ self.tunnelMonitor.start(
+ probeAddress: tunnelConfiguration.selectorResult.endpoint.ipv4Gateway
+ )
+ }
}
}
}
@@ -261,32 +259,32 @@ class PacketTunnelProvider: NEPacketTunnelProvider, TunnelMonitorDelegate {
with reason: NEProviderStopReason,
completionHandler: @escaping () -> Void
) {
- providerLogger.debug("Stop the tunnel: \(reason)")
-
dispatchQueue.async {
+ self.providerLogger.debug("Stop the tunnel: \(reason)")
+
self.isStopping = true
self.cancelTunnelStartupFailureRecovery()
self.startTunnelCompletionHandler = nil
- }
- // Cancel all operations: reconnection requests, network requests.
- operationQueue.cancelAllOperations()
+ // Cancel all operations: reconnection requests, network requests.
+ self.operationQueue.cancelAllOperations()
- // Stop tunnel monitor after all operations are kicked off the queue.
- operationQueue.addBarrierBlock {
- self.tunnelMonitor.stop()
+ // Stop tunnel monitor after all operations are kicked off the queue.
+ self.operationQueue.addBarrierBlock {
+ self.tunnelMonitor.stop()
- self.adapter.stop { error in
- self.dispatchQueue.async {
- if let error = error {
- self.providerLogger.error(
- error: error,
- message: "Failed to stop the tunnel gracefully."
- )
- } else {
- self.providerLogger.debug("Stopped the tunnel.")
+ self.adapter.stop { error in
+ self.dispatchQueue.async {
+ if let error = error {
+ self.providerLogger.error(
+ error: error,
+ message: "Failed to stop the tunnel gracefully."
+ )
+ } else {
+ self.providerLogger.debug("Stopped the tunnel.")
+ }
+ completionHandler()
}
- completionHandler()
}
}
}
@@ -403,6 +401,8 @@ class PacketTunnelProvider: NEPacketTunnelProvider, TunnelMonitorDelegate {
_ tunnelMonitor: TunnelMonitor,
networkReachabilityStatusDidChange isNetworkReachable: Bool
) {
+ dispatchPrecondition(condition: .onQueue(dispatchQueue))
+
guard self.isNetworkReachable != isNetworkReachable else { return }
self.isNetworkReachable = isNetworkReachable
@@ -451,6 +451,8 @@ class PacketTunnelProvider: NEPacketTunnelProvider, TunnelMonitorDelegate {
}
private func startEmptyTunnel(completionHandler: @escaping (Error?) -> Void) {
+ dispatchPrecondition(condition: .onQueue(dispatchQueue))
+
let emptyTunnelConfiguration = TunnelConfiguration(
name: nil,
interface: InterfaceConfiguration(privateKey: PrivateKey()),