@push.rocks/smartproxy 25.17.9 → 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.
- package/changelog.md +16 -0
- package/dist_rust/rustproxy_linux_amd64 +0 -0
- package/dist_rust/rustproxy_linux_arm64 +0 -0
- package/dist_ts/00_commitinfo_data.js +2 -2
- package/dist_ts/core/index.d.ts +0 -1
- package/dist_ts/core/index.js +1 -2
- package/dist_ts/core/models/index.d.ts +0 -1
- package/dist_ts/core/models/index.js +1 -2
- package/dist_ts/core/utils/index.d.ts +0 -12
- package/dist_ts/core/utils/index.js +1 -13
- package/dist_ts/index.d.ts +0 -3
- package/dist_ts/index.js +2 -7
- package/dist_ts/protocols/http/index.d.ts +0 -1
- package/dist_ts/protocols/http/index.js +1 -2
- package/dist_ts/protocols/index.d.ts +0 -7
- package/dist_ts/protocols/index.js +1 -8
- package/dist_ts/proxies/smart-proxy/socket-handler-server.js +6 -1
- package/dist_ts/proxies/smart-proxy/utils/route-helpers/socket-handlers.d.ts +0 -7
- package/dist_ts/proxies/smart-proxy/utils/route-helpers/socket-handlers.js +50 -51
- package/dist_ts/routing/index.d.ts +0 -1
- package/dist_ts/routing/index.js +1 -3
- package/package.json +1 -1
- package/ts/00_commitinfo_data.ts +1 -1
- package/ts/core/index.ts +0 -1
- package/ts/core/models/index.ts +0 -1
- package/ts/core/utils/index.ts +0 -12
- package/ts/index.ts +1 -7
- package/ts/protocols/http/index.ts +1 -2
- package/ts/protocols/index.ts +0 -7
- package/ts/proxies/smart-proxy/socket-handler-server.ts +6 -0
- package/ts/proxies/smart-proxy/utils/route-helpers/socket-handlers.ts +60 -59
- package/ts/routing/index.ts +0 -3
- package/dist_ts/core/events/index.d.ts +0 -4
- package/dist_ts/core/events/index.js +0 -5
- package/dist_ts/core/models/socket-augmentation.d.ts +0 -15
- package/dist_ts/core/models/socket-augmentation.js +0 -18
- package/dist_ts/core/utils/async-utils.d.ts +0 -81
- package/dist_ts/core/utils/async-utils.js +0 -216
- package/dist_ts/core/utils/binary-heap.d.ts +0 -73
- package/dist_ts/core/utils/binary-heap.js +0 -193
- package/dist_ts/core/utils/enhanced-connection-pool.d.ts +0 -110
- package/dist_ts/core/utils/enhanced-connection-pool.js +0 -325
- package/dist_ts/core/utils/fs-utils.d.ts +0 -144
- package/dist_ts/core/utils/fs-utils.js +0 -252
- package/dist_ts/core/utils/ip-utils.d.ts +0 -69
- package/dist_ts/core/utils/ip-utils.js +0 -270
- package/dist_ts/core/utils/lifecycle-component.d.ts +0 -59
- package/dist_ts/core/utils/lifecycle-component.js +0 -211
- package/dist_ts/core/utils/log-deduplicator.d.ts +0 -39
- package/dist_ts/core/utils/log-deduplicator.js +0 -305
- package/dist_ts/core/utils/security-utils.d.ts +0 -111
- package/dist_ts/core/utils/security-utils.js +0 -212
- package/dist_ts/core/utils/shared-security-manager.d.ts +0 -128
- package/dist_ts/core/utils/shared-security-manager.js +0 -362
- package/dist_ts/core/utils/socket-utils.d.ts +0 -63
- package/dist_ts/core/utils/socket-utils.js +0 -249
- package/dist_ts/core/utils/template-utils.d.ts +0 -37
- package/dist_ts/core/utils/template-utils.js +0 -104
- package/dist_ts/core/utils/validation-utils.d.ts +0 -61
- package/dist_ts/core/utils/validation-utils.js +0 -149
- package/dist_ts/core/utils/websocket-utils.d.ts +0 -22
- package/dist_ts/core/utils/websocket-utils.js +0 -30
- package/dist_ts/detection/detectors/http-detector.d.ts +0 -33
- package/dist_ts/detection/detectors/http-detector.js +0 -101
- package/dist_ts/detection/detectors/quick-detector.d.ts +0 -28
- package/dist_ts/detection/detectors/quick-detector.js +0 -131
- package/dist_ts/detection/detectors/routing-extractor.d.ts +0 -28
- package/dist_ts/detection/detectors/routing-extractor.js +0 -122
- package/dist_ts/detection/detectors/tls-detector.d.ts +0 -47
- package/dist_ts/detection/detectors/tls-detector.js +0 -183
- package/dist_ts/detection/index.d.ts +0 -17
- package/dist_ts/detection/index.js +0 -22
- package/dist_ts/detection/models/detection-types.d.ts +0 -87
- package/dist_ts/detection/models/detection-types.js +0 -5
- package/dist_ts/detection/models/interfaces.d.ts +0 -97
- package/dist_ts/detection/models/interfaces.js +0 -5
- package/dist_ts/detection/protocol-detector.d.ts +0 -79
- package/dist_ts/detection/protocol-detector.js +0 -253
- package/dist_ts/detection/utils/buffer-utils.d.ts +0 -61
- package/dist_ts/detection/utils/buffer-utils.js +0 -127
- package/dist_ts/detection/utils/fragment-manager.d.ts +0 -31
- package/dist_ts/detection/utils/fragment-manager.js +0 -53
- package/dist_ts/detection/utils/parser-utils.d.ts +0 -42
- package/dist_ts/detection/utils/parser-utils.js +0 -63
- package/dist_ts/protocols/common/fragment-handler.d.ts +0 -73
- package/dist_ts/protocols/common/fragment-handler.js +0 -121
- package/dist_ts/protocols/common/index.d.ts +0 -7
- package/dist_ts/protocols/common/index.js +0 -8
- package/dist_ts/protocols/common/types.d.ts +0 -68
- package/dist_ts/protocols/common/types.js +0 -7
- package/dist_ts/protocols/http/parser.d.ts +0 -58
- package/dist_ts/protocols/http/parser.js +0 -184
- package/dist_ts/protocols/proxy/index.d.ts +0 -5
- package/dist_ts/protocols/proxy/index.js +0 -6
- package/dist_ts/protocols/proxy/types.d.ts +0 -47
- package/dist_ts/protocols/proxy/types.js +0 -6
- package/dist_ts/protocols/tls/alerts/index.d.ts +0 -4
- package/dist_ts/protocols/tls/alerts/index.js +0 -5
- package/dist_ts/protocols/tls/alerts/tls-alert.d.ts +0 -150
- package/dist_ts/protocols/tls/alerts/tls-alert.js +0 -226
- package/dist_ts/protocols/tls/index.d.ts +0 -12
- package/dist_ts/protocols/tls/index.js +0 -27
- package/dist_ts/protocols/tls/sni/client-hello-parser.d.ts +0 -100
- package/dist_ts/protocols/tls/sni/client-hello-parser.js +0 -463
- package/dist_ts/protocols/tls/sni/index.d.ts +0 -5
- package/dist_ts/protocols/tls/sni/index.js +0 -6
- package/dist_ts/protocols/tls/sni/sni-extraction.d.ts +0 -58
- package/dist_ts/protocols/tls/sni/sni-extraction.js +0 -275
- package/dist_ts/protocols/tls/utils/index.d.ts +0 -4
- package/dist_ts/protocols/tls/utils/index.js +0 -5
- package/dist_ts/protocols/tls/utils/tls-utils.d.ts +0 -158
- package/dist_ts/protocols/tls/utils/tls-utils.js +0 -187
- package/dist_ts/protocols/websocket/constants.d.ts +0 -55
- package/dist_ts/protocols/websocket/constants.js +0 -58
- package/dist_ts/protocols/websocket/index.d.ts +0 -7
- package/dist_ts/protocols/websocket/index.js +0 -8
- package/dist_ts/protocols/websocket/types.d.ts +0 -47
- package/dist_ts/protocols/websocket/types.js +0 -5
- package/dist_ts/protocols/websocket/utils.d.ts +0 -25
- package/dist_ts/protocols/websocket/utils.js +0 -103
- package/dist_ts/routing/router/http-router.d.ts +0 -89
- package/dist_ts/routing/router/http-router.js +0 -205
- package/dist_ts/routing/router/index.d.ts +0 -5
- package/dist_ts/routing/router/index.js +0 -6
- package/dist_ts/tls/index.d.ts +0 -16
- package/dist_ts/tls/index.js +0 -24
- package/dist_ts/tls/sni/index.d.ts +0 -4
- package/dist_ts/tls/sni/index.js +0 -5
- package/dist_ts/tls/sni/sni-handler.d.ts +0 -154
- package/dist_ts/tls/sni/sni-handler.js +0 -191
- package/ts/core/events/index.ts +0 -3
- package/ts/core/models/socket-augmentation.ts +0 -38
- package/ts/core/utils/async-utils.ts +0 -275
- package/ts/core/utils/binary-heap.ts +0 -225
- package/ts/core/utils/enhanced-connection-pool.ts +0 -425
- package/ts/core/utils/fs-utils.ts +0 -270
- package/ts/core/utils/ip-utils.ts +0 -303
- package/ts/core/utils/lifecycle-component.ts +0 -251
- package/ts/core/utils/log-deduplicator.ts +0 -370
- package/ts/core/utils/security-utils.ts +0 -305
- package/ts/core/utils/shared-security-manager.ts +0 -470
- package/ts/core/utils/socket-utils.ts +0 -322
- package/ts/core/utils/template-utils.ts +0 -124
- package/ts/core/utils/validation-utils.ts +0 -177
- package/ts/core/utils/websocket-utils.ts +0 -33
- package/ts/detection/detectors/http-detector.ts +0 -127
- package/ts/detection/detectors/quick-detector.ts +0 -148
- package/ts/detection/detectors/routing-extractor.ts +0 -147
- package/ts/detection/detectors/tls-detector.ts +0 -223
- package/ts/detection/index.ts +0 -25
- package/ts/detection/models/detection-types.ts +0 -102
- package/ts/detection/models/interfaces.ts +0 -115
- package/ts/detection/protocol-detector.ts +0 -319
- package/ts/detection/utils/buffer-utils.ts +0 -141
- package/ts/detection/utils/fragment-manager.ts +0 -64
- package/ts/detection/utils/parser-utils.ts +0 -77
- package/ts/protocols/common/fragment-handler.ts +0 -167
- package/ts/protocols/common/index.ts +0 -8
- package/ts/protocols/common/types.ts +0 -76
- package/ts/protocols/http/parser.ts +0 -219
- package/ts/protocols/proxy/index.ts +0 -6
- package/ts/protocols/proxy/types.ts +0 -53
- package/ts/protocols/tls/alerts/index.ts +0 -3
- package/ts/protocols/tls/alerts/tls-alert.ts +0 -259
- package/ts/protocols/tls/index.ts +0 -37
- package/ts/protocols/tls/sni/client-hello-parser.ts +0 -629
- package/ts/protocols/tls/sni/index.ts +0 -6
- package/ts/protocols/tls/sni/sni-extraction.ts +0 -353
- package/ts/protocols/tls/utils/index.ts +0 -3
- package/ts/protocols/tls/utils/tls-utils.ts +0 -201
- package/ts/protocols/websocket/constants.ts +0 -60
- package/ts/protocols/websocket/index.ts +0 -8
- package/ts/protocols/websocket/types.ts +0 -53
- package/ts/protocols/websocket/utils.ts +0 -98
- package/ts/routing/router/http-router.ts +0 -266
- package/ts/routing/router/index.ts +0 -7
- package/ts/tls/index.ts +0 -29
- package/ts/tls/sni/index.ts +0 -3
- package/ts/tls/sni/sni-handler.ts +0 -264
package/ts/index.ts
CHANGED
|
@@ -11,18 +11,12 @@ export type { ISmartProxyOptions, IConnectionRecord, IRouteConfig, IRouteMatch,
|
|
|
11
11
|
export type { TSmartProxyCertProvisionObject, ICertProvisionEventComms, ICertificateIssuedEvent, ICertificateFailedEvent } from './proxies/smart-proxy/models/interfaces.js';
|
|
12
12
|
export * from './proxies/smart-proxy/utils/index.js';
|
|
13
13
|
|
|
14
|
-
// Original: export * from './smartproxy/classes.pp.snihandler.js'
|
|
15
|
-
// Now we export from the new module
|
|
16
|
-
export { SniHandler } from './tls/sni/sni-handler.js';
|
|
17
|
-
|
|
18
14
|
// Core types and utilities
|
|
19
15
|
export * from './core/models/common-types.js';
|
|
20
16
|
|
|
21
17
|
// Export IAcmeOptions from one place only
|
|
22
18
|
export type { IAcmeOptions } from './proxies/smart-proxy/models/interfaces.js';
|
|
23
19
|
|
|
24
|
-
// Modular exports
|
|
25
|
-
export * as tls from './tls/index.js';
|
|
20
|
+
// Modular exports
|
|
26
21
|
export * as routing from './routing/index.js';
|
|
27
|
-
export * as detection from './detection/index.js';
|
|
28
22
|
export * as protocols from './protocols/index.js';
|
package/ts/protocols/index.ts
CHANGED
|
@@ -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
|
-
|
|
124
|
-
|
|
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
|
-
|
|
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 =
|
|
185
|
-
if (requestParsed) return;
|
|
209
|
+
const processData = (data: Buffer) => {
|
|
210
|
+
if (requestParsed) return;
|
|
186
211
|
|
|
187
|
-
|
|
188
|
-
const detectionResult = await ProtocolDetector.detectWithConnectionTracking(
|
|
189
|
-
data,
|
|
190
|
-
connectionId,
|
|
191
|
-
{ extractFullHeaders: true }
|
|
192
|
-
);
|
|
212
|
+
const parsed = parseHttpRequest(data, true);
|
|
193
213
|
|
|
194
|
-
if (
|
|
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:
|
|
207
|
-
url:
|
|
208
|
-
headers:
|
|
209
|
-
body:
|
|
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[],
|
package/ts/routing/index.ts
CHANGED
|
@@ -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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
|