Skip to content

Commit

Permalink
quic: add additional QUIC implementation
Browse files Browse the repository at this point in the history
Adds most of the Endpoint implementation with a few tweaks to
other bits.

PR-URL: #47603
Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com>
Reviewed-By: Tobias Nießen <tniessen@tnie.de>
  • Loading branch information
jasnell committed Apr 26, 2023
1 parent 2ac5e98 commit 76044c4
Show file tree
Hide file tree
Showing 11 changed files with 2,004 additions and 14 deletions.
2 changes: 2 additions & 0 deletions src/async_wrap.h
Expand Up @@ -60,8 +60,10 @@ namespace node {
V(PROCESSWRAP) \
V(PROMISE) \
V(QUERYWRAP) \
V(QUIC_ENDPOINT) \
V(QUIC_LOGSTREAM) \
V(QUIC_PACKET) \
V(QUIC_UDP) \
V(SHUTDOWNWRAP) \
V(SIGNALWRAP) \
V(STATWATCHER) \
Expand Down
10 changes: 10 additions & 0 deletions src/quic/bindingdata.cc
Expand Up @@ -65,6 +65,7 @@ void BindingData::Initialize(Environment* env, Local<Object> target) {

void BindingData::RegisterExternalReferences(
ExternalReferenceRegistry* registry) {
registry->Register(IllegalConstructor);
registry->Register(SetCallbacks);
registry->Register(FlushPacketFreelist);
}
Expand Down Expand Up @@ -199,6 +200,15 @@ bool NgHttp3CallbackScope::in_nghttp3_callback(Environment* env) {
return binding.in_nghttp3_callback_scope;
}

CallbackScopeBase::CallbackScopeBase(Environment* env)
: env(env), context_scope(env->context()), try_catch(env->isolate()) {}

CallbackScopeBase::~CallbackScopeBase() {
if (try_catch.HasCaught() && !try_catch.HasTerminated()) {
errors::TriggerUncaughtException(env->isolate(), try_catch);
}
}

void IllegalConstructor(const FunctionCallbackInfo<Value>& args) {
THROW_ERR_ILLEGAL_CONSTRUCTOR(Environment::GetCurrent(args));
}
Expand Down
48 changes: 47 additions & 1 deletion src/quic/bindingdata.h
Expand Up @@ -12,6 +12,8 @@
#include <node.h>
#include <node_mem.h>
#include <v8.h>
#include <limits>
#include <unordered_map>
#include <vector>

namespace node {
Expand All @@ -26,6 +28,9 @@ enum class Side {
};

constexpr size_t kDefaultMaxPacketLength = NGTCP2_MAX_UDP_PAYLOAD_SIZE;
constexpr size_t kMaxSizeT = std::numeric_limits<size_t>::max();
constexpr uint64_t kMaxSafeJsInteger = 9007199254740991;
constexpr auto kSocketAddressInfoTimeout = 60 * NGTCP2_SECONDS;

// ============================================================================

Expand All @@ -44,7 +49,6 @@ constexpr size_t kDefaultMaxPacketLength = NGTCP2_MAX_UDP_PAYLOAD_SIZE;
// internalBinding('quic') is first loaded.
#define QUIC_JS_CALLBACKS(V) \
V(endpoint_close, EndpointClose) \
V(endpoint_error, EndpointError) \
V(session_new, SessionNew) \
V(session_close, SessionClose) \
V(session_error, SessionError) \
Expand All @@ -66,12 +70,15 @@ constexpr size_t kDefaultMaxPacketLength = NGTCP2_MAX_UDP_PAYLOAD_SIZE;
#define QUIC_STRINGS(V) \
V(ack_delay_exponent, "ackDelayExponent") \
V(active_connection_id_limit, "activeConnectionIDLimit") \
V(address_lru_size, "addressLRUSize") \
V(alpn, "alpn") \
V(ca, "ca") \
V(certs, "certs") \
V(cc_algorithm, "cc") \
V(crl, "crl") \
V(ciphers, "ciphers") \
V(disable_active_migration, "disableActiveMigration") \
V(disable_stateless_reset, "disableStatelessReset") \
V(enable_tls_trace, "tlsTrace") \
V(endpoint, "Endpoint") \
V(endpoint_udp, "Endpoint::UDP") \
Expand All @@ -84,18 +91,35 @@ constexpr size_t kDefaultMaxPacketLength = NGTCP2_MAX_UDP_PAYLOAD_SIZE;
V(initial_max_stream_data_uni, "initialMaxStreamDataUni") \
V(initial_max_streams_bidi, "initialMaxStreamsBidi") \
V(initial_max_streams_uni, "initialMaxStreamsUni") \
V(ipv6_only, "ipv6Only") \
V(keylog, "keylog") \
V(keys, "keys") \
V(logstream, "LogStream") \
V(max_ack_delay, "maxAckDelay") \
V(max_connections_per_host, "maxConnectionsPerHost") \
V(max_connections_total, "maxConnectionsTotal") \
V(max_datagram_frame_size, "maxDatagramFrameSize") \
V(max_idle_timeout, "maxIdleTimeout") \
V(max_payload_size, "maxPayloadSize") \
V(max_retries, "maxRetries") \
V(max_stateless_resets, "maxStatelessResetsPerHost") \
V(packetwrap, "PacketWrap") \
V(reject_unauthorized, "rejectUnauthorized") \
V(retry_token_expiration, "retryTokenExpiration") \
V(request_peer_certificate, "requestPeerCertificate") \
V(reset_token_secret, "resetTokenSecret") \
V(rx_loss, "rxDiagnosticLoss") \
V(session, "Session") \
V(session_id_ctx, "sessionIDContext") \
V(stream, "Stream") \
V(token_expiration, "tokenExpiration") \
V(token_secret, "tokenSecret") \
V(tx_loss, "txDiagnosticLoss") \
V(udp_receive_buffer_size, "udpReceiveBufferSize") \
V(udp_send_buffer_size, "udpSendBufferSize") \
V(udp_ttl, "udpTTL") \
V(unacknowledged_packet_threshold, "unacknowledgedPacketThreshold") \
V(validate_address, "validateAddress") \
V(verify_hostname_identity, "verifyHostnameIdentity")

// =============================================================================
Expand Down Expand Up @@ -133,6 +157,8 @@ class BindingData final

std::vector<BaseObjectPtr<BaseObject>> packet_freelist;

std::unordered_map<Endpoint*, BaseObjectPtr<BaseObject>> listening_endpoints;

// Purge the packet free list to free up memory.
static void FlushPacketFreelist(
const v8::FunctionCallbackInfo<v8::Value>& args);
Expand Down Expand Up @@ -203,6 +229,26 @@ struct NgHttp3CallbackScope {
static bool in_nghttp3_callback(Environment* env);
};

struct CallbackScopeBase {
Environment* env;
v8::Context::Scope context_scope;
v8::TryCatch try_catch;

explicit CallbackScopeBase(Environment* env);
CallbackScopeBase(const CallbackScopeBase&) = delete;
CallbackScopeBase(CallbackScopeBase&&) = delete;
CallbackScopeBase& operator=(const CallbackScopeBase&) = delete;
CallbackScopeBase& operator=(CallbackScopeBase&&) = delete;
~CallbackScopeBase();
};

template <typename T>
struct CallbackScope final : public CallbackScopeBase {
BaseObjectPtr<T> ref;
explicit CallbackScope(const T* ptr)
: CallbackScopeBase(ptr->env()), ref(ptr) {}
};

} // namespace quic
} // namespace node

Expand Down
17 changes: 12 additions & 5 deletions src/quic/defs.h
Expand Up @@ -90,13 +90,20 @@ uint64_t GetStat(Stats* stats) {
return stats->*member;
}

#define STAT_INCREMENT(Type, name) IncrementStat<Type, &Type::name>(&stats_);
#define STAT_INCREMENT(Type, name) \
IncrementStat<Type, &Type::name>(stats_.Data());
#define STAT_INCREMENT_N(Type, name, amt) \
IncrementStat<Type, &Type::name>(&stats_, amt);
IncrementStat<Type, &Type::name>(stats_.Data(), amt);
#define STAT_RECORD_TIMESTAMP(Type, name) \
RecordTimestampStat<Type, &Type::name>(&stats_);
#define STAT_SET(Type, name, val) SetStat<Type, &Type::name>(&stats_, val);
#define STAT_GET(Type, name) GetStat<Type, &Type::name>(&stats_);
RecordTimestampStat<Type, &Type::name>(stats_.Data());
#define STAT_SET(Type, name, val) \
SetStat<Type, &Type::name>(stats_.Data(), val);
#define STAT_GET(Type, name) GetStat<Type, &Type::name>(stats_.Data());
#define STAT_FIELD(_, name) uint64_t name;
#define STAT_STRUCT(name) \
struct Stats final { \
name##_STATS(STAT_FIELD) \
};

} // namespace quic
} // namespace node

0 comments on commit 76044c4

Please sign in to comment.