From 10aec5185d4d866a5dee941e8566f56989bb1ad6 Mon Sep 17 00:00:00 2001 From: Davide De Rosa Date: Sat, 13 Jun 2020 15:30:48 +0200 Subject: [PATCH] Document Manager subspec Refactor notifications to newer Swift convention. --- .jazzy.yaml | 10 +++ Demo/BasicTunnel-iOS/ViewController.swift | 2 +- Demo/BasicTunnel-macOS/ViewController.swift | 2 +- .../AppExtension/InterfaceObserver.swift | 2 +- .../Sources/Manager/MockVPNProvider.swift | 11 ++-- .../Sources/Manager/StandardVPNProvider.swift | 7 +- TunnelKit/Sources/Manager/VPN.swift | 12 ++++ .../Sources/Manager/VPNConfiguration.swift | 6 ++ TunnelKit/Sources/Manager/VPNProvider.swift | 65 ++++++++++++++++--- TunnelKit/Sources/Manager/VPNStatus.swift | 6 ++ 10 files changed, 103 insertions(+), 20 deletions(-) diff --git a/.jazzy.yaml b/.jazzy.yaml index d5a0d1a..ff5f93c 100644 --- a/.jazzy.yaml +++ b/.jazzy.yaml @@ -43,6 +43,16 @@ custom_categories: - NETunnelInterface - NEUDPSocket - NSNotification + - name: Manager + children: + - VPN + - VPNProvider + - MockVPNProvider + - StandardVPNProvider + - VPNConfiguration + - NetworkExtensionVPNConfiguration + - VPNStatus + - NSNotification - name: Protocols/OpenVPN children: - OpenVPN diff --git a/Demo/BasicTunnel-iOS/ViewController.swift b/Demo/BasicTunnel-iOS/ViewController.swift index 0361336..e5f7e36 100644 --- a/Demo/BasicTunnel-iOS/ViewController.swift +++ b/Demo/BasicTunnel-iOS/ViewController.swift @@ -62,7 +62,7 @@ class ViewController: UIViewController, URLSessionDataDelegate { NotificationCenter.default.addObserver( self, selector: #selector(VPNStatusDidChange(notification:)), - name: .VPNDidChangeStatus, + name: VPN.didChangeStatus, object: nil ) diff --git a/Demo/BasicTunnel-macOS/ViewController.swift b/Demo/BasicTunnel-macOS/ViewController.swift index 33fa275..7196256 100644 --- a/Demo/BasicTunnel-macOS/ViewController.swift +++ b/Demo/BasicTunnel-macOS/ViewController.swift @@ -58,7 +58,7 @@ class ViewController: NSViewController { NotificationCenter.default.addObserver( self, selector: #selector(VPNStatusDidChange(notification:)), - name: .NEVPNStatusDidChange, + name: VPN.didChangeStatus, object: nil ) diff --git a/TunnelKit/Sources/AppExtension/InterfaceObserver.swift b/TunnelKit/Sources/AppExtension/InterfaceObserver.swift index c1ad3d0..f364f84 100644 --- a/TunnelKit/Sources/AppExtension/InterfaceObserver.swift +++ b/TunnelKit/Sources/AppExtension/InterfaceObserver.swift @@ -44,7 +44,7 @@ private let log = SwiftyBeaver.self public class InterfaceObserver: NSObject { /// A change in Wi-Fi state occurred. - public static let didDetectWifiChange = NSNotification.Name("InterfaceObserverDidDetectWifiChange") + public static let didDetectWifiChange = Notification.Name("InterfaceObserverDidDetectWifiChange") private var queue: DispatchQueue? diff --git a/TunnelKit/Sources/Manager/MockVPNProvider.swift b/TunnelKit/Sources/Manager/MockVPNProvider.swift index 3e8dd00..8a363e1 100644 --- a/TunnelKit/Sources/Manager/MockVPNProvider.swift +++ b/TunnelKit/Sources/Manager/MockVPNProvider.swift @@ -25,6 +25,7 @@ import Foundation +/// :nodoc: public class MockVPNProvider: VPNProvider { public let isPrepared: Bool = true @@ -33,7 +34,7 @@ public class MockVPNProvider: VPNProvider { public private(set) var status: VPNStatus = .disconnected public func prepare(completionHandler: (() -> Void)?) { - NotificationCenter.default.post(name: .VPNDidPrepare, object: nil) + NotificationCenter.default.post(name: VPN.didPrepare, object: nil) completionHandler?() } @@ -45,28 +46,28 @@ public class MockVPNProvider: VPNProvider { public func connect(completionHandler: ((Error?) -> Void)?) { isEnabled = true status = .connected - NotificationCenter.default.post(name: .VPNDidChangeStatus, object: self) + NotificationCenter.default.post(name: VPN.didChangeStatus, object: self) completionHandler?(nil) } public func disconnect(completionHandler: ((Error?) -> Void)?) { isEnabled = false status = .disconnected - NotificationCenter.default.post(name: .VPNDidChangeStatus, object: self) + NotificationCenter.default.post(name: VPN.didChangeStatus, object: self) completionHandler?(nil) } public func reconnect(configuration: VPNConfiguration, completionHandler: ((Error?) -> Void)?) { isEnabled = true status = .connected - NotificationCenter.default.post(name: .VPNDidChangeStatus, object: self) + NotificationCenter.default.post(name: VPN.didChangeStatus, object: self) completionHandler?(nil) } public func uninstall(completionHandler: (() -> Void)?) { isEnabled = false status = .disconnected - NotificationCenter.default.post(name: .VPNDidChangeStatus, object: self) + NotificationCenter.default.post(name: VPN.didChangeStatus, object: self) completionHandler?() } diff --git a/TunnelKit/Sources/Manager/StandardVPNProvider.swift b/TunnelKit/Sources/Manager/StandardVPNProvider.swift index 518f015..fe76b6f 100644 --- a/TunnelKit/Sources/Manager/StandardVPNProvider.swift +++ b/TunnelKit/Sources/Manager/StandardVPNProvider.swift @@ -26,6 +26,7 @@ import Foundation import NetworkExtension +/// :nodoc: public class StandardVPNProvider: VPNProvider { private let bundleIdentifier: String @@ -83,7 +84,7 @@ public class StandardVPNProvider: VPNProvider { public func prepare(completionHandler: (() -> Void)?) { find(with: bundleIdentifier) { self.manager = $0 - NotificationCenter.default.post(name: .VPNDidPrepare, object: nil) + NotificationCenter.default.post(name: VPN.didPrepare, object: nil) completionHandler?() } } @@ -307,10 +308,10 @@ public class StandardVPNProvider: VPNProvider { } lastNotifiedStatus = status - NotificationCenter.default.post(name: .VPNDidChangeStatus, object: self) + NotificationCenter.default.post(name: VPN.didChangeStatus, object: self) } @objc private func vpnDidReinstall(_ notification: Notification) { - NotificationCenter.default.post(name: .VPNDidReinstall, object: self) + NotificationCenter.default.post(name: VPN.didReinstall, object: self) } } diff --git a/TunnelKit/Sources/Manager/VPN.swift b/TunnelKit/Sources/Manager/VPN.swift index f336318..9133332 100644 --- a/TunnelKit/Sources/Manager/VPN.swift +++ b/TunnelKit/Sources/Manager/VPN.swift @@ -25,6 +25,18 @@ import Foundation +/// Wrapper for shared access to VPN-related objects. public class VPN { + + /// The VPN became ready to use. + public static let didPrepare = Notification.Name("VPNDidPrepare") + + /// The VPN did change status. + public static let didChangeStatus = Notification.Name("VPNDidChangeStatus") + + /// The VPN profile did (re)install. + public static let didReinstall = Notification.Name("VPNDidReinstall") + + /// A singleton `VPNProvider` instance (default is a `MockVPNProvider`). Make sure to set this on app launch. public static var shared: VPNProvider = MockVPNProvider() } diff --git a/TunnelKit/Sources/Manager/VPNConfiguration.swift b/TunnelKit/Sources/Manager/VPNConfiguration.swift index 58412f3..16f42ea 100644 --- a/TunnelKit/Sources/Manager/VPNConfiguration.swift +++ b/TunnelKit/Sources/Manager/VPNConfiguration.swift @@ -26,14 +26,20 @@ import Foundation import NetworkExtension +/// Generic marker for objects able to configure a `VPNProvider`. public protocol VPNConfiguration { } +/// A `VPNConfiguration` built on top of NetworkExtension entities. public struct NetworkExtensionVPNConfiguration: VPNConfiguration { + + /// The `NETunnelProviderProtocol` object embedding tunnel configuration. public let protocolConfiguration: NETunnelProviderProtocol + /// The on-demand rules to establish. public let onDemandRules: [NEOnDemandRule] + /// :nodoc: public init(protocolConfiguration: NETunnelProviderProtocol, onDemandRules: [NEOnDemandRule]) { self.protocolConfiguration = protocolConfiguration self.onDemandRules = onDemandRules diff --git a/TunnelKit/Sources/Manager/VPNProvider.swift b/TunnelKit/Sources/Manager/VPNProvider.swift index c0f4167..6d2dd73 100644 --- a/TunnelKit/Sources/Manager/VPNProvider.swift +++ b/TunnelKit/Sources/Manager/VPNProvider.swift @@ -25,36 +25,83 @@ import Foundation +/// Helps controlling a VPN without messing with underlying implementations. public protocol VPNProvider: class { + + /// `true` if the VPN is ready for use. var isPrepared: Bool { get } + /// `true` if the associated VPN profile is enabled. var isEnabled: Bool { get } + /// The status of the VPN. var status: VPNStatus { get } - + + /** + Prepares the VPN for use. + + - Postcondition: The VPN is ready to use and `isPrepared` becomes `true`. + - Parameter completionHandler: The completion handler. + - Seealso: `isPrepared` + */ func prepare(completionHandler: (() -> Void)?) + /** + Installs the VPN profile. + + - Parameter configuration: The `VPNConfiguration` to install. + - Parameter completionHandler: The completion handler with an optional error. + */ func install(configuration: VPNConfiguration, completionHandler: ((Error?) -> Void)?) + /** + Connects to the VPN. + + - Parameter completionHandler: The completion handler with an optional error. + */ func connect(completionHandler: ((Error?) -> Void)?) + /** + Disconnects from the VPN. + + - Parameter completionHandler: The completion handler with an optional error. + */ func disconnect(completionHandler: ((Error?) -> Void)?) + /** + Reconnects to the VPN. + + - Parameter configuration: The `VPNConfiguration` to install. + - Parameter completionHandler: The completion handler with an optional error. + */ func reconnect(configuration: VPNConfiguration, completionHandler: ((Error?) -> Void)?) + /** + Uninstalls the VPN profile. + + - Parameter completionHandler: The completion handler. + */ func uninstall(completionHandler: (() -> Void)?) + /** + Request a debug log from the VPN. + + - Parameter fallback: The block resolving to a fallback `String` if no debug log is available. + - Parameter completionHandler: The completion handler with the debug log. + */ func requestDebugLog(fallback: (() -> String)?, completionHandler: @escaping (String) -> Void) + /** + Requests the current received/sent bytes count from the VPN. + + - Parameter completionHandler: The completion handler with an optional received/sent bytes count. + */ func requestBytesCount(completionHandler: @escaping ((UInt, UInt)?) -> Void) + /** + Requests the server configuration from the VPN. + + - Parameter completionHandler: The completion handler with an optional configuration object. + */ func requestServerConfiguration(completionHandler: @escaping (Any?) -> Void) } - -public extension Notification.Name { - static let VPNDidPrepare = Notification.Name("VPNDidPrepare") - - static let VPNDidChangeStatus = Notification.Name("VPNDidChangeStatus") - - static let VPNDidReinstall = Notification.Name("VPNDidReinstall") -} diff --git a/TunnelKit/Sources/Manager/VPNStatus.swift b/TunnelKit/Sources/Manager/VPNStatus.swift index 7f46a74..2f0d84b 100644 --- a/TunnelKit/Sources/Manager/VPNStatus.swift +++ b/TunnelKit/Sources/Manager/VPNStatus.swift @@ -25,12 +25,18 @@ import Foundation +/// Status of a `VPNProvider`. public enum VPNStatus { + + /// VPN is connected. case connected + /// VPN is attempting a connection. case connecting + /// VPN is disconnected. case disconnected + /// VPN is completing a disconnection. case disconnecting }