diff --git a/EduVPN-redesign/Controllers/PreferencesViewController.swift b/EduVPN-redesign/Controllers/PreferencesViewController.swift
index 09ebeb21..a551c9ee 100644
--- a/EduVPN-redesign/Controllers/PreferencesViewController.swift
+++ b/EduVPN-redesign/Controllers/PreferencesViewController.swift
@@ -32,6 +32,7 @@ class PreferencesViewController: ViewController, ParametrizedViewController {
@IBOutlet weak var showInStatusBarCheckbox: NSButton!
@IBOutlet weak var showInDockCheckbox: NSButton!
@IBOutlet weak var launchAtLoginCheckbox: NSButton!
+ @IBOutlet weak var assistPathUpgradingCheckbox: NSButton!
func initializeParameters(_ parameters: Parameters) {
guard self.parameters == nil else {
@@ -46,11 +47,13 @@ class PreferencesViewController: ViewController, ParametrizedViewController {
let isShowInStatusBarEnabled = userDefaults.showInStatusBar
let isShowInDockEnabled = userDefaults.showInDock
let isLaunchAtLoginEnabled = userDefaults.launchAtLogin
+ let isAssistPathUpgradingEnabled = userDefaults.assistPathUpgradingWithPathMonitor
useTCPOnlyCheckbox.state = isForceTCPEnabled ? .on : .off
showInStatusBarCheckbox.state = isShowInStatusBarEnabled ? .on : .off
showInDockCheckbox.state = isShowInDockEnabled ? .on : .off
launchAtLoginCheckbox.state = isLaunchAtLoginEnabled ? .on : .off
+ assistPathUpgradingCheckbox.state = isAssistPathUpgradingEnabled ? .on : .off
// If one of "Show in status bar" or "Show in Dock" is off,
// disable editing the other
@@ -67,6 +70,11 @@ class PreferencesViewController: ViewController, ParametrizedViewController {
UserDefaults.standard.forceTCP = isUseTCPOnlyChecked
}
+ @IBAction func assistPathUpgradingCheckboxClicked(_ sender: Any) {
+ let isChecked = (assistPathUpgradingCheckbox.state == .on)
+ UserDefaults.standard.assistPathUpgradingWithPathMonitor = isChecked
+ }
+
@IBAction func viewLogClicked(_ sender: Any) {
let connectionService = parameters.environment.connectionService
guard connectionService.isInitialized else { return }
diff --git a/EduVPN-redesign/Helpers/UserDefaults+Preferences.swift b/EduVPN-redesign/Helpers/UserDefaults+Preferences.swift
index d04f05ea..0363f073 100644
--- a/EduVPN-redesign/Helpers/UserDefaults+Preferences.swift
+++ b/EduVPN-redesign/Helpers/UserDefaults+Preferences.swift
@@ -12,6 +12,8 @@ extension UserDefaults {
private static let showInDockKey = "showInDock"
private static let launchAtLoginKey = "launchAtLogin"
+ private static let assistPathUpgradingWithPathMonitorKey = "assistPathUpgradingWithPathMonitor"
+
var forceTCP: Bool {
get { // swiftlint:disable:this implicit_getter
return bool(forKey: Self.forceTCPDefaultsKey)
@@ -53,4 +55,13 @@ extension UserDefaults {
set(newValue, forKey: Self.launchAtLoginKey)
}
}
+
+ var assistPathUpgradingWithPathMonitor: Bool {
+ get { // swiftlint:disable:this implicit_getter
+ return bool(forKey: Self.assistPathUpgradingWithPathMonitorKey)
+ }
+ set {
+ set(newValue, forKey: Self.assistPathUpgradingWithPathMonitorKey)
+ }
+ }
}
diff --git a/EduVPN-redesign/Resources/Mac/Base.lproj/Main.storyboard b/EduVPN-redesign/Resources/Mac/Base.lproj/Main.storyboard
index f5d93c85..39c95e8c 100644
--- a/EduVPN-redesign/Resources/Mac/Base.lproj/Main.storyboard
+++ b/EduVPN-redesign/Resources/Mac/Base.lproj/Main.storyboard
@@ -529,13 +529,13 @@ Gw
-
+
-
+
-
+
@@ -764,11 +764,11 @@ Gw
-
+
-
+
@@ -776,7 +776,7 @@ Gw
-
+
@@ -790,12 +790,12 @@ Gw
-
+
-
+
-
+
@@ -1476,10 +1476,10 @@ Gw
-
+
-
+
@@ -1487,10 +1487,10 @@ Gw
-
+
-
+
@@ -1508,10 +1508,10 @@ Gw
-
+
-
+
@@ -1542,10 +1542,10 @@ Gw
-
+
-
+
-
+
+
@@ -1618,6 +1628,7 @@ Gw
+
@@ -1633,6 +1644,7 @@ Gw
+
@@ -1644,6 +1656,7 @@ Gw
+
diff --git a/EduVPN-redesign/Services/ConnectionService.swift b/EduVPN-redesign/Services/ConnectionService.swift
index 1d54e483..41b50ec0 100644
--- a/EduVPN-redesign/Services/ConnectionService.swift
+++ b/EduVPN-redesign/Services/ConnectionService.swift
@@ -254,7 +254,11 @@ private extension ConnectionService {
}
return Promise { resolver in
do {
- try tunnelManager.session.startTunnel()
+ let options: [String: Any] = [
+ "assistPathUpgradingWithPathMonitor":
+ UserDefaults.standard.assistPathUpgradingWithPathMonitor
+ ]
+ try tunnelManager.session.startTunnel(options: options)
} catch {
throw error
}
diff --git a/EduVPNTunnelExtension-macOS/PacketTunnelProvider.swift b/EduVPNTunnelExtension-macOS/PacketTunnelProvider.swift
index ee6509ad..c7d735ea 100644
--- a/EduVPNTunnelExtension-macOS/PacketTunnelProvider.swift
+++ b/EduVPNTunnelExtension-macOS/PacketTunnelProvider.swift
@@ -6,4 +6,11 @@
import TunnelKit
class PacketTunnelProvider: OpenVPNTunnelProvider {
+ override func startTunnel(options: [String: NSObject]? = nil, completionHandler: @escaping (Error?) -> Void) {
+ let assistPathUpgradingWithPathMonitor = (options?["assistPathUpgradingWithPathMonitor"] as? NSNumber)?.boolValue ?? false
+ if assistPathUpgradingWithPathMonitor {
+ setPathMonitorUsageMode(.assistPathUpgrading)
+ }
+ super.startTunnel(options: options, completionHandler: completionHandler)
+ }
}
diff --git a/Pods/TunnelKit/TunnelKit/Sources/Protocols/OpenVPN/AppExtension/OpenVPNTunnelProvider.swift b/Pods/TunnelKit/TunnelKit/Sources/Protocols/OpenVPN/AppExtension/OpenVPNTunnelProvider.swift
index 0c46660e..1f740adc 100644
--- a/Pods/TunnelKit/TunnelKit/Sources/Protocols/OpenVPN/AppExtension/OpenVPNTunnelProvider.swift
+++ b/Pods/TunnelKit/TunnelKit/Sources/Protocols/OpenVPN/AppExtension/OpenVPNTunnelProvider.swift
@@ -130,6 +130,25 @@ open class OpenVPNTunnelProvider: NEPacketTunnelProvider {
private var shouldReconnect = false
+ // MARK: NWPathMonitor usage
+
+ private var pathMonitor: AnyObject?
+
+ public enum PathMonitorUsageMode {
+ // Do not use path monitor. The default mode.
+ case none
+
+ // Use path monitor to help in reacting to hasBetterPath becoming true
+ case assistPathUpgrading
+ }
+
+ private(set) var pathMonitorUsageMode: PathMonitorUsageMode = .none
+
+ @available(OSXApplicationExtension 10.14, iOSApplicationExtension 12.0, *)
+ public func setPathMonitorUsageMode(_ mode: PathMonitorUsageMode) {
+ pathMonitorUsageMode = mode
+ }
+
// MARK: NEPacketTunnelProvider (XPC queue)
open override var reasserting: Bool {
@@ -503,10 +522,32 @@ extension OpenVPNTunnelProvider: GenericSocketDelegate {
/// :nodoc:
public func socketHasBetterPath(_ socket: GenericSocket) {
+ if #available(OSXApplicationExtension 10.14, iOSApplicationExtension 12.0, *) {
+ if let pathMonitor = self.pathMonitor as? NWPathMonitor {
+ log.debug("Socket has better path. Path status: \(pathMonitor.currentPath.status). Interfaces: \(pathMonitor.currentPath.availableInterfaces)")
+ if self.pathMonitorUsageMode == .assistPathUpgrading && !pathMonitor.currentPath.isValid {
+ log.debug("Ignoring spurious better path call")
+ return
+ }
+ }
+ }
log.debug("Stopping tunnel due to a new better path")
logCurrentSSID()
session?.reconnect(error: ProviderError.networkChanged)
}
+
+}
+
+@available(OSXApplicationExtension 10.14, iOSApplicationExtension 12.0, *)
+extension Network.NWPath {
+ var isValid: Bool {
+ guard status == .satisfied else { return false }
+ guard let primaryInterface = availableInterfaces.first else { return false }
+ if primaryInterface.type == .other && primaryInterface.name.hasPrefix("u") {
+ return false
+ }
+ return true
+ }
}
extension OpenVPNTunnelProvider: OpenVPNSessionDelegate {
@@ -570,6 +611,15 @@ extension OpenVPNTunnelProvider: OpenVPNSessionDelegate {
session.setTunnel(tunnel: NETunnelInterface(impl: self.packetFlow))
+ if #available(OSXApplicationExtension 10.14, iOSApplicationExtension 12.0, *) {
+ if self.pathMonitorUsageMode != .none {
+ log.debug("Setting up path monitor")
+ let pathMonitor = NWPathMonitor()
+ pathMonitor.start(queue: self.tunnelQueue)
+ self.pathMonitor = pathMonitor
+ }
+ }
+
self.pendingStartHandler?(nil)
self.pendingStartHandler = nil
}