import * as plugins from '../../plugins.js'; /** * Safely cleanup a socket by removing all listeners and destroying it * @param socket The socket to cleanup * @param socketName Optional name for logging */ export function cleanupSocket(socket: plugins.net.Socket | plugins.tls.TLSSocket | null, socketName?: string): void { if (!socket) return; try { // Remove all event listeners socket.removeAllListeners(); // Unpipe any streams socket.unpipe(); // Destroy if not already destroyed if (!socket.destroyed) { socket.destroy(); } } catch (err) { console.error(`Error cleaning up socket${socketName ? ` (${socketName})` : ''}: ${err}`); } } /** * Create a cleanup handler for paired sockets (client and server) * @param clientSocket The client socket * @param serverSocket The server socket (optional) * @param onCleanup Optional callback when cleanup is done * @returns A cleanup function that can be called multiple times safely */ export function createSocketCleanupHandler( clientSocket: plugins.net.Socket | plugins.tls.TLSSocket, serverSocket?: plugins.net.Socket | plugins.tls.TLSSocket | null, onCleanup?: (reason: string) => void ): (reason: string) => void { let cleanedUp = false; return (reason: string) => { if (cleanedUp) return; cleanedUp = true; // Cleanup both sockets cleanupSocket(clientSocket, 'client'); if (serverSocket) { cleanupSocket(serverSocket, 'server'); } // Call cleanup callback if provided if (onCleanup) { onCleanup(reason); } }; } /** * Setup socket error and close handlers with proper cleanup * @param socket The socket to setup handlers for * @param handleClose The cleanup function to call * @param errorPrefix Optional prefix for error messages */ export function setupSocketHandlers( socket: plugins.net.Socket | plugins.tls.TLSSocket, handleClose: (reason: string) => void, errorPrefix?: string ): void { socket.on('error', (error) => { const prefix = errorPrefix || 'Socket'; handleClose(`${prefix}_error: ${error.message}`); }); socket.on('close', () => { const prefix = errorPrefix || 'socket'; handleClose(`${prefix}_closed`); }); socket.on('timeout', () => { const prefix = errorPrefix || 'socket'; handleClose(`${prefix}_timeout`); }); } /** * Pipe two sockets together with proper cleanup on either end * @param socket1 First socket * @param socket2 Second socket */ export function pipeSockets( socket1: plugins.net.Socket | plugins.tls.TLSSocket, socket2: plugins.net.Socket | plugins.tls.TLSSocket ): void { socket1.pipe(socket2); socket2.pipe(socket1); }