bdy 1.8.3-dev → 1.8.4-dev

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 (112) hide show
  1. package/distTs/bin/cli.js +5 -0
  2. package/distTs/src/agent/linux.js +119 -0
  3. package/distTs/src/agent/manager.js +395 -0
  4. package/distTs/src/agent/osx.js +139 -0
  5. package/distTs/src/agent/socket/tunnel.js +212 -0
  6. package/distTs/src/agent/socket.js +220 -0
  7. package/distTs/src/agent/system.js +177 -0
  8. package/distTs/src/agent/wait.js +23 -0
  9. package/distTs/src/agent/windows.js +159 -0
  10. package/distTs/src/agent.js +237 -0
  11. package/distTs/src/api/agent.js +84 -0
  12. package/distTs/src/api/buddy.js +117 -0
  13. package/distTs/src/api/socket.js +133 -0
  14. package/distTs/src/cfg.js +238 -0
  15. package/distTs/src/command/agent/install.js +106 -0
  16. package/distTs/src/command/agent/restart.js +27 -0
  17. package/distTs/src/command/agent/run.js +19 -0
  18. package/distTs/src/command/agent/start.js +28 -0
  19. package/distTs/src/command/agent/status.js +35 -0
  20. package/distTs/src/command/agent/stop.js +28 -0
  21. package/distTs/src/command/agent/tunnel/http.js +44 -0
  22. package/distTs/src/command/agent/tunnel/list.js +27 -0
  23. package/distTs/src/command/agent/tunnel/remove.js +28 -0
  24. package/distTs/src/command/agent/tunnel/start.js +34 -0
  25. package/distTs/src/command/agent/tunnel/status.js +31 -0
  26. package/distTs/src/command/agent/tunnel/tcp.js +43 -0
  27. package/distTs/src/command/agent/tunnel/tls.js +43 -0
  28. package/distTs/src/command/agent/tunnel.js +23 -0
  29. package/distTs/src/command/agent/uninstall.js +38 -0
  30. package/distTs/src/command/agent/update.js +38 -0
  31. package/distTs/src/command/agent/version.js +21 -0
  32. package/distTs/src/command/agent.js +29 -0
  33. package/distTs/src/command/config/add/http.js +25 -0
  34. package/distTs/src/command/config/add/tcp.js +25 -0
  35. package/distTs/src/command/config/add/tls.js +25 -0
  36. package/distTs/src/command/config/add.js +15 -0
  37. package/distTs/src/command/config/get/region.js +15 -0
  38. package/distTs/src/command/config/get/timeout.js +15 -0
  39. package/distTs/src/command/config/get/token.js +15 -0
  40. package/distTs/src/command/config/get/tunnel.js +19 -0
  41. package/distTs/src/command/config/get/tunnels.js +15 -0
  42. package/distTs/src/command/config/get/whitelist.js +15 -0
  43. package/distTs/src/command/config/get.js +21 -0
  44. package/distTs/src/command/config/remove/tunnel.js +19 -0
  45. package/distTs/src/command/config/remove.js +11 -0
  46. package/distTs/src/command/config/set/region.js +17 -0
  47. package/distTs/src/command/config/set/timeout.js +17 -0
  48. package/distTs/src/command/config/set/token.js +16 -0
  49. package/distTs/src/command/config/set/whitelist.js +17 -0
  50. package/distTs/src/command/config/set.js +17 -0
  51. package/distTs/src/command/config.js +17 -0
  52. package/distTs/src/command/http.js +30 -0
  53. package/distTs/src/command/pre.js +49 -0
  54. package/distTs/src/command/start.js +28 -0
  55. package/distTs/src/command/tcp.js +30 -0
  56. package/distTs/src/command/tls.js +30 -0
  57. package/distTs/src/command/version.js +13 -0
  58. package/distTs/src/command/vt/close.js +28 -0
  59. package/distTs/src/command/vt/exec.js +79 -0
  60. package/distTs/src/command/vt/storybook.js +90 -0
  61. package/distTs/src/command/vt.js +15 -0
  62. package/distTs/src/format.js +172 -0
  63. package/distTs/src/index.js +40 -0
  64. package/distTs/src/input.js +286 -0
  65. package/distTs/src/logger.js +93 -0
  66. package/distTs/src/output/interactive/tunnel.js +860 -0
  67. package/distTs/src/output/noninteractive/agent/tunnels.js +43 -0
  68. package/distTs/src/output/noninteractive/config/tunnel.js +67 -0
  69. package/distTs/src/output/noninteractive/config/tunnels.js +18 -0
  70. package/distTs/src/output/noninteractive/tunnel.js +59 -0
  71. package/distTs/src/output.js +138 -0
  72. package/distTs/src/server/cert.js +52 -0
  73. package/distTs/src/server/http1.js +74 -0
  74. package/distTs/src/server/http2.js +74 -0
  75. package/distTs/src/server/sftp.js +487 -0
  76. package/distTs/src/server/ssh.js +112 -0
  77. package/distTs/src/server/tls.js +41 -0
  78. package/distTs/src/ssh/client.js +191 -0
  79. package/distTs/src/texts.js +345 -0
  80. package/distTs/src/tunnel/agent.js +100 -0
  81. package/distTs/src/tunnel/compression.js +41 -0
  82. package/distTs/src/tunnel/dns.js +54 -0
  83. package/distTs/src/tunnel/html.js +30 -0
  84. package/distTs/src/tunnel/http/log.js +196 -0
  85. package/distTs/src/tunnel/http/serve.js +132 -0
  86. package/distTs/src/tunnel/http/stream.js +45 -0
  87. package/distTs/src/tunnel/http.js +405 -0
  88. package/distTs/src/tunnel/identification.js +96 -0
  89. package/distTs/src/tunnel/latency.js +71 -0
  90. package/distTs/src/tunnel/tcp.js +92 -0
  91. package/distTs/src/tunnel.js +647 -0
  92. package/distTs/src/types/ciInfo.js +10 -0
  93. package/distTs/src/types/options.js +2 -0
  94. package/distTs/src/types/plugin.js +2 -0
  95. package/distTs/src/types/queue.js +2 -0
  96. package/distTs/src/types/requests.js +2 -0
  97. package/distTs/src/types/resources.js +2 -0
  98. package/distTs/src/types/snapshots.js +2 -0
  99. package/distTs/src/types/storybook.js +2 -0
  100. package/distTs/src/utils.js +437 -0
  101. package/distTs/src/visualTest/browser.js +32 -0
  102. package/distTs/src/visualTest/ci.js +206 -0
  103. package/distTs/src/visualTest/context.js +44 -0
  104. package/distTs/src/visualTest/exec.js +51 -0
  105. package/distTs/src/visualTest/queue.js +43 -0
  106. package/distTs/src/visualTest/requests.js +197 -0
  107. package/distTs/src/visualTest/resources.js +195 -0
  108. package/distTs/src/visualTest/server.js +33 -0
  109. package/distTs/src/visualTest/snapshots.js +109 -0
  110. package/distTs/src/visualTest/utils/parseDom.js +238 -0
  111. package/distTs/src/visualTest/validation.js +18 -0
  112. package/package.json +1 -1
