Coverage Report

Created: 2025-10-31 09:06

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/node/src/quic/bindingdata.h
Line
Count
Source
1
#pragma once
2
3
#if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
4
5
#include <base_object.h>
6
#include <env.h>
7
#include <memory_tracker.h>
8
#include <nghttp3/nghttp3.h>
9
#include <ngtcp2/ngtcp2.h>
10
#include <ngtcp2/ngtcp2_crypto.h>
11
#include <node.h>
12
#include <node_mem.h>
13
#include <v8.h>
14
#include <list>
15
#include <unordered_map>
16
#include "defs.h"
17
18
namespace node::quic {
19
20
class Endpoint;
21
class Packet;
22
23
// ============================================================================
24
25
// The FunctionTemplates the BindingData will store for us.
26
#define QUIC_CONSTRUCTORS(V)                                                   \
27
  V(endpoint)                                                                  \
28
  V(http3application)                                                          \
29
  V(logstream)                                                                 \
30
  V(packet)                                                                    \
31
  V(session)                                                                   \
32
  V(stream)                                                                    \
33
  V(udp)
34
35
// The callbacks are persistent v8::Function references that are set in the
36
// quic::BindingState used to communicate data and events back out to the JS
37
// environment. They are set once from the JavaScript side when the
38
// internalBinding('quic') is first loaded.
39
#define QUIC_JS_CALLBACKS(V)                                                   \
40
0
  V(endpoint_close, EndpointClose)                                             \
41
0
  V(session_close, SessionClose)                                               \
42
0
  V(session_datagram, SessionDatagram)                                         \
43
0
  V(session_datagram_status, SessionDatagramStatus)                            \
44
0
  V(session_handshake, SessionHandshake)                                       \
45
0
  V(session_new, SessionNew)                                                   \
46
0
  V(session_path_validation, SessionPathValidation)                            \
47
0
  V(session_ticket, SessionTicket)                                             \
48
0
  V(session_version_negotiation, SessionVersionNegotiation)                    \
49
0
  V(stream_blocked, StreamBlocked)                                             \
50
0
  V(stream_close, StreamClose)                                                 \
51
0
  V(stream_created, StreamCreated)                                             \
52
0
  V(stream_headers, StreamHeaders)                                             \
53
0
  V(stream_reset, StreamReset)                                                 \
54
0
  V(stream_trailers, StreamTrailers)
55
56
// The various JS strings the implementation uses.
57
#define QUIC_STRINGS(V)                                                        \
58
0
  V(aborted, "aborted")                                                        \
59
0
  V(acknowledged, "acknowledged")                                              \
60
0
  V(ack_delay_exponent, "ackDelayExponent")                                    \
61
0
  V(active_connection_id_limit, "activeConnectionIDLimit")                     \
62
0
  V(address_lru_size, "addressLRUSize")                                        \
63
0
  V(application_provider, "provider")                                          \
64
0
  V(bbr, "bbr")                                                                \
65
0
  V(ca, "ca")                                                                  \
66
0
  V(cc_algorithm, "cc")                                                        \
67
0
  V(certs, "certs")                                                            \
68
0
  V(ciphers, "ciphers")                                                        \
69
0
  V(crl, "crl")                                                                \
70
0
  V(cubic, "cubic")                                                            \
71
0
  V(disable_stateless_reset, "disableStatelessReset")                          \
72
0
  V(enable_connect_protocol, "enableConnectProtocol")                          \
73
0
  V(enable_datagrams, "enableDatagrams")                                       \
74
0
  V(enable_tls_trace, "tlsTrace")                                              \
75
0
  V(endpoint, "Endpoint")                                                      \
76
0
  V(endpoint_udp, "Endpoint::UDP")                                             \
77
0
  V(failure, "failure")                                                        \
78
0
  V(groups, "groups")                                                          \
79
0
  V(handshake_timeout, "handshakeTimeout")                                     \
80
0
  V(http3_alpn, &NGHTTP3_ALPN_H3[1])                                           \
81
0
  V(http3application, "Http3Application")                                      \
82
0
  V(initial_max_data, "initialMaxData")                                        \
83
0
  V(initial_max_stream_data_bidi_local, "initialMaxStreamDataBidiLocal")       \
84
0
  V(initial_max_stream_data_bidi_remote, "initialMaxStreamDataBidiRemote")     \
85
0
  V(initial_max_stream_data_uni, "initialMaxStreamDataUni")                    \
86
0
  V(initial_max_streams_bidi, "initialMaxStreamsBidi")                         \
87
0
  V(initial_max_streams_uni, "initialMaxStreamsUni")                           \
88
0
  V(ipv6_only, "ipv6Only")                                                     \
89
0
  V(keylog, "keylog")                                                          \
90
0
  V(keys, "keys")                                                              \
91
0
  V(logstream, "LogStream")                                                    \
92
0
  V(lost, "lost")                                                              \
93
0
  V(max_ack_delay, "maxAckDelay")                                              \
94
0
  V(max_connections_per_host, "maxConnectionsPerHost")                         \
95
0
  V(max_connections_total, "maxConnectionsTotal")                              \
96
0
  V(max_datagram_frame_size, "maxDatagramFrameSize")                           \
97
0
  V(max_field_section_size, "maxFieldSectionSize")                             \
98
0
  V(max_header_length, "maxHeaderLength")                                      \
99
0
  V(max_header_pairs, "maxHeaderPairs")                                        \
100
0
  V(max_idle_timeout, "maxIdleTimeout")                                        \
101
0
  V(max_payload_size, "maxPayloadSize")                                        \
102
0
  V(max_retries, "maxRetries")                                                 \
103
0
  V(max_stateless_resets, "maxStatelessResetsPerHost")                         \
104
0
  V(max_stream_window, "maxStreamWindow")                                      \
105
0
  V(max_window, "maxWindow")                                                   \
106
0
  V(min_version, "minVersion")                                                 \
107
0
  V(packetwrap, "PacketWrap")                                                  \
108
0
  V(preferred_address_strategy, "preferredAddressPolicy")                      \
109
0
  V(protocol, "protocol")                                                      \
110
0
  V(qlog, "qlog")                                                              \
111
0
  V(qpack_blocked_streams, "qpackBlockedStreams")                              \
112
0
  V(qpack_encoder_max_dtable_capacity, "qpackEncoderMaxDTableCapacity")        \
113
0
  V(qpack_max_dtable_capacity, "qpackMaxDTableCapacity")                       \
114
0
  V(reject_unauthorized, "rejectUnauthorized")                                 \
115
0
  V(reno, "reno")                                                              \
116
0
  V(reset_token_secret, "resetTokenSecret")                                    \
117
0
  V(retry_token_expiration, "retryTokenExpiration")                            \
118
0
  V(rx_loss, "rxDiagnosticLoss")                                               \
119
0
  V(servername, "servername")                                                  \
120
0
  V(session, "Session")                                                        \
121
0
  V(stream, "Stream")                                                          \
122
0
  V(success, "success")                                                        \
123
0
  V(tls_options, "tls")                                                        \
124
0
  V(token_expiration, "tokenExpiration")                                       \
125
0
  V(token_secret, "tokenSecret")                                               \
126
0
  V(transport_params, "transportParams")                                       \
127
0
  V(tx_loss, "txDiagnosticLoss")                                               \
128
0
  V(udp_receive_buffer_size, "udpReceiveBufferSize")                           \
129
0
  V(udp_send_buffer_size, "udpSendBufferSize")                                 \
130
0
  V(udp_ttl, "udpTTL")                                                         \
131
0
  V(unacknowledged_packet_threshold, "unacknowledgedPacketThreshold")          \
132
0
  V(validate_address, "validateAddress")                                       \
133
0
  V(verify_client, "verifyClient")                                             \
134
0
  V(verify_private_key, "verifyPrivateKey")                                    \
135
0
  V(version, "version")
136
137
// =============================================================================
138
// The BindingState object holds state for the internalBinding('quic') binding
139
// instance. It is mostly used to hold the persistent constructors, strings, and
140
// callback references used for the rest of the implementation.
141
//
142
// TODO(@jasnell): Make this snapshotable?
143
class BindingData final
144
    : public BaseObject,
145
      public mem::NgLibMemoryManager<BindingData, ngtcp2_mem> {
146
 public:
147
  SET_BINDING_ID(quic_binding_data)
148
  static void InitPerContext(Realm* realm, v8::Local<v8::Object> target);
149
  static void RegisterExternalReferences(ExternalReferenceRegistry* registry);
150
151
  static BindingData& Get(Environment* env);
152
0
  static inline BindingData& Get(Realm* realm) { return Get(realm->env()); }
153
154
  BindingData(Realm* realm, v8::Local<v8::Object> object);
155
  DISALLOW_COPY_AND_MOVE(BindingData)
156
157
  void MemoryInfo(MemoryTracker* tracker) const override;
158
  SET_MEMORY_INFO_NAME(BindingData)
159
  SET_SELF_SIZE(BindingData)
160
161
  // NgLibMemoryManager
162
  operator ngtcp2_mem();
163
  operator nghttp3_mem();
164
  void CheckAllocatedSize(size_t previous_size) const;
165
  void IncreaseAllocatedSize(size_t size);
166
  void DecreaseAllocatedSize(size_t size);
167
168
  // Installs the set of JavaScript callback functions that are used to
169
  // bridge out to the JS API.
170
  JS_METHOD(SetCallbacks);
171
172
  // Purge the packet free list to free up memory.
173
  JS_METHOD(FlushPacketFreelist);
174
175
  std::list<BaseObjectPtr<BaseObject>> packet_freelist;
176
177
  std::unordered_map<Endpoint*, BaseObjectPtr<BaseObject>> listening_endpoints;
178
179
  bool in_ngtcp2_callback_scope = false;
180
  bool in_nghttp3_callback_scope = false;
181
  size_t current_ngtcp2_memory_ = 0;
182
183
  // The following set up various storage and accessors for common strings,
184
  // construction templates, and callbacks stored on the BindingData. These
185
  // are all defined in defs.h
186
187
#define V(name)                                                                \
188
  void set_##name##_constructor_template(                                      \
189
      v8::Local<v8::FunctionTemplate> tmpl);                                   \
190
  v8::Local<v8::FunctionTemplate> name##_constructor_template() const;
191
  QUIC_CONSTRUCTORS(V)
192
#undef V
193
194
#define V(name, _)                                                             \
195
  void set_##name##_callback(v8::Local<v8::Function> fn);                      \
196
  v8::Local<v8::Function> name##_callback() const;
197
  QUIC_JS_CALLBACKS(V)
198
#undef V
199
200
#define V(name, _) v8::Local<v8::String> name##_string() const;
201
  QUIC_STRINGS(V)
202
#undef V
203
204
#define V(name, _) v8::Local<v8::String> on_##name##_string() const;
205
  QUIC_JS_CALLBACKS(V)
206
#undef V
207
208
#define V(name) v8::Global<v8::FunctionTemplate> name##_constructor_template_;
209
  QUIC_CONSTRUCTORS(V)
210
#undef V
211
212
#define V(name, _) v8::Global<v8::Function> name##_callback_;
213
  QUIC_JS_CALLBACKS(V)
214
#undef V
215
216
#define V(name, _) mutable v8::Eternal<v8::String> name##_string_;
217
  QUIC_STRINGS(V)
218
#undef V
219
220
#define V(name, _) mutable v8::Eternal<v8::String> on_##name##_string_;
221
  QUIC_JS_CALLBACKS(V)
222
#undef V
223
};
224
225
JS_METHOD_IMPL(IllegalConstructor);
226
227
// The ngtcp2 and nghttp3 callbacks have certain restrictions
228
// that forbid re-entry. We provide the following scopes for
229
// use in those to help protect against it.
230
struct NgTcp2CallbackScope final {
231
  Environment* env;
232
  explicit NgTcp2CallbackScope(Environment* env);
233
  DISALLOW_COPY_AND_MOVE(NgTcp2CallbackScope)
234
  ~NgTcp2CallbackScope();
235
  static bool in_ngtcp2_callback(Environment* env);
236
};
237
238
struct NgHttp3CallbackScope final {
239
  Environment* env;
240
  explicit NgHttp3CallbackScope(Environment* env);
241
  DISALLOW_COPY_AND_MOVE(NgHttp3CallbackScope)
242
  ~NgHttp3CallbackScope();
243
  static bool in_nghttp3_callback(Environment* env);
244
};
245
246
struct CallbackScopeBase {
247
  Environment* env;
248
  v8::Context::Scope context_scope;
249
  v8::TryCatch try_catch;
250
251
  explicit CallbackScopeBase(Environment* env);
252
  DISALLOW_COPY_AND_MOVE(CallbackScopeBase)
253
  ~CallbackScopeBase();
254
};
255
256
// Maintains a strong reference to BaseObject type ptr to keep it alive during
257
// a MakeCallback during which it might be destroyed.
258
template <typename T>
259
struct CallbackScope final : public CallbackScopeBase {
260
  BaseObjectPtr<T> ref;
261
  explicit CallbackScope(const T* ptr)
262
      : CallbackScopeBase(ptr->env()), ref(ptr) {}
263
  DISALLOW_COPY_AND_MOVE(CallbackScope)
264
0
  explicit CallbackScope(T* ptr) : CallbackScopeBase(ptr->env()), ref(ptr) {}
Unexecuted instantiation: node::quic::CallbackScope<node::quic::Endpoint>::CallbackScope(node::quic::Endpoint*)
Unexecuted instantiation: node::quic::CallbackScope<node::quic::Session>::CallbackScope(node::quic::Session*)
Unexecuted instantiation: node::quic::CallbackScope<node::quic::Stream>::CallbackScope(node::quic::Stream*)
265
};
266
267
}  // namespace node::quic
268
269
#endif  // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS