@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
@@ -0,0 +1,239 @@
1
+ import { connect, constants as http2constants } from 'node:http2'
2
+ import { Http2WebTransportSession } from '../session.js'
3
+ import { Http2CapsuleParser } from './capsuleparser.js'
4
+ import { logger } from '../../utils.js'
5
+
6
+ const log = logger(`webtransport:http2:node:client(${process?.pid})`)
7
+
8
+ export class Http2WebTransportClient {
9
+ /**
10
+ * @param {import('../../types.js').NativeClientOptions} args
11
+ */
12
+ constructor(args) {
13
+ let port = args?.port
14
+ if (typeof port === 'undefined') port = 443
15
+ this.port = Number(port)
16
+ this.hostname = args?.host || 'localhost'
17
+ this.serverCertificateHashes = args?.serverCertificateHashes || undefined
18
+ this.localPort = Number(args?.localPort) || undefined
19
+ this.allowPooling = args?.allowPooling || false
20
+ this.forceIpv6 = args?.forceIpv6 || false
21
+ this.initialStreamFlowControlWindow =
22
+ args?.initialStreamFlowControlWindow || 16 * 1024 // 16 KB
23
+ this.initialSessionFlowControlWindow =
24
+ args?.initialSessionFlowControlWindow || 16 * 1024 // 16 KB
25
+
26
+ this.streamShouldAutoTuneReceiveWindow =
27
+ args.streamShouldAutoTuneReceiveWindow || false
28
+ this.streamFlowControlWindowSizeLimit =
29
+ args?.streamFlowControlWindowSizeLimit || 6 * 1024 * 1024
30
+
31
+ this.sessionShouldAutoTuneReceiveWindow =
32
+ args.sessionShouldAutoTuneReceiveWindow || false
33
+ this.sessionFlowControlWindowSizeLimit =
34
+ args?.sessionFlowControlWindowSizeLimit || 15 * 1024 * 1024
35
+ /** @type {import('../../session.js').HttpClient} */
36
+ // @ts-ignore
37
+ this.jsobj = undefined // the transport will set this
38
+ }
39
+
40
+ createTransport() {
41
+ /**
42
+ * @param {import('node:tls').PeerCertificate} cert
43
+ * */
44
+ const webTransportVerifier = (cert) => {
45
+ if (
46
+ this.serverCertificateHashes &&
47
+ this.serverCertificateHashes.some((el) => {
48
+ if (el.algorithm !== 'sha-256') return false
49
+ const cbytes = cert.fingerprint256
50
+ .split(':')
51
+ .map((el) => parseInt(el, 16))
52
+ const val = Buffer.isBuffer(el.value)
53
+ ? el.value
54
+ : new Uint8Array(
55
+ ArrayBuffer.isView(el.value) ? el.value.buffer : el.value
56
+ )
57
+ if (cbytes.length !== val.byteLength) return false
58
+ for (let i = 0; i < val.byteLength; i++) {
59
+ if (val[i] !== cbytes[i]) return false
60
+ }
61
+ const curdate = new Date()
62
+
63
+ if (
64
+ new Date(cert.valid_from) > curdate ||
65
+ new Date(cert.valid_to) < curdate
66
+ )
67
+ return false
68
+
69
+ const difference =
70
+ new Date(cert.valid_to).getTime() -
71
+ new Date(cert.valid_from).getTime()
72
+ if (difference > 1000 * 60 * 60 * 24 * 14) return false // no more than 14 days spec says.
73
+ return true
74
+ })
75
+ )
76
+ return true
77
+ else return false
78
+ }
79
+ const http2Options = {
80
+ settings: {
81
+ enableConnectProtocol: true,
82
+ customSettings: {
83
+ 0x2b60: 1, // SETTINGS_WEBTRANSPORT_MAX_SESSIONS, TODO fix number
84
+ 0x2b61: this.initialSessionFlowControlWindow, // SETTINGS_WEBTRANSPORT_INITIAL_MAX_DATA
85
+ 0x2b62: this.initialStreamFlowControlWindow, // SETTINGS_WEBTRANSPORT_INITIAL_MAX_STREAM_DATA_UNI
86
+ 0x2b63: this.initialStreamFlowControlWindow, // SETTINGS_WEBTRANSPORT_INITIAL_MAX_STREAM_DATA_BIDI
87
+ 0x2b64: 0xffffff, // SETTINGS_WEBTRANSPORT_INITIAL_MAX_STREAMS_UNI
88
+ 0x2b65: 0xffffff // SETTINGS_WEBTRANSPORT_INITIAL_MAX_STREAMS_BIDI
89
+ }
90
+ },
91
+ localPort: this.localPort,
92
+ // TODO: REMOVE BEFORE RELEASE; UNSAFE SETTING
93
+ rejectUnauthorized: !this.serverCertificateHashes
94
+ }
95
+ if (this.serverCertificateHashes)
96
+ // @ts-ignore
97
+ http2Options.checkServerIdentity = webTransportVerifier
98
+
99
+ // @ts-ignore
100
+ this.clientInt = connect(
101
+ 'https://' + this.hostname + ':' + this.port,
102
+ http2Options
103
+ )
104
+
105
+ let rtt = 100
106
+ let adjust = 1
107
+ // ok we got a session and want to measure RTT
108
+ let pingsender = setInterval(() => {
109
+ if (this.clientInt && !this.clientInt.closed) {
110
+ this.clientInt.ping((err, duration, payload) => {
111
+ if (!err) {
112
+ rtt = adjust * duration + (1 - adjust) * rtt
113
+ adjust = 0.2
114
+ // @ts-ignore
115
+ this.clientInt.WTrtt = rtt
116
+ }
117
+ })
118
+ } else {
119
+ clearInterval(pingsender)
120
+ // @ts-ignore
121
+ pingsender = undefined
122
+ }
123
+ }, 1000)
124
+
125
+ this.clientInt.on('close', () => {
126
+ if (pingsender) clearInterval(pingsender)
127
+ })
128
+
129
+ let authfail = false
130
+ this.clientInt.socket.on('secureConnect', () => {
131
+ /** @type {import('node:tls').TLSSocket} */
132
+ // @ts-ignore
133
+ const oursocket = this.clientInt?.socket
134
+ if (!oursocket) throw new Error('Can not get http2 TLSSocket')
135
+ // @ts-ignore
136
+ if (!oursocket.authorized) {
137
+ // ok last hope we have hashes
138
+ if (this.serverCertificateHashes) {
139
+ if (!webTransportVerifier(oursocket.getPeerCertificate())) {
140
+ this.clientInt?.destroy(
141
+ undefined,
142
+ http2constants.NGHTTP2_REFUSED_STREAM
143
+ )
144
+ log('Certificate hash does not match')
145
+ authfail = true
146
+ this.jsobj.onClientConnected({
147
+ success: false
148
+ })
149
+ } else {
150
+ oursocket.authorized = true
151
+ }
152
+ } else {
153
+ this.clientInt?.destroy(
154
+ new Error('Certificate not authorized'),
155
+ http2constants.NGHTTP2_REFUSED_STREAM
156
+ )
157
+ authfail = true
158
+ log('Certificate not authorized')
159
+ this.jsobj.onClientConnected({
160
+ success: false
161
+ })
162
+ }
163
+ }
164
+ })
165
+ let connected = false
166
+ this.clientInt.on('connect', (session, socket) => {
167
+ if (!authfail) {
168
+ connected = true
169
+ this.jsobj.onClientConnected({
170
+ success: true
171
+ })
172
+ }
173
+ })
174
+ this.clientInt.on('error', (error) => {
175
+ log('http2 client error:', error)
176
+ if (!connected && !authfail) {
177
+ this.jsobj.onClientConnected({
178
+ success: false
179
+ })
180
+ }
181
+ })
182
+ this.clientInt.on('remoteSettings', (settings) => {
183
+ if (settings.enableConnectProtocol && this.clientInt) {
184
+ // if (settings.webtansportmaxsessions)
185
+ // eslint-disable-next-line no-lone-blocks
186
+ {
187
+ const retObj = {}
188
+ this.jsobj.onClientWebTransportSupport(retObj)
189
+ }
190
+ }
191
+ })
192
+ }
193
+
194
+ /**
195
+ * @param {string} path
196
+ */
197
+ openWTSession(path) {
198
+ if (!this.clientInt) throw new Error('clientInt not present')
199
+
200
+ const stream = this.clientInt.request({
201
+ ':method': 'CONNECT',
202
+ ':protocol': 'webtransport',
203
+ ':scheme': 'https',
204
+ ':path': path,
205
+ authority: this.hostname,
206
+ origin: this.hostname
207
+ })
208
+
209
+ const retObj = {
210
+ header: stream.sentHeaders,
211
+ session: new Http2WebTransportSession({
212
+ stream,
213
+ isclient: true,
214
+ createParser: (/** @type {Http2WebTransportSession} */ nativesession) =>
215
+ new Http2CapsuleParser({
216
+ stream,
217
+ nativesession,
218
+ isclient: true,
219
+ initialStreamSendWindowOffset: this.initialStreamFlowControlWindow,
220
+ initialStreamReceiveWindowOffset:
221
+ this.initialStreamFlowControlWindow,
222
+ streamShouldAutoTuneReceiveWindow:
223
+ this.streamShouldAutoTuneReceiveWindow,
224
+ streamReceiveWindowSizeLimit: this.streamFlowControlWindowSizeLimit
225
+ }),
226
+ sendWindowOffset: this.sessionFlowControlWindowSizeLimit,
227
+ receiveWindowOffset: this.sessionFlowControlWindowSizeLimit,
228
+ shouldAutoTuneReceiveWindow: this.sessionShouldAutoTuneReceiveWindow,
229
+ receiveWindowSizeLimit: this.sessionFlowControlWindowSizeLimit
230
+ }),
231
+ reliable: true
232
+ }
233
+ this.jsobj.onHttpWTSessionVisitor(retObj)
234
+ }
235
+
236
+ closeClient() {
237
+ if (this.clientInt) this.clientInt.close()
238
+ }
239
+ }
@@ -0,0 +1,2 @@
1
+ export { Http2WebTransportClient } from './client.js'
2
+ export { Http2WebTransportServer } from './server.js'