@fails-components/webtransport 0.1.5 → 0.1.7
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/CMakeLists.txt +40 -109
- package/dist/lib/dom.d.ts +6 -0
- package/dist/lib/dom.d.ts.map +1 -1
- package/dist/lib/event-loop.d.ts +8 -3
- package/dist/lib/event-loop.d.ts.map +1 -1
- package/dist/lib/server.d.ts +3 -2
- package/dist/lib/server.d.ts.map +1 -1
- package/dist/lib/session.d.ts +66 -16
- package/dist/lib/session.d.ts.map +1 -1
- package/dist/lib/stream.d.ts +5 -5
- package/dist/lib/stream.d.ts.map +1 -1
- package/dist/lib/transport.d.ts.map +1 -1
- package/dist/lib/types.d.ts.map +1 -1
- package/dist/lib/webtransport.d.ts +22 -0
- package/dist/lib/webtransport.d.ts.map +1 -1
- package/lib/dom.ts +7 -2
- package/lib/event-loop.js +13 -7
- package/lib/server.js +1 -1
- package/lib/session.js +51 -20
- package/lib/stream.js +26 -5
- package/lib/transport.js +3 -1
- package/lib/types.ts +1 -0
- package/lib/webtransport.js +31 -0
- package/package.json +2 -2
- package/platform/quiche/quic/core/io/socket_win.inc +3 -0
- package/platform/quiche_platform_impl/quiche_command_line_flags_impl.h +7 -0
- package/platform/quiche_platform_impl/quiche_export_impl.h +3 -9
- package/platform/quiche_platform_impl/quiche_server_stats_impl.h +1 -22
- package/platform/quiche_platform_impl/quiche_stream_buffer_allocator_impl.h +1 -4
- package/platform/quiche_platform_impl/quiche_time_utils_impl.h +1 -13
- package/platform/quiche_platform_impl/quiche_udp_socket_platform_impl.h +9 -0
- package/readme.md +3 -1
- package/src/http3client.cc +13 -29
- package/src/http3client.h +2 -6
- package/src/http3clientsession.cc +3 -1
- package/src/http3clientsession.h +9 -0
- package/src/http3clientstream.cc +17 -0
- package/src/http3clientstream.h +10 -0
- package/src/http3eventloop.cc +42 -55
- package/src/http3eventloop.h +2 -5
- package/src/http3serversession.cc +1 -136
- package/src/http3serversession.h +1 -72
- package/src/http3serverstream.cc +0 -49
- package/src/http3serverstream.h +0 -5
- package/src/http3wtsessionvisitor.cc +1 -1
- package/src/http3wtsessionvisitor.h +5 -37
- package/src/http3wtstreamvisitor.cc +2 -2
- package/test/bidirectional-streams.spec.js +1 -0
- package/test/datagrams.spec.js +1 -0
- package/test/unidirectional-streams.spec.js +1 -0
- package/platform/net/quiche/common/platform/impl/quiche_flags_impl.h +0 -12
- package/platform/poll.h +0 -2
- package/platform/quiche/quic/core/io/quic_poll_event_loop.h +0 -8
- package/platform/quiche_platform_impl/quic_testvalue_impl.h +0 -19
- package/platform/quiche_platform_impl/quic_udp_socket_winsock.cc +0 -732
- package/platform/quiche_platform_impl/quiche_time_utils_impl.cc +0 -43
- package/platform/quiche_platform_impl/socket_winsock.cc +0 -535
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"webtransport.d.ts","sourceRoot":"","sources":["../../lib/webtransport.js"],"names":[],"mappings":"AAMA;;;;GAIG;AAEH;;;;GAIG;AACH;IACE;;;OAGG;IACH,iBAHW,MAAM,
|
|
1
|
+
{"version":3,"file":"webtransport.d.ts","sourceRoot":"","sources":["../../lib/webtransport.js"],"names":[],"mappings":"AAMA;;;;GAIG;AAEH;;;;GAIG;AACH;IACE;;;OAGG;IACH,iBAHW,MAAM,0DA0DhB;IAnCC,qBAA6B;IAC7B,uDAA+B;IAC/B,6BAAmC;IAEnC,4DAAqC;IAErC,8DAA8D;IAC9D,8BADW,eAAe,+BAA+B,CAAC,CACiB;IAE3E,wDAAwD;IACxD,+BADW,eAAe,yBAAyB,CAAC,CAEV;IA0B5C,+DAQC;IAED,uEAQC;IAED;;;;;;;;;;;;;;;;;;OAQC;IAED;;OAEG;IACH,2EASC;IAED,sFASC;IAED,8EASC;CACF;oCAzIY,OAAO,OAAO,EAAE,qBAAqB;8CACrC,OAAO,OAAO,EAAE,+BAA+B;wCAC/C,OAAO,OAAO,EAAE,yBAAyB;oCAIzC,OAAO,OAAO,EAAE,YAAY"}
|
package/lib/dom.ts
CHANGED
|
@@ -73,13 +73,16 @@ export interface WebTransportOptions {
|
|
|
73
73
|
allowPooling?: boolean
|
|
74
74
|
requireUnreliable?: boolean
|
|
75
75
|
serverCertificateHashes?: WebTransportHash[]
|
|
76
|
+
congestionControl?: WebTransportCongestionControl
|
|
76
77
|
}
|
|
77
78
|
|
|
78
79
|
export interface WebTransport {
|
|
79
|
-
|
|
80
|
+
getStats: () => Promise<WebTransportStats>
|
|
80
81
|
readonly ready: Promise<void>
|
|
81
|
-
|
|
82
|
+
readonly reliability: WebTransportReliabilityMode
|
|
83
|
+
readonly congestionControl: WebTransportCongestionControl
|
|
82
84
|
readonly closed: Promise<WebTransportCloseInfo>
|
|
85
|
+
readonly draining: Promise<undefined>
|
|
83
86
|
close: (closeInfo?: WebTransportCloseInfo) => void
|
|
84
87
|
readonly datagrams: WebTransportDatagramDuplexStream
|
|
85
88
|
|
|
@@ -93,3 +96,5 @@ export interface WebTransport {
|
|
|
93
96
|
}
|
|
94
97
|
|
|
95
98
|
export type WebTransportReliabilityMode = 'pending' | 'reliable-only' | 'supports-unreliable'
|
|
99
|
+
export type WebTransportCongestionControl = 'default' | 'throughput' | 'low-latency';
|
|
100
|
+
|
package/lib/event-loop.js
CHANGED
|
@@ -15,7 +15,8 @@ export class Http3EventLoop {
|
|
|
15
15
|
transportCallback: Http3WebTransport.transportCallback,
|
|
16
16
|
streamCallback: Http3WTStream.callback,
|
|
17
17
|
sessionCallback: Http3WTSession.callback,
|
|
18
|
-
eventloopCallback: Http3EventLoop.callback
|
|
18
|
+
eventloopCallback: Http3EventLoop.callback,
|
|
19
|
+
quicheLogVerbose: args?.quicheLogVerbose
|
|
19
20
|
})
|
|
20
21
|
this.eventloopInt.jsobj = this
|
|
21
22
|
|
|
@@ -23,9 +24,12 @@ export class Http3EventLoop {
|
|
|
23
24
|
this.loopGuardian = this.loopGuardian.bind(this)
|
|
24
25
|
}
|
|
25
26
|
|
|
26
|
-
|
|
27
|
+
/**
|
|
28
|
+
* @param {*} [args]
|
|
29
|
+
*/
|
|
30
|
+
startEventLoop(args) {
|
|
27
31
|
console.log('start GlobalEventLoop')
|
|
28
|
-
this.eventloopInt.startEventLoop()
|
|
32
|
+
this.eventloopInt.startEventLoop(args)
|
|
29
33
|
this.loopGuardianTimer = setInterval(this.loopGuardian, 5000)
|
|
30
34
|
}
|
|
31
35
|
|
|
@@ -54,12 +58,13 @@ export class Http3EventLoop {
|
|
|
54
58
|
}
|
|
55
59
|
|
|
56
60
|
/**
|
|
61
|
+
* @param {any} [args]
|
|
57
62
|
* @returns {Http3EventLoop}
|
|
58
63
|
*/
|
|
59
|
-
static createGlobalEventLoop() {
|
|
64
|
+
static createGlobalEventLoop(args) {
|
|
60
65
|
if (!Http3EventLoop.globalLoop) {
|
|
61
66
|
Http3EventLoop.globalLoop = new Http3EventLoop()
|
|
62
|
-
Http3EventLoop.globalLoop.startEventLoop()
|
|
67
|
+
Http3EventLoop.globalLoop.startEventLoop(args)
|
|
63
68
|
console.log('createGlobalEventLoop')
|
|
64
69
|
}
|
|
65
70
|
return Http3EventLoop.globalLoop
|
|
@@ -67,12 +72,13 @@ export class Http3EventLoop {
|
|
|
67
72
|
|
|
68
73
|
/**
|
|
69
74
|
* @param {any} object
|
|
75
|
+
* @param {any} args
|
|
70
76
|
* @returns {Http3EventLoop}
|
|
71
77
|
*/
|
|
72
|
-
static getGlobalEventLoop(object) {
|
|
78
|
+
static getGlobalEventLoop(object, args) {
|
|
73
79
|
if (!object) throw new Error('getGlobalEventLoop without reference object')
|
|
74
80
|
const loop =
|
|
75
|
-
Http3EventLoop.globalLoop ?? Http3EventLoop.createGlobalEventLoop()
|
|
81
|
+
Http3EventLoop.globalLoop ?? Http3EventLoop.createGlobalEventLoop(args)
|
|
76
82
|
loop.refObjects.add(new WeakRef(object))
|
|
77
83
|
return loop
|
|
78
84
|
}
|
package/lib/server.js
CHANGED
|
@@ -29,7 +29,7 @@ export class Http3Server extends Http3WebTransport {
|
|
|
29
29
|
/** @type {Record<string, ReadableStream>} */
|
|
30
30
|
this.sessionStreams = {}
|
|
31
31
|
|
|
32
|
-
/** @type {Record<string,
|
|
32
|
+
/** @type {Record<string, ReadableStreamDefaultController<Http3WTSession>>} */
|
|
33
33
|
this.sessionController = {}
|
|
34
34
|
|
|
35
35
|
this.port = null
|
package/lib/session.js
CHANGED
|
@@ -13,7 +13,11 @@ import { Http3WTStream } from './stream.js'
|
|
|
13
13
|
* @typedef {import('./dom').WebTransportCloseInfo} WebTransportCloseInfo
|
|
14
14
|
* @typedef {import('./dom').WebTransportBidirectionalStream} WebTransportBidirectionalStream
|
|
15
15
|
* @typedef {import('./dom').WebTransportSendStream} WebTransportSendStream
|
|
16
|
+
* @typedef {import('./dom').WebTransportReceiveStream} WebTransportReceiveStream
|
|
16
17
|
* @typedef {import('./dom').WebTransportDatagramDuplexStream} WebTransportDatagramDuplexStream
|
|
18
|
+
* @typedef {import('./dom').WebTransportReliabilityMode} WebTransportReliabilityMode
|
|
19
|
+
* @typedef {import('./dom').WebTransportCongestionControl} WebTransportCongestionControl
|
|
20
|
+
* @typedef {import('./dom').WebTransportStats} WebTransportStats
|
|
17
21
|
*
|
|
18
22
|
* @typedef {import('./types').NativeHttp3WTSession} NativeHttp3WTSession
|
|
19
23
|
*
|
|
@@ -58,19 +62,32 @@ export class Http3WTSession {
|
|
|
58
62
|
this.readyResolve = resolve
|
|
59
63
|
this.readyReject = reject
|
|
60
64
|
})
|
|
65
|
+
/** @type {WebTransportReliabilityMode} */
|
|
66
|
+
this.reliability = 'pending'
|
|
67
|
+
/** @type {WebTransportCongestionControl} */
|
|
68
|
+
this.congestionControl = 'default'
|
|
61
69
|
/** @type {Promise<WebTransportCloseInfo>} */
|
|
62
70
|
this.closed = new Promise((resolve, reject) => {
|
|
63
71
|
this.closedResolve = resolve
|
|
64
72
|
this.closedReject = reject
|
|
65
73
|
})
|
|
66
74
|
|
|
75
|
+
/** @type {Promise<undefined>} */
|
|
76
|
+
this.draining = new Promise((resolve, reject) => {
|
|
77
|
+
this.drainingResolve = resolve
|
|
78
|
+
this.drainingReject = reject
|
|
79
|
+
})
|
|
80
|
+
|
|
81
|
+
/** @type {ReadableStream<WebTransportBidirectionalStream>} */
|
|
67
82
|
this.incomingBidirectionalStreams = new ReadableStream({
|
|
83
|
+
/** @param {ReadableStreamDefaultController<WebTransportBidirectionalStream>} controller */
|
|
68
84
|
start: (controller) => {
|
|
69
85
|
this.incomBiDiController = controller
|
|
70
86
|
}
|
|
71
87
|
})
|
|
72
|
-
|
|
88
|
+
/** @type {ReadableStream<WebTransportReceiveStream>} */
|
|
73
89
|
this.incomingUnidirectionalStreams = new ReadableStream({
|
|
90
|
+
/** @param {ReadableStreamDefaultController<WebTransportReceiveStream>} controller */
|
|
74
91
|
start: (controller) => {
|
|
75
92
|
this.incomUniDiController = controller
|
|
76
93
|
}
|
|
@@ -86,7 +103,9 @@ export class Http3WTSession {
|
|
|
86
103
|
/** @type {WebTransportDatagramDuplexStream} */
|
|
87
104
|
this.datagrams = {
|
|
88
105
|
readable: new ReadableStream({
|
|
89
|
-
start: (
|
|
106
|
+
start: (
|
|
107
|
+
/** @type {ReadableStreamDefaultController<Uint8Array>} */ controller
|
|
108
|
+
) => {
|
|
90
109
|
this.incomDatagramController = controller
|
|
91
110
|
}
|
|
92
111
|
}),
|
|
@@ -126,7 +145,9 @@ export class Http3WTSession {
|
|
|
126
145
|
/** @type {Array<(err?: Error) => void>} */
|
|
127
146
|
this.rejectUniDi = []
|
|
128
147
|
|
|
148
|
+
/** @type {Set<WebTransportSendStream>} */
|
|
129
149
|
this.sendStreams = new Set()
|
|
150
|
+
/** @type {Set<WebTransportReceiveStream>} */
|
|
130
151
|
this.receiveStreams = new Set()
|
|
131
152
|
/** @type {Set<Http3WTStream>} */
|
|
132
153
|
this.streamObjs = new Set()
|
|
@@ -147,6 +168,28 @@ export class Http3WTSession {
|
|
|
147
168
|
}
|
|
148
169
|
}
|
|
149
170
|
|
|
171
|
+
getStats() {
|
|
172
|
+
return Promise.resolve({
|
|
173
|
+
timestamp: Date.now(),
|
|
174
|
+
bytesSent: BigInt(0),
|
|
175
|
+
packetsSent: BigInt(0),
|
|
176
|
+
packetsLost: BigInt(0),
|
|
177
|
+
numOutgoingStreamsCreated: 0,
|
|
178
|
+
numIncomingStreamsCreated: 0,
|
|
179
|
+
bytesReceived: BigInt(0),
|
|
180
|
+
packetsReceived: BigInt(0),
|
|
181
|
+
smoothedRtt: 0,
|
|
182
|
+
rttVariation: 0,
|
|
183
|
+
minRtt: 0,
|
|
184
|
+
datagrams: {
|
|
185
|
+
timestamp: Date.now(),
|
|
186
|
+
expiredOutgoing: BigInt(0),
|
|
187
|
+
droppedIncoming: BigInt(0),
|
|
188
|
+
lostOutgoing: BigInt(0)
|
|
189
|
+
}
|
|
190
|
+
})
|
|
191
|
+
}
|
|
192
|
+
|
|
150
193
|
async waitForDatagramsSend() {
|
|
151
194
|
while (this.writeDatagramProm.length > 0) {
|
|
152
195
|
try {
|
|
@@ -172,7 +215,7 @@ export class Http3WTSession {
|
|
|
172
215
|
}
|
|
173
216
|
|
|
174
217
|
/**
|
|
175
|
-
* @param {
|
|
218
|
+
* @param {WebTransportSendStream} stream
|
|
176
219
|
* @param {WritableStreamDefaultController} controller
|
|
177
220
|
*/
|
|
178
221
|
addSendStream(stream, controller) {
|
|
@@ -181,7 +224,7 @@ export class Http3WTSession {
|
|
|
181
224
|
}
|
|
182
225
|
|
|
183
226
|
/**
|
|
184
|
-
* @param {
|
|
227
|
+
* @param {WebTransportSendStream} stream
|
|
185
228
|
* @param {WritableStreamDefaultController} controller
|
|
186
229
|
*/
|
|
187
230
|
removeSendStream(stream, controller) {
|
|
@@ -190,7 +233,7 @@ export class Http3WTSession {
|
|
|
190
233
|
}
|
|
191
234
|
|
|
192
235
|
/**
|
|
193
|
-
* @param {
|
|
236
|
+
* @param {WebTransportReceiveStream } stream
|
|
194
237
|
* @param {ReadableStreamDefaultController} controller
|
|
195
238
|
*/
|
|
196
239
|
addReceiveStream(stream, controller) {
|
|
@@ -199,7 +242,7 @@ export class Http3WTSession {
|
|
|
199
242
|
}
|
|
200
243
|
|
|
201
244
|
/**
|
|
202
|
-
* @param {
|
|
245
|
+
* @param {WebTransportReceiveStream } stream
|
|
203
246
|
* @param {ReadableStreamDefaultController} controller
|
|
204
247
|
*/
|
|
205
248
|
removeReceiveStream(stream, controller) {
|
|
@@ -257,6 +300,7 @@ export class Http3WTSession {
|
|
|
257
300
|
}
|
|
258
301
|
|
|
259
302
|
onReady(/* error */) {
|
|
303
|
+
this.reliability = 'supports-unreliable'
|
|
260
304
|
if (this.readyResolve) this.readyResolve()
|
|
261
305
|
delete this.readyResolve
|
|
262
306
|
}
|
|
@@ -347,20 +391,7 @@ export class Http3WTSession {
|
|
|
347
391
|
const curres = this.resolveUniDi.shift()
|
|
348
392
|
|
|
349
393
|
if (curres != null && strobj.writable != null) {
|
|
350
|
-
|
|
351
|
-
// @ts-expect-error `getStats` property is missing from WritableStream
|
|
352
|
-
// we add it on the next line
|
|
353
|
-
const sendStream = strobj.writable
|
|
354
|
-
sendStream.getStats = () => {
|
|
355
|
-
return Promise.resolve({
|
|
356
|
-
timestamp: 0,
|
|
357
|
-
bytesWritten: 0n,
|
|
358
|
-
bytesSent: 0n,
|
|
359
|
-
bytesAcknowledged: 0n
|
|
360
|
-
})
|
|
361
|
-
}
|
|
362
|
-
|
|
363
|
-
curres(sendStream)
|
|
394
|
+
curres(strobj.writable)
|
|
364
395
|
}
|
|
365
396
|
}
|
|
366
397
|
}
|
package/lib/stream.js
CHANGED
|
@@ -39,21 +39,26 @@ export class Http3WTStream {
|
|
|
39
39
|
this.pendingres = null
|
|
40
40
|
|
|
41
41
|
if (this.bidirectional || this.incoming) {
|
|
42
|
+
// @ts-expect-error `getStats` property is missing from ReadavleStream
|
|
43
|
+
/** @type {WebTransportReceiveStream} */
|
|
42
44
|
this.readable = new ReadableStream(
|
|
43
45
|
{
|
|
44
|
-
start: (
|
|
46
|
+
start: (
|
|
47
|
+
/** @type {ReadableStreamDefaultController<Uint8Array>} */ controller
|
|
48
|
+
) => {
|
|
45
49
|
this.readableController = controller
|
|
46
|
-
// @ts-expect-error this.readable could be undefined
|
|
47
50
|
this.parentobj.addReceiveStream(this.readable, controller)
|
|
48
51
|
this.objint.startReading()
|
|
49
52
|
},
|
|
50
|
-
pull: (
|
|
53
|
+
pull: (
|
|
54
|
+
/** @type {ReadableStreamDefaultController<Uint8Array>} */ controller
|
|
55
|
+
) => {
|
|
51
56
|
if (this.readableclosed) {
|
|
52
57
|
return Promise.resolve()
|
|
53
58
|
}
|
|
54
59
|
this.objint.startReading()
|
|
55
60
|
},
|
|
56
|
-
cancel: (reason) => {
|
|
61
|
+
cancel: (/** @type {{ code: number; }} */ reason) => {
|
|
57
62
|
/** @type {Promise<void>} */
|
|
58
63
|
const promise = new Promise((resolve, reject) => {
|
|
59
64
|
this.cancelres = resolve
|
|
@@ -71,13 +76,21 @@ export class Http3WTStream {
|
|
|
71
76
|
},
|
|
72
77
|
{ highWaterMark: 4 }
|
|
73
78
|
)
|
|
79
|
+
this.readable.getStats = () => {
|
|
80
|
+
return Promise.resolve({
|
|
81
|
+
timestamp: 0,
|
|
82
|
+
bytesReceived: 0n,
|
|
83
|
+
bytesResd: 0n
|
|
84
|
+
})
|
|
85
|
+
}
|
|
74
86
|
}
|
|
75
87
|
if (this.bidirectional || !this.incoming) {
|
|
88
|
+
// @ts-expect-error `getStats` property is missing from WritableStream
|
|
89
|
+
/** @type {WebTransportSendStream} */
|
|
76
90
|
this.writable = new WritableStream(
|
|
77
91
|
{
|
|
78
92
|
start: (controller) => {
|
|
79
93
|
this.writableController = controller
|
|
80
|
-
// @ts-expect-error this.writable could be undefined
|
|
81
94
|
this.parentobj.addSendStream(this.writable, controller)
|
|
82
95
|
},
|
|
83
96
|
write: (chunk, controller) => {
|
|
@@ -130,6 +143,14 @@ export class Http3WTStream {
|
|
|
130
143
|
},
|
|
131
144
|
{ highWaterMark: 4 }
|
|
132
145
|
)
|
|
146
|
+
this.writable.getStats = () => {
|
|
147
|
+
return Promise.resolve({
|
|
148
|
+
timestamp: 0,
|
|
149
|
+
bytesWritten: 0n,
|
|
150
|
+
bytesSent: 0n,
|
|
151
|
+
bytesAcknowledged: 0n
|
|
152
|
+
})
|
|
153
|
+
}
|
|
133
154
|
}
|
|
134
155
|
|
|
135
156
|
/** @type {(() => void) | null} */
|
package/lib/transport.js
CHANGED
|
@@ -7,7 +7,9 @@ export class Http3WebTransport {
|
|
|
7
7
|
* @param {'server' | 'client'} purpose
|
|
8
8
|
*/
|
|
9
9
|
constructor(args, purpose) {
|
|
10
|
-
const eventloop = Http3EventLoop.getGlobalEventLoop(this
|
|
10
|
+
const eventloop = Http3EventLoop.getGlobalEventLoop(this, {
|
|
11
|
+
quicheLogVerbose: args.quicheLogVerbose
|
|
12
|
+
}).eventloopInt
|
|
11
13
|
|
|
12
14
|
if (purpose === 'server')
|
|
13
15
|
this.transportInt = new wtrouter.Http3WebTransportServer(args, eventloop)
|
package/lib/types.ts
CHANGED
package/lib/webtransport.js
CHANGED
|
@@ -42,6 +42,7 @@ export class WebTransport {
|
|
|
42
42
|
|
|
43
43
|
this.ready = sessionint.ready
|
|
44
44
|
this.closed = sessionint.closed
|
|
45
|
+
this.draining = sessionint.draining
|
|
45
46
|
|
|
46
47
|
this.datagrams = sessionint.datagrams
|
|
47
48
|
|
|
@@ -76,6 +77,36 @@ export class WebTransport {
|
|
|
76
77
|
})
|
|
77
78
|
}
|
|
78
79
|
|
|
80
|
+
get reliability() {
|
|
81
|
+
const session = sessions.get(this)
|
|
82
|
+
|
|
83
|
+
if (session == null) {
|
|
84
|
+
// should never happen as session is only removed when this instance is garbage collected
|
|
85
|
+
throw new Error('Http3WTSession was undefined')
|
|
86
|
+
}
|
|
87
|
+
return session.reliability
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
get congestionControl() {
|
|
91
|
+
const session = sessions.get(this)
|
|
92
|
+
|
|
93
|
+
if (session == null) {
|
|
94
|
+
// should never happen as session is only removed when this instance is garbage collected
|
|
95
|
+
throw new Error('Http3WTSession was undefined')
|
|
96
|
+
}
|
|
97
|
+
return session.congestionControl
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
getStats() {
|
|
101
|
+
const session = sessions.get(this)
|
|
102
|
+
|
|
103
|
+
if (session == null) {
|
|
104
|
+
// should never happen as session is only removed when this instance is garbage collected
|
|
105
|
+
throw new Error('Http3WTSession was undefined')
|
|
106
|
+
}
|
|
107
|
+
return session.getStats()
|
|
108
|
+
}
|
|
109
|
+
|
|
79
110
|
/**
|
|
80
111
|
* @param {WebTransportCloseInfo} [closeinfo]
|
|
81
112
|
*/
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fails-components/webtransport",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.7",
|
|
4
4
|
"description": "A component to add webtransport support (server and client) to node.js using libquiche",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"module": "lib/index.js",
|
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
"@types/chai": "^4.3.3",
|
|
46
46
|
"@types/dirty-chai": "^2.0.2",
|
|
47
47
|
"@types/mocha": "^10.0.0",
|
|
48
|
-
"@types/node": "^18.
|
|
48
|
+
"@types/node": "^18.15.3",
|
|
49
49
|
"chai": "^4.3.6",
|
|
50
50
|
"cmake-js": "^6.3.2",
|
|
51
51
|
"dirty-chai": "^2.0.1",
|
|
@@ -1,12 +1,6 @@
|
|
|
1
|
-
#ifndef
|
|
2
|
-
#define
|
|
1
|
+
#ifndef QUICHE_EXPORT_IMPL_HEADER
|
|
2
|
+
#define QUICHE_EXPORT_IMPL_HEADER
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
#include "absl/types/optional.h"
|
|
7
|
-
|
|
8
|
-
#define QUICHE_EXPORT_IMPL
|
|
9
|
-
#define QUICHE_EXPORT_PRIVATE_IMPL
|
|
10
|
-
#define QUICHE_NO_EXPORT_IMPL
|
|
4
|
+
#include "third_party/quiche/quiche/common/platform/default/quiche_platform_impl/quiche_export_impl.h"
|
|
11
5
|
|
|
12
6
|
#endif
|
|
@@ -2,27 +2,6 @@
|
|
|
2
2
|
#ifndef QUICHE_SERVER_STATS_IMPL
|
|
3
3
|
#define QUICHE_SERVER_STATS_IMPL
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
// NOLINT(namespace-envoy)
|
|
7
|
-
//
|
|
8
|
-
// This file is part of the QUICHE platform implementation, and is not to be
|
|
9
|
-
// consumed or referenced directly by other Envoy code. It serves purely as a
|
|
10
|
-
// porting layer for QUICHE.
|
|
11
|
-
|
|
12
|
-
#define QUICHE_SERVER_HISTOGRAM_ENUM_IMPL(name, sample, enum_size, docstring) \
|
|
13
|
-
do { \
|
|
14
|
-
} while (0)
|
|
15
|
-
|
|
16
|
-
#define QUICHE_SERVER_HISTOGRAM_BOOL_IMPL(name, sample, docstring) \
|
|
17
|
-
do { \
|
|
18
|
-
} while (0)
|
|
19
|
-
|
|
20
|
-
#define QUICHE_SERVER_HISTOGRAM_TIMES_IMPL(name, sample, min, max, bucket_count, docstring) \
|
|
21
|
-
do { \
|
|
22
|
-
} while (0)
|
|
23
|
-
|
|
24
|
-
#define QUICHE_SERVER_HISTOGRAM_COUNTS_IMPL(name, sample, min, max, bucket_count, docstring) \
|
|
25
|
-
do { \
|
|
26
|
-
} while (0)
|
|
5
|
+
#include "third_party/quiche/quiche/common/platform/default/quiche_platform_impl/quiche_server_stats_impl.h"
|
|
27
6
|
|
|
28
7
|
#endif
|
|
@@ -4,8 +4,5 @@
|
|
|
4
4
|
// found in the LICENSE file.
|
|
5
5
|
#ifndef NET_QUIC_PLATFORM_IMPL_QUIC_STREAM_BUFFER_ALLOCATOR_IMPL_H_
|
|
6
6
|
#define NET_QUIC_PLATFORM_IMPL_QUIC_STREAM_BUFFER_ALLOCATOR_IMPL_H_
|
|
7
|
-
#include "quiche/common/
|
|
8
|
-
namespace quiche {
|
|
9
|
-
using QuicheStreamBufferAllocatorImpl = quiche::SimpleBufferAllocator;
|
|
10
|
-
} // namespace quic
|
|
7
|
+
#include "third_party/quiche/quiche/common/platform/default/quiche_platform_impl/quiche_stream_buffer_allocator_impl.h"
|
|
11
8
|
#endif // NET_QUIC_PLATFORM_IMPL_QUIC_STREAM_BUFFER_ALLOCATOR_IMPL_H_
|
|
@@ -8,18 +8,6 @@
|
|
|
8
8
|
#ifndef QUICHE_TIME_UTILS_IMPL
|
|
9
9
|
#define QUICHE_TIME_UTILS_IMPL
|
|
10
10
|
|
|
11
|
-
#include
|
|
12
|
-
|
|
13
|
-
#include "absl/time/civil_time.h"
|
|
14
|
-
#include "absl/time/time.h"
|
|
15
|
-
#include "absl/types/optional.h"
|
|
16
|
-
|
|
17
|
-
namespace quiche {
|
|
18
|
-
|
|
19
|
-
// NOLINTNEXTLINE(readability-identifier-naming)
|
|
20
|
-
absl::optional<int64_t> QuicheUtcDateTimeToUnixSecondsImpl(int year, int month, int day, int hour,
|
|
21
|
-
int minute, int second);
|
|
22
|
-
|
|
23
|
-
} // namespace quiche
|
|
11
|
+
#include "third_party/quiche/quiche/common/platform/default/quiche_platform_impl/quiche_time_utils_impl.h"
|
|
24
12
|
|
|
25
13
|
#endif
|
|
@@ -25,6 +25,15 @@ inline bool GetGooglePacketHeadersFromControlMessageImpl(
|
|
|
25
25
|
|
|
26
26
|
inline void SetGoogleSocketOptionsImpl(int fd) {}
|
|
27
27
|
|
|
28
|
+
inline int GetEcnCmsgArgsPreserveDscpImpl(const int /*fd*/,
|
|
29
|
+
const int /*address_family*/,
|
|
30
|
+
uint8_t /*ecn_codepoint*/,
|
|
31
|
+
int& /*type*/, void* /*value*/,
|
|
32
|
+
socklen_t& /*value_len*/) {
|
|
33
|
+
// TODO(b/273081493): implement this.
|
|
34
|
+
return 0;
|
|
35
|
+
}
|
|
36
|
+
|
|
28
37
|
} // namespace quic
|
|
29
38
|
|
|
30
39
|
#endif // NET_QUIC_PLATFORM_IMPL_QUIC_UDP_SOCKET_PLATFORM_IMPL_H_
|
package/readme.md
CHANGED
|
@@ -59,7 +59,7 @@ When testing remember you might need to start chromium based browser with certai
|
|
|
59
59
|
```
|
|
60
60
|
chrome --ignore-certificate-errors-spki-list=FINGERPRINTOFYOURCERTIFICATE --ignore-certificate-errors --v=2 --enable-logging=stderr --origin-to-force-quic-on=192.168.1.50:8080
|
|
61
61
|
```
|
|
62
|
-
of course replace IP and fingerprint of your certificate accordingly.
|
|
62
|
+
of course replace IP and fingerprint of your certificate accordingly. However, the author never got this to work and is using this without flags, but supplies instead a fingerprint when opening a WebTransport session. (PR welcome).
|
|
63
63
|
|
|
64
64
|
## Specification divergence
|
|
65
65
|
|
|
@@ -76,6 +76,8 @@ They are:
|
|
|
76
76
|
* [getStats()](https://www.w3.org/TR/webtransport/#dom-webtransport-getstats)
|
|
77
77
|
* [reliability](https://www.w3.org/TR/webtransport/#dom-webtransport-reliability)
|
|
78
78
|
|
|
79
|
+
The WebTransport client only supports certification validation using fingerprints. Without a fingerprint it will accept any server without certificate checking.
|
|
80
|
+
|
|
79
81
|
### WebTransportDatagramDuplexStream
|
|
80
82
|
|
|
81
83
|
* [maxDatagramSize](https://www.w3.org/TR/webtransport/#dom-webtransportdatagramduplexstream-maxdatagramsize)
|
package/src/http3client.cc
CHANGED
|
@@ -63,10 +63,11 @@ namespace quic
|
|
|
63
63
|
WriteResult WritePacket(const char *buffer, size_t buf_len,
|
|
64
64
|
const QuicIpAddress &self_address,
|
|
65
65
|
const QuicSocketAddress &peer_address,
|
|
66
|
-
PerPacketOptions *options
|
|
66
|
+
PerPacketOptions *options,
|
|
67
|
+
const quic::QuicPacketWriterParams& wparams) override
|
|
67
68
|
{
|
|
68
69
|
WriteResult result = QuicDefaultPacketWriter::WritePacket(
|
|
69
|
-
buffer, buf_len, self_address, peer_address, options);
|
|
70
|
+
buffer, buf_len, self_address, peer_address, options, wparams);
|
|
70
71
|
if (IsWriteBlockedStatus(result.status))
|
|
71
72
|
{
|
|
72
73
|
bool success = event_loop_->RearmSocket(fd(), kSocketEventWritable);
|
|
@@ -148,7 +149,8 @@ namespace quic
|
|
|
148
149
|
connection_in_progress_(false),
|
|
149
150
|
num_attempts_connect_(0),
|
|
150
151
|
webtransport_server_support_inform_(false),
|
|
151
|
-
connection_debug_visitor_(nullptr)
|
|
152
|
+
connection_debug_visitor_(nullptr),
|
|
153
|
+
priority_(HttpStreamPriority())
|
|
152
154
|
{
|
|
153
155
|
set_server_address(server_address);
|
|
154
156
|
Initialize();
|
|
@@ -183,7 +185,7 @@ namespace quic
|
|
|
183
185
|
|
|
184
186
|
void Http3Client::Initialize()
|
|
185
187
|
{
|
|
186
|
-
priority_ = QuicStreamPriority();
|
|
188
|
+
priority_ = QuicStreamPriority(HttpStreamPriority());
|
|
187
189
|
connect_attempted_ = false;
|
|
188
190
|
auto_reconnect_ = false;
|
|
189
191
|
buffer_body_ = true;
|
|
@@ -891,7 +893,6 @@ namespace quic
|
|
|
891
893
|
response_ = "";
|
|
892
894
|
response_complete_ = false;
|
|
893
895
|
response_headers_complete_ = false;
|
|
894
|
-
preliminary_headers_.clear();
|
|
895
896
|
response_headers_.clear();
|
|
896
897
|
response_trailers_.clear();
|
|
897
898
|
bytes_read_ = 0;
|
|
@@ -990,21 +991,6 @@ namespace quic
|
|
|
990
991
|
return &response_headers_;
|
|
991
992
|
}
|
|
992
993
|
|
|
993
|
-
const spdy::Http2HeaderBlock *Http3Client::preliminary_headers() const
|
|
994
|
-
{
|
|
995
|
-
for (std::pair<QuicStreamId, QuicSpdyClientStream *> stream : open_streams_)
|
|
996
|
-
{
|
|
997
|
-
size_t bytes_read =
|
|
998
|
-
stream.second->stream_bytes_read() + stream.second->header_bytes_read();
|
|
999
|
-
if (bytes_read > 0)
|
|
1000
|
-
{
|
|
1001
|
-
preliminary_headers_ = stream.second->preliminary_headers().Clone();
|
|
1002
|
-
break;
|
|
1003
|
-
}
|
|
1004
|
-
}
|
|
1005
|
-
return &preliminary_headers_;
|
|
1006
|
-
}
|
|
1007
|
-
|
|
1008
994
|
const spdy::Http2HeaderBlock &Http3Client::response_trailers() const
|
|
1009
995
|
{
|
|
1010
996
|
return response_trailers_;
|
|
@@ -1042,7 +1028,7 @@ namespace quic
|
|
|
1042
1028
|
|
|
1043
1029
|
void Http3Client::OnCompleteResponse(
|
|
1044
1030
|
QuicStreamId id, const spdy::Http2HeaderBlock &response_headers,
|
|
1045
|
-
const
|
|
1031
|
+
const absl::string_view &response_body)
|
|
1046
1032
|
{
|
|
1047
1033
|
// implement
|
|
1048
1034
|
}
|
|
@@ -1076,8 +1062,11 @@ namespace quic
|
|
|
1076
1062
|
QUIC_LOG(ERROR) << "Invalid :status response header: " << status->second;
|
|
1077
1063
|
}
|
|
1078
1064
|
latest_response_headers_ = response_headers.DebugString();
|
|
1079
|
-
|
|
1080
|
-
|
|
1065
|
+
for (const Http2HeaderBlock &headers :
|
|
1066
|
+
client_stream->preliminary_headers())
|
|
1067
|
+
{
|
|
1068
|
+
absl::StrAppend(&preliminary_response_headers_, headers.DebugString());
|
|
1069
|
+
}
|
|
1081
1070
|
latest_response_header_block_ = response_headers.Clone();
|
|
1082
1071
|
latest_response_body_ = client_stream->data();
|
|
1083
1072
|
latest_response_trailers_ =
|
|
@@ -1101,7 +1090,6 @@ namespace quic
|
|
|
1101
1090
|
client_stream->stream_error(), connected(),
|
|
1102
1091
|
client_stream->headers_decompressed(),
|
|
1103
1092
|
client_stream->response_headers(),
|
|
1104
|
-
client_stream->preliminary_headers(),
|
|
1105
1093
|
(buffer_body() ? client_stream->data() : ""),
|
|
1106
1094
|
client_stream->received_trailers(),
|
|
1107
1095
|
// Use NumBytesConsumed to avoid counting retransmitted stream frames.
|
|
@@ -1226,7 +1214,6 @@ namespace quic
|
|
|
1226
1214
|
response_complete(other.response_complete),
|
|
1227
1215
|
response_headers_complete(other.response_headers_complete),
|
|
1228
1216
|
response_headers(other.response_headers.Clone()),
|
|
1229
|
-
preliminary_headers(other.preliminary_headers.Clone()),
|
|
1230
1217
|
response(other.response),
|
|
1231
1218
|
response_trailers(other.response_trailers.Clone()),
|
|
1232
1219
|
bytes_read(other.bytes_read),
|
|
@@ -1237,14 +1224,12 @@ namespace quic
|
|
|
1237
1224
|
QuicRstStreamErrorCode stream_error, bool response_complete,
|
|
1238
1225
|
bool response_headers_complete,
|
|
1239
1226
|
const spdy::Http2HeaderBlock &response_headers,
|
|
1240
|
-
const spdy::Http2HeaderBlock &
|
|
1241
|
-
const std::string &response, const spdy::Http2HeaderBlock &response_trailers,
|
|
1227
|
+
const absl::string_view response, const spdy::Http2HeaderBlock &response_trailers,
|
|
1242
1228
|
uint64_t bytes_read, uint64_t bytes_written, int64_t response_body_size)
|
|
1243
1229
|
: stream_error(stream_error),
|
|
1244
1230
|
response_complete(response_complete),
|
|
1245
1231
|
response_headers_complete(response_headers_complete),
|
|
1246
1232
|
response_headers(response_headers.Clone()),
|
|
1247
|
-
preliminary_headers(preliminary_headers.Clone()),
|
|
1248
1233
|
response(response),
|
|
1249
1234
|
response_trailers(response_trailers.Clone()),
|
|
1250
1235
|
bytes_read(bytes_read),
|
|
@@ -1286,7 +1271,6 @@ namespace quic
|
|
|
1286
1271
|
response_ = state.response;
|
|
1287
1272
|
response_complete_ = state.response_complete;
|
|
1288
1273
|
response_headers_complete_ = state.response_headers_complete;
|
|
1289
|
-
preliminary_headers_ = state.preliminary_headers.Clone();
|
|
1290
1274
|
response_headers_ = state.response_headers.Clone();
|
|
1291
1275
|
response_trailers_ = state.response_trailers.Clone();
|
|
1292
1276
|
bytes_read_ = state.bytes_read;
|