Merge branch 'improve-tunnel-status-reporting'

This commit is contained in:
Davide De Rosa 2018-10-23 12:56:49 +02:00
commit 4ac3017c59
15 changed files with 104 additions and 23 deletions

View File

@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Added ### Added
- Tunnel failure reporting in UI. [#8](https://github.com/keeshux/passepartout-ios/pull/8)
- Explicit "Reconnect" button. [#9](https://github.com/keeshux/passepartout-ios/pull/9) - Explicit "Reconnect" button. [#9](https://github.com/keeshux/passepartout-ios/pull/9)
### Fixed ### Fixed

View File

@ -24,6 +24,7 @@
// //
import UIKit import UIKit
import TunnelKit
extension UITableViewCell { extension UITableViewCell {
func applyChecked(_ checked: Bool, _ theme: Theme) { func applyChecked(_ checked: Bool, _ theme: Theme) {
@ -66,7 +67,7 @@ extension SettingTableViewCell {
accessoryType = .none accessoryType = .none
} }
func applyVPN(_ theme: Theme, with vpnStatus: VPNStatus?) { func applyVPN(_ theme: Theme, with vpnStatus: VPNStatus?, error: TunnelKitProvider.ProviderError?) {
leftTextColor = theme.palette.colorPrimaryText leftTextColor = theme.palette.colorPrimaryText
guard let vpnStatus = vpnStatus else { guard let vpnStatus = vpnStatus else {
rightText = L10n.Vpn.disabled rightText = L10n.Vpn.disabled
@ -83,13 +84,41 @@ extension SettingTableViewCell {
rightText = L10n.Vpn.active rightText = L10n.Vpn.active
rightTextColor = theme.palette.colorOn rightTextColor = theme.palette.colorOn
case .disconnecting: case .disconnecting, .disconnected:
rightText = L10n.Vpn.disconnecting var disconnectionReason: String?
rightTextColor = theme.palette.colorIndeterminate if let error = error {
switch error {
case .disconnected: case .socketActivity, .timeout:
rightText = L10n.Vpn.inactive disconnectionReason = L10n.Vpn.Errors.timeout
rightTextColor = theme.palette.colorOff
case .dnsFailure:
disconnectionReason = L10n.Vpn.Errors.dns
case .tlsFailed:
disconnectionReason = L10n.Vpn.Errors.tls
case .authenticationFailed:
disconnectionReason = L10n.Vpn.Errors.auth
case .networkChanged:
disconnectionReason = L10n.Vpn.Errors.network
default:
break
}
}
switch vpnStatus {
case .disconnecting:
rightText = disconnectionReason ?? L10n.Vpn.disconnecting
rightTextColor = theme.palette.colorIndeterminate
case .disconnected:
rightText = disconnectionReason ?? L10n.Vpn.inactive
rightTextColor = theme.palette.colorOff
default:
break
}
} }
} }
} }

View File

@ -293,7 +293,7 @@ extension EndpointViewController: UITableViewDataSource, UITableViewDelegate {
setNeedsRefresh() setNeedsRefresh()
commitChanges() commitChanges()
tableView.reloadRows(at: updatedIndexPaths, with: .automatic) tableView.reloadRows(at: updatedIndexPaths, with: .none)
} }
// MARK: Helpers // MARK: Helpers

View File

@ -88,6 +88,7 @@ class ServiceViewController: UIViewController, TableModelHost {
let nc = NotificationCenter.default let nc = NotificationCenter.default
nc.addObserver(self, selector: #selector(applicationDidBecomeActive), name: UIApplication.didBecomeActiveNotification, object: nil) nc.addObserver(self, selector: #selector(applicationDidBecomeActive), name: UIApplication.didBecomeActiveNotification, object: nil)
nc.addObserver(self, selector: #selector(vpnDidUpdate), name: .VPNDidChangeStatus, object: nil) nc.addObserver(self, selector: #selector(vpnDidUpdate), name: .VPNDidChangeStatus, object: nil)
nc.addObserver(self, selector: #selector(vpnDidUpdate), name: .VPNDidReinstall, object: nil)
// run this no matter what // run this no matter what
// XXX: convenient here vs AppDelegate for updating table // XXX: convenient here vs AppDelegate for updating table
@ -529,7 +530,7 @@ extension ServiceViewController: UITableViewDataSource, UITableViewDelegate, Tog
} }
let cell = Cells.setting.dequeue(from: tableView, for: indexPath) let cell = Cells.setting.dequeue(from: tableView, for: indexPath)
cell.applyVPN(Theme.current, with: vpn.isEnabled ? vpn.status : nil) cell.applyVPN(Theme.current, with: vpn.isEnabled ? vpn.status : nil, error: service.vpnLastError)
cell.leftText = L10n.Service.Cells.ConnectionStatus.caption cell.leftText = L10n.Service.Cells.ConnectionStatus.caption
cell.accessoryType = .none cell.accessoryType = .none
cell.isTappable = false cell.isTappable = false
@ -901,7 +902,7 @@ extension ServiceViewController: UITableViewDataSource, UITableViewDelegate, Tog
guard service.isActiveProfile(profile) else { guard service.isActiveProfile(profile) else {
return return
} }
tableView.reloadRows(at: [statusIndexPath], with: .automatic) tableView.reloadRows(at: [statusIndexPath], with: .none)
} }
func reloadSelectedRow(andRowAt indexPath: IndexPath? = nil) { func reloadSelectedRow(andRowAt indexPath: IndexPath? = nil) {

View File

@ -161,6 +161,12 @@
"vpn.inactive" = "Inactive"; "vpn.inactive" = "Inactive";
"vpn.disabled" = "Disabled"; "vpn.disabled" = "Disabled";
"vpn.errors.timeout" = "Timeout";
"vpn.errors.auth" = "Auth failed";
"vpn.errors.tls" = "TLS failed";
"vpn.errors.dns" = "DNS failed";
"vpn.errors.network" = "Network changed";
"issue_reporter.title" = "Submit debug log"; "issue_reporter.title" = "Submit debug log";
"issue_reporter.message" = "The debug log of your latest connections is crucial to resolve your connectivity issues and is completely anonymous."; "issue_reporter.message" = "The debug log of your latest connections is crucial to resolve your connectivity issues and is completely anonymous.";
"issue_reporter.buttons.accept" = "I understand"; "issue_reporter.buttons.accept" = "I understand";

View File

@ -47,6 +47,7 @@ class AppConstants {
// builder.debugLogFormat = "$DHH:mm:ss$d $N.$F:$l - $M" // builder.debugLogFormat = "$DHH:mm:ss$d $N.$F:$l - $M"
builder.debugLogFormat = Log.debugFormat builder.debugLogFormat = Log.debugFormat
builder.debugLogKey = "LastVPNLog" builder.debugLogKey = "LastVPNLog"
builder.lastErrorKey = "LastVPNError"
return builder.build() return builder.build()
} }

View File

@ -276,6 +276,23 @@ class ConnectionService: Codable {
return lines.joined(separator: "\n") return lines.joined(separator: "\n")
} }
var vpnLastError: TunnelKitProvider.ProviderError? {
guard let key = tunnelConfiguration.lastErrorKey else {
return nil
}
guard let rawValue = defaults.string(forKey: key) else {
return nil
}
return TunnelKitProvider.ProviderError(rawValue: rawValue)
}
func clearVpnLastError() {
guard let key = tunnelConfiguration.lastErrorKey else {
return
}
defaults.removeObject(forKey: key)
}
// func eraseVpnLog() { // func eraseVpnLog() {
// defaults.removeObject(forKey: Keys.vpnLog) // defaults.removeObject(forKey: Keys.vpnLog)
// } // }

View File

@ -60,6 +60,7 @@ class HostConnectionProfile: ConnectionProfile, Codable, Equatable {
builder.shouldDebug = configuration.shouldDebug builder.shouldDebug = configuration.shouldDebug
builder.debugLogFormat = configuration.debugLogFormat builder.debugLogFormat = configuration.debugLogFormat
builder.debugLogKey = configuration.debugLogKey builder.debugLogKey = configuration.debugLogKey
builder.lastErrorKey = configuration.lastErrorKey
return builder.build() return builder.build()
} }

View File

@ -121,6 +121,7 @@ class ProviderConnectionProfile: ConnectionProfile, Codable, Equatable {
builder.shouldDebug = configuration.shouldDebug builder.shouldDebug = configuration.shouldDebug
builder.debugLogFormat = configuration.debugLogFormat builder.debugLogFormat = configuration.debugLogFormat
builder.debugLogKey = configuration.debugLogKey builder.debugLogKey = configuration.debugLogKey
builder.lastErrorKey = configuration.lastErrorKey
if let address = manualAddress { if let address = manualAddress {
builder.prefersResolvedAddresses = true builder.prefersResolvedAddresses = true

View File

@ -686,6 +686,19 @@ internal enum L10n {
internal static let disconnecting = L10n.tr("Localizable", "vpn.disconnecting") internal static let disconnecting = L10n.tr("Localizable", "vpn.disconnecting")
/// Inactive /// Inactive
internal static let inactive = L10n.tr("Localizable", "vpn.inactive") internal static let inactive = L10n.tr("Localizable", "vpn.inactive")
internal enum Errors {
/// Auth failed
internal static let auth = L10n.tr("Localizable", "vpn.errors.auth")
/// DNS failed
internal static let dns = L10n.tr("Localizable", "vpn.errors.dns")
/// Network changed
internal static let network = L10n.tr("Localizable", "vpn.errors.network")
/// Timeout
internal static let timeout = L10n.tr("Localizable", "vpn.errors.timeout")
/// TLS failed
internal static let tls = L10n.tr("Localizable", "vpn.errors.tls")
}
} }
internal enum Wizards { internal enum Wizards {

View File

@ -58,10 +58,12 @@ class GracefulVPN {
func prepare(withProfile profile: ConnectionProfile?, completionHandler: (() -> Void)?) { func prepare(withProfile profile: ConnectionProfile?, completionHandler: (() -> Void)?) {
self.profile = profile self.profile = profile
log.info("Preparing...") log.info("Preparing...")
service.clearVpnLastError()
vpn?.prepare(completionHandler: completionHandler) vpn?.prepare(completionHandler: completionHandler)
} }
func reconnect(completionHandler: ((Error?) -> Void)?) { func reconnect(completionHandler: ((Error?) -> Void)?) {
service.clearVpnLastError()
do { do {
log.info("Reconnecting...") log.info("Reconnecting...")
try vpn?.reconnect(configuration: service.vpnConfiguration(), completionHandler: completionHandler) try vpn?.reconnect(configuration: service.vpnConfiguration(), completionHandler: completionHandler)
@ -71,6 +73,7 @@ class GracefulVPN {
} }
func reinstall(completionHandler: ((Error?) -> Void)?) { func reinstall(completionHandler: ((Error?) -> Void)?) {
service.clearVpnLastError()
do { do {
log.info("Reinstalling...") log.info("Reinstalling...")
try vpn?.install(configuration: service.vpnConfiguration(), completionHandler: completionHandler) try vpn?.install(configuration: service.vpnConfiguration(), completionHandler: completionHandler)

View File

@ -37,7 +37,9 @@ class StandardVPNProvider: VPNProvider {
init(bundleIdentifier: String) { init(bundleIdentifier: String) {
self.bundleIdentifier = bundleIdentifier self.bundleIdentifier = bundleIdentifier
NotificationCenter.default.addObserver(self, selector: #selector(vpnDidUpdate(_:)), name: .NEVPNStatusDidChange, object: nil) let nc = NotificationCenter.default
nc.addObserver(self, selector: #selector(vpnDidUpdate(_:)), name: .NEVPNStatusDidChange, object: nil)
nc.addObserver(self, selector: #selector(vpnDidReinstall(_:)), name: .NEVPNConfigurationChange, object: nil)
} }
deinit { deinit {
@ -264,4 +266,8 @@ class StandardVPNProvider: VPNProvider {
NotificationCenter.default.post(name: .VPNDidChangeStatus, object: self) NotificationCenter.default.post(name: .VPNDidChangeStatus, object: self)
} }
@objc private func vpnDidReinstall(_ notification: Notification) {
NotificationCenter.default.post(name: .VPNDidReinstall, object: self)
}
} }

View File

@ -53,4 +53,6 @@ extension Notification.Name {
static let VPNDidPrepare = Notification.Name("VPNDidPrepare") static let VPNDidPrepare = Notification.Name("VPNDidPrepare")
static let VPNDidChangeStatus = Notification.Name("VPNDidChangeStatus") static let VPNDidChangeStatus = Notification.Name("VPNDidChangeStatus")
static let VPNDidReinstall = Notification.Name("VPNDidReinstall")
} }

View File

@ -3,7 +3,7 @@ use_frameworks!
def shared_pods def shared_pods
#pod 'TunnelKit', '~> 1.1.2' #pod 'TunnelKit', '~> 1.1.2'
pod 'TunnelKit', :git => 'https://github.com/keeshux/tunnelkit', :commit => '29ec39f' pod 'TunnelKit', :git => 'https://github.com/keeshux/tunnelkit', :commit => '9829475'
#pod 'TunnelKit', :path => '../tunnelkit' #pod 'TunnelKit', :path => '../tunnelkit'
end end

View File

@ -2,19 +2,19 @@ PODS:
- MBProgressHUD (1.1.0) - MBProgressHUD (1.1.0)
- OpenSSL-Apple (1.1.0i-v2) - OpenSSL-Apple (1.1.0i-v2)
- SwiftyBeaver (1.6.1) - SwiftyBeaver (1.6.1)
- TunnelKit (1.2.0): - TunnelKit (1.2.1):
- TunnelKit/AppExtension (= 1.2.0) - TunnelKit/AppExtension (= 1.2.1)
- TunnelKit/Core (= 1.2.0) - TunnelKit/Core (= 1.2.1)
- TunnelKit/AppExtension (1.2.0): - TunnelKit/AppExtension (1.2.1):
- SwiftyBeaver - SwiftyBeaver
- TunnelKit/Core - TunnelKit/Core
- TunnelKit/Core (1.2.0): - TunnelKit/Core (1.2.1):
- OpenSSL-Apple (~> 1.1.0h) - OpenSSL-Apple (~> 1.1.0h)
- SwiftyBeaver - SwiftyBeaver
DEPENDENCIES: DEPENDENCIES:
- MBProgressHUD - MBProgressHUD
- TunnelKit (from `https://github.com/keeshux/tunnelkit`, commit `29ec39f`) - TunnelKit (from `https://github.com/keeshux/tunnelkit`, commit `9829475`)
SPEC REPOS: SPEC REPOS:
https://github.com/cocoapods/specs.git: https://github.com/cocoapods/specs.git:
@ -24,20 +24,20 @@ SPEC REPOS:
EXTERNAL SOURCES: EXTERNAL SOURCES:
TunnelKit: TunnelKit:
:commit: 29ec39f :commit: '9829475'
:git: https://github.com/keeshux/tunnelkit :git: https://github.com/keeshux/tunnelkit
CHECKOUT OPTIONS: CHECKOUT OPTIONS:
TunnelKit: TunnelKit:
:commit: 29ec39f :commit: '9829475'
:git: https://github.com/keeshux/tunnelkit :git: https://github.com/keeshux/tunnelkit
SPEC CHECKSUMS: SPEC CHECKSUMS:
MBProgressHUD: e7baa36a220447d8aeb12769bf0585582f3866d9 MBProgressHUD: e7baa36a220447d8aeb12769bf0585582f3866d9
OpenSSL-Apple: a93b8f2eec8783ff40d9a9304de180ab68bb647c OpenSSL-Apple: a93b8f2eec8783ff40d9a9304de180ab68bb647c
SwiftyBeaver: ccfcdf85a04d429f1633f668650b0ce8020bda3a SwiftyBeaver: ccfcdf85a04d429f1633f668650b0ce8020bda3a
TunnelKit: aad1982c96ba0eace1494d4020ecdd1a34c5a788 TunnelKit: 6c790dfbcb0042d6a5dfe2fda5b0eb5b895afaf1
PODFILE CHECKSUM: 3d7c4db47830b499bdcf24c498e36b5c619e2ad1 PODFILE CHECKSUM: 9054389b89f51fe7517cfecebde6520280df4799
COCOAPODS: 1.6.0.beta.2 COCOAPODS: 1.6.0.beta.2