blob: c89cce37dd6c75b7629c8b82e055d5b82637deb2 (
plain) (
blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
|
// SPDX-License-Identifier: MIT
// Copyright © 2018-2019 WireGuard LLC. All Rights Reserved.
import NetworkExtension
struct ActivateOnDemandSetting {
var isActivateOnDemandEnabled: Bool
var activateOnDemandOption: ActivateOnDemandOption
}
enum ActivateOnDemandOption {
case none // Valid only when isActivateOnDemandEnabled is false
case useOnDemandOverWiFiOnly
#if os(iOS)
case useOnDemandOverWiFiOrCellular
case useOnDemandOverCellularOnly
#elseif os(OSX)
case useOnDemandOverWiFiOrEthernet
case useOnDemandOverEthernetOnly
#endif
}
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
#if os(iOS)
case .useOnDemandOverWiFiOrCellular:
rules = [connectRule]
case .useOnDemandOverWiFiOnly:
connectRule.interfaceTypeMatch = .wiFi
disconnectRule.interfaceTypeMatch = .cellular
rules = [connectRule, disconnectRule]
case .useOnDemandOverCellularOnly:
connectRule.interfaceTypeMatch = .cellular
disconnectRule.interfaceTypeMatch = .wiFi
rules = [connectRule, disconnectRule]
#elseif os(OSX)
case .useOnDemandOverWiFiOrEthernet:
rules = [connectRule]
case .useOnDemandOverWiFiOnly:
connectRule.interfaceTypeMatch = .wiFi
disconnectRule.interfaceTypeMatch = .ethernet
rules = [connectRule, disconnectRule]
case .useOnDemandOverEthernetOnly:
connectRule.interfaceTypeMatch = .ethernet
disconnectRule.interfaceTypeMatch = .wiFi
rules = [connectRule, disconnectRule]
#endif
}
tunnelProviderManager.onDemandRules = rules
}
init(from tunnelProviderManager: NETunnelProviderManager) {
let rules = tunnelProviderManager.onDemandRules ?? []
#if os(iOS)
let otherInterfaceType: NEOnDemandRuleInterfaceType = .cellular
let useWiFiOrOtherOption: ActivateOnDemandOption = .useOnDemandOverWiFiOrCellular
let useOtherOnlyOption: ActivateOnDemandOption = .useOnDemandOverCellularOnly
#elseif os(OSX)
let otherInterfaceType: NEOnDemandRuleInterfaceType = .ethernet
let useWiFiOrOtherOption: ActivateOnDemandOption = .useOnDemandOverWiFiOrEthernet
let useOtherOnlyOption: ActivateOnDemandOption = .useOnDemandOverEthernetOnly
#endif
let activateOnDemandOption: ActivateOnDemandOption
switch rules.count {
case 0:
activateOnDemandOption = .none
case 1:
let rule = rules[0]
precondition(rule.action == .connect)
activateOnDemandOption = useWiFiOrOtherOption
case 2:
let connectRule = rules.first(where: { $0.action == .connect })!
let disconnectRule = rules.first(where: { $0.action == .disconnect })!
if connectRule.interfaceTypeMatch == .wiFi && disconnectRule.interfaceTypeMatch == otherInterfaceType {
activateOnDemandOption = .useOnDemandOverWiFiOnly
} else if connectRule.interfaceTypeMatch == otherInterfaceType && disconnectRule.interfaceTypeMatch == .wiFi {
activateOnDemandOption = useOtherOnlyOption
} else {
fatalError("Unexpected onDemandRules set on tunnel provider manager")
}
default:
fatalError("Unexpected number of onDemandRules set on tunnel provider manager")
}
self.activateOnDemandOption = activateOnDemandOption
if activateOnDemandOption == .none {
isActivateOnDemandEnabled = false
} else {
isActivateOnDemandEnabled = tunnelProviderManager.isOnDemandEnabled
}
}
}
extension ActivateOnDemandSetting {
static var defaultSetting = ActivateOnDemandSetting(isActivateOnDemandEnabled: false, activateOnDemandOption: .none)
}
|