Files
ProxyIOS/ProxyCore/Sources/ProxyEngine/ProxyServer.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

60 lines
2.3 KiB
Swift

import Foundation
import NIOCore
import NIOPosix
import NIOHTTP1
public final class ProxyServer: Sendable {
private let host: String
private let port: Int
private let group: EventLoopGroup
private let trafficRepo: TrafficRepository
nonisolated(unsafe) private var channel: Channel?
public init(
host: String = ProxyConstants.proxyHost,
port: Int = ProxyConstants.proxyPort,
trafficRepo: TrafficRepository = TrafficRepository()
) {
self.host = host
self.port = port
self.group = MultiThreadedEventLoopGroup(numberOfThreads: 1)
self.trafficRepo = trafficRepo
ProxyLogger.proxy.info("ProxyServer init: \(host):\(port)")
}
public func start() async throws {
let trafficRepo = self.trafficRepo
ProxyLogger.proxy.info("ProxyServer binding to \(self.host):\(self.port)...")
let bootstrap = ServerBootstrap(group: group)
.serverChannelOption(.backlog, value: 256)
.serverChannelOption(.socketOption(.so_reuseaddr), value: 1)
.childChannelInitializer { channel in
ProxyLogger.proxy.debug("New client connection from \(channel.remoteAddress?.description ?? "unknown")")
return channel.pipeline.addHandler(
ByteToMessageHandler(HTTPRequestDecoder(leftOverBytesStrategy: .forwardBytes))
).flatMap {
channel.pipeline.addHandler(HTTPResponseEncoder())
}.flatMap {
channel.pipeline.addHandler(ConnectHandler(trafficRepo: trafficRepo))
}
}
.childChannelOption(.socketOption(.so_reuseaddr), value: 1)
.childChannelOption(.maxMessagesPerRead, value: 16)
channel = try await bootstrap.bind(host: host, port: port).get()
ProxyLogger.proxy.info("ProxyServer LISTENING on \(self.host):\(self.port)")
}
public func stop() async {
ProxyLogger.proxy.info("ProxyServer stopping...")
do {
try await channel?.close()
try await group.shutdownGracefully()
ProxyLogger.proxy.info("ProxyServer stopped cleanly")
} catch {
ProxyLogger.proxy.error("ProxyServer shutdown error: \(error.localizedDescription)")
}
}
}