Refactor task usage and profile auto update

This commit is contained in:
世界
2023-09-22 11:32:51 +08:00
parent 390e063f20
commit 3374f8e727
49 changed files with 823 additions and 636 deletions
+20 -18
View File
@@ -37,8 +37,8 @@ public class CommandClient: ObservableObject {
if let connectTask {
connectTask.cancel()
}
connectTask = Task.detached {
await self.connect0()
connectTask = Task {
await connect0()
}
}
@@ -53,7 +53,7 @@ public class CommandClient: ObservableObject {
}
}
private func connect0() async {
private nonisolated func connect0() async {
let clientOptions = LibboxCommandClientOptions()
switch connectionType {
case .status:
@@ -73,7 +73,9 @@ public class CommandClient: ObservableObject {
try Task.checkCancellation()
do {
try client.connect()
commandClient = client
await MainActor.run {
commandClient = client
}
return
} catch {}
try Task.checkCancellation()
@@ -90,19 +92,19 @@ public class CommandClient: ObservableObject {
self.commandClient = commandClient
}
func connected() {
DispatchQueue.main.sync {
nonisolated func connected() {
Task { @MainActor [self] in
self.commandClient.isConnected = true
}
}
func disconnected(_: String?) {
DispatchQueue.main.sync {
nonisolated func disconnected(_: String?) {
Task { @MainActor [self] in
self.commandClient.isConnected = false
}
}
func writeLog(_ message: String?) {
nonisolated func writeLog(_ message: String?) {
guard let message else {
return
}
@@ -111,18 +113,18 @@ public class CommandClient: ObservableObject {
logList.removeFirst()
}
logList.append(message)
DispatchQueue.main.sync {
Task { @MainActor [self, logList] in
self.commandClient.logList = logList
}
}
func writeStatus(_ message: LibboxStatusMessage?) {
DispatchQueue.main.sync {
nonisolated func writeStatus(_ message: LibboxStatusMessage?) {
Task { @MainActor [self] in
self.commandClient.status = message
}
}
func writeGroups(_ groups: LibboxOutboundGroupIteratorProtocol?) {
nonisolated func writeGroups(_ groups: LibboxOutboundGroupIteratorProtocol?) {
guard let groups else {
return
}
@@ -130,20 +132,20 @@ public class CommandClient: ObservableObject {
while groups.hasNext() {
newGroups.append(groups.next()!)
}
DispatchQueue.main.sync {
Task { @MainActor [self, newGroups] in
self.commandClient.groups = newGroups
}
}
func initializeClashMode(_ modeList: LibboxStringIteratorProtocol?, currentMode: String?) {
DispatchQueue.main.sync {
nonisolated func initializeClashMode(_ modeList: LibboxStringIteratorProtocol?, currentMode: String?) {
Task { @MainActor [self] in
self.commandClient.clashModeList = modeList!.toArray()
self.commandClient.clashMode = currentMode!
}
}
func updateClashMode(_ newMode: String?) {
DispatchQueue.main.sync {
nonisolated func updateClashMode(_ newMode: String?) {
Task { @MainActor [self] in
self.commandClient.clashMode = newMode!
}
}
+16 -3
View File
@@ -2,12 +2,24 @@ import Foundation
import Libbox
import NetworkExtension
func runBlocking<T>(_ body: @escaping () async throws -> T) throws -> T {
func runBlocking<T>(_ block: @escaping () async -> T) -> T {
let semaphore = DispatchSemaphore(value: 0)
let box = resultBox<T>()
Task {
Task.detached {
let value = await block()
box.result0 = value
semaphore.signal()
}
semaphore.wait()
return box.result0
}
func runBlocking<T>(_ tBlock: @escaping () async throws -> T) throws -> T {
let semaphore = DispatchSemaphore(value: 0)
let box = resultBox<T>()
Task.detached {
do {
let value = try await body()
let value = try await tBlock()
box.result = .success(value)
} catch {
box.result = .failure(error)
@@ -20,4 +32,5 @@ func runBlocking<T>(_ body: @escaping () async throws -> T) throws -> T {
private class resultBox<T> {
var result: Result<T, Error>!
var result0: T!
}
+3 -3
View File
@@ -12,12 +12,12 @@ public class ExtensionEnvironments: ObservableObject {
}
public func postReload() {
Task.detached {
await self.reload()
Task {
await reload()
}
}
public func reload() async {
public nonisolated func reload() async {
if let newProfile = try? await ExtensionProfile.load() {
if extensionProfile == nil || extensionProfile?.status == .invalid {
newProfile.register()
@@ -11,6 +11,12 @@ public class ExtensionPlatformInterface: NSObject, LibboxPlatformInterfaceProtoc
}
public func openTun(_ options: LibboxTunOptionsProtocol?, ret0_: UnsafeMutablePointer<Int32>?) throws {
try runBlocking {
try await self.openTun0(options, ret0_)
}
}
private func openTun0(_ options: LibboxTunOptionsProtocol?, _ ret0_: UnsafeMutablePointer<Int32>?) async throws {
guard let options else {
throw NSError(domain: "nil options", code: 0)
}
@@ -82,7 +88,7 @@ public class ExtensionPlatformInterface: NSObject, LibboxPlatformInterfaceProtoc
let proxyServer = NEProxyServer(address: options.getHTTPProxyServer(), port: Int(options.getHTTPProxyServerPort()))
proxySettings.httpServer = proxyServer
proxySettings.httpsServer = proxyServer
if SharedPreferences.systemProxyEnabled {
if try await SharedPreferences.systemProxyEnabled.get() {
proxySettings.httpEnabled = true
proxySettings.httpsEnabled = true
}
@@ -169,7 +175,9 @@ public class ExtensionPlatformInterface: NSObject, LibboxPlatformInterfaceProtoc
}
public func serviceReload() throws {
tunnel.reloadService()
Task {
await tunnel.reloadService()
}
}
public func getSystemProxyStatus() -> LibboxSystemProxyStatus? {
+2 -6
View File
@@ -14,10 +14,6 @@ public class ExtensionProfile: ObservableObject {
status = manager.connection.status
}
deinit {
unregister()
}
public func register() {
observer = NotificationCenter.default.addObserver(
forName: NSNotification.Name.NEVPNStatusDidChange,
@@ -54,13 +50,13 @@ public class ExtensionProfile: ObservableObject {
public func start() async throws {
manager.isEnabled = true
if SharedPreferences.alwaysOn {
if try await SharedPreferences.alwaysOn.get() {
manager.isOnDemandEnabled = true
setOnDemandRules()
}
#if !os(tvOS)
if let protocolConfiguration = manager.protocolConfiguration {
let includeAllNetworks = SharedPreferences.includeAllNetworks
let includeAllNetworks = try await SharedPreferences.includeAllNetworks.get()
protocolConfiguration.includeAllNetworks = includeAllNetworks
if #available(iOS 16.4, macOS 13.3, *) {
protocolConfiguration.excludeCellularServices = !includeAllNetworks
+10 -15
View File
@@ -13,8 +13,6 @@ open class ExtensionProvider: NEPacketTunnelProvider {
private var platformInterface: ExtensionPlatformInterface!
override open func startTunnel(options _: [String: NSObject]?) async throws {
NSLog("Here I am")
try? FileManager.default.removeItem(at: ExtensionProvider.errorFile)
do {
@@ -45,12 +43,12 @@ open class ExtensionProvider: NEPacketTunnelProvider {
writeError("(packet-tunnel) redirect stderr error: \(error.localizedDescription)")
}
LibboxSetMemoryLimit(!SharedPreferences.disableMemoryLimit)
try await LibboxSetMemoryLimit(!SharedPreferences.disableMemoryLimit.get())
if platformInterface == nil {
platformInterface = ExtensionPlatformInterface(self)
}
commandServer = LibboxNewCommandServer(platformInterface, Int32(SharedPreferences.maxLogLines))
commandServer = try await LibboxNewCommandServer(platformInterface, Int32(SharedPreferences.maxLogLines.get()))
do {
try commandServer.start()
} catch {
@@ -58,8 +56,7 @@ open class ExtensionProvider: NEPacketTunnelProvider {
return
}
writeMessage("(packet-tunnel) log server started")
startService()
await startService()
}
func writeMessage(_ message: String) {
@@ -83,10 +80,10 @@ open class ExtensionProvider: NEPacketTunnelProvider {
cancelTunnelWithError(NSError(domain: message, code: 0))
}
private func startService() {
private func startService() async {
let profile: Profile?
do {
profile = try ProfileManager.get(Int64(SharedPreferences.selectedProfileID))
profile = try await ProfileManager.get(Int64(SharedPreferences.selectedProfileID.get()))
} catch {
writeFatalError("(packet-tunnel) error: missing default profile: \(error.localizedDescription)")
return
@@ -97,7 +94,7 @@ open class ExtensionProvider: NEPacketTunnelProvider {
}
let configContent: String
do {
configContent = try profile.read()
configContent = try await profile.read()
} catch {
writeFatalError("(packet-tunnel) error: read config file \(profile.path): \(error.localizedDescription)")
return
@@ -120,9 +117,7 @@ open class ExtensionProvider: NEPacketTunnelProvider {
boxService = service
commandServer.setService(service)
#if os(macOS)
Task.detached {
SharedPreferences.startedByUser = true
}
await SharedPreferences.startedByUser.set(true)
#endif
}
@@ -138,14 +133,14 @@ open class ExtensionProvider: NEPacketTunnelProvider {
}
}
func reloadService() {
func reloadService() async {
writeMessage("(packet-tunnel) reloading service")
reasserting = true
defer {
reasserting = false
}
stopService()
startService()
await startService()
}
override open func stopTunnel(with reason: NEProviderStopReason) async {
@@ -158,7 +153,7 @@ open class ExtensionProvider: NEPacketTunnelProvider {
}
#if os(macOS)
if reason == .userInitiated {
SharedPreferences.startedByUser = reason == .userInitiated
await SharedPreferences.startedByUser.set(reason == .userInitiated)
}
#endif
}
+21 -17
View File
@@ -76,26 +76,30 @@
}
public static func isInstalled() async -> Bool {
await (try? Task.detached {
for _ in 0 ..< 3 {
do {
let propList = try SystemExtension().getProperties()
if propList.isEmpty {
return false
}
for extensionProp in propList {
if !extensionProp.isAwaitingUserApproval, !extensionProp.isUninstalling {
return true
}
}
} catch {
try await Task.sleep(nanoseconds: NSEC_PER_SEC)
}
}
return false
await (try? Task {
try await isInstalledBackground()
}.result.get()) == true
}
public nonisolated static func isInstalledBackground() async throws -> Bool {
for _ in 0 ..< 3 {
do {
let propList = try SystemExtension().getProperties()
if propList.isEmpty {
return false
}
for extensionProp in propList {
if !extensionProp.isAwaitingUserApproval, !extensionProp.isUninstalling {
return true
}
}
} catch {
try await Task.sleep(nanoseconds: NSEC_PER_SEC)
}
}
return false
}
public static func install(forceUpdate: Bool = false, inBackground _: Bool = false) async throws -> OSSystemExtensionRequest.Result? {
try await Task.detached {
try SystemExtension(forceUpdate: forceUpdate).submitAndWait()