import Foundation import NIOCore /// Bidirectional TCP forwarder. Pairs two channels so bytes flow in both directions. /// Used for CONNECT tunneling (passthrough mode, no MITM). final class GlueHandler: ChannelInboundHandler, RemovableChannelHandler { typealias InboundIn = ByteBuffer typealias OutboundOut = ByteBuffer var partner: GlueHandler? private var context: ChannelHandlerContext? private var pendingRead = false func handlerAdded(context: ChannelHandlerContext) { self.context = context } func handlerRemoved(context: ChannelHandlerContext) { self.context = nil self.partner = nil } func channelRead(context: ChannelHandlerContext, data: NIOAny) { partner?.write(unwrapInboundIn(data)) } func channelReadComplete(context: ChannelHandlerContext) { partner?.flush() } func channelInactive(context: ChannelHandlerContext) { partner?.close() } func errorCaught(context: ChannelHandlerContext, error: Error) { context.close(promise: nil) } func channelWritabilityChanged(context: ChannelHandlerContext) { if context.channel.isWritable { partner?.read() } } // MARK: - Partner operations private func write(_ buffer: ByteBuffer) { context?.write(wrapOutboundOut(buffer), promise: nil) } private func flush() { context?.flush() } private func read() { if let context, !pendingRead { pendingRead = true context.read() pendingRead = false } } private func close() { context?.close(promise: nil) } }