This commit is contained in:
anlicheng 2026-05-28 16:03:04 +08:00
parent ce764d2314
commit c7f216e810
3 changed files with 26 additions and 48 deletions

View File

@ -5,7 +5,6 @@ actor DNSCloudService {
private var onEvent: DNSEventHandler = { _ in } private var onEvent: DNSEventHandler = { _ in }
private var currentClient: DNSCloudClient? private var currentClient: DNSCloudClient?
private var generation: UInt64 = 0
init(serverIP: String) { init(serverIP: String) {
self.serverIP = serverIP self.serverIP = serverIP
@ -16,12 +15,11 @@ actor DNSCloudService {
} }
func run() async throws { func run() async throws {
let generation = self.nextGeneration()
let client = DNSCloudClient(serverIP: self.serverIP, port: 15353) let client = DNSCloudClient(serverIP: self.serverIP, port: 15353)
self.currentClient = client self.currentClient = client
defer { defer {
self.clearCurrent(client, generation: generation) self.clearCurrent(client)
} }
do { do {
@ -57,8 +55,6 @@ actor DNSCloudService {
} }
func stop() async { func stop() async {
self.generation &+= 1
let client = self.currentClient let client = self.currentClient
self.currentClient = nil self.currentClient = nil
@ -69,16 +65,7 @@ actor DNSCloudService {
await self.currentClient?.forward(ipPacketData: ipPacketData) await self.currentClient?.forward(ipPacketData: ipPacketData)
} }
private func nextGeneration() -> UInt64 { private func clearCurrent(_ client: DNSCloudClient) {
self.generation &+= 1
return self.generation
}
private func clearCurrent(_ client: DNSCloudClient, generation: UInt64) {
guard self.generation == generation else {
return
}
if self.currentClient === client { if self.currentClient === client {
self.currentClient = nil self.currentClient = nil
} }

View File

@ -18,6 +18,7 @@ actor DNSLocalClient {
case failed(Error) case failed(Error)
case cancelled case cancelled
case sendFailed(Error) case sendFailed(Error)
case invalidData
} }
private let queue = DispatchQueue(label: "com.sdl.DNSCloudClient.queue") private let queue = DispatchQueue(label: "com.sdl.DNSCloudClient.queue")
@ -82,10 +83,9 @@ actor DNSLocalClient {
group.addTask { group.addTask {
try await self.readySignal.wait() try await self.readySignal.wait()
while true {
let stream = Self.makeReceiveStream(for: self.connection)
for await data in stream {
try Task.checkCancellation() try Task.checkCancellation()
let data = try await self.readOnce()
await self.handleResponse(data: data) await self.handleResponse(data: data)
} }
} }
@ -241,23 +241,27 @@ actor DNSLocalClient {
return rewrittenPayload return rewrittenPayload
} }
private static func makeReceiveStream(for connection: NWConnection) -> AsyncStream<Data> { private func readOnce() async throws -> Data {
return AsyncStream(bufferingPolicy: .bufferingNewest(256)) { continuation in guard self.connection.state == .ready else {
func receiveNext() { throw DNSLocalError.cancelled
connection.receiveMessage { content, _, _, error in }
if let data = content, !data.isEmpty {
continuation.yield(data) let readContinuation = OnceContinuation<Data, Error>()
} return try await withTaskCancellationHandler {
try await withCheckedThrowingContinuation { cont in
if error == nil && connection.state == .ready { readContinuation.set(cont)
receiveNext() self.connection.receiveMessage { content, _, _, error in
if let error {
readContinuation.resume(throwing: error)
} else if let data = content, !data.isEmpty {
readContinuation.resume(returning: data)
} else { } else {
continuation.finish() readContinuation.resume(throwing: DNSLocalError.invalidData)
} }
} }
} }
} onCancel: {
receiveNext() readContinuation.resume(throwing: CancellationError())
} }
} }

View File

@ -5,7 +5,6 @@ actor DNSLocalService {
private var onEvent: DNSEventHandler = { _ in } private var onEvent: DNSEventHandler = { _ in }
private var currentClient: DNSLocalClient? private var currentClient: DNSLocalClient?
private var generation: UInt64 = 0
init(publicDnsServers: [String]) { init(publicDnsServers: [String]) {
self.publicDnsServers = publicDnsServers self.publicDnsServers = publicDnsServers
@ -16,7 +15,6 @@ actor DNSLocalService {
} }
func run() async throws { func run() async throws {
let generation = self.nextGeneration()
let dnsServer = self.publicDnsServers.randomElement() ?? "223.5.5.5" let dnsServer = self.publicDnsServers.randomElement() ?? "223.5.5.5"
let client = DNSLocalClient(host: dnsServer) let client = DNSLocalClient(host: dnsServer)
self.currentClient = client self.currentClient = client
@ -25,22 +23,20 @@ actor DNSLocalService {
do { do {
try await self.run(client: client) try await self.run(client: client)
self.clearCurrent(client, generation: generation) self.clearCurrent(client)
await client.stop() await client.stop()
} catch is CancellationError { } catch is CancellationError {
self.clearCurrent(client, generation: generation) self.clearCurrent(client)
await client.stop() await client.stop()
throw CancellationError() throw CancellationError()
} catch { } catch {
self.clearCurrent(client, generation: generation) self.clearCurrent(client)
await client.stop() await client.stop()
throw error throw error
} }
} }
func stop() async { func stop() async {
self.generation &+= 1
let client = self.currentClient let client = self.currentClient
self.currentClient = nil self.currentClient = nil
@ -74,16 +70,7 @@ actor DNSLocalService {
} }
} }
private func nextGeneration() -> UInt64 { private func clearCurrent(_ client: DNSLocalClient) {
self.generation &+= 1
return self.generation
}
private func clearCurrent(_ client: DNSLocalClient, generation: UInt64) {
guard self.generation == generation else {
return
}
if self.currentClient === client { if self.currentClient === client {
self.currentClient = nil self.currentClient = nil
} }