log handler base functionality
+ fix makefile ios-temp-prepare upgrading pub + remove tvOS from libcore local spm +
This commit is contained in:
2
Makefile
2
Makefile
@@ -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
|
||||||
|
|||||||
@@ -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(
|
||||||
|
|||||||
@@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user