@fails-components/webtransport-transport-http3-quiche 1.3.0 → 1.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CMakeLists.txt CHANGED
@@ -88,7 +88,6 @@ platform/quiche_platform_impl/quiche_stream_buffer_allocator_impl.h
88
88
  platform/quiche_platform_impl/quiche_time_utils_impl.h
89
89
  platform/quiche_platform_impl/quiche_udp_socket_platform_impl.h
90
90
  platform/quiche_platform_impl/quiche_server_stats_impl.h
91
- platform/quiche_platform_impl/quiche_mem_slice_impl.h
92
91
  platform/quiche_platform_impl/quiche_flag_utils_impl.h
93
92
  #protofiles
94
93
  #${PROTO_SRCS}
@@ -157,7 +156,6 @@ third_party/quiche/quiche/common/platform/api/quiche_hostname_utils.cc
157
156
  third_party/quiche/quiche/common/platform/api/quiche_hostname_utils.h
158
157
  third_party/quiche/quiche/common/platform/api/quiche_iovec.h
159
158
  third_party/quiche/quiche/common/platform/api/quiche_logging.h
160
- third_party/quiche/quiche/common/platform/api/quiche_mem_slice.h
161
159
  third_party/quiche/quiche/common/platform/api/quiche_reference_counted.h
162
160
  third_party/quiche/quiche/common/platform/api/quiche_time_utils.h
163
161
  third_party/quiche/quiche/common/platform/api/quiche_url_utils.h
@@ -168,7 +166,6 @@ third_party/quiche/quiche/common/platform/default/quiche_platform_impl/quiche_fl
168
166
  third_party/quiche/quiche/common/platform/default/quiche_platform_impl/quiche_flags_impl.cc
169
167
  third_party/quiche/quiche/common/platform/default/quiche_platform_impl/quiche_logging_impl.cc
170
168
  third_party/quiche/quiche/common/platform/default/quiche_platform_impl/quiche_logging_impl.h
171
- third_party/quiche/quiche/common/platform/api/quiche_mem_slice.cc
172
169
  third_party/quiche/quiche/common/platform/default/quiche_platform_impl/quiche_stack_trace_impl.cc
173
170
  third_party/quiche/quiche/common/platform/default/quiche_platform_impl/quiche_stack_trace_impl.h
174
171
  third_party/quiche/quiche/common/platform/default/quiche_platform_impl/quiche_iovec_impl.h
@@ -189,6 +186,8 @@ third_party/quiche/quiche/common/quiche_ip_address.h
189
186
  third_party/quiche/quiche/common/quiche_ip_address_family.cc
190
187
  third_party/quiche/quiche/common/quiche_ip_address_family.h
191
188
  third_party/quiche/quiche/common/quiche_linked_hash_map.h
189
+ third_party/quiche/quiche/common/quiche_mem_slice.cc
190
+ third_party/quiche/quiche/common/quiche_mem_slice.h
192
191
  third_party/quiche/quiche/common/quiche_mem_slice_storage.h
193
192
  third_party/quiche/quiche/common/quiche_mem_slice_storage.cc
194
193
  third_party/quiche/quiche/common/quiche_random.cc
@@ -744,8 +743,12 @@ third_party/quiche/quiche/quic/core/quic_stream_id_manager.cc
744
743
  third_party/quiche/quiche/quic/core/quic_stream_id_manager.h
745
744
  third_party/quiche/quiche/quic/core/quic_stream_priority.cc
746
745
  third_party/quiche/quiche/quic/core/quic_stream_priority.h
746
+ third_party/quiche/quiche/quic/core/quic_stream_send_buffer_base.cc
747
+ third_party/quiche/quiche/quic/core/quic_stream_send_buffer_base.h
747
748
  third_party/quiche/quiche/quic/core/quic_stream_send_buffer.cc
748
749
  third_party/quiche/quiche/quic/core/quic_stream_send_buffer.h
750
+ third_party/quiche/quiche/quic/core/quic_stream_send_buffer_inlining.cc
751
+ third_party/quiche/quiche/quic/core/quic_stream_send_buffer_inlining.h
749
752
  third_party/quiche/quiche/quic/core/quic_stream_sequencer.cc
750
753
  third_party/quiche/quiche/quic/core/quic_stream_sequencer.h
751
754
  third_party/quiche/quiche/quic/core/quic_stream_sequencer_buffer.cc
