From 27411da64f5170579d0d24a5fe483ca8962b3eb3 Mon Sep 17 00:00:00 2001 From: Amir Mohammadi Date: Sat, 20 Jan 2024 18:55:25 +0330 Subject: [PATCH] log handler base functionality + fix makefile ios-temp-prepare upgrading pub + remove tvOS from libcore local spm + --- Makefile | 2 +- ios/Local Packages/Package.swift | 3 +- ios/Runner/Handlers/LogsEventHandler.swift | 3 + ios/Runner/VPN/VPNManager.swift | 117 ++++++++++++++------- 4 files changed, 82 insertions(+), 43 deletions(-) diff --git a/Makefile b/Makefile index 76aacf69c..bcbb10b30 100644 --- a/Makefile +++ b/Makefile @@ -159,7 +159,7 @@ release: # Create a new tag for release. ios-temp-prepare: flutter upgrade flutter clean - flutter pub upgrade + # flutter pub upgrade make prepare platform=ios # make get-geo-assets # make get diff --git a/ios/Local Packages/Package.swift b/ios/Local Packages/Package.swift index f12d83d95..2a4c3eb8b 100644 --- a/ios/Local Packages/Package.swift +++ b/ios/Local Packages/Package.swift @@ -7,8 +7,7 @@ let package = Package( name: "Libcore", platforms: [ // Minimum platform version - .iOS(.v13), - .tvOS(.v13) + .iOS(.v13) ], products: [ .library( diff --git a/ios/Runner/Handlers/LogsEventHandler.swift b/ios/Runner/Handlers/LogsEventHandler.swift index 85ab83eb9..11ee6396c 100644 --- a/ios/Runner/Handlers/LogsEventHandler.swift +++ b/ios/Runner/Handlers/LogsEventHandler.swift @@ -19,6 +19,9 @@ public class LogsEventHandler: NSObject, FlutterPlugin, FlutterStreamHandler { } public func onListen(withArguments arguments: Any?, eventSink events: @escaping FlutterEventSink) -> FlutterError? { + if VPNManager.shared.logCallback { + events(VPNManager.shared.logList) + } return nil } diff --git a/ios/Runner/VPN/VPNManager.swift b/ios/Runner/VPN/VPNManager.swift index a30b1ee16..1dfd8af06 100644 --- a/ios/Runner/VPN/VPNManager.swift +++ b/ios/Runner/VPN/VPNManager.swift @@ -39,6 +39,8 @@ class VPNManager: ObservableObject { @Published private(set) var upload: Int64 = 0 @Published private(set) var download: Int64 = 0 @Published private(set) var elapsedTime: TimeInterval = 0 + @Published private(set) var logList: [String] = [] + @Published private(set) var logCallback = false private var _connectTime: Date? private var connectTime: Date? { @@ -83,30 +85,42 @@ class VPNManager: ObservableObject { func setup() async throws { // guard !loaded else { return } loaded = true - try await loadVPNPreference() + do { + try await loadVPNPreference() + } catch { + onServiceWriteLog(message: error.localizedDescription) + } } private func loadVPNPreference() async throws { - let managers = try await NETunnelProviderManager.loadAllFromPreferences() - if let manager = managers.first { - self.manager = manager - return + do { + let managers = try await NETunnelProviderManager.loadAllFromPreferences() + if let manager = managers.first { + self.manager = manager + return + } + let newManager = NETunnelProviderManager() + let `protocol` = NETunnelProviderProtocol() + `protocol`.providerBundleIdentifier = "app.hiddify.com.SingBoxPacketTunnel" + `protocol`.serverAddress = "localhost" + newManager.protocolConfiguration = `protocol` + newManager.localizedDescription = "Hiddify" + try await newManager.saveToPreferences() + try await newManager.loadFromPreferences() + self.manager = newManager + } catch { + onServiceWriteLog(message: error.localizedDescription) } - let newManager = NETunnelProviderManager() - let `protocol` = NETunnelProviderProtocol() - `protocol`.providerBundleIdentifier = "app.hiddify.com.SingBoxPacketTunnel" - `protocol`.serverAddress = "localhost" - newManager.protocolConfiguration = `protocol` - newManager.localizedDescription = "Hiddify" - try await newManager.saveToPreferences() - try await newManager.loadFromPreferences() - self.manager = newManager } private func enableVPNManager() async throws { manager.isEnabled = true - try await manager.saveToPreferences() - try await manager.loadFromPreferences() + do { + try await manager.saveToPreferences() + try await manager.loadFromPreferences() + } catch { + onServiceWriteLog(message: error.localizedDescription) + } } @MainActor private func set(upload: Int64, download: Int64) { @@ -121,7 +135,7 @@ class VPNManager: ObservableObject { return false } for key: String in keys.allKeys as! [String] { - if (key == "tap" || key == "tun" || key == "ppp" || key == "ipsec" || key == "ipsec0" || key == "utun1" || key == "utun2") { + if key == "tap" || key == "tun" || key == "ppp" || key == "ipsec" || key == "ipsec0" { return true } else if key.starts(with: "utun") { return true @@ -138,11 +152,15 @@ class VPNManager: ObservableObject { $state.filter { $0 == .disconnected || $0 == .invalid }.first().sink { [weak self] _ in Task { [weak self] () in self?.manager = .shared() - let managers = try? await NETunnelProviderManager.loadAllFromPreferences() - for manager in managers ?? [] { - try? await manager.removeFromPreferences() + do { + let managers = try await NETunnelProviderManager.loadAllFromPreferences() + for manager in managers ?? [] { + try await manager.removeFromPreferences() + } + try await self?.loadVPNPreference() + } catch { + onServiceWriteLog(message: error.localizedDescription) } - try? await self?.loadVPNPreference() } }.store(in: &cancelBag) @@ -155,31 +173,39 @@ class VPNManager: ObservableObject { } guard state == .connected else { return } guard let connection = manager.connection as? NETunnelProviderSession else { return } - try? connection.sendProviderMessage("stats".data(using: .utf8)!) { [weak self] response in - guard - let response, - let response = String(data: response, encoding: .utf8) - else { return } - let responseComponents = response.components(separatedBy: ",") - guard - responseComponents.count == 2, - let upload = Int64(responseComponents[0]), - let download = Int64(responseComponents[1]) - else { return } - Task { [upload, download, weak self] () in - await self?.set(upload: upload, download: download) + do { + try connection.sendProviderMessage("stats".data(using: .utf8)!) { [weak self] response in + guard + let response, + let response = String(data: response, encoding: .utf8) + else { return } + let responseComponents = response.components(separatedBy: ",") + guard + responseComponents.count == 2, + let upload = Int64(responseComponents[0]), + let download = Int64(responseComponents[1]) + else { return } + Task { [upload, download, weak self] () in + await self?.set(upload: upload, download: download) + } } + } catch { + onServiceWriteLog(message: error.localizedDescription) } } func connect(with config: String, disableMemoryLimit: Bool = false) async throws { await set(upload: 0, download: 0) guard state == .disconnected else { return } - try await enableVPNManager() - try manager.connection.startVPNTunnel(options: [ - "Config": config as NSString, - "DisableMemoryLimit": (disableMemoryLimit ? "YES" : "NO") as NSString, - ]) + do { + try await enableVPNManager() + try manager.connection.startVPNTunnel(options: [ + "Config": config as NSString, + "DisableMemoryLimit": (disableMemoryLimit ? "YES" : "NO") as NSString, + ]) + } catch { + onServiceWriteLog(message: error.localizedDescription) + } connectTime = .now } @@ -188,5 +214,16 @@ class VPNManager: ObservableObject { manager.connection.stopVPNTunnel() } -} + func onServiceWriteLog(message: String) { + logCallback = true + if logList.count > 300 { + logList.removeFirst() + } + logList.append(message) + } + func onServiceResetLogs() { + logCallback = false + logList.removeAll() + } +}