@fails-components/webtransport 1.1.3 → 1.2.0

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 (75) hide show
  1. package/dist/lib/dom.d.ts +27 -10
  2. package/dist/lib/dom.d.ts.map +1 -1
  3. package/dist/lib/http2/browser/browser.d.ts +5 -2
  4. package/dist/lib/http2/browser/browser.d.ts.map +1 -1
  5. package/dist/lib/http2/browser/browserparser.d.ts.map +1 -1
  6. package/dist/lib/http2/node/capsuleparser.d.ts.map +1 -1
  7. package/dist/lib/http2/node/client.d.ts +3 -2
  8. package/dist/lib/http2/node/client.d.ts.map +1 -1
  9. package/dist/lib/http2/node/server.d.ts +10 -5
  10. package/dist/lib/http2/node/server.d.ts.map +1 -1
  11. package/dist/lib/http2/node/websocketparser.d.ts.map +1 -1
  12. package/dist/lib/http2/parserbase.d.ts +33 -1
  13. package/dist/lib/http2/parserbase.d.ts.map +1 -1
  14. package/dist/lib/http2/priorityscheduler.d.ts +167 -0
  15. package/dist/lib/http2/priorityscheduler.d.ts.map +1 -0
  16. package/dist/lib/http2/session.d.ts +25 -16
  17. package/dist/lib/http2/session.d.ts.map +1 -1
  18. package/dist/lib/http2/stream.d.ts +10 -0
  19. package/dist/lib/http2/stream.d.ts.map +1 -1
  20. package/dist/lib/http2/websocketcommon.d.ts.map +1 -1
  21. package/dist/lib/server.d.ts.map +1 -1
  22. package/dist/lib/session.d.ts +31 -17
  23. package/dist/lib/session.d.ts.map +1 -1
  24. package/dist/lib/stream.d.ts +13 -0
  25. package/dist/lib/stream.d.ts.map +1 -1
  26. package/dist/lib/types.d.ts +18 -15
  27. package/dist/lib/types.d.ts.map +1 -1
  28. package/dist/lib/webtransport.browser.d.ts +3 -2
  29. package/dist/lib/webtransport.browser.d.ts.map +1 -1
  30. package/dist/lib/webtransportbase.d.ts +1 -0
  31. package/dist/lib/webtransportbase.d.ts.map +1 -1
  32. package/eslint.config.js +20 -22
  33. package/lib/dom.ts +31 -13
  34. package/lib/http2/browser/browser.js +28 -13
  35. package/lib/http2/browser/browserparser.js +4 -1
  36. package/lib/http2/node/capsuleparser.js +4 -1
  37. package/lib/http2/node/client.js +38 -27
  38. package/lib/http2/node/server.js +56 -19
  39. package/lib/http2/node/websocketparser.js +5 -2
  40. package/lib/http2/parserbase.js +76 -7
  41. package/lib/http2/priorityscheduler.js +654 -0
  42. package/lib/http2/session.js +69 -20
  43. package/lib/http2/stream.js +60 -10
  44. package/lib/http2/websocketcommon.js +1 -1
  45. package/lib/server.js +0 -1
  46. package/lib/session.js +128 -64
  47. package/lib/stream.js +50 -8
  48. package/lib/types.ts +15 -8
  49. package/lib/webtransport.browser.js +77 -18
  50. package/lib/webtransportbase.js +7 -0
  51. package/old_test/echoserver.js +1 -1
  52. package/old_test/test.js +1 -1
  53. package/old_test/testsuite.js +6 -2
  54. package/package.json +7 -28
  55. package/readme.md +5 -3
  56. package/test/bidirectional-streams.spec.js +0 -150
  57. package/test/datagrams.spec.js +0 -104
  58. package/test/fixtures/certificate.js +0 -456
  59. package/test/fixtures/chai.js +0 -8
  60. package/test/fixtures/known-bytes.js +0 -44
  61. package/test/fixtures/p-timeout.js +0 -33
  62. package/test/fixtures/quiche.browser.js +0 -2
  63. package/test/fixtures/quiche.js +0 -1
  64. package/test/fixtures/read-cert-hash.js +0 -7
  65. package/test/fixtures/read-stream.js +0 -57
  66. package/test/fixtures/reader-value.js +0 -51
  67. package/test/fixtures/server.js +0 -467
  68. package/test/fixtures/webtransport.browser.js +0 -19
  69. package/test/fixtures/webtransport.js +0 -3
  70. package/test/fixtures/write-stream.js +0 -24
  71. package/test/index.js +0 -124
  72. package/test/pw-no-https-errors.json +0 -5
  73. package/test/session.spec.js +0 -199
  74. package/test/stream-limits.spec.js +0 -259
  75. package/test/unidirectional-streams.spec.js +0 -133