@@ -1 +1 @@
1
- {"version":3,"file":"socket.d.ts","sourceRoot":"","sources":["../../lib/socket.js"],"names":[],"mappings":"AAqEA;IACE;;OAEG;IAEH,kBAHW,OAAO,4BAA4B,EAAE,oBAAoB,GAAC,SAAS,EAc7E;IAVC,0CAA0C;IAE1C,WAFW,OAAO,YAAY,EAAE,MAAM,CAEZ;IAE1B,UAAqB;IACrB,oBAAuB;IAgCzB,qBASC;IAlCD,+BAGC;IAPC,iBAAoB;IACpB,gBAAmB;IAQrB;;OAEG;IAEH,mDAHW,OAAO,SAAS,EAAE,mBAAmB,WAiB/C;CAYF"}
1
+ {"version":3,"file":"socket.d.ts","sourceRoot":"","sources":["../../lib/socket.js"],"names":[],"mappings":"AAkFA;IACE;;OAEG;IAEH,kBAHW,OAAO,4BAA4B,EAAE,oBAAoB,GAAC,SAAS,EAc7E;IAVC,0CAA0C;IAE1C,WAFW,OAAO,YAAY,EAAE,MAAM,CAEZ;IAE1B,UAAqB;IACrB,oBAAuB;IAgCzB,qBASC;IAlCD,+BAGC;IAPC,iBAAoB;IACpB,gBAAmB;IAQrB;;OAEG;IAEH,mDAHW,OAAO,SAAS,EAAE,mBAAmB,WAiB/C;CAYF"}
package/eslint.config.js CHANGED
@@ -1,21 +1,22 @@
1
-
2
- import js from "@eslint/js"
3
- import promise from "eslint-plugin-promise"
4
- import babelParser from "@babel/eslint-parser"
1
+ import js from '@eslint/js'
2
+ import promise from 'eslint-plugin-promise'
3
+ import babelParser from '@babel/eslint-parser'
4
+ import importplug from 'eslint-plugin-import'
5
+ // eslint-disable-next-line import/extensions
5
6
  import eslintPluginPrettierRecommended from 'eslint-plugin-prettier/recommended'
6
- import globals from "globals";
7
+ import globals from 'globals'
7
8
 
8
9
  export default [
9
10
  js.configs.recommended,
10
11
  eslintPluginPrettierRecommended,
11
12
  {
12
13
  plugins: {
13
- promise
14
+ promise,
15
+ import: importplug
14
16
  },
15
17
  languageOptions: {
16
18
  globals: {
17
19
  ...globals.node
18
-
19
20
  },
20
21
  parser: babelParser,
21
22
  ecmaVersion: 2020,
@@ -24,28 +25,36 @@ export default [
24
25
  legacyDecorators: true,
25
26
  jsx: true
26
27
  },
27
- requireConfigFile: false,
28
+ requireConfigFile: false
28
29
  }
29
30
  },
30
31
  ignores: [
31
- "build/*",
32
- "dist/*",
33
- "node_modules/*",
34
- ".snapshots/*",
35
- "*.min.js"
32
+ 'build/*',
33
+ 'dist/*',
34
+ 'node_modules/*',
35
+ '.snapshots/*',
36
+ '*.min.js'
36
37
  ],
37
38
  rules: {
38
- "space-before-function-paren": 0,
39
- "import/export": 0,
40
- "promise/catch-or-return": "error",
41
- "no-useless-return": 1,
42
- "camelcase": 1,
43
- },
39
+ 'space-before-function-paren': 0,
40
+ 'import/export': 0,
41
+ 'promise/catch-or-return': 'error',
42
+ 'no-useless-return': 1,
43
+ camelcase: 1,
44
+ 'import/extensions': [
45
+ 'error',
46
+ 'always',
47
+ {
48
+ js: 'always',
49
+ jsx: 'always'
50
+ }
51
+ ]
52
+ }
44
53
  },
45
54
  {
46
- files: ["test/*.spec.js"],
55
+ files: ['test/*.spec.js'],
47
56
  rules: {
48
- "no-undef": 0
57
+ 'no-undef': 0
49
58
  }
50
- },
51
- ];
59
+ }
60
+ ]
package/lib/socket.js CHANGED
@@ -10,12 +10,24 @@ globalThis.FAILSsetTimeoutAlarm = (
10
10
  return setTimeout(alarm.fireJS.bind(alarm), delay)
11
11
  }
12
12
 
