Skip to content

Commit f8b4e26

Browse files
jasnellRafaelGSS
authored andcommitted
quic: add more QUIC impl
* add BindingData * add LogStream * add TransportParams PR-URL: #47348 Reviewed-By: Yagiz Nizipli <[email protected]> Reviewed-By: Stephen Belanger <[email protected]>
1 parent 757a586 commit f8b4e26

File tree

11 files changed

+1017
-1
lines changed

11 files changed

+1017
-1
lines changed

node.gyp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -337,16 +337,22 @@
337337
'src/node_crypto.h',
338338
],
339339
'node_quic_sources': [
340+
'src/quic/bindingdata.cc',
340341
'src/quic/cid.cc',
341342
'src/quic/data.cc',
343+
'src/quic/logstream.cc',
342344
'src/quic/preferredaddress.cc',
343345
'src/quic/sessionticket.cc',
344346
'src/quic/tokens.cc',
347+
'src/quic/transportparams.cc',
348+
'src/quic/bindingdata.h',
345349
'src/quic/cid.h',
346350
'src/quic/data.h',
351+
'src/quic/logstream.h',
347352
'src/quic/preferredaddress.h',
348353
'src/quic/sessionticket.h',
349354
'src/quic/tokens.h',
355+
'src/quic/transportparams.h',
350356
],
351357
'node_mksnapshot_exec': '<(PRODUCT_DIR)/<(EXECUTABLE_PREFIX)node_mksnapshot<(EXECUTABLE_SUFFIX)',
352358
'conditions': [

src/async_wrap.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ namespace node {
6060
V(PROCESSWRAP) \
6161
V(PROMISE) \
6262
V(QUERYWRAP) \
63+
V(QUIC_LOGSTREAM) \
6364
V(SHUTDOWNWRAP) \
6465
V(SIGNALWRAP) \
6566
V(STATWATCHER) \

src/base_object_types.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,8 @@ namespace node {
2020

2121
#define UNSERIALIZABLE_BINDING_TYPES(V) \
2222
V(http2_binding_data, http2::BindingData) \
23-
V(http_parser_binding_data, http_parser::BindingData)
23+
V(http_parser_binding_data, http_parser::BindingData) \
24+
V(quic_binding_data, quic::BindingData)
2425

2526
// List of (non-binding) BaseObjects that are serializable in the snapshot.
2627
// The first argument should match what the type passes to

src/quic/bindingdata.cc

Lines changed: 165 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
1+
#if HAVE_OPENSSL && NODE_OPENSSL_HAS_QUIC
2+
#include "bindingdata.h"
3+
#include <base_object-inl.h>
4+
#include <env-inl.h>
5+
#include <memory_tracker-inl.h>
6+
#include <nghttp3/nghttp3.h>
7+
#include <ngtcp2/ngtcp2.h>
8+
#include <node.h>
9+
#include <node_errors.h>
10+
#include <node_external_reference.h>
11+
#include <node_mem-inl.h>
12+
#include <node_realm-inl.h>
13+
#include <v8.h>
14+
15+
namespace node {
16+
17+
using v8::Function;
18+
using v8::FunctionCallbackInfo;
19+
using v8::FunctionTemplate;
20+
using v8::Local;
21+
using v8::Object;
22+
using v8::String;
23+
using v8::Value;
24+
25+
namespace quic {
26+
27+
BindingData& BindingData::Get(Environment* env) {
28+
return *Realm::GetBindingData<BindingData>(env->context());
29+
}
30+
31+
BindingData::operator ngtcp2_mem() {
32+
return MakeAllocator();
33+
}
34+
35+
BindingData::operator nghttp3_mem() {
36+
ngtcp2_mem allocator = *this;
37+
nghttp3_mem http3_allocator = {
38+
allocator.user_data,
39+
allocator.malloc,
40+
allocator.free,
41+
allocator.calloc,
42+
allocator.realloc,
43+
};
44+
return http3_allocator;
45+
}
46+
47+
void BindingData::CheckAllocatedSize(size_t previous_size) const {
48+
CHECK_GE(current_ngtcp2_memory_, previous_size);
49+
}
50+
51+
void BindingData::IncreaseAllocatedSize(size_t size) {
52+
current_ngtcp2_memory_ += size;
53+
}
54+
55+
void BindingData::DecreaseAllocatedSize(size_t size) {
56+
current_ngtcp2_memory_ -= size;
57+
}
58+
59+
void BindingData::Initialize(Environment* env, Local<Object> target) {
60+
SetMethod(env->context(), target, "setCallbacks", SetCallbacks);
61+
Realm::GetCurrent(env->context())
62+
->AddBindingData<BindingData>(env->context(), target);
63+
}
64+
65+
void BindingData::RegisterExternalReferences(
66+
ExternalReferenceRegistry* registry) {
67+
registry->Register(SetCallbacks);
68+
}
69+
70+
BindingData::BindingData(Realm* realm, Local<Object> object)
71+
: BaseObject(realm, object) {
72+
MakeWeak();
73+
}
74+
75+
void BindingData::MemoryInfo(MemoryTracker* tracker) const {
76+
#define V(name, _) tracker->TrackField(#name, name##_callback());
77+
78+
QUIC_JS_CALLBACKS(V)
79+
80+
#undef V
81+
82+
#define V(name, _) tracker->TrackField(#name, name##_string());
83+
84+
QUIC_STRINGS(V)
85+
86+
#undef V
87+
}
88+
89+
#define V(name) \
90+
void BindingData::set_##name##_constructor_template( \
91+
Local<FunctionTemplate> tmpl) { \
92+
name##_constructor_template_.Reset(env()->isolate(), tmpl); \
93+
} \
94+
Local<FunctionTemplate> BindingData::name##_constructor_template() const { \
95+
return PersistentToLocal::Default(env()->isolate(), \
96+
name##_constructor_template_); \
97+
}
98+
99+
QUIC_CONSTRUCTORS(V)
100+
101+
#undef V
102+
103+
#define V(name, _) \
104+
void BindingData::set_##name##_callback(Local<Function> fn) { \
105+
name##_callback_.Reset(env()->isolate(), fn); \
106+
} \
107+
Local<Function> BindingData::name##_callback() const { \
108+
return PersistentToLocal::Default(env()->isolate(), name##_callback_); \
109+
}
110+
111+
QUIC_JS_CALLBACKS(V)
112+
113+
#undef V
114+
115+
#define V(name, value) \
116+
Local<String> BindingData::name##_string() const { \
117+
if (name##_string_.IsEmpty()) \
118+
name##_string_.Set(env()->isolate(), \
119+
OneByteString(env()->isolate(), value)); \
120+
return name##_string_.Get(env()->isolate()); \
121+
}
122+
123+
QUIC_STRINGS(V)
124+
125+
#undef V
126+
127+
#define V(name, value) \
128+
Local<String> BindingData::on_##name##_string() const { \
129+
if (on_##name##_string_.IsEmpty()) \
130+
on_##name##_string_.Set( \
131+
env()->isolate(), \
132+
FIXED_ONE_BYTE_STRING(env()->isolate(), "on" #value)); \
133+
return on_##name##_string_.Get(env()->isolate()); \
134+
}
135+
136+
QUIC_JS_CALLBACKS(V)
137+
138+
#undef V
139+
140+
void BindingData::SetCallbacks(const FunctionCallbackInfo<Value>& args) {
141+
auto env = Environment::GetCurrent(args);
142+
auto isolate = env->isolate();
143+
BindingData& state = BindingData::Get(env);
144+
CHECK(args[0]->IsObject());
145+
Local<Object> obj = args[0].As<Object>();
146+
147+
#define V(name, key) \
148+
do { \
149+
Local<Value> val; \
150+
if (!obj->Get(env->context(), state.on_##name##_string()).ToLocal(&val) || \
151+
!val->IsFunction()) { \
152+
return THROW_ERR_MISSING_ARGS(isolate, "Missing Callback: on" #key); \
153+
} \
154+
state.set_##name##_callback(val.As<Function>()); \
155+
} while (0);
156+
157+
QUIC_JS_CALLBACKS(V)
158+
159+
#undef V
160+
}
161+
162+
} // namespace quic
163+
} // namespace node
164+
165+
#endif // HAVE_OPENSSL && NODE_OPENSSL_HAS_QUIC

src/quic/bindingdata.h

Lines changed: 173 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,173 @@
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

Comments
 (0)