@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/package.json CHANGED
@@ -1,9 +1,13 @@
1
1
  {
2
2
  "name": "@fails-components/webtransport",
3
- "version": "0.3.1",
3
+ "version": "1.0.1",
4
4
  "description": "A component to add webtransport support (server and client) to node.js using libquiche",
5
- "main": "lib/index.js",
6
- "module": "lib/index.js",
5
+ "exports": {
6
+ ".": {
7
+ "node": "./lib/index.node.js",
8
+ "browser": "./lib/index.browser.js"
9
+ }
10
+ },
7
11
  "engines": {
8
12
  "node": ">=16.5"
9
13
  },
@@ -11,15 +15,14 @@
11
15
  "types": "./dist/lib/index.d.ts",
12
16
  "scripts": {
13
17
  "start": "node test/echoserver.js",
14
- "test": "npm run test:node && npm run test:chromium",
15
- "test:node": "node test/index.js node",
16
- "test:chromium": "node test/index.js chromium",
18
+ "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",
19
+ "test:node": "node test/index.js node http3",
20
+ "test:node:http2": "node test/index.js node http2",
21
+ "test:chromium": "node test/index.js chromium http3",
22
+ "test:chromium:http2:polyfill": "node test/index.js chromium http2 polyfill",
23
+ "test:chromium:http2:ponyfill": "node test/index.js chromium http2 ponyfill",
17
24
  "oldtest": "node old_test/test.js",
18
- "install": "node build.js install",
19
- "build": "node build.js build",
20
- "rebuild": "node build.js rebuild",
21
- "rebuild-debug": "node build.js rebuild-debug -D",
22
- "build-debug": "node build.js build-debug",
25
+ "oldtesthttp2": "node old_test/test.js http2",
23
26
  "types": "tsc",
24
27
  "lint": "eslint lib test old_test"
25
28
  },
@@ -35,13 +38,11 @@
35
38
  "bugs": {
36
39
  "url": "https://github.com/fails-components/webtransport/issues"
37
40
  },
38
- "homepage": "https://github.com/fails-components/webtransport#readme",
41
+ "homepage": "https://github.com/fails-components/webtransport/main/#readme",
39
42
  "dependencies": {
40
43
  "@types/debug": "^4.1.7",
41
44
  "bindings": "^1.5.0",
42
- "debug": "^4.3.4",
43
- "node-addon-api": "^4.3.0",
44
- "prebuild-install": "^7.1.1"
45
+ "debug": "^4.3.4"
45
46
  },
46
47
  "devDependencies": {
47
48
  "@babel/core": "^7.17.10",
@@ -53,7 +54,6 @@
53
54
  "@types/node": "^18.15.3",
54
55
  "chai": "^4.3.6",
55
56
  "chai-as-promised": "^7.1.1",
56
- "cmake-js": "^6.3.2",
57
57
  "dirty-chai": "^2.0.1",
58
58
  "eslint": "^7.32.0",
59
59
  "eslint-config-prettier": "^7.2.0",
@@ -77,6 +77,7 @@
77
77
  ]
78
78
  },
79
79
  "browser": {
80
- "./test/fixtures/webtransport.js": "./test/fixtures/webtransport.browser.js"
80
+ "./test/fixtures/webtransport.js": "./test/fixtures/webtransport.browser.js",
81
+ "./lib/webstreams.js": "./lib/webstreams.browser.js"
81
82
  }
82
83
  }
