log handler base functionality

+ fix makefile ios-temp-prepare upgrading pub
+ remove tvOS from libcore local spm
+
This commit is contained in:
Amir Mohammadi
2024-01-20 18:55:25 +03:30
parent b088c24624
commit 27411da64f
4 changed files with 82 additions and 43 deletions

View File

@@ -159,7 +159,7 @@ release: # Create a new tag for release.
ios-temp-prepare: ios-temp-prepare:
flutter upgrade flutter upgrade
flutter clean flutter clean
flutter pub upgrade # flutter pub upgrade
make prepare platform=ios make prepare platform=ios
# make get-geo-assets # make get-geo-assets
# make get # make get

View File

@@ -7,8 +7,7 @@ let package = Package(
name: "Libcore", name: "Libcore",
platforms: [ platforms: [
// Minimum platform version // Minimum platform version
.iOS(.v13), .iOS(.v13)
.tvOS(.v13)
], ],
products: [ products: [
.library( .library(

View File

@@ -19,6 +19,9 @@ public class LogsEventHandler: NSObject, FlutterPlugin, FlutterStreamHandler {
} }
public func onListen(withArguments arguments: Any?, eventSink events: @escaping FlutterEventSink) -> FlutterError? { public func onListen(withArguments arguments: Any?, eventSink events: @escaping FlutterEventSink) -> FlutterError? {
if VPNManager.shared.logCallback {
events(VPNManager.shared.logList)
}
return nil return nil
} }

View File

@@ -39,6 +39,8 @@ class VPNManager: ObservableObject {
@Published private(set) var upload: Int64 = 0 @Published private(set) var upload: Int64 = 0
@Published private(set) var download: Int64 = 0 @Published private(set) var download: Int64 = 0
@Published private(set) var elapsedTime: TimeInterval = 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?
private var connectTime: Date? { private var connectTime: Date? {
@@ -83,30 +85,42 @@ class VPNManager: ObservableObject {
func setup() async throws { func setup() async throws {
// guard !loaded else { return } // guard !loaded else { return }
loaded = true loaded = true
try await loadVPNPreference() do {
try await loadVPNPreference()
} catch {
onServiceWriteLog(message: error.localizedDescription)
}
} }
private func loadVPNPreference() async throws { private func loadVPNPreference() async throws {
let managers = try await NETunnelProviderManager.loadAllFromPreferences() do {
if let manager = managers.first { let managers = try await NETunnelProviderManager.loadAllFromPreferences()
self.manager = manager if let manager = managers.first {
return 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 { private func enableVPNManager() async throws {
manager.isEnabled = true manager.isEnabled = true
try await manager.saveToPreferences() do {
try await manager.loadFromPreferences() try await manager.saveToPreferences()
try await manager.loadFromPreferences()
} catch {
onServiceWriteLog(message: error.localizedDescription)
}
} }
@MainActor private func set(upload: Int64, download: Int64) { @MainActor private func set(upload: Int64, download: Int64) {
@@ -121,7 +135,7 @@ class VPNManager: ObservableObject {
return false return false
} }
for key: String in keys.allKeys as! [String] { 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 return true
} else if key.starts(with: "utun") { } else if key.starts(with: "utun") {
return true return true
@@ -138,11 +152,15 @@ class VPNManager: ObservableObject {
$state.filter { $0 == .disconnected || $0 == .invalid }.first().sink { [weak self] _ in $state.filter { $0 == .disconnected || $0 == .invalid }.first().sink { [weak self] _ in
Task { [weak self] () in Task { [weak self] () in
self?.manager = .shared() self?.manager = .shared()
let managers = try? await NETunnelProviderManager.loadAllFromPreferences() do {
for manager in managers ?? [] { let managers = try await NETunnelProviderManager.loadAllFromPreferences()
try? await manager.removeFromPreferences() for manager in managers ?? [] {
try await manager.removeFromPreferences()
}
try await self?.loadVPNPreference()
} catch {
onServiceWriteLog(message: error.localizedDescription)
} }
try? await self?.loadVPNPreference()
} }
}.store(in: &cancelBag) }.store(in: &cancelBag)
@@ -155,31 +173,39 @@ class VPNManager: ObservableObject {
} }
guard state == .connected else { return } guard state == .connected else { return }
guard let connection = manager.connection as? NETunnelProviderSession else { return } guard let connection = manager.connection as? NETunnelProviderSession else { return }
try? connection.sendProviderMessage("stats".data(using: .utf8)!) { [weak self] response in do {
guard try connection.sendProviderMessage("stats".data(using: .utf8)!) { [weak self] response in
let response, guard
let response = String(data: response, encoding: .utf8) let response,
else { return } let response = String(data: response, encoding: .utf8)
let responseComponents = response.components(separatedBy: ",") else { return }
guard let responseComponents = response.components(separatedBy: ",")
responseComponents.count == 2, guard
let upload = Int64(responseComponents[0]), responseComponents.count == 2,
let download = Int64(responseComponents[1]) let upload = Int64(responseComponents[0]),
else { return } let download = Int64(responseComponents[1])
Task { [upload, download, weak self] () in else { return }
await self?.set(upload: upload, download: download) 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 { func connect(with config: String, disableMemoryLimit: Bool = false) async throws {
await set(upload: 0, download: 0) await set(upload: 0, download: 0)
guard state == .disconnected else { return } guard state == .disconnected else { return }
try await enableVPNManager() do {
try manager.connection.startVPNTunnel(options: [ try await enableVPNManager()
"Config": config as NSString, try manager.connection.startVPNTunnel(options: [
"DisableMemoryLimit": (disableMemoryLimit ? "YES" : "NO") as NSString, "Config": config as NSString,
]) "DisableMemoryLimit": (disableMemoryLimit ? "YES" : "NO") as NSString,
])
} catch {
onServiceWriteLog(message: error.localizedDescription)
}
connectTime = .now connectTime = .now
} }
@@ -188,5 +214,16 @@ class VPNManager: ObservableObject {
manager.connection.stopVPNTunnel() manager.connection.stopVPNTunnel()
} }
} func onServiceWriteLog(message: String) {
logCallback = true
if logList.count > 300 {
logList.removeFirst()
}
logList.append(message)
}
func onServiceResetLogs() {
logCallback = false
logList.removeAll()
}
}