aboutsummaryrefslogtreecommitdiffstats
path: root/WireGuard/WireGuard
diff options
context:
space:
mode:
authorRoopesh Chander <roop@roopc.net>2019-04-30 15:38:38 +0530
committerJason A. Donenfeld <Jason@zx2c4.com>2019-05-25 13:24:01 +0200
commitf852b6f91931fa545968ee38c4b43e1233a6ac43 (patch)
treeabfc7e701be7ac4c9433b5099b61f13d0e62a564 /WireGuard/WireGuard
parentmacOS: Workaround for unresponsive main menu when launched from Xcode (diff)
downloadwireguard-apple-f852b6f91931fa545968ee38c4b43e1233a6ac43.tar.xz
wireguard-apple-f852b6f91931fa545968ee38c4b43e1233a6ac43.zip
iOS: Keep track of most-recently-activated tunnels
Signed-off-by: Roopesh Chander <roop@roopc.net>
Diffstat (limited to 'WireGuard/WireGuard')
-rw-r--r--WireGuard/WireGuard/Tunnel/TunnelsManager.swift19
-rw-r--r--WireGuard/WireGuard/UI/iOS/RecentTunnelsTracker.swift72
2 files changed, 90 insertions, 1 deletions
diff --git a/WireGuard/WireGuard/Tunnel/TunnelsManager.swift b/WireGuard/WireGuard/Tunnel/TunnelsManager.swift
index edf7690..460a9f6 100644
--- a/WireGuard/WireGuard/Tunnel/TunnelsManager.swift
+++ b/WireGuard/WireGuard/Tunnel/TunnelsManager.swift
@@ -46,7 +46,11 @@ class TunnelsManager {
var tunnelManagers = managers ?? []
var refs: Set<Data> = []
+ var tunnelNames: Set<String> = []
for (index, tunnelManager) in tunnelManagers.enumerated().reversed() {
+ if let tunnelName = tunnelManager.localizedDescription {
+ tunnelNames.insert(tunnelName)
+ }
guard let proto = tunnelManager.protocolConfiguration as? NETunnelProviderProtocol else { continue }
if proto.migrateConfigurationIfNeeded(called: tunnelManager.localizedDescription ?? "unknown") {
tunnelManager.saveToPreferences { _ in }
@@ -66,6 +70,7 @@ class TunnelsManager {
}
}
Keychain.deleteReferences(except: refs)
+ RecentTunnelsTracker.cleanupTunnels(except: tunnelNames)
completionHandler(.success(TunnelsManager(tunnelProviders: tunnelManagers)))
}
#endif
@@ -188,7 +193,8 @@ class TunnelsManager {
}
let tunnelProviderManager = tunnel.tunnelProvider
- let isNameChanged = tunnelName != tunnelProviderManager.localizedDescription
+ let oldName = tunnelProviderManager.localizedDescription ?? ""
+ let isNameChanged = tunnelName != oldName
if isNameChanged {
guard !tunnels.contains(where: { $0.name == tunnelName }) else {
completionHandler(TunnelsManagerError.tunnelAlreadyExistsWithThatName)
@@ -220,6 +226,9 @@ class TunnelsManager {
self.tunnels.sort { TunnelsManager.tunnelNameIsLessThan($0.name, $1.name) }
let newIndex = self.tunnels.firstIndex(of: tunnel)!
self.tunnelsListDelegate?.tunnelMoved(from: oldIndex, to: newIndex)
+ #if os(iOS)
+ RecentTunnelsTracker.handleTunnelRenamed(oldName: oldName, newName: tunnelName)
+ #endif
}
self.tunnelsListDelegate?.tunnelModified(at: self.tunnels.firstIndex(of: tunnel)!)
@@ -266,6 +275,10 @@ class TunnelsManager {
self.tunnelsListDelegate?.tunnelRemoved(at: index, tunnel: tunnel)
}
completionHandler(nil)
+
+ #if os(iOS)
+ RecentTunnelsTracker.handleTunnelRemoved(tunnelName: tunnel.name)
+ #endif
}
}
@@ -343,6 +356,10 @@ class TunnelsManager {
#else
tunnel.startActivation(activationDelegate: activationDelegate)
#endif
+
+ #if os(iOS)
+ RecentTunnelsTracker.handleTunnelActivated(tunnelName: tunnel.name)
+ #endif
}
func startDeactivation(of tunnel: TunnelContainer) {
diff --git a/WireGuard/WireGuard/UI/iOS/RecentTunnelsTracker.swift b/WireGuard/WireGuard/UI/iOS/RecentTunnelsTracker.swift
new file mode 100644
index 0000000..787a624
--- /dev/null
+++ b/WireGuard/WireGuard/UI/iOS/RecentTunnelsTracker.swift
@@ -0,0 +1,72 @@
+// SPDX-License-Identifier: MIT
+// Copyright © 2018-2019 WireGuard LLC. All Rights Reserved.
+
+import Foundation
+
+class RecentTunnelsTracker {
+
+ private static let keyRecentlyActivatedTunnelNames = "recentlyActivatedTunnelNames"
+ private static let maxNumberOfTunnels = 10
+
+ private static var userDefaults: UserDefaults? {
+ guard let appGroupId = FileManager.appGroupId else {
+ wg_log(.error, staticMessage: "Cannot obtain app group ID from bundle for tracking recently used tunnels")
+ return nil
+ }
+ guard let userDefaults = UserDefaults(suiteName: appGroupId) else {
+ wg_log(.error, staticMessage: "Cannot obtain shared user defaults for tracking recently used tunnels")
+ return nil
+ }
+ return userDefaults
+ }
+
+ static func handleTunnelActivated(tunnelName: String) {
+ guard let userDefaults = RecentTunnelsTracker.userDefaults else { return }
+ var recentTunnels = userDefaults.stringArray(forKey: keyRecentlyActivatedTunnelNames) ?? []
+ if let existingIndex = recentTunnels.firstIndex(of: tunnelName) {
+ recentTunnels.remove(at: existingIndex)
+ }
+ recentTunnels.insert(tunnelName, at: 0)
+ if recentTunnels.count > maxNumberOfTunnels {
+ recentTunnels.removeLast(recentTunnels.count - maxNumberOfTunnels)
+ }
+ userDefaults.set(recentTunnels, forKey: keyRecentlyActivatedTunnelNames)
+ }
+
+ static func handleTunnelRemoved(tunnelName: String) {
+ guard let userDefaults = RecentTunnelsTracker.userDefaults else { return }
+ var recentTunnels = userDefaults.stringArray(forKey: keyRecentlyActivatedTunnelNames) ?? []
+ if let existingIndex = recentTunnels.firstIndex(of: tunnelName) {
+ recentTunnels.remove(at: existingIndex)
+ userDefaults.set(recentTunnels, forKey: keyRecentlyActivatedTunnelNames)
+ }
+ }
+
+ static func handleTunnelRenamed(oldName: String, newName: String) {
+ guard let userDefaults = RecentTunnelsTracker.userDefaults else { return }
+ var recentTunnels = userDefaults.stringArray(forKey: keyRecentlyActivatedTunnelNames) ?? []
+ if let existingIndex = recentTunnels.firstIndex(of: oldName) {
+ recentTunnels[existingIndex] = newName
+ userDefaults.set(recentTunnels, forKey: keyRecentlyActivatedTunnelNames)
+ }
+ }
+
+ static func cleanupTunnels(except tunnelNamesToKeep: Set<String>) {
+ guard let userDefaults = RecentTunnelsTracker.userDefaults else { return }
+ var recentTunnels = userDefaults.stringArray(forKey: keyRecentlyActivatedTunnelNames) ?? []
+ let oldCount = recentTunnels.count
+ recentTunnels.removeAll { !tunnelNamesToKeep.contains($0) }
+ if oldCount != recentTunnels.count {
+ userDefaults.set(recentTunnels, forKey: keyRecentlyActivatedTunnelNames)
+ }
+ }
+
+ static func recentlyActivatedTunnelNames(limit: Int) -> [String] {
+ guard let userDefaults = RecentTunnelsTracker.userDefaults else { return [] }
+ var recentTunnels = userDefaults.stringArray(forKey: keyRecentlyActivatedTunnelNames) ?? []
+ if limit < recentTunnels.count {
+ recentTunnels.removeLast(recentTunnels.count - limit)
+ }
+ return recentTunnels
+ }
+}