package/readme.md CHANGED
@@ -9,57 +9,121 @@ Macos tests on master ![master](https://github.com/fails-components/webtransport
9
9
 
10
10
  (c) 2022- Marten Richter
11
11
 
12
- The package provides Webtransport support to node.js .
12
+ The package provides Webtransport support to node.js.
13
13
 
14
14
  This package is part of FAILS.
15
- A web based lecture system developed out of university lectures.
15
+ A web-based lecture system developed out of university lectures.
16
16
 
17
17
  While FAILS as a whole is licensed via GNU Affero GPL version 3.0, this package is licensed under a BSD-style license that can be found in the LICENSE file, while code taken from other projects is still under their respective license (see LICENSE file for details).
18
- This package is licensed more permissive, since it can be useful outside of the FAILS environment.
18
+ This package is licensed more permissive since it can be useful outside of the FAILS environment.
19
19
 
20
- This module is a C++ node binding to libquiche [https://github.com/google/quiche](https://github.com/google/quiche)(note there is a second library with a similar purpose and the same name), which provides besides other network protocols HTTP/3 support.
21
- This packages currently only provides support for HTTP/3 WebTransport with an interface similar to the browser side (but not all features implemented), for server as well as for client, see `test/test.js`, `test/testsuite.js`, `test/echoclient.js`, `test/echoserver.js` for examples.
22
- Note, the client implementation only supports certificates checking via certificateHashes.
23
- It may be possible in the future to also support normal HTTP/3 not so much effort, however there is no intention from the author to implement this, since it will not be needed by FAILS. However PR request are welcome and will be supported by advise from the author.
24
- The package should be considered as a ducttape style solution, until a bullet proof native support of HTTP/3 and WebTransport is provided by node itself.
20
+ This module started as a C++ node binding to libquiche [https://github.com/google/quiche](https://github.com/google/quiche) (note there is a second library with a similar purpose and the same name), which provides besides other network protocols HTTP/3 support. Now it can also handle Webtransport over HTTP/2 and a WebSocket mapping of the HTTP/2 protocol together with a polyfill and ponyfill for the browsers without reliable WebTransport support or no WebTRansport support at all.
21
+ This package currently provides support for WebTransport with an interface similar to the browser side (but not all features implemented), for the server as well as for the client, see `old_test/test.js`, `old_test/testsuite.js`, `old_test/echoclient.js`, `old_test/echoserver.js` for examples.
22
+ Note, that the client implementation only supports certificate checking via `certificateHashes`, however experimental support for rootCA-based checking is introduced with version 1.0.0.
23
+ It may be possible in the future to also support normal HTTP/3 with not so much effort, however, there is no intention from the author to implement this since it will not be needed by FAILS. However, PR requests are welcome and will be supported by advice from the author.
24
+ The package for the HTTP/3 should be considered as a duct tape-style solution until a bulletproof native support of HTTP/3 and WebTransport is provided by node itself.
25
25
 
26
- If you need a ponyfill checkout the sister package [https://github.com/fails-components/webtransport-ponyfill-websocket/](https://github.com/fails-components/webtransport-ponyfill-websocket/),
27
- that provides a mapping of the Webtransport interfaces to Websocket connections.
26
+ If you need a ponyfill check out the sister package [https://github.com/fails-components/webtransport-ponyfill-websocket/](https://github.com/fails-components/webtransport-ponyfill-websocket/), which provides a mapping of the Webtransport interfaces to Websocket connections.
28
27
 
28
+ ## Changes for Version 1.x.x
29
+
30
+ The interface for version 1.x.x is not changed compared to 0.x.x.
31
+ However, it was heavily internally rewritten.
32
+ For example, the implementation does not use a separate event loop for quiche implementation anymore. Instead, it uses node.js native datagram sockets and the event loop of node.js.
33
+ So even though not intended, the library may behave unintended differently in detail.
34
+
35
+ Furthermore, support for WebTransport over http/2 was added, which has to be considered experimental (and the protocol may change anytime), as there is yet no released browser implementation.
36
+ Note, that it is only partially implemented and also some http2 features require changes of node.js itself.
37
+ Use for the server side either `HttpServer` for http/2 and http/3 support (including WebTransport over WebSocket), Http3Server for http/3 only and Http2Server for http/2 only.
38
+ For the client side pass the options `forceReliable`, `requireUnreliable` etc. to force/select a type of transport.
39
+
40
+ **Note, that the http/2 webtransport protocol (not supported by any browser yet), is implemented without the support of receiving initial settings, which can cause a problem with the initial flow control of the WebTransport streams. This is a current limitation in node.js. Note, that for sending the required initial setting you need a very recent (unreleased) version of node.js.** This limitation does not apply to the polyfill/ponyfill and the websocket protocol.
41
+
42
+ ### Ponyfill/Polyfill
43
+ Together with an experimental http/2 implementation of WebTransport, the underlying http/2 capsule protocol had been mapped to the WebSocket protocol, so that the packages can also be used as a ponyfill/polyfill on the browser side.
44
+ Please use `WebTransportPonyfill` for a WebSocket only or `WebTransportPolyfill` as a replacement for `WebTransport`, which automatically falls back to the browser's implementation, if the corresponding features are natively supported in the browser.
29
45
 
30
46
 
31
47
  ## Installation and usage
32
- You can install the package directly via npm from node.js or github packages:
33
48
 
34
- ```bash
49
+ ### Installation
50
+
51
+ You can install the package directly via npm from node.js or GitHub packages:
52
+ In the case of GitHub packages, please add this to your `.npmrc`` file
53
+ ```
54
+ @fails-components:registry=https://npm.pkg.github.com
55
+ ```
56
+ In this case, you need to be authenticated against Github.
57
+
58
+ For installation simply run:
59
+ ```
35
60
  npm install @fails-components/webtransport
36
61
  ```
37
- In case of github packages, please add to your `.npmrc` file
62
+ this will install the main package for node.js or the ponyfill and polyfill for the browser.
63
+ Starting with version 1.0, the binary required for Webtransport for node.js through libquiche is moved to a separate package,
64
+ which you need to install manually in addition to this package:
38
65
  ```
39
- @fails-components:registry=https://npm.pkg.github.com
66
+ npm install @fails-components/webtransport-transport-http3-quiche
40
67
  ```
41
- In this case you need to be authenticated against github.
68
+ this allows a faster installation for people only interested in the http2 WebTransport support or the ponyfill/polyfill mapping the http2 protocol to WebSocket.
42
69
 
43
- The package provides prebuild binaries for `windows`, `linux` and `macos` for the platform `x64` and `ia32` (only windows).
44
- Other platforms may be possible via crosscompiling in the github actions, if someone needs this, PRs are welcome.
70
+ The package `webtransport-transport-http3-quiche` provides prebuild binaries for `windows`, `linux` and `macos` for the platform `x64` and `ia32` (only Windows).
71
+ Other platforms may be possible via cross-compiling in the GitHub actions, if someone needs this, PRs are welcome.
45
72
 
46
- Of course you can also build the binary on your system.
47
- If you are running the compiling install as root, you need to use `--unsafe-perm` as flag.
48
- Installing the package without prebuild requires a full building environment including clang-9, perl6, python, golang, ninja-build, icu. See the `Dockerfile` or `Dockerfile.development` for required debian packages.
49
- This should work for Windows, linux and Mac OS X.
50
- (You may want to check out the building dependencies (especially for windows) for BoringSSl, zlib, abseil on their respective websites).
73
+ Of course, you can also build the binary on your system.
74
+ If you are running the compiling install as root, you need to use `--`unsafe-perm` as a flag.
75
+ 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.
76
+ This should work for Windows, Linux and Mac OS X.
77
+ (You may want to check out the building dependencies (especially for Windows) for BoringSSl, zlib, abseil on their respective websites).
51
78
 
52
79
  Of course, PR for patches and for compiling instructions and necessary changes are welcome for all possible environments.
53
80
 
54
- ** Warning the build time takes more than 15 minutes, on windows even longer! (Due to the building of the third party libraries). **
81
+ **Warning the build time takes more than 15 minutes, on Windows and Mac even longer! (Due to the building of the third-party libraries).**
55
82
 
56
- In the directory `test` you find a simple echo server code. That answers to a series of WebTransport echos. Furthermore some example browser code and finally a unit test of the library including certificate generation.
83
+ In the directory `old_test` you find a simple echo server code. That answers to a series of WebTransport echos. Furthermore some example browser code and finally a unit test of the library including certificate generation.
57
84
 
58
- When testing remember you might need to start chromium based browser with certain flags to accept your http/3 certificate with errors, e.g.:
85
+ When testing remember you might need to start a Chromium-based browser with certain flags to accept your http/3 certificate with errors, e.g.:
59
86
  ```
60
87
  chrome --ignore-certificate-errors-spki-list=FINGERPRINTOFYOURCERTIFICATE --ignore-certificate-errors --v=2 --enable-logging=stderr --origin-to-force-quic-on=192.168.1.50:8080
61
88
  ```
62
- of course replace IP and fingerprint of your certificate accordingly. However, the author never got this to work and is using this without flags, but supplies instead a fingerprint when opening a WebTransport session. (PR welcome).
89
+ of course, replace the IP and fingerprint of your certificate accordingly. However, the author never got this to work (except for http/2 websocket support, and uses only the `--ignore-certificate-errors` flag) and is using this without flags, but supplies instead a fingerprint when opening a WebTransport session. (PRs welcome).
90
+
91
+ ### Setting up a server
92
+ To setup a server use either the class `HttpServer`, `Http3Server` or `Http2Server`.
93
+ While `HttpServer` creates a server supporting http/2 and http/3 (so listening for TCP/IP and UDP), `Http3Server` only supports http/3 and `Http2Server` supports http/2. (Though `HttpServer` is merely a proxy to separate server objects).
94
+
95
+ For example:
96
+ ```
97
+ const server = new Http3Server({
98
+ port: 0,
99
+ host: '127.0.0.1',
100
+ secret: 'mysecret',
101
+ cert: certificate.cert, // unclear if it is the correct format
102
+ privKey: certificate.private
103
+ })
104
+ ```
105
+ create a new server listening on a random port (port `0` triggers that behavior) on host `127.0.0.1`. The secret is only relevant for http/3 and the underlying QUIC connection, the best is to choose a random value. `cert` and `privKey` are the certificate and private key for the server.
106
+
107
+ Other but more expert options include:
108
+ * `certhttp2` and `privKeyhttp2`: For providing a different certificate for the http/2 as the http/2 implementation does not support certificate matching by fingerprints.
109
+ * `initialStreamFlowControlWindow`, `initialSessionFlowControlWindow`, `streamShouldAutoTuneReceiveWindow`, `sessionShouldAutoTuneReceiveWindow`, `streamFlowControlWindowSizeLimit`, `sessionFlowControlWindowSizeLimit`: As expert's option for tweaking the internal flow control.
110
+
111
+ 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
+ In general, the HTTP header is attached as the `header` property to the WebTransport Session object.
113
+
114
+ The method `updateCert(cert, privKey, http2only)` allows to change the certificate, while the server is running (not supported by all transports).
115
+
116
+ With the methods `startServer` and `stopServer` the server can be started and stopped.
117
+ `address()` gives information about the current server address.
118
+
119
+ The properties `ready` and `closed` are Promises, that allow you to wait for the Server to be ready or closed.
120
+
121
+ The method `sessionStream(path, args)` allows to register a `path` to receive WebTransportSessions, it returns a `ReadableStream` of `WebTransportSession` objects.
122
+ The args object can be empty, or have the property `noAutoPaths` prevent the creation of new path streams (internal option, do not use in production).
123
+ The `WebTransportSession` should behave most like a WebTransport object on the browser according to the spec with few additions and some missing features.
124
+
125
+ ### Using a client
126
+ The `WebTransport` object for node or the `WebTransportPonyfill`, `WebTransportPolyfill` objects for the browser, behave like the `WebTransport` client object for the browser with few additions and some missing features.
63
127
 
64
128
  ## Specification divergence
65
129
 
@@ -76,7 +140,7 @@ They are:
76
140
  * [getStats()](https://www.w3.org/TR/webtransport/#dom-webtransport-getstats)
77
141
  * [reliability](https://www.w3.org/TR/webtransport/#dom-webtransport-reliability)
78
142
 
79
- The WebTransport client only supports certification validation using fingerprints. Without a fingerprint it will accept any server without certificate checking.
143
+ The WebTransport client only supports certification validation using fingerprints. Without a fingerprint, an experimental implementation for http/3 checks the certificates against the root certificates integrated with node.
80
144
 
81
145
  ### WebTransportDatagramDuplexStream
82
146
 
@@ -88,9 +152,9 @@ The WebTransport client only supports certification validation using fingerprint
88
152
 
89
153
  ## Development notes
90
154
 
91
- ### Tests
155
+ ### Test
92
156
 
93
- The unit test suite can be run on both node.js and Chrome to ensure behaviour is consistent between the two environments.
157
+ The unit test suite can be run on both node.js and Chrome to ensure behavior is consistent between the two environments.
94
158
 
95
159
  [Mocha](https://www.npmjs.com/package/mocha) is used as a test runner in both environments, in the browser it is run via [playwright-test](https://www.npmjs.com/package/playwright-test).
96
160
 
@@ -130,7 +194,7 @@ Disable headless mode to watch tests run in Chromium:
130
194
  $ npm run test:chromium -- --debug
131
195
  ```
132
196
 
133
- ### Logging
197
+ ### Logging
134
198
 
135
199
  This module uses the [debug](https://www.npmjs.com/package/debug) module for logging.
136
200
 
@@ -7,7 +7,12 @@ import { writeStream } from './fixtures/write-stream.js'
7
7
  import { readCertHash } from './fixtures/read-cert-hash.js'
8
8
  import WebTransport from './fixtures/webtransport.js'
9
9
  import * as ui8 from 'uint8arrays'
10
- import { KNOWN_BYTES, KNOWN_BYTES_LENGTH } from './fixtures/known-bytes.js'
10
+ import {
11
+ KNOWN_BYTES,
12
+ KNOWN_BYTES_LENGTH,
13
+ KNOWN_BYTES_LONG,
14
+ KNOWN_BYTES_LONG_LENGTH
15
+ } from './fixtures/known-bytes.js'
11
16
 
12
17
  /**
13
18
  * @template T
@@ -15,10 +20,8 @@ import { KNOWN_BYTES, KNOWN_BYTES_LENGTH } from './fixtures/known-bytes.js'
15
20
  */
16
21
 
17
22
  describe('bidirectional streams', function () {
18
- // FIXME: sometimes there are seemingly arbitrary 5s delays in
19
- // communicating with the server under node.js
20
- this.timeout(30000)
21
-
23
+ let forceReliable = false
24
+ if (process.env.USE_HTTP2 === 'true') forceReliable = true
22
25
  /** @type {import('../lib/dom').WebTransport | undefined} */
23
26
  let client
24
27
 
@@ -40,7 +43,9 @@ describe('bidirectional streams', function () {
40
43
  algorithm: 'sha-256',
41
44
  value: readCertHash(process.env.CERT_HASH)
42
45
  }
43
- ]
46
+ ],
47
+ // @ts-ignore
48
+ forceReliable
44
49
  }
45
50
  )
46
51
  await client.ready
@@ -55,9 +60,44 @@ describe('bidirectional streams', function () {
55
60
  )
56
61
  })
57
62
 
58
- it('sends and receives data over an incoming bidirectional stream', async () => {
59
- /** @type {Deferred<Uint8Array[]>} */
63
+ it('sends and receives data over an outgoing bidirectional stream with big buffers', async () => {
64
+ // client context - connects to the server, opens a bidi stream, sends some data and reads the response
65
+ client = new WebTransport(
66
+ `${process.env.SERVER_URL}/bidirectional_client_initiated_echo`,
67
+ {
68
+ serverCertificateHashes: [
69
+ {
70
+ algorithm: 'sha-256',
71
+ value: readCertHash(process.env.CERT_HASH)
72
+ }
73
+ ],
74
+ // @ts-ignore
75
+ forceReliable
76
+ }
77
+ )
78
+ await client.ready
79
+
80
+ const stream = await client.createBidirectionalStream()
81
+ await writeStream(stream.writable, KNOWN_BYTES_LONG)
82
+
83
+ const output = await readStream(stream.readable, KNOWN_BYTES_LONG_LENGTH)
84
+ const send = ui8.concat(KNOWN_BYTES_LONG)
85
+ const received = ui8.concat(output)
86
+ let failure = 0
87
+ for (let i = 0; i < Math.max(send.byteLength, received.byteLength); i++) {
88
+ if (send[i] !== received[i] && failure < 100) {
89
+ console.log('d: ', i, ' ,', send[i], ', ', received[i])
90
+ failure++
91
+ }
92
+ }
60
93
 
94
+ expect(ui8.concat(KNOWN_BYTES_LONG)).to.deep.equal(
95
+ ui8.concat(output),
96
+ 'Did not receive the same bytes we sent'
97
+ )
98
+ })
99
+
100
+ it('sends and receives data over an incoming bidirectional stream', async () => {
61
101
  // client context - waits for the server to open a bidi stream then pipes it back to them
62
102
  client = new WebTransport(
63
103
  `${process.env.SERVER_URL}/bidirectional_server_initiated_echo`,
@@ -67,7 +107,9 @@ describe('bidirectional streams', function () {
67
107
  algorithm: 'sha-256',
68
108
  value: readCertHash(process.env.CERT_HASH)
69
109
  }
70
- ]
110
+ ],
111
+ // @ts-ignore
112
+ forceReliable
71
113
  }
72
114
  )
73
115
  await client.ready
@@ -14,6 +14,8 @@ import { pTimeout } from './fixtures/p-timeout.js'
14
14
  describe('datagrams', function () {
15
15
  /** @type {import('../lib/dom').WebTransport | undefined} */
16
16
  let client
17
+ let forceReliable = false
18
+ if (process.env.USE_HTTP2 === 'true') forceReliable = true
17
19
 
18
20
  // @ts-ignore
19
21
  afterEach(async () => {
@@ -32,7 +34,9 @@ describe('datagrams', function () {
32
34
  algorithm: 'sha-256',
33
35
  value: readCertHash(process.env.CERT_HASH)
34
36
  }
35
- ]
37
+ ],
38
+ // @ts-ignore
39
+ forceReliable
36
40
  }
37
41
  )
38
42
  await client.ready
@@ -73,7 +77,9 @@ describe('datagrams', function () {
73
77
  algorithm: 'sha-256',
74
78
  value: readCertHash(process.env.CERT_HASH)
75
79
  }
76
- ]
80
+ ],
81
+ // @ts-ignore
82
+ forceReliable
77
83
  }
78
84
  )
79
85
  await client.ready
@@ -13,3 +13,32 @@ export const KNOWN_BYTES_LENGTH = KNOWN_BYTES.reduce(
13
13
  (accumulator, currentValue) => accumulator + currentValue.length,
14
14
  0
15
15
  )
16
+
17
+ const createBytesChunk = function (/** @type {number} */ length) {
18
+ const workArray = new Array(length / 2)
19
+ for (let i = 0; i < length / 4; i++) {
20
+ workArray[2 * i + 1] = length % 0xffff
21
+ workArray[2 * i] = i
22
+ }
23
+ const helper = new Uint16Array(workArray)
24
+ const toreturn = new Uint8Array(
25
+ helper.buffer,
26
+ helper.byteOffset,
27
+ helper.byteLength
28
+ )
29
+ return toreturn
30
+ }
31
+
32
+ export const KNOWN_BYTES_LONG = [
33
+ createBytesChunk(60000), // 96, 234
34
+ createBytesChunk(12), // 0, 12
35
+ createBytesChunk(50000), // 195, 80
36
+ createBytesChunk(1600), // 6, 64
37
+ createBytesChunk(20000), // 78, 32
38
+ createBytesChunk(30000) // 117, 48
39
+ ]
40
+
41
+ export const KNOWN_BYTES_LONG_LENGTH = KNOWN_BYTES_LONG.reduce(
42
+ (accumulator, currentValue) => accumulator + currentValue.length,
43
+ 0
44
+ )
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @template T
3
- * @typedef {import('node:stream/web').ReadableStream<T>} ReadableStream<T>
3
+ * @typedef {import('../../lib/webstreams').ReadableStream<T>} ReadableStream<T>
4
4
  */
5
5
 
6
6
  /**
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @template T
3
- * @typedef {import('node:stream/web').ReadableStream<T>} ReadableStream<T>
3
+ * @typedef {import('../../lib/webstreams').ReadableStream<T>} ReadableStream<T>
4
4
  */
5
5
 
6
6
  /**
@@ -1,5 +1,5 @@
1
1
  import { generateWebTransportCertificate } from './certificate.js'
2
- import { Http3Server } from '../../lib/index.js'
2
+ import { Http2Server, Http3Server } from '../../lib/index.node.js'
3
3
  import { pTimeout } from './p-timeout.js'
4
4
  import { getReaderStream, getReaderValue } from './reader-value.js'
5
5
  import { writeStream } from './write-stream.js'
@@ -24,15 +24,29 @@ export async function createServer() {
24
24
  throw new Error('Certificate generation failed')
25
25
  }
26
26
 
27
- const server = new Http3Server({
28
- /* port: 8080,
27
+ /** @type {Http2Server|Http3Server} */
28
+ let server
29
+ if (process.env.USE_HTTP2 === 'true') {
30
+ server = new Http2Server({
31
+ /* port: 8080,
32
+ host: '0.0.0.0', */
33
+ port: 0,
34
+ host: '127.0.0.1',
35
+ secret: 'mysecret',
36
+ cert: certificate.cert, // unclear if it is the correct format
37
+ privKey: certificate.private
38
+ })
39
+ } else {
40
+ server = new Http3Server({
41
+ /* port: 8080,
29
42
  host: '0.0.0.0', */
30
- port: 0,
31
- host: '127.0.0.1',
32
- secret: 'mysecret',
33
- cert: certificate.cert, // unclear if it is the correct format
34
- privKey: certificate.private
35
- })
43
+ port: 0,
44
+ host: '127.0.0.1',
45
+ secret: 'mysecret',
46
+ cert: certificate.cert, // unclear if it is the correct format
47
+ privKey: certificate.private
48
+ })
49
+ }
36
50
 
37
51
  server.ready
38
52
  .then(async () => {
@@ -153,7 +167,7 @@ export async function createServer() {
153
167
  for await (const session of getReaderStream(
154
168
  server.sessionStream('/session_close')
155
169
  )) {
156
- session.close()
170
+ await session.close()
157
171
  }
158
172
  },
159
173
 
@@ -1,2 +1,20 @@
1
- // @ts-expect-error not TypeScript's dom.d.ts yet
2
- export default WebTransport // eslint-disable-line no-undef
1
+ import {
2
+ WebTransportPolyfill,
3
+ WebTransportPonyfill
4
+ } from '../../lib/webtransport.browser'
5
+
6
+ /** @type {import('../../lib/dom').WebTransport} */
7
+ // @ts-ignore
8
+ // eslint-disable-next-line no-undef
9
+ let webtransport = WebTransport
10
+ if (process.env.USE_POLYFILL === 'true') {
11
+ // @ts-ignore
12
+ webtransport = WebTransportPolyfill
13
+ }
14
+
15
+ if (process.env.USE_PONYFILL === 'true') {
16
+ // @ts-ignore
17
+ webtransport = WebTransportPonyfill
18
+ }
19
+
20
+ export default webtransport // eslint-disable-line no-undef
@@ -1,3 +1,3 @@
1
- import { WebTransport } from '../../lib/index.js'
1
+ import { WebTransport } from '../../lib/index.node.js'
2
2
 
3
3
  export default WebTransport
package/test/index.js CHANGED
@@ -5,11 +5,16 @@ import { execa } from 'execa'
5
5
  * getting stuck waiting for the custom event loop to end.
6
6
  */
7
7
  async function startServer() {
8
+ let http2 = false
9
+ if (process.argv[3] === 'http2') http2 = true
8
10
  return new Promise((resolve, reject) => {
9
11
  let foundAddress = false
10
12
 
11
13
  const server = execa('node', ['./test/fixtures/server.js'], {
12
- stdio: ['inherit', 'inherit', 'inherit', 'ipc']
14
+ stdio: ['inherit', 'inherit', 'inherit', 'ipc'],
15
+ env: {
16
+ USE_HTTP2: http2 ? 'true' : 'false'
17
+ }
13
18
  })
14
19
  server.on('message', (data) => {
15
20
  if (!foundAddress) {
@@ -27,6 +32,21 @@ async function startServer() {
27
32
  */
28
33
  async function runTests(certificate, serverAddress) {
29
34
  const env = process.argv[2]
35
+ let http2 = false
36
+ if (process.argv[3] === 'http2') http2 = true
37
+ let polyfill = false
38
+ let ponyfill = false
39
+ let slice = 4
40
+ if (process.argv.length > 3 && process.argv[4] === 'polyfill') {
41
+ polyfill = true
42
+ slice++
43
+ if (env === 'node') throw new Error('Polyfill not supported on node')
44
+ }
45
+ if (process.argv.length > 3 && process.argv[4] === 'ponyfill') {
46
+ ponyfill = true
47
+ slice++
48
+ if (env === 'node') throw new Error('Ponyfill not supported on node')
49
+ }
30
50
  /** @type {string} */
31
51
  let command = ''
32
52
  /** @type {string[]} */
@@ -37,14 +57,14 @@ async function runTests(certificate, serverAddress) {
37
57
  args = [
38
58
  process.env.CI ? '--no-colors' : '--colors',
39
59
  './test/*.spec.js',
40
- './test/*.node.js',
41
- ...process.argv.slice(3)
60
+ ...process.argv.slice(4)
42
61
  ]
43
62
  const tests = execa(command, args, {
44
63
  env: {
45
64
  DEBUG_COLORS: process.env.CI ? '' : 'true',
46
65
  CERT_HASH: certificate,
47
- SERVER_URL: serverAddress
66
+ SERVER_URL: serverAddress,
67
+ USE_HTTP2: http2 ? 'true' : 'false'
48
68
  },
49
69
  stdio: ['inherit', 'inherit', 'inherit']
50
70
  })
@@ -52,12 +72,18 @@ async function runTests(certificate, serverAddress) {
52
72
  await tests
53
73
  } else if (env === 'chromium') {
54
74
  command = 'playwright-test'
55
- args = ['./test/*.spec.js', ...process.argv.slice(3)]
75
+ const otheropts = []
76
+ if (polyfill || ponyfill)
77
+ otheropts.push('--config', './test/pw-no-https-errors.json')
78
+ args = ['./test/*.spec.js', ...otheropts, ...process.argv.slice(slice)]
56
79
  const tests = execa(command, args, {
57
80
  env: {
58
81
  DEBUG_COLORS: process.env.CI ? '' : 'true',
59
82
  CERT_HASH: certificate,
60
- SERVER_URL: serverAddress
83
+ SERVER_URL: serverAddress,
84
+ USE_HTTP2: http2 ? 'true' : 'false',
85
+ USE_POLYFILL: polyfill ? 'true' : 'false',
86
+ USE_PONYFILL: ponyfill ? 'true' : 'false'
61
87
  },
62
88
  stdio: ['inherit', 'inherit', 'inherit']
63
89
  })
@@ -79,6 +105,7 @@ try {
79
105
  }
80
106
 
81
107
  if (err.failed || err.timedOut || err.isCancelled || err.isKilled) {
108
+ console.log('Error cause mocha process', err)
82
109
  success = false
83
110
  }
84
111
  } finally {
@@ -0,0 +1,5 @@
1
+ {
2
+ "browserContextOptions": {
3
+ "ignoreHTTPSErrors": true
4
+ }
5
+ }