Skip to content

Commit

Permalink
quic: add quic internalBinding, refine Endpoint, add types
Browse files Browse the repository at this point in the history
PR-URL: #51112
Reviewed-By: Stephen Belanger <admin@stephenbelanger.com>
Reviewed-By: Yagiz Nizipli <yagiz.nizipli@sentry.io>
Reviewed-By: Tobias Nießen <tniessen@tnie.de>
  • Loading branch information
jasnell committed Dec 27, 2023
1 parent 20c6313 commit c366422
Show file tree
Hide file tree
Showing 26 changed files with 996 additions and 256 deletions.
1 change: 1 addition & 0 deletions node.gyp
Original file line number Diff line number Diff line change
Expand Up @@ -377,6 +377,7 @@
'src/quic/tlscontext.h',
'src/quic/tokens.h',
'src/quic/transportparams.h',
'src/quic/quic.cc',
],
'node_cctest_sources': [
'src/node_snapshot_stub.cc',
Expand Down
3 changes: 2 additions & 1 deletion src/node_binding.cc
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,8 @@
NODE_BUILTIN_STANDARD_BINDINGS(V) \
NODE_BUILTIN_OPENSSL_BINDINGS(V) \
NODE_BUILTIN_ICU_BINDINGS(V) \
NODE_BUILTIN_PROFILER_BINDINGS(V)
NODE_BUILTIN_PROFILER_BINDINGS(V) \
NODE_BUILTIN_QUIC_BINDINGS(V)

// This is used to load built-in bindings. Instead of using
// __attribute__((constructor)), we call the _register_<modname>
Expand Down
9 changes: 8 additions & 1 deletion src/node_binding.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,12 @@ static_assert(static_cast<int>(NM_F_LINKED) ==
#define NODE_BUILTIN_ICU_BINDINGS(V)
#endif

#if HAVE_OPENSSL && NODE_OPENSSL_HAS_QUIC
#define NODE_BUILTIN_QUIC_BINDINGS(V) V(quic)
#else
#define NODE_BUILTIN_QUIC_BINDINGS(V)
#endif

#define NODE_BINDINGS_WITH_PER_ISOLATE_INIT(V) \
V(async_wrap) \
V(blob) \
Expand All @@ -47,7 +53,8 @@ static_assert(static_cast<int>(NM_F_LINKED) ==
V(timers) \
V(url) \
V(worker) \
NODE_BUILTIN_ICU_BINDINGS(V)
NODE_BUILTIN_ICU_BINDINGS(V) \
NODE_BUILTIN_QUIC_BINDINGS(V)

#define NODE_BINDING_CONTEXT_AWARE_CPP(modname, regfunc, priv, flags) \
static node::node_module _module = { \
Expand Down
9 changes: 8 additions & 1 deletion src/node_external_reference.h
Original file line number Diff line number Diff line change
Expand Up @@ -154,11 +154,18 @@ class ExternalReferenceRegistry {
#define EXTERNAL_REFERENCE_BINDING_LIST_CRYPTO(V)
#endif // HAVE_OPENSSL

#if HAVE_OPENSSL && NODE_OPENSSL_HAS_QUIC
#define EXTERNAL_REFERENCE_BINDING_LIST_QUIC(V) V(quic)
#else
#define EXTERNAL_REFERENCE_BINDING_LIST_QUIC(V)
#endif

#define EXTERNAL_REFERENCE_BINDING_LIST(V) \
EXTERNAL_REFERENCE_BINDING_LIST_BASE(V) \
EXTERNAL_REFERENCE_BINDING_LIST_INSPECTOR(V) \
EXTERNAL_REFERENCE_BINDING_LIST_I18N(V) \
EXTERNAL_REFERENCE_BINDING_LIST_CRYPTO(V)
EXTERNAL_REFERENCE_BINDING_LIST_CRYPTO(V) \
EXTERNAL_REFERENCE_BINDING_LIST_QUIC(V)

} // namespace node

Expand Down
19 changes: 14 additions & 5 deletions src/quic/application.cc
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
#include "node_bob.h"
#include "uv.h"
#if HAVE_OPENSSL && NODE_OPENSSL_HAS_QUIC

#include "application.h"
#include <node_bob.h>
#include <node_sockaddr-inl.h>
#include <uv.h>
#include <v8.h>
#include "application.h"
#include "defs.h"
#include "endpoint.h"
#include "packet.h"
Expand Down Expand Up @@ -38,14 +38,23 @@ const Session::Application_Options Session::Application_Options::kDefault = {};

Maybe<Session::Application_Options> Session::Application_Options::From(
Environment* env, Local<Value> value) {
if (value.IsEmpty() || !value->IsObject()) {
if (value.IsEmpty()) {
THROW_ERR_INVALID_ARG_TYPE(env, "options must be an object");
return Nothing<Application_Options>();
}

Application_Options options;
auto& state = BindingData::Get(env);
if (value->IsUndefined()) {
return Just<Application_Options>(options);
}

if (!value->IsObject()) {
THROW_ERR_INVALID_ARG_TYPE(env, "options must be an object");
return Nothing<Application_Options>();
}

auto params = value.As<Object>();
Application_Options options;

#define SET(name) \
SetOption<Session::Application_Options, \
Expand Down
9 changes: 5 additions & 4 deletions src/quic/bindingdata.cc
Original file line number Diff line number Diff line change
Expand Up @@ -56,10 +56,11 @@ void BindingData::DecreaseAllocatedSize(size_t size) {
current_ngtcp2_memory_ -= size;
}

void BindingData::Initialize(Environment* env, Local<Object> target) {
SetMethod(env->context(), target, "setCallbacks", SetCallbacks);
SetMethod(env->context(), target, "flushPacketFreelist", FlushPacketFreelist);
Realm::GetCurrent(env->context())->AddBindingData<BindingData>(target);
void BindingData::InitPerContext(Realm* realm, Local<Object> target) {
SetMethod(realm->context(), target, "setCallbacks", SetCallbacks);
SetMethod(
realm->context(), target, "flushPacketFreelist", FlushPacketFreelist);
Realm::GetCurrent(realm->context())->AddBindingData<BindingData>(target);
}

void BindingData::RegisterExternalReferences(
Expand Down
6 changes: 5 additions & 1 deletion src/quic/bindingdata.h
Original file line number Diff line number Diff line change
Expand Up @@ -118,11 +118,14 @@ constexpr size_t kMaxVectorCount = 16;
V(address_lru_size, "addressLRUSize") \
V(alpn, "alpn") \
V(application_options, "application") \
V(bbr, "bbr") \
V(bbr2, "bbr2") \
V(ca, "ca") \
V(certs, "certs") \
V(cc_algorithm, "cc") \
V(crl, "crl") \
V(ciphers, "ciphers") \
V(cubic, "cubic") \
V(disable_active_migration, "disableActiveMigration") \
V(disable_stateless_reset, "disableStatelessReset") \
V(enable_tls_trace, "tlsTrace") \
Expand Down Expand Up @@ -162,6 +165,7 @@ constexpr size_t kMaxVectorCount = 16;
V(qpack_encoder_max_dtable_capacity, "qpackEncoderMaxDTableCapacity") \
V(qpack_max_dtable_capacity, "qpackMaxDTableCapacity") \
V(reject_unauthorized, "rejectUnauthorized") \
V(reno, "reno") \
V(retry_token_expiration, "retryTokenExpiration") \
V(request_peer_certificate, "requestPeerCertificate") \
V(reset_token_secret, "resetTokenSecret") \
Expand Down Expand Up @@ -194,7 +198,7 @@ class BindingData final
public mem::NgLibMemoryManager<BindingData, ngtcp2_mem> {
public:
SET_BINDING_ID(quic_binding_data)
static void Initialize(Environment* env, v8::Local<v8::Object> target);
static void InitPerContext(Realm* realm, v8::Local<v8::Object> target);
static void RegisterExternalReferences(ExternalReferenceRegistry* registry);

static BindingData& Get(Environment* env);
Expand Down
46 changes: 40 additions & 6 deletions src/quic/defs.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,15 +28,38 @@ bool SetOption(Environment* env,
}

template <typename Opt, bool Opt::*member>
bool SetOption(Environment* env,
Opt* options,
const v8::Local<v8::Object>& object,
const v8::Local<v8::String>& name) {
v8::Local<v8::Value> value;
if (!object->Get(env->context(), name).ToLocal(&value)) return false;
options->*member = value->BooleanValue(env->isolate());
return true;
}

template <typename Opt, uint32_t Opt::*member>
bool SetOption(Environment* env,
Opt* options,
const v8::Local<v8::Object>& object,
const v8::Local<v8::String>& name) {
v8::Local<v8::Value> value;
if (!object->Get(env->context(), name).ToLocal(&value)) return false;
if (!value->IsUndefined()) {
CHECK(value->IsBoolean());
options->*member = value->IsTrue();
if (!value->IsUint32()) {
Utf8Value nameStr(env->isolate(), name);
THROW_ERR_INVALID_ARG_VALUE(
env, "The %s option must be an uint32", *nameStr);
return false;
}
v8::Local<v8::Uint32> num;
if (!value->ToUint32(env->context()).ToLocal(&num)) {
Utf8Value nameStr(env->isolate(), name);
THROW_ERR_INVALID_ARG_VALUE(
env, "The %s option must be an uint32", *nameStr);
return false;
}
options->*member = num->Value();
}
return true;
}
Expand All @@ -50,20 +73,31 @@ bool SetOption(Environment* env,
if (!object->Get(env->context(), name).ToLocal(&value)) return false;

if (!value->IsUndefined()) {
CHECK_IMPLIES(!value->IsBigInt(), value->IsNumber());
if (!value->IsBigInt() && !value->IsNumber()) {
Utf8Value nameStr(env->isolate(), name);
THROW_ERR_INVALID_ARG_VALUE(
env, "option %s must be a bigint or number", *nameStr);
return false;
}
DCHECK_IMPLIES(!value->IsBigInt(), value->IsNumber());

uint64_t val = 0;
if (value->IsBigInt()) {
bool lossless = true;
val = value.As<v8::BigInt>()->Uint64Value(&lossless);
if (!lossless) {
Utf8Value label(env->isolate(), name);
THROW_ERR_OUT_OF_RANGE(
env, ("options." + label.ToString() + " is out of range").c_str());
THROW_ERR_INVALID_ARG_VALUE(env, "option %s is out of range", *label);
return false;
}
} else {
val = static_cast<int64_t>(value.As<v8::Number>()->Value());
double dbl = value.As<v8::Number>()->Value();
if (dbl < 0) {
Utf8Value label(env->isolate(), name);
THROW_ERR_INVALID_ARG_VALUE(env, "option %s is out of range", *label);
return false;
}
val = static_cast<uint64_t>(dbl);
}
options->*member = val;
}
Expand Down
Loading

0 comments on commit c366422

Please sign in to comment.