@anycon/protocol 0.1.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.
Files changed (49) hide show
  1. package/LICENSE +176 -0
  2. package/README.md +146 -0
  3. package/README.zh-CN.md +118 -0
  4. package/dist/constants.d.ts +151 -0
  5. package/dist/constants.d.ts.map +1 -0
  6. package/dist/constants.js +159 -0
  7. package/dist/constants.js.map +1 -0
  8. package/dist/crypto.d.ts +202 -0
  9. package/dist/crypto.d.ts.map +1 -0
  10. package/dist/crypto.js +218 -0
  11. package/dist/crypto.js.map +1 -0
  12. package/dist/envelope.d.ts +105 -0
  13. package/dist/envelope.d.ts.map +1 -0
  14. package/dist/envelope.js +390 -0
  15. package/dist/envelope.js.map +1 -0
  16. package/dist/errors.d.ts +5 -0
  17. package/dist/errors.d.ts.map +1 -0
  18. package/dist/errors.js +5 -0
  19. package/dist/errors.js.map +1 -0
  20. package/dist/generated.d.ts +2007 -0
  21. package/dist/generated.d.ts.map +1 -0
  22. package/dist/generated.js +4 -0
  23. package/dist/generated.js.map +1 -0
  24. package/dist/index.d.ts +17 -0
  25. package/dist/index.d.ts.map +1 -0
  26. package/dist/index.js +16 -0
  27. package/dist/index.js.map +1 -0
  28. package/dist/method-types.d.ts +293 -0
  29. package/dist/method-types.d.ts.map +1 -0
  30. package/dist/method-types.js +2 -0
  31. package/dist/method-types.js.map +1 -0
  32. package/dist/rpc.d.ts +70 -0
  33. package/dist/rpc.d.ts.map +1 -0
  34. package/dist/rpc.js +310 -0
  35. package/dist/rpc.js.map +1 -0
  36. package/package.json +62 -0
  37. package/src/constants.ts +173 -0
  38. package/src/crypto.ts +427 -0
  39. package/src/envelope.ts +469 -0
  40. package/src/errors.ts +4 -0
  41. package/src/generated.ts +2094 -0
  42. package/src/index.ts +18 -0
  43. package/src/method-types.ts +183 -0
  44. package/src/rpc.ts +377 -0
  45. package/wasm/THIRD-PARTY-LICENSES.txt +1957 -0
  46. package/wasm/anycon_crypto.d.ts +248 -0
  47. package/wasm/anycon_crypto.js +1250 -0
  48. package/wasm/anycon_crypto_bg.wasm +0 -0
  49. package/wasm/anycon_crypto_bg.wasm.d.ts +48 -0
