@push.rocks/smartproxy 19.5.4 → 19.5.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (62) hide show
  1. package/dist_ts/core/utils/async-utils.d.ts +81 -0
  2. package/dist_ts/core/utils/async-utils.js +216 -0
  3. package/dist_ts/core/utils/binary-heap.d.ts +73 -0
  4. package/dist_ts/core/utils/binary-heap.js +193 -0
  5. package/dist_ts/core/utils/enhanced-connection-pool.d.ts +110 -0
  6. package/dist_ts/core/utils/enhanced-connection-pool.js +320 -0
  7. package/dist_ts/core/utils/fs-utils.d.ts +144 -0
  8. package/dist_ts/core/utils/fs-utils.js +252 -0
  9. package/dist_ts/core/utils/index.d.ts +6 -2
  10. package/dist_ts/core/utils/index.js +7 -3
  11. package/dist_ts/core/utils/lifecycle-component.d.ts +59 -0
  12. package/dist_ts/core/utils/lifecycle-component.js +195 -0
  13. package/dist_ts/core/utils/socket-utils.d.ts +28 -0
  14. package/dist_ts/core/utils/socket-utils.js +77 -0
  15. package/dist_ts/forwarding/handlers/http-handler.js +7 -4
  16. package/dist_ts/forwarding/handlers/https-passthrough-handler.js +14 -55
  17. package/dist_ts/forwarding/handlers/https-terminate-to-http-handler.js +52 -40
  18. package/dist_ts/forwarding/handlers/https-terminate-to-https-handler.js +31 -43
  19. package/dist_ts/plugins.d.ts +2 -1
  20. package/dist_ts/plugins.js +3 -2
  21. package/dist_ts/proxies/http-proxy/certificate-manager.d.ts +15 -0
  22. package/dist_ts/proxies/http-proxy/certificate-manager.js +49 -2
  23. package/dist_ts/proxies/http-proxy/connection-pool.js +4 -19
  24. package/dist_ts/proxies/http-proxy/http-proxy.js +3 -7
  25. package/dist_ts/proxies/nftables-proxy/nftables-proxy.d.ts +10 -0
  26. package/dist_ts/proxies/nftables-proxy/nftables-proxy.js +53 -43
  27. package/dist_ts/proxies/smart-proxy/cert-store.js +22 -20
  28. package/dist_ts/proxies/smart-proxy/connection-manager.d.ts +35 -9
  29. package/dist_ts/proxies/smart-proxy/connection-manager.js +243 -189
  30. package/dist_ts/proxies/smart-proxy/http-proxy-bridge.js +13 -2
  31. package/dist_ts/proxies/smart-proxy/port-manager.js +3 -3
  32. package/dist_ts/proxies/smart-proxy/route-connection-handler.js +35 -4
  33. package/package.json +2 -2
  34. package/readme.hints.md +96 -1
  35. package/readme.plan.md +1135 -221
  36. package/readme.problems.md +167 -83
  37. package/ts/core/utils/async-utils.ts +275 -0
  38. package/ts/core/utils/binary-heap.ts +225 -0
  39. package/ts/core/utils/enhanced-connection-pool.ts +420 -0
  40. package/ts/core/utils/fs-utils.ts +270 -0
  41. package/ts/core/utils/index.ts +6 -2
  42. package/ts/core/utils/lifecycle-component.ts +231 -0
  43. package/ts/core/utils/socket-utils.ts +96 -0
  44. package/ts/forwarding/handlers/http-handler.ts +7 -3
  45. package/ts/forwarding/handlers/https-passthrough-handler.ts +13 -62
  46. package/ts/forwarding/handlers/https-terminate-to-http-handler.ts +58 -46
  47. package/ts/forwarding/handlers/https-terminate-to-https-handler.ts +38 -53
  48. package/ts/plugins.ts +2 -1
  49. package/ts/proxies/http-proxy/certificate-manager.ts +52 -1
  50. package/ts/proxies/http-proxy/connection-pool.ts +3 -16
  51. package/ts/proxies/http-proxy/http-proxy.ts +2 -5
  52. package/ts/proxies/nftables-proxy/nftables-proxy.ts +64 -79
  53. package/ts/proxies/smart-proxy/cert-store.ts +26 -20
  54. package/ts/proxies/smart-proxy/connection-manager.ts +277 -197
  55. package/ts/proxies/smart-proxy/http-proxy-bridge.ts +15 -1
  56. package/ts/proxies/smart-proxy/port-manager.ts +2 -2
  57. package/ts/proxies/smart-proxy/route-connection-handler.ts +39 -4
  58. package/readme.plan2.md +0 -764
  59. package/ts/common/eventUtils.ts +0 -34
  60. package/ts/common/types.ts +0 -91
  61. package/ts/core/utils/event-system.ts +0 -376
  62. package/ts/core/utils/event-utils.ts +0 -25
