@moqtap/codec 0.9.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.
Files changed (232) hide show
  1. package/CHANGELOG.md +173 -0
  2. package/dist/auth-redaction-DsdLq4Qs.d.cts +102 -0
  3. package/dist/auth-redaction-DsdLq4Qs.d.ts +102 -0
  4. package/dist/{chunk-PU2KV7VP.cjs → chunk-27K5BUAG.cjs} +485 -515
  5. package/dist/{chunk-BV6MITLO.js → chunk-3RNQMGKA.js} +365 -390
  6. package/dist/{chunk-2XH6PHXR.js → chunk-5AWIXOLB.js} +442 -467
  7. package/dist/{chunk-4XLYCT5Q.cjs → chunk-5IMHJIAZ.cjs} +52 -2
  8. package/dist/{chunk-TVSFDQYE.cjs → chunk-5JGZCKJO.cjs} +513 -531
  9. package/dist/{chunk-IADVBKEJ.cjs → chunk-73K4OSAN.cjs} +407 -432
  10. package/dist/{chunk-N2V7Z37J.js → chunk-7VQKRGRD.js} +19 -3
  11. package/dist/{chunk-UZO5Z2XT.cjs → chunk-A3UCQOIB.cjs} +490 -515
  12. package/dist/{chunk-JKMYAUGY.js → chunk-A7PDMVXM.js} +35 -11
  13. package/dist/{chunk-VZHL2U2N.cjs → chunk-A7VQO6YC.cjs} +54 -38
  14. package/dist/{chunk-KCH4BQXK.cjs → chunk-ACQHZLRZ.cjs} +73 -47
  15. package/dist/{chunk-H6DTAIWM.js → chunk-BBICOMW6.js} +47 -19
  16. package/dist/{chunk-MAXEHYVB.cjs → chunk-BNIUVOCJ.cjs} +554 -612
  17. package/dist/{chunk-QGIHC6BA.cjs → chunk-CNC6ANS4.cjs} +70 -46
  18. package/dist/{chunk-NH4L6NIY.js → chunk-FDLQSWHK.js} +437 -467
  19. package/dist/{chunk-IJAF6PAY.js → chunk-FFNOE4UR.js} +19 -3
  20. package/dist/{chunk-CZNW3R5E.cjs → chunk-GMENT63T.cjs} +54 -38
  21. package/dist/{chunk-7ENEWAMZ.cjs → chunk-HM7BLRVP.cjs} +305 -305
  22. package/dist/{chunk-XHAP2YST.js → chunk-HZONHFNO.js} +19 -3
  23. package/dist/{chunk-EVCPBFSR.cjs → chunk-ILYABWDK.cjs} +83 -55
  24. package/dist/{chunk-IDV2JYJ6.cjs → chunk-KRSFTZVO.cjs} +56 -40
  25. package/dist/{chunk-RIIA4ALQ.cjs → chunk-KSPH6KMH.cjs} +54 -38
  26. package/dist/{chunk-UA5XFP4O.cjs → chunk-KTY4LAUV.cjs} +485 -494
  27. package/dist/{chunk-RZTLQAKF.js → chunk-OJNLJT5D.js} +0 -1
  28. package/dist/{chunk-YJGOD3Y4.js → chunk-PJK2ZS3I.js} +492 -550
  29. package/dist/{chunk-TMXRYOBS.js → chunk-PSMZKHOC.js} +444 -453
  30. package/dist/{chunk-7RE6KSIY.cjs → chunk-Q5JQGHWY.cjs} +0 -1
  31. package/dist/{chunk-23KRITJ6.js → chunk-SQTUQY5E.js} +37 -11
  32. package/dist/{chunk-XQGEOFGE.js → chunk-WCRLAKDW.js} +253 -253
  33. package/dist/{chunk-KYVTM5VI.js → chunk-WL2YUEXH.js} +19 -3
  34. package/dist/{chunk-Q7NSUXXB.js → chunk-YCNIVZS7.js} +464 -482
  35. package/dist/{chunk-KLPWJU6W.js → chunk-YRZQVNZO.js} +50 -0
  36. package/dist/{codec-Bym-K2q2.d.cts → codec-76xzrLTL.d.cts} +21 -2
  37. package/dist/{codec-BKsVu3Fr.d.ts → codec-8p40WdLg.d.ts} +21 -2
  38. package/dist/{codec-Dl_QIXMz.d.ts → codec-BN2Bu0KI.d.ts} +20 -1
  39. package/dist/{codec-D4RvFQmu.d.ts → codec-Bb6GKTrv.d.ts} +21 -2
  40. package/dist/{codec-DAyiF5sq.d.cts → codec-BgpfHoAd.d.cts} +21 -2
  41. package/dist/{codec-CA6nbbEk.d.ts → codec-BkheTXO7.d.ts} +21 -2
  42. package/dist/{codec-DchsPfr3.d.cts → codec-BwVDkokh.d.cts} +21 -2
  43. package/dist/{codec-CgZdadPt.d.cts → codec-C5s1eBJX.d.cts} +21 -2
  44. package/dist/codec-CM5yd6n3.d.ts +38 -0
  45. package/dist/{codec-DJmqoIsp.d.cts → codec-Cb8HC3XV.d.cts} +21 -2
  46. package/dist/codec-Clu_skx8.d.cts +38 -0
  47. package/dist/{codec-DzkdW4kO.d.cts → codec-CpOpemR8.d.cts} +20 -1
  48. package/dist/{codec-CXCjya_G.d.cts → codec-Cshdl9Tt.d.cts} +20 -1
  49. package/dist/{codec-CSBFdPgP.d.cts → codec-DELe00w_.d.cts} +21 -2
  50. package/dist/{codec-C_xxsbKy.d.cts → codec-DHzKAUCa.d.cts} +21 -2
  51. package/dist/{codec--CVeqGQv.d.ts → codec-DdVBtvx7.d.ts} +20 -1
  52. package/dist/{codec-CviAa4lp.d.ts → codec-DlxGuYMv.d.ts} +21 -2
  53. package/dist/{codec-BNy5syCU.d.ts → codec-DxtgPxJS.d.ts} +20 -1
  54. package/dist/{codec-CtvFK4aV.d.cts → codec-GAY4lybi.d.cts} +21 -2
  55. package/dist/{codec-Cfo_z5ET.d.cts → codec-I8u2pfS4.d.cts} +20 -1
  56. package/dist/{codec-vddqy0KY.d.cts → codec-XLrnreeu.d.cts} +21 -2
  57. package/dist/{codec-O-1Js7h4.d.ts → codec-c0YEwwWn.d.ts} +21 -2
  58. package/dist/{codec-Cl73EfRW.d.ts → codec-ejDu-va6.d.ts} +21 -2
  59. package/dist/{codec-C006F75E.d.ts → codec-kaBUzdpV.d.ts} +21 -2
  60. package/dist/{codec-C5evFHL-.d.ts → codec-mVYqkIUF.d.ts} +21 -2
  61. package/dist/{codec-BMwgZIgG.d.ts → codec-qSbO5nOa.d.ts} +21 -2
  62. package/dist/{codec-BQa6Qsav.d.ts → codec-yYKGOipj.d.ts} +21 -2
  63. package/dist/{codec-DzLvG8Wb.d.cts → codec-zfzg9uiy.d.cts} +21 -2
  64. package/dist/draft07.cjs +48 -4
  65. package/dist/draft07.d.cts +42 -2
  66. package/dist/draft07.d.ts +42 -2
  67. package/dist/draft07.js +49 -5
  68. package/dist/draft08.cjs +76 -3
  69. package/dist/draft08.d.cts +70 -2
  70. package/dist/draft08.d.ts +70 -2
  71. package/dist/draft08.js +77 -4
  72. package/dist/draft09.cjs +76 -3
  73. package/dist/draft09.d.cts +70 -2
  74. package/dist/draft09.d.ts +70 -2
  75. package/dist/draft09.js +77 -4
  76. package/dist/draft10.cjs +76 -3
  77. package/dist/draft10.d.cts +70 -2
  78. package/dist/draft10.d.ts +70 -2
  79. package/dist/draft10.js +77 -4
  80. package/dist/draft11-session.d.cts +1 -1
  81. package/dist/draft11-session.d.ts +1 -1
  82. package/dist/draft11.cjs +104 -3
  83. package/dist/draft11.d.cts +100 -4
  84. package/dist/draft11.d.ts +100 -4
  85. package/dist/draft11.js +105 -4
  86. package/dist/draft12-session.d.cts +1 -1
  87. package/dist/draft12-session.d.ts +1 -1
  88. package/dist/draft12.cjs +113 -3
  89. package/dist/draft12.d.cts +109 -4
  90. package/dist/draft12.d.ts +109 -4
  91. package/dist/draft12.js +114 -4
  92. package/dist/draft13-session.d.cts +1 -1
  93. package/dist/draft13-session.d.ts +1 -1
  94. package/dist/draft13.cjs +105 -3
  95. package/dist/draft13.d.cts +101 -4
  96. package/dist/draft13.d.ts +101 -4
  97. package/dist/draft13.js +106 -4
  98. package/dist/draft14-session.d.cts +1 -1
  99. package/dist/draft14-session.d.ts +1 -1
  100. package/dist/draft14.cjs +107 -3
  101. package/dist/draft14.d.cts +103 -30
  102. package/dist/draft14.d.ts +103 -30
  103. package/dist/draft14.js +108 -4
  104. package/dist/draft15-session.d.cts +1 -1
  105. package/dist/draft15-session.d.ts +1 -1
  106. package/dist/draft15.cjs +69 -3
  107. package/dist/draft15.d.cts +65 -22
  108. package/dist/draft15.d.ts +65 -22
  109. package/dist/draft15.js +70 -4
  110. package/dist/draft16-session.cjs +2 -2
  111. package/dist/draft16-session.d.cts +1 -1
  112. package/dist/draft16-session.d.ts +1 -1
  113. package/dist/draft16-session.js +1 -1
  114. package/dist/draft16.cjs +76 -8
  115. package/dist/draft16.d.cts +67 -13
  116. package/dist/draft16.d.ts +67 -13
  117. package/dist/draft16.js +73 -5
  118. package/dist/draft17-session.d.cts +1 -1
  119. package/dist/draft17-session.d.ts +1 -1
  120. package/dist/draft17.cjs +77 -3
  121. package/dist/draft17.d.cts +73 -4
  122. package/dist/draft17.d.ts +73 -4
  123. package/dist/draft17.js +78 -4
  124. package/dist/draft18-session.d.cts +1 -1
  125. package/dist/draft18-session.d.ts +1 -1
  126. package/dist/draft18.cjs +8 -3
  127. package/dist/draft18.d.cts +4 -3
  128. package/dist/draft18.d.ts +4 -3
  129. package/dist/draft18.js +9 -4
  130. package/dist/draft19-session.d.cts +1 -1
  131. package/dist/draft19-session.d.ts +1 -1
  132. package/dist/draft19.cjs +11 -4
  133. package/dist/draft19.d.cts +4 -3
  134. package/dist/draft19.d.ts +4 -3
  135. package/dist/draft19.js +12 -5
  136. package/dist/draft20-session.d.cts +1 -1
  137. package/dist/draft20-session.d.ts +1 -1
  138. package/dist/draft20.cjs +8 -3
  139. package/dist/draft20.d.cts +4 -3
  140. package/dist/draft20.d.ts +4 -3
  141. package/dist/draft20.js +9 -4
  142. package/dist/index.cjs +30 -30
  143. package/dist/index.d.cts +25 -24
  144. package/dist/index.d.ts +25 -24
  145. package/dist/index.js +15 -15
  146. package/dist/session.cjs +2 -2
  147. package/dist/session.d.cts +10 -10
  148. package/dist/session.d.ts +10 -10
  149. package/dist/session.js +1 -1
  150. package/dist/{types-zHgCS6o5.d.cts → types-Btp416jt.d.cts} +15 -7
  151. package/dist/{types-zHgCS6o5.d.ts → types-Btp416jt.d.ts} +15 -7
  152. package/dist/{types-Cm9fjeYC.d.cts → types-BxTL1NXw.d.cts} +9 -2
  153. package/dist/{types-Cm9fjeYC.d.ts → types-BxTL1NXw.d.ts} +9 -2
  154. package/dist/{types-Bio-91Rt.d.cts → types-CI_SX4Xe.d.cts} +2 -2
  155. package/dist/{types-Bio-91Rt.d.ts → types-CI_SX4Xe.d.ts} +2 -2
  156. package/dist/{types-HI_bbXka.d.cts → types-CmqT0jUf.d.cts} +1 -1
  157. package/dist/{types-HI_bbXka.d.ts → types-CmqT0jUf.d.ts} +1 -1
  158. package/dist/{types-CPaYBsMG.d.cts → types-CuibHYcf.d.cts} +9 -2
  159. package/dist/{types-CPaYBsMG.d.ts → types-CuibHYcf.d.ts} +9 -2
  160. package/dist/{types-CWCQwuvy.d.cts → types-CwN7AEoL.d.cts} +24 -12
  161. package/dist/{types-CWCQwuvy.d.ts → types-CwN7AEoL.d.ts} +24 -12
  162. package/dist/{types-Ck45Ex5S.d.cts → types-D0kTgUuL.d.cts} +1 -1
  163. package/dist/{types-Ck45Ex5S.d.ts → types-D0kTgUuL.d.ts} +1 -1
  164. package/dist/{types-D9eiB_9A.d.cts → types-DAnalt5K.d.cts} +9 -2
  165. package/dist/{types-D9eiB_9A.d.ts → types-DAnalt5K.d.ts} +9 -2
  166. package/dist/{types-CXlSn0I9.d.cts → types-DjxexghA.d.cts} +2 -2
  167. package/dist/{types-CXlSn0I9.d.ts → types-DjxexghA.d.ts} +2 -2
  168. package/dist/{types-Cqp10JtB.d.cts → types-DxXNP32l.d.cts} +10 -2
  169. package/dist/{types-Cqp10JtB.d.ts → types-DxXNP32l.d.ts} +10 -2
  170. package/package.json +3 -3
  171. package/src/core/auth-redaction.ts +192 -0
  172. package/src/drafts/draft07/codec.ts +40 -0
  173. package/src/drafts/draft07/error-codes.ts +44 -0
  174. package/src/drafts/draft07/index.ts +15 -0
  175. package/src/drafts/draft08/codec.ts +40 -0
  176. package/src/drafts/draft08/error-codes.ts +76 -0
  177. package/src/drafts/draft08/index.ts +21 -0
  178. package/src/drafts/draft09/codec.ts +40 -0
  179. package/src/drafts/draft09/error-codes.ts +76 -0
  180. package/src/drafts/draft09/index.ts +21 -0
  181. package/src/drafts/draft10/codec.ts +40 -0
  182. package/src/drafts/draft10/error-codes.ts +76 -0
  183. package/src/drafts/draft10/index.ts +21 -0
  184. package/src/drafts/draft11/codec.ts +71 -8
  185. package/src/drafts/draft11/error-codes.ts +106 -0
  186. package/src/drafts/draft11/index.ts +23 -0
  187. package/src/drafts/draft11/types.ts +1 -1
  188. package/src/drafts/draft12/codec.ts +83 -16
  189. package/src/drafts/draft12/error-codes.ts +116 -0
  190. package/src/drafts/draft12/index.ts +25 -0
  191. package/src/drafts/draft12/types.ts +2 -2
  192. package/src/drafts/draft13/codec.ts +75 -11
  193. package/src/drafts/draft13/error-codes.ts +107 -0
  194. package/src/drafts/draft13/index.ts +23 -0
  195. package/src/drafts/draft13/types.ts +3 -3
  196. package/src/drafts/draft14/codec.ts +79 -12
  197. package/src/drafts/draft14/data-streams.ts +331 -259
  198. package/src/drafts/draft14/error-codes.ts +109 -0
  199. package/src/drafts/draft14/index.ts +23 -0
  200. package/src/drafts/draft14/types.ts +1 -1
  201. package/src/drafts/draft15/codec.ts +71 -8
  202. package/src/drafts/draft15/data-streams.ts +489 -444
  203. package/src/drafts/draft15/error-codes.ts +66 -0
  204. package/src/drafts/draft15/index.ts +15 -0
  205. package/src/drafts/draft15/types.ts +9 -2
  206. package/src/drafts/draft16/codec.ts +149 -49
  207. package/src/drafts/draft16/data-streams.ts +513 -442
  208. package/src/drafts/draft16/error-codes.ts +68 -0
  209. package/src/drafts/draft16/index.ts +15 -0
  210. package/src/drafts/draft16/messages.ts +4 -4
  211. package/src/drafts/draft16/session-fsm.ts +0 -1
  212. package/src/drafts/draft16/types.ts +24 -10
  213. package/src/drafts/draft17/codec.ts +77 -10
  214. package/src/drafts/draft17/data-streams.ts +567 -488
  215. package/src/drafts/draft17/index.ts +15 -0
  216. package/src/drafts/draft17/types.ts +9 -2
  217. package/src/drafts/draft18/codec.ts +70 -7
  218. package/src/drafts/draft18/data-streams.ts +570 -482
  219. package/src/drafts/draft18/index.ts +3 -0
  220. package/src/drafts/draft18/types.ts +18 -10
  221. package/src/drafts/draft19/codec.ts +95 -23
  222. package/src/drafts/draft19/data-streams.ts +570 -482
  223. package/src/drafts/draft19/error-codes.ts +3 -1
  224. package/src/drafts/draft19/index.ts +3 -0
  225. package/src/drafts/draft19/messages.ts +3 -1
  226. package/src/drafts/draft19/types.ts +32 -18
  227. package/src/drafts/draft20/codec.ts +115 -36
  228. package/src/drafts/draft20/data-streams.ts +610 -563
  229. package/src/drafts/draft20/index.ts +3 -0
  230. package/src/drafts/draft20/types.ts +31 -13
  231. package/dist/codec-BJ7BHuiZ.d.ts +0 -18
  232. 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,
