im-rtc-call-engine 1.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/LICENSE +21 -0
- package/dist/bytes.d.ts +11 -0
- package/dist/bytes.d.ts.map +1 -0
- package/dist/bytes.js +20 -0
- package/dist/bytes.js.map +1 -0
- package/dist/callOptions.d.ts +27 -0
- package/dist/callOptions.d.ts.map +1 -0
- package/dist/callOptions.js +19 -0
- package/dist/callOptions.js.map +1 -0
- package/dist/deviceId.d.ts +10 -0
- package/dist/deviceId.d.ts.map +1 -0
- package/dist/deviceId.js +55 -0
- package/dist/deviceId.js.map +1 -0
- package/dist/engine.d.ts +302 -0
- package/dist/engine.d.ts.map +1 -0
- package/dist/engine.js +489 -0
- package/dist/engine.js.map +1 -0
- package/dist/engineBus.d.ts +16 -0
- package/dist/engineBus.d.ts.map +1 -0
- package/dist/engineBus.js +89 -0
- package/dist/engineBus.js.map +1 -0
- package/dist/engineWiring.d.ts +40 -0
- package/dist/engineWiring.d.ts.map +1 -0
- package/dist/engineWiring.js +57 -0
- package/dist/engineWiring.js.map +1 -0
- package/dist/errors.d.ts +185 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +253 -0
- package/dist/errors.js.map +1 -0
- package/dist/eventBus.d.ts +24 -0
- package/dist/eventBus.d.ts.map +1 -0
- package/dist/eventBus.js +50 -0
- package/dist/eventBus.js.map +1 -0
- package/dist/events.d.ts +220 -0
- package/dist/events.d.ts.map +1 -0
- package/dist/events.js +35 -0
- package/dist/events.js.map +1 -0
- package/dist/frameLoop.d.ts +93 -0
- package/dist/frameLoop.d.ts.map +1 -0
- package/dist/frameLoop.js +346 -0
- package/dist/frameLoop.js.map +1 -0
- package/dist/index.d.ts +60 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +42 -0
- package/dist/index.js.map +1 -0
- package/dist/logger.d.ts +64 -0
- package/dist/logger.d.ts.map +1 -0
- package/dist/logger.js +101 -0
- package/dist/logger.js.map +1 -0
- package/dist/media/engineMediaApi.d.ts +40 -0
- package/dist/media/engineMediaApi.d.ts.map +1 -0
- package/dist/media/engineMediaApi.js +71 -0
- package/dist/media/engineMediaApi.js.map +1 -0
- package/dist/media/firstFrameGate.d.ts +47 -0
- package/dist/media/firstFrameGate.d.ts.map +1 -0
- package/dist/media/firstFrameGate.js +117 -0
- package/dist/media/firstFrameGate.js.map +1 -0
- package/dist/media/mediaAdapter.d.ts +135 -0
- package/dist/media/mediaAdapter.d.ts.map +1 -0
- package/dist/media/mediaAdapter.js +2 -0
- package/dist/media/mediaAdapter.js.map +1 -0
- package/dist/media/mediaBridge.d.ts +99 -0
- package/dist/media/mediaBridge.d.ts.map +1 -0
- package/dist/media/mediaBridge.js +186 -0
- package/dist/media/mediaBridge.js.map +1 -0
- package/dist/media/mediaPlane.d.ts +58 -0
- package/dist/media/mediaPlane.d.ts.map +1 -0
- package/dist/media/mediaPlane.js +119 -0
- package/dist/media/mediaPlane.js.map +1 -0
- package/dist/media/videoProfile.d.ts +79 -0
- package/dist/media/videoProfile.d.ts.map +1 -0
- package/dist/media/videoProfile.js +46 -0
- package/dist/media/videoProfile.js.map +1 -0
- package/dist/media/videoProfile.test.d.ts +2 -0
- package/dist/media/videoProfile.test.d.ts.map +1 -0
- package/dist/media/videoProfile.test.js +26 -0
- package/dist/media/videoProfile.test.js.map +1 -0
- package/dist/media/viewRegistry.d.ts +75 -0
- package/dist/media/viewRegistry.d.ts.map +1 -0
- package/dist/media/viewRegistry.js +130 -0
- package/dist/media/viewRegistry.js.map +1 -0
- package/dist/media/webrtcAdapter.d.ts +158 -0
- package/dist/media/webrtcAdapter.d.ts.map +1 -0
- package/dist/media/webrtcAdapter.js +502 -0
- package/dist/media/webrtcAdapter.js.map +1 -0
- package/dist/protocolId.d.ts +14 -0
- package/dist/protocolId.d.ts.map +1 -0
- package/dist/protocolId.js +109 -0
- package/dist/protocolId.js.map +1 -0
- package/dist/reasons.d.ts +63 -0
- package/dist/reasons.d.ts.map +1 -0
- package/dist/reasons.js +81 -0
- package/dist/reasons.js.map +1 -0
- package/dist/redact.d.ts +19 -0
- package/dist/redact.d.ts.map +1 -0
- package/dist/redact.js +50 -0
- package/dist/redact.js.map +1 -0
- package/dist/signaling/backoff.d.ts +17 -0
- package/dist/signaling/backoff.d.ts.map +1 -0
- package/dist/signaling/backoff.js +23 -0
- package/dist/signaling/backoff.js.map +1 -0
- package/dist/signaling/candidate.d.ts +19 -0
- package/dist/signaling/candidate.d.ts.map +1 -0
- package/dist/signaling/candidate.js +22 -0
- package/dist/signaling/candidate.js.map +1 -0
- package/dist/signaling/caseMapping.d.ts +19 -0
- package/dist/signaling/caseMapping.d.ts.map +1 -0
- package/dist/signaling/caseMapping.js +34 -0
- package/dist/signaling/caseMapping.js.map +1 -0
- package/dist/signaling/connection.d.ts +110 -0
- package/dist/signaling/connection.d.ts.map +1 -0
- package/dist/signaling/connection.js +365 -0
- package/dist/signaling/connection.js.map +1 -0
- package/dist/signaling/connectionFactory.d.ts +55 -0
- package/dist/signaling/connectionFactory.d.ts.map +1 -0
- package/dist/signaling/connectionFactory.js +29 -0
- package/dist/signaling/connectionFactory.js.map +1 -0
- package/dist/signaling/connectionTypes.d.ts +94 -0
- package/dist/signaling/connectionTypes.d.ts.map +1 -0
- package/dist/signaling/connectionTypes.js +2 -0
- package/dist/signaling/connectionTypes.js.map +1 -0
- package/dist/signaling/discipline.d.ts +6 -0
- package/dist/signaling/discipline.d.ts.map +1 -0
- package/dist/signaling/discipline.js +100 -0
- package/dist/signaling/discipline.js.map +1 -0
- package/dist/signaling/enums.d.ts +53 -0
- package/dist/signaling/enums.d.ts.map +1 -0
- package/dist/signaling/enums.js +52 -0
- package/dist/signaling/enums.js.map +1 -0
- package/dist/signaling/envelope.d.ts +31 -0
- package/dist/signaling/envelope.d.ts.map +1 -0
- package/dist/signaling/envelope.js +91 -0
- package/dist/signaling/envelope.js.map +1 -0
- package/dist/signaling/fieldSpec.d.ts +101 -0
- package/dist/signaling/fieldSpec.d.ts.map +1 -0
- package/dist/signaling/fieldSpec.js +130 -0
- package/dist/signaling/fieldSpec.js.map +1 -0
- package/dist/signaling/frameSender.d.ts +34 -0
- package/dist/signaling/frameSender.d.ts.map +1 -0
- package/dist/signaling/frameSender.js +57 -0
- package/dist/signaling/frameSender.js.map +1 -0
- package/dist/signaling/frames.call.d.ts +299 -0
- package/dist/signaling/frames.call.d.ts.map +1 -0
- package/dist/signaling/frames.call.js +149 -0
- package/dist/signaling/frames.call.js.map +1 -0
- package/dist/signaling/frames.room.d.ts +566 -0
- package/dist/signaling/frames.room.d.ts.map +1 -0
- package/dist/signaling/frames.room.js +165 -0
- package/dist/signaling/frames.room.js.map +1 -0
- package/dist/signaling/frames.sys.d.ts +145 -0
- package/dist/signaling/frames.sys.d.ts.map +1 -0
- package/dist/signaling/frames.sys.js +53 -0
- package/dist/signaling/frames.sys.js.map +1 -0
- package/dist/signaling/handshakeGiveUp.d.ts +36 -0
- package/dist/signaling/handshakeGiveUp.d.ts.map +1 -0
- package/dist/signaling/handshakeGiveUp.js +48 -0
- package/dist/signaling/handshakeGiveUp.js.map +1 -0
- package/dist/signaling/heartbeat.d.ts +34 -0
- package/dist/signaling/heartbeat.d.ts.map +1 -0
- package/dist/signaling/heartbeat.js +52 -0
- package/dist/signaling/heartbeat.js.map +1 -0
- package/dist/signaling/pendingRequests.d.ts +33 -0
- package/dist/signaling/pendingRequests.d.ts.map +1 -0
- package/dist/signaling/pendingRequests.js +57 -0
- package/dist/signaling/pendingRequests.js.map +1 -0
- package/dist/signaling/reconnector.d.ts +43 -0
- package/dist/signaling/reconnector.d.ts.map +1 -0
- package/dist/signaling/reconnector.js +76 -0
- package/dist/signaling/reconnector.js.map +1 -0
- package/dist/signaling/registry.d.ts +100 -0
- package/dist/signaling/registry.d.ts.map +1 -0
- package/dist/signaling/registry.js +217 -0
- package/dist/signaling/registry.js.map +1 -0
- package/dist/signaling/resumeDeadline.d.ts +48 -0
- package/dist/signaling/resumeDeadline.d.ts.map +1 -0
- package/dist/signaling/resumeDeadline.js +89 -0
- package/dist/signaling/resumeDeadline.js.map +1 -0
- package/dist/signaling/tokenExpiry.d.ts +89 -0
- package/dist/signaling/tokenExpiry.d.ts.map +1 -0
- package/dist/signaling/tokenExpiry.js +106 -0
- package/dist/signaling/tokenExpiry.js.map +1 -0
- package/dist/signaling/webSocket.d.ts +59 -0
- package/dist/signaling/webSocket.d.ts.map +1 -0
- package/dist/signaling/webSocket.js +50 -0
- package/dist/signaling/webSocket.js.map +1 -0
- package/dist/state/callMachine.d.ts +56 -0
- package/dist/state/callMachine.d.ts.map +1 -0
- package/dist/state/callMachine.js +176 -0
- package/dist/state/callMachine.js.map +1 -0
- package/dist/state/callRecv.d.ts +12 -0
- package/dist/state/callRecv.d.ts.map +1 -0
- package/dist/state/callRecv.js +255 -0
- package/dist/state/callRecv.js.map +1 -0
- package/dist/state/engineMachine.d.ts +41 -0
- package/dist/state/engineMachine.d.ts.map +1 -0
- package/dist/state/engineMachine.js +210 -0
- package/dist/state/engineMachine.js.map +1 -0
- package/dist/state/forceEnd.d.ts +44 -0
- package/dist/state/forceEnd.d.ts.map +1 -0
- package/dist/state/forceEnd.js +96 -0
- package/dist/state/forceEnd.js.map +1 -0
- package/dist/state/roomMachine.d.ts +92 -0
- package/dist/state/roomMachine.d.ts.map +1 -0
- package/dist/state/roomMachine.js +319 -0
- package/dist/state/roomMachine.js.map +1 -0
- package/dist/state/roomRecv.d.ts +7 -0
- package/dist/state/roomRecv.d.ts.map +1 -0
- package/dist/state/roomRecv.js +209 -0
- package/dist/state/roomRecv.js.map +1 -0
- package/dist/state/types.d.ts +61 -0
- package/dist/state/types.d.ts.map +1 -0
- package/dist/state/types.js +30 -0
- package/dist/state/types.js.map +1 -0
- package/dist/version.d.ts +11 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +11 -0
- package/dist/version.js.map +1 -0
- package/package.json +35 -0
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { ErrorCode, RtcError, rtcErrorFromWire } from '../errors.js';
|
|
2
|
+
/** PendingRequests 管理在途请求与它们的超时。 */
|
|
3
|
+
export class PendingRequests {
|
|
4
|
+
timeoutMs;
|
|
5
|
+
waiters = new Map();
|
|
6
|
+
constructor(timeoutMs) {
|
|
7
|
+
this.timeoutMs = timeoutMs;
|
|
8
|
+
}
|
|
9
|
+
/** track 登记一个在途请求,返回它的 Promise。 */
|
|
10
|
+
track(reqId, type) {
|
|
11
|
+
return new Promise((resolve, reject) => {
|
|
12
|
+
const timer = setTimeout(() => {
|
|
13
|
+
this.waiters.delete(reqId);
|
|
14
|
+
reject(new RtcError(ErrorCode.signalingTimeout, { forType: type }));
|
|
15
|
+
}, this.timeoutMs);
|
|
16
|
+
this.waiters.set(reqId, { resolve, reject, timer, type });
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
/** abandon 撤掉一个还没发出去就失败的请求。 */
|
|
20
|
+
abandon(reqId) {
|
|
21
|
+
const waiter = this.waiters.get(reqId);
|
|
22
|
+
if (waiter === undefined)
|
|
23
|
+
return;
|
|
24
|
+
clearTimeout(waiter.timer);
|
|
25
|
+
this.waiters.delete(reqId);
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* settle 用一帧应答结算在途请求。
|
|
29
|
+
* 返回 false 表示这个 req_id 没人在等——调用方应当把它当事件处理。
|
|
30
|
+
*/
|
|
31
|
+
settle(envelope, decode) {
|
|
32
|
+
const waiter = this.waiters.get(envelope.reqId);
|
|
33
|
+
if (waiter === undefined)
|
|
34
|
+
return false;
|
|
35
|
+
this.waiters.delete(envelope.reqId);
|
|
36
|
+
clearTimeout(waiter.timer);
|
|
37
|
+
if (envelope.type === 'sys.error') {
|
|
38
|
+
waiter.reject(rtcErrorFromWire(envelope.data, waiter.type));
|
|
39
|
+
return true;
|
|
40
|
+
}
|
|
41
|
+
waiter.resolve({ envelope, data: decode(envelope) });
|
|
42
|
+
return true;
|
|
43
|
+
}
|
|
44
|
+
/** rejectAll 在断线时把全部在途请求失败掉——它们的应答永远不会来了。 */
|
|
45
|
+
rejectAll(error) {
|
|
46
|
+
for (const waiter of this.waiters.values()) {
|
|
47
|
+
clearTimeout(waiter.timer);
|
|
48
|
+
waiter.reject(error);
|
|
49
|
+
}
|
|
50
|
+
this.waiters.clear();
|
|
51
|
+
}
|
|
52
|
+
/** size 供测试与诊断观察。 */
|
|
53
|
+
get size() {
|
|
54
|
+
return this.waiters.size;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
//# sourceMappingURL=pendingRequests.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pendingRequests.js","sourceRoot":"","sources":["../../src/signaling/pendingRequests.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAuBrE,oCAAoC;AACpC,MAAM,OAAO,eAAe;IAGG;IAFZ,OAAO,GAAG,IAAI,GAAG,EAAkB,CAAC;IAErD,YAA6B,SAAiB;QAAjB,cAAS,GAAT,SAAS,CAAQ;IAAG,CAAC;IAElD,mCAAmC;IACnC,KAAK,CAAC,KAAa,EAAE,IAAY;QAC/B,OAAO,IAAI,OAAO,CAAgB,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YACpD,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE;gBAC5B,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;gBAC3B,MAAM,CAAC,IAAI,QAAQ,CAAC,SAAS,CAAC,gBAAgB,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;YACtE,CAAC,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC;YACnB,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;QAC5D,CAAC,CAAC,CAAC;IACL,CAAC;IAED,+BAA+B;IAC/B,OAAO,CAAC,KAAa;QACnB,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QACvC,IAAI,MAAM,KAAK,SAAS;YAAE,OAAO;QACjC,YAAY,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QAC3B,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IAC7B,CAAC;IAED;;;OAGG;IACH,MAAM,CAAC,QAAkB,EAAE,MAAkD;QAC3E,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;QAChD,IAAI,MAAM,KAAK,SAAS;YAAE,OAAO,KAAK,CAAC;QACvC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;QACpC,YAAY,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QAE3B,IAAI,QAAQ,CAAC,IAAI,KAAK,WAAW,EAAE,CAAC;YAClC,MAAM,CAAC,MAAM,CAAC,gBAAgB,CAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC;YAC5D,OAAO,IAAI,CAAC;QACd,CAAC;QACD,MAAM,CAAC,OAAO,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;QACrD,OAAO,IAAI,CAAC;IACd,CAAC;IAED,6CAA6C;IAC7C,SAAS,CAAC,KAAe;QACvB,KAAK,MAAM,MAAM,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC;YAC3C,YAAY,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YAC3B,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACvB,CAAC;QACD,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;IACvB,CAAC;IAED,qBAAqB;IACrB,IAAI,IAAI;QACN,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC;IAC3B,CAAC;CACF"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 重连调度(RTC_PROTOCOL.md §1.4)。
|
|
3
|
+
*
|
|
4
|
+
* 从 Connection 里拆出来是为了体量红线(CONVENTIONS §2),也让「退避档 + 抖动 +
|
|
5
|
+
* 什么时候放弃」这组规则有独立的测试面。
|
|
6
|
+
*
|
|
7
|
+
* **注意它不判断「该不该重连」**——那是关闭码的事(`webSocket.ts` 的
|
|
8
|
+
* `shouldReconnect`)。这里只管「决定重连之后,等多久、第几次」。
|
|
9
|
+
*/
|
|
10
|
+
export declare class Reconnector {
|
|
11
|
+
private readonly reconnect;
|
|
12
|
+
private readonly onFailed;
|
|
13
|
+
private readonly random;
|
|
14
|
+
private timer;
|
|
15
|
+
private attempt;
|
|
16
|
+
/** 已经彻底放弃。见 stop() —— 这是**闩**,不是一次性的取消。 */
|
|
17
|
+
private stopped;
|
|
18
|
+
constructor(reconnect: () => Promise<void>, onFailed: (error: unknown) => void, random?: () => number);
|
|
19
|
+
/**
|
|
20
|
+
* schedule 安排下一次重连。
|
|
21
|
+
*
|
|
22
|
+
* **已经排着一次就什么都不做**(不重排、不进档)。一次失败会从两条路同时走到这里:
|
|
23
|
+
* `connect()` 的 promise 被拒(下面的 catch)和 socket 的 close 事件——
|
|
24
|
+
* 每次都重排的话退避档一次涨两级,日志里是 `attempt=14` 紧跟着 `attempt=15`,
|
|
25
|
+
* 十几分钟后就退到了几十秒一次,看着像「不重连了」。
|
|
26
|
+
*/
|
|
27
|
+
schedule(): void;
|
|
28
|
+
/** succeeded 在一次连接成功后把退避档重置,并解掉 stop() 的闩。 */
|
|
29
|
+
succeeded(): void;
|
|
30
|
+
/**
|
|
31
|
+
* stop 彻底放弃重连,**并挡住之后的 schedule()**。
|
|
32
|
+
*
|
|
33
|
+
* 为什么不能只 `cancel()`:一次失败会从两条路走到这里,而 `connect()` 被拒的那条
|
|
34
|
+
* 是**微任务**——它排在 close 事件的处理之后。只取消定时器的话,
|
|
35
|
+
* 刚放弃完,那个迟到的 catch 又把重连排了回来,「不再重连」等于没生效。
|
|
36
|
+
*/
|
|
37
|
+
stop(): void;
|
|
38
|
+
/** cancel 取消未触发的重连。幂等。 */
|
|
39
|
+
cancel(): void;
|
|
40
|
+
/** attempts 供测试与诊断观察。 */
|
|
41
|
+
get attempts(): number;
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=reconnector.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reconnector.d.ts","sourceRoot":"","sources":["../../src/signaling/reconnector.ts"],"names":[],"mappings":"AAGA;;;;;;;;GAQG;AACH,qBAAa,WAAW;IAOpB,OAAO,CAAC,QAAQ,CAAC,SAAS;IAC1B,OAAO,CAAC,QAAQ,CAAC,QAAQ;IACzB,OAAO,CAAC,QAAQ,CAAC,MAAM;IARzB,OAAO,CAAC,KAAK,CAA8C;IAC3D,OAAO,CAAC,OAAO,CAAK;IACpB,2CAA2C;IAC3C,OAAO,CAAC,OAAO,CAAS;gBAGL,SAAS,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,EAC9B,QAAQ,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,EAClC,MAAM,GAAE,MAAM,MAAoB;IAGrD;;;;;;;OAOG;IACH,QAAQ,IAAI,IAAI;IAgBhB,8CAA8C;IAC9C,SAAS,IAAI,IAAI;IAKjB;;;;;;OAMG;IACH,IAAI,IAAI,IAAI;IAKZ,0BAA0B;IAC1B,MAAM,IAAI,IAAI;IAOd,yBAAyB;IACzB,IAAI,QAAQ,IAAI,MAAM,CAErB;CACF"}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { logger } from '../logger.js';
|
|
2
|
+
import { backoffDelayMs } from './backoff.js';
|
|
3
|
+
/**
|
|
4
|
+
* 重连调度(RTC_PROTOCOL.md §1.4)。
|
|
5
|
+
*
|
|
6
|
+
* 从 Connection 里拆出来是为了体量红线(CONVENTIONS §2),也让「退避档 + 抖动 +
|
|
7
|
+
* 什么时候放弃」这组规则有独立的测试面。
|
|
8
|
+
*
|
|
9
|
+
* **注意它不判断「该不该重连」**——那是关闭码的事(`webSocket.ts` 的
|
|
10
|
+
* `shouldReconnect`)。这里只管「决定重连之后,等多久、第几次」。
|
|
11
|
+
*/
|
|
12
|
+
export class Reconnector {
|
|
13
|
+
reconnect;
|
|
14
|
+
onFailed;
|
|
15
|
+
random;
|
|
16
|
+
timer = null;
|
|
17
|
+
attempt = 0;
|
|
18
|
+
/** 已经彻底放弃。见 stop() —— 这是**闩**,不是一次性的取消。 */
|
|
19
|
+
stopped = false;
|
|
20
|
+
constructor(reconnect, onFailed, random = Math.random) {
|
|
21
|
+
this.reconnect = reconnect;
|
|
22
|
+
this.onFailed = onFailed;
|
|
23
|
+
this.random = random;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* schedule 安排下一次重连。
|
|
27
|
+
*
|
|
28
|
+
* **已经排着一次就什么都不做**(不重排、不进档)。一次失败会从两条路同时走到这里:
|
|
29
|
+
* `connect()` 的 promise 被拒(下面的 catch)和 socket 的 close 事件——
|
|
30
|
+
* 每次都重排的话退避档一次涨两级,日志里是 `attempt=14` 紧跟着 `attempt=15`,
|
|
31
|
+
* 十几分钟后就退到了几十秒一次,看着像「不重连了」。
|
|
32
|
+
*/
|
|
33
|
+
schedule() {
|
|
34
|
+
if (this.stopped || this.timer !== null)
|
|
35
|
+
return;
|
|
36
|
+
const delayMs = backoffDelayMs(this.attempt, this.random);
|
|
37
|
+
this.attempt += 1;
|
|
38
|
+
logger.info('计划重连', { attempt: this.attempt, delayMs });
|
|
39
|
+
this.timer = setTimeout(() => {
|
|
40
|
+
this.timer = null;
|
|
41
|
+
void this.reconnect().catch((err) => {
|
|
42
|
+
this.onFailed(err);
|
|
43
|
+
// 失败后继续退避——档位不重置,否则断网期间会退化成每秒重试。
|
|
44
|
+
this.schedule();
|
|
45
|
+
});
|
|
46
|
+
}, delayMs);
|
|
47
|
+
}
|
|
48
|
+
/** succeeded 在一次连接成功后把退避档重置,并解掉 stop() 的闩。 */
|
|
49
|
+
succeeded() {
|
|
50
|
+
this.attempt = 0;
|
|
51
|
+
this.stopped = false;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* stop 彻底放弃重连,**并挡住之后的 schedule()**。
|
|
55
|
+
*
|
|
56
|
+
* 为什么不能只 `cancel()`:一次失败会从两条路走到这里,而 `connect()` 被拒的那条
|
|
57
|
+
* 是**微任务**——它排在 close 事件的处理之后。只取消定时器的话,
|
|
58
|
+
* 刚放弃完,那个迟到的 catch 又把重连排了回来,「不再重连」等于没生效。
|
|
59
|
+
*/
|
|
60
|
+
stop() {
|
|
61
|
+
this.stopped = true;
|
|
62
|
+
this.cancel();
|
|
63
|
+
}
|
|
64
|
+
/** cancel 取消未触发的重连。幂等。 */
|
|
65
|
+
cancel() {
|
|
66
|
+
if (this.timer !== null) {
|
|
67
|
+
clearTimeout(this.timer);
|
|
68
|
+
this.timer = null;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
/** attempts 供测试与诊断观察。 */
|
|
72
|
+
get attempts() {
|
|
73
|
+
return this.attempt;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
//# sourceMappingURL=reconnector.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reconnector.js","sourceRoot":"","sources":["../../src/signaling/reconnector.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AACtC,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAE9C;;;;;;;;GAQG;AACH,MAAM,OAAO,WAAW;IAOH;IACA;IACA;IARX,KAAK,GAAyC,IAAI,CAAC;IACnD,OAAO,GAAG,CAAC,CAAC;IACpB,2CAA2C;IACnC,OAAO,GAAG,KAAK,CAAC;IAExB,YACmB,SAA8B,EAC9B,QAAkC,EAClC,SAAuB,IAAI,CAAC,MAAM;QAFlC,cAAS,GAAT,SAAS,CAAqB;QAC9B,aAAQ,GAAR,QAAQ,CAA0B;QAClC,WAAM,GAAN,MAAM,CAA4B;IAClD,CAAC;IAEJ;;;;;;;OAOG;IACH,QAAQ;QACN,IAAI,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,KAAK,KAAK,IAAI;YAAE,OAAO;QAChD,MAAM,OAAO,GAAG,cAAc,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;QAC1D,IAAI,CAAC,OAAO,IAAI,CAAC,CAAC;QAClB,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,OAAO,EAAE,CAAC,CAAC;QAExD,IAAI,CAAC,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE;YAC3B,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC;YAClB,KAAK,IAAI,CAAC,SAAS,EAAE,CAAC,KAAK,CAAC,CAAC,GAAY,EAAE,EAAE;gBAC3C,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;gBACnB,iCAAiC;gBACjC,IAAI,CAAC,QAAQ,EAAE,CAAC;YAClB,CAAC,CAAC,CAAC;QACL,CAAC,EAAE,OAAO,CAAC,CAAC;IACd,CAAC;IAED,8CAA8C;IAC9C,SAAS;QACP,IAAI,CAAC,OAAO,GAAG,CAAC,CAAC;QACjB,IAAI,CAAC,OAAO,GAAG,KAAK,CAAC;IACvB,CAAC;IAED;;;;;;OAMG;IACH,IAAI;QACF,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;QACpB,IAAI,CAAC,MAAM,EAAE,CAAC;IAChB,CAAC;IAED,0BAA0B;IAC1B,MAAM;QACJ,IAAI,IAAI,CAAC,KAAK,KAAK,IAAI,EAAE,CAAC;YACxB,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YACzB,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC;QACpB,CAAC;IACH,CAAC;IAED,yBAAyB;IACzB,IAAI,QAAQ;QACV,OAAO,IAAI,CAAC,OAAO,CAAC;IACtB,CAAC;CACF"}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import type { Envelope } from './envelope.js';
|
|
2
|
+
import type { FrameData, FrameFields } from './fieldSpec.js';
|
|
3
|
+
/**
|
|
4
|
+
* 帧类型注册表,对应 RTC_PROTOCOL.md 附录 A 的帧索引。
|
|
5
|
+
*
|
|
6
|
+
* 「加一个帧」的完整动作是:改协议文档 → 改 conformance 向量 → 在这里注册 → 四仓跟进。
|
|
7
|
+
* 顺序不许颠倒(§9)。
|
|
8
|
+
*/
|
|
9
|
+
/** FrameType 是全部帧类型的常量表。命名规则见 §2.3:`<域>.<动作>[.ok]`。 */
|
|
10
|
+
export declare const FrameType: {
|
|
11
|
+
readonly hello: "sys.hello";
|
|
12
|
+
readonly helloOk: "sys.hello.ok";
|
|
13
|
+
readonly ping: "sys.ping";
|
|
14
|
+
readonly pong: "sys.pong";
|
|
15
|
+
readonly error: "sys.error";
|
|
16
|
+
readonly roomJoin: "room.join";
|
|
17
|
+
readonly roomLeave: "room.leave";
|
|
18
|
+
readonly roomPublish: "room.publish";
|
|
19
|
+
readonly roomUnpublish: "room.unpublish";
|
|
20
|
+
readonly roomMute: "room.mute";
|
|
21
|
+
readonly roomSubscribe: "room.subscribe";
|
|
22
|
+
readonly roomUnsubscribe: "room.unsubscribe";
|
|
23
|
+
readonly roomUpdateLayer: "room.update_layer";
|
|
24
|
+
readonly roomOffer: "room.offer";
|
|
25
|
+
readonly roomAnswer: "room.answer";
|
|
26
|
+
readonly roomIceCandidate: "room.ice_candidate";
|
|
27
|
+
readonly roomParticipantJoined: "room.participant_joined";
|
|
28
|
+
readonly roomParticipantLeft: "room.participant_left";
|
|
29
|
+
readonly roomTrackPublished: "room.track_published";
|
|
30
|
+
readonly roomTrackUnpublished: "room.track_unpublished";
|
|
31
|
+
readonly roomTrackMuted: "room.track_muted";
|
|
32
|
+
readonly roomActiveSpeakers: "room.active_speakers";
|
|
33
|
+
readonly roomQuality: "room.quality";
|
|
34
|
+
readonly roomClosed: "room.closed";
|
|
35
|
+
readonly callInvite: "call.invite";
|
|
36
|
+
readonly callAccept: "call.accept";
|
|
37
|
+
readonly callReject: "call.reject";
|
|
38
|
+
readonly callCancel: "call.cancel";
|
|
39
|
+
readonly callHangup: "call.hangup";
|
|
40
|
+
readonly callInviteMore: "call.invite_more";
|
|
41
|
+
readonly callJoin: "call.join";
|
|
42
|
+
readonly callIncoming: "call.incoming";
|
|
43
|
+
readonly callRinging: "call.ringing";
|
|
44
|
+
readonly callAccepted: "call.accepted";
|
|
45
|
+
readonly callRejected: "call.rejected";
|
|
46
|
+
readonly callBusy: "call.busy";
|
|
47
|
+
readonly callNoAnswer: "call.no_answer";
|
|
48
|
+
readonly callCancelled: "call.cancelled";
|
|
49
|
+
readonly callConnected: "call.connected";
|
|
50
|
+
readonly callHandledElsewhere: "call.handled_elsewhere";
|
|
51
|
+
readonly callEnded: "call.ended";
|
|
52
|
+
};
|
|
53
|
+
/**
|
|
54
|
+
* REQUEST_TYPES 是全部上行请求帧。请求必须带非空 req_id,且**恰好**有一条应答。
|
|
55
|
+
*
|
|
56
|
+
* room.offer / answer / ice_candidate 不在这张表里——它们是双向的,
|
|
57
|
+
* 「谁是请求方」由 pc 字段决定(§3.3),不由 type 决定。
|
|
58
|
+
*/
|
|
59
|
+
export declare const REQUEST_TYPES: readonly string[];
|
|
60
|
+
/**
|
|
61
|
+
* RESERVED_TYPES 是 §3.6 的会议层留位帧:**已占名但 v1 不实现**。
|
|
62
|
+
* 客户端不该发它们;收到服务端的 1003 时要能分清「将来会有」与「压根没有」。
|
|
63
|
+
*/
|
|
64
|
+
export declare const RESERVED_TYPES: readonly string[];
|
|
65
|
+
/** isRequestType 报告这个 type 是不是上行请求帧。 */
|
|
66
|
+
export declare function isRequestType(type: string): boolean;
|
|
67
|
+
/** isReservedType 报告这个 type 是不是已占名但未实现的会议层帧。 */
|
|
68
|
+
export declare function isReservedType(type: string): boolean;
|
|
69
|
+
/**
|
|
70
|
+
* lookupFrame 返回某帧类型的字段声明。
|
|
71
|
+
*
|
|
72
|
+
* 请求帧的 .ok 如果没单独登记,一律给空对象——纯 ack 是常态,
|
|
73
|
+
* 不必为每个 room.mute.ok 写一份声明。
|
|
74
|
+
*/
|
|
75
|
+
export declare function lookupFrame(type: string): FrameFields | undefined;
|
|
76
|
+
/** knownFrameTypes 列出全部已注册的帧类型(不含自动派生的 .ok),供测试核对。 */
|
|
77
|
+
export declare function knownFrameTypes(): string[];
|
|
78
|
+
/**
|
|
79
|
+
* decodeFrame 按 Envelope.type 解出帧数据。
|
|
80
|
+
*
|
|
81
|
+
* 未注册的 type 抛 unknown_type——但**客户端收到未知 type 时应当静默忽略**
|
|
82
|
+
* (§2.3 前向兼容,服务端可能比客户端新),别把这个错误抛给宿主。
|
|
83
|
+
*/
|
|
84
|
+
export declare function decodeFrame(envelope: Envelope): Record<string, unknown>;
|
|
85
|
+
/**
|
|
86
|
+
* newFrameData 返回某帧**已填好协议默认值**的数据对象。
|
|
87
|
+
*
|
|
88
|
+
* # 发送方必须用它
|
|
89
|
+
*
|
|
90
|
+
* 「可选字段用省略表达,接收方按默认值填」(§2.4 规则 2)只对**省略**成立。
|
|
91
|
+
* 而 JSON.stringify 会把显式的 false / 0 编码出去:直接写
|
|
92
|
+
* `{ room_id: 'r-1' }` 少了 auto_subscribe,写 `{ ..., auto_subscribe: false }`
|
|
93
|
+
* 又把默认的 true 覆盖成了 false。两种写法都会让人进了房收不到任何流。
|
|
94
|
+
*
|
|
95
|
+
* 三端同理(Go 的结构体零值、Swift 的 Codable)。**发送侧一律从这里开始改字段。**
|
|
96
|
+
*/
|
|
97
|
+
export declare function newFrameData<F extends FrameFields>(fields: F): FrameData<F>;
|
|
98
|
+
/** encodeFrame 把帧数据映射回线路上的 snake_case data。 */
|
|
99
|
+
export declare function encodeFrame<F extends FrameFields>(fields: F, value: FrameData<F>): Record<string, unknown>;
|
|
100
|
+
//# sourceMappingURL=registry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/signaling/registry.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAG9C,OAAO,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAK7D;;;;;GAKG;AAEH,uDAAuD;AACvD,eAAO,MAAM,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA8CZ,CAAC;AAEX;;;;;GAKG;AACH,eAAO,MAAM,aAAa,EAAE,SAAS,MAAM,EAkB1C,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,cAAc,EAAE,SAAS,MAAM,EAS3C,CAAC;AAKF,wCAAwC;AACxC,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEnD;AAED,gDAAgD;AAChD,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEpD;AA+DD;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW,GAAG,SAAS,CAQjE;AAED,sDAAsD;AACtD,wBAAgB,eAAe,IAAI,MAAM,EAAE,CAE1C;AAED;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,QAAQ,EAAE,QAAQ,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CASvE;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,YAAY,CAAC,CAAC,SAAS,WAAW,EAAE,MAAM,EAAE,CAAC,GAAG,SAAS,CAAC,CAAC,CAAC,CAE3E;AAED,+CAA+C;AAC/C,wBAAgB,WAAW,CAAC,CAAC,SAAS,WAAW,EAC/C,MAAM,EAAE,CAAC,EACT,KAAK,EAAE,SAAS,CAAC,CAAC,CAAC,GAClB,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAEzB"}
|
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
import { ErrorCode, RtcError } from '../errors.js';
|
|
2
|
+
import { OK_SUFFIX, okType } from './envelope.js';
|
|
3
|
+
import { decodeFields, encodeFields } from './fieldSpec.js';
|
|
4
|
+
import * as call from './frames.call.js';
|
|
5
|
+
import * as room from './frames.room.js';
|
|
6
|
+
import * as sys from './frames.sys.js';
|
|
7
|
+
/**
|
|
8
|
+
* 帧类型注册表,对应 RTC_PROTOCOL.md 附录 A 的帧索引。
|
|
9
|
+
*
|
|
10
|
+
* 「加一个帧」的完整动作是:改协议文档 → 改 conformance 向量 → 在这里注册 → 四仓跟进。
|
|
11
|
+
* 顺序不许颠倒(§9)。
|
|
12
|
+
*/
|
|
13
|
+
/** FrameType 是全部帧类型的常量表。命名规则见 §2.3:`<域>.<动作>[.ok]`。 */
|
|
14
|
+
export const FrameType = {
|
|
15
|
+
hello: 'sys.hello',
|
|
16
|
+
helloOk: 'sys.hello.ok',
|
|
17
|
+
ping: 'sys.ping',
|
|
18
|
+
pong: 'sys.pong',
|
|
19
|
+
error: 'sys.error',
|
|
20
|
+
roomJoin: 'room.join',
|
|
21
|
+
roomLeave: 'room.leave',
|
|
22
|
+
roomPublish: 'room.publish',
|
|
23
|
+
roomUnpublish: 'room.unpublish',
|
|
24
|
+
roomMute: 'room.mute',
|
|
25
|
+
roomSubscribe: 'room.subscribe',
|
|
26
|
+
roomUnsubscribe: 'room.unsubscribe',
|
|
27
|
+
roomUpdateLayer: 'room.update_layer',
|
|
28
|
+
roomOffer: 'room.offer',
|
|
29
|
+
roomAnswer: 'room.answer',
|
|
30
|
+
roomIceCandidate: 'room.ice_candidate',
|
|
31
|
+
roomParticipantJoined: 'room.participant_joined',
|
|
32
|
+
roomParticipantLeft: 'room.participant_left',
|
|
33
|
+
roomTrackPublished: 'room.track_published',
|
|
34
|
+
roomTrackUnpublished: 'room.track_unpublished',
|
|
35
|
+
roomTrackMuted: 'room.track_muted',
|
|
36
|
+
roomActiveSpeakers: 'room.active_speakers',
|
|
37
|
+
roomQuality: 'room.quality',
|
|
38
|
+
roomClosed: 'room.closed',
|
|
39
|
+
callInvite: 'call.invite',
|
|
40
|
+
callAccept: 'call.accept',
|
|
41
|
+
callReject: 'call.reject',
|
|
42
|
+
callCancel: 'call.cancel',
|
|
43
|
+
callHangup: 'call.hangup',
|
|
44
|
+
callInviteMore: 'call.invite_more',
|
|
45
|
+
callJoin: 'call.join',
|
|
46
|
+
callIncoming: 'call.incoming',
|
|
47
|
+
callRinging: 'call.ringing',
|
|
48
|
+
callAccepted: 'call.accepted',
|
|
49
|
+
callRejected: 'call.rejected',
|
|
50
|
+
callBusy: 'call.busy',
|
|
51
|
+
callNoAnswer: 'call.no_answer',
|
|
52
|
+
callCancelled: 'call.cancelled',
|
|
53
|
+
callConnected: 'call.connected',
|
|
54
|
+
callHandledElsewhere: 'call.handled_elsewhere',
|
|
55
|
+
callEnded: 'call.ended',
|
|
56
|
+
};
|
|
57
|
+
/**
|
|
58
|
+
* REQUEST_TYPES 是全部上行请求帧。请求必须带非空 req_id,且**恰好**有一条应答。
|
|
59
|
+
*
|
|
60
|
+
* room.offer / answer / ice_candidate 不在这张表里——它们是双向的,
|
|
61
|
+
* 「谁是请求方」由 pc 字段决定(§3.3),不由 type 决定。
|
|
62
|
+
*/
|
|
63
|
+
export const REQUEST_TYPES = [
|
|
64
|
+
FrameType.hello,
|
|
65
|
+
FrameType.ping,
|
|
66
|
+
FrameType.roomJoin,
|
|
67
|
+
FrameType.roomLeave,
|
|
68
|
+
FrameType.roomPublish,
|
|
69
|
+
FrameType.roomUnpublish,
|
|
70
|
+
FrameType.roomMute,
|
|
71
|
+
FrameType.roomSubscribe,
|
|
72
|
+
FrameType.roomUnsubscribe,
|
|
73
|
+
FrameType.roomUpdateLayer,
|
|
74
|
+
FrameType.callInvite,
|
|
75
|
+
FrameType.callAccept,
|
|
76
|
+
FrameType.callReject,
|
|
77
|
+
FrameType.callCancel,
|
|
78
|
+
FrameType.callHangup,
|
|
79
|
+
FrameType.callInviteMore,
|
|
80
|
+
FrameType.callJoin,
|
|
81
|
+
];
|
|
82
|
+
/**
|
|
83
|
+
* RESERVED_TYPES 是 §3.6 的会议层留位帧:**已占名但 v1 不实现**。
|
|
84
|
+
* 客户端不该发它们;收到服务端的 1003 时要能分清「将来会有」与「压根没有」。
|
|
85
|
+
*/
|
|
86
|
+
export const RESERVED_TYPES = [
|
|
87
|
+
'room.mute_participant',
|
|
88
|
+
'room.kick',
|
|
89
|
+
'room.lock',
|
|
90
|
+
'room.raise_hand',
|
|
91
|
+
'room.participant_muted',
|
|
92
|
+
'room.participant_kicked',
|
|
93
|
+
'room.hand_raised',
|
|
94
|
+
'room.locked',
|
|
95
|
+
];
|
|
96
|
+
const REQUEST_SET = new Set(REQUEST_TYPES);
|
|
97
|
+
const RESERVED_SET = new Set(RESERVED_TYPES);
|
|
98
|
+
/** isRequestType 报告这个 type 是不是上行请求帧。 */
|
|
99
|
+
export function isRequestType(type) {
|
|
100
|
+
return REQUEST_SET.has(type);
|
|
101
|
+
}
|
|
102
|
+
/** isReservedType 报告这个 type 是不是已占名但未实现的会议层帧。 */
|
|
103
|
+
export function isReservedType(type) {
|
|
104
|
+
return RESERVED_SET.has(type);
|
|
105
|
+
}
|
|
106
|
+
const REGISTRY = {
|
|
107
|
+
[FrameType.hello]: sys.HELLO_FIELDS,
|
|
108
|
+
[FrameType.helloOk]: sys.HELLO_OK_FIELDS,
|
|
109
|
+
[FrameType.ping]: sys.EMPTY_FIELDS,
|
|
110
|
+
[FrameType.pong]: sys.EMPTY_FIELDS,
|
|
111
|
+
[FrameType.error]: sys.ERROR_FIELDS,
|
|
112
|
+
[FrameType.roomJoin]: room.JOIN_FIELDS,
|
|
113
|
+
[FrameType.roomLeave]: room.LEAVE_FIELDS,
|
|
114
|
+
[FrameType.roomPublish]: room.PUBLISH_FIELDS,
|
|
115
|
+
[FrameType.roomUnpublish]: room.TRACK_ID_FIELDS,
|
|
116
|
+
[FrameType.roomMute]: room.MUTE_FIELDS,
|
|
117
|
+
[FrameType.roomSubscribe]: room.LAYER_FIELDS,
|
|
118
|
+
[FrameType.roomUnsubscribe]: room.TRACK_ID_FIELDS,
|
|
119
|
+
[FrameType.roomUpdateLayer]: room.LAYER_FIELDS,
|
|
120
|
+
[FrameType.roomOffer]: room.SDP_FIELDS,
|
|
121
|
+
[FrameType.roomAnswer]: room.SDP_FIELDS,
|
|
122
|
+
[FrameType.roomIceCandidate]: room.ICE_FIELDS,
|
|
123
|
+
[FrameType.roomParticipantJoined]: room.PARTICIPANT_JOINED_FIELDS,
|
|
124
|
+
[FrameType.roomParticipantLeft]: room.PARTICIPANT_LEFT_FIELDS,
|
|
125
|
+
[FrameType.roomTrackPublished]: room.TRACK_PUBLISHED_FIELDS,
|
|
126
|
+
[FrameType.roomTrackUnpublished]: room.TRACK_UNPUBLISHED_FIELDS,
|
|
127
|
+
[FrameType.roomTrackMuted]: room.TRACK_MUTED_FIELDS,
|
|
128
|
+
[FrameType.roomActiveSpeakers]: room.ACTIVE_SPEAKERS_FIELDS,
|
|
129
|
+
[FrameType.roomQuality]: room.QUALITY_FIELDS,
|
|
130
|
+
[FrameType.roomClosed]: room.ROOM_CLOSED_FIELDS,
|
|
131
|
+
[FrameType.callInvite]: call.INVITE_FIELDS,
|
|
132
|
+
[FrameType.callAccept]: call.CALL_ID_FIELDS,
|
|
133
|
+
[FrameType.callReject]: call.CALL_ID_FIELDS,
|
|
134
|
+
[FrameType.callCancel]: call.CALL_ID_FIELDS,
|
|
135
|
+
[FrameType.callHangup]: call.CALL_ID_FIELDS,
|
|
136
|
+
[FrameType.callInviteMore]: call.INVITE_MORE_FIELDS,
|
|
137
|
+
[FrameType.callJoin]: call.CALL_ID_FIELDS,
|
|
138
|
+
[FrameType.callIncoming]: call.INCOMING_FIELDS,
|
|
139
|
+
[FrameType.callRinging]: call.RINGING_FIELDS,
|
|
140
|
+
[FrameType.callAccepted]: call.MEMBER_OUTCOME_FIELDS,
|
|
141
|
+
[FrameType.callRejected]: call.MEMBER_OUTCOME_FIELDS,
|
|
142
|
+
[FrameType.callBusy]: call.MEMBER_OUTCOME_FIELDS,
|
|
143
|
+
[FrameType.callNoAnswer]: call.MEMBER_OUTCOME_FIELDS,
|
|
144
|
+
[FrameType.callCancelled]: call.CANCELLED_FIELDS,
|
|
145
|
+
[FrameType.callConnected]: call.CONNECTED_FIELDS,
|
|
146
|
+
[FrameType.callHandledElsewhere]: call.HANDLED_ELSEWHERE_FIELDS,
|
|
147
|
+
[FrameType.callEnded]: call.ENDED_FIELDS,
|
|
148
|
+
};
|
|
149
|
+
const OK_REGISTRY = {
|
|
150
|
+
[okType(FrameType.hello)]: sys.HELLO_OK_FIELDS,
|
|
151
|
+
[okType(FrameType.roomJoin)]: room.JOIN_OK_FIELDS,
|
|
152
|
+
[okType(FrameType.roomPublish)]: room.PUBLISH_OK_FIELDS,
|
|
153
|
+
[okType(FrameType.callInvite)]: call.INVITE_OK_FIELDS,
|
|
154
|
+
// room.offer 没有 .ok —— pub 侧的 offer 由 room.answer 直接作为应答回来(§3.3)。
|
|
155
|
+
[okType(FrameType.roomAnswer)]: sys.EMPTY_FIELDS,
|
|
156
|
+
[okType(FrameType.roomIceCandidate)]: sys.EMPTY_FIELDS,
|
|
157
|
+
[okType(FrameType.callAccept)]: sys.EMPTY_FIELDS,
|
|
158
|
+
[okType(FrameType.callJoin)]: sys.EMPTY_FIELDS,
|
|
159
|
+
[okType(FrameType.callInviteMore)]: sys.EMPTY_FIELDS,
|
|
160
|
+
};
|
|
161
|
+
/**
|
|
162
|
+
* lookupFrame 返回某帧类型的字段声明。
|
|
163
|
+
*
|
|
164
|
+
* 请求帧的 .ok 如果没单独登记,一律给空对象——纯 ack 是常态,
|
|
165
|
+
* 不必为每个 room.mute.ok 写一份声明。
|
|
166
|
+
*/
|
|
167
|
+
export function lookupFrame(type) {
|
|
168
|
+
const direct = REGISTRY[type] ?? OK_REGISTRY[type];
|
|
169
|
+
if (direct !== undefined)
|
|
170
|
+
return direct;
|
|
171
|
+
if (type.endsWith(OK_SUFFIX)) {
|
|
172
|
+
const base = type.slice(0, -OK_SUFFIX.length);
|
|
173
|
+
if (isRequestType(base))
|
|
174
|
+
return sys.EMPTY_FIELDS;
|
|
175
|
+
}
|
|
176
|
+
return undefined;
|
|
177
|
+
}
|
|
178
|
+
/** knownFrameTypes 列出全部已注册的帧类型(不含自动派生的 .ok),供测试核对。 */
|
|
179
|
+
export function knownFrameTypes() {
|
|
180
|
+
return [...Object.keys(REGISTRY), ...Object.keys(OK_REGISTRY)];
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* decodeFrame 按 Envelope.type 解出帧数据。
|
|
184
|
+
*
|
|
185
|
+
* 未注册的 type 抛 unknown_type——但**客户端收到未知 type 时应当静默忽略**
|
|
186
|
+
* (§2.3 前向兼容,服务端可能比客户端新),别把这个错误抛给宿主。
|
|
187
|
+
*/
|
|
188
|
+
export function decodeFrame(envelope) {
|
|
189
|
+
const fields = lookupFrame(envelope.type);
|
|
190
|
+
if (fields === undefined) {
|
|
191
|
+
throw new RtcError(ErrorCode.unknownType, {
|
|
192
|
+
forType: envelope.type,
|
|
193
|
+
cause: new Error(`未注册的帧 "${envelope.type}"`),
|
|
194
|
+
});
|
|
195
|
+
}
|
|
196
|
+
return decodeFields(fields, envelope.data);
|
|
197
|
+
}
|
|
198
|
+
/**
|
|
199
|
+
* newFrameData 返回某帧**已填好协议默认值**的数据对象。
|
|
200
|
+
*
|
|
201
|
+
* # 发送方必须用它
|
|
202
|
+
*
|
|
203
|
+
* 「可选字段用省略表达,接收方按默认值填」(§2.4 规则 2)只对**省略**成立。
|
|
204
|
+
* 而 JSON.stringify 会把显式的 false / 0 编码出去:直接写
|
|
205
|
+
* `{ room_id: 'r-1' }` 少了 auto_subscribe,写 `{ ..., auto_subscribe: false }`
|
|
206
|
+
* 又把默认的 true 覆盖成了 false。两种写法都会让人进了房收不到任何流。
|
|
207
|
+
*
|
|
208
|
+
* 三端同理(Go 的结构体零值、Swift 的 Codable)。**发送侧一律从这里开始改字段。**
|
|
209
|
+
*/
|
|
210
|
+
export function newFrameData(fields) {
|
|
211
|
+
return decodeFields(fields, {});
|
|
212
|
+
}
|
|
213
|
+
/** encodeFrame 把帧数据映射回线路上的 snake_case data。 */
|
|
214
|
+
export function encodeFrame(fields, value) {
|
|
215
|
+
return encodeFields(fields, value);
|
|
216
|
+
}
|
|
217
|
+
//# sourceMappingURL=registry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/signaling/registry.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/** 协议 §1.4 的恢复窗口:30 秒。**四端同一个值**,服务端的 `ResumeWindow` 也是它。 */
|
|
2
|
+
export declare const RESUME_WINDOW_SEC = 30;
|
|
3
|
+
/** 服务端判一条连接死掉要连续几个心跳周期收不到东西(§1.3)。 */
|
|
4
|
+
export declare const SERVER_DEATH_PINGS = 3;
|
|
5
|
+
/** 余量:跨过服务端窗口到期那一刻再收场,别跟它抢同一秒。 */
|
|
6
|
+
export declare const GIVE_UP_GRACE_SEC = 5;
|
|
7
|
+
export declare function giveUpDelayMs(pingIntervalSec: number): number;
|
|
8
|
+
/**
|
|
9
|
+
* 「服务端已经彻底放弃这条会话」的倒计时(协议 §1.4)。
|
|
10
|
+
*
|
|
11
|
+
* # 为什么需要它
|
|
12
|
+
*
|
|
13
|
+
* 客户端本地放弃的唯一入口原本是「重连上了但 `resumed=false`」——**它要求先连回来**。
|
|
14
|
+
* 网络一直不回来的话那一刻永远不会到,界面就永远停在「正在重连」,
|
|
15
|
+
* 而且**连挂断都点不动**(挂断只产出一帧发不出去的 `call.hangup`,
|
|
16
|
+
* 本地状态按 §4.2 铁律 1 一动不动)。真机 2026-09-08 的 iOS 端就是这一幕。
|
|
17
|
+
*
|
|
18
|
+
* # 从 Connection 里拆出来
|
|
19
|
+
*
|
|
20
|
+
* 和 `Reconnector` 同一个理由:体量红线(CONVENTIONS §2),
|
|
21
|
+
* 也让「什么时候该放弃」这条规则有独立的测试面。
|
|
22
|
+
*/
|
|
23
|
+
export declare class ResumeDeadline {
|
|
24
|
+
private readonly onUnrecoverable;
|
|
25
|
+
private timer;
|
|
26
|
+
private pingIntervalSec;
|
|
27
|
+
constructor(onUnrecoverable: () => void);
|
|
28
|
+
/**
|
|
29
|
+
* 握手成功:撤掉倒计时,并记下服务端给的心跳周期(上界要拿它推算)。
|
|
30
|
+
*
|
|
31
|
+
* **不管 `resumed` 是真是假都要撤** —— 服务端已经给出裁决,
|
|
32
|
+
* `resumed=false` 那条自有 `handleHelloOk` 去收场,不该再由倒计时补一刀。
|
|
33
|
+
*/
|
|
34
|
+
connected(pingIntervalSec: number): void;
|
|
35
|
+
/**
|
|
36
|
+
* 起倒计时。
|
|
37
|
+
*
|
|
38
|
+
* **只在第一次断开时起**:每一次重连失败都会走到调用点,每次都重排的话
|
|
39
|
+
* 截止时刻就一直往后挪、永远不会到——而那正是它要治的病。
|
|
40
|
+
* 起点是第一次断开的那一刻,与服务端算的是同一笔账。
|
|
41
|
+
*/
|
|
42
|
+
arm(): void;
|
|
43
|
+
/** 撤销。连上了、或宿主 logout 了都要调。幂等。 */
|
|
44
|
+
cancel(): void;
|
|
45
|
+
/** armed 供测试与诊断观察。 */
|
|
46
|
+
get armed(): boolean;
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=resumeDeadline.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resumeDeadline.d.ts","sourceRoot":"","sources":["../../src/signaling/resumeDeadline.ts"],"names":[],"mappings":"AAEA,6DAA6D;AAC7D,eAAO,MAAM,iBAAiB,KAAK,CAAC;AAEpC,sCAAsC;AACtC,eAAO,MAAM,kBAAkB,IAAI,CAAC;AAEpC,kCAAkC;AAClC,eAAO,MAAM,iBAAiB,IAAI,CAAC;AAkBnC,wBAAgB,aAAa,CAAC,eAAe,EAAE,MAAM,GAAG,MAAM,CAE7D;AAED;;;;;;;;;;;;;;GAcG;AACH,qBAAa,cAAc;IAIb,OAAO,CAAC,QAAQ,CAAC,eAAe;IAH5C,OAAO,CAAC,KAAK,CAA8C;IAC3D,OAAO,CAAC,eAAe,CAAM;gBAEA,eAAe,EAAE,MAAM,IAAI;IAExD;;;;;OAKG;IACH,SAAS,CAAC,eAAe,EAAE,MAAM,GAAG,IAAI;IAKxC;;;;;;OAMG;IACH,GAAG,IAAI,IAAI;IAWX,iCAAiC;IACjC,MAAM,IAAI,IAAI;IAOd,sBAAsB;IACtB,IAAI,KAAK,IAAI,OAAO,CAEnB;CACF"}
|