13
+ function convertToPem(/** @type {ArrayBuffer} */ cert) {
14
+ return (
15
+ '-----BEGIN CERTIFICATE-----\n' +
16
+ Buffer.from(new Uint8Array(cert)).toString('base64') +
17
+ '\n-----END CERTIFICATE-----\n'
18
+ )
19
+ }
20
+
13
21
  globalThis.FAILSVerifyProof = (
14
- /** @type {{ certs: string[]; hostname: string; server_config?: string; signature?: string; }} */ obj
22
+ /** @type {{ certs: ArrayBuffer[]; hostname: string; server_config?: string; signature?: string; }} */ obj
15
23
  ) => {
16
24
  try {
25
+ console.warn(
26
+ 'Non serverCertificateHashes certificate verification is an experimental feature for webtransport node client and not covered by tests and thus may be broken (DO NOT USE IN PRODUCTION)'
27
+ )
17
28
  if (obj.certs.length < 1) return false
18
- const leafcert = new X509Certificate(obj.certs[0])
29
+ const pem = convertToPem(obj.certs[0])
30
+ const leafcert = new X509Certificate(pem)
19
31
  if (!leafcert.checkHost(obj.hostname)) return false
20
32
 
21
33
  if (obj.server_config) {
@@ -36,7 +48,8 @@ globalThis.FAILSVerifyProof = (
36
48
 
37
49
  let curcert = leafcert
38
50
  for (let certnum = 1; certnum < obj.certs.length; certnum++) {
39
- const nextcert = new X509Certificate(obj.certs[certnum])
51
+ const nextpem = convertToPem(obj.certs[certnum])
52
+ const nextcert = new X509Certificate(nextpem)
40
53
 
41
54
  if (
42
55
  new Date(nextcert.validFrom) > curdate ||
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fails-components/webtransport-transport-http3-quiche",
3
- "version": "1.3.0",
3
+ "version": "1.4.0",
4
4
  "description": "A component to add webtransport support (server and client) to node.js, transport using libquiche",
5
5
  "exports": {
6
6
  ".": {
@@ -38,6 +38,7 @@
38
38
  #include "quiche/quic/core/quic_udp_socket.h"
39
39
  #include "quiche/quic/tools/quic_url.h"
40
40
  #include "quiche/common/quiche_text_utils.h"
41
+ #include "quiche/web_transport/web_transport_headers.h"
41
42
 
42
43
  using quiche::HttpHeaderBlock;
43
44
 
@@ -91,12 +92,14 @@ namespace quic
91
92
  retObj.Set("hostname", hostname);
92
93
  retObj.Set("port", port);
93
94
  retObj.Set("serverconfig", server_config);
94
- // todo certs
95
95
 
96
96
  Napi::Array jscerts = Napi::Array::New(env, certs.size());
97
97
  for (size_t i = 0; i < certs.size(); i++) {
98
- jscerts.Set(i, certs[i]);
98
+ jscerts.Set(i, Napi::Buffer<uint8_t>::Copy(env,
99
+ reinterpret_cast<const uint8_t*>(certs[i].data()),
100
+ certs[i].size()));
99
101
  }
102
+ retObj.Set("certs", jscerts);
100
103
  retObj.Set("signature", signature);
101
104
 
102
105
  Napi::Value verifyres = env.Global().Get("FAILSVerifyProof").As<Napi::Function>().Call({
@@ -125,13 +128,15 @@ namespace quic
125
128
 
126
129
  Napi::Array jscerts = Napi::Array::New(env, certs.size());
127
130
  for (size_t i = 0; i < certs.size(); i++) {
128
- jscerts.Set(i, certs[i]);
131
+ jscerts.Set(i, Napi::Buffer<uint8_t>::Copy(env,
132
+ reinterpret_cast<const uint8_t*>(certs[i].data()),
133
+ certs[i].size()));
129
134
  }
135
+ retObj.Set("certs", jscerts);
130
136
  Napi::Value verifyres = env.Global().Get("FAILSVerifyProof").As<Napi::Function>().Call({
131
137
  retObj });
132
138
  if (verifyres.As<Napi::Boolean>().Value()) {
133
139
  return QUIC_SUCCESS;
134
-
135
140
  } else {
136
141
  return QUIC_FAILURE;
137
142
  }
@@ -616,7 +621,7 @@ namespace quic
616
621
  return finish_stream_open_.size() > 0;
617
622
  }
618
623
 
619
- void Http3Client::openWTSessionInt(absl::string_view path)
624
+ bool Http3Client::openWTSessionInt(absl::string_view path)
620
625
  {
621
626
  quiche::HttpHeaderBlock headers;
622
627
  headers[":scheme"] = "https";
@@ -624,17 +629,15 @@ namespace quic
624
629
  headers[":path"] = path;
625
630
  headers[":method"] = "CONNECT";
626
631
  headers[":protocol"] = "webtransport";
627
- if (protocols_.size() > 0) { // not very efficient
628
- std::string protocols = "";
629
- for (size_t i=0; i < protocols_.size(); i++) {
630
- protocols += protocols_[i];
631
- if (i!= protocols_.size()-1) {
632
- protocols += ',';
633
- }
632
+ if (protocols_.size() > 0) {
633
+ absl::StatusOr<std::string> wtavail = webtransport::SerializeSubprotocolRequestHeader(protocols_);
634
+ if (!wtavail.ok()) {
635
+ return false;
634
636
  }
635
- headers["wt-available-protocols"] = protocols;
637
+ headers["wt-available-protocols"] = *wtavail;
636
638
  }
637
639
  SendMessageAsync(headers, "", /*fin=*/false);
640
+ return true;
638
641
  }
639
642
 
640
643
  void Http3Client::StartConnect()
@@ -1376,7 +1379,9 @@ namespace quic
1376
1379
  {
1377
1380
  std::string lpath(info[0].ToString().Utf8Value());
1378
1381
 
1379
- obj->openWTSessionInt(lpath);
1382
+ if (!obj->openWTSessionInt(lpath)) {
1383
+ Napi::Error::New(info.Env(), "openWTSessionInt failed, invalid protocols?").ThrowAsJavaScriptException();
1384
+ }
1380
1385
  }
1381
1386
  else
1382
1387
  {
package/src/http3client.h CHANGED
@@ -365,7 +365,7 @@ namespace quic
365
365
  // tracking its state.
366
366
  void SetLatestCreatedStream(QuicSpdyClientStream *stream);
367
367
 
368
- void openWTSessionInt(absl::string_view path);
368
+ bool openWTSessionInt(absl::string_view path);
369
369
 
370
370
  bool closeClientInt();
371
371
 
@@ -17,6 +17,7 @@
17
17
  #include "quiche/quic/tools/quic_simple_crypto_server_stream_helper.h"
18
18
  #include "quiche/quic/core/crypto/proof_source_x509.h"
19
19
  #include "quiche/common/platform/api/quiche_reference_counted.h"
20
+ #include "quiche/web_transport/web_transport_headers.h"
20
21
 
21
22
  using namespace Napi;
22
23
 
@@ -448,6 +449,17 @@ namespace quic
448
449
  for (auto pair : reqhead)
449
450
  {
450
451
  // we iterate over all header fields
452
+ if (pair.first.compare("wt-available-protocols") == 0) {
453
+ absl::StatusOr<std::vector<std::string>> prots = webtransport::ParseSubprotocolRequestHeader(pair.second);
454
+ if (prots.ok()) {
455
+ Napi::Array protArray = Napi::Array::New(Env(), (*prots).size());
456
+ for (size_t i = 0; i < (*prots).size(); i++) {
457
+ protArray.Set(i, std::string((*prots)[i]));
458
+ }
459
+ headObj.Set(std::string("wt-available-protocols"), protArray);
460
+ continue;
461
+ } // otherwise fall through to default
462
+ }
451
463
  headObj.Set(std::string(pair.first), std::string(pair.second));
452
464
  }
453
465
  retObj.Set("header", headObj);
@@ -586,7 +598,11 @@ namespace quic
586
598
  std::unique_ptr<Http3ServerBackend::WebTransportResponse> response = std::make_unique<Http3ServerBackend::WebTransportResponse>();
587
599
  response->response_headers[":status"] = std::to_string(status);
588
600
  if (selectedProtocol != "") {
589
- response->response_headers["wt-protocol"] = selectedProtocol;
601
+ absl::StatusOr<std::string> selprot = webtransport::SerializeSubprotocolResponseHeader(selectedProtocol);
602
+ if (!selprot.ok()) {
603
+ return Napi::Error::New(Env(), "Selected protocol is invalid").ThrowAsJavaScriptException();
604
+ }
605
+ response->response_headers["wt-protocol"] = *selprot;
590
606
  }
591
607
  Http3WTSession *wtsession = new Http3WTSession();
592
608
  wtsession->init(session);
@@ -25,7 +25,7 @@
25
25
  #include "quiche/quic/core/web_transport_interface.h"
26
26
  #include "quiche/quic/platform/api/quic_logging.h"
27
27
  #include "quiche/common/quiche_circular_deque.h"
28
- #include "quiche/common/platform/api/quiche_mem_slice.h"
28
+ #include "quiche/common/quiche_mem_slice.h"
29
29
 
30
30
  namespace quic
31
31
  {
@@ -1,2 +0,0 @@
1
- // use the default
2
- #include "quiche/common/platform/default/quiche_platform_impl/quiche_mem_slice_impl.h"