@fails-components/webtransport 1.6.7 → 1.6.9

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.
@@ -5,18 +5,6 @@ import { PriorityScheduler } from './priorityscheduler.js'
5
5
  const pid = typeof process !== 'undefined' ? process.pid : 0
6
6
  const log = logger(`webtransport:parserbase(${pid})`)
7
7
 
8
- /**
9
- * @param{Number|bigint} int
10
- * @returns {Number}
11
- */
12
- export function lengthVarInt(int) {
13
- if (BigInt(int) < 64n) return 1
14
- if (BigInt(int) < 16384n) return 2
15
- if (BigInt(int) < 1073741824n) return 4
16
- /* if (BigInt(int) < 4611686018427387904 ) */
17
- return 8
18
- }
19
-
20
8
  export class ParserBase {
21
9
  static PADDING = 0x190b4d38
22
10
  static WT_RESET_STREAM = 0x190b4d39
@@ -66,7 +54,7 @@ export class ParserBase {
66
54
 
67
55
  /**
68
56
  * @abstract
69
- * @param {Buffer|Uint8Array} data
57
+ * @param {Uint8Array[]} data
70
58
  */
71
59
  // eslint-disable-next-line no-unused-vars
72
60
  parseData(data) {
@@ -282,10 +270,17 @@ export class ParserBase {
282
270
  * @param {{code: number, reason: string}} opts
283
271
  */
284
272
  onCloseWebTransportSession({ code, reason }) {
285
- this.session.jsobj.onClose({
286
- errorcode: code,
287
- error: reason
288
- })
273
+ if (
274
+ !(
275
+ this.session.jsobj.state === 'failed' ||
276
+ this.session.jsobj.state === 'closed'
277
+ )
278
+ ) {
279
+ this.session.jsobj.onClose({
280
+ errorcode: code,
281
+ error: reason
282
+ })
283
+ }
289
284
  this.closeHttp2Stream(code) // is this necessary
290
285
  }
291
286
 
@@ -4,68 +4,6 @@ import { ParserBase } from './parserbase.js'
4
4
  * @typedef {import('node:http2').Http2Stream} Http2Stream
5
5
  */
6
6
 
7
- /**
8
- * @param{{offset: Number, buffer: Buffer, size: Number}} bs
9
- */
10
-
11
- export function readUint32(bs) {
12
- if (bs.offset + 4 > bs.size) return undefined
13
- const toret = bs.buffer.readUInt32BE(bs.offset)
14
- bs.offset += 4
15
- return toret
16
- }
17
-
18
- /**
19
- * @param{{offset: Number, buffer: Buffer, size: Number}} bs
20
- */
21
- export function readVarInt(bs) {
22
- if (bs.offset + 1 > bs.size) return undefined
23
- let val = BigInt(bs.buffer.readUInt8(bs.offset))
24
- bs.offset++
25
- const prefix = Number(val) >>> 6
26
- const intlength = 1 << prefix
27
-
28
- if (bs.offset + intlength - 1 > bs.size) {
29
- return undefined
30
- }
31
- val = val & 0x3fn
32
- for (let i = 0; i < intlength - 1; i++) {
33
- val = (val << 8n) | BigInt(bs.buffer.readUInt8(bs.offset))
34
- bs.offset++
35
- }
36
- return val
37
- }
38
-
39
- /**
40
- * @param{{offset: Number, buffer: Buffer, size: Number}} bs
41
- * @param{Number|bigint} int
42
- */
43
- export function writeVarInt(bs, int) {
44
- let numbytes = 8n
45
- let msb = 0xc0n
46
- const bint = BigInt(int)
47
- if (bint < 64) {
48
- numbytes = 1n
49
- msb = 0x0n
50
- } else if (bint < 16384) {
51
- numbytes = 2n
52
- msb = 0x40n
53
- } else if (bint < 1073741824) {
54
- numbytes = 4n
55
- msb = 0x80n
56
- }
57
- bs.buffer.writeUInt8(
58
- Number(msb | ((bint >> ((numbytes - 1n) * 8n)) & 0xffn)),
59
- bs.offset
60
- )
61
- bs.offset++
62
-
63
- for (let i = numbytes - 2n; i >= 0; i--) {
64
- bs.buffer.writeUInt8(Number((bint >> (i * 8n)) & 0xffn), bs.offset)
65
- bs.offset++
66
- }
67
- }
68
-
69
7
  export class ParserBaseHttp2 extends ParserBase {
70
8
  /**
71
9
  * @param {import('../types').ParserHttp2Init} stream
@@ -96,7 +34,7 @@ export class ParserBaseHttp2 extends ParserBase {
96
34
  this.stream.on('readable', () => {
97
35
  let data
98
36
  while ((data = this.stream.read()) !== null) {
99
- this.parseData(data)
37
+ this.parseData([data])
100
38
  }
101
39
  })
102
40
 
@@ -110,10 +48,17 @@ export class ParserBaseHttp2 extends ParserBase {
110
48
  * @param {Error} error
111
49
  */ (error) => {
112
50
  // readable error
113
- this.session.jsobj.onClose({
114
- errorcode: this.stream.rstCode,
115
- error: error.toString()
116
- })
51
+ if (
52
+ !(
53
+ this.session.jsobj.state === 'failed' ||
54
+ this.session.jsobj.state === 'closed'
55
+ )
56
+ ) {
57
+ this.session.jsobj.onClose({
58
+ errorcode: this.stream.rstCode,
59
+ error: error.toString()
60
+ })
61
+ }
117
62
  }
118
63
  )
119
64
 
@@ -92,17 +92,26 @@ export class Http2WebTransportStream {
92
92
 
93
93
  /**
94
94
  * @param {Object} obj
95
- * @param {Uint8Array|undefined} obj.data
95
+ * @param {Uint8Array[]|undefined} obj.data
96
96
  * @param {Boolean} obj.fin
97
97
  */
98
98
  recvData({ data, fin }) {
99
- this.incomdata.push({ data, fin })
100
- if (data && data?.byteLength > 0) {
101
- const checkstream = this.flowController.updateHighestReceivedOffset(
102
- data?.byteLength
103
- )
99
+ let datasize = 0
100
+ if (data) {
101
+ const newincomdata = data.map((el, ind, array) => ({
102
+ data: el,
103
+ fin: fin && ind + 1 === array.length
104
+ }))
105
+ datasize = data.reduce((acc, curVal) => acc + curVal.byteLength, 0)
106
+ this.incomdata.push(...newincomdata)
107
+ } else if (fin) {
108
+ this.incomdata.push({ data: undefined, fin })
109
+ }
110
+ if (datasize > 0) {
111
+ const checkstream =
112
+ this.flowController.updateHighestReceivedOffset(datasize)
104
113
  const checksession =
105
- this.sessionFlowController.updateHighestReceivedOffset(data?.byteLength)
114
+ this.sessionFlowController.updateHighestReceivedOffset(datasize)
106
115
  if (checksession && checkstream) {
107
116
  // As the highest received offset has changed, check to see if this is a
108
117
  // violation of flow control.
package/lib/session.js CHANGED
@@ -388,39 +388,41 @@ export class HttpWTSession {
388
388
  }
389
389
 
390
390
  /**
391
- * @param {WebTransportSendStream} stream
392
- * @param {WritableStreamDefaultController} controller
391
+ * @param {HttpWTStream} streamobj
393
392
  */
394
- addSendStream(stream, controller) {
395
- this.sendStreams.add(stream)
396
- this.sendStreamsController.add(controller)
393
+ addSendStream(streamobj) {
394
+ this.sendStreams.add(streamobj.writable)
395
+ this.sendStreamsController.add(streamobj.writableController)
397
396
  }
398
397
 
399
398
  /**
400
- * @param {WebTransportSendStream} stream
401
- * @param {WritableStreamDefaultController} controller
399
+ * @param {HttpWTStream} streamobj
402
400
  */
403
- removeSendStream(stream, controller) {
404
- this.sendStreams.delete(stream)
405
- this.sendStreamsController.delete(controller)
401
+ removeSendStream(streamobj) {
402
+ this.sendStreams.delete(streamobj.writable)
403
+ this.sendStreamsController.delete(streamobj.writableController)
404
+ if (!streamobj.readable || !this.receiveStreams.has(streamobj.readable)) {
405
+ this.streamObjs.delete(streamobj)
406
+ }
406
407
  }
407
408
 
408
409
  /**
409
- * @param {WebTransportReceiveStream } stream
410
- * @param {ReadableStreamDefaultController} controller
410
+ * @param {HttpWTStream} streamobj
411
411
  */
412
- addReceiveStream(stream, controller) {
413
- this.receiveStreams.add(stream)
414
- this.receiveStreamsController.add(controller)
412
+ addReceiveStream(streamobj) {
413
+ this.receiveStreams.add(streamobj.readable)
414
+ this.receiveStreamsController.add(streamobj.readableController)
415
415
  }
416
416
 
417
417
  /**
418
- * @param {WebTransportReceiveStream } stream
419
- * @param {ReadableStreamDefaultController} controller
418
+ * @param {HttpWTStream} streamobj
420
419
  */
421
- removeReceiveStream(stream, controller) {
422
- this.receiveStreams.delete(stream)
423
- this.receiveStreamsController.delete(controller)
420
+ removeReceiveStream(streamobj) {
421
+ this.receiveStreams.delete(streamobj.readable)
422
+ this.receiveStreamsController.delete(streamobj.readableController)
423
+ if (!streamobj.writable || !this.sendStreams.has(streamobj.writable)) {
424
+ this.streamObjs.delete(streamobj)
425
+ }
424
426
  }
425
427
 
426
428
  /**
package/lib/stream.js CHANGED
@@ -102,10 +102,7 @@ export class HttpWTStream {
102
102
  else code = reason.code
103
103
  }
104
104
  this.readableclosed = true
105
- this.parentobj.removeReceiveStream(
106
- this.readable,
107
- this.readableController
108
- )
105
+ this.parentobj.removeReceiveStream(this)
109
106
  this.objint.stopSending(code)
110
107
  return promise
111
108
  },
@@ -129,8 +126,7 @@ export class HttpWTStream {
129
126
  bytesRead: 0n
130
127
  })
131
128
  }
132
- // @ts-ignore
133
- this.parentobj.addReceiveStream(this.readable, this.readableController)
129
+ this.parentobj.addReceiveStream(this)
134
130
  }
135
131
  if (this.bidirectional || !this.incoming) {
136
132
  /** @type {WebTransportSendStream} */
@@ -173,10 +169,7 @@ export class HttpWTStream {
173
169
  }
174
170
  this.writableclosed = true
175
171
  this.objint.streamFinal()
176
- this.parentobj.removeSendStream(
177
- this.writable,
178
- this.writableController
179
- )
172
+ this.parentobj.removeSendStream(this)
180
173
  // eslint-disable-next-line no-unused-vars
181
174
  this.pendingoperation = new Promise((resolve, reject) => {
182
175
  this.pendingres = resolve
@@ -197,10 +190,7 @@ export class HttpWTStream {
197
190
  else if (reason.code > 255) code = 255
198
191
  else code = reason.code
199
192
  }
200
- this.parentobj.removeSendStream(
201
- this.writable,
202
- this.writableController
203
- )
193
+ this.parentobj.removeSendStream(this)
204
194
  /** @type {Promise<void>} */
205
195
  // eslint-disable-next-line no-unused-vars
206
196
  const promise = new Promise((resolve, reject) => {
@@ -250,8 +240,7 @@ export class HttpWTStream {
250
240
  }
251
241
  }
252
242
  })
253
- // @ts-ignore
254
- this.parentobj.addSendStream(this.writable, this.writableController)
243
+ this.parentobj.addSendStream(this)
255
244
  }
256
245
 
257
246
  /** @type {(() => void) | null} */
@@ -321,10 +310,7 @@ export class HttpWTStream {
321
310
  if (parentstate === 'closed' || parentstate === 'failed') {
322
311
  log('no parent cleanup for fin as parent was closed or failed')
323
312
  } else {
324
- this.parentobj.removeReceiveStream(
325
- this.readable,
326
- this.readableController
327
- )
313
+ this.parentobj.removeReceiveStream(this)
328
314
  }
329
315
  if (!this.readableclosed) {
330
316
  this.readableController.close()
@@ -361,11 +347,7 @@ export class HttpWTStream {
361
347
  case 'resetStream':
362
348
  if (this.readable) {
363
349
  this.finalDrain()
364
- if (parentcleanup)
365
- this.parentobj.removeReceiveStream(
366
- this.readable,
367
- this.readableController
368
- )
350
+ if (parentcleanup) this.parentobj.removeReceiveStream(this)
369
351
  if (!this.readableclosed) {
370
352
  this.readableclosed = true
371
353
  this.readableController.error(
@@ -379,11 +361,7 @@ export class HttpWTStream {
379
361
 
380
362
  case 'stopSending':
381
363
  if (this.writable) {
382
- if (parentcleanup)
383
- this.parentobj.removeSendStream(
384
- this.writable,
385
- this.writableController
386
- )
364
+ if (parentcleanup) this.parentobj.removeSendStream(this)
387
365
  if (!this.writableclosed) {
388
366
  this.writableclosed = true
389
367
  this.writableController.error(
@@ -457,16 +435,8 @@ export class HttpWTStream {
457
435
  const res = this.abortres
458
436
  this.abortres = null
459
437
  res()
460
- if (this.readable)
461
- this.parentobj.removeReceiveStream(
462
- this.readable,
463
- this.readableController
464
- )
465
- if (this.writable)
466
- this.parentobj.removeSendStream(
467
- this.writable,
468
- this.writableController
469
- )
438
+ if (this.readable) this.parentobj.removeReceiveStream(this)
439
+ if (this.writable) this.parentobj.removeSendStream(this)
470
440
  this.readableclosed = true
471
441
  this.parentobj.removeStreamObj(this)
472
442
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fails-components/webtransport",
3
- "version": "1.6.7",
3
+ "version": "1.6.9",
4
4
  "description": "A component to add webtransport support (server and client) to node.js using libquiche",
5
5
  "exports": {
6
6
  ".": {