quic: refactor QuicSession shared state to use AliasedStruct

PR-URL: https://github.com/nodejs/node/pull/34160
Reviewed-By: Anna Henningsen <anna@addaleax.net>
This commit is contained in:
James M Snell
2020-07-01 16:40:16 -07:00
parent f9c2245fb5
commit 3acdd6aac7
6 changed files with 196 additions and 141 deletions

View File

@@ -39,6 +39,7 @@ const {
validateQuicEndpointOptions,
validateCreateSecureContextOptions,
validateQuicSocketConnectOptions,
QuicSessionSharedState,
} = require('internal/quic/util');
const util = require('util');
const assert = require('internal/assert');
@@ -131,12 +132,6 @@ const {
AF_INET,
AF_INET6,
NGTCP2_DEFAULT_MAX_PKTLEN,
IDX_QUIC_SESSION_STATE_MAX_STREAMS_BIDI,
IDX_QUIC_SESSION_STATE_MAX_STREAMS_UNI,
IDX_QUIC_SESSION_STATE_MAX_DATA_LEFT,
IDX_QUIC_SESSION_STATE_HANDSHAKE_CONFIRMED,
IDX_QUIC_SESSION_STATE_IDLE_TIMEOUT,
IDX_QUIC_SESSION_STATE_BYTES_IN_FLIGHT,
IDX_QUIC_SESSION_STATS_CREATED_AT,
IDX_QUIC_SESSION_STATS_HANDSHAKE_START_AT,
IDX_QUIC_SESSION_STATS_BYTES_RECEIVED,
@@ -605,11 +600,11 @@ function createSecureContext(options, init_cb) {
}
function onNewListener(event) {
toggleListeners(this[kHandle], event, true);
toggleListeners(this[kInternalState].state, event, true);
}
function onRemoveListener(event) {
toggleListeners(this[kHandle], event, false);
toggleListeners(this[kInternalState].state, event, false);
}
function getStats(obj, idx) {
@@ -1651,6 +1646,7 @@ class QuicSession extends EventEmitter {
handshakeContinuationHistogram: undefined,
highWaterMark: undefined,
defaultEncoding: undefined,
state: undefined,
};
constructor(socket, options) {
@@ -1693,6 +1689,7 @@ class QuicSession extends EventEmitter {
this[kHandle] = handle;
if (handle !== undefined) {
handle[owner_symbol] = this;
state.state = new QuicSessionSharedState(handle.state);
state.handshakeAckHistogram = new Histogram(handle.ack);
state.handshakeContinuationHistogram = new Histogram(handle.rate);
} else {
@@ -1849,10 +1846,10 @@ class QuicSession extends EventEmitter {
return false;
}
// Closing allows any existing QuicStream's to complete
// normally but disallows any new QuicStreams from being
// opened. Calls to openStream() will fail, and new streams
// from the peer will be rejected/ignored.
// Closing allows any existing QuicStream's to gracefully
// complete while disallowing any new QuicStreams from being
// opened (in either direction). Calls to openStream() will
// fail, and new streams from the peer will be rejected/ignored.
close(callback) {
const state = this[kInternalState];
if (state.destroyed)
@@ -1921,8 +1918,7 @@ class QuicSession extends EventEmitter {
if (handle !== undefined) {
// Copy the stats for use after destruction
state.stats = new BigInt64Array(handle.stats);
state.idleTimeout =
Boolean(handle.state[IDX_QUIC_SESSION_STATE_IDLE_TIMEOUT]);
state.idleTimeout = this[kInternalState].state.idleTimeout;
// Destroy the underlying QuicSession handle
handle.destroy(state.closeCode, state.closeFamily);
@@ -1950,8 +1946,8 @@ class QuicSession extends EventEmitter {
let bidi = 0;
let uni = 0;
if (this[kHandle]) {
bidi = this[kHandle].state[IDX_QUIC_SESSION_STATE_MAX_STREAMS_BIDI];
uni = this[kHandle].state[IDX_QUIC_SESSION_STATE_MAX_STREAMS_UNI];
bidi = this[kInternalState].state.maxStreamsBidi;
uni = this[kInternalState].state.maxStreamsUni;
}
return { bidi, uni };
}
@@ -1961,15 +1957,15 @@ class QuicSession extends EventEmitter {
}
get maxDataLeft() {
return this[kHandle]?.state[IDX_QUIC_SESSION_STATE_MAX_DATA_LEFT] || 0;
return this[kHandle] ? this[kInternalState].state.maxDataLeft : 0;
}
get bytesInFlight() {
return this[kHandle]?.state[IDX_QUIC_SESSION_STATE_BYTES_IN_FLIGHT] || 0;
return this[kHandle] ? this[kInternalState].state.bytesInFlight : 0;
}
get blockCount() {
return this[kHandle]?.state[IDX_QUIC_SESSION_STATS_BLOCK_COUNT] || 0;
return this[kHandle]?.stats[IDX_QUIC_SESSION_STATS_BLOCK_COUNT] || 0;
}
get authenticated() {
@@ -2003,8 +1999,9 @@ class QuicSession extends EventEmitter {
}
get handshakeConfirmed() {
return Boolean(
this[kHandle]?.state[IDX_QUIC_SESSION_STATE_HANDSHAKE_CONFIRMED]);
return this[kHandle] ?
this[kInternalState].state.handshakeConfirmed :
false;
}
get idleTimeout() {
@@ -2449,14 +2446,16 @@ class QuicClientSession extends QuicSession {
// Listeners may have been added before the handle was created.
// Ensure that we toggle those listeners in the handle state.
if (this.listenerCount('keylog') > 0)
toggleListeners(handle, 'keylog', true);
const internalState = this[kInternalState];
if (this.listenerCount('keylog') > 0) {
toggleListeners(internalState.state, 'keylog', true);
}
if (this.listenerCount('pathValidation') > 0)
toggleListeners(handle, 'pathValidation', true);
toggleListeners(internalState.state, 'pathValidation', true);
if (this.listenerCount('usePreferredAddress') > 0)
toggleListeners(handle, 'usePreferredAddress', true);
toggleListeners(internalState.state, 'usePreferredAddress', true);
this[kMaybeReady](0x2);
}

View File

@@ -15,6 +15,12 @@ const {
},
} = require('internal/errors');
const {
kHandle,
} = require('internal/stream_base_commons');
const endianness = require('os').endianness();
const assert = require('internal/assert');
assert(process.versions.ngtcp2 !== undefined);
@@ -52,11 +58,19 @@ const {
IDX_QUIC_SESSION_MAX_UDP_PAYLOAD_SIZE,
IDX_QUIC_SESSION_CC_ALGO,
IDX_QUIC_SESSION_CONFIG_COUNT,
IDX_QUIC_SESSION_STATE_CERT_ENABLED,
IDX_QUIC_SESSION_STATE_CLIENT_HELLO_ENABLED,
IDX_QUIC_SESSION_STATE_KEYLOG_ENABLED,
IDX_QUIC_SESSION_STATE_PATH_VALIDATED_ENABLED,
IDX_QUIC_SESSION_STATE_USE_PREFERRED_ADDRESS_ENABLED,
IDX_QUICSESSION_STATE_KEYLOG_ENABLED,
IDX_QUICSESSION_STATE_CLIENT_HELLO_ENABLED,
IDX_QUICSESSION_STATE_CERT_ENABLED,
IDX_QUICSESSION_STATE_PATH_VALIDATED_ENABLED,
IDX_QUICSESSION_STATE_USE_PREFERRED_ADDRESS_ENABLED,
IDX_QUICSESSION_STATE_HANDSHAKE_CONFIRMED,
IDX_QUICSESSION_STATE_IDLE_TIMEOUT,
IDX_QUICSESSION_STATE_MAX_STREAMS_BIDI,
IDX_QUICSESSION_STATE_MAX_STREAMS_UNI,
IDX_QUICSESSION_STATE_MAX_DATA_LEFT,
IDX_QUICSESSION_STATE_BYTES_IN_FLIGHT,
IDX_HTTP3_QPACK_MAX_TABLE_CAPACITY,
IDX_HTTP3_QPACK_BLOCKED_STREAMS,
IDX_HTTP3_MAX_HEADER_LIST_SIZE,
@@ -756,29 +770,121 @@ function setTransportParams(config) {
// communicate that a handler has been added for the optional events
// so that the C++ internals know there is an actual listener. The event
// will not be emitted if there is no handler.
function toggleListeners(handle, event, on) {
if (handle === undefined)
function toggleListeners(state, event, on) {
if (state === undefined)
return;
const val = on ? 1 : 0;
switch (event) {
case 'keylog':
handle.state[IDX_QUIC_SESSION_STATE_KEYLOG_ENABLED] = val;
state.keylogEnabled = on;
break;
case 'clientHello':
handle.state[IDX_QUIC_SESSION_STATE_CLIENT_HELLO_ENABLED] = val;
state.clientHelloEnabled = on;
break;
case 'pathValidation':
handle.state[IDX_QUIC_SESSION_STATE_PATH_VALIDATED_ENABLED] = val;
state.pathValidatedEnabled = on;
break;
case 'OCSPRequest':
handle.state[IDX_QUIC_SESSION_STATE_CERT_ENABLED] = val;
state.certEnabled = on;
break;
case 'usePreferredAddress':
handle.state[IDX_QUIC_SESSION_STATE_USE_PREFERRED_ADDRESS_ENABLED] = on;
state.usePreferredAddressEnabled = on;
break;
}
}
// A utility class used to handle reading / modifying shared JS/C++
// state associated with a QuicSession
class QuicSessionSharedState {
constructor(state) {
this[kHandle] = Buffer.from(state);
}
get keylogEnabled() {
return Boolean(this[kHandle]
.readUInt8(IDX_QUICSESSION_STATE_KEYLOG_ENABLED));
}
set keylogEnabled(on) {
this[kHandle]
.writeUInt8(on ? 1 : 0, IDX_QUICSESSION_STATE_KEYLOG_ENABLED);
}
get clientHelloEnabled() {
return Boolean(this[kHandle]
.readUInt8(IDX_QUICSESSION_STATE_CLIENT_HELLO_ENABLED));
}
set clientHelloEnabled(on) {
this[kHandle]
.writeUInt8(on ? 1 : 0, IDX_QUICSESSION_STATE_CLIENT_HELLO_ENABLED);
}
get certEnabled() {
return Boolean(this[kHandle]
.readUInt8(IDX_QUICSESSION_STATE_CERT_ENABLED));
}
set certEnabled(on) {
this[kHandle]
.writeUInt8(on ? 1 : 0, IDX_QUICSESSION_STATE_CERT_ENABLED);
}
get pathValidatedEnabled() {
return Boolean(this[kHandle]
.readUInt8(IDX_QUICSESSION_STATE_PATH_VALIDATED_ENABLED));
}
set pathValidatedEnabled(on) {
this[kHandle]
.writeUInt8(on ? 1 : 0, IDX_QUICSESSION_STATE_PATH_VALIDATED_ENABLED);
}
get usePreferredAddressEnabled() {
return Boolean(this[kHandle]
.readUInt8(IDX_QUICSESSION_STATE_USE_PREFERRED_ADDRESS_ENABLED));
}
set usePreferredAddressEnabled(on) {
this[kHandle]
.writeUInt8(on ? 1 : 0,
IDX_QUICSESSION_STATE_USE_PREFERRED_ADDRESS_ENABLED);
}
get handshakeConfirmed() {
return Boolean(this[kHandle]
.readUInt8(IDX_QUICSESSION_STATE_HANDSHAKE_CONFIRMED));
}
get idleTimeout() {
return Boolean(this[kHandle]
.readUInt8(IDX_QUICSESSION_STATE_IDLE_TIMEOUT));
}
get maxStreamsBidi() {
return Number(endianness === 'BE' ?
this[kHandle].readBigInt64BE(IDX_QUICSESSION_STATE_MAX_STREAMS_BIDI) :
this[kHandle].readBigInt64LE(IDX_QUICSESSION_STATE_MAX_STREAMS_BIDI));
}
get maxStreamsUni() {
return Number(endianness === 'BE' ?
this[kHandle].readBigInt64BE(IDX_QUICSESSION_STATE_MAX_STREAMS_UNI) :
this[kHandle].readBigInt64LE(IDX_QUICSESSION_STATE_MAX_STREAMS_UNI));
}
get maxDataLeft() {
return Number(endianness === 'BE' ?
this[kHandle].readBigInt64BE(IDX_QUICSESSION_STATE_MAX_DATA_LEFT) :
this[kHandle].readBigInt64LE(IDX_QUICSESSION_STATE_MAX_DATA_LEFT));
}
get bytesInFlight() {
return Number(endianness === 'BE' ?
this[kHandle].readBigInt64BE(IDX_QUICSESSION_STATE_BYTES_IN_FLIGHT) :
this[kHandle].readBigInt64LE(IDX_QUICSESSION_STATE_BYTES_IN_FLIGHT));
}
}
module.exports = {
getAllowUnauthorized,
getSocketType,
@@ -796,4 +902,5 @@ module.exports = {
validateQuicEndpointOptions,
validateCreateSecureContextOptions,
validateQuicSocketConnectOptions,
QuicSessionSharedState,
};

View File

@@ -173,17 +173,6 @@ void Initialize(Local<Object> target,
V(IDX_QUIC_SESSION_MAX_ACK_DELAY) \
V(IDX_QUIC_SESSION_CC_ALGO) \
V(IDX_QUIC_SESSION_CONFIG_COUNT) \
V(IDX_QUIC_SESSION_STATE_CERT_ENABLED) \
V(IDX_QUIC_SESSION_STATE_CLIENT_HELLO_ENABLED) \
V(IDX_QUIC_SESSION_STATE_USE_PREFERRED_ADDRESS_ENABLED) \
V(IDX_QUIC_SESSION_STATE_PATH_VALIDATED_ENABLED) \
V(IDX_QUIC_SESSION_STATE_KEYLOG_ENABLED) \
V(IDX_QUIC_SESSION_STATE_MAX_STREAMS_BIDI) \
V(IDX_QUIC_SESSION_STATE_MAX_STREAMS_UNI) \
V(IDX_QUIC_SESSION_STATE_MAX_DATA_LEFT) \
V(IDX_QUIC_SESSION_STATE_BYTES_IN_FLIGHT) \
V(IDX_QUIC_SESSION_STATE_HANDSHAKE_CONFIRMED) \
V(IDX_QUIC_SESSION_STATE_IDLE_TIMEOUT) \
V(MAX_RETRYTOKEN_EXPIRATION) \
V(MIN_RETRYTOKEN_EXPIRATION) \
V(NGTCP2_APP_NOERROR) \
@@ -212,6 +201,11 @@ void Initialize(Local<Object> target,
V(ERR_FAILED_TO_CREATE_SESSION) \
V(UV_EBADF)
#define V(id, _, __) \
NODE_DEFINE_CONSTANT(constants, IDX_QUICSESSION_STATE_##id);
QUICSESSION_SHARED_STATE(V)
#undef V
#define V(name, _, __) \
NODE_DEFINE_CONSTANT(constants, IDX_QUIC_SESSION_STATS_##name);
SESSION_STATS(V)

View File

@@ -105,7 +105,7 @@ ngtcp2_crypto_level QuicCryptoContext::write_crypto_level() const {
// to a keylog file that can be consumed by tools like Wireshark to intercept
// and decrypt QUIC network traffic.
void QuicCryptoContext::Keylog(const char* line) {
if (UNLIKELY(session_->state_[IDX_QUIC_SESSION_STATE_KEYLOG_ENABLED] == 1))
if (UNLIKELY(session_->state_->keylog_enabled))
session_->listener()->OnKeylog(line, strlen(line));
}
@@ -117,7 +117,7 @@ void QuicCryptoContext::OnClientHelloDone() {
[&]() { set_in_client_hello(false); });
// Disable the callback at this point so we don't loop continuously
session_->state_[IDX_QUIC_SESSION_STATE_CLIENT_HELLO_ENABLED] = 0;
session_->state_->client_hello_enabled = 0;
}
// Following a pause in the handshake for OCSP or client hello, we kickstart
@@ -274,14 +274,12 @@ void QuicSession::ExtendMaxStreamsRemoteBidi(uint64_t max_streams) {
void QuicSession::ExtendMaxStreamsUni(uint64_t max_streams) {
Debug(this, "Setting max unidirectional streams to %" PRIu64, max_streams);
state_[IDX_QUIC_SESSION_STATE_MAX_STREAMS_UNI] =
static_cast<double>(max_streams);
state_->max_streams_uni = max_streams;
}
void QuicSession::ExtendMaxStreamsBidi(uint64_t max_streams) {
Debug(this, "Setting max bidirectional streams to %" PRIu64, max_streams);
state_[IDX_QUIC_SESSION_STATE_MAX_STREAMS_BIDI] =
static_cast<double>(max_streams);
state_->max_streams_bidi = max_streams;
}
// Extends the stream-level flow control by the given number of bytes.
@@ -327,7 +325,7 @@ void QuicSession::HandshakeCompleted() {
void QuicSession::HandshakeConfirmed() {
Debug(this, "Handshake is confirmed");
RecordTimestamp(&QuicSessionStats::handshake_confirmed_at);
state_[IDX_QUIC_SESSION_STATE_HANDSHAKE_CONFIRMED] = 1;
state_->handshake_confirmed = 1;
}
bool QuicSession::is_handshake_completed() const {
@@ -346,7 +344,7 @@ void QuicSession::InitApplication() {
// the peer. All existing streams are abandoned and closed.
void QuicSession::OnIdleTimeout() {
if (!is_destroyed()) {
state_[IDX_QUIC_SESSION_STATE_IDLE_TIMEOUT] = 1;
state_->idle_timeout = 1;
Debug(this, "Idle timeout");
Close(QuicSessionListener::SESSION_CLOSE_FLAG_SILENT);
}

View File

@@ -1,5 +1,6 @@
#include "node_quic_session-inl.h" // NOLINT(build/include)
#include "aliased_buffer.h"
#include "aliased_struct-inl.h"
#include "allocated_buffer-inl.h"
#include "debug_utils-inl.h"
#include "env-inl.h"
@@ -919,10 +920,8 @@ void QuicCryptoContext::EnableTrace() {
// when the peer certificate is received, allowing additional tweaks
// and verifications to be performed.
int QuicCryptoContext::OnClientHello() {
if (LIKELY(session_->state_[
IDX_QUIC_SESSION_STATE_CLIENT_HELLO_ENABLED] == 0)) {
if (LIKELY(session_->state_->client_hello_enabled == 0))
return 0;
}
TLSCallbackScope callback_scope(this);
@@ -952,7 +951,7 @@ int QuicCryptoContext::OnClientHello() {
// function that must be called in order for the TLS handshake to
// continue.
int QuicCryptoContext::OnOCSP() {
if (LIKELY(session_->state_[IDX_QUIC_SESSION_STATE_CERT_ENABLED] == 0)) {
if (LIKELY(session_->state_->cert_enabled == 0)) {
Debug(session(), "No OCSPRequest handler registered");
return 1;
}
@@ -991,7 +990,7 @@ void QuicCryptoContext::OnOCSPDone(
[&]() { set_in_ocsp_request(false); });
// Disable the callback at this point so we don't loop continuously
session_->state_[IDX_QUIC_SESSION_STATE_CERT_ENABLED] = 0;
session_->state_->cert_enabled = 0;
if (context) {
int err = crypto::UseSNIContext(ssl_, context);
@@ -1446,7 +1445,7 @@ QuicSession::QuicSession(
idle_(new Timer(socket->env(), [this]() { OnIdleTimeout(); })),
retransmit_(new Timer(socket->env(), [this]() { MaybeTimeout(); })),
dcid_(dcid),
state_(env()->isolate(), IDX_QUIC_SESSION_STATE_COUNT),
state_(env()->isolate()),
quic_state_(socket->quic_state()) {
PushListener(&default_listener_);
set_connection_id_strategy(RandomConnectionIDStrategy);
@@ -1459,13 +1458,10 @@ QuicSession::QuicSession(
options));
application_.reset(SelectApplication(this));
// TODO(@jasnell): For now, the following is a check rather than properly
// handled. Before this code moves out of experimental, this should be
// properly handled.
wrap->DefineOwnProperty(
env()->context(),
env()->state_string(),
state_.GetJSArray(),
state_.GetArrayBuffer(),
PropertyAttribute::ReadOnly).Check();
// TODO(@jasnell): memory accounting
@@ -1814,7 +1810,7 @@ void QuicSession::PathValidation(
// Only emit the callback if there is a handler for the pathValidation
// event on the JavaScript QuicSession object.
if (UNLIKELY(state_[IDX_QUIC_SESSION_STATE_PATH_VALIDATED_ENABLED] == 1)) {
if (UNLIKELY(state_->path_validated_enabled == 1)) {
listener_->OnPathValidation(
res,
reinterpret_cast<const sockaddr*>(path->local.addr),
@@ -2190,14 +2186,12 @@ void QuicSession::IgnorePreferredAddressStrategy(
void QuicSession::UsePreferredAddressStrategy(
QuicSession* session,
const PreferredAddress& preferred_address) {
static constexpr int idx =
IDX_QUIC_SESSION_STATE_USE_PREFERRED_ADDRESS_ENABLED;
int family = session->socket()->local_address().family();
if (preferred_address.Use(family)) {
Debug(session, "Using server preferred address");
// Emit only if the QuicSession has a usePreferredAddress handler
// on the JavaScript side.
if (UNLIKELY(session->state_[idx] == 1)) {
if (UNLIKELY(session->state_->use_preferred_address_enabled == 1)) {
session->listener()->OnUsePreferredAddress(family, preferred_address);
}
} else {
@@ -2550,7 +2544,6 @@ void QuicSession::MemoryInfo(MemoryTracker* tracker) const {
tracker->TrackField("idle", idle_);
tracker->TrackField("retransmit", retransmit_);
tracker->TrackField("streams", streams_);
tracker->TrackField("state", state_);
tracker->TrackFieldWithSize("current_ngtcp2_memory", current_ngtcp2_memory_);
tracker->TrackField("conn_closebuf", conn_closebuf_);
tracker->TrackField("application", application_);
@@ -2697,14 +2690,12 @@ void QuicSession::UpdateRecoveryStats() {
void QuicSession::UpdateDataStats() {
if (is_destroyed())
return;
state_[IDX_QUIC_SESSION_STATE_MAX_DATA_LEFT] =
static_cast<double>(ngtcp2_conn_get_max_data_left(connection()));
state_->max_data_left = ngtcp2_conn_get_max_data_left(connection());
ngtcp2_conn_stat stat;
ngtcp2_conn_get_conn_stat(connection(), &stat);
state_[IDX_QUIC_SESSION_STATE_BYTES_IN_FLIGHT] =
static_cast<double>(stat.bytes_in_flight);
state_->bytes_in_flight = stat.bytes_in_flight;
// The max_bytes_in_flight is a highwater mark that can be used
// in performance analysis operations.
if (stat.bytes_in_flight > GetStat(&QuicSessionStats::max_bytes_in_flight))

View File

@@ -4,6 +4,7 @@
#if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
#include "aliased_buffer.h"
#include "aliased_struct.h"
#include "async_wrap.h"
#include "env.h"
#include "handle_wrap.h"
@@ -141,67 +142,32 @@ enum QuicClientSessionOptions : uint32_t {
QUICCLIENTSESSION_OPTION_RESUME = 0x4
};
#define QUICSESSION_SHARED_STATE(V) \
V(KEYLOG_ENABLED, keylog_enabled, uint8_t) \
V(CLIENT_HELLO_ENABLED, client_hello_enabled, uint8_t) \
V(CERT_ENABLED, cert_enabled, uint8_t) \
V(PATH_VALIDATED_ENABLED, path_validated_enabled, uint8_t) \
V(USE_PREFERRED_ADDRESS_ENABLED, use_preferred_address_enabled, uint8_t) \
V(HANDSHAKE_CONFIRMED, handshake_confirmed, uint8_t) \
V(IDLE_TIMEOUT, idle_timeout, uint8_t) \
V(MAX_STREAMS_BIDI, max_streams_bidi, uint64_t) \
V(MAX_STREAMS_UNI, max_streams_uni, uint64_t) \
V(MAX_DATA_LEFT, max_data_left, uint64_t) \
V(BYTES_IN_FLIGHT, bytes_in_flight, uint64_t)
// The QuicSessionState enums are used with the QuicSession's
// private state_ array. This is exposed to JavaScript via an
// aliased buffer and is used to communicate various types of
// state efficiently across the native/JS boundary.
enum QuicSessionState : int {
// Communicates whether a 'keylog' event listener has been
// registered on the JavaScript QuicSession object. The
// value will be either 1 or 0. When set to 1, the native
// code will emit TLS keylog entries to the JavaScript
// side triggering the 'keylog' event once for each line.
IDX_QUIC_SESSION_STATE_KEYLOG_ENABLED,
// Communicates whether a 'clientHello' event listener has
// been registered on the JavaScript QuicServerSession.
// The value will be either 1 or 0. When set to 1, the
// native code will callout to the JavaScript side causing
// the 'clientHello' event to be emitted. This is only
// used on server QuicSession instances.
IDX_QUIC_SESSION_STATE_CLIENT_HELLO_ENABLED,
// Communicates whether a 'cert' event listener has been
// registered on the JavaScript QuicSession. The value will
// be either 1 or 0. When set to 1, the native code will
// callout to the JavaScript side causing the 'cert' event
// to be emitted.
IDX_QUIC_SESSION_STATE_CERT_ENABLED,
// Communicates whether a 'pathValidation' event listener
// has been registered on the JavaScript QuicSession. The
// value will be either 1 or 0. When set to 1, the native
// code will callout to the JavaScript side causing the
// 'pathValidation' event to be emitted
IDX_QUIC_SESSION_STATE_PATH_VALIDATED_ENABLED,
// Communicates the current max cumulative number of
// bidi and uni streams that may be opened on the session
IDX_QUIC_SESSION_STATE_MAX_STREAMS_BIDI,
IDX_QUIC_SESSION_STATE_MAX_STREAMS_UNI,
// Communicates the current maxinum number of bytes that
// the local endpoint can send in this connection
// (updated immediately after processing sent/received packets)
IDX_QUIC_SESSION_STATE_MAX_DATA_LEFT,
// Communicates the current total number of bytes in flight
IDX_QUIC_SESSION_STATE_BYTES_IN_FLIGHT,
// Communicates whether a 'usePreferredAddress' event listener
// has been registered.
IDX_QUIC_SESSION_STATE_USE_PREFERRED_ADDRESS_ENABLED,
IDX_QUIC_SESSION_STATE_HANDSHAKE_CONFIRMED,
// Communicates whether a session was closed due to idle timeout
IDX_QUIC_SESSION_STATE_IDLE_TIMEOUT,
// Just the number of session state enums for use when
// creating the AliasedBuffer.
IDX_QUIC_SESSION_STATE_COUNT
#define V(_, name, type) type name;
struct QuicSessionState {
QUICSESSION_SHARED_STATE(V)
};
#undef V
#define V(id, name, _) \
IDX_QUICSESSION_STATE_##id = offsetof(QuicSessionState, name),
enum QuicSessionStateFields {
QUICSESSION_SHARED_STATE(V)
IDX_QUICSESSION_STATE_END
};
#undef V
#define SESSION_STATS(V) \
V(CREATED_AT, created_at, "Created At") \
@@ -1163,9 +1129,9 @@ class QuicSession : public AsyncWrap,
private:
static void RandomConnectionIDStrategy(
QuicSession* session,
ngtcp2_cid* cid,
size_t cidlen);
QuicSession* session,
ngtcp2_cid* cid,
size_t cidlen);
// Initialize the QuicSession as a server
void InitServer(
@@ -1219,8 +1185,8 @@ class QuicSession : public AsyncWrap,
inline void HandshakeConfirmed();
void PathValidation(
const ngtcp2_path* path,
ngtcp2_path_validation_result res);
const ngtcp2_path* path,
ngtcp2_path_validation_result res);
bool ReceivePacket(ngtcp2_path* path, const uint8_t* data, ssize_t nread);
@@ -1484,7 +1450,7 @@ class QuicSession : public AsyncWrap,
StreamsMap streams_;
AliasedFloat64Array state_;
AliasedStruct<QuicSessionState> state_;
struct RemoteTransportParamsDebug {
QuicSession* session;