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