@fails-components/webtransport 0.0.9 → 0.1.0-macarmbuild.6

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 (90) hide show
  1. package/CMakeLists.txt +110 -73
  2. package/build.js +32 -8
  3. package/dist/lib/client.d.ts +74 -0
  4. package/dist/lib/client.d.ts.map +1 -0
  5. package/dist/lib/dom.d.ts +70 -0
  6. package/dist/lib/dom.d.ts.map +1 -0
  7. package/dist/lib/event-loop.d.ts +26 -0
  8. package/dist/lib/event-loop.d.ts.map +1 -0
  9. package/dist/lib/index.d.ts +79 -0
  10. package/dist/lib/index.d.ts.map +1 -0
  11. package/dist/lib/native.d.ts +2 -0
  12. package/dist/lib/native.d.ts.map +1 -0
  13. package/dist/lib/server.d.ts +75 -0
  14. package/dist/lib/server.d.ts.map +1 -0
  15. package/dist/lib/session.d.ts +221 -0
  16. package/dist/lib/session.d.ts.map +1 -0
  17. package/dist/lib/stream.d.ts +116 -0
  18. package/dist/lib/stream.d.ts.map +1 -0
  19. package/dist/lib/transport.d.ts +25 -0
  20. package/dist/lib/transport.d.ts.map +1 -0
  21. package/dist/lib/types.d.ts +157 -0
  22. package/dist/lib/types.d.ts.map +1 -0
  23. package/dist/lib/utils.d.ts +6 -0
  24. package/dist/lib/utils.d.ts.map +1 -0
  25. package/dist/lib/webtransport.d.ts +35 -0
  26. package/dist/lib/webtransport.d.ts.map +1 -0
  27. package/dist/test/bidirectional-streams.spec.d.ts +5 -0
  28. package/dist/test/bidirectional-streams.spec.d.ts.map +1 -0
  29. package/dist/test/datagrams.spec.d.ts +5 -0
  30. package/dist/test/datagrams.spec.d.ts.map +1 -0
  31. package/dist/test/echoclient.d.ts +2 -0
  32. package/dist/test/echoclient.d.ts.map +1 -0
  33. package/dist/test/echoserver.d.ts +2 -0
  34. package/dist/test/echoserver.d.ts.map +1 -0
  35. package/dist/test/event-loop.spec.d.ts +2 -0
  36. package/dist/test/event-loop.spec.d.ts.map +1 -0
  37. package/dist/test/fixtures/certificate.d.ts +21 -0
  38. package/dist/test/fixtures/certificate.d.ts.map +1 -0
  39. package/dist/test/fixtures/chai.d.ts +2 -0
  40. package/dist/test/fixtures/chai.d.ts.map +1 -0
  41. package/dist/test/fixtures/read-stream.d.ts +10 -0
  42. package/dist/test/fixtures/read-stream.d.ts.map +1 -0
  43. package/dist/test/fixtures/reader-value.d.ts +7 -0
  44. package/dist/test/fixtures/reader-value.d.ts.map +1 -0
  45. package/dist/test/fixtures/server.d.ts +10 -0
  46. package/dist/test/fixtures/server.d.ts.map +1 -0
  47. package/dist/test/fixtures/write-stream.d.ts +10 -0
  48. package/dist/test/fixtures/write-stream.d.ts.map +1 -0
  49. package/dist/test/test.d.ts +2 -0
  50. package/dist/test/test.d.ts.map +1 -0
  51. package/dist/test/testsuite.d.ts +25 -0
  52. package/dist/test/testsuite.d.ts.map +1 -0
  53. package/dist/test/unidirectional-streams.spec.d.ts +5 -0
  54. package/dist/test/unidirectional-streams.spec.d.ts.map +1 -0
  55. package/lib/client.js +163 -0
  56. package/lib/dom.ts +95 -0
  57. package/lib/event-loop.js +79 -0
  58. package/lib/index.js +33 -0
  59. package/lib/native.js +25 -0
  60. package/lib/server.js +165 -0
  61. package/lib/session.js +422 -0
  62. package/lib/stream.js +325 -0
  63. package/lib/transport.js +42 -0
  64. package/lib/types.ts +181 -0
  65. package/lib/utils.js +22 -0
  66. package/lib/webtransport.js +114 -0
  67. package/package.json +18 -6
  68. package/readme.md +28 -5
  69. package/src/http3client.h +0 -1
  70. package/src/http3eventloop.cc +52 -0
  71. package/src/http3eventloop.h +22 -1
  72. package/src/http3server.cc +4 -1
  73. package/src/http3server.h +8 -0
  74. package/src/http3serversession.h +1 -1
  75. package/test/bidirectional-streams.spec.js +138 -0
  76. package/test/datagrams.spec.js +132 -0
  77. package/test/echoclient.js +10 -6
  78. package/test/echoserver.js +6 -8
  79. package/test/event-loop.spec.js +24 -0
  80. package/test/{certificate.js → fixtures/certificate.js} +31 -15
  81. package/test/fixtures/chai.js +6 -0
  82. package/test/fixtures/read-stream.js +36 -0
  83. package/test/fixtures/reader-value.js +24 -0
  84. package/test/fixtures/server.js +58 -0
  85. package/test/fixtures/write-stream.js +17 -0
  86. package/test/test.js +29 -3
  87. package/test/testsuite.js +22 -0
  88. package/test/unidirectional-streams.spec.js +128 -0
  89. package/tsconfig.json +40 -0
  90. package/src/webtransport.js +0 -870
