feat(socket-utils): implement socket cleanup utilities and enhance socket handling in forwarding handlers

This commit is contained in:
2025-06-01 07:51:20 +00:00
parent c7c325a7d8
commit eb2e67fecc
9 changed files with 273 additions and 181 deletions

View File

@ -2,6 +2,7 @@ import * as plugins from '../../plugins.js';
import { ForwardingHandler } from './base-handler.js';
import type { IForwardConfig } from '../config/forwarding-types.js';
import { ForwardingHandlerEvents } from '../config/forwarding-types.js';
import { createSocketCleanupHandler, setupSocketHandlers, pipeSockets } from '../../core/utils/socket-utils.js';
/**
* Handler for HTTPS passthrough (SNI forwarding without termination)
@ -50,36 +51,24 @@ export class HttpsPassthroughHandler extends ForwardingHandler {
// Create a connection to the target server
const serverSocket = plugins.net.connect(target.port, target.host);
// Handle errors on the server socket
serverSocket.on('error', (error) => {
this.emit(ForwardingHandlerEvents.ERROR, {
remoteAddress,
error: `Target connection error: ${error.message}`
});
// Close the client socket if it's still open
if (!clientSocket.destroyed) {
clientSocket.destroy();
}
});
// Handle errors on the client socket
clientSocket.on('error', (error) => {
this.emit(ForwardingHandlerEvents.ERROR, {
remoteAddress,
error: `Client connection error: ${error.message}`
});
// Close the server socket if it's still open
if (!serverSocket.destroyed) {
serverSocket.destroy();
}
});
// Track data transfer for logging
let bytesSent = 0;
let bytesReceived = 0;
// Create cleanup handler with our utility
const handleClose = createSocketCleanupHandler(clientSocket, serverSocket, (reason) => {
this.emit(ForwardingHandlerEvents.DISCONNECTED, {
remoteAddress,
bytesSent,
bytesReceived,
reason
});
});
// Setup error and close handlers for both sockets
setupSocketHandlers(serverSocket, handleClose, 'server');
setupSocketHandlers(clientSocket, handleClose, 'client');
// Forward data from client to server
clientSocket.on('data', (data) => {
bytesSent += data.length;
@ -128,48 +117,10 @@ export class HttpsPassthroughHandler extends ForwardingHandler {
});
});
// Handle connection close
const handleClose = () => {
if (!clientSocket.destroyed) {
clientSocket.destroy();
}
if (!serverSocket.destroyed) {
serverSocket.destroy();
}
this.emit(ForwardingHandlerEvents.DISCONNECTED, {
remoteAddress,
bytesSent,
bytesReceived
});
};
// Set up close handlers
clientSocket.on('close', handleClose);
serverSocket.on('close', handleClose);
// Set timeouts
const timeout = this.getTimeout();
clientSocket.setTimeout(timeout);
serverSocket.setTimeout(timeout);
// Handle timeouts
clientSocket.on('timeout', () => {
this.emit(ForwardingHandlerEvents.ERROR, {
remoteAddress,
error: 'Client connection timeout'
});
handleClose();
});
serverSocket.on('timeout', () => {
this.emit(ForwardingHandlerEvents.ERROR, {
remoteAddress,
error: 'Server connection timeout'
});
handleClose();
});
}
/**