@fails-components/webtransport 1.0.9 → 1.0.11
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/dist/lib/http2/browser/browser.d.ts.map +1 -1
- package/dist/lib/http2/browser/browserparser.d.ts +4 -3
- package/dist/lib/http2/browser/browserparser.d.ts.map +1 -1
- package/dist/lib/http2/node/capsuleparser.d.ts +3 -2
- package/dist/lib/http2/node/capsuleparser.d.ts.map +1 -1
- package/dist/lib/http2/node/client.d.ts.map +1 -1
- package/dist/lib/http2/node/server.d.ts.map +1 -1
- package/dist/lib/http2/node/websocketparser.d.ts +7 -6
- package/dist/lib/http2/node/websocketparser.d.ts.map +1 -1
- package/dist/lib/http2/parserbase.d.ts +16 -4
- package/dist/lib/http2/parserbase.d.ts.map +1 -1
- package/dist/lib/http2/parserbasehttp2.d.ts +9 -1
- package/dist/lib/http2/parserbasehttp2.d.ts.map +1 -1
- package/dist/lib/http2/session.d.ts.map +1 -1
- package/dist/lib/index.node.d.ts +1 -1
- package/dist/lib/index.node.d.ts.map +1 -1
- package/dist/lib/index.types.d.ts +60 -0
- package/dist/lib/index.types.d.ts.map +1 -0
- package/dist/lib/types.d.ts +9 -2
- package/dist/lib/types.d.ts.map +1 -1
- package/dist/lib/webtransport.node.d.ts +1 -0
- package/dist/lib/webtransport.node.d.ts.map +1 -1
- package/lib/http2/browser/browser.js +2 -1
- package/lib/http2/browser/browserparser.js +43 -7
- package/lib/http2/node/capsuleparser.js +41 -10
- package/lib/http2/node/client.js +23 -5
- package/lib/http2/node/server.js +53 -16
- package/lib/http2/node/websocketparser.js +42 -20
- package/lib/http2/parserbase.js +44 -7
- package/lib/http2/parserbasehttp2.js +15 -2
- package/lib/http2/session.js +1 -5
- package/lib/index.browser.js +1 -0
- package/lib/index.node.js +2 -1
- package/lib/index.types.js +33 -0
- package/lib/types.ts +10 -2
- package/lib/webtransport.node.js +10 -1
- package/lib/webtransportbase.js +1 -1
- package/old_test/test.js +13 -1
- package/package.json +4 -3
- package/readme.md +4 -1
- package/test/bidirectional-streams.spec.js +31 -0
- package/test/datagrams.spec.js +12 -0
- package/test/fixtures/quiche.browser.js +2 -0
- package/test/fixtures/quiche.js +1 -0
- package/test/fixtures/server.js +24 -0
- package/test/session.spec.js +13 -3
- package/test/stream-limits.spec.js +12 -0
- package/test/unidirectional-streams.spec.js +12 -0
package/lib/http2/node/client.js
CHANGED
|
@@ -91,7 +91,8 @@ export class Http2WebTransportClient {
|
|
|
91
91
|
0x2b63: this.initialStreamFlowControlWindow, // SETTINGS_WEBTRANSPORT_INITIAL_MAX_STREAM_DATA_BIDI
|
|
92
92
|
0x2b64: this.initialUnidirectionalStreams, // SETTINGS_WEBTRANSPORT_INITIAL_MAX_STREAMS_UNI
|
|
93
93
|
0x2b65: this.initialBidirectionalStreams // SETTINGS_WEBTRANSPORT_INITIAL_MAX_STREAMS_BIDI
|
|
94
|
-
}
|
|
94
|
+
},
|
|
95
|
+
remoteCustomSettings: [0x2b60, 0x2b61, 0x2b62, 0x2b63, 0x2b64, 0x2b65]
|
|
95
96
|
},
|
|
96
97
|
localPort: this.localPort,
|
|
97
98
|
// TODO: REMOVE BEFORE RELEASE; UNSAFE SETTING
|
|
@@ -210,6 +211,14 @@ export class Http2WebTransportClient {
|
|
|
210
211
|
authority: this.hostname,
|
|
211
212
|
origin: this.hostname
|
|
212
213
|
})
|
|
214
|
+
const {
|
|
215
|
+
0x2b65: remoteBidirectionalStreams = undefined,
|
|
216
|
+
0x2b64: remoteUnidirectionalStreams = undefined,
|
|
217
|
+
0x2b63: remoteBidirectionalStreamFlowControlWindow = undefined,
|
|
218
|
+
0x2b62: remoteUnidirectionalStreamFlowControlWindow = undefined,
|
|
219
|
+
0x2b61: remoteSessionFlowControlWindow = undefined
|
|
220
|
+
// @ts-ignore
|
|
221
|
+
} = this.clientInt.remoteSettings?.customSettings || {}
|
|
213
222
|
|
|
214
223
|
const retObj = {
|
|
215
224
|
header: stream.sentHeaders,
|
|
@@ -221,18 +230,27 @@ export class Http2WebTransportClient {
|
|
|
221
230
|
stream,
|
|
222
231
|
nativesession,
|
|
223
232
|
isclient: true,
|
|
224
|
-
|
|
233
|
+
initialStreamSendWindowOffsetBidi:
|
|
234
|
+
remoteBidirectionalStreamFlowControlWindow ||
|
|
235
|
+
this.initialStreamFlowControlWindow,
|
|
236
|
+
initialStreamSendWindowOffsetUnidi:
|
|
237
|
+
remoteUnidirectionalStreamFlowControlWindow ||
|
|
238
|
+
this.initialStreamFlowControlWindow,
|
|
225
239
|
initialStreamReceiveWindowOffset:
|
|
226
240
|
this.initialStreamFlowControlWindow,
|
|
227
241
|
streamShouldAutoTuneReceiveWindow:
|
|
228
242
|
this.streamShouldAutoTuneReceiveWindow,
|
|
229
243
|
streamReceiveWindowSizeLimit: this.streamFlowControlWindowSizeLimit
|
|
230
244
|
}),
|
|
231
|
-
initialBidirectionalSendStreams:
|
|
245
|
+
initialBidirectionalSendStreams:
|
|
246
|
+
remoteBidirectionalStreams || this.initialBidirectionalStreams,
|
|
232
247
|
initialBidirectionalReceiveStreams: this.initialBidirectionalStreams,
|
|
233
|
-
initialUnidirectionalSendStreams:
|
|
248
|
+
initialUnidirectionalSendStreams:
|
|
249
|
+
remoteUnidirectionalStreams || this.initialUnidirectionalStreams,
|
|
234
250
|
initialUnidirectionalReceiveStreams: this.initialUnidirectionalStreams,
|
|
235
|
-
sendWindowOffset:
|
|
251
|
+
sendWindowOffset:
|
|
252
|
+
remoteSessionFlowControlWindow ||
|
|
253
|
+
this.sessionFlowControlWindowSizeLimit,
|
|
236
254
|
receiveWindowOffset: this.sessionFlowControlWindowSizeLimit,
|
|
237
255
|
shouldAutoTuneReceiveWindow: this.sessionShouldAutoTuneReceiveWindow,
|
|
238
256
|
receiveWindowSizeLimit: this.sessionFlowControlWindowSizeLimit
|
package/lib/http2/node/server.js
CHANGED
|
@@ -65,7 +65,8 @@ export class Http2WebTransportServer {
|
|
|
65
65
|
0x2b63: this.initialStreamFlowControlWindow, // SETTINGS_WEBTRANSPORT_INITIAL_MAX_STREAM_DATA_BIDI
|
|
66
66
|
0x2b64: this.initialUnidirectionalStreams, // SETTINGS_WEBTRANSPORT_INITIAL_MAX_STREAMS_UNI
|
|
67
67
|
0x2b65: this.initialBidirectionalStreams // SETTINGS_WEBTRANSPORT_INITIAL_MAX_STREAMS_BIDI
|
|
68
|
-
}
|
|
68
|
+
},
|
|
69
|
+
remoteCustomSettings: [0x2b60, 0x2b61, 0x2b62, 0x2b63, 0x2b64, 0x2b65]
|
|
69
70
|
}
|
|
70
71
|
})
|
|
71
72
|
|
|
@@ -153,7 +154,8 @@ export class Http2WebTransportServer {
|
|
|
153
154
|
stream,
|
|
154
155
|
nativesession,
|
|
155
156
|
isclient: false,
|
|
156
|
-
|
|
157
|
+
initialStreamSendWindowOffsetBidi: 0,
|
|
158
|
+
initialStreamSendWindowOffsetUnidi: 0,
|
|
157
159
|
initialStreamReceiveWindowOffset:
|
|
158
160
|
this.initialStreamFlowControlWindow,
|
|
159
161
|
streamShouldAutoTuneReceiveWindow:
|
|
@@ -244,6 +246,14 @@ export class Http2WebTransportServer {
|
|
|
244
246
|
path = path?.slice(1)
|
|
245
247
|
}
|
|
246
248
|
if (this.paths[path]) {
|
|
249
|
+
const {
|
|
250
|
+
0x2b65: remoteBidirectionalStreams = undefined,
|
|
251
|
+
0x2b64: remoteUnidirectionalStreams = undefined,
|
|
252
|
+
0x2b63: remoteBidirectionalStreamFlowControlWindow = undefined,
|
|
253
|
+
0x2b62: remoteUnidirectionalStreamFlowControlWindow = undefined,
|
|
254
|
+
0x2b61: remoteSessionFlowControlWindow = undefined
|
|
255
|
+
// @ts-ignore
|
|
256
|
+
} = stream?.session?.remoteSettings?.customSettings || {}
|
|
247
257
|
const retObj = {
|
|
248
258
|
session: new Http2WebTransportSession({
|
|
249
259
|
stream,
|
|
@@ -256,8 +266,12 @@ export class Http2WebTransportServer {
|
|
|
256
266
|
stream,
|
|
257
267
|
nativesession,
|
|
258
268
|
isclient: false,
|
|
259
|
-
|
|
260
|
-
|
|
269
|
+
initialStreamSendWindowOffsetBidi:
|
|
270
|
+
remoteBidirectionalStreamFlowControlWindow ||
|
|
271
|
+
this.initialStreamFlowControlWindow,
|
|
272
|
+
initialStreamSendWindowOffsetUnidi:
|
|
273
|
+
remoteUnidirectionalStreamFlowControlWindow ||
|
|
274
|
+
this.initialStreamFlowControlWindow,
|
|
261
275
|
initialStreamReceiveWindowOffset:
|
|
262
276
|
this.initialStreamFlowControlWindow,
|
|
263
277
|
streamShouldAutoTuneReceiveWindow:
|
|
@@ -270,7 +284,8 @@ export class Http2WebTransportServer {
|
|
|
270
284
|
stream,
|
|
271
285
|
nativesession,
|
|
272
286
|
isclient: false,
|
|
273
|
-
|
|
287
|
+
initialStreamSendWindowOffsetBidi: 0,
|
|
288
|
+
initialStreamSendWindowOffsetUnidi: 0,
|
|
274
289
|
initialStreamReceiveWindowOffset:
|
|
275
290
|
this.initialStreamFlowControlWindow,
|
|
276
291
|
streamShouldAutoTuneReceiveWindow:
|
|
@@ -280,18 +295,20 @@ export class Http2WebTransportServer {
|
|
|
280
295
|
}))
|
|
281
296
|
}
|
|
282
297
|
},
|
|
283
|
-
initialBidirectionalSendStreams: websocketProt
|
|
298
|
+
initialBidirectionalSendStreams: websocketProt
|
|
284
299
|
? 0
|
|
285
|
-
: this.initialBidirectionalStreams,
|
|
300
|
+
: remoteBidirectionalStreams || this.initialBidirectionalStreams,
|
|
286
301
|
initialBidirectionalReceiveStreams:
|
|
287
302
|
this.initialBidirectionalStreams,
|
|
288
303
|
initialUnidirectionalSendStreams: websocketProt
|
|
289
304
|
? 0
|
|
290
|
-
:
|
|
305
|
+
: remoteUnidirectionalStreams ||
|
|
306
|
+
this.initialUnidirectionalStreams,
|
|
291
307
|
initialUnidirectionalReceiveStreams:
|
|
292
308
|
this.initialUnidirectionalStreams,
|
|
293
309
|
sendWindowOffset: !websocketProt
|
|
294
|
-
?
|
|
310
|
+
? remoteSessionFlowControlWindow ||
|
|
311
|
+
this.sessionFlowControlWindowSizeLimit
|
|
295
312
|
: 0, // TODO, once supported by node, use initial settings
|
|
296
313
|
receiveWindowOffset: this.sessionFlowControlWindowSizeLimit,
|
|
297
314
|
shouldAutoTuneReceiveWindow:
|
|
@@ -443,7 +460,8 @@ export class Http2WebTransportServer {
|
|
|
443
460
|
stream,
|
|
444
461
|
nativesession,
|
|
445
462
|
isclient: false,
|
|
446
|
-
|
|
463
|
+
initialStreamSendWindowOffsetBidi: 0,
|
|
464
|
+
initialStreamSendWindowOffsetUnidi: 0,
|
|
447
465
|
initialStreamReceiveWindowOffset:
|
|
448
466
|
this.initialStreamFlowControlWindow,
|
|
449
467
|
streamShouldAutoTuneReceiveWindow:
|
|
@@ -476,6 +494,14 @@ export class Http2WebTransportServer {
|
|
|
476
494
|
log('sendHttp1Headers error', error)
|
|
477
495
|
})
|
|
478
496
|
} else {
|
|
497
|
+
const {
|
|
498
|
+
0x2b65: remoteBidirectionalStreams = undefined,
|
|
499
|
+
0x2b64: remoteUnidirectionalStreams = undefined,
|
|
500
|
+
0x2b63: remoteBidirectionalStreamFlowControlWindow = undefined,
|
|
501
|
+
0x2b62: remoteUnidirectionalStreamFlowControlWindow = undefined,
|
|
502
|
+
0x2b61: remoteSessionFlowControlWindow = undefined
|
|
503
|
+
// @ts-ignore
|
|
504
|
+
} = stream?.session?.remoteSettings?.customSettings || {}
|
|
479
505
|
const retObj = {
|
|
480
506
|
session: new Http2WebTransportSession({
|
|
481
507
|
stream,
|
|
@@ -488,8 +514,12 @@ export class Http2WebTransportServer {
|
|
|
488
514
|
stream,
|
|
489
515
|
nativesession,
|
|
490
516
|
isclient: false,
|
|
491
|
-
|
|
492
|
-
|
|
517
|
+
initialStreamSendWindowOffsetBidi:
|
|
518
|
+
remoteBidirectionalStreamFlowControlWindow ||
|
|
519
|
+
this.initialStreamFlowControlWindow,
|
|
520
|
+
initialStreamSendWindowOffsetUnidi:
|
|
521
|
+
remoteUnidirectionalStreamFlowControlWindow ||
|
|
522
|
+
this.initialStreamFlowControlWindow,
|
|
493
523
|
initialStreamReceiveWindowOffset:
|
|
494
524
|
this.initialStreamFlowControlWindow,
|
|
495
525
|
streamShouldAutoTuneReceiveWindow:
|
|
@@ -502,7 +532,8 @@ export class Http2WebTransportServer {
|
|
|
502
532
|
stream,
|
|
503
533
|
nativesession,
|
|
504
534
|
isclient: false,
|
|
505
|
-
|
|
535
|
+
initialStreamSendWindowOffsetBidi: 0,
|
|
536
|
+
initialStreamSendWindowOffsetUnidi: 0,
|
|
506
537
|
initialStreamReceiveWindowOffset:
|
|
507
538
|
this.initialStreamFlowControlWindow,
|
|
508
539
|
streamShouldAutoTuneReceiveWindow:
|
|
@@ -513,16 +544,22 @@ export class Http2WebTransportServer {
|
|
|
513
544
|
}
|
|
514
545
|
},
|
|
515
546
|
initialBidirectionalSendStreams:
|
|
516
|
-
protocol !== 'websocket'
|
|
547
|
+
protocol !== 'websocket'
|
|
548
|
+
? remoteBidirectionalStreams || this.initialBidirectionalStreams
|
|
549
|
+
: 0, // TODO, once supported by node, use initial settings
|
|
517
550
|
initialBidirectionalReceiveStreams:
|
|
518
551
|
this.initialBidirectionalStreams,
|
|
519
552
|
initialUnidirectionalSendStreams:
|
|
520
|
-
protocol !== 'websocket'
|
|
553
|
+
protocol !== 'websocket'
|
|
554
|
+
? remoteUnidirectionalStreams ||
|
|
555
|
+
this.initialUnidirectionalStreams
|
|
556
|
+
: 0, // TODO, once supported by node, use initial settings
|
|
521
557
|
initialUnidirectionalReceiveStreams:
|
|
522
558
|
this.initialUnidirectionalStreams,
|
|
523
559
|
sendWindowOffset:
|
|
524
560
|
protocol !== 'websocket'
|
|
525
|
-
?
|
|
561
|
+
? remoteSessionFlowControlWindow ||
|
|
562
|
+
this.sessionFlowControlWindowSizeLimit
|
|
526
563
|
: 0, // TODO, once supported by node, use initial settings
|
|
527
564
|
receiveWindowOffset: this.sessionFlowControlWindowSizeLimit,
|
|
528
565
|
shouldAutoTuneReceiveWindow:
|
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
import { randomBytes } from 'node:crypto'
|
|
2
2
|
import { ParserBase, lengthVarInt } from '../parserbase.js'
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
ParserBaseHttp2,
|
|
5
|
+
readVarInt,
|
|
6
|
+
writeVarInt,
|
|
7
|
+
readUint32
|
|
8
|
+
} from '../parserbasehttp2.js'
|
|
4
9
|
import { logger } from '../../utils.js'
|
|
5
10
|
|
|
6
11
|
const log = logger(`webtransport:http2:node:websocketparser(${process?.pid})`)
|
|
@@ -174,7 +179,8 @@ export class WebSocketParser extends ParserBaseHttp2 {
|
|
|
174
179
|
stream,
|
|
175
180
|
nativesession,
|
|
176
181
|
isclient,
|
|
177
|
-
|
|
182
|
+
initialStreamSendWindowOffsetUnidi,
|
|
183
|
+
initialStreamSendWindowOffsetBidi,
|
|
178
184
|
initialStreamReceiveWindowOffset,
|
|
179
185
|
streamShouldAutoTuneReceiveWindow,
|
|
180
186
|
streamReceiveWindowSizeLimit
|
|
@@ -183,7 +189,8 @@ export class WebSocketParser extends ParserBaseHttp2 {
|
|
|
183
189
|
stream,
|
|
184
190
|
nativesession,
|
|
185
191
|
isclient,
|
|
186
|
-
|
|
192
|
+
initialStreamSendWindowOffsetUnidi,
|
|
193
|
+
initialStreamSendWindowOffsetBidi,
|
|
187
194
|
initialStreamReceiveWindowOffset,
|
|
188
195
|
streamShouldAutoTuneReceiveWindow,
|
|
189
196
|
streamReceiveWindowSizeLimit
|
|
@@ -598,6 +605,23 @@ export class WebSocketParser extends ParserBaseHttp2 {
|
|
|
598
605
|
case ParserBase.WT_STREAMS_BLOCKED_BIDI:
|
|
599
606
|
this.onStreamsBlockedBidi(readVarInt(bufferstate))
|
|
600
607
|
break
|
|
608
|
+
case ParserBase.CLOSE_WEBTRANSPORT_SESSION:
|
|
609
|
+
{
|
|
610
|
+
const code = readUint32(bufferstate) || 0
|
|
611
|
+
const decoder = new TextDecoder()
|
|
612
|
+
const reason = decoder.decode(
|
|
613
|
+
new Uint8Array(
|
|
614
|
+
bufferstate.buffer.buffer,
|
|
615
|
+
bufferstate.buffer.byteOffset + bufferstate.offset,
|
|
616
|
+
offsetend - bufferstate.offset
|
|
617
|
+
)
|
|
618
|
+
)
|
|
619
|
+
this.onCloseWebTransportSession({ code, reason })
|
|
620
|
+
}
|
|
621
|
+
break
|
|
622
|
+
case ParserBase.DRAIN_WEBTRANSPORT_SESSION:
|
|
623
|
+
this.onDrain()
|
|
624
|
+
break
|
|
601
625
|
case ParserBase.DATAGRAM:
|
|
602
626
|
if (wbufferstate) {
|
|
603
627
|
this.session.jsobj.onDatagramReceived({
|
|
@@ -688,19 +712,12 @@ export class WebSocketParser extends ParserBaseHttp2 {
|
|
|
688
712
|
* @param{{code: Number, reason: string}}arg
|
|
689
713
|
*/
|
|
690
714
|
sendClose({ code, reason }) {
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
'utf8'
|
|
694
|
-
)
|
|
695
|
-
const wbuf = Buffer.allocUnsafe(2 + reasBuf.byteLength)
|
|
696
|
-
const errorcode = code === 0 ? 1000 : 1003
|
|
697
|
-
wbuf.writeUint16BE(errorcode, 0)
|
|
698
|
-
reasBuf.copy(wbuf, 2)
|
|
699
|
-
this.sendCloseInt(wbuf)
|
|
715
|
+
super.sendClose({ code, reason })
|
|
716
|
+
this.sendCloseInt()
|
|
700
717
|
}
|
|
701
718
|
|
|
702
719
|
/**
|
|
703
|
-
* @param {Uint8Array} payload
|
|
720
|
+
* @param {Uint8Array} [payload]
|
|
704
721
|
*/
|
|
705
722
|
sendCloseInt(payload) {
|
|
706
723
|
this.writeWSFrame({ opcode: WebSocketParser.WS_CLOSE, payload })
|
|
@@ -715,9 +732,9 @@ export class WebSocketParser extends ParserBaseHttp2 {
|
|
|
715
732
|
}
|
|
716
733
|
|
|
717
734
|
/**
|
|
718
|
-
* @param{{type: Number, headerVints: Array<Number|bigint>, payload: Uint8Array|undefined}} bs
|
|
735
|
+
* @param{{type: Number, headerVints: Array<Number|bigint>, payload: Uint8Array|undefined, end?: () => void}} bs
|
|
719
736
|
*/
|
|
720
|
-
writeCapsule({ type, headerVints, payload }) {
|
|
737
|
+
writeCapsule({ type, headerVints, payload, end }) {
|
|
721
738
|
let plength = 0
|
|
722
739
|
for (const ind in headerVints) plength += lengthVarInt(headerVints[ind])
|
|
723
740
|
plength += lengthVarInt(type)
|
|
@@ -762,8 +779,13 @@ export class WebSocketParser extends ParserBaseHttp2 {
|
|
|
762
779
|
payload.byteLength
|
|
763
780
|
)
|
|
764
781
|
}
|
|
765
|
-
let blocked =
|
|
766
|
-
if (payload)
|
|
782
|
+
let blocked = false
|
|
783
|
+
if (payload) {
|
|
784
|
+
blocked = !this.stream.write(cdata)
|
|
785
|
+
blocked = !this.stream.write(payload, end) || blocked
|
|
786
|
+
} else {
|
|
787
|
+
blocked = !this.stream.write(cdata, end)
|
|
788
|
+
}
|
|
767
789
|
// do something if blocked
|
|
768
790
|
if (blocked) this.blocked = true
|
|
769
791
|
return blocked
|
|
@@ -802,10 +824,10 @@ export class WebSocketParser extends ParserBaseHttp2 {
|
|
|
802
824
|
}
|
|
803
825
|
|
|
804
826
|
/**
|
|
805
|
-
* @param {{ opcode: number; payload: Uint8Array; }} args
|
|
827
|
+
* @param {{ opcode: number; payload: Uint8Array|undefined; }} args
|
|
806
828
|
*/
|
|
807
829
|
writeWSFrame({ opcode, payload }) {
|
|
808
|
-
const plength = payload
|
|
830
|
+
const plength = payload?.byteLength || 0
|
|
809
831
|
let headlength = 2
|
|
810
832
|
let mask = 0
|
|
811
833
|
if (this.isclient) {
|
|
@@ -825,7 +847,7 @@ export class WebSocketParser extends ParserBaseHttp2 {
|
|
|
825
847
|
throw new Error('Headlength does not match pos')
|
|
826
848
|
|
|
827
849
|
let blocked = !this.stream.write(cdata)
|
|
828
|
-
if (maskstate)
|
|
850
|
+
if (maskstate && payload)
|
|
829
851
|
applyMask(
|
|
830
852
|
maskstate,
|
|
831
853
|
Buffer.from(payload.buffer, payload.byteOffset, payload.byteLength),
|
package/lib/http2/parserbase.js
CHANGED
|
@@ -30,6 +30,8 @@ export class ParserBase {
|
|
|
30
30
|
static WT_STREAM_DATA_BLOCKED = 0x190b4d42
|
|
31
31
|
static WT_STREAMS_BLOCKED_UNIDI = 0x190b4d43
|
|
32
32
|
static WT_STREAMS_BLOCKED_BIDI = 0x190b4d44
|
|
33
|
+
static CLOSE_WEBTRANSPORT_SESSION = 0x2843
|
|
34
|
+
static DRAIN_WEBTRANSPORT_SESSION = 0x78ae
|
|
33
35
|
static DATAGRAM = 0x00
|
|
34
36
|
|
|
35
37
|
/**
|
|
@@ -38,7 +40,8 @@ export class ParserBase {
|
|
|
38
40
|
constructor({
|
|
39
41
|
nativesession,
|
|
40
42
|
isclient,
|
|
41
|
-
|
|
43
|
+
initialStreamSendWindowOffsetBidi,
|
|
44
|
+
initialStreamSendWindowOffsetUnidi,
|
|
42
45
|
initialStreamReceiveWindowOffset,
|
|
43
46
|
streamShouldAutoTuneReceiveWindow,
|
|
44
47
|
streamReceiveWindowSizeLimit
|
|
@@ -48,7 +51,8 @@ export class ParserBase {
|
|
|
48
51
|
/** @type {boolean} */
|
|
49
52
|
this.blocked = false
|
|
50
53
|
|
|
51
|
-
this.
|
|
54
|
+
this.initialStreamSendWindowOffsetUnidi = initialStreamSendWindowOffsetUnidi
|
|
55
|
+
this.initialStreamSendWindowOffsetBidi = initialStreamSendWindowOffsetBidi
|
|
52
56
|
this.initialStreamReceiveWindowOffset = initialStreamReceiveWindowOffset
|
|
53
57
|
this.streamShouldAutoTuneReceiveWindow = streamShouldAutoTuneReceiveWindow
|
|
54
58
|
this.streamReceiveWindowSizeLimit = streamReceiveWindowSizeLimit
|
|
@@ -67,16 +71,31 @@ export class ParserBase {
|
|
|
67
71
|
|
|
68
72
|
/**
|
|
69
73
|
* @abstract
|
|
70
|
-
* @param{{type: Number, headerVints: Array<Number|bigint>, payload: Uint8Array|undefined}} bs
|
|
74
|
+
* @param{{type: Number, headerVints: Array<Number|bigint>, payload: Uint8Array|undefined, end?: () => void}} bs
|
|
71
75
|
*/
|
|
72
|
-
writeCapsule({ type, headerVints, payload }) {
|
|
76
|
+
writeCapsule({ type, headerVints, payload, end }) {
|
|
73
77
|
throw new Error('Implement writeCapsule in derived Class')
|
|
74
78
|
}
|
|
75
79
|
|
|
76
80
|
/**
|
|
77
81
|
* @param{{code: Number, reason: string}}arg
|
|
78
82
|
*/
|
|
79
|
-
sendClose({ code, reason }) {
|
|
83
|
+
sendClose({ code, reason }) {
|
|
84
|
+
const encoder = new TextEncoder()
|
|
85
|
+
const payload = encoder.encode('AAAA' + reason)
|
|
86
|
+
payload[0] = (code >> 24) & 0xff
|
|
87
|
+
payload[1] = (code >> 16) & 0xff
|
|
88
|
+
payload[2] = (code >> 8) & 0xff
|
|
89
|
+
payload[3] = code & 0xff
|
|
90
|
+
this.writeCapsule({
|
|
91
|
+
type: ParserBase.CLOSE_WEBTRANSPORT_SESSION,
|
|
92
|
+
headerVints: [],
|
|
93
|
+
payload,
|
|
94
|
+
end: () => {
|
|
95
|
+
this.closeHttp2Stream(code)
|
|
96
|
+
}
|
|
97
|
+
})
|
|
98
|
+
}
|
|
80
99
|
|
|
81
100
|
/**
|
|
82
101
|
* @param {bigint} streamid
|
|
@@ -101,12 +120,15 @@ export class ParserBase {
|
|
|
101
120
|
return undefined
|
|
102
121
|
}
|
|
103
122
|
}
|
|
123
|
+
const unidirectional = !!(streamid & 0x2n)
|
|
104
124
|
const stream = new Http2WebTransportStream({
|
|
105
125
|
streamid,
|
|
106
|
-
unidirectional
|
|
126
|
+
unidirectional,
|
|
107
127
|
incoming,
|
|
108
128
|
capsuleParser: this,
|
|
109
|
-
sendWindowOffset:
|
|
129
|
+
sendWindowOffset: unidirectional
|
|
130
|
+
? this.initialStreamSendWindowOffsetUnidi
|
|
131
|
+
: this.initialStreamSendWindowOffsetBidi,
|
|
110
132
|
receiveWindowOffset: this.initialStreamReceiveWindowOffset,
|
|
111
133
|
shouldAutoTuneReceiveWindow: this.streamShouldAutoTuneReceiveWindow,
|
|
112
134
|
receiveWindowSizeLimit: this.streamReceiveWindowSizeLimit,
|
|
@@ -212,6 +234,21 @@ export class ParserBase {
|
|
|
212
234
|
}
|
|
213
235
|
}
|
|
214
236
|
|
|
237
|
+
/**
|
|
238
|
+
* @param {{code: number, reason: string}} opts
|
|
239
|
+
*/
|
|
240
|
+
onCloseWebTransportSession({ code, reason }) {
|
|
241
|
+
this.session.jsobj.onClose({
|
|
242
|
+
errorcode: code,
|
|
243
|
+
error: reason
|
|
244
|
+
})
|
|
245
|
+
this.closeHttp2Stream(code) // is this necessary
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
onDrain() {
|
|
249
|
+
this.session.jsobj.onGoAwayReceived()
|
|
250
|
+
}
|
|
251
|
+
|
|
215
252
|
/**
|
|
216
253
|
* @param {number} code
|
|
217
254
|
*/
|
|
@@ -4,6 +4,17 @@ 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
|
+
|
|
7
18
|
/**
|
|
8
19
|
* @param{{offset: Number, buffer: Buffer, size: Number}} bs
|
|
9
20
|
*/
|
|
@@ -63,7 +74,8 @@ export class ParserBaseHttp2 extends ParserBase {
|
|
|
63
74
|
stream,
|
|
64
75
|
nativesession,
|
|
65
76
|
isclient,
|
|
66
|
-
|
|
77
|
+
initialStreamSendWindowOffsetBidi,
|
|
78
|
+
initialStreamSendWindowOffsetUnidi,
|
|
67
79
|
initialStreamReceiveWindowOffset,
|
|
68
80
|
streamShouldAutoTuneReceiveWindow,
|
|
69
81
|
streamReceiveWindowSizeLimit
|
|
@@ -71,7 +83,8 @@ export class ParserBaseHttp2 extends ParserBase {
|
|
|
71
83
|
super({
|
|
72
84
|
nativesession,
|
|
73
85
|
isclient,
|
|
74
|
-
|
|
86
|
+
initialStreamSendWindowOffsetBidi,
|
|
87
|
+
initialStreamSendWindowOffsetUnidi,
|
|
75
88
|
initialStreamReceiveWindowOffset,
|
|
76
89
|
streamShouldAutoTuneReceiveWindow,
|
|
77
90
|
streamReceiveWindowSizeLimit
|
package/lib/http2/session.js
CHANGED
|
@@ -209,10 +209,7 @@ export class Http2WebTransportSession {
|
|
|
209
209
|
*/
|
|
210
210
|
close({ code, reason }) {
|
|
211
211
|
this.capsParser.sendClose({ code, reason }) // this includes for ws closing the session!
|
|
212
|
-
//
|
|
213
|
-
if (this.stream) {
|
|
214
|
-
this.capsParser.closeHttp2Stream(code)
|
|
215
|
-
}
|
|
212
|
+
// should also close the stream
|
|
216
213
|
}
|
|
217
214
|
|
|
218
215
|
/**
|
|
@@ -252,7 +249,6 @@ export class Http2WebTransportSession {
|
|
|
252
249
|
* @param {{ code: number, reason: string }} arg
|
|
253
250
|
*/
|
|
254
251
|
closeConnection({ code, reason }) {
|
|
255
|
-
console.trace()
|
|
256
252
|
// called in case of failure in parsing or flowcontrol
|
|
257
253
|
this.jsobj.onClose({
|
|
258
254
|
errorcode: code,
|
package/lib/index.browser.js
CHANGED
package/lib/index.node.js
CHANGED
|
@@ -23,5 +23,6 @@
|
|
|
23
23
|
* @typedef {import('./types').HttpServerInit} HttpServerInit
|
|
24
24
|
*/
|
|
25
25
|
|
|
26
|
+
// also edit index.types.js
|
|
26
27
|
export { HttpServer, Http3Server, Http2Server } from './server.js'
|
|
27
|
-
export { WebTransport } from './webtransport.node.js'
|
|
28
|
+
export { WebTransport, quicheLoaded } from './webtransport.node.js'
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/* eslint-disable no-prototype-builtins */
|
|
2
|
+
// Copyright (c) 2022 Marten Richter or other contributers (see commit). All rights reserved.
|
|
3
|
+
// Use of this source code is governed by a BSD-style license that can be
|
|
4
|
+
// found in the LICENSE file.
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* // Spec
|
|
8
|
+
* @typedef {import('./dom').WebTransportDatagramStats} WebTransportDatagramStats
|
|
9
|
+
* @typedef {import('./dom').WebTransportStats} WebTransportStats
|
|
10
|
+
* @typedef {import('./dom').WebTransportCloseInfo} WebTransportCloseInfo
|
|
11
|
+
* @typedef {import('./dom').WebTransportDatagramDuplexStream} WebTransportDatagramDuplexStream
|
|
12
|
+
* @typedef {import('./dom').WebTransportBidirectionalStream} WebTransportBidirectionalStream
|
|
13
|
+
* @typedef {import('./dom').WebTransportSendStreamStats} WebTransportSendStreamStats
|
|
14
|
+
* @typedef {import('./dom').WebTransportSendStream} WebTransportSendStream
|
|
15
|
+
* @typedef {import('./dom').WebTransportReceiveStreamStats} WebTransportReceiveStreamStats
|
|
16
|
+
* @typedef {import('./dom').WebTransportReceiveStream} WebTransportReceiveStream
|
|
17
|
+
* @typedef {import('./dom').WebTransportHash} WebTransportHash
|
|
18
|
+
* @typedef {import('./dom').WebTransportOptions} WebTransportOptions
|
|
19
|
+
* @typedef {import('./dom').WebTransportReliabilityMode} WebTransportReliabilityMode
|
|
20
|
+
*
|
|
21
|
+
* Public API
|
|
22
|
+
* @typedef {import('./types').WebTransportSessionImpl} WebTransportSession
|
|
23
|
+
* @typedef {import('./types').HttpServerInit} HttpServerInit
|
|
24
|
+
*/
|
|
25
|
+
|
|
26
|
+
// both imports from the browser side and for nodes to generate a joint type file
|
|
27
|
+
export { HttpServer, Http3Server, Http2Server } from './server.js'
|
|
28
|
+
export { WebTransport, quicheLoaded } from './webtransport.node.js'
|
|
29
|
+
|
|
30
|
+
export {
|
|
31
|
+
WebTransportPonyfill,
|
|
32
|
+
WebTransportPolyfill
|
|
33
|
+
} from './webtransport.browser.js'
|
package/lib/types.ts
CHANGED
|
@@ -266,10 +266,17 @@ export interface WebTransportSessionImpl extends WebTransportSession {
|
|
|
266
266
|
state: WebTransportSessionState
|
|
267
267
|
}
|
|
268
268
|
|
|
269
|
+
export type QUICHE_LOG_OFF = -1
|
|
270
|
+
export type QUICHE_LOG_INFO = 0
|
|
271
|
+
export type QUICHE_LOG_WARNING = 1
|
|
272
|
+
export type QUICHE_LOG_ERROR = 2
|
|
273
|
+
export type QUICHE_LOG_FATAL = 3
|
|
274
|
+
export type QUICHE_LOG = QUICHE_LOG_OFF | QUICHE_LOG_INFO | QUICHE_LOG_WARNING | QUICHE_LOG_ERROR | QUICHE_LOG_FATAL
|
|
275
|
+
|
|
269
276
|
export interface HttpWebTransportInit extends WebTransportOptions {
|
|
270
277
|
host: string
|
|
271
278
|
port: string | number
|
|
272
|
-
quicheLogVerbose?:
|
|
279
|
+
quicheLogVerbose?: QUICHE_LOG
|
|
273
280
|
forceIpv6?: boolean
|
|
274
281
|
localPort?: number
|
|
275
282
|
}
|
|
@@ -331,7 +338,8 @@ export type CreateParserFunction = (
|
|
|
331
338
|
export interface ParserInit {
|
|
332
339
|
isclient: boolean
|
|
333
340
|
nativesession: any
|
|
334
|
-
|
|
341
|
+
initialStreamSendWindowOffsetBidi: number
|
|
342
|
+
initialStreamSendWindowOffsetUnidi: number
|
|
335
343
|
initialStreamReceiveWindowOffset: number
|
|
336
344
|
streamShouldAutoTuneReceiveWindow: boolean
|
|
337
345
|
streamReceiveWindowSizeLimit: number
|
package/lib/webtransport.node.js
CHANGED
|
@@ -18,9 +18,13 @@ let Http3WebTransportClientSocket
|
|
|
18
18
|
* @type {new (arg0: import("./types").HttpWebTransportInit) => any}
|
|
19
19
|
*/
|
|
20
20
|
let Http3WebTransportClient
|
|
21
|
+
/**
|
|
22
|
+
* @type {boolean}
|
|
23
|
+
*/
|
|
24
|
+
let quicheLoadedReady
|
|
21
25
|
// @ts-ignore
|
|
22
26
|
// eslint-disable-next-line no-unused-vars
|
|
23
|
-
const quicheLoaded = new Promise((resolve, reject) => {
|
|
27
|
+
export const quicheLoaded = new Promise((resolve, reject) => {
|
|
24
28
|
// @ts-ignore
|
|
25
29
|
import('@fails-components/webtransport-transport-http3-quiche')
|
|
26
30
|
.then(
|
|
@@ -39,6 +43,9 @@ const quicheLoaded = new Promise((resolve, reject) => {
|
|
|
39
43
|
resolve(undefined)
|
|
40
44
|
}
|
|
41
45
|
)
|
|
46
|
+
.finally(() => {
|
|
47
|
+
quicheLoadedReady = true
|
|
48
|
+
})
|
|
42
49
|
.catch((error) => {
|
|
43
50
|
log('Problem loading http3-quiche transport', error)
|
|
44
51
|
reject(error)
|
|
@@ -102,6 +109,8 @@ export class WebTransport extends WebTransportBase {
|
|
|
102
109
|
*/
|
|
103
110
|
createClient(args) {
|
|
104
111
|
let createUnreliableClient
|
|
112
|
+
if (!quicheLoadedReady)
|
|
113
|
+
throw new Error('Lib quiche loading attempt did not end')
|
|
105
114
|
if (checkQuicheInit) {
|
|
106
115
|
createUnreliableClient = function (/** @type {any} */ _client) {
|
|
107
116
|
if (
|
package/lib/webtransportbase.js
CHANGED
package/old_test/test.js
CHANGED
|
@@ -5,7 +5,12 @@
|
|
|
5
5
|
// this file runs various tests
|
|
6
6
|
|
|
7
7
|
import { generateWebTransportCertificate } from '../test/fixtures/certificate.js'
|
|
8
|
-
import {
|
|
8
|
+
import {
|
|
9
|
+
Http3Server,
|
|
10
|
+
Http2Server,
|
|
11
|
+
WebTransport,
|
|
12
|
+
quicheLoaded
|
|
13
|
+
} from '../lib/index.node.js'
|
|
9
14
|
import { echoTestsConnection, runEchoServer } from './testsuite.js'
|
|
10
15
|
|
|
11
16
|
let http2 = false
|
|
@@ -15,6 +20,13 @@ if (process.argv.some((el) => el === 'http2')) {
|
|
|
15
20
|
}
|
|
16
21
|
|
|
17
22
|
async function run() {
|
|
23
|
+
if (
|
|
24
|
+
process.env.USE_HTTP2 !== 'true' &&
|
|
25
|
+
process.env.USE_PONYFILL !== 'true' &&
|
|
26
|
+
process.env.USE_POLYFILL !== 'true'
|
|
27
|
+
) {
|
|
28
|
+
await quicheLoaded
|
|
29
|
+
}
|
|
18
30
|
console.log('try connecting to server that does not exist')
|
|
19
31
|
const badClient = new WebTransport('https://127.0.0.1:49823/echo', {
|
|
20
32
|
serverCertificateHashes: [
|