@encharm/cws 4.5.3 → 4.8.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/CHANGELOG.md +18 -0
- package/CLAUDE.md +83 -0
- package/README.md +20 -4
- package/binding.gyp +8 -2
- package/dist/bindings/cws_darwin_arm64_node115.node +0 -0
- package/dist/bindings/cws_darwin_arm64_node127.node +0 -0
- package/dist/bindings/cws_darwin_arm64_node137.node +0 -0
- package/dist/bindings/cws_darwin_arm64_node147.node +0 -0
- package/dist/bindings/cws_linux_arm64_node115.node +0 -0
- package/dist/bindings/cws_linux_arm64_node127.node +0 -0
- package/dist/bindings/cws_linux_arm64_node137.node +0 -0
- package/dist/bindings/cws_linux_arm64_node147.node +0 -0
- package/dist/bindings/cws_linux_x64_node115.node +0 -0
- package/dist/bindings/cws_linux_x64_node127.node +0 -0
- package/dist/bindings/cws_linux_x64_node137.node +0 -0
- package/dist/bindings/cws_linux_x64_node147.node +0 -0
- package/dist/bindings/cws_win32_x64_node115.node +0 -0
- package/dist/bindings/cws_win32_x64_node127.node +0 -0
- package/dist/bindings/cws_win32_x64_node137.node +0 -0
- package/dist/bindings/cws_win32_x64_node147.node +0 -0
- package/dist/client.d.ts +1 -0
- package/dist/client.js +15 -1
- package/dist/index.d.ts +6 -1
- package/dist/index.js +2 -0
- package/dist/server.d.ts +1 -0
- package/dist/server.js +16 -2
- package/dist/shared.d.ts +1 -0
- package/dist/shared.js +3 -2
- package/package.json +1 -1
- package/src/Addon.cpp +4 -1
- package/src/Addon.h +80 -15
- package/src/Extensions.cpp +7 -1
- package/src/Extensions.h +2 -1
- package/src/Group.cpp +1 -1
- package/src/Group.h +4 -1
- package/src/HTTPSocket.cpp +1 -1
- package/src/Hub.cpp +11 -76
- package/src/Hub.h +12 -10
- package/src/Networking.h +11 -0
- package/src/Socket.h +201 -6
- package/src/WebSocket.cpp +8 -5
- package/src/Zlib.cpp +138 -0
- package/src/Zlib.h +38 -0
- package/src/cSNode.cpp +2 -0
- package/src/cSNode.h +4 -0
- package/src/headers/26/acorn_version.h +6 -0
- package/src/headers/26/aliased_buffer-inl.h +264 -0
- package/src/headers/26/aliased_buffer.h +205 -0
- package/src/headers/26/aliased_struct-inl.h +143 -0
- package/src/headers/26/aliased_struct.h +248 -0
- package/src/headers/26/amaro_version.h +6 -0
- package/src/headers/26/async_context_frame.h +33 -0
- package/src/headers/26/async_wrap-inl.h +123 -0
- package/src/headers/26/async_wrap.h +254 -0
- package/src/headers/26/base_object-inl.h +333 -0
- package/src/headers/26/base_object.h +339 -0
- package/src/headers/26/base_object_types.h +76 -0
- package/src/headers/26/blob_serializer_deserializer-inl.h +385 -0
- package/src/headers/26/blob_serializer_deserializer.h +142 -0
- package/src/headers/26/builtin_info.h +57 -0
- package/src/headers/26/callback_queue-inl.h +97 -0
- package/src/headers/26/callback_queue.h +79 -0
- package/src/headers/26/cares_wrap.h +475 -0
- package/src/headers/26/cleanup_queue-inl.h +36 -0
- package/src/headers/26/cleanup_queue.h +79 -0
- package/src/headers/26/compile_cache.h +134 -0
- package/src/headers/26/connect_wrap.h +26 -0
- package/src/headers/26/connection_wrap.h +30 -0
- package/src/headers/26/cppgc_helpers-inl.h +69 -0
- package/src/headers/26/cppgc_helpers.h +162 -0
- package/src/headers/26/crypto/crypto_aes.h +107 -0
- package/src/headers/26/crypto/crypto_argon2.h +88 -0
- package/src/headers/26/crypto/crypto_bio.h +193 -0
- package/src/headers/26/crypto/crypto_chacha20_poly1305.h +62 -0
- package/src/headers/26/crypto/crypto_cipher.h +291 -0
- package/src/headers/26/crypto/crypto_common.h +48 -0
- package/src/headers/26/crypto/crypto_context.h +219 -0
- package/src/headers/26/crypto/crypto_dh.h +104 -0
- package/src/headers/26/crypto/crypto_dsa.h +50 -0
- package/src/headers/26/crypto/crypto_ec.h +102 -0
- package/src/headers/26/crypto/crypto_hash.h +157 -0
- package/src/headers/26/crypto/crypto_hkdf.h +62 -0
- package/src/headers/26/crypto/crypto_hmac.h +92 -0
- package/src/headers/26/crypto/crypto_kem.h +131 -0
- package/src/headers/26/crypto/crypto_keygen.h +382 -0
- package/src/headers/26/crypto/crypto_keys.h +366 -0
- package/src/headers/26/crypto/crypto_kmac.h +79 -0
- package/src/headers/26/crypto/crypto_pbkdf2.h +76 -0
- package/src/headers/26/crypto/crypto_pqc.h +39 -0
- package/src/headers/26/crypto/crypto_random.h +127 -0
- package/src/headers/26/crypto/crypto_rsa.h +108 -0
- package/src/headers/26/crypto/crypto_scrypt.h +85 -0
- package/src/headers/26/crypto/crypto_sig.h +159 -0
- package/src/headers/26/crypto/crypto_spkac.h +21 -0
- package/src/headers/26/crypto/crypto_timing.h +20 -0
- package/src/headers/26/crypto/crypto_tls.h +342 -0
- package/src/headers/26/crypto/crypto_turboshake.h +105 -0
- package/src/headers/26/crypto/crypto_util.h +775 -0
- package/src/headers/26/crypto/crypto_x509.h +140 -0
- package/src/headers/26/dataqueue/queue.h +311 -0
- package/src/headers/26/debug_utils-inl.h +291 -0
- package/src/headers/26/debug_utils.h +200 -0
- package/src/headers/26/diagnosticfilename-inl.h +33 -0
- package/src/headers/26/embedded_data.h +17 -0
- package/src/headers/26/encoding_binding.h +59 -0
- package/src/headers/26/env-inl.h +956 -0
- package/src/headers/26/env.h +1294 -0
- package/src/headers/26/env_properties.h +562 -0
- package/src/headers/26/ffi/data.h +30 -0
- package/src/headers/26/ffi/fast.h +96 -0
- package/src/headers/26/ffi/jit_memory.h +26 -0
- package/src/headers/26/ffi/types.h +99 -0
- package/src/headers/26/handle_wrap.h +123 -0
- package/src/headers/26/histogram-inl.h +211 -0
- package/src/headers/26/histogram.h +474 -0
- package/src/headers/26/inspector/dom_storage_agent.h +68 -0
- package/src/headers/26/inspector/inspector_object_utils.h +38 -0
- package/src/headers/26/inspector/io_agent.h +30 -0
- package/src/headers/26/inspector/main_thread_interface.h +116 -0
- package/src/headers/26/inspector/network_agent.h +110 -0
- package/src/headers/26/inspector/network_inspector.h +45 -0
- package/src/headers/26/inspector/network_requests_buffer.h +195 -0
- package/src/headers/26/inspector/network_resource_manager.h +29 -0
- package/src/headers/26/inspector/node_json.h +24 -0
- package/src/headers/26/inspector/node_string.h +101 -0
- package/src/headers/26/inspector/notification_emitter.h +38 -0
- package/src/headers/26/inspector/protocol_helper.h +27 -0
- package/src/headers/26/inspector/runtime_agent.h +41 -0
- package/src/headers/26/inspector/storage_agent.h +33 -0
- package/src/headers/26/inspector/target_agent.h +59 -0
- package/src/headers/26/inspector/target_manager.h +70 -0
- package/src/headers/26/inspector/tracing_agent.h +43 -0
- package/src/headers/26/inspector/worker_agent.h +40 -0
- package/src/headers/26/inspector/worker_inspector.h +124 -0
- package/src/headers/26/inspector_agent.h +168 -0
- package/src/headers/26/inspector_io.h +78 -0
- package/src/headers/26/inspector_profiler.h +149 -0
- package/src/headers/26/inspector_socket.h +60 -0
- package/src/headers/26/inspector_socket_server.h +110 -0
- package/src/headers/26/js_native_api.h +634 -0
- package/src/headers/26/js_native_api_types.h +244 -0
- package/src/headers/26/js_native_api_v8.h +485 -0
- package/src/headers/26/js_native_api_v8_internals.h +45 -0
- package/src/headers/26/js_stream.h +57 -0
- package/src/headers/26/json_utils.h +172 -0
- package/src/headers/26/large_pages/node_large_page.h +34 -0
- package/src/headers/26/lru_cache-inl.h +69 -0
- package/src/headers/26/memory_tracker-inl.h +461 -0
- package/src/headers/26/memory_tracker.h +341 -0
- package/src/headers/26/module_wrap.h +231 -0
- package/src/headers/26/ncrypto.h +2008 -0
- package/src/headers/26/node.h +1693 -0
- package/src/headers/26/node_api.h +265 -0
- package/src/headers/26/node_api_internals.h +48 -0
- package/src/headers/26/node_api_types.h +58 -0
- package/src/headers/26/node_binding.h +170 -0
- package/src/headers/26/node_blob.h +160 -0
- package/src/headers/26/node_bob-inl.h +36 -0
- package/src/headers/26/node_bob.h +107 -0
- package/src/headers/26/node_buffer.h +92 -0
- package/src/headers/26/node_builtins.h +239 -0
- package/src/headers/26/node_concepts.h +46 -0
- package/src/headers/26/node_config_file.h +77 -0
- package/src/headers/26/node_constants.h +82 -0
- package/src/headers/26/node_context_data.h +171 -0
- package/src/headers/26/node_contextify.h +261 -0
- package/src/headers/26/node_crypto.h +66 -0
- package/src/headers/26/node_debug.h +30 -0
- package/src/headers/26/node_diagnostics_channel.h +121 -0
- package/src/headers/26/node_dir.h +52 -0
- package/src/headers/26/node_dotenv.h +45 -0
- package/src/headers/26/node_errors.h +378 -0
- package/src/headers/26/node_exit_code.h +54 -0
- package/src/headers/26/node_external_reference.h +171 -0
- package/src/headers/26/node_ffi.h +212 -0
- package/src/headers/26/node_file-inl.h +421 -0
- package/src/headers/26/node_file.h +561 -0
- package/src/headers/26/node_file_utils.h +39 -0
- package/src/headers/26/node_hash.h +212 -0
- package/src/headers/26/node_http2.h +1202 -0
- package/src/headers/26/node_http2_state.h +159 -0
- package/src/headers/26/node_http_common-inl.h +199 -0
- package/src/headers/26/node_http_common.h +535 -0
- package/src/headers/26/node_i18n.h +132 -0
- package/src/headers/26/node_internals.h +485 -0
- package/src/headers/26/node_locks.h +184 -0
- package/src/headers/26/node_main_instance.h +67 -0
- package/src/headers/26/node_mem-inl.h +113 -0
- package/src/headers/26/node_mem.h +45 -0
- package/src/headers/26/node_messaging.h +389 -0
- package/src/headers/26/node_metadata.h +172 -0
- package/src/headers/26/node_modules.h +102 -0
- package/src/headers/26/node_mutex.h +323 -0
- package/src/headers/26/node_object_wrap.h +145 -0
- package/src/headers/26/node_options-inl.h +524 -0
- package/src/headers/26/node_options.h +710 -0
- package/src/headers/26/node_perf.h +167 -0
- package/src/headers/26/node_perf_common.h +103 -0
- package/src/headers/26/node_platform.h +290 -0
- package/src/headers/26/node_process-inl.h +26 -0
- package/src/headers/26/node_process.h +112 -0
- package/src/headers/26/node_profiling.h +38 -0
- package/src/headers/26/node_realm-inl.h +156 -0
- package/src/headers/26/node_realm.h +236 -0
- package/src/headers/26/node_report.h +43 -0
- package/src/headers/26/node_revert.h +82 -0
- package/src/headers/26/node_root_certs.h +2937 -0
- package/src/headers/26/node_sea.h +101 -0
- package/src/headers/26/node_shadow_realm.h +46 -0
- package/src/headers/26/node_snapshot_builder.h +57 -0
- package/src/headers/26/node_snapshotable.h +167 -0
- package/src/headers/26/node_sockaddr-inl.h +248 -0
- package/src/headers/26/node_sockaddr.h +459 -0
- package/src/headers/26/node_sqlite.h +607 -0
- package/src/headers/26/node_stat_watcher.h +73 -0
- package/src/headers/26/node_task_runner.h +92 -0
- package/src/headers/26/node_threadsafe_cow-inl.h +54 -0
- package/src/headers/26/node_threadsafe_cow.h +105 -0
- package/src/headers/26/node_union_bytes.h +81 -0
- package/src/headers/26/node_url.h +101 -0
- package/src/headers/26/node_url_pattern.h +118 -0
- package/src/headers/26/node_v8.h +78 -0
- package/src/headers/26/node_v8_embedder.h +26 -0
- package/src/headers/26/node_v8_platform-inl.h +96 -0
- package/src/headers/26/node_version.h +116 -0
- package/src/headers/26/node_wasi.h +184 -0
- package/src/headers/26/node_wasm_web_api.h +55 -0
- package/src/headers/26/node_watchdog.h +164 -0
- package/src/headers/26/node_webstorage.h +62 -0
- package/src/headers/26/node_worker.h +162 -0
- package/src/headers/26/path.h +36 -0
- package/src/headers/26/permission/boolean_permission.h +50 -0
- package/src/headers/26/permission/fs_permission.h +192 -0
- package/src/headers/26/permission/permission.h +155 -0
- package/src/headers/26/permission/permission_base.h +79 -0
- package/src/headers/26/pipe_wrap.h +80 -0
- package/src/headers/26/quic/application.h +279 -0
- package/src/headers/26/quic/arena.h +373 -0
- package/src/headers/26/quic/bindingdata.h +440 -0
- package/src/headers/26/quic/cid.h +127 -0
- package/src/headers/26/quic/data.h +358 -0
- package/src/headers/26/quic/defs.h +417 -0
- package/src/headers/26/quic/endpoint.h +519 -0
- package/src/headers/26/quic/guard.h +5 -0
- package/src/headers/26/quic/http3.h +25 -0
- package/src/headers/26/quic/packet.h +166 -0
- package/src/headers/26/quic/preferredaddress.h +72 -0
- package/src/headers/26/quic/session.h +770 -0
- package/src/headers/26/quic/session_manager.h +107 -0
- package/src/headers/26/quic/sessionticket.h +110 -0
- package/src/headers/26/quic/streams.h +518 -0
- package/src/headers/26/quic/tlscontext.h +353 -0
- package/src/headers/26/quic/tokens.h +263 -0
- package/src/headers/26/quic/transportparams.h +184 -0
- package/src/headers/26/req_wrap-inl.h +175 -0
- package/src/headers/26/req_wrap.h +79 -0
- package/src/headers/26/spawn_sync.h +243 -0
- package/src/headers/26/stream_base-inl.h +170 -0
- package/src/headers/26/stream_base.h +487 -0
- package/src/headers/26/stream_pipe.h +76 -0
- package/src/headers/26/stream_wrap.h +137 -0
- package/src/headers/26/string_bytes.h +114 -0
- package/src/headers/26/string_decoder-inl.h +31 -0
- package/src/headers/26/string_decoder.h +49 -0
- package/src/headers/26/tcp_wrap.h +138 -0
- package/src/headers/26/threadpoolwork-inl.h +70 -0
- package/src/headers/26/timer_wrap-inl.h +32 -0
- package/src/headers/26/timer_wrap.h +87 -0
- package/src/headers/26/timers.h +70 -0
- package/src/headers/26/tracing/agent.h +125 -0
- package/src/headers/26/tracing/agent_legacy.h +146 -0
- package/src/headers/26/tracing/agent_perfetto.h +145 -0
- package/src/headers/26/tracing/node_trace_buffer.h +91 -0
- package/src/headers/26/tracing/node_trace_writer.h +79 -0
- package/src/headers/26/tracing/trace_event.h +27 -0
- package/src/headers/26/tracing/trace_event_helper.h +40 -0
- package/src/headers/26/tracing/trace_event_legacy.h +1113 -0
- package/src/headers/26/tracing/trace_event_legacy_inl.h +711 -0
- package/src/headers/26/tracing/trace_event_perfetto.h +47 -0
- package/src/headers/26/tracing/traced_value.h +167 -0
- package/src/headers/26/tty_wrap.h +65 -0
- package/src/headers/26/udp_wrap.h +231 -0
- package/src/headers/26/undici_version.h +6 -0
- package/src/headers/26/util-inl.h +788 -0
- package/src/headers/26/util.h +1207 -0
- package/src/headers/26/v8-cpp-heap-external.h +56 -0
- package/src/headers/26/v8-external-memory-accounter.h +60 -0
- package/src/headers/26/v8-fast-api-calls.h +784 -0
- package/src/headers/26/v8-inspector-protocol.h +13 -0
- package/src/headers/26/v8-inspector.h +458 -0
- package/src/headers/26/v8-metrics.h +273 -0
- package/src/headers/26/v8-trace-categories.h +28 -0
- package/src/headers/26/v8-unwinder-state.h +30 -0
- package/src/headers/26/v8-util.h +549 -0
- package/src/headers/26/v8-value-serializer-version.h +24 -0
- package/src/headers/26/v8-version-string.h +38 -0
- package/src/headers/26/v8-wasm-trap-handler-posix.h +31 -0
- package/src/headers/26/v8-wasm-trap-handler-win.h +28 -0
- package/src/headers/26/zlib_version.h +6 -0
- package/dist/bindings/cws_darwin_arm64_node115.node.dSYM/Contents/Info.plist +0 -20
- package/dist/bindings/cws_darwin_arm64_node115.node.dSYM/Contents/Resources/DWARF/cws_darwin_arm64_node115.node +0 -0
- package/dist/bindings/cws_darwin_arm64_node115.node.dSYM/Contents/Resources/Relocations/aarch64/cws_darwin_arm64_node115.node.yml +0 -931
- package/dist/bindings/cws_darwin_arm64_node127.node.dSYM/Contents/Info.plist +0 -20
- package/dist/bindings/cws_darwin_arm64_node127.node.dSYM/Contents/Resources/DWARF/cws_darwin_arm64_node127.node +0 -0
- package/dist/bindings/cws_darwin_arm64_node127.node.dSYM/Contents/Resources/Relocations/aarch64/cws_darwin_arm64_node127.node.yml +0 -931
|
@@ -0,0 +1,518 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
|
|
4
|
+
|
|
5
|
+
#include <aliased_struct.h>
|
|
6
|
+
#include <async_wrap.h>
|
|
7
|
+
#include <base_object.h>
|
|
8
|
+
#include <dataqueue/queue.h>
|
|
9
|
+
#include <env.h>
|
|
10
|
+
#include <memory_tracker.h>
|
|
11
|
+
#include <node_blob.h>
|
|
12
|
+
#include <node_bob.h>
|
|
13
|
+
#include <node_http_common.h>
|
|
14
|
+
#include <util.h>
|
|
15
|
+
#include "bindingdata.h"
|
|
16
|
+
#include "data.h"
|
|
17
|
+
|
|
18
|
+
#include <vector>
|
|
19
|
+
|
|
20
|
+
namespace node::quic {
|
|
21
|
+
|
|
22
|
+
class Session;
|
|
23
|
+
class Stream;
|
|
24
|
+
|
|
25
|
+
// An elastic ring buffer used by Stream to coalesce received data before
|
|
26
|
+
// flushing it into the DataQueue. This avoids creating many small V8
|
|
27
|
+
// BackingStore allocations from per-QUIC-frame ngtcp2 callbacks. Data is
|
|
28
|
+
// memcpy'd into the ring buffer and flushed as a single right-sized
|
|
29
|
+
// BackingStore when the reader pulls or the buffer reaches its flush
|
|
30
|
+
// threshold. The buffer starts at kMinCapacity and can grow up to a
|
|
31
|
+
// configured maximum (typically the stream flow control window).
|
|
32
|
+
class RecvAccumulator final {
|
|
33
|
+
public:
|
|
34
|
+
static constexpr size_t kMinCapacity = 64 * 1024; // 64 KB
|
|
35
|
+
static constexpr size_t kFlushThreshold = kMinCapacity; // flush at 64 KB
|
|
36
|
+
|
|
37
|
+
explicit RecvAccumulator(size_t max_capacity);
|
|
38
|
+
~RecvAccumulator() = default;
|
|
39
|
+
|
|
40
|
+
DISALLOW_COPY_AND_MOVE(RecvAccumulator)
|
|
41
|
+
|
|
42
|
+
// Append data. Returns the number of bytes written (may be less than
|
|
43
|
+
// len if the buffer is full). The caller should flush and retry with
|
|
44
|
+
// the remaining bytes.
|
|
45
|
+
size_t Write(const uint8_t* data, size_t len);
|
|
46
|
+
|
|
47
|
+
// Flush accumulated data as a single DataQueue entry backed by a
|
|
48
|
+
// right-sized V8 BackingStore. Returns nullptr if nothing is
|
|
49
|
+
// accumulated. Resets the read/write cursors and shrinks the buffer
|
|
50
|
+
// back toward kMinCapacity if it was expanded.
|
|
51
|
+
std::unique_ptr<DataQueue::Entry> Flush(Environment* env);
|
|
52
|
+
|
|
53
|
+
// Current number of bytes awaiting flush.
|
|
54
|
+
size_t available() const { return len_; }
|
|
55
|
+
|
|
56
|
+
// Number of bytes that can still be written before the buffer is full.
|
|
57
|
+
size_t remaining() const { return buf_.size() - len_; }
|
|
58
|
+
|
|
59
|
+
// True if accumulated data has reached the flush threshold.
|
|
60
|
+
bool should_flush() const { return len_ >= kFlushThreshold; }
|
|
61
|
+
|
|
62
|
+
// Grow the buffer capacity (doubles, up to max_capacity_).
|
|
63
|
+
void Grow();
|
|
64
|
+
|
|
65
|
+
private:
|
|
66
|
+
std::vector<uint8_t> buf_;
|
|
67
|
+
size_t max_capacity_;
|
|
68
|
+
size_t read_pos_ = 0;
|
|
69
|
+
size_t write_pos_ = 0;
|
|
70
|
+
size_t len_ = 0; // write_pos_ - read_pos_, accounting for wrap
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
using Ngtcp2Source = bob::SourceImpl<ngtcp2_vec>;
|
|
74
|
+
|
|
75
|
+
// When a request to open a stream is made before a Session is able to actually
|
|
76
|
+
// open a stream (either because the handshake is not yet sufficiently complete
|
|
77
|
+
// or concurrency limits are temporarily reached) then the request to open the
|
|
78
|
+
// stream is represented as a queued PendingStream.
|
|
79
|
+
//
|
|
80
|
+
// The PendingStream instance itself is owned by the stream created but a
|
|
81
|
+
// reference sits in a linked list in the session.
|
|
82
|
+
//
|
|
83
|
+
// The PendingStream request can be canceled by dropping the PendingStream
|
|
84
|
+
// instance before it can be fulfilled, at which point it is removed from the
|
|
85
|
+
// pending stream queue.
|
|
86
|
+
//
|
|
87
|
+
// Note that only locally initiated streams can be created in a pending state.
|
|
88
|
+
class PendingStream final {
|
|
89
|
+
public:
|
|
90
|
+
explicit PendingStream(Direction direction,
|
|
91
|
+
Stream* stream,
|
|
92
|
+
BaseObjectWeakPtr<Session> session);
|
|
93
|
+
DISALLOW_COPY_AND_MOVE(PendingStream)
|
|
94
|
+
~PendingStream();
|
|
95
|
+
|
|
96
|
+
// Called when the stream has been opened. Transitions the stream from a
|
|
97
|
+
// pending state to an opened state.
|
|
98
|
+
void fulfill(stream_id id);
|
|
99
|
+
|
|
100
|
+
// Called when opening the stream fails or is canceled. Transitions the
|
|
101
|
+
// stream into a closed/destroyed state.
|
|
102
|
+
void reject(QuicError error = QuicError());
|
|
103
|
+
|
|
104
|
+
inline Direction direction() const { return direction_; }
|
|
105
|
+
|
|
106
|
+
private:
|
|
107
|
+
Direction direction_;
|
|
108
|
+
Stream* stream_;
|
|
109
|
+
BaseObjectWeakPtr<Session> session_;
|
|
110
|
+
bool waiting_ = true;
|
|
111
|
+
|
|
112
|
+
ListNode<PendingStream> pending_stream_queue_;
|
|
113
|
+
|
|
114
|
+
public:
|
|
115
|
+
using PendingStreamQueue =
|
|
116
|
+
ListHead<PendingStream, &PendingStream::pending_stream_queue_>;
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
// QUIC Stream's are simple data flows that may be:
|
|
120
|
+
//
|
|
121
|
+
// * Bidirectional (both sides can send) or Unidirectional (one side can send)
|
|
122
|
+
// * Server or Client Initiated
|
|
123
|
+
//
|
|
124
|
+
// The flow direction and origin of the stream are important in determining the
|
|
125
|
+
// write and read state (Open or Closed). Specifically:
|
|
126
|
+
//
|
|
127
|
+
// Bidirectional Stream States:
|
|
128
|
+
// +--------+--------------+----------+----------+
|
|
129
|
+
// | ON | Initiated By | Readable | Writable |
|
|
130
|
+
// +--------+--------------+----------+----------+
|
|
131
|
+
// | Server | Server | Y | Y |
|
|
132
|
+
// +--------+--------------+----------+----------+
|
|
133
|
+
// | Server | Client | Y | Y |
|
|
134
|
+
// +--------+--------------+----------+----------+
|
|
135
|
+
// | Client | Server | Y | Y |
|
|
136
|
+
// +--------+--------------+----------+----------+
|
|
137
|
+
// | Client | Client | Y | Y |
|
|
138
|
+
// +--------+--------------+----------+----------+
|
|
139
|
+
//
|
|
140
|
+
// Unidirectional Stream States
|
|
141
|
+
// +--------+--------------+----------+----------+
|
|
142
|
+
// | ON | Initiated By | Readable | Writable |
|
|
143
|
+
// +--------+--------------+----------+----------+
|
|
144
|
+
// | Server | Server | N | Y |
|
|
145
|
+
// +--------+--------------+----------+----------+
|
|
146
|
+
// | Server | Client | Y | N |
|
|
147
|
+
// +--------+--------------+----------+----------+
|
|
148
|
+
// | Client | Server | Y | N |
|
|
149
|
+
// +--------+--------------+----------+----------+
|
|
150
|
+
// | Client | Client | N | Y |
|
|
151
|
+
// +--------+--------------+----------+----------+
|
|
152
|
+
//
|
|
153
|
+
// All data sent via the Stream is buffered internally until either receipt is
|
|
154
|
+
// acknowledged from the peer or attempts to send are abandoned. The fact that
|
|
155
|
+
// data is buffered in memory makes it essential that the flow control for the
|
|
156
|
+
// session and the stream are properly handled. For now, we are largely relying
|
|
157
|
+
// on ngtcp2's default flow control mechanisms which generally should be doing
|
|
158
|
+
// the right thing. From the JavaScript side, the application pushes data into
|
|
159
|
+
// the stream's outbound queue and ngtcp2 pulls data from that queue as it is
|
|
160
|
+
// able. The stream outbound has a high watermark. The JS side can choose to
|
|
161
|
+
// continue writing data even after the high watermark is reached but this
|
|
162
|
+
// risks using up large amounts of memory if the session is slow to send data
|
|
163
|
+
// or the peer is slow to acknowledge receipt. The JavaScript side needs to
|
|
164
|
+
// be aware of this risk and pay proper attention to the backpressure signals.
|
|
165
|
+
//
|
|
166
|
+
// A Stream may be in a fully closed state (No longer readable nor writable)
|
|
167
|
+
// state but still have unacknowledged data in both the inbound and outbound
|
|
168
|
+
// queues.
|
|
169
|
+
//
|
|
170
|
+
// A Stream is gracefully closed when (a) both read and write states are closed,
|
|
171
|
+
// (b) all queued data has been acknowledged.
|
|
172
|
+
//
|
|
173
|
+
// The Stream may be forcefully closed immediately using destroy(err). This
|
|
174
|
+
// causes all queued outbound data to be cleared, pending JavaScript writes
|
|
175
|
+
// to be abandoned, the Stream to be immediately closed at the ngtcp2 level
|
|
176
|
+
// without waiting for any outstanding acknowledgements. Keep in mind, however,
|
|
177
|
+
// that the peer is not notified that the stream is destroyed and may attempt
|
|
178
|
+
// to continue sending data and acknowledgements until it is able to determine
|
|
179
|
+
// that the stream is gone. Any data that has already been received and is in
|
|
180
|
+
// the inbound queue is preserved and may be read by the application.
|
|
181
|
+
//
|
|
182
|
+
// QUIC streams in general do not have headers. Some QUIC applications, however,
|
|
183
|
+
// may associate headers with the stream (HTTP/3 for instance). As a
|
|
184
|
+
// convenience, the Stream class will hold onto these headers for the
|
|
185
|
+
// application.
|
|
186
|
+
//
|
|
187
|
+
// Streams may be created in a pending state. This means that while the Stream
|
|
188
|
+
// object is created, it has not yet been opened in ngtcp2 and therefore has
|
|
189
|
+
// no official status yet. Certain operations can still be performed on the
|
|
190
|
+
// stream object such as providing data, adding headers, or destroying the
|
|
191
|
+
// stream.
|
|
192
|
+
//
|
|
193
|
+
// When a stream is created the data source for the stream must be given.
|
|
194
|
+
// If no data source is given, then the stream is assumed to not have any
|
|
195
|
+
// outbound data. If the stream was created as bidirectional, the outbound
|
|
196
|
+
// side will be closed. The data source can be fixed length or may support
|
|
197
|
+
// streaming. What this means practically is, when a stream is opened,
|
|
198
|
+
// you must already have a sense of whether that will provide data or
|
|
199
|
+
// not. When in doubt, specify a streaming data source, which can produce
|
|
200
|
+
// zero-length output.
|
|
201
|
+
class Stream final : public AsyncWrap,
|
|
202
|
+
public Ngtcp2Source,
|
|
203
|
+
public DataQueue::BackpressureListener {
|
|
204
|
+
public:
|
|
205
|
+
using Header = NgHeaderBase<BindingData>;
|
|
206
|
+
|
|
207
|
+
// Acquire a DataQueue from the given value if it is valid. The return
|
|
208
|
+
// follows the typical V8 rules for Maybe types. If an error occurs,
|
|
209
|
+
// the Maybe will be empty and an exception will be set on the isolate.
|
|
210
|
+
static v8::Maybe<std::shared_ptr<DataQueue>> GetDataQueueFromSource(
|
|
211
|
+
Environment* env, v8::Local<v8::Value> value);
|
|
212
|
+
|
|
213
|
+
// The stream_user_data field is from ngtcp2 and will point to the
|
|
214
|
+
// Stream instance associated with the stream_id.
|
|
215
|
+
static Stream* From(void* stream_user_data);
|
|
216
|
+
|
|
217
|
+
JS_CONSTRUCTOR(Stream);
|
|
218
|
+
JS_BINDING_INIT_BOILERPLATE();
|
|
219
|
+
|
|
220
|
+
// Creates a new non-pending stream. The directionality of the stream
|
|
221
|
+
// is inferred from the stream id.
|
|
222
|
+
static BaseObjectPtr<Stream> Create(
|
|
223
|
+
Session* session,
|
|
224
|
+
stream_id id,
|
|
225
|
+
std::shared_ptr<DataQueue> source = nullptr);
|
|
226
|
+
|
|
227
|
+
// Creates a new pending stream.
|
|
228
|
+
static BaseObjectPtr<Stream> Create(
|
|
229
|
+
Session* session,
|
|
230
|
+
Direction direction,
|
|
231
|
+
std::shared_ptr<DataQueue> source = nullptr);
|
|
232
|
+
|
|
233
|
+
// The constructor is only public to be visible by MakeDetachedBaseObject.
|
|
234
|
+
// Call Create to create new instances of Stream.
|
|
235
|
+
Stream(BaseObjectWeakPtr<Session> session,
|
|
236
|
+
v8::Local<v8::Object> obj,
|
|
237
|
+
stream_id id,
|
|
238
|
+
std::shared_ptr<DataQueue> source);
|
|
239
|
+
|
|
240
|
+
// Creates the stream in a pending state. The constructor is only public
|
|
241
|
+
// to be visible to MakeDetachedBaseObject. Call Create to create new
|
|
242
|
+
// instances of Stream.
|
|
243
|
+
Stream(BaseObjectWeakPtr<Session> session,
|
|
244
|
+
v8::Local<v8::Object> obj,
|
|
245
|
+
Direction direction,
|
|
246
|
+
std::shared_ptr<DataQueue> source);
|
|
247
|
+
DISALLOW_COPY_AND_MOVE(Stream)
|
|
248
|
+
~Stream() override;
|
|
249
|
+
|
|
250
|
+
// While the stream is still pending, the id will be kMaxStreamId,
|
|
251
|
+
// inidicating the maximum possible stream id is kMaxStreamId - 1.
|
|
252
|
+
stream_id id() const;
|
|
253
|
+
|
|
254
|
+
// While the stream is still pending, the origin will be invalid.
|
|
255
|
+
Side origin() const;
|
|
256
|
+
|
|
257
|
+
Direction direction() const;
|
|
258
|
+
|
|
259
|
+
Session& session() const;
|
|
260
|
+
|
|
261
|
+
// Returns the most recent activity timestamp for this stream in
|
|
262
|
+
// nanoseconds (uv_hrtime). Uses received_at if data has been received,
|
|
263
|
+
// otherwise falls back to created_at. Returns 0 if neither is set.
|
|
264
|
+
uint64_t last_activity_timestamp() const;
|
|
265
|
+
|
|
266
|
+
// True if this stream was created in a pending state and is still waiting
|
|
267
|
+
// to be created.
|
|
268
|
+
bool is_pending() const;
|
|
269
|
+
|
|
270
|
+
// True if the stream is already destroyed.
|
|
271
|
+
bool is_destroyed() const;
|
|
272
|
+
|
|
273
|
+
// True if we've completely sent all outbound data for this stream.
|
|
274
|
+
// Importantly, this does not necessarily mean that we are completely
|
|
275
|
+
// done with the outbound data. We may still be waiting on outbound
|
|
276
|
+
// data to be acknowledged by the remote peer.
|
|
277
|
+
bool is_eos() const;
|
|
278
|
+
|
|
279
|
+
// True if the stream wants to send trailing headers after the body.
|
|
280
|
+
bool wants_trailers() const;
|
|
281
|
+
|
|
282
|
+
// Marks this stream as having received 0-RTT early data.
|
|
283
|
+
void set_early();
|
|
284
|
+
|
|
285
|
+
// True if this stream is still in a readable state.
|
|
286
|
+
bool is_readable() const;
|
|
287
|
+
|
|
288
|
+
// True if this stream is still in a writable state.
|
|
289
|
+
bool is_writable() const;
|
|
290
|
+
|
|
291
|
+
// True if an outbound data source has been configured.
|
|
292
|
+
bool has_outbound() const;
|
|
293
|
+
|
|
294
|
+
// True if a Blob::Reader has been created for the inbound data.
|
|
295
|
+
bool has_reader() const;
|
|
296
|
+
|
|
297
|
+
// Returns the Blob::Reader for the inbound data, or nullptr.
|
|
298
|
+
Blob::Reader* reader() const;
|
|
299
|
+
|
|
300
|
+
// Called by the session/application to indicate that the specified number
|
|
301
|
+
// of bytes have been acknowledged by the peer.
|
|
302
|
+
void Acknowledge(size_t datalen);
|
|
303
|
+
|
|
304
|
+
// Called by the session/application to indicate that the specified number
|
|
305
|
+
// of bytes have been transmitted to the peer. This is an initial
|
|
306
|
+
// indication occuring the first time data is sent. It does not indicate
|
|
307
|
+
// that the data has been retransmitted due to loss or has been
|
|
308
|
+
// acknowledged to have been received by the peer.
|
|
309
|
+
void Commit(size_t datalen, bool fin = false);
|
|
310
|
+
|
|
311
|
+
void EndWritable();
|
|
312
|
+
void EndReadable(std::optional<uint64_t> maybe_final_size = std::nullopt);
|
|
313
|
+
void EntryRead(size_t amount) override;
|
|
314
|
+
void BeforePull() override;
|
|
315
|
+
|
|
316
|
+
// Pulls data from the internal outbound DataQueue configured for this stream.
|
|
317
|
+
// This is called by the session/application when it is preparing to send
|
|
318
|
+
// data to the peer. There is no guarantee that the requested amount of data
|
|
319
|
+
// will actually be sent. The amount of data actually sent is indicated
|
|
320
|
+
// by the datalen argument to the Commit() method.
|
|
321
|
+
int DoPull(bob::Next<ngtcp2_vec> next,
|
|
322
|
+
int options,
|
|
323
|
+
ngtcp2_vec* data,
|
|
324
|
+
size_t count,
|
|
325
|
+
size_t max_count_hint) override;
|
|
326
|
+
|
|
327
|
+
// Forcefully close the stream immediately. Data already queued in the
|
|
328
|
+
// inbound is preserved but new data will not be accepted. All pending
|
|
329
|
+
// writes are abandoned, and the stream is immediately closed at the ngtcp2
|
|
330
|
+
// level without waiting for any outstanding acknowledgements.
|
|
331
|
+
void Destroy(QuicError error = QuicError());
|
|
332
|
+
|
|
333
|
+
struct ReceiveDataFlags final {
|
|
334
|
+
// Identifies the final chunk of data that the peer will send for the
|
|
335
|
+
// stream.
|
|
336
|
+
bool fin = false;
|
|
337
|
+
// Indicates that this chunk of data was received in a 0RTT packet before
|
|
338
|
+
// the TLS handshake completed, suggesting that is is not as secure and
|
|
339
|
+
// could be replayed by an attacker.
|
|
340
|
+
bool early = false;
|
|
341
|
+
};
|
|
342
|
+
|
|
343
|
+
void ReceiveData(const uint8_t* data, size_t len, ReceiveDataFlags flags);
|
|
344
|
+
void ReceiveStopSending(QuicError error);
|
|
345
|
+
void ReceiveStreamReset(uint64_t final_size, QuicError error);
|
|
346
|
+
|
|
347
|
+
// Sends a reset stream to the peer to tell it we will not be sending any
|
|
348
|
+
// more data for this stream. This has the effect of shutting down the
|
|
349
|
+
// writable side of the stream for this peer. Any data that is held in the
|
|
350
|
+
// outbound queue will be dropped. The stream may still be readable.
|
|
351
|
+
void DoStreamReset(error_code code);
|
|
352
|
+
|
|
353
|
+
// Tells the peer to stop sending data for this stream. This has the effect
|
|
354
|
+
// of shutting down the readable side of the stream for this peer. Any data
|
|
355
|
+
// that has already been received is still readable.
|
|
356
|
+
void SendStopSending(error_code code);
|
|
357
|
+
|
|
358
|
+
// Currently, only HTTP/3 streams support headers. These methods are here
|
|
359
|
+
// to support that. They are not used when using any other QUIC application.
|
|
360
|
+
|
|
361
|
+
void BeginHeaders(HeadersKind kind);
|
|
362
|
+
void set_headers_kind(HeadersKind kind);
|
|
363
|
+
// Returns false if the header cannot be added. This will typically happen
|
|
364
|
+
// if the application does not support headers, a maximum number of headers
|
|
365
|
+
// have already been added, or the maximum total header length is reached.
|
|
366
|
+
bool AddHeader(std::unique_ptr<Header> header);
|
|
367
|
+
|
|
368
|
+
// TODO(@jasnell): Implement MemoryInfo to track outbound_, inbound_,
|
|
369
|
+
// reader_, headers_, and pending_headers_queue_.
|
|
370
|
+
SET_NO_MEMORY_INFO()
|
|
371
|
+
SET_MEMORY_INFO_NAME(Stream)
|
|
372
|
+
SET_SELF_SIZE(Stream)
|
|
373
|
+
|
|
374
|
+
struct State;
|
|
375
|
+
struct Stats;
|
|
376
|
+
|
|
377
|
+
// Typed accessors for arena-allocated state/stats. These are defined
|
|
378
|
+
// in streams.cc where State and Stats are complete types.
|
|
379
|
+
inline State* state() { return static_cast<State*>(state_slot_.ptr); }
|
|
380
|
+
inline const State* state() const {
|
|
381
|
+
return static_cast<const State*>(state_slot_.ptr);
|
|
382
|
+
}
|
|
383
|
+
inline Stats* stats() { return static_cast<Stats*>(stats_slot_.ptr); }
|
|
384
|
+
inline const Stats* stats() const {
|
|
385
|
+
return static_cast<const Stats*>(stats_slot_.ptr);
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
private:
|
|
389
|
+
struct Impl;
|
|
390
|
+
struct PendingHeaders;
|
|
391
|
+
|
|
392
|
+
class Outbound;
|
|
393
|
+
|
|
394
|
+
// Flushes any data accumulated in the receive ring buffer into the
|
|
395
|
+
// inbound DataQueue as a single right-sized entry.
|
|
396
|
+
void FlushAccumulation();
|
|
397
|
+
|
|
398
|
+
// Gets a reader for the data received for this stream from the peer,
|
|
399
|
+
BaseObjectPtr<Blob::Reader> get_reader();
|
|
400
|
+
|
|
401
|
+
void set_final_size(uint64_t amount);
|
|
402
|
+
void set_outbound(std::shared_ptr<DataQueue> source);
|
|
403
|
+
|
|
404
|
+
// Streaming outbound support
|
|
405
|
+
void InitStreaming();
|
|
406
|
+
void WriteStreamData(const v8::FunctionCallbackInfo<v8::Value>& args);
|
|
407
|
+
void EndWriting();
|
|
408
|
+
|
|
409
|
+
bool is_local_unidirectional() const;
|
|
410
|
+
bool is_remote_unidirectional() const;
|
|
411
|
+
|
|
412
|
+
// JavaScript callouts
|
|
413
|
+
|
|
414
|
+
// Notifies the JavaScript side that the stream has been destroyed.
|
|
415
|
+
void EmitClose(const QuicError& error);
|
|
416
|
+
|
|
417
|
+
// Notifies the JavaScript side that the stream has been reset.
|
|
418
|
+
void EmitReset(const QuicError& error);
|
|
419
|
+
|
|
420
|
+
// Notifies the JavaScript side that the peer asked it to stop sending.
|
|
421
|
+
void EmitStopSending(const QuicError& error);
|
|
422
|
+
|
|
423
|
+
// Notifies the JavaScript side that the application is ready to receive
|
|
424
|
+
// trailing headers. Any trailing headers must be sent immediately, and
|
|
425
|
+
// synchronously when this callback is triggered.
|
|
426
|
+
void EmitWantTrailers();
|
|
427
|
+
|
|
428
|
+
// Notifies the JavaScript side that sending data on the stream has been
|
|
429
|
+
// blocked because of flow control restriction.
|
|
430
|
+
void EmitBlocked();
|
|
431
|
+
|
|
432
|
+
// Notifies the JavaScript side that the outbound buffer has capacity
|
|
433
|
+
// for more data. Fires when write_desired_size transitions from 0 to > 0.
|
|
434
|
+
void EmitDrain();
|
|
435
|
+
|
|
436
|
+
// Updates the write_desired_size state field based on current flow control
|
|
437
|
+
// and outbound buffer state. Emits drain if transitioning from 0 to > 0.
|
|
438
|
+
void UpdateWriteDesiredSize();
|
|
439
|
+
|
|
440
|
+
// Delivers the set of inbound headers that have been collected.
|
|
441
|
+
void EmitHeaders();
|
|
442
|
+
|
|
443
|
+
void NotifyReadableEnded(error_code code);
|
|
444
|
+
void NotifyWritableEnded(error_code code);
|
|
445
|
+
|
|
446
|
+
// When a pending stream is finally opened, the NotifyStreamOpened method
|
|
447
|
+
// will be called and the id will be assigned.
|
|
448
|
+
void NotifyStreamOpened(stream_id id);
|
|
449
|
+
void EnqueuePendingHeaders(HeadersKind kind,
|
|
450
|
+
v8::Local<v8::Array> headers,
|
|
451
|
+
HeadersFlags flags);
|
|
452
|
+
|
|
453
|
+
ArenaSlotBase stats_slot_;
|
|
454
|
+
ArenaSlotBase state_slot_;
|
|
455
|
+
BaseObjectWeakPtr<Session> session_;
|
|
456
|
+
std::unique_ptr<Outbound> outbound_;
|
|
457
|
+
std::shared_ptr<DataQueue> inbound_;
|
|
458
|
+
BaseObjectWeakPtr<Blob::Reader> reader_;
|
|
459
|
+
std::unique_ptr<RecvAccumulator> recv_accumulator_;
|
|
460
|
+
|
|
461
|
+
// If the stream cannot be opened yet, it will be created in a pending state.
|
|
462
|
+
// Once the owning session is able to, it will complete opening of the stream
|
|
463
|
+
// and the stream id will be assigned.
|
|
464
|
+
std::optional<std::unique_ptr<PendingStream>> maybe_pending_stream_ =
|
|
465
|
+
std::nullopt;
|
|
466
|
+
std::vector<std::unique_ptr<PendingHeaders>> pending_headers_queue_;
|
|
467
|
+
error_code pending_close_read_code_ = 0;
|
|
468
|
+
error_code pending_close_write_code_ = 0;
|
|
469
|
+
|
|
470
|
+
struct StoredPriority {
|
|
471
|
+
StreamPriority priority = StreamPriority::DEFAULT;
|
|
472
|
+
StreamPriorityFlags flags = StreamPriorityFlags::NON_INCREMENTAL;
|
|
473
|
+
bool pending = false;
|
|
474
|
+
};
|
|
475
|
+
StoredPriority priority_;
|
|
476
|
+
|
|
477
|
+
const StoredPriority& stored_priority() const { return priority_; }
|
|
478
|
+
|
|
479
|
+
// The headers_ field holds a block of headers that have been received and
|
|
480
|
+
// are being buffered for delivery to the JavaScript side. Headers are
|
|
481
|
+
// stored as C++ objects during collection (AddHeader) and converted to
|
|
482
|
+
// V8 strings only when emitted (EmitHeaders), avoiding StrongRootAllocator
|
|
483
|
+
// mutex contention on the per-header hot path.
|
|
484
|
+
std::vector<std::unique_ptr<Header>> headers_;
|
|
485
|
+
|
|
486
|
+
// The headers_kind_ field indicates the kind of headers that are being
|
|
487
|
+
// buffered.
|
|
488
|
+
HeadersKind headers_kind_ = HeadersKind::INITIAL;
|
|
489
|
+
|
|
490
|
+
// The headers_length_ field holds the total length of the headers that have
|
|
491
|
+
// been buffered.
|
|
492
|
+
size_t headers_length_ = 0;
|
|
493
|
+
|
|
494
|
+
friend struct Impl;
|
|
495
|
+
friend class PendingStream;
|
|
496
|
+
friend class Http3ApplicationImpl;
|
|
497
|
+
friend class DefaultApplication;
|
|
498
|
+
|
|
499
|
+
public:
|
|
500
|
+
// The Queue/Schedule here are part of the mechanism used to
|
|
501
|
+
// determine which streams have data to send on the session. When a stream
|
|
502
|
+
// potentially has data available, it will be scheduled in the Queue. Then,
|
|
503
|
+
// when the Session::Application starts sending pending data, it will check
|
|
504
|
+
// the queue to see if there are streams waiting. If there are, it will grab
|
|
505
|
+
// one and check to see if there is data to send. When a stream does not have
|
|
506
|
+
// data to send (such as when it is initially created or is using an async
|
|
507
|
+
// source that is still waiting for data to be pushed) it will not appear in
|
|
508
|
+
// the queue.
|
|
509
|
+
ListNode<Stream> stream_queue_;
|
|
510
|
+
using Queue = ListHead<Stream, &Stream::stream_queue_>;
|
|
511
|
+
|
|
512
|
+
void Schedule(Queue* queue);
|
|
513
|
+
void Unschedule();
|
|
514
|
+
};
|
|
515
|
+
|
|
516
|
+
} // namespace node::quic
|
|
517
|
+
|
|
518
|
+
#endif // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
|