wireguard-apple/WireGuard/WireGuardNetworkExtension/ErrorNotifier.swift

57 lines
2.7 KiB
Swift

// SPDX-License-Identifier: MIT
// Copyright © 2018 WireGuard LLC. All Rights Reserved.
import NetworkExtension
class ErrorNotifier {
let activationAttemptId: String?
weak var tunnelProvider: NEPacketTunnelProvider?
var tunnelName: String?
var isActivateOnDemandEnabled = false
init(activationAttemptId: String?, tunnelProvider: NEPacketTunnelProvider) {
self.activationAttemptId = activationAttemptId
self.tunnelProvider = tunnelProvider
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) {
guard let (title, message) = errorMessage(for: error) else { return }
if let activationAttemptId = activationAttemptId, let lastErrorFilePath = FileManager.networkExtensionLastErrorFileURL?.path {
// The tunnel was started from the app
let onDemandMessage = isActivateOnDemandEnabled ? " This tunnel has Activate On Demand enabled, so this tunnel might be activated automatically. You may turn off Activate On Demand in the WireGuard app by navigating to: '\(tunnelName ?? "tunnel")' > Edit." : ""
let errorMessageData = "\(activationAttemptId)\n\(title)\n\(message)\(onDemandMessage)".data(using: .utf8)
FileManager.default.createFile(atPath: lastErrorFilePath, contents: errorMessageData, attributes: nil)
} else {
// The tunnel was probably started from iOS Settings app or activated on-demand
if let tunnelProvider = self.tunnelProvider {
// displayMessage() is deprecated, but there's no better alternative if invoked from iOS Settings
if !isActivateOnDemandEnabled { // If using activate-on-demand, don't use displayMessage
tunnelProvider.displayMessage("\(title): \(message)") { _ in }
}
}
}
}
static func removeLastErrorFile() {
if let lastErrorFileURL = FileManager.networkExtensionLastErrorFileURL {
_ = FileManager.deleteFile(at: lastErrorFileURL)
}
}
}