punchnet-macos/Tun/Punchnet/SDLNoticeClient.swift
2026-02-03 23:45:03 +08:00

98 lines
2.8 KiB
Swift

//
// SDLNoticeClient.swift
// Tun
//
// Created by on 2024/5/20.
//
import Foundation
//
// SDLanServer.swift
// Tun
//
// Created by on 2024/1/31.
//
import Foundation
import NIOCore
import NIOPosix
// sn-server
final class SDLNoticeClient {
private let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)
let (writeStream, writeContinuation) = AsyncStream<Data>.makeStream(of: Data.self)
private var task: Task<Void, Never>?
private var channel: Channel
private let logger: SDLLogger
private let noticePort: Int
//
init(noticePort: Int, logger: SDLLogger) throws {
self.logger = logger
self.noticePort = noticePort
let bootstrap = DatagramBootstrap(group: self.group)
.channelOption(ChannelOptions.socketOption(.so_reuseaddr), value: 1)
.channelInitializer { channel in
channel.pipeline.addHandler(SDLNoticeClientInboundHandler())
}
self.channel = try bootstrap.bind(host: "0.0.0.0", port: 0).wait()
self.logger.log("[SDLNoticeClient] started", level: .debug)
}
func start() {
let channel = self.channel
self.task = Task.detached {
self.logger.log("[SDLNoticeClient] task 11", level: .debug)
guard let remoteAddress = try? await SDLAddressResolver.shared.resolve(host: "127.0.0.1", port: self.noticePort) else {
self.logger.log("[SDLNoticeClient] task 22", level: .debug)
return
}
for await data in self.writeStream {
if Task.isCancelled {
self.logger.log("[SDLNoticeClient] task 33", level: .debug)
break
}
self.logger.log("[SDLNoticeClient] task 44", level: .debug)
self.logger.log("[SDLNoticeClient] send packet", level: .debug)
let buf = channel.allocator.buffer(bytes: data)
let envelope = AddressedEnvelope<ByteBuffer>(remoteAddress: remoteAddress, data: buf)
channel.eventLoop.execute {
channel.writeAndFlush(envelope, promise: nil)
}
}
}
}
//
func send(data: Data) {
self.writeContinuation.yield(data)
}
func waitClose() async throws {
try await self.channel.closeFuture.get()
}
deinit {
self.writeContinuation.finish()
self.task?.cancel()
try? self.group.syncShutdownGracefully()
}
}
extension SDLNoticeClient {
private class SDLNoticeClientInboundHandler: ChannelInboundHandler {
typealias InboundIn = AddressedEnvelope<ByteBuffer>
}
}