@dainprotocol/tunnel 2.0.1 → 2.0.3
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/dist/client/index.js +13 -4
- package/dist/server/index.js +20 -11
- package/package.json +19 -14
package/dist/client/index.js
CHANGED
|
@@ -18,6 +18,11 @@ const RECONNECT = {
|
|
|
18
18
|
const LIMITS = {
|
|
19
19
|
MAX_PENDING_WS_MESSAGES_PER_CONNECTION: 256,
|
|
20
20
|
};
|
|
21
|
+
function emitClientError(emitter, error) {
|
|
22
|
+
if (emitter.listenerCount("error") > 0) {
|
|
23
|
+
emitter.emit("error", error);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
21
26
|
function rawDataToString(message) {
|
|
22
27
|
if (typeof message === "string")
|
|
23
28
|
return message;
|
|
@@ -81,7 +86,7 @@ class DainTunnel extends EventEmitter {
|
|
|
81
86
|
this.ws.ping();
|
|
82
87
|
}
|
|
83
88
|
catch {
|
|
84
|
-
this
|
|
89
|
+
emitClientError(this, new Error("Heartbeat ping failed"));
|
|
85
90
|
}
|
|
86
91
|
}
|
|
87
92
|
}, TIMEOUTS.HEARTBEAT);
|
|
@@ -160,7 +165,7 @@ class DainTunnel extends EventEmitter {
|
|
|
160
165
|
finish(undefined, new Error("Connection closed before tunnel established"));
|
|
161
166
|
}
|
|
162
167
|
});
|
|
163
|
-
this.ws.on("error", (error) => this
|
|
168
|
+
this.ws.on("error", (error) => emitClientError(this, error));
|
|
164
169
|
connectionTimeoutId = setTimeout(() => {
|
|
165
170
|
if (!resolved && (!this.ws || this.ws.readyState !== WebSocket.OPEN)) {
|
|
166
171
|
finish(undefined, new Error("Connection timeout"));
|
|
@@ -552,8 +557,12 @@ class DainTunnel extends EventEmitter {
|
|
|
552
557
|
}
|
|
553
558
|
if (this.ws) {
|
|
554
559
|
try {
|
|
555
|
-
if (this.ws.readyState === WebSocket.OPEN)
|
|
556
|
-
this.ws.close();
|
|
560
|
+
if (this.ws.readyState === WebSocket.OPEN || this.ws.readyState === WebSocket.CONNECTING) {
|
|
561
|
+
this.ws.close(1000, "Client stopping");
|
|
562
|
+
}
|
|
563
|
+
else if (this.ws.readyState !== WebSocket.CLOSED) {
|
|
564
|
+
this.ws.terminate();
|
|
565
|
+
}
|
|
557
566
|
}
|
|
558
567
|
catch { }
|
|
559
568
|
this.ws = null;
|
package/dist/server/index.js
CHANGED
|
@@ -20,6 +20,15 @@ const LIMITS = {
|
|
|
20
20
|
WS_BACKLOG: 100,
|
|
21
21
|
TUNNEL_RETRY_COUNT: 2,
|
|
22
22
|
};
|
|
23
|
+
const DEBUG_TUNNEL = process.env.DAIN_TUNNEL_DEBUG === "1";
|
|
24
|
+
function debugLog(...args) {
|
|
25
|
+
if (DEBUG_TUNNEL)
|
|
26
|
+
console.log(...args);
|
|
27
|
+
}
|
|
28
|
+
function debugError(...args) {
|
|
29
|
+
if (DEBUG_TUNNEL)
|
|
30
|
+
console.error(...args);
|
|
31
|
+
}
|
|
23
32
|
let idCounter = 0;
|
|
24
33
|
const ID_PREFIX = Date.now().toString(36);
|
|
25
34
|
function fastId() {
|
|
@@ -76,7 +85,7 @@ class DainTunnelServer {
|
|
|
76
85
|
}
|
|
77
86
|
}
|
|
78
87
|
catch (error) {
|
|
79
|
-
|
|
88
|
+
debugError("[Tunnel] SafeSend error:", error);
|
|
80
89
|
}
|
|
81
90
|
return false;
|
|
82
91
|
}
|
|
@@ -200,7 +209,7 @@ class DainTunnelServer {
|
|
|
200
209
|
}
|
|
201
210
|
}
|
|
202
211
|
catch (error) {
|
|
203
|
-
|
|
212
|
+
debugError("[Tunnel] Message error:", error);
|
|
204
213
|
ws.close(1008, "Invalid message");
|
|
205
214
|
}
|
|
206
215
|
}
|
|
@@ -296,7 +305,7 @@ class DainTunnelServer {
|
|
|
296
305
|
if (!isAlive) {
|
|
297
306
|
missedPongs++;
|
|
298
307
|
if (missedPongs >= LIMITS.MAX_MISSED_PONGS) {
|
|
299
|
-
|
|
308
|
+
debugLog(`[Tunnel] ${tunnelId} failed liveness check (${missedPongs} missed pongs), terminating`);
|
|
300
309
|
clearInterval(intervalId);
|
|
301
310
|
ws.close(1001, "Liveness check failed");
|
|
302
311
|
return;
|
|
@@ -317,13 +326,13 @@ class DainTunnelServer {
|
|
|
317
326
|
// We track isAlive through the pong handler set up in Bun.serve websocket config
|
|
318
327
|
const tunnelUrl = this.buildTunnelUrl(tunnelId);
|
|
319
328
|
ws.send(JSON.stringify({ type: "tunnelUrl", url: tunnelUrl }));
|
|
320
|
-
|
|
329
|
+
debugLog(`[Tunnel] Created: ${tunnelUrl}`);
|
|
321
330
|
// Store isAlive/missedPongs on ws.data for the pong handler
|
|
322
331
|
ws.data._isAlive = true;
|
|
323
332
|
ws.data._missedPongsReset = () => { isAlive = true; missedPongs = 0; };
|
|
324
333
|
}
|
|
325
334
|
catch (error) {
|
|
326
|
-
|
|
335
|
+
debugError(`Error in handleStartMessage for tunnel ${tunnelId}:`, error);
|
|
327
336
|
ws.close(1011, "Internal server error");
|
|
328
337
|
}
|
|
329
338
|
}
|
|
@@ -646,7 +655,7 @@ class DainTunnelServer {
|
|
|
646
655
|
this.cleanupChallengesForSocket(ws);
|
|
647
656
|
}
|
|
648
657
|
catch (error) {
|
|
649
|
-
|
|
658
|
+
debugError("[Tunnel] Remove error:", error);
|
|
650
659
|
}
|
|
651
660
|
}
|
|
652
661
|
findAndRemoveTunnel(ws) {
|
|
@@ -816,7 +825,7 @@ class DainTunnelServer {
|
|
|
816
825
|
backpressureLimit: LIMITS.BACKPRESSURE_THRESHOLD,
|
|
817
826
|
},
|
|
818
827
|
});
|
|
819
|
-
|
|
828
|
+
debugLog(`DainTunnel Server is running on ${this.hostname}:${this.port}`);
|
|
820
829
|
}
|
|
821
830
|
async stop() {
|
|
822
831
|
try {
|
|
@@ -827,7 +836,7 @@ class DainTunnelServer {
|
|
|
827
836
|
tunnel.ws.close(1001, "Server shutting down");
|
|
828
837
|
}
|
|
829
838
|
catch (error) {
|
|
830
|
-
|
|
839
|
+
debugError(`Error closing tunnel ${tunnel.id}:`, error);
|
|
831
840
|
}
|
|
832
841
|
}
|
|
833
842
|
this.tunnels.clear();
|
|
@@ -855,7 +864,7 @@ class DainTunnelServer {
|
|
|
855
864
|
conn.controller.close();
|
|
856
865
|
}
|
|
857
866
|
catch (error) {
|
|
858
|
-
|
|
867
|
+
debugError(`Error closing SSE ${sseId}:`, error);
|
|
859
868
|
}
|
|
860
869
|
conn.closed = true;
|
|
861
870
|
this.sseConnections.delete(sseId);
|
|
@@ -865,7 +874,7 @@ class DainTunnelServer {
|
|
|
865
874
|
conn.clientSocket.close(1001, "Server shutting down");
|
|
866
875
|
}
|
|
867
876
|
catch (error) {
|
|
868
|
-
|
|
877
|
+
debugError(`Error closing WS ${wsId}:`, error);
|
|
869
878
|
}
|
|
870
879
|
this.wsConnections.delete(wsId);
|
|
871
880
|
}
|
|
@@ -875,7 +884,7 @@ class DainTunnelServer {
|
|
|
875
884
|
}
|
|
876
885
|
}
|
|
877
886
|
catch (error) {
|
|
878
|
-
|
|
887
|
+
debugError('Error during server shutdown:', error);
|
|
879
888
|
}
|
|
880
889
|
}
|
|
881
890
|
}
|
package/package.json
CHANGED
|
@@ -1,18 +1,22 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dainprotocol/tunnel",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.3",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"private": false,
|
|
7
|
+
"packageManager": "bun@1.3.13",
|
|
7
8
|
"publishConfig": {
|
|
8
9
|
"access": "public"
|
|
9
10
|
},
|
|
10
11
|
"scripts": {
|
|
11
|
-
"build": "tsc",
|
|
12
|
-
"build:production": "
|
|
13
|
-
"build:types": "tsc --emitDeclarationOnly",
|
|
14
|
-
"test": "bun test",
|
|
15
|
-
"
|
|
12
|
+
"build": "bunx --bun tsc",
|
|
13
|
+
"build:production": "bun run build && bun build dist/server/start.js --outdir dist-prod --target bun --minify --sourcemap=external",
|
|
14
|
+
"build:types": "bunx --bun tsc --emitDeclarationOnly",
|
|
15
|
+
"test": "bun test --parallel=4",
|
|
16
|
+
"test:serial": "bun test --isolate",
|
|
17
|
+
"test:watch": "bun test --watch",
|
|
18
|
+
"test:coverage": "bun test --coverage --isolate",
|
|
19
|
+
"prepublishOnly": "bun run build && bun run build:types",
|
|
16
20
|
"start": "bun dist/server/start.js",
|
|
17
21
|
"start-server": "bun src/server/start.ts"
|
|
18
22
|
},
|
|
@@ -20,22 +24,23 @@
|
|
|
20
24
|
"author": "Ryan",
|
|
21
25
|
"license": "ISC",
|
|
22
26
|
"dependencies": {
|
|
23
|
-
"@dainprotocol/service-sdk": "2.0.
|
|
24
|
-
"
|
|
25
|
-
"
|
|
26
|
-
"hono": "^4.7.0",
|
|
27
|
-
"ws": "^8.18.0"
|
|
27
|
+
"@dainprotocol/service-sdk": "^2.0.95",
|
|
28
|
+
"hono": "^4.12.14",
|
|
29
|
+
"ws": "^8.20.0"
|
|
28
30
|
},
|
|
29
31
|
"devDependencies": {
|
|
30
|
-
"@types/bun": "^1.
|
|
31
|
-
"
|
|
32
|
+
"@types/bun": "^1.3.12",
|
|
33
|
+
"@types/node": "^25.6.0",
|
|
34
|
+
"@types/ws": "^8.18.1",
|
|
35
|
+
"eventsource": "^4.1.0",
|
|
36
|
+
"typescript": "^6.0.3"
|
|
32
37
|
},
|
|
33
38
|
"files": [
|
|
34
39
|
"dist",
|
|
35
40
|
"README.md"
|
|
36
41
|
],
|
|
37
42
|
"engines": {
|
|
38
|
-
"bun": ">=1.
|
|
43
|
+
"bun": ">=1.3.13"
|
|
39
44
|
},
|
|
40
45
|
"exports": {
|
|
41
46
|
".": "./dist/index.js",
|