@@ -2,6 +2,7 @@ import * as plugins from '../../plugins.js';
2
2
  import { ForwardingHandler } from './base-handler.js';
3
3
  import type { IForwardConfig } from '../config/forwarding-types.js';
4
4
  import { ForwardingHandlerEvents } from '../config/forwarding-types.js';
5
+ import { createSocketCleanupHandler, setupSocketHandlers, pipeSockets } from '../../core/utils/socket-utils.js';
5
6
 
6
7
  /**
7
8
  * Handler for HTTPS passthrough (SNI forwarding without termination)
@@ -50,35 +51,23 @@ export class HttpsPassthroughHandler extends ForwardingHandler {
50
51
  // Create a connection to the target server
51
52
  const serverSocket = plugins.net.connect(target.port, target.host);
52
53
 
53
- // Handle errors on the server socket
54
- serverSocket.on('error', (error) => {
55
- this.emit(ForwardingHandlerEvents.ERROR, {
56
- remoteAddress,
57
- error: `Target connection error: ${error.message}`
58
- });
59
-
60
- // Close the client socket if it's still open
61
- if (!clientSocket.destroyed) {
62
- clientSocket.destroy();
63
- }
64
- });
54
+ // Track data transfer for logging
55
+ let bytesSent = 0;
56
+ let bytesReceived = 0;
65
57
 
66
- // Handle errors on the client socket
67
- clientSocket.on('error', (error) => {
68
- this.emit(ForwardingHandlerEvents.ERROR, {
58
+ // Create cleanup handler with our utility
59
+ const handleClose = createSocketCleanupHandler(clientSocket, serverSocket, (reason) => {
60
+ this.emit(ForwardingHandlerEvents.DISCONNECTED, {
69
61
  remoteAddress,
70
- error: `Client connection error: ${error.message}`
62
+ bytesSent,
63
+ bytesReceived,
64
+ reason
71
65
  });
72
-
73
- // Close the server socket if it's still open
74
- if (!serverSocket.destroyed) {
75
- serverSocket.destroy();
76
- }
77
66
  });
78
67
 
79
- // Track data transfer for logging
80
- let bytesSent = 0;
81
- let bytesReceived = 0;
68
+ // Setup error and close handlers for both sockets
69
+ setupSocketHandlers(serverSocket, handleClose, 'server');
70
+ setupSocketHandlers(clientSocket, handleClose, 'client');
82
71
 
83
72
  // Forward data from client to server
84
73
  clientSocket.on('data', (data) => {
@@ -128,48 +117,10 @@ export class HttpsPassthroughHandler extends ForwardingHandler {
128
117
  });
129
118
  });
130
119
 
131
- // Handle connection close
132
- const handleClose = () => {
133
- if (!clientSocket.destroyed) {
134
- clientSocket.destroy();
135
- }
136
-
137
- if (!serverSocket.destroyed) {
138
- serverSocket.destroy();
139
- }
140
-
141
- this.emit(ForwardingHandlerEvents.DISCONNECTED, {
142
- remoteAddress,
143
- bytesSent,
144
- bytesReceived
145
- });
146
- };
147
-
148
- // Set up close handlers
149
- clientSocket.on('close', handleClose);
150
- serverSocket.on('close', handleClose);
151
-
152
120
  // Set timeouts
153
121
  const timeout = this.getTimeout();
154
122
  clientSocket.setTimeout(timeout);
155
123
  serverSocket.setTimeout(timeout);
156
-
157
- // Handle timeouts
158
- clientSocket.on('timeout', () => {
159
- this.emit(ForwardingHandlerEvents.ERROR, {
160
- remoteAddress,
161
- error: 'Client connection timeout'
162
- });
163
- handleClose();
164
- });
165
-
166
- serverSocket.on('timeout', () => {
167
- this.emit(ForwardingHandlerEvents.ERROR, {
168
- remoteAddress,
169
- error: 'Server connection timeout'
170
- });
171
- handleClose();
172
- });
173
124
  }
174
125
 
175
126
  /**
@@ -2,6 +2,7 @@ import * as plugins from '../../plugins.js';
2
2
  import { ForwardingHandler } from './base-handler.js';
3
3
  import type { IForwardConfig } from '../config/forwarding-types.js';
4
4
  import { ForwardingHandlerEvents } from '../config/forwarding-types.js';
5
+ import { createSocketCleanupHandler, setupSocketHandlers } from '../../core/utils/socket-utils.js';
5
6
 
6
7
  /**
7
8
  * Handler for HTTPS termination with HTTP backend
@@ -95,76 +96,87 @@ export class HttpsTerminateToHttpHandler extends ForwardingHandler {
95
96
  tls: true
96
97
  });
97
98
 
98
- // Handle TLS errors
99
- tlsSocket.on('error', (error) => {
100
- this.emit(ForwardingHandlerEvents.ERROR, {
99
+ // Variables to track connections
100
+ let backendSocket: plugins.net.Socket | null = null;
101
+ let dataBuffer = Buffer.alloc(0);
102
+ let connectionEstablished = false;
103
+
104
+ // Create cleanup handler for all sockets
105
+ const handleClose = createSocketCleanupHandler(tlsSocket, backendSocket, (reason) => {
106
+ this.emit(ForwardingHandlerEvents.DISCONNECTED, {
101
107
  remoteAddress,
102
- error: `TLS error: ${error.message}`
108
+ reason
103
109
  });
104
-
105
- if (!tlsSocket.destroyed) {
106
- tlsSocket.destroy();
107
- }
110
+ dataBuffer = Buffer.alloc(0);
111
+ connectionEstablished = false;
108
112
  });
109
113
 
110
- // The TLS socket will now emit HTTP traffic that can be processed
111
- // In a real implementation, we would create an HTTP parser and handle
112
- // the requests here, but for simplicity, we'll just log the data
114
+ // Set up error handling with our cleanup utility
115
+ setupSocketHandlers(tlsSocket, handleClose, 'tls');
113
116
 
114
- let dataBuffer = Buffer.alloc(0);
117
+ // Set timeout
118
+ const timeout = this.getTimeout();
119
+ tlsSocket.setTimeout(timeout);
120
+
121
+ tlsSocket.on('timeout', () => {
122
+ this.emit(ForwardingHandlerEvents.ERROR, {
123
+ remoteAddress,
124
+ error: 'TLS connection timeout'
125
+ });
126
+ handleClose('timeout');
127
+ });
115
128
 
129
+ // Handle TLS data
116
130
  tlsSocket.on('data', (data) => {
131
+ // If backend connection already established, just forward the data
132
+ if (connectionEstablished && backendSocket && !backendSocket.destroyed) {
133
+ backendSocket.write(data);
134
+ return;
135
+ }
136
+
117
137
  // Append to buffer
118
138
  dataBuffer = Buffer.concat([dataBuffer, data]);
119
139
 
120
140
  // Very basic HTTP parsing - in a real implementation, use http-parser
121
- if (dataBuffer.includes(Buffer.from('\r\n\r\n'))) {
141
+ if (dataBuffer.includes(Buffer.from('\r\n\r\n')) && !connectionEstablished) {
122
142
  const target = this.getTargetFromConfig();
123
143
 
124
- // Simple example: forward the data to an HTTP server
125
- const socket = plugins.net.connect(target.port, target.host, () => {
126
- socket.write(dataBuffer);
127
- dataBuffer = Buffer.alloc(0);
144
+ // Create backend connection
145
+ backendSocket = plugins.net.connect(target.port, target.host, () => {
146
+ connectionEstablished = true;
147
+
148
+ // Send buffered data
149
+ if (dataBuffer.length > 0) {
150
+ backendSocket!.write(dataBuffer);
151
+ dataBuffer = Buffer.alloc(0);
152
+ }
128
153
 
129
154
  // Set up bidirectional data flow
130
- tlsSocket.pipe(socket);
131
- socket.pipe(tlsSocket);
155
+ tlsSocket.pipe(backendSocket!);
156
+ backendSocket!.pipe(tlsSocket);
132
157
  });
133
158
 
134
- socket.on('error', (error) => {
159
+ // Update the cleanup handler with the backend socket
160
+ const newHandleClose = createSocketCleanupHandler(tlsSocket, backendSocket, (reason) => {
161
+ this.emit(ForwardingHandlerEvents.DISCONNECTED, {
162
+ remoteAddress,
163
+ reason
164
+ });
165
+ dataBuffer = Buffer.alloc(0);
166
+ connectionEstablished = false;
167
+ });
168
+
169
+ // Set up handlers for backend socket
170
+ setupSocketHandlers(backendSocket, newHandleClose, 'backend');
171
+
172
+ backendSocket.on('error', (error) => {
135
173
  this.emit(ForwardingHandlerEvents.ERROR, {
136
174
  remoteAddress,
137
175
  error: `Target connection error: ${error.message}`
138
176
  });
139
-
140
- if (!tlsSocket.destroyed) {
141
- tlsSocket.destroy();
142
- }
143
177
  });
144
178
  }
145
179
  });
146
-
147
- // Handle close
148
- tlsSocket.on('close', () => {
149
- this.emit(ForwardingHandlerEvents.DISCONNECTED, {
150
- remoteAddress
151
- });
152
- });
153
-
154
- // Set timeout
155
- const timeout = this.getTimeout();
156
- tlsSocket.setTimeout(timeout);
157
-
158
- tlsSocket.on('timeout', () => {
159
- this.emit(ForwardingHandlerEvents.ERROR, {
160
- remoteAddress,
161
- error: 'TLS connection timeout'
162
- });
163
-
164
- if (!tlsSocket.destroyed) {
165
- tlsSocket.destroy();
166
- }
167
- });
168
180
  }
169
181
 
170
182
  /**
@@ -2,6 +2,7 @@ import * as plugins from '../../plugins.js';
2
2
  import { ForwardingHandler } from './base-handler.js';
3
3
  import type { IForwardConfig } from '../config/forwarding-types.js';
4
4
  import { ForwardingHandlerEvents } from '../config/forwarding-types.js';
5
+ import { createSocketCleanupHandler, setupSocketHandlers } from '../../core/utils/socket-utils.js';
5
6
 
6
7
  /**
7
8
  * Handler for HTTPS termination with HTTPS backend
@@ -93,28 +94,38 @@ export class HttpsTerminateToHttpsHandler extends ForwardingHandler {
93
94
  tls: true
94
95
  });
95
96
 
96
- // Handle TLS errors
97
- tlsSocket.on('error', (error) => {
98
- this.emit(ForwardingHandlerEvents.ERROR, {
97
+ // Variable to track backend socket
98
+ let backendSocket: plugins.tls.TLSSocket | null = null;
99
+
100
+ // Create cleanup handler for both sockets
101
+ const handleClose = createSocketCleanupHandler(tlsSocket, backendSocket, (reason) => {
102
+ this.emit(ForwardingHandlerEvents.DISCONNECTED, {
99
103
  remoteAddress,
100
- error: `TLS error: ${error.message}`
104
+ reason
101
105
  });
102
-
103
- if (!tlsSocket.destroyed) {
104
- tlsSocket.destroy();
105
- }
106
106
  });
107
107
 
108
- // The TLS socket will now emit HTTP traffic that can be processed
109
- // In a real implementation, we would create an HTTP parser and handle
110
- // the requests here, but for simplicity, we'll just forward the data
108
+ // Set up error handling with our cleanup utility
109
+ setupSocketHandlers(tlsSocket, handleClose, 'tls');
110
+
111
+ // Set timeout
112
+ const timeout = this.getTimeout();
113
+ tlsSocket.setTimeout(timeout);
114
+
115
+ tlsSocket.on('timeout', () => {
116
+ this.emit(ForwardingHandlerEvents.ERROR, {
117
+ remoteAddress,
118
+ error: 'TLS connection timeout'
119
+ });
120
+ handleClose('timeout');
121
+ });
111
122
 
112
123
  // Get the target from configuration
113
124
  const target = this.getTargetFromConfig();
114
125
 
115
126
  // Set up the connection to the HTTPS backend
116
127
  const connectToBackend = () => {
117
- const backendSocket = plugins.tls.connect({
128
+ backendSocket = plugins.tls.connect({
118
129
  host: target.host,
119
130
  port: target.port,
120
131
  // In a real implementation, we would configure TLS options
@@ -127,30 +138,29 @@ export class HttpsTerminateToHttpsHandler extends ForwardingHandler {
127
138
  });
128
139
 
129
140
  // Set up bidirectional data flow
130
- tlsSocket.pipe(backendSocket);
131
- backendSocket.pipe(tlsSocket);
141
+ tlsSocket.pipe(backendSocket!);
142
+ backendSocket!.pipe(tlsSocket);
132
143
  });
133
144
 
145
+ // Update the cleanup handler with the backend socket
146
+ const newHandleClose = createSocketCleanupHandler(tlsSocket, backendSocket, (reason) => {
147
+ this.emit(ForwardingHandlerEvents.DISCONNECTED, {
148
+ remoteAddress,
149
+ reason
150
+ });
151
+ });
152
+
153
+ // Set up handlers for backend socket
154
+ setupSocketHandlers(backendSocket, newHandleClose, 'backend');
155
+
134
156
  backendSocket.on('error', (error) => {
135
157
  this.emit(ForwardingHandlerEvents.ERROR, {
136
158
  remoteAddress,
137
159
  error: `Backend connection error: ${error.message}`
138
160
  });
139
-
140
- if (!tlsSocket.destroyed) {
141
- tlsSocket.destroy();
142
- }
143
- });
144
-
145
- // Handle close
146
- backendSocket.on('close', () => {
147
- if (!tlsSocket.destroyed) {
148
- tlsSocket.destroy();
149
- }
150
161
  });
151
162
 
152
- // Set timeout
153
- const timeout = this.getTimeout();
163
+ // Set timeout for backend socket
154
164
  backendSocket.setTimeout(timeout);
155
165
 
156
166
  backendSocket.on('timeout', () => {
@@ -158,10 +168,7 @@ export class HttpsTerminateToHttpsHandler extends ForwardingHandler {
158
168
  remoteAddress,
159
169
  error: 'Backend connection timeout'
160
170
  });
161
-
162
- if (!backendSocket.destroyed) {
163
- backendSocket.destroy();
164
- }
171
+ newHandleClose('backend_timeout');
165
172
  });
166
173
  };
167
174
 
@@ -169,28 +176,6 @@ export class HttpsTerminateToHttpsHandler extends ForwardingHandler {
169
176
  tlsSocket.on('secure', () => {
170
177
  connectToBackend();
171
178
  });
172
-
173
- // Handle close
174
- tlsSocket.on('close', () => {
175
- this.emit(ForwardingHandlerEvents.DISCONNECTED, {
176
- remoteAddress
177
- });
178
- });
179
-
180
- // Set timeout
181
- const timeout = this.getTimeout();
182
- tlsSocket.setTimeout(timeout);
183
-
184
- tlsSocket.on('timeout', () => {
185
- this.emit(ForwardingHandlerEvents.ERROR, {
186
- remoteAddress,
187
- error: 'TLS connection timeout'
188
- });
189
-
190
- if (!tlsSocket.destroyed) {
191
- tlsSocket.destroy();
192
- }
193
- });
194
179
  }
195
180
 
196
181
  /**
package/ts/plugins.ts CHANGED
@@ -4,11 +4,12 @@ import * as fs from 'fs';
4
4
  import * as http from 'http';
5
5
  import * as https from 'https';
6
6
  import * as net from 'net';
7
+ import * as path from 'path';
7
8
  import * as tls from 'tls';
8
9
  import * as url from 'url';
9
10
  import * as http2 from 'http2';
10
11
 
11
- export { EventEmitter, fs, http, https, net, tls, url, http2 };
12
+ export { EventEmitter, fs, http, https, net, path, tls, url, http2 };
12
13
 
13
14
  // tsclass scope
14
15
  import * as tsclass from '@tsclass/tsclass';
@@ -2,6 +2,7 @@ import * as plugins from '../../plugins.js';
2
2
  import * as fs from 'fs';
3
3
  import * as path from 'path';
4
4
  import { fileURLToPath } from 'url';
5
+ import { AsyncFileSystem } from '../../core/utils/fs-utils.js';
5
6
  import { type IHttpProxyOptions, type ICertificateEntry, type ILogger, createLogger } from './models/types.js';
6
7
  import type { IRouteConfig } from '../smart-proxy/models/route-types.js';
7
8
 
@@ -17,6 +18,7 @@ export class CertificateManager {
17
18
  private certificateStoreDir: string;
18
19
  private logger: ILogger;
19
20
  private httpsServer: plugins.https.Server | null = null;
21
+ private initialized = false;
20
22
 
21
23
  constructor(private options: IHttpProxyOptions) {
22
24
  this.certificateStoreDir = path.resolve(options.acme?.certificateStore || './certs');
@@ -24,6 +26,15 @@ export class CertificateManager {
24
26
 
25
27
  this.logger.warn('CertificateManager is deprecated - use SmartCertManager instead');
26
28
 
29
+ // Initialize synchronously for backward compatibility but log warning
30
+ this.initializeSync();
31
+ }
32
+
33
+ /**
34
+ * Synchronous initialization for backward compatibility
35
+ * @deprecated This uses sync filesystem operations which block the event loop
36
+ */
37
+ private initializeSync(): void {
27
38
  // Ensure certificate store directory exists
28
39
  try {
29
40
  if (!fs.existsSync(this.certificateStoreDir)) {
@@ -36,9 +47,28 @@ export class CertificateManager {
36
47
 
37
48
  this.loadDefaultCertificates();
38
49
  }
50
+
51
+ /**
52
+ * Async initialization - preferred method
53
+ */
54
+ public async initialize(): Promise<void> {
55
+ if (this.initialized) return;
56
+
57
+ // Ensure certificate store directory exists
58
+ try {
59
+ await AsyncFileSystem.ensureDir(this.certificateStoreDir);
60
+ this.logger.info(`Ensured certificate store directory: ${this.certificateStoreDir}`);
61
+ } catch (error) {
62
+ this.logger.warn(`Failed to create certificate store directory: ${error}`);
63
+ }
64
+
65
+ await this.loadDefaultCertificatesAsync();
66
+ this.initialized = true;
67
+ }
39
68
 
40
69
  /**
41
70
  * Loads default certificates from the filesystem
71
+ * @deprecated This uses sync filesystem operations which block the event loop
42
72
  */
43
73
  public loadDefaultCertificates(): void {
44
74
  const __dirname = path.dirname(fileURLToPath(import.meta.url));
@@ -49,7 +79,28 @@ export class CertificateManager {
49
79
  key: fs.readFileSync(path.join(certPath, 'key.pem'), 'utf8'),
50
80
  cert: fs.readFileSync(path.join(certPath, 'cert.pem'), 'utf8')
51
81
  };
52
- this.logger.info('Loaded default certificates from filesystem');
82
+ this.logger.info('Loaded default certificates from filesystem (sync - deprecated)');
83
+ } catch (error) {
84
+ this.logger.error(`Failed to load default certificates: ${error}`);
85
+ this.generateSelfSignedCertificate();
86
+ }
87
+ }
88
+
89
+ /**
90
+ * Loads default certificates from the filesystem asynchronously
91
+ */
92
+ public async loadDefaultCertificatesAsync(): Promise<void> {
93
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
94
+ const certPath = path.join(__dirname, '..', '..', '..', 'assets', 'certs');
95
+
96
+ try {
97
+ const [key, cert] = await Promise.all([
98
+ AsyncFileSystem.readFile(path.join(certPath, 'key.pem')),
99
+ AsyncFileSystem.readFile(path.join(certPath, 'cert.pem'))
100
+ ]);
101
+
102
+ this.defaultCertificates = { key, cert };
103
+ this.logger.info('Loaded default certificates from filesystem (async)');
53
104
  } catch (error) {
54
105
  this.logger.error(`Failed to load default certificates: ${error}`);
55
106
  this.generateSelfSignedCertificate();
@@ -1,5 +1,6 @@
1
1
  import * as plugins from '../../plugins.js';
2
2
  import { type IHttpProxyOptions, type IConnectionEntry, type ILogger, createLogger } from './models/types.js';
3
+ import { cleanupSocket } from '../../core/utils/socket-utils.js';
3
4
 
4
5
  /**
5
6
  * Manages a pool of backend connections for efficient reuse
@@ -133,14 +134,7 @@ export class ConnectionPool {
133
134
  if ((connection.isIdle && now - connection.lastUsed > idleTimeout) ||
134
135
  connections.length > (this.options.connectionPoolSize || 50)) {
135
136
 
136
- try {
137
- if (!connection.socket.destroyed) {
138
- connection.socket.end();
139
- connection.socket.destroy();
140
- }
141
- } catch (err) {
142
- this.logger.error(`Error destroying pooled connection to ${host}`, err);
143
- }
137
+ cleanupSocket(connection.socket, `pool-${host}-idle`);
144
138
 
145
139
  connections.shift(); // Remove from pool
146
140
  removed++;
@@ -170,14 +164,7 @@ export class ConnectionPool {
170
164
  this.logger.debug(`Closing ${connections.length} connections to ${host}`);
171
165
 
172
166
  for (const connection of connections) {
173
- try {
174
- if (!connection.socket.destroyed) {
175
- connection.socket.end();
176
- connection.socket.destroy();
177
- }
178
- } catch (error) {
179
- this.logger.error(`Error closing connection to ${host}:`, error);
180
- }
167
+ cleanupSocket(connection.socket, `pool-${host}-close`);
181
168
  }
182
169
  }
183
170
 
@@ -18,6 +18,7 @@ import { RequestHandler, type IMetricsTracker } from './request-handler.js';
18
18
  import { WebSocketHandler } from './websocket-handler.js';
19
19
  import { ProxyRouter } from '../../routing/router/index.js';
20
20
  import { RouteRouter } from '../../routing/router/route-router.js';
21
+ import { cleanupSocket } from '../../core/utils/socket-utils.js';
21
22
  import { FunctionCache } from './function-cache.js';
22
23
 
23
24
  /**
@@ -520,11 +521,7 @@ export class HttpProxy implements IMetricsTracker {
520
521
 
521
522
  // Close all tracked sockets
522
523
  for (const socket of this.socketMap.getArray()) {
523
- try {
524
- socket.destroy();
525
- } catch (error) {
526
- this.logger.error('Error destroying socket', error);
527
- }
524
+ cleanupSocket(socket, 'http-proxy-stop');
528
525
  }
529
526
 
530
527
  // Close all connection pool connections