summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorsajacl <sajaclvishkai@gmail.com>2022-10-21 13:27:05 +0200
committersajacl <sajaclvishkai@gmail.com>2022-10-21 15:16:32 +0200
commit8ad5803493f26eefaa4d2e72980919e3b7233cd7 (patch)
treef543cabaa48d6e942b79500d0129d9606484f713
parentd3ef8d298dbd3ceee5bc2dfbe0c25d610e664c5f (diff)
downloadmullvadvpn-8ad5803493f26eefaa4d2e72980919e3b7233cd7.tar.xz
mullvadvpn-8ad5803493f26eefaa4d2e72980919e3b7233cd7.zip
Move RelayCache.IO and CachedRelays into new RelayCache.framework
Moved RelayCache.IO and CachedRelays into new RelayCache.framework Moved prebuild script to build phase script. Renamed script, renamed/moved RelayCache.IO to RelayCache. Renamed RelayCache.Tracker to RelayCacheTracker. Set APPLICATION_EXTENSION_API_ONLY to true for RelayCache framework. Updated gitignore. Removed relays.json from git. Removed relays.json from RelayCache framework Removed RelayCache/FetchResult, moved/renamed code into RelayCacheTracker file. Renamed CachedRelaysFetchResult to RelaysFetchResult. Changed access level for RelaysFetchResult and NoCachedRelaysError.
-rw-r--r--ios/.gitignore2
-rw-r--r--ios/MullvadVPN.xcodeproj/project.pbxproj252
-rw-r--r--ios/MullvadVPN.xcodeproj/xcshareddata/xcschemes/MullvadVPN.xcscheme20
-rw-r--r--ios/MullvadVPN/AppDelegate.swift5
-rw-r--r--ios/MullvadVPN/RelayCache/CachedRelays.swift24
-rw-r--r--ios/MullvadVPN/RelayCache/RelayCache.swift11
-rw-r--r--ios/MullvadVPN/RelayCache/RelayCacheObserver.swift5
-rw-r--r--ios/MullvadVPN/RelayCache/RelayCacheTracker.swift427
-rw-r--r--ios/MullvadVPN/SceneDelegate.swift13
-rw-r--r--ios/MullvadVPN/SelectLocationViewController.swift5
-rw-r--r--ios/MullvadVPN/SimulatorTunnelProviderHost.swift3
-rw-r--r--ios/MullvadVPN/TunnelManager/ReconnectTunnelOperation.swift3
-rw-r--r--ios/MullvadVPN/TunnelManager/StartTunnelOperation.swift3
-rw-r--r--ios/PacketTunnel/PacketTunnelProvider.swift7
-rw-r--r--ios/RelayCache/CachedRelays.swift28
-rw-r--r--ios/RelayCache/RelayCache.h19
-rw-r--r--ios/RelayCache/RelayCache.swift (renamed from ios/MullvadVPN/RelayCache/RelayCacheIO.swift)34
-rwxr-xr-xios/relays-prebuild.sh (renamed from ios/prebuild.sh)4
18 files changed, 535 insertions, 330 deletions
diff --git a/ios/.gitignore b/ios/.gitignore
index 061879af51..bb4d979639 100644
--- a/ios/.gitignore
+++ b/ios/.gitignore
@@ -3,7 +3,7 @@
# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
## Generated assets
-Assets/relays.json
+RelayCache/Assets/relays.json
MullvadREST/Assets/api-ip-address.json
## Build generated
diff --git a/ios/MullvadVPN.xcodeproj/project.pbxproj b/ios/MullvadVPN.xcodeproj/project.pbxproj
index 7acd1abd75..0d86521498 100644
--- a/ios/MullvadVPN.xcodeproj/project.pbxproj
+++ b/ios/MullvadVPN.xcodeproj/project.pbxproj
@@ -18,6 +18,13 @@
063F026628FFE11C001FA09F /* RESTCreateApplePaymentResponse+Localization.swift in Sources */ = {isa = PBXBuildFile; fileRef = 06FAE67828F83CA50033DD93 /* RESTCreateApplePaymentResponse+Localization.swift */; };
063F026729002768001FA09F /* Cancellable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 06AC113628F83FD70037AF9A /* Cancellable.swift */; };
063F026A29002E44001FA09F /* IPv4Endpoint.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58561C98239A5D1500BD6B5E /* IPv4Endpoint.swift */; };
+ 063F02762902B63F001FA09F /* RelayCache.h in Headers */ = {isa = PBXBuildFile; fileRef = 063F02752902B63F001FA09F /* RelayCache.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 063F02792902B63F001FA09F /* RelayCache.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 063F02732902B63F001FA09F /* RelayCache.framework */; };
+ 063F027A2902B63F001FA09F /* RelayCache.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 063F02732902B63F001FA09F /* RelayCache.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
+ 063F027E2902B6EB001FA09F /* RelayCache.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5820675A26E6576800655B05 /* RelayCache.swift */; };
+ 063F027F2902B6EB001FA09F /* CachedRelays.swift in Sources */ = {isa = PBXBuildFile; fileRef = 585DA87626B024A600B8C587 /* CachedRelays.swift */; };
+ 063F028A2902B7B2001FA09F /* WireGuardKitTypes in Frameworks */ = {isa = PBXBuildFile; productRef = 063F02892902B7B2001FA09F /* WireGuardKitTypes */; };
+ 063F028F2902BD8C001FA09F /* relays.json in Resources */ = {isa = PBXBuildFile; fileRef = 58F3C0A524A50155003E76BE /* relays.json */; };
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, ); }; };
@@ -88,9 +95,6 @@
5819C2142726CC8D00D6EC38 /* DataSourceSnapshotTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5819C2132726CC8D00D6EC38 /* DataSourceSnapshotTests.swift */; };
5819C2152726CC9400D6EC38 /* DataSourceSnapshot.swift in Sources */ = {isa = PBXBuildFile; fileRef = 587EB66F27143B6500123C75 /* DataSourceSnapshot.swift */; };
5819C2172729595500D6EC38 /* SettingsAddDNSEntryCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5819C2162729595500D6EC38 /* SettingsAddDNSEntryCell.swift */; };
- 5820675826E652AF00655B05 /* RelayCacheIO.swift in Sources */ = {isa = PBXBuildFile; fileRef = 585DA87C26B0254000B8C587 /* RelayCacheIO.swift */; };
- 5820675B26E6576800655B05 /* RelayCache.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5820675A26E6576800655B05 /* RelayCache.swift */; };
- 5820675C26E6576800655B05 /* RelayCache.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5820675A26E6576800655B05 /* RelayCache.swift */; };
5820676426E771DB00655B05 /* TunnelManagerErrors.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5820676326E771DB00655B05 /* TunnelManagerErrors.swift */; };
5820EDA9288FE064006BF4E4 /* DeviceManagementInteractor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5820EDA8288FE064006BF4E4 /* DeviceManagementInteractor.swift */; };
5820EDAB288FF0D2006BF4E4 /* DeviceRowView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5820EDAA288FF0D2006BF4E4 /* DeviceRowView.swift */; };
@@ -133,9 +137,6 @@
585B4B8726D9098900555C4C /* TunnelStatusNotificationProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58A94AE326CFD945001CB97C /* TunnelStatusNotificationProvider.swift */; };
585C6F4C28F80745005196BE /* Logging in Frameworks */ = {isa = PBXBuildFile; productRef = 585C6F4B28F80745005196BE /* Logging */; };
585CA70F25F8C44600B47C62 /* UIMetrics.swift in Sources */ = {isa = PBXBuildFile; fileRef = 585CA70E25F8C44600B47C62 /* UIMetrics.swift */; };
- 585DA87726B024A600B8C587 /* CachedRelays.swift in Sources */ = {isa = PBXBuildFile; fileRef = 585DA87626B024A600B8C587 /* CachedRelays.swift */; };
- 585DA87826B024A900B8C587 /* CachedRelays.swift in Sources */ = {isa = PBXBuildFile; fileRef = 585DA87626B024A600B8C587 /* CachedRelays.swift */; };
- 585DA87D26B0254000B8C587 /* RelayCacheIO.swift in Sources */ = {isa = PBXBuildFile; fileRef = 585DA87C26B0254000B8C587 /* RelayCacheIO.swift */; };
585DA89326B0323E00B8C587 /* TunnelProviderMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 585DA89226B0323E00B8C587 /* TunnelProviderMessage.swift */; };
585DA89426B0323E00B8C587 /* TunnelProviderMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 585DA89226B0323E00B8C587 /* TunnelProviderMessage.swift */; };
585DA89926B0329200B8C587 /* PacketTunnelStatus.swift in Sources */ = {isa = PBXBuildFile; fileRef = 585DA89826B0329200B8C587 /* PacketTunnelStatus.swift */; };
@@ -284,8 +285,6 @@
58F2E148276A307400A79513 /* MapConnectionStatusOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58F2E147276A307400A79513 /* MapConnectionStatusOperation.swift */; };
58F2E14C276A61C000A79513 /* RotateKeyOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58F2E14B276A61C000A79513 /* RotateKeyOperation.swift */; };
58F3C0A4249CB069003E76BE /* HeaderBarView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58F3C0A3249CB069003E76BE /* HeaderBarView.swift */; };
- 58F3C0A624A50157003E76BE /* relays.json in Resources */ = {isa = PBXBuildFile; fileRef = 58F3C0A524A50155003E76BE /* relays.json */; };
- 58F3C0A724A50C02003E76BE /* relays.json in Resources */ = {isa = PBXBuildFile; fileRef = 58F3C0A524A50155003E76BE /* relays.json */; };
58F7CA882692E34000FC59FD /* WireguardKeysContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58F7CA872692E34000FC59FD /* WireguardKeysContentView.swift */; };
58F8AC0E25D3F8CE002BE0ED /* ProblemReportReviewViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58F8AC0D25D3F8CE002BE0ED /* ProblemReportReviewViewController.swift */; };
58FB865526E8BF3100F188BC /* AppStorePaymentManagerError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58FB865426E8BF3100F188BC /* AppStorePaymentManagerError.swift */; };
@@ -329,6 +328,27 @@
remoteGlobalIDString = 581943F028F8014500B0CB5E;
remoteInfo = MullvadTypes;
};
+ 063F02772902B63F001FA09F /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 58CE5E58224146200008646E /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = 063F02722902B63F001FA09F;
+ remoteInfo = RelayCache;
+ };
+ 063F02812902B6F8001FA09F /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 58CE5E58224146200008646E /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = 06799ABB28F98E1D00ACD94E;
+ remoteInfo = MullvadREST;
+ };
+ 063F028B2902B83C001FA09F /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 58CE5E58224146200008646E /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = 063F02722902B63F001FA09F;
+ remoteInfo = RelayCache;
+ };
06799ACF28F98E1D00ACD94E /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 58CE5E58224146200008646E /* Project object */;
@@ -409,6 +429,7 @@
dstSubfolderSpec = 10;
files = (
06799AD228F98E1D00ACD94E /* MullvadREST.framework in Embed Frameworks */,
+ 063F027A2902B63F001FA09F /* RelayCache.framework in Embed Frameworks */,
);
name = "Embed Frameworks";
runOnlyForDeploymentPostprocessing = 0;
@@ -458,6 +479,8 @@
062B45C128FE97FF00746E77 /* api-ip-address.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "api-ip-address.json"; sourceTree = "<group>"; };
063687AF28EB083800BE7161 /* ProxyURLRequest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProxyURLRequest.swift; sourceTree = "<group>"; };
063687B928EB234F00BE7161 /* PacketTunnelTransport.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PacketTunnelTransport.swift; sourceTree = "<group>"; };
+ 063F02732902B63F001FA09F /* RelayCache.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = RelayCache.framework; sourceTree = BUILT_PRODUCTS_DIR; };
+ 063F02752902B63F001FA09F /* RelayCache.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RelayCache.h; 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>"; };
@@ -569,7 +592,6 @@
5857F24624C882D700CF6F47 /* SelectLocationNavigationController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SelectLocationNavigationController.swift; sourceTree = "<group>"; };
585CA70E25F8C44600B47C62 /* UIMetrics.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIMetrics.swift; sourceTree = "<group>"; };
585DA87626B024A600B8C587 /* CachedRelays.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CachedRelays.swift; sourceTree = "<group>"; };
- 585DA87C26B0254000B8C587 /* RelayCacheIO.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RelayCacheIO.swift; sourceTree = "<group>"; };
585DA89226B0323E00B8C587 /* TunnelProviderMessage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TunnelProviderMessage.swift; sourceTree = "<group>"; };
585DA89826B0329200B8C587 /* PacketTunnelStatus.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PacketTunnelStatus.swift; sourceTree = "<group>"; };
585E820227F3285E00939F0E /* SendAppStoreReceiptOperation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SendAppStoreReceiptOperation.swift; sourceTree = "<group>"; };
@@ -727,6 +749,14 @@
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
+ 063F02702902B63F001FA09F /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 063F028A2902B7B2001FA09F /* WireGuardKitTypes in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
06799AB928F98E1D00ACD94E /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
@@ -782,6 +812,7 @@
06799AD128F98E1D00ACD94E /* MullvadREST.framework in Frameworks */,
58AC829528F803A200181C40 /* libMullvadTypes.a in Frameworks */,
5818139F28E09BD8002817DE /* libOperations.a in Frameworks */,
+ 063F02792902B63F001FA09F /* RelayCache.framework in Frameworks */,
5807483B27DB8A980020ECBF /* WireGuardKitTypes in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
@@ -822,6 +853,25 @@
path = Assets;
sourceTree = "<group>";
};
+ 063F02742902B63F001FA09F /* RelayCache */ = {
+ isa = PBXGroup;
+ children = (
+ 063F028E2902BD0F001FA09F /* Assets */,
+ 063F02752902B63F001FA09F /* RelayCache.h */,
+ 585DA87626B024A600B8C587 /* CachedRelays.swift */,
+ 5820675A26E6576800655B05 /* RelayCache.swift */,
+ );
+ path = RelayCache;
+ sourceTree = "<group>";
+ };
+ 063F028E2902BD0F001FA09F /* Assets */ = {
+ isa = PBXGroup;
+ children = (
+ 58F3C0A524A50155003E76BE /* relays.json */,
+ );
+ path = Assets;
+ sourceTree = "<group>";
+ };
06799ABD28F98E1D00ACD94E /* MullvadREST */ = {
isa = PBXGroup;
children = (
@@ -961,9 +1011,6 @@
585DA87526B0249A00B8C587 /* RelayCache */ = {
isa = PBXGroup;
children = (
- 585DA87626B024A600B8C587 /* CachedRelays.swift */,
- 5820675A26E6576800655B05 /* RelayCache.swift */,
- 585DA87C26B0254000B8C587 /* RelayCacheIO.swift */,
58FB865926EA214400F188BC /* RelayCacheObserver.swift */,
58BFA5C522A7C97F00A6173D /* RelayCacheTracker.swift */,
);
@@ -1036,6 +1083,7 @@
children = (
58F3C0A824A50C0E003E76BE /* Assets */,
58ECD29023F178FD004298B6 /* Configurations */,
+ 063F02742902B63F001FA09F /* RelayCache */,
0E15C74FDCF763609B367486 /* Frameworks */,
582CFEE1269448160072883A /* Localizations */,
589A454A28DDF59B00565204 /* Shared */,
@@ -1064,6 +1112,7 @@
581943D628F800C900B0CB5E /* libMullvadLogging.a */,
581943F128F8014500B0CB5E /* libMullvadTypes.a */,
06799ABC28F98E1D00ACD94E /* MullvadREST.framework */,
+ 063F02732902B63F001FA09F /* RelayCache.framework */,
);
name = Products;
sourceTree = "<group>";
@@ -1277,7 +1326,6 @@
isa = PBXGroup;
children = (
587DCCEE287D84A500CE821E /* countries.geo.json */,
- 58F3C0A524A50155003E76BE /* relays.json */,
);
path = Assets;
sourceTree = "<group>";
@@ -1285,6 +1333,14 @@
/* End PBXGroup section */
/* Begin PBXHeadersBuildPhase section */
+ 063F026E2902B63F001FA09F /* Headers */ = {
+ isa = PBXHeadersBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 063F02762902B63F001FA09F /* RelayCache.h in Headers */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
06799AB728F98E1D00ACD94E /* Headers */ = {
isa = PBXHeadersBuildPhase;
buildActionMask = 2147483647;
@@ -1313,6 +1369,29 @@
/* End PBXLegacyTarget section */
/* Begin PBXNativeTarget section */
+ 063F02722902B63F001FA09F /* RelayCache */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 063F027D2902B63F001FA09F /* Build configuration list for PBXNativeTarget "RelayCache" */;
+ buildPhases = (
+ 063F028D2902BC8E001FA09F /* Run prebuild script */,
+ 063F026E2902B63F001FA09F /* Headers */,
+ 063F026F2902B63F001FA09F /* Sources */,
+ 063F02702902B63F001FA09F /* Frameworks */,
+ 063F02712902B63F001FA09F /* Resources */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ 063F02822902B6F8001FA09F /* PBXTargetDependency */,
+ );
+ name = RelayCache;
+ packageProductDependencies = (
+ 063F02892902B7B2001FA09F /* WireGuardKitTypes */,
+ );
+ productName = RelayCache;
+ productReference = 063F02732902B63F001FA09F /* RelayCache.framework */;
+ productType = "com.apple.product-type.framework";
+ };
06799ABB28F98E1D00ACD94E /* MullvadREST */ = {
isa = PBXNativeTarget;
buildConfigurationList = 06799AD328F98E1D00ACD94E /* Build configuration list for PBXNativeTarget "MullvadREST" */;
@@ -1432,6 +1511,7 @@
06799AD028F98E1D00ACD94E /* PBXTargetDependency */,
58E5126E28DDF09F00B0BCDE /* PBXTargetDependency */,
58CE5E80224146470008646E /* PBXTargetDependency */,
+ 063F02782902B63F001FA09F /* PBXTargetDependency */,
);
name = MullvadVPN;
packageProductDependencies = (
@@ -1453,6 +1533,7 @@
buildRules = (
);
dependencies = (
+ 063F028C2902B83C001FA09F /* PBXTargetDependency */,
062B45A628FD4FD500746E77 /* PBXTargetDependency */,
58FBDAA222A52A6800EB69A3 /* PBXTargetDependency */,
06D9846528F9A049003AABE9 /* PBXTargetDependency */,
@@ -1511,6 +1592,9 @@
LastUpgradeCheck = 1400;
ORGANIZATIONNAME = "Mullvad VPN AB";
TargetAttributes = {
+ 063F02722902B63F001FA09F = {
+ CreatedOnToolsVersion = 14.0.1;
+ };
06799ABB28F98E1D00ACD94E = {
CreatedOnToolsVersion = 14.0.1;
};
@@ -1587,11 +1671,20 @@
581943D528F800C900B0CB5E /* MullvadLogging */,
581943F028F8014500B0CB5E /* MullvadTypes */,
06799ABB28F98E1D00ACD94E /* MullvadREST */,
+ 063F02722902B63F001FA09F /* RelayCache */,
);
};
/* End PBXProject section */
/* Begin PBXResourcesBuildPhase section */
+ 063F02712902B63F001FA09F /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 063F028F2902BD8C001FA09F /* relays.json in Resources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
06799ABA28F98E1D00ACD94E /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
@@ -1619,7 +1712,6 @@
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
- 58F3C0A624A50157003E76BE /* relays.json in Resources */,
58727283265D173C00F315B2 /* LaunchScreen.storyboard in Resources */,
587DCCEF287D84A500CE821E /* countries.geo.json in Resources */,
58CE5E6B224146210008646E /* Assets.xcassets in Resources */,
@@ -1631,7 +1723,6 @@
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
- 58F3C0A724A50C02003E76BE /* relays.json in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -1645,6 +1736,25 @@
/* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase section */
+ 063F028D2902BC8E001FA09F /* Run prebuild script */ = {
+ isa = PBXShellScriptBuildPhase;
+ alwaysOutOfDate = 1;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ inputFileListPaths = (
+ );
+ inputPaths = (
+ );
+ name = "Run prebuild script";
+ outputFileListPaths = (
+ );
+ outputPaths = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ shellPath = /bin/sh;
+ shellScript = "exec > $PROJECT_DIR/relays-prebuild.log 2>&1\n\n$PROJECT_DIR/relays-prebuild.sh\n";
+ };
588E4EB028FEF1CA008046E3 /* Run prebuild script */ = {
isa = PBXShellScriptBuildPhase;
alwaysOutOfDate = 1;
@@ -1667,6 +1777,15 @@
/* End PBXShellScriptBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
+ 063F026F2902B63F001FA09F /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 063F027E2902B6EB001FA09F /* RelayCache.swift in Sources */,
+ 063F027F2902B6EB001FA09F /* CachedRelays.swift in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
06799AB828F98E1D00ACD94E /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
@@ -1781,12 +1900,10 @@
5857F24724C882D700CF6F47 /* SelectLocationNavigationController.swift in Sources */,
5846227126E229F20035F7C2 /* AppStoreSubscription.swift in Sources */,
58421030282D8A3C00F24E46 /* UpdateAccountDataOperation.swift in Sources */,
- 5820675B26E6576800655B05 /* RelayCache.swift in Sources */,
58FF2C03281BDE02009EF542 /* SettingsManager.swift in Sources */,
587EB672271451E300123C75 /* PreferencesViewModel.swift in Sources */,
586A950C290125EE007BAF2B /* AlertPresenter.swift in Sources */,
584D26C6270C8741004EA533 /* SettingsDNSTextCell.swift in Sources */,
- 585DA87D26B0254000B8C587 /* RelayCacheIO.swift in Sources */,
58F2E148276A307400A79513 /* MapConnectionStatusOperation.swift in Sources */,
58BA693123EADA6A009DC256 /* SimulatorTunnelProvider.swift in Sources */,
587C575326D2615F005EF767 /* PacketTunnelOptions.swift in Sources */,
@@ -1909,7 +2026,6 @@
063687BA28EB234F00BE7161 /* PacketTunnelTransport.swift in Sources */,
58293FB725138B88005D0BB5 /* CustomNavigationController.swift in Sources */,
587425C12299833500CA2045 /* RootContainerViewController.swift in Sources */,
- 585DA87726B024A600B8C587 /* CachedRelays.swift in Sources */,
5896AE84246D5889005B36CB /* CustomDateComponentsFormatting.swift in Sources */,
587AD7C623421D7000E93A53 /* TunnelSettingsV1.swift in Sources */,
58E20771274672CA00DE5D77 /* LaunchViewController.swift in Sources */,
@@ -1931,7 +2047,6 @@
buildActionMask = 2147483647;
files = (
587C575426D2615F005EF767 /* PacketTunnelOptions.swift in Sources */,
- 5820675826E652AF00655B05 /* RelayCacheIO.swift in Sources */,
5806767C27048E9B00C858CB /* PacketTunnelProvider.swift in Sources */,
585DA89426B0323E00B8C587 /* TunnelProviderMessage.swift in Sources */,
587AD7C723421D8600E93A53 /* TunnelSettingsV1.swift in Sources */,
@@ -1939,7 +2054,6 @@
58CE38C828992C9200A6D6E5 /* TunnelMonitorDelegate.swift in Sources */,
58FC040A27B3EE03001C21F0 /* TunnelMonitor.swift in Sources */,
5838318B27C40A3900000571 /* Pinger.swift in Sources */,
- 5820675C26E6576800655B05 /* RelayCache.swift in Sources */,
585DA89A26B0329200B8C587 /* PacketTunnelStatus.swift in Sources */,
58E0729D28814AAE008902F8 /* PacketTunnelConfiguration.swift in Sources */,
58E0729F28814ACC008902F8 /* WireGuardLogLevel+Logging.swift in Sources */,
@@ -1947,7 +2061,6 @@
5840250522B11AB700E4CFEC /* MullvadEndpoint.swift in Sources */,
58906DE02445C7A5002F0673 /* NEProviderStopReason+Debug.swift in Sources */,
580F8B872819795C002E0998 /* DNSSettings.swift in Sources */,
- 585DA87826B024A900B8C587 /* CachedRelays.swift in Sources */,
58E072A128814B0E008902F8 /* MullvadEndpoint+WgEndpoint.swift in Sources */,
584E96BD240FD4DA00D3334F /* Location.swift in Sources */,
06AC116228F94C450037AF9A /* ApplicationConfiguration.swift in Sources */,
@@ -2015,6 +2128,21 @@
target = 581943F028F8014500B0CB5E /* MullvadTypes */;
targetProxy = 063F0268290027F8001FA09F /* PBXContainerItemProxy */;
};
+ 063F02782902B63F001FA09F /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = 063F02722902B63F001FA09F /* RelayCache */;
+ targetProxy = 063F02772902B63F001FA09F /* PBXContainerItemProxy */;
+ };
+ 063F02822902B6F8001FA09F /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = 06799ABB28F98E1D00ACD94E /* MullvadREST */;
+ targetProxy = 063F02812902B6F8001FA09F /* PBXContainerItemProxy */;
+ };
+ 063F028C2902B83C001FA09F /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = 063F02722902B63F001FA09F /* RelayCache */;
+ targetProxy = 063F028B2902B83C001FA09F /* PBXContainerItemProxy */;
+ };
06799AD028F98E1D00ACD94E /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 06799ABB28F98E1D00ACD94E /* MullvadREST */;
@@ -2079,6 +2207,72 @@
/* End PBXVariantGroup section */
/* Begin XCBuildConfiguration section */
+ 063F027B2902B63F001FA09F /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ APPLICATION_EXTENSION_API_ONLY = YES;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
+ CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
+ CODE_SIGN_STYLE = Automatic;
+ CURRENT_PROJECT_VERSION = 1;
+ DEFINES_MODULE = YES;
+ DYLIB_COMPATIBILITY_VERSION = 1;
+ DYLIB_CURRENT_VERSION = 1;
+ DYLIB_INSTALL_NAME_BASE = "@rpath";
+ GENERATE_INFOPLIST_FILE = YES;
+ INFOPLIST_KEY_NSHumanReadableCopyright = "Copyright © 2022 Mullvad VPN AB. All rights reserved.";
+ INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
+ IPHONEOS_DEPLOYMENT_TARGET = 13.0;
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/Frameworks",
+ "@loader_path/Frameworks",
+ );
+ MARKETING_VERSION = 1.0;
+ PRODUCT_BUNDLE_IDENTIFIER = net.mullvad.RelayCache;
+ PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
+ SKIP_INSTALL = YES;
+ SWIFT_EMIT_LOC_STRINGS = YES;
+ SWIFT_VERSION = 5.0;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ VERSIONING_SYSTEM = "apple-generic";
+ VERSION_INFO_PREFIX = "";
+ };
+ name = Debug;
+ };
+ 063F027C2902B63F001FA09F /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ APPLICATION_EXTENSION_API_ONLY = YES;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
+ CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
+ CODE_SIGN_STYLE = Automatic;
+ CURRENT_PROJECT_VERSION = 1;
+ DEFINES_MODULE = YES;
+ DYLIB_COMPATIBILITY_VERSION = 1;
+ DYLIB_CURRENT_VERSION = 1;
+ DYLIB_INSTALL_NAME_BASE = "@rpath";
+ GENERATE_INFOPLIST_FILE = YES;
+ INFOPLIST_KEY_NSHumanReadableCopyright = "Copyright © 2022 Mullvad VPN AB. All rights reserved.";
+ INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
+ IPHONEOS_DEPLOYMENT_TARGET = 13.0;
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/Frameworks",
+ "@loader_path/Frameworks",
+ );
+ MARKETING_VERSION = 1.0;
+ PRODUCT_BUNDLE_IDENTIFIER = net.mullvad.RelayCache;
+ PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
+ SKIP_INSTALL = YES;
+ SWIFT_EMIT_LOC_STRINGS = YES;
+ SWIFT_VERSION = 5.0;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ VERSIONING_SYSTEM = "apple-generic";
+ VERSION_INFO_PREFIX = "";
+ };
+ name = Release;
+ };
06799AD428F98E1D00ACD94E /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
@@ -2580,6 +2774,7 @@
GCC_OPTIMIZATION_LEVEL = 0;
OTHER_CFLAGS = "";
OTHER_LDFLAGS = "";
+ PATH = "${PATH}:/opt/homebrew/opt/go@1.19/bin";
PRODUCT_NAME = "$(TARGET_NAME)";
};
name = Debug;
@@ -2591,6 +2786,7 @@
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
OTHER_CFLAGS = "";
OTHER_LDFLAGS = "";
+ PATH = "${PATH}:/opt/homebrew/opt/go@1.19/bin";
PRODUCT_NAME = "$(TARGET_NAME)";
};
name = Release;
@@ -2598,6 +2794,15 @@
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
+ 063F027D2902B63F001FA09F /* Build configuration list for PBXNativeTarget "RelayCache" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 063F027B2902B63F001FA09F /* Debug */,
+ 063F027C2902B63F001FA09F /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
06799AD328F98E1D00ACD94E /* Build configuration list for PBXNativeTarget "MullvadREST" */ = {
isa = XCConfigurationList;
buildConfigurations = (
@@ -2729,6 +2934,11 @@
package = 585834F624D2BC1F00A8AF56 /* XCRemoteSwiftPackageReference "swift-log" */;
productName = Logging;
};
+ 063F02892902B7B2001FA09F /* WireGuardKitTypes */ = {
+ isa = XCSwiftPackageProductDependency;
+ package = 58BA79192578F092006FAEA0 /* XCRemoteSwiftPackageReference "wireguard-apple" */;
+ productName = WireGuardKitTypes;
+ };
06D9844B28F990AB003AABE9 /* WireGuardKitTypes */ = {
isa = XCSwiftPackageProductDependency;
package = 58BA79192578F092006FAEA0 /* XCRemoteSwiftPackageReference "wireguard-apple" */;
diff --git a/ios/MullvadVPN.xcodeproj/xcshareddata/xcschemes/MullvadVPN.xcscheme b/ios/MullvadVPN.xcodeproj/xcshareddata/xcschemes/MullvadVPN.xcscheme
index 0a251cac49..5f4b4b5a25 100644
--- a/ios/MullvadVPN.xcodeproj/xcshareddata/xcschemes/MullvadVPN.xcscheme
+++ b/ios/MullvadVPN.xcodeproj/xcshareddata/xcschemes/MullvadVPN.xcscheme
@@ -1,28 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1400"
- version = "1.7">
+ version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
- <PreActions>
- <ExecutionAction
- ActionType = "Xcode.IDEStandardExecutionActionsCore.ExecutionActionType.ShellScriptAction">
- <ActionContent
- title = "Run Script"
- scriptText = "exec &gt; $PROJECT_DIR/prebuild.log 2&gt;&amp;1&#10;&#10;$PROJECT_DIR/prebuild.sh&#10;">
- <EnvironmentBuildable>
- <BuildableReference
- BuildableIdentifier = "primary"
- BlueprintIdentifier = "58CE5E5F224146200008646E"
- BuildableName = "MullvadVPN.app"
- BlueprintName = "MullvadVPN"
- ReferencedContainer = "container:MullvadVPN.xcodeproj">
- </BuildableReference>
- </EnvironmentBuildable>
- </ActionContent>
- </ExecutionAction>
- </PreActions>
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
diff --git a/ios/MullvadVPN/AppDelegate.swift b/ios/MullvadVPN/AppDelegate.swift
index 7ce348123c..acff5835fe 100644
--- a/ios/MullvadVPN/AppDelegate.swift
+++ b/ios/MullvadVPN/AppDelegate.swift
@@ -11,6 +11,7 @@ import Intents
import MullvadLogging
import MullvadREST
import Operations
+import RelayCache
import StoreKit
import UIKit
import UserNotifications
@@ -129,7 +130,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
forTaskWithIdentifier: ApplicationConfiguration.appRefreshTaskIdentifier,
using: nil
) { task in
- let handle = RelayCache.Tracker.shared.updateRelays { completion in
+ let handle = RelayCacheTracker.shared.updateRelays { completion in
task.setTaskCompleted(success: completion.isSuccess)
}
@@ -201,7 +202,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
private func scheduleAppRefreshTask() {
do {
- let date = RelayCache.Tracker.shared.getNextUpdateDate()
+ let date = RelayCacheTracker.shared.getNextUpdateDate()
let request = BGAppRefreshTaskRequest(
identifier: ApplicationConfiguration.appRefreshTaskIdentifier
diff --git a/ios/MullvadVPN/RelayCache/CachedRelays.swift b/ios/MullvadVPN/RelayCache/CachedRelays.swift
deleted file mode 100644
index 22bfaa1fdd..0000000000
--- a/ios/MullvadVPN/RelayCache/CachedRelays.swift
+++ /dev/null
@@ -1,24 +0,0 @@
-//
-// CachedRelays.swift
-// CachedRelays
-//
-// Created by pronebird on 27/07/2021.
-// Copyright © 2021 Mullvad VPN AB. All rights reserved.
-//
-
-import Foundation
-import MullvadREST
-
-extension RelayCache {
- /// A struct that represents the relay cache on disk
- struct CachedRelays: Codable {
- /// E-tag returned by server
- var etag: String?
-
- /// The relay list stored within the cache entry
- var relays: REST.ServerRelaysResponse
-
- /// The date when this cache was last updated
- var updatedAt: Date
- }
-}
diff --git a/ios/MullvadVPN/RelayCache/RelayCache.swift b/ios/MullvadVPN/RelayCache/RelayCache.swift
deleted file mode 100644
index 6ad72e205a..0000000000
--- a/ios/MullvadVPN/RelayCache/RelayCache.swift
+++ /dev/null
@@ -1,11 +0,0 @@
-//
-// RelayCache.swift
-// RelayCache
-//
-// Created by pronebird on 06/09/2021.
-// Copyright © 2021 Mullvad VPN AB. All rights reserved.
-//
-
-import Foundation
-
-enum RelayCache {}
diff --git a/ios/MullvadVPN/RelayCache/RelayCacheObserver.swift b/ios/MullvadVPN/RelayCache/RelayCacheObserver.swift
index 879157bf60..4b109340f0 100644
--- a/ios/MullvadVPN/RelayCache/RelayCacheObserver.swift
+++ b/ios/MullvadVPN/RelayCache/RelayCacheObserver.swift
@@ -7,10 +7,11 @@
//
import Foundation
+import RelayCache
protocol RelayCacheObserver: AnyObject {
func relayCache(
- _ relayCache: RelayCache.Tracker,
- didUpdateCachedRelays cachedRelays: RelayCache.CachedRelays
+ _ relayCache: RelayCacheTracker,
+ didUpdateCachedRelays cachedRelays: CachedRelays
)
}
diff --git a/ios/MullvadVPN/RelayCache/RelayCacheTracker.swift b/ios/MullvadVPN/RelayCache/RelayCacheTracker.swift
index 2f9d0eea1d..b003ae6868 100644
--- a/ios/MullvadVPN/RelayCache/RelayCacheTracker.swift
+++ b/ios/MullvadVPN/RelayCache/RelayCacheTracker.swift
@@ -11,291 +11,290 @@ import MullvadLogging
import MullvadREST
import MullvadTypes
import Operations
+import RelayCache
import UIKit
-extension RelayCache {
- /// Type describing the result of an attempt to fetch the new relay list from server.
- enum FetchResult: CustomStringConvertible {
- /// Request to update relays was throttled.
- case throttled
+class RelayCacheTracker {
+ /// Relay update interval (in seconds).
+ static let relayUpdateInterval: TimeInterval = 60 * 60
- /// Refreshed relays but the same content was found on remote.
- case sameContent
+ /// Tracker log.
+ private let logger = Logger(label: "RelayCacheTracker")
- /// Refreshed relays with new content.
- case newContent
+ /// The cache location used by the class instance.
+ private let cacheFileURL: URL
- var description: String {
- switch self {
- case .throttled:
- return "throttled"
- case .sameContent:
- return "same content"
- case .newContent:
- return "new content"
- }
- }
- }
-
- struct NoCachedRelaysError: LocalizedError {
- var errorDescription: String? {
- return "Relay cache is empty."
- }
- }
-
- class Tracker {
- /// Relay update interval (in seconds).
- static let relayUpdateInterval: TimeInterval = 60 * 60
-
- /// Tracker log.
- private let logger = Logger(label: "RelayCacheTracker")
+ /// The location of prebundled `relays.json`.
+ private let prebundledRelaysFileURL: URL
- /// The cache location used by the class instance.
- private let cacheFileURL: URL
+ /// Lock used for synchronization.
+ private let nslock = NSLock()
- /// The location of prebundled `relays.json`.
- private let prebundledRelaysFileURL: URL
+ /// Internal operation queue.
+ private let operationQueue: OperationQueue = {
+ let operationQueue = AsyncOperationQueue()
+ operationQueue.maxConcurrentOperationCount = 1
+ return operationQueue
+ }()
- /// Lock used for synchronization.
- private let nslock = NSLock()
+ /// A timer source used for periodic updates.
+ private var timerSource: DispatchSourceTimer?
- /// Internal operation queue.
- private let operationQueue: OperationQueue = {
- let operationQueue = AsyncOperationQueue()
- operationQueue.maxConcurrentOperationCount = 1
- return operationQueue
- }()
+ /// A flag that indicates whether periodic updates are running.
+ private var isPeriodicUpdatesEnabled = false
- /// A timer source used for periodic updates.
- private var timerSource: DispatchSourceTimer?
+ /// API proxy.
+ private let apiProxy = REST.ProxyFactory.shared.createAPIProxy()
- /// A flag that indicates whether periodic updates are running.
- private var isPeriodicUpdatesEnabled = false
+ /// Observers.
+ private let observerList = ObserverList<RelayCacheObserver>()
- /// API proxy.
- private let apiProxy = REST.ProxyFactory.shared.createAPIProxy()
+ /// Memory cache.
+ private var cachedRelays: CachedRelays?
- /// Observers.
- private let observerList = ObserverList<RelayCacheObserver>()
+ /// A shared instance of `RelayCache`
+ static let shared: RelayCacheTracker = {
+ let cacheFileURL = RelayCache
+ .defaultCacheFileURL(
+ forSecurityApplicationGroupIdentifier: ApplicationConfiguration
+ .securityGroupIdentifier
+ )!
+ let prebundledRelaysFileURL = RelayCache.preBundledRelaysFileURL!
- /// Memory cache.
- private var cachedRelays: CachedRelays?
+ return RelayCacheTracker(
+ cacheFileURL: cacheFileURL,
+ prebundledRelaysFileURL: prebundledRelaysFileURL
+ )
+ }()
- /// A shared instance of `RelayCache`
- static let shared: RelayCache.Tracker = {
- let cacheFileURL = RelayCache.IO
- .defaultCacheFileURL(
- forSecurityApplicationGroupIdentifier: ApplicationConfiguration
- .securityGroupIdentifier
- )!
- let prebundledRelaysFileURL = RelayCache.IO.preBundledRelaysFileURL!
+ private init(cacheFileURL: URL, prebundledRelaysFileURL: URL) {
+ self.cacheFileURL = cacheFileURL
+ self.prebundledRelaysFileURL = prebundledRelaysFileURL
- return Tracker(
+ do {
+ cachedRelays = try RelayCache.readWithFallback(
cacheFileURL: cacheFileURL,
- prebundledRelaysFileURL: prebundledRelaysFileURL
+ preBundledRelaysFileURL: prebundledRelaysFileURL
+ )
+ } catch {
+ logger.error(
+ error: error,
+ message: "Failed to read the relay cache during initialization."
)
- }()
-
- private init(cacheFileURL: URL, prebundledRelaysFileURL: URL) {
- self.cacheFileURL = cacheFileURL
- self.prebundledRelaysFileURL = prebundledRelaysFileURL
-
- do {
- cachedRelays = try RelayCache.IO.readWithFallback(
- cacheFileURL: cacheFileURL,
- preBundledRelaysFileURL: prebundledRelaysFileURL
- )
- } catch {
- logger.error(
- error: error,
- message: "Failed to read the relay cache during initialization."
- )
- _ = updateRelays(completionHandler: nil)
- }
+ _ = updateRelays(completionHandler: nil)
}
+ }
- func startPeriodicUpdates() {
- nslock.lock()
- defer { nslock.unlock() }
-
- guard !isPeriodicUpdatesEnabled else { return }
-
- logger.debug("Start periodic relay updates.")
+ func startPeriodicUpdates() {
+ nslock.lock()
+ defer { nslock.unlock() }
- isPeriodicUpdatesEnabled = true
+ guard !isPeriodicUpdatesEnabled else { return }
- let nextUpdate = _getNextUpdateDate()
+ logger.debug("Start periodic relay updates.")
- scheduleRepeatingTimer(startTime: .now() + nextUpdate.timeIntervalSinceNow)
- }
+ isPeriodicUpdatesEnabled = true
- func stopPeriodicUpdates() {
- nslock.lock()
- defer { nslock.unlock() }
+ let nextUpdate = _getNextUpdateDate()
- guard isPeriodicUpdatesEnabled else { return }
+ scheduleRepeatingTimer(startTime: .now() + nextUpdate.timeIntervalSinceNow)
+ }
- logger.debug("Stop periodic relay updates.")
+ func stopPeriodicUpdates() {
+ nslock.lock()
+ defer { nslock.unlock() }
- isPeriodicUpdatesEnabled = false
+ guard isPeriodicUpdatesEnabled else { return }
- timerSource?.cancel()
- timerSource = nil
- }
+ logger.debug("Stop periodic relay updates.")
- func updateRelays(
- completionHandler: (
- (OperationCompletion<RelayCache.FetchResult, Error>) -> Void
- )? = nil
- ) -> Cancellable {
- let operation = ResultBlockOperation<RelayCache.FetchResult, Error>(
- dispatchQueue: nil
- ) { operation in
- let cachedRelays = try? self.getCachedRelays()
+ isPeriodicUpdatesEnabled = false
- if self.getNextUpdateDate() > Date() {
- operation.finish(completion: .success(.throttled))
- return
- }
+ timerSource?.cancel()
+ timerSource = nil
+ }
- let task = self.apiProxy.getRelays(
- etag: cachedRelays?.etag,
- retryStrategy: .noRetry
- ) { completion in
- operation.finish(
- completion: self.handleResponse(completion: completion)
- )
- }
+ func updateRelays(
+ completionHandler: (
+ (OperationCompletion<RelaysFetchResult, Error>) -> Void
+ )? = nil
+ ) -> Cancellable {
+ let operation = ResultBlockOperation<RelaysFetchResult, Error>(
+ dispatchQueue: nil
+ ) { operation in
+ let cachedRelays = try? self.getCachedRelays()
- operation.addCancellationBlock {
- task.cancel()
- }
+ if self.getNextUpdateDate() > Date() {
+ operation.finish(completion: .success(.throttled))
+ return
}
- operation.addObserver(
- BackgroundObserver(
- application: .shared,
- name: "Update relays",
- cancelUponExpiration: true
+ let task = self.apiProxy.getRelays(
+ etag: cachedRelays?.etag,
+ retryStrategy: .noRetry
+ ) { completion in
+ operation.finish(
+ completion: self.handleResponse(completion: completion)
)
- )
+ }
- operation.completionQueue = .main
- operation.completionHandler = completionHandler
+ operation.addCancellationBlock {
+ task.cancel()
+ }
+ }
- operationQueue.addOperation(operation)
+ operation.addObserver(
+ BackgroundObserver(
+ application: .shared,
+ name: "Update relays",
+ cancelUponExpiration: true
+ )
+ )
- return operation
- }
+ operation.completionQueue = .main
+ operation.completionHandler = completionHandler
- func getCachedRelays() throws -> CachedRelays {
- nslock.lock()
- defer { nslock.unlock() }
+ operationQueue.addOperation(operation)
- if let cachedRelays = cachedRelays {
- return cachedRelays
- } else {
- throw NoCachedRelaysError()
- }
- }
+ return operation
+ }
- func getNextUpdateDate() -> Date {
- nslock.lock()
- defer { nslock.unlock() }
+ func getCachedRelays() throws -> CachedRelays {
+ nslock.lock()
+ defer { nslock.unlock() }
- return _getNextUpdateDate()
+ if let cachedRelays = cachedRelays {
+ return cachedRelays
+ } else {
+ throw NoCachedRelaysError()
}
+ }
- // MARK: - Observation
+ func getNextUpdateDate() -> Date {
+ nslock.lock()
+ defer { nslock.unlock() }
- func addObserver(_ observer: RelayCacheObserver) {
- observerList.append(observer)
- }
+ return _getNextUpdateDate()
+ }
- func removeObserver(_ observer: RelayCacheObserver) {
- observerList.remove(observer)
- }
+ // MARK: - Observation
- // MARK: - Private
+ func addObserver(_ observer: RelayCacheObserver) {
+ observerList.append(observer)
+ }
- private func _getNextUpdateDate() -> Date {
- let now = Date()
+ func removeObserver(_ observer: RelayCacheObserver) {
+ observerList.remove(observer)
+ }
- guard let cachedRelays = cachedRelays else {
- return now
- }
+ // MARK: - Private
- let nextUpdate = cachedRelays.updatedAt.addingTimeInterval(Self.relayUpdateInterval)
+ private func _getNextUpdateDate() -> Date {
+ let now = Date()
- return max(nextUpdate, Date())
+ guard let cachedRelays = cachedRelays else {
+ return now
}
- private func handleResponse(
- completion: OperationCompletion<REST.ServerRelaysCacheResponse, REST.Error>
- ) -> OperationCompletion<FetchResult, Error> {
- let mappedCompletion = completion.tryMap { response -> FetchResult in
- switch response {
- case let .newContent(etag, relays):
- try self.storeResponse(etag: etag, relays: relays)
+ let nextUpdate = cachedRelays.updatedAt.addingTimeInterval(Self.relayUpdateInterval)
- return .newContent
+ return max(nextUpdate, Date())
+ }
- case .notModified:
- return .sameContent
- }
- }
+ private func handleResponse(
+ completion: OperationCompletion<REST.ServerRelaysCacheResponse, REST.Error>
+ ) -> OperationCompletion<RelaysFetchResult, Error> {
+ let mappedCompletion = completion.tryMap { response -> RelaysFetchResult in
+ switch response {
+ case let .newContent(etag, relays):
+ try self.storeResponse(etag: etag, relays: relays)
- if let error = mappedCompletion.error {
- logger.error(
- error: error,
- message: "Failed to update relays."
- )
+ return .newContent
+
+ case .notModified:
+ return .sameContent
}
+ }
- return mappedCompletion
+ if let error = mappedCompletion.error {
+ logger.error(
+ error: error,
+ message: "Failed to update relays."
+ )
}
- private func storeResponse(etag: String?, relays: REST.ServerRelaysResponse) throws {
- let numRelays = relays.wireguard.relays.count
+ return mappedCompletion
+ }
- logger.info("Downloaded \(numRelays) relays.")
+ private func storeResponse(etag: String?, relays: REST.ServerRelaysResponse) throws {
+ let numRelays = relays.wireguard.relays.count
- let newCachedRelays = RelayCache.CachedRelays(
- etag: etag,
- relays: relays,
- updatedAt: Date()
- )
+ logger.info("Downloaded \(numRelays) relays.")
- nslock.lock()
- cachedRelays = newCachedRelays
- nslock.unlock()
+ let newCachedRelays = CachedRelays(
+ etag: etag,
+ relays: relays,
+ updatedAt: Date()
+ )
- try RelayCache.IO.write(
- cacheFileURL: cacheFileURL,
- record: newCachedRelays
- )
+ nslock.lock()
+ cachedRelays = newCachedRelays
+ nslock.unlock()
+
+ try RelayCache.write(
+ cacheFileURL: cacheFileURL,
+ record: newCachedRelays
+ )
- DispatchQueue.main.async {
- self.observerList.forEach { observer in
- observer.relayCache(self, didUpdateCachedRelays: newCachedRelays)
- }
+ DispatchQueue.main.async {
+ self.observerList.forEach { observer in
+ observer.relayCache(self, didUpdateCachedRelays: newCachedRelays)
}
}
+ }
- private func scheduleRepeatingTimer(startTime: DispatchWallTime) {
- let timerSource = DispatchSource.makeTimerSource()
- timerSource.setEventHandler { [weak self] in
- _ = self?.updateRelays()
- }
+ private func scheduleRepeatingTimer(startTime: DispatchWallTime) {
+ let timerSource = DispatchSource.makeTimerSource()
+ timerSource.setEventHandler { [weak self] in
+ _ = self?.updateRelays()
+ }
- timerSource.schedule(
- wallDeadline: startTime,
- repeating: .seconds(Int(Self.relayUpdateInterval))
- )
- timerSource.activate()
+ timerSource.schedule(
+ wallDeadline: startTime,
+ repeating: .seconds(Int(Self.relayUpdateInterval))
+ )
+ timerSource.activate()
- self.timerSource = timerSource
+ self.timerSource = timerSource
+ }
+}
+
+/// Type describing the result of an attempt to fetch the new relay list from server.
+enum RelaysFetchResult: CustomStringConvertible {
+ /// Request to update relays was throttled.
+ case throttled
+
+ /// Refreshed relays but the same content was found on remote.
+ case sameContent
+
+ /// Refreshed relays with new content.
+ case newContent
+
+ var description: String {
+ switch self {
+ case .throttled:
+ return "throttled"
+ case .sameContent:
+ return "same content"
+ case .newContent:
+ return "new content"
}
}
}
+
+struct NoCachedRelaysError: LocalizedError {
+ var errorDescription: String? {
+ return "Relay cache is empty."
+ }
+}
diff --git a/ios/MullvadVPN/SceneDelegate.swift b/ios/MullvadVPN/SceneDelegate.swift
index d495ceb7a7..b77ccf42ae 100644
--- a/ios/MullvadVPN/SceneDelegate.swift
+++ b/ios/MullvadVPN/SceneDelegate.swift
@@ -9,6 +9,7 @@
import MullvadLogging
import MullvadREST
import Operations
+import RelayCache
import UIKit
class SceneDelegate: UIResponder {
@@ -86,7 +87,7 @@ class SceneDelegate: UIResponder {
fatalError()
}
- RelayCache.Tracker.shared.addObserver(self)
+ RelayCacheTracker.shared.addObserver(self)
NotificationManager.shared.delegate = self
accountDataThrottling.requestUpdate(condition: .always)
@@ -113,7 +114,7 @@ class SceneDelegate: UIResponder {
)
}
- RelayCache.Tracker.shared.startPeriodicUpdates()
+ RelayCacheTracker.shared.startPeriodicUpdates()
TunnelManager.shared.startPeriodicPrivateKeyRotation()
AddressCacheTracker.shared.startPeriodicUpdates()
ShortcutsManager.shared.updateVoiceShortcuts()
@@ -122,7 +123,7 @@ class SceneDelegate: UIResponder {
}
@objc private func sceneWillResignActive() {
- RelayCache.Tracker.shared.stopPeriodicUpdates()
+ RelayCacheTracker.shared.stopPeriodicUpdates()
TunnelManager.shared.stopPeriodicPrivateKeyRotation()
AddressCacheTracker.shared.stopPeriodicUpdates()
@@ -414,7 +415,7 @@ extension SceneDelegate {
let selectLocationController = SelectLocationViewController()
selectLocationController.delegate = self
- if let cachedRelays = try? RelayCache.Tracker.shared.getCachedRelays() {
+ if let cachedRelays = try? RelayCacheTracker.shared.getCachedRelays() {
selectLocationController.setCachedRelays(cachedRelays)
}
@@ -933,8 +934,8 @@ extension SceneDelegate: TunnelObserver {
extension SceneDelegate: RelayCacheObserver {
func relayCache(
- _ relayCache: RelayCache.Tracker,
- didUpdateCachedRelays cachedRelays: RelayCache.CachedRelays
+ _ relayCache: RelayCacheTracker,
+ didUpdateCachedRelays cachedRelays: CachedRelays
) {
selectLocationViewController?.setCachedRelays(cachedRelays)
}
diff --git a/ios/MullvadVPN/SelectLocationViewController.swift b/ios/MullvadVPN/SelectLocationViewController.swift
index 147fc3b54e..abe8d765f4 100644
--- a/ios/MullvadVPN/SelectLocationViewController.swift
+++ b/ios/MullvadVPN/SelectLocationViewController.swift
@@ -7,6 +7,7 @@
//
import MullvadLogging
+import RelayCache
import UIKit
protocol SelectLocationViewControllerDelegate: AnyObject {
@@ -26,7 +27,7 @@ class SelectLocationViewController: UIViewController, UITableViewDelegate {
private var tableHeaderFooterViewBottomConstraints: [NSLayoutConstraint] = []
private var dataSource: LocationDataSource?
- private var setCachedRelaysOnViewDidLoad: RelayCache.CachedRelays?
+ private var setCachedRelaysOnViewDidLoad: CachedRelays?
private var setRelayLocationOnViewDidLoad: RelayLocation?
private var setScrollPositionOnViewDidLoad: UITableView.ScrollPosition = .none
private var isViewAppeared = false
@@ -229,7 +230,7 @@ class SelectLocationViewController: UIViewController, UITableViewDelegate {
// MARK: - Public
- func setCachedRelays(_ cachedRelays: RelayCache.CachedRelays) {
+ func setCachedRelays(_ cachedRelays: CachedRelays) {
guard isViewLoaded else {
setCachedRelaysOnViewDidLoad = cachedRelays
return
diff --git a/ios/MullvadVPN/SimulatorTunnelProviderHost.swift b/ios/MullvadVPN/SimulatorTunnelProviderHost.swift
index ef159e7886..4bd7b19696 100644
--- a/ios/MullvadVPN/SimulatorTunnelProviderHost.swift
+++ b/ios/MullvadVPN/SimulatorTunnelProviderHost.swift
@@ -12,6 +12,7 @@ import Foundation
import MullvadLogging
import MullvadREST
import enum NetworkExtension.NEProviderStopReason
+import RelayCache
class SimulatorTunnelProviderHost: SimulatorTunnelProviderDelegate {
private var selectorResult: RelaySelectorResult?
@@ -154,7 +155,7 @@ class SimulatorTunnelProviderHost: SimulatorTunnelProviderDelegate {
}
private func pickRelay() throws -> RelaySelectorResult {
- let cachedRelays = try RelayCache.Tracker.shared.getCachedRelays()
+ let cachedRelays = try RelayCacheTracker.shared.getCachedRelays()
let tunnelSettings = try SettingsManager.readSettings()
return try RelaySelector.evaluate(
diff --git a/ios/MullvadVPN/TunnelManager/ReconnectTunnelOperation.swift b/ios/MullvadVPN/TunnelManager/ReconnectTunnelOperation.swift
index 5105108acb..748a77e3a6 100644
--- a/ios/MullvadVPN/TunnelManager/ReconnectTunnelOperation.swift
+++ b/ios/MullvadVPN/TunnelManager/ReconnectTunnelOperation.swift
@@ -10,6 +10,7 @@ import Foundation
import MullvadREST
import MullvadTypes
import Operations
+import RelayCache
class ReconnectTunnelOperation: ResultOperation<Void, Error> {
private let interactor: TunnelInteractor
@@ -37,7 +38,7 @@ class ReconnectTunnelOperation: ResultOperation<Void, Error> {
var selectorResult: RelaySelectorResult?
if selectNewRelay {
- let cachedRelays = try RelayCache.Tracker.shared.getCachedRelays()
+ let cachedRelays = try RelayCacheTracker.shared.getCachedRelays()
selectorResult = try RelaySelector.evaluate(
relays: cachedRelays.relays,
constraints: interactor.settings.relayConstraints
diff --git a/ios/MullvadVPN/TunnelManager/StartTunnelOperation.swift b/ios/MullvadVPN/TunnelManager/StartTunnelOperation.swift
index 71210438e5..c2611323a0 100644
--- a/ios/MullvadVPN/TunnelManager/StartTunnelOperation.swift
+++ b/ios/MullvadVPN/TunnelManager/StartTunnelOperation.swift
@@ -10,6 +10,7 @@ import Foundation
import MullvadLogging
import NetworkExtension
import Operations
+import RelayCache
class StartTunnelOperation: ResultOperation<Void, Error> {
typealias EncodeErrorHandler = (Error) -> Void
@@ -48,7 +49,7 @@ class StartTunnelOperation: ResultOperation<Void, Error> {
case .disconnected, .pendingReconnect:
do {
- let cachedRelays = try RelayCache.Tracker.shared.getCachedRelays()
+ let cachedRelays = try RelayCacheTracker.shared.getCachedRelays()
let selectorResult = try RelaySelector.evaluate(
relays: cachedRelays.relays,
constraints: interactor.settings.relayConstraints
diff --git a/ios/PacketTunnel/PacketTunnelProvider.swift b/ios/PacketTunnel/PacketTunnelProvider.swift
index 982b583e56..45b79f51ac 100644
--- a/ios/PacketTunnel/PacketTunnelProvider.swift
+++ b/ios/PacketTunnel/PacketTunnelProvider.swift
@@ -11,6 +11,7 @@ import MullvadLogging
import MullvadREST
import Network
import NetworkExtension
+import RelayCache
import WireGuardKit
class PacketTunnelProvider: NEPacketTunnelProvider, TunnelMonitorDelegate {
@@ -435,11 +436,11 @@ class PacketTunnelProvider: NEPacketTunnelProvider, TunnelMonitorDelegate {
private class func selectRelayEndpoint(relayConstraints: RelayConstraints) throws
-> RelaySelectorResult
{
- let cacheFileURL = RelayCache.IO.defaultCacheFileURL(
+ let cacheFileURL = RelayCache.defaultCacheFileURL(
forSecurityApplicationGroupIdentifier: ApplicationConfiguration.securityGroupIdentifier
)!
- let prebundledRelaysURL = RelayCache.IO.preBundledRelaysFileURL!
- let cachedRelayList = try RelayCache.IO.readWithFallback(
+ let prebundledRelaysURL = RelayCache.preBundledRelaysFileURL!
+ let cachedRelayList = try RelayCache.readWithFallback(
cacheFileURL: cacheFileURL,
preBundledRelaysFileURL: prebundledRelaysURL
)
diff --git a/ios/RelayCache/CachedRelays.swift b/ios/RelayCache/CachedRelays.swift
new file mode 100644
index 0000000000..6ff9c36091
--- /dev/null
+++ b/ios/RelayCache/CachedRelays.swift
@@ -0,0 +1,28 @@
+//
+// CachedRelays.swift
+// CachedRelays
+//
+// Created by pronebird on 27/07/2021.
+// Copyright © 2021 Mullvad VPN AB. All rights reserved.
+//
+
+import Foundation
+import MullvadREST
+
+/// A struct that represents the relay cache on disk
+public struct CachedRelays: Codable {
+ /// E-tag returned by server
+ public var etag: String?
+
+ /// The relay list stored within the cache entry
+ public var relays: REST.ServerRelaysResponse
+
+ /// The date when this cache was last updated
+ public var updatedAt: Date
+
+ public init(etag: String? = nil, relays: REST.ServerRelaysResponse, updatedAt: Date) {
+ self.etag = etag
+ self.relays = relays
+ self.updatedAt = updatedAt
+ }
+}
diff --git a/ios/RelayCache/RelayCache.h b/ios/RelayCache/RelayCache.h
new file mode 100644
index 0000000000..abe3d1b983
--- /dev/null
+++ b/ios/RelayCache/RelayCache.h
@@ -0,0 +1,19 @@
+//
+// RelayCache.h
+// RelayCache
+//
+// Created by Sajad Vishkai on 2022-10-21.
+// Copyright © 2022 Mullvad VPN AB. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+
+//! Project version number for RelayCache.
+FOUNDATION_EXPORT double RelayCacheVersionNumber;
+
+//! Project version string for RelayCache.
+FOUNDATION_EXPORT const unsigned char RelayCacheVersionString[];
+
+// In this header, you should import all the public headers of your framework using statements like #import <RelayCache/PublicHeader.h>
+
+
diff --git a/ios/MullvadVPN/RelayCache/RelayCacheIO.swift b/ios/RelayCache/RelayCache.swift
index d2e9e91070..64ce748128 100644
--- a/ios/MullvadVPN/RelayCache/RelayCacheIO.swift
+++ b/ios/RelayCache/RelayCache.swift
@@ -1,21 +1,17 @@
//
-// RelayCacheIO.swift
-// RelayCacheIO
+// RelayCache.swift
+// RelayCache
//
-// Created by pronebird on 27/07/2021.
+// Created by pronebird on 06/09/2021.
// Copyright © 2021 Mullvad VPN AB. All rights reserved.
//
import Foundation
import MullvadREST
-extension RelayCache {
- enum IO {}
-}
-
-extension RelayCache.IO {
+public class RelayCache {
/// The default cache file location bound by app group container.
- static func defaultCacheFileURL(
+ public static func defaultCacheFileURL(
forSecurityApplicationGroupIdentifier appGroupIdentifier: String
) -> URL? {
let containerURL = FileManager.default.containerURL(
@@ -26,19 +22,19 @@ extension RelayCache.IO {
}
/// The path to pre-bundled `relays.json` file.
- static var preBundledRelaysFileURL: URL? {
- return Bundle.main.url(forResource: "relays", withExtension: "json")
+ public static var preBundledRelaysFileURL: URL? {
+ return Bundle(for: Self.self).url(forResource: "relays", withExtension: "json")
}
/// Safely read the cache file from disk using file coordinator.
- static func read(cacheFileURL: URL) throws -> RelayCache.CachedRelays {
- var result: Result<RelayCache.CachedRelays, Error>?
+ public static func read(cacheFileURL: URL) throws -> CachedRelays {
+ var result: Result<CachedRelays, Error>?
let fileCoordinator = NSFileCoordinator(filePresenter: nil)
let accessor = { (fileURLForReading: URL) in
result = Result {
let data = try Data(contentsOf: fileURLForReading)
- return try JSONDecoder().decode(RelayCache.CachedRelays.self, from: data)
+ return try JSONDecoder().decode(CachedRelays.self, from: data)
}
}
@@ -59,8 +55,8 @@ extension RelayCache.IO {
/// Safely read the cache file from disk using file coordinator and fallback to prebundled
/// relays in case if the relay cache file is missing.
- static func readWithFallback(cacheFileURL: URL, preBundledRelaysFileURL: URL)
- throws -> RelayCache.CachedRelays
+ public static func readWithFallback(cacheFileURL: URL, preBundledRelaysFileURL: URL)
+ throws -> CachedRelays
{
do {
return try Self.read(cacheFileURL: cacheFileURL)
@@ -74,19 +70,19 @@ extension RelayCache.IO {
}
/// Read pre-bundled relays file from disk.
- static func readPrebundledRelays(fileURL: URL) throws -> RelayCache.CachedRelays {
+ public static func readPrebundledRelays(fileURL: URL) throws -> CachedRelays {
let data = try Data(contentsOf: fileURL)
let relays = try REST.Coding.makeJSONDecoder()
.decode(REST.ServerRelaysResponse.self, from: data)
- return RelayCache.CachedRelays(
+ return CachedRelays(
relays: relays,
updatedAt: Date(timeIntervalSince1970: 0)
)
}
/// Safely write the cache file on disk using file coordinator.
- static func write(cacheFileURL: URL, record: RelayCache.CachedRelays) throws {
+ public static func write(cacheFileURL: URL, record: CachedRelays) throws {
var result: Result<Void, Error>?
let fileCoordinator = NSFileCoordinator(filePresenter: nil)
diff --git a/ios/prebuild.sh b/ios/relays-prebuild.sh
index 22a8ae4f9d..caef0efe4a 100755
--- a/ios/prebuild.sh
+++ b/ios/relays-prebuild.sh
@@ -5,9 +5,7 @@ if [ -z "$PROJECT_DIR" ]; then
exit 1
fi
-ASSETS_DIR_PATH="$PROJECT_DIR/Assets"
-
-RELAYS_FILE="$ASSETS_DIR_PATH/relays.json"
+RELAYS_FILE="$PROJECT_DIR/RelayCache/Assets/relays.json"
if [ $CONFIGURATION == "Release" ]; then
echo "Remove relays file"