@fails-components/webtransport 0.3.1 → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/client.js +81 -40
- package/lib/dom.ts +7 -5
- package/lib/http2/browser/browser.js +168 -0
- package/lib/http2/browser/browserparser.js +248 -0
- package/lib/http2/flowcontroller.js +371 -0
- package/lib/http2/node/capsuleparser.js +291 -0
- package/lib/http2/node/client.js +239 -0
- package/lib/http2/node/index.js +2 -0
- package/lib/http2/node/server.js +499 -0
- package/lib/http2/node/websocketparser.js +829 -0
- package/lib/http2/parserbase.js +139 -0
- package/lib/http2/parserbasehttp2.js +128 -0
- package/lib/http2/session.js +225 -0
- package/lib/http2/stream.js +354 -0
- package/lib/http2/websocketcommon.js +1 -0
- package/lib/{index.js → index.browser.js} +6 -10
- package/lib/index.node.js +27 -0
- package/lib/server.js +252 -69
- package/lib/session.js +31 -68
- package/lib/stream.js +103 -179
- package/lib/types.ts +174 -87
- package/lib/utils.js +2 -1
- package/lib/webstreams.browser.js +6 -0
- package/lib/webstreams.js +7 -0
- package/lib/webtransport.browser.js +284 -0
- package/lib/webtransport.node.js +137 -0
- package/lib/{webtransport.js → webtransportbase.js} +47 -41
- package/old_test/test.js +31 -29
- package/old_test/testsuite.js +1 -1
- package/package.json +18 -17
- package/readme.md +94 -30
- package/test/bidirectional-streams.spec.js +51 -9
- package/test/datagrams.spec.js +8 -2
- package/test/fixtures/known-bytes.js +29 -0
- package/test/fixtures/read-stream.js +1 -1
- package/test/fixtures/reader-value.js +1 -1
- package/test/fixtures/server.js +24 -10
- package/test/fixtures/webtransport.browser.js +20 -2
- package/test/fixtures/webtransport.js +1 -1
- package/test/index.js +33 -6
- package/test/pw-no-https-errors.json +5 -0
- package/test/session.spec.js +71 -52
- package/test/unidirectional-streams.spec.js +20 -4
- package/CMakeLists.txt +0 -991
- package/LICENSE.chromium +0 -27
- package/LICENSE.envoy +0 -207
- package/build.js +0 -313
- package/dist/lib/client.d.ts +0 -78
- package/dist/lib/client.d.ts.map +0 -1
- package/dist/lib/dom.d.ts +0 -87
- package/dist/lib/dom.d.ts.map +0 -1
- package/dist/lib/error.d.ts +0 -8
- package/dist/lib/error.d.ts.map +0 -1
- package/dist/lib/event-loop.d.ts +0 -33
- package/dist/lib/event-loop.d.ts.map +0 -1
- package/dist/lib/index.d.ts +0 -79
- package/dist/lib/index.d.ts.map +0 -1
- package/dist/lib/native.d.ts +0 -2
- package/dist/lib/native.d.ts.map +0 -1
- package/dist/lib/server.d.ts +0 -92
- package/dist/lib/server.d.ts.map +0 -1
- package/dist/lib/session.d.ts +0 -298
- package/dist/lib/session.d.ts.map +0 -1
- package/dist/lib/stream.d.ts +0 -135
- package/dist/lib/stream.d.ts.map +0 -1
- package/dist/lib/transport.d.ts +0 -34
- package/dist/lib/transport.d.ts.map +0 -1
- package/dist/lib/types.d.ts +0 -212
- package/dist/lib/types.d.ts.map +0 -1
- package/dist/lib/utils.d.ts +0 -11
- package/dist/lib/utils.d.ts.map +0 -1
- package/dist/lib/webtransport.d.ts +0 -47
- package/dist/lib/webtransport.d.ts.map +0 -1
- package/dist/test/bidirectional-streams.spec.d.ts +0 -5
- package/dist/test/bidirectional-streams.spec.d.ts.map +0 -1
- package/dist/test/datagrams.spec.d.ts +0 -5
- package/dist/test/datagrams.spec.d.ts.map +0 -1
- package/dist/test/event-loop.node.d.ts +0 -2
- package/dist/test/event-loop.node.d.ts.map +0 -1
- package/dist/test/fixtures/certificate.d.ts +0 -21
- package/dist/test/fixtures/certificate.d.ts.map +0 -1
- package/dist/test/fixtures/chai.d.ts +0 -2
- package/dist/test/fixtures/chai.d.ts.map +0 -1
- package/dist/test/fixtures/known-bytes.d.ts +0 -6
- package/dist/test/fixtures/known-bytes.d.ts.map +0 -1
- package/dist/test/fixtures/p-timeout.d.ts +0 -8
- package/dist/test/fixtures/p-timeout.d.ts.map +0 -1
- package/dist/test/fixtures/read-cert-hash.d.ts +0 -6
- package/dist/test/fixtures/read-cert-hash.d.ts.map +0 -1
- package/dist/test/fixtures/read-stream.d.ts +0 -19
- package/dist/test/fixtures/read-stream.d.ts.map +0 -1
- package/dist/test/fixtures/reader-value.d.ts +0 -22
- package/dist/test/fixtures/reader-value.d.ts.map +0 -1
- package/dist/test/fixtures/server.d.ts +0 -5
- package/dist/test/fixtures/server.d.ts.map +0 -1
- package/dist/test/fixtures/webtransport.browser.d.ts +0 -3
- package/dist/test/fixtures/webtransport.browser.d.ts.map +0 -1
- package/dist/test/fixtures/webtransport.d.ts +0 -3
- package/dist/test/fixtures/webtransport.d.ts.map +0 -1
- package/dist/test/fixtures/write-stream.d.ts +0 -10
- package/dist/test/fixtures/write-stream.d.ts.map +0 -1
- package/dist/test/index.d.ts +0 -2
- package/dist/test/index.d.ts.map +0 -1
- package/dist/test/session.spec.d.ts +0 -5
- package/dist/test/session.spec.d.ts.map +0 -1
- package/dist/test/unidirectional-streams.spec.d.ts +0 -2
- package/dist/test/unidirectional-streams.spec.d.ts.map +0 -1
- package/failslogolicensereadme.txt +0 -4
- package/lib/event-loop.js +0 -88
- package/lib/native.js +0 -28
- package/lib/transport.js +0 -82
- package/platform/icufix/fakedata.cpp +0 -8
- package/platform/quiche/quic/core/io/socket_win.inc +0 -3
- package/platform/quiche_platform_impl/quiche_bug_tracker_impl.h +0 -7
- package/platform/quiche_platform_impl/quiche_client_stats_impl.h +0 -7
- package/platform/quiche_platform_impl/quiche_command_line_flags_impl.h +0 -7
- package/platform/quiche_platform_impl/quiche_containers_impl.h +0 -7
- package/platform/quiche_platform_impl/quiche_event_loop_impl.h +0 -7
- package/platform/quiche_platform_impl/quiche_export_impl.h +0 -6
- package/platform/quiche_platform_impl/quiche_flag_utils_impl.h +0 -11
- package/platform/quiche_platform_impl/quiche_flags_impl.h +0 -8
- package/platform/quiche_platform_impl/quiche_iovec_impl.h +0 -10
- package/platform/quiche_platform_impl/quiche_logging_impl.h +0 -21
- package/platform/quiche_platform_impl/quiche_mem_slice_impl.h +0 -2
- package/platform/quiche_platform_impl/quiche_mutex_impl.h +0 -8
- package/platform/quiche_platform_impl/quiche_prefetch_impl.h +0 -11
- package/platform/quiche_platform_impl/quiche_reference_counted_impl.h +0 -16
- package/platform/quiche_platform_impl/quiche_server_stats_impl.h +0 -7
- package/platform/quiche_platform_impl/quiche_stack_trace_impl.h +0 -12
- package/platform/quiche_platform_impl/quiche_stream_buffer_allocator_impl.h +0 -8
- package/platform/quiche_platform_impl/quiche_testvalue_impl.h +0 -1
- package/platform/quiche_platform_impl/quiche_thread_local_impl.h +0 -6
- package/platform/quiche_platform_impl/quiche_time_utils_impl.h +0 -13
- package/platform/quiche_platform_impl/quiche_udp_socket_platform_impl.h +0 -39
- package/src/http3backendresponse.cc +0 -36
- package/src/http3backendresponse.h +0 -109
- package/src/http3client.cc +0 -1529
- package/src/http3client.h +0 -557
- package/src/http3clientsession.cc +0 -65
- package/src/http3clientsession.h +0 -60
- package/src/http3clientstream.cc +0 -52
- package/src/http3clientstream.h +0 -42
- package/src/http3dispatcher.cc +0 -62
- package/src/http3dispatcher.h +0 -57
- package/src/http3eventloop.cc +0 -1107
- package/src/http3eventloop.h +0 -316
- package/src/http3server.cc +0 -514
- package/src/http3server.h +0 -151
- package/src/http3serverbackend.cc +0 -105
- package/src/http3serverbackend.h +0 -98
- package/src/http3serversession.cc +0 -123
- package/src/http3serversession.h +0 -95
- package/src/http3serverstream.cc +0 -463
- package/src/http3serverstream.h +0 -114
- package/src/http3sessioncache.cc +0 -85
- package/src/http3sessioncache.h +0 -59
- package/src/http3wtsessionvisitor.cc +0 -46
- package/src/http3wtsessionvisitor.h +0 -397
- package/src/http3wtstreamvisitor.cc +0 -155
- package/src/http3wtstreamvisitor.h +0 -404
- package/test/event-loop.node.js +0 -24
- package/tsconfig.json +0 -39
package/package.json
CHANGED
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fails-components/webtransport",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "1.0.1",
|
|
4
4
|
"description": "A component to add webtransport support (server and client) to node.js using libquiche",
|
|
5
|
-
"
|
|
6
|
-
|
|
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:
|
|
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
|
-
"
|
|
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
|
|
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  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
|
|
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
|
|
18
|
+
This package is licensed more permissive since it can be useful outside of the FAILS environment.
|
|
19
19
|
|
|
20
|
-
This module
|
|
21
|
-
This
|
|
22
|
-
Note, the client implementation only supports
|
|
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
|
|
24
|
-
The package should be considered as a
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
66
|
+
npm install @fails-components/webtransport-transport-http3-quiche
|
|
40
67
|
```
|
|
41
|
-
|
|
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
|
|
44
|
-
Other platforms may be possible via
|
|
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
|
|
48
|
-
Installing the package without prebuild requires a full building environment including clang-9, perl6, python, golang, ninja-build, icu
|
|
49
|
-
This should work for Windows,
|
|
50
|
-
(You may want to check out the building dependencies (especially for
|
|
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
|
-
**
|
|
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 `
|
|
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
|
|
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. (
|
|
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
|
|
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
|
-
###
|
|
155
|
+
### Test
|
|
92
156
|
|
|
93
|
-
The unit test suite can be run on both node.js and Chrome to ensure
|
|
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
|
-
###
|
|
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 {
|
|
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
|
-
|
|
19
|
-
|
|
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
|
|
59
|
-
|
|
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
|
package/test/datagrams.spec.js
CHANGED
|
@@ -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
|
+
)
|
package/test/fixtures/server.js
CHANGED
|
@@ -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
|
-
|
|
28
|
-
|
|
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
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
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
|
-
|
|
2
|
-
|
|
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
|
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
|
-
|
|
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
|
-
|
|
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 {
|