|
| 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 | + |
| 16 | +namespace node { |
| 17 | +namespace quic { |
| 18 | + |
| 19 | +class Endpoint; |
| 20 | + |
| 21 | +enum class Side { |
| 22 | + CLIENT = NGTCP2_CRYPTO_SIDE_CLIENT, |
| 23 | + SERVER = NGTCP2_CRYPTO_SIDE_SERVER, |
| 24 | +}; |
| 25 | + |
| 26 | +constexpr size_t kDefaultMaxPacketLength = NGTCP2_MAX_UDP_PAYLOAD_SIZE; |
| 27 | + |
| 28 | +// ============================================================================ |
| 29 | + |
| 30 | +// The FunctionTemplates the BindingData will store for us. |
| 31 | +#define QUIC_CONSTRUCTORS(V) \ |
| 32 | + V(endpoint) \ |
| 33 | + V(logstream) \ |
| 34 | + V(packet) \ |
| 35 | + V(session) \ |
| 36 | + V(stream) \ |
| 37 | + V(udp) |
| 38 | + |
| 39 | +// The callbacks are persistent v8::Function references that are set in the |
| 40 | +// quic::BindingState used to communicate data and events back out to the JS |
| 41 | +// environment. They are set once from the JavaScript side when the |
| 42 | +// internalBinding('quic') is first loaded. |
| 43 | +#define QUIC_JS_CALLBACKS(V) \ |
| 44 | + V(endpoint_close, EndpointClose) \ |
| 45 | + V(endpoint_error, EndpointError) \ |
| 46 | + V(session_new, SessionNew) \ |
| 47 | + V(session_close, SessionClose) \ |
| 48 | + V(session_error, SessionError) \ |
| 49 | + V(session_datagram, SessionDatagram) \ |
| 50 | + V(session_datagram_status, SessionDatagramStatus) \ |
| 51 | + V(session_handshake, SessionHandshake) \ |
| 52 | + V(session_ticket, SessionTicket) \ |
| 53 | + V(session_version_negotiation, SessionVersionNegotiation) \ |
| 54 | + V(session_path_validation, SessionPathValidation) \ |
| 55 | + V(stream_close, StreamClose) \ |
| 56 | + V(stream_error, StreamError) \ |
| 57 | + V(stream_created, StreamCreated) \ |
| 58 | + V(stream_reset, StreamReset) \ |
| 59 | + V(stream_headers, StreamHeaders) \ |
| 60 | + V(stream_blocked, StreamBlocked) \ |
| 61 | + V(stream_trailers, StreamTrailers) |
| 62 | + |
| 63 | +// The various JS strings the implementation uses. |
| 64 | +#define QUIC_STRINGS(V) \ |
| 65 | + V(ack_delay_exponent, "ackDelayExponent") \ |
| 66 | + V(active_connection_id_limit, "activeConnectionIDLimit") \ |
| 67 | + V(disable_active_migration, "disableActiveMigration") \ |
| 68 | + V(endpoint, "Endpoint") \ |
| 69 | + V(endpoint_udp, "Endpoint::UDP") \ |
| 70 | + V(http3_alpn, &NGHTTP3_ALPN_H3[1]) \ |
| 71 | + V(initial_max_data, "initialMaxData") \ |
| 72 | + V(initial_max_stream_data_bidi_local, "initialMaxStreamDataBidiLocal") \ |
| 73 | + V(initial_max_stream_data_bidi_remote, "initialMaxStreamDataBidiRemote") \ |
| 74 | + V(initial_max_stream_data_uni, "initialMaxStreamDataUni") \ |
| 75 | + V(initial_max_streams_bidi, "initialMaxStreamsBidi") \ |
| 76 | + V(initial_max_streams_uni, "initialMaxStreamsUni") \ |
| 77 | + V(logstream, "LogStream") \ |
| 78 | + V(max_ack_delay, "maxAckDelay") \ |
| 79 | + V(max_datagram_frame_size, "maxDatagramFrameSize") \ |
| 80 | + V(max_idle_timeout, "maxIdleTimeout") \ |
| 81 | + V(packetwrap, "PacketWrap") \ |
| 82 | + V(session, "Session") \ |
| 83 | + V(stream, "Stream") |
| 84 | + |
| 85 | +// ============================================================================= |
| 86 | +// The BindingState object holds state for the internalBinding('quic') binding |
| 87 | +// instance. It is mostly used to hold the persistent constructors, strings, and |
| 88 | +// callback references used for the rest of the implementation. |
| 89 | +// |
| 90 | +// TODO(@jasnell): Make this snapshotable? |
| 91 | +class BindingData final |
| 92 | + : public BaseObject, |
| 93 | + public mem::NgLibMemoryManager<BindingData, ngtcp2_mem> { |
| 94 | + public: |
| 95 | + SET_BINDING_ID(quic_binding_data) |
| 96 | + static void Initialize(Environment* env, v8::Local<v8::Object> target); |
| 97 | + static void RegisterExternalReferences(ExternalReferenceRegistry* registry); |
| 98 | + |
| 99 | + static BindingData& Get(Environment* env); |
| 100 | + |
| 101 | + BindingData(Realm* realm, v8::Local<v8::Object> object); |
| 102 | + |
| 103 | + void MemoryInfo(MemoryTracker* tracker) const override; |
| 104 | + SET_MEMORY_INFO_NAME(BindingData) |
| 105 | + SET_SELF_SIZE(BindingData) |
| 106 | + |
| 107 | + // NgLibMemoryManager |
| 108 | + operator ngtcp2_mem(); |
| 109 | + operator nghttp3_mem(); |
| 110 | + void CheckAllocatedSize(size_t previous_size) const; |
| 111 | + void IncreaseAllocatedSize(size_t size); |
| 112 | + void DecreaseAllocatedSize(size_t size); |
| 113 | + |
| 114 | + // Installs the set of JavaScript callback functions that are used to |
| 115 | + // bridge out to the JS API. |
| 116 | + static void SetCallbacks(const v8::FunctionCallbackInfo<v8::Value>& args); |
| 117 | + |
| 118 | + // TODO(@jasnell) This will be added when Endpoint is implemented. |
| 119 | + // // A set of listening Endpoints. We maintain this to ensure that the |
| 120 | + // Endpoint |
| 121 | + // // cannot be gc'd while it is still listening and there are active |
| 122 | + // // connections. |
| 123 | + // std::unordered_map<Endpoint*, BaseObjectPtr<Endpoint>> listening_endpoints; |
| 124 | + |
| 125 | + // The following set up various storage and accessors for common strings, |
| 126 | + // construction templates, and callbacks stored on the BindingData. These |
| 127 | + // are all defined in defs.h |
| 128 | + |
| 129 | +#define V(name) \ |
| 130 | + void set_##name##_constructor_template( \ |
| 131 | + v8::Local<v8::FunctionTemplate> tmpl); \ |
| 132 | + v8::Local<v8::FunctionTemplate> name##_constructor_template() const; |
| 133 | + QUIC_CONSTRUCTORS(V) |
| 134 | +#undef V |
| 135 | + |
| 136 | +#define V(name, _) \ |
| 137 | + void set_##name##_callback(v8::Local<v8::Function> fn); \ |
| 138 | + v8::Local<v8::Function> name##_callback() const; |
| 139 | + QUIC_JS_CALLBACKS(V) |
| 140 | +#undef V |
| 141 | + |
| 142 | +#define V(name, _) v8::Local<v8::String> name##_string() const; |
| 143 | + QUIC_STRINGS(V) |
| 144 | +#undef V |
| 145 | + |
| 146 | +#define V(name, _) v8::Local<v8::String> on_##name##_string() const; |
| 147 | + QUIC_JS_CALLBACKS(V) |
| 148 | +#undef V |
| 149 | + |
| 150 | + size_t current_ngtcp2_memory_ = 0; |
| 151 | + |
| 152 | +#define V(name) v8::Global<v8::FunctionTemplate> name##_constructor_template_; |
| 153 | + QUIC_CONSTRUCTORS(V) |
| 154 | +#undef V |
| 155 | + |
| 156 | +#define V(name, _) v8::Global<v8::Function> name##_callback_; |
| 157 | + QUIC_JS_CALLBACKS(V) |
| 158 | +#undef V |
| 159 | + |
| 160 | +#define V(name, _) mutable v8::Eternal<v8::String> name##_string_; |
| 161 | + QUIC_STRINGS(V) |
| 162 | +#undef V |
| 163 | + |
| 164 | +#define V(name, _) mutable v8::Eternal<v8::String> on_##name##_string_; |
| 165 | + QUIC_JS_CALLBACKS(V) |
| 166 | +#undef V |
| 167 | +}; |
| 168 | + |
| 169 | +} // namespace quic |
| 170 | +} // namespace node |
| 171 | + |
| 172 | +#endif // HAVE_OPENSSL && NODE_OPENSSL_HAS_QUIC |
| 173 | +#endif // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS |
0 commit comments