/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  |