67 lines
1.6 KiB
Swift
67 lines
1.6 KiB
Swift
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)
|
|
}
|
|
}
|