fix dnsClient
This commit is contained in:
parent
ad6f7a8c42
commit
288c58d1a7
@ -56,7 +56,6 @@ actor SDLContextActor {
|
|||||||
|
|
||||||
// dns的client对象
|
// dns的client对象
|
||||||
private var dnsClient: DNSCloudClient?
|
private var dnsClient: DNSCloudClient?
|
||||||
private var dnsWorker: Task<Void, Never>?
|
|
||||||
|
|
||||||
// Localdns的client对象
|
// Localdns的client对象
|
||||||
private var dnsLocalClient: DNSLocalClient?
|
private var dnsLocalClient: DNSLocalClient?
|
||||||
@ -124,10 +123,20 @@ actor SDLContextActor {
|
|||||||
// 启动arp的定时清理任务
|
// 启动arp的定时清理任务
|
||||||
await self.puncherActor.start()
|
await self.puncherActor.start()
|
||||||
await self.arpServer.start()
|
await self.arpServer.start()
|
||||||
await self.startDnsClient()
|
|
||||||
await self.startDnsLocalClient()
|
|
||||||
|
|
||||||
// 先启动udp
|
await self.supervisor.addWorker(name: "dnsClient") {
|
||||||
|
SDLLogger.log("[SDLContext] dnsClient running!!!!")
|
||||||
|
try await self.startDnsClient()
|
||||||
|
SDLLogger.log("[SDLContext] dnsClient closed!!!!")
|
||||||
|
}
|
||||||
|
|
||||||
|
await self.supervisor.addWorker(name: "dnsLocalClient") {
|
||||||
|
SDLLogger.log("[SDLContext] dnsLocalClient running!!!!")
|
||||||
|
try await self.startDnsLocalClient()
|
||||||
|
SDLLogger.log("[SDLContext] dnsLocalClient closed!!!!")
|
||||||
|
}
|
||||||
|
|
||||||
|
// 启动udp
|
||||||
await self.supervisor.addWorker(name: "udpHole") {
|
await self.supervisor.addWorker(name: "udpHole") {
|
||||||
SDLLogger.log("[SDLContext] udp running!!!!")
|
SDLLogger.log("[SDLContext] udp running!!!!")
|
||||||
try await self.startUDPHole()
|
try await self.startUDPHole()
|
||||||
@ -294,26 +303,52 @@ actor SDLContextActor {
|
|||||||
SDLLogger.log("[SDLContext] tunnelAppNotifier ready")
|
SDLLogger.log("[SDLContext] tunnelAppNotifier ready")
|
||||||
}
|
}
|
||||||
|
|
||||||
private func startDnsClient() async {
|
private func startDnsClient() async throws {
|
||||||
self.dnsWorker?.cancel()
|
|
||||||
self.dnsWorker = nil
|
|
||||||
|
|
||||||
// 启动dns服务
|
// 启动dns服务
|
||||||
let dnsClient = DNSCloudClient(host: self.config.serverHost, port: 15353)
|
let dnsClient = DNSCloudClient(host: self.config.serverHost, port: 15353)
|
||||||
await dnsClient.start()
|
dnsClient.start()
|
||||||
SDLLogger.log("[SDLContext] dnsClient started")
|
SDLLogger.log("[SDLContext] dnsClient started")
|
||||||
self.dnsClient = dnsClient
|
self.dnsClient = dnsClient
|
||||||
let packetFlow = dnsClient.packetFlow
|
|
||||||
self.dnsWorker = Task.detached {
|
defer {
|
||||||
// 处理事件流
|
self.dnsClient?.stop()
|
||||||
for await packet in packetFlow {
|
self.dnsClient = nil
|
||||||
if Task.isCancelled {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
let nePacket = NEPacket(data: packet, protocolFamily: 2)
|
|
||||||
self.provider.packetFlow.writePacketObjects([nePacket])
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
try await withThrowingTaskGroup { group in
|
||||||
|
defer {
|
||||||
|
group.cancelAll()
|
||||||
|
}
|
||||||
|
|
||||||
|
group.addTask {
|
||||||
|
for await packet in dnsClient.packetFlow {
|
||||||
|
try Task.checkCancellation()
|
||||||
|
|
||||||
|
let nePacket = NEPacket(data: packet, protocolFamily: 2)
|
||||||
|
self.provider.packetFlow.writePacketObjects([nePacket])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
group.addTask {
|
||||||
|
for await event in dnsClient.eventStream {
|
||||||
|
try Task.checkCancellation()
|
||||||
|
switch event {
|
||||||
|
case .failed(let error):
|
||||||
|
SDLLogger.log("[SDLContext] dnsClient failed with error: \(error)")
|
||||||
|
throw error
|
||||||
|
case .cancelled:
|
||||||
|
SDLLogger.log("[SDLContext] dnsClient cancelled")
|
||||||
|
return
|
||||||
|
case .sendFailed(let error):
|
||||||
|
SDLLogger.log("[SDLContext] dnsClient sendFailed with error: \(error)")
|
||||||
|
throw error
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try await group.next()
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private func startDnsLocalClient() async {
|
private func startDnsLocalClient() async {
|
||||||
|
|||||||
@ -7,7 +7,14 @@
|
|||||||
import Foundation
|
import Foundation
|
||||||
import Network
|
import Network
|
||||||
|
|
||||||
actor DNSCloudClient {
|
final class DNSCloudClient {
|
||||||
|
|
||||||
|
enum Event {
|
||||||
|
case failed(Error)
|
||||||
|
case cancelled
|
||||||
|
case sendFailed(Error)
|
||||||
|
}
|
||||||
|
|
||||||
private enum State {
|
private enum State {
|
||||||
case idle
|
case idle
|
||||||
case running
|
case running
|
||||||
@ -15,6 +22,7 @@ actor DNSCloudClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private var state: State = .idle
|
private var state: State = .idle
|
||||||
|
|
||||||
private var connection: NWConnection?
|
private var connection: NWConnection?
|
||||||
private var receiveTask: Task<Void, Never>?
|
private var receiveTask: Task<Void, Never>?
|
||||||
private let dnsServerAddress: NWEndpoint
|
private let dnsServerAddress: NWEndpoint
|
||||||
@ -22,37 +30,28 @@ actor DNSCloudClient {
|
|||||||
// 用于对外输出收到的 DNS 响应包
|
// 用于对外输出收到的 DNS 响应包
|
||||||
public let packetFlow: AsyncStream<Data>
|
public let packetFlow: AsyncStream<Data>
|
||||||
private let packetContinuation: AsyncStream<Data>.Continuation
|
private let packetContinuation: AsyncStream<Data>.Continuation
|
||||||
private var didFinishPacketFlow = false
|
|
||||||
|
|
||||||
// 用来处理关闭事件
|
// 处理Connection的事件
|
||||||
private let closeStream: AsyncStream<Void>
|
public let eventStream: AsyncStream<Event>
|
||||||
private let closeContinuation: AsyncStream<Void>.Continuation
|
private let eventContinuation: AsyncStream<Event>.Continuation
|
||||||
private var didFinishCloseStream = false
|
|
||||||
|
|
||||||
/// - Parameter host: 你的 sn-server 地址 (如 "8.8.8.8")
|
/// - Parameter host: 你的 sn-server 地址 (如 "8.8.8.8")
|
||||||
/// - Parameter port: 端口 (如 53)
|
/// - Parameter port: 端口 (如 53)
|
||||||
init(host: String, port: UInt16 ) {
|
init(host: String, port: UInt16 ) {
|
||||||
self.dnsServerAddress = .hostPort(host: NWEndpoint.Host(host), port: NWEndpoint.Port(integerLiteral: port))
|
self.dnsServerAddress = .hostPort(host: NWEndpoint.Host(host), port: NWEndpoint.Port(integerLiteral: port))
|
||||||
|
|
||||||
let (packetStream, packetContinuation) = AsyncStream.makeStream(of: Data.self, bufferingPolicy: .bufferingNewest(256))
|
let packetPair = AsyncStream.makeStream(of: Data.self, bufferingPolicy: .bufferingNewest(256))
|
||||||
self.packetFlow = packetStream
|
self.packetFlow = packetPair.stream
|
||||||
self.packetContinuation = packetContinuation
|
self.packetContinuation = packetPair.continuation
|
||||||
|
|
||||||
let (closeStream, closeContinuation) = AsyncStream.makeStream(of: Void.self, bufferingPolicy: .bufferingNewest(1))
|
let eventPair = AsyncStream.makeStream(of: Event.self)
|
||||||
self.closeStream = closeStream
|
self.eventStream = eventPair.stream
|
||||||
self.closeContinuation = closeContinuation
|
self.eventContinuation = eventPair.continuation
|
||||||
}
|
}
|
||||||
|
|
||||||
func start() {
|
func start() {
|
||||||
guard case .idle = self.state else {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
self.state = .running
|
|
||||||
|
|
||||||
// 1. 配置参数:这是解决环路的关键
|
// 1. 配置参数:这是解决环路的关键
|
||||||
let parameters = NWParameters.udp
|
let parameters = NWParameters.udp
|
||||||
|
|
||||||
// 禁止此连接走 TUN 网卡(在 NE 中 TUN 通常被归类为 .other)
|
// 禁止此连接走 TUN 网卡(在 NE 中 TUN 通常被归类为 .other)
|
||||||
parameters.prohibitedInterfaceTypes = [.other]
|
parameters.prohibitedInterfaceTypes = [.other]
|
||||||
// 2. 增强健壮性:启用多路径切换(替代 pathSelectionOptions 的意图)
|
// 2. 增强健壮性:启用多路径切换(替代 pathSelectionOptions 的意图)
|
||||||
@ -60,20 +59,74 @@ actor DNSCloudClient {
|
|||||||
|
|
||||||
// 2. 创建连接
|
// 2. 创建连接
|
||||||
let connection = NWConnection(to: self.dnsServerAddress, using: parameters)
|
let connection = NWConnection(to: self.dnsServerAddress, using: parameters)
|
||||||
self.connection = connection
|
|
||||||
|
|
||||||
connection.stateUpdateHandler = { [weak self] state in
|
connection.stateUpdateHandler = { [weak self] state in
|
||||||
Task {
|
self?.handleConnectionStateUpdate(state, for: connection)
|
||||||
await self?.handleConnectionStateUpdate(state, for: connection)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 启动连接队列
|
// 启动连接队列
|
||||||
connection.start(queue: .global())
|
connection.start(queue: .global())
|
||||||
|
|
||||||
|
self.connection = connection
|
||||||
}
|
}
|
||||||
|
|
||||||
public func waitClose() async {
|
/// 发送 DNS 查询包(由 TUN 拦截到的原始 IP 包数据)
|
||||||
for await _ in self.closeStream { }
|
func forward(ipPacketData: Data) {
|
||||||
|
guard let connection = self.connection, connection.state == .ready else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
connection.send(content: ipPacketData, completion: .contentProcessed { error in
|
||||||
|
if let error = error {
|
||||||
|
self.eventContinuation.yield(.sendFailed(error))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func stop() {
|
||||||
|
guard self.state != .stopped else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
self.state = .stopped
|
||||||
|
|
||||||
|
self.receiveTask?.cancel()
|
||||||
|
self.receiveTask = nil
|
||||||
|
|
||||||
|
self.connection?.cancel()
|
||||||
|
self.connection = nil
|
||||||
|
|
||||||
|
self.packetContinuation.finish()
|
||||||
|
self.eventContinuation.finish()
|
||||||
|
}
|
||||||
|
|
||||||
|
private func handleConnectionStateUpdate(_ state: NWConnection.State, for connection: NWConnection) {
|
||||||
|
switch state {
|
||||||
|
case .ready:
|
||||||
|
SDLLogger.log("[DNSClient] Connection ready", for: .debug)
|
||||||
|
self.startReceiveTask(for: connection)
|
||||||
|
self.state = .running
|
||||||
|
case .failed(let error):
|
||||||
|
self.eventContinuation.yield(.failed(error))
|
||||||
|
case .cancelled:
|
||||||
|
self.eventContinuation.yield(.cancelled)
|
||||||
|
default:
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private func startReceiveTask(for connection: NWConnection) {
|
||||||
|
guard self.receiveTask == nil else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
let stream = Self.makeReceiveStream(for: connection)
|
||||||
|
self.receiveTask = Task { [weak self] in
|
||||||
|
for await data in stream {
|
||||||
|
if Task.isCancelled {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
self?.packetContinuation.yield(data)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 接收数据的递归循环
|
/// 接收数据的递归循环
|
||||||
@ -98,109 +151,4 @@ actor DNSCloudClient {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 发送 DNS 查询包(由 TUN 拦截到的原始 IP 包数据)
|
|
||||||
func forward(ipPacketData: Data) {
|
|
||||||
guard case .running = self.state, let connection = self.connection, connection.state == .ready else {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
connection.send(content: ipPacketData, completion: .contentProcessed { error in
|
|
||||||
if let error = error {
|
|
||||||
SDLLogger.log("[DNSClient] Send error: \(error)", for: .debug)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func stop() {
|
|
||||||
guard self.state != .stopped else {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
self.state = .stopped
|
|
||||||
self.receiveTask?.cancel()
|
|
||||||
self.receiveTask = nil
|
|
||||||
self.connection?.cancel()
|
|
||||||
self.connection = nil
|
|
||||||
self.finishPacketFlowIfNeeded()
|
|
||||||
self.finishCloseStreamIfNeeded()
|
|
||||||
}
|
|
||||||
|
|
||||||
private func handleConnectionStateUpdate(_ state: NWConnection.State, for connection: NWConnection) {
|
|
||||||
guard case .running = self.state else {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
switch state {
|
|
||||||
case .ready:
|
|
||||||
SDLLogger.log("[DNSClient] Connection ready", for: .debug)
|
|
||||||
self.startReceiveTask(for: connection)
|
|
||||||
case .failed(let error):
|
|
||||||
SDLLogger.log("[DNSClient] Connection failed: \(error)", for: .debug)
|
|
||||||
self.stop()
|
|
||||||
case .cancelled:
|
|
||||||
self.stop()
|
|
||||||
default:
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private func startReceiveTask(for connection: NWConnection) {
|
|
||||||
guard self.receiveTask == nil else {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
let stream = Self.makeReceiveStream(for: connection)
|
|
||||||
self.receiveTask = Task { [weak self] in
|
|
||||||
for await data in stream {
|
|
||||||
guard let self else {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
await self.handleReceivedPacket(data)
|
|
||||||
}
|
|
||||||
|
|
||||||
await self?.didFinishReceiving(for: connection)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private func handleReceivedPacket(_ data: Data) {
|
|
||||||
guard case .running = self.state else {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
self.packetContinuation.yield(data)
|
|
||||||
}
|
|
||||||
|
|
||||||
private func didFinishReceiving(for connection: NWConnection) {
|
|
||||||
guard case .running = self.state else {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if self.connection === connection, connection.state != .ready {
|
|
||||||
self.stop()
|
|
||||||
} else {
|
|
||||||
self.receiveTask = nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private func finishPacketFlowIfNeeded() {
|
|
||||||
guard !self.didFinishPacketFlow else {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
self.didFinishPacketFlow = true
|
|
||||||
self.packetContinuation.finish()
|
|
||||||
}
|
|
||||||
|
|
||||||
private func finishCloseStreamIfNeeded() {
|
|
||||||
guard !self.didFinishCloseStream else {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
self.didFinishCloseStream = true
|
|
||||||
self.closeContinuation.finish()
|
|
||||||
}
|
|
||||||
|
|
||||||
deinit {
|
|
||||||
self.connection?.cancel()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user