package/lib/server.js ADDED
@@ -0,0 +1,165 @@
1
+ import { Http3WebTransport } from './transport.js'
2
+ import { ReadableStream } from 'node:stream/web'
3
+ import { Http3WTSession } from './session.js'
4
+ import { isIPv4 } from 'net'
5
+ // @ts-ignore
6
+ import { defer } from './utils.js'
7
+
8
+ /**
9
+ * @typedef {import('./types').WebTransportSession} WebTransportSession
10
+ * @typedef {import('./types').NativeHttp3WTSession} NativeHttp3WTSession
11
+ * @typedef {import('./types').Http3ServerEventHandler} Http3ServerEventHandler
12
+ * @typedef {import('./types').Http3WTServerSessionVisitorEvent} Http3WTServerSessionVisitorEvent
13
+ * @typedef {import('./types').ServerStatusEvent} ServerStatusEvent
14
+ * @typedef {import('./types').Http3ServerInit} Http3ServerInit
15
+ */
16
+
17
+ /**
18
+ * @implements {Http3ServerEventHandler}
19
+ */
20
+ export class Http3Server extends Http3WebTransport {
21
+ /**
22
+ *
23
+ * @param {Http3ServerInit} args
24
+ */
25
+ constructor(args) {
26
+ super(args, 'server')
27
+
28
+ /** @type {Record<string, ReadableStream>} */
29
+ this.sessionStreams = {}
30
+
31
+ /** @type {Record<string, ReadableStreamController<any>>} */
32
+ this.sessionController = {}
33
+
34
+ this.port = null
35
+ this.host = null
36
+
37
+ this._ready = defer()
38
+ this.ready = this._ready.promise
39
+
40
+ this._closed = defer()
41
+ this.closed = this._closed.promise
42
+ }
43
+
44
+ startServer() {
45
+ this.transportInt.startServer()
46
+ }
47
+
48
+ stopServer() {
49
+ this.transportInt.stopServer()
50
+ for (const i in this.sessionController) {
51
+ this.sessionController[i].close() // inform the controller, that we are closing
52
+ delete this.sessionController[i]
53
+ }
54
+ this.stopped = true
55
+ }
56
+
57
+ /**
58
+ * @returns {{ port: number, host: string, family: 'IPv4' | 'IPv6' } | null}
59
+ */
60
+ address() {
61
+ if (this.port == null || this.host == null) {
62
+ console.info('returning null')
63
+ return null
64
+ }
65
+
66
+ return {
67
+ port: this.port,
68
+ host: this.host,
69
+ family: isIPv4(this.host) ? 'IPv4' : 'IPv6'
70
+ }
71
+ }
72
+
73
+ /**
74
+ * @param {string} path
75
+ * @returns {ReadableStream<WebTransportSession>}
76
+ */
77
+ sessionStream(path) {
78
+ if (path in this.sessionStreams) {
79
+ return this.sessionStreams[path]
80
+ }
81
+ this.sessionStreams[path] = new ReadableStream({
82
+ start: async (controller) => {
83
+ this.sessionController[path] = controller
84
+ }
85
+ })
86
+ this.transportInt.addPath(path)
87
+ return this.sessionStreams[path]
88
+ }
89
+
90
+ /**
91
+ * @param {Http3WTServerSessionVisitorEvent} args
92
+ */
93
+ onHttp3WTSessionVisitor(args) {
94
+ // create Http3 Visitor
95
+ if (args.object) {
96
+ const sesobj = new Http3WTSession({
97
+ object: args.session,
98
+ parentobj: this
99
+ })
100
+ if (this.sessionController[args.path])
101
+ this.sessionController[args.path].enqueue(sesobj)
102
+ } else throw new Error('Http3WTSessionVisitor')
103
+ }
104
+
105
+ /**
106
+ */
107
+ onServerError() {
108
+ this._ready.reject()
109
+ }
110
+
111
+ /**
112
+ */
113
+ onServerListening() {
114
+ this._ready.resolve()
115
+ }
116
+
117
+ /**
118
+ */
119
+ onServerClose() {
120
+ this._closed.resolve()
121
+ }
122
+
123
+ /**
124
+ * @param {ServerStatusEvent} evt
125
+ */
126
+ onServerStatus(evt) {
127
+ if (evt.host) this.host = evt.host
128
+ if (evt.port) this.port = evt.port
129
+
130
+ switch (evt.status) {
131
+ case 'close':
132
+ this.onServerClose()
133
+ break
134
+ case 'listening':
135
+ this.onServerListening()
136
+ break
137
+ case 'error':
138
+ this.onServerListening()
139
+ break
140
+ default: {
141
+ throw new Error('unknown status')
142
+ }
143
+ }
144
+ }
145
+
146
+ /**
147
+ * @param {Http3WTServerSessionVisitorEvent | ServerStatusEvent} args
148
+ */
149
+ customCallback(args) {
150
+ // console.log('incoming callback server', args)
151
+ if (args.purpose) {
152
+ switch (args.purpose) {
153
+ case 'Http3WTSessionVisitor':
154
+ this.onHttp3WTSessionVisitor(args)
155
+ break
156
+ case 'ServerStatus':
157
+ this.onServerStatus(args)
158
+ break
159
+ default: {
160
+ throw new Error('unknown purpose')
161
+ }
162
+ }
163
+ }
164
+ }
165
+ }
package/lib/session.js ADDED
@@ -0,0 +1,422 @@
1
+ import { ReadableStream, WritableStream } from 'node:stream/web'
2
+ import { Http3WTStream } from './stream.js'
3
+
4
+ /**
5
+ * WebTransport session events
6
+ * @typedef {import('./types').WebTransportSessionEventHandler} WebTransportSessionEventHandler
7
+ * @typedef {import('./types').SessionReadyEvent} SessionReadyEvent
8
+ * @typedef {import('./types').SessionCloseEvent} SessionCloseEvent
9
+ * @typedef {import('./types').DatagramReceivedEvent} DatagramReceivedEvent
10
+ * @typedef {import('./types').DatagramSendEvent} DatagramSendEvent
11
+ * @typedef {import('./types').NewStreamEvent} NewStreamEvent
12
+ *
13
+ * @typedef {import('./dom').WebTransportCloseInfo} WebTransportCloseInfo
14
+ * @typedef {import('./dom').WebTransportBidirectionalStream} WebTransportBidirectionalStream
15
+ * @typedef {import('./dom').WebTransportSendStream} WebTransportSendStream
16
+ * @typedef {import('./dom').WebTransportDatagramDuplexStream} WebTransportDatagramDuplexStream
17
+ *
18
+ * @typedef {import('./types').NativeHttp3WTSession} NativeHttp3WTSession
19
+ *
20
+ * Public API
21
+ * @typedef {import('./types').WebTransportSession} WebTransportSession
22
+ *
23
+ * @typedef {import('./server').Http3Server} Http3Server
24
+ * @typedef {import('./client').Http3Client} Http3Client
25
+ *
26
+ * @typedef {import('stream/web').WritableStreamDefaultController} WritableStreamDefaultController
27
+ */
28
+
29
+ /**
30
+ * @implements {WebTransportSessionEventHandler}
31
+ * @implements {WebTransportSession}
32
+ */
33
+ export class Http3WTSession {
34
+ /**
35
+ * @param {object} args
36
+ * @param {import('./types').NativeHttp3WTSession} [args.object]
37
+ * @param {Http3Server | Http3Client} args.parentobj
38
+ */
39
+ constructor(args) {
40
+ if (args.object) {
41
+ this.objint = args.object
42
+ this.objint.jsobj = this
43
+ }
44
+ this.parentobj = args.parentobj
45
+ /** @type {import('./types').WebTransportSessionState} */
46
+ this.state = 'connected'
47
+
48
+ /** @type {((value?: any) => void) | null | undefined} */
49
+ this.readyResolve = null
50
+ /** @type {(() => void) | null | undefined} */
51
+ this.closeHook = null
52
+
53
+ /** @type {Promise<void>} */
54
+ this.ready = new Promise((resolve, reject) => {
55
+ this.readyResolve = resolve
56
+ this.readyReject = reject
57
+ })
58
+ /** @type {Promise<WebTransportCloseInfo>} */
59
+ this.closed = new Promise((resolve, reject) => {
60
+ this.closedResolve = resolve
61
+ this.closedReject = reject
62
+ })
63
+
64
+ this.incomingBidirectionalStreams = new ReadableStream({
65
+ start: (controller) => {
66
+ this.incomBiDiController = controller
67
+ }
68
+ })
69
+
70
+ this.incomingUnidirectionalStreams = new ReadableStream({
71
+ start: (controller) => {
72
+ this.incomUniDiController = controller
73
+ }
74
+ })
75
+
76
+ /** @type {Array<() => void>} */
77
+ this.writeDatagramRes = []
78
+ /** @type {Array<() => void>} */
79
+ this.writeDatagramRej = []
80
+ /** @type {Array<Promise<void>>} */
81
+ this.writeDatagramProm = []
82
+
83
+ /** @type {WebTransportDatagramDuplexStream} */
84
+ this.datagrams = {
85
+ readable: new ReadableStream({
86
+ start: (controller) => {
87
+ this.incomDatagramController = controller
88
+ }
89
+ }),
90
+ writable: new WritableStream({
91
+ start: (controller) => {
92
+ this.outgoDatagramController = controller
93
+ },
94
+ write: (chunk, controller) => {
95
+ if (this.state === 'closed') throw new Error('Session is closed')
96
+ if (chunk instanceof Uint8Array) {
97
+ /** @type {Promise<void>} */
98
+ const ret = new Promise((resolve, reject) => {
99
+ this.writeDatagramRes.push(resolve)
100
+ this.writeDatagramRej.push(reject)
101
+ })
102
+ this.writeDatagramProm.push(ret)
103
+ // console.log('b4 datagram write', chunk, Date.now())
104
+ if (this.objint == null) {
105
+ throw new Error('this.objint is not set')
106
+ }
107
+ this.objint.writeDatagram(chunk)
108
+ return ret
109
+ } else throw new Error('chunk is not of type Uint8Array')
110
+ },
111
+ close: () => {
112
+ // do nothing
113
+ }
114
+ })
115
+ }
116
+
117
+ /** @type {Array<(stream: WebTransportBidirectionalStream) => void>} */
118
+ this.resolveBiDi = []
119
+ /** @type {Array<(stream: WebTransportSendStream) => void>} */
120
+ this.resolveUniDi = []
121
+ /** @type {Array<(err?: Error) => void>} */
122
+ this.rejectBiDi = []
123
+ /** @type {Array<(err?: Error) => void>} */
124
+ this.rejectUniDi = []
125
+
126
+ this.sendStreams = new Set()
127
+ this.receiveStreams = new Set()
128
+ /** @type {Set<Http3WTStream>} */
129
+ this.streamObjs = new Set()
130
+
131
+ /** @type {Set<WritableStreamDefaultController>} */
132
+ this.sendStreamsController = new Set()
133
+ /** @type {Set<ReadableStreamDefaultController>} */
134
+ this.receiveStreamsController = new Set()
135
+ }
136
+
137
+ /**
138
+ * @param {NativeHttp3WTSession} object
139
+ */
140
+ setSessionObj(object) {
141
+ if (object) {
142
+ this.objint = object
143
+ this.objint.jsobj = this
144
+ }
145
+ }
146
+
147
+ async waitForDatagramsSend() {
148
+ while (this.writeDatagramProm.length > 0) {
149
+ try {
150
+ await Promise.allSettled(this.writeDatagramProm)
151
+ } catch (error) {
152
+ console.log('datagram promise failed ', error)
153
+ }
154
+ }
155
+ }
156
+
157
+ /**
158
+ * @param {Http3WTStream} stream
159
+ */
160
+ addStreamObj(stream) {
161
+ this.streamObjs.add(stream)
162
+ }
163
+
164
+ /**
165
+ * @param {Http3WTStream} stream
166
+ */
167
+ removeStreamObj(stream) {
168
+ this.streamObjs.delete(stream)
169
+ }
170
+
171
+ /**
172
+ * @param {WritableStream} stream
173
+ * @param {WritableStreamDefaultController} controller
174
+ */
175
+ addSendStream(stream, controller) {
176
+ this.sendStreams.add(stream)
177
+ this.sendStreamsController.add(controller)
178
+ }
179
+
180
+ /**
181
+ * @param {WritableStream} stream
182
+ * @param {WritableStreamDefaultController} controller
183
+ */
184
+ removeSendStream(stream, controller) {
185
+ this.sendStreams.delete(stream)
186
+ this.sendStreamsController.delete(controller)
187
+ }
188
+
189
+ /**
190
+ * @param {ReadableStream} stream
191
+ * @param {ReadableStreamDefaultController} controller
192
+ */
193
+ addReceiveStream(stream, controller) {
194
+ this.receiveStreams.add(stream)
195
+ this.receiveStreamsController.add(controller)
196
+ }
197
+
198
+ /**
199
+ * @param {ReadableStream} stream
200
+ * @param {ReadableStreamDefaultController} controller
201
+ */
202
+ removeReceiveStream(stream, controller) {
203
+ this.receiveStreams.delete(stream)
204
+ this.receiveStreamsController.delete(controller)
205
+ }
206
+
207
+ /**
208
+ * @returns {Promise<WebTransportBidirectionalStream>}
209
+ */
210
+ createBidirectionalStream() {
211
+ if (this.objint == null) {
212
+ throw new Error('this.objint not set')
213
+ }
214
+ /** @type {Promise<WebTransportBidirectionalStream>} */
215
+ const prom = new Promise((resolve, reject) => {
216
+ this.resolveBiDi.push(resolve)
217
+ this.rejectBiDi.push(reject)
218
+ })
219
+ this.objint.orderBidiStream()
220
+ return prom
221
+ }
222
+
223
+ /**
224
+ *@returns {Promise<WebTransportSendStream>}
225
+ */
226
+ createUnidirectionalStream() {
227
+ if (this.objint == null) {
228
+ throw new Error('this.objint not set')
229
+ }
230
+ /** @type {Promise<WebTransportSendStream>} */
231
+ const prom = new Promise((resolve, reject) => {
232
+ this.resolveUniDi.push(resolve)
233
+ this.rejectUniDi.push(reject)
234
+ })
235
+ this.objint.orderUnidiStream()
236
+ return prom
237
+ }
238
+
239
+ /**
240
+ * @param {object} [closeInfo]
241
+ * @param {number} closeInfo.closeCode
242
+ * @param {string} closeInfo.reason
243
+ * @returns {void}
244
+ */
245
+ close(closeInfo) {
246
+ // console.log('closeinfo', closeInfo)
247
+ if (this.state === 'closed' || this.state === 'failed') return
248
+ if (this.objint) {
249
+ this.objint.close({
250
+ code: closeInfo?.closeCode ?? 0,
251
+ reason: closeInfo?.reason.substring(0, 1023) ?? ''
252
+ })
253
+ }
254
+ }
255
+
256
+ onReady(/* error */) {
257
+ if (this.readyResolve) this.readyResolve()
258
+ delete this.readyResolve
259
+ }
260
+
261
+ /**
262
+ * @param {SessionCloseEvent} args
263
+ */
264
+ onClose(args) {
265
+ delete this.objint // not valid any more
266
+ // console.log('onClose')
267
+ for (const rej of this.rejectBiDi) rej()
268
+ for (const rej of this.rejectUniDi) rej()
269
+ for (const rej of this.writeDatagramRej) rej()
270
+ this.writeDatagramRej = []
271
+ this.writeDatagramRes = []
272
+ this.writeDatagramProm = []
273
+ this.resolveBiDi = []
274
+ this.resolveUniDi = []
275
+ this.rejectBiDi = []
276
+ this.rejectUniDi = []
277
+
278
+ this.incomBiDiController.close()
279
+ this.incomUniDiController.close()
280
+ this.incomDatagramController.close()
281
+ // this.outgoDatagramController.error(errorcode)
282
+ this.state = 'closed'
283
+
284
+ this.sendStreamsController.forEach((ele) => ele.error(args.errorcode))
285
+ this.receiveStreamsController.forEach((ele) => ele.error(args.errorcode))
286
+ this.streamObjs.forEach((ele) => (ele.readableclosed = true))
287
+
288
+ this.sendStreams.clear()
289
+ this.receiveStreams.clear()
290
+ this.sendStreamsController.clear()
291
+ this.receiveStreamsController.clear()
292
+ this.streamObjs.clear()
293
+
294
+ if (this.closedResolve)
295
+ this.closedResolve({ closeCode: args.errorcode, reason: 'closed' })
296
+ if (this.closeHook) {
297
+ this.closeHook()
298
+ delete this.closeHook
299
+ }
300
+ }
301
+
302
+ /**
303
+ * @param {NewStreamEvent} args
304
+ */
305
+ onStream(args) {
306
+ const strobj = new Http3WTStream({
307
+ object: args.stream,
308
+ parentobj: this,
309
+ transport: this.parentobj,
310
+ bidirectional: args.bidirectional,
311
+ incoming: args.incoming
312
+ })
313
+ this.addStreamObj(strobj)
314
+ if (args.incoming) {
315
+ if (args.bidirectional) {
316
+ this.incomBiDiController.enqueue(strobj)
317
+ } else {
318
+ this.incomUniDiController.enqueue(strobj.readable)
319
+ }
320
+ } else {
321
+ if (args.bidirectional) {
322
+ if (this.resolveBiDi.length === 0)
323
+ throw new Error('Got bidirectional stream without asking for it')
324
+ this.rejectBiDi.shift()
325
+ const curres = this.resolveBiDi.shift()
326
+
327
+ if (
328
+ curres != null &&
329
+ strobj.readable != null &&
330
+ strobj.writable != null
331
+ ) {
332
+ curres({
333
+ readable: strobj.readable,
334
+ writable: strobj.writable
335
+ })
336
+ }
337
+ } else {
338
+ if (this.resolveUniDi.length === 0)
339
+ throw new Error('Got unidirectional stream without asking for it')
340
+ this.rejectUniDi.shift()
341
+ const curres = this.resolveUniDi.shift()
342
+
343
+ if (curres != null && strobj.writable != null) {
344
+ /** @type {WebTransportSendStream} */
345
+ // @ts-expect-error `getStats` property is missing from WritableStream
346
+ // we add it on the next line
347
+ const sendStream = strobj.writable
348
+ sendStream.getStats = () => {
349
+ return Promise.resolve({
350
+ timestamp: 0,
351
+ bytesWritten: 0n,
352
+ bytesSent: 0n,
353
+ bytesAcknowledged: 0n
354
+ })
355
+ }
356
+
357
+ curres(sendStream)
358
+ }
359
+ }
360
+ }
361
+ }
362
+
363
+ /**
364
+ * @param {DatagramReceivedEvent} args
365
+ */
366
+ onDatagramReceived(args) {
367
+ // console.log('datagram received', args.datagram, Date.now())
368
+ this.incomDatagramController.enqueue(args.datagram)
369
+ }
370
+
371
+ /**
372
+ * @param {DatagramSendEvent} args
373
+ */
374
+ onDatagramSend(args) {
375
+ if (this.state === 'closed') return
376
+ this.writeDatagramRej.shift()
377
+ this.writeDatagramProm.shift()
378
+ const res = this.writeDatagramRes.shift()
379
+
380
+ if (res != null) {
381
+ res()
382
+ }
383
+ }
384
+
385
+ /**
386
+ * @param {SessionReadyEvent | SessionCloseEvent | DatagramReceivedEvent | DatagramSendEvent | NewStreamEvent} args
387
+ */
388
+ static callback(args) {
389
+ // console.log('Session callback called', args)
390
+ if (!args || !args.object || !args.object.jsobj)
391
+ throw new Error('Session callback without jsobj')
392
+ const visitor = args.object.jsobj
393
+ if (args.purpose) {
394
+ switch (args.purpose) {
395
+ case 'SessionReady':
396
+ visitor.onReady(args)
397
+ break
398
+ case 'SessionClose':
399
+ visitor.onClose(args)
400
+ break
401
+ case 'DatagramReceived':
402
+ if (visitor && Object.prototype.hasOwnProperty.call(args, 'datagram'))
403
+ visitor.onDatagramReceived(args)
404
+ break
405
+ case 'DatagramSend':
406
+ if (visitor) visitor.onDatagramSend(args)
407
+ break
408
+ case 'Http3WTStreamVisitor':
409
+ if (
410
+ visitor &&
411
+ Object.prototype.hasOwnProperty.call(args, 'bidirectional') &&
412
+ Object.prototype.hasOwnProperty.call(args, 'incoming')
413
+ ) {
414
+ visitor.onStream(args)
415
+ } else throw new Error('Malformed Http3WTStreamVisitor')
416
+ break
417
+ default:
418
+ throw new Error('unknown purpose Sessioncb')
419
+ }
420
+ } else throw new Error('no purpose Sessioncb')
421
+ }
422
+ }