@push.rocks/smartproxy 25.17.10 → 26.0.0

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 (179) hide show
  1. package/changelog.md +8 -0
  2. package/dist_rust/rustproxy_linux_amd64 +0 -0
  3. package/dist_rust/rustproxy_linux_arm64 +0 -0
  4. package/dist_ts/00_commitinfo_data.js +2 -2
  5. package/dist_ts/core/index.d.ts +0 -1
  6. package/dist_ts/core/index.js +1 -2
  7. package/dist_ts/core/models/index.d.ts +0 -1
  8. package/dist_ts/core/models/index.js +1 -2
  9. package/dist_ts/core/utils/index.d.ts +0 -12
  10. package/dist_ts/core/utils/index.js +1 -13
  11. package/dist_ts/index.d.ts +0 -3
  12. package/dist_ts/index.js +2 -7
  13. package/dist_ts/protocols/http/index.d.ts +0 -1
  14. package/dist_ts/protocols/http/index.js +1 -2
  15. package/dist_ts/protocols/index.d.ts +0 -7
  16. package/dist_ts/protocols/index.js +1 -8
  17. package/dist_ts/proxies/smart-proxy/socket-handler-server.js +6 -1
  18. package/dist_ts/proxies/smart-proxy/utils/route-helpers/socket-handlers.d.ts +0 -7
  19. package/dist_ts/proxies/smart-proxy/utils/route-helpers/socket-handlers.js +50 -51
  20. package/dist_ts/routing/index.d.ts +0 -1
  21. package/dist_ts/routing/index.js +1 -3
  22. package/package.json +1 -1
  23. package/ts/00_commitinfo_data.ts +1 -1
  24. package/ts/core/index.ts +0 -1
  25. package/ts/core/models/index.ts +0 -1
  26. package/ts/core/utils/index.ts +0 -12
  27. package/ts/index.ts +1 -7
  28. package/ts/protocols/http/index.ts +1 -2
  29. package/ts/protocols/index.ts +0 -7
  30. package/ts/proxies/smart-proxy/socket-handler-server.ts +6 -0
  31. package/ts/proxies/smart-proxy/utils/route-helpers/socket-handlers.ts +60 -59
  32. package/ts/routing/index.ts +0 -3
  33. package/dist_ts/core/events/index.d.ts +0 -4
  34. package/dist_ts/core/events/index.js +0 -5
  35. package/dist_ts/core/models/socket-augmentation.d.ts +0 -15
  36. package/dist_ts/core/models/socket-augmentation.js +0 -18
  37. package/dist_ts/core/utils/async-utils.d.ts +0 -81
  38. package/dist_ts/core/utils/async-utils.js +0 -216
  39. package/dist_ts/core/utils/binary-heap.d.ts +0 -73
  40. package/dist_ts/core/utils/binary-heap.js +0 -193
  41. package/dist_ts/core/utils/enhanced-connection-pool.d.ts +0 -110
  42. package/dist_ts/core/utils/enhanced-connection-pool.js +0 -325
  43. package/dist_ts/core/utils/fs-utils.d.ts +0 -144
  44. package/dist_ts/core/utils/fs-utils.js +0 -252
  45. package/dist_ts/core/utils/ip-utils.d.ts +0 -69
  46. package/dist_ts/core/utils/ip-utils.js +0 -270
  47. package/dist_ts/core/utils/lifecycle-component.d.ts +0 -59
  48. package/dist_ts/core/utils/lifecycle-component.js +0 -211
  49. package/dist_ts/core/utils/log-deduplicator.d.ts +0 -39
  50. package/dist_ts/core/utils/log-deduplicator.js +0 -305
  51. package/dist_ts/core/utils/security-utils.d.ts +0 -111
  52. package/dist_ts/core/utils/security-utils.js +0 -212
  53. package/dist_ts/core/utils/shared-security-manager.d.ts +0 -128
  54. package/dist_ts/core/utils/shared-security-manager.js +0 -362
  55. package/dist_ts/core/utils/socket-utils.d.ts +0 -63
  56. package/dist_ts/core/utils/socket-utils.js +0 -249
  57. package/dist_ts/core/utils/template-utils.d.ts +0 -37
  58. package/dist_ts/core/utils/template-utils.js +0 -104
  59. package/dist_ts/core/utils/validation-utils.d.ts +0 -61
  60. package/dist_ts/core/utils/validation-utils.js +0 -149
  61. package/dist_ts/core/utils/websocket-utils.d.ts +0 -22
  62. package/dist_ts/core/utils/websocket-utils.js +0 -30
  63. package/dist_ts/detection/detectors/http-detector.d.ts +0 -33
  64. package/dist_ts/detection/detectors/http-detector.js +0 -101
  65. package/dist_ts/detection/detectors/quick-detector.d.ts +0 -28
  66. package/dist_ts/detection/detectors/quick-detector.js +0 -131
  67. package/dist_ts/detection/detectors/routing-extractor.d.ts +0 -28
  68. package/dist_ts/detection/detectors/routing-extractor.js +0 -122
  69. package/dist_ts/detection/detectors/tls-detector.d.ts +0 -47
  70. package/dist_ts/detection/detectors/tls-detector.js +0 -183
  71. package/dist_ts/detection/index.d.ts +0 -17
  72. package/dist_ts/detection/index.js +0 -22
  73. package/dist_ts/detection/models/detection-types.d.ts +0 -87
  74. package/dist_ts/detection/models/detection-types.js +0 -5
  75. package/dist_ts/detection/models/interfaces.d.ts +0 -97
  76. package/dist_ts/detection/models/interfaces.js +0 -5
  77. package/dist_ts/detection/protocol-detector.d.ts +0 -79
  78. package/dist_ts/detection/protocol-detector.js +0 -253
  79. package/dist_ts/detection/utils/buffer-utils.d.ts +0 -61
  80. package/dist_ts/detection/utils/buffer-utils.js +0 -127
  81. package/dist_ts/detection/utils/fragment-manager.d.ts +0 -31
  82. package/dist_ts/detection/utils/fragment-manager.js +0 -53
  83. package/dist_ts/detection/utils/parser-utils.d.ts +0 -42
  84. package/dist_ts/detection/utils/parser-utils.js +0 -63
  85. package/dist_ts/protocols/common/fragment-handler.d.ts +0 -73
  86. package/dist_ts/protocols/common/fragment-handler.js +0 -121
  87. package/dist_ts/protocols/common/index.d.ts +0 -7
  88. package/dist_ts/protocols/common/index.js +0 -8
  89. package/dist_ts/protocols/common/types.d.ts +0 -68
  90. package/dist_ts/protocols/common/types.js +0 -7
  91. package/dist_ts/protocols/http/parser.d.ts +0 -58
  92. package/dist_ts/protocols/http/parser.js +0 -184
  93. package/dist_ts/protocols/proxy/index.d.ts +0 -5
  94. package/dist_ts/protocols/proxy/index.js +0 -6
  95. package/dist_ts/protocols/proxy/types.d.ts +0 -47
  96. package/dist_ts/protocols/proxy/types.js +0 -6
  97. package/dist_ts/protocols/tls/alerts/index.d.ts +0 -4
  98. package/dist_ts/protocols/tls/alerts/index.js +0 -5
  99. package/dist_ts/protocols/tls/alerts/tls-alert.d.ts +0 -150
  100. package/dist_ts/protocols/tls/alerts/tls-alert.js +0 -226
  101. package/dist_ts/protocols/tls/index.d.ts +0 -12
  102. package/dist_ts/protocols/tls/index.js +0 -27
  103. package/dist_ts/protocols/tls/sni/client-hello-parser.d.ts +0 -100
  104. package/dist_ts/protocols/tls/sni/client-hello-parser.js +0 -463
  105. package/dist_ts/protocols/tls/sni/index.d.ts +0 -5
  106. package/dist_ts/protocols/tls/sni/index.js +0 -6
  107. package/dist_ts/protocols/tls/sni/sni-extraction.d.ts +0 -58
  108. package/dist_ts/protocols/tls/sni/sni-extraction.js +0 -275
  109. package/dist_ts/protocols/tls/utils/index.d.ts +0 -4
  110. package/dist_ts/protocols/tls/utils/index.js +0 -5
  111. package/dist_ts/protocols/tls/utils/tls-utils.d.ts +0 -158
  112. package/dist_ts/protocols/tls/utils/tls-utils.js +0 -187
  113. package/dist_ts/protocols/websocket/constants.d.ts +0 -55
  114. package/dist_ts/protocols/websocket/constants.js +0 -58
  115. package/dist_ts/protocols/websocket/index.d.ts +0 -7
  116. package/dist_ts/protocols/websocket/index.js +0 -8
  117. package/dist_ts/protocols/websocket/types.d.ts +0 -47
  118. package/dist_ts/protocols/websocket/types.js +0 -5
  119. package/dist_ts/protocols/websocket/utils.d.ts +0 -25
  120. package/dist_ts/protocols/websocket/utils.js +0 -103
  121. package/dist_ts/routing/router/http-router.d.ts +0 -89
  122. package/dist_ts/routing/router/http-router.js +0 -205
  123. package/dist_ts/routing/router/index.d.ts +0 -5
  124. package/dist_ts/routing/router/index.js +0 -6
  125. package/dist_ts/tls/index.d.ts +0 -16
  126. package/dist_ts/tls/index.js +0 -24
  127. package/dist_ts/tls/sni/index.d.ts +0 -4
  128. package/dist_ts/tls/sni/index.js +0 -5
  129. package/dist_ts/tls/sni/sni-handler.d.ts +0 -154
  130. package/dist_ts/tls/sni/sni-handler.js +0 -191
  131. package/ts/core/events/index.ts +0 -3
  132. package/ts/core/models/socket-augmentation.ts +0 -38
  133. package/ts/core/utils/async-utils.ts +0 -275
  134. package/ts/core/utils/binary-heap.ts +0 -225
  135. package/ts/core/utils/enhanced-connection-pool.ts +0 -425
  136. package/ts/core/utils/fs-utils.ts +0 -270
  137. package/ts/core/utils/ip-utils.ts +0 -303
  138. package/ts/core/utils/lifecycle-component.ts +0 -251
  139. package/ts/core/utils/log-deduplicator.ts +0 -370
  140. package/ts/core/utils/security-utils.ts +0 -305
  141. package/ts/core/utils/shared-security-manager.ts +0 -470
  142. package/ts/core/utils/socket-utils.ts +0 -322
  143. package/ts/core/utils/template-utils.ts +0 -124
  144. package/ts/core/utils/validation-utils.ts +0 -177
  145. package/ts/core/utils/websocket-utils.ts +0 -33
  146. package/ts/detection/detectors/http-detector.ts +0 -127
  147. package/ts/detection/detectors/quick-detector.ts +0 -148
  148. package/ts/detection/detectors/routing-extractor.ts +0 -147
  149. package/ts/detection/detectors/tls-detector.ts +0 -223
  150. package/ts/detection/index.ts +0 -25
  151. package/ts/detection/models/detection-types.ts +0 -102
  152. package/ts/detection/models/interfaces.ts +0 -115
  153. package/ts/detection/protocol-detector.ts +0 -319
  154. package/ts/detection/utils/buffer-utils.ts +0 -141
  155. package/ts/detection/utils/fragment-manager.ts +0 -64
  156. package/ts/detection/utils/parser-utils.ts +0 -77
  157. package/ts/protocols/common/fragment-handler.ts +0 -167
  158. package/ts/protocols/common/index.ts +0 -8
  159. package/ts/protocols/common/types.ts +0 -76
  160. package/ts/protocols/http/parser.ts +0 -219
  161. package/ts/protocols/proxy/index.ts +0 -6
  162. package/ts/protocols/proxy/types.ts +0 -53
  163. package/ts/protocols/tls/alerts/index.ts +0 -3
  164. package/ts/protocols/tls/alerts/tls-alert.ts +0 -259
  165. package/ts/protocols/tls/index.ts +0 -37
  166. package/ts/protocols/tls/sni/client-hello-parser.ts +0 -629
  167. package/ts/protocols/tls/sni/index.ts +0 -6
  168. package/ts/protocols/tls/sni/sni-extraction.ts +0 -353
  169. package/ts/protocols/tls/utils/index.ts +0 -3
  170. package/ts/protocols/tls/utils/tls-utils.ts +0 -201
  171. package/ts/protocols/websocket/constants.ts +0 -60
  172. package/ts/protocols/websocket/index.ts +0 -8
  173. package/ts/protocols/websocket/types.ts +0 -53
  174. package/ts/protocols/websocket/utils.ts +0 -98
  175. package/ts/routing/router/http-router.ts +0 -266
  176. package/ts/routing/router/index.ts +0 -7
  177. package/ts/tls/index.ts +0 -29
  178. package/ts/tls/sni/index.ts +0 -3
  179. package/ts/tls/sni/sni-handler.ts +0 -264