package/lib/stream.js CHANGED
@@ -20,6 +20,8 @@ const log = logger(`webtransport:http3wtstream(${pid})`)
20
20
  * @typedef {import('./dom').WebTransportReceiveStream} WebTransportReceiveStream
21
21
  * @typedef {import('./dom').WebTransportSendStream} WebTransportSendStream
22
22
  *
23
+ * @typedef {import('./dom').WebTransportSendGroup} WebTransportSendGroup
24
+ *
23
25
  * @typedef {import('./session').HttpWTSession} HttpWTSession
24
26
  *
25
27
  * @typedef {import('stream/web').WritableStreamDefaultController} WritableStreamDefaultController
@@ -33,6 +35,8 @@ export class HttpWTStream {
33
35
  * @param {object} args.transport
34
36
  * @param {boolean} args.bidirectional
35
37
  * @param {boolean} args.incoming
38
+ * @param {WebTransportSendGroup|undefined} args.sendGroup
39
+ * @param {bigint} args.sendOrder
36
40
  */
37
41
  constructor(args) {
38
42
  this.objint = args.object
@@ -43,6 +47,9 @@ export class HttpWTStream {
43
47
  this.incoming = args.incoming
44
48
  this.closed = false
45
49
 
50
+ this._sendGroup = args.sendGroup
51
+ this._sendOrder = args.sendOrder
52
+
46
53
  if (this.objint.sendInitialParameters) {
47
54
  this.objint.sendInitialParameters()
48
55
  }
@@ -140,18 +147,15 @@ export class HttpWTStream {
140
147
  wchunk = new Uint8Array(wchunk)
141
148
  }
142
149
  if (wchunk instanceof Uint8Array) {
150
+ if (wchunk.byteLength === 0) {
151
+ // or should we throw an error ?, Ask the W3C people!
152
+ return
153
+ }
143
154
  // eslint-disable-next-line no-unused-vars
144
155
  this.pendingoperation = new Promise((resolve, reject) => {
145
156
  this.pendingres = resolve
146
157
  })
147
- this.parentobj
148
- .waitForDatagramsSend()
149
- .finally(() => {
150
- this.objint.writeChunk(wchunk)
151
- })
152
- .catch((/** @type {any} */ err) => {
153
- log.error(err)
154
- })
158
+ this.objint.writeChunk(wchunk)
155
159
  return this.pendingoperation
156
160
  } else {
157
161
  log.trace('chunk info:', chunk)
@@ -203,6 +207,36 @@ export class HttpWTStream {
203
207
  bytesAcknowledged: 0n
204
208
  })
205
209
  }
210
+ Object.defineProperties(this.writable, {
211
+ sendOrder: {
212
+ get: () => {
213
+ return this._sendOrder
214
+ },
215
+ /**
216
+ * @param {bigint} value
217
+ */
218
+ set: (value) => {
219
+ if (value !== this._sendOrder) {
220
+ this._sendOrder = args.sendOrder
221
+ this.updateSendOrderAndGroup()
222
+ }
223
+ }
224
+ },
225
+ sendGroup: {
226
+ get: () => {
227
+ return this._sendGroup
228
+ },
229
+ /**
230
+ * @param {WebTransportSendGroup} value
231
+ */
232
+ set: (value) => {
233
+ if (value !== this._sendGroup) {
234
+ this._sendGroup = value
235
+ this.updateSendOrderAndGroup()
236
+ }
237
+ }
238
+ }
239
+ })
206
240
  // @ts-ignore
207
241
  this.parentobj.addSendStream(this.writable, this.writableController)
208
242
  }
@@ -278,6 +312,14 @@ export class HttpWTStream {
278
312
  return retObj
279
313
  }
280
314
 
315
+ updateSendOrderAndGroup() {
316
+ this.objint.updateSendOrderAndGroup({
317
+ sendOrder: this._sendOrder,
318
+ // @ts-ignore
319
+ sendGroupId: this._sendGroup._sendGroupId
320
+ })
321
+ }
322
+
281
323
  /**
282
324
  * @param {import('./types').StreamRecvSignalEvent} args
283
325
  * @returns {void}
package/lib/types.ts CHANGED
@@ -2,7 +2,7 @@ import type {
2
2
  WebTransportSession,
3
3
  WebTransportHash,
4
4
  WebTransportOptions,
5
- WebTransportSendGroup
5
+ WebTransportSendStreamOptions
6
6
  } from './dom'
7
7
  import type { IncomingHttpHeaders, Http2Stream, ServerHttp2Stream } from 'http2'
8
8
  import { ParserBase } from './http2/parserbase'
@@ -15,12 +15,13 @@ import { HttpClient } from './client'
15
15
  export interface NativeHttpWTSession {
16
16
  jsobj: WebTransportSessionEventHandler
17
17
  sendInitialParameters?: () => void
18
- writeDatagram: (chunk: Uint8Array) => void
19
- orderUnidiStream: (opts:{sendGroup: WebTransportSendGroup|null, sendOrder: number, waitUntilAvailable: boolean}) => boolean
20
- orderBidiStream: (opts:{sendGroup: WebTransportSendGroup|null, sendOrder: number, waitUntilAvailable: boolean}) => boolean
18
+ writeDatagram: (chunk: Uint8Array) => { code: 'success' | 'blocked' | 'internalError' | 'tooBig', message?: string}
19
+ orderUnidiStream: (opts: WebTransportSendStreamOptions) => boolean
20
+ orderBidiStream: (opts: WebTransportSendStreamOptions) => boolean
21
21
  orderSessionStats: () => void
22
22
  orderDatagramStats: () => void
23
23
  notifySessionDraining: () => void
24
+ getMaxDatagramSize: () => number
24
25
  close: (arg: { code: number; reason: string }) => void
25
26
  }
26
27
 
@@ -38,6 +39,10 @@ export interface NativeHttpWTStream {
38
39
  resetStream: (code: number) => void
39
40
  writeChunk: (buf: Uint8Array) => void
40
41
  streamFinal: () => void
42
+ updateSendOrderAndGroup: (args :{
43
+ sendOrder: bigint,
44
+ sendGroupId: bigint
45
+ }) => void
41
46
  }
42
47
 
43
48
  export interface NativeServerOptions {
@@ -79,6 +84,7 @@ export interface NativeClientOptions {
79
84
  initialSessionFlowControlWindow?: number
80
85
  sessionShouldAutoTuneReceiveWindow?: boolean
81
86
  sessionFlowControlWindowSizeLimit?: number
87
+ protocols?: string[]
82
88
  }
83
89
 
84
90
  export interface FlowControlable {
@@ -110,7 +116,8 @@ export interface NativeFinishSessionRequest {
110
116
  protocol: 'capsule' | 'websocket' | 'websocketoverhttp1' | 'http3'
111
117
  head?: Buffer
112
118
  userData?: object
113
- transportPrivate?: object
119
+ transportPrivate?: object,
120
+ selectedProtocol?: string
114
121
  }
115
122
 
116
123
  export type Purpose =
@@ -150,6 +157,7 @@ export interface WebTransportStreamEventHandler {
150
157
 
151
158
  export interface SessionReadyEvent {
152
159
  object: NativeHttpWTSession
160
+ protocol?: string
153
161
  }
154
162
 
155
163
  export interface SessionCloseEvent {
@@ -179,21 +187,20 @@ export interface DatagramReceivedEvent {
179
187
  datagram: Uint8Array
180
188
  }
181
189
 
182
- export interface DatagramSendEvent {}
183
-
184
190
  export interface GoawayReceivedEvent {}
185
191
 
186
192
  export interface NewStreamEvent {
187
193
  stream: NativeHttpWTStream
188
194
  bidirectional: boolean
189
195
  incoming: boolean
196
+ sendGroupId?: bigint;
197
+ sendOrder: bigint;
190
198
  }
191
199
 
192
200
  export interface WebTransportSessionEventHandler {
193
201
  onReady: (evt: SessionReadyEvent) => void
194
202
  onClose: (evt: SessionCloseEvent) => void
195
203
  onDatagramReceived: (evt: DatagramReceivedEvent) => void
196
- onDatagramSend: (evt: DatagramSendEvent) => void
197
204
  onGoAwayReceived: (evt: GoawayReceivedEvent) => void
198
205
  onSessionStats: (evt: SessionStatsEvent) => void
199
206
  onDatagramStats: (evt: DatagramStatsEvent) => void
@@ -3,6 +3,7 @@ import { HttpWTSession } from './session.js'
3
3
  import { HttpClient } from './client.js'
4
4
  import { Http2WebTransportBrowser } from './http2/browser/browser.js'
5
5
  import { logger } from './utils.js'
6
+ import { WebTransportError } from './error'
6
7
 
7
8
  const log = logger(`webtransport:browser()`)
8
9
 
@@ -13,7 +14,7 @@ const log = logger(`webtransport:browser()`)
13
14
  * @typedef {import('./dom').WebTransportSendStream} WebTransportSendStream
14
15
  * @typedef {import('./dom').WebTransportSendStreamOptions} WebTransportSendStreamOptions
15
16
  * @typedef {import('./dom').WebTransportReceiveStream} WebTransportReceiveStream
16
- * @typedef {import('./error').WebTransportError} WebTransportError
17
+ * @typedef {import('./dom').WebTransportSendGroup} WebTransportSendGroup
17
18
  */
18
19
 
19
20
  /**
@@ -215,7 +216,17 @@ export class WebTransportPolyfill {
215
216
  }
216
217
  /** @type {import('./dom').WebTransportDatagramDuplexStream} */
217
218
  // @ts-ignore
218
- this.datagrams = {}
219
+ this.datagrams = {
220
+ // @ts-ignore
221
+ get writable() {
222
+ // @ts-ignore
223
+ if (!this.datagramwritablepolyfilled_) {
224
+ console.warn('datagrams.writable is deprecated')
225
+ }
226
+ // @ts-ignore
227
+ return (this.datagramwritablepolyfilled_ ||= this.createWritable())
228
+ }
229
+ }
219
230
  // @ts-ignore
220
231
  this.datagrams.readable = new ReadableStream({
221
232
  // eslint-disable-next-line no-unused-vars
@@ -233,23 +244,67 @@ export class WebTransportPolyfill {
233
244
  }
234
245
  })
235
246
  // @ts-ignore
236
- this.datagrams.writable = new WritableStream({
237
- // eslint-disable-next-line no-unused-vars
238
- start: async (controller) => {
239
- await this.ready
240
- this.datagramsWriter = this.curtransport.datagrams.writable.getWriter()
241
- },
242
- // eslint-disable-next-line no-unused-vars
243
- write: async (chunk, controller) => {
244
- await this.datagramsWriter.write(chunk)
245
- },
246
- abort: async (reason) => {
247
- await this.datagramsWriter.abort(reason)
248
- },
249
- close: async () => {
250
- await this.datagramsWriter.close()
247
+ this.datagrams.createWritable = (options) => {
248
+ // @ts-ignore Must not exist for older browser
249
+ if (this.curtransport.datagrams.createWritable) {
250
+ return this.curtransport.datagrams.createWritable(options)
251
251
  }
252
- })
252
+ // we need to fallback to the old default writable
253
+ // @ts-ignore
254
+ if (!this.curtransport.datagrams.writable) {
255
+ throw new WebTransportError('No way to send out datagrams')
256
+ }
257
+ let sendOrder = options?.sendOrder
258
+ let sendGroup = options?.sendGroup
259
+ const retWritable = new WritableStream({
260
+ // eslint-disable-next-line no-unused-vars
261
+ start: async (controller) => {
262
+ await this.ready
263
+ if (!this.datagramsWriter) {
264
+ this.datagramsWriter =
265
+ // @ts-ignore
266
+ this.curtransport.datagrams.writable.getWriter()
267
+ }
268
+ },
269
+ // eslint-disable-next-line no-unused-vars
270
+ write: async (chunk, controller) => {
271
+ await this.datagramsWriter.write(chunk)
272
+ },
273
+ abort: async (reason) => {
274
+ await this.datagramsWriter.abort(reason)
275
+ },
276
+ close: async () => {
277
+ await this.datagramsWriter.close()
278
+ }
279
+ })
280
+ Object.defineProperties(retWritable, {
281
+ sendOrder: {
282
+ get: () => {
283
+ return sendOrder
284
+ },
285
+ /**
286
+ * @param {number} value
287
+ */
288
+ set: (value) => {
289
+ sendOrder = value
290
+ }
291
+ },
292
+ sendGroup: {
293
+ get: () => {
294
+ return sendGroup
295
+ },
296
+ /**
297
+ * @param {WebTransportSendGroup} value
298
+ */
299
+ set: (value) => {
300
+ if (value !== sendGroup) {
301
+ sendGroup = value
302
+ }
303
+ }
304
+ }
305
+ })
306
+ return retWritable
307
+ }
253
308
  this.incomingBidirectionalStreams = new ReadableStream({
254
309
  // eslint-disable-next-line no-unused-vars
255
310
  start: async (controller) => {
@@ -300,6 +355,10 @@ export class WebTransportPolyfill {
300
355
  return true
301
356
  }
302
357
 
358
+ get protocol() {
359
+ return this.curtransport?.protocol || undefined
360
+ }
361
+
303
362
  getStats() {
304
363
  // @ts-ignore
305
364
  return this.curtransport.getStats()
@@ -152,4 +152,11 @@ export class WebTransportBase {
152
152
 
153
153
  return session.createUnidirectionalStream(opts)
154
154
  }
155
+
156
+ get protocol() {
157
+ const session = this.sessionint
158
+ if (!session) return undefined
159
+
160
+ return session.protocol
161
+ }
155
162
  }
@@ -5,7 +5,7 @@
5
5
  import { Http3Server } from '../lib/index.js'
6
6
  import { runEchoServer } from './testsuite.js'
7
7
  import { existsSync, readFileSync, writeFile } from 'node:fs'
8
- import { generateWebTransportCertificate } from '../test/fixtures/certificate.js'
8
+ import { generateWebTransportCertificate } from '../../test/fixtures/certificate.js'
9
9
 
10
10
  let certificate = null
11
11
 
package/old_test/test.js CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
  // this file runs various tests
6
6
 
7
- import { generateWebTransportCertificate } from '../test/fixtures/certificate.js'
7
+ import { generateWebTransportCertificate } from '../../test/fixtures/certificate.js'
8
8
  import {
9
9
  Http3Server,
10
10
  Http2Server,
@@ -70,7 +70,9 @@ export async function unidirectionalEchoTest(session) {
70
70
  */
71
71
  export async function datagramEchoTest(session) {
72
72
  try {
73
- session.datagrams.readable.pipeTo(session.datagrams.writable)
73
+ const writable =
74
+ session.datagrams.writable || session.datagrams.createWritable()
75
+ session.datagrams.readable.pipeTo(writable)
74
76
  } catch (error) {
75
77
  console.log('datagram echo exited with', error)
76
78
  }
@@ -287,7 +289,9 @@ export async function echoTestsConnection(transport) {
287
289
  console.log('TEST 3: finish')
288
290
  console.log('TEST 4: start')
289
291
  console.log('finally test datagrams')
290
- const datawrite = await transport.datagrams.writable.getWriter()
292
+ const dwritable =
293
+ transport.datagrams.writable || transport.datagrams.createWritable()
294
+ const datawrite = await dwritable.getWriter()
291
295
  const data7 = new Uint8Array([83, 84, 85])
292
296
  const data8 = new Uint8Array([86, 87, 88])
293
297
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fails-components/webtransport",
3
- "version": "1.1.3",
3
+ "version": "1.2.0",
4
4
  "description": "A component to add webtransport support (server and client) to node.js using libquiche",
5
5
  "exports": {
6
6
  ".": {
@@ -21,21 +21,9 @@
21
21
  "types": "./dist/lib/index.types.d.ts",
22
22
  "scripts": {
23
23
  "start": "node test/echoserver.js",
24
- "test": "npm run test:node && npm run test:node:http2 && npm run test:chromium && npm run test:chromium:http2:polyfill && npm run test:chromium:http2:ponyfill && npm run test:firefox:http2:polyfill && npm run test:firefox:http2:ponyfill && npm run test:webkit:http2:polyfill && npm run test:webkit:http2:ponyfill",
25
- "test:node": "node test/index.js node http3",
26
- "test:node:http2": "node test/index.js node http2",
27
- "test:chromium": "node test/index.js chromium http3",
28
- "test:chromium:http2:polyfill": "node test/index.js chromium http2 polyfill",
29
- "test:chromium:http2:ponyfill": "node test/index.js chromium http2 ponyfill",
30
- "test:firefox": "node test/index.js firefox http3",
31
- "test:firefox:http2:polyfill": "node test/index.js firefox http2 polyfill",
32
- "test:firefox:http2:ponyfill": "node test/index.js firefox http2 ponyfill",
33
- "test:webkit": "node test/index.js webkit http3",
34
- "test:webkit:http2:polyfill": "node test/index.js webkit http2 polyfill",
35
- "test:webkit:http2:ponyfill": "node test/index.js webkit http2 ponyfill",
36
24
  "oldtest": "node old_test/test.js",
37
25
  "oldtesthttp2": "node old_test/test.js http2",
38
- "lint": "eslint lib test old_test"
26
+ "lint": "eslint lib old_test"
39
27
  },
40
28
  "repository": {
41
29
  "type": "git",
@@ -63,22 +51,15 @@
63
51
  "@types/dirty-chai": "^2.0.2",
64
52
  "@types/mocha": "^10.0.0",
65
53
  "@types/node": "^18.15.3",
66
- "chai": "^4.3.6",
67
- "chai-as-promised": "^7.1.1",
68
- "dirty-chai": "^2.0.1",
69
54
  "eslint": "^9.3.0",
70
55
  "eslint-config-prettier": "^9.1.0",
71
- "eslint-config-standard": "^16.0.2",
72
- "eslint-plugin-import": "^2.25.2",
56
+ "eslint-plugin-import": "^2.31.0",
73
57
  "eslint-plugin-node": "^11.1.0",
74
58
  "eslint-plugin-prettier": "^5.1.3",
75
- "eslint-plugin-promise": "^4.3.1",
76
- "eslint-plugin-standard": "^4.1.0",
77
- "execa": "^6.1.0",
78
- "mocha": "^10.1.0",
79
- "node-forge": "^1.3.1",
80
- "playwright-test": "^12.3.4",
81
- "prettier": "^3.2.5",
59
+ "eslint-plugin-promise": "^7.2.1",
60
+ "prettier": "^3.5.3",
61
+ "prettier-linter-helpers": "^1.0.0",
62
+ "synckit": "^0.11.4",
82
63
  "typescript": "^4.8.4",
83
64
  "uint8arrays": "^4.0.2"
84
65
  },
@@ -88,8 +69,6 @@
88
69
  ]
89
70
  },
90
71
  "browser": {
91
- "./test/fixtures/webtransport.js": "./test/fixtures/webtransport.browser.js",
92
- "./test/fixtures/quiche.js": "./test/fixtures/quiche.browser.js",
93
72
  "./lib/webstreams.js": "./lib/webstreams.browser.js"
94
73
  }
95
74
  }
package/readme.md CHANGED
@@ -72,8 +72,8 @@ The package `webtransport-transport-http3-quiche` provides prebuild binaries for
72
72
  Other platforms may be possible via cross-compiling in the GitHub actions, if someone needs this, PRs are welcome.
73
73
 
74
74
  Of course, you can also build the binary on your system.
75
- If you are running the compiling install as root, you need to use `--`unsafe-perm` as a flag.
76
- Installing the package without prebuild requires a full building environment including clang-9, perl6, python, golang, `ninja-build, `and `icu``.` See the `Dockerfile` or `Dockerfile.development` for required Debian packages.
75
+ If you are running the compiling install as root, you need to use `--unsafe-perm` as a flag.
76
+ Installing the package without prebuild requires a full building environment including `clang-9`, `perl6`, `python`, `golang`, `ninja-build`, and `icu`. See the `Dockerfile` or `Dockerfile.development` for required Debian packages.
77
77
  This should work for Windows, Linux and Mac OS X.
78
78
  (You may want to check out the building dependencies (especially for Windows) for BoringSSl, zlib, abseil on their respective websites).
79
79
 
@@ -109,7 +109,9 @@ Other but more expert options include:
109
109
  * `certhttp2` and `privKeyhttp2`: For providing a different certificate for the http/2 as the http/2 implementation does not support certificate matching by fingerprints.
110
110
  * `initialStreamFlowControlWindow`, `initialSessionFlowControlWindow`, `streamShouldAutoTuneReceiveWindow`, `sessionShouldAutoTuneReceiveWindow`, `streamFlowControlWindowSizeLimit`, `sessionFlowControlWindowSizeLimit`: As expert's option for tweaking the internal flow control.
111
111
 
112
- The method `setRequestHandler(callback)` sets a callback, that inspects incoming headers and allows to change the incoming path header and also to throw an error if the session should not be opened. This method is considered to be experimental.
112
+ The method `setRequestCallback(callback)` sets a callback, that inspects incoming headers and allows to change the incoming path header and also to throw an error if the session should not be opened.
113
+ It is also required for selecting the application level protocol.
114
+ In order to see how it is used, look into `test/fixtures/server.js` for a working example.
113
115
  In general, the HTTP header is attached as the `header` property to the WebTransport Session object.
114
116
 
115
117
  The method `updateCert(cert, privKey, http2only)` allows to change the certificate, while the server is running (not supported by all transports).
@@ -1,150 +0,0 @@
1
- /* eslint-env mocha */
2
-
3
- import { getReaderValue } from './fixtures/reader-value.js'
4
- import { expect } from './fixtures/chai.js'
5
- import { readStream } from './fixtures/read-stream.js'
6
- import { writeStream } from './fixtures/write-stream.js'
7
- import { readCertHash } from './fixtures/read-cert-hash.js'
8
- import WebTransport from './fixtures/webtransport.js'
9
- import { quicheLoaded } from './fixtures/quiche.js'
10
- import * as ui8 from 'uint8arrays'
11
- import {
12
- KNOWN_BYTES,
13
- KNOWN_BYTES_LENGTH,
14
- KNOWN_BYTES_LONG,
15
- KNOWN_BYTES_LONG_LENGTH
16
- } from './fixtures/known-bytes.js'
17
-
18
- /**
19
- * @template T
20
- * @typedef {import('../lib/types').Deferred<T>} Deferred<T>
21
- */
22
- describe('bidirectional streams', function () {
23
- let forceReliable = false
24
- if (process.env.USE_HTTP2 === 'true') forceReliable = true
25
- /** @type {import('../lib/dom').WebTransport | undefined} */
26
- let client
27
-
28
- const wtOptions = {
29
- serverCertificateHashes: [
30
- {
31
- algorithm: 'sha-256',
32
- value: readCertHash(process.env.CERT_HASH)
33
- }
34
- ],
35
- // @ts-ignore
36
- forceReliable
37
- }
38
- if (process.env.NO_CERT_HASHES === 'true')
39
- // @ts-ignore
40
- delete wtOptions.serverCertificateHashes
41
-
42
- // @ts-ignore
43
- beforeEach(async () => {
44
- if (
45
- process.env.USE_HTTP2 !== 'true' &&
46
- process.env.USE_PONYFILL !== 'true' &&
47
- process.env.USE_POLYFILL !== 'true'
48
- ) {
49
- await quicheLoaded
50
- }
51
- })
52
-
53
- // @ts-ignore
54
- afterEach(async () => {
55
- if (client != null) {
56
- client.close()
57
- client = undefined
58
- }
59
- })
60
-
61
- it('sends and receives data over an outgoing bidirectional stream', async () => {
62
- // client context - connects to the server, opens a bidi stream, sends some data and reads the response
63
- client = new WebTransport(
64
- `${process.env.SERVER_URL}/bidirectional_client_initiated_echo`,
65
- wtOptions
66
- )
67
- await client.ready
68
-
69
- const stream = await client.createBidirectionalStream()
70
- await writeStream(stream.writable, KNOWN_BYTES)
71
-
72
- const output = await readStream(stream.readable, KNOWN_BYTES_LENGTH)
73
- expect(ui8.concat(KNOWN_BYTES)).to.deep.equal(
74
- ui8.concat(output),
75
- 'Did not receive the same bytes we sent'
76
- )
77
- })
78
-
79
- it('sends and receives data over an outgoing bidirectional stream with big buffers', async () => {
80
- // client context - connects to the server, opens a bidi stream, sends some data and reads the response
81
- client = new WebTransport(
82
- `${process.env.SERVER_URL}/bidirectional_client_initiated_echo`,
83
- wtOptions
84
- )
85
- await client.ready
86
-
87
- const stream = await client.createBidirectionalStream()
88
- await writeStream(stream.writable, KNOWN_BYTES_LONG)
89
-
90
- const output = await readStream(stream.readable, KNOWN_BYTES_LONG_LENGTH)
91
- const send = ui8.concat(KNOWN_BYTES_LONG)
92
- const received = ui8.concat(output)
93
- let failure = 0
94
- for (let i = 0; i < Math.max(send.byteLength, received.byteLength); i++) {
95
- if (send[i] !== received[i] && failure < 100) {
96
- console.log('d: ', i, ' ,', send[i], ', ', received[i])
97
- failure++
98
- }
99
- }
100
-
101
- expect(ui8.concat(KNOWN_BYTES_LONG)).to.deep.equal(
102
- ui8.concat(output),
103
- 'Did not receive the same bytes we sent'
104
- )
105
- })
106
-
107
- it('sends and receives data over an incoming bidirectional stream', async () => {
108
- // client context - waits for the server to open a bidi stream then pipes it back to them
109
- client = new WebTransport(
110
- `${process.env.SERVER_URL}/bidirectional_server_initiated_echo`,
111
- wtOptions
112
- )
113
- await client.ready
114
-
115
- const bidiStream = await getReaderValue(client.incomingBidirectionalStreams)
116
-
117
- // redirect input to output
118
- try {
119
- await bidiStream.readable.pipeTo(bidiStream.writable)
120
- } catch (error) {
121
- console.log('Pipe to error (ignore)', error) // Actually all you can get is, that the fin is catched
122
- }
123
-
124
- // the remote will close the session
125
- const result = await client.closed
126
-
127
- // should receive the default close info
128
- expect(result).to.have.property('reason', '')
129
- expect(result).to.have.property('closeCode', 0)
130
- })
131
-
132
- it('receives data from server and checks receiving stream fin', async () => {
133
- // client context - waits for the server to open a bidi stream then pipes it back to them
134
- client = new WebTransport(
135
- `${process.env.SERVER_URL}/bidirectional_server_fin_send`,
136
- wtOptions
137
- )
138
- await client.ready
139
-
140
- const bidiStream = await getReaderValue(client.incomingBidirectionalStreams)
141
- const reader = bidiStream.readable.getReader()
142
-
143
- while (true) {
144
- const res = await reader.read()
145
- if (res.done) {
146
- break
147
- }
148
- }
149
- })
150
- })