@@ -0,0 +1,405 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const events_1 = __importDefault(require("events"));
7
+ const uuid_1 = require("uuid");
8
+ const http_1 = __importDefault(require("http"));
9
+ const utils_1 = require("../utils");
10
+ const stream_1 = __importDefault(require("stream"));
11
+ const texts_js_1 = require("../texts.js");
12
+ const logger_js_1 = __importDefault(require("../logger.js"));
13
+ const serve_js_1 = __importDefault(require("./http/serve.js"));
14
+ const https_1 = __importDefault(require("https"));
15
+ const compression_js_1 = __importDefault(require("./compression.js"));
16
+ const html_js_1 = __importDefault(require("./html.js"));
17
+ const url_1 = __importDefault(require("url"));
18
+ const agent_js_1 = __importDefault(require("./agent.js"));
19
+ class TunnelHttp extends events_1.default {
20
+ constructor({ req, res, proto, host, port, hostHeader, serve, timeout, httpIdentify, verify, httpLog, compression, headers, responseHeaders, auth = null, }) {
21
+ super();
22
+ this.id = (0, uuid_1.v4)();
23
+ this.host = host;
24
+ this.port = port;
25
+ this.proto = proto;
26
+ this.auth = auth;
27
+ this.req = req;
28
+ this.res = res;
29
+ this.hostHeader = hostHeader;
30
+ this.timeout = timeout || utils_1.DEFAULT_TIMEOUT;
31
+ this.httpIdentify = httpIdentify;
32
+ this.verify = verify;
33
+ this.compression = compression;
34
+ this.headers = {};
35
+ this.responseHeaders = {};
36
+ this.serve = serve;
37
+ if (responseHeaders) {
38
+ responseHeaders.forEach((header) => {
39
+ this.responseHeaders[header.name.toLowerCase()] = header.value;
40
+ });
41
+ }
42
+ if (headers) {
43
+ headers.forEach((header) => {
44
+ this.headers[header.name.toLowerCase()] = header.value;
45
+ });
46
+ }
47
+ this.httpLog = httpLog;
48
+ this.logRequest = null;
49
+ }
50
+ outputEnd(code, html) {
51
+ try {
52
+ if (this.logRequest) {
53
+ const s = new stream_1.default.Readable();
54
+ s.push(html);
55
+ s.push(null);
56
+ s.pipe(this.logRequest.responseBody);
57
+ }
58
+ this.httpLog.newResponse(this.req, code, {}, this.logRequest);
59
+ this.res.statusCode = code;
60
+ this.res.end(html);
61
+ }
62
+ catch {
63
+ // do nothing
64
+ }
65
+ this.clear();
66
+ }
67
+ getDisplayTarget() {
68
+ let t = `${this.proto}://${this.host}`;
69
+ if (this.proto === 'http' && this.port !== 80)
70
+ t += `:${this.port}`;
71
+ else if (this.proto === 'https' && this.port !== 443)
72
+ t += `:${this.port}`;
73
+ return t;
74
+ }
75
+ output503() {
76
+ this.outputEnd(503, html_js_1.default.get503(this.getDisplayTarget()));
77
+ }
78
+ outputHeaders(statusCode, headers) {
79
+ this.res.statusCode = statusCode;
80
+ Object.keys(headers).forEach((name) => {
81
+ this.res.setHeader(name.toLowerCase(), headers[name]);
82
+ });
83
+ Object.keys(this.responseHeaders).forEach((name) => {
84
+ this.res.setHeader(name.toLowerCase(), this.responseHeaders[name]);
85
+ });
86
+ }
87
+ getHostHeader() {
88
+ if (this.hostHeader)
89
+ return this.hostHeader;
90
+ let h = this.host;
91
+ if (this.proto === 'http' && this.port !== 80)
92
+ h += `:${this.port}`;
93
+ else if (this.proto === 'https' && this.port !== 443)
94
+ h += `:${this.port}`;
95
+ return h;
96
+ }
97
+ getRequestHeaders(http2) {
98
+ const h = {};
99
+ let ip;
100
+ if (this.req.httpVersion === '2.0') {
101
+ ip = this.req.socket.stream
102
+ ? this.req.socket.stream.remoteAddress
103
+ : '::1';
104
+ }
105
+ else {
106
+ ip = this.req.socket.remoteAddress;
107
+ }
108
+ if (http2) {
109
+ h[':scheme'] = this.proto;
110
+ h[':authority'] = this.getHostHeader();
111
+ h[':method'] = this.getMethod();
112
+ h[':path'] = this.getPath();
113
+ }
114
+ else {
115
+ h.host = this.getHostHeader();
116
+ }
117
+ h['x-forwarded-for'] = ip || '0.0.0.0';
118
+ h['x-forwarded-proto'] = 'https';
119
+ if (this.auth) {
120
+ h['authorization'] = `Basic ${Buffer.from(this.auth).toString('base64')}`;
121
+ }
122
+ return h;
123
+ }
124
+ getClearedHeaders(headers = {}, compressionMethod) {
125
+ const hop = [
126
+ ':method',
127
+ ':path',
128
+ ':scheme',
129
+ ':authority',
130
+ ':status',
131
+ 'keep-alive',
132
+ 'host',
133
+ 'connection',
134
+ 'proxy-authenticate',
135
+ 'proxy-connection',
136
+ 'Proxy-authorization',
137
+ 'trailer',
138
+ 'upgrade',
139
+ 'transfer-encoding',
140
+ 'strict-transport-security',
141
+ 'te',
142
+ ];
143
+ const tmp = {};
144
+ if (compressionMethod &&
145
+ compressionMethod !== utils_1.TUNNEL_COMPRESSION_METHOD_IDENTITY) {
146
+ tmp['content-encoding'] = compressionMethod;
147
+ hop.push('content-length');
148
+ hop.push('content-encoding');
149
+ }
150
+ Object.keys(headers).forEach((name) => {
151
+ if (!hop.includes(name)) {
152
+ tmp[name] = headers[name];
153
+ }
154
+ });
155
+ return tmp;
156
+ }
157
+ getPath() {
158
+ const { pathname, search } = url_1.default.parse(this.req.url);
159
+ let path = pathname;
160
+ if (search)
161
+ path += search;
162
+ return path;
163
+ }
164
+ getMethod() {
165
+ return this.req.method;
166
+ }
167
+ createRequestHttp1() {
168
+ const reqHeaders = this.req.headers;
169
+ const method = this.getMethod();
170
+ const path = this.getPath();
171
+ const headers = {
172
+ ...this.getClearedHeaders(reqHeaders),
173
+ ...this.headers,
174
+ ...this.getRequestHeaders(false),
175
+ };
176
+ const r = http_1.default.request({
177
+ agent: agent_js_1.default.getHttp1(),
178
+ host: (0, utils_1.getRealTargetHost)(this.host),
179
+ port: this.port,
180
+ method,
181
+ protocol: 'http:',
182
+ setHost: false,
183
+ path,
184
+ headers,
185
+ });
186
+ this.logRequest = this.httpLog.newRequest(method, headers, path, utils_1.TUNNEL_IDENTIFIED_HTTP1, this.req);
187
+ r.on('response', (proxyRes) => {
188
+ this.proxyRes = proxyRes;
189
+ const statusCode = this.proxyRes.statusCode;
190
+ const resHeaders = this.proxyRes.headers;
191
+ const compressionMethod = compression_js_1.default.detect(this.compression, reqHeaders, resHeaders);
192
+ this.outputHeaders(statusCode, this.getClearedHeaders(resHeaders, compressionMethod));
193
+ if (this.logRequest) {
194
+ this.proxyRes
195
+ .pipe(this.logRequest.responseBody)
196
+ .pipe(compression_js_1.default.compress(compressionMethod))
197
+ .pipe(this.res);
198
+ }
199
+ else {
200
+ this.proxyRes
201
+ .pipe(compression_js_1.default.compress(compressionMethod))
202
+ .pipe(this.res);
203
+ }
204
+ this.httpLog.newResponse(this.req, statusCode, resHeaders, this.logRequest);
205
+ });
206
+ return r;
207
+ }
208
+ createRequestHttps1() {
209
+ const reqHeaders = this.req.headers;
210
+ const method = this.getMethod();
211
+ const headers = {
212
+ ...this.getClearedHeaders(reqHeaders),
213
+ ...this.headers,
214
+ ...this.getRequestHeaders(false),
215
+ };
216
+ const path = this.getPath();
217
+ const r = https_1.default.request({
218
+ agent: agent_js_1.default.getHttps1(),
219
+ host: (0, utils_1.getRealTargetHost)(this.host),
220
+ port: this.port,
221
+ method,
222
+ protocol: 'https:',
223
+ setHost: false,
224
+ path,
225
+ rejectUnauthorized: this.verify,
226
+ headers,
227
+ });
228
+ this.logRequest = this.httpLog.newRequest(method, headers, path, utils_1.TUNNEL_IDENTIFIED_HTTP1, this.req);
229
+ r.on('response', (proxyRes) => {
230
+ this.proxyRes = proxyRes;
231
+ const statusCode = this.proxyRes.statusCode;
232
+ const resHeaders = this.proxyRes.headers;
233
+ const compressionMethod = compression_js_1.default.detect(this.compression, reqHeaders, resHeaders);
234
+ this.outputHeaders(statusCode, this.getClearedHeaders(resHeaders, compressionMethod));
235
+ if (this.logRequest) {
236
+ this.proxyRes
237
+ .pipe(this.logRequest.responseBody)
238
+ .pipe(compression_js_1.default.compress(compressionMethod))
239
+ .pipe(this.res);
240
+ }
241
+ else {
242
+ this.proxyRes
243
+ .pipe(compression_js_1.default.compress(compressionMethod))
244
+ .pipe(this.res);
245
+ }
246
+ this.httpLog.newResponse(this.req, statusCode, resHeaders, this.logRequest);
247
+ });
248
+ return r;
249
+ }
250
+ createServe() {
251
+ const reqHeaders = this.req.headers;
252
+ const r = new serve_js_1.default(this.serve);
253
+ const method = this.getMethod();
254
+ const path = this.getPath();
255
+ this.logRequest = this.httpLog.newRequest(method, reqHeaders, path, utils_1.TUNNEL_IDENTIFIED_HTTP1, this.req);
256
+ r.on('response', (statusCode, resHeaders, stream) => {
257
+ if (!stream) {
258
+ this.outputHeaders(statusCode, this.getClearedHeaders(resHeaders));
259
+ this.res.end();
260
+ }
261
+ else {
262
+ const compressionMethod = compression_js_1.default.detect(this.compression, reqHeaders, resHeaders);
263
+ this.outputHeaders(statusCode, this.getClearedHeaders(resHeaders, compressionMethod));
264
+ if (this.logRequest) {
265
+ stream
266
+ .pipe(this.logRequest.responseBody)
267
+ .pipe(compression_js_1.default.compress(compressionMethod))
268
+ .pipe(this.res);
269
+ }
270
+ else {
271
+ stream
272
+ .pipe(compression_js_1.default.compress(compressionMethod))
273
+ .pipe(this.res);
274
+ }
275
+ }
276
+ this.httpLog.newResponse(this.req, statusCode, resHeaders, this.logRequest);
277
+ });
278
+ return r;
279
+ }
280
+ async createRequestHttps2() {
281
+ const reqHeaders = this.req.headers;
282
+ const authority = `${this.proto}://${(0, utils_1.getRealTargetHost)(this.host)}:${this.port}`;
283
+ const client = await agent_js_1.default.getHttp2Client(authority, this.host, this.verify);
284
+ const method = this.getMethod();
285
+ const path = this.getPath();
286
+ const headers = {
287
+ ...this.getClearedHeaders(reqHeaders),
288
+ ...this.headers,
289
+ ...this.getRequestHeaders(true),
290
+ };
291
+ const r = client.request(headers);
292
+ this.logRequest = this.httpLog.newRequest(method, headers, path, utils_1.TUNNEL_IDENTIFIED_HTTP2, this.req);
293
+ r.on('response', (resHeaders) => {
294
+ const status = resHeaders[':status'] || 200;
295
+ const compressionMethod = compression_js_1.default.detect(this.compression, reqHeaders, resHeaders);
296
+ this.outputHeaders(status, this.getClearedHeaders(resHeaders, compressionMethod));
297
+ if (this.logRequest) {
298
+ r.pipe(this.logRequest.responseBody)
299
+ .pipe(compression_js_1.default.compress(compressionMethod))
300
+ .pipe(this.res);
301
+ }
302
+ else {
303
+ r.pipe(compression_js_1.default.compress(compressionMethod)).pipe(this.res);
304
+ }
305
+ this.httpLog.newResponse(this.req, status, resHeaders, this.logRequest);
306
+ });
307
+ return r;
308
+ }
309
+ async createRequest() {
310
+ if (this.httpIdentify === utils_1.TUNNEL_IDENTIFIED_HTTP1) {
311
+ if (this.proto === 'http')
312
+ return this.createRequestHttp1();
313
+ return this.createRequestHttps1();
314
+ }
315
+ return this.createRequestHttps2();
316
+ }
317
+ clear() {
318
+ if (this.req) {
319
+ this.req.removeAllListeners();
320
+ this.req = null;
321
+ }
322
+ if (this.res) {
323
+ this.res.removeAllListeners();
324
+ this.res = null;
325
+ }
326
+ if (this.proxyReq) {
327
+ this.proxyReq.removeAllListeners();
328
+ this.proxyReq = null;
329
+ }
330
+ if (this.proxyRes) {
331
+ this.proxyRes.removeAllListeners();
332
+ this.proxyRes = null;
333
+ }
334
+ if (this.httpLog) {
335
+ this.httpLog = null;
336
+ }
337
+ if (this.logRequest) {
338
+ this.logRequest.removeAllListeners();
339
+ this.logRequest = null;
340
+ }
341
+ }
342
+ async pipe() {
343
+ if (this.serve) {
344
+ try {
345
+ this.proxyReq = this.createServe();
346
+ }
347
+ catch (err) {
348
+ logger_js_1.default.debug(texts_js_1.LOG_ERROR);
349
+ logger_js_1.default.debug(err);
350
+ this.output503();
351
+ return;
352
+ }
353
+ this.proxyReq.on('error', () => {
354
+ this.output503();
355
+ });
356
+ this.proxyReq.on('close', () => {
357
+ setTimeout(() => {
358
+ this.clear();
359
+ }, 5000);
360
+ });
361
+ this.proxyReq.process(this.req);
362
+ }
363
+ else {
364
+ try {
365
+ this.proxyReq = await this.createRequest();
366
+ }
367
+ catch (err) {
368
+ logger_js_1.default.debug(texts_js_1.LOG_ERROR);
369
+ logger_js_1.default.debug(err);
370
+ if (this.logRequest) {
371
+ this.req.pipe(this.logRequest.requestBody);
372
+ // no real request waiting for this data -> push it into the void
373
+ this.logRequest.requestBody.pipeToNothing(() => {
374
+ // wait for piping request
375
+ this.output503();
376
+ });
377
+ return;
378
+ }
379
+ this.output503();
380
+ return;
381
+ }
382
+ this.proxyReq.setTimeout(this.timeout * 1000);
383
+ this.proxyReq.on('timeout', () => {
384
+ this.output503();
385
+ });
386
+ this.proxyReq.on('error', (err) => {
387
+ logger_js_1.default.debug(texts_js_1.LOG_ERROR);
388
+ logger_js_1.default.debug(err);
389
+ this.output503();
390
+ });
391
+ this.proxyReq.on('close', () => {
392
+ setTimeout(() => {
393
+ this.clear();
394
+ }, 5000);
395
+ });
396
+ if (this.logRequest) {
397
+ this.req.pipe(this.logRequest.requestBody).pipe(this.proxyReq);
398
+ }
399
+ else {
400
+ this.req.pipe(this.proxyReq);
401
+ }
402
+ }
403
+ }
404
+ }
405
+ exports.default = TunnelHttp;
@@ -0,0 +1,96 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const events_1 = __importDefault(require("events"));
7
+ const tls_1 = __importDefault(require("tls"));
8
+ const net_1 = __importDefault(require("net"));
9
+ const utils_js_1 = require("../utils.js");
10
+ const utils_1 = require("../utils");
11
+ const CHECK_INTERVAL = 300000;
12
+ const CHECK_TIMEOUT = 5000;
13
+ class TunnelIdentification extends events_1.default {
14
+ constructor(proto, host, port, forceHttp2) {
15
+ super();
16
+ this.proto = proto;
17
+ this.host = (0, utils_js_1.getRealTargetHost)(host);
18
+ this.port = port;
19
+ this.forceHttp2 = forceHttp2;
20
+ this.type = utils_1.TUNNEL_IDENTIFIED_HTTP1;
21
+ this.identify();
22
+ this.ts = setInterval(() => this.identify(), CHECK_INTERVAL);
23
+ }
24
+ stop() {
25
+ if (this.ts) {
26
+ clearInterval(this.ts);
27
+ this.ts = null;
28
+ }
29
+ }
30
+ identify() {
31
+ if (this.forceHttp2) {
32
+ this.type = utils_1.TUNNEL_IDENTIFIED_HTTP2;
33
+ this.emit(utils_1.EVENT_TUNNEL_IDENTIFIED, utils_1.TUNNEL_IDENTIFIED_HTTP2);
34
+ return;
35
+ }
36
+ let socket;
37
+ const close = () => {
38
+ try {
39
+ socket.removeAllListeners();
40
+ socket.close();
41
+ }
42
+ catch {
43
+ // do nothing
44
+ }
45
+ };
46
+ const connected = () => {
47
+ if (socket.alpnProtocol) {
48
+ if (socket.alpnProtocol === 'h2') {
49
+ this.type = utils_1.TUNNEL_IDENTIFIED_HTTP2;
50
+ this.emit(utils_1.EVENT_TUNNEL_IDENTIFIED, utils_1.TUNNEL_IDENTIFIED_HTTP2);
51
+ }
52
+ else {
53
+ this.type = utils_1.TUNNEL_IDENTIFIED_HTTP1;
54
+ this.emit(utils_1.EVENT_TUNNEL_IDENTIFIED, utils_1.TUNNEL_IDENTIFIED_HTTP1);
55
+ }
56
+ close();
57
+ }
58
+ else {
59
+ socket.write('GET / HTTP/1.1\r\nHost: example.com\r\n\r\n');
60
+ socket.on('data', (d) => {
61
+ if (/HTTP\/1\.1/.test(d.toString('utf8'))) {
62
+ this.type = utils_1.TUNNEL_IDENTIFIED_HTTP1;
63
+ this.emit(utils_1.EVENT_TUNNEL_IDENTIFIED, utils_1.TUNNEL_IDENTIFIED_HTTP1);
64
+ }
65
+ else {
66
+ this.type = utils_1.TUNNEL_IDENTIFIED_HTTP2;
67
+ this.emit(utils_1.EVENT_TUNNEL_IDENTIFIED, utils_1.TUNNEL_IDENTIFIED_HTTP2);
68
+ }
69
+ close();
70
+ });
71
+ }
72
+ };
73
+ if (this.proto === 'http') {
74
+ socket = net_1.default.connect({
75
+ host: this.host,
76
+ port: this.port,
77
+ });
78
+ socket.on('connect', connected);
79
+ }
80
+ else {
81
+ socket = tls_1.default.connect({
82
+ host: this.host,
83
+ port: this.port,
84
+ rejectUnauthorized: true,
85
+ ALPNProtocols: ['h2', 'http/1.1'],
86
+ servername: this.host,
87
+ });
88
+ socket.on('secureConnect', connected);
89
+ }
90
+ socket.setTimeout(CHECK_TIMEOUT);
91
+ socket.on('timeout', close);
92
+ socket.on('error', close);
93
+ socket.on('close', close);
94
+ }
95
+ }
96
+ exports.default = TunnelIdentification;
@@ -0,0 +1,71 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const net_1 = require("net");
7
+ const events_1 = __importDefault(require("events"));
8
+ const utils_js_1 = require("../utils.js");
9
+ class TunnelLatency extends events_1.default {
10
+ constructor(host, port) {
11
+ super();
12
+ this.latency = -1;
13
+ this.isChecking = false;
14
+ this.port = port;
15
+ this.host = (0, utils_js_1.getRealTargetHost)(host);
16
+ this.ts = null;
17
+ }
18
+ check() {
19
+ if (this.isChecking)
20
+ return;
21
+ this.isChecking = true;
22
+ let socket = new net_1.Socket();
23
+ let ts = null;
24
+ const clear = () => {
25
+ clearTimeout(ts);
26
+ try {
27
+ socket.removeAllListeners();
28
+ socket.once('error', () => {
29
+ });
30
+ socket.end();
31
+ socket.destroy();
32
+ }
33
+ catch {
34
+ // do nothing
35
+ }
36
+ socket = null;
37
+ this.isChecking = false;
38
+ };
39
+ ts = setTimeout(() => {
40
+ this.latency = -1;
41
+ clear();
42
+ }, 30000);
43
+ const start = process.hrtime();
44
+ socket.on('error', () => {
45
+ this.latency = -1;
46
+ clear();
47
+ });
48
+ socket.on('ready', () => {
49
+ const elapsed = process.hrtime(start);
50
+ if (this.latency < 0)
51
+ this.emit(utils_js_1.TUNNEL_LATENCY_EVENT_RECONNECTED);
52
+ this.latency = elapsed[0] * 1000 + elapsed[1] / 1000000; // ms
53
+ clear();
54
+ });
55
+ socket.connect(this.port, this.host);
56
+ }
57
+ startChecking() {
58
+ this.check();
59
+ this.stopChecking();
60
+ this.ts = setInterval(() => {
61
+ this.check();
62
+ }, 3000);
63
+ }
64
+ stopChecking() {
65
+ if (this.ts) {
66
+ clearInterval(this.ts);
67
+ this.ts = null;
68
+ }
69
+ }
70
+ }
71
+ exports.default = TunnelLatency;
@@ -0,0 +1,92 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const net_1 = require("net");
7
+ const uuid_1 = require("uuid");
8
+ const events_1 = __importDefault(require("events"));
9
+ const utils_js_1 = require("../utils.js");
10
+ const utils_1 = require("../utils");
11
+ class TunnelTcp extends events_1.default {
12
+ constructor(host, port, stream) {
13
+ super();
14
+ this.id = (0, uuid_1.v4)();
15
+ this.host = host;
16
+ this.port = port;
17
+ this.stream = stream;
18
+ this.socket = new net_1.Socket();
19
+ }
20
+ end() {
21
+ try {
22
+ this.stream.unpipe();
23
+ this.socket.unpipe();
24
+ }
25
+ catch {
26
+ // do nothing
27
+ }
28
+ try {
29
+ this.stream.removeAllListeners();
30
+ this.stream.on('error', () => { });
31
+ this.stream.end();
32
+ }
33
+ catch {
34
+ // do nothing
35
+ }
36
+ const s1 = this.stream;
37
+ try {
38
+ this.socket.removeAllListeners();
39
+ this.socket.once('error', () => { });
40
+ this.socket.end();
41
+ }
42
+ catch {
43
+ // do nothing
44
+ }
45
+ const s2 = this.socket;
46
+ setTimeout(() => {
47
+ try {
48
+ s1.destroy();
49
+ }
50
+ catch {
51
+ // do nothing
52
+ }
53
+ try {
54
+ s2.destroy();
55
+ }
56
+ catch {
57
+ // do nothing
58
+ }
59
+ }, 1000);
60
+ this.socket = null;
61
+ this.stream = null;
62
+ this.host = null;
63
+ this.port = null;
64
+ this.emit(utils_1.TCP_EVENT_CLOSED);
65
+ }
66
+ pipe() {
67
+ this.socket.on('error', () => {
68
+ this.end();
69
+ });
70
+ this.socket.on('close', () => {
71
+ this.end();
72
+ });
73
+ this.stream.on('error', () => {
74
+ this.end();
75
+ });
76
+ this.stream.on('close', () => {
77
+ this.end();
78
+ });
79
+ try {
80
+ this.socket.connect({
81
+ host: (0, utils_js_1.getRealTargetHost)(this.host),
82
+ port: this.port,
83
+ }, () => {
84
+ this.socket.pipe(this.stream).pipe(this.socket);
85
+ });
86
+ }
87
+ catch {
88
+ this.end();
89
+ }
90
+ }
91
+ }
92
+ exports.default = TunnelTcp;