@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.
Files changed (162) hide show
  1. package/lib/client.js +81 -40
  2. package/lib/dom.ts +7 -5
  3. package/lib/http2/browser/browser.js +168 -0
  4. package/lib/http2/browser/browserparser.js +248 -0
  5. package/lib/http2/flowcontroller.js +371 -0
  6. package/lib/http2/node/capsuleparser.js +291 -0
  7. package/lib/http2/node/client.js +239 -0
  8. package/lib/http2/node/index.js +2 -0
  9. package/lib/http2/node/server.js +499 -0
  10. package/lib/http2/node/websocketparser.js +829 -0
  11. package/lib/http2/parserbase.js +139 -0
  12. package/lib/http2/parserbasehttp2.js +128 -0
  13. package/lib/http2/session.js +225 -0
  14. package/lib/http2/stream.js +354 -0
  15. package/lib/http2/websocketcommon.js +1 -0
  16. package/lib/{index.js → index.browser.js} +6 -10
  17. package/lib/index.node.js +27 -0
  18. package/lib/server.js +252 -69
  19. package/lib/session.js +31 -68
  20. package/lib/stream.js +103 -179
  21. package/lib/types.ts +174 -87
  22. package/lib/utils.js +2 -1
  23. package/lib/webstreams.browser.js +6 -0
  24. package/lib/webstreams.js +7 -0
  25. package/lib/webtransport.browser.js +284 -0
  26. package/lib/webtransport.node.js +137 -0
  27. package/lib/{webtransport.js → webtransportbase.js} +47 -41
  28. package/old_test/test.js +31 -29
  29. package/old_test/testsuite.js +1 -1
  30. package/package.json +18 -17
  31. package/readme.md +94 -30
  32. package/test/bidirectional-streams.spec.js +51 -9
  33. package/test/datagrams.spec.js +8 -2
  34. package/test/fixtures/known-bytes.js +29 -0
  35. package/test/fixtures/read-stream.js +1 -1
  36. package/test/fixtures/reader-value.js +1 -1
  37. package/test/fixtures/server.js +24 -10
  38. package/test/fixtures/webtransport.browser.js +20 -2
  39. package/test/fixtures/webtransport.js +1 -1
  40. package/test/index.js +33 -6
  41. package/test/pw-no-https-errors.json +5 -0
  42. package/test/session.spec.js +71 -52
  43. package/test/unidirectional-streams.spec.js +20 -4
  44. package/CMakeLists.txt +0 -991
  45. package/LICENSE.chromium +0 -27
  46. package/LICENSE.envoy +0 -207
  47. package/build.js +0 -313
  48. package/dist/lib/client.d.ts +0 -78
  49. package/dist/lib/client.d.ts.map +0 -1
  50. package/dist/lib/dom.d.ts +0 -87
  51. package/dist/lib/dom.d.ts.map +0 -1
  52. package/dist/lib/error.d.ts +0 -8
  53. package/dist/lib/error.d.ts.map +0 -1
  54. package/dist/lib/event-loop.d.ts +0 -33
  55. package/dist/lib/event-loop.d.ts.map +0 -1
  56. package/dist/lib/index.d.ts +0 -79
  57. package/dist/lib/index.d.ts.map +0 -1
  58. package/dist/lib/native.d.ts +0 -2
  59. package/dist/lib/native.d.ts.map +0 -1
  60. package/dist/lib/server.d.ts +0 -92
  61. package/dist/lib/server.d.ts.map +0 -1
  62. package/dist/lib/session.d.ts +0 -298
  63. package/dist/lib/session.d.ts.map +0 -1
  64. package/dist/lib/stream.d.ts +0 -135
  65. package/dist/lib/stream.d.ts.map +0 -1
  66. package/dist/lib/transport.d.ts +0 -34
  67. package/dist/lib/transport.d.ts.map +0 -1
  68. package/dist/lib/types.d.ts +0 -212
  69. package/dist/lib/types.d.ts.map +0 -1
  70. package/dist/lib/utils.d.ts +0 -11
  71. package/dist/lib/utils.d.ts.map +0 -1
  72. package/dist/lib/webtransport.d.ts +0 -47
  73. package/dist/lib/webtransport.d.ts.map +0 -1
  74. package/dist/test/bidirectional-streams.spec.d.ts +0 -5
  75. package/dist/test/bidirectional-streams.spec.d.ts.map +0 -1
  76. package/dist/test/datagrams.spec.d.ts +0 -5
  77. package/dist/test/datagrams.spec.d.ts.map +0 -1
  78. package/dist/test/event-loop.node.d.ts +0 -2
  79. package/dist/test/event-loop.node.d.ts.map +0 -1
  80. package/dist/test/fixtures/certificate.d.ts +0 -21
  81. package/dist/test/fixtures/certificate.d.ts.map +0 -1
  82. package/dist/test/fixtures/chai.d.ts +0 -2
  83. package/dist/test/fixtures/chai.d.ts.map +0 -1
  84. package/dist/test/fixtures/known-bytes.d.ts +0 -6
  85. package/dist/test/fixtures/known-bytes.d.ts.map +0 -1
  86. package/dist/test/fixtures/p-timeout.d.ts +0 -8
  87. package/dist/test/fixtures/p-timeout.d.ts.map +0 -1
  88. package/dist/test/fixtures/read-cert-hash.d.ts +0 -6
  89. package/dist/test/fixtures/read-cert-hash.d.ts.map +0 -1
  90. package/dist/test/fixtures/read-stream.d.ts +0 -19
  91. package/dist/test/fixtures/read-stream.d.ts.map +0 -1
  92. package/dist/test/fixtures/reader-value.d.ts +0 -22
  93. package/dist/test/fixtures/reader-value.d.ts.map +0 -1
  94. package/dist/test/fixtures/server.d.ts +0 -5
  95. package/dist/test/fixtures/server.d.ts.map +0 -1
  96. package/dist/test/fixtures/webtransport.browser.d.ts +0 -3
  97. package/dist/test/fixtures/webtransport.browser.d.ts.map +0 -1
  98. package/dist/test/fixtures/webtransport.d.ts +0 -3
  99. package/dist/test/fixtures/webtransport.d.ts.map +0 -1
  100. package/dist/test/fixtures/write-stream.d.ts +0 -10
  101. package/dist/test/fixtures/write-stream.d.ts.map +0 -1
  102. package/dist/test/index.d.ts +0 -2
  103. package/dist/test/index.d.ts.map +0 -1
  104. package/dist/test/session.spec.d.ts +0 -5
  105. package/dist/test/session.spec.d.ts.map +0 -1
  106. package/dist/test/unidirectional-streams.spec.d.ts +0 -2
  107. package/dist/test/unidirectional-streams.spec.d.ts.map +0 -1
  108. package/failslogolicensereadme.txt +0 -4
  109. package/lib/event-loop.js +0 -88
  110. package/lib/native.js +0 -28
  111. package/lib/transport.js +0 -82
  112. package/platform/icufix/fakedata.cpp +0 -8
  113. package/platform/quiche/quic/core/io/socket_win.inc +0 -3
  114. package/platform/quiche_platform_impl/quiche_bug_tracker_impl.h +0 -7
  115. package/platform/quiche_platform_impl/quiche_client_stats_impl.h +0 -7
  116. package/platform/quiche_platform_impl/quiche_command_line_flags_impl.h +0 -7
  117. package/platform/quiche_platform_impl/quiche_containers_impl.h +0 -7
  118. package/platform/quiche_platform_impl/quiche_event_loop_impl.h +0 -7
  119. package/platform/quiche_platform_impl/quiche_export_impl.h +0 -6
  120. package/platform/quiche_platform_impl/quiche_flag_utils_impl.h +0 -11
  121. package/platform/quiche_platform_impl/quiche_flags_impl.h +0 -8
  122. package/platform/quiche_platform_impl/quiche_iovec_impl.h +0 -10
  123. package/platform/quiche_platform_impl/quiche_logging_impl.h +0 -21
  124. package/platform/quiche_platform_impl/quiche_mem_slice_impl.h +0 -2
  125. package/platform/quiche_platform_impl/quiche_mutex_impl.h +0 -8
  126. package/platform/quiche_platform_impl/quiche_prefetch_impl.h +0 -11
  127. package/platform/quiche_platform_impl/quiche_reference_counted_impl.h +0 -16
  128. package/platform/quiche_platform_impl/quiche_server_stats_impl.h +0 -7
  129. package/platform/quiche_platform_impl/quiche_stack_trace_impl.h +0 -12
  130. package/platform/quiche_platform_impl/quiche_stream_buffer_allocator_impl.h +0 -8
  131. package/platform/quiche_platform_impl/quiche_testvalue_impl.h +0 -1
  132. package/platform/quiche_platform_impl/quiche_thread_local_impl.h +0 -6
  133. package/platform/quiche_platform_impl/quiche_time_utils_impl.h +0 -13
  134. package/platform/quiche_platform_impl/quiche_udp_socket_platform_impl.h +0 -39
  135. package/src/http3backendresponse.cc +0 -36
  136. package/src/http3backendresponse.h +0 -109
  137. package/src/http3client.cc +0 -1529
  138. package/src/http3client.h +0 -557
  139. package/src/http3clientsession.cc +0 -65
  140. package/src/http3clientsession.h +0 -60
  141. package/src/http3clientstream.cc +0 -52
  142. package/src/http3clientstream.h +0 -42
  143. package/src/http3dispatcher.cc +0 -62
  144. package/src/http3dispatcher.h +0 -57
  145. package/src/http3eventloop.cc +0 -1107
  146. package/src/http3eventloop.h +0 -316
  147. package/src/http3server.cc +0 -514
  148. package/src/http3server.h +0 -151
  149. package/src/http3serverbackend.cc +0 -105
  150. package/src/http3serverbackend.h +0 -98
  151. package/src/http3serversession.cc +0 -123
  152. package/src/http3serversession.h +0 -95
  153. package/src/http3serverstream.cc +0 -463
  154. package/src/http3serverstream.h +0 -114
  155. package/src/http3sessioncache.cc +0 -85
  156. package/src/http3sessioncache.h +0 -59
  157. package/src/http3wtsessionvisitor.cc +0 -46
  158. package/src/http3wtsessionvisitor.h +0 -397
  159. package/src/http3wtstreamvisitor.cc +0 -155
  160. package/src/http3wtstreamvisitor.h +0 -404
  161. package/test/event-loop.node.js +0 -24
  162. 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 { Http3WTSession } from './session.js'
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:http3server(${process.pid})`)
8
+ const log = logger(`webtransport:httpserver(${process?.pid})`)
8
9
 
9
10
  /**
10
- * @typedef {import('./types').WebTransportSession} WebTransportSession
11
- * @typedef {import('./types').NativeHttp3WTSession} NativeHttp3WTSession
12
- * @typedef {import('./types').Http3ServerEventHandler} Http3ServerEventHandler
13
- * @typedef {import('./types').Http3WTServerSessionVisitorEvent} Http3WTServerSessionVisitorEvent
14
- * @typedef {import('./types').ServerStatusEvent} ServerStatusEvent
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').Http3ServerInit} Http3ServerInit
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 {Http3ServerEventHandler}
121
+ * @implements {HttpServerEventHandler}
21
122
  */
22
- export class Http3Server extends Http3WebTransport {
123
+ export class HttpServer {
23
124
  /**
24
125
  *
25
- * @param {Http3ServerInit} args
126
+ * @param {HttpServerInit} args
26
127
  */
27
128
  constructor(args) {
28
- super(args, 'server')
29
-
129
+ this.args = args
30
130
  /** @type {Record<string, ReadableStream>} */
31
131
  this.sessionStreams = {}
32
132
 
33
- /** @type {Record<string, ReadableStreamDefaultController<Http3WTSession>>} */
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
- this.transportInt.startServer()
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
- this.transportInt.finishSessionRequest({
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 {Http3WTServerSessionVisitorEvent} args
268
+ * @param {HttpWTServerSessionVisitorEvent} args
134
269
  */
135
- onHttp3WTSessionVisitor(args) {
270
+ onHttpWTSessionVisitor(args) {
136
271
  // create Http3 Visitor
137
- if (args.object) {
138
- const sesobj = new Http3WTSession({
139
- object: args.session,
140
- header: args.header,
141
- parentobj: this
142
- })
143
- if (this.sessionController[args.path])
144
- this.sessionController[args.path].enqueue(sesobj)
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 {ServerStatusEvent} evt
168
- */
169
- onServerStatus(evt) {
170
- if (evt.host) this.host = evt.host
171
- if (evt.port) this.port = evt.port
305
+ * @param{{path: string} |undefined} [args]
306
+ **/
307
+ async createTransportInt(args) {
308
+ if (this.transportInt != null) {
309
+ return
310
+ }
172
311
 
173
- switch (evt.status) {
174
- case 'close':
175
- this.onServerClose()
176
- break
177
- case 'listening':
178
- this.onServerListening()
179
- break
180
- case 'error':
181
- this.onServerListening()
182
- break
183
- default: {
184
- throw new Error('unknown status')
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
- * @param {Http3WTServerSessionVisitorEvent | ServerStatusEvent | ServerSessionRequestEvent} args
191
- */
192
- customCallback(args) {
193
- log('callback', args?.purpose)
194
- log.trace(args)
195
- if (args.purpose) {
196
- switch (args.purpose) {
197
- case 'SessionRequest':
198
- this.onSessionRequest(args)
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 'Http3WTSessionVisitor':
201
- this.onHttp3WTSessionVisitor(args)
342
+ case 'reliableOnly':
343
+ // @ts-ignore
344
+ this.transportInt = new Http2WebTransportServer(this.args)
202
345
  break
203
- case 'ServerStatus':
204
- this.onServerStatus(args)
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 'node:stream/web'
2
- import { Http3WTStream } from './stream.js'
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 log = logger(`webtransport:http3wtsession(${process.pid})`)
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').NativeHttp3WTSession} NativeHttp3WTSession
31
+ * @typedef {import('./types').NativeHttpWTSession} NativeHttpWTSession
31
32
  *
32
33
  * Public API
33
- * @typedef {import('./types').WebTransportSession} WebTransportSession
34
+ * @typedef {import('./types').WebTransportSessionImpl} WebTransportSession
34
35
  *
35
- * @typedef {import('./server').Http3Server} Http3Server
36
- * @typedef {import('./client').Http3Client} Http3Client
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 Http3WTSession {
46
+ export class HttpWTSession {
46
47
  /**
47
48
  * @param {object} args
48
- * @param {import('./types').NativeHttp3WTSession} [args.object]
49
- * @param {Http3Server | Http3Client} args.parentobj
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<Http3WTStream>} */
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 {NativeHttp3WTSession} object
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 {Http3WTStream} stream
287
+ * @param {HttpWTStream} stream
279
288
  */
280
289
  addStreamObj(stream) {
281
290
  this.streamObjs.add(stream)
282
291
  }
283
292
 
284
293
  /**
285
- * @param {Http3WTStream} stream
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 ${process.pid}) with code ` +
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 Http3WTStream({
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
  }