summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorAndrej Mihajlov <and@mullvad.net>2020-07-30 11:31:29 +0300
committerAndrej Mihajlov <and@mullvad.net>2020-08-13 15:55:14 +0200
commit30466abf6356d87e51b46b139caf441f4e54f759 (patch)
tree64cab4e2253728ec031536a1a31a94ccf501d514
parent10da3af6d2a12e11f8f46dbd28116bc5a13e1196 (diff)
downloadmullvadvpn-30466abf6356d87e51b46b139caf441f4e54f759.tar.xz
mullvadvpn-30466abf6356d87e51b46b139caf441f4e54f759.zip
Add SwiftLog
-rw-r--r--ios/CHANGELOG.md1
-rw-r--r--ios/MullvadVPN.xcodeproj/project.pbxproj69
-rw-r--r--ios/MullvadVPN.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved9
-rw-r--r--ios/MullvadVPN/Account.swift6
-rw-r--r--ios/MullvadVPN/AccountViewController.swift5
-rw-r--r--ios/MullvadVPN/AppDelegate.swift3
-rw-r--r--ios/MullvadVPN/AppStorePaymentManager.swift25
-rw-r--r--ios/MullvadVPN/AutomaticKeyRotationManager.swift24
-rw-r--r--ios/MullvadVPN/ChainedError.swift5
-rw-r--r--ios/MullvadVPN/ConnectViewController.swift16
-rw-r--r--ios/MullvadVPN/Logging/ChainedError+Logger.swift24
-rw-r--r--ios/MullvadVPN/Logging/CustomFormatLogHandler.swift68
-rw-r--r--ios/MullvadVPN/Logging/LogRotation.swift59
-rw-r--r--ios/MullvadVPN/Logging/Logging.swift50
-rw-r--r--ios/MullvadVPN/Logging/TextFileOutputStream.swift61
-rw-r--r--ios/MullvadVPN/LoginViewController.swift8
-rw-r--r--ios/MullvadVPN/RelayCache.swift16
-rw-r--r--ios/MullvadVPN/SelectLocationController.swift10
-rw-r--r--ios/MullvadVPN/SimulatorTunnelProviderHost.swift10
-rw-r--r--ios/MullvadVPN/TunnelManager.swift33
-rw-r--r--ios/MullvadVPN/WireguardKeysViewController.swift5
-rw-r--r--ios/PacketTunnel/AnyIPEndpoint+DNS64.swift1
-rw-r--r--ios/PacketTunnel/Logging.swift21
-rw-r--r--ios/PacketTunnel/PacketTunnelProvider.swift63
-rw-r--r--ios/PacketTunnel/PacketTunnelSettingsGenerator.swift1
-rw-r--r--ios/PacketTunnel/WireguardDevice.swift51
26 files changed, 478 insertions, 166 deletions
diff --git a/ios/CHANGELOG.md b/ios/CHANGELOG.md
index 13cb39d70b..9e0e294233 100644
--- a/ios/CHANGELOG.md
+++ b/ios/CHANGELOG.md
@@ -24,6 +24,7 @@ Line wrap the file at 100 chars. Th
## [Unreleased]
### Added
+- Save application logs to file.
- Add button to reconnect the tunnel.
- Add support for iOS 12.
- Ship the initial relay list with the app, and do once an hour periodic refresh in background.
diff --git a/ios/MullvadVPN.xcodeproj/project.pbxproj b/ios/MullvadVPN.xcodeproj/project.pbxproj
index 0c188fa520..de75dd4a2f 100644
--- a/ios/MullvadVPN.xcodeproj/project.pbxproj
+++ b/ios/MullvadVPN.xcodeproj/project.pbxproj
@@ -39,6 +39,16 @@
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 */; };
+ 5815039724D6ECAE00C9C50E /* CustomFormatLogHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5815039624D6ECAE00C9C50E /* CustomFormatLogHandler.swift */; };
+ 5815039824D6ECAE00C9C50E /* CustomFormatLogHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5815039624D6ECAE00C9C50E /* CustomFormatLogHandler.swift */; };
+ 5815039D24D6ECE600C9C50E /* TextFileOutputStream.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5815039C24D6ECE600C9C50E /* TextFileOutputStream.swift */; };
+ 5815039E24D6ECE600C9C50E /* TextFileOutputStream.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5815039C24D6ECE600C9C50E /* TextFileOutputStream.swift */; };
+ 581503A024D6F01E00C9C50E /* LogRotation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5815039324D6EB7200C9C50E /* LogRotation.swift */; };
+ 581503A124D6F01F00C9C50E /* LogRotation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5815039324D6EB7200C9C50E /* LogRotation.swift */; };
+ 581503A324D6F1EC00C9C50E /* ChainedError+Logger.swift in Sources */ = {isa = PBXBuildFile; fileRef = 581503A224D6F1EC00C9C50E /* ChainedError+Logger.swift */; };
+ 581503A424D6F1EC00C9C50E /* ChainedError+Logger.swift in Sources */ = {isa = PBXBuildFile; fileRef = 581503A224D6F1EC00C9C50E /* ChainedError+Logger.swift */; };
+ 581503A624D6F4AE00C9C50E /* Logging.swift in Sources */ = {isa = PBXBuildFile; fileRef = 581503A524D6F4AE00C9C50E /* Logging.swift */; };
+ 581503A724D6F4AE00C9C50E /* Logging.swift in Sources */ = {isa = PBXBuildFile; fileRef = 581503A524D6F4AE00C9C50E /* Logging.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 */; };
@@ -77,9 +87,10 @@
5857F23F24C844AD00CF6F47 /* Locking.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58BA692D23E99EFF009DC256 /* Locking.swift */; };
5857F24324C8662600CF6F47 /* SelectLocationHeaderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5857F24224C8662600CF6F47 /* SelectLocationHeaderView.swift */; };
5857F24724C882D700CF6F47 /* SelectLocationNavigationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5857F24624C882D700CF6F47 /* SelectLocationNavigationController.swift */; };
+ 585834F824D2BC1F00A8AF56 /* Logging in Frameworks */ = {isa = PBXBuildFile; productRef = 585834F724D2BC1F00A8AF56 /* Logging */; };
+ 585834FC24D2BC9500A8AF56 /* Logging in Frameworks */ = {isa = PBXBuildFile; productRef = 585834FB24D2BC9500A8AF56 /* Logging */; };
5860F1C223A785C600CEA666 /* WireguardDevice.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5860F1C123A785C600CEA666 /* WireguardDevice.swift */; };
5860F1C423A8D25F00CEA666 /* WireguardConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5860F1C323A8D25F00CEA666 /* WireguardConfiguration.swift */; };
- 5860F1EB23AA4CF300CEA666 /* Logging.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5860F1EA23AA4CF300CEA666 /* Logging.swift */; };
5862805422428EF100F5A6E1 /* TranslucentButtonBlurView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5862805322428EF100F5A6E1 /* TranslucentButtonBlurView.swift */; };
5867A51C2248F26A005513C0 /* SegueIdentifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5867A51B2248F26A005513C0 /* SegueIdentifier.swift */; };
5868585524054096000B8131 /* AppButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5868585424054096000B8131 /* AppButton.swift */; };
@@ -258,6 +269,11 @@
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>"; };
+ 5815039324D6EB7200C9C50E /* LogRotation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LogRotation.swift; sourceTree = "<group>"; };
+ 5815039624D6ECAE00C9C50E /* CustomFormatLogHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomFormatLogHandler.swift; sourceTree = "<group>"; };
+ 5815039C24D6ECE600C9C50E /* TextFileOutputStream.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextFileOutputStream.swift; sourceTree = "<group>"; };
+ 581503A224D6F1EC00C9C50E /* ChainedError+Logger.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ChainedError+Logger.swift"; sourceTree = "<group>"; };
+ 581503A524D6F4AE00C9C50E /* Logging.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Logging.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>"; };
@@ -277,7 +293,6 @@
5857F24624C882D700CF6F47 /* SelectLocationNavigationController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SelectLocationNavigationController.swift; sourceTree = "<group>"; };
5860F1C123A785C600CEA666 /* WireguardDevice.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WireguardDevice.swift; sourceTree = "<group>"; };
5860F1C323A8D25F00CEA666 /* WireguardConfiguration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WireguardConfiguration.swift; sourceTree = "<group>"; };
- 5860F1EA23AA4CF300CEA666 /* Logging.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Logging.swift; sourceTree = "<group>"; };
5862805322428EF100F5A6E1 /* TranslucentButtonBlurView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TranslucentButtonBlurView.swift; sourceTree = "<group>"; };
5866F39B2243B82D00168AE5 /* MullvadVPN.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = MullvadVPN.entitlements; sourceTree = "<group>"; };
5867A51B2248F26A005513C0 /* SegueIdentifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SegueIdentifier.swift; sourceTree = "<group>"; };
@@ -387,6 +402,7 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
+ 585834F824D2BC1F00A8AF56 /* Logging in Frameworks */,
58F3C0A0249BBF1E003E76BE /* DiffableDataSources in Frameworks */,
586BD68422B7BBE400BB7F9F /* NetworkExtension.framework in Frameworks */,
);
@@ -396,6 +412,7 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
+ 585834FC24D2BC9500A8AF56 /* Logging in Frameworks */,
586BD68322B7BBD800BB7F9F /* NetworkExtension.framework in Frameworks */,
58723E7522A54CB2009837F5 /* libwg-go.a in Frameworks */,
);
@@ -442,6 +459,18 @@
path = Operations;
sourceTree = "<group>";
};
+ 5815039F24D6ECF200C9C50E /* Logging */ = {
+ isa = PBXGroup;
+ children = (
+ 581503A224D6F1EC00C9C50E /* ChainedError+Logger.swift */,
+ 5815039624D6ECAE00C9C50E /* CustomFormatLogHandler.swift */,
+ 5815039C24D6ECE600C9C50E /* TextFileOutputStream.swift */,
+ 581503A524D6F4AE00C9C50E /* Logging.swift */,
+ 5815039324D6EB7200C9C50E /* LogRotation.swift */,
+ );
+ path = Logging;
+ sourceTree = "<group>";
+ };
58B0A2A1238EE67E00BC001D /* MullvadVPNTests */ = {
isa = PBXGroup;
children = (
@@ -483,6 +512,7 @@
58CE5E62224146200008646E /* MullvadVPN */ = {
isa = PBXGroup;
children = (
+ 5815039F24D6ECF200C9C50E /* Logging */,
587AD7C92342283900E93A53 /* Account.swift */,
582BB1B42295780F0055B6EF /* AccountExpiry.swift */,
58C3A4B122456F1A00340BDB /* AccountInputGroupView.swift */,
@@ -590,7 +620,6 @@
58C6B36622C106FC003C19AD /* WireguardCommand.swift */,
5860F1C123A785C600CEA666 /* WireguardDevice.swift */,
5860F1C323A8D25F00CEA666 /* WireguardConfiguration.swift */,
- 5860F1EA23AA4CF300CEA666 /* Logging.swift */,
);
path = PacketTunnel;
sourceTree = "<group>";
@@ -676,6 +705,7 @@
name = MullvadVPN;
packageProductDependencies = (
58F3C09F249BBF1E003E76BE /* DiffableDataSources */,
+ 585834F724D2BC1F00A8AF56 /* Logging */,
);
productName = MullvadVPN;
productReference = 58CE5E60224146200008646E /* MullvadVPN.app */;
@@ -696,6 +726,9 @@
58FBDAA222A52A6800EB69A3 /* PBXTargetDependency */,
);
name = PacketTunnel;
+ packageProductDependencies = (
+ 585834FB24D2BC9500A8AF56 /* Logging */,
+ );
productName = PacketTunnel;
productReference = 58CE5E79224146470008646E /* PacketTunnel.appex */;
productType = "com.apple.product-type.app-extension";
@@ -772,6 +805,7 @@
mainGroup = 58CE5E57224146200008646E;
packageReferences = (
58F3C09E249BBF1E003E76BE /* XCRemoteSwiftPackageReference "DiffableDataSources" */,
+ 585834F624D2BC1F00A8AF56 /* XCRemoteSwiftPackageReference "swift-log" */,
);
productRefGroup = 58CE5E61224146200008646E /* Products */;
projectDirPath = "";
@@ -952,6 +986,7 @@
5845F842236CBACD00B2D93C /* PacketTunnelIpc.swift in Sources */,
58781CC922AE7CA8009B9D8E /* RelayConstraints.swift in Sources */,
584E96BC240FD4DA00D3334F /* Location.swift in Sources */,
+ 581503A124D6F01F00C9C50E /* LogRotation.swift in Sources */,
580EE20F24B322E700F9D8A1 /* TransformOperation.swift in Sources */,
58B8743222B25A7600015324 /* WireguardAssociatedAddresses.swift in Sources */,
58C6B34F22BB7AC0003C19AD /* IPAddressRange.swift in Sources */,
@@ -972,12 +1007,15 @@
5877152E23981C5B001F8237 /* SettingsBasicCell.swift in Sources */,
58FD5BE724192A2C00112C88 /* AppStoreReceipt.swift in Sources */,
5835B7CC233B76CB0096D79F /* TunnelManager.swift in Sources */,
+ 5815039724D6ECAE00C9C50E /* CustomFormatLogHandler.swift in Sources */,
+ 5815039D24D6ECE600C9C50E /* TextFileOutputStream.swift in Sources */,
581CBCEE229826FD00727D7F /* StaticTableViewDataSource.swift in Sources */,
58CE5E64224146200008646E /* AppDelegate.swift in Sources */,
58C6B35E22BBBFE3003C19AD /* Data+HexCoding.swift in Sources */,
5857F24324C8662600CF6F47 /* SelectLocationHeaderView.swift in Sources */,
58AEEF652344A36000C9BBD5 /* KeychainError.swift in Sources */,
580EE22824B3289300F9D8A1 /* AssociatedValue.swift in Sources */,
+ 581503A624D6F4AE00C9C50E /* Logging.swift in Sources */,
58CCA01222424D11004F3011 /* SettingsViewController.swift in Sources */,
58FD5BF42428C67600112C88 /* InAppPurchaseButton.swift in Sources */,
580EE22424B3243100F9D8A1 /* AsyncBlockOperation.swift in Sources */,
@@ -993,6 +1031,7 @@
5896AE84246D5889005B36CB /* CustomDateComponentsFormatting.swift in Sources */,
580EE21824B3235100F9D8A1 /* AnyOperationObserver.swift in Sources */,
587AD7C623421D7000E93A53 /* TunnelSettings.swift in Sources */,
+ 581503A324D6F1EC00C9C50E /* ChainedError+Logger.swift in Sources */,
58FD5BF024238EB300112C88 /* SKProduct+Formatting.swift in Sources */,
58561C99239A5D1500BD6B5E /* IPEndpoint.swift in Sources */,
58FD5BF22424F7D700112C88 /* UserInterfaceInteractionRestriction.swift in Sources */,
@@ -1034,18 +1073,21 @@
586AA296234B696B00502875 /* WireguardAssociatedAddresses.swift in Sources */,
58BA692F23E99F5B009DC256 /* Locking.swift in Sources */,
58B8743B22B788D200015324 /* PacketTunnelSettingsGenerator.swift in Sources */,
- 5860F1EB23AA4CF300CEA666 /* Logging.swift in Sources */,
5860F1C223A785C600CEA666 /* WireguardDevice.swift in Sources */,
580EE21624B3231200F9D8A1 /* OperationBlockObserver.swift in Sources */,
58CC40F024A602780019D96E /* ObserverList.swift in Sources */,
58C6B35522BB87C4003C19AD /* WireguardPrivateKey.swift in Sources */,
+ 581503A724D6F4AE00C9C50E /* Logging.swift in Sources */,
58FAEE0424533AC000CB0F5B /* KeychainClass.swift in Sources */,
58AEEF6C2344A49D00C9BBD5 /* TunnelSettingsManager.swift in Sources */,
58C6B35F22BBBFE3003C19AD /* Data+HexCoding.swift in Sources */,
+ 581503A424D6F1EC00C9C50E /* ChainedError+Logger.swift in Sources */,
+ 5815039824D6ECAE00C9C50E /* CustomFormatLogHandler.swift in Sources */,
5840250522B11AB700E4CFEC /* MullvadEndpoint.swift in Sources */,
58BFA5C722A7C97F00A6173D /* RelayCache.swift in Sources */,
580EE21024B322E700F9D8A1 /* TransformOperation.swift in Sources */,
58906DE02445C7A5002F0673 /* NEProviderStopReason+Debug.swift in Sources */,
+ 5815039E24D6ECE600C9C50E /* TextFileOutputStream.swift in Sources */,
584E96BD240FD4DA00D3334F /* Location.swift in Sources */,
58FAEDF8245088E100CB0F5B /* Keychain.swift in Sources */,
58C6B36122C0EC82003C19AD /* AnyIPEndpoint+DNS64.swift in Sources */,
@@ -1057,6 +1099,7 @@
580EE20D24B3225F00F9D8A1 /* DelayOperation.swift in Sources */,
588534BF246193D90018B744 /* AutomaticKeyRotationManager.swift in Sources */,
58781CCE22AE8918009B9D8E /* RelayConstraints.swift in Sources */,
+ 581503A024D6F01E00C9C50E /* LogRotation.swift in Sources */,
58781CD522AFBA39009B9D8E /* RelaySelector.swift in Sources */,
580EE21C24B3236900F9D8A1 /* InputOperation.swift in Sources */,
580EE22224B3240100F9D8A1 /* TransformOperationObserver.swift in Sources */,
@@ -1515,6 +1558,14 @@
/* End XCConfigurationList section */
/* Begin XCRemoteSwiftPackageReference section */
+ 585834F624D2BC1F00A8AF56 /* XCRemoteSwiftPackageReference "swift-log" */ = {
+ isa = XCRemoteSwiftPackageReference;
+ repositoryURL = "https://github.com/apple/swift-log.git";
+ requirement = {
+ kind = exactVersion;
+ version = 1.4.0;
+ };
+ };
58F3C09E249BBF1E003E76BE /* XCRemoteSwiftPackageReference "DiffableDataSources" */ = {
isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/ra1028/DiffableDataSources.git";
@@ -1526,6 +1577,16 @@
/* End XCRemoteSwiftPackageReference section */
/* Begin XCSwiftPackageProductDependency section */
+ 585834F724D2BC1F00A8AF56 /* Logging */ = {
+ isa = XCSwiftPackageProductDependency;
+ package = 585834F624D2BC1F00A8AF56 /* XCRemoteSwiftPackageReference "swift-log" */;
+ productName = Logging;
+ };
+ 585834FB24D2BC9500A8AF56 /* Logging */ = {
+ isa = XCSwiftPackageProductDependency;
+ package = 585834F624D2BC1F00A8AF56 /* XCRemoteSwiftPackageReference "swift-log" */;
+ productName = Logging;
+ };
58F3C09F249BBF1E003E76BE /* DiffableDataSources */ = {
isa = XCSwiftPackageProductDependency;
package = 58F3C09E249BBF1E003E76BE /* XCRemoteSwiftPackageReference "DiffableDataSources" */;
diff --git a/ios/MullvadVPN.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/ios/MullvadVPN.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved
index 497878448d..e49461b65b 100644
--- a/ios/MullvadVPN.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved
+++ b/ios/MullvadVPN.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved
@@ -18,6 +18,15 @@
"revision": "14c66681e12a38b81045f44c6c29724a0d4b0e72",
"version": "1.1.5"
}
+ },
+ {
+ "package": "swift-log",
+ "repositoryURL": "https://github.com/apple/swift-log.git",
+ "state": {
+ "branch": null,
+ "revision": "173f567a2dfec11d74588eea82cecea555bdc0bc",
+ "version": "1.4.0"
+ }
}
]
},
diff --git a/ios/MullvadVPN/Account.swift b/ios/MullvadVPN/Account.swift
index 2dee095be1..3f96d9308b 100644
--- a/ios/MullvadVPN/Account.swift
+++ b/ios/MullvadVPN/Account.swift
@@ -9,7 +9,7 @@
import Foundation
import NetworkExtension
import StoreKit
-import os
+import Logging
/// A enum holding the `UserDefaults` string keys
private enum UserDefaultsKeys: String {
@@ -41,6 +41,8 @@ class Account {
/// A shared instance of `Account`
static let shared = Account()
+ private let logger = Logger(label: "Account")
+
/// Returns true if user agreed to terms of service, otherwise false
var isAgreedToTermsOfService: Bool {
return UserDefaults.standard.bool(forKey: UserDefaultsKeys.isAgreedToTermsOfService.rawValue)
@@ -169,7 +171,7 @@ class Account {
self.postExpiryUpdateNotification(newExpiry: response.expires)
case .failure(let error):
- error.logChain(message: "Failed to update account expiry")
+ self.logger.error(chainedError: error, message: "Failed to update account expiry")
}
}
diff --git a/ios/MullvadVPN/AccountViewController.swift b/ios/MullvadVPN/AccountViewController.swift
index 1c0ed4177c..5c81d561d4 100644
--- a/ios/MullvadVPN/AccountViewController.swift
+++ b/ios/MullvadVPN/AccountViewController.swift
@@ -8,7 +8,7 @@
import StoreKit
import UIKit
-import os
+import Logging
class AccountViewController: UIViewController, AppStorePaymentObserver {
@@ -24,6 +24,7 @@ class AccountViewController: UIViewController, AppStorePaymentObserver {
private var pendingPayment: SKPayment?
private let alertPresenter = AlertPresenter()
+ private let logger = Logger(label: "AccountViewController")
private lazy var purchaseButtonInteractionRestriction =
UserInterfaceInteractionRestriction { [weak self] (enableUserInteraction, _) in
@@ -236,7 +237,7 @@ class AccountViewController: UIViewController, AppStorePaymentObserver {
alertController.dismiss(animated: true) {
switch result {
case .failure(let error):
- error.logChain(message: "Failed to log out")
+ self.logger.error(chainedError: error, message: "Failed to log out")
let errorAlertController = UIAlertController(
title: NSLocalizedString("Failed to log out", comment: ""),
diff --git a/ios/MullvadVPN/AppDelegate.swift b/ios/MullvadVPN/AppDelegate.swift
index 16062c16b9..2ee783dad0 100644
--- a/ios/MullvadVPN/AppDelegate.swift
+++ b/ios/MullvadVPN/AppDelegate.swift
@@ -8,6 +8,7 @@
import UIKit
import StoreKit
+import Logging
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
@@ -21,6 +22,8 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
#endif
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
+ initLoggingSystem(bundleIdentifier: Bundle.main.bundleIdentifier!)
+
#if targetEnvironment(simulator)
SimulatorTunnelProvider.shared.delegate = simulatorTunnelProvider
#endif
diff --git a/ios/MullvadVPN/AppStorePaymentManager.swift b/ios/MullvadVPN/AppStorePaymentManager.swift
index 690c6bb1cd..ed8a1ad1f9 100644
--- a/ios/MullvadVPN/AppStorePaymentManager.swift
+++ b/ios/MullvadVPN/AppStorePaymentManager.swift
@@ -8,7 +8,7 @@
import Foundation
import StoreKit
-import os
+import Logging
enum AppStoreSubscription: String {
/// Thirty days non-renewable subscription
@@ -122,6 +122,8 @@ class AppStorePaymentManager: NSObject, SKPaymentTransactionObserver {
/// A shared instance of `AppStorePaymentManager`
static let shared = AppStorePaymentManager(queue: SKPaymentQueue.default())
+ private let logger = Logger(label: "AppStorePaymentManager")
+
private let operationQueue = OperationQueue()
private lazy var exclusivityController = ExclusivityController<ExlcusivityCategory>(operationQueue: operationQueue)
@@ -254,8 +256,7 @@ class AppStorePaymentManager: NSObject, SKPaymentTransactionObserver {
createApplePaymentOperation.addDidFinishBlockObserver { (operation, result) in
switch result {
case .success(let response):
- os_log(.info, "AppStore Receipt was processed. Time added: %{public}.2f, New expiry: %{private}s",
- response.timeAdded, "\(response.newExpiry)")
+ self.logger.info("AppStore Receipt was processed. Time added: \(response.timeAdded), New expiry: \(response.newExpiry)")
completionHandler(.success(response))
@@ -267,6 +268,7 @@ class AppStorePaymentManager: NSObject, SKPaymentTransactionObserver {
self.exclusivityController.addOperation(createApplePaymentOperation, categories: [.sendReceipt])
case .failure(let error):
+ self.logger.error(chainedError: error, message: "Failed to fetch the AppStore receipt")
completionHandler(.failure(.readReceipt(error)))
}
}
@@ -275,31 +277,28 @@ class AppStorePaymentManager: NSObject, SKPaymentTransactionObserver {
private func handleTransaction(_ transaction: SKPaymentTransaction) {
switch transaction.transactionState {
case .deferred:
- os_log(.debug, "Deferred %{public}s", transaction.payment.productIdentifier)
+ logger.info("Deferred \(transaction.payment.productIdentifier)")
case .failed:
- os_log(.debug, "Failed to purchase %{public}s: %{public}s",
- transaction.payment.productIdentifier,
- transaction.error?.localizedDescription ?? "No error")
+ logger.error("Failed to purchase \(transaction.payment.productIdentifier): \(transaction.error?.localizedDescription ?? "No error")")
didFailPurchase(transaction: transaction)
case .purchased:
- os_log(.debug, "Purchased %{public}s", transaction.payment.productIdentifier)
+ logger.info("Purchased \(transaction.payment.productIdentifier)")
didFinishOrRestorePurchase(transaction: transaction)
case .purchasing:
- os_log(.debug, "Purchasing %{public}s", transaction.payment.productIdentifier)
+ logger.info("Purchasing \(transaction.payment.productIdentifier)")
case .restored:
- os_log(.debug, "Restored %{public}s", transaction.payment.productIdentifier)
+ logger.info("Restored \(transaction.payment.productIdentifier)")
didFinishOrRestorePurchase(transaction: transaction)
@unknown default:
- os_log(.debug, "Unknown transactionState = %{public}d",
- transaction.transactionState.rawValue)
+ logger.warning("Unknown transactionState = \(transaction.transactionState.rawValue)")
}
}
@@ -354,7 +353,7 @@ class AppStorePaymentManager: NSObject, SKPaymentTransactionObserver {
}
case .failure(let error):
- error.logChain(message: "Failed to upload the AppStore receipt")
+ self.logger.error(chainedError: error, message: "Failed to upload the AppStore receipt")
self.observerList.forEach { (observer) in
observer.appStorePaymentManager(
diff --git a/ios/MullvadVPN/AutomaticKeyRotationManager.swift b/ios/MullvadVPN/AutomaticKeyRotationManager.swift
index b9f706d11d..79e435a2a6 100644
--- a/ios/MullvadVPN/AutomaticKeyRotationManager.swift
+++ b/ios/MullvadVPN/AutomaticKeyRotationManager.swift
@@ -7,7 +7,7 @@
//
import Foundation
-import os
+import Logging
/// A private key rotation retry interval on failure (in seconds)
private let kRetryIntervalOnFailure = 300
@@ -46,6 +46,8 @@ class AutomaticKeyRotationManager {
}
}
+ private let logger = Logger(label: "AutomaticKeyRotationManager")
+
private let rest = MullvadRest(session: URLSession(configuration: .ephemeral))
private let persistentKeychainReference: Data
@@ -89,7 +91,7 @@ class AutomaticKeyRotationManager {
dispatchQueue.async {
guard !self.isAutomaticRotationEnabled else { return }
- os_log(.default, log: tunnelProviderLog, "Start automatic key rotation")
+ self.logger.info("Start automatic key rotation")
self.isAutomaticRotationEnabled = true
self.performKeyRotation()
@@ -102,7 +104,7 @@ class AutomaticKeyRotationManager {
dispatchQueue.async {
guard self.isAutomaticRotationEnabled else { return }
- os_log(.default, log: tunnelProviderLog, "Stop automatic key rotation")
+ self.logger.info("Stop automatic key rotation")
self.isAutomaticRotationEnabled = false
@@ -211,7 +213,7 @@ class AutomaticKeyRotationManager {
switch result {
case .success(let event):
if event.isNew {
- os_log(.default, log: tunnelProviderLog, "Finished private key rotation")
+ logger.info("Finished private key rotation")
eventHandler?(event)
}
@@ -219,26 +221,20 @@ class AutomaticKeyRotationManager {
if let rotationDate = Self.nextRotation(creationDate: event.creationDate) {
let interval = rotationDate.timeIntervalSinceNow
- os_log(.default, log: tunnelProviderLog,
- "Next private key rotation on %{public}s", "\(rotationDate)")
+ logger.info("Next private key rotation on \(rotationDate)")
nextRotationTime = .now() + .seconds(Int(interval))
} else {
- os_log(.error, log: tunnelProviderLog,
- "Failed to compute the next private rotation date. Retry in %d seconds.")
+ logger.error("Failed to compute the next private rotation date. Retry in \(kRetryIntervalOnFailure) seconds.")
nextRotationTime = .now() + .seconds(kRetryIntervalOnFailure)
}
case .failure(.rest(.network(URLError.cancelled))):
- os_log(.default, log: tunnelProviderLog, "Key rotation was cancelled")
- break
+ logger.info("Key rotation was cancelled")
case .failure(let error):
- os_log(.error, log: tunnelProviderLog,
- "Failed to rotate the private key: %{public}s. Retry in %d seconds.",
- error.localizedDescription,
- kRetryIntervalOnFailure)
+ logger.error("Failed to rotate the private key. Retry in \(kRetryIntervalOnFailure) seconds. Error: \(error.displayChain())")
nextRotationTime = .now() + .seconds(kRetryIntervalOnFailure)
}
diff --git a/ios/MullvadVPN/ChainedError.swift b/ios/MullvadVPN/ChainedError.swift
index 71e0fff44d..cadad2609c 100644
--- a/ios/MullvadVPN/ChainedError.swift
+++ b/ios/MullvadVPN/ChainedError.swift
@@ -7,7 +7,6 @@
//
import Foundation
-import os
/// A protocol describing errors that can be chained together
protocol ChainedError: LocalizedError {
@@ -44,10 +43,6 @@ extension ChainedError {
return s
}
- func logChain(message: String? = nil, log: OSLog = .default) {
- os_log(.error, log: log, "%{public}s", displayChain(message: message))
- }
-
private func makeChainIterator() -> AnyIterator<Error> {
var current: Error? = self
return AnyIterator { () -> Error? in
diff --git a/ios/MullvadVPN/ConnectViewController.swift b/ios/MullvadVPN/ConnectViewController.swift
index 53e5fd47ab..16eafc26c9 100644
--- a/ios/MullvadVPN/ConnectViewController.swift
+++ b/ios/MullvadVPN/ConnectViewController.swift
@@ -8,7 +8,7 @@
import UIKit
import NetworkExtension
-import os
+import Logging
class ConnectViewController: UIViewController, RootContainment, TunnelObserver,
SelectLocationDelegate
@@ -19,6 +19,8 @@ class ConnectViewController: UIViewController, RootContainment, TunnelObserver,
@IBOutlet var connectionPanel: ConnectionPanelView!
@IBOutlet var buttonsStackView: UIStackView!
+ private let logger = Logger(label: "ConnectViewController")
+
private let connectButton = makeButton(style: .success)
private let selectLocationButton = makeButton(style: .translucentNeutral)
private lazy var selectLocationBlurView = Self.makeBlurButton(button: selectLocationButton)
@@ -95,13 +97,15 @@ class ConnectViewController: UIViewController, RootContainment, TunnelObserver,
TunnelManager.shared.setRelayConstraints(relayConstraints) { [weak self] (result) in
DispatchQueue.main.async {
+ guard let self = self else { return }
+
switch result {
case .success:
- os_log(.debug, "Updated relay constraints: %{public}s", "\(relayConstraints)")
- self?.connectTunnel()
+ self.logger.debug("Updated relay constraints: \(relayConstraints)")
+ self.connectTunnel()
case .failure(let error):
- os_log(.error, "Failed to update relay constraints: %{public}s", error.localizedDescription)
+ self.logger.error(chainedError: error, message: "Failed to update relay constraints")
}
}
}
@@ -214,7 +218,7 @@ class ConnectViewController: UIViewController, RootContainment, TunnelObserver,
break
case .failure(let error):
- error.logChain(message: "Failed to start the VPN tunnel")
+ self.logger.error(chainedError: error, message: "Failed to start the VPN tunnel")
let alertController = UIAlertController(
title: NSLocalizedString("Failed to start the VPN tunnel", comment: ""),
@@ -234,7 +238,7 @@ class ConnectViewController: UIViewController, RootContainment, TunnelObserver,
private func disconnectTunnel() {
TunnelManager.shared.stopTunnel { (result) in
if case .failure(let error) = result {
- error.logChain(message: "Failed to stop the VPN tunnel")
+ self.logger.error(chainedError: error, message: "Failed to stop the VPN tunnel")
let alertController = UIAlertController(
title: NSLocalizedString("Failed to stop the VPN tunnel", comment: ""),
diff --git a/ios/MullvadVPN/Logging/ChainedError+Logger.swift b/ios/MullvadVPN/Logging/ChainedError+Logger.swift
new file mode 100644
index 0000000000..a0f396767a
--- /dev/null
+++ b/ios/MullvadVPN/Logging/ChainedError+Logger.swift
@@ -0,0 +1,24 @@
+//
+// ChainedError+Logger.swift
+// MullvadVPN
+//
+// Created by pronebird on 02/08/2020.
+// Copyright © 2020 Mullvad VPN AB. All rights reserved.
+//
+
+import Foundation
+import Logging
+
+extension Logger {
+
+ func error<T: ChainedError>(chainedError: T,
+ message: @autoclosure () -> String? = nil,
+ metadata: @autoclosure () -> Logger.Metadata? = nil,
+ source: @autoclosure () -> String? = nil,
+ file: String = #file, function: String = #function, line: UInt = #line)
+ {
+ let s = Message(stringLiteral: chainedError.displayChain(message: message()))
+ log(level: .error, s, metadata: metadata(), source: source(), file: file, function: function, line: line)
+ }
+
+}
diff --git a/ios/MullvadVPN/Logging/CustomFormatLogHandler.swift b/ios/MullvadVPN/Logging/CustomFormatLogHandler.swift
new file mode 100644
index 0000000000..e8c93a7c42
--- /dev/null
+++ b/ios/MullvadVPN/Logging/CustomFormatLogHandler.swift
@@ -0,0 +1,68 @@
+//
+// CustomFormatLogHandler.swift
+// MullvadVPN
+//
+// Created by pronebird on 02/08/2020.
+// Copyright © 2020 Mullvad VPN AB. All rights reserved.
+//
+
+import Foundation
+import Logging
+
+struct CustomFormatLogHandler: LogHandler {
+ var metadata: Logger.Metadata = [:]
+ var logLevel: Logger.Level = .debug
+
+ private let label: String
+ private let streams: [TextOutputStream]
+
+ init(label: String, streams: [TextOutputStream]) {
+ self.label = label
+ self.streams = streams
+ }
+
+ subscript(metadataKey metadataKey: String) -> Logger.Metadata.Value? {
+ get {
+ return metadata[metadataKey]
+ }
+ set(newValue) {
+ metadata[metadataKey] = newValue
+ }
+ }
+
+ func log(level: Logger.Level,
+ message: Logger.Message,
+ metadata: Logger.Metadata?,
+ source: String,
+ file: String,
+ function: String,
+ line: UInt)
+ {
+ let mergedMetadata = self.metadata.merging(metadata ?? [:]) { (lhs, rhs) -> Logger.MetadataValue in
+ return rhs
+ }
+ let prettyMetadata = Self.formatMetadata(mergedMetadata)
+ let metadataOutput = prettyMetadata.isEmpty ? "" : " \(prettyMetadata)"
+ let formattedMessage = "[\(Self.timestamp())][\(self.label)][\(level)]\(metadataOutput) \(message)\n"
+
+ for var stream in streams {
+ stream.write(formattedMessage)
+ }
+ }
+
+ private static func formatMetadata(_ metadata: Logger.Metadata) -> String {
+ return metadata.map { "\($0)=\($1)" }.joined(separator: " ")
+ }
+
+ private static func timestamp() -> String {
+ var buffer = [Int8](repeating: 0, count: 255)
+ var timestamp = time(nil)
+ let localTime = localtime(&timestamp)
+ strftime(&buffer, buffer.count, "%Y-%m-%dT%H:%M:%S%z", localTime)
+ return buffer.withUnsafeBufferPointer {
+ $0.withMemoryRebound(to: CChar.self) {
+ String(cString: $0.baseAddress!)
+ }
+ }
+ }
+}
diff --git a/ios/MullvadVPN/Logging/LogRotation.swift b/ios/MullvadVPN/Logging/LogRotation.swift
new file mode 100644
index 0000000000..fdc66c20b6
--- /dev/null
+++ b/ios/MullvadVPN/Logging/LogRotation.swift
@@ -0,0 +1,59 @@
+//
+// LogRotation.swift
+// MullvadVPN
+//
+// Created by pronebird on 02/08/2020.
+// Copyright © 2020 Mullvad VPN AB. All rights reserved.
+//
+
+import Foundation
+
+enum LogRotation {
+
+ enum Error: ChainedError {
+ case noSourceLogFile
+ case moveSourceLogFile(Swift.Error)
+
+ var errorDescription: String? {
+ switch self {
+ case .noSourceLogFile:
+ return "Source log file does not exist"
+ case .moveSourceLogFile:
+ return "Failure to move the source log file to backup"
+ }
+ }
+ }
+
+ static func rotateLog(logsDirectory: URL, logFileName: String) -> Result<(), Error> {
+ let fileManager = FileManager.default
+ let source = logsDirectory.appendingPathComponent(logFileName)
+ let backup = source.deletingPathExtension().appendingPathExtension("old.log")
+
+ return Result { _ = try fileManager.replaceItemAt(backup, withItemAt: source) }
+ .mapError { (error) -> Error in
+ // FileManager returns a very obscure error chain so we need to traverse it to find
+ // the root cause of the error.
+ var errorCursor: Swift.Error? = error
+ let cocoaErrorIterator = AnyIterator { () -> CocoaError? in
+ if let cocoaError = errorCursor as? CocoaError {
+ errorCursor = cocoaError.underlying
+ return cocoaError
+ } else {
+ errorCursor = nil
+ return nil
+ }
+ }
+
+ while let fileError = cocoaErrorIterator.next() {
+ // .fileNoSuchFile is returned when both backup and source log files do not exist
+ // .fileReadNoSuchFile is returned when backup exists but source log file does not
+ if fileError.code == .fileNoSuchFile || fileError.code == .fileReadNoSuchFile,
+ fileError.url == source {
+ return .noSourceLogFile
+ }
+ }
+
+ return .moveSourceLogFile(error)
+ }
+ }
+}
diff --git a/ios/MullvadVPN/Logging/Logging.swift b/ios/MullvadVPN/Logging/Logging.swift
new file mode 100644
index 0000000000..e21c5a5b24
--- /dev/null
+++ b/ios/MullvadVPN/Logging/Logging.swift
@@ -0,0 +1,50 @@
+//
+// Logging.swift
+// MullvadVPN
+//
+// Created by pronebird on 02/08/2020.
+// Copyright © 2020 Mullvad VPN AB. All rights reserved.
+//
+
+import Foundation
+import Logging
+
+func initLoggingSystem(bundleIdentifier: String) {
+ let containerURL = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: ApplicationConfiguration.securityGroupIdentifier)!
+ let logsDirectoryURL = containerURL.appendingPathComponent("Logs", isDirectory: true)
+ let logFileName = "\(bundleIdentifier).log"
+ let logFileURL = logsDirectoryURL.appendingPathComponent(logFileName)
+
+ // Create Logs folder within container if it doesn't exist
+ try? FileManager.default.createDirectory(at: logsDirectoryURL, withIntermediateDirectories: false, attributes: nil)
+
+ // Rotate log
+ let logRotationResult = LogRotation.rotateLog(logsDirectory: logsDirectoryURL, logFileName: logFileName)
+
+ // Create an array of log output streams
+ var streams: [TextOutputStream] = []
+
+ #if DEBUG
+ // Add standard output logging in debug
+ streams.append(TextFileOutputStream.standardOutputStream())
+ #endif
+
+ // Create output stream to file
+ if let fileLogStream = TextFileOutputStream(fileURL: logFileURL, createFile: true) {
+ streams.append(fileLogStream)
+ }
+
+ // Configure Logging system
+ LoggingSystem.bootstrap { (label) -> LogHandler in
+ if streams.isEmpty {
+ return SwiftLogNoOpLogHandler()
+ } else {
+ return CustomFormatLogHandler(label: label, streams: streams)
+ }
+ }
+
+ if case .failure(let logRotationError) = logRotationResult {
+ Logger(label: "LogRotation")
+ .error(chainedError: logRotationError, message: "Failed to rotate log")
+ }
+}
diff --git a/ios/MullvadVPN/Logging/TextFileOutputStream.swift b/ios/MullvadVPN/Logging/TextFileOutputStream.swift
new file mode 100644
index 0000000000..006e79a6e1
--- /dev/null
+++ b/ios/MullvadVPN/Logging/TextFileOutputStream.swift
@@ -0,0 +1,61 @@
+//
+// TextFileOutputStream.swift
+// MullvadVPN
+//
+// Created by pronebird on 02/08/2020.
+// Copyright © 2020 Mullvad VPN AB. All rights reserved.
+//
+
+import Foundation
+
+class TextFileOutputStream: TextOutputStream {
+ private let writer: DispatchIO
+ private let encoding: String.Encoding
+ private let queue = DispatchQueue.global(qos: .utility)
+
+ class func standardOutputStream(encoding: String.Encoding = .utf8) -> TextFileOutputStream {
+ return TextFileOutputStream(fileDescriptor: FileHandle.standardOutput.fileDescriptor, encoding: encoding)
+ }
+
+ init(fileDescriptor: Int32, encoding: String.Encoding = .utf8) {
+ self.encoding = encoding
+ writer = DispatchIO(type: .stream, fileDescriptor: fileDescriptor, queue: queue) { (errno) in
+ if errno != 0 {
+ print("TextFileOutputStream: closed channel with error: \(errno)")
+ }
+ }
+ }
+
+ init?(fileURL: URL, createFile: Bool, filePermissions: mode_t = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH, encoding: String.Encoding = .utf8) {
+ var oflag: Int32 = O_WRONLY
+ var mode: mode_t = .zero
+ if createFile {
+ oflag |= O_CREAT
+ mode = filePermissions
+ }
+
+ let filePath = fileURL.path.utf8CString.map { $0 }
+ guard let writer = DispatchIO(type: .stream, path: filePath, oflag: oflag, mode: mode, queue: queue, cleanupHandler: { (errno) in
+ if errno != 0 {
+ print("TextFileOutputStream: closed channel with error: \(errno)")
+ }
+ }) else { return nil }
+
+ self.writer = writer
+ self.encoding = encoding
+ }
+
+ deinit {
+ writer.close()
+ }
+
+ func write(_ string: String) {
+ string.data(using: encoding)?.withUnsafeBytes { (bytes) in
+ writer.write(offset: .zero, data: DispatchData(bytes: bytes), queue: queue) { (done, data, errno) in
+ if errno != 0 {
+ print("TextFileOutputStream: write error: \(errno)")
+ }
+ }
+ }
+ }
+}
diff --git a/ios/MullvadVPN/LoginViewController.swift b/ios/MullvadVPN/LoginViewController.swift
index b6cb895389..9138e15bbb 100644
--- a/ios/MullvadVPN/LoginViewController.swift
+++ b/ios/MullvadVPN/LoginViewController.swift
@@ -7,7 +7,7 @@
//
import UIKit
-import os
+import Logging
private let kMinimumAccountTokenLength = 10
@@ -36,6 +36,8 @@ class LoginViewController: UIViewController, RootContainment {
@IBOutlet var statusImageView: UIImageView!
@IBOutlet var createAccountButton: AppButton!
+ private let logger = Logger(label: "LoginViewController")
+
private var loginState = LoginState.default {
didSet {
loginStateDidChange()
@@ -159,7 +161,7 @@ class LoginViewController: UIViewController, RootContainment {
self.endLogin(.success(.existingAccount))
case .failure(let error):
- error.logChain(message: "Failed to log in with existing account")
+ self.logger.error(chainedError: error, message: "Failed to log in with existing account")
self.endLogin(.failure(error))
}
@@ -179,7 +181,7 @@ class LoginViewController: UIViewController, RootContainment {
self.endLogin(.success(.newAccount))
case .failure(let error):
- error.logChain(message: "Failed to log in with new account")
+ self.logger.error(chainedError: error, message: "Failed to log in with new account")
self.endLogin(.failure(error))
}
diff --git a/ios/MullvadVPN/RelayCache.swift b/ios/MullvadVPN/RelayCache.swift
index bf15933187..802e278c14 100644
--- a/ios/MullvadVPN/RelayCache.swift
+++ b/ios/MullvadVPN/RelayCache.swift
@@ -7,7 +7,7 @@
//
import Foundation
-import os
+import Logging
/// Periodic update interval
private let kUpdateIntervalSeconds = 3600
@@ -66,6 +66,8 @@ private class AnyRelayCacheObserver: WeakObserverBox, RelayCacheObserver {
}
class RelayCache {
+ private let logger = Logger(label: "RelayCache")
+
/// Mullvad REST client
private let rest: MullvadRest
@@ -125,7 +127,7 @@ class RelayCache {
}
case .failure(let readError):
- readError.logChain(message: "Failed to read the relay cache")
+ self.logger.error(chainedError: readError, message: "Failed to read the relay cache")
if Self.shouldDownloadRelaysOnReadFailure(readError) {
self.scheduleRepeatingTimer(startTime: .now())
@@ -192,7 +194,7 @@ class RelayCache {
}
case .failure(let readError):
- readError.logChain(message: "Failed to read the relay cache")
+ self.logger.error(chainedError: readError, message: "Failed to read the relay cache")
if Self.shouldDownloadRelaysOnReadFailure(readError) {
self.downloadRelays()
@@ -211,14 +213,16 @@ class RelayCache {
switch result {
case .success(let cachedRelays):
- os_log(.default, "Downloaded %d relays", cachedRelays.relays.wireguard.relays.count)
+ let numRelays = cachedRelays.relays.wireguard.relays.count
+
+ self.logger.info("Downloaded \(numRelays) relays")
self.observerList.forEach { (observer) in
observer.relayCache(self, didUpdateCachedRelays: cachedRelays)
}
case .failure(let error):
- error.logChain(message: "Failed to update the relays")
+ self.logger.error(chainedError: error, message: "Failed to update the relays")
}
}
@@ -230,7 +234,7 @@ class RelayCache {
newDownloadTask.resume()
case .failure(let restError):
- restError.logChain(message: "Failed to create a REST request for updating relays", log: .default)
+ self.logger.error(chainedError: restError, message: "Failed to create a REST request for updating relays")
downloadTask = nil
}
}
diff --git a/ios/MullvadVPN/SelectLocationController.swift b/ios/MullvadVPN/SelectLocationController.swift
index d996421b20..44e8751919 100644
--- a/ios/MullvadVPN/SelectLocationController.swift
+++ b/ios/MullvadVPN/SelectLocationController.swift
@@ -8,7 +8,7 @@
import DiffableDataSources
import UIKit
-import os
+import Logging
private let kCellIdentifier = "Cell"
@@ -28,6 +28,7 @@ class SelectLocationController: UITableViewController, RelayCacheObserver {
}
}
+ private let logger = Logger(label: "SelectLocationController")
private var cachedRelays: CachedRelays?
private var relayConstraints: RelayConstraints?
private var expandedItems = [RelayLocation]()
@@ -114,7 +115,7 @@ class SelectLocationController: UITableViewController, RelayCacheObserver {
self.didReceiveCachedRelays(cachedRelays, relayConstraints: relayConstraints)
case .failure(let error):
- error.logChain()
+ self.logger.error(chainedError: error)
}
}
}
@@ -130,7 +131,7 @@ class SelectLocationController: UITableViewController, RelayCacheObserver {
self.didReceiveCachedRelays(cachedRelays, relayConstraints: relayConstraints)
case .failure(let error):
- error.logChain()
+ self.logger.error(chainedError: error)
}
completionHandler()
@@ -422,7 +423,8 @@ extension ServerRelaysResponse {
for (cityCode, relays) in relaysByCity {
guard let location = locations[cityCode] else {
- os_log(.info, "Location is not found: %{public}s", cityCode)
+ // TODO: log to file?
+ print("Location not found: \(cityCode)")
continue
}
diff --git a/ios/MullvadVPN/SimulatorTunnelProviderHost.swift b/ios/MullvadVPN/SimulatorTunnelProviderHost.swift
index 5b85acefa9..1e418c2d77 100644
--- a/ios/MullvadVPN/SimulatorTunnelProviderHost.swift
+++ b/ios/MullvadVPN/SimulatorTunnelProviderHost.swift
@@ -11,10 +11,12 @@
import Foundation
import Network
import NetworkExtension
+import Logging
class SimulatorTunnelProviderHost: SimulatorTunnelProviderDelegate {
private var connectionInfo: TunnelConnectionInfo?
+ private let logger = Logger(label: "SimulatorTunnelProviderHost")
func startTunnel(options: [String: Any]?, completionHandler: @escaping (Error?) -> Void) {
DispatchQueue.main.async {
@@ -51,10 +53,10 @@ class SimulatorTunnelProviderHost: SimulatorTunnelProviderDelegate {
case .success(let request):
switch request {
case .reloadTunnelSettings:
- Self.replyAppMessage(true, completionHandler: completionHandler)
+ self.replyAppMessage(true, completionHandler: completionHandler)
case .tunnelInformation:
- Self.replyAppMessage(self.connectionInfo, completionHandler: completionHandler)
+ self.replyAppMessage(self.connectionInfo, completionHandler: completionHandler)
}
case .failure:
@@ -63,14 +65,14 @@ class SimulatorTunnelProviderHost: SimulatorTunnelProviderDelegate {
}
}
- private static func replyAppMessage<T: Encodable>(_ response: T, completionHandler: ((Data?) -> Void)?)
+ private func replyAppMessage<T: Encodable>(_ response: T, completionHandler: ((Data?) -> Void)?)
{
switch PacketTunnelIpcHandler.encodeResponse(response: response) {
case .success(let data):
completionHandler?(data)
case .failure(let error):
- error.logChain()
+ self.logger.error(chainedError: error)
completionHandler?(nil)
}
}
diff --git a/ios/MullvadVPN/TunnelManager.swift b/ios/MullvadVPN/TunnelManager.swift
index f45daca22a..412fea9bf5 100644
--- a/ios/MullvadVPN/TunnelManager.swift
+++ b/ios/MullvadVPN/TunnelManager.swift
@@ -8,7 +8,7 @@
import Foundation
import NetworkExtension
-import os
+import Logging
enum MapConnectionStatusError: ChainedError {
/// A failure to perform the IPC request because the tunnel IPC is already deallocated
@@ -239,6 +239,7 @@ class TunnelManager {
// MARK: - Internal variables
+ private let logger = Logger(label: "TunnelManager")
private let dispatchQueue = DispatchQueue(label: "net.mullvad.MullvadVPN.TunnelManager")
private let rest = MullvadRest(session: URLSession(configuration: .ephemeral))
@@ -266,7 +267,7 @@ class TunnelManager {
stateLock.withCriticalBlock {
guard _tunnelState != newValue else { return }
- os_log(.default, "Set tunnel state: %{public}s", String(reflecting: newValue))
+ logger.info("Set tunnel state: \(newValue)")
_tunnelState = newValue
@@ -315,7 +316,7 @@ class TunnelManager {
} else {
if let accountToken = self.accountToken {
// Migrate the tunnel settings if needed
- Self.migrateTunnelSettings(accountToken: accountToken)
+ self.migrateTunnelSettings(accountToken: accountToken)
// Load last known public key
self.loadPublicKey(accountToken: accountToken)
@@ -444,7 +445,7 @@ class TunnelManager {
tunnelIpc.reloadTunnelSettings { (result) in
if case .failure(let error) = result {
- error.logChain(message: "Failed to reconnect the tunnel")
+ self.logger.error(chainedError: error, message: "Failed to reconnect the tunnel")
}
finish()
}
@@ -525,7 +526,7 @@ class TunnelManager {
// Ignore Keychain errors because that normally means that the Keychain
// configuration was already removed and we shouldn't be blocking the
// user from logging out
- error.logChain(message: "Unset account error")
+ self.logger.error(chainedError: error, message: "Unset account error")
}
guard let tunnelProvider = self.tunnelProvider else {
@@ -563,10 +564,10 @@ class TunnelManager {
self.removeWireguardKeyFromServer(accountToken: accountToken, publicKey: publicKey) { (result) in
switch result {
case .success(let isRemoved):
- os_log(.debug, "Removed the WireGuard key from server: %{public}s", "\(isRemoved)")
+ self.logger.warning("Removed the WireGuard key from server: \(isRemoved)")
case .failure(let error):
- error.logChain(message: "Unset account error")
+ self.logger.error(chainedError: error, message: "Unset account error")
}
removeTunnel()
@@ -576,7 +577,7 @@ class TunnelManager {
// Ignore Keychain errors because that normally means that the Keychain
// configuration was already removed and we shouldn't be blocking the
// user from logging out
- error.logChain(message: "Unset account error")
+ self.logger.error(chainedError: error, message: "Unset account error")
removeTunnel()
}
@@ -662,7 +663,7 @@ class TunnelManager {
tunnelIpc.reloadTunnelSettings { (ipcResult) in
if case .failure(let error) = ipcResult {
// Ignore Packet Tunnel IPC errors but log them
- error.logChain(message: "Failed to IPC the tunnel to reload configuration")
+ self.logger.error(chainedError: error, message: "Failed to IPC the tunnel to reload configuration")
}
finish(.success(()))
@@ -701,7 +702,7 @@ class TunnelManager {
tunnelIpc.reloadTunnelSettings { (ipcResult) in
// Ignore Packet Tunnel IPC errors but log them
if case .failure(let error) = ipcResult {
- error.logChain(message: "Failed to reload tunnel settings")
+ self.logger.error(chainedError: error, message: "Failed to reload tunnel settings")
}
finish(.success(()))
@@ -811,7 +812,7 @@ class TunnelManager {
self.publicKey = entry.tunnelSettings.interface.privateKey.publicKey
case .failure(let error):
- error.logChain(message: "Failed to load the public key")
+ self.logger.error(chainedError: error, message: "Failed to load the public key")
self.publicKey = nil
}
@@ -912,7 +913,7 @@ class TunnelManager {
self.tunnelState = tunnelState
case .failure(let error):
- error.logChain(message: "Failed to map the tunnel state")
+ self.logger.error(chainedError: error, message: "Failed to map the tunnel state")
}
finish()
@@ -1080,20 +1081,20 @@ class TunnelManager {
}
}
- private class func migrateTunnelSettings(accountToken: String) {
+ private func migrateTunnelSettings(accountToken: String) {
let result = TunnelSettingsManager
.migrateKeychainEntry(searchTerm: .accountToken(accountToken))
switch result {
case .success(let migrated):
if migrated {
- os_log("Migrated Keychain tunnel configuration")
+ self.logger.info("Migrated Keychain tunnel configuration")
} else {
- os_log("Tunnel settings are up to date. No migration needed.")
+ self.logger.info("Tunnel settings are up to date. No migration needed.")
}
case .failure(let error):
- error.logChain(message: "Failed to migrate tunnel settings")
+ self.logger.error(chainedError: error, message: "Failed to migrate tunnel settings")
}
}
diff --git a/ios/MullvadVPN/WireguardKeysViewController.swift b/ios/MullvadVPN/WireguardKeysViewController.swift
index d7ed4dfe03..66cd8abf33 100644
--- a/ios/MullvadVPN/WireguardKeysViewController.swift
+++ b/ios/MullvadVPN/WireguardKeysViewController.swift
@@ -8,7 +8,7 @@
import Foundation
import UIKit
-import os
+import Logging
/// A UI refresh interval for the public key creation date (in seconds)
private let kCreationDateRefreshInterval = Int(60)
@@ -35,6 +35,7 @@ class WireguardKeysViewController: UIViewController, TunnelObserver {
private var copyToPasteboardWork: DispatchWorkItem?
private let alertPresenter = AlertPresenter()
+ private let logger = Logger(label: "WireguardKeysViewController")
private var state: WireguardKeysViewState = .default {
didSet {
@@ -207,7 +208,7 @@ class WireguardKeysViewController: UIViewController, TunnelObserver {
UIAlertAction(title: NSLocalizedString("OK", comment: ""), style: .cancel)
)
- error.logChain(message: "Failed to regenerate the private key")
+ self.logger.error(chainedError: error, message: "Failed to regenerate the private key")
self.alertPresenter.enqueue(alertController, presentingController: self)
}
diff --git a/ios/PacketTunnel/AnyIPEndpoint+DNS64.swift b/ios/PacketTunnel/AnyIPEndpoint+DNS64.swift
index 238db4b253..6d55db6612 100644
--- a/ios/PacketTunnel/AnyIPEndpoint+DNS64.swift
+++ b/ios/PacketTunnel/AnyIPEndpoint+DNS64.swift
@@ -8,7 +8,6 @@
import Foundation
import Network
-import os
extension AnyIPEndpoint {
diff --git a/ios/PacketTunnel/Logging.swift b/ios/PacketTunnel/Logging.swift
deleted file mode 100644
index 60d20d7c58..0000000000
--- a/ios/PacketTunnel/Logging.swift
+++ /dev/null
@@ -1,21 +0,0 @@
-//
-// Logging.swift
-// PacketTunnel
-//
-// Created by pronebird on 18/12/2019.
-// Copyright © 2019 Mullvad VPN AB. All rights reserved.
-//
-
-import Foundation
-import os
-
-private let kLogSubsystem = "net.mullvad.vpn.packet-tunnel"
-
-/// A Wireguard event log
-let wireguardLog = OSLog(subsystem: kLogSubsystem, category: "WireGuard")
-
-/// A general tunnel provider log
-let tunnelProviderLog = OSLog(subsystem: kLogSubsystem, category: "Tunnel Provider")
-
-/// A WireguardDevice log
-let wireguardDeviceLog = OSLog(subsystem: kLogSubsystem, category: "WireGuard Device")
diff --git a/ios/PacketTunnel/PacketTunnelProvider.swift b/ios/PacketTunnel/PacketTunnelProvider.swift
index 0e71c6aa14..e5249cfb20 100644
--- a/ios/PacketTunnel/PacketTunnelProvider.swift
+++ b/ios/PacketTunnel/PacketTunnelProvider.swift
@@ -9,7 +9,7 @@
import Foundation
import Network
import NetworkExtension
-import os
+import Logging
enum PacketTunnelProviderError: ChainedError {
/// Failure to read the relay cache
@@ -109,12 +109,16 @@ class PacketTunnelProvider: NEPacketTunnelProvider {
case exclusive
}
+ /// Tunnel provider logger
+ private let logger: Logger
+
/// Active wireguard device
private var wireguardDevice: WireguardDevice?
/// Active tunnel connection information
private var connectionInfo: TunnelConnectionInfo?
+ /// Internal queue
private let dispatchQueue = DispatchQueue(label: "net.mullvad.MullvadVPN.PacketTunnel", qos: .utility)
private lazy var operationQueue: OperationQueue = {
@@ -122,6 +126,7 @@ class PacketTunnelProvider: NEPacketTunnelProvider {
operationQueue.underlyingQueue = self.dispatchQueue
return operationQueue
}()
+
private lazy var exclusivityController: ExclusivityController<OperationCategory> = {
return ExclusivityController(operationQueue: self.operationQueue)
}()
@@ -129,25 +134,26 @@ class PacketTunnelProvider: NEPacketTunnelProvider {
private var keyRotationManager: AutomaticKeyRotationManager?
override init() {
- super.init()
+ initLoggingSystem(bundleIdentifier: Bundle.main.bundleIdentifier!)
+ WireguardDevice.setTunnelLogger(Logger(label: "WireGuard"))
- self.configureLogger()
+ logger = Logger(label: "PacketTunnelProvider")
}
// MARK: - Subclass
override func startTunnel(options: [String : NSObject]?, completionHandler: @escaping (Error?) -> Void) {
- os_log(.default, log: tunnelProviderLog, "Start the tunnel")
+ logger.info("Start the tunnel")
let operation = AsyncBlockOperation { (finish) in
self.doStartTunnel { (result) in
switch result {
case .success:
- os_log(.default, log: tunnelProviderLog, "Started the tunnel")
+ self.logger.info("Started the tunnel")
completionHandler(nil)
case .failure(let error):
- error.logChain(message: "Failed to start the tunnel", log: tunnelProviderLog)
+ self.logger.error(chainedError: error, message: "Failed to start the tunnel")
completionHandler(error)
}
@@ -159,15 +165,15 @@ class PacketTunnelProvider: NEPacketTunnelProvider {
}
override func stopTunnel(with reason: NEProviderStopReason, completionHandler: @escaping () -> Void) {
- os_log(.default, log: tunnelProviderLog, "Stop the tunnel. Reason: %{public}s", "\(reason)")
+ logger.info("Stop the tunnel. Reason: \(reason)")
let operation = AsyncBlockOperation { (finish) in
self.doStopTunnel { (result) in
switch result {
case .success:
- os_log(.default, log: tunnelProviderLog, "Stopped the tunnel")
+ self.logger.info("Stopped the tunnel")
case .failure(let error):
- error.logChain(message: "Failed to stop the tunnel", log: tunnelProviderLog)
+ self.logger.error(chainedError: error, message: "Failed to stop the tunnel")
}
completionHandler()
@@ -188,15 +194,15 @@ class PacketTunnelProvider: NEPacketTunnelProvider {
switch request {
case .reloadTunnelSettings:
self.reloadTunnelSettings { (result) in
- Self.replyAppMessage(result.map { true }, completionHandler: completionHandler)
+ self.replyAppMessage(result.map { true }, completionHandler: completionHandler)
}
case .tunnelInformation:
- Self.replyAppMessage(.success(self.connectionInfo), completionHandler: completionHandler)
+ self.replyAppMessage(.success(self.connectionInfo), completionHandler: completionHandler)
}
case .failure(let error):
- Self.replyAppMessage(Result<String, PacketTunnelProviderError>.failure(error), completionHandler: completionHandler)
+ self.replyAppMessage(Result<String, PacketTunnelProviderError>.failure(error), completionHandler: completionHandler)
}
}
}
@@ -225,7 +231,7 @@ class PacketTunnelProvider: NEPacketTunnelProvider {
return
}
- Self.startWireguardDevice(packetFlow: self.packetFlow, configuration: packetTunnelConfig.wireguardConfig) { (result) in
+ self.startWireguardDevice(packetFlow: self.packetFlow, configuration: packetTunnelConfig.wireguardConfig) { (result) in
self.dispatchQueue.async {
guard case .success(let device) = result else {
completionHandler(result.map { _ in () })
@@ -242,7 +248,7 @@ class PacketTunnelProvider: NEPacketTunnelProvider {
break
case .failure(let error):
- error.logChain(message: "Failed to reload tunnel settings", log: tunnelProviderLog)
+ self.logger.error(chainedError: error, message: "Failed to reload tunnel settings")
}
}
}
@@ -290,13 +296,13 @@ class PacketTunnelProvider: NEPacketTunnelProvider {
private func doReloadTunnelSettings(completionHandler: @escaping (Result<(), PacketTunnelProviderError>) -> Void) {
guard let device = self.wireguardDevice else {
- os_log(.default, log: tunnelProviderLog, "Ignore reloading tunnel settings. The WireguardDevice is not set yet.")
+ logger.warning("Ignore reloading tunnel settings. The WireguardDevice is not set yet.")
completionHandler(.success(()))
return
}
- os_log(.default, log: tunnelProviderLog, "Reload tunnel settings")
+ logger.info("Reload tunnel settings")
makePacketTunnelConfig { (result) in
guard case .success(let packetTunnelConfig) = result else {
@@ -331,13 +337,7 @@ class PacketTunnelProvider: NEPacketTunnelProvider {
// MARK: - Private
- private func configureLogger() {
- WireguardDevice.setLogger { (level, message) in
- os_log(level.osLogType, log: wireguardLog, "%{public}s", message)
- }
- }
-
- private static func replyAppMessage<T: Encodable>(
+ private func replyAppMessage<T: Encodable>(
_ result: Result<T, PacketTunnelProviderError>,
completionHandler: ((Data?) -> Void)?) {
let result = result.flatMap { (response) -> Result<Data, PacketTunnelProviderError> in
@@ -350,7 +350,7 @@ class PacketTunnelProvider: NEPacketTunnelProvider {
completionHandler?(data)
case .failure(let error):
- error.logChain(log: tunnelProviderLog)
+ self.logger.error(chainedError: error)
completionHandler?(nil)
}
}
@@ -363,8 +363,7 @@ class PacketTunnelProvider: NEPacketTunnelProvider {
location: selectorResult.location
)
- os_log(.default, log: tunnelProviderLog, "Tunnel connection info: %{public}s",
- selectorResult.relay.hostname)
+ logger.info("Tunnel connection info: \(selectorResult.relay.hostname)")
}
private func makePacketTunnelConfig(completionHandler: @escaping (Result<PacketTunnelConfiguration, PacketTunnelProviderError>) -> Void) {
@@ -393,18 +392,16 @@ class PacketTunnelProvider: NEPacketTunnelProvider {
tunnelSettings: packetTunnelConfig.tunnelSettings
)
- os_log(.default, log: tunnelProviderLog, "Updating network settings...")
+ logger.info("Updating network settings...")
setTunnelNetworkSettings(settingsGenerator.networkSettings()) { (error) in
self.dispatchQueue.async {
if let error = error {
- os_log(.error, log: tunnelProviderLog,
- "Cannot update network settings: %{public}s",
- error.localizedDescription)
+ self.logger.error("Cannot update network settings: \(error.localizedDescription)")
completionHandler(.failure(.setNetworkSettings(error)))
} else {
- os_log(.default, log: tunnelProviderLog, "Updated network settings")
+ self.logger.info("Updated network settings")
completionHandler(.success(()))
}
@@ -473,7 +470,7 @@ class PacketTunnelProvider: NEPacketTunnelProvider {
}
}
- private class func startWireguardDevice(packetFlow: NEPacketTunnelFlow, configuration: WireguardConfiguration, completionHandler: @escaping (Result<WireguardDevice, PacketTunnelProviderError>) -> Void) {
+ private func startWireguardDevice(packetFlow: NEPacketTunnelFlow, configuration: WireguardConfiguration, completionHandler: @escaping (Result<WireguardDevice, PacketTunnelProviderError>) -> Void) {
let result = WireguardDevice.fromPacketFlow(packetFlow)
guard case .success(let device) = result else {
@@ -483,7 +480,7 @@ class PacketTunnelProvider: NEPacketTunnelProvider {
let tunnelDeviceName = device.getInterfaceName() ?? "unknown"
- os_log(.default, log: tunnelProviderLog, "Tunnel interface is %{public}s", tunnelDeviceName)
+ logger.info("Tunnel interface is \(tunnelDeviceName)")
device.start(configuration: configuration) { (result) in
let result = result.map { device }
diff --git a/ios/PacketTunnel/PacketTunnelSettingsGenerator.swift b/ios/PacketTunnel/PacketTunnelSettingsGenerator.swift
index b91c7bc326..b4b118a0a0 100644
--- a/ios/PacketTunnel/PacketTunnelSettingsGenerator.swift
+++ b/ios/PacketTunnel/PacketTunnelSettingsGenerator.swift
@@ -9,7 +9,6 @@
import Foundation
import Network
import NetworkExtension
-import os
struct PacketTunnelSettingsGenerator {
let mullvadEndpoint: MullvadEndpoint
diff --git a/ios/PacketTunnel/WireguardDevice.swift b/ios/PacketTunnel/WireguardDevice.swift
index 86af84473c..71f8fe2e80 100644
--- a/ios/PacketTunnel/WireguardDevice.swift
+++ b/ios/PacketTunnel/WireguardDevice.swift
@@ -8,7 +8,7 @@
import Foundation
import NetworkExtension
-import os
+import Logging
/// A class describing the `wireguard-go` interactions
///
@@ -16,8 +16,6 @@ import os
/// This class is thread safe.
class WireguardDevice {
- typealias WireguardLogHandler = (WireguardLogLevel, String) -> Void
-
/// An error type describing the errors returned by `WireguardDevice`
enum Error: ChainedError {
/// A failure to obtain the tunnel device file descriptor
@@ -51,9 +49,12 @@ class WireguardDevice {
}
}
- /// A global Wireguard log handler
+ /// A global Wireguard logger
/// It should only be accessed from the `loggingQueue`
- private static var wireguardLogHandler: WireguardLogHandler?
+ private static var tunnelLogger: Logger?
+
+ /// A logger used by WireguardDevice
+ private let logger = Logger(label: "WireguardDevice")
/// A private queue used for Wireguard logging
private static let loggingQueue = DispatchQueue(
@@ -94,17 +95,17 @@ class WireguardDevice {
///
/// - Thread safety:
/// This function is thread safe
- class func setLogger(with handler: @escaping WireguardLogHandler) {
+ class func setTunnelLogger(_ logger: Logger) {
WireguardDevice.loggingQueue.async {
- WireguardDevice.wireguardLogHandler = handler
+ WireguardDevice.tunnelLogger = logger
}
wgSetLogger { (level, messagePtr) in
guard let message = messagePtr.map({ String(cString: $0) }) else { return }
- let logType = WireguardLogLevel(rawValue: level) ?? .debug
+ let logLevel = WireguardLogLevel(rawValue: level) ?? .debug
WireguardDevice.loggingQueue.async {
- WireguardDevice.wireguardLogHandler?(logType, message)
+ WireguardDevice.tunnelLogger?.log(level: logLevel.loggerLevel, Logger.Message(stringLiteral: message))
}
}
}
@@ -138,7 +139,7 @@ class WireguardDevice {
return
}
- let resolvedConfiguration = Self.resolveConfiguration(configuration)
+ let resolvedConfiguration = self.resolveConfiguration(configuration)
let handle = resolvedConfiguration
.uapiConfiguration()
.toRawWireguardConfigString()
@@ -176,7 +177,7 @@ class WireguardDevice {
func setConfiguration(_ newConfiguration: WireguardConfiguration, completionHandler: @escaping (Result<(), Error>) -> Void) {
workQueue.async {
if let handle = self.wireguardHandle {
- let resolvedConfiguration = Self.resolveConfiguration(newConfiguration)
+ let resolvedConfiguration = self.resolveConfiguration(newConfiguration)
let commands = resolvedConfiguration.uapiConfiguration()
Self.setWireguardConfig(handle: handle, commands: commands)
@@ -222,7 +223,7 @@ class WireguardDevice {
.withCString { wgSetConfig(handle, $0) }
}
- private class func resolveConfiguration(_ configuration: WireguardConfiguration)
+ private func resolveConfiguration(_ configuration: WireguardConfiguration)
-> WireguardConfiguration
{
return WireguardConfiguration(
@@ -232,11 +233,11 @@ class WireguardDevice {
)
}
- private class func resolvePeers(_ peers: [WireguardPeer]) -> [WireguardPeer] {
+ private func resolvePeers(_ peers: [WireguardPeer]) -> [WireguardPeer] {
var newPeers = [WireguardPeer]()
for peer in peers {
- switch self.resolvePeer(peer) {
+ switch resolvePeer(peer) {
case .success(let resolvedPeer):
newPeers.append(resolvedPeer)
case .failure(_):
@@ -248,24 +249,19 @@ class WireguardDevice {
return newPeers
}
- private class func resolvePeer(_ peer: WireguardPeer) -> Result<WireguardPeer, Error> {
+ private func resolvePeer(_ peer: WireguardPeer) -> Result<WireguardPeer, Error> {
switch peer.withReresolvedEndpoint() {
case .success(let resolvedPeer):
if "\(peer.endpoint.ip)" == "\(resolvedPeer.endpoint.ip)" {
- os_log(.debug, log: wireguardDeviceLog,
- "DNS64: mapped %{public}s to itself", "\(resolvedPeer.endpoint.ip)")
+ logger.debug("DNS64: mapped \(resolvedPeer.endpoint.ip) to itself")
} else {
- os_log(.debug, log: wireguardDeviceLog,
- "DNS64: mapped %{public}s to %{public}s",
- "\(peer.endpoint.ip)", "\(resolvedPeer.endpoint.ip)")
+ logger.debug("DNS64: mapped \(peer.endpoint.ip) to \(resolvedPeer.endpoint.ip)")
}
return .success(resolvedPeer)
case .failure(let error):
- os_log(.error, log: wireguardDeviceLog,
- "Failed to re-resolve the peer: %{public}s. Error: %{public}s",
- "\(peer.endpoint.ip)", error.localizedDescription)
+ logger.error("Failed to re-resolve the peer: \(peer.endpoint.ip). Error: \(error.localizedDescription)")
return .failure(.resolveEndpoint(peer.endpoint, error))
}
@@ -288,14 +284,11 @@ class WireguardDevice {
workQueue.async {
guard let handle = self.wireguardHandle else { return }
- os_log(.debug, log: wireguardDeviceLog,
- "Network change detected. Status: %{public}s, interfaces %{public}s.",
- String(describing: path.status),
- String(describing: path.availableInterfaces))
+ self.logger.debug("Network change detected. Status: \(path.status), interfaces \(path.availableInterfaces).")
// Re-resolve endpoints on network changes
if let currentConfiguration = self.configuration {
- let resolvedConfiguration = Self.resolveConfiguration(currentConfiguration)
+ let resolvedConfiguration = self.resolveConfiguration(currentConfiguration)
let commands = resolvedConfiguration.endpointUapiConfiguration()
Self.setWireguardConfig(handle: handle, commands: commands)
@@ -313,7 +306,7 @@ enum WireguardLogLevel: Int32 {
case info = 1
case error = 2
- var osLogType: OSLogType {
+ var loggerLevel: Logger.Level {
switch self {
case .debug:
return .debug