fix SDLIPV6AssistClient

This commit is contained in:
anlicheng 2026-04-16 15:53:37 +08:00
parent fb60f1ab68
commit 720bf3549a

View File

@ -0,0 +1,148 @@
//
// SDLDNSClient 2.swift
// punchnet
//
// Created by on 2026/4/9.
//
import Foundation
import Network
actor SDLIPV6AssistClient {
private enum State {
case idle
case running
case stopped
}
private var state: State = .idle
private var connection: NWConnection?
private var receiveTask: Task<Void, Never>?
private let assistServerAddress: NWEndpoint
init(host: String, port: UInt16 ) {
self.assistServerAddress = .hostPort(host: NWEndpoint.Host(host), port: NWEndpoint.Port(integerLiteral: port))
}
func start() {
guard case .idle = self.state else {
return
}
self.state = .running
// 1.
let parameters = NWParameters.udp
// TUN NE TUN .other
parameters.prohibitedInterfaceTypes = [.other]
// 2. pathSelectionOptions
parameters.multipathServiceType = .handover
// 2.
let connection = NWConnection(to: self.assistServerAddress, using: parameters)
self.connection = connection
connection.stateUpdateHandler = { [weak self] state in
Task {
await self?.handleConnectionStateUpdate(state, for: connection)
}
}
//
connection.start(queue: .global())
}
///
private static func makeReceiveStream(for connection: NWConnection) -> AsyncStream<Data> {
return AsyncStream(bufferingPolicy: .bufferingNewest(256)) { continuation in
func receiveNext() {
connection.receiveMessage { content, _, _, error in
if let data = content, !data.isEmpty {
// DNS AsyncStream
continuation.yield(data)
}
if error == nil && connection.state == .ready {
receiveNext() //
} else {
continuation.finish()
}
}
}
receiveNext()
}
}
/// 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("[SDLIPV6AssistClient] 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
}
private func handleConnectionStateUpdate(_ state: NWConnection.State, for connection: NWConnection) {
guard case .running = self.state else {
return
}
switch state {
case .ready:
SDLLogger.log("[SDLIPV6AssistClient] Connection ready", for: .debug)
self.startReceiveTask(for: connection)
case .failed(let error):
SDLLogger.log("[SDLIPV6AssistClient] 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)
}
}
}
private func handleReceivedPacket(_ data: Data) {
guard case .running = self.state else {
return
}
NSLog("data: \(data)")
}
deinit {
self.connection?.cancel()
}
}