@@ -20,7 +20,7 @@ export interface AuthorizationToken {
20
20
  export interface Draft15SetupParams {
21
21
  path?: string // 0x01 odd
22
22
  max_request_id?: bigint // 0x02 even
23
- authorization_token?: AuthorizationToken // 0x03 odd (length-prefixed, nested)
23
+ authorization_token?: readonly AuthorizationToken[] // 0x03 odd (length-prefixed, nested)
24
24
  max_auth_token_cache_size?: bigint // 0x04 even
25
25
  authority?: string // 0x05 odd
26
26
  moqt_implementation?: string // 0x07 odd
@@ -44,7 +44,7 @@ export interface LargestObject {
44
44
  // Version-specific parameters (well-known + unknown)
45
45
  export interface Draft15Params {
46
46
  delivery_timeout?: bigint // 0x02 even
47
- authorization_token?: AuthorizationToken // 0x03 odd (length-prefixed, nested)
47
+ authorization_token?: readonly AuthorizationToken[] // 0x03 odd (length-prefixed, nested)
48
48
  max_cache_duration?: bigint // 0x04 even
49
49
  expires?: bigint // 0x08 even
50
50
  largest_object?: LargestObject // 0x09 odd (length-prefixed)
@@ -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
- let count = 0
66
- if (params.path !== undefined) count++
67
- if (params.max_request_id !== undefined) count++
68
- if (params.authorization_token !== undefined) count++
69
- if (params.max_auth_token_cache_size !== undefined) count++
70
- if (params.authority !== undefined) count++
71
- if (params.moqt_implementation !== undefined) count++
72
- if (params.unknown) count += params.unknown.length
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
- writer.writeVarInt(SETUP_PARAM_PATH)
79
- const encoded = textEncoder.encode(params.path)
80
- writer.writeVarInt(encoded.byteLength)
81
- writer.writeBytes(encoded)
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
- writer.writeVarInt(SETUP_PARAM_MAX_REQUEST_ID)
87
- writer.writeVarInt(params.max_request_id)
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
- if (params.authorization_token !== undefined) {
92
- writer.writeVarInt(SETUP_PARAM_AUTHORIZATION_TOKEN)
93
- const tmpW = new BufferWriter(64)
94
- encodeAuthorizationToken(params.authorization_token, tmpW)
95
- const raw = tmpW.finish()
96
- writer.writeVarInt(raw.byteLength)
97
- writer.writeBytes(raw)
96
+ for (const token of params.authorization_token ?? []) {
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
- writer.writeVarInt(SETUP_PARAM_MAX_AUTH_TOKEN_CACHE_SIZE)
103
- writer.writeVarInt(params.max_auth_token_cache_size)
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
- writer.writeVarInt(SETUP_PARAM_AUTHORITY)
109
- const encoded = textEncoder.encode(params.authority)
110
- writer.writeVarInt(encoded.byteLength)
111
- writer.writeBytes(encoded)
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
- writer.writeVarInt(SETUP_PARAM_MOQT_IMPLEMENTATION)
117
- const encoded = textEncoder.encode(params.moqt_implementation)
118
- writer.writeVarInt(encoded.byteLength)
119
- writer.writeBytes(encoded)
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
- writer.writeVarInt(id)
127
- if (id % 2n === 0n) {
128
- const raw = hexToBytes(u.raw_hex)
129
- const tmpReader = new BufferReader(raw)
130
- const value = tmpReader.readVarInt()
131
- writer.writeVarInt(value)
132
- } else {
133
- const raw = hexToBytes(u.raw_hex)
134
- writer.writeVarInt(raw.byteLength)
135
- writer.writeBytes(raw)
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
- const paramType = reader.readVarInt()
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,7 +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
- result.authorization_token = decodeAuthorizationToken(new BufferReader(bytes))
209
+ const token = decodeAuthorizationToken(new BufferReader(bytes))
210
+ noteAuthTokenValue(reader.offset - length, length, token.token_value)
211
+ result.authorization_token = [...(result.authorization_token ?? []), token]
172
212
  } else if (paramType === SETUP_PARAM_AUTHORITY) {
173
213
  result.authority = textDecoder.decode(bytes)
174
214
  } else if (paramType === SETUP_PARAM_MOQT_IMPLEMENTATION) {
@@ -324,12 +364,12 @@ function encodeParams(params: Draft16Params, writer: BufferWriter): void {
324
364
  encode: (w) => w.writeVarInt(params.delivery_timeout!),
325
365
  })
326
366
  }
327
- if (params.authorization_token !== undefined) {
367
+ for (const token of params.authorization_token ?? []) {
328
368
  entries.push({
329
369
  type: PARAM_AUTHORIZATION_TOKEN,
330
370
  encode: (w) => {
331
371
  const tmpW = new BufferWriter(64)
332
- encodeAuthorizationToken(params.authorization_token!, tmpW)
372
+ encodeAuthorizationToken(token, tmpW)
333
373
  const raw = tmpW.finish()
334
374
  w.writeVarInt(raw.byteLength)
335
375
  w.writeBytes(raw)
@@ -457,7 +497,9 @@ function decodeParams(reader: BufferReader): Draft16Params {
457
497
  } else if (paramType === PARAM_AUTHORIZATION_TOKEN) {
458
498
  const length = Number(reader.readVarInt())
459
499
  const tokenBytes = reader.readBytes(length)
460
- result.authorization_token = decodeAuthorizationToken(new BufferReader(tokenBytes))
500
+ const token = decodeAuthorizationToken(new BufferReader(tokenBytes))
501
+ noteAuthTokenValue(reader.offset - length, length, token.token_value)
502
+ result.authorization_token = [...(result.authorization_token ?? []), token]
461
503
  } else if (paramType === PARAM_MAX_CACHE_DURATION) {
462
504
  result.max_cache_duration = reader.readVarInt()
463
505
  } else if (paramType === PARAM_EXPIRES) {
@@ -1262,3 +1304,61 @@ export function createDraft16Codec(): Draft16Codec {
1262
1304
  createDataStreamDecoder,
1263
1305
  }
1264
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
+ }