@@ -4,5 +4,4 @@
4
4
  */
5
5
 
6
6
  export * from './constants.js';
7
- export * from './types.js';
8
- export * from './parser.js';
7
+ export * from './types.js';
@@ -1,12 +1,5 @@
1
1
  /**
2
2
  * Protocol-specific modules for smartproxy
3
- *
4
- * This directory contains generic protocol knowledge separated from
5
- * smartproxy-specific implementation details.
6
3
  */
7
4
 
8
- export * as common from './common/index.js';
9
- export * as tls from './tls/index.js';
10
5
  export * as http from './http/index.js';
11
- export * as proxy from './proxy/index.js';
12
- export * as websocket from './websocket/index.js';
@@ -274,6 +274,12 @@ export class SocketHandlerServer {
274
274
  backend.pipe(socket);
275
275
  });
276
276
 
277
+ // Track backend socket for cleanup on stop()
278
+ this.activeSockets.add(backend);
279
+ backend.on('close', () => {
280
+ this.activeSockets.delete(backend);
281
+ });
282
+
277
283
  // Connect timeout: if backend doesn't connect within 30s, destroy both
278
284
  backend.setTimeout(30_000);
279
285
 
@@ -7,9 +7,54 @@
7
7
 
8
8
  import * as plugins from '../../../../plugins.js';
