Files
ProxyIOS/ProxyCore/Sources/ProxyEngine/GlueHandler.swift
Trey t 148bc3887c Add iPad support, auto-pinning, and comprehensive logging
- Adaptive iPhone/iPad layout with NavigationSplitView sidebar
- Auto-detect SSL-pinned domains, fall back to passthrough
- Certificate install via local HTTP server (Safari profile flow)
- App Group-backed CA, per-domain leaf cert LRU cache
- DB-backed config repository, Darwin notification throttling
- Rules engine, breakpoint rules, pinned domain tracking
- os.Logger instrumentation across tunnel/proxy/mitm/capture/cert/rules/db/ipc/ui
- Fix dyld framework embed, race conditions, thread safety
2026-04-11 12:52:18 -05:00

70 lines
2.0 KiB
Swift

import Foundation
import NIOCore
/// Bidirectional TCP forwarder. Pairs two channels so bytes flow in both directions.
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
ProxyLogger.glue.debug("GlueHandler added to \(context.channel.localAddress?.description ?? "?")")
}
func handlerRemoved(context: ChannelHandlerContext) {
ProxyLogger.glue.debug("GlueHandler removed from \(context.channel.localAddress?.description ?? "?")")
self.context = nil
self.partner = nil
}
func channelRead(context: ChannelHandlerContext, data: NIOAny) {
let buf = unwrapInboundIn(data)
ProxyLogger.glue.debug("GlueHandler read \(buf.readableBytes) bytes, forwarding to partner")
partner?.write(buf)
}
func channelReadComplete(context: ChannelHandlerContext) {
partner?.flush()
}
func channelInactive(context: ChannelHandlerContext) {
ProxyLogger.glue.debug("GlueHandler channelInactive — closing partner")
partner?.close()
}
func errorCaught(context: ChannelHandlerContext, error: Error) {
ProxyLogger.glue.error("GlueHandler error: \(error.localizedDescription)")
context.close(promise: nil)
}
func channelWritabilityChanged(context: ChannelHandlerContext) {
if context.channel.isWritable {
partner?.read()
}
}
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)
}
}