@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
|
@@ -0,0 +1,284 @@
|
|
|
1
|
+
import { WebTransportBase } from './webtransportbase.js'
|
|
2
|
+
import { HttpWTSession } from './session.js'
|
|
3
|
+
import { HttpClient } from './client.js'
|
|
4
|
+
import { Http2WebTransportBrowser } from './http2/browser/browser.js'
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* @typedef {import('./dom').WebTransport} WebTransport
|
|
8
|
+
* @typedef {import('./dom').WebTransportCloseInfo} WebTransportCloseInfo
|
|
9
|
+
* @typedef {import('./dom').WebTransportBidirectionalStream} WebTransportBidirectionalStream
|
|
10
|
+
* @typedef {import('./dom').WebTransportReceiveStream} WebTransportReceiveStream
|
|
11
|
+
* @typedef {import('./error').WebTransportError} WebTransportError
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* @template T
|
|
16
|
+
* @typedef {import('node:stream/web').ReadableStream<T>} ReadableStream<T>
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* @typedef {import('./dom').WebTransport} WebTransportInterface
|
|
21
|
+
*
|
|
22
|
+
* @implements {WebTransportInterface}
|
|
23
|
+
*/
|
|
24
|
+
export class WebTransportPonyfill extends WebTransportBase {
|
|
25
|
+
/**
|
|
26
|
+
* @param{{client: HttpClient, sessionint: HttpWTSession, ourl: URL}} args
|
|
27
|
+
*/
|
|
28
|
+
startUpConnection({ client, sessionint, ourl }) {
|
|
29
|
+
client
|
|
30
|
+
.handleConnection({ createTransport: true, path: ourl.pathname })
|
|
31
|
+
.then(() => client.createWTSession(sessionint, ourl.pathname))
|
|
32
|
+
.catch((error) => {
|
|
33
|
+
client.closeHookSession()
|
|
34
|
+
sessionint.readyReject(error)
|
|
35
|
+
sessionint.closedReject(error)
|
|
36
|
+
})
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
get supportsReliableOnly() {
|
|
40
|
+
return true
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* @param{import('./types.js').HttpWebTransportInit} args
|
|
45
|
+
* @return {{sessionint: HttpWTSession, client: HttpClient}}
|
|
46
|
+
*/
|
|
47
|
+
createClient(args) {
|
|
48
|
+
this.curtype = 'websocket'
|
|
49
|
+
const client = new HttpClient({
|
|
50
|
+
createReliableClient: (client) => {
|
|
51
|
+
// @ts-ignore
|
|
52
|
+
return new Http2WebTransportBrowser({ ...args })
|
|
53
|
+
},
|
|
54
|
+
...args
|
|
55
|
+
})
|
|
56
|
+
const sessionint = new HttpWTSession({
|
|
57
|
+
/* object: args.session, */
|
|
58
|
+
parentobj: client
|
|
59
|
+
})
|
|
60
|
+
return { client, sessionint }
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export class WebTransportPolyfill {
|
|
65
|
+
/**
|
|
66
|
+
* @param {string} url
|
|
67
|
+
* @param {import('./dom.js').WebTransportOptions} [args]
|
|
68
|
+
*/
|
|
69
|
+
constructor(url, args) {
|
|
70
|
+
this.curtype = 'native'
|
|
71
|
+
this.closeset = false
|
|
72
|
+
this.allowFallback = true
|
|
73
|
+
this.initiatedFallback = false
|
|
74
|
+
this.args = args
|
|
75
|
+
|
|
76
|
+
this.closed = new Promise((resolve, reject) => {
|
|
77
|
+
this.closeRes = resolve
|
|
78
|
+
this.closeRej = reject
|
|
79
|
+
})
|
|
80
|
+
|
|
81
|
+
this.ready = new Promise((resolve, reject) => {
|
|
82
|
+
this.readyRes = resolve
|
|
83
|
+
this.readyRej = reject
|
|
84
|
+
})
|
|
85
|
+
|
|
86
|
+
this.draining = new Promise((resolve, reject) => {
|
|
87
|
+
this.drainingRes = resolve
|
|
88
|
+
this.drainingRej = reject
|
|
89
|
+
})
|
|
90
|
+
|
|
91
|
+
const initiateFallback = () => {
|
|
92
|
+
this.initiatedFallback = true
|
|
93
|
+
this.curtype = 'websocket'
|
|
94
|
+
this.curtransport = new WebTransportPonyfill(url, args)
|
|
95
|
+
this.curtransport.ready
|
|
96
|
+
.then((val) => this.readyRes(val))
|
|
97
|
+
.catch((error) => this.readyRej(error))
|
|
98
|
+
this.curtransport.closed
|
|
99
|
+
.then((val) => this.closeRes(val))
|
|
100
|
+
.catch((error) => this.closeRej(error))
|
|
101
|
+
this.curtransport.draining
|
|
102
|
+
.then((val) => this.drainingRes(val))
|
|
103
|
+
.catch((error) => this.drainingRej(error))
|
|
104
|
+
}
|
|
105
|
+
// @ts-ignore
|
|
106
|
+
if (globalThis.WebTransport) {
|
|
107
|
+
/** @type {WebTransport|WebTransportPonyfill} */
|
|
108
|
+
// @ts-ignore
|
|
109
|
+
// eslint-disable-next-line no-undef
|
|
110
|
+
this.curtransport = new WebTransport(url, args)
|
|
111
|
+
// if browser takes too long for waiting for client, we use the ponyfill
|
|
112
|
+
setTimeout(() => {
|
|
113
|
+
if (this.allowFallback && !this.closeset) {
|
|
114
|
+
if (
|
|
115
|
+
!this.initiatedFallback &&
|
|
116
|
+
!this.curtransport?.supportsReliableOnly // way how browser signals support for http/2, no polyfill needed in this cases
|
|
117
|
+
) {
|
|
118
|
+
const oldtransport = this.curtransport
|
|
119
|
+
if (oldtransport)
|
|
120
|
+
oldtransport.ready
|
|
121
|
+
.then(async () => {
|
|
122
|
+
oldtransport.close()
|
|
123
|
+
})
|
|
124
|
+
.catch(() => {})
|
|
125
|
+
initiateFallback()
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
}, 2000)
|
|
129
|
+
|
|
130
|
+
this.curtransport.ready
|
|
131
|
+
.then((val) => {
|
|
132
|
+
this.allowFallback = false
|
|
133
|
+
this.readyRes(val)
|
|
134
|
+
})
|
|
135
|
+
.catch((error) => {
|
|
136
|
+
if (this.allowFallback && !this.closeset) {
|
|
137
|
+
if (
|
|
138
|
+
!this.initiatedFallback &&
|
|
139
|
+
!this.curtransport?.supportsReliableOnly // way how browser signals support for http/2, no polyfill needed in this cases
|
|
140
|
+
) {
|
|
141
|
+
initiateFallback()
|
|
142
|
+
}
|
|
143
|
+
} else {
|
|
144
|
+
this.readyRej(error)
|
|
145
|
+
}
|
|
146
|
+
})
|
|
147
|
+
this.curtransport.closed
|
|
148
|
+
.then((val) => {
|
|
149
|
+
if (this.curtype === 'native') this.closeRes(val)
|
|
150
|
+
})
|
|
151
|
+
.catch((error) => {
|
|
152
|
+
if (this.allowFallback && !this.closeset) {
|
|
153
|
+
if (
|
|
154
|
+
!this.initiatedFallback &&
|
|
155
|
+
!this.curtransport?.supportsReliableOnly // way how browser signals support for http/2, no polyfill needed in this cases
|
|
156
|
+
) {
|
|
157
|
+
initiateFallback()
|
|
158
|
+
}
|
|
159
|
+
} else {
|
|
160
|
+
this.closeRej(error)
|
|
161
|
+
}
|
|
162
|
+
})
|
|
163
|
+
if (this.curtransport.draining) {
|
|
164
|
+
// @ts-ignore
|
|
165
|
+
this.curtransport.draining
|
|
166
|
+
.then((/** @type {any} */ val) => {
|
|
167
|
+
if (this.curtype === 'native') this.drainingRes(val)
|
|
168
|
+
})
|
|
169
|
+
.catch((/** @type {WebTransportError} */ error) => {
|
|
170
|
+
if (this.curtype === 'native') this.drainingRej(error)
|
|
171
|
+
})
|
|
172
|
+
}
|
|
173
|
+
} else {
|
|
174
|
+
initiateFallback()
|
|
175
|
+
}
|
|
176
|
+
/** @type {import('./dom').WebTransportDatagramDuplexStream} */
|
|
177
|
+
// @ts-ignore
|
|
178
|
+
this.datagrams = {}
|
|
179
|
+
// @ts-ignore
|
|
180
|
+
// eslint-disable-next-line no-undef
|
|
181
|
+
this.datagrams.readable = new ReadableStream({
|
|
182
|
+
start: async (controller) => {
|
|
183
|
+
await this.ready
|
|
184
|
+
this.datagramsReader = this.curtransport.datagrams.readable.getReader()
|
|
185
|
+
},
|
|
186
|
+
pull: async (controller) => {
|
|
187
|
+
const { value, done } = await this.datagramsReader.read()
|
|
188
|
+
if (value) controller.enqueue(value)
|
|
189
|
+
if (done) controller.close()
|
|
190
|
+
},
|
|
191
|
+
cancel: async (reason) => {
|
|
192
|
+
await this.datagramsReader.cancel(reason)
|
|
193
|
+
}
|
|
194
|
+
})
|
|
195
|
+
// @ts-ignore
|
|
196
|
+
// eslint-disable-next-line no-undef
|
|
197
|
+
this.datagrams.writable = new WritableStream({
|
|
198
|
+
start: async (controller) => {
|
|
199
|
+
await this.ready
|
|
200
|
+
this.datagramsWriter = this.curtransport.datagrams.writable.getWriter()
|
|
201
|
+
},
|
|
202
|
+
write: async (chunk, controller) => {
|
|
203
|
+
await this.datagramsWriter.write(chunk)
|
|
204
|
+
},
|
|
205
|
+
abort: async (reason) => {
|
|
206
|
+
await this.datagramsWriter.abort(reason)
|
|
207
|
+
},
|
|
208
|
+
close: async () => {
|
|
209
|
+
await this.datagramsWriter.close()
|
|
210
|
+
}
|
|
211
|
+
})
|
|
212
|
+
// eslint-disable-next-line no-undef
|
|
213
|
+
this.incomingBidirectionalStreams = new ReadableStream({
|
|
214
|
+
start: async (controller) => {
|
|
215
|
+
await this.ready
|
|
216
|
+
this.incomingBidirectionalStreamsReader =
|
|
217
|
+
this.curtransport.incomingBidirectionalStreams.getReader()
|
|
218
|
+
},
|
|
219
|
+
pull: async (controller) => {
|
|
220
|
+
const { value, done } =
|
|
221
|
+
await this.incomingBidirectionalStreamsReader.read()
|
|
222
|
+
if (value) controller.enqueue(value)
|
|
223
|
+
if (done) controller.close()
|
|
224
|
+
},
|
|
225
|
+
cancel: async (reason) => {
|
|
226
|
+
await this.incomingBidirectionalStreamsReader.cancel(reason)
|
|
227
|
+
}
|
|
228
|
+
})
|
|
229
|
+
// eslint-disable-next-line no-undef
|
|
230
|
+
this.incomingUnidirectionalStreams = new ReadableStream({
|
|
231
|
+
start: async (controller) => {
|
|
232
|
+
await this.ready
|
|
233
|
+
this.incomingUnidirectionalStreamsReader =
|
|
234
|
+
this.curtransport.incomingUnidirectionalStreams.getReader()
|
|
235
|
+
},
|
|
236
|
+
pull: async (controller) => {
|
|
237
|
+
const { value, done } =
|
|
238
|
+
await this.incomingUnidirectionalStreamsReader.read()
|
|
239
|
+
if (value) controller.enqueue(value)
|
|
240
|
+
if (done) controller.close()
|
|
241
|
+
},
|
|
242
|
+
cancel: async (reason) => {
|
|
243
|
+
await this.incomingUnidirectionalStreamsReader.cancel(reason)
|
|
244
|
+
}
|
|
245
|
+
})
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
get congestionControl() {
|
|
249
|
+
// @ts-ignore
|
|
250
|
+
return this.curtransport?.congestionControl || undefined
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
get reliability() {
|
|
254
|
+
// @ts-ignore
|
|
255
|
+
return this.curtransport?.reliability || undefined
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
get supportsReliableOnly() {
|
|
259
|
+
return true
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
getStats() {
|
|
263
|
+
// @ts-ignore
|
|
264
|
+
return this.curtransport.getStats()
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
/**
|
|
268
|
+
* @param {WebTransportCloseInfo} [closeinfo]
|
|
269
|
+
*/
|
|
270
|
+
close(closeinfo) {
|
|
271
|
+
this.closeset = true
|
|
272
|
+
this.curtransport.close(closeinfo)
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
async createBidirectionalStream() {
|
|
276
|
+
await this.ready
|
|
277
|
+
return await this.curtransport.createBidirectionalStream()
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
async createUnidirectionalStream() {
|
|
281
|
+
await this.ready
|
|
282
|
+
return await this.curtransport.createUnidirectionalStream()
|
|
283
|
+
}
|
|
284
|
+
}
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
import { HttpWTSession } from './session.js'
|
|
2
|
+
import { WebTransportBase } from './webtransportbase.js'
|
|
3
|
+
import { HttpClient } from './client.js'
|
|
4
|
+
import { Http2WebTransportClient } from './http2/node/index.js'
|
|
5
|
+
import { logger } from './utils.js'
|
|
6
|
+
|
|
7
|
+
const log = logger(`webtransportnode(${process?.pid})`)
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* @type {(arg0: import("./types").HttpWebTransportInit) => void}
|
|
11
|
+
*/
|
|
12
|
+
let checkQuicheInit
|
|
13
|
+
/**
|
|
14
|
+
* @type {new (arg0: import("./types").HttpWebTransportInit) => any}
|
|
15
|
+
*/
|
|
16
|
+
let Http3WebTransportClientSocket
|
|
17
|
+
/**
|
|
18
|
+
* @type {new (arg0: import("./types").HttpWebTransportInit) => any}
|
|
19
|
+
*/
|
|
20
|
+
let Http3WebTransportClient
|
|
21
|
+
// @ts-ignore
|
|
22
|
+
// eslint-disable-next-line no-unused-vars
|
|
23
|
+
const quicheLoaded = new Promise((resolve, reject) => {
|
|
24
|
+
// @ts-ignore
|
|
25
|
+
import('@fails-components/webtransport-transport-http3-quiche')
|
|
26
|
+
.then(
|
|
27
|
+
/**
|
|
28
|
+
* @type {import("./types").TransportHttp3Quiche}
|
|
29
|
+
*/
|
|
30
|
+
(http3lib) => {
|
|
31
|
+
/**
|
|
32
|
+
* @type {import("./types").TransportHttp3Quiche}
|
|
33
|
+
*/
|
|
34
|
+
;({
|
|
35
|
+
checkQuicheInit,
|
|
36
|
+
Http3WebTransportClientSocket,
|
|
37
|
+
Http3WebTransportClient
|
|
38
|
+
} = http3lib)
|
|
39
|
+
resolve(undefined)
|
|
40
|
+
}
|
|
41
|
+
)
|
|
42
|
+
.catch((error) => {
|
|
43
|
+
log('Problem loading http3-quiche transport', error)
|
|
44
|
+
reject(error)
|
|
45
|
+
})
|
|
46
|
+
}).catch((error) => {
|
|
47
|
+
console.log('http3 loader:', error)
|
|
48
|
+
})
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* @typedef {import('./dom').WebTransportCloseInfo} WebTransportCloseInfo
|
|
52
|
+
* @typedef {import('./dom').WebTransportBidirectionalStream} WebTransportBidirectionalStream
|
|
53
|
+
* @typedef {import('./dom').WebTransportReceiveStream} WebTransportReceiveStream
|
|
54
|
+
*/
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* @template T
|
|
58
|
+
* @typedef {import('node:stream/web').ReadableStream<T>} ReadableStream<T>
|
|
59
|
+
*/
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* @typedef {import('./dom').WebTransport} WebTransportInterface
|
|
63
|
+
*
|
|
64
|
+
* @implements {WebTransportInterface}
|
|
65
|
+
*/
|
|
66
|
+
export class WebTransport extends WebTransportBase {
|
|
67
|
+
/**
|
|
68
|
+
* @param{{client: HttpClient, sessionint: HttpWTSession, ourl: URL}} args
|
|
69
|
+
*/
|
|
70
|
+
startUpConnection({ client, sessionint, ourl }) {
|
|
71
|
+
client
|
|
72
|
+
.handleConnection({ createTransport: true, path: ourl.pathname })
|
|
73
|
+
.then(() => client.createWTSession(sessionint, ourl.pathname))
|
|
74
|
+
.catch((error) => {
|
|
75
|
+
if (client.transportIntSwitchToReliable) {
|
|
76
|
+
log('Connecting to unreliable failed:', error)
|
|
77
|
+
log('Now switching to reliable')
|
|
78
|
+
client.transportIntSwitchToReliable()
|
|
79
|
+
client
|
|
80
|
+
.handleConnection({ createTransport: false, path: ourl.pathname })
|
|
81
|
+
.then(() => client.createWTSession(sessionint, ourl.pathname))
|
|
82
|
+
.catch((error) => {
|
|
83
|
+
client.closeHookSession()
|
|
84
|
+
sessionint.readyReject(error)
|
|
85
|
+
sessionint.closedReject(error)
|
|
86
|
+
})
|
|
87
|
+
} else {
|
|
88
|
+
client.closeHookSession()
|
|
89
|
+
sessionint.readyReject(error)
|
|
90
|
+
sessionint.closedReject(error)
|
|
91
|
+
}
|
|
92
|
+
})
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
get supportsReliableOnly() {
|
|
96
|
+
return true
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* @param{import('./types.js').HttpWebTransportInit} args
|
|
101
|
+
* @return {{sessionint: HttpWTSession, client: HttpClient}}
|
|
102
|
+
*/
|
|
103
|
+
createClient(args) {
|
|
104
|
+
let createUnreliableClient
|
|
105
|
+
if (checkQuicheInit) {
|
|
106
|
+
createUnreliableClient = function (/** @type {any} */ _client) {
|
|
107
|
+
if (
|
|
108
|
+
// @ts-ignore
|
|
109
|
+
!args?.forceReliable
|
|
110
|
+
) {
|
|
111
|
+
checkQuicheInit(args)
|
|
112
|
+
}
|
|
113
|
+
const socket = new Http3WebTransportClientSocket(args)
|
|
114
|
+
const uclient = new Http3WebTransportClient(args)
|
|
115
|
+
uclient.closeClientInt = uclient.closeClient
|
|
116
|
+
uclient.closeClient = socket.closeClient.bind(socket)
|
|
117
|
+
socket.init()
|
|
118
|
+
socket.cobj = uclient
|
|
119
|
+
uclient.socket = socket
|
|
120
|
+
return uclient
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
const client = new HttpClient({
|
|
124
|
+
createReliableClient: function (client) {
|
|
125
|
+
// @ts-ignore
|
|
126
|
+
return new Http2WebTransportClient({ ...args })
|
|
127
|
+
},
|
|
128
|
+
createUnreliableClient,
|
|
129
|
+
...args
|
|
130
|
+
})
|
|
131
|
+
const sessionint = new HttpWTSession({
|
|
132
|
+
/* object: args.session, */
|
|
133
|
+
parentobj: client
|
|
134
|
+
})
|
|
135
|
+
return { client, sessionint }
|
|
136
|
+
}
|
|
137
|
+
}
|
|
@@ -1,13 +1,11 @@
|
|
|
1
|
-
|
|
2
|
-
import { Http3WTSession } from './session.js'
|
|
3
|
-
|
|
4
|
-
/** @type {WeakMap<WebTransport, Http3WTSession>} */
|
|
5
|
-
const sessions = new WeakMap()
|
|
1
|
+
/** @type {WeakMap<WebTransportBase, import('./session.js').HttpWTSession>} */
|
|
6
2
|
|
|
7
3
|
/**
|
|
8
|
-
* @typedef {import('./dom').WebTransportCloseInfo} WebTransportCloseInfo
|
|
9
|
-
* @typedef {import('./dom').WebTransportBidirectionalStream} WebTransportBidirectionalStream
|
|
10
|
-
* @typedef {import('./dom').WebTransportReceiveStream} WebTransportReceiveStream
|
|
4
|
+
* @typedef {import('./dom.js').WebTransportCloseInfo} WebTransportCloseInfo
|
|
5
|
+
* @typedef {import('./dom.js').WebTransportBidirectionalStream} WebTransportBidirectionalStream
|
|
6
|
+
* @typedef {import('./dom.js').WebTransportReceiveStream} WebTransportReceiveStream
|
|
7
|
+
* @typedef {import('./session.js').HttpWTSession} HttpWTSession
|
|
8
|
+
* @typedef { import('./session.js').HttpClient} HttpClient
|
|
11
9
|
*/
|
|
12
10
|
|
|
13
11
|
/**
|
|
@@ -16,14 +14,14 @@ const sessions = new WeakMap()
|
|
|
16
14
|
*/
|
|
17
15
|
|
|
18
16
|
/**
|
|
19
|
-
* @typedef {import('./dom').WebTransport} WebTransportInterface
|
|
17
|
+
* @typedef {import('./dom.js').WebTransport} WebTransportInterface
|
|
20
18
|
*
|
|
21
19
|
* @implements {WebTransportInterface}
|
|
22
20
|
*/
|
|
23
|
-
export class
|
|
21
|
+
export class WebTransportBase {
|
|
24
22
|
/**
|
|
25
23
|
* @param {string} url
|
|
26
|
-
* @param {import('./dom').WebTransportOptions} [args]
|
|
24
|
+
* @param {import('./dom.js').WebTransportOptions} [args]
|
|
27
25
|
*/
|
|
28
26
|
constructor(url, args) {
|
|
29
27
|
if (!url) throw new Error('no URL supplied')
|
|
@@ -37,42 +35,44 @@ export class WebTransport {
|
|
|
37
35
|
const host = ourl.hostname
|
|
38
36
|
let port = ourl.port
|
|
39
37
|
if (port === '') port = '443'
|
|
40
|
-
|
|
41
|
-
const client = new Http3Client({ host, port, ...args })
|
|
42
|
-
|
|
43
|
-
const sessionint = new Http3WTSession({
|
|
44
|
-
/* object: args.session, */
|
|
45
|
-
parentobj: client
|
|
46
|
-
})
|
|
47
|
-
|
|
38
|
+
const { sessionint, client } = this.createClient({ host, port, ...args })
|
|
48
39
|
this.ready = sessionint.ready
|
|
49
40
|
this.closed = sessionint.closed
|
|
50
41
|
this.draining = sessionint.draining
|
|
51
42
|
|
|
52
43
|
this.datagrams = sessionint.datagrams
|
|
53
44
|
|
|
54
|
-
/** @type {ReadableStream<WebTransportBidirectionalStream>} */
|
|
55
45
|
this.incomingBidirectionalStreams = sessionint.incomingBidirectionalStreams
|
|
56
46
|
|
|
57
47
|
this.incomingUnidirectionalStreams =
|
|
58
48
|
sessionint.incomingUnidirectionalStreams
|
|
59
49
|
|
|
60
|
-
|
|
50
|
+
this.sessionint = sessionint
|
|
51
|
+
|
|
52
|
+
this.startUpConnection({ client, sessionint, ourl })
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* @param{import('./types.js').HttpWebTransportInit} args
|
|
57
|
+
* @return {{sessionint: HttpWTSession, client: HttpClient}}
|
|
58
|
+
* @abstract
|
|
59
|
+
*/
|
|
60
|
+
createClient(args) {
|
|
61
|
+
throw new Error('Implement createClient')
|
|
62
|
+
}
|
|
61
63
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
sessionint.closedReject(error)
|
|
69
|
-
})
|
|
64
|
+
/**
|
|
65
|
+
* @param{{client: HttpClient, sessionint: HttpWTSession, ourl: URL}} args
|
|
66
|
+
* @abstract
|
|
67
|
+
*/
|
|
68
|
+
startUpConnection({ client, sessionint, ourl }) {
|
|
69
|
+
throw new Error('Implement createClient')
|
|
70
70
|
}
|
|
71
71
|
|
|
72
72
|
get reliability() {
|
|
73
|
-
const session =
|
|
73
|
+
const session = this.sessionint
|
|
74
74
|
|
|
75
|
-
if (session
|
|
75
|
+
if (!session) {
|
|
76
76
|
// should never happen as session is only removed when this instance is garbage collected
|
|
77
77
|
throw new Error('Http3WTSession was undefined')
|
|
78
78
|
}
|
|
@@ -80,19 +80,25 @@ export class WebTransport {
|
|
|
80
80
|
}
|
|
81
81
|
|
|
82
82
|
get congestionControl() {
|
|
83
|
-
const session =
|
|
83
|
+
const session = this.sessionint
|
|
84
84
|
|
|
85
|
-
if (session
|
|
85
|
+
if (!session) {
|
|
86
86
|
// should never happen as session is only removed when this instance is garbage collected
|
|
87
87
|
throw new Error('Http3WTSession was undefined')
|
|
88
88
|
}
|
|
89
89
|
return session.congestionControl
|
|
90
90
|
}
|
|
91
91
|
|
|
92
|
+
get supportsReliableOnly() {
|
|
93
|
+
throw new Error('Implement supportsReliableOnly')
|
|
94
|
+
// eslint-disable-next-line no-unreachable
|
|
95
|
+
return false
|
|
96
|
+
}
|
|
97
|
+
|
|
92
98
|
getStats() {
|
|
93
|
-
const session =
|
|
99
|
+
const session = this.sessionint
|
|
94
100
|
|
|
95
|
-
if (session
|
|
101
|
+
if (!session) {
|
|
96
102
|
// should never happen as session is only removed when this instance is garbage collected
|
|
97
103
|
throw new Error('Http3WTSession was undefined')
|
|
98
104
|
}
|
|
@@ -103,9 +109,9 @@ export class WebTransport {
|
|
|
103
109
|
* @param {WebTransportCloseInfo} [closeinfo]
|
|
104
110
|
*/
|
|
105
111
|
close(closeinfo) {
|
|
106
|
-
const session =
|
|
112
|
+
const session = this.sessionint
|
|
107
113
|
|
|
108
|
-
if (session
|
|
114
|
+
if (!session) {
|
|
109
115
|
// should never happen as session is only removed when this instance is garbage collected
|
|
110
116
|
throw new Error('Http3WTSession was undefined')
|
|
111
117
|
}
|
|
@@ -114,9 +120,9 @@ export class WebTransport {
|
|
|
114
120
|
}
|
|
115
121
|
|
|
116
122
|
createBidirectionalStream() {
|
|
117
|
-
const session =
|
|
123
|
+
const session = this.sessionint
|
|
118
124
|
|
|
119
|
-
if (session
|
|
125
|
+
if (!session) {
|
|
120
126
|
// should never happen as session is only removed when this instance is garbage collected
|
|
121
127
|
throw new Error('Http3WTSession was undefined')
|
|
122
128
|
}
|
|
@@ -125,9 +131,9 @@ export class WebTransport {
|
|
|
125
131
|
}
|
|
126
132
|
|
|
127
133
|
createUnidirectionalStream() {
|
|
128
|
-
const session =
|
|
134
|
+
const session = this.sessionint
|
|
129
135
|
|
|
130
|
-
if (session
|
|
136
|
+
if (!session) {
|
|
131
137
|
// should never happen as session is only removed when this instance is garbage collected
|
|
132
138
|
throw new Error('Http3WTSession was undefined')
|
|
133
139
|
}
|
package/old_test/test.js
CHANGED
|
@@ -5,19 +5,16 @@
|
|
|
5
5
|
// this file runs various tests
|
|
6
6
|
|
|
7
7
|
import { generateWebTransportCertificate } from '../test/fixtures/certificate.js'
|
|
8
|
-
import { Http3Server,
|
|
8
|
+
import { Http3Server, Http2Server, WebTransport } from '../lib/index.node.js'
|
|
9
9
|
import { echoTestsConnection, runEchoServer } from './testsuite.js'
|
|
10
10
|
|
|
11
|
+
let http2 = false
|
|
12
|
+
|
|
13
|
+
if (process.argv.some((el) => el === 'http2')) {
|
|
14
|
+
http2 = true
|
|
15
|
+
}
|
|
16
|
+
|
|
11
17
|
async function run() {
|
|
12
|
-
setTimeout(() => {
|
|
13
|
-
if (!testcheck()) {
|
|
14
|
-
console.log('tests took too long, probably hanging')
|
|
15
|
-
process.exit(1)
|
|
16
|
-
} else {
|
|
17
|
-
console.log('global event loop gone, everything alright')
|
|
18
|
-
process.exit(0)
|
|
19
|
-
}
|
|
20
|
-
}, 50 * 1000)
|
|
21
18
|
console.log('try connecting to server that does not exist')
|
|
22
19
|
const badClient = new WebTransport('https://127.0.0.1:49823/echo', {
|
|
23
20
|
serverCertificateHashes: [
|
|
@@ -57,18 +54,29 @@ async function run() {
|
|
|
57
54
|
throw new Error('Certificate generation failed')
|
|
58
55
|
}
|
|
59
56
|
|
|
60
|
-
console.log('start
|
|
57
|
+
console.log('start HttpServer and startup echo tests')
|
|
61
58
|
// now ramp up the server
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
59
|
+
let httpserver
|
|
60
|
+
if (!http2) {
|
|
61
|
+
httpserver = new Http3Server({
|
|
62
|
+
port: 8080,
|
|
63
|
+
host: '127.0.0.1',
|
|
64
|
+
secret: 'mysecret',
|
|
65
|
+
cert: certificate.cert, // unclear if it is the correct format
|
|
66
|
+
privKey: certificate.private
|
|
67
|
+
})
|
|
68
|
+
} else {
|
|
69
|
+
httpserver = new Http2Server({
|
|
70
|
+
port: 8080,
|
|
71
|
+
host: '127.0.0.1',
|
|
72
|
+
secret: 'mysecret',
|
|
73
|
+
cert: certificate.cert, // unclear if it is the correct format
|
|
74
|
+
privKey: certificate.private
|
|
75
|
+
})
|
|
76
|
+
}
|
|
69
77
|
|
|
70
|
-
|
|
71
|
-
runEchoServer(
|
|
78
|
+
httpserver.startServer() // you can call destroy to remove the server
|
|
79
|
+
runEchoServer(httpserver)
|
|
72
80
|
|
|
73
81
|
console.log('server started now wait 2 seconds')
|
|
74
82
|
|
|
@@ -83,16 +91,10 @@ async function run() {
|
|
|
83
91
|
})
|
|
84
92
|
client.closed
|
|
85
93
|
.then(() => {
|
|
86
|
-
console.log('The HTTP
|
|
94
|
+
console.log('The HTTP connection to ', url, 'closed gracefully.')
|
|
87
95
|
})
|
|
88
96
|
.catch((error) => {
|
|
89
|
-
console.error(
|
|
90
|
-
'The HTTP/3 connection to',
|
|
91
|
-
url,
|
|
92
|
-
'closed due to ',
|
|
93
|
-
error,
|
|
94
|
-
'.'
|
|
95
|
-
)
|
|
97
|
+
console.error('The HTTP connection to', url, 'closed due to ', error, '.')
|
|
96
98
|
})
|
|
97
99
|
console.log('wait for client to be ready')
|
|
98
100
|
await client.ready
|
|
@@ -114,7 +116,7 @@ async function run() {
|
|
|
114
116
|
|
|
115
117
|
console.log('now stop server')
|
|
116
118
|
|
|
117
|
-
|
|
119
|
+
httpserver.stopServer()
|
|
118
120
|
console.log('tests finished!')
|
|
119
121
|
}
|
|
120
122
|
run()
|
package/old_test/testsuite.js
CHANGED