Skip to content

Commit e30a9be

Browse files
committed
feat: remove and re-add VPN configuration if not working properly
1 parent 5b3b1bb commit e30a9be

4 files changed

+84
-2
lines changed

FirewallController.swift

+10
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,16 @@ class FirewallController: NSObject {
4747
return .invalid
4848
}
4949
}
50+
51+
func deleteConfigurationAndAddAgain() {
52+
refreshManager { (error) in
53+
self.manager?.removeFromPreferences(completionHandler: { (removeError) in
54+
DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) {
55+
self.setEnabled(true, isUserExplicitToggle: true)
56+
}
57+
})
58+
}
59+
}
5060

5161
func restart(completion: @escaping (_ error: Error?) -> Void = {_ in }) {
5262
// Don't let this affect userWantsFirewallOn/Off config

LockdowniOS/AccountVC.swift

+7
Original file line numberDiff line numberDiff line change
@@ -347,6 +347,13 @@ final class AccountViewController: BaseViewController, Loadable {
347347
for cell in otherCells {
348348
tableView.addCell(cell)
349349
}
350+
351+
#if DEBUG
352+
let fixVPNConfig = DefaultCell(title: "_Fix Firewall Config", height: buttonHeight, dismissOnTap: true, action: {
353+
354+
})
355+
tableView.addCell(fixVPNConfig)
356+
#endif
350357
}
351358

352359
func startTutorial() {

LockdowniOS/BaseViewController.swift

+13
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,19 @@ open class BaseViewController: UIViewController, MFMailComposeViewControllerDele
238238
self.present(popup, animated: true, completion: nil)
239239
}
240240

241+
func showFixFirewallConnectionDialog(completion: @escaping () -> ()) {
242+
self.showPopupDialog(
243+
title: "Tap \"Allow\" on the Next Popup",
244+
message: "Due to a recent iOS or Lockdown update, the Firewall needs to be refreshed to run properly.\n\nIf asked, tap \"Allow\" on the next dialog to automatically complete this process.",
245+
buttons: [
246+
.cancel(),
247+
.defaultAccept(completion: {
248+
completion()
249+
})
250+
]
251+
)
252+
}
253+
241254
// func showPopupDialogSubmitError(title : String = "Sorry, An Error Occurred", message : String, error: Error?) {
242255
// let popup = PopupDialog(title: title, message: message, image: nil, transitionStyle: .zoomIn, hideStatusBar: false)
243256
// let acceptButton = DefaultButton(title: "Don't Submit", dismissOnTap: true) { }

LockdowniOS/HomeViewController.swift

+54-2
Original file line numberDiff line numberDiff line change
@@ -329,7 +329,7 @@ class HomeViewController: BaseViewController, AwesomeSpotlightViewDelegate, Load
329329
@objc func tunnelStatusDidChange(_ notification: Notification) {
330330
// Firewall
331331
if let tunnelProviderSession = notification.object as? NETunnelProviderSession {
332-
DDLogInfo("VPNStatusDidChange as NETunnelProviderSession with status: \(tunnelProviderSession.status.rawValue)");
332+
DDLogInfo("VPNStatusDidChange as NETunnelProviderSession with status: \(tunnelProviderSession.status.description)");
333333
if (!getUserWantsFirewallEnabled()) {
334334
updateFirewallButtonWithStatus(status: .disconnected)
335335
}
@@ -346,7 +346,7 @@ class HomeViewController: BaseViewController, AwesomeSpotlightViewDelegate, Load
346346
}
347347
// VPN
348348
else if let neVPNConnection = notification.object as? NEVPNConnection {
349-
DDLogInfo("VPNStatusDidChange as NEVPNConnection with status: \(neVPNConnection.status.rawValue)");
349+
DDLogInfo("VPNStatusDidChange as NEVPNConnection with status: \(neVPNConnection.status.description)");
350350
updateVPNButtonWithStatus(status: neVPNConnection.status);
351351
updateVPNRegionLabel()
352352
if NEVPNManager.shared().connection.status == .connected || NEVPNManager.shared().connection.status == .disconnected {
@@ -505,9 +505,11 @@ class HomeViewController: BaseViewController, AwesomeSpotlightViewDelegate, Load
505505
switch FirewallController.shared.status() {
506506
case .invalid:
507507
FirewallController.shared.setEnabled(true, isUserExplicitToggle: true)
508+
ensureFirewallWorkingAfterEnabling(waitingSeconds: 3.0)
508509
case .disconnected:
509510
updateFirewallButtonWithStatus(status: .connecting)
510511
FirewallController.shared.setEnabled(true, isUserExplicitToggle: true)
512+
ensureFirewallWorkingAfterEnabling(waitingSeconds: 3.0)
511513

512514
checkForAskRating()
513515
case .connected:
@@ -518,6 +520,35 @@ class HomeViewController: BaseViewController, AwesomeSpotlightViewDelegate, Load
518520
}
519521
}
520522

523+
func ensureFirewallWorkingAfterEnabling(waitingSeconds: TimeInterval) {
524+
DispatchQueue.main.asyncAfter(deadline: .now() + waitingSeconds) {
525+
DDLogInfo("\(waitingSeconds) seconds passed, checking if Firewall is enabled")
526+
guard getUserWantsFirewallEnabled() else {
527+
// firewall shouldn't be enabled, no need to act
528+
DDLogInfo("User doesn't want Firewall enabled, no action")
529+
return
530+
}
531+
532+
let status = FirewallController.shared.status()
533+
switch status {
534+
case .connecting, .disconnecting, .reasserting:
535+
// check again in three seconds
536+
DDLogInfo("Firewall is in transient state, will check again in 3 seconds")
537+
self.ensureFirewallWorkingAfterEnabling(waitingSeconds: 3.0)
538+
case .connected:
539+
// all good
540+
DDLogInfo("Firewall is connected, no action")
541+
break
542+
case .disconnected, .invalid:
543+
// we suppose that the connection is somehow broken, trying to fix
544+
DDLogInfo("Firewall is not connected even though it should be, attempting to fix")
545+
self.showFixFirewallConnectionDialog {
546+
FirewallController.shared.deleteConfigurationAndAddAgain()
547+
}
548+
}
549+
}
550+
}
551+
521552
func updateFirewallButtonWithStatus(status: NEVPNStatus) {
522553
DDLogInfo("UpdateFirewallButton")
523554
switch status {
@@ -1008,3 +1039,24 @@ final class DynamicButton: PopupDialogButton {
10081039
}
10091040
}
10101041
}
1042+
1043+
extension NEVPNStatus: CustomStringConvertible {
1044+
1045+
public var description: String {
1046+
switch self {
1047+
case .invalid:
1048+
return "invalid"
1049+
case .disconnected:
1050+
return "disconnected"
1051+
case .connecting:
1052+
return "connecting"
1053+
case .connected:
1054+
return "connected"
1055+
case .reasserting:
1056+
return "reasserting"
1057+
case .disconnecting:
1058+
return "disconnecting"
1059+
}
1060+
}
1061+
1062+
}

0 commit comments

Comments
 (0)