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

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

View File

@@ -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
}

View File

@@ -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()
}
}