Work around Xcode 26 tunnel isolation
This commit is contained in:
parent
028627bfcb
commit
5c0a9b3f54
1 changed files with 15 additions and 15 deletions
|
|
@ -5,19 +5,17 @@ import libburrow
|
||||||
@preconcurrency import NetworkExtension
|
@preconcurrency import NetworkExtension
|
||||||
import os
|
import os
|
||||||
|
|
||||||
|
// Xcode 26 imports `startTunnel(options:)` as `[String: NSObject]?` and treats the
|
||||||
|
// override as crossing a nonisolated boundary. The extension target does not
|
||||||
|
// mutate or forward these Cocoa objects, so treat them as an unchecked escape hatch.
|
||||||
|
extension NSObject: @retroactive @unchecked Sendable {}
|
||||||
|
|
||||||
class PacketTunnelProvider: NEPacketTunnelProvider {
|
class PacketTunnelProvider: NEPacketTunnelProvider {
|
||||||
enum Error: Swift.Error {
|
enum Error: Swift.Error {
|
||||||
case missingTunnelConfiguration
|
case missingTunnelConfiguration
|
||||||
}
|
}
|
||||||
|
|
||||||
private let logger = Logger.logger(for: PacketTunnelProvider.self)
|
private static let logger = Logger.logger(for: PacketTunnelProvider.self)
|
||||||
|
|
||||||
private var client: TunnelClient {
|
|
||||||
get throws { try _client.get() }
|
|
||||||
}
|
|
||||||
private let _client: Result<TunnelClient, Swift.Error> = Result {
|
|
||||||
try TunnelClient.unix(socketURL: Constants.socketURL)
|
|
||||||
}
|
|
||||||
|
|
||||||
override init() {
|
override init() {
|
||||||
do {
|
do {
|
||||||
|
|
@ -26,31 +24,33 @@ class PacketTunnelProvider: NEPacketTunnelProvider {
|
||||||
databasePath: try Constants.databaseURL.path(percentEncoded: false)
|
databasePath: try Constants.databaseURL.path(percentEncoded: false)
|
||||||
)
|
)
|
||||||
} catch {
|
} catch {
|
||||||
logger.error("Failed to spawn networking thread: \(error)")
|
Self.logger.error("Failed to spawn networking thread: \(error)")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override func startTunnel(options: [String: NSObject]? = nil) async throws {
|
nonisolated override func startTunnel(options: [String: NSObject]? = nil) async throws {
|
||||||
do {
|
do {
|
||||||
|
let client = try TunnelClient.unix(socketURL: Constants.socketURL)
|
||||||
let configuration = try await Array(client.tunnelConfiguration(.init()).prefix(1)).first
|
let configuration = try await Array(client.tunnelConfiguration(.init()).prefix(1)).first
|
||||||
guard let settings = configuration?.settings else {
|
guard let settings = configuration?.settings else {
|
||||||
throw Error.missingTunnelConfiguration
|
throw Error.missingTunnelConfiguration
|
||||||
}
|
}
|
||||||
try await setTunnelNetworkSettings(settings)
|
try await setTunnelNetworkSettings(settings)
|
||||||
_ = try await client.tunnelStart(.init())
|
_ = try await client.tunnelStart(.init())
|
||||||
logger.log("Started tunnel with network settings: \(settings)")
|
Self.logger.log("Started tunnel with network settings: \(settings)")
|
||||||
} catch {
|
} catch {
|
||||||
logger.error("Failed to start tunnel: \(error)")
|
Self.logger.error("Failed to start tunnel: \(error)")
|
||||||
throw error
|
throw error
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override func stopTunnel(with reason: NEProviderStopReason) async {
|
nonisolated override func stopTunnel(with reason: NEProviderStopReason) async {
|
||||||
do {
|
do {
|
||||||
|
let client = try TunnelClient.unix(socketURL: Constants.socketURL)
|
||||||
_ = try await client.tunnelStop(.init())
|
_ = try await client.tunnelStop(.init())
|
||||||
logger.log("Stopped client")
|
Self.logger.log("Stopped client")
|
||||||
} catch {
|
} catch {
|
||||||
logger.error("Failed to stop tunnel: \(error)")
|
Self.logger.error("Failed to stop tunnel: \(error)")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue