on-demand: Infrastructure for supporting SSID-based rules
Signed-off-by: Roopesh Chander <roop@roopc.net>
This commit is contained in:
parent
3767a12983
commit
5d757982ba
|
@ -8,11 +8,11 @@ struct ActivateOnDemandSetting {
|
||||||
var activateOnDemandOption: ActivateOnDemandOption
|
var activateOnDemandOption: ActivateOnDemandOption
|
||||||
}
|
}
|
||||||
|
|
||||||
enum ActivateOnDemandOption {
|
enum ActivateOnDemandOption: Equatable {
|
||||||
case none // Valid only when isActivateOnDemandEnabled is false
|
case none // Valid only when isActivateOnDemandEnabled is false
|
||||||
case wiFiInterfaceOnly
|
case wiFiInterfaceOnly(ActivateOnDemandSSIDOption)
|
||||||
case nonWiFiInterfaceOnly
|
case nonWiFiInterfaceOnly
|
||||||
case anyInterface
|
case anyInterface(ActivateOnDemandSSIDOption)
|
||||||
}
|
}
|
||||||
|
|
||||||
#if os(iOS)
|
#if os(iOS)
|
||||||
|
@ -23,25 +23,29 @@ private let nonWiFiInterfaceType: NEOnDemandRuleInterfaceType = .ethernet
|
||||||
#error("Unimplemented")
|
#error("Unimplemented")
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
enum ActivateOnDemandSSIDOption: Equatable {
|
||||||
|
case anySSID
|
||||||
|
case onlySpecificSSIDs([String])
|
||||||
|
case exceptSpecificSSIDs([String])
|
||||||
|
}
|
||||||
|
|
||||||
extension ActivateOnDemandSetting {
|
extension ActivateOnDemandSetting {
|
||||||
func apply(on tunnelProviderManager: NETunnelProviderManager) {
|
func apply(on tunnelProviderManager: NETunnelProviderManager) {
|
||||||
tunnelProviderManager.isOnDemandEnabled = isActivateOnDemandEnabled
|
tunnelProviderManager.isOnDemandEnabled = isActivateOnDemandEnabled
|
||||||
let rules: [NEOnDemandRule]?
|
let rules: [NEOnDemandRule]?
|
||||||
let connectRule = NEOnDemandRuleConnect()
|
|
||||||
let disconnectRule = NEOnDemandRuleDisconnect()
|
|
||||||
switch activateOnDemandOption {
|
switch activateOnDemandOption {
|
||||||
case .none:
|
case .none:
|
||||||
rules = nil
|
rules = nil
|
||||||
case .wiFiInterfaceOnly:
|
case .wiFiInterfaceOnly(let ssidOption):
|
||||||
connectRule.interfaceTypeMatch = .wiFi
|
rules = ssidOnDemandRules(option: ssidOption) + [NEOnDemandRuleDisconnect(interfaceType: nonWiFiInterfaceType)]
|
||||||
disconnectRule.interfaceTypeMatch = nonWiFiInterfaceType
|
|
||||||
rules = [connectRule, disconnectRule]
|
|
||||||
case .nonWiFiInterfaceOnly:
|
case .nonWiFiInterfaceOnly:
|
||||||
connectRule.interfaceTypeMatch = nonWiFiInterfaceType
|
rules = [NEOnDemandRuleConnect(interfaceType: nonWiFiInterfaceType), NEOnDemandRuleDisconnect(interfaceType: .wiFi)]
|
||||||
disconnectRule.interfaceTypeMatch = .wiFi
|
case .anyInterface(let ssidOption):
|
||||||
rules = [connectRule, disconnectRule]
|
if case .anySSID = ssidOption {
|
||||||
case .anyInterface:
|
rules = [NEOnDemandRuleConnect(interfaceType: .any)]
|
||||||
rules = [connectRule]
|
} else {
|
||||||
|
rules = ssidOnDemandRules(option: ssidOption) + [NEOnDemandRuleConnect(interfaceType: nonWiFiInterfaceType)]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
tunnelProviderManager.onDemandRules = rules
|
tunnelProviderManager.onDemandRules = rules
|
||||||
}
|
}
|
||||||
|
@ -55,17 +59,33 @@ extension ActivateOnDemandSetting {
|
||||||
case 1:
|
case 1:
|
||||||
let rule = rules[0]
|
let rule = rules[0]
|
||||||
precondition(rule.action == .connect)
|
precondition(rule.action == .connect)
|
||||||
activateOnDemandOption = .anyInterface
|
activateOnDemandOption = .anyInterface(.anySSID)
|
||||||
case 2:
|
case 2:
|
||||||
let connectRule = rules.first(where: { $0.action == .connect })!
|
let connectRule = rules.first(where: { $0.action == .connect })!
|
||||||
let disconnectRule = rules.first(where: { $0.action == .disconnect })!
|
let disconnectRule = rules.first(where: { $0.action == .disconnect })!
|
||||||
if connectRule.interfaceTypeMatch == .wiFi && disconnectRule.interfaceTypeMatch == nonWiFiInterfaceType {
|
if connectRule.interfaceTypeMatch == .wiFi && disconnectRule.interfaceTypeMatch == nonWiFiInterfaceType {
|
||||||
activateOnDemandOption = .wiFiInterfaceOnly
|
activateOnDemandOption = .wiFiInterfaceOnly(.anySSID)
|
||||||
} else if connectRule.interfaceTypeMatch == nonWiFiInterfaceType && disconnectRule.interfaceTypeMatch == .wiFi {
|
} else if connectRule.interfaceTypeMatch == nonWiFiInterfaceType && disconnectRule.interfaceTypeMatch == .wiFi {
|
||||||
activateOnDemandOption = .nonWiFiInterfaceOnly
|
activateOnDemandOption = .nonWiFiInterfaceOnly
|
||||||
} else {
|
} else {
|
||||||
fatalError("Unexpected onDemandRules set on tunnel provider manager")
|
fatalError("Unexpected onDemandRules set on tunnel provider manager")
|
||||||
}
|
}
|
||||||
|
case 3:
|
||||||
|
let ssidRule = rules.first(where: { $0.interfaceTypeMatch == .wiFi && $0.ssidMatch != nil })!
|
||||||
|
let nonWiFiRule = rules.first(where: { $0.interfaceTypeMatch == nonWiFiInterfaceType })!
|
||||||
|
let ssids = ssidRule.ssidMatch!
|
||||||
|
switch (ssidRule.action, nonWiFiRule.action) {
|
||||||
|
case (.connect, .connect):
|
||||||
|
activateOnDemandOption = .anyInterface(.onlySpecificSSIDs(ssids))
|
||||||
|
case (.connect, .disconnect):
|
||||||
|
activateOnDemandOption = .wiFiInterfaceOnly(.onlySpecificSSIDs(ssids))
|
||||||
|
case (.disconnect, .connect):
|
||||||
|
activateOnDemandOption = .anyInterface(.exceptSpecificSSIDs(ssids))
|
||||||
|
case (.disconnect, .disconnect):
|
||||||
|
activateOnDemandOption = .wiFiInterfaceOnly(.exceptSpecificSSIDs(ssids))
|
||||||
|
default:
|
||||||
|
fatalError("Unexpected SSID onDemandRules set on tunnel provider manager")
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
fatalError("Unexpected number of onDemandRules set on tunnel provider manager")
|
fatalError("Unexpected number of onDemandRules set on tunnel provider manager")
|
||||||
}
|
}
|
||||||
|
@ -82,3 +102,33 @@ extension ActivateOnDemandSetting {
|
||||||
extension ActivateOnDemandSetting {
|
extension ActivateOnDemandSetting {
|
||||||
static var defaultSetting = ActivateOnDemandSetting(isActivateOnDemandEnabled: false, activateOnDemandOption: .none)
|
static var defaultSetting = ActivateOnDemandSetting(isActivateOnDemandEnabled: false, activateOnDemandOption: .none)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private extension NEOnDemandRuleConnect {
|
||||||
|
convenience init(interfaceType: NEOnDemandRuleInterfaceType, ssids: [String]? = nil) {
|
||||||
|
self.init()
|
||||||
|
interfaceTypeMatch = interfaceType
|
||||||
|
ssidMatch = ssids
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private extension NEOnDemandRuleDisconnect {
|
||||||
|
convenience init(interfaceType: NEOnDemandRuleInterfaceType, ssids: [String]? = nil) {
|
||||||
|
self.init()
|
||||||
|
interfaceTypeMatch = interfaceType
|
||||||
|
ssidMatch = ssids
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private func ssidOnDemandRules(option: ActivateOnDemandSSIDOption) -> [NEOnDemandRule] {
|
||||||
|
switch option {
|
||||||
|
case .anySSID:
|
||||||
|
return [NEOnDemandRuleConnect(interfaceType: .wiFi)]
|
||||||
|
case .onlySpecificSSIDs(let ssids):
|
||||||
|
assert(!ssids.isEmpty)
|
||||||
|
return [NEOnDemandRuleConnect(interfaceType: .wiFi, ssids: ssids),
|
||||||
|
NEOnDemandRuleDisconnect(interfaceType: .wiFi)]
|
||||||
|
case .exceptSpecificSSIDs(let ssids):
|
||||||
|
return [NEOnDemandRuleDisconnect(interfaceType: .wiFi, ssids: ssids),
|
||||||
|
NEOnDemandRuleConnect(interfaceType: .wiFi)]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -661,7 +661,7 @@ extension TunnelViewModel {
|
||||||
}
|
}
|
||||||
|
|
||||||
static func defaultActivateOnDemandOption() -> ActivateOnDemandOption {
|
static func defaultActivateOnDemandOption() -> ActivateOnDemandOption {
|
||||||
return .anyInterface
|
return .anyInterface(.anySSID)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -44,8 +44,8 @@ class TunnelEditTableViewController: UITableViewController {
|
||||||
]
|
]
|
||||||
|
|
||||||
let activateOnDemandOptions: [ActivateOnDemandOption] = [
|
let activateOnDemandOptions: [ActivateOnDemandOption] = [
|
||||||
.anyInterface,
|
.anyInterface(.anySSID),
|
||||||
.wiFiInterfaceOnly,
|
.wiFiInterfaceOnly(.anySSID),
|
||||||
.nonWiFiInterfaceOnly
|
.nonWiFiInterfaceOnly
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
|
@ -82,8 +82,8 @@ class TunnelEditViewController: NSViewController {
|
||||||
|
|
||||||
let activateOnDemandOptions: [ActivateOnDemandOption] = [
|
let activateOnDemandOptions: [ActivateOnDemandOption] = [
|
||||||
.none,
|
.none,
|
||||||
.anyInterface,
|
.anyInterface(.anySSID),
|
||||||
.wiFiInterfaceOnly,
|
.wiFiInterfaceOnly(.anySSID),
|
||||||
.nonWiFiInterfaceOnly
|
.nonWiFiInterfaceOnly
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue