summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--ios/MullvadVPN.xcodeproj/project.pbxproj26
-rw-r--r--ios/MullvadVPN/AnyEncodable.swift28
-rw-r--r--ios/MullvadVPN/DisplayChainedError.swift45
-rw-r--r--ios/MullvadVPN/JsonRpc.swift87
-rw-r--r--ios/MullvadVPN/MullvadRpc.swift347
-rw-r--r--ios/MullvadVPN/RelayList.swift91
6 files changed, 44 insertions, 580 deletions
diff --git a/ios/MullvadVPN.xcodeproj/project.pbxproj b/ios/MullvadVPN.xcodeproj/project.pbxproj
index 9d2adfa428..e259a3aef0 100644
--- a/ios/MullvadVPN.xcodeproj/project.pbxproj
+++ b/ios/MullvadVPN.xcodeproj/project.pbxproj
@@ -39,6 +39,8 @@
580EE22824B3289300F9D8A1 /* AssociatedValue.swift in Sources */ = {isa = PBXBuildFile; fileRef = 580EE22724B3289300F9D8A1 /* AssociatedValue.swift */; };
580EE22924B3289300F9D8A1 /* AssociatedValue.swift in Sources */ = {isa = PBXBuildFile; fileRef = 580EE22724B3289300F9D8A1 /* AssociatedValue.swift */; };
5811DE50239014550011EB53 /* NEVPNStatus+Debug.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5811DE4F239014550011EB53 /* NEVPNStatus+Debug.swift */; };
+ 581C9BF524C7096E0059F0C6 /* AnyEncodable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 581C9BF424C7096E0059F0C6 /* AnyEncodable.swift */; };
+ 581C9BF624C7096E0059F0C6 /* AnyEncodable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 581C9BF424C7096E0059F0C6 /* AnyEncodable.swift */; };
581CBCE62296B97300727D7F /* ViewControllerIdentifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 581CBCE52296B97300727D7F /* ViewControllerIdentifier.swift */; };
581CBCEC2298041B00727D7F /* SettingsAppVersionCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 581CBCEB2298041B00727D7F /* SettingsAppVersionCell.swift */; };
581CBCEE229826FD00727D7F /* StaticTableViewDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = 581CBCED229826FD00727D7F /* StaticTableViewDataSource.swift */; };
@@ -88,7 +90,6 @@
5888AD7F2279B6BF0051EB06 /* RelayStatusIndicatorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5888AD7E2279B6BF0051EB06 /* RelayStatusIndicatorView.swift */; };
5888AD83227B11080051EB06 /* SelectLocationCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5888AD82227B11080051EB06 /* SelectLocationCell.swift */; };
5888AD87227B17950051EB06 /* SelectLocationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5888AD86227B17950051EB06 /* SelectLocationController.swift */; };
- 5888AD89227B18C40051EB06 /* RelayList.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5888AD88227B18C40051EB06 /* RelayList.swift */; };
588D2FE3248AC27F00E313F7 /* AsyncOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58E973DD24850EB600096F90 /* AsyncOperation.swift */; };
58906DE02445C7A5002F0673 /* NEProviderStopReason+Debug.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58906DDF2445C7A5002F0673 /* NEProviderStopReason+Debug.swift */; };
5896AE7E246ACE65005B36CB /* KeychainAttributes.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58FAEDEB245059F000CB0F5B /* KeychainAttributes.swift */; };
@@ -103,8 +104,6 @@
58A1AA8C23F5584C009F7EA6 /* ConnectionPanelView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58A1AA8B23F5584B009F7EA6 /* ConnectionPanelView.swift */; };
58A8BE81239FBE62006B74AC /* IPEndpoint.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58561C98239A5D1500BD6B5E /* IPEndpoint.swift */; };
58A99ED3240014A0006599E9 /* ConsentViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58A99ED2240014A0006599E9 /* ConsentViewController.swift */; };
- 58ADDB3C227B1BD200FAFEA7 /* JsonRpc.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58ADDB3B227B1BD200FAFEA7 /* JsonRpc.swift */; };
- 58ADDB3E227B1CD900FAFEA7 /* MullvadRpc.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58ADDB3D227B1CD900FAFEA7 /* MullvadRpc.swift */; };
58AEEF652344A36000C9BBD5 /* KeychainError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58AEEF642344A36000C9BBD5 /* KeychainError.swift */; };
58AEEF662344A37400C9BBD5 /* KeychainError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58AEEF642344A36000C9BBD5 /* KeychainError.swift */; };
58AEEF6B2344A46200C9BBD5 /* TunnelSettingsManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58AEEF6A2344A46200C9BBD5 /* TunnelSettingsManager.swift */; };
@@ -112,7 +111,6 @@
58B0A2A8238EE68200BC001D /* RelaySelectorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 584B26F3237434D00073B10E /* RelaySelectorTests.swift */; };
58B0A2A9238EE6A100BC001D /* RelayConstraints.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58781CC822AE7CA8009B9D8E /* RelayConstraints.swift */; };
58B0A2AA238EE6A900BC001D /* RelaySelector.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58781CD422AFBA39009B9D8E /* RelaySelector.swift */; };
- 58B0A2AB238EE6BF00BC001D /* RelayList.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5888AD88227B18C40051EB06 /* RelayList.swift */; };
58B0A2AC238EE6D500BC001D /* IpAddress+Codable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5840250022B1124600E4CFEC /* IpAddress+Codable.swift */; };
58B0A2AD238EE6EC00BC001D /* MullvadEndpoint.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5840250322B11AB700E4CFEC /* MullvadEndpoint.swift */; };
58B8743222B25A7600015324 /* WireguardAssociatedAddresses.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58B8743122B25A7600015324 /* WireguardAssociatedAddresses.swift */; };
@@ -123,9 +121,6 @@
58BA692F23E99F5B009DC256 /* Locking.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58BA692D23E99EFF009DC256 /* Locking.swift */; };
58BA693123EADA6A009DC256 /* SimulatorTunnelProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58BA693023EADA6A009DC256 /* SimulatorTunnelProvider.swift */; };
58BA693223EAE1AE009DC256 /* SimulatorTunnelProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58BA693023EADA6A009DC256 /* SimulatorTunnelProvider.swift */; };
- 58BFA5C022A7C8A900A6173D /* MullvadRpc.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58ADDB3D227B1CD900FAFEA7 /* MullvadRpc.swift */; };
- 58BFA5C222A7C92900A6173D /* JsonRpc.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58ADDB3B227B1BD200FAFEA7 /* JsonRpc.swift */; };
- 58BFA5C322A7C93400A6173D /* RelayList.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5888AD88227B18C40051EB06 /* RelayList.swift */; };
58BFA5C622A7C97F00A6173D /* RelayCache.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58BFA5C522A7C97F00A6173D /* RelayCache.swift */; };
58BFA5C722A7C97F00A6173D /* RelayCache.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58BFA5C522A7C97F00A6173D /* RelayCache.swift */; };
58BFA5CC22A7CE1F00A6173D /* ApplicationConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58BFA5CB22A7CE1F00A6173D /* ApplicationConfiguration.swift */; };
@@ -249,6 +244,7 @@
580EE22324B3243100F9D8A1 /* AsyncBlockOperation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AsyncBlockOperation.swift; sourceTree = "<group>"; };
580EE22724B3289300F9D8A1 /* AssociatedValue.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AssociatedValue.swift; sourceTree = "<group>"; };
5811DE4F239014550011EB53 /* NEVPNStatus+Debug.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NEVPNStatus+Debug.swift"; sourceTree = "<group>"; };
+ 581C9BF424C7096E0059F0C6 /* AnyEncodable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnyEncodable.swift; sourceTree = "<group>"; };
581CBCE52296B97300727D7F /* ViewControllerIdentifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewControllerIdentifier.swift; sourceTree = "<group>"; };
581CBCEB2298041B00727D7F /* SettingsAppVersionCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SettingsAppVersionCell.swift; sourceTree = "<group>"; };
581CBCED229826FD00727D7F /* StaticTableViewDataSource.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StaticTableViewDataSource.swift; sourceTree = "<group>"; };
@@ -288,7 +284,6 @@
5888AD7E2279B6BF0051EB06 /* RelayStatusIndicatorView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RelayStatusIndicatorView.swift; sourceTree = "<group>"; };
5888AD82227B11080051EB06 /* SelectLocationCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SelectLocationCell.swift; sourceTree = "<group>"; };
5888AD86227B17950051EB06 /* SelectLocationController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SelectLocationController.swift; sourceTree = "<group>"; };
- 5888AD88227B18C40051EB06 /* RelayList.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RelayList.swift; sourceTree = "<group>"; };
58906DDF2445C7A5002F0673 /* NEProviderStopReason+Debug.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NEProviderStopReason+Debug.swift"; sourceTree = "<group>"; };
5894E725236B2801008A2793 /* SwiftUI.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SwiftUI.framework; path = System/Library/Frameworks/SwiftUI.framework; sourceTree = SDKROOT; };
5896AE83246D5889005B36CB /* CustomDateComponentsFormatting.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomDateComponentsFormatting.swift; sourceTree = "<group>"; };
@@ -297,8 +292,6 @@
58A1AA8623F43901009F7EA6 /* Location.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Location.swift; sourceTree = "<group>"; };
58A1AA8B23F5584B009F7EA6 /* ConnectionPanelView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ConnectionPanelView.swift; sourceTree = "<group>"; };
58A99ED2240014A0006599E9 /* ConsentViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConsentViewController.swift; sourceTree = "<group>"; };
- 58ADDB3B227B1BD200FAFEA7 /* JsonRpc.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JsonRpc.swift; sourceTree = "<group>"; };
- 58ADDB3D227B1CD900FAFEA7 /* MullvadRpc.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MullvadRpc.swift; sourceTree = "<group>"; };
58AEEF642344A36000C9BBD5 /* KeychainError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeychainError.swift; sourceTree = "<group>"; };
58AEEF6A2344A46200C9BBD5 /* TunnelSettingsManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TunnelSettingsManager.swift; sourceTree = "<group>"; };
58B0A2A0238EE67E00BC001D /* MullvadVPNTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = MullvadVPNTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
@@ -508,7 +501,6 @@
5840250022B1124600E4CFEC /* IpAddress+Codable.swift */,
58C6B34E22BB7AC0003C19AD /* IPAddressRange.swift */,
58561C98239A5D1500BD6B5E /* IPEndpoint.swift */,
- 58ADDB3B227B1BD200FAFEA7 /* JsonRpc.swift */,
58FAEDF6245088E100CB0F5B /* Keychain.swift */,
58FAEDEB245059F000CB0F5B /* KeychainAttributes.swift */,
58FAEE0024533A9C00CB0F5B /* KeychainClass.swift */,
@@ -523,7 +515,6 @@
58CE5E67224146200008646E /* Main.storyboard */,
5840250322B11AB700E4CFEC /* MullvadEndpoint.swift */,
58CB0EDF24B86751001EF0D8 /* MullvadRest.swift */,
- 58ADDB3D227B1CD900FAFEA7 /* MullvadRpc.swift */,
58FBDAAA22A52DC500EB69A3 /* MullvadVPN-Bridging-Header.h */,
5866F39B2243B82D00168AE5 /* MullvadVPN.entitlements */,
58906DDF2445C7A5002F0673 /* NEProviderStopReason+Debug.swift */,
@@ -533,7 +524,6 @@
5845F841236CBACD00B2D93C /* PacketTunnelIpc.swift */,
58BFA5C522A7C97F00A6173D /* RelayCache.swift */,
58781CC822AE7CA8009B9D8E /* RelayConstraints.swift */,
- 5888AD88227B18C40051EB06 /* RelayList.swift */,
58781CD422AFBA39009B9D8E /* RelaySelector.swift */,
5888AD7E2279B6BF0051EB06 /* RelayStatusIndicatorView.swift */,
587425C02299833500CA2045 /* RootContainerViewController.swift */,
@@ -566,6 +556,7 @@
58C6B35322BB87C4003C19AD /* WireguardPrivateKey.swift */,
58F3C098249B978C003E76BE /* x25519.c */,
58F3C097249B978C003E76BE /* x25519.h */,
+ 581C9BF424C7096E0059F0C6 /* AnyEncodable.swift */,
);
path = MullvadVPN;
sourceTree = "<group>";
@@ -871,7 +862,6 @@
58B0A2A8238EE68200BC001D /* RelaySelectorTests.swift in Sources */,
584E96BE240FD4DB00D3334F /* Location.swift in Sources */,
58B0A2AC238EE6D500BC001D /* IpAddress+Codable.swift in Sources */,
- 58B0A2AB238EE6BF00BC001D /* RelayList.swift in Sources */,
58B0A2AD238EE6EC00BC001D /* MullvadEndpoint.swift in Sources */,
58FAEDF4245088B300CB0F5B /* KeychainError.swift in Sources */,
5896AE88246D7FAF005B36CB /* CustomDateComponentsFormatting.swift in Sources */,
@@ -931,7 +921,6 @@
5845F842236CBACD00B2D93C /* PacketTunnelIpc.swift in Sources */,
58781CC922AE7CA8009B9D8E /* RelayConstraints.swift in Sources */,
584E96BC240FD4DA00D3334F /* Location.swift in Sources */,
- 58ADDB3E227B1CD900FAFEA7 /* MullvadRpc.swift in Sources */,
580EE20F24B322E700F9D8A1 /* TransformOperation.swift in Sources */,
58B8743222B25A7600015324 /* WireguardAssociatedAddresses.swift in Sources */,
58C6B34F22BB7AC0003C19AD /* IPAddressRange.swift in Sources */,
@@ -952,7 +941,6 @@
5877152E23981C5B001F8237 /* SettingsBasicCell.swift in Sources */,
58FD5BE724192A2C00112C88 /* AppStoreReceipt.swift in Sources */,
5835B7CC233B76CB0096D79F /* TunnelManager.swift in Sources */,
- 58ADDB3C227B1BD200FAFEA7 /* JsonRpc.swift in Sources */,
581CBCEE229826FD00727D7F /* StaticTableViewDataSource.swift in Sources */,
58CE5E64224146200008646E /* AppDelegate.swift in Sources */,
58C6B35E22BBBFE3003C19AD /* Data+HexCoding.swift in Sources */,
@@ -971,7 +959,6 @@
587425C12299833500CA2045 /* RootContainerViewController.swift in Sources */,
580EE20124B321D500F9D8A1 /* OperationProtocol.swift in Sources */,
5896AE84246D5889005B36CB /* CustomDateComponentsFormatting.swift in Sources */,
- 5888AD89227B18C40051EB06 /* RelayList.swift in Sources */,
580EE21824B3235100F9D8A1 /* AnyOperationObserver.swift in Sources */,
587AD7C623421D7000E93A53 /* TunnelSettings.swift in Sources */,
58FD5BF024238EB300112C88 /* SKProduct+Formatting.swift in Sources */,
@@ -981,6 +968,7 @@
58C3A4B222456F1B00340BDB /* AccountInputGroupView.swift in Sources */,
58F840B22464491D0044E708 /* ChainedError.swift in Sources */,
58FAEDFF24533A7000CB0F5B /* KeychainReturn.swift in Sources */,
+ 581C9BF524C7096E0059F0C6 /* AnyEncodable.swift in Sources */,
580EE20C24B3225F00F9D8A1 /* DelayOperation.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
@@ -995,16 +983,15 @@
580EE21F24B3237F00F9D8A1 /* OutputOperation.swift in Sources */,
580EE20224B321DB00F9D8A1 /* OperationProtocol.swift in Sources */,
58FAEE0224533ABB00CB0F5B /* KeychainMatchLimit.swift in Sources */,
+ 581C9BF624C7096E0059F0C6 /* AnyEncodable.swift in Sources */,
58FAEE0324533ABE00CB0F5B /* KeychainReturn.swift in Sources */,
58BFA5CD22A7CE1F00A6173D /* ApplicationConfiguration.swift in Sources */,
- 58BFA5C222A7C92900A6173D /* JsonRpc.swift in Sources */,
580EE20724B3222400F9D8A1 /* ExclusivityController.swift in Sources */,
58F840B02464382C0044E708 /* KeychainItemRevision.swift in Sources */,
58C6B35122BB7CFD003C19AD /* IPAddressRange.swift in Sources */,
587AD7C723421D8600E93A53 /* TunnelSettings.swift in Sources */,
58F3C0962492617E003E76BE /* AsyncOperation.swift in Sources */,
580EE22924B3289300F9D8A1 /* AssociatedValue.swift in Sources */,
- 58BFA5C322A7C93400A6173D /* RelayList.swift in Sources */,
58AEEF662344A37400C9BBD5 /* KeychainError.swift in Sources */,
5840250222B1124600E4CFEC /* IpAddress+Codable.swift in Sources */,
58BA693223EAE1AE009DC256 /* SimulatorTunnelProvider.swift in Sources */,
@@ -1027,7 +1014,6 @@
58C6B35F22BBBFE3003C19AD /* Data+HexCoding.swift in Sources */,
5840250522B11AB700E4CFEC /* MullvadEndpoint.swift in Sources */,
58BFA5C722A7C97F00A6173D /* RelayCache.swift in Sources */,
- 58BFA5C022A7C8A900A6173D /* MullvadRpc.swift in Sources */,
580EE21024B322E700F9D8A1 /* TransformOperation.swift in Sources */,
58906DE02445C7A5002F0673 /* NEProviderStopReason+Debug.swift in Sources */,
584E96BD240FD4DA00D3334F /* Location.swift in Sources */,
diff --git a/ios/MullvadVPN/AnyEncodable.swift b/ios/MullvadVPN/AnyEncodable.swift
new file mode 100644
index 0000000000..b4b27a1507
--- /dev/null
+++ b/ios/MullvadVPN/AnyEncodable.swift
@@ -0,0 +1,28 @@
+//
+// AnyEncodable.swift
+// MullvadVPN
+//
+// Created by pronebird on 21/07/2020.
+// Copyright © 2020 Mullvad VPN AB. All rights reserved.
+//
+
+import Foundation
+
+extension Encodable {
+ fileprivate func encode(to container: inout SingleValueEncodingContainer) throws {
+ try container.encode(self)
+ }
+}
+
+struct AnyEncodable: Encodable {
+ let value: Encodable
+
+ init(_ value: Encodable) {
+ self.value = value
+ }
+
+ func encode(to encoder: Encoder) throws {
+ var container = encoder.singleValueContainer()
+ try value.encode(to: &container)
+ }
+}
diff --git a/ios/MullvadVPN/DisplayChainedError.swift b/ios/MullvadVPN/DisplayChainedError.swift
index cae6437af2..4fa2883e6b 100644
--- a/ios/MullvadVPN/DisplayChainedError.swift
+++ b/ios/MullvadVPN/DisplayChainedError.swift
@@ -36,31 +36,6 @@ extension RestError: DisplayChainedError {
}
}
-extension MullvadRpc.Error: DisplayChainedError {
- var errorChainDescription: String? {
- switch self {
- case .network(let urlError):
- return urlError.localizedDescription
-
- case .server(let serverError):
- if let knownErrorDescription = serverError.errorDescription {
- return knownErrorDescription
- } else {
- return String(
- format: NSLocalizedString("Server error: %@", comment: ""),
- serverError.message
- )
- }
-
- case .encoding:
- return NSLocalizedString("Server request encoding error", comment: "")
-
- case .decoding:
- return NSLocalizedString("Server response decoding error", comment: "")
- }
- }
-}
-
extension TunnelManager.Error: DisplayChainedError {
var errorChainDescription: String? {
switch self {
@@ -97,22 +72,22 @@ extension TunnelManager.Error: DisplayChainedError {
case .removeTunnelSettings(_):
return NSLocalizedString("Failed to remove tunnel settings", comment: "")
- case .pushWireguardKey(let rpcError):
- let reason = rpcError.errorChainDescription ?? ""
+ case .pushWireguardKey(let restError):
+ let reason = restError.errorChainDescription ?? ""
var message = String(format: NSLocalizedString("Failed to send the WireGuard key to server: %@", comment: ""), reason)
- if case .server(let serverError) = rpcError, serverError.code == .tooManyWireguardKeys {
+ if case .server(.keyLimitReached) = restError {
message.append("\n\n")
message.append(NSLocalizedString("Remove unused WireGuard keys and try again", comment: ""))
}
return message
- case .replaceWireguardKey(let rpcError):
- let reason = rpcError.errorChainDescription ?? ""
+ case .replaceWireguardKey(let restError):
+ let reason = restError.errorChainDescription ?? ""
var message = String(format: NSLocalizedString("Failed to replace the WireGuard key on server: %@", comment: ""), reason)
- if case .server(let serverError) = rpcError, serverError.code == .tooManyWireguardKeys {
+ if case .server(.keyLimitReached) = restError {
message.append("\n\n")
message.append(NSLocalizedString("Remove unused WireGuard keys and try again", comment: ""))
}
@@ -123,8 +98,8 @@ extension TunnelManager.Error: DisplayChainedError {
// This error is never displayed anywhere
return nil
- case .verifyWireguardKey(let rpcError):
- let reason = rpcError.errorChainDescription ?? ""
+ case .verifyWireguardKey(let restError):
+ let reason = restError.errorChainDescription ?? ""
return String(format: NSLocalizedString("Failed to verify the WireGuard key on server: %@", comment: ""), reason)
@@ -157,8 +132,8 @@ extension AppStorePaymentManager.Error: DisplayChainedError {
case .readReceipt(let readReceiptError):
return String(format: NSLocalizedString("Cannot read the receipt: %@", comment: ""), readReceiptError.errorChainDescription ?? "")
- case .sendReceipt(let rpcError):
- let reason = rpcError.errorChainDescription ?? ""
+ case .sendReceipt(let restError):
+ let reason = restError.errorChainDescription ?? ""
return String(format: NSLocalizedString(#"Failed to send the receipt to server: %@\n\nPlease retry by using the "Restore purchases" button."#, comment: ""), reason)
diff --git a/ios/MullvadVPN/JsonRpc.swift b/ios/MullvadVPN/JsonRpc.swift
deleted file mode 100644
index a41678fa1e..0000000000
--- a/ios/MullvadVPN/JsonRpc.swift
+++ /dev/null
@@ -1,87 +0,0 @@
-//
-// JsonRpc.swift
-// MullvadVPN
-//
-// Created by pronebird on 02/05/2019.
-// Copyright © 2019 Mullvad VPN AB. All rights reserved.
-//
-
-import Foundation
-
-extension Encodable {
- fileprivate func encode(to container: inout SingleValueEncodingContainer) throws {
- try container.encode(self)
- }
-}
-
-struct AnyEncodable: Encodable {
- let value: Encodable
-
- init(_ value: Encodable) {
- self.value = value
- }
-
- func encode(to encoder: Encoder) throws {
- var container = encoder.singleValueContainer()
- try value.encode(to: &container)
- }
-}
-
-struct JsonRpcRequest: Encodable {
- let version = "2.0"
- let id = UUID().uuidString
- let method: String
- let params: [AnyEncodable]
-
- fileprivate enum CodingKeys: String, CodingKey {
- case version = "jsonrpc", id, method, params
- }
-}
-
-class JsonRpcResponseError<ResponseCode>: Error, Decodable
- where ResponseCode: Decodable
-{
- let code: ResponseCode
- let message: String
-
- var localizedDescription: String {
- return message
- }
-
- private enum CodingKeys: String, CodingKey {
- case code, message
- }
-
- required init(from decoder: Decoder) throws {
- let container = try decoder.container(keyedBy: CodingKeys.self)
-
- code = try container.decode(ResponseCode.self, forKey: .code)
- message = try container.decode(String.self, forKey: .message)
- }
-}
-
-struct JsonRpcResponse<T, ResponseCode>: Decodable
- where
- T: Decodable, ResponseCode: Decodable
-{
- let version: String
- let id: String
- let result: Result<T, JsonRpcResponseError<ResponseCode>>
-
- private enum CodingKeys: String, CodingKey {
- case version = "jsonrpc", id, result, error
- }
-
- init(from decoder: Decoder) throws {
- let container = try decoder.container(keyedBy: CodingKeys.self)
-
- self.version = try container.decode(String.self, forKey: .version)
- self.id = try container.decode(String.self, forKey: .id)
-
- if container.contains(.result) {
- self.result = .success(try container.decode(T.self, forKey: .result))
- } else {
- self.result = .failure(try container.decode(JsonRpcResponseError<ResponseCode>.self, forKey: .error))
- }
- }
-}
diff --git a/ios/MullvadVPN/MullvadRpc.swift b/ios/MullvadVPN/MullvadRpc.swift
deleted file mode 100644
index 59c53348fe..0000000000
--- a/ios/MullvadVPN/MullvadRpc.swift
+++ /dev/null
@@ -1,347 +0,0 @@
-//
-// MullvadRpc.swift
-// MullvadVPN
-//
-// Created by pronebird on 02/05/2019.
-// Copyright © 2019 Mullvad VPN AB. All rights reserved.
-//
-
-import Foundation
-import Network
-
-/// API server URL
-private let kMullvadAPIURL = URL(string: "https://api.mullvad.net/rpc/")!
-
-/// Network request timeout in seconds
-private let kNetworkTimeout: TimeInterval = 10
-
-/// A response received when sending the AppStore receipt to the backend
-struct SendAppStoreReceiptResponse: Codable {
- let timeAdded: TimeInterval
- let newExpiry: Date
-
- /// Returns a formatted string for the `timeAdded` interval, i.e "30 days"
- var formattedTimeAdded: String? {
- let formatter = DateComponentsFormatter()
- formatter.allowedUnits = [.day, .hour]
- formatter.unitsStyle = .full
-
- return formatter.string(from: timeAdded)
- }
-}
-
-class MullvadRpc {
- private let session: URLSession
-
- /// A enum mapping the integer codes returned by Mullvad API with the corresponding enum
- /// variants
- private enum RawResponseCode: Int {
- case accountDoesNotExist = -200
- case tooManyWireguardKeys = -703
- }
-
- /// A enum describing the Mullvad API response code
- enum ResponseCode: RawRepresentable, Codable {
- var rawValue: Int {
- switch self {
- case .accountDoesNotExist:
- return RawResponseCode.accountDoesNotExist.rawValue
-
- case .tooManyWireguardKeys:
- return RawResponseCode.tooManyWireguardKeys.rawValue
-
- case .other(let value):
- return value
- }
- }
-
- init?(rawValue: Int) {
- switch RawResponseCode(rawValue: rawValue) {
- case .accountDoesNotExist:
- self = .accountDoesNotExist
- case .tooManyWireguardKeys:
- self = .tooManyWireguardKeys
- case .none:
- self = ResponseCode.other(rawValue)
- }
- }
-
- case accountDoesNotExist
- case tooManyWireguardKeys
- case other(Int)
- }
-
- /// An error type emitted by `MullvadRpc`
- enum Error: ChainedError {
- /// A network communication error
- case network(URLError)
-
- /// A server error
- case server(JsonRpcResponseError<ResponseCode>)
-
- /// An error occured when decoding the JSON response
- case decoding(Swift.Error)
-
- /// An error occured when encoding the JSON request
- case encoding(Swift.Error)
-
- var errorDescription: String? {
- switch self {
- case .network:
- return "Network error"
-
- case .server:
- return "Server error"
-
- case .encoding:
- return "Encoding error"
-
- case .decoding:
- return "Decoding error"
- }
- }
- }
-
- /// Returns an instance of `MullvadRpc` configured with ephemeral `URLSession` configuration
- class func withEphemeralURLSession() -> MullvadRpc {
- return MullvadRpc(session: URLSession(configuration: .ephemeral))
- }
-
- class func makeJSONEncoder() -> JSONEncoder {
- let encoder = JSONEncoder()
- encoder.keyEncodingStrategy = .convertToSnakeCase
- encoder.dateEncodingStrategy = .iso8601
- encoder.dataEncodingStrategy = .base64
- return encoder
- }
-
- class func makeJSONDecoder() -> JSONDecoder {
- let decoder = JSONDecoder()
- decoder.keyDecodingStrategy = .convertFromSnakeCase
- decoder.dateDecodingStrategy = .iso8601
- decoder.dataDecodingStrategy = .base64
- return decoder
- }
-
- init(session: URLSession) {
- self.session = session
- }
-
- func createAccount() -> MullvadRpc.Request<String> {
- let request = JsonRpcRequest(method: "create_account", params: [])
-
- return MullvadRpc.Request(session: session, request: request)
- }
-
- func getRelayList() -> MullvadRpc.Request<RelayList> {
- let request = JsonRpcRequest(method: "relay_list_v3", params: [])
-
- return MullvadRpc.Request(session: session, request: request)
- }
-
- func getAccountExpiry(accountToken: String) -> MullvadRpc.Request<Date> {
- let request = JsonRpcRequest(method: "get_expiry", params: [AnyEncodable(accountToken)])
-
- return MullvadRpc.Request(session: session, request: request)
- }
-
- func getAccountExpiry(request: MullvadRpc.Request<Date>? = nil) -> MullvadRpc.Operation<Date> {
- return MullvadRpc.Operation(request: request)
- }
-
- func pushWireguardKey(accountToken: String, publicKey: Data) -> MullvadRpc.Request<WireguardAssociatedAddresses> {
- let request = JsonRpcRequest(method: "push_wg_key", params: [
- AnyEncodable(accountToken),
- AnyEncodable(publicKey)
- ])
-
- return MullvadRpc.Request(session: session, request: request)
- }
-
- func replaceWireguardKey(accountToken: String, oldPublicKey: Data, newPublicKey: Data) -> MullvadRpc.Request<WireguardAssociatedAddresses> {
- let request = JsonRpcRequest(method: "replace_wg_key", params: [
- AnyEncodable(accountToken),
- AnyEncodable(oldPublicKey),
- AnyEncodable(newPublicKey)
- ])
-
- return MullvadRpc.Request(session: session, request: request)
- }
-
- func checkWireguardKey(accountToken: String, publicKey: Data) -> MullvadRpc.Request<Bool> {
- let request = JsonRpcRequest(method: "check_wg_key", params: [
- AnyEncodable(accountToken),
- AnyEncodable(publicKey)
- ])
-
- return MullvadRpc.Request(session: session, request: request)
- }
-
- func checkWireguardKey(request: MullvadRpc.Request<Bool>? = nil) -> MullvadRpc.Operation<Bool> {
- return MullvadRpc.Operation(request: request)
- }
-
- func removeWireguardKey(accountToken: String, publicKey: Data) -> MullvadRpc.Request<Bool> {
- let request = JsonRpcRequest(method: "remove_wg_key", params: [
- AnyEncodable(accountToken),
- AnyEncodable(publicKey)
- ])
-
- return MullvadRpc.Request(session: session, request: request)
- }
-
- func sendAppStoreReceipt(accountToken: String, receiptData: Data) -> MullvadRpc.Request<SendAppStoreReceiptResponse> {
- let request = JsonRpcRequest(method: "apple_payment", params: [
- AnyEncodable(accountToken),
- AnyEncodable(receiptData)
- ])
-
- return MullvadRpc.Request(session: session, request: request)
- }
-}
-
-
-extension JsonRpcResponseError: LocalizedError
- where
- ResponseCode == MullvadRpc.ResponseCode
-{
- var errorDescription: String? {
- switch code {
- case .accountDoesNotExist:
- return NSLocalizedString("Invalid account", comment: "")
-
- case .tooManyWireguardKeys:
- return NSLocalizedString("Too many public WireGuard keys", comment: "")
-
- case .other:
- return nil
- }
- }
-
- var recoverySuggestion: String? {
- switch code {
- case .tooManyWireguardKeys:
- return NSLocalizedString("Remove unused WireGuard keys", comment: "")
-
- default:
- return nil
- }
- }
-}
-
-
-extension MullvadRpc {
-
- class Request<Response: Decodable> {
- typealias RequestCompletionHandler = (Result<Response, MullvadRpc.Error>) -> Void
-
- private let session: URLSession
- private let request: JsonRpcRequest
-
- private let lock = NSLock()
- private var urlSessionTask: URLSessionTask?
-
- fileprivate init(session: URLSession, request: JsonRpcRequest) {
- self.session = session
- self.request = request
- }
-
- func start(completionHandler: @escaping RequestCompletionHandler) {
- lock.withCriticalBlock {
- assert(self.urlSessionTask == nil)
-
- switch makeURLRequest() {
- case .success(let urlRequest):
- let task = session.dataTask(with: urlRequest) { (responseData, urlResponse, error) in
- switch (responseData, error) {
- case (.some(let data), .none):
- completionHandler(Self.decodeResponse(data))
-
- case (.none, .some(let urlError as URLError)):
- completionHandler(.failure(.network(urlError)))
-
- default:
- fatalError()
- }
- }
- self.urlSessionTask = task
- task.resume()
-
- case .failure(let error):
- completionHandler(.failure(error))
- }
- }
- }
-
- func cancel() {
- lock.withCriticalBlock {
- self.urlSessionTask?.cancel()
- }
- }
-
- func operation() -> MullvadRpc.Operation<Response> {
- return MullvadRpc.Operation(request: self)
- }
-
- private func makeURLRequest() -> Result<URLRequest, MullvadRpc.Error> {
- do {
- let data = try MullvadRpc.makeJSONEncoder().encode(request)
-
- return .success(Self.makeURLRequest(httpBody: data))
- } catch {
- return .failure(.encoding(error))
- }
- }
-
- private static func decodeResponse(_ responseData: Data) -> Result<Response, MullvadRpc.Error> {
- do {
- let serverResponse = try MullvadRpc.makeJSONDecoder()
- .decode(JsonRpcResponse<Response, MullvadRpc.ResponseCode>.self, from: responseData)
-
- // unwrap JsonRpcResponse.result
- return serverResponse.result
- .mapError { .server($0) }
- } catch {
- return .failure(.decoding(error))
- }
- }
-
- private static func makeURLRequest(httpBody: Data) -> URLRequest {
- var request = URLRequest(
- url: kMullvadAPIURL,
- cachePolicy: .useProtocolCachePolicy,
- timeoutInterval: kNetworkTimeout
- )
- request.addValue("application/json", forHTTPHeaderField: "Content-Type")
- request.httpMethod = "POST"
- request.httpBody = httpBody
-
- return request
- }
- }
-
- class Operation<Response>: AsyncOperation, InputOperation, OutputOperation where Response: Decodable {
- typealias Input = Request<Response>
- typealias Output = Result<Response, MullvadRpc.Error>
-
- init(request: Input? = nil) {
- super.init()
- self.input = request
- }
-
- override func main() {
- guard let request = self.input else {
- self.finish()
- return
- }
-
- request.start { [weak self] (result) in
- self?.finish(with: result)
- }
- }
-
- override func operationDidCancel() {
- input?.cancel()
- }
- }
-}
diff --git a/ios/MullvadVPN/RelayList.swift b/ios/MullvadVPN/RelayList.swift
deleted file mode 100644
index d4384696d7..0000000000
--- a/ios/MullvadVPN/RelayList.swift
+++ /dev/null
@@ -1,91 +0,0 @@
-
-//
-// RelayList.swift
-// MullvadVPN
-//
-// Created by pronebird on 02/05/2019.
-// Copyright © 2019 Mullvad VPN AB. All rights reserved.
-//
-
-import Foundation
-import Network
-
-struct RelayList: Codable {
- struct Country: Codable {
- var name: String
- var code: String
- var cities: [City]
- }
-
- struct City: Codable {
- var name: String
- var code: String
- var latitude: Double
- var longitude: Double
- var relays: [Relay]
- }
-
- struct Relay: Codable {
- var hostname: String
- var provider: String
- var ipv4AddrIn: IPv4Address
- var includeInCountry: Bool
- var active: Bool
- var owned: Bool
- var weight: Int32
- var tunnels: Tunnels?
- }
-
- struct Tunnels: Codable {
- var wireguard: [WireguardTunnel]?
- }
-
- struct WireguardTunnel: Codable {
- var ipv4Gateway: IPv4Address
- var ipv6Gateway: IPv6Address
- var publicKey: Data
- var portRanges: [ClosedRange<UInt16>]
- }
-
- var countries: [Country]
-}
-
-extension RelayList {
-
- /// Returns the total number of relays
- var numRelays: Int {
- return countries.reduce(0) { (accum, country) -> Int in
- return country.cities.reduce(accum, { (accum, city) -> Int in
- return accum + city.relays.count
- })
- }
- }
-
- /// Returns an alphabetically sorted `RelayList`
- func sorted() -> Self {
- let lexicalComparator = { (a: String, b: String) -> Bool in
- return a.localizedCaseInsensitiveCompare(b) == .orderedAscending
- }
-
- let fileComparator = { (a: String, b: String) -> Bool in
- return a.localizedStandardCompare(b) == .orderedAscending
- }
-
- let sortedCountries = countries
- .sorted { lexicalComparator($0.name, $1.name) }
- .map { (country) -> RelayList.Country in
- var sortedCountry = country
- sortedCountry.cities = country.cities.sorted { lexicalComparator($0.name, $1.name) }
- .map({ (city) -> RelayList.City in
- var sortedCity = city
- sortedCity.relays = city.relays
- .sorted { fileComparator($0.hostname, $1.hostname) }
- return sortedCity
- })
- return sortedCountry
- }
-
- return RelayList(countries: sortedCountries)
- }
-
-}