feat(smart-proxy): add socket-handler relay, fast-path port-only forwarding, metrics and bridge improvements, and various TS/Rust integration fixes

This commit is contained in:
2026-02-09 16:25:33 +00:00
parent 41efdb47f8
commit f7605e042e
17 changed files with 724 additions and 300 deletions

View File

@@ -37,6 +37,7 @@ export class SmartProxy extends plugins.EventEmitter {
private socketHandlerServer: SocketHandlerServer | null = null;
private metricsAdapter: RustMetricsAdapter;
private routeUpdateLock: Mutex;
private stopping = false;
constructor(settingsArg: ISmartProxyOptions) {
super();
@@ -102,7 +103,10 @@ export class SmartProxy extends plugins.EventEmitter {
this.bridge = new RustProxyBridge();
this.preprocessor = new RoutePreprocessor();
this.metricsAdapter = new RustMetricsAdapter(this.bridge);
this.metricsAdapter = new RustMetricsAdapter(
this.bridge,
this.settings.metrics?.sampleIntervalMs ?? 1000
);
this.routeUpdateLock = new Mutex();
}
@@ -120,23 +124,24 @@ export class SmartProxy extends plugins.EventEmitter {
);
}
// Handle unexpected exit
// Handle unexpected exit (only emits error if not intentionally stopping)
this.bridge.on('exit', (code: number | null, signal: string | null) => {
if (this.stopping) return;
logger.log('error', `RustProxy exited unexpectedly (code=${code}, signal=${signal})`, { component: 'smart-proxy' });
this.emit('error', new Error(`RustProxy exited (code=${code}, signal=${signal})`));
});
// Start socket handler relay if any routes need TS-side handling
// Check if any routes need TS-side handling (socket handlers, dynamic functions)
const hasHandlerRoutes = this.settings.routes.some(
(r) =>
(r.action.type === 'socket-handler' && r.action.socketHandler) ||
r.action.targets?.some((t) => typeof t.host === 'function' || typeof t.port === 'function')
);
// Start socket handler relay server (but don't tell Rust yet - proxy not started)
if (hasHandlerRoutes) {
this.socketHandlerServer = new SocketHandlerServer(this.preprocessor);
await this.socketHandlerServer.start();
await this.bridge.setSocketHandlerRelay(this.socketHandlerServer.getSocketPath());
}
// Preprocess routes (strip JS functions, convert socket-handler routes)
@@ -148,6 +153,11 @@ export class SmartProxy extends plugins.EventEmitter {
// Start the Rust proxy
await this.bridge.startProxy(config);
// Now that Rust proxy is running, configure socket handler relay
if (this.socketHandlerServer) {
await this.bridge.setSocketHandlerRelay(this.socketHandlerServer.getSocketPath());
}
// Handle certProvisionFunction
await this.provisionCertificatesViaCallback();
@@ -162,10 +172,14 @@ export class SmartProxy extends plugins.EventEmitter {
*/
public async stop(): Promise<void> {
logger.log('info', 'SmartProxy shutting down...', { component: 'smart-proxy' });
this.stopping = true;
// Stop metrics polling
this.metricsAdapter.stopPolling();
// Remove exit listener before killing to avoid spurious error events
this.bridge.removeAllListeners('exit');
// Stop Rust proxy
try {
await this.bridge.stopProxy();
@@ -283,6 +297,7 @@ export class SmartProxy extends plugins.EventEmitter {
* Get all currently listening ports (async - calls Rust).
*/
public async getListeningPorts(): Promise<number[]> {
if (!this.bridge.running) return [];
return this.bridge.getListeningPorts();
}