fix
This commit is contained in:
parent
47e45bbec4
commit
3217614f02
@ -62,6 +62,8 @@ actor SDLContextActor {
|
|||||||
// 处理权限控制
|
// 处理权限控制
|
||||||
private let policyService: PolicyService
|
private let policyService: PolicyService
|
||||||
private var rootTask: Task<Void, Error>?
|
private var rootTask: Task<Void, Error>?
|
||||||
|
private var rootTaskID: UUID?
|
||||||
|
private var terminalError: Error?
|
||||||
private let readySignal = AsyncOneShot<Void>()
|
private let readySignal = AsyncOneShot<Void>()
|
||||||
|
|
||||||
public init(provider: NEPacketTunnelProvider, config: SDLConfiguration, rsaCipher: RSACipher) {
|
public init(provider: NEPacketTunnelProvider, config: SDLConfiguration, rsaCipher: RSACipher) {
|
||||||
@ -140,21 +142,31 @@ actor SDLContextActor {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let rootTaskID = UUID()
|
||||||
let rootTask = Task {
|
let rootTask = Task {
|
||||||
|
var result: Result<Void, Error> = .success(())
|
||||||
|
|
||||||
do {
|
do {
|
||||||
try await self.runRootBody()
|
try await self.runRootBody()
|
||||||
await self.cleanupRoot()
|
|
||||||
} catch is CancellationError {
|
} catch is CancellationError {
|
||||||
|
if let terminalError = await self.consumeTerminalError() {
|
||||||
|
SDLLogger.fatal("[SDLContext] root task stopped by terminal error: \(terminalError)", category: .context)
|
||||||
|
result = .failure(terminalError)
|
||||||
|
} else {
|
||||||
SDLLogger.fatal("[SDLContext] root task cancelled", category: .context)
|
SDLLogger.fatal("[SDLContext] root task cancelled", category: .context)
|
||||||
await self.cleanupRoot()
|
result = .failure(CancellationError())
|
||||||
throw CancellationError()
|
}
|
||||||
} catch {
|
} catch {
|
||||||
SDLLogger.fatal("[SDLContext] root task failed: \(error)", category: .context)
|
SDLLogger.fatal("[SDLContext] root task failed: \(error)", category: .context)
|
||||||
await self.readySignal.fail(error)
|
await self.readySignal.fail(error)
|
||||||
|
result = .failure(error)
|
||||||
|
}
|
||||||
|
|
||||||
await self.cleanupRoot()
|
await self.cleanupRoot()
|
||||||
throw error
|
await self.finishRootTask(id: rootTaskID)
|
||||||
}
|
try result.get()
|
||||||
}
|
}
|
||||||
|
self.rootTaskID = rootTaskID
|
||||||
self.rootTask = rootTask
|
self.rootTask = rootTask
|
||||||
|
|
||||||
do {
|
do {
|
||||||
@ -164,6 +176,8 @@ actor SDLContextActor {
|
|||||||
rootTask.cancel()
|
rootTask.cancel()
|
||||||
_ = try? await rootTask.value
|
_ = try? await rootTask.value
|
||||||
self.rootTask = nil
|
self.rootTask = nil
|
||||||
|
self.rootTaskID = nil
|
||||||
|
self.terminalError = nil
|
||||||
throw error
|
throw error
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -172,13 +186,14 @@ actor SDLContextActor {
|
|||||||
public func stop() async {
|
public func stop() async {
|
||||||
SDLLogger.fatal("[SDLContext] stop requested", category: .context)
|
SDLLogger.fatal("[SDLContext] stop requested", category: .context)
|
||||||
let rootTask = self.rootTask
|
let rootTask = self.rootTask
|
||||||
self.rootTask = nil
|
|
||||||
|
|
||||||
rootTask?.cancel()
|
rootTask?.cancel()
|
||||||
await self.readySignal.fail(CancellationError())
|
await self.readySignal.fail(CancellationError())
|
||||||
_ = try? await rootTask?.value
|
_ = try? await rootTask?.value
|
||||||
|
|
||||||
await self.cleanupRoot()
|
self.rootTask = nil
|
||||||
|
self.rootTaskID = nil
|
||||||
|
self.terminalError = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
private func runRootBody() async throws {
|
private func runRootBody() async throws {
|
||||||
@ -370,6 +385,28 @@ actor SDLContextActor {
|
|||||||
await self.stopCurrentIPv6AssistClient()
|
await self.stopCurrentIPv6AssistClient()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private func requestRootShutdown(error: Error) async {
|
||||||
|
self.terminalError = error
|
||||||
|
await self.readySignal.fail(error)
|
||||||
|
self.rootTask?.cancel()
|
||||||
|
}
|
||||||
|
|
||||||
|
private func consumeTerminalError() -> Error? {
|
||||||
|
let error = self.terminalError
|
||||||
|
self.terminalError = nil
|
||||||
|
return error
|
||||||
|
}
|
||||||
|
|
||||||
|
private func finishRootTask(id: UUID) {
|
||||||
|
guard self.rootTaskID == id else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
self.rootTask = nil
|
||||||
|
self.rootTaskID = nil
|
||||||
|
self.terminalError = nil
|
||||||
|
}
|
||||||
|
|
||||||
deinit {
|
deinit {
|
||||||
SDLLogger.log("[SDLContext] deinit", category: .context)
|
SDLLogger.log("[SDLContext] deinit", category: .context)
|
||||||
}
|
}
|
||||||
@ -441,7 +478,7 @@ extension SDLContextActor {
|
|||||||
SDLLogger.fatal("[SDLContext] Super shutdown received: \(message)", category: .context)
|
SDLLogger.fatal("[SDLContext] Super shutdown received: \(message)", category: .context)
|
||||||
self.publishTunnelEvent(message: message)
|
self.publishTunnelEvent(message: message)
|
||||||
let error = NSError(domain: "com.jihe.punchnet.tun", code: -2)
|
let error = NSError(domain: "com.jihe.punchnet.tun", code: -2)
|
||||||
self.provider.cancelTunnelWithError(error)
|
await self.failTunnel(error)
|
||||||
case .applyPolicyResponse(let policyResponse):
|
case .applyPolicyResponse(let policyResponse):
|
||||||
await self.policyService.applyPolicyResponse(policyResponse)
|
await self.policyService.applyPolicyResponse(policyResponse)
|
||||||
case .applyExposedServiceResponse(let response):
|
case .applyExposedServiceResponse(let response):
|
||||||
@ -469,8 +506,8 @@ extension SDLContextActor {
|
|||||||
|
|
||||||
private func failTunnel(_ error: Error) async {
|
private func failTunnel(_ error: Error) async {
|
||||||
SDLLogger.fatal("[SDLContext] failTunnel: \(error)", category: .context)
|
SDLLogger.fatal("[SDLContext] failTunnel: \(error)", category: .context)
|
||||||
await self.readySignal.fail(error)
|
|
||||||
self.provider.cancelTunnelWithError(error)
|
self.provider.cancelTunnelWithError(error)
|
||||||
|
await self.requestRootShutdown(error: error)
|
||||||
}
|
}
|
||||||
|
|
||||||
private func requestExposedService() async {
|
private func requestExposedService() async {
|
||||||
|
|||||||
@ -82,8 +82,15 @@ actor DNSCloudClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// 发送 DNS 查询包(由 TUN 拦截到的原始 IP 包数据)
|
/// 发送 DNS 查询包(由 TUN 拦截到的原始 IP 包数据)
|
||||||
func forward(ipPacketData: Data) {
|
func forward(ipPacketData: Data) async {
|
||||||
guard connection.state == .ready else {
|
do {
|
||||||
|
try await self.readySignal.wait(timeout: .seconds(3))
|
||||||
|
} catch {
|
||||||
|
SDLLogger.log("[DNSCloudClient] drop query before ready: \(error)", category: .dns)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
guard !self.isStopped, connection.state == .ready else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -104,8 +104,19 @@ actor DNSLocalClient {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func query(tracker: DNSTracker, dnsPayload: Data) {
|
func query(tracker: DNSTracker, dnsPayload: Data) async {
|
||||||
guard connection.state == .ready, dnsPayload.count >= 2 else {
|
guard dnsPayload.count >= 2 else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
do {
|
||||||
|
try await self.readySignal.wait(timeout: .seconds(3))
|
||||||
|
} catch {
|
||||||
|
SDLLogger.log("[DNSLocalClient] drop query before ready: \(error)", category: .dns)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
guard !self.isStopped, connection.state == .ready else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -146,6 +157,10 @@ actor DNSLocalClient {
|
|||||||
private func handleConnectionStateUpdate(_ state: NWConnection.State) async {
|
private func handleConnectionStateUpdate(_ state: NWConnection.State) async {
|
||||||
switch state {
|
switch state {
|
||||||
case .ready:
|
case .ready:
|
||||||
|
guard !self.isStopped else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
await self.readySignal.succeed(())
|
await self.readySignal.succeed(())
|
||||||
case .failed(let error):
|
case .failed(let error):
|
||||||
await self.readySignal.fail(DNSLocalError.failed(error))
|
await self.readySignal.fail(DNSLocalError.failed(error))
|
||||||
|
|||||||
@ -44,6 +44,7 @@ struct FlowSession: Hashable {
|
|||||||
|
|
||||||
// MARK: - 会话表
|
// MARK: - 会话表
|
||||||
final class FlowSessionTable: @unchecked Sendable {
|
final class FlowSessionTable: @unchecked Sendable {
|
||||||
|
|
||||||
private enum SessionState: Hashable {
|
private enum SessionState: Hashable {
|
||||||
case tcpPending
|
case tcpPending
|
||||||
case tcpEstablished
|
case tcpEstablished
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user