Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

quic: more implementation #56328

Closed
wants to merge 7 commits into from
Closed
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
quic: add --experimental-quic cli option, add node:quic module
  • Loading branch information
jasnell committed Jan 3, 2025
commit c7711b10d28f3eb4798e14e55d078bf230905359
3 changes: 3 additions & 0 deletions doc/node.1
Original file line number Diff line number Diff line change
@@ -217,6 +217,9 @@ flag is no longer required as WASI is enabled by default.
.It Fl -experimental-wasm-modules
Enable experimental WebAssembly module support.
.
.It Fl -experimental-quic
Enable the experimental QUIC support.
.
.It Fl -force-context-aware
Disable loading native addons that are not context-aware.
.
3 changes: 2 additions & 1 deletion lib/internal/bootstrap/realm.js
Original file line number Diff line number Diff line change
@@ -131,11 +131,12 @@ const legacyWrapperList = new SafeSet([
const schemelessBlockList = new SafeSet([
'sea',
'sqlite',
'quic',
'test',
'test/reporters',
]);
// Modules that will only be enabled at run time.
const experimentalModuleList = new SafeSet(['sqlite']);
const experimentalModuleList = new SafeSet(['sqlite', 'quic']);

// Set up process.binding() and process._linkedBinding().
{
10 changes: 10 additions & 0 deletions lib/internal/process/pre_execution.js
Original file line number Diff line number Diff line change
@@ -101,6 +101,7 @@ function prepareExecution(options) {
setupNavigator();
setupWarningHandler();
setupSQLite();
setupQuic();
setupWebStorage();
setupWebsocket();
setupEventsource();
@@ -311,6 +312,15 @@ function setupSQLite() {
BuiltinModule.allowRequireByUsers('sqlite');
}

function setupQuic() {
if (!getOptionValue('--experimental-quic')) {
return;
}

const { BuiltinModule } = require('internal/bootstrap/realm');
BuiltinModule.allowRequireByUsers('quic');
}

function setupWebStorage() {
if (getEmbedderOptions().noBrowserGlobals ||
!getOptionValue('--experimental-webstorage')) {
20 changes: 9 additions & 11 deletions lib/internal/quic/quic.js
Original file line number Diff line number Diff line change
@@ -108,7 +108,6 @@ const {
kBlocked,
kDatagram,
kDatagramStatus,
kError,
kFinishClose,
kHandshake,
kHeaders,
@@ -591,7 +590,7 @@ setCallbacks({
},
onStreamClose(error) {
// Called when the stream C++ handle has been closed.
debug('stream closed callback', this[kOwner], error)
debug('stream closed callback', this[kOwner], error);
this[kOwner].destroy(error);
},
onStreamReset(error) {
@@ -1410,6 +1409,10 @@ class QuicSession {
async [SymbolAsyncDispose]() { await this.close(); }
}

// The QuicEndpoint represents a local UDP port binding. It can act as both a
// server for receiving peer sessions, or a client for initiating them. The
// local UDP port will be lazily bound only when connect() or listen() are
// called.
class QuicEndpoint {
/**
* The local socket address on which the endpoint is listening (lazily created)
@@ -1696,7 +1699,10 @@ class QuicEndpoint {
debug('endpoint created');
}

/** @type {QuicEndpointStats} */
/**
* Statistics collected while the endpoint is operational.
* @type {QuicEndpointStats}
*/
get stats() { return this.#stats; }

/** @type {QuicEndpointState} */
@@ -2034,14 +2040,6 @@ class QuicEndpoint {
return this.closed;
}

ref() {
if (this.#handle !== undefined) this.#handle.ref(true);
}

unref() {
if (this.#handle !== undefined) this.#handle.ref(false);
}

#maybeGetCloseError(context, status) {
switch (context) {
case kCloseContextClose: {
2 changes: 0 additions & 2 deletions lib/internal/quic/symbols.js
Original file line number Diff line number Diff line change
@@ -19,7 +19,6 @@ const {
const kBlocked = Symbol('kBlocked');
const kDatagram = Symbol('kDatagram');
const kDatagramStatus = Symbol('kDatagramStatus');
const kError = Symbol('kError');
const kFinishClose = Symbol('kFinishClose');
const kHandshake = Symbol('kHandshake');
const kHeaders = Symbol('kHeaders');
@@ -39,7 +38,6 @@ module.exports = {
kBlocked,
kDatagram,
kDatagramStatus,
kError,
kFinishClose,
kHandshake,
kHeaders,
13 changes: 13 additions & 0 deletions lib/quic.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
'use strict';

const {
QuicEndpoint,
QuicEndpointState,
QuicEndpointStats,
} = require('internal/quic/quic');

module.exports = {
QuicEndpoint,
QuicEndpointState,
QuicEndpointStats,
};
4 changes: 4 additions & 0 deletions src/node_options.cc
Original file line number Diff line number Diff line change
@@ -436,6 +436,10 @@ EnvironmentOptionsParser::EnvironmentOptionsParser() {
&EnvironmentOptions::experimental_sqlite,
kAllowedInEnvvar,
true);
AddOption("--experimental-quic",
"experimental QUIC API",
&EnvironmentOptions::experimental_quic,
kAllowedInEnvvar);
AddOption("--experimental-webstorage",
"experimental Web Storage API",
&EnvironmentOptions::experimental_webstorage,
1 change: 1 addition & 0 deletions src/node_options.h
Original file line number Diff line number Diff line change
@@ -126,6 +126,7 @@ class EnvironmentOptions : public Options {
bool experimental_websocket = true;
bool experimental_sqlite = true;
bool experimental_webstorage = false;
bool experimental_quic = false;
std::string localstorage_file;
bool experimental_global_navigator = true;
bool experimental_global_web_crypto = true;
9 changes: 6 additions & 3 deletions src/quic/data.cc
Original file line number Diff line number Diff line change
@@ -257,9 +257,12 @@ std::optional<int> QuicError::crypto_error() const {
}

MaybeLocal<Value> QuicError::ToV8Value(Environment* env) const {
if ((type() == QuicError::Type::TRANSPORT && code() == NGTCP2_NO_ERROR) ||
(type() == QuicError::Type::APPLICATION && code() == NGTCP2_APP_NOERROR) ||
(type() == QuicError::Type::APPLICATION && code() == NGHTTP3_H3_NO_ERROR)) {
if ((type() == QuicError::Type::TRANSPORT &&
code() == NGTCP2_NO_ERROR) ||
(type() == QuicError::Type::APPLICATION &&
code() == NGTCP2_APP_NOERROR) ||
(type() == QuicError::Type::APPLICATION &&
code() == NGHTTP3_H3_NO_ERROR)) {
return Undefined(env->isolate());
}