Fix packet tunnel start options persistence

This commit is contained in:
世界
2026-01-13 15:46:25 +08:00
parent 7097f8747d
commit b726d76d7c
+67 -49
View File
@@ -13,7 +13,7 @@ open class ExtensionProvider: NEPacketTunnelProvider {
private static let logger = Logger(category: "ExtensionProvider") private static let logger = Logger(category: "ExtensionProvider")
public private(set) var commandServer: LibboxCommandServer? public private(set) var commandServer: LibboxCommandServer?
private var platformInterface: ExtensionPlatformInterface! private lazy var platformInterface = ExtensionPlatformInterface(self)
public var tunnelOptions: [String: NSObject]? public var tunnelOptions: [String: NSObject]?
private var startOptionsURL: URL? private var startOptionsURL: URL?
@@ -29,13 +29,13 @@ open class ExtensionProvider: NEPacketTunnelProvider {
private func applyStartOptions(_ options: [String: NSObject]) { private func applyStartOptions(_ options: [String: NSObject]) {
tunnelOptions = options tunnelOptions = options
var prefs = OverridePreferences() overridePreferences = OverridePreferences(
prefs.includeAllNetworks = (options["includeAllNetworks"] as? NSNumber)?.boolValue ?? false includeAllNetworks: (options["includeAllNetworks"] as? NSNumber)?.boolValue ?? false,
prefs.systemProxyEnabled = (options["systemProxyEnabled"] as? NSNumber)?.boolValue ?? true systemProxyEnabled: (options["systemProxyEnabled"] as? NSNumber)?.boolValue ?? true,
prefs.excludeDefaultRoute = (options["excludeDefaultRoute"] as? NSNumber)?.boolValue ?? false excludeDefaultRoute: (options["excludeDefaultRoute"] as? NSNumber)?.boolValue ?? false,
prefs.autoRouteUseSubRangesByDefault = (options["autoRouteUseSubRangesByDefault"] as? NSNumber)?.boolValue ?? false autoRouteUseSubRangesByDefault: (options["autoRouteUseSubRangesByDefault"] as? NSNumber)?.boolValue ?? false,
prefs.excludeAPNsRoute = (options["excludeAPNsRoute"] as? NSNumber)?.boolValue ?? false excludeAPNsRoute: (options["excludeAPNsRoute"] as? NSNumber)?.boolValue ?? false
overridePreferences = prefs )
} }
private func persistStartOptions(_ options: [String: NSObject]) throws { private func persistStartOptions(_ options: [String: NSObject]) throws {
@@ -46,9 +46,36 @@ open class ExtensionProvider: NEPacketTunnelProvider {
try data.write(to: startOptionsURL, options: .atomic) try data.write(to: startOptionsURL, options: .atomic)
} }
private func loadPersistedStartOptions() throws -> [String: NSObject]? {
guard let startOptionsURL, FileManager.default.fileExists(atPath: startOptionsURL.path) else {
return nil
}
let data = try Data(contentsOf: startOptionsURL)
return try ExtensionStartOptions.decode(data)
}
private func resolveStartOptions(_ startOptions: [String: NSObject]?) throws -> [String: NSObject] {
if let startOptions, startOptions["configContent"] as? String != nil {
return startOptions
}
let persistedOptions: [String: NSObject]?
do {
persistedOptions = try loadPersistedStartOptions()
} catch {
throw ExtensionStartupError("(packet-tunnel) error: load start options: \(error.localizedDescription)")
}
if let persistedOptions {
if let startOptions {
return persistedOptions.merging(startOptions) { _, new in new }
}
return persistedOptions
}
throw ExtensionStartupError("(packet-tunnel) error: missing start options")
}
#if os(macOS) #if os(macOS)
private var xpcListener: NSXPCListener? private var xpcListener: NSXPCListener!
private var xpcService: CommandXPCService? private var xpcService: CommandXPCService!
private var locationManager: CLLocationManager? private var locationManager: CLLocationManager?
private var locationDelegate: stubLocationDelegate? private var locationDelegate: stubLocationDelegate?
#endif #endif
@@ -76,27 +103,28 @@ open class ExtensionProvider: NEPacketTunnelProvider {
#endif #endif
startOptionsURL = URL(fileURLWithPath: basePath).appendingPathComponent(ExtensionStartOptions.snapshotFileName) startOptionsURL = URL(fileURLWithPath: basePath).appendingPathComponent(ExtensionStartOptions.snapshotFileName)
var effectiveOptions = startOptions
if let startOptions { #if os(macOS)
do { if Variant.useSystemExtension {
try persistStartOptions(startOptions) let socketPath = basePath + "/command.sock"
} catch { let machServiceName = AppConfiguration.appGroupID + ".system"
throw ExtensionStartupError("(packet-tunnel) error: persist start options: \(error.localizedDescription)") xpcService = CommandXPCService(socketPath: socketPath)
xpcListener = NSXPCListener(machServiceName: machServiceName)
xpcListener.delegate = xpcService
} }
} else if let startOptionsURL, FileManager.default.fileExists(atPath: startOptionsURL.path) { #endif
do {
let data = try Data(contentsOf: startOptionsURL) let effectiveOptions = try resolveStartOptions(startOptions)
effectiveOptions = try ExtensionStartOptions.decode(data) if effectiveOptions["configContent"] == nil {
} catch { throw ExtensionStartupError("(packet-tunnel) error: missing configContent in tunnel options")
throw ExtensionStartupError("(packet-tunnel) error: load start options: \(error.localizedDescription)") }
} do {
} else { try persistStartOptions(effectiveOptions)
throw ExtensionStartupError("(packet-tunnel) error: missing start options") } catch {
throw ExtensionStartupError("(packet-tunnel) error: persist start options: \(error.localizedDescription)")
} }
if let effectiveOptions { applyStartOptions(effectiveOptions)
applyStartOptions(effectiveOptions)
}
let options = LibboxSetupOptions() let options = LibboxSetupOptions()
options.basePath = basePath options.basePath = basePath
@@ -106,10 +134,10 @@ open class ExtensionProvider: NEPacketTunnelProvider {
options.logMaxLines = 3000 options.logMaxLines = 3000
#if os(tvOS) #if os(tvOS)
if let port = effectiveOptions?["commandServerPort"] as? NSNumber { if let port = effectiveOptions["commandServerPort"] as? NSNumber {
options.commandServerListenPort = port.int32Value options.commandServerListenPort = port.int32Value
} }
if let secret = effectiveOptions?["commandServerSecret"] as? String { if let secret = effectiveOptions["commandServerSecret"] as? String {
options.commandServerSecret = secret options.commandServerSecret = secret
} }
#endif #endif
@@ -120,12 +148,9 @@ open class ExtensionProvider: NEPacketTunnelProvider {
throw ExtensionStartupError("(packet-tunnel) error: setup service: \(setupError.localizedDescription)") throw ExtensionStartupError("(packet-tunnel) error: setup service: \(setupError.localizedDescription)")
} }
let ignoreMemoryLimit = (effectiveOptions?["ignoreMemoryLimit"] as? NSNumber)?.boolValue ?? false let ignoreMemoryLimit = (effectiveOptions["ignoreMemoryLimit"] as? NSNumber)?.boolValue ?? false
LibboxSetMemoryLimit(!ignoreMemoryLimit) LibboxSetMemoryLimit(!ignoreMemoryLimit)
if platformInterface == nil {
platformInterface = ExtensionPlatformInterface(self)
}
var error: NSError? var error: NSError?
commandServer = LibboxNewCommandServer(platformInterface, platformInterface, &error) commandServer = LibboxNewCommandServer(platformInterface, platformInterface, &error)
if let error { if let error {
@@ -139,14 +164,9 @@ open class ExtensionProvider: NEPacketTunnelProvider {
#if os(macOS) #if os(macOS)
if Variant.useSystemExtension { if Variant.useSystemExtension {
let socketPath = options.basePath + "/command.sock" xpcListener.resume()
xpcService = CommandXPCService(socketPath: socketPath)
let machServiceName = AppConfiguration.appGroupID + ".system"
xpcListener = NSXPCListener(machServiceName: machServiceName)
xpcListener!.delegate = xpcService
xpcListener!.resume()
Self.logger.info("set Command Server") Self.logger.info("set Command Server")
xpcService!.commandServer = commandServer xpcService.commandServer = commandServer
} }
#endif #endif
@@ -154,7 +174,7 @@ open class ExtensionProvider: NEPacketTunnelProvider {
try await startService() try await startService()
#if os(macOS) #if os(macOS)
if Variant.useSystemExtension { if Variant.useSystemExtension {
xpcService!.markServiceReady() xpcService.markServiceReady()
} }
#endif #endif
#if os(iOS) #if os(iOS)
@@ -185,8 +205,8 @@ open class ExtensionProvider: NEPacketTunnelProvider {
if !Variant.useSystemExtension, commandServer!.needWIFIState() { if !Variant.useSystemExtension, commandServer!.needWIFIState() {
locationManager = CLLocationManager() locationManager = CLLocationManager()
locationDelegate = stubLocationDelegate() locationDelegate = stubLocationDelegate()
locationManager?.delegate = locationDelegate locationManager!.delegate = locationDelegate
locationManager?.requestLocation() locationManager!.requestLocation()
} }
#endif #endif
} }
@@ -209,9 +229,7 @@ open class ExtensionProvider: NEPacketTunnelProvider {
} catch { } catch {
writeMessage("(packet-tunnel) stop service: \(error.localizedDescription)") writeMessage("(packet-tunnel) stop service: \(error.localizedDescription)")
} }
if let platformInterface { platformInterface.reset()
platformInterface.reset()
}
} }
func reloadService() async throws { func reloadService() async throws {
@@ -233,9 +251,9 @@ open class ExtensionProvider: NEPacketTunnelProvider {
} }
#if os(macOS) #if os(macOS)
if Variant.useSystemExtension { if Variant.useSystemExtension {
xpcListener?.invalidate() xpcListener.invalidate()
xpcListener = nil xpcListener = nil
xpcService?.commandServer = nil xpcService.commandServer = nil
xpcService = nil xpcService = nil
UserServiceEndpointRegistry.shared.clear() UserServiceEndpointRegistry.shared.clear()
} }