Localize remaining strings in network extension

Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
This commit is contained in:
Jason A. Donenfeld 2018-12-22 03:41:54 +01:00
parent 9d9859248e
commit 8365adf435
5 changed files with 42 additions and 40 deletions

View File

@ -3,6 +3,14 @@
import NetworkExtension import NetworkExtension
enum PacketTunnelProviderError: String, Error {
case savedProtocolConfigurationIsInvalid
case dnsResolutionFailure
case couldNotStartBackend
case couldNotDetermineFileDescriptor
case couldNotSetNetworkSettings
}
extension NETunnelProviderProtocol { extension NETunnelProviderProtocol {
enum Keys: String { enum Keys: String {

View File

@ -178,15 +178,23 @@
"alertTunnelActivationFailureTitle" = "Activation failure"; "alertTunnelActivationFailureTitle" = "Activation failure";
"alertTunnelActivationFailureMessage" = "The tunnel could not be activated. Please ensure that you are connected to the Internet."; "alertTunnelActivationFailureMessage" = "The tunnel could not be activated. Please ensure that you are connected to the Internet.";
"alertTunnelActivationSavedConfigFailureMessage" = "Unable to retrieve tunnel information from the saved configuration.";
"alertTunnelActivationBackendFailureMessage" = "Unable to turn on Go backend library.";
"alertTunnelActivationFileDescriptorFailureMessage" = "Unable to determine TUN device file descriptor.";
"alertTunnelActivationSetNetworkSettingsMessage" = "Unable to apply network settings to tunnel object.";
"alertTunnelActivationFailureOnDemandAddendum" = " This tunnel has Activate On Demand enabled, so this tunnel might be re-activated automatically by the OS. You may turn off Activate On Demand in this app by editing the tunnel configuration."; "alertTunnelActivationFailureOnDemandAddendum" = " This tunnel has Activate On Demand enabled, so this tunnel might be re-activated automatically by the OS. You may turn off Activate On Demand in this app by editing the tunnel configuration.";
"alertTunnelDNSFailureTitle" = "DNS resolution failure";
"alertTunnelDNSFailureMessage" = "One or more endpoint domains could not be resolved.";
"alertTunnelNameEmptyTitle" = "No name provided"; "alertTunnelNameEmptyTitle" = "No name provided";
"alertTunnelNameEmptyMessage" = "Cannot create tunnel with an empty name"; "alertTunnelNameEmptyMessage" = "Cannot create tunnel with an empty name";
"alertTunnelAlreadyExistsWithThatNameTitle" = "Name already exists"; "alertTunnelAlreadyExistsWithThatNameTitle" = "Name already exists";
"alertTunnelAlreadyExistsWithThatNameMessage" = "A tunnel with that name already exists"; "alertTunnelAlreadyExistsWithThatNameMessage" = "A tunnel with that name already exists";
"alertTunnelActivationErrorTunnelIsNotInactiveTitle" = "Activation failure"; "alertTunnelActivationErrorTunnelIsNotInactiveTitle" = "Activation in progress";
"alertTunnelActivationErrorTunnelIsNotInactiveMessage" = "The tunnel is already active or in the process of being activated"; "alertTunnelActivationErrorTunnelIsNotInactiveMessage" = "The tunnel is already active or in the process of being activated";
// Tunnel management error alerts on system error // Tunnel management error alerts on system error

View File

@ -298,13 +298,22 @@ class TunnelsManager {
guard let lastErrorData = try? Data(contentsOf: lastErrorFileURL) else { return nil } guard let lastErrorData = try? Data(contentsOf: lastErrorFileURL) else { return nil }
guard let lastErrorText = String(data: lastErrorData, encoding: .utf8) else { return nil } guard let lastErrorText = String(data: lastErrorData, encoding: .utf8) else { return nil }
let lastErrorStrings = lastErrorText.splitToArray(separator: "\n") let lastErrorStrings = lastErrorText.splitToArray(separator: "\n")
guard lastErrorStrings.count == 3 else { return nil } guard lastErrorStrings.count == 2 && tunnel.activationAttemptId == lastErrorStrings[0] else { return nil }
let attemptIdInDisk = lastErrorStrings[0]
if let attemptIdForTunnel = tunnel.activationAttemptId, attemptIdInDisk == attemptIdForTunnel {
return (title: lastErrorStrings[1], message: lastErrorStrings[2])
}
return nil switch PacketTunnelProviderError(rawValue: lastErrorStrings[1]) {
case .some(.savedProtocolConfigurationIsInvalid):
return (tr("alertTunnelActivationFailureTitle"), tr("alertTunnelActivationSavedConfigFailureMessage"))
case .some(.dnsResolutionFailure):
return (tr("alertTunnelDNSFailureTitle"), tr("alertTunnelDNSFailureMessage"))
case .some(.couldNotStartBackend):
return (tr("alertTunnelActivationFailureTitle"), tr("alertTunnelActivationBackendFailureMessage"))
case .some(.couldNotDetermineFileDescriptor):
return (tr("alertTunnelActivationFailureTitle"), tr("alertTunnelActivationFileDescriptorFailureMessage"))
case .some(.couldNotSetNetworkSettings):
return (tr("alertTunnelActivationFailureTitle"), tr("alertTunnelActivationSetNetworkSettingsMessage"))
default:
return (tr("alertTunnelActivationFailureTitle"), tr("alertTunnelActivationFailureMessage"))
}
} }
deinit { deinit {

View File

@ -4,32 +4,16 @@
import NetworkExtension import NetworkExtension
class ErrorNotifier { class ErrorNotifier {
let activationAttemptId: String? let activationAttemptId: String?
weak var tunnelProvider: NEPacketTunnelProvider?
init(activationAttemptId: String?, tunnelProvider: NEPacketTunnelProvider) { init(activationAttemptId: String?) {
self.activationAttemptId = activationAttemptId self.activationAttemptId = activationAttemptId
self.tunnelProvider = tunnelProvider
ErrorNotifier.removeLastErrorFile() ErrorNotifier.removeLastErrorFile()
} }
func errorMessage(for error: PacketTunnelProviderError) -> (String, String)? {
switch error {
case .savedProtocolConfigurationIsInvalid:
return ("Activation failure", "Could not retrieve tunnel information from the saved configuration.")
case .dnsResolutionFailure:
return ("DNS resolution failure", "One or more endpoint domains could not be resolved.")
case .couldNotStartWireGuard:
return ("Activation failure", "WireGuard backend could not be started.")
case .coultNotSetNetworkSettings:
return ("Activation failure", "Error applying network settings on the tunnel.")
}
}
func notify(_ error: PacketTunnelProviderError) { func notify(_ error: PacketTunnelProviderError) {
guard let (title, message) = errorMessage(for: error), let activationAttemptId = activationAttemptId, let lastErrorFilePath = FileManager.networkExtensionLastErrorFileURL?.path else { return } guard let activationAttemptId = activationAttemptId, let lastErrorFilePath = FileManager.networkExtensionLastErrorFileURL?.path else { return }
let errorMessageData = "\(activationAttemptId)\n\(title)\n\(message)".data(using: .utf8) let errorMessageData = "\(activationAttemptId)\n\(error)".data(using: .utf8)
FileManager.default.createFile(atPath: lastErrorFilePath, contents: errorMessageData, attributes: nil) FileManager.default.createFile(atPath: lastErrorFilePath, contents: errorMessageData, attributes: nil)
} }

View File

@ -6,13 +6,6 @@ import Network
import NetworkExtension import NetworkExtension
import os.log import os.log
enum PacketTunnelProviderError: Error {
case savedProtocolConfigurationIsInvalid
case dnsResolutionFailure
case couldNotStartWireGuard
case coultNotSetNetworkSettings
}
class PacketTunnelProvider: NEPacketTunnelProvider { class PacketTunnelProvider: NEPacketTunnelProvider {
private var wgHandle: Int32? private var wgHandle: Int32?
@ -26,7 +19,7 @@ class PacketTunnelProvider: NEPacketTunnelProvider {
override func startTunnel(options: [String: NSObject]?, completionHandler startTunnelCompletionHandler: @escaping (Error?) -> Void) { override func startTunnel(options: [String: NSObject]?, completionHandler startTunnelCompletionHandler: @escaping (Error?) -> Void) {
let activationAttemptId = options?["activationAttemptId"] as? String let activationAttemptId = options?["activationAttemptId"] as? String
let errorNotifier = ErrorNotifier(activationAttemptId: activationAttemptId, tunnelProvider: self) let errorNotifier = ErrorNotifier(activationAttemptId: activationAttemptId)
guard let tunnelProviderProtocol = protocolConfiguration as? NETunnelProviderProtocol, guard let tunnelProviderProtocol = protocolConfiguration as? NETunnelProviderProtocol,
let tunnelConfiguration = tunnelProviderProtocol.asTunnelConfiguration() else { let tunnelConfiguration = tunnelProviderProtocol.asTunnelConfiguration() else {
@ -52,8 +45,8 @@ class PacketTunnelProvider: NEPacketTunnelProvider {
let fileDescriptor = packetFlow.value(forKeyPath: "socket.fileDescriptor") as! Int32 //swiftlint:disable:this force_cast let fileDescriptor = packetFlow.value(forKeyPath: "socket.fileDescriptor") as! Int32 //swiftlint:disable:this force_cast
if fileDescriptor < 0 { if fileDescriptor < 0 {
wg_log(.error, staticMessage: "Starting tunnel failed: Could not determine file descriptor") wg_log(.error, staticMessage: "Starting tunnel failed: Could not determine file descriptor")
errorNotifier.notify(PacketTunnelProviderError.couldNotStartWireGuard) errorNotifier.notify(PacketTunnelProviderError.couldNotDetermineFileDescriptor)
startTunnelCompletionHandler(PacketTunnelProviderError.couldNotStartWireGuard) startTunnelCompletionHandler(PacketTunnelProviderError.couldNotDetermineFileDescriptor)
return return
} }
@ -67,8 +60,8 @@ class PacketTunnelProvider: NEPacketTunnelProvider {
let handle = wireguardSettings.withGoString { return wgTurnOn($0, fileDescriptor) } let handle = wireguardSettings.withGoString { return wgTurnOn($0, fileDescriptor) }
if handle < 0 { if handle < 0 {
wg_log(.error, message: "Starting tunnel failed with wgTurnOn returning \(handle)") wg_log(.error, message: "Starting tunnel failed with wgTurnOn returning \(handle)")
errorNotifier.notify(PacketTunnelProviderError.couldNotStartWireGuard) errorNotifier.notify(PacketTunnelProviderError.couldNotStartBackend)
startTunnelCompletionHandler(PacketTunnelProviderError.couldNotStartWireGuard) startTunnelCompletionHandler(PacketTunnelProviderError.couldNotStartBackend)
return return
} }
wgHandle = handle wgHandle = handle
@ -77,8 +70,8 @@ class PacketTunnelProvider: NEPacketTunnelProvider {
setTunnelNetworkSettings(networkSettings) { error in setTunnelNetworkSettings(networkSettings) { error in
if let error = error { if let error = error {
wg_log(.error, message: "Starting tunnel failed with setTunnelNetworkSettings returning \(error.localizedDescription)") wg_log(.error, message: "Starting tunnel failed with setTunnelNetworkSettings returning \(error.localizedDescription)")
errorNotifier.notify(PacketTunnelProviderError.coultNotSetNetworkSettings) errorNotifier.notify(PacketTunnelProviderError.couldNotSetNetworkSettings)
startTunnelCompletionHandler(PacketTunnelProviderError.coultNotSetNetworkSettings) startTunnelCompletionHandler(PacketTunnelProviderError.couldNotSetNetworkSettings)
} else { } else {
startTunnelCompletionHandler(nil) startTunnelCompletionHandler(nil)
} }