• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
17 namespace node {
18 namespace quic {
19 
20 class Endpoint;
21 class Packet;
22 
23 enum class Side {
24   CLIENT = NGTCP2_CRYPTO_SIDE_CLIENT,
25   SERVER = NGTCP2_CRYPTO_SIDE_SERVER,
26 };
27 
28 constexpr 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?
107 class 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 
187 void 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.
192 struct NgTcp2CallbackScope {
193   Environment* env;
194   explicit NgTcp2CallbackScope(Environment* env);
195   ~NgTcp2CallbackScope();
196   static bool in_ngtcp2_callback(Environment* env);
197 };
198 
199 struct 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