Move VPN manager logic into its own controller
This commit is contained in:
@@ -27,7 +27,6 @@
|
|||||||
54448A2E2486464F00771C96 /* Array.swift in Sources */ = {isa = PBXBuildFile; fileRef = 54448A2D2486464F00771C96 /* Array.swift */; };
|
54448A2E2486464F00771C96 /* Array.swift in Sources */ = {isa = PBXBuildFile; fileRef = 54448A2D2486464F00771C96 /* Array.swift */; };
|
||||||
54448A30248647D900771C96 /* Time.swift in Sources */ = {isa = PBXBuildFile; fileRef = 54448A2F248647D900771C96 /* Time.swift */; };
|
54448A30248647D900771C96 /* Time.swift in Sources */ = {isa = PBXBuildFile; fileRef = 54448A2F248647D900771C96 /* Time.swift */; };
|
||||||
54448A3224899A4000771C96 /* SearchBarManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 54448A3124899A4000771C96 /* SearchBarManager.swift */; };
|
54448A3224899A4000771C96 /* SearchBarManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 54448A3124899A4000771C96 /* SearchBarManager.swift */; };
|
||||||
544C95262407B1C700AB89D0 /* SharedState.swift in Sources */ = {isa = PBXBuildFile; fileRef = 544C95252407B1C700AB89D0 /* SharedState.swift */; };
|
|
||||||
544F912024A67EC5001D4B00 /* TVCOccurrenceContext.swift in Sources */ = {isa = PBXBuildFile; fileRef = 544F911F24A67EC5001D4B00 /* TVCOccurrenceContext.swift */; };
|
544F912024A67EC5001D4B00 /* TVCOccurrenceContext.swift in Sources */ = {isa = PBXBuildFile; fileRef = 544F911F24A67EC5001D4B00 /* TVCOccurrenceContext.swift */; };
|
||||||
5458EBC0243A3F2200CFEB15 /* TVCRecordingDetails.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5458EBBF243A3F2200CFEB15 /* TVCRecordingDetails.swift */; };
|
5458EBC0243A3F2200CFEB15 /* TVCRecordingDetails.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5458EBBF243A3F2200CFEB15 /* TVCRecordingDetails.swift */; };
|
||||||
545DDDCF243E6267003B6544 /* TutorialSheet.swift in Sources */ = {isa = PBXBuildFile; fileRef = 545DDDCE243E6267003B6544 /* TutorialSheet.swift */; };
|
545DDDCF243E6267003B6544 /* TutorialSheet.swift in Sources */ = {isa = PBXBuildFile; fileRef = 545DDDCE243E6267003B6544 /* TutorialSheet.swift */; };
|
||||||
@@ -143,6 +142,7 @@
|
|||||||
54E540FA2482414800F7C34A /* SyncUpdate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 54E540F92482414800F7C34A /* SyncUpdate.swift */; };
|
54E540FA2482414800F7C34A /* SyncUpdate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 54E540F92482414800F7C34A /* SyncUpdate.swift */; };
|
||||||
54E67E4624A8B0FE0025D261 /* PrefsShared.swift in Sources */ = {isa = PBXBuildFile; fileRef = 54E67E4524A8B0FE0025D261 /* PrefsShared.swift */; };
|
54E67E4624A8B0FE0025D261 /* PrefsShared.swift in Sources */ = {isa = PBXBuildFile; fileRef = 54E67E4524A8B0FE0025D261 /* PrefsShared.swift */; };
|
||||||
54E67E4924A8B1280025D261 /* Prefs.swift in Sources */ = {isa = PBXBuildFile; fileRef = 54E67E4824A8B1280025D261 /* Prefs.swift */; };
|
54E67E4924A8B1280025D261 /* Prefs.swift in Sources */ = {isa = PBXBuildFile; fileRef = 54E67E4824A8B1280025D261 /* Prefs.swift */; };
|
||||||
|
54E67E4B24A8C6370025D261 /* GlassVPN.swift in Sources */ = {isa = PBXBuildFile; fileRef = 54E67E4A24A8C6370025D261 /* GlassVPN.swift */; };
|
||||||
54EFA4E82491A16A0022D618 /* Font.swift in Sources */ = {isa = PBXBuildFile; fileRef = 54EFA4E72491A16A0022D618 /* Font.swift */; };
|
54EFA4E82491A16A0022D618 /* Font.swift in Sources */ = {isa = PBXBuildFile; fileRef = 54EFA4E72491A16A0022D618 /* Font.swift */; };
|
||||||
/* End PBXBuildFile section */
|
/* End PBXBuildFile section */
|
||||||
|
|
||||||
@@ -195,7 +195,6 @@
|
|||||||
54448A2D2486464F00771C96 /* Array.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Array.swift; sourceTree = "<group>"; };
|
54448A2D2486464F00771C96 /* Array.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Array.swift; sourceTree = "<group>"; };
|
||||||
54448A2F248647D900771C96 /* Time.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Time.swift; sourceTree = "<group>"; };
|
54448A2F248647D900771C96 /* Time.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Time.swift; sourceTree = "<group>"; };
|
||||||
54448A3124899A4000771C96 /* SearchBarManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchBarManager.swift; sourceTree = "<group>"; };
|
54448A3124899A4000771C96 /* SearchBarManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchBarManager.swift; sourceTree = "<group>"; };
|
||||||
544C95252407B1C700AB89D0 /* SharedState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SharedState.swift; sourceTree = "<group>"; };
|
|
||||||
544F911F24A67EC5001D4B00 /* TVCOccurrenceContext.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TVCOccurrenceContext.swift; sourceTree = "<group>"; };
|
544F911F24A67EC5001D4B00 /* TVCOccurrenceContext.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TVCOccurrenceContext.swift; sourceTree = "<group>"; };
|
||||||
5458EBBF243A3F2200CFEB15 /* TVCRecordingDetails.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TVCRecordingDetails.swift; sourceTree = "<group>"; };
|
5458EBBF243A3F2200CFEB15 /* TVCRecordingDetails.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TVCRecordingDetails.swift; sourceTree = "<group>"; };
|
||||||
545DDDCE243E6267003B6544 /* TutorialSheet.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TutorialSheet.swift; sourceTree = "<group>"; };
|
545DDDCE243E6267003B6544 /* TutorialSheet.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TutorialSheet.swift; sourceTree = "<group>"; };
|
||||||
@@ -312,6 +311,7 @@
|
|||||||
54E540F92482414800F7C34A /* SyncUpdate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SyncUpdate.swift; sourceTree = "<group>"; };
|
54E540F92482414800F7C34A /* SyncUpdate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SyncUpdate.swift; sourceTree = "<group>"; };
|
||||||
54E67E4524A8B0FE0025D261 /* PrefsShared.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PrefsShared.swift; sourceTree = "<group>"; };
|
54E67E4524A8B0FE0025D261 /* PrefsShared.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PrefsShared.swift; sourceTree = "<group>"; };
|
||||||
54E67E4824A8B1280025D261 /* Prefs.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Prefs.swift; sourceTree = "<group>"; };
|
54E67E4824A8B1280025D261 /* Prefs.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Prefs.swift; sourceTree = "<group>"; };
|
||||||
|
54E67E4A24A8C6370025D261 /* GlassVPN.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GlassVPN.swift; sourceTree = "<group>"; };
|
||||||
54EFA4E72491A16A0022D618 /* Font.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Font.swift; sourceTree = "<group>"; };
|
54EFA4E72491A16A0022D618 /* Font.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Font.swift; sourceTree = "<group>"; };
|
||||||
/* End PBXFileReference section */
|
/* End PBXFileReference section */
|
||||||
|
|
||||||
@@ -393,6 +393,7 @@
|
|||||||
545DDDD224436A03003B6544 /* Common Classes */,
|
545DDDD224436A03003B6544 /* Common Classes */,
|
||||||
548B1F9423D338EC005B047C /* main.entitlements */,
|
548B1F9423D338EC005B047C /* main.entitlements */,
|
||||||
541AC5D72399498A00A769D7 /* AppDelegate.swift */,
|
541AC5D72399498A00A769D7 /* AppDelegate.swift */,
|
||||||
|
54E67E4A24A8C6370025D261 /* GlassVPN.swift */,
|
||||||
542E2A972404973F001462DC /* TBCMain.swift */,
|
542E2A972404973F001462DC /* TBCMain.swift */,
|
||||||
540C6454240D5BAE00E948F9 /* Requests */,
|
540C6454240D5BAE00E948F9 /* Requests */,
|
||||||
540E677E242D2CD200871BBE /* Recordings */,
|
540E677E242D2CD200871BBE /* Recordings */,
|
||||||
@@ -469,7 +470,6 @@
|
|||||||
54B345A4241BB975004C53CC /* Extensions */ = {
|
54B345A4241BB975004C53CC /* Extensions */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
544C95252407B1C700AB89D0 /* SharedState.swift */,
|
|
||||||
54B345A8241BBA0B004C53CC /* Generic.swift */,
|
54B345A8241BBA0B004C53CC /* Generic.swift */,
|
||||||
54B345A5241BB982004C53CC /* Notifications.swift */,
|
54B345A5241BB982004C53CC /* Notifications.swift */,
|
||||||
54B345AA241BBA5B004C53CC /* AlertSheet.swift */,
|
54B345AA241BBA5B004C53CC /* AlertSheet.swift */,
|
||||||
@@ -857,9 +857,9 @@
|
|||||||
540E67842433FAFE00871BBE /* TVCPreviousRecords.swift in Sources */,
|
540E67842433FAFE00871BBE /* TVCPreviousRecords.swift in Sources */,
|
||||||
54B345A6241BB982004C53CC /* Notifications.swift in Sources */,
|
54B345A6241BB982004C53CC /* Notifications.swift in Sources */,
|
||||||
54448A2E2486464F00771C96 /* Array.swift in Sources */,
|
54448A2E2486464F00771C96 /* Array.swift in Sources */,
|
||||||
|
54E67E4B24A8C6370025D261 /* GlassVPN.swift in Sources */,
|
||||||
541FC47824A1453F009154D8 /* VCCoOccurrence.swift in Sources */,
|
541FC47824A1453F009154D8 /* VCCoOccurrence.swift in Sources */,
|
||||||
54B345AB241BBA5B004C53CC /* AlertSheet.swift in Sources */,
|
54B345AB241BBA5B004C53CC /* AlertSheet.swift in Sources */,
|
||||||
544C95262407B1C700AB89D0 /* SharedState.swift in Sources */,
|
|
||||||
541DCA6124A6B0F6005F1A4B /* Color.swift in Sources */,
|
541DCA6124A6B0F6005F1A4B /* Color.swift in Sources */,
|
||||||
545DDDCF243E6267003B6544 /* TutorialSheet.swift in Sources */,
|
545DDDCF243E6267003B6544 /* TutorialSheet.swift in Sources */,
|
||||||
54B345A9241BBA0B004C53CC /* Generic.swift in Sources */,
|
54B345A9241BBA0B004C53CC /* Generic.swift in Sources */,
|
||||||
|
|||||||
@@ -1,13 +1,9 @@
|
|||||||
import UIKit
|
import UIKit
|
||||||
import NetworkExtension
|
|
||||||
|
|
||||||
let VPNConfigBundleIdentifier = "de.uni-bamberg.psi.AppCheck.VPN"
|
|
||||||
|
|
||||||
@UIApplicationMain
|
@UIApplicationMain
|
||||||
class AppDelegate: UIResponder, UIApplicationDelegate {
|
class AppDelegate: UIResponder, UIApplicationDelegate {
|
||||||
|
|
||||||
var window: UIWindow?
|
var window: UIWindow?
|
||||||
var managerVPN: NETunnelProviderManager?
|
|
||||||
|
|
||||||
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
|
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
|
||||||
if UserDefaults.standard.bool(forKey: "kill_db") {
|
if UserDefaults.standard.bool(forKey: "kill_db") {
|
||||||
@@ -23,119 +19,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
|
|||||||
TestDataSource.load()
|
TestDataSource.load()
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
loadVPN { mgr in
|
|
||||||
self.managerVPN = mgr
|
|
||||||
self.postVPNState()
|
|
||||||
}
|
|
||||||
NSNotification.Name.NEVPNStatusDidChange.observe(call: #selector(vpnStatusChanged(_:)), on: self)
|
|
||||||
NotifyDNSFilterChanged.observe(call: #selector(didChangeDomainFilter), on: self)
|
|
||||||
|
|
||||||
sync.start()
|
sync.start()
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
@objc private func vpnStatusChanged(_ notification: Notification) {
|
|
||||||
postRawVPNState((notification.object as? NETunnelProviderSession)?.status ?? .invalid)
|
|
||||||
}
|
|
||||||
|
|
||||||
@objc private func didChangeDomainFilter() {
|
|
||||||
// Notify VPN extension about changes
|
|
||||||
if let session = self.managerVPN?.connection as? NETunnelProviderSession,
|
|
||||||
session.status == .connected {
|
|
||||||
try? session.sendProviderMessage("filter-update".data(using: .ascii)!, responseHandler: nil)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func setProxyEnabled(_ newState: Bool) {
|
|
||||||
guard let mgr = self.managerVPN else {
|
|
||||||
self.createNewVPN { manager in
|
|
||||||
self.managerVPN = manager
|
|
||||||
self.setProxyEnabled(newState)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
let state = mgr.isEnabled && (mgr.connection.status == .connected)
|
|
||||||
if state != newState {
|
|
||||||
self.updateVPN({ mgr.isEnabled = true }) {
|
|
||||||
newState ? try? mgr.connection.startVPNTunnel() : mgr.connection.stopVPNTunnel()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// MARK: VPN
|
|
||||||
|
|
||||||
private func createNewVPN(_ success: @escaping (_ manager: NETunnelProviderManager) -> Void) {
|
|
||||||
let mgr = NETunnelProviderManager()
|
|
||||||
mgr.localizedDescription = "AppCheck Monitor"
|
|
||||||
let proto = NETunnelProviderProtocol()
|
|
||||||
proto.providerBundleIdentifier = VPNConfigBundleIdentifier
|
|
||||||
proto.serverAddress = "127.0.0.1"
|
|
||||||
mgr.protocolConfiguration = proto
|
|
||||||
mgr.isEnabled = true
|
|
||||||
mgr.saveToPreferences { error in
|
|
||||||
guard error == nil else {
|
|
||||||
self.postProcessedVPNState(.off)
|
|
||||||
//ErrorAlert(error!).presentIn(self.window?.rootViewController)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
success(mgr)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private func loadVPN(_ finally: @escaping (_ manager: NETunnelProviderManager?) -> Void) {
|
|
||||||
NETunnelProviderManager.loadAllFromPreferences { managers, error in
|
|
||||||
guard let mgrs = managers, mgrs.count > 0 else {
|
|
||||||
finally(nil)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
for mgr in mgrs {
|
|
||||||
if let proto = (mgr.protocolConfiguration as? NETunnelProviderProtocol) {
|
|
||||||
if proto.providerBundleIdentifier == VPNConfigBundleIdentifier {
|
|
||||||
finally(mgr)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
finally(nil)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private func updateVPN(_ body: @escaping () -> Void, _ onSuccess: @escaping () -> Void) {
|
|
||||||
self.managerVPN?.loadFromPreferences { error in
|
|
||||||
guard error == nil else { return }
|
|
||||||
body()
|
|
||||||
self.managerVPN?.saveToPreferences { error in
|
|
||||||
guard error == nil else { return }
|
|
||||||
onSuccess()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private func postVPNState() {
|
|
||||||
guard let mgr = self.managerVPN else {
|
|
||||||
self.postRawVPNState(.invalid)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
mgr.loadFromPreferences { _ in
|
|
||||||
self.postRawVPNState(mgr.connection.status)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// MARK: Notifications
|
|
||||||
|
|
||||||
private func postRawVPNState(_ origState: NEVPNStatus) {
|
|
||||||
let state: VPNState
|
|
||||||
switch origState {
|
|
||||||
case .connected: state = .on
|
|
||||||
case .connecting, .disconnecting, .reasserting: state = .inbetween
|
|
||||||
case .invalid, .disconnected: fallthrough
|
|
||||||
@unknown default: state = .off
|
|
||||||
}
|
|
||||||
postProcessedVPNState(state)
|
|
||||||
}
|
|
||||||
|
|
||||||
private func postProcessedVPNState(_ state: VPNState) {
|
|
||||||
currentVPNState = state
|
|
||||||
NotifyVPNStateChanged.post(state)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
import UIKit
|
import UIKit
|
||||||
|
|
||||||
|
let sync = SyncUpdate(periodic: 7)
|
||||||
|
|
||||||
class SyncUpdate {
|
class SyncUpdate {
|
||||||
private var lastSync: TimeInterval = 0
|
private var lastSync: TimeInterval = 0
|
||||||
private var timer: Timer!
|
private var timer: Timer!
|
||||||
@@ -18,7 +20,7 @@ class SyncUpdate {
|
|||||||
private(set) var tsLatest: Timestamp? // as set per user, not actual latest
|
private(set) var tsLatest: Timestamp? // as set per user, not actual latest
|
||||||
|
|
||||||
|
|
||||||
init(periodic interval: TimeInterval) {
|
fileprivate init(periodic interval: TimeInterval) {
|
||||||
(filterType, tsEarliest, tsLatest) = Prefs.DateFilter.restrictions()
|
(filterType, tsEarliest, tsLatest) = Prefs.DateFilter.restrictions()
|
||||||
reloadRangeFromDB()
|
reloadRangeFromDB()
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +0,0 @@
|
|||||||
import Foundation
|
|
||||||
|
|
||||||
var currentVPNState: VPNState = .off
|
|
||||||
let sync = SyncUpdate(periodic: 7)
|
|
||||||
|
|
||||||
public enum VPNState : Int {
|
|
||||||
case on = 1, inbetween, off
|
|
||||||
}
|
|
||||||
111
main/GlassVPN.swift
Normal file
111
main/GlassVPN.swift
Normal file
@@ -0,0 +1,111 @@
|
|||||||
|
import NetworkExtension
|
||||||
|
|
||||||
|
let GlassVPN = GlassVPNManager()
|
||||||
|
|
||||||
|
enum VPNState : Int { case on = 1, inbetween, off }
|
||||||
|
|
||||||
|
final class GlassVPNManager {
|
||||||
|
static let bundleIdentifier = "de.uni-bamberg.psi.AppCheck.VPN"
|
||||||
|
private var managerVPN: NETunnelProviderManager?
|
||||||
|
private(set) var state: VPNState = .off
|
||||||
|
|
||||||
|
fileprivate init() {
|
||||||
|
NETunnelProviderManager.loadAllFromPreferences { managers, error in
|
||||||
|
self.managerVPN = managers?.first {
|
||||||
|
($0.protocolConfiguration as? NETunnelProviderProtocol)?
|
||||||
|
.providerBundleIdentifier == GlassVPNManager.bundleIdentifier
|
||||||
|
}
|
||||||
|
guard let mgr = self.managerVPN else {
|
||||||
|
self.postRawVPNState(.invalid)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
mgr.loadFromPreferences { _ in
|
||||||
|
self.postRawVPNState(mgr.connection.status)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
NSNotification.Name.NEVPNStatusDidChange.observe(call: #selector(vpnStatusChanged(_:)), on: self)
|
||||||
|
NotifyDNSFilterChanged.observe(call: #selector(didChangeDomainFilter), on: self)
|
||||||
|
}
|
||||||
|
|
||||||
|
func setEnabled(_ newState: Bool) {
|
||||||
|
guard let mgr = self.managerVPN else {
|
||||||
|
self.createNewVPN { manager in
|
||||||
|
self.managerVPN = manager
|
||||||
|
self.setEnabled(newState)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
let state = mgr.isEnabled && (mgr.connection.status == .connected)
|
||||||
|
if state != newState {
|
||||||
|
self.updateVPN({ mgr.isEnabled = true }) {
|
||||||
|
newState ? try? mgr.connection.startVPNTunnel() : mgr.connection.stopVPNTunnel()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// MARK: - Notify callback
|
||||||
|
|
||||||
|
@objc private func vpnStatusChanged(_ notification: Notification) {
|
||||||
|
postRawVPNState((notification.object as? NETunnelProviderSession)?.status ?? .invalid)
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc private func didChangeDomainFilter() {
|
||||||
|
// Notify VPN extension about changes
|
||||||
|
if let session = self.managerVPN?.connection as? NETunnelProviderSession,
|
||||||
|
session.status == .connected {
|
||||||
|
try? session.sendProviderMessage("filter-update".data(using: .ascii)!, responseHandler: nil)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// MARK: - Manage configuration
|
||||||
|
|
||||||
|
private func createNewVPN(_ success: @escaping (_ manager: NETunnelProviderManager) -> Void) {
|
||||||
|
let mgr = NETunnelProviderManager()
|
||||||
|
mgr.localizedDescription = "AppCheck Monitor"
|
||||||
|
let proto = NETunnelProviderProtocol()
|
||||||
|
proto.providerBundleIdentifier = GlassVPNManager.bundleIdentifier
|
||||||
|
proto.serverAddress = "127.0.0.1"
|
||||||
|
mgr.protocolConfiguration = proto
|
||||||
|
mgr.isEnabled = true
|
||||||
|
mgr.saveToPreferences { error in
|
||||||
|
guard error == nil else {
|
||||||
|
self.postProcessedVPNState(.off)
|
||||||
|
//ErrorAlert(error!).presentIn(self.window?.rootViewController)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
success(mgr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private func updateVPN(_ body: @escaping () -> Void, _ onSuccess: @escaping () -> Void) {
|
||||||
|
self.managerVPN?.loadFromPreferences { error in
|
||||||
|
guard error == nil else { return }
|
||||||
|
body()
|
||||||
|
self.managerVPN?.saveToPreferences { error in
|
||||||
|
guard error == nil else { return }
|
||||||
|
onSuccess()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// MARK: - Post Notifications
|
||||||
|
|
||||||
|
private func postRawVPNState(_ origState: NEVPNStatus) {
|
||||||
|
let state: VPNState
|
||||||
|
switch origState {
|
||||||
|
case .connected: state = .on
|
||||||
|
case .connecting, .disconnecting, .reasserting: state = .inbetween
|
||||||
|
case .invalid, .disconnected: fallthrough
|
||||||
|
@unknown default: state = .off
|
||||||
|
}
|
||||||
|
postProcessedVPNState(state)
|
||||||
|
}
|
||||||
|
|
||||||
|
private func postProcessedVPNState(_ state: VPNState) {
|
||||||
|
self.state = state
|
||||||
|
NotifyVPNStateChanged.post(state)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -10,32 +10,28 @@ class TVCSettings: UITableViewController {
|
|||||||
|
|
||||||
override func viewDidLoad() {
|
override func viewDidLoad() {
|
||||||
super.viewDidLoad()
|
super.viewDidLoad()
|
||||||
NotifyVPNStateChanged.observe(call: #selector(vpnStateChanged(_:)), on: self)
|
reloadToggleState()
|
||||||
changedState(currentVPNState)
|
|
||||||
NotifyDNSFilterChanged.observe(call: #selector(reloadDataSource), on: self)
|
|
||||||
reloadDataSource()
|
reloadDataSource()
|
||||||
|
NotifyVPNStateChanged.observe(call: #selector(reloadToggleState), on: self)
|
||||||
|
NotifyDNSFilterChanged.observe(call: #selector(reloadDataSource), on: self)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// MARK: - VPN Proxy Settings
|
// MARK: - VPN Proxy Settings
|
||||||
|
|
||||||
@IBAction private func toggleVPNProxy(_ sender: UISwitch) {
|
@IBAction private func toggleVPNProxy(_ sender: UISwitch) {
|
||||||
appDelegate.setProxyEnabled(sender.isOn)
|
GlassVPN.setEnabled(sender.isOn)
|
||||||
}
|
}
|
||||||
|
|
||||||
@objc func vpnStateChanged(_ notification: Notification) {
|
@objc private func reloadToggleState() {
|
||||||
changedState(notification.object as! VPNState)
|
vpnToggle.isOn = (GlassVPN.state != .off)
|
||||||
}
|
vpnToggle.onTintColor = (GlassVPN.state == .inbetween ? .systemYellow : nil)
|
||||||
|
|
||||||
func changedState(_ newState: VPNState) {
|
|
||||||
vpnToggle.isOn = (newState != .off)
|
|
||||||
vpnToggle.onTintColor = (newState == .inbetween ? .systemYellow : nil)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// MARK: - Logging Filter
|
// MARK: - Logging Filter
|
||||||
|
|
||||||
@objc func reloadDataSource() {
|
@objc private func reloadDataSource() {
|
||||||
let (blocked, ignored) = DomainFilter.counts()
|
let (blocked, ignored) = DomainFilter.counts()
|
||||||
cellDomainsIgnored.detailTextLabel?.text = "\(ignored) Domains"
|
cellDomainsIgnored.detailTextLabel?.text = "\(ignored) Domains"
|
||||||
cellDomainsBlocked.detailTextLabel?.text = "\(blocked) Domains"
|
cellDomainsBlocked.detailTextLabel?.text = "\(blocked) Domains"
|
||||||
|
|||||||
@@ -5,15 +5,31 @@ class TBCMain: UITabBarController {
|
|||||||
|
|
||||||
override func viewDidLoad() {
|
override func viewDidLoad() {
|
||||||
super.viewDidLoad()
|
super.viewDidLoad()
|
||||||
NotifyVPNStateChanged.observe(call: #selector(vpnStateChanged(_:)), on: self)
|
reloadTabBarBadge()
|
||||||
changedState(currentVPNState)
|
NotifyVPNStateChanged.observe(call: #selector(reloadTabBarBadge), on: self)
|
||||||
|
|
||||||
if !Prefs.DidShowTutorial.Welcome {
|
if !Prefs.DidShowTutorial.Welcome {
|
||||||
self.perform(#selector(showWelcomeMessage), with: nil, afterDelay: 0.5)
|
self.perform(#selector(showWelcomeMessage), with: nil, afterDelay: 0.5)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@objc func showWelcomeMessage() {
|
@objc private func reloadTabBarBadge() {
|
||||||
|
let stateView = self.tabBar.items?.last
|
||||||
|
switch GlassVPN.state {
|
||||||
|
case .on: stateView?.badgeValue = "✓"
|
||||||
|
case .inbetween: stateView?.badgeValue = "⋯"
|
||||||
|
case .off: stateView?.badgeValue = "✗"
|
||||||
|
}
|
||||||
|
if #available(iOS 10.0, *) {
|
||||||
|
switch GlassVPN.state {
|
||||||
|
case .on: stateView?.badgeColor = .systemGreen
|
||||||
|
case .inbetween: stateView?.badgeColor = .systemYellow
|
||||||
|
case .off: stateView?.badgeColor = .systemRed
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc private func showWelcomeMessage() {
|
||||||
let x = TutorialSheet()
|
let x = TutorialSheet()
|
||||||
x.addSheet().addArrangedSubview(QuickUI.text(attributed: NSMutableAttributedString()
|
x.addSheet().addArrangedSubview(QuickUI.text(attributed: NSMutableAttributedString()
|
||||||
.h1("Welcome\n")
|
.h1("Welcome\n")
|
||||||
@@ -40,24 +56,4 @@ class TBCMain: UITabBarController {
|
|||||||
Prefs.DidShowTutorial.Welcome = true
|
Prefs.DidShowTutorial.Welcome = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@objc func vpnStateChanged(_ notification: Notification) {
|
|
||||||
changedState(notification.object as! VPNState)
|
|
||||||
}
|
|
||||||
|
|
||||||
func changedState(_ newState: VPNState) {
|
|
||||||
let stateView = self.tabBar.items?.last
|
|
||||||
switch newState {
|
|
||||||
case .on: stateView?.badgeValue = "✓"
|
|
||||||
case .inbetween: stateView?.badgeValue = "⋯"
|
|
||||||
case .off: stateView?.badgeValue = "✗"
|
|
||||||
}
|
|
||||||
if #available(iOS 10.0, *) {
|
|
||||||
switch newState {
|
|
||||||
case .on: stateView?.badgeColor = .systemGreen
|
|
||||||
case .inbetween: stateView?.badgeColor = .systemYellow
|
|
||||||
case .off: stateView?.badgeColor = .systemRed
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user