@moqtap/codec 0.2.3 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -21
- package/README.md +100 -99
- package/dist/{chunk-RZHAPEXO.js → chunk-2A57DRXV.js} +36 -10
- package/dist/{chunk-73MWUKSJ.js → chunk-2UTVXWFF.js} +190 -102
- package/dist/{chunk-JTVCOMBI.cjs → chunk-3XKO6PCR.cjs} +290 -183
- package/dist/{chunk-ACQ4CUJP.cjs → chunk-4BDEU3D4.cjs} +237 -158
- package/dist/{chunk-4N4INRE7.cjs → chunk-4HBKHNU2.cjs} +144 -110
- package/dist/{chunk-2ZT6CVSE.js → chunk-4IVZZOY3.js} +269 -162
- package/dist/{chunk-GLBQDG4L.cjs → chunk-5O764MBD.cjs} +508 -117
- package/dist/chunk-7KBAWOBA.js +1212 -0
- package/dist/{chunk-JSQM2MG3.js → chunk-7QOPNSDF.js} +44 -12
- package/dist/{chunk-SYHW3FLI.cjs → chunk-7RE6KSIY.cjs} +28 -8
- package/dist/{chunk-YG5KJESI.js → chunk-AY6IAHUM.js} +28 -8
- package/dist/{chunk-EFM5T7OM.js → chunk-BLQDWOSG.js} +36 -10
- package/dist/{chunk-UYXTY6ZQ.cjs → chunk-E65QKRSN.cjs} +20 -12
- package/dist/{chunk-BISI45MN.cjs → chunk-EAHE3IOG.cjs} +44 -12
- package/dist/{chunk-PZBPH2D7.js → chunk-GCBFHZW6.js} +216 -137
- package/dist/{chunk-GXEW4COZ.cjs → chunk-H5NSL4MO.cjs} +36 -10
- package/dist/chunk-HZHSO7EW.cjs +1212 -0
- package/dist/{chunk-KZCYQ7ED.cjs → chunk-IILNSDEQ.cjs} +69 -41
- package/dist/{chunk-4XYGE53S.cjs → chunk-J3XCPBW3.cjs} +36 -10
- package/dist/{chunk-6AEHWULA.cjs → chunk-JKOEJZ5B.cjs} +28 -8
- package/dist/{chunk-RUPCJTC3.cjs → chunk-JL3NEW3O.cjs} +23 -1
- package/dist/{chunk-G7GI7LJA.js → chunk-LORZMJJB.js} +36 -10
- package/dist/{chunk-DUBCL3WF.cjs → chunk-LV5C6MEC.cjs} +36 -10
- package/dist/{chunk-ENURAVHI.cjs → chunk-MYXAD5JC.cjs} +44 -12
- package/dist/{chunk-FXZ2MYKJ.js → chunk-MZ7HUCGJ.js} +20 -12
- package/dist/{chunk-S74DWJE2.cjs → chunk-OKG2HT25.cjs} +277 -88
- package/dist/{chunk-BGWGVINJ.cjs → chunk-PKEOQSSZ.cjs} +144 -110
- package/dist/{chunk-2GODRVT5.js → chunk-Q46ZURKX.js} +325 -48
- package/dist/{chunk-UR6JKS56.js → chunk-Q7IGWV3P.js} +41 -9
- package/dist/{chunk-XSNX2IUJ.js → chunk-RW4UG7CN.js} +121 -87
- package/dist/{chunk-DWK5ZQZ4.js → chunk-RZTLQAKF.js} +28 -8
- package/dist/{chunk-UNS34PTA.cjs → chunk-S6IPIN66.cjs} +44 -12
- package/dist/{chunk-YIG2C3LF.cjs → chunk-SDWRXXOO.cjs} +214 -126
- package/dist/{chunk-CEH7ESNC.js → chunk-SHMA4PBY.js} +121 -87
- package/dist/{chunk-MC7W6PMI.js → chunk-U3ZVLT5L.js} +483 -135
- package/dist/{chunk-VJUUZ4W2.cjs → chunk-UJU63EFY.cjs} +374 -97
- package/dist/{chunk-7L43FE6P.js → chunk-VOU7PNHI.js} +23 -1
- package/dist/{chunk-E6E3NQYU.js → chunk-WRHGCVYN.js} +44 -12
- package/dist/{chunk-FPISPJ5N.cjs → chunk-XNWYLVGU.cjs} +529 -181
- package/dist/{chunk-U3IPZYPX.js → chunk-XS77RBY7.js} +228 -39
- package/dist/{chunk-JGG7CMSZ.cjs → chunk-XZE5R57R.cjs} +144 -110
- package/dist/{chunk-77MNXX3M.js → chunk-Y6KCSM3V.js} +121 -87
- package/dist/{chunk-TLYNOOQP.cjs → chunk-YTPZZI2M.cjs} +41 -9
- package/dist/{chunk-7DUBLRXC.js → chunk-YWRCSQBA.js} +44 -12
- package/dist/{chunk-MRJWLGYH.js → chunk-Z3VKP3PJ.js} +69 -41
- package/dist/{chunk-E6P74GDT.js → chunk-Z6U26IRI.js} +464 -73
- package/dist/{codec-FvGCxIhr.d.ts → codec-25u4_1HS.d.ts} +4 -4
- package/dist/{codec-DRcsBCsb.d.ts → codec-3Ppy_5Gd.d.ts} +4 -4
- package/dist/{codec-BdVMRMOI.d.ts → codec-BB0U8MF2.d.cts} +4 -4
- package/dist/{codec-B2cH-f5V.d.cts → codec-BHHfBTnV.d.ts} +4 -4
- package/dist/{codec-B5K73Bdj.d.ts → codec-BN6jk0Td.d.cts} +4 -4
- package/dist/{codec-R8GrCPt2.d.ts → codec-BU0gaSZm.d.ts} +4 -4
- package/dist/{codec-Bq-tLtfP.d.ts → codec-C-Yk2RNa.d.ts} +4 -4
- package/dist/codec-CFWQY9Lj.d.cts +18 -0
- package/dist/{codec-CPlK3Pi5.d.ts → codec-COy4uuPO.d.cts} +4 -4
- package/dist/codec-CewFCsEy.d.ts +18 -0
- package/dist/{codec-KXHvXZVb.d.cts → codec-Ck7ZwFF1.d.cts} +4 -4
- package/dist/{codec-DZhZSIii.d.cts → codec-D2QVSH9D.d.ts} +4 -4
- package/dist/{codec-BwFgpeQu.d.ts → codec-DDUBJGn0.d.cts} +4 -4
- package/dist/{codec-BFeliJFc.d.ts → codec-DNfml-se.d.ts} +4 -4
- package/dist/{codec-C4n1PS09.d.cts → codec-DoOGjjDq.d.cts} +4 -4
- package/dist/{codec-Bap882Fh.d.cts → codec-J7ekOSMc.d.ts} +4 -4
- package/dist/{codec-SKBeHQk7.d.ts → codec-R9TJCq-E.d.cts} +4 -4
- package/dist/{codec-DNUIgLqc.d.cts → codec-ZwV-Njt6.d.ts} +4 -4
- package/dist/{codec-HgBgHkFI.d.cts → codec-j819z_hL.d.cts} +4 -4
- package/dist/{codec-DY4QH364.d.cts → codec-w8z2j_uo.d.cts} +4 -4
- package/dist/{codec-CPvPq0sb.d.cts → codec-wtt6WF1K.d.ts} +4 -4
- package/dist/{codec-BUMjz0J4.d.cts → codec-z6_2PSzi.d.cts} +4 -4
- package/dist/draft10-session.cjs +2 -2
- package/dist/draft10-session.d.cts +6 -6
- package/dist/draft10-session.d.ts +6 -6
- package/dist/draft10-session.js +1 -1
- package/dist/draft10.cjs +8 -5
- package/dist/draft10.d.cts +14 -12
- package/dist/draft10.d.ts +14 -12
- package/dist/draft10.js +16 -13
- package/dist/draft11-session.cjs +2 -2
- package/dist/draft11-session.d.cts +6 -6
- package/dist/draft11-session.d.ts +6 -6
- package/dist/draft11-session.js +1 -1
- package/dist/draft11.cjs +8 -5
- package/dist/draft11.d.cts +14 -12
- package/dist/draft11.d.ts +14 -12
- package/dist/draft11.js +16 -13
- package/dist/draft12-session.cjs +2 -2
- package/dist/draft12-session.d.cts +6 -6
- package/dist/draft12-session.d.ts +6 -6
- package/dist/draft12-session.js +1 -1
- package/dist/draft12.cjs +8 -5
- package/dist/draft12.d.cts +16 -14
- package/dist/draft12.d.ts +16 -14
- package/dist/draft12.js +16 -13
- package/dist/draft13-session.cjs +2 -2
- package/dist/draft13-session.d.cts +6 -6
- package/dist/draft13-session.d.ts +6 -6
- package/dist/draft13-session.js +1 -1
- package/dist/draft13.cjs +8 -5
- package/dist/draft13.d.cts +16 -14
- package/dist/draft13.d.ts +16 -14
- package/dist/draft13.js +16 -13
- package/dist/draft14-session.cjs +2 -2
- package/dist/draft14-session.d.cts +6 -6
- package/dist/draft14-session.d.ts +6 -6
- package/dist/draft14-session.js +1 -1
- package/dist/draft14.cjs +14 -5
- package/dist/draft14.d.cts +14 -12
- package/dist/draft14.d.ts +14 -12
- package/dist/draft14.js +13 -4
- package/dist/draft15-session.cjs +2 -2
- package/dist/draft15-session.d.cts +6 -6
- package/dist/draft15-session.d.ts +6 -6
- package/dist/draft15-session.js +1 -1
- package/dist/draft15.cjs +8 -5
- package/dist/draft15.d.cts +14 -12
- package/dist/draft15.d.ts +14 -12
- package/dist/draft15.js +16 -13
- package/dist/draft16-session.cjs +2 -2
- package/dist/draft16-session.d.cts +6 -6
- package/dist/draft16-session.d.ts +6 -6
- package/dist/draft16-session.js +1 -1
- package/dist/draft16.cjs +8 -5
- package/dist/draft16.d.cts +14 -12
- package/dist/draft16.d.ts +14 -12
- package/dist/draft16.js +16 -13
- package/dist/draft17-session.cjs +2 -2
- package/dist/draft17-session.d.cts +7 -7
- package/dist/draft17-session.d.ts +7 -7
- package/dist/draft17-session.js +1 -1
- package/dist/draft17.cjs +8 -5
- package/dist/draft17.d.cts +11 -9
- package/dist/draft17.d.ts +11 -9
- package/dist/draft17.js +16 -13
- package/dist/draft7-session.cjs +2 -2
- package/dist/draft7-session.d.cts +6 -5
- package/dist/draft7-session.d.ts +6 -5
- package/dist/draft7-session.js +1 -1
- package/dist/draft7.cjs +71 -14
- package/dist/draft7.d.cts +53 -134
- package/dist/draft7.d.ts +53 -134
- package/dist/draft7.js +76 -19
- package/dist/draft8-session.cjs +2 -2
- package/dist/draft8-session.d.cts +6 -6
- package/dist/draft8-session.d.ts +6 -6
- package/dist/draft8-session.js +1 -1
- package/dist/draft8.cjs +8 -5
- package/dist/draft8.d.cts +14 -12
- package/dist/draft8.d.ts +14 -12
- package/dist/draft8.js +7 -4
- package/dist/draft9-session.cjs +2 -2
- package/dist/draft9-session.d.cts +6 -6
- package/dist/draft9-session.d.ts +6 -6
- package/dist/draft9-session.js +1 -1
- package/dist/draft9.cjs +8 -5
- package/dist/draft9.d.cts +14 -12
- package/dist/draft9.d.ts +14 -12
- package/dist/draft9.js +7 -4
- package/dist/index.cjs +52 -74
- package/dist/index.d.cts +41 -60
- package/dist/index.d.ts +41 -60
- package/dist/index.js +40 -62
- package/dist/{session-types-CJIFbTPd.d.ts → session-types-C7UONex5.d.cts} +28 -27
- package/dist/{session-types-Cbq8IGCP.d.cts → session-types-X-IYEGoG.d.ts} +28 -27
- package/dist/session.cjs +46 -13
- package/dist/session.d.cts +28 -9
- package/dist/session.d.ts +28 -9
- package/dist/session.js +46 -13
- package/dist/{types-DxSFvL2b.d.cts → types--Q7_DcvP.d.cts} +43 -39
- package/dist/{types-DxSFvL2b.d.ts → types--Q7_DcvP.d.ts} +43 -39
- package/dist/{types-B0FT5Qs2.d.ts → types-0IWbU9Z_.d.cts} +36 -36
- package/dist/{types-B0FT5Qs2.d.cts → types-0IWbU9Z_.d.ts} +36 -36
- package/dist/{types-gQsr0AAA.d.cts → types-B3g5G9KP.d.cts} +36 -36
- package/dist/{types-gQsr0AAA.d.ts → types-B3g5G9KP.d.ts} +36 -36
- package/dist/{types-Pme7sua0.d.cts → types-BFpFNM_m.d.cts} +57 -32
- package/dist/{types-Pme7sua0.d.ts → types-BFpFNM_m.d.ts} +57 -32
- package/dist/{types-8gUGeMgs.d.ts → types-Br7fm2mf.d.cts} +48 -26
- package/dist/{types-8gUGeMgs.d.cts → types-Br7fm2mf.d.ts} +48 -26
- package/dist/{types-BeAVNU-F.d.cts → types-C2qKTRR_.d.cts} +50 -45
- package/dist/{types-BeAVNU-F.d.ts → types-C2qKTRR_.d.ts} +50 -45
- package/dist/{types-DKpsfD3i.d.cts → types-DEaypVsD.d.cts} +115 -55
- package/dist/{types-DKpsfD3i.d.ts → types-DEaypVsD.d.ts} +115 -55
- package/dist/types-Dl4IaAHR.d.cts +282 -0
- package/dist/types-Dl4IaAHR.d.ts +282 -0
- package/dist/{types-CDa7F5ct.d.cts → types-DrQpTW1G.d.cts} +58 -50
- package/dist/{types-CDa7F5ct.d.ts → types-DrQpTW1G.d.ts} +58 -50
- package/dist/types-DuIO7cWK.d.cts +25 -0
- package/dist/types-DuIO7cWK.d.ts +25 -0
- package/dist/{types-B9A2g05r.d.cts → types-DuxfOYiO.d.cts} +47 -31
- package/dist/{types-B9A2g05r.d.ts → types-DuxfOYiO.d.ts} +47 -31
- package/dist/{types-D1dI_oTX.d.cts → types-jV1yDDBA.d.cts} +36 -36
- package/dist/{types-D1dI_oTX.d.ts → types-jV1yDDBA.d.ts} +36 -36
- package/package.json +192 -192
- package/src/core/buffer-reader.ts +130 -130
- package/src/core/buffer-writer.ts +100 -100
- package/src/core/errors.ts +1 -1
- package/src/core/hex.ts +21 -21
- package/src/core/session-types.ts +61 -59
- package/src/core/types.ts +18 -361
- package/src/drafts/draft07/codec.ts +1058 -938
- package/src/drafts/draft07/data-streams.ts +240 -240
- package/src/drafts/draft07/index.ts +124 -89
- package/src/drafts/draft07/messages.ts +76 -42
- package/src/drafts/draft07/rules.ts +107 -101
- package/src/drafts/draft07/session-fsm.ts +315 -287
- package/src/drafts/draft07/session.ts +8 -6
- package/src/drafts/draft07/types.ts +406 -72
- package/src/drafts/draft07/varint.ts +51 -51
- package/src/drafts/draft08/codec.ts +985 -953
- package/src/drafts/draft08/data-streams.ts +363 -359
- package/src/drafts/draft08/index.ts +10 -9
- package/src/drafts/draft08/messages.ts +59 -59
- package/src/drafts/draft08/rules.ts +73 -73
- package/src/drafts/draft08/session-fsm.ts +335 -303
- package/src/drafts/draft08/session.ts +6 -7
- package/src/drafts/draft08/types.ts +380 -384
- package/src/drafts/draft09/codec.ts +977 -945
- package/src/drafts/draft09/data-streams.ts +336 -332
- package/src/drafts/draft09/index.ts +10 -9
- package/src/drafts/draft09/messages.ts +59 -59
- package/src/drafts/draft09/rules.ts +73 -73
- package/src/drafts/draft09/session-fsm.ts +335 -303
- package/src/drafts/draft09/session.ts +6 -7
- package/src/drafts/draft09/types.ts +380 -384
- package/src/drafts/draft10/codec.ts +977 -945
- package/src/drafts/draft10/data-streams.ts +336 -332
- package/src/drafts/draft10/index.ts +10 -9
- package/src/drafts/draft10/messages.ts +59 -59
- package/src/drafts/draft10/rules.ts +73 -73
- package/src/drafts/draft10/session-fsm.ts +335 -303
- package/src/drafts/draft10/session.ts +6 -7
- package/src/drafts/draft10/types.ts +380 -384
- package/src/drafts/draft11/codec.ts +1054 -988
- package/src/drafts/draft11/data-streams.ts +316 -269
- package/src/drafts/draft11/index.ts +10 -9
- package/src/drafts/draft11/messages.ts +60 -59
- package/src/drafts/draft11/rules.ts +73 -73
- package/src/drafts/draft11/session-fsm.ts +359 -333
- package/src/drafts/draft11/session.ts +6 -7
- package/src/drafts/draft11/types.ts +385 -381
- package/src/drafts/draft12/codec.ts +1178 -1122
- package/src/drafts/draft12/data-streams.ts +324 -275
- package/src/drafts/draft12/index.ts +10 -9
- package/src/drafts/draft12/messages.ts +67 -66
- package/src/drafts/draft12/rules.ts +79 -79
- package/src/drafts/draft12/session-fsm.ts +384 -358
- package/src/drafts/draft12/session.ts +6 -7
- package/src/drafts/draft12/types.ts +424 -419
- package/src/drafts/draft13/codec.ts +1296 -1206
- package/src/drafts/draft13/data-streams.ts +326 -275
- package/src/drafts/draft13/index.ts +10 -9
- package/src/drafts/draft13/messages.ts +73 -68
- package/src/drafts/draft13/rules.ts +81 -81
- package/src/drafts/draft13/session-fsm.ts +392 -366
- package/src/drafts/draft13/session.ts +6 -7
- package/src/drafts/draft13/types.ts +447 -438
- package/src/drafts/draft14/codec.ts +1347 -1043
- package/src/drafts/draft14/data-streams.ts +831 -813
- package/src/drafts/draft14/index.ts +17 -9
- package/src/drafts/draft14/messages.ts +65 -65
- package/src/drafts/draft14/rules.ts +81 -81
- package/src/drafts/draft14/session-fsm.ts +415 -405
- package/src/drafts/draft14/session.ts +6 -7
- package/src/drafts/draft14/types.ts +451 -381
- package/src/drafts/draft15/codec.ts +1138 -978
- package/src/drafts/draft15/data-streams.ts +842 -794
- package/src/drafts/draft15/index.ts +10 -9
- package/src/drafts/draft15/messages.ts +54 -53
- package/src/drafts/draft15/rules.ts +67 -67
- package/src/drafts/draft15/session-fsm.ts +319 -299
- package/src/drafts/draft15/session.ts +6 -7
- package/src/drafts/draft15/types.ts +357 -339
- package/src/drafts/draft16/codec.ts +1242 -966
- package/src/drafts/draft16/data-streams.ts +835 -789
- package/src/drafts/draft16/index.ts +10 -9
- package/src/drafts/draft16/messages.ts +56 -55
- package/src/drafts/draft16/rules.ts +69 -69
- package/src/drafts/draft16/session-fsm.ts +319 -299
- package/src/drafts/draft16/session.ts +6 -7
- package/src/drafts/draft16/types.ts +386 -357
- package/src/drafts/draft17/codec.ts +1209 -971
- package/src/drafts/draft17/data-streams.ts +969 -758
- package/src/drafts/draft17/index.ts +9 -7
- package/src/drafts/draft17/messages.ts +43 -42
- package/src/drafts/draft17/rules.ts +58 -58
- package/src/drafts/draft17/session-fsm.ts +248 -216
- package/src/drafts/draft17/session.ts +5 -5
- package/src/drafts/draft17/types.ts +337 -313
- package/src/index.ts +85 -274
- package/src/session.ts +62 -23
- package/dist/chunk-FZDIEHQL.cjs +0 -1042
- package/dist/chunk-HDWJ2GDE.js +0 -24
- package/dist/chunk-KNDYS3DK.cjs +0 -24
- package/dist/chunk-N2KBF5Q2.js +0 -1042
- package/dist/types-QNXoxC9Y.d.cts +0 -236
- package/dist/types-QNXoxC9Y.d.ts +0 -236
- package/src/drafts/draft07/announce-fsm.ts +0 -2
- package/src/drafts/draft07/parameters.ts +0 -12
- package/src/drafts/draft07/subscription-fsm.ts +0 -3
|
@@ -6,561 +6,589 @@ import type {
|
|
|
6
6
|
SubscriptionState,
|
|
7
7
|
TransitionResult,
|
|
8
8
|
ValidationResult,
|
|
9
|
-
} from
|
|
10
|
-
import type { MoqtMessage, MoqtMessageType } from "../../core/types.js";
|
|
9
|
+
} from '../../core/session-types.js'
|
|
11
10
|
import {
|
|
12
11
|
CLIENT_ONLY_MESSAGES,
|
|
13
12
|
getLegalIncoming,
|
|
14
13
|
getLegalOutgoing,
|
|
15
14
|
SERVER_ONLY_MESSAGES,
|
|
16
|
-
} from
|
|
15
|
+
} from './rules.js'
|
|
16
|
+
import type { Draft07Message, Draft07MessageType } from './types.js'
|
|
17
17
|
|
|
18
18
|
function violation(
|
|
19
|
-
code: ProtocolViolation[
|
|
19
|
+
code: ProtocolViolation<Draft07MessageType>['code'],
|
|
20
20
|
message: string,
|
|
21
21
|
currentPhase: SessionPhase,
|
|
22
|
-
offendingMessage:
|
|
23
|
-
): ProtocolViolation {
|
|
24
|
-
return { code, message, currentPhase, offendingMessage }
|
|
22
|
+
offendingMessage: Draft07MessageType,
|
|
23
|
+
): ProtocolViolation<Draft07MessageType> {
|
|
24
|
+
return { code, message, currentPhase, offendingMessage }
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
-
export class
|
|
28
|
-
private _phase: SessionPhase =
|
|
29
|
-
private _role:
|
|
30
|
-
private _subscriptions = new Map<bigint, SubscriptionState>()
|
|
31
|
-
private _announces = new Map<string, AnnounceState>()
|
|
27
|
+
export class Draft07SessionFSM {
|
|
28
|
+
private _phase: SessionPhase = 'idle'
|
|
29
|
+
private _role: 'client' | 'server'
|
|
30
|
+
private _subscriptions = new Map<bigint, SubscriptionState>()
|
|
31
|
+
private _announces = new Map<string, AnnounceState>()
|
|
32
32
|
|
|
33
|
-
constructor(role:
|
|
34
|
-
this._role = role
|
|
33
|
+
constructor(role: 'client' | 'server') {
|
|
34
|
+
this._role = role
|
|
35
35
|
}
|
|
36
36
|
|
|
37
37
|
get phase(): SessionPhase {
|
|
38
|
-
return this._phase
|
|
38
|
+
return this._phase
|
|
39
39
|
}
|
|
40
|
-
get role():
|
|
41
|
-
return this._role
|
|
40
|
+
get role(): 'client' | 'server' {
|
|
41
|
+
return this._role
|
|
42
42
|
}
|
|
43
43
|
get subscriptions(): ReadonlyMap<bigint, SubscriptionState> {
|
|
44
|
-
return this._subscriptions
|
|
44
|
+
return this._subscriptions
|
|
45
45
|
}
|
|
46
46
|
get announces(): ReadonlyMap<string, AnnounceState> {
|
|
47
|
-
return this._announces
|
|
47
|
+
return this._announces
|
|
48
48
|
}
|
|
49
49
|
|
|
50
|
-
get legalOutgoing(): ReadonlySet<
|
|
51
|
-
return getLegalOutgoing(this._phase, this._role)
|
|
50
|
+
get legalOutgoing(): ReadonlySet<Draft07MessageType> {
|
|
51
|
+
return getLegalOutgoing(this._phase, this._role)
|
|
52
52
|
}
|
|
53
53
|
|
|
54
|
-
get legalIncoming(): ReadonlySet<
|
|
55
|
-
return getLegalIncoming(this._phase, this._role)
|
|
54
|
+
get legalIncoming(): ReadonlySet<Draft07MessageType> {
|
|
55
|
+
return getLegalIncoming(this._phase, this._role)
|
|
56
56
|
}
|
|
57
57
|
|
|
58
58
|
// Validate role constraints
|
|
59
59
|
private checkRole(
|
|
60
|
-
message:
|
|
61
|
-
direction:
|
|
62
|
-
): ProtocolViolation | null {
|
|
60
|
+
message: Draft07Message,
|
|
61
|
+
direction: 'inbound' | 'outbound',
|
|
62
|
+
): ProtocolViolation<Draft07MessageType> | null {
|
|
63
63
|
const senderRole =
|
|
64
|
-
direction ===
|
|
64
|
+
direction === 'outbound' ? this._role : this._role === 'client' ? 'server' : 'client'
|
|
65
65
|
|
|
66
|
-
if (CLIENT_ONLY_MESSAGES.has(message.type) && senderRole !==
|
|
66
|
+
if (CLIENT_ONLY_MESSAGES.has(message.type) && senderRole !== 'client') {
|
|
67
67
|
return violation(
|
|
68
|
-
|
|
68
|
+
'ROLE_VIOLATION',
|
|
69
69
|
`${message.type} can only be sent by client`,
|
|
70
70
|
this._phase,
|
|
71
71
|
message.type,
|
|
72
|
-
)
|
|
72
|
+
)
|
|
73
73
|
}
|
|
74
|
-
if (SERVER_ONLY_MESSAGES.has(message.type) && senderRole !==
|
|
74
|
+
if (SERVER_ONLY_MESSAGES.has(message.type) && senderRole !== 'server') {
|
|
75
75
|
return violation(
|
|
76
|
-
|
|
76
|
+
'ROLE_VIOLATION',
|
|
77
77
|
`${message.type} can only be sent by server`,
|
|
78
78
|
this._phase,
|
|
79
79
|
message.type,
|
|
80
|
-
)
|
|
80
|
+
)
|
|
81
81
|
}
|
|
82
|
-
return null
|
|
82
|
+
return null
|
|
83
83
|
}
|
|
84
84
|
|
|
85
|
-
validateOutgoing(message:
|
|
86
|
-
const roleViolation = this.checkRole(message,
|
|
87
|
-
if (roleViolation) return { ok: false, violation: roleViolation }
|
|
85
|
+
validateOutgoing(message: Draft07Message): ValidationResult<Draft07MessageType> {
|
|
86
|
+
const roleViolation = this.checkRole(message, 'outbound')
|
|
87
|
+
if (roleViolation) return { ok: false, violation: roleViolation }
|
|
88
88
|
|
|
89
89
|
if (!this.legalOutgoing.has(message.type)) {
|
|
90
90
|
return {
|
|
91
91
|
ok: false,
|
|
92
92
|
violation: violation(
|
|
93
|
-
this._phase ===
|
|
94
|
-
?
|
|
95
|
-
:
|
|
93
|
+
this._phase === 'idle' || this._phase === 'setup'
|
|
94
|
+
? 'MESSAGE_BEFORE_SETUP'
|
|
95
|
+
: 'UNEXPECTED_MESSAGE',
|
|
96
96
|
`Cannot send ${message.type} in phase ${this._phase}`,
|
|
97
97
|
this._phase,
|
|
98
98
|
message.type,
|
|
99
99
|
),
|
|
100
|
-
}
|
|
100
|
+
}
|
|
101
101
|
}
|
|
102
|
-
return { ok: true }
|
|
102
|
+
return { ok: true }
|
|
103
103
|
}
|
|
104
104
|
|
|
105
|
-
receive(message:
|
|
106
|
-
const roleViolation = this.checkRole(message,
|
|
107
|
-
if (roleViolation) return { ok: false, violation: roleViolation }
|
|
105
|
+
receive(message: Draft07Message): TransitionResult<Draft07MessageType> {
|
|
106
|
+
const roleViolation = this.checkRole(message, 'inbound')
|
|
107
|
+
if (roleViolation) return { ok: false, violation: roleViolation }
|
|
108
108
|
|
|
109
|
-
return this.applyTransition(message,
|
|
109
|
+
return this.applyTransition(message, 'inbound')
|
|
110
110
|
}
|
|
111
111
|
|
|
112
|
-
send(message:
|
|
113
|
-
const roleViolation = this.checkRole(message,
|
|
114
|
-
if (roleViolation) return { ok: false, violation: roleViolation }
|
|
112
|
+
send(message: Draft07Message): TransitionResult<Draft07MessageType> {
|
|
113
|
+
const roleViolation = this.checkRole(message, 'outbound')
|
|
114
|
+
if (roleViolation) return { ok: false, violation: roleViolation }
|
|
115
115
|
|
|
116
|
-
return this.applyTransition(message,
|
|
116
|
+
return this.applyTransition(message, 'outbound')
|
|
117
117
|
}
|
|
118
118
|
|
|
119
119
|
private applyTransition(
|
|
120
|
-
message:
|
|
121
|
-
direction:
|
|
122
|
-
): TransitionResult {
|
|
123
|
-
const sideEffects: SideEffect[] = []
|
|
120
|
+
message: Draft07Message,
|
|
121
|
+
direction: 'inbound' | 'outbound',
|
|
122
|
+
): TransitionResult<Draft07MessageType> {
|
|
123
|
+
const sideEffects: SideEffect[] = []
|
|
124
124
|
|
|
125
125
|
switch (message.type) {
|
|
126
|
-
case
|
|
127
|
-
return this.handleClientSetup(message, direction)
|
|
128
|
-
case
|
|
129
|
-
return this.handleServerSetup(message, direction)
|
|
130
|
-
case
|
|
131
|
-
return this.handleGoAway(message, direction, sideEffects)
|
|
126
|
+
case 'client_setup':
|
|
127
|
+
return this.handleClientSetup(message, direction)
|
|
128
|
+
case 'server_setup':
|
|
129
|
+
return this.handleServerSetup(message, direction)
|
|
130
|
+
case 'goaway':
|
|
131
|
+
return this.handleGoAway(message, direction, sideEffects)
|
|
132
132
|
|
|
133
133
|
// Subscription lifecycle
|
|
134
|
-
case
|
|
135
|
-
return this.handleSubscribe(message, direction, sideEffects)
|
|
136
|
-
case
|
|
137
|
-
return this.handleSubscribeOk(message, direction, sideEffects)
|
|
138
|
-
case
|
|
139
|
-
return this.handleSubscribeError(message, direction, sideEffects)
|
|
140
|
-
case
|
|
141
|
-
return this.handleSubscribeDone(message, direction, sideEffects)
|
|
142
|
-
case
|
|
143
|
-
return this.handleUnsubscribe(message, direction, sideEffects)
|
|
134
|
+
case 'subscribe':
|
|
135
|
+
return this.handleSubscribe(message, direction, sideEffects)
|
|
136
|
+
case 'subscribe_ok':
|
|
137
|
+
return this.handleSubscribeOk(message, direction, sideEffects)
|
|
138
|
+
case 'subscribe_error':
|
|
139
|
+
return this.handleSubscribeError(message, direction, sideEffects)
|
|
140
|
+
case 'subscribe_done':
|
|
141
|
+
return this.handleSubscribeDone(message, direction, sideEffects)
|
|
142
|
+
case 'unsubscribe':
|
|
143
|
+
return this.handleUnsubscribe(message, direction, sideEffects)
|
|
144
144
|
|
|
145
145
|
// Announce lifecycle
|
|
146
|
-
case
|
|
147
|
-
return this.handleAnnounce(message, direction, sideEffects)
|
|
148
|
-
case
|
|
149
|
-
return this.handleAnnounceOk(message, direction, sideEffects)
|
|
150
|
-
case
|
|
151
|
-
return this.handleAnnounceError(message, direction, sideEffects)
|
|
152
|
-
case
|
|
153
|
-
return this.handleAnnounceCancel(message, direction, sideEffects)
|
|
154
|
-
case
|
|
155
|
-
return this.handleUnannounce(message, direction, sideEffects)
|
|
146
|
+
case 'announce':
|
|
147
|
+
return this.handleAnnounce(message, direction, sideEffects)
|
|
148
|
+
case 'announce_ok':
|
|
149
|
+
return this.handleAnnounceOk(message, direction, sideEffects)
|
|
150
|
+
case 'announce_error':
|
|
151
|
+
return this.handleAnnounceError(message, direction, sideEffects)
|
|
152
|
+
case 'announce_cancel':
|
|
153
|
+
return this.handleAnnounceCancel(message, direction, sideEffects)
|
|
154
|
+
case 'unannounce':
|
|
155
|
+
return this.handleUnannounce(message, direction, sideEffects)
|
|
156
156
|
|
|
157
157
|
// Fetch lifecycle
|
|
158
|
-
case
|
|
159
|
-
case
|
|
160
|
-
case
|
|
161
|
-
case
|
|
162
|
-
return this.handleReadyPhaseMessage(message)
|
|
158
|
+
case 'fetch':
|
|
159
|
+
case 'fetch_ok':
|
|
160
|
+
case 'fetch_error':
|
|
161
|
+
case 'fetch_cancel':
|
|
162
|
+
return this.handleReadyPhaseMessage(message)
|
|
163
163
|
|
|
164
164
|
// Other ready-phase messages
|
|
165
165
|
default:
|
|
166
|
-
return this.handleReadyPhaseMessage(message)
|
|
166
|
+
return this.handleReadyPhaseMessage(message)
|
|
167
167
|
}
|
|
168
168
|
}
|
|
169
169
|
|
|
170
170
|
private handleClientSetup(
|
|
171
|
-
_message:
|
|
172
|
-
direction:
|
|
173
|
-
): TransitionResult {
|
|
174
|
-
if (this._phase !==
|
|
171
|
+
_message: Draft07Message,
|
|
172
|
+
direction: 'inbound' | 'outbound',
|
|
173
|
+
): TransitionResult<Draft07MessageType> {
|
|
174
|
+
if (this._phase !== 'idle') {
|
|
175
175
|
return {
|
|
176
176
|
ok: false,
|
|
177
177
|
violation: violation(
|
|
178
|
-
|
|
179
|
-
|
|
178
|
+
'SETUP_VIOLATION',
|
|
179
|
+
'CLIENT_SETUP already sent/received',
|
|
180
180
|
this._phase,
|
|
181
|
-
|
|
181
|
+
'client_setup',
|
|
182
182
|
),
|
|
183
|
-
}
|
|
183
|
+
}
|
|
184
184
|
}
|
|
185
185
|
|
|
186
|
-
if (direction ===
|
|
186
|
+
if (direction === 'outbound' && this._role !== 'client') {
|
|
187
187
|
return {
|
|
188
188
|
ok: false,
|
|
189
189
|
violation: violation(
|
|
190
|
-
|
|
191
|
-
|
|
190
|
+
'ROLE_VIOLATION',
|
|
191
|
+
'Only client can send CLIENT_SETUP',
|
|
192
192
|
this._phase,
|
|
193
|
-
|
|
193
|
+
'client_setup',
|
|
194
194
|
),
|
|
195
|
-
}
|
|
195
|
+
}
|
|
196
196
|
}
|
|
197
197
|
|
|
198
|
-
this._phase =
|
|
199
|
-
return { ok: true, phase: this._phase, sideEffects: [] }
|
|
198
|
+
this._phase = 'setup'
|
|
199
|
+
return { ok: true, phase: this._phase, sideEffects: [] }
|
|
200
200
|
}
|
|
201
201
|
|
|
202
202
|
private handleServerSetup(
|
|
203
|
-
_message:
|
|
204
|
-
direction:
|
|
205
|
-
): TransitionResult {
|
|
206
|
-
if (this._phase !==
|
|
203
|
+
_message: Draft07Message,
|
|
204
|
+
direction: 'inbound' | 'outbound',
|
|
205
|
+
): TransitionResult<Draft07MessageType> {
|
|
206
|
+
if (this._phase !== 'setup') {
|
|
207
207
|
return {
|
|
208
208
|
ok: false,
|
|
209
209
|
violation: violation(
|
|
210
|
-
|
|
211
|
-
|
|
210
|
+
'SETUP_VIOLATION',
|
|
211
|
+
'SERVER_SETUP before CLIENT_SETUP',
|
|
212
212
|
this._phase,
|
|
213
|
-
|
|
213
|
+
'server_setup',
|
|
214
214
|
),
|
|
215
|
-
}
|
|
215
|
+
}
|
|
216
216
|
}
|
|
217
217
|
|
|
218
|
-
if (direction ===
|
|
218
|
+
if (direction === 'outbound' && this._role !== 'server') {
|
|
219
219
|
return {
|
|
220
220
|
ok: false,
|
|
221
221
|
violation: violation(
|
|
222
|
-
|
|
223
|
-
|
|
222
|
+
'ROLE_VIOLATION',
|
|
223
|
+
'Only server can send SERVER_SETUP',
|
|
224
224
|
this._phase,
|
|
225
|
-
|
|
225
|
+
'server_setup',
|
|
226
226
|
),
|
|
227
|
-
}
|
|
227
|
+
}
|
|
228
228
|
}
|
|
229
229
|
|
|
230
|
-
this._phase =
|
|
231
|
-
return {
|
|
230
|
+
this._phase = 'ready'
|
|
231
|
+
return {
|
|
232
|
+
ok: true,
|
|
233
|
+
phase: this._phase,
|
|
234
|
+
sideEffects: [{ type: 'session-ready' }],
|
|
235
|
+
}
|
|
232
236
|
}
|
|
233
237
|
|
|
234
238
|
private handleGoAway(
|
|
235
|
-
message:
|
|
236
|
-
_direction:
|
|
239
|
+
message: Draft07Message,
|
|
240
|
+
_direction: 'inbound' | 'outbound',
|
|
237
241
|
sideEffects: SideEffect[],
|
|
238
|
-
): TransitionResult {
|
|
239
|
-
if (this._phase !==
|
|
242
|
+
): TransitionResult<Draft07MessageType> {
|
|
243
|
+
if (this._phase !== 'ready' && this._phase !== 'draining') {
|
|
240
244
|
return {
|
|
241
245
|
ok: false,
|
|
242
246
|
violation: violation(
|
|
243
|
-
|
|
247
|
+
'UNEXPECTED_MESSAGE',
|
|
244
248
|
`GOAWAY not valid in phase ${this._phase}`,
|
|
245
249
|
this._phase,
|
|
246
|
-
|
|
250
|
+
'goaway',
|
|
247
251
|
),
|
|
248
|
-
}
|
|
252
|
+
}
|
|
249
253
|
}
|
|
250
|
-
this._phase =
|
|
251
|
-
const goaway = message as import(
|
|
252
|
-
sideEffects.push({
|
|
253
|
-
|
|
254
|
+
this._phase = 'draining'
|
|
255
|
+
const goaway = message as import('./types.js').GoAway
|
|
256
|
+
sideEffects.push({
|
|
257
|
+
type: 'session-draining',
|
|
258
|
+
goAwayUri: goaway.new_session_uri,
|
|
259
|
+
})
|
|
260
|
+
return { ok: true, phase: this._phase, sideEffects }
|
|
254
261
|
}
|
|
255
262
|
|
|
256
|
-
private requireReady(msgType:
|
|
257
|
-
if (this._phase !==
|
|
263
|
+
private requireReady(msgType: Draft07MessageType): ProtocolViolation<Draft07MessageType> | null {
|
|
264
|
+
if (this._phase !== 'ready' && this._phase !== 'draining') {
|
|
258
265
|
return violation(
|
|
259
|
-
this._phase ===
|
|
260
|
-
?
|
|
261
|
-
:
|
|
266
|
+
this._phase === 'idle' || this._phase === 'setup'
|
|
267
|
+
? 'MESSAGE_BEFORE_SETUP'
|
|
268
|
+
: 'UNEXPECTED_MESSAGE',
|
|
262
269
|
`${msgType} requires ready phase, current: ${this._phase}`,
|
|
263
270
|
this._phase,
|
|
264
271
|
msgType,
|
|
265
|
-
)
|
|
272
|
+
)
|
|
266
273
|
}
|
|
267
|
-
return null
|
|
274
|
+
return null
|
|
268
275
|
}
|
|
269
276
|
|
|
270
277
|
private handleSubscribe(
|
|
271
|
-
message:
|
|
272
|
-
_direction:
|
|
278
|
+
message: Draft07Message,
|
|
279
|
+
_direction: 'inbound' | 'outbound',
|
|
273
280
|
sideEffects: SideEffect[],
|
|
274
|
-
): TransitionResult {
|
|
275
|
-
const err = this.requireReady(message.type)
|
|
276
|
-
if (err) return { ok: false, violation: err }
|
|
281
|
+
): TransitionResult<Draft07MessageType> {
|
|
282
|
+
const err = this.requireReady(message.type)
|
|
283
|
+
if (err) return { ok: false, violation: err }
|
|
277
284
|
|
|
278
|
-
const sub = message as import(
|
|
279
|
-
if (this._subscriptions.has(sub.
|
|
285
|
+
const sub = message as import('./types.js').Subscribe
|
|
286
|
+
if (this._subscriptions.has(sub.subscribe_id)) {
|
|
280
287
|
return {
|
|
281
288
|
ok: false,
|
|
282
289
|
violation: violation(
|
|
283
|
-
|
|
284
|
-
`Subscribe ID ${sub.
|
|
290
|
+
'DUPLICATE_SUBSCRIBE_ID',
|
|
291
|
+
`Subscribe ID ${sub.subscribe_id} already exists`,
|
|
285
292
|
this._phase,
|
|
286
293
|
message.type,
|
|
287
294
|
),
|
|
288
|
-
}
|
|
295
|
+
}
|
|
289
296
|
}
|
|
290
297
|
|
|
291
|
-
this._subscriptions.set(sub.
|
|
292
|
-
subscribeId: sub.
|
|
293
|
-
phase:
|
|
294
|
-
trackNamespace: sub.
|
|
295
|
-
trackName: sub.
|
|
296
|
-
})
|
|
298
|
+
this._subscriptions.set(sub.subscribe_id, {
|
|
299
|
+
subscribeId: sub.subscribe_id,
|
|
300
|
+
phase: 'pending',
|
|
301
|
+
trackNamespace: sub.track_namespace,
|
|
302
|
+
trackName: sub.track_name,
|
|
303
|
+
})
|
|
297
304
|
|
|
298
|
-
return { ok: true, phase: this._phase, sideEffects }
|
|
305
|
+
return { ok: true, phase: this._phase, sideEffects }
|
|
299
306
|
}
|
|
300
307
|
|
|
301
308
|
private handleSubscribeOk(
|
|
302
|
-
message:
|
|
303
|
-
_direction:
|
|
309
|
+
message: Draft07Message,
|
|
310
|
+
_direction: 'inbound' | 'outbound',
|
|
304
311
|
sideEffects: SideEffect[],
|
|
305
|
-
): TransitionResult {
|
|
306
|
-
const err = this.requireReady(message.type)
|
|
307
|
-
if (err) return { ok: false, violation: err }
|
|
312
|
+
): TransitionResult<Draft07MessageType> {
|
|
313
|
+
const err = this.requireReady(message.type)
|
|
314
|
+
if (err) return { ok: false, violation: err }
|
|
308
315
|
|
|
309
|
-
const ok = message as import(
|
|
310
|
-
const existing = this._subscriptions.get(ok.
|
|
316
|
+
const ok = message as import('./types.js').SubscribeOk
|
|
317
|
+
const existing = this._subscriptions.get(ok.subscribe_id)
|
|
311
318
|
if (!existing) {
|
|
312
319
|
return {
|
|
313
320
|
ok: false,
|
|
314
321
|
violation: violation(
|
|
315
|
-
|
|
316
|
-
`No subscription with ID ${ok.
|
|
322
|
+
'UNKNOWN_SUBSCRIBE_ID',
|
|
323
|
+
`No subscription with ID ${ok.subscribe_id}`,
|
|
317
324
|
this._phase,
|
|
318
325
|
message.type,
|
|
319
326
|
),
|
|
320
|
-
}
|
|
327
|
+
}
|
|
321
328
|
}
|
|
322
|
-
if (existing.phase !==
|
|
329
|
+
if (existing.phase !== 'pending') {
|
|
323
330
|
return {
|
|
324
331
|
ok: false,
|
|
325
332
|
violation: violation(
|
|
326
|
-
|
|
327
|
-
`Subscription ${ok.
|
|
333
|
+
'STATE_VIOLATION',
|
|
334
|
+
`Subscription ${ok.subscribe_id} is ${existing.phase}, not pending`,
|
|
328
335
|
this._phase,
|
|
329
336
|
message.type,
|
|
330
337
|
),
|
|
331
|
-
}
|
|
338
|
+
}
|
|
332
339
|
}
|
|
333
340
|
|
|
334
|
-
this._subscriptions.set(ok.
|
|
335
|
-
sideEffects.push({
|
|
336
|
-
|
|
341
|
+
this._subscriptions.set(ok.subscribe_id, { ...existing, phase: 'active' })
|
|
342
|
+
sideEffects.push({
|
|
343
|
+
type: 'subscription-activated',
|
|
344
|
+
subscribeId: ok.subscribe_id,
|
|
345
|
+
})
|
|
346
|
+
return { ok: true, phase: this._phase, sideEffects }
|
|
337
347
|
}
|
|
338
348
|
|
|
339
349
|
private handleSubscribeError(
|
|
340
|
-
message:
|
|
341
|
-
_direction:
|
|
350
|
+
message: Draft07Message,
|
|
351
|
+
_direction: 'inbound' | 'outbound',
|
|
342
352
|
sideEffects: SideEffect[],
|
|
343
|
-
): TransitionResult {
|
|
344
|
-
const err = this.requireReady(message.type)
|
|
345
|
-
if (err) return { ok: false, violation: err }
|
|
353
|
+
): TransitionResult<Draft07MessageType> {
|
|
354
|
+
const err = this.requireReady(message.type)
|
|
355
|
+
if (err) return { ok: false, violation: err }
|
|
346
356
|
|
|
347
|
-
const subErr = message as import(
|
|
348
|
-
const existing = this._subscriptions.get(subErr.
|
|
357
|
+
const subErr = message as import('./types.js').SubscribeError
|
|
358
|
+
const existing = this._subscriptions.get(subErr.subscribe_id)
|
|
349
359
|
if (!existing) {
|
|
350
360
|
return {
|
|
351
361
|
ok: false,
|
|
352
362
|
violation: violation(
|
|
353
|
-
|
|
354
|
-
`No subscription with ID ${subErr.
|
|
363
|
+
'UNKNOWN_SUBSCRIBE_ID',
|
|
364
|
+
`No subscription with ID ${subErr.subscribe_id}`,
|
|
355
365
|
this._phase,
|
|
356
366
|
message.type,
|
|
357
367
|
),
|
|
358
|
-
}
|
|
368
|
+
}
|
|
359
369
|
}
|
|
360
|
-
if (existing.phase !==
|
|
370
|
+
if (existing.phase !== 'pending') {
|
|
361
371
|
return {
|
|
362
372
|
ok: false,
|
|
363
373
|
violation: violation(
|
|
364
|
-
|
|
365
|
-
`Subscription ${subErr.
|
|
374
|
+
'STATE_VIOLATION',
|
|
375
|
+
`Subscription ${subErr.subscribe_id} is ${existing.phase}, not pending`,
|
|
366
376
|
this._phase,
|
|
367
377
|
message.type,
|
|
368
378
|
),
|
|
369
|
-
}
|
|
379
|
+
}
|
|
370
380
|
}
|
|
371
381
|
|
|
372
|
-
this._subscriptions.set(subErr.
|
|
382
|
+
this._subscriptions.set(subErr.subscribe_id, {
|
|
383
|
+
...existing,
|
|
384
|
+
phase: 'error',
|
|
385
|
+
})
|
|
373
386
|
sideEffects.push({
|
|
374
|
-
type:
|
|
375
|
-
subscribeId: subErr.
|
|
376
|
-
reason: subErr.
|
|
377
|
-
})
|
|
378
|
-
return { ok: true, phase: this._phase, sideEffects }
|
|
387
|
+
type: 'subscription-ended',
|
|
388
|
+
subscribeId: subErr.subscribe_id,
|
|
389
|
+
reason: subErr.reason_phrase,
|
|
390
|
+
})
|
|
391
|
+
return { ok: true, phase: this._phase, sideEffects }
|
|
379
392
|
}
|
|
380
393
|
|
|
381
394
|
private handleSubscribeDone(
|
|
382
|
-
message:
|
|
383
|
-
_direction:
|
|
395
|
+
message: Draft07Message,
|
|
396
|
+
_direction: 'inbound' | 'outbound',
|
|
384
397
|
sideEffects: SideEffect[],
|
|
385
|
-
): TransitionResult {
|
|
386
|
-
const err = this.requireReady(message.type)
|
|
387
|
-
if (err) return { ok: false, violation: err }
|
|
398
|
+
): TransitionResult<Draft07MessageType> {
|
|
399
|
+
const err = this.requireReady(message.type)
|
|
400
|
+
if (err) return { ok: false, violation: err }
|
|
388
401
|
|
|
389
|
-
const done = message as import(
|
|
390
|
-
const existing = this._subscriptions.get(done.
|
|
402
|
+
const done = message as import('./types.js').SubscribeDone
|
|
403
|
+
const existing = this._subscriptions.get(done.subscribe_id)
|
|
391
404
|
if (!existing) {
|
|
392
405
|
return {
|
|
393
406
|
ok: false,
|
|
394
407
|
violation: violation(
|
|
395
|
-
|
|
396
|
-
`No subscription with ID ${done.
|
|
408
|
+
'UNKNOWN_SUBSCRIBE_ID',
|
|
409
|
+
`No subscription with ID ${done.subscribe_id}`,
|
|
397
410
|
this._phase,
|
|
398
411
|
message.type,
|
|
399
412
|
),
|
|
400
|
-
}
|
|
413
|
+
}
|
|
401
414
|
}
|
|
402
415
|
|
|
403
|
-
this._subscriptions.set(done.
|
|
416
|
+
this._subscriptions.set(done.subscribe_id, { ...existing, phase: 'done' })
|
|
404
417
|
sideEffects.push({
|
|
405
|
-
type:
|
|
406
|
-
subscribeId: done.
|
|
407
|
-
reason: done.
|
|
408
|
-
})
|
|
409
|
-
return { ok: true, phase: this._phase, sideEffects }
|
|
418
|
+
type: 'subscription-ended',
|
|
419
|
+
subscribeId: done.subscribe_id,
|
|
420
|
+
reason: done.reason_phrase,
|
|
421
|
+
})
|
|
422
|
+
return { ok: true, phase: this._phase, sideEffects }
|
|
410
423
|
}
|
|
411
424
|
|
|
412
425
|
private handleUnsubscribe(
|
|
413
|
-
message:
|
|
414
|
-
_direction:
|
|
426
|
+
message: Draft07Message,
|
|
427
|
+
_direction: 'inbound' | 'outbound',
|
|
415
428
|
sideEffects: SideEffect[],
|
|
416
|
-
): TransitionResult {
|
|
417
|
-
const err = this.requireReady(message.type)
|
|
418
|
-
if (err) return { ok: false, violation: err }
|
|
429
|
+
): TransitionResult<Draft07MessageType> {
|
|
430
|
+
const err = this.requireReady(message.type)
|
|
431
|
+
if (err) return { ok: false, violation: err }
|
|
419
432
|
|
|
420
|
-
const unsub = message as import(
|
|
421
|
-
const existing = this._subscriptions.get(unsub.
|
|
433
|
+
const unsub = message as import('./types.js').Unsubscribe
|
|
434
|
+
const existing = this._subscriptions.get(unsub.subscribe_id)
|
|
422
435
|
if (!existing) {
|
|
423
436
|
return {
|
|
424
437
|
ok: false,
|
|
425
438
|
violation: violation(
|
|
426
|
-
|
|
427
|
-
`No subscription with ID ${unsub.
|
|
439
|
+
'UNKNOWN_SUBSCRIBE_ID',
|
|
440
|
+
`No subscription with ID ${unsub.subscribe_id}`,
|
|
428
441
|
this._phase,
|
|
429
442
|
message.type,
|
|
430
443
|
),
|
|
431
|
-
}
|
|
444
|
+
}
|
|
432
445
|
}
|
|
433
446
|
|
|
434
|
-
this._subscriptions.set(unsub.
|
|
447
|
+
this._subscriptions.set(unsub.subscribe_id, { ...existing, phase: 'done' })
|
|
435
448
|
sideEffects.push({
|
|
436
|
-
type:
|
|
437
|
-
subscribeId: unsub.
|
|
438
|
-
reason:
|
|
439
|
-
})
|
|
440
|
-
return { ok: true, phase: this._phase, sideEffects }
|
|
449
|
+
type: 'subscription-ended',
|
|
450
|
+
subscribeId: unsub.subscribe_id,
|
|
451
|
+
reason: 'unsubscribed',
|
|
452
|
+
})
|
|
453
|
+
return { ok: true, phase: this._phase, sideEffects }
|
|
441
454
|
}
|
|
442
455
|
|
|
443
456
|
// Announce handlers
|
|
444
457
|
private namespaceKey(ns: string[]): string {
|
|
445
|
-
return ns.join(
|
|
458
|
+
return ns.join('/')
|
|
446
459
|
}
|
|
447
460
|
|
|
448
461
|
private handleAnnounce(
|
|
449
|
-
message:
|
|
450
|
-
_direction:
|
|
462
|
+
message: Draft07Message,
|
|
463
|
+
_direction: 'inbound' | 'outbound',
|
|
451
464
|
sideEffects: SideEffect[],
|
|
452
|
-
): TransitionResult {
|
|
453
|
-
const err = this.requireReady(message.type)
|
|
454
|
-
if (err) return { ok: false, violation: err }
|
|
455
|
-
|
|
456
|
-
const ann = message as import(
|
|
457
|
-
const key = this.namespaceKey(ann.
|
|
458
|
-
|
|
459
|
-
this._announces.set(key, {
|
|
460
|
-
|
|
465
|
+
): TransitionResult<Draft07MessageType> {
|
|
466
|
+
const err = this.requireReady(message.type)
|
|
467
|
+
if (err) return { ok: false, violation: err }
|
|
468
|
+
|
|
469
|
+
const ann = message as import('./types.js').Announce
|
|
470
|
+
const key = this.namespaceKey(ann.track_namespace)
|
|
471
|
+
|
|
472
|
+
this._announces.set(key, {
|
|
473
|
+
namespace: ann.track_namespace,
|
|
474
|
+
phase: 'pending',
|
|
475
|
+
})
|
|
476
|
+
return { ok: true, phase: this._phase, sideEffects }
|
|
461
477
|
}
|
|
462
478
|
|
|
463
479
|
private handleAnnounceOk(
|
|
464
|
-
message:
|
|
465
|
-
_direction:
|
|
480
|
+
message: Draft07Message,
|
|
481
|
+
_direction: 'inbound' | 'outbound',
|
|
466
482
|
sideEffects: SideEffect[],
|
|
467
|
-
): TransitionResult {
|
|
468
|
-
const err = this.requireReady(message.type)
|
|
469
|
-
if (err) return { ok: false, violation: err }
|
|
483
|
+
): TransitionResult<Draft07MessageType> {
|
|
484
|
+
const err = this.requireReady(message.type)
|
|
485
|
+
if (err) return { ok: false, violation: err }
|
|
470
486
|
|
|
471
|
-
const ok = message as import(
|
|
472
|
-
const key = this.namespaceKey(ok.
|
|
473
|
-
const existing = this._announces.get(key)
|
|
487
|
+
const ok = message as import('./types.js').AnnounceOk
|
|
488
|
+
const key = this.namespaceKey(ok.track_namespace)
|
|
489
|
+
const existing = this._announces.get(key)
|
|
474
490
|
if (!existing) {
|
|
475
491
|
return {
|
|
476
492
|
ok: false,
|
|
477
493
|
violation: violation(
|
|
478
|
-
|
|
494
|
+
'UNEXPECTED_MESSAGE',
|
|
479
495
|
`No announce for namespace ${key}`,
|
|
480
496
|
this._phase,
|
|
481
497
|
message.type,
|
|
482
498
|
),
|
|
483
|
-
}
|
|
499
|
+
}
|
|
484
500
|
}
|
|
485
501
|
|
|
486
|
-
this._announces.set(key, { ...existing, phase:
|
|
487
|
-
sideEffects.push({
|
|
488
|
-
|
|
502
|
+
this._announces.set(key, { ...existing, phase: 'active' })
|
|
503
|
+
sideEffects.push({
|
|
504
|
+
type: 'announce-activated',
|
|
505
|
+
namespace: ok.track_namespace,
|
|
506
|
+
})
|
|
507
|
+
return { ok: true, phase: this._phase, sideEffects }
|
|
489
508
|
}
|
|
490
509
|
|
|
491
510
|
private handleAnnounceError(
|
|
492
|
-
message:
|
|
493
|
-
_direction:
|
|
511
|
+
message: Draft07Message,
|
|
512
|
+
_direction: 'inbound' | 'outbound',
|
|
494
513
|
sideEffects: SideEffect[],
|
|
495
|
-
): TransitionResult {
|
|
496
|
-
const err = this.requireReady(message.type)
|
|
497
|
-
if (err) return { ok: false, violation: err }
|
|
514
|
+
): TransitionResult<Draft07MessageType> {
|
|
515
|
+
const err = this.requireReady(message.type)
|
|
516
|
+
if (err) return { ok: false, violation: err }
|
|
498
517
|
|
|
499
|
-
const annErr = message as import(
|
|
500
|
-
const key = this.namespaceKey(annErr.
|
|
501
|
-
const existing = this._announces.get(key)
|
|
518
|
+
const annErr = message as import('./types.js').AnnounceError
|
|
519
|
+
const key = this.namespaceKey(annErr.track_namespace)
|
|
520
|
+
const existing = this._announces.get(key)
|
|
502
521
|
if (!existing) {
|
|
503
522
|
return {
|
|
504
523
|
ok: false,
|
|
505
524
|
violation: violation(
|
|
506
|
-
|
|
525
|
+
'UNEXPECTED_MESSAGE',
|
|
507
526
|
`No announce for namespace ${key}`,
|
|
508
527
|
this._phase,
|
|
509
528
|
message.type,
|
|
510
529
|
),
|
|
511
|
-
}
|
|
530
|
+
}
|
|
512
531
|
}
|
|
513
532
|
|
|
514
|
-
this._announces.set(key, { ...existing, phase:
|
|
515
|
-
sideEffects.push({
|
|
516
|
-
|
|
533
|
+
this._announces.set(key, { ...existing, phase: 'error' })
|
|
534
|
+
sideEffects.push({
|
|
535
|
+
type: 'announce-ended',
|
|
536
|
+
namespace: annErr.track_namespace,
|
|
537
|
+
})
|
|
538
|
+
return { ok: true, phase: this._phase, sideEffects }
|
|
517
539
|
}
|
|
518
540
|
|
|
519
541
|
private handleAnnounceCancel(
|
|
520
|
-
message:
|
|
521
|
-
_direction:
|
|
542
|
+
message: Draft07Message,
|
|
543
|
+
_direction: 'inbound' | 'outbound',
|
|
522
544
|
sideEffects: SideEffect[],
|
|
523
|
-
): TransitionResult {
|
|
524
|
-
const err = this.requireReady(message.type)
|
|
525
|
-
if (err) return { ok: false, violation: err }
|
|
545
|
+
): TransitionResult<Draft07MessageType> {
|
|
546
|
+
const err = this.requireReady(message.type)
|
|
547
|
+
if (err) return { ok: false, violation: err }
|
|
526
548
|
|
|
527
|
-
const cancel = message as import(
|
|
528
|
-
const key = this.namespaceKey(cancel.
|
|
529
|
-
const existing = this._announces.get(key)
|
|
549
|
+
const cancel = message as import('./types.js').AnnounceCancel
|
|
550
|
+
const key = this.namespaceKey(cancel.track_namespace)
|
|
551
|
+
const existing = this._announces.get(key)
|
|
530
552
|
if (existing) {
|
|
531
|
-
this._announces.delete(key)
|
|
532
|
-
sideEffects.push({
|
|
553
|
+
this._announces.delete(key)
|
|
554
|
+
sideEffects.push({
|
|
555
|
+
type: 'announce-ended',
|
|
556
|
+
namespace: cancel.track_namespace,
|
|
557
|
+
})
|
|
533
558
|
}
|
|
534
|
-
return { ok: true, phase: this._phase, sideEffects }
|
|
559
|
+
return { ok: true, phase: this._phase, sideEffects }
|
|
535
560
|
}
|
|
536
561
|
|
|
537
562
|
private handleUnannounce(
|
|
538
|
-
message:
|
|
539
|
-
_direction:
|
|
563
|
+
message: Draft07Message,
|
|
564
|
+
_direction: 'inbound' | 'outbound',
|
|
540
565
|
sideEffects: SideEffect[],
|
|
541
|
-
): TransitionResult {
|
|
542
|
-
const err = this.requireReady(message.type)
|
|
543
|
-
if (err) return { ok: false, violation: err }
|
|
566
|
+
): TransitionResult<Draft07MessageType> {
|
|
567
|
+
const err = this.requireReady(message.type)
|
|
568
|
+
if (err) return { ok: false, violation: err }
|
|
544
569
|
|
|
545
|
-
const unann = message as import(
|
|
546
|
-
const key = this.namespaceKey(unann.
|
|
547
|
-
const existing = this._announces.get(key)
|
|
570
|
+
const unann = message as import('./types.js').Unannounce
|
|
571
|
+
const key = this.namespaceKey(unann.track_namespace)
|
|
572
|
+
const existing = this._announces.get(key)
|
|
548
573
|
if (existing) {
|
|
549
|
-
this._announces.delete(key)
|
|
550
|
-
sideEffects.push({
|
|
574
|
+
this._announces.delete(key)
|
|
575
|
+
sideEffects.push({
|
|
576
|
+
type: 'announce-ended',
|
|
577
|
+
namespace: unann.track_namespace,
|
|
578
|
+
})
|
|
551
579
|
}
|
|
552
|
-
return { ok: true, phase: this._phase, sideEffects }
|
|
580
|
+
return { ok: true, phase: this._phase, sideEffects }
|
|
553
581
|
}
|
|
554
582
|
|
|
555
|
-
private handleReadyPhaseMessage(message:
|
|
556
|
-
const err = this.requireReady(message.type)
|
|
557
|
-
if (err) return { ok: false, violation: err }
|
|
558
|
-
return { ok: true, phase: this._phase, sideEffects: [] }
|
|
583
|
+
private handleReadyPhaseMessage(message: Draft07Message): TransitionResult<Draft07MessageType> {
|
|
584
|
+
const err = this.requireReady(message.type)
|
|
585
|
+
if (err) return { ok: false, violation: err }
|
|
586
|
+
return { ok: true, phase: this._phase, sideEffects: [] }
|
|
559
587
|
}
|
|
560
588
|
|
|
561
589
|
reset(): void {
|
|
562
|
-
this._phase =
|
|
563
|
-
this._subscriptions.clear()
|
|
564
|
-
this._announces.clear()
|
|
590
|
+
this._phase = 'idle'
|
|
591
|
+
this._subscriptions.clear()
|
|
592
|
+
this._announces.clear()
|
|
565
593
|
}
|
|
566
594
|
}
|