fix(routing): unify route based architecture

This commit is contained in:
2025-05-13 12:48:41 +00:00
parent fe632bde67
commit fcc8cf9caa
46 changed files with 7943 additions and 1332 deletions

View File

@@ -6,7 +6,7 @@ import { SecurityManager } from './security-manager.js';
import { TlsManager } from './tls-manager.js';
import { NetworkProxyBridge } from './network-proxy-bridge.js';
import { TimeoutManager } from './timeout-manager.js';
// import { PortRangeManager } from './port-range-manager.js';
import { PortManager } from './port-manager.js';
import { RouteManager } from './route-manager.js';
import { RouteConnectionHandler } from './route-connection-handler.js';
@@ -39,7 +39,8 @@ import type { IRouteConfig } from './models/route-types.js';
* - Advanced options (timeout, headers, etc.)
*/
export class SmartProxy extends plugins.EventEmitter {
private netServers: plugins.net.Server[] = [];
// Port manager handles dynamic listener management
private portManager: PortManager;
private connectionLogger: NodeJS.Timeout | null = null;
private isShuttingDown: boolean = false;
@@ -49,8 +50,7 @@ export class SmartProxy extends plugins.EventEmitter {
private tlsManager: TlsManager;
private networkProxyBridge: NetworkProxyBridge;
private timeoutManager: TimeoutManager;
// private portRangeManager: PortRangeManager;
private routeManager: RouteManager;
public routeManager: RouteManager; // Made public for route management
private routeConnectionHandler: RouteConnectionHandler;
// Port80Handler for ACME certificate management
@@ -151,8 +151,6 @@ export class SmartProxy extends plugins.EventEmitter {
// Create the route manager
this.routeManager = new RouteManager(this.settings);
// Create port range manager
// this.portRangeManager = new PortRangeManager(this.settings);
// Create other required components
this.tlsManager = new TlsManager(this.settings);
@@ -168,6 +166,9 @@ export class SmartProxy extends plugins.EventEmitter {
this.timeoutManager,
this.routeManager
);
// Initialize port manager
this.portManager = new PortManager(this.settings, this.routeConnectionHandler);
}
/**
@@ -271,33 +272,8 @@ export class SmartProxy extends plugins.EventEmitter {
// Get listening ports from RouteManager
const listeningPorts = this.routeManager.getListeningPorts();
// Create servers for each port
for (const port of listeningPorts) {
const server = plugins.net.createServer((socket) => {
// Check if shutting down
if (this.isShuttingDown) {
socket.end();
socket.destroy();
return;
}
// Delegate to route connection handler
this.routeConnectionHandler.handleConnection(socket);
}).on('error', (err: Error) => {
console.log(`Server Error on port ${port}: ${err.message}`);
});
server.listen(port, () => {
const isNetworkProxyPort = this.settings.useNetworkProxy?.includes(port);
console.log(
`SmartProxy -> OK: Now listening on port ${port}${
isNetworkProxyPort ? ' (NetworkProxy forwarding enabled)' : ''
}`
);
});
this.netServers.push(server);
}
// Start port listeners using the PortManager
await this.portManager.addPorts(listeningPorts);
// Set up periodic connection logging and inactivity checks
this.connectionLogger = setInterval(() => {
@@ -383,6 +359,7 @@ export class SmartProxy extends plugins.EventEmitter {
public async stop() {
console.log('SmartProxy shutting down...');
this.isShuttingDown = true;
this.portManager.setShuttingDown(true);
// Stop CertProvisioner if active
if (this.certProvisioner) {
@@ -401,31 +378,14 @@ export class SmartProxy extends plugins.EventEmitter {
}
}
// Stop accepting new connections
const closeServerPromises: Promise<void>[] = this.netServers.map(
(server) =>
new Promise<void>((resolve) => {
if (!server.listening) {
resolve();
return;
}
server.close((err) => {
if (err) {
console.log(`Error closing server: ${err.message}`);
}
resolve();
});
})
);
// Stop the connection logger
if (this.connectionLogger) {
clearInterval(this.connectionLogger);
this.connectionLogger = null;
}
// Wait for servers to close
await Promise.all(closeServerPromises);
// Stop all port listeners
await this.portManager.closeAll();
console.log('All servers closed. Cleaning up active connections...');
// Clean up all active connections
@@ -434,8 +394,6 @@ export class SmartProxy extends plugins.EventEmitter {
// Stop NetworkProxy
await this.networkProxyBridge.stop();
// Clear all servers
this.netServers = [];
console.log('SmartProxy shutdown complete.');
}
@@ -479,6 +437,12 @@ export class SmartProxy extends plugins.EventEmitter {
// Update routes in RouteManager
this.routeManager.updateRoutes(newRoutes);
// Get the new set of required ports
const requiredPorts = this.routeManager.getListeningPorts();
// Update port listeners to match the new configuration
await this.portManager.updatePorts(requiredPorts);
// If NetworkProxy is initialized, resync the configurations
if (this.networkProxyBridge.getNetworkProxy()) {
await this.networkProxyBridge.syncRoutesToNetworkProxy(newRoutes);
@@ -609,6 +573,41 @@ export class SmartProxy extends plugins.EventEmitter {
return true;
}
/**
* Add a new listening port without changing the route configuration
*
* This allows you to add a port listener without updating routes.
* Useful for preparing to listen on a port before adding routes for it.
*
* @param port The port to start listening on
* @returns Promise that resolves when the port is listening
*/
public async addListeningPort(port: number): Promise<void> {
return this.portManager.addPort(port);
}
/**
* Stop listening on a specific port without changing the route configuration
*
* This allows you to stop a port listener without updating routes.
* Useful for temporary maintenance or port changes.
*
* @param port The port to stop listening on
* @returns Promise that resolves when the port is closed
*/
public async removeListeningPort(port: number): Promise<void> {
return this.portManager.removePort(port);
}
/**
* Get a list of all ports currently being listened on
*
* @returns Array of port numbers
*/
public getListeningPorts(): number[] {
return this.portManager.getListeningPorts();
}
/**
* Get statistics about current connections
*/
@@ -638,7 +637,9 @@ export class SmartProxy extends plugins.EventEmitter {
terminationStats,
acmeEnabled: !!this.port80Handler,
port80HandlerPort: this.port80Handler ? this.settings.acme?.port : null,
routes: this.routeManager.getListeningPorts().length
routes: this.routeManager.getListeningPorts().length,
listeningPorts: this.portManager.getListeningPorts(),
activePorts: this.portManager.getListeningPorts().length
};
}