@moqtap/codec 0.10.0 → 0.11.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/CHANGELOG.md +147 -0
- package/dist/auth-redaction-DsdLq4Qs.d.cts +102 -0
- package/dist/auth-redaction-DsdLq4Qs.d.ts +102 -0
- package/dist/{chunk-RYKQXBG6.cjs → chunk-27K5BUAG.cjs} +481 -517
- package/dist/{chunk-WCPENYNE.js → chunk-3RNQMGKA.js} +359 -390
- package/dist/{chunk-TSUZ6GJV.js → chunk-5AWIXOLB.js} +438 -469
- package/dist/{chunk-4XLYCT5Q.cjs → chunk-5IMHJIAZ.cjs} +52 -2
- package/dist/{chunk-KTNERCTZ.cjs → chunk-5JGZCKJO.cjs} +488 -518
- package/dist/{chunk-WCTMPDUX.cjs → chunk-73K4OSAN.cjs} +401 -432
- package/dist/{chunk-N2V7Z37J.js → chunk-7VQKRGRD.js} +19 -3
- package/dist/{chunk-BIBMDTU5.cjs → chunk-A3UCQOIB.cjs} +486 -517
- package/dist/{chunk-K2B3OVFK.js → chunk-A7PDMVXM.js} +24 -3
- package/dist/{chunk-VZHL2U2N.cjs → chunk-A7VQO6YC.cjs} +54 -38
- package/dist/{chunk-AQ445VV7.cjs → chunk-ACQHZLRZ.cjs} +66 -46
- package/dist/{chunk-L5DRACXS.js → chunk-BBICOMW6.js} +25 -3
- package/dist/{chunk-T4VWPKDG.cjs → chunk-BNIUVOCJ.cjs} +529 -599
- package/dist/{chunk-UKKDOOUO.cjs → chunk-CNC6ANS4.cjs} +58 -37
- package/dist/{chunk-OZRK73NQ.js → chunk-FDLQSWHK.js} +433 -469
- package/dist/{chunk-IJAF6PAY.js → chunk-FFNOE4UR.js} +19 -3
- package/dist/{chunk-CZNW3R5E.cjs → chunk-GMENT63T.cjs} +54 -38
- package/dist/{chunk-XCRCAUGI.cjs → chunk-HM7BLRVP.cjs} +291 -297
- package/dist/{chunk-XHAP2YST.js → chunk-HZONHFNO.js} +19 -3
- package/dist/{chunk-SDJTSMOW.cjs → chunk-ILYABWDK.cjs} +60 -38
- package/dist/{chunk-IDV2JYJ6.cjs → chunk-KRSFTZVO.cjs} +56 -40
- package/dist/{chunk-RIIA4ALQ.cjs → chunk-KSPH6KMH.cjs} +54 -38
- package/dist/{chunk-OUNN4IQB.cjs → chunk-KTY4LAUV.cjs} +482 -497
- package/dist/{chunk-RZTLQAKF.js → chunk-OJNLJT5D.js} +0 -1
- package/dist/{chunk-FT3HDNIB.js → chunk-PJK2ZS3I.js} +467 -537
- package/dist/{chunk-G53WYUXL.js → chunk-PSMZKHOC.js} +441 -456
- package/dist/{chunk-7RE6KSIY.cjs → chunk-Q5JQGHWY.cjs} +0 -1
- package/dist/{chunk-BX2N7TZM.js → chunk-SQTUQY5E.js} +31 -11
- package/dist/{chunk-CF5DDD3Q.js → chunk-WCRLAKDW.js} +239 -245
- package/dist/{chunk-KYVTM5VI.js → chunk-WL2YUEXH.js} +19 -3
- package/dist/{chunk-KGDVC4O6.js → chunk-YCNIVZS7.js} +439 -469
- package/dist/{chunk-KLPWJU6W.js → chunk-YRZQVNZO.js} +50 -0
- package/dist/{codec-CFWu5KVT.d.cts → codec-76xzrLTL.d.cts} +21 -2
- package/dist/{codec-gl4_QEva.d.ts → codec-8p40WdLg.d.ts} +20 -1
- package/dist/{codec-Dl_QIXMz.d.ts → codec-BN2Bu0KI.d.ts} +20 -1
- package/dist/{codec-Bux_Q40X.d.ts → codec-Bb6GKTrv.d.ts} +21 -2
- package/dist/{codec-EvybrBuY.d.cts → codec-BgpfHoAd.d.cts} +20 -1
- package/dist/{codec-alVA27Uc.d.ts → codec-BkheTXO7.d.ts} +20 -1
- package/dist/{codec-Czejcmxr.d.cts → codec-BwVDkokh.d.cts} +21 -2
- package/dist/{codec-BrTi4K7r.d.cts → codec-C5s1eBJX.d.cts} +21 -2
- package/dist/codec-CM5yd6n3.d.ts +38 -0
- package/dist/{codec-CWnf8mn_.d.cts → codec-Cb8HC3XV.d.cts} +21 -2
- package/dist/codec-Clu_skx8.d.cts +38 -0
- package/dist/{codec-DzkdW4kO.d.cts → codec-CpOpemR8.d.cts} +20 -1
- package/dist/{codec-CXCjya_G.d.cts → codec-Cshdl9Tt.d.cts} +20 -1
- package/dist/{codec-f7vxeVIS.d.cts → codec-DELe00w_.d.cts} +21 -2
- package/dist/{codec-DNmiG2e0.d.cts → codec-DHzKAUCa.d.cts} +20 -1
- package/dist/{codec--CVeqGQv.d.ts → codec-DdVBtvx7.d.ts} +20 -1
- package/dist/{codec-CBdOIfMY.d.ts → codec-DlxGuYMv.d.ts} +21 -2
- package/dist/{codec-BNy5syCU.d.ts → codec-DxtgPxJS.d.ts} +20 -1
- package/dist/{codec-guzqtfMk.d.cts → codec-GAY4lybi.d.cts} +20 -1
- package/dist/{codec-Cfo_z5ET.d.cts → codec-I8u2pfS4.d.cts} +20 -1
- package/dist/{codec-BxQTybUX.d.cts → codec-XLrnreeu.d.cts} +21 -2
- package/dist/{codec-DOmAmFkI.d.ts → codec-c0YEwwWn.d.ts} +20 -1
- package/dist/{codec-DaXjRrOV.d.ts → codec-ejDu-va6.d.ts} +21 -2
- package/dist/{codec-C3mdsGx3.d.ts → codec-kaBUzdpV.d.ts} +21 -2
- package/dist/{codec-CwZ6OCPP.d.ts → codec-mVYqkIUF.d.ts} +21 -2
- package/dist/{codec-08ZOr5wI.d.ts → codec-qSbO5nOa.d.ts} +21 -2
- package/dist/{codec-Cm3D261p.d.ts → codec-yYKGOipj.d.ts} +20 -1
- package/dist/{codec-Bd60SGKH.d.cts → codec-zfzg9uiy.d.cts} +20 -1
- package/dist/draft07.cjs +48 -4
- package/dist/draft07.d.cts +42 -2
- package/dist/draft07.d.ts +42 -2
- package/dist/draft07.js +49 -5
- package/dist/draft08.cjs +76 -3
- package/dist/draft08.d.cts +70 -2
- package/dist/draft08.d.ts +70 -2
- package/dist/draft08.js +77 -4
- package/dist/draft09.cjs +76 -3
- package/dist/draft09.d.cts +70 -2
- package/dist/draft09.d.ts +70 -2
- package/dist/draft09.js +77 -4
- package/dist/draft10.cjs +76 -3
- package/dist/draft10.d.cts +70 -2
- package/dist/draft10.d.ts +70 -2
- package/dist/draft10.js +77 -4
- package/dist/draft11.cjs +104 -3
- package/dist/draft11.d.cts +98 -2
- package/dist/draft11.d.ts +98 -2
- package/dist/draft11.js +105 -4
- package/dist/draft12.cjs +113 -3
- package/dist/draft12.d.cts +107 -2
- package/dist/draft12.d.ts +107 -2
- package/dist/draft12.js +114 -4
- package/dist/draft13.cjs +105 -3
- package/dist/draft13.d.cts +99 -2
- package/dist/draft13.d.ts +99 -2
- package/dist/draft13.js +106 -4
- package/dist/draft14.cjs +107 -3
- package/dist/draft14.d.cts +101 -28
- package/dist/draft14.d.ts +101 -28
- package/dist/draft14.js +108 -4
- package/dist/draft15-session.d.cts +1 -1
- package/dist/draft15-session.d.ts +1 -1
- package/dist/draft15.cjs +69 -3
- package/dist/draft15.d.cts +65 -22
- package/dist/draft15.d.ts +65 -22
- package/dist/draft15.js +70 -4
- package/dist/draft16-session.cjs +2 -2
- package/dist/draft16-session.d.cts +1 -1
- package/dist/draft16-session.d.ts +1 -1
- package/dist/draft16-session.js +1 -1
- package/dist/draft16.cjs +76 -8
- package/dist/draft16.d.cts +67 -13
- package/dist/draft16.d.ts +67 -13
- package/dist/draft16.js +73 -5
- package/dist/draft17-session.d.cts +1 -1
- package/dist/draft17-session.d.ts +1 -1
- package/dist/draft17.cjs +77 -3
- package/dist/draft17.d.cts +73 -4
- package/dist/draft17.d.ts +73 -4
- package/dist/draft17.js +78 -4
- package/dist/draft18-session.d.cts +1 -1
- package/dist/draft18-session.d.ts +1 -1
- package/dist/draft18.cjs +8 -3
- package/dist/draft18.d.cts +4 -3
- package/dist/draft18.d.ts +4 -3
- package/dist/draft18.js +9 -4
- package/dist/draft19-session.d.cts +1 -1
- package/dist/draft19-session.d.ts +1 -1
- package/dist/draft19.cjs +11 -4
- package/dist/draft19.d.cts +4 -3
- package/dist/draft19.d.ts +4 -3
- package/dist/draft19.js +12 -5
- package/dist/draft20-session.d.cts +1 -1
- package/dist/draft20-session.d.ts +1 -1
- package/dist/draft20.cjs +8 -3
- package/dist/draft20.d.cts +4 -3
- package/dist/draft20.d.ts +4 -3
- package/dist/draft20.js +9 -4
- package/dist/index.cjs +30 -30
- package/dist/index.d.cts +21 -20
- package/dist/index.d.ts +21 -20
- package/dist/index.js +15 -15
- package/dist/session.cjs +2 -2
- package/dist/session.d.cts +6 -6
- package/dist/session.d.ts +6 -6
- package/dist/session.js +1 -1
- package/dist/{types-C1rxh-id.d.cts → types-Btp416jt.d.cts} +8 -0
- package/dist/{types-C1rxh-id.d.ts → types-Btp416jt.d.ts} +8 -0
- package/dist/{types-CZTzbIzQ.d.cts → types-BxTL1NXw.d.cts} +7 -0
- package/dist/{types-CZTzbIzQ.d.ts → types-BxTL1NXw.d.ts} +7 -0
- package/dist/{types-pShrs3fN.d.cts → types-CuibHYcf.d.cts} +7 -0
- package/dist/{types-pShrs3fN.d.ts → types-CuibHYcf.d.ts} +7 -0
- package/dist/{types-CY-QWxd-.d.cts → types-CwN7AEoL.d.cts} +13 -1
- package/dist/{types-CY-QWxd-.d.ts → types-CwN7AEoL.d.ts} +13 -1
- package/dist/{types-D4bmW8rY.d.cts → types-DAnalt5K.d.cts} +7 -0
- package/dist/{types-D4bmW8rY.d.ts → types-DAnalt5K.d.ts} +7 -0
- package/dist/{types-Bg86GGVZ.d.cts → types-DxXNP32l.d.cts} +8 -0
- package/dist/{types-Bg86GGVZ.d.ts → types-DxXNP32l.d.ts} +8 -0
- package/package.json +3 -3
- package/src/core/auth-redaction.ts +192 -0
- package/src/drafts/draft07/codec.ts +40 -0
- package/src/drafts/draft07/error-codes.ts +44 -0
- package/src/drafts/draft07/index.ts +15 -0
- package/src/drafts/draft08/codec.ts +40 -0
- package/src/drafts/draft08/error-codes.ts +76 -0
- package/src/drafts/draft08/index.ts +21 -0
- package/src/drafts/draft09/codec.ts +40 -0
- package/src/drafts/draft09/error-codes.ts +76 -0
- package/src/drafts/draft09/index.ts +21 -0
- package/src/drafts/draft10/codec.ts +40 -0
- package/src/drafts/draft10/error-codes.ts +76 -0
- package/src/drafts/draft10/index.ts +21 -0
- package/src/drafts/draft11/codec.ts +60 -0
- package/src/drafts/draft11/error-codes.ts +106 -0
- package/src/drafts/draft11/index.ts +23 -0
- package/src/drafts/draft12/codec.ts +61 -0
- package/src/drafts/draft12/error-codes.ts +116 -0
- package/src/drafts/draft12/index.ts +25 -0
- package/src/drafts/draft13/codec.ts +69 -11
- package/src/drafts/draft13/error-codes.ts +107 -0
- package/src/drafts/draft13/index.ts +23 -0
- package/src/drafts/draft13/types.ts +1 -1
- package/src/drafts/draft14/codec.ts +65 -4
- package/src/drafts/draft14/data-streams.ts +331 -259
- package/src/drafts/draft14/error-codes.ts +109 -0
- package/src/drafts/draft14/index.ts +23 -0
- package/src/drafts/draft15/codec.ts +65 -8
- package/src/drafts/draft15/data-streams.ts +489 -444
- package/src/drafts/draft15/error-codes.ts +66 -0
- package/src/drafts/draft15/index.ts +15 -0
- package/src/drafts/draft15/types.ts +7 -0
- package/src/drafts/draft16/codec.ts +146 -52
- package/src/drafts/draft16/data-streams.ts +513 -442
- package/src/drafts/draft16/error-codes.ts +68 -0
- package/src/drafts/draft16/index.ts +15 -0
- package/src/drafts/draft16/messages.ts +4 -4
- package/src/drafts/draft16/session-fsm.ts +0 -1
- package/src/drafts/draft16/types.ts +22 -8
- package/src/drafts/draft17/codec.ts +73 -12
- package/src/drafts/draft17/data-streams.ts +567 -488
- package/src/drafts/draft17/index.ts +15 -0
- package/src/drafts/draft17/types.ts +7 -0
- package/src/drafts/draft18/codec.ts +66 -9
- package/src/drafts/draft18/data-streams.ts +570 -482
- package/src/drafts/draft18/index.ts +3 -0
- package/src/drafts/draft18/types.ts +16 -8
- package/src/drafts/draft19/codec.ts +70 -10
- package/src/drafts/draft19/data-streams.ts +570 -482
- package/src/drafts/draft19/error-codes.ts +3 -1
- package/src/drafts/draft19/index.ts +3 -0
- package/src/drafts/draft19/messages.ts +3 -1
- package/src/drafts/draft19/types.ts +22 -11
- package/src/drafts/draft20/codec.ts +90 -23
- package/src/drafts/draft20/data-streams.ts +610 -563
- package/src/drafts/draft20/index.ts +3 -0
- package/src/drafts/draft20/types.ts +14 -2
- package/dist/codec-BJ7BHuiZ.d.ts +0 -18
- package/dist/codec-C6Mx4bwz.d.cts +0 -18
|
@@ -249,10 +249,17 @@ interface FetchStream {
|
|
|
249
249
|
type Draft16DataStream = SubgroupStream | DatagramObject | FetchStream;
|
|
250
250
|
interface SubgroupStreamHeader {
|
|
251
251
|
readonly type: 'subgroup_header';
|
|
252
|
+
/**
|
|
253
|
+
* The stream Type Flags, the same value `SubgroupStream.headerType` carries.
|
|
254
|
+
* Without it the incremental decoder drops every flag the header encodes
|
|
255
|
+
* and a consumer cannot tell the modes apart.
|
|
256
|
+
*/
|
|
257
|
+
readonly headerType: number;
|
|
252
258
|
readonly trackAlias: bigint;
|
|
253
259
|
readonly groupId: bigint;
|
|
254
260
|
readonly subgroupId: bigint;
|
|
255
261
|
readonly publisherPriority: number;
|
|
262
|
+
readonly endOfGroup?: boolean;
|
|
256
263
|
}
|
|
257
264
|
interface FetchStreamHeader {
|
|
258
265
|
readonly type: 'fetch_header';
|
|
@@ -234,10 +234,17 @@ interface FetchStream {
|
|
|
234
234
|
type Draft15DataStream = SubgroupStream | DatagramObject | FetchStream;
|
|
235
235
|
interface SubgroupStreamHeader {
|
|
236
236
|
readonly type: 'subgroup_header';
|
|
237
|
+
/**
|
|
238
|
+
* The stream Type Flags, the same value `SubgroupStream.headerType` carries.
|
|
239
|
+
* Without it the incremental decoder discarded every flag the header
|
|
240
|
+
* encodes and a consumer could not tell the modes apart.
|
|
241
|
+
*/
|
|
242
|
+
readonly headerType: number;
|
|
237
243
|
readonly trackAlias: bigint;
|
|
238
244
|
readonly groupId: bigint;
|
|
239
245
|
readonly subgroupId: bigint;
|
|
240
246
|
readonly publisherPriority: number;
|
|
247
|
+
readonly endOfGroup?: boolean;
|
|
241
248
|
}
|
|
242
249
|
interface FetchStreamHeader {
|
|
243
250
|
readonly type: 'fetch_header';
|
|
@@ -234,10 +234,17 @@ interface FetchStream {
|
|
|
234
234
|
type Draft15DataStream = SubgroupStream | DatagramObject | FetchStream;
|
|
235
235
|
interface SubgroupStreamHeader {
|
|
236
236
|
readonly type: 'subgroup_header';
|
|
237
|
+
/**
|
|
238
|
+
* The stream Type Flags, the same value `SubgroupStream.headerType` carries.
|
|
239
|
+
* Without it the incremental decoder discarded every flag the header
|
|
240
|
+
* encodes and a consumer could not tell the modes apart.
|
|
241
|
+
*/
|
|
242
|
+
readonly headerType: number;
|
|
237
243
|
readonly trackAlias: bigint;
|
|
238
244
|
readonly groupId: bigint;
|
|
239
245
|
readonly subgroupId: bigint;
|
|
240
246
|
readonly publisherPriority: number;
|
|
247
|
+
readonly endOfGroup?: boolean;
|
|
241
248
|
}
|
|
242
249
|
interface FetchStreamHeader {
|
|
243
250
|
readonly type: 'fetch_header';
|
|
@@ -20,7 +20,7 @@ interface Draft20SetupOptions {
|
|
|
20
20
|
unknown?: UnknownParam[];
|
|
21
21
|
}
|
|
22
22
|
/**
|
|
23
|
-
* LOCATION_FILTER (0x21) —
|
|
23
|
+
* LOCATION_FILTER (0x21) — draft-20 Section 5.1.2.
|
|
24
24
|
*
|
|
25
25
|
* The draft-19 `Filter Type` discriminator (0x1 Next Group Start / 0x2 Largest
|
|
26
26
|
* Object / 0x3 AbsoluteStart / 0x4 AbsoluteRange) is gone; the shape is the
|
|
@@ -344,10 +344,22 @@ interface FetchStream {
|
|
|
344
344
|
type Draft20DataStream = SubgroupStream | DatagramObject | FetchStream;
|
|
345
345
|
interface SubgroupStreamHeader {
|
|
346
346
|
readonly type: 'subgroup_header';
|
|
347
|
+
/**
|
|
348
|
+
* SUBGROUP_HEADER `Type Flags`, the same value `SubgroupStream.headerType`
|
|
349
|
+
* carries. It is reported so the incremental decoder does not drop the flags
|
|
350
|
+
* the header encodes, which is what lets a consumer tell the modes apart.
|
|
351
|
+
*/
|
|
352
|
+
readonly headerType: number;
|
|
347
353
|
readonly trackAlias: bigint;
|
|
348
354
|
readonly groupId: bigint;
|
|
355
|
+
/**
|
|
356
|
+
* Under Subgroup Mode 0b01 this is the first Object's ID, which is why the
|
|
357
|
+
* header is not emitted until that Object has been read.
|
|
358
|
+
*/
|
|
349
359
|
readonly subgroupId: bigint;
|
|
350
360
|
readonly publisherPriority: number;
|
|
361
|
+
readonly endOfGroup?: boolean;
|
|
362
|
+
readonly firstObject?: boolean;
|
|
351
363
|
}
|
|
352
364
|
interface FetchStreamHeader {
|
|
353
365
|
readonly type: 'fetch_header';
|
|
@@ -20,7 +20,7 @@ interface Draft20SetupOptions {
|
|
|
20
20
|
unknown?: UnknownParam[];
|
|
21
21
|
}
|
|
22
22
|
/**
|
|
23
|
-
* LOCATION_FILTER (0x21) —
|
|
23
|
+
* LOCATION_FILTER (0x21) — draft-20 Section 5.1.2.
|
|
24
24
|
*
|
|
25
25
|
* The draft-19 `Filter Type` discriminator (0x1 Next Group Start / 0x2 Largest
|
|
26
26
|
* Object / 0x3 AbsoluteStart / 0x4 AbsoluteRange) is gone; the shape is the
|
|
@@ -344,10 +344,22 @@ interface FetchStream {
|
|
|
344
344
|
type Draft20DataStream = SubgroupStream | DatagramObject | FetchStream;
|
|
345
345
|
interface SubgroupStreamHeader {
|
|
346
346
|
readonly type: 'subgroup_header';
|
|
347
|
+
/**
|
|
348
|
+
* SUBGROUP_HEADER `Type Flags`, the same value `SubgroupStream.headerType`
|
|
349
|
+
* carries. It is reported so the incremental decoder does not drop the flags
|
|
350
|
+
* the header encodes, which is what lets a consumer tell the modes apart.
|
|
351
|
+
*/
|
|
352
|
+
readonly headerType: number;
|
|
347
353
|
readonly trackAlias: bigint;
|
|
348
354
|
readonly groupId: bigint;
|
|
355
|
+
/**
|
|
356
|
+
* Under Subgroup Mode 0b01 this is the first Object's ID, which is why the
|
|
357
|
+
* header is not emitted until that Object has been read.
|
|
358
|
+
*/
|
|
349
359
|
readonly subgroupId: bigint;
|
|
350
360
|
readonly publisherPriority: number;
|
|
361
|
+
readonly endOfGroup?: boolean;
|
|
362
|
+
readonly firstObject?: boolean;
|
|
351
363
|
}
|
|
352
364
|
interface FetchStreamHeader {
|
|
353
365
|
readonly type: 'fetch_header';
|
|
@@ -227,10 +227,17 @@ interface FetchStream {
|
|
|
227
227
|
type Draft17DataStream = SubgroupStream | DatagramObject | FetchStream;
|
|
228
228
|
interface SubgroupStreamHeader {
|
|
229
229
|
readonly type: 'subgroup_header';
|
|
230
|
+
/**
|
|
231
|
+
* The stream Type Flags, the same value `SubgroupStream.headerType` carries.
|
|
232
|
+
* Without it the incremental decoder discarded every flag the header
|
|
233
|
+
* encodes and a consumer could not tell the modes apart.
|
|
234
|
+
*/
|
|
235
|
+
readonly headerType: number;
|
|
230
236
|
readonly trackAlias: bigint;
|
|
231
237
|
readonly groupId: bigint;
|
|
232
238
|
readonly subgroupId: bigint;
|
|
233
239
|
readonly publisherPriority: number;
|
|
240
|
+
readonly endOfGroup?: boolean;
|
|
234
241
|
}
|
|
235
242
|
interface FetchStreamHeader {
|
|
236
243
|
readonly type: 'fetch_header';
|
|
@@ -227,10 +227,17 @@ interface FetchStream {
|
|
|
227
227
|
type Draft17DataStream = SubgroupStream | DatagramObject | FetchStream;
|
|
228
228
|
interface SubgroupStreamHeader {
|
|
229
229
|
readonly type: 'subgroup_header';
|
|
230
|
+
/**
|
|
231
|
+
* The stream Type Flags, the same value `SubgroupStream.headerType` carries.
|
|
232
|
+
* Without it the incremental decoder discarded every flag the header
|
|
233
|
+
* encodes and a consumer could not tell the modes apart.
|
|
234
|
+
*/
|
|
235
|
+
readonly headerType: number;
|
|
230
236
|
readonly trackAlias: bigint;
|
|
231
237
|
readonly groupId: bigint;
|
|
232
238
|
readonly subgroupId: bigint;
|
|
233
239
|
readonly publisherPriority: number;
|
|
240
|
+
readonly endOfGroup?: boolean;
|
|
234
241
|
}
|
|
235
242
|
interface FetchStreamHeader {
|
|
236
243
|
readonly type: 'fetch_header';
|
|
@@ -234,10 +234,18 @@ interface FetchStream {
|
|
|
234
234
|
type Draft18DataStream = SubgroupStream | DatagramObject | FetchStream;
|
|
235
235
|
interface SubgroupStreamHeader {
|
|
236
236
|
readonly type: 'subgroup_header';
|
|
237
|
+
/**
|
|
238
|
+
* The stream Type Flags, the same value `SubgroupStream.headerType` carries.
|
|
239
|
+
* It is reported so the incremental decoder does not drop the flags the
|
|
240
|
+
* header encodes, which is what lets a consumer tell the modes apart.
|
|
241
|
+
*/
|
|
242
|
+
readonly headerType: number;
|
|
237
243
|
readonly trackAlias: bigint;
|
|
238
244
|
readonly groupId: bigint;
|
|
239
245
|
readonly subgroupId: bigint;
|
|
240
246
|
readonly publisherPriority: number;
|
|
247
|
+
readonly endOfGroup?: boolean;
|
|
248
|
+
readonly firstObject?: boolean;
|
|
241
249
|
}
|
|
242
250
|
interface FetchStreamHeader {
|
|
243
251
|
readonly type: 'fetch_header';
|
|
@@ -234,10 +234,18 @@ interface FetchStream {
|
|
|
234
234
|
type Draft18DataStream = SubgroupStream | DatagramObject | FetchStream;
|
|
235
235
|
interface SubgroupStreamHeader {
|
|
236
236
|
readonly type: 'subgroup_header';
|
|
237
|
+
/**
|
|
238
|
+
* The stream Type Flags, the same value `SubgroupStream.headerType` carries.
|
|
239
|
+
* It is reported so the incremental decoder does not drop the flags the
|
|
240
|
+
* header encodes, which is what lets a consumer tell the modes apart.
|
|
241
|
+
*/
|
|
242
|
+
readonly headerType: number;
|
|
237
243
|
readonly trackAlias: bigint;
|
|
238
244
|
readonly groupId: bigint;
|
|
239
245
|
readonly subgroupId: bigint;
|
|
240
246
|
readonly publisherPriority: number;
|
|
247
|
+
readonly endOfGroup?: boolean;
|
|
248
|
+
readonly firstObject?: boolean;
|
|
241
249
|
}
|
|
242
250
|
interface FetchStreamHeader {
|
|
243
251
|
readonly type: 'fetch_header';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@moqtap/codec",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.11.0",
|
|
4
4
|
"description": "MoQT wire-format codec and session state machine — multi-draft, zero dependencies",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -221,9 +221,9 @@
|
|
|
221
221
|
"test": "vitest run"
|
|
222
222
|
},
|
|
223
223
|
"devDependencies": {
|
|
224
|
-
"@moqtap/test-vectors": "^0.
|
|
224
|
+
"@moqtap/test-vectors": "^0.16.0",
|
|
225
225
|
"tsup": "^8.0.0",
|
|
226
226
|
"typescript": "^5.5.0",
|
|
227
|
-
"vitest": "^3.
|
|
227
|
+
"vitest": "^3.2.7"
|
|
228
228
|
}
|
|
229
229
|
}
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Overwriting Authorization Token values at the point of parse.
|
|
3
|
+
*
|
|
4
|
+
* A collector that ships a customer's control plane verbatim is useful — the
|
|
5
|
+
* control plane is the part of a session a player library cannot misreport —
|
|
6
|
+
* right up until it also ships the bearer token sitting in a SETUP option or a
|
|
7
|
+
* SUBSCRIBE parameter. At that point a debugging tool has become a
|
|
8
|
+
* credential-exfiltration path.
|
|
9
|
+
*
|
|
10
|
+
* The fix has to happen **where the parse happens**, not on the way out. Bytes
|
|
11
|
+
* that were merely *masked before upload* still sat in memory in a form a later
|
|
12
|
+
* feature — a dump, an export, a bug — could reach. So this module hangs off
|
|
13
|
+
* the decoders themselves: the one pass that reads a Token Value is the pass
|
|
14
|
+
* that records where it was, and the value is overwritten before the frame is
|
|
15
|
+
* handed to anything that retains it.
|
|
16
|
+
*
|
|
17
|
+
* ── What is overwritten, and what deliberately is not
|
|
18
|
+
*
|
|
19
|
+
* Only the **Token Value** (draft-20 Section 10.2.2, Figure 5). The Alias Type,
|
|
20
|
+
* the Token Alias and the Token Type all stay:
|
|
21
|
+
*
|
|
22
|
+
* - the parameter's *presence* distinguishes a session that failed to
|
|
23
|
+
* authenticate from one that never tried, and losing that distinction blinds
|
|
24
|
+
* the tool at exactly the moment it is most wanted;
|
|
25
|
+
* - the Token Alias is how you see the same credential being reused across
|
|
26
|
+
* messages, which is a real debugging signal and is not itself a secret;
|
|
27
|
+
* - `USE_ALIAS` and `DELETE` carry no value at all, so those frames pass
|
|
28
|
+
* through untouched and it is visible that they did.
|
|
29
|
+
*
|
|
30
|
+
* The overwrite is **length-preserving**. That is not an aesthetic choice: a
|
|
31
|
+
* control frame carries a fixed 16-bit Message Length, and every offset a
|
|
32
|
+
* caller has already computed into the frame stays valid only if the frame does
|
|
33
|
+
* not change size. Preserving the length also preserves the fact that a token
|
|
34
|
+
* of *some* size was sent.
|
|
35
|
+
*
|
|
36
|
+
* ── Why a span sink and not a return value
|
|
37
|
+
*
|
|
38
|
+
* A Token Value is read in `decodeParams` and `decodeSetupOptions`, which sit
|
|
39
|
+
* under a dozen per-message payload decoders per draft. Threading a redaction
|
|
40
|
+
* channel out through all of them would mean changing every one of those
|
|
41
|
+
* signatures, in every draft, to carry something almost none of them use.
|
|
42
|
+
*
|
|
43
|
+
* The sink is module state, which is safe here for one specific reason and it
|
|
44
|
+
* is worth being explicit about it: **decoding is synchronous and single
|
|
45
|
+
* threaded, and no decoder re-enters the redactor.** {@link redactWith} opens
|
|
46
|
+
* the capture, runs one decode to completion, and closes it in a `finally`.
|
|
47
|
+
* There is no `await` between those points, so no second capture can interleave
|
|
48
|
+
* with the first.
|
|
49
|
+
*
|
|
50
|
+
* Spec of record: `wt-logging-1-collector.md` Section 1.6.
|
|
51
|
+
*/
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* The byte written over a redacted Token Value.
|
|
55
|
+
*
|
|
56
|
+
* Zero, so that a redacted frame is obviously not a token rather than
|
|
57
|
+
* plausibly one. A caller who needs to tell "redacted" from "the peer really
|
|
58
|
+
* sent zeros" has {@link AuthRedaction.redacted}, which counts what was
|
|
59
|
+
* overwritten.
|
|
60
|
+
*/
|
|
61
|
+
export const REDACTION_FILL = 0x00
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* The result of a redaction pass over one control frame.
|
|
65
|
+
*/
|
|
66
|
+
export interface AuthRedaction {
|
|
67
|
+
/**
|
|
68
|
+
* The frame with every Token Value overwritten, exactly as long as the input.
|
|
69
|
+
*
|
|
70
|
+
* When nothing needed redacting this is the **same reference** as the input,
|
|
71
|
+
* so the common case costs no copy. Callers that retain it must copy for the
|
|
72
|
+
* same reason they would have had to copy the input.
|
|
73
|
+
*/
|
|
74
|
+
readonly bytes: Uint8Array
|
|
75
|
+
/** How many Token Values were overwritten. */
|
|
76
|
+
readonly redacted: number
|
|
77
|
+
/**
|
|
78
|
+
* A span was recorded that could not be applied to the frame.
|
|
79
|
+
*
|
|
80
|
+
* This means the offset arithmetic and the frame disagree, which is a defect
|
|
81
|
+
* rather than a wire condition. **A caller must not treat {@link bytes} as
|
|
82
|
+
* clean when this is set** — the safe response is to drop the frame's raw
|
|
83
|
+
* bytes rather than ship them, because the one thing that is certain is that
|
|
84
|
+
* a token was seen and its position is not trusted.
|
|
85
|
+
*/
|
|
86
|
+
readonly incomplete: boolean
|
|
87
|
+
/**
|
|
88
|
+
* Whether the message parsed all the way through.
|
|
89
|
+
*
|
|
90
|
+
* A frame can be perfectly legitimate and still not decode: an unknown or
|
|
91
|
+
* extension message codepoint is something a peer is allowed to send, and a
|
|
92
|
+
* collector ships those raw on purpose rather than losing the whole control
|
|
93
|
+
* plane over one of them. But a message that cannot be parsed is a message
|
|
94
|
+
* whose parameters cannot be walked, so `redacted === 0` on such a frame
|
|
95
|
+
* means "nothing was found", not "there is nothing there".
|
|
96
|
+
*
|
|
97
|
+
* That residual is narrow and it is real, and the only dishonest thing to do
|
|
98
|
+
* with it is hide it. Count the frames where this is false, so the gap in the
|
|
99
|
+
* guarantee is a number somebody can look at.
|
|
100
|
+
*/
|
|
101
|
+
readonly decoded: boolean
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Payload-relative `[start, length]` pairs, flat. `null` when not capturing —
|
|
106
|
+
* which is the state every ordinary decode runs in, so the recording hook costs
|
|
107
|
+
* one null check on a path that is otherwise untouched.
|
|
108
|
+
*/
|
|
109
|
+
let spans: number[] | null = null
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Record that a Token Value occupies `length` bytes at `start`, measured from
|
|
113
|
+
* the beginning of the **payload** the current decoder is reading.
|
|
114
|
+
*
|
|
115
|
+
* Called from the draft decoders. A zero-length value records nothing: there is
|
|
116
|
+
* nothing to overwrite, and a zero-length span would only inflate the count.
|
|
117
|
+
*/
|
|
118
|
+
export function recordAuthValueSpan(start: number, length: number): void {
|
|
119
|
+
if (spans === null || length <= 0) return
|
|
120
|
+
spans.push(start, length)
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Run `decode` with span capture suspended.
|
|
125
|
+
*
|
|
126
|
+
* For decoders that read a parameter block out of a **nested** buffer — draft-20's
|
|
127
|
+
* `FILL_PARAMETERS` is the case that exists today. Offsets recorded inside a
|
|
128
|
+
* nested reader are relative to that reader, and applying them to the outer
|
|
129
|
+
* payload would overwrite unrelated bytes: not a failed redaction but a
|
|
130
|
+
* corrupted frame, and a silent one. Scope rules already forbid an
|
|
131
|
+
* AUTHORIZATION_TOKEN inside FILL_PARAMETERS, so this guards against a future
|
|
132
|
+
* nesting rather than a present one — which is exactly when it is cheap to add.
|
|
133
|
+
*/
|
|
134
|
+
export function withoutAuthValueSpans<T>(decode: () => T): T {
|
|
135
|
+
const saved = spans
|
|
136
|
+
spans = null
|
|
137
|
+
try {
|
|
138
|
+
return decode()
|
|
139
|
+
} finally {
|
|
140
|
+
spans = saved
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* Decode `frame` once, capturing Token Value spans, and return the frame with
|
|
146
|
+
* those values overwritten.
|
|
147
|
+
*
|
|
148
|
+
* `payloadStart` is where the message payload begins inside the frame; the
|
|
149
|
+
* spans the decoders record are payload-relative, and this is what makes them
|
|
150
|
+
* frame-relative. `decode` may fail — a malformed message decodes partially and
|
|
151
|
+
* throws or returns an error — and **spans recorded before it failed are still
|
|
152
|
+
* applied**, because a value that was read is a value that was exposed
|
|
153
|
+
* regardless of what happened afterwards.
|
|
154
|
+
*
|
|
155
|
+
* `decode` reports whether it parsed the whole message; a throw counts as no.
|
|
156
|
+
*/
|
|
157
|
+
export function redactWith(
|
|
158
|
+
frame: Uint8Array,
|
|
159
|
+
payloadStart: number,
|
|
160
|
+
decode: () => boolean,
|
|
161
|
+
): AuthRedaction {
|
|
162
|
+
const outer = spans
|
|
163
|
+
spans = []
|
|
164
|
+
let captured: number[]
|
|
165
|
+
let decoded = false
|
|
166
|
+
try {
|
|
167
|
+
decoded = decode()
|
|
168
|
+
} catch {
|
|
169
|
+
// The caller's decoder threw. Whatever it recorded before it did is real.
|
|
170
|
+
} finally {
|
|
171
|
+
captured = spans
|
|
172
|
+
spans = outer
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
if (captured.length === 0) return { bytes: frame, redacted: 0, incomplete: false, decoded }
|
|
176
|
+
|
|
177
|
+
let out: Uint8Array | null = null
|
|
178
|
+
let redacted = 0
|
|
179
|
+
let incomplete = false
|
|
180
|
+
for (let i = 0; i < captured.length; i += 2) {
|
|
181
|
+
const start = payloadStart + (captured[i] as number)
|
|
182
|
+
const length = captured[i + 1] as number
|
|
183
|
+
if (payloadStart < 0 || start < 0 || start + length > frame.length) {
|
|
184
|
+
incomplete = true
|
|
185
|
+
continue
|
|
186
|
+
}
|
|
187
|
+
if (out === null) out = frame.slice()
|
|
188
|
+
out.fill(REDACTION_FILL, start, start + length)
|
|
189
|
+
redacted++
|
|
190
|
+
}
|
|
191
|
+
return { bytes: out ?? frame, redacted, incomplete, decoded }
|
|
192
|
+
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type AuthRedaction, recordAuthValueSpan, redactWith } from '../../core/auth-redaction.js'
|
|
1
2
|
import { BufferReader } from '../../core/buffer-reader.js'
|
|
2
3
|
import { BufferWriter } from '../../core/buffer-writer.js'
|
|
3
4
|
import { bytesToHex, hexToBytes } from '../../core/hex.js'
|
|
@@ -213,6 +214,11 @@ function decodeParams(r: BufferReader): Draft07Params {
|
|
|
213
214
|
|
|
214
215
|
if (paramType === PARAM_AUTHORIZATION_INFO) {
|
|
215
216
|
const bytes = r.readBytes(length)
|
|
217
|
+
// The credential is the whole value in this draft: a bare UTF-8 string,
|
|
218
|
+
// with no alias and no token type around it. What survives the overwrite
|
|
219
|
+
// is the parameter's presence, which is what says authorization was
|
|
220
|
+
// attempted at all.
|
|
221
|
+
recordAuthValueSpan(r.offset - length, length)
|
|
216
222
|
result.authorization_info = textDecoder.decode(bytes)
|
|
217
223
|
} else if (paramType === PARAM_DELIVERY_TIMEOUT) {
|
|
218
224
|
const blob = r.readBytes(length)
|
|
@@ -1056,3 +1062,37 @@ export function createDraft07Codec(): Draft07Codec {
|
|
|
1056
1062
|
|
|
1057
1063
|
// Export data-stream decoder map for callers that need to disambiguate
|
|
1058
1064
|
export { dataStreamDecoders }
|
|
1065
|
+
|
|
1066
|
+
/**
|
|
1067
|
+
* Overwrite every AUTHORIZATION_INFO value in a draft-07 control frame.
|
|
1068
|
+
*
|
|
1069
|
+
* One decode, whose *output is discarded*: the point is not to read the
|
|
1070
|
+
* message, it is to learn where the credentials were so the caller never has to
|
|
1071
|
+
* hold a frame that contains one. A caller that also wants the message should
|
|
1072
|
+
* decode the **redacted** frame with {@link decodeMessage}, which then cannot
|
|
1073
|
+
* produce a value because there is no longer one in the bytes.
|
|
1074
|
+
*
|
|
1075
|
+
* A frame that fails to decode is still redacted as far as the decode got. That
|
|
1076
|
+
* is the useful direction to fail in: a value that was read is a value that was
|
|
1077
|
+
* exposed, whatever went wrong after it.
|
|
1078
|
+
*
|
|
1079
|
+
* See {@link AuthRedaction.incomplete} for the one result a caller must not
|
|
1080
|
+
* treat as clean, and {@link AuthRedaction.decoded} for the residual it cannot
|
|
1081
|
+
* close.
|
|
1082
|
+
*/
|
|
1083
|
+
export function redactAuthTokens(bytes: Uint8Array): AuthRedaction {
|
|
1084
|
+
let payloadStart: number
|
|
1085
|
+
try {
|
|
1086
|
+
const probe = new BufferReader(bytes)
|
|
1087
|
+
probe.readVarInt()
|
|
1088
|
+
probe.readVarInt()
|
|
1089
|
+
payloadStart = probe.offset
|
|
1090
|
+
} catch {
|
|
1091
|
+
// Too short to carry a message header, and so too short for the parameters
|
|
1092
|
+
// that carry a credential. Reported as not decoded rather than as clean: a
|
|
1093
|
+
// framer only ever emits complete frames, so a caller that gets here is
|
|
1094
|
+
// holding something this function did not check.
|
|
1095
|
+
return { bytes, redacted: 0, incomplete: false, decoded: false }
|
|
1096
|
+
}
|
|
1097
|
+
return redactWith(bytes, payloadStart, () => decodeMessage(bytes).ok)
|
|
1098
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
// Draft-07 error, status and termination code registries.
|
|
2
|
+
|
|
3
|
+
export const SessionErrorCode = {
|
|
4
|
+
NoError: 0x0n,
|
|
5
|
+
InternalError: 0x1n,
|
|
6
|
+
Unauthorized: 0x2n,
|
|
7
|
+
ProtocolViolation: 0x3n,
|
|
8
|
+
DuplicateTrackAlias: 0x4n,
|
|
9
|
+
ParameterLengthMismatch: 0x5n,
|
|
10
|
+
TooManySubscribes: 0x6n,
|
|
11
|
+
GoawayTimeout: 0x10n,
|
|
12
|
+
} as const
|
|
13
|
+
export type SessionErrorCodeValue = (typeof SessionErrorCode)[keyof typeof SessionErrorCode]
|
|
14
|
+
|
|
15
|
+
export const SubscribeErrorCode = {
|
|
16
|
+
InternalError: 0x0n,
|
|
17
|
+
InvalidRange: 0x1n,
|
|
18
|
+
RetryTrackAlias: 0x2n,
|
|
19
|
+
TrackDoesNotExist: 0x3n,
|
|
20
|
+
Unauthorized: 0x4n,
|
|
21
|
+
Timeout: 0x5n,
|
|
22
|
+
} as const
|
|
23
|
+
export type SubscribeErrorCodeValue = (typeof SubscribeErrorCode)[keyof typeof SubscribeErrorCode]
|
|
24
|
+
|
|
25
|
+
export const SubscribeDoneStatusCode = {
|
|
26
|
+
Unsubscribed: 0x0n,
|
|
27
|
+
InternalError: 0x1n,
|
|
28
|
+
Unauthorized: 0x2n,
|
|
29
|
+
TrackEnded: 0x3n,
|
|
30
|
+
SubscriptionEnded: 0x4n,
|
|
31
|
+
GoingAway: 0x5n,
|
|
32
|
+
Expired: 0x6n,
|
|
33
|
+
} as const
|
|
34
|
+
export type SubscribeDoneStatusCodeValue =
|
|
35
|
+
(typeof SubscribeDoneStatusCode)[keyof typeof SubscribeDoneStatusCode]
|
|
36
|
+
|
|
37
|
+
export const TrackStatusCode = {
|
|
38
|
+
InProgress: 0x00n,
|
|
39
|
+
TrackDoesNotExist: 0x01n,
|
|
40
|
+
NotYetBegun: 0x02n,
|
|
41
|
+
Finished: 0x03n,
|
|
42
|
+
RelayStatusUnavailable: 0x04n,
|
|
43
|
+
} as const
|
|
44
|
+
export type TrackStatusCodeValue = (typeof TrackStatusCode)[keyof typeof TrackStatusCode]
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
export const DRAFT_VERSION = 0xff000007n
|
|
2
2
|
|
|
3
|
+
export type { AuthRedaction } from '../../core/auth-redaction.js'
|
|
4
|
+
export { REDACTION_FILL } from '../../core/auth-redaction.js'
|
|
3
5
|
export type { DecodeErrorCode, DecodeResult } from '../../core/types.js'
|
|
4
6
|
// Re-export types consumers need
|
|
5
7
|
export { DecodeError } from '../../core/types.js'
|
|
@@ -12,7 +14,20 @@ export {
|
|
|
12
14
|
encodeDatagram,
|
|
13
15
|
encodeFetchStream,
|
|
14
16
|
encodeSubgroupStream,
|
|
17
|
+
redactAuthTokens,
|
|
15
18
|
} from './codec.js'
|
|
19
|
+
export type {
|
|
20
|
+
SessionErrorCodeValue,
|
|
21
|
+
SubscribeDoneStatusCodeValue,
|
|
22
|
+
SubscribeErrorCodeValue,
|
|
23
|
+
TrackStatusCodeValue,
|
|
24
|
+
} from './error-codes.js'
|
|
25
|
+
export {
|
|
26
|
+
SessionErrorCode,
|
|
27
|
+
SubscribeDoneStatusCode,
|
|
28
|
+
SubscribeErrorCode,
|
|
29
|
+
TrackStatusCode,
|
|
30
|
+
} from './error-codes.js'
|
|
16
31
|
export {
|
|
17
32
|
MESSAGE_ID_MAP,
|
|
18
33
|
MESSAGE_TYPE_MAP,
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type AuthRedaction, recordAuthValueSpan, redactWith } from '../../core/auth-redaction.js'
|
|
1
2
|
import { BufferReader } from '../../core/buffer-reader.js'
|
|
2
3
|
import { BufferWriter } from '../../core/buffer-writer.js'
|
|
3
4
|
import { bytesToHex, hexToBytes } from '../../core/hex.js'
|
|
@@ -183,6 +184,11 @@ function decodeParams(r: BufferReader): Draft08Params {
|
|
|
183
184
|
|
|
184
185
|
if (paramType === PARAM_AUTHORIZATION_INFO) {
|
|
185
186
|
const bytes = r.readBytes(length)
|
|
187
|
+
// The credential is the whole value in this draft: a bare UTF-8 string,
|
|
188
|
+
// with no alias and no token type around it. What survives the overwrite
|
|
189
|
+
// is the parameter's presence, which is what says authorization was
|
|
190
|
+
// attempted at all.
|
|
191
|
+
recordAuthValueSpan(r.offset - length, length)
|
|
186
192
|
result.authorization_info = textDecoder.decode(bytes)
|
|
187
193
|
} else if (paramType === PARAM_DELIVERY_TIMEOUT) {
|
|
188
194
|
const blob = r.readBytes(length)
|
|
@@ -983,3 +989,37 @@ export function createDraft08Codec(): Draft08Codec {
|
|
|
983
989
|
createStreamDecoder,
|
|
984
990
|
}
|
|
985
991
|
}
|
|
992
|
+
|
|
993
|
+
/**
|
|
994
|
+
* Overwrite every AUTHORIZATION_INFO value in a draft-08 control frame.
|
|
995
|
+
*
|
|
996
|
+
* One decode, whose *output is discarded*: the point is not to read the
|
|
997
|
+
* message, it is to learn where the credentials were so the caller never has to
|
|
998
|
+
* hold a frame that contains one. A caller that also wants the message should
|
|
999
|
+
* decode the **redacted** frame with {@link decodeMessage}, which then cannot
|
|
1000
|
+
* produce a value because there is no longer one in the bytes.
|
|
1001
|
+
*
|
|
1002
|
+
* A frame that fails to decode is still redacted as far as the decode got. That
|
|
1003
|
+
* is the useful direction to fail in: a value that was read is a value that was
|
|
1004
|
+
* exposed, whatever went wrong after it.
|
|
1005
|
+
*
|
|
1006
|
+
* See {@link AuthRedaction.incomplete} for the one result a caller must not
|
|
1007
|
+
* treat as clean, and {@link AuthRedaction.decoded} for the residual it cannot
|
|
1008
|
+
* close.
|
|
1009
|
+
*/
|
|
1010
|
+
export function redactAuthTokens(bytes: Uint8Array): AuthRedaction {
|
|
1011
|
+
let payloadStart: number
|
|
1012
|
+
try {
|
|
1013
|
+
const probe = new BufferReader(bytes)
|
|
1014
|
+
probe.readVarInt()
|
|
1015
|
+
probe.readVarInt()
|
|
1016
|
+
payloadStart = probe.offset
|
|
1017
|
+
} catch {
|
|
1018
|
+
// Too short to carry a message header, and so too short for the parameters
|
|
1019
|
+
// that carry a credential. Reported as not decoded rather than as clean: a
|
|
1020
|
+
// framer only ever emits complete frames, so a caller that gets here is
|
|
1021
|
+
// holding something this function did not check.
|
|
1022
|
+
return { bytes, redacted: 0, incomplete: false, decoded: false }
|
|
1023
|
+
}
|
|
1024
|
+
return redactWith(bytes, payloadStart, () => decodeMessage(bytes).ok)
|
|
1025
|
+
}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
// Draft-08 error, status and termination code registries.
|
|
2
|
+
|
|
3
|
+
export const SessionErrorCode = {
|
|
4
|
+
NoError: 0x0n,
|
|
5
|
+
InternalError: 0x1n,
|
|
6
|
+
Unauthorized: 0x2n,
|
|
7
|
+
ProtocolViolation: 0x3n,
|
|
8
|
+
DuplicateTrackAlias: 0x4n,
|
|
9
|
+
ParameterLengthMismatch: 0x5n,
|
|
10
|
+
TooManySubscribes: 0x6n,
|
|
11
|
+
GoawayTimeout: 0x10n,
|
|
12
|
+
ControlMessageTimeout: 0x11n,
|
|
13
|
+
DataStreamTimeout: 0x12n,
|
|
14
|
+
} as const
|
|
15
|
+
export type SessionErrorCodeValue = (typeof SessionErrorCode)[keyof typeof SessionErrorCode]
|
|
16
|
+
|
|
17
|
+
export const AnnounceErrorCode = {
|
|
18
|
+
InternalError: 0x0n,
|
|
19
|
+
Unauthorized: 0x1n,
|
|
20
|
+
Timeout: 0x2n,
|
|
21
|
+
NotSupported: 0x3n,
|
|
22
|
+
Uninterested: 0x4n,
|
|
23
|
+
} as const
|
|
24
|
+
export type AnnounceErrorCodeValue = (typeof AnnounceErrorCode)[keyof typeof AnnounceErrorCode]
|
|
25
|
+
|
|
26
|
+
export const SubscribeErrorCode = {
|
|
27
|
+
InternalError: 0x0n,
|
|
28
|
+
Unauthorized: 0x1n,
|
|
29
|
+
Timeout: 0x2n,
|
|
30
|
+
NotSupported: 0x3n,
|
|
31
|
+
TrackDoesNotExist: 0x4n,
|
|
32
|
+
InvalidRange: 0x5n,
|
|
33
|
+
RetryTrackAlias: 0x6n,
|
|
34
|
+
} as const
|
|
35
|
+
export type SubscribeErrorCodeValue = (typeof SubscribeErrorCode)[keyof typeof SubscribeErrorCode]
|
|
36
|
+
|
|
37
|
+
export const FetchErrorCode = {
|
|
38
|
+
InternalError: 0x0n,
|
|
39
|
+
Unauthorized: 0x1n,
|
|
40
|
+
Timeout: 0x2n,
|
|
41
|
+
NotSupported: 0x3n,
|
|
42
|
+
TrackDoesNotExist: 0x4n,
|
|
43
|
+
InvalidRange: 0x5n,
|
|
44
|
+
} as const
|
|
45
|
+
export type FetchErrorCodeValue = (typeof FetchErrorCode)[keyof typeof FetchErrorCode]
|
|
46
|
+
|
|
47
|
+
export const SubscribeDoneStatusCode = {
|
|
48
|
+
InternalError: 0x0n,
|
|
49
|
+
Unauthorized: 0x1n,
|
|
50
|
+
TrackEnded: 0x2n,
|
|
51
|
+
SubscriptionEnded: 0x3n,
|
|
52
|
+
GoingAway: 0x4n,
|
|
53
|
+
Expired: 0x5n,
|
|
54
|
+
TooFarBehind: 0x6n,
|
|
55
|
+
} as const
|
|
56
|
+
export type SubscribeDoneStatusCodeValue =
|
|
57
|
+
(typeof SubscribeDoneStatusCode)[keyof typeof SubscribeDoneStatusCode]
|
|
58
|
+
|
|
59
|
+
export const SubscribeAnnouncesErrorCode = {
|
|
60
|
+
InternalError: 0x0n,
|
|
61
|
+
Unauthorized: 0x1n,
|
|
62
|
+
Timeout: 0x2n,
|
|
63
|
+
NotSupported: 0x3n,
|
|
64
|
+
NamespacePrefixUnknown: 0x4n,
|
|
65
|
+
} as const
|
|
66
|
+
export type SubscribeAnnouncesErrorCodeValue =
|
|
67
|
+
(typeof SubscribeAnnouncesErrorCode)[keyof typeof SubscribeAnnouncesErrorCode]
|
|
68
|
+
|
|
69
|
+
export const TrackStatusCode = {
|
|
70
|
+
InProgress: 0x00n,
|
|
71
|
+
TrackDoesNotExist: 0x01n,
|
|
72
|
+
NotYetBegun: 0x02n,
|
|
73
|
+
Finished: 0x03n,
|
|
74
|
+
RelayStatusUnavailable: 0x04n,
|
|
75
|
+
} as const
|
|
76
|
+
export type TrackStatusCodeValue = (typeof TrackStatusCode)[keyof typeof TrackStatusCode]
|