@fails-components/webtransport 0.3.1 → 1.0.1
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/lib/client.js +81 -40
- package/lib/dom.ts +7 -5
- package/lib/http2/browser/browser.js +168 -0
- package/lib/http2/browser/browserparser.js +248 -0
- package/lib/http2/flowcontroller.js +371 -0
- package/lib/http2/node/capsuleparser.js +291 -0
- package/lib/http2/node/client.js +239 -0
- package/lib/http2/node/index.js +2 -0
- package/lib/http2/node/server.js +499 -0
- package/lib/http2/node/websocketparser.js +829 -0
- package/lib/http2/parserbase.js +139 -0
- package/lib/http2/parserbasehttp2.js +128 -0
- package/lib/http2/session.js +225 -0
- package/lib/http2/stream.js +354 -0
- package/lib/http2/websocketcommon.js +1 -0
- package/lib/{index.js → index.browser.js} +6 -10
- package/lib/index.node.js +27 -0
- package/lib/server.js +252 -69
- package/lib/session.js +31 -68
- package/lib/stream.js +103 -179
- package/lib/types.ts +174 -87
- package/lib/utils.js +2 -1
- package/lib/webstreams.browser.js +6 -0
- package/lib/webstreams.js +7 -0
- package/lib/webtransport.browser.js +284 -0
- package/lib/webtransport.node.js +137 -0
- package/lib/{webtransport.js → webtransportbase.js} +47 -41
- package/old_test/test.js +31 -29
- package/old_test/testsuite.js +1 -1
- package/package.json +18 -17
- package/readme.md +94 -30
- package/test/bidirectional-streams.spec.js +51 -9
- package/test/datagrams.spec.js +8 -2
- package/test/fixtures/known-bytes.js +29 -0
- package/test/fixtures/read-stream.js +1 -1
- package/test/fixtures/reader-value.js +1 -1
- package/test/fixtures/server.js +24 -10
- package/test/fixtures/webtransport.browser.js +20 -2
- package/test/fixtures/webtransport.js +1 -1
- package/test/index.js +33 -6
- package/test/pw-no-https-errors.json +5 -0
- package/test/session.spec.js +71 -52
- package/test/unidirectional-streams.spec.js +20 -4
- package/CMakeLists.txt +0 -991
- package/LICENSE.chromium +0 -27
- package/LICENSE.envoy +0 -207
- package/build.js +0 -313
- package/dist/lib/client.d.ts +0 -78
- package/dist/lib/client.d.ts.map +0 -1
- package/dist/lib/dom.d.ts +0 -87
- package/dist/lib/dom.d.ts.map +0 -1
- package/dist/lib/error.d.ts +0 -8
- package/dist/lib/error.d.ts.map +0 -1
- package/dist/lib/event-loop.d.ts +0 -33
- package/dist/lib/event-loop.d.ts.map +0 -1
- package/dist/lib/index.d.ts +0 -79
- package/dist/lib/index.d.ts.map +0 -1
- package/dist/lib/native.d.ts +0 -2
- package/dist/lib/native.d.ts.map +0 -1
- package/dist/lib/server.d.ts +0 -92
- package/dist/lib/server.d.ts.map +0 -1
- package/dist/lib/session.d.ts +0 -298
- package/dist/lib/session.d.ts.map +0 -1
- package/dist/lib/stream.d.ts +0 -135
- package/dist/lib/stream.d.ts.map +0 -1
- package/dist/lib/transport.d.ts +0 -34
- package/dist/lib/transport.d.ts.map +0 -1
- package/dist/lib/types.d.ts +0 -212
- package/dist/lib/types.d.ts.map +0 -1
- package/dist/lib/utils.d.ts +0 -11
- package/dist/lib/utils.d.ts.map +0 -1
- package/dist/lib/webtransport.d.ts +0 -47
- package/dist/lib/webtransport.d.ts.map +0 -1
- package/dist/test/bidirectional-streams.spec.d.ts +0 -5
- package/dist/test/bidirectional-streams.spec.d.ts.map +0 -1
- package/dist/test/datagrams.spec.d.ts +0 -5
- package/dist/test/datagrams.spec.d.ts.map +0 -1
- package/dist/test/event-loop.node.d.ts +0 -2
- package/dist/test/event-loop.node.d.ts.map +0 -1
- package/dist/test/fixtures/certificate.d.ts +0 -21
- package/dist/test/fixtures/certificate.d.ts.map +0 -1
- package/dist/test/fixtures/chai.d.ts +0 -2
- package/dist/test/fixtures/chai.d.ts.map +0 -1
- package/dist/test/fixtures/known-bytes.d.ts +0 -6
- package/dist/test/fixtures/known-bytes.d.ts.map +0 -1
- package/dist/test/fixtures/p-timeout.d.ts +0 -8
- package/dist/test/fixtures/p-timeout.d.ts.map +0 -1
- package/dist/test/fixtures/read-cert-hash.d.ts +0 -6
- package/dist/test/fixtures/read-cert-hash.d.ts.map +0 -1
- package/dist/test/fixtures/read-stream.d.ts +0 -19
- package/dist/test/fixtures/read-stream.d.ts.map +0 -1
- package/dist/test/fixtures/reader-value.d.ts +0 -22
- package/dist/test/fixtures/reader-value.d.ts.map +0 -1
- package/dist/test/fixtures/server.d.ts +0 -5
- package/dist/test/fixtures/server.d.ts.map +0 -1
- package/dist/test/fixtures/webtransport.browser.d.ts +0 -3
- package/dist/test/fixtures/webtransport.browser.d.ts.map +0 -1
- package/dist/test/fixtures/webtransport.d.ts +0 -3
- package/dist/test/fixtures/webtransport.d.ts.map +0 -1
- package/dist/test/fixtures/write-stream.d.ts +0 -10
- package/dist/test/fixtures/write-stream.d.ts.map +0 -1
- package/dist/test/index.d.ts +0 -2
- package/dist/test/index.d.ts.map +0 -1
- package/dist/test/session.spec.d.ts +0 -5
- package/dist/test/session.spec.d.ts.map +0 -1
- package/dist/test/unidirectional-streams.spec.d.ts +0 -2
- package/dist/test/unidirectional-streams.spec.d.ts.map +0 -1
- package/failslogolicensereadme.txt +0 -4
- package/lib/event-loop.js +0 -88
- package/lib/native.js +0 -28
- package/lib/transport.js +0 -82
- package/platform/icufix/fakedata.cpp +0 -8
- package/platform/quiche/quic/core/io/socket_win.inc +0 -3
- package/platform/quiche_platform_impl/quiche_bug_tracker_impl.h +0 -7
- package/platform/quiche_platform_impl/quiche_client_stats_impl.h +0 -7
- package/platform/quiche_platform_impl/quiche_command_line_flags_impl.h +0 -7
- package/platform/quiche_platform_impl/quiche_containers_impl.h +0 -7
- package/platform/quiche_platform_impl/quiche_event_loop_impl.h +0 -7
- package/platform/quiche_platform_impl/quiche_export_impl.h +0 -6
- package/platform/quiche_platform_impl/quiche_flag_utils_impl.h +0 -11
- package/platform/quiche_platform_impl/quiche_flags_impl.h +0 -8
- package/platform/quiche_platform_impl/quiche_iovec_impl.h +0 -10
- package/platform/quiche_platform_impl/quiche_logging_impl.h +0 -21
- package/platform/quiche_platform_impl/quiche_mem_slice_impl.h +0 -2
- package/platform/quiche_platform_impl/quiche_mutex_impl.h +0 -8
- package/platform/quiche_platform_impl/quiche_prefetch_impl.h +0 -11
- package/platform/quiche_platform_impl/quiche_reference_counted_impl.h +0 -16
- package/platform/quiche_platform_impl/quiche_server_stats_impl.h +0 -7
- package/platform/quiche_platform_impl/quiche_stack_trace_impl.h +0 -12
- package/platform/quiche_platform_impl/quiche_stream_buffer_allocator_impl.h +0 -8
- package/platform/quiche_platform_impl/quiche_testvalue_impl.h +0 -1
- package/platform/quiche_platform_impl/quiche_thread_local_impl.h +0 -6
- package/platform/quiche_platform_impl/quiche_time_utils_impl.h +0 -13
- package/platform/quiche_platform_impl/quiche_udp_socket_platform_impl.h +0 -39
- package/src/http3backendresponse.cc +0 -36
- package/src/http3backendresponse.h +0 -109
- package/src/http3client.cc +0 -1529
- package/src/http3client.h +0 -557
- package/src/http3clientsession.cc +0 -65
- package/src/http3clientsession.h +0 -60
- package/src/http3clientstream.cc +0 -52
- package/src/http3clientstream.h +0 -42
- package/src/http3dispatcher.cc +0 -62
- package/src/http3dispatcher.h +0 -57
- package/src/http3eventloop.cc +0 -1107
- package/src/http3eventloop.h +0 -316
- package/src/http3server.cc +0 -514
- package/src/http3server.h +0 -151
- package/src/http3serverbackend.cc +0 -105
- package/src/http3serverbackend.h +0 -98
- package/src/http3serversession.cc +0 -123
- package/src/http3serversession.h +0 -95
- package/src/http3serverstream.cc +0 -463
- package/src/http3serverstream.h +0 -114
- package/src/http3sessioncache.cc +0 -85
- package/src/http3sessioncache.h +0 -59
- package/src/http3wtsessionvisitor.cc +0 -46
- package/src/http3wtsessionvisitor.h +0 -397
- package/src/http3wtstreamvisitor.cc +0 -155
- package/src/http3wtstreamvisitor.h +0 -404
- package/test/event-loop.node.js +0 -24
- package/tsconfig.json +0 -39
package/lib/server.js
CHANGED
|
@@ -1,36 +1,136 @@
|
|
|
1
|
-
import { Http3WebTransport } from './transport.js'
|
|
2
1
|
import { ReadableStream } from 'node:stream/web'
|
|
3
|
-
import {
|
|
2
|
+
import { HttpWTSession } from './session.js'
|
|
3
|
+
import { WebTransportError } from './error.js'
|
|
4
|
+
import { Http2WebTransportServer } from './http2/node/index.js'
|
|
4
5
|
import { isIPv4 } from 'net'
|
|
5
6
|
import { defer, logger } from './utils.js'
|
|
6
7
|
|
|
7
|
-
const log = logger(`webtransport:
|
|
8
|
+
const log = logger(`webtransport:httpserver(${process?.pid})`)
|
|
8
9
|
|
|
9
10
|
/**
|
|
10
|
-
* @
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
* @
|
|
11
|
+
* @type {(arg: { path: string; } | undefined) => void}
|
|
12
|
+
*/
|
|
13
|
+
let checkQuicheInit
|
|
14
|
+
/**
|
|
15
|
+
* @type {new (arg: import("./types").HttpServerInit) => any}
|
|
16
|
+
*/
|
|
17
|
+
let Http3WebTransportServer
|
|
18
|
+
/**
|
|
19
|
+
* @type {new (arg: import("./types").HttpServerInit) => any}
|
|
20
|
+
*/
|
|
21
|
+
let Http3WebTransportServerSocket
|
|
22
|
+
const quicheLoaded = new Promise((resolve, reject) => {
|
|
23
|
+
// @ts-ignore
|
|
24
|
+
import('@fails-components/webtransport-transport-http3-quiche')
|
|
25
|
+
.then(
|
|
26
|
+
/**
|
|
27
|
+
* @type {import("./types").TransportHttp3Quiche}
|
|
28
|
+
*/
|
|
29
|
+
(http3lib) => {
|
|
30
|
+
;({
|
|
31
|
+
checkQuicheInit,
|
|
32
|
+
Http3WebTransportServer,
|
|
33
|
+
Http3WebTransportServerSocket
|
|
34
|
+
} = http3lib)
|
|
35
|
+
resolve(undefined)
|
|
36
|
+
}
|
|
37
|
+
)
|
|
38
|
+
.catch((error) => {
|
|
39
|
+
console.error('Problem loading http3-quiche transport')
|
|
40
|
+
console.error(
|
|
41
|
+
'Did you install @fails-components/webtransport-transport-http3-quiche?'
|
|
42
|
+
)
|
|
43
|
+
log('Problem loading http3-quiche transport', error)
|
|
44
|
+
log(
|
|
45
|
+
'Did you install @fails-components/webtransport-transport-http3-quiche?'
|
|
46
|
+
)
|
|
47
|
+
reject(error)
|
|
48
|
+
})
|
|
49
|
+
}).catch((error) => {
|
|
50
|
+
console.log('http3 loader:', error)
|
|
51
|
+
})
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* @typedef {import('./types').WebTransportSessionImpl} WebTransportSession
|
|
55
|
+
* @typedef {import('./types').NativeHttpWTSession} NativeHttpWTSession
|
|
56
|
+
* @typedef {import('./types').HttpServerEventHandler} HttpServerEventHandler
|
|
57
|
+
* @typedef {import('./types').HttpWTServerSessionVisitorEvent} HttpWTServerSessionVisitorEvent
|
|
58
|
+
* @typedef {import('./types').HttpServerListeningEvent} HttpServerListeningEvent
|
|
15
59
|
* @typedef {import('./types').ServerSessionRequestEvent} ServerSessionRequestEvent
|
|
16
|
-
* @typedef {import('./types').
|
|
60
|
+
* @typedef {import('./types').HttpServerInit} HttpServerInit
|
|
17
61
|
*/
|
|
18
62
|
|
|
63
|
+
// @ts-ignore
|
|
64
|
+
class TransportIntServerProxy {
|
|
65
|
+
/**
|
|
66
|
+
* @param {Array<any>} transportInts
|
|
67
|
+
* */
|
|
68
|
+
constructor(transportInts) {
|
|
69
|
+
this.transportsInts = new Set(transportInts)
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
startServer() {
|
|
73
|
+
this.transportsInts.forEach((transport) => {
|
|
74
|
+
if (transport.startServer) transport.startServer()
|
|
75
|
+
})
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
stopServer() {
|
|
79
|
+
this.transportsInts.forEach((transport) => {
|
|
80
|
+
if (transport.stopServer) transport.stopServer()
|
|
81
|
+
})
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* @param {string} cert
|
|
86
|
+
* @param {string} privKey
|
|
87
|
+
* @param {boolean} http2only
|
|
88
|
+
* */
|
|
89
|
+
updateCert(cert, privKey, http2only) {
|
|
90
|
+
this.transportsInts.forEach((transport) => {
|
|
91
|
+
if (transport.updateCert) transport.updateCert(cert, privKey, http2only)
|
|
92
|
+
})
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* @param {boolean} hasHandler
|
|
97
|
+
*/
|
|
98
|
+
setJSRequestHandler(hasHandler) {
|
|
99
|
+
this.transportsInts.forEach((transport) =>
|
|
100
|
+
transport.setJSRequestHandler(hasHandler)
|
|
101
|
+
)
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* @param {string} path
|
|
106
|
+
*/
|
|
107
|
+
addPath(path) {
|
|
108
|
+
this.transportsInts.forEach((transport) => transport.addPath(path))
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
set jsobj(newJSobj) {
|
|
112
|
+
this.transportsInts.forEach((transport) => (transport.jsobj = newJSobj))
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
get jsobj() {
|
|
116
|
+
return this.transportsInts.values().next().value
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
19
120
|
/**
|
|
20
|
-
* @implements {
|
|
121
|
+
* @implements {HttpServerEventHandler}
|
|
21
122
|
*/
|
|
22
|
-
export class
|
|
123
|
+
export class HttpServer {
|
|
23
124
|
/**
|
|
24
125
|
*
|
|
25
|
-
* @param {
|
|
126
|
+
* @param {HttpServerInit} args
|
|
26
127
|
*/
|
|
27
128
|
constructor(args) {
|
|
28
|
-
|
|
29
|
-
|
|
129
|
+
this.args = args
|
|
30
130
|
/** @type {Record<string, ReadableStream>} */
|
|
31
131
|
this.sessionStreams = {}
|
|
32
132
|
|
|
33
|
-
/** @type {Record<string, ReadableStreamDefaultController<
|
|
133
|
+
/** @type {Record<string, ReadableStreamDefaultController<HttpWTSession>>} */
|
|
34
134
|
this.sessionController = {}
|
|
35
135
|
|
|
36
136
|
this.port = null
|
|
@@ -45,11 +145,33 @@ export class Http3Server extends Http3WebTransport {
|
|
|
45
145
|
|
|
46
146
|
this._closed = defer()
|
|
47
147
|
this.closed = this._closed.promise
|
|
148
|
+
/**
|
|
149
|
+
* @type {string[]}
|
|
150
|
+
*/
|
|
151
|
+
this._pendingPaths = []
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* @type {undefined|boolean}
|
|
155
|
+
*/
|
|
156
|
+
this._pendingRequestCallback = undefined
|
|
48
157
|
}
|
|
49
158
|
|
|
50
159
|
startServer() {
|
|
51
160
|
this.createTransportInt()
|
|
52
|
-
|
|
161
|
+
.then(() => {
|
|
162
|
+
if (this.transportInt.startServer) this.transportInt.startServer()
|
|
163
|
+
while (this._pendingPaths.length > 0) {
|
|
164
|
+
const path = this._pendingPaths.shift()
|
|
165
|
+
this.transportInt.addPath(path)
|
|
166
|
+
}
|
|
167
|
+
if (typeof this._pendingRequestCallback !== 'undefined') {
|
|
168
|
+
this.transportInt.setJSRequestHandler(this._pendingRequestCallback)
|
|
169
|
+
delete this._pendingRequestCallback
|
|
170
|
+
}
|
|
171
|
+
})
|
|
172
|
+
.catch((error) => {
|
|
173
|
+
log('Problem in startServer', error)
|
|
174
|
+
})
|
|
53
175
|
}
|
|
54
176
|
|
|
55
177
|
stopServer() {
|
|
@@ -61,12 +183,21 @@ export class Http3Server extends Http3WebTransport {
|
|
|
61
183
|
this.stopped = true
|
|
62
184
|
}
|
|
63
185
|
|
|
186
|
+
/**
|
|
187
|
+
* @param {string} cert
|
|
188
|
+
* @param {string} privKey
|
|
189
|
+
* @param {boolean} http2only
|
|
190
|
+
* */
|
|
191
|
+
updateCert(cert, privKey, http2only) {
|
|
192
|
+
if (this.transportInt.updateCert)
|
|
193
|
+
this.transportInt.updateCert(cert, privKey, http2only)
|
|
194
|
+
}
|
|
195
|
+
|
|
64
196
|
/**
|
|
65
197
|
* @returns {{ port: number, host: string, family: 'IPv4' | 'IPv6' } | null}
|
|
66
198
|
*/
|
|
67
199
|
address() {
|
|
68
200
|
if (this.port == null || this.host == null) {
|
|
69
|
-
console.info('returning null')
|
|
70
201
|
return null
|
|
71
202
|
}
|
|
72
203
|
|
|
@@ -84,6 +215,8 @@ export class Http3Server extends Http3WebTransport {
|
|
|
84
215
|
this.requestHandler = callback
|
|
85
216
|
|
|
86
217
|
this.transportInt.setJSRequestHandler(!!callback)
|
|
218
|
+
if (this.transportInt) this.transportInt.setJSRequestHandler(!!callback)
|
|
219
|
+
else this._pendingRequestCallback = !!callback
|
|
87
220
|
}
|
|
88
221
|
|
|
89
222
|
/**
|
|
@@ -102,7 +235,8 @@ export class Http3Server extends Http3WebTransport {
|
|
|
102
235
|
}
|
|
103
236
|
})
|
|
104
237
|
if (!args || !args.noAutoPaths) {
|
|
105
|
-
this.transportInt.addPath(path)
|
|
238
|
+
if (this.transportInt) this.transportInt.addPath(path)
|
|
239
|
+
else this._pendingPaths.push(path)
|
|
106
240
|
}
|
|
107
241
|
return this.sessionStreams[path]
|
|
108
242
|
}
|
|
@@ -116,10 +250,11 @@ export class Http3Server extends Http3WebTransport {
|
|
|
116
250
|
this.requestHandler({ header: args.header })
|
|
117
251
|
.then((/** @type {any} */ result) => {
|
|
118
252
|
log('oSR', result)
|
|
119
|
-
|
|
253
|
+
args.object.finishSessionRequest({
|
|
120
254
|
promise: args.promise,
|
|
121
255
|
header: args.header,
|
|
122
256
|
session: args.session,
|
|
257
|
+
head: args.head,
|
|
123
258
|
...result
|
|
124
259
|
})
|
|
125
260
|
})
|
|
@@ -130,30 +265,33 @@ export class Http3Server extends Http3WebTransport {
|
|
|
130
265
|
}
|
|
131
266
|
|
|
132
267
|
/**
|
|
133
|
-
* @param {
|
|
268
|
+
* @param {HttpWTServerSessionVisitorEvent} args
|
|
134
269
|
*/
|
|
135
|
-
|
|
270
|
+
onHttpWTSessionVisitor(args) {
|
|
136
271
|
// create Http3 Visitor
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
} else throw new Error('Http3WTSessionVisitor')
|
|
272
|
+
const sesobj = new HttpWTSession({
|
|
273
|
+
object: args.session,
|
|
274
|
+
header: args.header,
|
|
275
|
+
parentobj: this
|
|
276
|
+
})
|
|
277
|
+
args.session.jsobj = sesobj
|
|
278
|
+
if (this.sessionController[args.path])
|
|
279
|
+
this.sessionController[args.path].enqueue(sesobj)
|
|
146
280
|
}
|
|
147
281
|
|
|
148
282
|
/**
|
|
283
|
+
* @param {Error} [error]
|
|
149
284
|
*/
|
|
150
|
-
onServerError() {
|
|
151
|
-
this._ready.reject()
|
|
285
|
+
onServerError(error) {
|
|
286
|
+
this._ready.reject(error)
|
|
152
287
|
}
|
|
153
288
|
|
|
154
289
|
/**
|
|
290
|
+
* @param {HttpServerListeningEvent} evt
|
|
155
291
|
*/
|
|
156
|
-
onServerListening() {
|
|
292
|
+
onServerListening(evt) {
|
|
293
|
+
if (evt.host) this.host = evt.host
|
|
294
|
+
if (evt.port) this.port = evt.port
|
|
157
295
|
this._ready.resolve()
|
|
158
296
|
}
|
|
159
297
|
|
|
@@ -164,49 +302,94 @@ export class Http3Server extends Http3WebTransport {
|
|
|
164
302
|
}
|
|
165
303
|
|
|
166
304
|
/**
|
|
167
|
-
* @param
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
if (
|
|
171
|
-
|
|
305
|
+
* @param{{path: string} |undefined} [args]
|
|
306
|
+
**/
|
|
307
|
+
async createTransportInt(args) {
|
|
308
|
+
if (this.transportInt != null) {
|
|
309
|
+
return
|
|
310
|
+
}
|
|
172
311
|
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
this.
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
}
|
|
312
|
+
if (
|
|
313
|
+
// @ts-ignore
|
|
314
|
+
this.args &&
|
|
315
|
+
// @ts-ignore
|
|
316
|
+
(this.args?.reliability === 'unreliableOnly' ||
|
|
317
|
+
// @ts-ignore
|
|
318
|
+
typeof this.args?.reliability === 'undefined' ||
|
|
319
|
+
// @ts-ignore
|
|
320
|
+
this.args?.reliability === 'both')
|
|
321
|
+
) {
|
|
322
|
+
await quicheLoaded
|
|
323
|
+
checkQuicheInit(args)
|
|
186
324
|
}
|
|
187
|
-
}
|
|
188
325
|
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
326
|
+
try {
|
|
327
|
+
let socket
|
|
328
|
+
// @ts-ignore
|
|
329
|
+
const reliability = this.args?.reliability || 'unreliableOnly'
|
|
330
|
+
switch (reliability) {
|
|
331
|
+
case 'unreliableOnly':
|
|
332
|
+
socket = new Http3WebTransportServerSocket(this.args)
|
|
333
|
+
this.transportInt = new Http3WebTransportServer(this.args)
|
|
334
|
+
this.transportInt.stopServer = socket.stopServer.bind(socket)
|
|
335
|
+
socket.init()
|
|
336
|
+
socket.cobj = this.transportInt
|
|
337
|
+
// @ts-ignore
|
|
338
|
+
socket.jsobj = this
|
|
339
|
+
// @ts-ignore
|
|
340
|
+
this.transportInt.socket = socket
|
|
199
341
|
break
|
|
200
|
-
case '
|
|
201
|
-
|
|
342
|
+
case 'reliableOnly':
|
|
343
|
+
// @ts-ignore
|
|
344
|
+
this.transportInt = new Http2WebTransportServer(this.args)
|
|
202
345
|
break
|
|
203
|
-
case '
|
|
204
|
-
|
|
346
|
+
case 'both':
|
|
347
|
+
{
|
|
348
|
+
socket = new Http3WebTransportServerSocket(this.args)
|
|
349
|
+
const server3 = new Http3WebTransportServer(this.args)
|
|
350
|
+
server3.stopServer = socket.stopServer.bind(socket)
|
|
351
|
+
socket.init()
|
|
352
|
+
server3.socket = socket
|
|
353
|
+
socket.cobj = server3
|
|
354
|
+
// @ts-ignore
|
|
355
|
+
socket.jsobj = this
|
|
356
|
+
// @ts-ignore
|
|
357
|
+
const server2 = new Http2WebTransportServer(this.args)
|
|
358
|
+
server2.jsobj = this
|
|
359
|
+
this.transportInt = new TransportIntServerProxy([server2, server3])
|
|
360
|
+
}
|
|
205
361
|
break
|
|
206
|
-
default: {
|
|
207
|
-
throw new Error('unknown purpose')
|
|
208
|
-
}
|
|
209
362
|
}
|
|
363
|
+
} catch (/** @type {any} */ err) {
|
|
364
|
+
const error = new WebTransportError('Opening handshake failed.')
|
|
365
|
+
error.stack = err.stack
|
|
366
|
+
|
|
367
|
+
throw error
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
this.transportInt.jsobj = this
|
|
371
|
+
if (this.transportInt.createTransport) {
|
|
372
|
+
this.transportInt.createTransport()
|
|
210
373
|
}
|
|
211
374
|
}
|
|
212
375
|
}
|
|
376
|
+
|
|
377
|
+
export class Http3Server extends HttpServer {
|
|
378
|
+
/**
|
|
379
|
+
*
|
|
380
|
+
* @param {HttpServerInit} args
|
|
381
|
+
*/
|
|
382
|
+
constructor(args) {
|
|
383
|
+
super({ ...args, reliability: 'unreliableOnly' })
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
export class Http2Server extends HttpServer {
|
|
388
|
+
/**
|
|
389
|
+
*
|
|
390
|
+
* @param {HttpServerInit} args
|
|
391
|
+
*/
|
|
392
|
+
constructor(args) {
|
|
393
|
+
super({ ...args, reliability: 'reliableOnly' })
|
|
394
|
+
}
|
|
395
|
+
}
|
package/lib/session.js
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import { ReadableStream, WritableStream } from '
|
|
2
|
-
import {
|
|
1
|
+
import { ReadableStream, WritableStream } from './webstreams.js'
|
|
2
|
+
import { HttpWTStream } from './stream.js'
|
|
3
3
|
import { WebTransportError } from './error.js'
|
|
4
4
|
import { logger } from './utils.js'
|
|
5
5
|
|
|
6
|
-
const
|
|
6
|
+
const pid = typeof process !== 'undefined' ? process.pid : 0
|
|
7
|
+
const log = logger(`webtransport:httpwtsession(${pid})`)
|
|
7
8
|
|
|
8
9
|
/**
|
|
9
10
|
* WebTransport session events
|
|
@@ -27,13 +28,13 @@ const log = logger(`webtransport:http3wtsession(${process.pid})`)
|
|
|
27
28
|
* @typedef {import('./dom').WebTransportStats} WebTransportStats
|
|
28
29
|
* @typedef {import('./dom').WebTransportDatagramStats} WebTransportDatagramStats
|
|
29
30
|
*
|
|
30
|
-
* @typedef {import('./types').
|
|
31
|
+
* @typedef {import('./types').NativeHttpWTSession} NativeHttpWTSession
|
|
31
32
|
*
|
|
32
33
|
* Public API
|
|
33
|
-
* @typedef {import('./types').
|
|
34
|
+
* @typedef {import('./types').WebTransportSessionImpl} WebTransportSession
|
|
34
35
|
*
|
|
35
|
-
* @typedef {import('./server').
|
|
36
|
-
* @typedef {import('./client').
|
|
36
|
+
* @typedef {import('./server').HttpServer} HttpServer
|
|
37
|
+
* @typedef {import('./client').HttpClient} HttpClient
|
|
37
38
|
*
|
|
38
39
|
* @typedef {import('stream/web').WritableStreamDefaultController} WritableStreamDefaultController
|
|
39
40
|
*/
|
|
@@ -42,17 +43,20 @@ const log = logger(`webtransport:http3wtsession(${process.pid})`)
|
|
|
42
43
|
* @implements {WebTransportSessionEventHandler}
|
|
43
44
|
* @implements {WebTransportSession}
|
|
44
45
|
*/
|
|
45
|
-
export class
|
|
46
|
+
export class HttpWTSession {
|
|
46
47
|
/**
|
|
47
48
|
* @param {object} args
|
|
48
|
-
* @param {import('./types').
|
|
49
|
-
* @param {
|
|
49
|
+
* @param {import('./types').NativeHttpWTSession} [args.object]
|
|
50
|
+
* @param {HttpServer | HttpClient} args.parentobj
|
|
50
51
|
* @param {any | undefined} [args.header= undefined]
|
|
51
52
|
*/
|
|
52
53
|
constructor(args) {
|
|
53
54
|
if (args.object) {
|
|
54
55
|
this.objint = args.object
|
|
55
56
|
this.objint.jsobj = this
|
|
57
|
+
if (this.objint.sendInitialParameters) {
|
|
58
|
+
this.objint.sendInitialParameters()
|
|
59
|
+
}
|
|
56
60
|
}
|
|
57
61
|
this.parentobj = args.parentobj
|
|
58
62
|
/** @type {import('./types').WebTransportSessionState} */
|
|
@@ -87,6 +91,7 @@ export class Http3WTSession {
|
|
|
87
91
|
})
|
|
88
92
|
|
|
89
93
|
/** @type {ReadableStream<WebTransportBidirectionalStream>} */
|
|
94
|
+
// @ts-ignore
|
|
90
95
|
this.incomingBidirectionalStreams = new ReadableStream({
|
|
91
96
|
/** @param {ReadableStreamDefaultController<WebTransportBidirectionalStream>} controller */
|
|
92
97
|
start: (controller) => {
|
|
@@ -94,6 +99,7 @@ export class Http3WTSession {
|
|
|
94
99
|
}
|
|
95
100
|
})
|
|
96
101
|
/** @type {ReadableStream<WebTransportReceiveStream>} */
|
|
102
|
+
// @ts-ignore
|
|
97
103
|
this.incomingUnidirectionalStreams = new ReadableStream({
|
|
98
104
|
/** @param {ReadableStreamDefaultController<WebTransportReceiveStream>} controller */
|
|
99
105
|
start: (controller) => {
|
|
@@ -111,6 +117,7 @@ export class Http3WTSession {
|
|
|
111
117
|
/** @type {WebTransportDatagramDuplexStream} */
|
|
112
118
|
this.datagrams = {
|
|
113
119
|
/** @type {ReadableStream<Uint8Array>} */
|
|
120
|
+
// @ts-ignore
|
|
114
121
|
readable: new ReadableStream({
|
|
115
122
|
start: (
|
|
116
123
|
/** @type {import("stream/web").ReadableByteStreamController} */ controller
|
|
@@ -169,7 +176,7 @@ export class Http3WTSession {
|
|
|
169
176
|
this.sendStreams = new Set()
|
|
170
177
|
/** @type {Set<WebTransportReceiveStream>} */
|
|
171
178
|
this.receiveStreams = new Set()
|
|
172
|
-
/** @type {Set<
|
|
179
|
+
/** @type {Set<HttpWTStream>} */
|
|
173
180
|
this.streamObjs = new Set()
|
|
174
181
|
|
|
175
182
|
/** @type {Set<WritableStreamDefaultController>} */
|
|
@@ -179,12 +186,14 @@ export class Http3WTSession {
|
|
|
179
186
|
}
|
|
180
187
|
|
|
181
188
|
/**
|
|
182
|
-
* @param {
|
|
189
|
+
* @param {NativeHttpWTSession} object
|
|
190
|
+
* @param {boolean} reliable
|
|
183
191
|
*/
|
|
184
|
-
setSessionObj(object) {
|
|
192
|
+
setSessionObj(object, reliable) {
|
|
185
193
|
if (object) {
|
|
186
194
|
this.objint = object
|
|
187
195
|
this.objint.jsobj = this
|
|
196
|
+
this.reliable = !!reliable
|
|
188
197
|
}
|
|
189
198
|
}
|
|
190
199
|
|
|
@@ -275,14 +284,14 @@ export class Http3WTSession {
|
|
|
275
284
|
}
|
|
276
285
|
|
|
277
286
|
/**
|
|
278
|
-
* @param {
|
|
287
|
+
* @param {HttpWTStream} stream
|
|
279
288
|
*/
|
|
280
289
|
addStreamObj(stream) {
|
|
281
290
|
this.streamObjs.add(stream)
|
|
282
291
|
}
|
|
283
292
|
|
|
284
293
|
/**
|
|
285
|
-
* @param {
|
|
294
|
+
* @param {HttpWTStream} stream
|
|
286
295
|
*/
|
|
287
296
|
removeStreamObj(stream) {
|
|
288
297
|
this.streamObjs.delete(stream)
|
|
@@ -375,7 +384,8 @@ export class Http3WTSession {
|
|
|
375
384
|
|
|
376
385
|
onReady(/* error */) {
|
|
377
386
|
this.state = 'connected'
|
|
378
|
-
this.reliability = 'supports-unreliable'
|
|
387
|
+
if (!this.reliable) this.reliability = 'supports-unreliable'
|
|
388
|
+
else this.reliability = 'reliable-only'
|
|
379
389
|
if (this.readyResolve) this.readyResolve()
|
|
380
390
|
delete this.readyResolve
|
|
381
391
|
}
|
|
@@ -407,6 +417,8 @@ export class Http3WTSession {
|
|
|
407
417
|
}
|
|
408
418
|
|
|
409
419
|
log('onClose')
|
|
420
|
+
this.streamObjs.forEach((ele) => ele.finalDrain())
|
|
421
|
+
|
|
410
422
|
const error = new WebTransportError('Session closed')
|
|
411
423
|
|
|
412
424
|
for (const rej of this.rejectBiDi) rej(error)
|
|
@@ -435,7 +447,7 @@ export class Http3WTSession {
|
|
|
435
447
|
this.state = 'closed'
|
|
436
448
|
|
|
437
449
|
const wtError = new WebTransportError(
|
|
438
|
-
`Session closed (on process ${
|
|
450
|
+
`Session closed (on process ${pid}) with code ` +
|
|
439
451
|
args.errorcode +
|
|
440
452
|
' and reason' +
|
|
441
453
|
args.error
|
|
@@ -467,7 +479,7 @@ export class Http3WTSession {
|
|
|
467
479
|
* @param {NewStreamEvent} args
|
|
468
480
|
*/
|
|
469
481
|
onStream(args) {
|
|
470
|
-
const strobj = new
|
|
482
|
+
const strobj = new HttpWTStream({
|
|
471
483
|
object: args.stream,
|
|
472
484
|
parentobj: this,
|
|
473
485
|
transport: this.parentobj,
|
|
@@ -537,7 +549,7 @@ export class Http3WTSession {
|
|
|
537
549
|
destview.set(args.datagram)
|
|
538
550
|
byob.respond(args.datagram.byteLength)
|
|
539
551
|
}
|
|
540
|
-
this.incomDatagramController.enqueue(args.datagram)
|
|
552
|
+
this.incomDatagramController.enqueue(new Uint8Array(args.datagram))
|
|
541
553
|
}
|
|
542
554
|
|
|
543
555
|
/**
|
|
@@ -561,53 +573,4 @@ export class Http3WTSession {
|
|
|
561
573
|
if (this.drainingResolve) this.drainingResolve(undefined)
|
|
562
574
|
this.state = 'draining'
|
|
563
575
|
}
|
|
564
|
-
|
|
565
|
-
/**
|
|
566
|
-
* @param {SessionReadyEvent | SessionCloseEvent | DatagramReceivedEvent | DatagramSendEvent | GoawayReceivedEvent | SessionStatsEvent | DatagramStatsEvent | NewStreamEvent} args
|
|
567
|
-
*/
|
|
568
|
-
static callback(args) {
|
|
569
|
-
log('callback', args?.purpose)
|
|
570
|
-
log.trace(args)
|
|
571
|
-
|
|
572
|
-
if (!args || !args.object || !args.object.jsobj)
|
|
573
|
-
throw new Error('Session callback without jsobj')
|
|
574
|
-
const visitor = args.object.jsobj
|
|
575
|
-
if (args.purpose) {
|
|
576
|
-
switch (args.purpose) {
|
|
577
|
-
case 'SessionReady':
|
|
578
|
-
visitor.onReady(args)
|
|
579
|
-
break
|
|
580
|
-
case 'SessionClose':
|
|
581
|
-
visitor.onClose(args)
|
|
582
|
-
break
|
|
583
|
-
case 'DatagramReceived':
|
|
584
|
-
if (visitor && Object.prototype.hasOwnProperty.call(args, 'datagram'))
|
|
585
|
-
visitor.onDatagramReceived(args)
|
|
586
|
-
break
|
|
587
|
-
case 'DatagramSend':
|
|
588
|
-
if (visitor) visitor.onDatagramSend(args)
|
|
589
|
-
break
|
|
590
|
-
case 'GoawayReceived':
|
|
591
|
-
visitor.onGoAwayReceived(args)
|
|
592
|
-
break
|
|
593
|
-
case 'SessionStats':
|
|
594
|
-
visitor.onSessionStats(args)
|
|
595
|
-
break
|
|
596
|
-
case 'DatagramStats':
|
|
597
|
-
visitor.onDatagramStats(args)
|
|
598
|
-
break
|
|
599
|
-
case 'Http3WTStreamVisitor':
|
|
600
|
-
if (
|
|
601
|
-
visitor &&
|
|
602
|
-
Object.prototype.hasOwnProperty.call(args, 'bidirectional') &&
|
|
603
|
-
Object.prototype.hasOwnProperty.call(args, 'incoming')
|
|
604
|
-
) {
|
|
605
|
-
visitor.onStream(args)
|
|
606
|
-
} else throw new Error('Malformed Http3WTStreamVisitor')
|
|
607
|
-
break
|
|
608
|
-
default:
|
|
609
|
-
throw new Error('unknown purpose Sessioncb')
|
|
610
|
-
}
|
|
611
|
-
} else throw new Error('no purpose Sessioncb')
|
|
612
|
-
}
|
|
613
576
|
}
|