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
|
||||
}
|
||||
|
||||
enum ActivateOnDemandOption {
|
||||
enum ActivateOnDemandOption: Equatable {
|
||||
case none // Valid only when isActivateOnDemandEnabled is false
|
||||
case wiFiInterfaceOnly
|
||||
case wiFiInterfaceOnly(ActivateOnDemandSSIDOption)
|
||||
case nonWiFiInterfaceOnly
|
||||
case anyInterface
|
||||
case anyInterface(ActivateOnDemandSSIDOption)
|
||||
}
|
||||
|
||||
#if os(iOS)
|
||||
|
@ -23,25 +23,29 @@ private let nonWiFiInterfaceType: NEOnDemandRuleInterfaceType = .ethernet
|
|||
#error("Unimplemented")
|
||||
#endif
|
||||
|
||||
enum ActivateOnDemandSSIDOption: Equatable {
|
||||
case anySSID
|
||||
case onlySpecificSSIDs([String])
|
||||
case exceptSpecificSSIDs([String])
|
||||
}
|
||||
|
||||
extension ActivateOnDemandSetting {
|
||||
func apply(on tunnelProviderManager: NETunnelProviderManager) {
|
||||
tunnelProviderManager.isOnDemandEnabled = isActivateOnDemandEnabled
|
||||
let rules: [NEOnDemandRule]?
|
||||
let connectRule = NEOnDemandRuleConnect()
|
||||
let disconnectRule = NEOnDemandRuleDisconnect()
|
||||
switch activateOnDemandOption {
|
||||
case .none:
|
||||
rules = nil
|
||||
case .wiFiInterfaceOnly:
|
||||
connectRule.interfaceTypeMatch = .wiFi
|
||||
disconnectRule.interfaceTypeMatch = nonWiFiInterfaceType
|
||||
rules = [connectRule, disconnectRule]
|
||||
case .wiFiInterfaceOnly(let ssidOption):
|
||||
rules = ssidOnDemandRules(option: ssidOption) + [NEOnDemandRuleDisconnect(interfaceType: nonWiFiInterfaceType)]
|
||||
case .nonWiFiInterfaceOnly:
|
||||
connectRule.interfaceTypeMatch = nonWiFiInterfaceType
|
||||
disconnectRule.interfaceTypeMatch = .wiFi
|
||||
rules = [connectRule, disconnectRule]
|
||||
case .anyInterface:
|
||||
rules = [connectRule]
|
||||
rules = [NEOnDemandRuleConnect(interfaceType: nonWiFiInterfaceType), NEOnDemandRuleDisconnect(interfaceType: .wiFi)]
|
||||
case .anyInterface(let ssidOption):
|
||||
if case .anySSID = ssidOption {
|
||||
rules = [NEOnDemandRuleConnect(interfaceType: .any)]
|
||||
} else {
|
||||
rules = ssidOnDemandRules(option: ssidOption) + [NEOnDemandRuleConnect(interfaceType: nonWiFiInterfaceType)]
|
||||
}
|
||||
}
|
||||
tunnelProviderManager.onDemandRules = rules
|
||||
}
|
||||
|
@ -55,17 +59,33 @@ extension ActivateOnDemandSetting {
|
|||
case 1:
|
||||
let rule = rules[0]
|
||||
precondition(rule.action == .connect)
|
||||
activateOnDemandOption = .anyInterface
|
||||
activateOnDemandOption = .anyInterface(.anySSID)
|
||||
case 2:
|
||||
let connectRule = rules.first(where: { $0.action == .connect })!
|
||||
let disconnectRule = rules.first(where: { $0.action == .disconnect })!
|
||||
if connectRule.interfaceTypeMatch == .wiFi && disconnectRule.interfaceTypeMatch == nonWiFiInterfaceType {
|
||||
activateOnDemandOption = .wiFiInterfaceOnly
|
||||
activateOnDemandOption = .wiFiInterfaceOnly(.anySSID)
|
||||
} else if connectRule.interfaceTypeMatch == nonWiFiInterfaceType && disconnectRule.interfaceTypeMatch == .wiFi {
|
||||
activateOnDemandOption = .nonWiFiInterfaceOnly
|
||||
} else {
|
||||
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:
|
||||
fatalError("Unexpected number of onDemandRules set on tunnel provider manager")
|
||||
}
|
||||
|
@ -82,3 +102,33 @@ extension ActivateOnDemandSetting {
|
|||
extension ActivateOnDemandSetting {
|
||||
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 {
|
||||
return .anyInterface
|
||||
return .anyInterface(.anySSID)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -44,8 +44,8 @@ class TunnelEditTableViewController: UITableViewController {
|
|||
]
|
||||
|
||||
let activateOnDemandOptions: [ActivateOnDemandOption] = [
|
||||
.anyInterface,
|
||||
.wiFiInterfaceOnly,
|
||||
.anyInterface(.anySSID),
|
||||
.wiFiInterfaceOnly(.anySSID),
|
||||
.nonWiFiInterfaceOnly
|
||||
]
|
||||
|
||||
|
|
|
@ -82,8 +82,8 @@ class TunnelEditViewController: NSViewController {
|
|||
|
||||
let activateOnDemandOptions: [ActivateOnDemandOption] = [
|
||||
.none,
|
||||
.anyInterface,
|
||||
.wiFiInterfaceOnly,
|
||||
.anyInterface(.anySSID),
|
||||
.wiFiInterfaceOnly(.anySSID),
|
||||
.nonWiFiInterfaceOnly
|
||||
]
|
||||
|
||||
|
|
Loading…
Reference in New Issue