56 lines
1.9 KiB
Swift
56 lines
1.9 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
|
|
// Use only 1 thread to conserve memory in the extension (50MB budget)
|
|
self.group = MultiThreadedEventLoopGroup(numberOfThreads: 1)
|
|
self.trafficRepo = trafficRepo
|
|
}
|
|
|
|
public func start() async throws {
|
|
let trafficRepo = self.trafficRepo
|
|
|
|
let bootstrap = ServerBootstrap(group: group)
|
|
.serverChannelOption(.backlog, value: 256)
|
|
.serverChannelOption(.socketOption(.so_reuseaddr), value: 1)
|
|
.childChannelInitializer { channel in
|
|
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()
|
|
print("[ProxyServer] Listening on \(host):\(port)")
|
|
}
|
|
|
|
public func stop() async {
|
|
do {
|
|
try await channel?.close()
|
|
try await group.shutdownGracefully()
|
|
} catch {
|
|
print("[ProxyServer] Shutdown error: \(error)")
|
|
}
|
|
}
|
|
}
|