Make framework internal components public
This commit is contained in:
parent
cf499739f7
commit
f661008679
|
@ -27,27 +27,27 @@ import Foundation
|
|||
import TunnelKit
|
||||
import SwiftyBeaver
|
||||
|
||||
class AppConstants {
|
||||
class Flags {
|
||||
static let isBeta = false
|
||||
public class AppConstants {
|
||||
public class Flags {
|
||||
public static let isBeta = false
|
||||
}
|
||||
|
||||
class Domain {
|
||||
static let name = "passepartoutvpn.app"
|
||||
public class Domain {
|
||||
public static let name = "passepartoutvpn.app"
|
||||
}
|
||||
|
||||
class Store {
|
||||
static let serviceFilename = "ConnectionService.json"
|
||||
public class Store {
|
||||
public static let serviceFilename = "ConnectionService.json"
|
||||
|
||||
static let webCacheDirectory = "Web"
|
||||
public static let webCacheDirectory = "Web"
|
||||
|
||||
static let providersDirectory = "Providers"
|
||||
public static let providersDirectory = "Providers"
|
||||
|
||||
static let hostsDirectory = "Hosts"
|
||||
public static let hostsDirectory = "Hosts"
|
||||
}
|
||||
|
||||
class VPN {
|
||||
static func baseConfiguration() -> TunnelKitProvider.Configuration {
|
||||
public class VPN {
|
||||
public static func baseConfiguration() -> TunnelKitProvider.Configuration {
|
||||
let sessionBuilder = SessionProxy.ConfigurationBuilder(ca: CryptoContainer(pem: ""))
|
||||
var builder = TunnelKitProvider.ConfigurationBuilder(sessionConfiguration: sessionBuilder.build())
|
||||
builder.mtu = 1250
|
||||
|
@ -66,37 +66,37 @@ class AppConstants {
|
|||
"https://www.instagram.com"
|
||||
]
|
||||
|
||||
static let connectivityURL = URL(string: connectivityStrings.customRandomElement())!
|
||||
public static let connectivityURL = URL(string: connectivityStrings.customRandomElement())!
|
||||
|
||||
static let connectivityTimeout: TimeInterval = 10.0
|
||||
public static let connectivityTimeout: TimeInterval = 10.0
|
||||
}
|
||||
|
||||
class Web {
|
||||
public class Web {
|
||||
private static let version = "v1"
|
||||
|
||||
private static let baseURL = Repos.api.appendingPathComponent(version)
|
||||
|
||||
static func url(path: String) -> URL {
|
||||
public static func url(path: String) -> URL {
|
||||
return baseURL.appendingPathComponent(path)
|
||||
}
|
||||
|
||||
static let timeout: TimeInterval = 3.0
|
||||
public static let timeout: TimeInterval = 3.0
|
||||
|
||||
static let minimumUpdateInterval: TimeInterval = 600.0 // 10 minutes
|
||||
public static let minimumUpdateInterval: TimeInterval = 600.0 // 10 minutes
|
||||
}
|
||||
|
||||
class Log {
|
||||
static let level: SwiftyBeaver.Level = .debug
|
||||
public class Log {
|
||||
public static let level: SwiftyBeaver.Level = .debug
|
||||
|
||||
static let debugFormat = "$DHH:mm:ss$d - $M"
|
||||
public static let debugFormat = "$DHH:mm:ss$d - $M"
|
||||
|
||||
static var debugSnapshot: () -> String = { TransientStore.shared.service.vpnLog }
|
||||
public static var debugSnapshot: () -> String = { TransientStore.shared.service.vpnLog }
|
||||
|
||||
static let viewerRefreshInterval: TimeInterval = 3.0
|
||||
public static let viewerRefreshInterval: TimeInterval = 3.0
|
||||
|
||||
private static let fileName = "Debug.log"
|
||||
|
||||
static var fileURL: URL {
|
||||
public static var fileURL: URL {
|
||||
return GroupConstants.App.cachesURL.appendingPathComponent(fileName)
|
||||
}
|
||||
|
||||
|
@ -115,51 +115,51 @@ class AppConstants {
|
|||
return dest
|
||||
}()
|
||||
|
||||
static func configure() {
|
||||
public static func configure() {
|
||||
SwiftyBeaver.addDestination(console)
|
||||
SwiftyBeaver.addDestination(file)
|
||||
}
|
||||
}
|
||||
|
||||
class IssueReporter {
|
||||
static let recipient = "issues@\(Domain.name)"
|
||||
public class IssueReporter {
|
||||
public static let recipient = "issues@\(Domain.name)"
|
||||
|
||||
class Filenames {
|
||||
static var debugLog: String {
|
||||
public class Filenames {
|
||||
public static var debugLog: String {
|
||||
let fmt = DateFormatter()
|
||||
fmt.dateFormat = "yyyyMMdd-HHmmss"
|
||||
let iso = fmt.string(from: Date())
|
||||
return "debug-\(iso).txt"
|
||||
}
|
||||
|
||||
static let configuration = "profile.ovpn"
|
||||
// static let configuration = "profile.ovpn.txt"
|
||||
public static let configuration = "profile.ovpn"
|
||||
// public static let configuration = "profile.ovpn.txt"
|
||||
}
|
||||
|
||||
class MIME {
|
||||
static let debugLog = "text/plain"
|
||||
public class MIME {
|
||||
public static let debugLog = "text/plain"
|
||||
|
||||
// static let configuration = "application/x-openvpn-profile"
|
||||
static let configuration = "text/plain"
|
||||
// public static let configuration = "application/x-openvpn-profile"
|
||||
public static let configuration = "text/plain"
|
||||
}
|
||||
}
|
||||
|
||||
class URLs {
|
||||
static let website = URL(string: "https://\(Domain.name)")!
|
||||
public class URLs {
|
||||
public static let website = URL(string: "https://\(Domain.name)")!
|
||||
|
||||
static let faq = website.appendingPathComponent("faq")
|
||||
public static let faq = website.appendingPathComponent("faq")
|
||||
|
||||
static let disclaimer = website.appendingPathComponent("disclaimer")
|
||||
public static let disclaimer = website.appendingPathComponent("disclaimer")
|
||||
|
||||
static let privacyPolicy = website.appendingPathComponent("privacy")
|
||||
public static let privacyPolicy = website.appendingPathComponent("privacy")
|
||||
|
||||
static let changelog = Repos.ios.appendingPathComponent("blob/master/CHANGELOG.md")
|
||||
public static let changelog = Repos.ios.appendingPathComponent("blob/master/CHANGELOG.md")
|
||||
|
||||
static let subreddit = URL(string: "https://www.reddit.com/r/passepartout")!
|
||||
public static let subreddit = URL(string: "https://www.reddit.com/r/passepartout")!
|
||||
|
||||
private static let twitterHashtags = ["OpenVPN", "iOS", "macOS"]
|
||||
|
||||
static var twitterIntent: URL {
|
||||
public static var twitterIntent: URL {
|
||||
var text = L10n.Share.message
|
||||
for ht in twitterHashtags {
|
||||
text = text.replacingOccurrences(of: ht, with: "#\(ht)")
|
||||
|
@ -173,17 +173,17 @@ class AppConstants {
|
|||
return comps.url!
|
||||
}
|
||||
|
||||
static func review(withId id: String) -> URL {
|
||||
public static func review(withId id: String) -> URL {
|
||||
return URL(string: "https://itunes.apple.com/app/id\(id)?action=write-review")!
|
||||
}
|
||||
|
||||
static let referrals: [Infrastructure.Name: String] = [
|
||||
public static let referrals: [Infrastructure.Name: String] = [
|
||||
.pia: "https://www.privateinternetaccess.com/pages/buy-vpn/",
|
||||
.tunnelBear: "https://click.tunnelbear.com/aff_c?offer_id=2&aff_id=7464"
|
||||
]
|
||||
}
|
||||
|
||||
class Repos {
|
||||
public class Repos {
|
||||
private static let githubRoot = URL(string: "https://github.com/passepartoutvpn/")!
|
||||
|
||||
private static let githubRawRoot = URL(string: "https://\(Domain.name)/")!
|
||||
|
@ -196,25 +196,25 @@ class AppConstants {
|
|||
return githubRawRoot.appendingPathComponent(repo)
|
||||
}
|
||||
|
||||
static let ios = github(repo: "passepartout-ios")
|
||||
public static let ios = github(repo: "passepartout-ios")
|
||||
|
||||
static let api = githubRaw(repo: "api")
|
||||
public static let api = githubRaw(repo: "api")
|
||||
}
|
||||
|
||||
struct License {
|
||||
let name: String
|
||||
public struct License {
|
||||
public let name: String
|
||||
|
||||
let type: String
|
||||
public let type: String
|
||||
|
||||
let url: URL
|
||||
public let url: URL
|
||||
|
||||
init(_ name: String, _ type: String, _ urlString: String) {
|
||||
public init(_ name: String, _ type: String, _ urlString: String) {
|
||||
self.name = name
|
||||
self.type = type
|
||||
url = URL(string: urlString)!
|
||||
}
|
||||
|
||||
static let all: [License] = [
|
||||
public static let all: [License] = [
|
||||
License(
|
||||
"MBProgressHUD",
|
||||
"MIT",
|
||||
|
@ -242,20 +242,20 @@ class AppConstants {
|
|||
)
|
||||
]
|
||||
|
||||
static var cachedContent: [String: String] = [:]
|
||||
public static var cachedContent: [String: String] = [:]
|
||||
}
|
||||
|
||||
struct Notice {
|
||||
let name: String
|
||||
public struct Notice {
|
||||
public let name: String
|
||||
|
||||
let statement: String
|
||||
public let statement: String
|
||||
|
||||
init(_ name: String, _ statement: String) {
|
||||
public init(_ name: String, _ statement: String) {
|
||||
self.name = name
|
||||
self.statement = statement
|
||||
}
|
||||
|
||||
static let all: [Notice] = [
|
||||
public static let all: [Notice] = [
|
||||
Notice(
|
||||
"Circle Icons",
|
||||
"The logo is taken from the awesome Circle Icons set by Nick Roach."
|
||||
|
@ -267,7 +267,7 @@ class AppConstants {
|
|||
]
|
||||
}
|
||||
|
||||
struct Rating {
|
||||
static let eventCount = 3
|
||||
public struct Rating {
|
||||
public static let eventCount = 3
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
|
||||
import Foundation
|
||||
|
||||
enum ApplicationError: String, Error {
|
||||
public enum ApplicationError: String, Error {
|
||||
case missingProfile
|
||||
|
||||
case missingCredentials
|
||||
|
|
|
@ -25,33 +25,33 @@
|
|||
|
||||
import Foundation
|
||||
|
||||
class GroupConstants {
|
||||
class App {
|
||||
static let name = "Passepartout"
|
||||
public class GroupConstants {
|
||||
public class App {
|
||||
public static let name = "Passepartout"
|
||||
|
||||
static let tunnelKitName = "TunnelKit"
|
||||
public static let tunnelKitName = "TunnelKit"
|
||||
|
||||
static let title = name
|
||||
// static let title = "\u{1F511}"
|
||||
public static let title = name
|
||||
// public static let title = "\u{1F511}"
|
||||
|
||||
static let versionNumber = Bundle.main.infoDictionary!["CFBundleShortVersionString"] as! String
|
||||
public static let versionNumber = Bundle.main.infoDictionary!["CFBundleShortVersionString"] as! String
|
||||
|
||||
static let buildNumber = Int(Bundle.main.infoDictionary![kCFBundleVersionKey as String] as! String)!
|
||||
public static let buildNumber = Int(Bundle.main.infoDictionary![kCFBundleVersionKey as String] as! String)!
|
||||
|
||||
static let versionString = "\(versionNumber) (\(buildNumber))"
|
||||
public static let versionString = "\(versionNumber) (\(buildNumber))"
|
||||
|
||||
static let teamId = "DTDYD63ZX9"
|
||||
public static let teamId = "DTDYD63ZX9"
|
||||
|
||||
static let appId = "1433648537"
|
||||
public static let appId = "1433648537"
|
||||
|
||||
#if os(iOS)
|
||||
static let appGroup = "group.com.algoritmico.Passepartout"
|
||||
public static let appGroup = "group.com.algoritmico.Passepartout"
|
||||
|
||||
static let tunnelIdentifier = "com.algoritmico.ios.Passepartout.Tunnel"
|
||||
public static let tunnelIdentifier = "com.algoritmico.ios.Passepartout.Tunnel"
|
||||
#else
|
||||
static let appGroup = "\(teamId).group.com.algoritmico.Passepartout"
|
||||
public static let appGroup = "\(teamId).group.com.algoritmico.Passepartout"
|
||||
|
||||
static let tunnelIdentifier = "com.algoritmico.macos.Passepartout.Tunnel"
|
||||
public static let tunnelIdentifier = "com.algoritmico.macos.Passepartout.Tunnel"
|
||||
#endif
|
||||
|
||||
private static var containerURL: URL {
|
||||
|
@ -62,22 +62,22 @@ class GroupConstants {
|
|||
return url
|
||||
}
|
||||
|
||||
static let documentsURL: URL = {
|
||||
public static let documentsURL: URL = {
|
||||
let url = containerURL.appendingPathComponent("Documents", isDirectory: true)
|
||||
try? FileManager.default.createDirectory(at: url, withIntermediateDirectories: true, attributes: nil)
|
||||
return url
|
||||
}()
|
||||
|
||||
static let cachesURL: URL = {
|
||||
public static let cachesURL: URL = {
|
||||
let url = containerURL.appendingPathComponent("Library/Caches", isDirectory: true)
|
||||
try? FileManager.default.createDirectory(at: url, withIntermediateDirectories: true, attributes: nil)
|
||||
return url
|
||||
}()
|
||||
}
|
||||
|
||||
class VPN {
|
||||
static let dnsTimeout = 5000
|
||||
public class VPN {
|
||||
public static let dnsTimeout = 5000
|
||||
|
||||
static let sessionMarker = "--- EOF ---"
|
||||
public static let sessionMarker = "--- EOF ---"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,13 +27,13 @@ import Foundation
|
|||
import TunnelKit
|
||||
import NetworkExtension
|
||||
|
||||
enum Context: String, Codable {
|
||||
public enum Context: String, Codable {
|
||||
case provider
|
||||
|
||||
case host
|
||||
}
|
||||
|
||||
protocol ConnectionProfile: class, EndpointDataSource, CustomStringConvertible {
|
||||
public protocol ConnectionProfile: class, EndpointDataSource, CustomStringConvertible {
|
||||
var context: Context { get }
|
||||
|
||||
var id: String { get }
|
||||
|
@ -47,7 +47,7 @@ protocol ConnectionProfile: class, EndpointDataSource, CustomStringConvertible {
|
|||
func with(newId: String) -> ConnectionProfile
|
||||
}
|
||||
|
||||
extension ConnectionProfile {
|
||||
public extension ConnectionProfile {
|
||||
var passwordKey: String? {
|
||||
guard let username = username else {
|
||||
return nil
|
||||
|
@ -81,7 +81,7 @@ extension ConnectionProfile {
|
|||
}
|
||||
}
|
||||
|
||||
extension ConnectionProfile {
|
||||
public extension ConnectionProfile {
|
||||
var description: String {
|
||||
return "(\(context):\(id))"
|
||||
}
|
||||
|
|
|
@ -28,7 +28,7 @@ import SwiftyBeaver
|
|||
|
||||
private let log = SwiftyBeaver.self
|
||||
|
||||
extension ConnectionService {
|
||||
public extension ConnectionService {
|
||||
func save(configurationURL: URL, for key: ProfileKey) throws -> URL {
|
||||
let destinationURL = targetConfigurationURL(for: key)
|
||||
let fm = FileManager.default
|
||||
|
|
|
@ -28,7 +28,7 @@ import SwiftyBeaver
|
|||
|
||||
private let log = SwiftyBeaver.self
|
||||
|
||||
extension ConnectionService {
|
||||
public extension ConnectionService {
|
||||
static func migrateJSON(from: URL, to: URL) {
|
||||
do {
|
||||
let newData = try migrateJSON(at: from)
|
||||
|
|
|
@ -30,7 +30,7 @@ import SwiftyBeaver
|
|||
|
||||
private let log = SwiftyBeaver.self
|
||||
|
||||
protocol ConnectionServiceDelegate: class {
|
||||
public protocol ConnectionServiceDelegate: class {
|
||||
func connectionService(didAdd profile: ConnectionProfile)
|
||||
|
||||
func connectionService(didRename oldProfile: ConnectionProfile, to newProfile: ConnectionProfile)
|
||||
|
@ -42,8 +42,8 @@ protocol ConnectionServiceDelegate: class {
|
|||
func connectionService(didActivate profile: ConnectionProfile)
|
||||
}
|
||||
|
||||
class ConnectionService: Codable {
|
||||
enum CodingKeys: String, CodingKey {
|
||||
public class ConnectionService: Codable {
|
||||
public enum CodingKeys: String, CodingKey {
|
||||
case build
|
||||
|
||||
case appGroup
|
||||
|
@ -55,9 +55,9 @@ class ConnectionService: Codable {
|
|||
case preferences
|
||||
}
|
||||
|
||||
var directory: String? = nil
|
||||
public var directory: String? = nil
|
||||
|
||||
var rootURL: URL {
|
||||
public var rootURL: URL {
|
||||
var url = GroupConstants.App.documentsURL
|
||||
if let directory = directory {
|
||||
url.appendPathComponent(directory)
|
||||
|
@ -81,11 +81,11 @@ class ConnectionService: Codable {
|
|||
|
||||
private let keychain: Keychain
|
||||
|
||||
var baseConfiguration: TunnelKitProvider.Configuration
|
||||
public var baseConfiguration: TunnelKitProvider.Configuration
|
||||
|
||||
private var cache: [ProfileKey: ConnectionProfile]
|
||||
|
||||
private(set) var activeProfileKey: ProfileKey? {
|
||||
public private(set) var activeProfileKey: ProfileKey? {
|
||||
willSet {
|
||||
if let oldProfile = activeProfile {
|
||||
delegate?.connectionService(willDeactivate: oldProfile)
|
||||
|
@ -98,7 +98,7 @@ class ConnectionService: Codable {
|
|||
}
|
||||
}
|
||||
|
||||
var activeProfile: ConnectionProfile? {
|
||||
public var activeProfile: ConnectionProfile? {
|
||||
guard let id = activeProfileKey else {
|
||||
return nil
|
||||
}
|
||||
|
@ -110,11 +110,11 @@ class ConnectionService: Codable {
|
|||
return hit
|
||||
}
|
||||
|
||||
let preferences: EditablePreferences
|
||||
public let preferences: EditablePreferences
|
||||
|
||||
weak var delegate: ConnectionServiceDelegate?
|
||||
public weak var delegate: ConnectionServiceDelegate?
|
||||
|
||||
init(withAppGroup appGroup: String, baseConfiguration: TunnelKitProvider.Configuration) {
|
||||
public init(withAppGroup appGroup: String, baseConfiguration: TunnelKitProvider.Configuration) {
|
||||
guard let defaults = UserDefaults(suiteName: appGroup) else {
|
||||
fatalError("No entitlements for group '\(appGroup)'")
|
||||
}
|
||||
|
@ -132,7 +132,7 @@ class ConnectionService: Codable {
|
|||
|
||||
// MARK: Codable
|
||||
|
||||
required init(from decoder: Decoder) throws {
|
||||
public required init(from decoder: Decoder) throws {
|
||||
let container = try decoder.container(keyedBy: CodingKeys.self)
|
||||
let appGroup = try container.decode(String.self, forKey: .appGroup)
|
||||
guard let defaults = UserDefaults(suiteName: appGroup) else {
|
||||
|
@ -150,7 +150,7 @@ class ConnectionService: Codable {
|
|||
cache = [:]
|
||||
}
|
||||
|
||||
func encode(to encoder: Encoder) throws {
|
||||
public func encode(to encoder: Encoder) throws {
|
||||
build = GroupConstants.App.buildNumber
|
||||
|
||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||
|
@ -163,7 +163,7 @@ class ConnectionService: Codable {
|
|||
|
||||
// MARK: Serialization
|
||||
|
||||
func loadProfiles() {
|
||||
public func loadProfiles() {
|
||||
let fm = FileManager.default
|
||||
try? fm.createDirectory(at: providersURL, withIntermediateDirectories: false, attributes: nil)
|
||||
try? fm.createDirectory(at: hostsURL, withIntermediateDirectories: false, attributes: nil)
|
||||
|
@ -196,7 +196,7 @@ class ConnectionService: Codable {
|
|||
}
|
||||
}
|
||||
|
||||
func saveProfiles() {
|
||||
public func saveProfiles() {
|
||||
let encoder = JSONEncoder()
|
||||
ensureDirectoriesExistence()
|
||||
|
||||
|
@ -237,7 +237,7 @@ class ConnectionService: Codable {
|
|||
}
|
||||
}
|
||||
|
||||
func profile(withContext context: Context, id: String) -> ConnectionProfile? {
|
||||
public func profile(withContext context: Context, id: String) -> ConnectionProfile? {
|
||||
let key = ProfileKey(context, id)
|
||||
var profile = cache[key]
|
||||
if let _ = profile as? PlaceholderConnectionProfile {
|
||||
|
@ -260,11 +260,11 @@ class ConnectionService: Codable {
|
|||
return profile
|
||||
}
|
||||
|
||||
func ids(forContext context: Context) -> [String] {
|
||||
public func ids(forContext context: Context) -> [String] {
|
||||
return cache.keys.filter { $0.context == context }.map { $0.id }
|
||||
}
|
||||
|
||||
func contextURL(_ key: ProfileKey) -> URL {
|
||||
public func contextURL(_ key: ProfileKey) -> URL {
|
||||
switch key.context {
|
||||
case .provider:
|
||||
return providersURL
|
||||
|
@ -274,11 +274,11 @@ class ConnectionService: Codable {
|
|||
}
|
||||
}
|
||||
|
||||
func profileURL(_ key: ProfileKey) -> URL {
|
||||
public func profileURL(_ key: ProfileKey) -> URL {
|
||||
return contextURL(key).appendingPathComponent(key.id).appendingPathExtension("json")
|
||||
}
|
||||
|
||||
func profileData(_ key: ProfileKey) throws -> Data {
|
||||
public func profileData(_ key: ProfileKey) throws -> Data {
|
||||
return try Data(contentsOf: profileURL(key))
|
||||
}
|
||||
|
||||
|
@ -291,7 +291,7 @@ class ConnectionService: Codable {
|
|||
|
||||
// MARK: Profiles
|
||||
|
||||
func addProfile(_ profile: ConnectionProfile, credentials: Credentials?) -> Bool {
|
||||
public func addProfile(_ profile: ConnectionProfile, credentials: Credentials?) -> Bool {
|
||||
guard cache.index(forKey: ProfileKey(profile)) == nil else {
|
||||
return false
|
||||
}
|
||||
|
@ -299,7 +299,7 @@ class ConnectionService: Codable {
|
|||
return true
|
||||
}
|
||||
|
||||
func addOrReplaceProfile(_ profile: ConnectionProfile, credentials: Credentials?) {
|
||||
public func addOrReplaceProfile(_ profile: ConnectionProfile, credentials: Credentials?) {
|
||||
let key = ProfileKey(profile)
|
||||
cache[key] = profile
|
||||
try? setCredentials(credentials, for: profile)
|
||||
|
@ -312,7 +312,8 @@ class ConnectionService: Codable {
|
|||
saveProfile(profile, withEncoder: JSONEncoder(), checkDirectories: true)
|
||||
}
|
||||
|
||||
@discardableResult func renameProfile(_ key: ProfileKey, to newId: String) -> ConnectionProfile? {
|
||||
@discardableResult
|
||||
public func renameProfile(_ key: ProfileKey, to newId: String) -> ConnectionProfile? {
|
||||
precondition(newId != key.id)
|
||||
|
||||
// WARNING: can be a placeholder
|
||||
|
@ -351,11 +352,12 @@ class ConnectionService: Codable {
|
|||
return newProfile
|
||||
}
|
||||
|
||||
@discardableResult func renameProfile(_ profile: ConnectionProfile, to id: String) -> ConnectionProfile? {
|
||||
@discardableResult
|
||||
public func renameProfile(_ profile: ConnectionProfile, to id: String) -> ConnectionProfile? {
|
||||
return renameProfile(ProfileKey(profile), to: id)
|
||||
}
|
||||
|
||||
func removeProfile(_ key: ProfileKey) {
|
||||
public func removeProfile(_ key: ProfileKey) {
|
||||
guard let profile = cache[key] else {
|
||||
return
|
||||
}
|
||||
|
@ -382,33 +384,33 @@ class ConnectionService: Codable {
|
|||
}
|
||||
}
|
||||
|
||||
func containsProfile(_ key: ProfileKey) -> Bool {
|
||||
public func containsProfile(_ key: ProfileKey) -> Bool {
|
||||
return cache.index(forKey: key) != nil
|
||||
}
|
||||
|
||||
func containsProfile(_ profile: ConnectionProfile) -> Bool {
|
||||
public func containsProfile(_ profile: ConnectionProfile) -> Bool {
|
||||
return containsProfile(ProfileKey(profile))
|
||||
}
|
||||
|
||||
func hasActiveProfile() -> Bool {
|
||||
public func hasActiveProfile() -> Bool {
|
||||
return activeProfileKey != nil
|
||||
}
|
||||
|
||||
func isActiveProfile(_ key: ProfileKey) -> Bool {
|
||||
public func isActiveProfile(_ key: ProfileKey) -> Bool {
|
||||
return key == activeProfileKey
|
||||
}
|
||||
|
||||
func isActiveProfile(_ profile: ConnectionProfile) -> Bool {
|
||||
public func isActiveProfile(_ profile: ConnectionProfile) -> Bool {
|
||||
return isActiveProfile(ProfileKey(profile))
|
||||
}
|
||||
|
||||
func activateProfile(_ profile: ConnectionProfile) {
|
||||
public func activateProfile(_ profile: ConnectionProfile) {
|
||||
activeProfileKey = ProfileKey(profile)
|
||||
}
|
||||
|
||||
// MARK: Credentials
|
||||
|
||||
func needsCredentials(for profile: ConnectionProfile) -> Bool {
|
||||
public func needsCredentials(for profile: ConnectionProfile) -> Bool {
|
||||
guard profile.requiresCredentials else {
|
||||
return false
|
||||
}
|
||||
|
@ -418,7 +420,7 @@ class ConnectionService: Codable {
|
|||
return creds.isEmpty
|
||||
}
|
||||
|
||||
func credentials(for profile: ConnectionProfile) -> Credentials? {
|
||||
public func credentials(for profile: ConnectionProfile) -> Credentials? {
|
||||
guard let username = profile.username, let key = profile.passwordKey else {
|
||||
return nil
|
||||
}
|
||||
|
@ -428,18 +430,18 @@ class ConnectionService: Codable {
|
|||
return Credentials(username, password)
|
||||
}
|
||||
|
||||
func setCredentials(_ credentials: Credentials?, for profile: ConnectionProfile) throws {
|
||||
public func setCredentials(_ credentials: Credentials?, for profile: ConnectionProfile) throws {
|
||||
profile.username = credentials?.username
|
||||
try profile.setPassword(credentials?.password, in: keychain)
|
||||
}
|
||||
|
||||
func removeCredentials(for profile: ConnectionProfile) {
|
||||
public func removeCredentials(for profile: ConnectionProfile) {
|
||||
profile.removePassword(in: keychain)
|
||||
}
|
||||
|
||||
// MARK: VPN
|
||||
|
||||
func vpnConfiguration() throws -> NetworkExtensionVPNConfiguration {
|
||||
public func vpnConfiguration() throws -> NetworkExtensionVPNConfiguration {
|
||||
guard let profile = activeProfile else {
|
||||
throw ApplicationError.missingProfile
|
||||
}
|
||||
|
@ -492,19 +494,19 @@ class ConnectionService: Codable {
|
|||
}
|
||||
}
|
||||
|
||||
var vpnLog: String {
|
||||
public var vpnLog: String {
|
||||
return baseConfiguration.existingLog(in: appGroup) ?? ""
|
||||
}
|
||||
|
||||
var vpnLastError: TunnelKitProvider.ProviderError? {
|
||||
public var vpnLastError: TunnelKitProvider.ProviderError? {
|
||||
return baseConfiguration.lastError(in: appGroup)
|
||||
}
|
||||
|
||||
func clearVpnLastError() {
|
||||
public func clearVpnLastError() {
|
||||
baseConfiguration.clearLastError(in: appGroup)
|
||||
}
|
||||
|
||||
// func eraseVpnLog() {
|
||||
// public func eraseVpnLog() {
|
||||
// defaults.removeObject(forKey: Keys.vpnLog)
|
||||
// }
|
||||
}
|
||||
|
|
|
@ -26,9 +26,9 @@
|
|||
import Foundation
|
||||
import TunnelKit
|
||||
|
||||
typealias Credentials = SessionProxy.Credentials
|
||||
public typealias Credentials = SessionProxy.Credentials
|
||||
|
||||
extension Credentials {
|
||||
public extension Credentials {
|
||||
var isEmpty: Bool {
|
||||
return username.isEmpty || password.isEmpty
|
||||
}
|
||||
|
|
|
@ -30,22 +30,22 @@ import UIKit
|
|||
import Cocoa
|
||||
#endif
|
||||
|
||||
struct DebugLog {
|
||||
public struct DebugLog {
|
||||
private let raw: String
|
||||
|
||||
init(raw: String) {
|
||||
public init(raw: String) {
|
||||
self.raw = raw
|
||||
}
|
||||
|
||||
func string() -> String {
|
||||
public func string() -> String {
|
||||
return raw
|
||||
}
|
||||
|
||||
func data() -> Data? {
|
||||
public func data() -> Data? {
|
||||
return raw.data(using: .utf8)
|
||||
}
|
||||
|
||||
func decoratedString() -> String {
|
||||
public func decoratedString() -> String {
|
||||
let appName = GroupConstants.App.name
|
||||
let appVersion = GroupConstants.App.versionString
|
||||
|
||||
|
@ -75,7 +75,7 @@ struct DebugLog {
|
|||
return fullText
|
||||
}
|
||||
|
||||
func decoratedData() -> Data {
|
||||
public func decoratedData() -> Data {
|
||||
guard let data = decoratedString().data(using: .utf8) else {
|
||||
fatalError("Could not encode log metadata to UTF8?")
|
||||
}
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
import Foundation
|
||||
import TunnelKit
|
||||
|
||||
protocol EndpointDataSource {
|
||||
public protocol EndpointDataSource {
|
||||
var mainAddress: String { get }
|
||||
|
||||
var addresses: [String] { get }
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
|
||||
import Foundation
|
||||
|
||||
protocol Preferences {
|
||||
public protocol Preferences {
|
||||
var resolvesHostname: Bool { get }
|
||||
|
||||
var disconnectsOnSleep: Bool { get }
|
||||
|
@ -39,16 +39,16 @@ protocol Preferences {
|
|||
var trustPolicy: TrustPolicy { get }
|
||||
}
|
||||
|
||||
class EditablePreferences: Preferences, Codable {
|
||||
var resolvesHostname: Bool = true
|
||||
public class EditablePreferences: Preferences, Codable {
|
||||
public var resolvesHostname: Bool = true
|
||||
|
||||
var disconnectsOnSleep: Bool = false
|
||||
public var disconnectsOnSleep: Bool = false
|
||||
|
||||
#if os(iOS)
|
||||
var trustsMobileNetwork: Bool = false
|
||||
public var trustsMobileNetwork: Bool = false
|
||||
#endif
|
||||
|
||||
var trustedWifis: [String: Bool] = [:]
|
||||
public var trustedWifis: [String: Bool] = [:]
|
||||
|
||||
var trustPolicy: TrustPolicy = .disconnect
|
||||
public var trustPolicy: TrustPolicy = .disconnect
|
||||
}
|
||||
|
|
|
@ -26,14 +26,14 @@
|
|||
import Foundation
|
||||
import TunnelKit
|
||||
|
||||
class HostConnectionProfile: ConnectionProfile, Codable, Equatable {
|
||||
var title: String
|
||||
public class HostConnectionProfile: ConnectionProfile, Codable, Equatable {
|
||||
public var title: String
|
||||
|
||||
let hostname: String
|
||||
public let hostname: String
|
||||
|
||||
var parameters: TunnelKitProvider.Configuration
|
||||
public var parameters: TunnelKitProvider.Configuration
|
||||
|
||||
init(title: String, hostname: String) {
|
||||
public init(title: String, hostname: String) {
|
||||
self.title = title
|
||||
self.hostname = hostname
|
||||
let sessionConfiguration = SessionProxy.ConfigurationBuilder(ca: CryptoContainer(pem: "")).build()
|
||||
|
@ -42,19 +42,19 @@ class HostConnectionProfile: ConnectionProfile, Codable, Equatable {
|
|||
|
||||
// MARK: ConnectionProfile
|
||||
|
||||
let context: Context = .host
|
||||
public let context: Context = .host
|
||||
|
||||
var id: String {
|
||||
public var id: String {
|
||||
return title
|
||||
}
|
||||
|
||||
var username: String?
|
||||
public var username: String?
|
||||
|
||||
var requiresCredentials: Bool {
|
||||
public var requiresCredentials: Bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func generate(from configuration: TunnelKitProvider.Configuration, preferences: Preferences) throws -> TunnelKitProvider.Configuration {
|
||||
public func generate(from configuration: TunnelKitProvider.Configuration, preferences: Preferences) throws -> TunnelKitProvider.Configuration {
|
||||
precondition(!parameters.endpointProtocols.isEmpty)
|
||||
|
||||
// XXX: copy paste, error prone
|
||||
|
@ -66,7 +66,7 @@ class HostConnectionProfile: ConnectionProfile, Codable, Equatable {
|
|||
return builder.build()
|
||||
}
|
||||
|
||||
func with(newId: String) -> ConnectionProfile {
|
||||
public func with(newId: String) -> ConnectionProfile {
|
||||
let profile = HostConnectionProfile(title: newId, hostname: hostname)
|
||||
profile.username = username
|
||||
profile.parameters = parameters
|
||||
|
@ -74,13 +74,13 @@ class HostConnectionProfile: ConnectionProfile, Codable, Equatable {
|
|||
}
|
||||
}
|
||||
|
||||
extension HostConnectionProfile {
|
||||
public extension HostConnectionProfile {
|
||||
static func ==(lhs: HostConnectionProfile, rhs: HostConnectionProfile) -> Bool {
|
||||
return lhs.id == rhs.id
|
||||
}
|
||||
}
|
||||
|
||||
extension HostConnectionProfile {
|
||||
public extension HostConnectionProfile {
|
||||
var mainAddress: String {
|
||||
return hostname
|
||||
}
|
||||
|
|
|
@ -26,41 +26,41 @@
|
|||
import Foundation
|
||||
import TunnelKit
|
||||
|
||||
class PlaceholderConnectionProfile: ConnectionProfile {
|
||||
let context: Context
|
||||
public class PlaceholderConnectionProfile: ConnectionProfile {
|
||||
public let context: Context
|
||||
|
||||
let id: String
|
||||
public let id: String
|
||||
|
||||
var username: String? = nil
|
||||
public var username: String? = nil
|
||||
|
||||
var requiresCredentials: Bool = false
|
||||
public var requiresCredentials: Bool = false
|
||||
|
||||
func generate(from configuration: TunnelKitProvider.Configuration, preferences: Preferences) throws -> TunnelKitProvider.Configuration {
|
||||
public func generate(from configuration: TunnelKitProvider.Configuration, preferences: Preferences) throws -> TunnelKitProvider.Configuration {
|
||||
fatalError("Generating configuration from a PlaceholderConnectionProfile")
|
||||
}
|
||||
|
||||
func with(newId: String) -> ConnectionProfile {
|
||||
public func with(newId: String) -> ConnectionProfile {
|
||||
return PlaceholderConnectionProfile(context, newId)
|
||||
}
|
||||
|
||||
var mainAddress: String = ""
|
||||
public var mainAddress: String = ""
|
||||
|
||||
var addresses: [String] = []
|
||||
public var addresses: [String] = []
|
||||
|
||||
var protocols: [EndpointProtocol] = []
|
||||
public var protocols: [EndpointProtocol] = []
|
||||
|
||||
var canCustomizeEndpoint: Bool = false
|
||||
public var canCustomizeEndpoint: Bool = false
|
||||
|
||||
var customAddress: String?
|
||||
public var customAddress: String?
|
||||
|
||||
var customProtocol: EndpointProtocol?
|
||||
public var customProtocol: EndpointProtocol?
|
||||
|
||||
init(_ context: Context, _ id: String) {
|
||||
public init(_ context: Context, _ id: String) {
|
||||
self.context = context
|
||||
self.id = id
|
||||
}
|
||||
|
||||
init(_ key: ProfileKey) {
|
||||
public init(_ key: ProfileKey) {
|
||||
context = key.context
|
||||
id = key.id
|
||||
}
|
||||
|
|
|
@ -25,30 +25,30 @@
|
|||
|
||||
import Foundation
|
||||
|
||||
struct ProfileKey: RawRepresentable, Hashable, Codable, CustomStringConvertible {
|
||||
public struct ProfileKey: RawRepresentable, Hashable, Codable, CustomStringConvertible {
|
||||
private static let separator: Character = "."
|
||||
|
||||
let context: Context
|
||||
public let context: Context
|
||||
|
||||
let id: String
|
||||
public let id: String
|
||||
|
||||
init(_ context: Context, _ id: String) {
|
||||
public init(_ context: Context, _ id: String) {
|
||||
self.context = context
|
||||
self.id = id
|
||||
}
|
||||
|
||||
init(_ profile: ConnectionProfile) {
|
||||
public init(_ profile: ConnectionProfile) {
|
||||
context = profile.context
|
||||
id = profile.id
|
||||
}
|
||||
|
||||
// MARK: RawRepresentable
|
||||
|
||||
var rawValue: String {
|
||||
public var rawValue: String {
|
||||
return "\(context)\(ProfileKey.separator)\(id)"
|
||||
}
|
||||
|
||||
init?(rawValue: String) {
|
||||
public init?(rawValue: String) {
|
||||
guard let separatorIndex = rawValue.firstIndex(of: ProfileKey.separator) else {
|
||||
return nil
|
||||
}
|
||||
|
@ -66,7 +66,7 @@ struct ProfileKey: RawRepresentable, Hashable, Codable, CustomStringConvertible
|
|||
|
||||
// MARK: CustomStringConvertible
|
||||
|
||||
var description: String {
|
||||
public var description: String {
|
||||
return "{context=\(context), id=\(id)}"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,42 +26,42 @@
|
|||
import Foundation
|
||||
import TunnelKit
|
||||
|
||||
class ProviderConnectionProfile: ConnectionProfile, Codable, Equatable {
|
||||
let name: Infrastructure.Name
|
||||
public class ProviderConnectionProfile: ConnectionProfile, Codable, Equatable {
|
||||
public let name: Infrastructure.Name
|
||||
|
||||
var infrastructure: Infrastructure {
|
||||
public var infrastructure: Infrastructure {
|
||||
return InfrastructureFactory.shared.get(name)
|
||||
}
|
||||
|
||||
var poolId: String {
|
||||
public var poolId: String {
|
||||
didSet {
|
||||
validateEndpoint()
|
||||
}
|
||||
}
|
||||
|
||||
var pool: Pool? {
|
||||
public var pool: Pool? {
|
||||
return infrastructure.pool(for: poolId) ?? infrastructure.pool(for: infrastructure.defaults.pool)
|
||||
}
|
||||
|
||||
var presetId: String {
|
||||
public var presetId: String {
|
||||
didSet {
|
||||
validateEndpoint()
|
||||
}
|
||||
}
|
||||
|
||||
var preset: InfrastructurePreset? {
|
||||
public var preset: InfrastructurePreset? {
|
||||
return infrastructure.preset(for: presetId)
|
||||
}
|
||||
|
||||
var manualAddress: String?
|
||||
public var manualAddress: String?
|
||||
|
||||
var manualProtocol: EndpointProtocol?
|
||||
public var manualProtocol: EndpointProtocol?
|
||||
|
||||
var usesProviderEndpoint: Bool {
|
||||
public var usesProviderEndpoint: Bool {
|
||||
return (manualAddress != nil) || (manualProtocol != nil)
|
||||
}
|
||||
|
||||
init(name: Infrastructure.Name) {
|
||||
public init(name: Infrastructure.Name) {
|
||||
self.name = name
|
||||
poolId = ""
|
||||
presetId = ""
|
||||
|
@ -72,7 +72,7 @@ class ProviderConnectionProfile: ConnectionProfile, Codable, Equatable {
|
|||
presetId = infrastructure.defaults.preset
|
||||
}
|
||||
|
||||
func sortedPools() -> [Pool] {
|
||||
public func sortedPools() -> [Pool] {
|
||||
return infrastructure.pools.sorted()
|
||||
}
|
||||
|
||||
|
@ -92,19 +92,19 @@ class ProviderConnectionProfile: ConnectionProfile, Codable, Equatable {
|
|||
|
||||
// MARK: ConnectionProfile
|
||||
|
||||
let context: Context = .provider
|
||||
public let context: Context = .provider
|
||||
|
||||
var id: String {
|
||||
public var id: String {
|
||||
return name.rawValue
|
||||
}
|
||||
|
||||
var username: String?
|
||||
public var username: String?
|
||||
|
||||
var requiresCredentials: Bool {
|
||||
public var requiresCredentials: Bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func generate(from configuration: TunnelKitProvider.Configuration, preferences: Preferences) throws -> TunnelKitProvider.Configuration {
|
||||
public func generate(from configuration: TunnelKitProvider.Configuration, preferences: Preferences) throws -> TunnelKitProvider.Configuration {
|
||||
guard let pool = pool else {
|
||||
preconditionFailure("Nil pool?")
|
||||
}
|
||||
|
@ -140,18 +140,18 @@ class ProviderConnectionProfile: ConnectionProfile, Codable, Equatable {
|
|||
return builder.build()
|
||||
}
|
||||
|
||||
func with(newId: String) -> ConnectionProfile {
|
||||
public func with(newId: String) -> ConnectionProfile {
|
||||
fatalError("Cannot rename a ProviderConnectionProfile")
|
||||
}
|
||||
}
|
||||
|
||||
extension ProviderConnectionProfile {
|
||||
public extension ProviderConnectionProfile {
|
||||
static func ==(lhs: ProviderConnectionProfile, rhs: ProviderConnectionProfile) -> Bool {
|
||||
return lhs.id == rhs.id
|
||||
}
|
||||
}
|
||||
|
||||
extension ProviderConnectionProfile {
|
||||
public extension ProviderConnectionProfile {
|
||||
var mainAddress: String {
|
||||
assert(pool != nil, "Getting provider main address but no pool set")
|
||||
return pool?.hostname ?? ""
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
import Foundation
|
||||
import TunnelKit
|
||||
|
||||
extension SessionProxy.ConfigurationBuilder {
|
||||
public extension SessionProxy.ConfigurationBuilder {
|
||||
// mutating func copyCommunication(from other: SessionProxy.ConfigurationBuilder) {
|
||||
// cipher = other.cipher
|
||||
// digest = other.digest
|
||||
|
|
|
@ -28,20 +28,20 @@ import SwiftyBeaver
|
|||
|
||||
private let log = SwiftyBeaver.self
|
||||
|
||||
class TransientStore {
|
||||
public class TransientStore {
|
||||
private struct Keys {
|
||||
static let didHandleSubreddit = "DidHandleSubreddit"
|
||||
}
|
||||
|
||||
static let shared = TransientStore()
|
||||
public static let shared = TransientStore()
|
||||
|
||||
private static var serviceURL: URL {
|
||||
return GroupConstants.App.documentsURL.appendingPathComponent(AppConstants.Store.serviceFilename)
|
||||
}
|
||||
|
||||
let service: ConnectionService
|
||||
public let service: ConnectionService
|
||||
|
||||
var didHandleSubreddit: Bool {
|
||||
public var didHandleSubreddit: Bool {
|
||||
get {
|
||||
return UserDefaults.standard.bool(forKey: Keys.didHandleSubreddit)
|
||||
}
|
||||
|
@ -80,7 +80,7 @@ class TransientStore {
|
|||
}
|
||||
}
|
||||
|
||||
func serialize(withProfiles: Bool) {
|
||||
public func serialize(withProfiles: Bool) {
|
||||
try? JSONEncoder().encode(service).write(to: TransientStore.serviceURL)
|
||||
if withProfiles {
|
||||
service.saveProfiles()
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
|
||||
import Foundation
|
||||
|
||||
enum TrustPolicy: String, Codable {
|
||||
public enum TrustPolicy: String, Codable {
|
||||
case ignore
|
||||
|
||||
case disconnect
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
|
||||
import Foundation
|
||||
|
||||
protocol TrustedNetworksModelDelegate: class {
|
||||
public protocol TrustedNetworksModelDelegate: class {
|
||||
func trustedNetworksCouldDisconnect(_: TrustedNetworksModel) -> Bool
|
||||
|
||||
func trustedNetworksShouldConfirmDisconnection(_: TrustedNetworksModel, triggeredAt rowIndex: Int, completionHandler: @escaping () -> Void)
|
||||
|
@ -39,24 +39,24 @@ protocol TrustedNetworksModelDelegate: class {
|
|||
func trustedNetworksShouldReinstall(_: TrustedNetworksModel)
|
||||
}
|
||||
|
||||
class TrustedNetworksModel {
|
||||
private(set) var trustedWifis: [String: Bool]
|
||||
public class TrustedNetworksModel {
|
||||
public private(set) var trustedWifis: [String: Bool]
|
||||
|
||||
private(set) var sortedWifis: [String]
|
||||
public private(set) var sortedWifis: [String]
|
||||
|
||||
#if os(iOS)
|
||||
private let hasMobileNetwork: Bool
|
||||
|
||||
private(set) var trustsMobileNetwork: Bool
|
||||
public private(set) var trustsMobileNetwork: Bool
|
||||
|
||||
// FIXME
|
||||
// private(set) var rows: [ServiceViewController.RowType]
|
||||
private(set) var rows: [Int]
|
||||
// public private(set) var rows: [ServiceViewController.RowType]
|
||||
public private(set) var rows: [Int]
|
||||
#endif
|
||||
|
||||
weak var delegate: TrustedNetworksModelDelegate?
|
||||
public weak var delegate: TrustedNetworksModelDelegate?
|
||||
|
||||
init() {
|
||||
public init() {
|
||||
trustedWifis = [:]
|
||||
sortedWifis = []
|
||||
|
||||
|
@ -67,7 +67,7 @@ class TrustedNetworksModel {
|
|||
#endif
|
||||
}
|
||||
|
||||
func load(from preferences: Preferences) {
|
||||
public func load(from preferences: Preferences) {
|
||||
trustedWifis = preferences.trustedWifis
|
||||
sortedWifis = trustedWifis.keys.sorted()
|
||||
|
||||
|
@ -86,7 +86,7 @@ class TrustedNetworksModel {
|
|||
}
|
||||
|
||||
#if os(iOS)
|
||||
func setMobile(_ isTrusted: Bool) {
|
||||
public func setMobile(_ isTrusted: Bool) {
|
||||
let completionHandler: () -> Void = {
|
||||
self.trustsMobileNetwork = isTrusted
|
||||
self.delegate?.trustedNetworksShouldReinstall(self)
|
||||
|
@ -99,14 +99,14 @@ class TrustedNetworksModel {
|
|||
}
|
||||
#endif
|
||||
|
||||
func wifi(at rowIndex: Int) -> (String, Bool) {
|
||||
public func wifi(at rowIndex: Int) -> (String, Bool) {
|
||||
let index = indexForWifi(at: rowIndex)
|
||||
let wifiName = sortedWifis[index]
|
||||
let isTrusted = trustedWifis[wifiName] ?? false
|
||||
return (wifiName, isTrusted)
|
||||
}
|
||||
|
||||
func addCurrentWifi() -> Bool {
|
||||
public func addCurrentWifi() -> Bool {
|
||||
guard let currentWifi = Utils.currentWifiNetworkName() else {
|
||||
return false
|
||||
}
|
||||
|
@ -114,7 +114,7 @@ class TrustedNetworksModel {
|
|||
return true
|
||||
}
|
||||
|
||||
func addWifi(_ wifiToAdd: String) {
|
||||
public func addWifi(_ wifiToAdd: String) {
|
||||
var index = 0
|
||||
var isDuplicate = false
|
||||
for wifi in sortedWifis {
|
||||
|
@ -150,7 +150,7 @@ class TrustedNetworksModel {
|
|||
delegate?.trustedNetworksShouldReinstall(self)
|
||||
}
|
||||
|
||||
func removeWifi(at rowIndex: Int) {
|
||||
public func removeWifi(at rowIndex: Int) {
|
||||
let index = indexForWifi(at: rowIndex)
|
||||
let removedWifi = sortedWifis.remove(at: index)
|
||||
trustedWifis.removeValue(forKey: removedWifi)
|
||||
|
@ -162,7 +162,7 @@ class TrustedNetworksModel {
|
|||
delegate?.trustedNetworksShouldReinstall(self)
|
||||
}
|
||||
|
||||
func enableWifi(at rowIndex: Int) {
|
||||
public func enableWifi(at rowIndex: Int) {
|
||||
let index = indexForWifi(at: rowIndex)
|
||||
let wifi = sortedWifis[index]
|
||||
|
||||
|
@ -179,7 +179,7 @@ class TrustedNetworksModel {
|
|||
completionHandler()
|
||||
}
|
||||
|
||||
func disableWifi(at rowIndex: Int) {
|
||||
public func disableWifi(at rowIndex: Int) {
|
||||
let index = indexForWifi(at: rowIndex)
|
||||
let wifi = sortedWifis[index]
|
||||
|
||||
|
@ -189,7 +189,7 @@ class TrustedNetworksModel {
|
|||
delegate?.trustedNetworksShouldReinstall(self)
|
||||
}
|
||||
|
||||
func isTrusted(wifi: String) -> Bool {
|
||||
public func isTrusted(wifi: String) -> Bool {
|
||||
return trustedWifis[wifi] ?? false
|
||||
}
|
||||
|
||||
|
|
|
@ -28,24 +28,24 @@ import SwiftyBeaver
|
|||
|
||||
private let log = SwiftyBeaver.self
|
||||
|
||||
class Reviewer {
|
||||
public class Reviewer {
|
||||
private struct Keys {
|
||||
static let eventCount = "ReviewerEventCount"
|
||||
|
||||
static let lastVersion = "ReviewerLastVersion"
|
||||
}
|
||||
|
||||
static let shared = Reviewer()
|
||||
public static let shared = Reviewer()
|
||||
|
||||
private let defaults: UserDefaults
|
||||
|
||||
var eventCountBeforeRating = 3
|
||||
public var eventCountBeforeRating = 3
|
||||
|
||||
private init() {
|
||||
defaults = .standard
|
||||
}
|
||||
|
||||
func reportEvent() {
|
||||
public func reportEvent() {
|
||||
let currentVersion = GroupConstants.App.buildNumber
|
||||
let lastVersion = defaults.integer(forKey: Keys.lastVersion)
|
||||
if lastVersion > 0 {
|
||||
|
|
|
@ -26,49 +26,49 @@
|
|||
import Foundation
|
||||
import TunnelKit
|
||||
|
||||
struct Infrastructure: Codable {
|
||||
enum Name: String, Codable, Comparable {
|
||||
public struct Infrastructure: Codable {
|
||||
public enum Name: String, Codable, Comparable {
|
||||
case pia = "PIA"
|
||||
|
||||
case tunnelBear = "TunnelBear"
|
||||
|
||||
var webName: String {
|
||||
public var webName: String {
|
||||
return rawValue.lowercased()
|
||||
}
|
||||
|
||||
static func <(lhs: Name, rhs: Name) -> Bool {
|
||||
public static func <(lhs: Name, rhs: Name) -> Bool {
|
||||
return lhs.webName < rhs.webName
|
||||
}
|
||||
}
|
||||
|
||||
struct Defaults: Codable {
|
||||
let username: String?
|
||||
public struct Defaults: Codable {
|
||||
public let username: String?
|
||||
|
||||
let pool: String
|
||||
public let pool: String
|
||||
|
||||
let preset: String
|
||||
public let preset: String
|
||||
}
|
||||
|
||||
let build: Int
|
||||
public let build: Int
|
||||
|
||||
let name: Name
|
||||
public let name: Name
|
||||
|
||||
let pools: [Pool]
|
||||
public let pools: [Pool]
|
||||
|
||||
let presets: [InfrastructurePreset]
|
||||
public let presets: [InfrastructurePreset]
|
||||
|
||||
let defaults: Defaults
|
||||
public let defaults: Defaults
|
||||
|
||||
static func loaded(from url: URL) throws -> Infrastructure {
|
||||
public static func loaded(from url: URL) throws -> Infrastructure {
|
||||
let json = try Data(contentsOf: url)
|
||||
return try JSONDecoder().decode(Infrastructure.self, from: json)
|
||||
}
|
||||
|
||||
func pool(for identifier: String) -> Pool? {
|
||||
public func pool(for identifier: String) -> Pool? {
|
||||
return pools.first { $0.id == identifier }
|
||||
}
|
||||
|
||||
func preset(for identifier: String) -> InfrastructurePreset? {
|
||||
public func preset(for identifier: String) -> InfrastructurePreset? {
|
||||
return presets.first { $0.id == identifier }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,7 +28,7 @@ import SwiftyBeaver
|
|||
|
||||
private let log = SwiftyBeaver.self
|
||||
|
||||
class InfrastructureFactory {
|
||||
public class InfrastructureFactory {
|
||||
private static func embedded(withName name: Infrastructure.Name) -> Infrastructure {
|
||||
guard let url = name.bundleURL else {
|
||||
fatalError("Cannot find JSON for infrastructure '\(name)'")
|
||||
|
@ -53,9 +53,9 @@ class InfrastructureFactory {
|
|||
return cacheDate > bundleDate
|
||||
}
|
||||
|
||||
static let shared = InfrastructureFactory()
|
||||
public static let shared = InfrastructureFactory()
|
||||
|
||||
let allNames: [Infrastructure.Name] = [
|
||||
public let allNames: [Infrastructure.Name] = [
|
||||
.pia,
|
||||
.tunnelBear
|
||||
]
|
||||
|
@ -80,7 +80,7 @@ class InfrastructureFactory {
|
|||
lastUpdate = [:]
|
||||
}
|
||||
|
||||
func loadCache() {
|
||||
public func loadCache() {
|
||||
let cacheEntries: [URL]
|
||||
do {
|
||||
cacheEntries = try FileManager.default.contentsOfDirectory(at: cachePath, includingPropertiesForKeys: nil)
|
||||
|
@ -110,14 +110,14 @@ class InfrastructureFactory {
|
|||
}
|
||||
}
|
||||
|
||||
func get(_ name: Infrastructure.Name) -> Infrastructure {
|
||||
public func get(_ name: Infrastructure.Name) -> Infrastructure {
|
||||
guard let infra = cache[name] ?? bundle[name] else {
|
||||
fatalError("No infrastructure embedded nor cached for '\(name)'")
|
||||
}
|
||||
return infra
|
||||
}
|
||||
|
||||
func update(_ name: Infrastructure.Name, notBeforeInterval minInterval: TimeInterval?, completionHandler: @escaping ((Infrastructure, Date)?, Error?) -> Void) -> Bool {
|
||||
public func update(_ name: Infrastructure.Name, notBeforeInterval minInterval: TimeInterval?, completionHandler: @escaping ((Infrastructure, Date)?, Error?) -> Void) -> Bool {
|
||||
let ifModifiedSince = modificationDate(for: name)
|
||||
|
||||
if let lastInfrastructureUpdate = lastUpdate[name] {
|
||||
|
@ -191,7 +191,7 @@ class InfrastructureFactory {
|
|||
return true
|
||||
}
|
||||
|
||||
func modificationDate(for name: Infrastructure.Name) -> Date? {
|
||||
public func modificationDate(for name: Infrastructure.Name) -> Date? {
|
||||
let optBundleDate = bundleModificationDate(for: name)
|
||||
guard let cacheDate = cacheModificationDate(for: name) else {
|
||||
return optBundleDate
|
||||
|
|
|
@ -29,8 +29,8 @@ import TunnelKit
|
|||
// supports a subset of TunnelKitProvider.Configuration
|
||||
// ignores new JSON keys
|
||||
|
||||
struct InfrastructurePreset: Codable {
|
||||
enum PresetKeys: String, CodingKey {
|
||||
public struct InfrastructurePreset: Codable {
|
||||
public enum PresetKeys: String, CodingKey {
|
||||
case id
|
||||
|
||||
case name
|
||||
|
@ -40,7 +40,7 @@ struct InfrastructurePreset: Codable {
|
|||
case configuration = "cfg"
|
||||
}
|
||||
|
||||
enum ConfigurationKeys: String, CodingKey {
|
||||
public enum ConfigurationKeys: String, CodingKey {
|
||||
case endpointProtocols = "ep"
|
||||
|
||||
case cipher
|
||||
|
@ -62,21 +62,21 @@ struct InfrastructurePreset: Codable {
|
|||
case usesPIAPatches = "pia"
|
||||
}
|
||||
|
||||
let id: String
|
||||
public let id: String
|
||||
|
||||
let name: String
|
||||
public let name: String
|
||||
|
||||
let comment: String
|
||||
public let comment: String
|
||||
|
||||
let configuration: TunnelKitProvider.Configuration
|
||||
public let configuration: TunnelKitProvider.Configuration
|
||||
|
||||
func hasProtocol(_ proto: EndpointProtocol) -> Bool {
|
||||
public func hasProtocol(_ proto: EndpointProtocol) -> Bool {
|
||||
return configuration.endpointProtocols.index(of: proto) != nil
|
||||
}
|
||||
|
||||
// MARK: Codable
|
||||
|
||||
init(from decoder: Decoder) throws {
|
||||
public init(from decoder: Decoder) throws {
|
||||
let container = try decoder.container(keyedBy: PresetKeys.self)
|
||||
id = try container.decode(String.self, forKey: .id)
|
||||
name = try container.decode(String.self, forKey: .name)
|
||||
|
@ -102,7 +102,7 @@ struct InfrastructurePreset: Codable {
|
|||
configuration = builder.build()
|
||||
}
|
||||
|
||||
func encode(to encoder: Encoder) throws {
|
||||
public func encode(to encoder: Encoder) throws {
|
||||
var container = encoder.container(keyedBy: PresetKeys.self)
|
||||
try container.encode(id, forKey: .id)
|
||||
try container.encode(name, forKey: .name)
|
||||
|
|
|
@ -26,8 +26,8 @@
|
|||
import Foundation
|
||||
import TunnelKit
|
||||
|
||||
struct Pool: Codable, Comparable, CustomStringConvertible {
|
||||
enum CodingKeys: String, CodingKey {
|
||||
public struct Pool: Codable, Comparable, CustomStringConvertible {
|
||||
public enum CodingKeys: String, CodingKey {
|
||||
case id
|
||||
|
||||
case name
|
||||
|
@ -41,19 +41,19 @@ struct Pool: Codable, Comparable, CustomStringConvertible {
|
|||
case numericAddresses = "addrs"
|
||||
}
|
||||
|
||||
let id: String
|
||||
public let id: String
|
||||
|
||||
let name: String
|
||||
public let name: String
|
||||
|
||||
let country: String
|
||||
public let country: String
|
||||
|
||||
// let location: (Double, Double)
|
||||
// public let location: (Double, Double)
|
||||
|
||||
let hostname: String
|
||||
public let hostname: String
|
||||
|
||||
let numericAddresses: [UInt32]
|
||||
public let numericAddresses: [UInt32]
|
||||
|
||||
func hasAddress(_ address: String) -> Bool {
|
||||
public func hasAddress(_ address: String) -> Bool {
|
||||
guard let ipv4 = DNSResolver.ipv4(fromString: address) else {
|
||||
return false
|
||||
}
|
||||
|
@ -61,7 +61,7 @@ struct Pool: Codable, Comparable, CustomStringConvertible {
|
|||
}
|
||||
|
||||
// XXX: inefficient, can't easily use lazy on struct
|
||||
func addresses() -> [String] {
|
||||
public func addresses() -> [String] {
|
||||
var addrs = numericAddresses.map { DNSResolver.string(fromIPv4: $0) }
|
||||
addrs.insert(hostname, at: 0)
|
||||
return addrs
|
||||
|
@ -69,13 +69,13 @@ struct Pool: Codable, Comparable, CustomStringConvertible {
|
|||
|
||||
// MARK: Comparable
|
||||
|
||||
static func <(lhs: Pool, rhs: Pool) -> Bool {
|
||||
public static func <(lhs: Pool, rhs: Pool) -> Bool {
|
||||
return lhs.name < rhs.name
|
||||
}
|
||||
|
||||
// MARK: CustomStringConvertible
|
||||
|
||||
var description: String {
|
||||
public var description: String {
|
||||
return "{[\(id)] \"\(name)\"}"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,8 +28,8 @@ import SwiftyBeaver
|
|||
|
||||
private let log = SwiftyBeaver.self
|
||||
|
||||
class WebServices {
|
||||
enum Endpoint {
|
||||
public class WebServices {
|
||||
public enum Endpoint {
|
||||
case network(Infrastructure.Name)
|
||||
|
||||
var path: String {
|
||||
|
@ -40,22 +40,22 @@ class WebServices {
|
|||
}
|
||||
}
|
||||
|
||||
struct Response<T> {
|
||||
let value: T?
|
||||
public struct Response<T> {
|
||||
public let value: T?
|
||||
|
||||
let lastModifiedString: String?
|
||||
public let lastModifiedString: String?
|
||||
|
||||
var lastModified: Date? {
|
||||
public var lastModified: Date? {
|
||||
guard let string = lastModifiedString else {
|
||||
return nil
|
||||
}
|
||||
return lmFormatter.date(from: string)
|
||||
}
|
||||
|
||||
let isCached: Bool
|
||||
public let isCached: Bool
|
||||
}
|
||||
|
||||
static let shared = WebServices()
|
||||
public static let shared = WebServices()
|
||||
|
||||
private static let lmFormatter: DateFormatter = {
|
||||
let fmt = DateFormatter()
|
||||
|
@ -64,7 +64,7 @@ class WebServices {
|
|||
return fmt
|
||||
}()
|
||||
|
||||
func network(with name: Infrastructure.Name, ifModifiedSince lastModified: Date?, completionHandler: @escaping (Response<Infrastructure>?, Error?) -> Void) {
|
||||
public func network(with name: Infrastructure.Name, ifModifiedSince lastModified: Date?, completionHandler: @escaping (Response<Infrastructure>?, Error?) -> Void) {
|
||||
var request = get(.network(name))
|
||||
if let lastModified = lastModified {
|
||||
request.addValue(WebServices.lmFormatter.string(from: lastModified), forHTTPHeaderField: "If-Modified-Since")
|
||||
|
|
|
@ -33,7 +33,7 @@ import SwiftyBeaver
|
|||
|
||||
private let log = SwiftyBeaver.self
|
||||
|
||||
class Utils {
|
||||
public class Utils {
|
||||
fileprivate static let timestampFormatter: DateFormatter = {
|
||||
let fmt = DateFormatter()
|
||||
fmt.dateStyle = .medium
|
||||
|
@ -47,7 +47,7 @@ class Utils {
|
|||
return fmt
|
||||
}()
|
||||
|
||||
static func versionString() -> String {
|
||||
public static func versionString() -> String {
|
||||
let info = Bundle.main.infoDictionary
|
||||
guard let version = info?["CFBundleShortVersionString"] else {
|
||||
fatalError("No bundle version?")
|
||||
|
@ -59,11 +59,11 @@ class Utils {
|
|||
}
|
||||
|
||||
#if targetEnvironment(simulator)
|
||||
static func hasCellularData() -> Bool {
|
||||
public static func hasCellularData() -> Bool {
|
||||
return true
|
||||
}
|
||||
#else
|
||||
static func hasCellularData() -> Bool {
|
||||
public static func hasCellularData() -> Bool {
|
||||
var addrs: UnsafeMutablePointer<ifaddrs>?
|
||||
guard getifaddrs(&addrs) == 0 else {
|
||||
return false
|
||||
|
@ -84,12 +84,12 @@ class Utils {
|
|||
#endif
|
||||
|
||||
#if targetEnvironment(simulator)
|
||||
static func currentWifiNetworkName() -> String? {
|
||||
public static func currentWifiNetworkName() -> String? {
|
||||
// return nil
|
||||
return ["FOO", "BAR", "WIFI"].customRandomElement()
|
||||
}
|
||||
#else
|
||||
static func currentWifiNetworkName() -> String? {
|
||||
public static func currentWifiNetworkName() -> String? {
|
||||
#if os(iOS)
|
||||
guard let interfaceNames = CNCopySupportedInterfaces() as? [CFString] else {
|
||||
return nil
|
||||
|
@ -109,11 +109,11 @@ class Utils {
|
|||
}
|
||||
#endif
|
||||
|
||||
static func regex(_ pattern: String) -> NSRegularExpression {
|
||||
public static func regex(_ pattern: String) -> NSRegularExpression {
|
||||
return try! NSRegularExpression(pattern: pattern, options: [])
|
||||
}
|
||||
|
||||
static func checkConnectivityURL(_ url: URL, timeout: TimeInterval, completionHandler: @escaping (Bool) -> Void) {
|
||||
public static func checkConnectivityURL(_ url: URL, timeout: TimeInterval, completionHandler: @escaping (Bool) -> Void) {
|
||||
let session = URLSession(configuration: .ephemeral)
|
||||
let request = URLRequest(url: url, cachePolicy: .reloadIgnoringLocalAndRemoteCacheData, timeoutInterval: timeout)
|
||||
|
||||
|
@ -137,7 +137,7 @@ class Utils {
|
|||
}
|
||||
}
|
||||
|
||||
extension FileManager {
|
||||
public extension FileManager {
|
||||
func userURL(for searchPath: SearchPathDirectory, appending: String?) -> URL {
|
||||
let paths = urls(for: .documentDirectory, in: .userDomainMask)
|
||||
var directory = paths[0]
|
||||
|
@ -155,13 +155,13 @@ extension FileManager {
|
|||
}
|
||||
}
|
||||
|
||||
extension Date {
|
||||
public extension Date {
|
||||
var timestamp: String {
|
||||
return Utils.timestampFormatter.string(from: self)
|
||||
}
|
||||
}
|
||||
|
||||
extension TimeInterval {
|
||||
public extension TimeInterval {
|
||||
var localized: String {
|
||||
guard let str = Utils.componentsFormatter.string(from: self) else {
|
||||
fatalError("Could not format a TimeInterval?")
|
||||
|
@ -170,7 +170,7 @@ extension TimeInterval {
|
|||
}
|
||||
}
|
||||
|
||||
extension Sequence {
|
||||
public extension Sequence {
|
||||
func stableSorted(by areInIncreasingOrder: (Element, Element) throws -> Bool) rethrows -> [Element] {
|
||||
return try enumerated().sorted {
|
||||
return try areInIncreasingOrder($0.element, $1.element) ||
|
||||
|
@ -179,20 +179,20 @@ extension Sequence {
|
|||
}
|
||||
}
|
||||
|
||||
extension Array {
|
||||
public extension Array {
|
||||
func customRandomElement() -> Element {
|
||||
let i = Int(arc4random() % UInt32(count))
|
||||
return self[i]
|
||||
}
|
||||
}
|
||||
|
||||
extension StringProtocol where Index == String.Index {
|
||||
public extension StringProtocol where Index == String.Index {
|
||||
func nsRange(from range: Range<Index>) -> NSRange {
|
||||
return NSRange(range, in: self)
|
||||
}
|
||||
}
|
||||
|
||||
extension CharacterSet {
|
||||
public extension CharacterSet {
|
||||
static let filename: CharacterSet = {
|
||||
var chars: CharacterSet = .decimalDigits
|
||||
let english = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
|
@ -204,7 +204,7 @@ extension CharacterSet {
|
|||
}()
|
||||
}
|
||||
|
||||
extension URL {
|
||||
public extension URL {
|
||||
private static let illegalCharacterFallback = "_"
|
||||
|
||||
var normalizedFilename: String {
|
||||
|
@ -213,8 +213,8 @@ extension URL {
|
|||
}
|
||||
}
|
||||
|
||||
extension Array where Element: CustomStringConvertible {
|
||||
public func sortedCaseInsensitive() -> [Element] {
|
||||
public extension Array where Element: CustomStringConvertible {
|
||||
func sortedCaseInsensitive() -> [Element] {
|
||||
return sorted { $0.description.lowercased() < $1.description.lowercased() }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,10 +28,10 @@ import SwiftyBeaver
|
|||
|
||||
private let log = SwiftyBeaver.self
|
||||
|
||||
class GracefulVPN {
|
||||
public class GracefulVPN {
|
||||
private let service: ConnectionService
|
||||
|
||||
var profile: ConnectionProfile?
|
||||
public var profile: ConnectionProfile?
|
||||
|
||||
private var vpn: VPNProvider? {
|
||||
guard let profile = profile else {
|
||||
|
@ -43,19 +43,19 @@ class GracefulVPN {
|
|||
return VPN.shared
|
||||
}
|
||||
|
||||
var isEnabled: Bool {
|
||||
public var isEnabled: Bool {
|
||||
return vpn?.isEnabled ?? false
|
||||
}
|
||||
|
||||
var status: VPNStatus? {
|
||||
public var status: VPNStatus? {
|
||||
return vpn?.status
|
||||
}
|
||||
|
||||
init(service: ConnectionService) {
|
||||
public init(service: ConnectionService) {
|
||||
self.service = service
|
||||
}
|
||||
|
||||
func prepare(completionHandler: (() -> Void)?) {
|
||||
public func prepare(completionHandler: (() -> Void)?) {
|
||||
service.clearVpnLastError()
|
||||
guard let vpn = vpn else {
|
||||
completionHandler?()
|
||||
|
@ -65,7 +65,7 @@ class GracefulVPN {
|
|||
vpn.prepare(completionHandler: completionHandler)
|
||||
}
|
||||
|
||||
func reconnect(completionHandler: ((Error?) -> Void)?) {
|
||||
public func reconnect(completionHandler: ((Error?) -> Void)?) {
|
||||
service.clearVpnLastError()
|
||||
guard let vpn = vpn else {
|
||||
completionHandler?(ApplicationError.inactiveProfile)
|
||||
|
@ -79,7 +79,7 @@ class GracefulVPN {
|
|||
}
|
||||
}
|
||||
|
||||
func reinstall(completionHandler: ((Error?) -> Void)?) {
|
||||
public func reinstall(completionHandler: ((Error?) -> Void)?) {
|
||||
service.clearVpnLastError()
|
||||
guard let vpn = vpn else {
|
||||
completionHandler?(ApplicationError.inactiveProfile)
|
||||
|
@ -93,7 +93,7 @@ class GracefulVPN {
|
|||
}
|
||||
}
|
||||
|
||||
func reinstallIfEnabled() {
|
||||
public func reinstallIfEnabled() {
|
||||
guard isEnabled else {
|
||||
log.warning("Not reinstalling (VPN is disabled)")
|
||||
return
|
||||
|
@ -105,7 +105,7 @@ class GracefulVPN {
|
|||
}
|
||||
}
|
||||
|
||||
func disconnect(completionHandler: ((Error?) -> Void)?) {
|
||||
public func disconnect(completionHandler: ((Error?) -> Void)?) {
|
||||
guard let vpn = vpn else {
|
||||
completionHandler?(ApplicationError.inactiveProfile)
|
||||
return
|
||||
|
@ -113,7 +113,7 @@ class GracefulVPN {
|
|||
vpn.disconnect(completionHandler: completionHandler)
|
||||
}
|
||||
|
||||
func uninstall(completionHandler: (() -> Void)?) {
|
||||
public func uninstall(completionHandler: (() -> Void)?) {
|
||||
guard let vpn = vpn else {
|
||||
completionHandler?()
|
||||
return
|
||||
|
@ -121,7 +121,7 @@ class GracefulVPN {
|
|||
vpn.uninstall(completionHandler: completionHandler)
|
||||
}
|
||||
|
||||
func requestBytesCount(completionHandler: @escaping ((UInt, UInt)?) -> Void) {
|
||||
public func requestBytesCount(completionHandler: @escaping ((UInt, UInt)?) -> Void) {
|
||||
guard let vpn = vpn else {
|
||||
completionHandler(nil)
|
||||
return
|
||||
|
|
|
@ -25,57 +25,57 @@
|
|||
|
||||
import Foundation
|
||||
|
||||
class MockVPNProvider: VPNProvider {
|
||||
let isPrepared: Bool = true
|
||||
public class MockVPNProvider: VPNProvider {
|
||||
public let isPrepared: Bool = true
|
||||
|
||||
private(set) var isEnabled: Bool = false
|
||||
public private(set) var isEnabled: Bool = false
|
||||
|
||||
private(set) var status: VPNStatus = .disconnected
|
||||
public private(set) var status: VPNStatus = .disconnected
|
||||
|
||||
func prepare(completionHandler: (() -> Void)?) {
|
||||
public func prepare(completionHandler: (() -> Void)?) {
|
||||
NotificationCenter.default.post(name: .VPNDidPrepare, object: nil)
|
||||
completionHandler?()
|
||||
}
|
||||
|
||||
func install(configuration: VPNConfiguration, completionHandler: ((Error?) -> Void)?) {
|
||||
public func install(configuration: VPNConfiguration, completionHandler: ((Error?) -> Void)?) {
|
||||
isEnabled = true
|
||||
completionHandler?(nil)
|
||||
}
|
||||
|
||||
func connect(completionHandler: ((Error?) -> Void)?) {
|
||||
public func connect(completionHandler: ((Error?) -> Void)?) {
|
||||
isEnabled = true
|
||||
status = .connected
|
||||
NotificationCenter.default.post(name: .VPNDidChangeStatus, object: self)
|
||||
completionHandler?(nil)
|
||||
}
|
||||
|
||||
func disconnect(completionHandler: ((Error?) -> Void)?) {
|
||||
public func disconnect(completionHandler: ((Error?) -> Void)?) {
|
||||
isEnabled = false
|
||||
status = .disconnected
|
||||
NotificationCenter.default.post(name: .VPNDidChangeStatus, object: self)
|
||||
completionHandler?(nil)
|
||||
}
|
||||
|
||||
func reconnect(configuration: VPNConfiguration, completionHandler: ((Error?) -> Void)?) {
|
||||
public func reconnect(configuration: VPNConfiguration, completionHandler: ((Error?) -> Void)?) {
|
||||
isEnabled = true
|
||||
status = .connected
|
||||
NotificationCenter.default.post(name: .VPNDidChangeStatus, object: self)
|
||||
completionHandler?(nil)
|
||||
}
|
||||
|
||||
func uninstall(completionHandler: (() -> Void)?) {
|
||||
public func uninstall(completionHandler: (() -> Void)?) {
|
||||
isEnabled = false
|
||||
status = .disconnected
|
||||
NotificationCenter.default.post(name: .VPNDidChangeStatus, object: self)
|
||||
completionHandler?()
|
||||
}
|
||||
|
||||
func requestDebugLog(fallback: (() -> String)?, completionHandler: @escaping (String) -> Void) {
|
||||
public func requestDebugLog(fallback: (() -> String)?, completionHandler: @escaping (String) -> Void) {
|
||||
let log = [String](repeating: "lorem ipsum", count: 1000).joined(separator: " ")
|
||||
completionHandler(log)
|
||||
}
|
||||
|
||||
func requestBytesCount(completionHandler: @escaping ((UInt, UInt)?) -> Void) {
|
||||
public func requestBytesCount(completionHandler: @escaping ((UInt, UInt)?) -> Void) {
|
||||
completionHandler((0, 0))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,14 +27,14 @@ import Foundation
|
|||
import NetworkExtension
|
||||
import TunnelKit
|
||||
|
||||
class StandardVPNProvider: VPNProvider {
|
||||
public class StandardVPNProvider: VPNProvider {
|
||||
private let bundleIdentifier: String
|
||||
|
||||
private var manager: NETunnelProviderManager?
|
||||
|
||||
private var lastNotifiedStatus: VPNStatus?
|
||||
|
||||
init(bundleIdentifier: String) {
|
||||
public init(bundleIdentifier: String) {
|
||||
self.bundleIdentifier = bundleIdentifier
|
||||
|
||||
let nc = NotificationCenter.default
|
||||
|
@ -48,18 +48,18 @@ class StandardVPNProvider: VPNProvider {
|
|||
|
||||
// MARK: VPNProvider
|
||||
|
||||
var isPrepared: Bool {
|
||||
public var isPrepared: Bool {
|
||||
return manager != nil
|
||||
}
|
||||
|
||||
var isEnabled: Bool {
|
||||
public var isEnabled: Bool {
|
||||
guard let manager = manager else {
|
||||
return false
|
||||
}
|
||||
return manager.isEnabled && manager.isOnDemandEnabled
|
||||
}
|
||||
|
||||
var status: VPNStatus {
|
||||
public var status: VPNStatus {
|
||||
guard let neStatus = manager?.connection.status else {
|
||||
return .disconnected
|
||||
}
|
||||
|
@ -78,7 +78,7 @@ class StandardVPNProvider: VPNProvider {
|
|||
}
|
||||
}
|
||||
|
||||
func prepare(completionHandler: (() -> Void)?) {
|
||||
public func prepare(completionHandler: (() -> Void)?) {
|
||||
find(with: bundleIdentifier) {
|
||||
self.manager = $0
|
||||
NotificationCenter.default.post(name: .VPNDidPrepare, object: nil)
|
||||
|
@ -86,7 +86,7 @@ class StandardVPNProvider: VPNProvider {
|
|||
}
|
||||
}
|
||||
|
||||
func install(configuration: VPNConfiguration, completionHandler: ((Error?) -> Void)?) {
|
||||
public func install(configuration: VPNConfiguration, completionHandler: ((Error?) -> Void)?) {
|
||||
guard let configuration = configuration as? NetworkExtensionVPNConfiguration else {
|
||||
fatalError("Not a NetworkExtensionVPNConfiguration")
|
||||
}
|
||||
|
@ -110,7 +110,7 @@ class StandardVPNProvider: VPNProvider {
|
|||
}
|
||||
}
|
||||
|
||||
func connect(completionHandler: ((Error?) -> Void)?) {
|
||||
public func connect(completionHandler: ((Error?) -> Void)?) {
|
||||
do {
|
||||
try manager?.connection.startVPNTunnel()
|
||||
completionHandler?(nil)
|
||||
|
@ -119,14 +119,14 @@ class StandardVPNProvider: VPNProvider {
|
|||
}
|
||||
}
|
||||
|
||||
func disconnect(completionHandler: ((Error?) -> Void)?) {
|
||||
public func disconnect(completionHandler: ((Error?) -> Void)?) {
|
||||
manager?.connection.stopVPNTunnel()
|
||||
manager?.isOnDemandEnabled = false
|
||||
manager?.isEnabled = false
|
||||
manager?.saveToPreferences(completionHandler: completionHandler)
|
||||
}
|
||||
|
||||
func reconnect(configuration: VPNConfiguration, completionHandler: ((Error?) -> Void)?) {
|
||||
public func reconnect(configuration: VPNConfiguration, completionHandler: ((Error?) -> Void)?) {
|
||||
guard let configuration = configuration as? NetworkExtensionVPNConfiguration else {
|
||||
fatalError("Not a NetworkExtensionVPNConfiguration")
|
||||
}
|
||||
|
@ -147,7 +147,7 @@ class StandardVPNProvider: VPNProvider {
|
|||
}
|
||||
}
|
||||
|
||||
func uninstall(completionHandler: (() -> Void)?) {
|
||||
public func uninstall(completionHandler: (() -> Void)?) {
|
||||
find(with: bundleIdentifier) { (manager) in
|
||||
manager?.connection.stopVPNTunnel()
|
||||
manager?.removeFromPreferences { (error) in
|
||||
|
@ -157,7 +157,7 @@ class StandardVPNProvider: VPNProvider {
|
|||
}
|
||||
}
|
||||
|
||||
func requestDebugLog(fallback: (() -> String)?, completionHandler: @escaping (String) -> Void) {
|
||||
public func requestDebugLog(fallback: (() -> String)?, completionHandler: @escaping (String) -> Void) {
|
||||
guard status != .disconnected else {
|
||||
completionHandler(fallback?() ?? "")
|
||||
return
|
||||
|
@ -173,7 +173,7 @@ class StandardVPNProvider: VPNProvider {
|
|||
}
|
||||
}
|
||||
|
||||
func requestBytesCount(completionHandler: @escaping ((UInt, UInt)?) -> Void) {
|
||||
public func requestBytesCount(completionHandler: @escaping ((UInt, UInt)?) -> Void) {
|
||||
find(with: bundleIdentifier) {
|
||||
self.manager = $0
|
||||
guard let session = self.manager?.connection as? NETunnelProviderSession else {
|
||||
|
|
|
@ -25,10 +25,10 @@
|
|||
|
||||
import Foundation
|
||||
|
||||
class VPN {
|
||||
public class VPN {
|
||||
#if targetEnvironment(simulator)
|
||||
static let shared = MockVPNProvider()
|
||||
public static let shared = MockVPNProvider()
|
||||
#else
|
||||
static let shared = StandardVPNProvider(bundleIdentifier: GroupConstants.App.tunnelIdentifier)
|
||||
public static let shared = StandardVPNProvider(bundleIdentifier: GroupConstants.App.tunnelIdentifier)
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -26,11 +26,11 @@
|
|||
import Foundation
|
||||
import NetworkExtension
|
||||
|
||||
protocol VPNConfiguration {
|
||||
public protocol VPNConfiguration {
|
||||
}
|
||||
|
||||
struct NetworkExtensionVPNConfiguration: VPNConfiguration {
|
||||
let protocolConfiguration: NETunnelProviderProtocol
|
||||
public struct NetworkExtensionVPNConfiguration: VPNConfiguration {
|
||||
public let protocolConfiguration: NETunnelProviderProtocol
|
||||
|
||||
let onDemandRules: [NEOnDemandRule]
|
||||
public let onDemandRules: [NEOnDemandRule]
|
||||
}
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
|
||||
import Foundation
|
||||
|
||||
protocol VPNProvider: class {
|
||||
public protocol VPNProvider: class {
|
||||
var isPrepared: Bool { get }
|
||||
|
||||
var isEnabled: Bool { get }
|
||||
|
@ -49,7 +49,7 @@ protocol VPNProvider: class {
|
|||
func requestBytesCount(completionHandler: @escaping ((UInt, UInt)?) -> Void)
|
||||
}
|
||||
|
||||
extension Notification.Name {
|
||||
public extension Notification.Name {
|
||||
static let VPNDidPrepare = Notification.Name("VPNDidPrepare")
|
||||
|
||||
static let VPNDidChangeStatus = Notification.Name("VPNDidChangeStatus")
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
|
||||
import Foundation
|
||||
|
||||
enum VPNStatus {
|
||||
public enum VPNStatus {
|
||||
case connected
|
||||
|
||||
case connecting
|
||||
|
|
Loading…
Reference in New Issue