diff options
| author | Andrej Mihajlov <and@mullvad.net> | 2019-08-13 13:59:11 +0300 |
|---|---|---|
| committer | Andrej Mihajlov <and@mullvad.net> | 2019-08-16 12:50:07 +0300 |
| commit | d9e1776ae310c2b1d4b5cf6627f05530afcc0e95 (patch) | |
| tree | aab9aea4e022d3fd8436faea50dc8d50a0e955c0 | |
| parent | 3605029f6f78b6ad43d6af0537ac1cb4c6190202 (diff) | |
| download | mullvadvpn-d9e1776ae310c2b1d4b5cf6627f05530afcc0e95.tar.xz mullvadvpn-d9e1776ae310c2b1d4b5cf6627f05530afcc0e95.zip | |
Add wireguard related API methods
| -rw-r--r-- | ios/MullvadVPN.xcodeproj/project.pbxproj | 42 | ||||
| -rw-r--r-- | ios/MullvadVPN/IPAddressRange.swift | 92 | ||||
| -rw-r--r-- | ios/MullvadVPN/IpAddress+Codable.swift | 47 | ||||
| -rw-r--r-- | ios/MullvadVPN/JsonRequestProcedure.swift (renamed from ios/MullvadVPN/JSONRequestProcedure.swift) | 13 | ||||
| -rw-r--r-- | ios/MullvadVPN/JsonRpc.swift | 36 | ||||
| -rw-r--r-- | ios/MullvadVPN/MullvadAPI.swift | 42 | ||||
| -rw-r--r-- | ios/MullvadVPN/ProcedureKit+Patches.swift | 49 | ||||
| -rw-r--r-- | ios/MullvadVPN/WireguardAssociatedAddresses.swift | 15 |
8 files changed, 305 insertions, 31 deletions
diff --git a/ios/MullvadVPN.xcodeproj/project.pbxproj b/ios/MullvadVPN.xcodeproj/project.pbxproj index 8b44ec32f3..df975f7b3c 100644 --- a/ios/MullvadVPN.xcodeproj/project.pbxproj +++ b/ios/MullvadVPN.xcodeproj/project.pbxproj @@ -16,12 +16,16 @@ 582BB1B1229569620055B6EF /* CustomNavigationBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 582BB1B0229569620055B6EF /* CustomNavigationBar.swift */; }; 582BB1B3229574F40055B6EF /* SettingsAccountCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 582BB1B2229574F40055B6EF /* SettingsAccountCell.swift */; }; 582BB1B52295780F0055B6EF /* AccountExpiry.swift in Sources */ = {isa = PBXBuildFile; fileRef = 582BB1B42295780F0055B6EF /* AccountExpiry.swift */; }; + 5840250122B1124600E4CFEC /* IpAddress+Codable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5840250022B1124600E4CFEC /* IpAddress+Codable.swift */; }; + 5840250222B1124600E4CFEC /* IpAddress+Codable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5840250022B1124600E4CFEC /* IpAddress+Codable.swift */; }; 58461AD3228D622E00B72ECB /* Account.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58461AD2228D622E00B72ECB /* Account.swift */; }; 58535B85229E89E7004BCBBD /* WeakBox.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58535B84229E89E7004BCBBD /* WeakBox.swift */; }; 5862805422428EF100F5A6E1 /* TranslucentButtonBlurView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5862805322428EF100F5A6E1 /* TranslucentButtonBlurView.swift */; }; 5867A51C2248F26A005513C0 /* SegueIdentifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5867A51B2248F26A005513C0 /* SegueIdentifier.swift */; }; 58723E7522A54CB2009837F5 /* libwg-go.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 58723E7422A54C63009837F5 /* libwg-go.a */; }; 587425C12299833500CA2045 /* RootContainerViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 587425C02299833500CA2045 /* RootContainerViewController.swift */; }; + 58781CC622AE5F4B009B9D8E /* ProcedureKit+Patches.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58781CC522AE5F4B009B9D8E /* ProcedureKit+Patches.swift */; }; + 58781CC722AE602B009B9D8E /* ProcedureKit+Patches.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58781CC522AE5F4B009B9D8E /* ProcedureKit+Patches.swift */; }; 587B08E0229433EB000E6F17 /* LoginState.swift in Sources */ = {isa = PBXBuildFile; fileRef = 587B08DF229433EB000E6F17 /* LoginState.swift */; }; 587B08E2229460C1000E6F17 /* WebLinks.swift in Sources */ = {isa = PBXBuildFile; fileRef = 587B08E1229460C1000E6F17 /* WebLinks.swift */; }; 587CBFE322807F530028DED3 /* UIColor+Helpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 587CBFE222807F530028DED3 /* UIColor+Helpers.swift */; }; @@ -34,7 +38,13 @@ 58ADDB3C227B1BD200FAFEA7 /* JsonRpc.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58ADDB3B227B1BD200FAFEA7 /* JsonRpc.swift */; }; 58ADDB3E227B1CD900FAFEA7 /* MullvadAPI.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58ADDB3D227B1CD900FAFEA7 /* MullvadAPI.swift */; }; 58ADDB40227B1E7100FAFEA7 /* Optional+Unwrap.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58ADDB3F227B1E7100FAFEA7 /* Optional+Unwrap.swift */; }; + 58B8743222B25A7600015324 /* WireguardAssociatedAddresses.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58B8743122B25A7600015324 /* WireguardAssociatedAddresses.swift */; }; + 58BFA5C022A7C8A900A6173D /* MullvadAPI.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58ADDB3D227B1CD900FAFEA7 /* MullvadAPI.swift */; }; + 58BFA5C122A7C92400A6173D /* JsonRequestProcedure.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58F19E30228B2AEB00C7710B /* JsonRequestProcedure.swift */; }; + 58BFA5C222A7C92900A6173D /* JsonRpc.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58ADDB3B227B1BD200FAFEA7 /* JsonRpc.swift */; }; 58C3A4B222456F1B00340BDB /* AccountInputGroupView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58C3A4B122456F1A00340BDB /* AccountInputGroupView.swift */; }; + 58C6B34F22BB7AC0003C19AD /* IPAddressRange.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58C6B34E22BB7AC0003C19AD /* IPAddressRange.swift */; }; + 58C6B35122BB7CFD003C19AD /* IPAddressRange.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58C6B34E22BB7AC0003C19AD /* IPAddressRange.swift */; }; 58CCA010224249A1004F3011 /* ConnectViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58CCA00F224249A1004F3011 /* ConnectViewController.swift */; }; 58CCA01222424D11004F3011 /* SettingsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58CCA01122424D11004F3011 /* SettingsViewController.swift */; }; 58CCA0162242560B004F3011 /* UIColor+Palette.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58CCA0152242560B004F3011 /* UIColor+Palette.swift */; }; @@ -47,7 +57,10 @@ 58CE5E6E224146210008646E /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 58CE5E6C224146210008646E /* LaunchScreen.storyboard */; }; 58CE5E7C224146470008646E /* PacketTunnelProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58CE5E7B224146470008646E /* PacketTunnelProvider.swift */; }; 58CE5E81224146470008646E /* PacketTunnel.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = 58CE5E79224146470008646E /* PacketTunnel.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; - 58F19E31228B2AEB00C7710B /* JSONRequestProcedure.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58F19E30228B2AEB00C7710B /* JSONRequestProcedure.swift */; }; + 58D06EA82302E1A1000C75C6 /* WireguardAssociatedAddresses.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58B8743122B25A7600015324 /* WireguardAssociatedAddresses.swift */; }; + 58D06EA92302E1A8000C75C6 /* RelayList.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5888AD88227B18C40051EB06 /* RelayList.swift */; }; + 58D06EAA2302E1B0000C75C6 /* AccountVerificationProcedure.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58F19E32228B383300C7710B /* AccountVerificationProcedure.swift */; }; + 58F19E31228B2AEB00C7710B /* JsonRequestProcedure.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58F19E30228B2AEB00C7710B /* JsonRequestProcedure.swift */; }; 58F19E33228B383300C7710B /* AccountVerificationProcedure.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58F19E32228B383300C7710B /* AccountVerificationProcedure.swift */; }; 58F19E35228C15BA00C7710B /* SpinnerActivityIndicatorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58F19E34228C15BA00C7710B /* SpinnerActivityIndicatorView.swift */; }; 58F83F08229D3F560086FCE3 /* AccountExpiryRefresh.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58F83F07229D3F560086FCE3 /* AccountExpiryRefresh.swift */; }; @@ -95,6 +108,7 @@ 582BB1B0229569620055B6EF /* CustomNavigationBar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomNavigationBar.swift; sourceTree = "<group>"; }; 582BB1B2229574F40055B6EF /* SettingsAccountCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsAccountCell.swift; sourceTree = "<group>"; }; 582BB1B42295780F0055B6EF /* AccountExpiry.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountExpiry.swift; sourceTree = "<group>"; }; + 5840250022B1124600E4CFEC /* IpAddress+Codable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "IpAddress+Codable.swift"; sourceTree = "<group>"; }; 58461AD2228D622E00B72ECB /* Account.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Account.swift; sourceTree = "<group>"; }; 58535B84229E89E7004BCBBD /* WeakBox.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WeakBox.swift; sourceTree = "<group>"; }; 5862805322428EF100F5A6E1 /* TranslucentButtonBlurView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TranslucentButtonBlurView.swift; sourceTree = "<group>"; }; @@ -102,6 +116,7 @@ 5867A51B2248F26A005513C0 /* SegueIdentifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SegueIdentifier.swift; sourceTree = "<group>"; }; 58723E7422A54C63009837F5 /* libwg-go.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = "libwg-go.a"; sourceTree = BUILT_PRODUCTS_DIR; }; 587425C02299833500CA2045 /* RootContainerViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RootContainerViewController.swift; sourceTree = "<group>"; }; + 58781CC522AE5F4B009B9D8E /* ProcedureKit+Patches.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ProcedureKit+Patches.swift"; sourceTree = "<group>"; }; 587B08DF229433EB000E6F17 /* LoginState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginState.swift; sourceTree = "<group>"; }; 587B08E1229460C1000E6F17 /* WebLinks.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WebLinks.swift; sourceTree = "<group>"; }; 587CBFE222807F530028DED3 /* UIColor+Helpers.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIColor+Helpers.swift"; sourceTree = "<group>"; }; @@ -114,7 +129,9 @@ 58ADDB3B227B1BD200FAFEA7 /* JsonRpc.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JsonRpc.swift; sourceTree = "<group>"; }; 58ADDB3D227B1CD900FAFEA7 /* MullvadAPI.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MullvadAPI.swift; sourceTree = "<group>"; }; 58ADDB3F227B1E7100FAFEA7 /* Optional+Unwrap.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Optional+Unwrap.swift"; sourceTree = "<group>"; }; + 58B8743122B25A7600015324 /* WireguardAssociatedAddresses.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WireguardAssociatedAddresses.swift; sourceTree = "<group>"; }; 58C3A4B122456F1A00340BDB /* AccountInputGroupView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountInputGroupView.swift; sourceTree = "<group>"; }; + 58C6B34E22BB7AC0003C19AD /* IPAddressRange.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IPAddressRange.swift; sourceTree = "<group>"; }; 58CCA00F224249A1004F3011 /* ConnectViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConnectViewController.swift; sourceTree = "<group>"; }; 58CCA01122424D11004F3011 /* SettingsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsViewController.swift; sourceTree = "<group>"; }; 58CCA0152242560B004F3011 /* UIColor+Palette.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIColor+Palette.swift"; sourceTree = "<group>"; }; @@ -131,7 +148,7 @@ 58CE5E7B224146470008646E /* PacketTunnelProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PacketTunnelProvider.swift; sourceTree = "<group>"; }; 58CE5E7D224146470008646E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; }; 58CE5E7E224146470008646E /* PacketTunnel.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = PacketTunnel.entitlements; sourceTree = "<group>"; }; - 58F19E30228B2AEB00C7710B /* JSONRequestProcedure.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JSONRequestProcedure.swift; sourceTree = "<group>"; }; + 58F19E30228B2AEB00C7710B /* JsonRequestProcedure.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JsonRequestProcedure.swift; sourceTree = "<group>"; }; 58F19E32228B383300C7710B /* AccountVerificationProcedure.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountVerificationProcedure.swift; sourceTree = "<group>"; }; 58F19E34228C15BA00C7710B /* SpinnerActivityIndicatorView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SpinnerActivityIndicatorView.swift; sourceTree = "<group>"; }; 58F83F07229D3F560086FCE3 /* AccountExpiryRefresh.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountExpiryRefresh.swift; sourceTree = "<group>"; }; @@ -212,7 +229,9 @@ 5894FC482296A8090017471D /* CustomButton.swift */, 582BB1B0229569620055B6EF /* CustomNavigationBar.swift */, 58CE5E6F224146210008646E /* Info.plist */, - 58F19E30228B2AEB00C7710B /* JSONRequestProcedure.swift */, + 5840250022B1124600E4CFEC /* IpAddress+Codable.swift */, + 58C6B34E22BB7AC0003C19AD /* IPAddressRange.swift */, + 58F19E30228B2AEB00C7710B /* JsonRequestProcedure.swift */, 58ADDB3B227B1BD200FAFEA7 /* JsonRpc.swift */, 58CE5E6C224146210008646E /* LaunchScreen.storyboard */, 587B08DF229433EB000E6F17 /* LoginState.swift */, @@ -221,6 +240,7 @@ 58ADDB3D227B1CD900FAFEA7 /* MullvadAPI.swift */, 5866F39B2243B82D00168AE5 /* MullvadVPN.entitlements */, 58ADDB3F227B1E7100FAFEA7 /* Optional+Unwrap.swift */, + 58781CC522AE5F4B009B9D8E /* ProcedureKit+Patches.swift */, 5888AD88227B18C40051EB06 /* RelayList.swift */, 5888AD7E2279B6BF0051EB06 /* RelayStatusIndicatorView.swift */, 587425C02299833500CA2045 /* RootContainerViewController.swift */, @@ -241,6 +261,7 @@ 58535B84229E89E7004BCBBD /* WeakBox.swift */, 587B08E1229460C1000E6F17 /* WebLinks.swift */, 58FBDAAA22A52DC500EB69A3 /* MullvadVPN-Bridging-Header.h */, + 58B8743122B25A7600015324 /* WireguardAssociatedAddresses.swift */, ); path = MullvadVPN; sourceTree = "<group>"; @@ -508,6 +529,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 5840250122B1124600E4CFEC /* IpAddress+Codable.swift in Sources */, 582BB1B52295780F0055B6EF /* AccountExpiry.swift in Sources */, 582BB1B3229574F40055B6EF /* SettingsAccountCell.swift in Sources */, 58CCA010224249A1004F3011 /* ConnectViewController.swift in Sources */, @@ -515,6 +537,7 @@ 582BB1B1229569620055B6EF /* CustomNavigationBar.swift in Sources */, 58461AD3228D622E00B72ECB /* Account.swift in Sources */, 5888AD87227B17950051EB06 /* SelectLocationController.swift in Sources */, + 58781CC622AE5F4B009B9D8E /* ProcedureKit+Patches.swift in Sources */, 58F19E35228C15BA00C7710B /* SpinnerActivityIndicatorView.swift in Sources */, 58ADDB40227B1E7100FAFEA7 /* Optional+Unwrap.swift in Sources */, 58CCA0162242560B004F3011 /* UIColor+Palette.swift in Sources */, @@ -524,7 +547,9 @@ 587B08E2229460C1000E6F17 /* WebLinks.swift in Sources */, 58CCA01822426713004F3011 /* AccountViewController.swift in Sources */, 58ADDB3E227B1CD900FAFEA7 /* MullvadAPI.swift in Sources */, + 58B8743222B25A7600015324 /* WireguardAssociatedAddresses.swift in Sources */, 587B08E0229433EB000E6F17 /* LoginState.swift in Sources */, + 58C6B34F22BB7AC0003C19AD /* IPAddressRange.swift in Sources */, 582BB1AF229566420055B6EF /* SettingsCell.swift in Sources */, 58535B85229E89E7004BCBBD /* WeakBox.swift in Sources */, 5862805422428EF100F5A6E1 /* TranslucentButtonBlurView.swift in Sources */, @@ -538,7 +563,7 @@ 589AB4F7227B64450039131E /* BasicTableViewCell.swift in Sources */, 5888AD7F2279B6BF0051EB06 /* RelayStatusIndicatorView.swift in Sources */, 5867A51C2248F26A005513C0 /* SegueIdentifier.swift in Sources */, - 58F19E31228B2AEB00C7710B /* JSONRequestProcedure.swift in Sources */, + 58F19E31228B2AEB00C7710B /* JsonRequestProcedure.swift in Sources */, 5894FC492296A8090017471D /* CustomButton.swift in Sources */, 58CCA01E2242787B004F3011 /* AccountTextField.swift in Sources */, 587425C12299833500CA2045 /* RootContainerViewController.swift in Sources */, @@ -552,7 +577,16 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 58D06EAA2302E1B0000C75C6 /* AccountVerificationProcedure.swift in Sources */, + 58781CC722AE602B009B9D8E /* ProcedureKit+Patches.swift in Sources */, + 58D06EA92302E1A8000C75C6 /* RelayList.swift in Sources */, + 58D06EA82302E1A1000C75C6 /* WireguardAssociatedAddresses.swift in Sources */, + 58BFA5C222A7C92900A6173D /* JsonRpc.swift in Sources */, + 58C6B35122BB7CFD003C19AD /* IPAddressRange.swift in Sources */, + 58BFA5C122A7C92400A6173D /* JsonRequestProcedure.swift in Sources */, + 5840250222B1124600E4CFEC /* IpAddress+Codable.swift in Sources */, 58CE5E7C224146470008646E /* PacketTunnelProvider.swift in Sources */, + 58BFA5C022A7C8A900A6173D /* MullvadAPI.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/ios/MullvadVPN/IPAddressRange.swift b/ios/MullvadVPN/IPAddressRange.swift new file mode 100644 index 0000000000..a8169877cb --- /dev/null +++ b/ios/MullvadVPN/IPAddressRange.swift @@ -0,0 +1,92 @@ +// +// IPAddressRange.swift +// MullvadVPN +// +// Created by pronebird on 20/06/2019. +// Copyright © 2019 Amagicom AB. All rights reserved. +// + +import Foundation +import Network + +struct IPAddressRange { + let address: IPAddress + var networkPrefixLength: UInt8 +} + +extension IPAddressRange: Equatable { + static func == (lhs: IPAddressRange, rhs: IPAddressRange) -> Bool { + return lhs.address.rawValue == rhs.address.rawValue && + lhs.networkPrefixLength == rhs.networkPrefixLength + } +} + +extension IPAddressRange: Hashable { + func hash(into hasher: inout Hasher) { + hasher.combine(address.rawValue) + hasher.combine(networkPrefixLength) + } +} + +extension IPAddressRange: CustomStringConvertible { + var description: String { + return "\(address)/\(networkPrefixLength)" + } +} + +extension IPAddressRange { + + init?(from string: String) { + guard let parsed = IPAddressRange.parseAddressString(string) else { return nil } + address = parsed.0 + networkPrefixLength = parsed.1 + } + + private static func parseAddressString(_ string: String) -> (IPAddress, UInt8)? { + let endOfIPAddress = string.lastIndex(of: "/") ?? string.endIndex + let addressString = String(string[string.startIndex ..< endOfIPAddress]) + let address: IPAddress + if let addr = IPv4Address(addressString) { + address = addr + } else if let addr = IPv6Address(addressString) { + address = addr + } else { + return nil + } + + let maxNetworkPrefixLength: UInt8 = address is IPv4Address ? 32 : 128 + var networkPrefixLength: UInt8 + if endOfIPAddress < string.endIndex { // "/" was located + let indexOfNetworkPrefixLength = string.index(after: endOfIPAddress) + guard indexOfNetworkPrefixLength < string.endIndex else { return nil } + let networkPrefixLengthSubstring = string[indexOfNetworkPrefixLength ..< string.endIndex] + guard let npl = UInt8(networkPrefixLengthSubstring) else { return nil } + networkPrefixLength = min(npl, maxNetworkPrefixLength) + } else { + networkPrefixLength = maxNetworkPrefixLength + } + + return (address, networkPrefixLength) + } +} + +extension IPAddressRange: Codable { + + func encode(to encoder: Encoder) throws { + var container = encoder.singleValueContainer() + + try container.encode("\(self)") + } + + init(from decoder: Decoder) throws { + let container = try decoder.singleValueContainer() + let value = try container.decode(String.self) + + if let addressRange = IPAddressRange(from: value) { + self = addressRange + } else { + throw DecodingError.dataCorruptedError( + in: container, debugDescription: "Invalid IPAddressRange representation") + } + } +} diff --git a/ios/MullvadVPN/IpAddress+Codable.swift b/ios/MullvadVPN/IpAddress+Codable.swift new file mode 100644 index 0000000000..104aae7cdb --- /dev/null +++ b/ios/MullvadVPN/IpAddress+Codable.swift @@ -0,0 +1,47 @@ +// +// IpAddress+Codable.swift +// MullvadVPN +// +// Created by pronebird on 12/06/2019. +// Copyright © 2019 Amagicom AB. All rights reserved. +// + +import Network + +extension IPv4Address: Codable { + public init(from decoder: Decoder) throws { + let container = try decoder.singleValueContainer() + let ipString = try container.decode(String.self) + + if let decoded = IPv4Address(ipString) { + self = decoded + } else { + throw DecodingError.dataCorruptedError(in: container, debugDescription: "Invalid IPv4 representation") + } + } + + public func encode(to encoder: Encoder) throws { + var container = encoder.singleValueContainer() + + try container.encode(String(reflecting: self)) + } +} + +extension IPv6Address: Codable { + public init(from decoder: Decoder) throws { + let container = try decoder.singleValueContainer() + let ipString = try container.decode(String.self) + + if let decoded = IPv6Address(ipString) { + self = decoded + } else { + throw DecodingError.dataCorruptedError(in: container, debugDescription: "Invalid IPv6 representation") + } + } + + public func encode(to encoder: Encoder) throws { + var container = encoder.singleValueContainer() + + try container.encode(String(reflecting: self)) + } +} diff --git a/ios/MullvadVPN/JSONRequestProcedure.swift b/ios/MullvadVPN/JsonRequestProcedure.swift index 6b6527b6f1..762bb1f1b3 100644 --- a/ios/MullvadVPN/JSONRequestProcedure.swift +++ b/ios/MullvadVPN/JsonRequestProcedure.swift @@ -1,5 +1,5 @@ // -// JSONRequestProcedure.swift +// JsonRequestProcedure.swift // MullvadVPN // // Created by pronebird on 14/05/2019. @@ -9,7 +9,7 @@ import Foundation import ProcedureKit -final class JSONRequestProcedure<Input, Output: Decodable>: GroupProcedure, InputProcedure, OutputProcedure { +final class JsonRequestProcedure<Input, Output: Decodable>: GroupProcedure, InputProcedure, OutputProcedure { typealias URLRequestBuilder = (Input) throws -> URLRequest @@ -20,6 +20,7 @@ final class JSONRequestProcedure<Input, Output: Decodable>: GroupProcedure, Inpu self.input = input.flatMap { .ready($0) } ?? .pending let createRequest = TransformProcedure { try requestBuilder($0) } + createRequest.input = self.input let networkRequest = NetworkProcedure { NetworkDataProcedure(session: URLSession.shared) @@ -27,20 +28,18 @@ final class JSONRequestProcedure<Input, Output: Decodable>: GroupProcedure, Inpu let payloadParsing = DecodeJSONProcedure<Output>( dateDecodingStrategy: .iso8601, + dataDecodingStrategy: .base64, keyDecodingStrategy: .convertFromSnakeCase ).injectPayload(fromNetwork: networkRequest) super.init(dispatchQueue: underlyingQueue, operations: [createRequest, networkRequest, payloadParsing]) bind(from: payloadParsing) - - addWillExecuteBlockObserver { (procedure, _) in - createRequest.input = procedure.input - } + bindAndNotifySetInputReady(to: createRequest) } } -extension JSONRequestProcedure where Input == Void { +extension JsonRequestProcedure where Input == Void { convenience init(requestBuilder: @escaping URLRequestBuilder) { self.init(input: (), requestBuilder: requestBuilder) } diff --git a/ios/MullvadVPN/JsonRpc.swift b/ios/MullvadVPN/JsonRpc.swift index ac1d44660c..6c54bf6adb 100644 --- a/ios/MullvadVPN/JsonRpc.swift +++ b/ios/MullvadVPN/JsonRpc.swift @@ -8,26 +8,36 @@ import Foundation -typealias JsonRpcRequestId = String -struct JsonRpcRequest<T: Encodable>: Encodable { +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: JsonRpcRequestId = UUID().uuidString + let id = UUID().uuidString let method: String - let params: [T] + let params: [AnyEncodable] fileprivate enum CodingKeys: String, CodingKey { case version = "jsonrpc", id, method, params } } -extension JsonRpcRequest where T == NoData { - init(method: String) { - self.init(method: method, params: []) - } -} - -struct NoData: Encodable {} - class JsonRpcResponseError: Error, Decodable { let code: Int let message: String @@ -50,7 +60,7 @@ class JsonRpcResponseError: Error, Decodable { struct JsonRpcResponse<T: Decodable>: Decodable { let version: String - let id: JsonRpcRequestId + let id: String let result: Result<T, JsonRpcResponseError> private enum CodingKeys: String, CodingKey { diff --git a/ios/MullvadVPN/MullvadAPI.swift b/ios/MullvadVPN/MullvadAPI.swift index 28bc9f9894..fe2160af68 100644 --- a/ios/MullvadVPN/MullvadAPI.swift +++ b/ios/MullvadVPN/MullvadAPI.swift @@ -7,23 +7,30 @@ // import Foundation +import Network import ProcedureKit private let kMullvadAPIURL = URL(string: "https://api.mullvad.net/rpc/")! class MullvadAPI { - class func getRelayList() -> JSONRequestProcedure<Void, JsonRpcResponse<RelayList>> { - return JSONRequestProcedure(requestBuilder: { - try makeURLRequest(method: "POST", rpcRequest: JsonRpcRequest(method: "relay_list_v2")) + struct WireguardKeyRequest: Codable { + var accountToken: String + var publicKey: Data + } + + class func getRelayList() -> JsonRequestProcedure<Void, JsonRpcResponse<RelayList>> { + return JsonRequestProcedure(requestBuilder: { + try makeURLRequest(method: "POST", + rpcRequest: JsonRpcRequest(method: "relay_list_v2", params: [])) }) } - class func getAccountExpiry(accountToken: String? = nil) -> JSONRequestProcedure<String, JsonRpcResponse<Date>> { - return JSONRequestProcedure(input: accountToken, requestBuilder: { + class func getAccountExpiry(accountToken: String? = nil) -> JsonRequestProcedure<String, JsonRpcResponse<Date>> { + return JsonRequestProcedure(input: accountToken, requestBuilder: { try makeURLRequest( method: "POST", - rpcRequest: JsonRpcRequest(method: "get_expiry", params: [$0]) + rpcRequest: JsonRpcRequest(method: "get_expiry", params: [AnyEncodable($0)]) ) }) } @@ -32,10 +39,31 @@ class MullvadAPI { return AccountVerificationProcedure(accountToken: accountToken) } - private class func makeURLRequest<T: Encodable>(method: String, rpcRequest: JsonRpcRequest<T>) throws -> URLRequest { + class func pushWireguardKey(_ pushRequest: WireguardKeyRequest? = nil) -> JsonRequestProcedure<WireguardKeyRequest, JsonRpcResponse<WireguardAssociatedAddresses>> { + return JsonRequestProcedure(input: pushRequest, requestBuilder: { (input) -> URLRequest in + let rpcRequest = JsonRpcRequest(method: "push_wg_key", params: [ + AnyEncodable(input.accountToken), + AnyEncodable(input.publicKey) + ]) + return try makeURLRequest(method: "POST", rpcRequest: rpcRequest) + }) + } + + class func checkWireguardKey(_ pushRequest: WireguardKeyRequest? = nil) -> JsonRequestProcedure<WireguardKeyRequest, JsonRpcResponse<Bool>> { + return JsonRequestProcedure(input: pushRequest, requestBuilder: { (input) -> URLRequest in + let rpcRequest = JsonRpcRequest(method: "check_wg_key", params: [ + AnyEncodable(input.accountToken), + AnyEncodable(input.publicKey) + ]) + return try makeURLRequest(method: "POST", rpcRequest: rpcRequest) + }) + } + + private class func makeURLRequest(method: String, rpcRequest: JsonRpcRequest) throws -> URLRequest { let encoder = JSONEncoder() encoder.keyEncodingStrategy = .convertToSnakeCase encoder.dateEncodingStrategy = .iso8601 + encoder.dataEncodingStrategy = .base64 var urlRequest = URLRequest(url: kMullvadAPIURL) urlRequest.httpMethod = method diff --git a/ios/MullvadVPN/ProcedureKit+Patches.swift b/ios/MullvadVPN/ProcedureKit+Patches.swift new file mode 100644 index 0000000000..86b644f6a2 --- /dev/null +++ b/ios/MullvadVPN/ProcedureKit+Patches.swift @@ -0,0 +1,49 @@ +// +// ProcedureKit+Patches.swift +// MullvadVPN +// +// Created by pronebird on 10/06/2019. +// Copyright © 2019 Amagicom AB. All rights reserved. +// + +import ProcedureKit + +extension InputProcedure { + + /// The original implementation of bind(to: T) has a bug + /// This is an attempt to temporarily patch it. + /// Github issue: https://github.com/ProcedureKit/ProcedureKit/issues/936 + func bindAndNotifySetInputReady<T: InputProcedure>(to target: T) where T.Input == Self.Input { + addDidSetInputReadyBlockObserver { (procedure) in + if case .ready = procedure.input { + target.input = procedure.input + target.didSetInputReady() + } + } + } +} + +extension ProcedureResult { + /// Turn ProcedureResult into Swift 5 Result<T, Error> + func into() -> Result<Value, Error> { + switch self { + case .success(let value): + return .success(value) + case .failure(let error): + return .failure(error) + } + } +} + +extension Result { + /// Turn Swift 5 Result<T, _> into ProcedureResult<T> + func into() -> ProcedureResult<Success> { + switch self { + case .success(let value): + return .success(value) + case .failure(let error): + return .failure(error) + } + } + +} diff --git a/ios/MullvadVPN/WireguardAssociatedAddresses.swift b/ios/MullvadVPN/WireguardAssociatedAddresses.swift new file mode 100644 index 0000000000..c4c543d832 --- /dev/null +++ b/ios/MullvadVPN/WireguardAssociatedAddresses.swift @@ -0,0 +1,15 @@ +// +// WireguardAssociatedAddresses.swift +// MullvadVPN +// +// Created by pronebird on 13/06/2019. +// Copyright © 2019 Amagicom AB. All rights reserved. +// + +import Foundation +import Network + +struct WireguardAssociatedAddresses: Codable { + let ipv4Address: IPAddressRange + let ipv6Address: IPAddressRange +} |
