From 74776e90c19f4164906454b303fe4e2b07d0755d Mon Sep 17 00:00:00 2001 From: hiddify <114227601+hiddify-com@users.noreply.github.com> Date: Tue, 24 Dec 2024 14:36:18 +0100 Subject: [PATCH] new: update the ios interface --- Makefile | 4 +- hiddify-core | 2 +- ios/HiddifyPacketTunnel/Logger.swift | 2 + .../PacketTunnelProvider.swift | 2 + .../SingBox/Extension+RunBlocking.swift | 2 +- .../SingBox/ExtensionPlatformInterface.swift | 23 ++- .../SingBox/ExtensionProvider.swift | 128 ++++++++------- ios/HiddifyPacketTunnel/SingBox/SingBox.swift | 1 + ios/HiddifyPacketTunnel/TrafficReader.swift | 3 + ios/Local Packages/Package.swift | 8 +- ios/Podfile.lock | 4 +- ios/Runner.xcodeproj/project.pbxproj | 12 +- ios/Runner/AppDelegate.swift | 2 +- .../Handlers/ActiveGroupsEventHandler.swift | 2 +- ios/Runner/Handlers/GroupsEventHandler.swift | 2 +- ios/Runner/Handlers/LogsEventHandler.swift | 2 +- ios/Runner/Handlers/MethodHandler.swift | 146 ++++++++++-------- .../Handlers/PlatformMethodHandler.swift | 4 +- ios/Runner/Handlers/StatsEventHandler.swift | 2 +- ios/Runner/VPN/VPNConfig.swift | 19 +++ ios/Runner/VPN/VPNManager.swift | 9 +- ios/Shared/CommandClient.swift | 29 ++-- .../core_interface/core_interface.dart | 4 + .../core_interface/core_interface_mobile.dart | 8 +- lib/hiddifycore/hiddify_core_service.dart | 20 +-- 25 files changed, 263 insertions(+), 177 deletions(-) diff --git a/Makefile b/Makefile index 4ebb07fe..043178bd 100644 --- a/Makefile +++ b/Makefile @@ -197,7 +197,7 @@ macos-libs: ios-libs: #not tested mkdir -p $(IOS_OUT) - rm -rf $(IOS_OUT)/Libcore.xcframework + rm -rf $(IOS_OUT)/HiddifyCore.xcframework curl -L $(CORE_URL)/$(CORE_NAME)-ios.tar.gz | tar xz -C "$(IOS_OUT)" get-geo-assets: @@ -224,7 +224,7 @@ build-macos-libs: build-ios-libs: rm -rf $(IOS_OUT)/HiddifyCore.xcframework make -C hiddify-core -f Makefile ios - mv $(BINDIR)/HiddifyCore.xcframework $(IOS_OUT)/Libcore.xcframework + mv $(BINDIR)/HiddifyCore.xcframework $(IOS_OUT)/HiddifyCore.xcframework release: # Create a new tag for release. @CORE_VERSION=$(core.version) bash -c ".github/change_version.sh " diff --git a/hiddify-core b/hiddify-core index 3d52467c..7dcd1cd5 160000 --- a/hiddify-core +++ b/hiddify-core @@ -1 +1 @@ -Subproject commit 3d52467c735070195ca3e448c9069f5226c5059f +Subproject commit 7dcd1cd527240325aec6a71278ed068bb321e3a9 diff --git a/ios/HiddifyPacketTunnel/Logger.swift b/ios/HiddifyPacketTunnel/Logger.swift index 99edbd5f..e723f1fa 100644 --- a/ios/HiddifyPacketTunnel/Logger.swift +++ b/ios/HiddifyPacketTunnel/Logger.swift @@ -26,10 +26,12 @@ class Logger { private var lock = NSLock() init(path: URL) { + NSLog("H?G1") url = path } func write(_ message: String) { + NSLog("H?G2") Logger.queue.async { [message, unowned self] () in lock.lock() defer { lock.unlock() } diff --git a/ios/HiddifyPacketTunnel/PacketTunnelProvider.swift b/ios/HiddifyPacketTunnel/PacketTunnelProvider.swift index 093e2ddb..f62364b9 100644 --- a/ios/HiddifyPacketTunnel/PacketTunnelProvider.swift +++ b/ios/HiddifyPacketTunnel/PacketTunnelProvider.swift @@ -16,6 +16,7 @@ class PacketTunnelProvider: ExtensionProvider { // var trafficReader: TrafficReader! override func startTunnel(options: [String : NSObject]?) async throws { + NSLog("H?C1") try await super.startTunnel(options: options) /*trafficReader = TrafficReader { [unowned self] traffic in trafficLock.lock() @@ -26,6 +27,7 @@ class PacketTunnelProvider: ExtensionProvider { } override func handleAppMessage(_ messageData: Data) async -> Data? { + NSLog("H?C2") let message = String(data: messageData, encoding: .utf8) switch message { case "stats": diff --git a/ios/HiddifyPacketTunnel/SingBox/Extension+RunBlocking.swift b/ios/HiddifyPacketTunnel/SingBox/Extension+RunBlocking.swift index b6c8685d..1cc6ee52 100644 --- a/ios/HiddifyPacketTunnel/SingBox/Extension+RunBlocking.swift +++ b/ios/HiddifyPacketTunnel/SingBox/Extension+RunBlocking.swift @@ -6,7 +6,7 @@ // import Foundation -import Libcore +import HiddifyCore import NetworkExtension func runBlocking(_ block: @escaping () async -> T) -> T { diff --git a/ios/HiddifyPacketTunnel/SingBox/ExtensionPlatformInterface.swift b/ios/HiddifyPacketTunnel/SingBox/ExtensionPlatformInterface.swift index 4ec909f9..b5a9992e 100644 --- a/ios/HiddifyPacketTunnel/SingBox/ExtensionPlatformInterface.swift +++ b/ios/HiddifyPacketTunnel/SingBox/ExtensionPlatformInterface.swift @@ -6,10 +6,17 @@ // import Foundation -import Libcore +import HiddifyCore import NetworkExtension public class ExtensionPlatformInterface: NSObject, LibboxPlatformInterfaceProtocol, LibboxCommandServerHandlerProtocol { + public func writeLog(_ message: String?) { + + } + + public func send(_ notification: LibboxNotification?) throws { + } + public func readWIFIState() -> LibboxWIFIState? { return nil; } @@ -22,12 +29,14 @@ public class ExtensionPlatformInterface: NSObject, LibboxPlatformInterfaceProtoc } public func openTun(_ options: LibboxTunOptionsProtocol?, ret0_: UnsafeMutablePointer?) throws { + NSLog("H?A1") try runBlocking { [self] in try await openTun0(options, ret0_) } } private func openTun0(_ options: LibboxTunOptionsProtocol?, _ ret0_: UnsafeMutablePointer?) async throws { + NSLog("H?A2") guard let options else { throw NSError(domain: "nil options", code: 0) } @@ -140,11 +149,11 @@ public class ExtensionPlatformInterface: NSObject, LibboxPlatformInterfaceProtoc false } - public func writeLog(_ message: String?) { - guard let message else { - return - } - tunnel.writeMessage(message) + func writeLogs(_ messageList: (any LibboxStringIteratorProtocol)?) { +// guard let message else { +// return +// } +// tunnel.writeMessage(message) } public func usePlatformDefaultInterfaceMonitor() -> Bool { @@ -230,10 +239,12 @@ public class ExtensionPlatformInterface: NSObject, LibboxPlatformInterfaceProtoc } public func postServiceClose() { + NSLog("H?A3") // TODO } func reset() { + NSLog("H?A4") networkSettings = nil } diff --git a/ios/HiddifyPacketTunnel/SingBox/ExtensionProvider.swift b/ios/HiddifyPacketTunnel/SingBox/ExtensionProvider.swift index 85ab3102..cce0f2b5 100644 --- a/ios/HiddifyPacketTunnel/SingBox/ExtensionProvider.swift +++ b/ios/HiddifyPacketTunnel/SingBox/ExtensionProvider.swift @@ -6,33 +6,37 @@ // import Foundation -import Libcore +import HiddifyCore import NetworkExtension open class ExtensionProvider: NEPacketTunnelProvider { public static let errorFile = FilePath.workingDirectory.appendingPathComponent("network_extension_error") - private var commandServer: LibboxCommandServer! - private var boxService: LibboxBoxService! +// private var commandServer: LibboxCommandServer! +// private var boxService: LibboxBoxService! private var systemProxyAvailable = false private var systemProxyEnabled = false private var platformInterface: ExtensionPlatformInterface! private var config: String! override open func startTunnel(options: [String: NSObject]?) async throws { + NSLog("H?1") + writeFatalError("(packet-tunnel) starting") + try? FileManager.default.removeItem(at: ExtensionProvider.errorFile) try? FileManager.default.removeItem(at: FilePath.workingDirectory.appendingPathComponent("TestLog")) let disableMemoryLimit = (options?["DisableMemoryLimit"] as? NSString as? String ?? "NO") == "YES" - +// let grpcServiceModePort = (options?["GrpcServiceModePort"] as? NSNumber)?.intValue ?? 17079 + let grpcServiceModePort = 17079 guard let config = options?["Config"] as? NSString as? String else { writeFatalError("(packet-tunnel) error: config not provided") return } - guard let config = SingBox.setupConfig(config: config) else { - writeFatalError("(packet-tunnel) error: config is invalid") - return - } +// guard let config = SingBox.setupConfig(config: config) else { +// writeFatalError("(packet-tunnel) error: config is invalid") +// return +// } self.config = config do { @@ -41,15 +45,18 @@ open class ExtensionProvider: NEPacketTunnelProvider { writeFatalError("(packet-tunnel) error: create working directory: \(error.localizedDescription)") return } - - LibboxSetup( + var error: NSError? + MobileSetup( FilePath.sharedDirectory.relativePath, FilePath.workingDirectory.relativePath, FilePath.cacheDirectory.relativePath, - false + 4, + "127.0.0.1:\(grpcServiceModePort)", + "", + false, + &error ) - var error: NSError? LibboxRedirectStderr(FilePath.cacheDirectory.appendingPathComponent("stderr.log").relativePath, &error) if let error { writeError("(packet-tunnel) redirect stderr error: \(error.localizedDescription)") @@ -60,23 +67,23 @@ open class ExtensionProvider: NEPacketTunnelProvider { if platformInterface == nil { platformInterface = ExtensionPlatformInterface(self) } - commandServer = LibboxNewCommandServer(platformInterface, Int32(30)) - do { - try commandServer.start() - } catch { - writeFatalError("(packet-tunnel): log server start error: \(error.localizedDescription)") - return - } +// commandServer = LibboxNewCommandServer(platformInterface, Int32(30)) +// do { +// try commandServer.start() +// } catch { +// writeFatalError("(packet-tunnel): log server start error: \(error.localizedDescription)") +// return +// } writeMessage("(packet-tunnel) log server started") await startService() } func writeMessage(_ message: String) { - if let commandServer { - commandServer.writeMessage(message) - } else { - NSLog(message) - } +// if let commandServer { +// commandServer.writeMessage(message) +// } else { +// NSLog(message) +// } } func writeError(_ message: String) { @@ -88,47 +95,53 @@ open class ExtensionProvider: NEPacketTunnelProvider { #if DEBUG NSLog(message) #endif + NSLog(message) writeError(message) cancelTunnelWithError(NSError(domain: message, code: 0)) } private func startService() async { + NSLog("H?2") let configContent = config var error: NSError? - let service = LibboxNewService(configContent, platformInterface, &error) + + let service = MobileStart(configContent, platformInterface, &error) if let error { writeError("(packet-tunnel) error: create service: \(error.localizedDescription)") return } - guard let service else { - return - } - do { - try service.start() - } catch { - writeError("(packet-tunnel) error: start service: \(error.localizedDescription)") - return - } - boxService = service - commandServer.setService(service) +// guard let service else { +// return +// } +// do { +// try service.start() +// } catch { +// writeError("(packet-tunnel) error: start service: \(error.localizedDescription)") +// return +// } +// boxService = service +// commandServer.setService(service) } private func stopService() { - if let service = boxService { - do { - try service.close() - } catch { - writeError("(packet-tunnel) error: stop service: \(error.localizedDescription)") - } - boxService = nil - commandServer.setService(nil) - } + NSLog("H?3") +// if let service = boxService { +// do { +// try service.close() +// } catch { +// writeError("(packet-tunnel) error: stop service: \(error.localizedDescription)") +// } +// boxService = nil +// commandServer.setService(nil) +// } + MobileClose(4) if let platformInterface { platformInterface.reset() } } func reloadService() async { + NSLog("H?4") writeMessage("(packet-tunnel) reloading service") reasserting = true defer { @@ -140,13 +153,14 @@ open class ExtensionProvider: NEPacketTunnelProvider { override open func stopTunnel(with reason: NEProviderStopReason) async { + NSLog("H?5") writeMessage("(packet-tunnel) stopping, reason: \(reason)") stopService() - if let server = commandServer { - try? await Task.sleep(nanoseconds: 100 * NSEC_PER_MSEC) - try? server.close() - commandServer = nil - } +// if let server = commandServer { +// try? await Task.sleep(nanoseconds: 100 * NSEC_PER_MSEC) +// try? server.close() +// commandServer = nil +// } } override open func handleAppMessage(_ messageData: Data) async -> Data? { @@ -154,14 +168,16 @@ open class ExtensionProvider: NEPacketTunnelProvider { } override open func sleep() async { - if let boxService { - boxService.pause() - } + NSLog("H?6") +// if let boxService { +// boxService.pause() +// } } override open func wake() { - if let boxService { - boxService.wake() - } + NSLog("H?7") +// if let boxService { +// boxService.wake() +// } } } diff --git a/ios/HiddifyPacketTunnel/SingBox/SingBox.swift b/ios/HiddifyPacketTunnel/SingBox/SingBox.swift index c3911c24..bf2dd03a 100644 --- a/ios/HiddifyPacketTunnel/SingBox/SingBox.swift +++ b/ios/HiddifyPacketTunnel/SingBox/SingBox.swift @@ -9,6 +9,7 @@ import Foundation class SingBox { static func setupConfig(config: String, mtu: Int = 9000) -> String? { + NSLog("H?B1") guard let config = config.data(using: .utf8), var json = try? JSONSerialization diff --git a/ios/HiddifyPacketTunnel/TrafficReader.swift b/ios/HiddifyPacketTunnel/TrafficReader.swift index 117c8e87..ea092478 100644 --- a/ios/HiddifyPacketTunnel/TrafficReader.swift +++ b/ios/HiddifyPacketTunnel/TrafficReader.swift @@ -18,6 +18,7 @@ class TrafficReader { private let callback: (TrafficReaderUpdate) -> () init(onUpdate: @escaping (TrafficReaderUpdate) -> ()) { + NSLog("H?D2") self.callback = onUpdate Task(priority: .background) { [weak self] () in await self?.setup() @@ -25,6 +26,7 @@ class TrafficReader { } private func setup() async { + NSLog("H?D1") try? await Task.sleep(nanoseconds: 5_000_000_000) //return while true { @@ -46,6 +48,7 @@ class TrafficReader { } private func read() { + NSLog("H?D3") task.receive { [weak self] result in switch result { case .failure(_): diff --git a/ios/Local Packages/Package.swift b/ios/Local Packages/Package.swift index bf864f8c..28815f7a 100644 --- a/ios/Local Packages/Package.swift +++ b/ios/Local Packages/Package.swift @@ -11,16 +11,16 @@ let package = Package( ], products: [ .library( - name: "Libcore", - targets: ["Libcore"]), + name: "HiddifyCore", + targets: ["HiddifyCore"]), ], dependencies: [ // No dependencies ], targets: [ .binaryTarget( - name: "Libcore", - path: "../Frameworks/Libcore.xcframework" + name: "HiddifyCore", + path: "../Frameworks/HiddifyCore.xcframework" ) ] ) diff --git a/ios/Podfile.lock b/ios/Podfile.lock index a0790af6..ab1f2995 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -79,7 +79,7 @@ PODS: - protocol_handler_ios (0.0.1): - Flutter - Sentry/HybridSDK (8.41.0) - - sentry_flutter (8.11.1): + - sentry_flutter (8.11.2): - Flutter - FlutterMacOS - Sentry/HybridSDK (= 8.41.0) @@ -217,7 +217,7 @@ SPEC CHECKSUMS: PromisesObjC: f5707f49cb48b9636751c5b2e7d227e43fba9f47 protocol_handler_ios: a5db8abc38526ee326988b808be621e5fd568990 Sentry: 54d0fe6c0df448497c8ed4cce66ccf7027e1823e - sentry_flutter: d8bce6e1d6c4f57d0208e274f745d1eee8bae249 + sentry_flutter: f8796ae209d02920fa58f9cfd4eae00ec685bf37 share_plus: 8b6f8b3447e494cca5317c8c3073de39b3600d1f shared_preferences_foundation: fcdcbc04712aee1108ac7fda236f363274528f78 sqlite3: 7559e33dae4c78538df563795af3a86fc887ee71 diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj index 732a4183..3a1dc71a 100644 --- a/ios/Runner.xcodeproj/project.pbxproj +++ b/ios/Runner.xcodeproj/project.pbxproj @@ -3,7 +3,7 @@ archiveVersion = 1; classes = { }; - objectVersion = 54; + objectVersion = 60; objects = { /* Begin PBXBuildFile section */ @@ -34,7 +34,8 @@ 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 */; }; - 4132706C2C8A9C44003A1E9B /* Libcore.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 413270682C8A9BA2003A1E9B /* Libcore.xcframework */; }; + 4110F9E22D1AEDAB0085FD09 /* HiddifyPacketTunnel.entitlements in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = 03E392BD2ADDA00F000ADF15 /* HiddifyPacketTunnel.entitlements */; }; + 4132706C2C8A9C44003A1E9B /* HiddifyCore.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 413270682C8A9BA2003A1E9B /* HiddifyCore.xcframework */; }; 59E8864FB99B37076B22F32B /* Pods_RunnerTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 30560DB3EFDF5E86AAD00AB8 /* Pods_RunnerTests.framework */; }; 68885DD72B4EF33400D214BA /* NetworkExtension.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 03E392B72ADDA00E000ADF15 /* NetworkExtension.framework */; }; 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; @@ -70,6 +71,7 @@ dstPath = ""; dstSubfolderSpec = 13; files = ( + 4110F9E22D1AEDAB0085FD09 /* HiddifyPacketTunnel.entitlements in Embed Foundation Extensions */, 03E392C02ADDA00F000ADF15 /* HiddifyPacketTunnel.appex in Embed Foundation Extensions */, ); name = "Embed Foundation Extensions"; @@ -138,7 +140,7 @@ 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 = ""; }; - 413270682C8A9BA2003A1E9B /* Libcore.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = Libcore.xcframework; path = Frameworks/Libcore.xcframework; sourceTree = ""; }; + 413270682C8A9BA2003A1E9B /* HiddifyCore.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = HiddifyCore.xcframework; path = Frameworks/HiddifyCore.xcframework; sourceTree = ""; }; 574F12C7748958784380337F /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; 60F1D4AAC33ACF5C8307310D /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 6836D3FA2B57FDFF00A79D75 /* Package.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Package.swift; sourceTree = ""; }; @@ -170,7 +172,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 4132706C2C8A9C44003A1E9B /* Libcore.xcframework in Frameworks */, + 4132706C2C8A9C44003A1E9B /* HiddifyCore.xcframework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -363,7 +365,7 @@ B8133545EEE13EDD5549E6A3 /* Frameworks */ = { isa = PBXGroup; children = ( - 413270682C8A9BA2003A1E9B /* Libcore.xcframework */, + 413270682C8A9BA2003A1E9B /* HiddifyCore.xcframework */, 0736954E2B1FEB3E007249BE /* mobile_scanner.xcframework */, 07A63A932B1E72FB00CAFA4D /* cupertino_http.xcframework */, 07A63A972B1E72FB00CAFA4D /* device_info_plus.xcframework */, diff --git a/ios/Runner/AppDelegate.swift b/ios/Runner/AppDelegate.swift index 5f647bec..4078f5af 100644 --- a/ios/Runner/AppDelegate.swift +++ b/ios/Runner/AppDelegate.swift @@ -1,6 +1,6 @@ import UIKit import Flutter -import Libcore +import HiddifyCore @main @objc class AppDelegate: FlutterAppDelegate { diff --git a/ios/Runner/Handlers/ActiveGroupsEventHandler.swift b/ios/Runner/Handlers/ActiveGroupsEventHandler.swift index 431e1ebc..e6326997 100644 --- a/ios/Runner/Handlers/ActiveGroupsEventHandler.swift +++ b/ios/Runner/Handlers/ActiveGroupsEventHandler.swift @@ -1,6 +1,6 @@ import Foundation import Combine -import Libcore +import HiddifyCore public class ActiveGroupsEventHandler: NSObject, FlutterPlugin, FlutterStreamHandler { diff --git a/ios/Runner/Handlers/GroupsEventHandler.swift b/ios/Runner/Handlers/GroupsEventHandler.swift index e0dcce2b..e7f51d34 100644 --- a/ios/Runner/Handlers/GroupsEventHandler.swift +++ b/ios/Runner/Handlers/GroupsEventHandler.swift @@ -1,6 +1,6 @@ import Foundation import Combine -import Libcore +import HiddifyCore public class GroupsEventHandler: NSObject, FlutterPlugin, FlutterStreamHandler{ diff --git a/ios/Runner/Handlers/LogsEventHandler.swift b/ios/Runner/Handlers/LogsEventHandler.swift index 09fb600f..9575e157 100644 --- a/ios/Runner/Handlers/LogsEventHandler.swift +++ b/ios/Runner/Handlers/LogsEventHandler.swift @@ -1,6 +1,6 @@ import Foundation import Combine -import Libcore +import HiddifyCore class LogsEventHandler: NSObject, FlutterPlugin, FlutterStreamHandler { static let name = "\(Bundle.main.serviceIdentifier)/service.logs" diff --git a/ios/Runner/Handlers/MethodHandler.swift b/ios/Runner/Handlers/MethodHandler.swift index f1043c33..4d8b180c 100644 --- a/ios/Runner/Handlers/MethodHandler.swift +++ b/ios/Runner/Handlers/MethodHandler.swift @@ -7,7 +7,7 @@ import Flutter import Combine -import Libcore +import HiddifyCore public class MethodHandler: NSObject, FlutterPlugin { @@ -32,6 +32,10 @@ public class MethodHandler: NSObject, FlutterPlugin { } switch call.method { + case "get_grpc_server_public_key": + result("") + case "add_grpc_client_public_key": + result("") case "parse_config": guard let args = call.arguments as? [String:Any?], @@ -43,7 +47,7 @@ public class MethodHandler: NSObject, FlutterPlugin { return } var error: NSError? - MobileParse(path, tempPath, debug, &error) + //MobileParse(path, tempPath, debug, &error) if let error { result(FlutterError(code: String(error.code), message: error.description, details: nil)) return @@ -57,83 +61,89 @@ public class MethodHandler: NSObject, FlutterPlugin { VPNConfig.shared.configOptions = options result(true) case "setup": - Task { - // guard - // let args = call.arguments as? [String:Any?], - // let path = args["path"] as? String, - // let tempPath = args["tempPath"] as? String, - // let debug = (args["debug"] as? NSNumber)?.boolValue - // else { - // result(FlutterError(code: "INVALID_ARGS", message: nil, details: nil)) - // return - // } - // var error: NSError? - // MobileSetup(path, tempPath, 0, "","" debug, &error) - // if let error { - // result(FlutterError(code: String(error.code), message: error.description, details: nil)) - // return - // } - result("") - do { - try await VPNManager.shared.setup() - } catch { - await mainResult(FlutterError(code: "SETUP", message: error.localizedDescription, details: nil)) - return + Task { + guard + let args = call.arguments as? [String: Any?], + let baseDir = args["baseDir"] as? String, + let workingDir = args["workingDir"] as? String, + let tempDir = args["tempDir"] as? String, + let mode = args["mode"] as? Int, + let grpcPort = args["grpcPort"] as? Int + else { + result(FlutterError(code: "INVALID_ARGS", message: nil, details: nil)) + return + } + VPNConfig.shared.baseDir=baseDir + VPNConfig.shared.workingDir=workingDir + VPNConfig.shared.tempDir=tempDir + var error: NSError? + MobileSetup(baseDir, workingDir, tempDir, mode, "127.0.0.1:\(grpcPort)", "", false, &error) + if let error { + result(FlutterError(code: String(error.code), message: error.localizedDescription, details: nil)) + return + } + do { + try await VPNManager.shared.setup() + } catch { + result(FlutterError(code: "SETUP", message: error.localizedDescription, details: nil)) + return + } + result(true) } - await mainResult(true) - } case "start": Task { guard let args = call.arguments as? [String:Any?], - let path = args["path"] as? String + let path = args["path"] as? String, + let name = args["name"] as? String, + let grpcPort=args["grpcPort"] as? Int else { await mainResult(FlutterError(code: "INVALID_ARGS", message: nil, details: nil)) return } VPNConfig.shared.activeConfigPath = path + VPNConfig.shared.activeProfileName = name + VPNConfig.shared.grpcServiceModePort=grpcPort + var error: NSError? - let config = MobileBuildConfig(path, VPNConfig.shared.configOptions, &error) - if let error { - await mainResult(FlutterError(code: String(error.code), message: error.description, details: nil)) - return - } + do { try await VPNManager.shared.setup() - try await VPNManager.shared.connect(with: config, disableMemoryLimit: VPNConfig.shared.disableMemoryLimit) - } catch { - await mainResult(FlutterError(code: "SETUP_CONNECTION", message: error.localizedDescription, details: nil)) - return - } - await mainResult(true) - } - case "restart": - Task { [unowned self] in - guard - let args = call.arguments as? [String:Any?], - let path = args["path"] as? String - else { - await mainResult(FlutterError(code: "INVALID_ARGS", message: nil, details: nil)) - return - } - VPNConfig.shared.activeConfigPath = path - VPNManager.shared.disconnect() - await waitForStop().value - var error: NSError? - let config = MobileBuildConfig(path, VPNConfig.shared.configOptions, &error) - if let error { - await mainResult(FlutterError(code: "BUILD_CONFIG", message: error.localizedDescription, details: nil)) - return - } - do { - try await VPNManager.shared.setup() - try await VPNManager.shared.connect(with: config, disableMemoryLimit: VPNConfig.shared.disableMemoryLimit) + try await VPNManager.shared.connect(with: path,grpcServiceModePort: grpcPort, disableMemoryLimit: VPNConfig.shared.disableMemoryLimit) } catch { await mainResult(FlutterError(code: "SETUP_CONNECTION", message: error.localizedDescription, details: nil)) return } await mainResult(true) } +// case "restart": +// Task { [unowned self] in +// guard +// let args = call.arguments as? [String:Any?], +// let path = args["path"] as? String, +// let name = args["name"] as? String, +// let grpcPort=args["grpcPort"] as? Int +// else { +// await mainResult(FlutterError(code: "INVALID_ARGS", message: nil, details: nil)) +// return +// } +// VPNConfig.shared.activeConfigPath = path +// VPNConfig.shared.activeProfileName = name +// VPNConfig.shared.grpcServiceModePort=grpcPort +// +// +// VPNManager.shared.disconnect() +// await waitForStop().value +// var error: NSError? +// do { +// try await VPNManager.shared.setup() +// try await VPNManager.shared.connect(with: path, disableMemoryLimit: VPNConfig.shared.disableMemoryLimit) +// } catch { +// await mainResult(FlutterError(code: "SETUP_CONNECTION", message: error.localizedDescription, details: nil)) +// return +// } +// await mainResult(true) +// } case "stop": VPNManager.shared.disconnect() result(true) @@ -182,12 +192,12 @@ public class MethodHandler: NSObject, FlutterPlugin { return } var error: NSError? - let config = MobileBuildConfig(path, VPNConfig.shared.configOptions, &error) - if let error { - result(FlutterError(code: "BUILD_CONFIG", message: error.localizedDescription, details: nil)) - return - } - result(config) +// let config = MobileBuildConfig(path, VPNConfig.shared.configOptions, &error) +// if let error { +// result(FlutterError(code: "BUILD_CONFIG", message: error.localizedDescription, details: nil)) +// return +// } +// result(config) case "generate_warp_config": guard let args = call.arguments as? [String: Any], let licenseKey = args["license-key"] as? String, @@ -196,8 +206,8 @@ public class MethodHandler: NSObject, FlutterPlugin { result(FlutterError(code: "INVALID_ARGS", message: nil, details: nil)) return } - let warpConfig = MobileGenerateWarpConfig(licenseKey, accountId, accessToken, nil) - result(warpConfig) +// let warpConfig = MobileGenerateWarpConfig(licenseKey, accountId, accessToken, nil) +// result(warpConfig) default: result(FlutterMethodNotImplemented) } diff --git a/ios/Runner/Handlers/PlatformMethodHandler.swift b/ios/Runner/Handlers/PlatformMethodHandler.swift index b79f48a9..17fd4055 100644 --- a/ios/Runner/Handlers/PlatformMethodHandler.swift +++ b/ios/Runner/Handlers/PlatformMethodHandler.swift @@ -7,7 +7,7 @@ import Flutter import Combine -import Libcore +import HiddifyCore public class PlatformMethodHandler: NSObject, FlutterPlugin { @@ -25,7 +25,7 @@ public class PlatformMethodHandler: NSObject, FlutterPlugin { public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) { switch call.method { case "get_paths": - result(getPaths(args: call.arguments)) + result(getPaths(args: call.arguments) as NSDictionary) default: result(FlutterMethodNotImplemented) } diff --git a/ios/Runner/Handlers/StatsEventHandler.swift b/ios/Runner/Handlers/StatsEventHandler.swift index 8884cdea..c8476f05 100644 --- a/ios/Runner/Handlers/StatsEventHandler.swift +++ b/ios/Runner/Handlers/StatsEventHandler.swift @@ -1,7 +1,7 @@ import Foundation import Flutter import Combine -import Libcore +import HiddifyCore public class StatsEventHandler: NSObject, FlutterPlugin, FlutterStreamHandler { diff --git a/ios/Runner/VPN/VPNConfig.swift b/ios/Runner/VPN/VPNConfig.swift index f8e7a536..d9995437 100644 --- a/ios/Runner/VPN/VPNConfig.swift +++ b/ios/Runner/VPN/VPNConfig.swift @@ -14,6 +14,25 @@ class VPNConfig: ObservableObject { @Stored(key: "VPN.ActiveConfigPath") var activeConfigPath: String = "" + @Stored(key: "VPN.ActiveProfileName") + var activeProfileName: String = "" + + @Stored(key: "VPN.GrpcServiceModePort") + var grpcServiceModePort: Int = 0 + + @Stored(key: "VPN.workingDir") + var workingDir: String = "" + + @Stored(key: "VPN.tempDir") + var tempDir: String = "" + + @Stored(key: "VPN.baseDir") + var baseDir: String = "" + +// @Stored(key: "VPN.grpcFlutterPublicKey") +// var grpcFlutterPublicKey: String = "" + + @Stored(key: "VPN.ConfigOptions") var configOptions: String = "" diff --git a/ios/Runner/VPN/VPNManager.swift b/ios/Runner/VPN/VPNManager.swift index 7d352457..e55b98d7 100644 --- a/ios/Runner/VPN/VPNManager.swift +++ b/ios/Runner/VPN/VPNManager.swift @@ -192,15 +192,18 @@ class VPNManager: ObservableObject { } } - func connect(with config: String, disableMemoryLimit: Bool = false) async throws { + func connect(with config: String, grpcServiceModePort:Int, disableMemoryLimit: Bool = false) async throws { + await set(upload: 0, download: 0) - guard state == .disconnected else { return } +// guard state == .disconnected else { return } do { try await enableVPNManager() try manager.connection.startVPNTunnel(options: [ "Config": config as NSString, +// "GrpcServiceModePort":NSNumber(value: grpcServiceModePort), "DisableMemoryLimit": (disableMemoryLimit ? "YES" : "NO") as NSString, ]) + } catch { print(error.localizedDescription) } @@ -208,7 +211,7 @@ class VPNManager: ObservableObject { } func disconnect() { - guard state == .connected else { return } +// guard state == .connected else { return } manager.connection.stopVPNTunnel() } } diff --git a/ios/Shared/CommandClient.swift b/ios/Shared/CommandClient.swift index b98a1045..3702fb2d 100644 --- a/ios/Shared/CommandClient.swift +++ b/ios/Shared/CommandClient.swift @@ -1,5 +1,5 @@ import Foundation -import Libcore +import HiddifyCore public class CommandClient: ObservableObject { public enum ConnectionType { @@ -82,6 +82,8 @@ public class CommandClient: ObservableObject { } private class clientHandler: NSObject, LibboxCommandClientHandlerProtocol { + + private let commandClient: CommandClient init(_ commandClient: CommandClient) { @@ -103,22 +105,22 @@ public class CommandClient: ObservableObject { } } - func clearLog() { + func clearLogs() { 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 writeLogs(_ messageList: (any LibboxStringIteratorProtocol)?) { +// 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?) { @@ -162,5 +164,8 @@ public class CommandClient: ObservableObject { func updateClashMode(_ newMode: String?) { } + func write(_ message: LibboxConnections?) { + } + } } diff --git a/lib/hiddifycore/core_interface/core_interface.dart b/lib/hiddifycore/core_interface/core_interface.dart index 623c0277..c59238c2 100644 --- a/lib/hiddifycore/core_interface/core_interface.dart +++ b/lib/hiddifycore/core_interface/core_interface.dart @@ -29,4 +29,8 @@ class CoreInterface { return true; // return fgClient == bgClient; } + + Future resetTunnel() async { + return false; + } } diff --git a/lib/hiddifycore/core_interface/core_interface_mobile.dart b/lib/hiddifycore/core_interface/core_interface_mobile.dart index c6be3507..9f0049f7 100644 --- a/lib/hiddifycore/core_interface/core_interface_mobile.dart +++ b/lib/hiddifycore/core_interface/core_interface_mobile.dart @@ -41,7 +41,7 @@ class CoreInterfaceMobile extends CoreInterface with InfraLogger { "mode": mode, }, ); - serverPublicKey = await methodChannel.invokeMethod("get_grpc_server_public_key") ?? Uint8List.fromList([]); + // serverPublicKey = await methodChannel.invokeMethod("get_grpc_server_public_key") ?? Uint8List.fromList([]); await methodChannel.invokeMethod( "add_grpc_client_public_key", { @@ -109,4 +109,10 @@ class CoreInterfaceMobile extends CoreInterface with InfraLogger { Future isBgClientAvailable() async { return _isBgClientAvailable; } + + @override + Future resetTunnel() async { + await methodChannel.invokeMethod("reset"); + return true; + } } diff --git a/lib/hiddifycore/hiddify_core_service.dart b/lib/hiddifycore/hiddify_core_service.dart index 9dee17f5..3258e202 100644 --- a/lib/hiddifycore/hiddify_core_service.dart +++ b/lib/hiddifycore/hiddify_core_service.dart @@ -15,6 +15,7 @@ import 'package:hiddify/singbox/model/warp_account.dart'; import 'package:hiddify/hiddifycore/core_interface/core_interface_wrapper_stub.dart' if (dart.library.io) 'package:hiddify/hiddifycore/core_interface/core_interface_wrapper.dart'; import 'package:hiddify/utils/custom_loggers.dart'; +import 'package:hiddify/utils/platform_utils.dart'; import 'package:loggy/loggy.dart' as loggyl; import 'package:riverpod_annotation/riverpod_annotation.dart'; import 'package:rxdart/rxdart.dart'; @@ -180,17 +181,18 @@ class HiddifyCoreService with InfraLogger { return TaskEither( () async { // only available on iOS (and macOS later) - // if (!Platform.isIOS) { - throw UnimplementedError( - "reset tunnel function unavailable on platform", - ); - // } + if (!PlatformUtils.isIOS) { + throw UnimplementedError( + "reset tunnel function unavailable on platform", + ); + } // loggy.debug("resetting tunnel"); - // final res = await core.bgClient.resetTunnel(); - // if (res.messageType != MessageType.EMPTY) return left("${res.messageType} ${res.message}"); - - // return right(unit); + final res = await core.resetTunnel(); + if (res) { + return right(unit); + } + return left("failed to reset tunnel"); }, ); }