@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
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
// Draft-15 error, status and termination code registries.
|
|
2
|
+
|
|
3
|
+
export const SessionErrorCode = {
|
|
4
|
+
NoError: 0x0n,
|
|
5
|
+
InternalError: 0x1n,
|
|
6
|
+
Unauthorized: 0x2n,
|
|
7
|
+
ProtocolViolation: 0x3n,
|
|
8
|
+
InvalidRequestId: 0x4n,
|
|
9
|
+
DuplicateTrackAlias: 0x5n,
|
|
10
|
+
KeyValueFormattingError: 0x6n,
|
|
11
|
+
TooManyRequests: 0x7n,
|
|
12
|
+
InvalidPath: 0x8n,
|
|
13
|
+
MalformedPath: 0x9n,
|
|
14
|
+
GoawayTimeout: 0x10n,
|
|
15
|
+
ControlMessageTimeout: 0x11n,
|
|
16
|
+
DataStreamTimeout: 0x12n,
|
|
17
|
+
AuthTokenCacheOverflow: 0x13n,
|
|
18
|
+
DuplicateAuthTokenAlias: 0x14n,
|
|
19
|
+
VersionNegotiationFailed: 0x15n,
|
|
20
|
+
MalformedAuthToken: 0x16n,
|
|
21
|
+
UnknownAuthTokenAlias: 0x17n,
|
|
22
|
+
ExpiredAuthToken: 0x18n,
|
|
23
|
+
InvalidAuthority: 0x19n,
|
|
24
|
+
MalformedAuthority: 0x1an,
|
|
25
|
+
} as const
|
|
26
|
+
export type SessionErrorCodeValue = (typeof SessionErrorCode)[keyof typeof SessionErrorCode]
|
|
27
|
+
|
|
28
|
+
export const RequestErrorCode = {
|
|
29
|
+
InternalError: 0x0n,
|
|
30
|
+
Unauthorized: 0x1n,
|
|
31
|
+
Timeout: 0x2n,
|
|
32
|
+
NotSupported: 0x3n,
|
|
33
|
+
MalformedAuthToken: 0x4n,
|
|
34
|
+
ExpiredAuthToken: 0x5n,
|
|
35
|
+
DoesNotExist: 0x10n,
|
|
36
|
+
InvalidRange: 0x11n,
|
|
37
|
+
MalformedTrack: 0x12n,
|
|
38
|
+
Uninterested: 0x20n,
|
|
39
|
+
PrefixOverlap: 0x30n,
|
|
40
|
+
InvalidJoiningRequestId: 0x32n,
|
|
41
|
+
UnknownStatusInRange: 0x33n,
|
|
42
|
+
} as const
|
|
43
|
+
export type RequestErrorCodeValue = (typeof RequestErrorCode)[keyof typeof RequestErrorCode]
|
|
44
|
+
|
|
45
|
+
export const PublishDoneStatusCode = {
|
|
46
|
+
InternalError: 0x0n,
|
|
47
|
+
Unauthorized: 0x1n,
|
|
48
|
+
TrackEnded: 0x2n,
|
|
49
|
+
SubscriptionEnded: 0x3n,
|
|
50
|
+
GoingAway: 0x4n,
|
|
51
|
+
Expired: 0x5n,
|
|
52
|
+
TooFarBehind: 0x6n,
|
|
53
|
+
MalformedTrack: 0x7n,
|
|
54
|
+
UpdateFailed: 0x8n,
|
|
55
|
+
} as const
|
|
56
|
+
export type PublishDoneStatusCodeValue =
|
|
57
|
+
(typeof PublishDoneStatusCode)[keyof typeof PublishDoneStatusCode]
|
|
58
|
+
|
|
59
|
+
export const DataStreamResetErrorCode = {
|
|
60
|
+
InternalError: 0x0n,
|
|
61
|
+
Cancelled: 0x1n,
|
|
62
|
+
DeliveryTimeout: 0x2n,
|
|
63
|
+
SessionClosed: 0x3n,
|
|
64
|
+
} as const
|
|
65
|
+
export type DataStreamResetErrorCodeValue =
|
|
66
|
+
(typeof DataStreamResetErrorCode)[keyof typeof DataStreamResetErrorCode]
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
export const DRAFT_VERSION = 0xff00000fn
|
|
2
2
|
|
|
3
|
+
export type { AuthRedaction } from '../../core/auth-redaction.js'
|
|
4
|
+
export { REDACTION_FILL } from '../../core/auth-redaction.js'
|
|
3
5
|
export type { Draft15Codec } from './codec.js'
|
|
4
6
|
export {
|
|
5
7
|
createDataStreamDecoder,
|
|
@@ -16,7 +18,20 @@ export {
|
|
|
16
18
|
encodeFetchStream,
|
|
17
19
|
encodeMessage,
|
|
18
20
|
encodeSubgroupStream,
|
|
21
|
+
redactAuthTokens,
|
|
19
22
|
} from './codec.js'
|
|
23
|
+
export type {
|
|
24
|
+
DataStreamResetErrorCodeValue,
|
|
25
|
+
PublishDoneStatusCodeValue,
|
|
26
|
+
RequestErrorCodeValue,
|
|
27
|
+
SessionErrorCodeValue,
|
|
28
|
+
} from './error-codes.js'
|
|
29
|
+
export {
|
|
30
|
+
DataStreamResetErrorCode,
|
|
31
|
+
PublishDoneStatusCode,
|
|
32
|
+
RequestErrorCode,
|
|
33
|
+
SessionErrorCode,
|
|
34
|
+
} from './error-codes.js'
|
|
20
35
|
export {
|
|
21
36
|
MESSAGE_ID_MAP,
|
|
22
37
|
MESSAGE_TYPE_MAP,
|
|
@@ -342,10 +342,17 @@ export type Draft15DataStream = SubgroupStream | DatagramObject | FetchStream
|
|
|
342
342
|
// Streaming data stream decoder types
|
|
343
343
|
export interface SubgroupStreamHeader {
|
|
344
344
|
readonly type: 'subgroup_header'
|
|
345
|
+
/**
|
|
346
|
+
* The stream Type Flags, the same value `SubgroupStream.headerType` carries.
|
|
347
|
+
* Without it the incremental decoder discarded every flag the header
|
|
348
|
+
* encodes and a consumer could not tell the modes apart.
|
|
349
|
+
*/
|
|
350
|
+
readonly headerType: number
|
|
345
351
|
readonly trackAlias: bigint
|
|
346
352
|
readonly groupId: bigint
|
|
347
353
|
readonly subgroupId: bigint
|
|
348
354
|
readonly publisherPriority: number
|
|
355
|
+
readonly endOfGroup?: boolean
|
|
349
356
|
}
|
|
350
357
|
|
|
351
358
|
export interface FetchStreamHeader {
|
|
@@ -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'
|
|
@@ -62,89 +63,126 @@ const textDecoder = /* @__PURE__ */ new TextDecoder()
|
|
|
62
63
|
// ─── Setup Parameter Encoding/Decoding ──────────────────────────────────────────
|
|
63
64
|
|
|
64
65
|
function encodeSetupParams(params: Draft16SetupParams, writer: BufferWriter): void {
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
writer.writeVarInt(count)
|
|
66
|
+
// Draft-16 Section 9.2: "Parameters are serialized as Key-Value-Pairs." That
|
|
67
|
+
// includes Setup Parameters, so Section 1.4.2 applies here exactly as it does
|
|
68
|
+
// in encodeParams: "Key-Value-Pairs encode a Type value as a delta from the
|
|
69
|
+
// previous Type value, or from 0 if there is no previous Type value." A Delta
|
|
70
|
+
// Type is an unsigned varint, so ascending order is the only order the wire
|
|
71
|
+
// format can express. The entries are collected, sorted, and written as
|
|
72
|
+
// differences. Drafts 15 and earlier wrote the Type absolutely.
|
|
73
|
+
const entries: Array<{ type: bigint; encode: (w: BufferWriter) => void }> = []
|
|
75
74
|
|
|
76
75
|
// PATH (0x01) - odd, length-prefixed bytes
|
|
77
76
|
if (params.path !== undefined) {
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
77
|
+
entries.push({
|
|
78
|
+
type: SETUP_PARAM_PATH,
|
|
79
|
+
encode: (w) => {
|
|
80
|
+
const encoded = textEncoder.encode(params.path!)
|
|
81
|
+
w.writeVarInt(encoded.byteLength)
|
|
82
|
+
w.writeBytes(encoded)
|
|
83
|
+
},
|
|
84
|
+
})
|
|
82
85
|
}
|
|
83
86
|
|
|
84
87
|
// MAX_REQUEST_ID (0x02) - even, varint value
|
|
85
88
|
if (params.max_request_id !== undefined) {
|
|
86
|
-
|
|
87
|
-
|
|
89
|
+
entries.push({
|
|
90
|
+
type: SETUP_PARAM_MAX_REQUEST_ID,
|
|
91
|
+
encode: (w) => w.writeVarInt(params.max_request_id!),
|
|
92
|
+
})
|
|
88
93
|
}
|
|
89
94
|
|
|
90
95
|
// AUTHORIZATION_TOKEN (0x03) - odd, length-prefixed with nested structure
|
|
91
96
|
for (const token of params.authorization_token ?? []) {
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
97
|
+
entries.push({
|
|
98
|
+
type: SETUP_PARAM_AUTHORIZATION_TOKEN,
|
|
99
|
+
encode: (w) => {
|
|
100
|
+
const tmpW = new BufferWriter(64)
|
|
101
|
+
encodeAuthorizationToken(token, tmpW)
|
|
102
|
+
const raw = tmpW.finish()
|
|
103
|
+
w.writeVarInt(raw.byteLength)
|
|
104
|
+
w.writeBytes(raw)
|
|
105
|
+
},
|
|
106
|
+
})
|
|
98
107
|
}
|
|
99
108
|
|
|
100
109
|
// MAX_AUTH_TOKEN_CACHE_SIZE (0x04) - even, varint value
|
|
101
110
|
if (params.max_auth_token_cache_size !== undefined) {
|
|
102
|
-
|
|
103
|
-
|
|
111
|
+
entries.push({
|
|
112
|
+
type: SETUP_PARAM_MAX_AUTH_TOKEN_CACHE_SIZE,
|
|
113
|
+
encode: (w) => w.writeVarInt(params.max_auth_token_cache_size!),
|
|
114
|
+
})
|
|
104
115
|
}
|
|
105
116
|
|
|
106
117
|
// AUTHORITY (0x05) - odd, length-prefixed bytes
|
|
107
118
|
if (params.authority !== undefined) {
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
119
|
+
entries.push({
|
|
120
|
+
type: SETUP_PARAM_AUTHORITY,
|
|
121
|
+
encode: (w) => {
|
|
122
|
+
const encoded = textEncoder.encode(params.authority!)
|
|
123
|
+
w.writeVarInt(encoded.byteLength)
|
|
124
|
+
w.writeBytes(encoded)
|
|
125
|
+
},
|
|
126
|
+
})
|
|
112
127
|
}
|
|
113
128
|
|
|
114
129
|
// MOQT_IMPLEMENTATION (0x07) - odd, length-prefixed bytes
|
|
115
130
|
if (params.moqt_implementation !== undefined) {
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
131
|
+
entries.push({
|
|
132
|
+
type: SETUP_PARAM_MOQT_IMPLEMENTATION,
|
|
133
|
+
encode: (w) => {
|
|
134
|
+
const encoded = textEncoder.encode(params.moqt_implementation!)
|
|
135
|
+
w.writeVarInt(encoded.byteLength)
|
|
136
|
+
w.writeBytes(encoded)
|
|
137
|
+
},
|
|
138
|
+
})
|
|
120
139
|
}
|
|
121
140
|
|
|
122
141
|
// Unknown params
|
|
123
142
|
if (params.unknown) {
|
|
124
143
|
for (const u of params.unknown) {
|
|
125
144
|
const id = BigInt(u.id)
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
145
|
+
entries.push({
|
|
146
|
+
type: id,
|
|
147
|
+
encode: (w) => {
|
|
148
|
+
const raw = hexToBytes(u.raw_hex)
|
|
149
|
+
if (id % 2n === 0n) {
|
|
150
|
+
w.writeVarInt(new BufferReader(raw).readVarInt())
|
|
151
|
+
} else {
|
|
152
|
+
w.writeVarInt(raw.byteLength)
|
|
153
|
+
w.writeBytes(raw)
|
|
154
|
+
}
|
|
155
|
+
},
|
|
156
|
+
})
|
|
137
157
|
}
|
|
138
158
|
}
|
|
159
|
+
|
|
160
|
+
// Stable, so a repeated AUTHORIZATION_TOKEN keeps the order it was given in
|
|
161
|
+
// and encodes as a Delta Type of 0.
|
|
162
|
+
entries.sort((a, b) => (a.type < b.type ? -1 : a.type > b.type ? 1 : 0))
|
|
163
|
+
|
|
164
|
+
writer.writeVarInt(entries.length)
|
|
165
|
+
let prevType = 0n
|
|
166
|
+
for (const entry of entries) {
|
|
167
|
+
writer.writeVarInt(entry.type - prevType)
|
|
168
|
+
entry.encode(writer)
|
|
169
|
+
prevType = entry.type
|
|
170
|
+
}
|
|
139
171
|
}
|
|
140
172
|
|
|
141
173
|
function decodeSetupParams(reader: BufferReader): Draft16SetupParams {
|
|
142
174
|
const count = Number(reader.readVarInt())
|
|
143
175
|
const result: Draft16SetupParams = {}
|
|
144
176
|
const unknown: UnknownParam[] = []
|
|
177
|
+
let prevType = 0n
|
|
145
178
|
|
|
146
179
|
for (let i = 0; i < count; i++) {
|
|
147
|
-
|
|
180
|
+
// Draft-16 Section 1.4.2: the Type is a delta from the previous Type, or
|
|
181
|
+
// from 0 for the first pair. Parity -- "Length: Only present when Type is
|
|
182
|
+
// odd" -- is decided by the resolved Type, never by the delta.
|
|
183
|
+
const delta = reader.readVarInt()
|
|
184
|
+
const paramType = prevType + delta
|
|
185
|
+
prevType = paramType
|
|
148
186
|
|
|
149
187
|
if (paramType % 2n === 0n) {
|
|
150
188
|
const value = reader.readVarInt()
|
|
@@ -168,10 +206,9 @@ function decodeSetupParams(reader: BufferReader): Draft16SetupParams {
|
|
|
168
206
|
if (paramType === SETUP_PARAM_PATH) {
|
|
169
207
|
result.path = textDecoder.decode(bytes)
|
|
170
208
|
} else if (paramType === SETUP_PARAM_AUTHORIZATION_TOKEN) {
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
]
|
|
209
|
+
const token = decodeAuthorizationToken(new BufferReader(bytes))
|
|
210
|
+
noteAuthTokenValue(reader.offset - length, length, token.token_value)
|
|
211
|
+
result.authorization_token = [...(result.authorization_token ?? []), token]
|
|
175
212
|
} else if (paramType === SETUP_PARAM_AUTHORITY) {
|
|
176
213
|
result.authority = textDecoder.decode(bytes)
|
|
177
214
|
} else if (paramType === SETUP_PARAM_MOQT_IMPLEMENTATION) {
|
|
@@ -460,10 +497,9 @@ function decodeParams(reader: BufferReader): Draft16Params {
|
|
|
460
497
|
} else if (paramType === PARAM_AUTHORIZATION_TOKEN) {
|
|
461
498
|
const length = Number(reader.readVarInt())
|
|
462
499
|
const tokenBytes = reader.readBytes(length)
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
]
|
|
500
|
+
const token = decodeAuthorizationToken(new BufferReader(tokenBytes))
|
|
501
|
+
noteAuthTokenValue(reader.offset - length, length, token.token_value)
|
|
502
|
+
result.authorization_token = [...(result.authorization_token ?? []), token]
|
|
467
503
|
} else if (paramType === PARAM_MAX_CACHE_DURATION) {
|
|
468
504
|
result.max_cache_duration = reader.readVarInt()
|
|
469
505
|
} else if (paramType === PARAM_EXPIRES) {
|
|
@@ -1268,3 +1304,61 @@ export function createDraft16Codec(): Draft16Codec {
|
|
|
1268
1304
|
createDataStreamDecoder,
|
|
1269
1305
|
}
|
|
1270
1306
|
}
|
|
1307
|
+
|
|
1308
|
+
/**
|
|
1309
|
+
* Record where a Token Value sits, so it can be overwritten before the frame
|
|
1310
|
+
* reaches anything that keeps it.
|
|
1311
|
+
*
|
|
1312
|
+
* The span falls out of the decode with no second walk. The Token Value is the
|
|
1313
|
+
* last field of the Token structure, so its start is the parameter value's end
|
|
1314
|
+
* minus the value's own length. The fields before it are left alone
|
|
1315
|
+
* deliberately: Alias Type, Token Alias and Token Type are structure rather
|
|
1316
|
+
* than secret, and they are what distinguishes a session that failed to
|
|
1317
|
+
* authenticate from one that never tried.
|
|
1318
|
+
*
|
|
1319
|
+
* A token carrying no value at all -- DELETE and USE_ALIAS -- records nothing,
|
|
1320
|
+
* and its frame passes through untouched.
|
|
1321
|
+
*/
|
|
1322
|
+
function noteAuthTokenValue(
|
|
1323
|
+
valueStart: number,
|
|
1324
|
+
valueLength: number,
|
|
1325
|
+
value: Uint8Array | undefined,
|
|
1326
|
+
): void {
|
|
1327
|
+
if (value === undefined || value.byteLength === 0) return
|
|
1328
|
+
recordAuthValueSpan(valueStart + valueLength - value.byteLength, value.byteLength)
|
|
1329
|
+
}
|
|
1330
|
+
|
|
1331
|
+
/**
|
|
1332
|
+
* Overwrite every Authorization Token value in a draft-16 control frame.
|
|
1333
|
+
*
|
|
1334
|
+
* One decode, whose *output is discarded*: the point is not to read the
|
|
1335
|
+
* message, it is to learn where the credentials were so the caller never has to
|
|
1336
|
+
* hold a frame that contains one. A caller that also wants the message should
|
|
1337
|
+
* decode the **redacted** frame with {@link decodeMessage}, which then cannot
|
|
1338
|
+
* produce a value because there is no longer one in the bytes.
|
|
1339
|
+
*
|
|
1340
|
+
* A frame that fails to decode is still redacted as far as the decode got. That
|
|
1341
|
+
* is the useful direction to fail in: a value that was read is a value that was
|
|
1342
|
+
* exposed, whatever went wrong after it.
|
|
1343
|
+
*
|
|
1344
|
+
* See {@link AuthRedaction.incomplete} for the one result a caller must not
|
|
1345
|
+
* treat as clean, and {@link AuthRedaction.decoded} for the residual it cannot
|
|
1346
|
+
* close.
|
|
1347
|
+
*/
|
|
1348
|
+
export function redactAuthTokens(bytes: Uint8Array): AuthRedaction {
|
|
1349
|
+
let payloadStart: number
|
|
1350
|
+
try {
|
|
1351
|
+
const probe = new BufferReader(bytes)
|
|
1352
|
+
probe.readVarInt()
|
|
1353
|
+
probe.readUint8()
|
|
1354
|
+
probe.readUint8()
|
|
1355
|
+
payloadStart = probe.offset
|
|
1356
|
+
} catch {
|
|
1357
|
+
// Too short to carry a message header, and so too short for the parameters
|
|
1358
|
+
// that carry a credential. Reported as not decoded rather than as clean: a
|
|
1359
|
+
// framer only ever emits complete frames, so a caller that gets here is
|
|
1360
|
+
// holding something this function did not check.
|
|
1361
|
+
return { bytes, redacted: 0, incomplete: false, decoded: false }
|
|
1362
|
+
}
|
|
1363
|
+
return redactWith(bytes, payloadStart, () => decodeMessage(bytes).ok)
|
|
1364
|
+
}
|