smartproxy/ts/core/utils/socket-utils.ts

96 lines
2.7 KiB
TypeScript

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);
}