VPN: When activating while another tunnel is active, deactivate the other tunnel
Signed-off-by: Roopesh Chander <roop@roopc.net>
This commit is contained in:
parent
8e7bfb15ed
commit
e8d68396ca
|
@ -23,21 +23,6 @@ class ErrorPresenter {
|
||||||
// TunnelActivationError
|
// TunnelActivationError
|
||||||
case TunnelActivationError.tunnelActivationFailed:
|
case TunnelActivationError.tunnelActivationFailed:
|
||||||
return ("Activation failure", "The tunnel could not be activated due to an internal error")
|
return ("Activation failure", "The tunnel could not be activated due to an internal error")
|
||||||
case TunnelActivationError.attemptingActivationWhenAnotherTunnelIsBusy(let otherTunnelStatus):
|
|
||||||
let statusString: String = {
|
|
||||||
switch (otherTunnelStatus) {
|
|
||||||
case .active: fallthrough
|
|
||||||
case .reasserting: fallthrough
|
|
||||||
case .restarting:
|
|
||||||
return "active"
|
|
||||||
case .activating: fallthrough
|
|
||||||
case .deactivating:
|
|
||||||
return "being deactivated"
|
|
||||||
case .inactive:
|
|
||||||
fatalError()
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
return ("Activation failure", "Another tunnel is currently \(statusString)")
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
os_log("ErrorPresenter: Error not presented: %{public}@", log: OSLog.default, type: .error, "\(error)")
|
os_log("ErrorPresenter: Error not presented: %{public}@", log: OSLog.default, type: .error, "\(error)")
|
||||||
|
|
|
@ -259,6 +259,8 @@ class TunnelDetailTableViewStatusCell: UITableViewCell {
|
||||||
text = "Reactivating"
|
text = "Reactivating"
|
||||||
case .restarting:
|
case .restarting:
|
||||||
text = "Restarting"
|
text = "Restarting"
|
||||||
|
case .waiting:
|
||||||
|
text = "Waiting"
|
||||||
}
|
}
|
||||||
textLabel?.text = text
|
textLabel?.text = text
|
||||||
DispatchQueue.main.async { [weak statusSwitch] in
|
DispatchQueue.main.async { [weak statusSwitch] in
|
||||||
|
|
|
@ -14,7 +14,6 @@ protocol TunnelsManagerDelegate: class {
|
||||||
|
|
||||||
enum TunnelActivationError: Error {
|
enum TunnelActivationError: Error {
|
||||||
case tunnelActivationFailed
|
case tunnelActivationFailed
|
||||||
case attemptingActivationWhenAnotherTunnelIsBusy(otherTunnelStatus: TunnelStatus)
|
|
||||||
case attemptingActivationWhenTunnelIsNotInactive
|
case attemptingActivationWhenTunnelIsNotInactive
|
||||||
case attemptingDeactivationWhenTunnelIsInactive
|
case attemptingDeactivationWhenTunnelIsInactive
|
||||||
}
|
}
|
||||||
|
@ -191,13 +190,15 @@ class TunnelsManager {
|
||||||
completionHandler(TunnelActivationError.attemptingActivationWhenTunnelIsNotInactive)
|
completionHandler(TunnelActivationError.attemptingActivationWhenTunnelIsNotInactive)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
for t in tunnels {
|
if let tunnelInOperation = tunnels.first(where: { $0.status != .inactive }) {
|
||||||
if t.status != .inactive {
|
tunnel.status = .waiting
|
||||||
completionHandler(TunnelActivationError.attemptingActivationWhenAnotherTunnelIsBusy(otherTunnelStatus: t.status))
|
tunnelInOperation.onDeactivationComplete = {
|
||||||
return
|
tunnel.startActivation(completionHandler: completionHandler)
|
||||||
}
|
}
|
||||||
|
startDeactivation(of: tunnelInOperation)
|
||||||
|
} else {
|
||||||
|
tunnel.startActivation(completionHandler: completionHandler)
|
||||||
}
|
}
|
||||||
tunnel.startActivation(completionHandler: completionHandler)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func startDeactivation(of tunnel: TunnelContainer) {
|
func startDeactivation(of tunnel: TunnelContainer) {
|
||||||
|
@ -218,6 +219,8 @@ class TunnelContainer: NSObject {
|
||||||
@objc dynamic var name: String
|
@objc dynamic var name: String
|
||||||
@objc dynamic var status: TunnelStatus
|
@objc dynamic var status: TunnelStatus
|
||||||
|
|
||||||
|
var onDeactivationComplete: (() -> Void)?
|
||||||
|
|
||||||
fileprivate let tunnelProvider: NETunnelProviderManager
|
fileprivate let tunnelProvider: NETunnelProviderManager
|
||||||
private var statusObservationToken: AnyObject?
|
private var statusObservationToken: AnyObject?
|
||||||
|
|
||||||
|
@ -245,10 +248,11 @@ class TunnelContainer: NSObject {
|
||||||
}
|
}
|
||||||
|
|
||||||
fileprivate func startActivation(completionHandler: @escaping (Error?) -> Void) {
|
fileprivate func startActivation(completionHandler: @escaping (Error?) -> Void) {
|
||||||
assert(status == .inactive || status == .restarting)
|
assert(status == .inactive || status == .restarting || status == .waiting)
|
||||||
|
|
||||||
guard let tunnelConfiguration = tunnelConfiguration() else { fatalError() }
|
guard let tunnelConfiguration = tunnelConfiguration() else { fatalError() }
|
||||||
|
|
||||||
|
onDeactivationComplete = nil
|
||||||
startActivation(tunnelConfiguration: tunnelConfiguration,
|
startActivation(tunnelConfiguration: tunnelConfiguration,
|
||||||
completionHandler: completionHandler)
|
completionHandler: completionHandler)
|
||||||
}
|
}
|
||||||
|
@ -356,6 +360,8 @@ class TunnelContainer: NSObject {
|
||||||
s.status = TunnelStatus(from: connection.status)
|
s.status = TunnelStatus(from: connection.status)
|
||||||
if (s.status == .inactive) {
|
if (s.status == .inactive) {
|
||||||
s.statusObservationToken = nil
|
s.statusObservationToken = nil
|
||||||
|
s.onDeactivationComplete?()
|
||||||
|
s.onDeactivationComplete = nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -369,6 +375,7 @@ class TunnelContainer: NSObject {
|
||||||
case reasserting // Not a possible state at present
|
case reasserting // Not a possible state at present
|
||||||
|
|
||||||
case restarting // Restarting tunnel (done after saving modifications to an active tunnel)
|
case restarting // Restarting tunnel (done after saving modifications to an active tunnel)
|
||||||
|
case waiting // Waiting for another tunnel to be brought down
|
||||||
|
|
||||||
init(from vpnStatus: NEVPNStatus) {
|
init(from vpnStatus: NEVPNStatus) {
|
||||||
switch (vpnStatus) {
|
switch (vpnStatus) {
|
||||||
|
|
Loading…
Reference in New Issue