punchnet-macos/Tun/UDPHoleV6/SDLUDPHoleV6Session.swift
2026-05-27 21:45:53 +08:00

85 lines
2.6 KiB
Swift

import Foundation
import NIOCore
actor SDLUDPHoleV6Session {
private let onEvent: SDLUDPHoleService.EventHandler
private let onData: SDLUDPHoleService.DataHandler
private var udpHoleV6: SDLUDPHoleV6?
init(
onEvent: @escaping SDLUDPHoleService.EventHandler,
onData: @escaping SDLUDPHoleService.DataHandler
) {
self.onEvent = onEvent
self.onData = onData
}
func run() async throws {
let udpHoleV6 = try SDLUDPHoleV6()
let localAddress = try udpHoleV6.start()
self.udpHoleV6 = udpHoleV6
if let localAddress {
SDLLogger.log("[SDLUDPHoleV6Session] udpHoleV6 started, on address: \(localAddress)")
} else {
SDLLogger.log("[SDLUDPHoleV6Session] udpHoleV6 started, no local address")
}
try await withThrowingTaskGroup(of: Void.self) { group in
defer {
group.cancelAll()
}
let onEvent = self.onEvent
let onData = self.onData
group.addTask {
for await (remoteAddress, message) in udpHoleV6.messageStream {
try Task.checkCancellation()
switch message {
case .control(let control):
await onEvent(.packet(remoteAddress, control))
case .data(let data):
await onData(data)
}
}
}
group.addTask {
for await event in udpHoleV6.eventStream {
try Task.checkCancellation()
switch event {
case .ready:
SDLLogger.log("[SDLUDPHoleV6Session] udpHoleV6 ready")
case .closed, .errorCaught:
throw SDLContextError.udpHoleClosed
}
}
}
_ = try await group.next()
}
}
func stop() async {
let udpHoleV6 = self.udpHoleV6
self.udpHoleV6 = nil
udpHoleV6?.stop()
}
func send(type: SDLPacketType, data: Data, remoteAddress: SocketAddress) {
guard case .v6 = remoteAddress else {
SDLLogger.log("[SDLUDPHoleV6Session] unsupported socket family: \(remoteAddress)", for: .debug)
return
}
guard let udpHoleV6 else {
SDLLogger.log("[SDLUDPHoleV6Session] udpHoleV6 is nil for remoteAddress: \(remoteAddress)", for: .debug)
return
}
udpHoleV6.send(type: type, data: data, remoteAddress: remoteAddress)
}
}