rdsh-gateway 0.8.1 → 0.8.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/join.d.ts +10 -0
- package/dist/join.js +34 -2
- package/dist/spawn-dsh.d.ts +4 -1
- package/dist/spawn-dsh.js +4 -1
- package/package.json +1 -1
package/dist/join.d.ts
CHANGED
|
@@ -62,6 +62,16 @@ export interface StartJoinOptions {
|
|
|
62
62
|
name?: string;
|
|
63
63
|
/** 宿主代持的 dsh 浏览器会话 cookie(`dsh-auth-*`,0.1.2+);有值时注入隧道→本地转发 */
|
|
64
64
|
dshAuthCookieHeader?: string | null;
|
|
65
|
+
/**
|
|
66
|
+
* 心跳间隔(缺省 30s,协议 PROTOCOL.md「心跳与重连」)。
|
|
67
|
+
* 测试可注入毫秒级小值以快速验证超时判定。
|
|
68
|
+
*/
|
|
69
|
+
heartbeatMs?: number;
|
|
70
|
+
/**
|
|
71
|
+
* 发出 PING 后等待对端任何帧的上限(缺省 10s);超时即判连接已死并主动断开。
|
|
72
|
+
* 测试可注入小值。
|
|
73
|
+
*/
|
|
74
|
+
pongTimeoutMs?: number;
|
|
65
75
|
}
|
|
66
76
|
/** 可停止的 join 隧道句柄。 */
|
|
67
77
|
export interface JoinHandle {
|
package/dist/join.js
CHANGED
|
@@ -41,6 +41,8 @@ export async function detectInsecure(hubUrl) {
|
|
|
41
41
|
}
|
|
42
42
|
}
|
|
43
43
|
const HEARTBEAT_MS = 30_000;
|
|
44
|
+
/** 发出 PING 后等待对端任何帧的上限:超时即判连接已死并主动断开(协议 PROTOCOL.md)。 */
|
|
45
|
+
const PONG_TIMEOUT_MS = 10_000;
|
|
44
46
|
const RECONNECT_BASE_MS = 1_000;
|
|
45
47
|
const RECONNECT_MAX_MS = 60_000;
|
|
46
48
|
/** hub HTTP 调用(node:https 支持自签跳过校验 —— undici fetch 不受 NODE_TLS_REJECT_UNAUTHORIZED 影响)。 */
|
|
@@ -212,7 +214,13 @@ export function startJoin(opts) {
|
|
|
212
214
|
let shuttingDown = false;
|
|
213
215
|
let reconnectDelay = RECONNECT_BASE_MS;
|
|
214
216
|
let heartbeat;
|
|
217
|
+
/** 发出 PING 后的存活死线:期间收到**任何**入站帧即撤销(PROTOCOL.md 心跳与重连)。 */
|
|
218
|
+
let livenessDeadline;
|
|
215
219
|
let currentClient;
|
|
220
|
+
const heartbeatMs = opts.heartbeatMs ?? HEARTBEAT_MS;
|
|
221
|
+
const pongTimeoutMs = opts.pongTimeoutMs ?? PONG_TIMEOUT_MS;
|
|
222
|
+
/** 日志用人类可读单位:生产 30000ms → "30s";测试注入的毫秒值原样显示。 */
|
|
223
|
+
const heartbeatLabel = heartbeatMs % 1000 === 0 ? `${heartbeatMs / 1000}s` : `${heartbeatMs}ms`;
|
|
216
224
|
/** 发送一个隧道帧(走当前隧道 WS;flags 由调用方在 encodeFrame 时给定)。 */
|
|
217
225
|
function sendTunnelFrame(frame) {
|
|
218
226
|
if (currentClient !== undefined && currentClient.readyState === currentClient.OPEN) {
|
|
@@ -597,6 +605,10 @@ export function startJoin(opts) {
|
|
|
597
605
|
clearInterval(heartbeat);
|
|
598
606
|
heartbeat = undefined;
|
|
599
607
|
}
|
|
608
|
+
if (livenessDeadline !== undefined) {
|
|
609
|
+
clearTimeout(livenessDeadline);
|
|
610
|
+
livenessDeadline = undefined;
|
|
611
|
+
}
|
|
600
612
|
plainDispatcher.cleanup();
|
|
601
613
|
for (const raw of rawStreams.values())
|
|
602
614
|
raw.inner.cleanup();
|
|
@@ -626,18 +638,38 @@ export function startJoin(opts) {
|
|
|
626
638
|
client.on("open", () => {
|
|
627
639
|
reconnectDelay = RECONNECT_BASE_MS;
|
|
628
640
|
setState("connected");
|
|
629
|
-
log("info",
|
|
641
|
+
log("info", `tunnel established (heartbeat ${heartbeatLabel})`);
|
|
630
642
|
if (heartbeat !== undefined)
|
|
631
643
|
clearInterval(heartbeat);
|
|
632
644
|
heartbeat = setInterval(() => {
|
|
633
645
|
if (client.readyState === client.OPEN) {
|
|
634
646
|
client.send(encodeFrame(FRAME_TYPE.PING, 0, jsonPayload({ ts: Date.now() })));
|
|
647
|
+
// 发出 PING 后武装死线:pongTimeoutMs 内收到任何入站帧即撤销(下方 message 处理)。
|
|
648
|
+
// 只在**没有未决死线**时武装——上一发 PING 未获回应时原死线继续计时,不重置。
|
|
649
|
+
if (livenessDeadline === undefined) {
|
|
650
|
+
livenessDeadline = setTimeout(() => {
|
|
651
|
+
livenessDeadline = undefined;
|
|
652
|
+
log("info", `heartbeat timeout — no frame from hub within ${pongTimeoutMs}ms; reconnecting`);
|
|
653
|
+
try {
|
|
654
|
+
client.terminate();
|
|
655
|
+
}
|
|
656
|
+
catch {
|
|
657
|
+
/* 已关闭 */
|
|
658
|
+
}
|
|
659
|
+
}, pongTimeoutMs);
|
|
660
|
+
livenessDeadline.unref?.();
|
|
661
|
+
}
|
|
635
662
|
}
|
|
636
|
-
},
|
|
663
|
+
}, heartbeatMs);
|
|
637
664
|
});
|
|
638
665
|
client.on("message", (data, isBinary) => {
|
|
639
666
|
if (!isBinary)
|
|
640
667
|
return;
|
|
668
|
+
// 任何入站帧都是存活证据 → 撤销死线(不限于 PONG)
|
|
669
|
+
if (livenessDeadline !== undefined) {
|
|
670
|
+
clearTimeout(livenessDeadline);
|
|
671
|
+
livenessDeadline = undefined;
|
|
672
|
+
}
|
|
641
673
|
const chunk = Array.isArray(data)
|
|
642
674
|
? Buffer.concat(data)
|
|
643
675
|
: Buffer.isBuffer(data)
|
package/dist/spawn-dsh.d.ts
CHANGED
|
@@ -40,9 +40,12 @@ export declare function compareDshVersions(a: string, b: string): number;
|
|
|
40
40
|
/**
|
|
41
41
|
* remote-dsh 已实测兼容的 dsh 版本窗口(registry 实存版本定界)。
|
|
42
42
|
* ⚠️ 适配新的 dsh 版本并真机实测后,须同步扩展此窗口(见 doc/fix/20260907-dsh-0.1.2-rc1-auth/)。
|
|
43
|
+
* 2026-09-11:MAX 扩到 `0.1.5-rc.2` —— 真机实测通过(spawn + ready 行 token + 会话 cookie 换发 +
|
|
44
|
+
* `/api` 转发 + HTML 注入 + WS `/api/remote.mux` 桥接 + join 的 `patchLoopbackJs` 命中),
|
|
45
|
+
* 见 doc/review/20260911-dsh-0.1.5-rc.2-plugin-compat.md §5。
|
|
43
46
|
*/
|
|
44
47
|
export declare const DSH_COMPAT_MIN = "0.1.1-rc.2";
|
|
45
|
-
export declare const DSH_COMPAT_MAX = "0.1.
|
|
48
|
+
export declare const DSH_COMPAT_MAX = "0.1.5-rc.2";
|
|
46
49
|
/**
|
|
47
50
|
* 版本落在实测窗口外时的提示文案(零文档导向:直接给动作指令,用户不查表)。
|
|
48
51
|
* - 比 max 新 → 升级 remote-dsh 或暂用旧 dsh;
|
package/dist/spawn-dsh.js
CHANGED
|
@@ -197,9 +197,12 @@ export function compareDshVersions(a, b) {
|
|
|
197
197
|
/**
|
|
198
198
|
* remote-dsh 已实测兼容的 dsh 版本窗口(registry 实存版本定界)。
|
|
199
199
|
* ⚠️ 适配新的 dsh 版本并真机实测后,须同步扩展此窗口(见 doc/fix/20260907-dsh-0.1.2-rc1-auth/)。
|
|
200
|
+
* 2026-09-11:MAX 扩到 `0.1.5-rc.2` —— 真机实测通过(spawn + ready 行 token + 会话 cookie 换发 +
|
|
201
|
+
* `/api` 转发 + HTML 注入 + WS `/api/remote.mux` 桥接 + join 的 `patchLoopbackJs` 命中),
|
|
202
|
+
* 见 doc/review/20260911-dsh-0.1.5-rc.2-plugin-compat.md §5。
|
|
200
203
|
*/
|
|
201
204
|
export const DSH_COMPAT_MIN = "0.1.1-rc.2";
|
|
202
|
-
export const DSH_COMPAT_MAX = "0.1.
|
|
205
|
+
export const DSH_COMPAT_MAX = "0.1.5-rc.2";
|
|
203
206
|
/**
|
|
204
207
|
* 版本落在实测窗口外时的提示文案(零文档导向:直接给动作指令,用户不查表)。
|
|
205
208
|
* - 比 max 新 → 升级 remote-dsh 或暂用旧 dsh;
|