swiftlib_sdlan/Sources/sdlan/SDLNoticeClient.swift
2025-07-14 17:10:55 +08:00

91 lines
2.7 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
class SDLNoticeClient: ChannelInboundHandler, @unchecked Sendable {
public typealias InboundIn = AddressedEnvelope<ByteBuffer>
public typealias OutboundOut = AddressedEnvelope<ByteBuffer>
var context: ChannelHandlerContext?
private let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)
private let remoteAddress: SocketAddress
init() {
self.remoteAddress = try! SocketAddress(ipAddress: "127.0.0.1", port: 50195)
}
//
func start() {
let bootstrap = DatagramBootstrap(group: self.group)
.channelOption(ChannelOptions.socketOption(.so_reuseaddr), value: 1)
.channelInitializer { channel in
//
channel.pipeline.addHandler(self)
}
let channel = try! bootstrap.bind(host: "0.0.0.0", port: 0).wait()
SDLLogger.log("[SDLNoticeClient] started and listening on: \(channel.localAddress!)", level: .debug)
// This will never unblock as we don't close the channel
try! channel.closeFuture.wait()
}
// -- MARK: ChannelInboundHandler Methods
public func channelActive(context: ChannelHandlerContext) {
self.context = context
}
// ,
public func channelRead(context: ChannelHandlerContext, data: NIOAny) {
context.fireChannelRead(data)
}
public func errorCaught(context: ChannelHandlerContext, error: Error) {
// As we are not really interested getting notified on success or failure we just pass nil as promise to
// reduce allocations.
context.close(promise: nil)
self.context = nil
}
public func channelInactive(context: ChannelHandlerContext) {
self.context = nil
context.close(promise: nil)
}
//
func send(data: Data) {
guard let context = self.context else {
return
}
let remoteAddress = self.remoteAddress
context.eventLoop.execute {
let buffer = context.channel.allocator.buffer(bytes: data)
let envelope = AddressedEnvelope<ByteBuffer>(remoteAddress: remoteAddress, data: buffer)
context.writeAndFlush(self.wrapOutboundOut(envelope), promise: nil)
}
}
deinit {
try? self.group.syncShutdownGracefully()
}
}