xref: /third_party/node/src/quic/bindingdata.h (revision 1cb0ef41)
1#pragma once
2
3#if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
4#if HAVE_OPENSSL && NODE_OPENSSL_HAS_QUIC
5
6#include <base_object.h>
7#include <env.h>
8#include <memory_tracker.h>
9#include <nghttp3/nghttp3.h>
10#include <ngtcp2/ngtcp2.h>
11#include <ngtcp2/ngtcp2_crypto.h>
12#include <node.h>
13#include <node_mem.h>
14#include <v8.h>
15#include <vector>
16
17namespace node {
18namespace quic {
19
20class Endpoint;
21class Packet;
22
23enum class Side {
24  CLIENT = NGTCP2_CRYPTO_SIDE_CLIENT,
25  SERVER = NGTCP2_CRYPTO_SIDE_SERVER,
26};
27
28constexpr size_t kDefaultMaxPacketLength = NGTCP2_MAX_UDP_PAYLOAD_SIZE;
29
30// ============================================================================
31
32// The FunctionTemplates the BindingData will store for us.
33#define QUIC_CONSTRUCTORS(V)                                                   \
34  V(endpoint)                                                                  \
35  V(logstream)                                                                 \
36  V(packet)                                                                    \
37  V(session)                                                                   \
38  V(stream)                                                                    \
39  V(udp)
40
41// The callbacks are persistent v8::Function references that are set in the
42// quic::BindingState used to communicate data and events back out to the JS
43// environment. They are set once from the JavaScript side when the
44// internalBinding('quic') is first loaded.
45#define QUIC_JS_CALLBACKS(V)                                                   \
46  V(endpoint_close, EndpointClose)                                             \
47  V(endpoint_error, EndpointError)                                             \
48  V(session_new, SessionNew)                                                   \
49  V(session_close, SessionClose)                                               \
50  V(session_error, SessionError)                                               \
51  V(session_datagram, SessionDatagram)                                         \
52  V(session_datagram_status, SessionDatagramStatus)                            \
53  V(session_handshake, SessionHandshake)                                       \
54  V(session_ticket, SessionTicket)                                             \
55  V(session_version_negotiation, SessionVersionNegotiation)                    \
56  V(session_path_validation, SessionPathValidation)                            \
57  V(stream_close, StreamClose)                                                 \
58  V(stream_error, StreamError)                                                 \
59  V(stream_created, StreamCreated)                                             \
60  V(stream_reset, StreamReset)                                                 \
61  V(stream_headers, StreamHeaders)                                             \
62  V(stream_blocked, StreamBlocked)                                             \
63  V(stream_trailers, StreamTrailers)
64
65// The various JS strings the implementation uses.
66#define QUIC_STRINGS(V)                                                        \
67  V(ack_delay_exponent, "ackDelayExponent")                                    \
68  V(active_connection_id_limit, "activeConnectionIDLimit")                     \
69  V(alpn, "alpn")                                                              \
70  V(ca, "ca")                                                                  \
71  V(certs, "certs")                                                            \
72  V(crl, "crl")                                                                \
73  V(ciphers, "ciphers")                                                        \
74  V(disable_active_migration, "disableActiveMigration")                        \
75  V(enable_tls_trace, "tlsTrace")                                              \
76  V(endpoint, "Endpoint")                                                      \
77  V(endpoint_udp, "Endpoint::UDP")                                             \
78  V(groups, "groups")                                                          \
79  V(hostname, "hostname")                                                      \
80  V(http3_alpn, &NGHTTP3_ALPN_H3[1])                                           \
81  V(initial_max_data, "initialMaxData")                                        \
82  V(initial_max_stream_data_bidi_local, "initialMaxStreamDataBidiLocal")       \
83  V(initial_max_stream_data_bidi_remote, "initialMaxStreamDataBidiRemote")     \
84  V(initial_max_stream_data_uni, "initialMaxStreamDataUni")                    \
85  V(initial_max_streams_bidi, "initialMaxStreamsBidi")                         \
86  V(initial_max_streams_uni, "initialMaxStreamsUni")                           \
87  V(keylog, "keylog")                                                          \
88  V(keys, "keys")                                                              \
89  V(logstream, "LogStream")                                                    \
90  V(max_ack_delay, "maxAckDelay")                                              \
91  V(max_datagram_frame_size, "maxDatagramFrameSize")                           \
92  V(max_idle_timeout, "maxIdleTimeout")                                        \
93  V(packetwrap, "PacketWrap")                                                  \
94  V(reject_unauthorized, "rejectUnauthorized")                                 \
95  V(request_peer_certificate, "requestPeerCertificate")                        \
96  V(session, "Session")                                                        \
97  V(session_id_ctx, "sessionIDContext")                                        \
98  V(stream, "Stream")                                                          \
99  V(verify_hostname_identity, "verifyHostnameIdentity")
100
101// =============================================================================
102// The BindingState object holds state for the internalBinding('quic') binding
103// instance. It is mostly used to hold the persistent constructors, strings, and
104// callback references used for the rest of the implementation.
105//
106// TODO(@jasnell): Make this snapshotable?
107class BindingData final
108    : public BaseObject,
109      public mem::NgLibMemoryManager<BindingData, ngtcp2_mem> {
110 public:
111  SET_BINDING_ID(quic_binding_data)
112  static void Initialize(Environment* env, v8::Local<v8::Object> target);
113  static void RegisterExternalReferences(ExternalReferenceRegistry* registry);
114
115  static BindingData& Get(Environment* env);
116
117  BindingData(Realm* realm, v8::Local<v8::Object> object);
118
119  void MemoryInfo(MemoryTracker* tracker) const override;
120  SET_MEMORY_INFO_NAME(BindingData)
121  SET_SELF_SIZE(BindingData)
122
123  // NgLibMemoryManager
124  operator ngtcp2_mem();
125  operator nghttp3_mem();
126  void CheckAllocatedSize(size_t previous_size) const;
127  void IncreaseAllocatedSize(size_t size);
128  void DecreaseAllocatedSize(size_t size);
129
130  // Installs the set of JavaScript callback functions that are used to
131  // bridge out to the JS API.
132  static void SetCallbacks(const v8::FunctionCallbackInfo<v8::Value>& args);
133
134  std::vector<BaseObjectPtr<BaseObject>> packet_freelist;
135
136  // Purge the packet free list to free up memory.
137  static void FlushPacketFreelist(
138      const v8::FunctionCallbackInfo<v8::Value>& args);
139
140  bool in_ngtcp2_callback_scope = false;
141  bool in_nghttp3_callback_scope = false;
142
143  // The following set up various storage and accessors for common strings,
144  // construction templates, and callbacks stored on the BindingData. These
145  // are all defined in defs.h
146
147#define V(name)                                                                \
148  void set_##name##_constructor_template(                                      \
149      v8::Local<v8::FunctionTemplate> tmpl);                                   \
150  v8::Local<v8::FunctionTemplate> name##_constructor_template() const;
151  QUIC_CONSTRUCTORS(V)
152#undef V
153
154#define V(name, _)                                                             \
155  void set_##name##_callback(v8::Local<v8::Function> fn);                      \
156  v8::Local<v8::Function> name##_callback() const;
157  QUIC_JS_CALLBACKS(V)
158#undef V
159
160#define V(name, _) v8::Local<v8::String> name##_string() const;
161  QUIC_STRINGS(V)
162#undef V
163
164#define V(name, _) v8::Local<v8::String> on_##name##_string() const;
165  QUIC_JS_CALLBACKS(V)
166#undef V
167
168  size_t current_ngtcp2_memory_ = 0;
169
170#define V(name) v8::Global<v8::FunctionTemplate> name##_constructor_template_;
171  QUIC_CONSTRUCTORS(V)
172#undef V
173
174#define V(name, _) v8::Global<v8::Function> name##_callback_;
175  QUIC_JS_CALLBACKS(V)
176#undef V
177
178#define V(name, _) mutable v8::Eternal<v8::String> name##_string_;
179  QUIC_STRINGS(V)
180#undef V
181
182#define V(name, _) mutable v8::Eternal<v8::String> on_##name##_string_;
183  QUIC_JS_CALLBACKS(V)
184#undef V
185};
186
187void IllegalConstructor(const v8::FunctionCallbackInfo<v8::Value>& args);
188
189// The ngtcp2 and nghttp3 callbacks have certain restrictions
190// that forbid re-entry. We provide the following scopes for
191// use in those to help protect against it.
192struct NgTcp2CallbackScope {
193  Environment* env;
194  explicit NgTcp2CallbackScope(Environment* env);
195  ~NgTcp2CallbackScope();
196  static bool in_ngtcp2_callback(Environment* env);
197};
198
199struct NgHttp3CallbackScope {
200  Environment* env;
201  explicit NgHttp3CallbackScope(Environment* env);
202  ~NgHttp3CallbackScope();
203  static bool in_nghttp3_callback(Environment* env);
204};
205
206}  // namespace quic
207}  // namespace node
208
209#endif  // HAVE_OPENSSL && NODE_OPENSSL_HAS_QUIC
210#endif  // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
211