summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorAndrej Mihajlov <and@mullvad.net>2022-12-09 16:06:03 +0100
committerAndrej Mihajlov <and@mullvad.net>2022-12-09 16:06:03 +0100
commitfe9fe00c2630efa49d2007dc5c38584aab81dabb (patch)
tree476b397e186c024c84ecab5377ac28f384694a46
parentbdbd4047299f4ee07ca24d652f3893f35741a98b (diff)
parent16c758b397b3a139f5a8662619822fa274fb99e5 (diff)
downloadmullvadvpn-fe9fe00c2630efa49d2007dc5c38584aab81dabb.tar.xz
mullvadvpn-fe9fe00c2630efa49d2007dc5c38584aab81dabb.zip
Merge branch 'handle-application-updates-with-settings-migration'
-rw-r--r--ios/MullvadTypes/PacketTunnelErrorWrapper.swift39
-rw-r--r--ios/MullvadTypes/PacketTunnelStatus.swift6
-rw-r--r--ios/MullvadVPN.xcodeproj/project.pbxproj4
-rw-r--r--ios/MullvadVPN/Notifications/TunnelStatusNotificationProvider.swift9
-rw-r--r--ios/MullvadVPN/TransportMonitor/PacketTunnelTransport.swift1
-rw-r--r--ios/MullvadVPN/TunnelManager/TunnelManager.swift11
-rw-r--r--ios/PacketTunnel/PacketTunnelProvider.swift54
7 files changed, 113 insertions, 11 deletions
diff --git a/ios/MullvadTypes/PacketTunnelErrorWrapper.swift b/ios/MullvadTypes/PacketTunnelErrorWrapper.swift
new file mode 100644
index 0000000000..e70bdb0c9f
--- /dev/null
+++ b/ios/MullvadTypes/PacketTunnelErrorWrapper.swift
@@ -0,0 +1,39 @@
+//
+// PacketTunnelErrorWrapper.swift
+// MullvadTypes
+//
+// Created by Sajad Vishkai on 2022-11-28.
+// Copyright © 2022 Mullvad VPN AB. All rights reserved.
+//
+
+import Foundation
+
+public enum PacketTunnelErrorWrapper: Codable, Equatable, LocalizedError {
+ /// Failure that indicates wire guard errors.
+ case wireguard(error: String)
+
+ /// Failure to read stored settings.
+ case readConfiguration
+
+ public var errorDescription: String? {
+ switch self {
+ case let .wireguard(error):
+ return error
+ case .readConfiguration:
+ return "Failure to read settings."
+ }
+ }
+
+ public static func == (lhs: PacketTunnelErrorWrapper, rhs: PacketTunnelErrorWrapper) -> Bool {
+ switch (lhs, rhs) {
+ case (.readConfiguration, .readConfiguration):
+ return true
+
+ case let (.wireguard(error: lhsError), .wireguard(error: rhsError)):
+ return lhsError == rhsError
+
+ default:
+ return false
+ }
+ }
+}
diff --git a/ios/MullvadTypes/PacketTunnelStatus.swift b/ios/MullvadTypes/PacketTunnelStatus.swift
index 2b5a1abf91..6f38c25c78 100644
--- a/ios/MullvadTypes/PacketTunnelStatus.swift
+++ b/ios/MullvadTypes/PacketTunnelStatus.swift
@@ -35,7 +35,7 @@ public struct DeviceCheck: Codable, Equatable {
/// Struct describing packet tunnel process status.
public struct PacketTunnelStatus: Codable, Equatable {
/// Last tunnel error.
- public var lastError: String?
+ public var lastErrors: [PacketTunnelErrorWrapper]
/// Flag indicating whether network is reachable.
public var isNetworkReachable: Bool
@@ -47,12 +47,12 @@ public struct PacketTunnelStatus: Codable, Equatable {
public var tunnelRelay: PacketTunnelRelay?
public init(
- lastError: String? = nil,
+ lastErrors: [PacketTunnelErrorWrapper] = [],
isNetworkReachable: Bool = true,
deviceCheck: DeviceCheck? = nil,
tunnelRelay: PacketTunnelRelay? = nil
) {
- self.lastError = lastError
+ self.lastErrors = lastErrors
self.isNetworkReachable = isNetworkReachable
self.deviceCheck = deviceCheck
self.tunnelRelay = tunnelRelay
diff --git a/ios/MullvadVPN.xcodeproj/project.pbxproj b/ios/MullvadVPN.xcodeproj/project.pbxproj
index 03f0efe43a..9c8eb65127 100644
--- a/ios/MullvadVPN.xcodeproj/project.pbxproj
+++ b/ios/MullvadVPN.xcodeproj/project.pbxproj
@@ -31,6 +31,7 @@
06410E07292D108E00AFC18C /* SettingsStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 06410E06292D108E00AFC18C /* SettingsStore.swift */; };
06410E08292D117800AFC18C /* SettingsStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 06410E06292D108E00AFC18C /* SettingsStore.swift */; };
06410E09292D990C00AFC18C /* Result+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58F1311427E0B2AB007AC5BC /* Result+Extensions.swift */; };
+ 06410E182934F43B00AFC18C /* PacketTunnelErrorWrapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 06410E172934F43B00AFC18C /* PacketTunnelErrorWrapper.swift */; };
06799ACE28F98E1D00ACD94E /* MullvadREST.h in Headers */ = {isa = PBXBuildFile; fileRef = 06799ABE28F98E1D00ACD94E /* MullvadREST.h */; settings = {ATTRIBUTES = (Public, ); }; };
06799AD128F98E1D00ACD94E /* MullvadREST.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 06799ABC28F98E1D00ACD94E /* MullvadREST.framework */; };
06799AD228F98E1D00ACD94E /* MullvadREST.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 06799ABC28F98E1D00ACD94E /* MullvadREST.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
@@ -539,6 +540,7 @@
06410DFD292CE18F00AFC18C /* KeychainSettingsStore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeychainSettingsStore.swift; sourceTree = "<group>"; };
06410E03292D0F7100AFC18C /* SettingsParser.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsParser.swift; sourceTree = "<group>"; };
06410E06292D108E00AFC18C /* SettingsStore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsStore.swift; sourceTree = "<group>"; };
+ 06410E172934F43B00AFC18C /* PacketTunnelErrorWrapper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PacketTunnelErrorWrapper.swift; sourceTree = "<group>"; };
06799AB428F98CE700ACD94E /* le_root_cert.cer */ = {isa = PBXFileReference; lastKnownFileType = file; path = le_root_cert.cer; sourceTree = "<group>"; };
06799ABC28F98E1D00ACD94E /* MullvadREST.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = MullvadREST.framework; sourceTree = BUILT_PRODUCTS_DIR; };
06799ABE28F98E1D00ACD94E /* MullvadREST.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MullvadREST.h; sourceTree = "<group>"; };
@@ -1080,6 +1082,7 @@
585DA89826B0329200B8C587 /* PacketTunnelStatus.swift */,
5898D2B62902A9EA00EB5EBA /* PacketTunnelRelay.swift */,
58900D0228BBDCC70094E4F0 /* FixedWidthInteger+Arithmetics.swift */,
+ 06410E172934F43B00AFC18C /* PacketTunnelErrorWrapper.swift */,
);
path = MullvadTypes;
sourceTree = "<group>";
@@ -2092,6 +2095,7 @@
586A9516290133ED007BAF2B /* AnyIPAddress.swift in Sources */,
5856AD592902BE1A008E5127 /* PacketTunnelStatus.swift in Sources */,
5898D2A32901807500EB5EBA /* MullvadEndpoint.swift in Sources */,
+ 06410E182934F43B00AFC18C /* PacketTunnelErrorWrapper.swift in Sources */,
5898D2B32902A8F000EB5EBA /* RelayLocation.swift in Sources */,
063F026A29002E44001FA09F /* IPv4Endpoint.swift in Sources */,
5856AD582902BE1A008E5127 /* PacketTunnelRelay.swift in Sources */,
diff --git a/ios/MullvadVPN/Notifications/TunnelStatusNotificationProvider.swift b/ios/MullvadVPN/Notifications/TunnelStatusNotificationProvider.swift
index 426d97dbad..81c2709267 100644
--- a/ios/MullvadVPN/Notifications/TunnelStatusNotificationProvider.swift
+++ b/ios/MullvadVPN/Notifications/TunnelStatusNotificationProvider.swift
@@ -42,8 +42,13 @@ class TunnelStatusNotificationProvider: NotificationProvider, InAppNotificationP
private func handleTunnelStatus(_ tunnelStatus: TunnelStatus) {
let invalidateForTunnelError = updateLastTunnelError(
- tunnelStatus.packetTunnelStatus
- .lastError
+ tunnelStatus.packetTunnelStatus.lastErrors.first(where: {
+ if case .wireguard = $0 {
+ return true
+ }
+
+ return false
+ })?.localizedDescription
)
let invalidateForManagerError = updateTunnelManagerError(tunnelStatus.state)
let invalidateForConnectivity = updateConnectivity(tunnelStatus.state)
diff --git a/ios/MullvadVPN/TransportMonitor/PacketTunnelTransport.swift b/ios/MullvadVPN/TransportMonitor/PacketTunnelTransport.swift
index 65f8f9196f..aa85eda6b2 100644
--- a/ios/MullvadVPN/TransportMonitor/PacketTunnelTransport.swift
+++ b/ios/MullvadVPN/TransportMonitor/PacketTunnelTransport.swift
@@ -17,6 +17,7 @@ struct PacketTunnelTransport: RESTTransport {
}
let tunnel: Tunnel
+
init(tunnel: Tunnel) {
self.tunnel = tunnel
}
diff --git a/ios/MullvadVPN/TunnelManager/TunnelManager.swift b/ios/MullvadVPN/TunnelManager/TunnelManager.swift
index 0489d70229..5dd4711ed1 100644
--- a/ios/MullvadVPN/TunnelManager/TunnelManager.swift
+++ b/ios/MullvadVPN/TunnelManager/TunnelManager.swift
@@ -84,6 +84,9 @@ final class TunnelManager: StorePaymentObserver {
/// Last processed device check identifier.
private var lastDeviceCheckIdentifier: UUID?
+ /// Flag indicating tunnel reconnected after settings migration.
+ private var reconnectedTunnelAfterMigration = false
+
// MARK: - Initialization
init(
@@ -698,6 +701,14 @@ final class TunnelManager: StorePaymentObserver {
// while the tunnel process is trying to connect.
startPollingTunnelStatus(interval: establishingTunnelStatusPollInterval)
+ if newTunnelStatus.packetTunnelStatus.lastErrors.contains(.readConfiguration),
+ !reconnectedTunnelAfterMigration
+ {
+ reconnectTunnel(selectNewRelay: true)
+
+ reconnectedTunnelAfterMigration = true
+ }
+
case .connected, .waitingForConnectivity:
// Start polling tunnel status to keep connectivity status up to date.
startPollingTunnelStatus(interval: establishedTunnelStatusPollInterval)
diff --git a/ios/PacketTunnel/PacketTunnelProvider.swift b/ios/PacketTunnel/PacketTunnelProvider.swift
index b83271ad82..13f7646b9f 100644
--- a/ios/PacketTunnel/PacketTunnelProvider.swift
+++ b/ios/PacketTunnel/PacketTunnelProvider.swift
@@ -44,8 +44,11 @@ class PacketTunnelProvider: NEPacketTunnelProvider, TunnelMonitorDelegate {
/// Number of consecutive connection failure attempts.
private var numberOfFailedAttempts: UInt = 0
- /// Last runtime error.
- private var lastError: Error?
+ /// Last wireguard error.
+ private var wgError: PacketTunnelErrorWrapper?
+
+ /// Last tunnel provider error.
+ private var tunnelProviderError: PacketTunnelErrorWrapper?
/// Relay cache.
private let relayCache = RelayCache(
@@ -87,7 +90,7 @@ class PacketTunnelProvider: NEPacketTunnelProvider, TunnelMonitorDelegate {
/// Returns `PacketTunnelStatus` used for sharing with main bundle process.
private var packetTunnelStatus: PacketTunnelStatus {
return PacketTunnelStatus(
- lastError: lastError?.localizedDescription,
+ lastErrors: [wgError, tunnelProviderError].compactMap { $0 },
isNetworkReachable: isNetworkReachable,
deviceCheck: deviceCheck,
tunnelRelay: selectorResult?.packetTunnelRelay
@@ -186,7 +189,9 @@ class PacketTunnelProvider: NEPacketTunnelProvider, TunnelMonitorDelegate {
message: "Failed to read tunnel configuration when starting the tunnel."
)
- completionHandler(error)
+ tunnelProviderError = .readConfiguration
+
+ startEmptyTunnel(completionHandler: completionHandler)
return
}
@@ -223,6 +228,34 @@ class PacketTunnelProvider: NEPacketTunnelProvider, TunnelMonitorDelegate {
}
}
+ private func startEmptyTunnel(completionHandler: @escaping (Error?) -> Void) {
+ let emptyTunnelConfiguration = TunnelConfiguration(
+ name: nil,
+ interface: InterfaceConfiguration(privateKey: PrivateKey()),
+ peers: []
+ )
+
+ adapter.start(tunnelConfiguration: emptyTunnelConfiguration) { error in
+ self.dispatchQueue.async {
+ if let error = error {
+ self.providerLogger.error(
+ error: error,
+ message: "Failed to start an empty tunnel."
+ )
+
+ completionHandler(error)
+ } else {
+ self.providerLogger.debug("Started an empty tunnel.")
+
+ self.startTunnelCompletionHandler = { [weak self] in
+ self?.isConnected = true
+ completionHandler(nil)
+ }
+ }
+ }
+ }
+ }
+
override func stopTunnel(
with reason: NEProviderStopReason,
completionHandler: @escaping () -> Void
@@ -411,8 +444,11 @@ class PacketTunnelProvider: NEPacketTunnelProvider, TunnelMonitorDelegate {
private func makeConfiguration(_ nextRelay: NextRelay)
throws -> PacketTunnelConfiguration
{
- let deviceState = try SettingsManager.readDeviceState()
let tunnelSettings = try SettingsManager.readSettings()
+ let deviceState = try SettingsManager.readDeviceState()
+
+ tunnelProviderError = nil
+
let selectorResult: RelaySelectorResult
switch nextRelay {
@@ -459,7 +495,13 @@ class PacketTunnelProvider: NEPacketTunnelProvider, TunnelMonitorDelegate {
adapter.update(tunnelConfiguration: tunnelConfiguration.wgTunnelConfig) { error in
self.dispatchQueue.async {
- self.lastError = error
+ if let error = error {
+ let wrappedError: PacketTunnelErrorWrapper = .wireguard(
+ error: error.localizedDescription
+ )
+
+ self.wgError = wrappedError
+ }
if let error = error {
self.providerLogger.error(