From b1d6c56a3edeef7a2f8eeaf106afc369e46decb5 Mon Sep 17 00:00:00 2001 From: problematicconsumer Date: Sat, 3 Feb 2024 21:21:46 +0330 Subject: [PATCH] Add ios command client --- ios/Network/CommandClient.swift | 160 ++++++++++++++++ ios/Network/Extension+Iterator.swift | 12 ++ ios/Runner.xcodeproj/project.pbxproj | 203 +++++++-------------- ios/Runner/Handlers/LogsEventHandler.swift | 15 +- ios/Runner/VPN/VPNManager.swift | 3 + 5 files changed, 246 insertions(+), 147 deletions(-) create mode 100644 ios/Network/CommandClient.swift create mode 100644 ios/Network/Extension+Iterator.swift diff --git a/ios/Network/CommandClient.swift b/ios/Network/CommandClient.swift new file mode 100644 index 00000000..4b2cac05 --- /dev/null +++ b/ios/Network/CommandClient.swift @@ -0,0 +1,160 @@ +import Foundation +import Libcore + +public class CommandClient: ObservableObject { + public enum ConnectionType { + case status + case groups + case log + case clashMode + } + + private let connectionType: ConnectionType + private let logMaxLines: Int + private var commandClient: LibboxCommandClient? + private var connectTask: Task? + + @Published public var isConnected: Bool + @Published public var status: LibboxStatusMessage? + @Published public var groups: [LibboxOutboundGroup]? + @Published public var logList: [String] + @Published public var clashModeList: [String] + @Published public var clashMode: String + + public init(_ connectionType: ConnectionType, logMaxLines: Int = 300) { + self.connectionType = connectionType + self.logMaxLines = logMaxLines + logList = [] + clashModeList = [] + clashMode = "" + isConnected = false + } + + public func connect() { + if isConnected { + return + } + if let connectTask { + connectTask.cancel() + } + connectTask = Task { + await connect0() + } + } + + public func disconnect() { + if let connectTask { + connectTask.cancel() + self.connectTask = nil + } + if let commandClient { + try? commandClient.disconnect() + self.commandClient = nil + } + } + + private nonisolated func connect0() async { + let clientOptions = LibboxCommandClientOptions() + switch connectionType { + case .status: + clientOptions.command = LibboxCommandStatus + case .groups: + clientOptions.command = LibboxCommandGroup + case .log: + clientOptions.command = LibboxCommandLog + case .clashMode: + clientOptions.command = LibboxCommandClashMode + } + clientOptions.statusInterval = Int64(2 * NSEC_PER_SEC) + let client = LibboxNewCommandClient(clientHandler(self), clientOptions)! + do { + for i in 0 ..< 10 { + try await Task.sleep(nanoseconds: UInt64(Double(100 + (i * 50)) * Double(NSEC_PER_MSEC))) + try Task.checkCancellation() + do { + try client.connect() + await MainActor.run { + commandClient = client + } + return + } catch {} + try Task.checkCancellation() + } + } catch { + try? client.disconnect() + } + } + + private class clientHandler: NSObject, LibboxCommandClientHandlerProtocol { + private let commandClient: CommandClient + + init(_ commandClient: CommandClient) { + self.commandClient = commandClient + } + + func connected() { + DispatchQueue.main.async { [self] in + if commandClient.connectionType == .log { + commandClient.logList = [] + } + commandClient.isConnected = true + } + } + + func disconnected(_: String?) { + DispatchQueue.main.async { [self] in + commandClient.isConnected = false + } + } + + func clearLog() { + DispatchQueue.main.async { [self] in + commandClient.logList.removeAll() + } + } + + func writeLog(_ message: String?) { + guard let message else { + return + } + DispatchQueue.main.async { [self] in + if commandClient.logList.count > commandClient.logMaxLines { + commandClient.logList.removeFirst() + } + commandClient.logList.append(message) + } + } + + func writeStatus(_ message: LibboxStatusMessage?) { + DispatchQueue.main.async { [self] in + commandClient.status = message + } + } + + func writeGroups(_ groups: LibboxOutboundGroupIteratorProtocol?) { + guard let groups else { + return + } + var newGroups: [LibboxOutboundGroup] = [] + while groups.hasNext() { + newGroups.append(groups.next()!) + } + DispatchQueue.main.async { [self] in + commandClient.groups = newGroups + } + } + + func initializeClashMode(_ modeList: LibboxStringIteratorProtocol?, currentMode: String?) { + DispatchQueue.main.async { [self] in + commandClient.clashModeList = modeList!.toArray() + commandClient.clashMode = currentMode! + } + } + + func updateClashMode(_ newMode: String?) { + DispatchQueue.main.async { [self] in + commandClient.clashMode = newMode! + } + } + } +} \ No newline at end of file diff --git a/ios/Network/Extension+Iterator.swift b/ios/Network/Extension+Iterator.swift new file mode 100644 index 00000000..b54611d0 --- /dev/null +++ b/ios/Network/Extension+Iterator.swift @@ -0,0 +1,12 @@ +import Foundation +import Libcore + +extension LibboxStringIteratorProtocol { + func toArray() -> [String] { + var array: [String] = [] + while hasNext() { + array.append(next()) + } + return array + } +} diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj index cd4282c9..22c5f1fb 100644 --- a/ios/Runner.xcodeproj/project.pbxproj +++ b/ios/Runner.xcodeproj/project.pbxproj @@ -34,7 +34,7 @@ 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; 331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C807B294A618700263BE5 /* RunnerTests.swift */; }; 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; - 54EA599BF9C050F2827533D5 /* Pods_RunnerTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DDA50BDF2E5E5DDA3995F24D /* Pods_RunnerTests.framework */; }; + 59E8864FB99B37076B22F32B /* Pods_RunnerTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 30560DB3EFDF5E86AAD00AB8 /* Pods_RunnerTests.framework */; }; 6836D3FD2B57FE4300A79D75 /* Libcore in Frameworks */ = {isa = PBXBuildFile; productRef = 6836D3FC2B57FE4300A79D75 /* Libcore */; }; 6836D4022B57FEFF00A79D75 /* Libcore in Frameworks */ = {isa = PBXBuildFile; productRef = 6836D4012B57FEFF00A79D75 /* Libcore */; }; 68885DD72B4EF33400D214BA /* NetworkExtension.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 03E392B72ADDA00E000ADF15 /* NetworkExtension.framework */; }; @@ -42,6 +42,8 @@ 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; + D78B64E92B6EB41900C5D800 /* Extension+Iterator.swift in Sources */ = {isa = PBXBuildFile; fileRef = D78B64E82B6EB41900C5D800 /* Extension+Iterator.swift */; }; + D7A729302B6E44F200FFFF41 /* CommandClient.swift in Sources */ = {isa = PBXBuildFile; fileRef = D7A7292F2B6E44F200FFFF41 /* CommandClient.swift */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -89,6 +91,7 @@ 032158B72ADDF8BF008D943B /* VPNManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VPNManager.swift; sourceTree = ""; }; 032158B92ADDFCC9008D943B /* TrafficReader.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TrafficReader.swift; sourceTree = ""; }; 032158BB2ADDFD09008D943B /* SingBox.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SingBox.swift; sourceTree = ""; }; + 0337C822BEDF7A95576475B3 /* Pods-RunnerTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.debug.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.debug.xcconfig"; sourceTree = ""; }; 03B516662AE6B93A00EA47E2 /* MethodHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MethodHandler.swift; sourceTree = ""; }; 03B516682AE7306B00EA47E2 /* StatusEventHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatusEventHandler.swift; sourceTree = ""; }; 03B5166A2AE7315E00EA47E2 /* AlertsEventHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AlertsEventHandler.swift; sourceTree = ""; }; @@ -109,6 +112,7 @@ 03E392CE2ADDEFC8000ADF15 /* FilePath.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FilePath.swift; sourceTree = ""; }; 03E392D12ADDF1F4000ADF15 /* ExtensionPlatformInterface.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExtensionPlatformInterface.swift; sourceTree = ""; }; 03E392D32ADDF262000ADF15 /* Extension+RunBlocking.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Extension+RunBlocking.swift"; sourceTree = ""; }; + 040FA3EB0673B72D60CC7145 /* Pods-RunnerTests.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.profile.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.profile.xcconfig"; sourceTree = ""; }; 0736954E2B1FEB3E007249BE /* mobile_scanner.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = mobile_scanner.xcframework; path = ../build/ios/framework/Release/mobile_scanner.xcframework; sourceTree = ""; }; 0736958A2B3AC96D007249BE /* Bundle+Properties.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Bundle+Properties.swift"; sourceTree = ""; }; 0736958C2B3B79E0007249BE /* StatsEventHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatsEventHandler.swift; sourceTree = ""; }; @@ -138,9 +142,9 @@ 07A63A9F2B1E72FC00CAFA4D /* path_provider_foundation.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = path_provider_foundation.xcframework; path = ../build/ios/framework/release/path_provider_foundation.xcframework; sourceTree = ""; }; 07A63AA02B1E72FC00CAFA4D /* shared_preferences_foundation.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = shared_preferences_foundation.xcframework; path = ../build/ios/framework/release/shared_preferences_foundation.xcframework; sourceTree = ""; }; 07A63AA12B1E72FC00CAFA4D /* Sentry.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = Sentry.xcframework; path = ../build/ios/framework/release/Sentry.xcframework; sourceTree = ""; }; - 0F7E04B7207513677AF77112 /* Pods-RunnerTests.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.profile.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.profile.xcconfig"; sourceTree = ""; }; 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; + 30560DB3EFDF5E86AAD00AB8 /* Pods_RunnerTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RunnerTests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 331C807B294A618700263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = ""; }; 331C8081294A63A400263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; @@ -151,7 +155,7 @@ 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; 7CA62594950187FCFE36B54C /* Pods-Runner-SingBoxPacketTunnel.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner-SingBoxPacketTunnel.debug.xcconfig"; path = "Target Support Files/Pods-Runner-SingBoxPacketTunnel/Pods-Runner-SingBoxPacketTunnel.debug.xcconfig"; sourceTree = ""; }; - 7E8B7AF73AD416B8FAA5E9B0 /* Pods-RunnerTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.debug.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.debug.xcconfig"; sourceTree = ""; }; + 808A94F72872B54716770416 /* Pods-RunnerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.release.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.release.xcconfig"; sourceTree = ""; }; 90E93DE403BDFA627F3AA51E /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; @@ -160,10 +164,10 @@ 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 9A37A927A1A9458918B3C12A /* Pods-RunnerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.release.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.release.xcconfig"; sourceTree = ""; }; 9AC67B4DCF829F5B6F63AA7D /* Pods-Runner-SingBoxPacketTunnel.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner-SingBoxPacketTunnel.release.xcconfig"; path = "Target Support Files/Pods-Runner-SingBoxPacketTunnel/Pods-Runner-SingBoxPacketTunnel.release.xcconfig"; sourceTree = ""; }; C20A211B58CE31B2738D133C /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; - DDA50BDF2E5E5DDA3995F24D /* Pods_RunnerTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RunnerTests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + D78B64E82B6EB41900C5D800 /* Extension+Iterator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Extension+Iterator.swift"; sourceTree = ""; }; + D7A7292F2B6E44F200FFFF41 /* CommandClient.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CommandClient.swift; sourceTree = ""; }; F3FFE1D9C2D5629FACC123EE /* Pods-Runner-SingBoxPacketTunnel.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner-SingBoxPacketTunnel.profile.xcconfig"; path = "Target Support Files/Pods-Runner-SingBoxPacketTunnel/Pods-Runner-SingBoxPacketTunnel.profile.xcconfig"; sourceTree = ""; }; /* End PBXFileReference section */ @@ -181,7 +185,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 54EA599BF9C050F2827533D5 /* Pods_RunnerTests.framework in Frameworks */, + 59E8864FB99B37076B22F32B /* Pods_RunnerTests.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -276,12 +280,12 @@ 574F12C7748958784380337F /* Pods-Runner.debug.xcconfig */, 90E93DE403BDFA627F3AA51E /* Pods-Runner.release.xcconfig */, C20A211B58CE31B2738D133C /* Pods-Runner.profile.xcconfig */, - 7E8B7AF73AD416B8FAA5E9B0 /* Pods-RunnerTests.debug.xcconfig */, - 9A37A927A1A9458918B3C12A /* Pods-RunnerTests.release.xcconfig */, - 0F7E04B7207513677AF77112 /* Pods-RunnerTests.profile.xcconfig */, 7CA62594950187FCFE36B54C /* Pods-Runner-SingBoxPacketTunnel.debug.xcconfig */, 9AC67B4DCF829F5B6F63AA7D /* Pods-Runner-SingBoxPacketTunnel.release.xcconfig */, F3FFE1D9C2D5629FACC123EE /* Pods-Runner-SingBoxPacketTunnel.profile.xcconfig */, + 0337C822BEDF7A95576475B3 /* Pods-RunnerTests.debug.xcconfig */, + 808A94F72872B54716770416 /* Pods-RunnerTests.release.xcconfig */, + 040FA3EB0673B72D60CC7145 /* Pods-RunnerTests.profile.xcconfig */, ); path = Pods; sourceTree = ""; @@ -317,6 +321,7 @@ 97C146E51CF9000F007C117D = { isa = PBXGroup; children = ( + D7A7292E2B6E44D500FFFF41 /* Network */, 6836D3FF2B57FECF00A79D75 /* Local Packages */, 03E392CD2ADDE103000ADF15 /* Shared */, 9740EEB11CF90186004384FC /* Flutter */, @@ -388,12 +393,21 @@ 07A63A842B1E72AE00CAFA4D /* App.xcframework */, 07A63A832B1E728C00CAFA4D /* Release */, 60F1D4AAC33ACF5C8307310D /* Pods_Runner.framework */, - DDA50BDF2E5E5DDA3995F24D /* Pods_RunnerTests.framework */, 03E392B72ADDA00E000ADF15 /* NetworkExtension.framework */, + 30560DB3EFDF5E86AAD00AB8 /* Pods_RunnerTests.framework */, ); name = Frameworks; sourceTree = ""; }; + D7A7292E2B6E44D500FFFF41 /* Network */ = { + isa = PBXGroup; + children = ( + D7A7292F2B6E44F200FFFF41 /* CommandClient.swift */, + D78B64E82B6EB41900C5D800 /* Extension+Iterator.swift */, + ); + path = Network; + sourceTree = ""; + }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ @@ -424,7 +438,7 @@ isa = PBXNativeTarget; buildConfigurationList = 331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */; buildPhases = ( - F63DAC79B8A3B6681959DBC1 /* [CP] Check Pods Manifest.lock */, + 2058E420D1A8B6F0E5E03873 /* [CP] Check Pods Manifest.lock */, 331C807D294A63A400263BE5 /* Sources */, 331C807F294A63A400263BE5 /* Resources */, 531FE8242BCD501C24C8E9FA /* Frameworks */, @@ -546,6 +560,28 @@ /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ + 2058E420D1A8B6F0E5E03873 /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-RunnerTests-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { isa = PBXShellScriptBuildPhase; alwaysOutOfDate = 1; @@ -599,28 +635,6 @@ shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; showEnvVarsInLog = 0; }; - F63DAC79B8A3B6681959DBC1 /* [CP] Check Pods Manifest.lock */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - ); - inputPaths = ( - "${PODS_PODFILE_DIR_PATH}/Podfile.lock", - "${PODS_ROOT}/Manifest.lock", - ); - name = "[CP] Check Pods Manifest.lock"; - outputFileListPaths = ( - ); - outputPaths = ( - "$(DERIVED_FILE_DIR)/Pods-RunnerTests-checkManifestLockResult.txt", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; - showEnvVarsInLog = 0; - }; FBEFD3291AEA65EDE2F5AEF6 /* [CP] Embed Pods Frameworks */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; @@ -673,12 +687,14 @@ 03B516772AE7634400EA47E2 /* Logger.swift in Sources */, 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */, 03B516712AE74CCD00EA47E2 /* VPNConfig.swift in Sources */, + D78B64E92B6EB41900C5D800 /* Extension+Iterator.swift in Sources */, 03B5166B2AE7315E00EA47E2 /* AlertsEventHandler.swift in Sources */, 0736958B2B3AC96D007249BE /* Bundle+Properties.swift in Sources */, 0736958D2B3B79E0007249BE /* StatsEventHandler.swift in Sources */, 03B516692AE7306B00EA47E2 /* StatusEventHandler.swift in Sources */, 032158B82ADDF8BF008D943B /* VPNManager.swift in Sources */, 0736958F2B3B8048007249BE /* PlatformMethodHandler.swift in Sources */, + D7A729302B6E44F200FFFF41 /* CommandClient.swift in Sources */, 03B516672AE6B93A00EA47E2 /* MethodHandler.swift in Sources */, 03B5166D2AE7325500EA47E2 /* LogsEventHandler.swift in Sources */, 03E392D02ADDF1BD000ADF15 /* FilePath.swift in Sources */, @@ -800,6 +816,8 @@ INFOPLIST_KEY_NSHumanReadableCopyright = ""; IPHONEOS_DEPLOYMENT_TARGET = 15.0; LD_RUNPATH_SEARCH_PATHS = ( + "$(SDKROOT)/usr/lib/swift", + "$(TOOLCHAIN_DIR)/usr/lib/swift-5.5/$(PLATFORM_NAME)", "$(inherited)", "@executable_path/Frameworks", "@executable_path/../../Frameworks", @@ -847,6 +865,8 @@ INFOPLIST_KEY_NSHumanReadableCopyright = ""; IPHONEOS_DEPLOYMENT_TARGET = 15.0; LD_RUNPATH_SEARCH_PATHS = ( + "$(SDKROOT)/usr/lib/swift", + "$(TOOLCHAIN_DIR)/usr/lib/swift-5.5/$(PLATFORM_NAME)", "$(inherited)", "@executable_path/Frameworks", "@executable_path/../../Frameworks", @@ -942,49 +962,18 @@ DEVELOPMENT_TEAM = 3JFTY5BP58; ENABLE_BITCODE = NO; "EXCLUDED_ARCHS[sdk=iphoneos*]" = armv7; - FRAMEWORK_SEARCH_PATHS = ( - "$(inherited)", - "\"${PODS_CONFIGURATION_BUILD_DIR}/GTMSessionFetcher\"", - "\"${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransport\"", - "\"${PODS_CONFIGURATION_BUILD_DIR}/GoogleToolboxForMac\"", - "\"${PODS_CONFIGURATION_BUILD_DIR}/GoogleUtilities\"", - "\"${PODS_CONFIGURATION_BUILD_DIR}/GoogleUtilitiesComponents\"", - "\"${PODS_CONFIGURATION_BUILD_DIR}/PromisesObjC\"", - "\"${PODS_CONFIGURATION_BUILD_DIR}/Sentry\"", - "\"${PODS_CONFIGURATION_BUILD_DIR}/SentryPrivate\"", - "\"${PODS_CONFIGURATION_BUILD_DIR}/cupertino_http\"", - "\"${PODS_CONFIGURATION_BUILD_DIR}/device_info_plus\"", - "\"${PODS_CONFIGURATION_BUILD_DIR}/flutter_native_splash\"", - "\"${PODS_CONFIGURATION_BUILD_DIR}/mobile_scanner\"", - "\"${PODS_CONFIGURATION_BUILD_DIR}/nanopb\"", - "\"${PODS_CONFIGURATION_BUILD_DIR}/package_info_plus\"", - "\"${PODS_CONFIGURATION_BUILD_DIR}/path_provider_foundation\"", - "\"${PODS_CONFIGURATION_BUILD_DIR}/protocol_handler\"", - "\"${PODS_CONFIGURATION_BUILD_DIR}/sentry_flutter\"", - "\"${PODS_CONFIGURATION_BUILD_DIR}/share_plus\"", - "\"${PODS_CONFIGURATION_BUILD_DIR}/shared_preferences_foundation\"", - "\"${PODS_CONFIGURATION_BUILD_DIR}/sqlite3\"", - "\"${PODS_CONFIGURATION_BUILD_DIR}/sqlite3_flutter_libs\"", - "\"${PODS_CONFIGURATION_BUILD_DIR}/url_launcher_ios\"", - "\"${PODS_ROOT}/MLImage/Frameworks\"", - "\"${PODS_ROOT}/MLKitBarcodeScanning/Frameworks\"", - "\"${PODS_ROOT}/MLKitCommon/Frameworks\"", - "\"${PODS_ROOT}/MLKitVision/Frameworks\"", - "$(PROJECT_DIR)/Flutter", - "$(PROJECT_DIR)/Frameworks/**", - "$(PROJECT_DIR)/..", - ); INFOPLIST_FILE = Runner/Info.plist; INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.utilities"; LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", "$(PROJECT_DIR)/build/ios/framework/$(CONFIGURATION)", "$(PROJECT_DIR)/../build/ios/framework/$(CONFIGURATION)", "$(SDKROOT)/usr/lib/swift", "$(TOOLCHAIN_DIR)/usr/lib/swift-5.5/$(PLATFORM_NAME)", + "$(inherited)", "@executable_path/Frameworks", + "@executable_path/../../Frameworks", "@executable_path/../libcore/", - "@executable_path/libcore", + "@executable_path/libcore/", ); ONLY_ACTIVE_ARCH = NO; OTHER_CPLUSPLUSFLAGS = ( @@ -1010,7 +999,7 @@ }; 331C8088294A63A400263BE5 /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 7E8B7AF73AD416B8FAA5E9B0 /* Pods-RunnerTests.debug.xcconfig */; + baseConfigurationReference = 0337C822BEDF7A95576475B3 /* Pods-RunnerTests.debug.xcconfig */; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; CODE_SIGN_STYLE = Automatic; @@ -1028,7 +1017,7 @@ }; 331C8089294A63A400263BE5 /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 9A37A927A1A9458918B3C12A /* Pods-RunnerTests.release.xcconfig */; + baseConfigurationReference = 808A94F72872B54716770416 /* Pods-RunnerTests.release.xcconfig */; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; CODE_SIGN_STYLE = Automatic; @@ -1044,7 +1033,7 @@ }; 331C808A294A63A400263BE5 /* Profile */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 0F7E04B7207513677AF77112 /* Pods-RunnerTests.profile.xcconfig */; + baseConfigurationReference = 040FA3EB0673B72D60CC7145 /* Pods-RunnerTests.profile.xcconfig */; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; CODE_SIGN_STYLE = Automatic; @@ -1194,49 +1183,18 @@ ENABLE_BITCODE = NO; "EXCLUDED_ARCHS[sdk=iphoneos*]" = armv7; "EXCLUDED_ARCHS[sdk=iphonesimulator*]" = "i386 arm64"; - FRAMEWORK_SEARCH_PATHS = ( - "$(inherited)", - "\"${PODS_CONFIGURATION_BUILD_DIR}/GTMSessionFetcher\"", - "\"${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransport\"", - "\"${PODS_CONFIGURATION_BUILD_DIR}/GoogleToolboxForMac\"", - "\"${PODS_CONFIGURATION_BUILD_DIR}/GoogleUtilities\"", - "\"${PODS_CONFIGURATION_BUILD_DIR}/GoogleUtilitiesComponents\"", - "\"${PODS_CONFIGURATION_BUILD_DIR}/PromisesObjC\"", - "\"${PODS_CONFIGURATION_BUILD_DIR}/Sentry\"", - "\"${PODS_CONFIGURATION_BUILD_DIR}/SentryPrivate\"", - "\"${PODS_CONFIGURATION_BUILD_DIR}/cupertino_http\"", - "\"${PODS_CONFIGURATION_BUILD_DIR}/device_info_plus\"", - "\"${PODS_CONFIGURATION_BUILD_DIR}/flutter_native_splash\"", - "\"${PODS_CONFIGURATION_BUILD_DIR}/mobile_scanner\"", - "\"${PODS_CONFIGURATION_BUILD_DIR}/nanopb\"", - "\"${PODS_CONFIGURATION_BUILD_DIR}/package_info_plus\"", - "\"${PODS_CONFIGURATION_BUILD_DIR}/path_provider_foundation\"", - "\"${PODS_CONFIGURATION_BUILD_DIR}/protocol_handler\"", - "\"${PODS_CONFIGURATION_BUILD_DIR}/sentry_flutter\"", - "\"${PODS_CONFIGURATION_BUILD_DIR}/share_plus\"", - "\"${PODS_CONFIGURATION_BUILD_DIR}/shared_preferences_foundation\"", - "\"${PODS_CONFIGURATION_BUILD_DIR}/sqlite3\"", - "\"${PODS_CONFIGURATION_BUILD_DIR}/sqlite3_flutter_libs\"", - "\"${PODS_CONFIGURATION_BUILD_DIR}/url_launcher_ios\"", - "\"${PODS_ROOT}/MLImage/Frameworks\"", - "\"${PODS_ROOT}/MLKitBarcodeScanning/Frameworks\"", - "\"${PODS_ROOT}/MLKitCommon/Frameworks\"", - "\"${PODS_ROOT}/MLKitVision/Frameworks\"", - "$(PROJECT_DIR)/Flutter", - "$(PROJECT_DIR)/Frameworks/**", - "$(PROJECT_DIR)/..", - ); INFOPLIST_FILE = Runner/Info.plist; INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.utilities"; LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", "$(PROJECT_DIR)/build/ios/framework/$(CONFIGURATION)", "$(PROJECT_DIR)/../build/ios/framework/$(CONFIGURATION)", "$(SDKROOT)/usr/lib/swift", "$(TOOLCHAIN_DIR)/usr/lib/swift-5.5/$(PLATFORM_NAME)", + "$(inherited)", "@executable_path/Frameworks", + "@executable_path/../../Frameworks", "@executable_path/../libcore/", - "@executable_path/libcore", + "@executable_path/libcore/", ); OTHER_CPLUSPLUSFLAGS = ( "-fcxx-modules", @@ -1273,49 +1231,18 @@ DEVELOPMENT_TEAM = 3JFTY5BP58; ENABLE_BITCODE = NO; "EXCLUDED_ARCHS[sdk=iphoneos*]" = armv7; - FRAMEWORK_SEARCH_PATHS = ( - "$(inherited)", - "\"${PODS_CONFIGURATION_BUILD_DIR}/GTMSessionFetcher\"", - "\"${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransport\"", - "\"${PODS_CONFIGURATION_BUILD_DIR}/GoogleToolboxForMac\"", - "\"${PODS_CONFIGURATION_BUILD_DIR}/GoogleUtilities\"", - "\"${PODS_CONFIGURATION_BUILD_DIR}/GoogleUtilitiesComponents\"", - "\"${PODS_CONFIGURATION_BUILD_DIR}/PromisesObjC\"", - "\"${PODS_CONFIGURATION_BUILD_DIR}/Sentry\"", - "\"${PODS_CONFIGURATION_BUILD_DIR}/SentryPrivate\"", - "\"${PODS_CONFIGURATION_BUILD_DIR}/cupertino_http\"", - "\"${PODS_CONFIGURATION_BUILD_DIR}/device_info_plus\"", - "\"${PODS_CONFIGURATION_BUILD_DIR}/flutter_native_splash\"", - "\"${PODS_CONFIGURATION_BUILD_DIR}/mobile_scanner\"", - "\"${PODS_CONFIGURATION_BUILD_DIR}/nanopb\"", - "\"${PODS_CONFIGURATION_BUILD_DIR}/package_info_plus\"", - "\"${PODS_CONFIGURATION_BUILD_DIR}/path_provider_foundation\"", - "\"${PODS_CONFIGURATION_BUILD_DIR}/protocol_handler\"", - "\"${PODS_CONFIGURATION_BUILD_DIR}/sentry_flutter\"", - "\"${PODS_CONFIGURATION_BUILD_DIR}/share_plus\"", - "\"${PODS_CONFIGURATION_BUILD_DIR}/shared_preferences_foundation\"", - "\"${PODS_CONFIGURATION_BUILD_DIR}/sqlite3\"", - "\"${PODS_CONFIGURATION_BUILD_DIR}/sqlite3_flutter_libs\"", - "\"${PODS_CONFIGURATION_BUILD_DIR}/url_launcher_ios\"", - "\"${PODS_ROOT}/MLImage/Frameworks\"", - "\"${PODS_ROOT}/MLKitBarcodeScanning/Frameworks\"", - "\"${PODS_ROOT}/MLKitCommon/Frameworks\"", - "\"${PODS_ROOT}/MLKitVision/Frameworks\"", - "$(PROJECT_DIR)/Flutter", - "$(PROJECT_DIR)/Frameworks/**", - "$(PROJECT_DIR)/..", - ); INFOPLIST_FILE = Runner/Info.plist; INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.utilities"; LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", "$(PROJECT_DIR)/build/ios/framework/$(CONFIGURATION)", "$(PROJECT_DIR)/../build/ios/framework/$(CONFIGURATION)", "$(SDKROOT)/usr/lib/swift", "$(TOOLCHAIN_DIR)/usr/lib/swift-5.5/$(PLATFORM_NAME)", + "$(inherited)", "@executable_path/Frameworks", + "@executable_path/../../Frameworks", "@executable_path/../libcore/", - "@executable_path/libcore", + "@executable_path/libcore/", ); ONLY_ACTIVE_ARCH = NO; OTHER_CPLUSPLUSFLAGS = ( diff --git a/ios/Runner/Handlers/LogsEventHandler.swift b/ios/Runner/Handlers/LogsEventHandler.swift index 11ee6396..368f6e66 100644 --- a/ios/Runner/Handlers/LogsEventHandler.swift +++ b/ios/Runner/Handlers/LogsEventHandler.swift @@ -1,16 +1,11 @@ -// -// LogsEventHandler.swift -// Runner -// -// Created by GFWFighter on 10/24/23. -// - import Foundation +import Combine public class LogsEventHandler: NSObject, FlutterPlugin, FlutterStreamHandler { static let name = "\(Bundle.main.serviceIdentifier)/service.logs" private var channel: FlutterEventChannel? + private var cancellable: AnyCancellable? public static func register(with registrar: FlutterPluginRegistrar) { let instance = LogsEventHandler() @@ -19,13 +14,15 @@ 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) + VPNManager.shared.logClient?.connect() + cancellable = VPNManager.shared.logClient?.$logList.sink { [events] logsList in + events(logsList) } return nil } public func onCancel(withArguments arguments: Any?) -> FlutterError? { + cancellable?.cancel() return nil } } diff --git a/ios/Runner/VPN/VPNManager.swift b/ios/Runner/VPN/VPNManager.swift index 1ade3291..0bb1d9c3 100644 --- a/ios/Runner/VPN/VPNManager.swift +++ b/ios/Runner/VPN/VPNManager.swift @@ -41,6 +41,7 @@ class VPNManager: ObservableObject { @Published private(set) var elapsedTime: TimeInterval = 0 @Published private(set) var logList: [String] = [] @Published private(set) var logCallback = false + private(set) var logClient: CommandClient? private var _connectTime: Date? private var connectTime: Date? { @@ -73,6 +74,8 @@ class VPNManager: ObservableObject { updateStats() elapsedTime = -1 * (connectTime?.timeIntervalSinceNow ?? 0) } + + logClient = CommandClient(.log) } deinit {