9
9
  import type { IRouteConfig, TPortRange, IRouteContext } from '../../models/route-types.js';
10
- import { ProtocolDetector } from '../../../../detection/index.js';
11
10
  import { createSocketTracker } from '../../../../core/utils/socket-tracker.js';
12
11
 
12
+ /**
13
+ * Minimal HTTP request parser for socket handlers.
14
+ * Parses method, path, and optionally headers from a raw buffer.
15
+ */
16
+ function parseHttpRequest(data: Buffer, extractHeaders: boolean = false): {
17
+ method: string;
18
+ path: string;
19
+ headers: Record<string, string>;
20
+ isComplete: boolean;
21
+ body?: string;
22
+ } | null {
23
+ const str = data.toString('utf8');
24
+ const headerEnd = str.indexOf('\r\n\r\n');
25
+ const isComplete = headerEnd !== -1;
26
+ const headerSection = isComplete ? str.slice(0, headerEnd) : str;
27
+ const lines = headerSection.split('\r\n');
28
+ const requestLine = lines[0];
29
+ if (!requestLine) return null;
30
+
31
+ const parts = requestLine.split(' ');
32
+ if (parts.length < 2) return null;
33
+
34
+ const method = parts[0];
35
+ const path = parts[1];
36
+
37
+ // Quick check: valid HTTP method
38
+ const validMethods = ['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'HEAD', 'OPTIONS', 'CONNECT', 'TRACE'];
39
+ if (!validMethods.includes(method)) return null;
40
+
41
+ const headers: Record<string, string> = {};
42
+ if (extractHeaders) {
43
+ for (let i = 1; i < lines.length; i++) {
44
+ const colonIdx = lines[i].indexOf(':');
45
+ if (colonIdx > 0) {
46
+ const name = lines[i].slice(0, colonIdx).trim().toLowerCase();
47
+ const value = lines[i].slice(colonIdx + 1).trim();
48
+ headers[name] = value;
49
+ }
50
+ }
51
+ }
52
+
53
+ const body = isComplete ? str.slice(headerEnd + 4) : undefined;
54
+
55
+ return { method, path, headers, isComplete, body };
56
+ }
57
+
13
58
  /**
14
59
  * Pre-built socket handlers for common use cases
15
60
  */
@@ -104,30 +149,19 @@ export const SocketHandlers = {
104
149
 
105
150
  /**
106
151
  * HTTP redirect handler
107
- * Uses the centralized detection module for HTTP parsing
108
152
  */
109
153
  httpRedirect: (locationTemplate: string, statusCode: number = 301) => (socket: plugins.net.Socket, context: IRouteContext) => {
110
154
  const tracker = createSocketTracker(socket);
111
- const connectionId = ProtocolDetector.createConnectionId({
112
- socketId: context.connectionId || `${Date.now()}-${Math.random()}`
113
- });
114
-
115
- const handleData = async (data: Buffer) => {
116
- // Use detection module for parsing
117
- const detectionResult = await ProtocolDetector.detectWithConnectionTracking(
118
- data,
119
- connectionId,
120
- { extractFullHeaders: false } // We only need method and path
121
- );
122
155
 
123
- if (detectionResult.protocol === 'http' && detectionResult.connectionInfo.path) {
124
- const method = detectionResult.connectionInfo.method || 'GET';
125
- const path = detectionResult.connectionInfo.path || '/';
156
+ const handleData = (data: Buffer) => {
157
+ const parsed = parseHttpRequest(data);
126
158
 
159
+ if (parsed) {
160
+ const path = parsed.path || '/';
127
161
  const domain = context.domain || 'localhost';
128
162
  const port = context.port;
129
163
 
130
- let finalLocation = locationTemplate
164
+ const finalLocation = locationTemplate
131
165
  .replace('{domain}', domain)
132
166
  .replace('{port}', String(port))
133
167
  .replace('{path}', path)
@@ -146,18 +180,13 @@ export const SocketHandlers = {
146
180
 
147
181
  socket.write(response);
148
182
  } else {
149
- // Not a valid HTTP request, close connection
150
183
  socket.write('HTTP/1.1 400 Bad Request\r\nConnection: close\r\n\r\n');
151
184
  }
152
185
 
153
186
  socket.end();
154
- // Clean up detection state
155
- ProtocolDetector.cleanupConnections();
156
- // Clean up all tracked resources
157
187
  tracker.cleanup();
158
188
  };
159
189
 
160
- // Use tracker to manage the listener
161
190
  socket.once('data', handleData);
162
191
 
163
192
  tracker.addListener('error', (err) => {
@@ -171,45 +200,31 @@ export const SocketHandlers = {
171
200
 
172
201
  /**
173
202
  * HTTP server handler for ACME challenges and other HTTP needs
174
- * Uses the centralized detection module for HTTP parsing
175
203
  */
176
204
  httpServer: (handler: (req: { method: string; url: string; headers: Record<string, string>; body?: string }, res: { status: (code: number) => void; header: (name: string, value: string) => void; send: (data: string) => void; end: () => void }) => void) => (socket: plugins.net.Socket, context: IRouteContext) => {
177
205
  const tracker = createSocketTracker(socket);
178
206
  let requestParsed = false;
179
207
  let responseTimer: NodeJS.Timeout | null = null;
180
- const connectionId = ProtocolDetector.createConnectionId({
181
- socketId: context.connectionId || `${Date.now()}-${Math.random()}`
182
- });
183
208
 
184
- const processData = async (data: Buffer) => {
185
- if (requestParsed) return; // Only handle the first request
209
+ const processData = (data: Buffer) => {
210
+ if (requestParsed) return;
186
211
 
187
- // Use HttpDetector for parsing
188
- const detectionResult = await ProtocolDetector.detectWithConnectionTracking(
189
- data,
190
- connectionId,
191
- { extractFullHeaders: true }
192
- );
212
+ const parsed = parseHttpRequest(data, true);
193
213
 
194
- if (detectionResult.protocol !== 'http' || !detectionResult.isComplete) {
195
- // Not a complete HTTP request yet
196
- return;
214
+ if (!parsed || !parsed.isComplete) {
215
+ return; // Not a complete HTTP request yet
197
216
  }
198
217
 
199
218
  requestParsed = true;
200
- // Remove data listener after parsing request
201
219
  socket.removeListener('data', processData);
202
- const connInfo = detectionResult.connectionInfo;
203
220
 
204
- // Create request object from detection result
205
221
  const req = {
206
- method: connInfo.method || 'GET',
207
- url: connInfo.path || '/',
208
- headers: connInfo.headers || {},
209
- body: detectionResult.remainingBuffer?.toString() || ''
222
+ method: parsed.method,
223
+ url: parsed.path,
224
+ headers: parsed.headers,
225
+ body: parsed.body || ''
210
226
  };
211
227
 
212
- // Create response object
213
228
  let statusCode = 200;
214
229
  const responseHeaders: Record<string, string> = {};
215
230
  let ended = false;
@@ -225,7 +240,6 @@ export const SocketHandlers = {
225
240
  if (ended) return;
226
241
  ended = true;
227
242
 
228
- // Clear response timer since we're sending now
229
243
  if (responseTimer) {
230
244
  clearTimeout(responseTimer);
231
245
  responseTimer = null;
@@ -261,26 +275,22 @@ export const SocketHandlers = {
261
275
 
262
276
  try {
263
277
  handler(req, res);
264
- // Ensure response is sent even if handler doesn't call send()
265
278
  responseTimer = setTimeout(() => {
266
279
  if (!ended) {
267
280
  res.send('');
268
281
  }
269
282
  responseTimer = null;
270
283
  }, 1000);
271
- // Track and unref the timer
272
284
  tracker.addTimer(responseTimer);
273
285
  } catch (error) {
274
286
  if (!ended) {
275
287
  res.status(500);
276
288
  res.send('Internal Server Error');
277
289
  }
278
- // Use safeDestroy for error cases
279
290
  tracker.safeDestroy(error instanceof Error ? error : new Error('Handler error'));
280
291
  }
281
292
  };
282
293
 
283
- // Use tracker to manage listeners
284
294
  tracker.addListener('data', processData);
285
295
 
286
296
  tracker.addListener('error', (err) => {
@@ -290,14 +300,10 @@ export const SocketHandlers = {
290
300
  });
291
301
 
292
302
  tracker.addListener('close', () => {
293
- // Clear any pending response timer
294
303
  if (responseTimer) {
295
304
  clearTimeout(responseTimer);
296
305
  responseTimer = null;
297
306
  }
298
- // Clean up detection state
299
- ProtocolDetector.cleanupConnections();
300
- // Clean up all tracked resources
301
307
  tracker.cleanup();
302
308
  });
303
309
  }
@@ -305,11 +311,6 @@ export const SocketHandlers = {
305
311
 
306
312
  /**
307
313
  * Create a socket handler route configuration
308
- * @param domains Domain(s) to match
309
- * @param ports Port(s) to listen on
310
- * @param handler Socket handler function
311
- * @param options Additional route options
312
- * @returns Route configuration object
313
314
  */
314
315
  export function createSocketHandlerRoute(
315
316
  domains: string | string[],
@@ -4,6 +4,3 @@
4
4
 
5
5
  // Export types and models
6
6
  export * from './models/http-types.js';
7
-
8
- // Export router functionality
9
- export * from './router/index.js';
@@ -1,4 +0,0 @@
1
- export {};
2
- /**
3
- * Common event definitions
4
- */
@@ -1,5 +0,0 @@
1
- export {};
2
- /**
3
- * Common event definitions
4
- */
5
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi90cy9jb3JlL2V2ZW50cy9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUE7O0dBRUcifQ==
@@ -1,15 +0,0 @@
1
- import * as plugins from '../../plugins.js';
2
- declare module 'net' {
3
- interface Socket {
4
- encrypted?: boolean;
5
- authorizationError?: Error;
6
- getTLSVersion?(): string;
7
- getPeerCertificate?(detailed?: boolean): any;
8
- getSession?(): Buffer;
9
- _connectionId?: string;
10
- _remoteIP?: string;
11
- _realRemoteIP?: string;
12
- }
13
- }
14
- export declare function isTLSSocket(socket: plugins.net.Socket): boolean;
15
- export declare function getTLSVersion(socket: plugins.net.Socket): string | null;
@@ -1,18 +0,0 @@
1
- import * as plugins from '../../plugins.js';
2
- // Export a utility function to check if a socket is a TLS socket
3
- export function isTLSSocket(socket) {
4
- return 'encrypted' in socket && !!socket.encrypted;
5
- }
6
- // Export a utility function to safely get the TLS version
7
- export function getTLSVersion(socket) {
8
- if (socket.getTLSVersion) {
9
- try {
10
- return socket.getTLSVersion();
11
- }
12
- catch (e) {
13
- return null;
14
- }
15
- }
16
- return null;
17
- }
18
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic29ja2V0LWF1Z21lbnRhdGlvbi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3RzL2NvcmUvbW9kZWxzL3NvY2tldC1hdWdtZW50YXRpb24udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxLQUFLLE9BQU8sTUFBTSxrQkFBa0IsQ0FBQztBQXNCNUMsaUVBQWlFO0FBQ2pFLE1BQU0sVUFBVSxXQUFXLENBQUMsTUFBMEI7SUFDcEQsT0FBTyxXQUFXLElBQUksTUFBTSxJQUFJLENBQUMsQ0FBQyxNQUFNLENBQUMsU0FBUyxDQUFDO0FBQ3JELENBQUM7QUFFRCwwREFBMEQ7QUFDMUQsTUFBTSxVQUFVLGFBQWEsQ0FBQyxNQUEwQjtJQUN0RCxJQUFJLE1BQU0sQ0FBQyxhQUFhLEVBQUUsQ0FBQztRQUN6QixJQUFJLENBQUM7WUFDSCxPQUFPLE1BQU0sQ0FBQyxhQUFhLEVBQUUsQ0FBQztRQUNoQyxDQUFDO1FBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQztZQUNYLE9BQU8sSUFBSSxDQUFDO1FBQ2QsQ0FBQztJQUNILENBQUM7SUFDRCxPQUFPLElBQUksQ0FBQztBQUNkLENBQUMifQ==
@@ -1,81 +0,0 @@
1
- /**
2
- * Async utility functions for SmartProxy
3
- * Provides non-blocking alternatives to synchronous operations
4
- */
5
- /**
6
- * Delays execution for the specified number of milliseconds
7
- * Non-blocking alternative to busy wait loops
8
- * @param ms - Number of milliseconds to delay
9
- * @returns Promise that resolves after the delay
10
- */
11
- export declare function delay(ms: number): Promise<void>;
12
- /**
13
- * Retry an async operation with exponential backoff
14
- * @param fn - The async function to retry
15
- * @param options - Retry options
16
- * @returns The result of the function or throws the last error
17
- */
18
- export declare function retryWithBackoff<T>(fn: () => Promise<T>, options?: {
19
- maxAttempts?: number;
20
- initialDelay?: number;
21
- maxDelay?: number;
22
- factor?: number;
23
- onRetry?: (attempt: number, error: Error) => void;
24
- }): Promise<T>;
25
- /**
26
- * Execute an async operation with a timeout
27
- * @param fn - The async function to execute
28
- * @param timeoutMs - Timeout in milliseconds
29
- * @param timeoutError - Optional custom timeout error
30
- * @returns The result of the function or throws timeout error
31
- */
32
- export declare function withTimeout<T>(fn: () => Promise<T>, timeoutMs: number, timeoutError?: Error): Promise<T>;
33
- /**
34
- * Run multiple async operations in parallel with a concurrency limit
35
- * @param items - Array of items to process
36
- * @param fn - Async function to run for each item
37
- * @param concurrency - Maximum number of concurrent operations
38
- * @returns Array of results in the same order as input
39
- */
40
- export declare function parallelLimit<T, R>(items: T[], fn: (item: T, index: number) => Promise<R>, concurrency: number): Promise<R[]>;
41
- /**
42
- * Debounce an async function
43
- * @param fn - The async function to debounce
44
- * @param delayMs - Delay in milliseconds
45
- * @returns Debounced function with cancel method
46
- */
47
- export declare function debounceAsync<T extends (...args: any[]) => Promise<any>>(fn: T, delayMs: number): T & {
48
- cancel: () => void;
49
- };
50
- /**
51
- * Create a mutex for ensuring exclusive access to a resource
52
- */
53
- export declare class AsyncMutex {
54
- private queue;
55
- private locked;
56
- acquire(): Promise<() => void>;
57
- private release;
58
- runExclusive<T>(fn: () => Promise<T>): Promise<T>;
59
- }
60
- /**
61
- * Circuit breaker for protecting against cascading failures
62
- */
63
- export declare class CircuitBreaker {
64
- private options;
65
- private failureCount;
66
- private lastFailureTime;
67
- private state;
68
- constructor(options: {
69
- failureThreshold: number;
70
- resetTimeout: number;
71
- onStateChange?: (state: 'closed' | 'open' | 'half-open') => void;
72
- });
73
- execute<T>(fn: () => Promise<T>): Promise<T>;
74
- private onSuccess;
75
- private onFailure;
76
- private setState;
77
- isOpen(): boolean;
78
- getState(): 'closed' | 'open' | 'half-open';
79
- recordSuccess(): void;
80
- recordFailure(): void;
81
- }
@@ -1,216 +0,0 @@
1
- /**
2
- * Async utility functions for SmartProxy
3
- * Provides non-blocking alternatives to synchronous operations
4
- */
5
- /**
6
- * Delays execution for the specified number of milliseconds
7
- * Non-blocking alternative to busy wait loops
8
- * @param ms - Number of milliseconds to delay
9
- * @returns Promise that resolves after the delay
10
- */
11
- export async function delay(ms) {
12
- return new Promise(resolve => setTimeout(resolve, ms));
13
- }
14
- /**
15
- * Retry an async operation with exponential backoff
16
- * @param fn - The async function to retry
17
- * @param options - Retry options
18
- * @returns The result of the function or throws the last error
19
- */
20
- export async function retryWithBackoff(fn, options = {}) {
21
- const { maxAttempts = 3, initialDelay = 100, maxDelay = 10000, factor = 2, onRetry } = options;
22
- let lastError = null;
23
- let currentDelay = initialDelay;
24
- for (let attempt = 1; attempt <= maxAttempts; attempt++) {
25
- try {
26
- return await fn();
27
- }
28
- catch (error) {
29
- lastError = error;
30
- if (attempt === maxAttempts) {
31
- throw error;
32
- }
33
- if (onRetry) {
34
- onRetry(attempt, error);
35
- }
36
- await delay(currentDelay);
37
- currentDelay = Math.min(currentDelay * factor, maxDelay);
38
- }
39
- }
40
- throw lastError || new Error('Retry failed');
41
- }
42
- /**
43
- * Execute an async operation with a timeout
44
- * @param fn - The async function to execute
45
- * @param timeoutMs - Timeout in milliseconds
46
- * @param timeoutError - Optional custom timeout error
47
- * @returns The result of the function or throws timeout error
48
- */
49
- export async function withTimeout(fn, timeoutMs, timeoutError) {
50
- const timeoutPromise = new Promise((_, reject) => {
51
- setTimeout(() => {
52
- reject(timeoutError || new Error(`Operation timed out after ${timeoutMs}ms`));
53
- }, timeoutMs);
54
- });
55
- return Promise.race([fn(), timeoutPromise]);
56
- }
57
- /**
58
- * Run multiple async operations in parallel with a concurrency limit
59
- * @param items - Array of items to process
60
- * @param fn - Async function to run for each item
61
- * @param concurrency - Maximum number of concurrent operations
62
- * @returns Array of results in the same order as input
63
- */
64
- export async function parallelLimit(items, fn, concurrency) {
65
- const results = new Array(items.length);
66
- const executing = new Set();
67
- for (let i = 0; i < items.length; i++) {
68
- const promise = fn(items[i], i).then(result => {
69
- results[i] = result;
70
- executing.delete(promise);
71
- });
72
- executing.add(promise);
73
- if (executing.size >= concurrency) {
74
- await Promise.race(executing);
75
- }
76
- }
77
- await Promise.all(executing);
78
- return results;
79
- }
80
- /**
81
- * Debounce an async function
82
- * @param fn - The async function to debounce
83
- * @param delayMs - Delay in milliseconds
84
- * @returns Debounced function with cancel method
85
- */
86
- export function debounceAsync(fn, delayMs) {
87
- let timeoutId = null;
88
- let lastPromise = null;
89
- const debounced = ((...args) => {
90
- if (timeoutId) {
91
- clearTimeout(timeoutId);
92
- }
93
- lastPromise = new Promise((resolve, reject) => {
94
- timeoutId = setTimeout(async () => {
95
- timeoutId = null;
96
- try {
97
- const result = await fn(...args);
98
- resolve(result);
99
- }
100
- catch (error) {
101
- reject(error);
102
- }
103
- }, delayMs);
104
- });
105
- return lastPromise;
106
- });
107
- debounced.cancel = () => {
108
- if (timeoutId) {
109
- clearTimeout(timeoutId);
110
- timeoutId = null;
111
- }
112
- };
113
- return debounced;
114
- }
115
- /**
116
- * Create a mutex for ensuring exclusive access to a resource
117
- */
118
- export class AsyncMutex {
119
- constructor() {
120
- this.queue = [];
121
- this.locked = false;
122
- }
123
- async acquire() {
124
- if (!this.locked) {
125
- this.locked = true;
126
- return () => this.release();
127
- }
128
- return new Promise(resolve => {
129
- this.queue.push(() => {
130
- resolve(() => this.release());
131
- });
132
- });
133
- }
134
- release() {
135
- const next = this.queue.shift();
136
- if (next) {
137
- next();
138
- }
139
- else {
140
- this.locked = false;
141
- }
142
- }
143
- async runExclusive(fn) {
144
- const release = await this.acquire();
145
- try {
146
- return await fn();
147
- }
148
- finally {
149
- release();
150
- }
151
- }
152
- }
153
- /**
154
- * Circuit breaker for protecting against cascading failures
155
- */
156
- export class CircuitBreaker {
157
- constructor(options) {
158
- this.options = options;
159
- this.failureCount = 0;
160
- this.lastFailureTime = 0;
161
- this.state = 'closed';
162
- }
163
- async execute(fn) {
164
- if (this.state === 'open') {
165
- if (Date.now() - this.lastFailureTime > this.options.resetTimeout) {
166
- this.setState('half-open');
167
- }
168
- else {
169
- throw new Error('Circuit breaker is open');
170
- }
171
- }
172
- try {
173
- const result = await fn();
174
- this.onSuccess();
175
- return result;
176
- }
177
- catch (error) {
178
- this.onFailure();
179
- throw error;
180
- }
181
- }
182
- onSuccess() {
183
- this.failureCount = 0;
184
- if (this.state !== 'closed') {
185
- this.setState('closed');
186
- }
187
- }
188
- onFailure() {
189
- this.failureCount++;
190
- this.lastFailureTime = Date.now();
191
- if (this.failureCount >= this.options.failureThreshold) {
192
- this.setState('open');
193
- }
194
- }
195
- setState(state) {
196
- if (this.state !== state) {
197
- this.state = state;
198
- if (this.options.onStateChange) {
199
- this.options.onStateChange(state);
200
- }
201
- }
202
- }
203
- isOpen() {
204
- return this.state === 'open';
205
- }
206
- getState() {
207
- return this.state;
208
- }
209
- recordSuccess() {
210
- this.onSuccess();
211
- }
212
- recordFailure() {
213
- this.onFailure();
214
- }
215
- }
216
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXN5bmMtdXRpbHMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi90cy9jb3JlL3V0aWxzL2FzeW5jLXV0aWxzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7R0FHRztBQUVIOzs7OztHQUtHO0FBQ0gsTUFBTSxDQUFDLEtBQUssVUFBVSxLQUFLLENBQUMsRUFBVTtJQUNwQyxPQUFPLElBQUksT0FBTyxDQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUMsVUFBVSxDQUFDLE9BQU8sRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDO0FBQ3pELENBQUM7QUFFRDs7Ozs7R0FLRztBQUNILE1BQU0sQ0FBQyxLQUFLLFVBQVUsZ0JBQWdCLENBQ3BDLEVBQW9CLEVBQ3BCLFVBTUksRUFBRTtJQUVOLE1BQU0sRUFDSixXQUFXLEdBQUcsQ0FBQyxFQUNmLFlBQVksR0FBRyxHQUFHLEVBQ2xCLFFBQVEsR0FBRyxLQUFLLEVBQ2hCLE1BQU0sR0FBRyxDQUFDLEVBQ1YsT0FBTyxFQUNSLEdBQUcsT0FBTyxDQUFDO0lBRVosSUFBSSxTQUFTLEdBQWlCLElBQUksQ0FBQztJQUNuQyxJQUFJLFlBQVksR0FBRyxZQUFZLENBQUM7SUFFaEMsS0FBSyxJQUFJLE9BQU8sR0FBRyxDQUFDLEVBQUUsT0FBTyxJQUFJLFdBQVcsRUFBRSxPQUFPLEVBQUUsRUFBRSxDQUFDO1FBQ3hELElBQUksQ0FBQztZQUNILE9BQU8sTUFBTSxFQUFFLEVBQUUsQ0FBQztRQUNwQixDQUFDO1FBQUMsT0FBTyxLQUFVLEVBQUUsQ0FBQztZQUNwQixTQUFTLEdBQUcsS0FBSyxDQUFDO1lBRWxCLElBQUksT0FBTyxLQUFLLFdBQVcsRUFBRSxDQUFDO2dCQUM1QixNQUFNLEtBQUssQ0FBQztZQUNkLENBQUM7WUFFRCxJQUFJLE9BQU8sRUFBRSxDQUFDO2dCQUNaLE9BQU8sQ0FBQyxPQUFPLEVBQUUsS0FBSyxDQUFDLENBQUM7WUFDMUIsQ0FBQztZQUVELE1BQU0sS0FBSyxDQUFDLFlB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