@@ -0,0 +1,105 @@
1
+ import { ProtocolError } from './errors.js';
2
+ import type { Control, EnrollFrame, Kind } from './generated.js';
3
+ export type { Control, EnrollFrame, Kind };
4
+ /** 外层信封。 */
5
+ export interface Envelope {
6
+ /** 信封版本,见 `ENVELOPE_VERSION`。 */
7
+ v: number;
8
+ /** 发送设备。hub 校验它等于当前连接的设备 id。 */
9
+ from: string;
10
+ /** 目标设备。发给 hub 的 `control` 填空字符串。 */
11
+ to: string;
12
+ kind: Kind;
13
+ /** 发送方单调递增。 */
14
+ seq: number;
15
+ body: Uint8Array;
16
+ }
17
+ /** 全部信封种类,对应 envelope.rs 的 `Kind`。 */
18
+ export declare const ENVELOPE_KINDS: readonly Kind[];
19
+ export declare function isKind(value: unknown): value is Kind;
20
+ /** 构造信封,`v` 默认当前版本。 */
21
+ export declare function makeEnvelope(from: string, to: string, kind: Kind, seq: number, body: Uint8Array): Envelope;
22
+ export declare function encodeEnvelope(env: Envelope): Uint8Array;
23
+ export declare function decodeEnvelope(bytes: Uint8Array): Envelope;
24
+ type ControlType = Control['type'];
25
+ /** 全部控制消息的 `type`,对应 control.rs 的 `Control` 变体(snake_case)。 */
26
+ export declare const CONTROL_TYPES: readonly ControlType[];
27
+ export declare function encodeControl(ctrl: Control): Uint8Array;
28
+ /** 未知的 `type`(版本错位时 hub 可能发来新消息)。调用方应忽略这一帧,而不是断开。 */
29
+ export declare class UnknownControlError extends ProtocolError {
30
+ readonly controlType: string;
31
+ readonly name = "UnknownControlError";
32
+ constructor(controlType: string);
33
+ }
34
+ export declare function decodeControl(bytes: Uint8Array): Control;
35
+ /** 接入期间 `handshake` 信封的 body:msgpack,`type` 在最前,其余字段按 Rust 声明顺序。 */
36
+ export declare function encodeEnrollFrame(frame: EnrollFrame): Uint8Array;
37
+ /** 解 `encodeEnrollFrame` 的输出。不是 map、没有 `type` 或 `type` 未知都抛 `ProtocolError`。 */
38
+ export declare function decodeEnrollFrame(bytes: Uint8Array): EnrollFrame;
39
+ /** 构造 `kind = control` 的信封(发往 hub,`to` 为空串)。 */
40
+ export declare function controlEnvelope(from: string, seq: number, ctrl: Control): Envelope;
41
+ /** 解出 `kind = control` 信封里的控制消息。 */
42
+ export declare function controlBody(env: Envelope): Control;
43
+ /**
44
+ * `kind = data` 的 body 框架,和 `crates/protocol/src/envelope.rs` 的 `mod frame` 字节一致
45
+ * (`tests/vectors/frames.json` 由 `tools/gen-vectors` 用 Rust 生成,TS 侧逐字节比对)。
46
+ *
47
+ * body 第一个字节是 `flags`:
48
+ * - `0x00` WHOLE:后面是一整条 `Transport.encrypt` 的输出;
49
+ * - `0x01` FRAGMENT:`[u32 be msg_id][u16 be index][u16 be count]` + 密文切片。同一 `msg_id` 的分片按
50
+ * `index` 顺序、不与其他消息交错地发送;接收方收齐 `count` 片后拼接再解密;
51
+ * - `0x02` RESET:无载荷。发送方发现自己的传输层失步(解密失败 / 丢片)时发给对端,对端丢弃传输并重新握手。
52
+ *
53
+ * Noise 的 nonce 是顺序的,所以**任何一片丢失都意味着整条传输失步**:收到 `backpressure`(hub 指明了被拒的 seq)
54
+ * 时发送方必须原样重发同一片(不能重新加密);`dropped`(hub 每连接每秒至多回一条)是「发错东西」的信号
55
+ * (`too_large` = 没分片 / 分片后仍超限),不据此逐条重发;接收方解密失败时按 RESET 处理。
56
+ */
57
+ export declare const FRAME_WHOLE = 0;
58
+ export declare const FRAME_FRAGMENT = 1;
59
+ export declare const FRAME_RESET = 2;
60
+ /** 每个 `data` 信封里最多放多少密文字节(留出信封头和 hub 上限的余量)。 */
61
+ export declare const MAX_FRAGMENT: number;
62
+ /** 重组时单条消息密文总长上限,防内存耗尽。 */
63
+ export declare const MAX_MESSAGE: number;
64
+ /** 解出来的一帧。`data` 是 `body` 的视图(零拷贝);需要长期持有时由调用方拷贝(`Reassembler` 会拷)。 */
65
+ export type DataFrame = {
66
+ readonly kind: 'whole';
67
+ readonly data: Uint8Array;
68
+ } | {
69
+ readonly kind: 'fragment';
70
+ readonly msgId: number;
71
+ readonly index: number;
72
+ readonly count: number;
73
+ readonly data: Uint8Array;
74
+ } | {
75
+ readonly kind: 'reset';
76
+ };
77
+ /** 与 Rust `FrameError` 的变体一一对应(snake_case)。 */
78
+ export type FrameErrorCode = 'empty' | 'unknown_flags' | 'truncated' | 'out_of_order' | 'count_mismatch' | 'too_large';
79
+ export declare class FrameError extends ProtocolError {
80
+ readonly code: FrameErrorCode;
81
+ readonly name = "FrameError";
82
+ constructor(code: FrameErrorCode, message: string);
83
+ }
84
+ /** 把一条密文切成若干 body。短消息一个 `WHOLE`,长消息若干 `FRAGMENT`(每片 ≤ `MAX_FRAGMENT`)。 */
85
+ export declare function encodeFrames(ciphertext: Uint8Array, msgId: number): Uint8Array[];
86
+ /** `RESET` 帧的 body:请求对端丢弃传输并重新握手。 */
87
+ export declare function resetBody(): Uint8Array;
88
+ /** 解一个 `data` 信封的 body。格式不对抛 `FrameError`。 */
89
+ export declare function decodeFrame(body: Uint8Array): DataFrame;
90
+ /**
91
+ * 每个发送方(对端)一个。`push` 返回整条密文表示可以解密了,返回 `undefined` 表示还在等后续分片。
92
+ * 行为与 Rust `Reassembler` 一致:严格按序(`index` 必须等于期望的下一片),`index < count`,同一 `msg_id`
93
+ * 的 `count` 中途不能变;`count == 1` 的单片 FRAGMENT 也能收;一条收完后同一 `msg_id` 再来要从 0 开始。
94
+ * `WHOLE` / `RESET` 丢弃进行中的重组;分片报错时进行中的重组也被丢弃(`count == 0` 例外:头部非法,不动状态)。
95
+ * 报错后调用方应当按「传输失步」处理(丢传输、重新握手)。`index` / `count` 都是 u16,这里的比较不会溢出。
96
+ */
97
+ export declare class Reassembler {
98
+ #private;
99
+ push(frame: DataFrame): Uint8Array | undefined;
100
+ /** 丢弃进行中的重组(连接断开、传输重建时调用)。 */
101
+ clear(): void;
102
+ }
103
+ /** 便捷:直接喂 body。 */
104
+ export declare function pushBody(reassembler: Reassembler, body: Uint8Array): Uint8Array | undefined;
105
+ //# sourceMappingURL=envelope.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"envelope.d.ts","sourceRoot":"","sources":["../src/envelope.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,390 @@
1
+ /**
2
+ * 外层信封与控制消息的 msgpack 编解码。手写,和 `crates/protocol/src/{envelope,control}.rs`
3
+ * 的 `rmp_serde::to_vec_named` 输出字节一致:
4
+ *
5
+ * - 信封是字符串键的 map,键序 `v, from, to, kind, seq, body`;`body` 是 bin(`Uint8Array`),不是数组。
6
+ * - 控制消息是内部标签 `type` 的 map:`type` 在最前,其余字段按 Rust 声明顺序;
7
+ * `skip_serializing_if = Option::is_none` 的字段为 null / undefined 时整键省略。
8
+ *
9
+ * 字节级一致由 `tests/vectors/*.hex`(`tools/gen-vectors` 用 Rust 生成)守住。
10
+ */
11
+ import { decode, encode } from '@msgpack/msgpack';
12
+ import { ENVELOPE_VERSION } from './constants.js';
13
+ import { ProtocolError } from './errors.js';
14
+ /** 全部信封种类,对应 envelope.rs 的 `Kind`。 */
15
+ export const ENVELOPE_KINDS = ['handshake', 'data', 'notify', 'control'];
16
+ const KINDS = new Set(ENVELOPE_KINDS);
17
+ export function isKind(value) {
18
+ return typeof value === 'string' && KINDS.has(value);
19
+ }
20
+ /** 构造信封,`v` 默认当前版本。 */
21
+ export function makeEnvelope(from, to, kind, seq, body) {
22
+ return { v: ENVELOPE_VERSION, from, to, kind, seq, body };
23
+ }
24
+ export function encodeEnvelope(env) {
25
+ if (!Number.isSafeInteger(env.seq) || env.seq < 0) {
26
+ throw new ProtocolError(`envelope seq must be a non-negative safe integer, got ${env.seq}`);
27
+ }
28
+ if (!Number.isInteger(env.v) || env.v < 0 || env.v > 255) {
29
+ throw new ProtocolError(`envelope v must fit in u8, got ${env.v}`);
30
+ }
31
+ if (!(env.body instanceof Uint8Array)) {
32
+ throw new ProtocolError('envelope body must be a Uint8Array');
33
+ }
34
+ // 键序固定,和 Rust 结构体声明顺序一致。
35
+ return encode({
36
+ v: env.v,
37
+ from: env.from,
38
+ to: env.to,
39
+ kind: env.kind,
40
+ seq: env.seq,
41
+ body: env.body,
42
+ });
43
+ }
44
+ export function decodeEnvelope(bytes) {
45
+ let raw;
46
+ try {
47
+ raw = decode(bytes);
48
+ }
49
+ catch (cause) {
50
+ throw new ProtocolError('envelope is not valid msgpack', { cause });
51
+ }
52
+ if (typeof raw !== 'object' || raw === null || Array.isArray(raw)) {
53
+ throw new ProtocolError('envelope must be a msgpack map');
54
+ }
55
+ const m = raw;
56
+ const { v, from, to, kind, seq, body } = m;
57
+ if (typeof v !== 'number')
58
+ throw new ProtocolError('envelope.v must be a number');
59
+ if (typeof from !== 'string')
60
+ throw new ProtocolError('envelope.from must be a string');
61
+ if (typeof to !== 'string')
62
+ throw new ProtocolError('envelope.to must be a string');
63
+ if (!isKind(kind))
64
+ throw new ProtocolError(`envelope.kind is unknown: ${String(kind)}`);
65
+ if (typeof seq !== 'number')
66
+ throw new ProtocolError('envelope.seq must be a number');
67
+ if (!(body instanceof Uint8Array))
68
+ throw new ProtocolError('envelope.body must be bin');
69
+ // body 是输入 buffer 的视图;拷一份,避免调用方复用 WebSocket 缓冲时被改写。
70
+ return { v, from, to, kind, seq, body: body.slice() };
71
+ }
72
+ /** 每个变体的字段声明顺序(不含 `type`),对应 control.rs。 */
73
+ const CONTROL_FIELD_ORDER = {
74
+ auth: ['device_token', 'protocol_version', 'client'],
75
+ auth_ok: ['device_id', 'server_time_ms', 'peers_online', 'quota'],
76
+ auth_fail: ['reason'],
77
+ pair_begin: ['match_id'],
78
+ pair_registered: ['expires_at_ms'],
79
+ pair_join: ['match_id'],
80
+ pair_matched: ['peer', 'role'],
81
+ pair_confirm: ['peer'],
82
+ pair_done: ['peer', 'device_id', 'device_token'],
83
+ pair_failed: ['reason'],
84
+ enroll_begin: ['node'],
85
+ enroll_started: ['enroll_id', 'node', 'expires_at_ms'],
86
+ enroll_request: ['enroll_id', 'peer', 'expires_at_ms'],
87
+ enroll_cancel: ['enroll_id'],
88
+ enroll_failed: ['enroll_id', 'reason'],
89
+ revoke: ['device'],
90
+ peer_online: ['device'],
91
+ peer_offline: ['device'],
92
+ undeliverable: ['to', 'seq'],
93
+ queue_overflow: ['to', 'dropped_seqs'],
94
+ queue_drop: ['seq'],
95
+ backpressure: ['to', 'seq'],
96
+ dropped: ['seq', 'reason'],
97
+ rate_limited: ['retry_after_ms'],
98
+ quota_update: ['quota'],
99
+ rotate_token: [],
100
+ token_rotated: ['device_token'],
101
+ };
102
+ /** Rust 侧 `#[serde(skip_serializing_if = "Option::is_none")]` 的字段:None 时整键省略,而不是编码为 nil。 */
103
+ const CONTROL_SKIP_NONE = {
104
+ auth: new Set(['device_token']),
105
+ auth_ok: new Set(['quota']),
106
+ pair_done: new Set(['device_id', 'device_token']),
107
+ enroll_failed: new Set(['enroll_id']),
108
+ };
109
+ /** 全部控制消息的 `type`,对应 control.rs 的 `Control` 变体(snake_case)。 */
110
+ export const CONTROL_TYPES = Object.keys(CONTROL_FIELD_ORDER);
111
+ const CLIENT_INFO_ORDER = ['name', 'kind', 'platform', 'version', 'origin'];
112
+ const CLIENT_INFO_SKIP_NONE = new Set(['origin']);
113
+ const QUOTA_ORDER = [
114
+ 'devices',
115
+ 'devices_max',
116
+ 'daemons',
117
+ 'daemons_max',
118
+ 'connections',
119
+ 'connections_max',
120
+ ];
121
+ function isDict(v) {
122
+ return typeof v === 'object' && v !== null && !Array.isArray(v) && !(v instanceof Uint8Array);
123
+ }
124
+ /** 按 `order` 重排键;`skipNone` 里的键为 null / undefined 时省略;未知键保持原序追加在后(前向兼容)。 */
125
+ function orderKeys(src, order, skipNone, head) {
126
+ const out = head ? { ...head } : {};
127
+ for (const key of order) {
128
+ const value = src[key];
129
+ if (value === undefined)
130
+ continue;
131
+ if (value === null && skipNone?.has(key))
132
+ continue;
133
+ out[key] = value;
134
+ }
135
+ const known = new Set(order);
136
+ for (const key of Object.keys(src)) {
137
+ if (key === 'type' || known.has(key) || src[key] === undefined)
138
+ continue;
139
+ out[key] = src[key];
140
+ }
141
+ return out;
142
+ }
143
+ function canonicalControl(ctrl) {
144
+ const order = CONTROL_FIELD_ORDER[ctrl.type];
145
+ if (!order)
146
+ throw new ProtocolError(`unknown control type: ${String(ctrl.type)}`);
147
+ const src = { ...ctrl };
148
+ if (isDict(src.client)) {
149
+ src.client = orderKeys(src.client, CLIENT_INFO_ORDER, CLIENT_INFO_SKIP_NONE);
150
+ }
151
+ if (isDict(src.quota)) {
152
+ src.quota = orderKeys(src.quota, QUOTA_ORDER, undefined);
153
+ }
154
+ return orderKeys(src, order, CONTROL_SKIP_NONE[ctrl.type], { type: ctrl.type });
155
+ }
156
+ export function encodeControl(ctrl) {
157
+ return encode(canonicalControl(ctrl), { ignoreUndefined: true });
158
+ }
159
+ /** 未知的 `type`(版本错位时 hub 可能发来新消息)。调用方应忽略这一帧,而不是断开。 */
160
+ export class UnknownControlError extends ProtocolError {
161
+ controlType;
162
+ name = 'UnknownControlError';
163
+ constructor(controlType) {
164
+ super(`unknown control type: ${controlType}`);
165
+ this.controlType = controlType;
166
+ }
167
+ }
168
+ export function decodeControl(bytes) {
169
+ let raw;
170
+ try {
171
+ raw = decode(bytes);
172
+ }
173
+ catch (cause) {
174
+ throw new ProtocolError('control is not valid msgpack', { cause });
175
+ }
176
+ if (!isDict(raw) || typeof raw.type !== 'string') {
177
+ throw new ProtocolError('control must be a map with a string `type`');
178
+ }
179
+ if (!Object.hasOwn(CONTROL_FIELD_ORDER, raw.type))
180
+ throw new UnknownControlError(raw.type);
181
+ return raw;
182
+ }
183
+ /** `EnrollFrame` 每个变体的字段声明顺序,对应 `crates/protocol/src/enroll.rs`。 */
184
+ const ENROLL_FRAME_FIELD_ORDER = {
185
+ hello: ['v', 'method', 'approval', 'nonce', 'hint'],
186
+ reply: ['status', 'nonce', 'reason', 'retry_after_ms', 'attempts_left', 'salt', 'cpace'],
187
+ cpace: ['share'],
188
+ noise: ['msg'],
189
+ };
190
+ const ENROLL_FRAME_SKIP_NONE = {
191
+ reply: new Set(['nonce', 'reason', 'retry_after_ms', 'attempts_left', 'salt', 'cpace']),
192
+ };
193
+ const ENROLL_HINT_ORDER = ['name', 'kind', 'platform'];
194
+ /** 接入期间 `handshake` 信封的 body:msgpack,`type` 在最前,其余字段按 Rust 声明顺序。 */
195
+ export function encodeEnrollFrame(frame) {
196
+ const order = ENROLL_FRAME_FIELD_ORDER[frame.type];
197
+ if (!order)
198
+ throw new ProtocolError(`unknown enroll frame type: ${String(frame.type)}`);
199
+ const src = { ...frame };
200
+ if (isDict(src.hint))
201
+ src.hint = orderKeys(src.hint, ENROLL_HINT_ORDER, undefined);
202
+ const out = orderKeys(src, order, ENROLL_FRAME_SKIP_NONE[frame.type], { type: frame.type });
203
+ return encode(out, { ignoreUndefined: true });
204
+ }
205
+ /** 解 `encodeEnrollFrame` 的输出。不是 map、没有 `type` 或 `type` 未知都抛 `ProtocolError`。 */
206
+ export function decodeEnrollFrame(bytes) {
207
+ let raw;
208
+ try {
209
+ raw = decode(bytes);
210
+ }
211
+ catch (cause) {
212
+ throw new ProtocolError('enroll frame is not valid msgpack', { cause });
213
+ }
214
+ if (!isDict(raw) || typeof raw.type !== 'string') {
215
+ throw new ProtocolError('enroll frame must be a map with a string `type`');
216
+ }
217
+ if (!Object.hasOwn(ENROLL_FRAME_FIELD_ORDER, raw.type)) {
218
+ throw new ProtocolError(`unknown enroll frame type: ${raw.type}`);
219
+ }
220
+ return raw;
221
+ }
222
+ /** 构造 `kind = control` 的信封(发往 hub,`to` 为空串)。 */
223
+ export function controlEnvelope(from, seq, ctrl) {
224
+ return makeEnvelope(from, '', 'control', seq, encodeControl(ctrl));
225
+ }
226
+ /** 解出 `kind = control` 信封里的控制消息。 */
227
+ export function controlBody(env) {
228
+ if (env.kind !== 'control')
229
+ throw new ProtocolError(`envelope kind is ${env.kind}, not control`);
230
+ return decodeControl(env.body);
231
+ }
232
+ // ---------- data 信封的 body 框架(ADR-30) ----------
233
+ /**
234
+ * `kind = data` 的 body 框架,和 `crates/protocol/src/envelope.rs` 的 `mod frame` 字节一致
235
+ * (`tests/vectors/frames.json` 由 `tools/gen-vectors` 用 Rust 生成,TS 侧逐字节比对)。
236
+ *
237
+ * body 第一个字节是 `flags`:
238
+ * - `0x00` WHOLE:后面是一整条 `Transport.encrypt` 的输出;
239
+ * - `0x01` FRAGMENT:`[u32 be msg_id][u16 be index][u16 be count]` + 密文切片。同一 `msg_id` 的分片按
240
+ * `index` 顺序、不与其他消息交错地发送;接收方收齐 `count` 片后拼接再解密;
241
+ * - `0x02` RESET:无载荷。发送方发现自己的传输层失步(解密失败 / 丢片)时发给对端,对端丢弃传输并重新握手。
242
+ *
243
+ * Noise 的 nonce 是顺序的,所以**任何一片丢失都意味着整条传输失步**:收到 `backpressure`(hub 指明了被拒的 seq)
244
+ * 时发送方必须原样重发同一片(不能重新加密);`dropped`(hub 每连接每秒至多回一条)是「发错东西」的信号
245
+ * (`too_large` = 没分片 / 分片后仍超限),不据此逐条重发;接收方解密失败时按 RESET 处理。
246
+ */
247
+ export const FRAME_WHOLE = 0x00;
248
+ export const FRAME_FRAGMENT = 0x01;
249
+ export const FRAME_RESET = 0x02;
250
+ /** 每个 `data` 信封里最多放多少密文字节(留出信封头和 hub 上限的余量)。 */
251
+ export const MAX_FRAGMENT = 200 * 1024;
252
+ /** 重组时单条消息密文总长上限,防内存耗尽。 */
253
+ export const MAX_MESSAGE = 16 * 1024 * 1024;
254
+ /** FRAGMENT 头长度:flags(1) + msg_id(4) + index(2) + count(2)。 */
255
+ const FRAGMENT_HEADER = 1 + 4 + 2 + 2;
256
+ export class FrameError extends ProtocolError {
257
+ code;
258
+ name = 'FrameError';
259
+ constructor(code, message) {
260
+ super(message);
261
+ this.code = code;
262
+ }
263
+ }
264
+ /** 把一条密文切成若干 body。短消息一个 `WHOLE`,长消息若干 `FRAGMENT`(每片 ≤ `MAX_FRAGMENT`)。 */
265
+ export function encodeFrames(ciphertext, msgId) {
266
+ if (!Number.isInteger(msgId) || msgId < 0 || msgId > 0xffff_ffff) {
267
+ throw new ProtocolError(`frame msg_id must fit in u32, got ${msgId}`);
268
+ }
269
+ if (ciphertext.length <= MAX_FRAGMENT) {
270
+ const body = new Uint8Array(1 + ciphertext.length);
271
+ body[0] = FRAME_WHOLE;
272
+ body.set(ciphertext, 1);
273
+ return [body];
274
+ }
275
+ const count = Math.ceil(ciphertext.length / MAX_FRAGMENT);
276
+ if (count > 0xffff)
277
+ throw new ProtocolError(`message needs ${count} fragments, more than u16`);
278
+ const bodies = [];
279
+ for (let index = 0; index < count; index++) {
280
+ const slice = ciphertext.subarray(index * MAX_FRAGMENT, (index + 1) * MAX_FRAGMENT);
281
+ const body = new Uint8Array(FRAGMENT_HEADER + slice.length);
282
+ const view = new DataView(body.buffer);
283
+ body[0] = FRAME_FRAGMENT;
284
+ view.setUint32(1, msgId, false);
285
+ view.setUint16(5, index, false);
286
+ view.setUint16(7, count, false);
287
+ body.set(slice, FRAGMENT_HEADER);
288
+ bodies.push(body);
289
+ }
290
+ return bodies;
291
+ }
292
+ /** `RESET` 帧的 body:请求对端丢弃传输并重新握手。 */
293
+ export function resetBody() {
294
+ return Uint8Array.of(FRAME_RESET);
295
+ }
296
+ /** 解一个 `data` 信封的 body。格式不对抛 `FrameError`。 */
297
+ export function decodeFrame(body) {
298
+ if (body.length === 0)
299
+ throw new FrameError('empty', 'empty body');
300
+ const flags = body[0];
301
+ switch (flags) {
302
+ case FRAME_WHOLE:
303
+ return { kind: 'whole', data: body.subarray(1) };
304
+ case FRAME_RESET:
305
+ return { kind: 'reset' };
306
+ case FRAME_FRAGMENT: {
307
+ if (body.length < FRAGMENT_HEADER) {
308
+ throw new FrameError('truncated', 'truncated fragment header');
309
+ }
310
+ const view = new DataView(body.buffer, body.byteOffset, body.byteLength);
311
+ return {
312
+ kind: 'fragment',
313
+ msgId: view.getUint32(1, false),
314
+ index: view.getUint16(5, false),
315
+ count: view.getUint16(7, false),
316
+ data: body.subarray(FRAGMENT_HEADER),
317
+ };
318
+ }
319
+ default:
320
+ throw new FrameError('unknown_flags', `unknown flags ${flags}`);
321
+ }
322
+ }
323
+ /**
324
+ * 每个发送方(对端)一个。`push` 返回整条密文表示可以解密了,返回 `undefined` 表示还在等后续分片。
325
+ * 行为与 Rust `Reassembler` 一致:严格按序(`index` 必须等于期望的下一片),`index < count`,同一 `msg_id`
326
+ * 的 `count` 中途不能变;`count == 1` 的单片 FRAGMENT 也能收;一条收完后同一 `msg_id` 再来要从 0 开始。
327
+ * `WHOLE` / `RESET` 丢弃进行中的重组;分片报错时进行中的重组也被丢弃(`count == 0` 例外:头部非法,不动状态)。
328
+ * 报错后调用方应当按「传输失步」处理(丢传输、重新握手)。`index` / `count` 都是 u16,这里的比较不会溢出。
329
+ */
330
+ export class Reassembler {
331
+ #current;
332
+ push(frame) {
333
+ switch (frame.kind) {
334
+ case 'whole':
335
+ this.#current = undefined;
336
+ return frame.data.slice();
337
+ case 'reset':
338
+ this.#current = undefined;
339
+ return undefined;
340
+ case 'fragment': {
341
+ const { msgId, index, count, data } = frame;
342
+ if (count === 0)
343
+ throw new FrameError('count_mismatch', 'fragment count mismatch');
344
+ if (index >= count) {
345
+ this.#current = undefined;
346
+ throw new FrameError('out_of_order', `fragment index ${index} is not below its count ${count}`);
347
+ }
348
+ let cur = this.#current;
349
+ this.#current = undefined;
350
+ if (cur && cur.msgId === msgId) {
351
+ if (cur.count !== count) {
352
+ throw new FrameError('count_mismatch', `fragment count changed mid-message: ${cur.count} -> ${count}`);
353
+ }
354
+ }
355
+ else {
356
+ cur = { msgId, count, next: 0, chunks: [], length: 0 };
357
+ }
358
+ if (index !== cur.next) {
359
+ throw new FrameError('out_of_order', `fragment out of order: expected ${cur.next}, got ${index}`);
360
+ }
361
+ if (cur.length + data.length > MAX_MESSAGE) {
362
+ throw new FrameError('too_large', 'message too large');
363
+ }
364
+ cur.chunks.push(data.slice());
365
+ cur.length += data.length;
366
+ if (index + 1 === count) {
367
+ const out = new Uint8Array(cur.length);
368
+ let at = 0;
369
+ for (const chunk of cur.chunks) {
370
+ out.set(chunk, at);
371
+ at += chunk.length;
372
+ }
373
+ return out;
374
+ }
375
+ cur.next = index + 1;
376
+ this.#current = cur;
377
+ return undefined;
378
+ }
379
+ }
380
+ }
381
+ /** 丢弃进行中的重组(连接断开、传输重建时调用)。 */
382
+ clear() {
383
+ this.#current = undefined;
384
+ }
385
+ }
386
+ /** 便捷:直接喂 body。 */
387
+ export function pushBody(reassembler, body) {
388
+ return reassembler.push(decodeFrame(body));
389
+ }
390
+ //# sourceMappingURL=envelope.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"envelope.js","sourceRoot":"","sources":["../src/envelope.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ /** 编解码层错误。收到的字节不合法时抛出,调用方通常记日志后丢弃该帧。 */
2
+ export declare class ProtocolError extends Error {
3
+ readonly name: string;
4
+ }
5
+ //# sourceMappingURL=errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,wCAAwC;AACxC,qBAAa,aAAc,SAAQ,KAAK;IACtC,SAAkB,IAAI,EAAE,MAAM,CAAkB;CACjD"}
package/dist/errors.js ADDED
@@ -0,0 +1,5 @@
1
+ /** 编解码层错误。收到的字节不合法时抛出,调用方通常记日志后丢弃该帧。 */
2
+ export class ProtocolError extends Error {
3
+ name = 'ProtocolError';
4
+ }
5
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,wCAAwC;AACxC,MAAM,OAAO,aAAc,SAAQ,KAAK;IACpB,IAAI,GAAW,eAAe,CAAA;CACjD"}