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: multiple cleanups #34137

Closed
wants to merge 8 commits into from
Closed
Show file tree
Hide file tree
Changes from 6 commits
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
68 changes: 21 additions & 47 deletions lib/internal/quic/core.js
Original file line number Diff line number Diff line change
Expand Up @@ -247,19 +247,11 @@ let warnedVerifyHostnameIdentity = false;

assert(process.versions.ngtcp2 !== undefined);

// Called by the C++ internals when the socket is closed.
// When this is called, the only thing left to do is destroy
// the QuicSocket instance.
function onSocketClose() {
this[owner_symbol].destroy();
}

// Called by the C++ internals when an error occurs on the socket.
// When this is called, the only thing left to do is destroy
// the QuicSocket instance with an error.
// TODO(@jasnell): Should consolidate this with onSocketClose
function onSocketError(err) {
this[owner_symbol].destroy(errnoException(err));
// Called by the C++ internals when the QuicSocket is closed with
// or without an error. The only thing left to do is destroy the
// QuicSocket instance.
function onSocketClose(err) {
this[owner_symbol].destroy(err != null ? errnoException(err) : undefined);
}

// Called by the C++ internals when the server busy state of
Expand All @@ -279,23 +271,24 @@ function onSessionReady(handle) {
process.nextTick(emit.bind(socket, 'session', session));
}

// During an immediate close, all currently open QuicStreams are
// abruptly closed. If they are still writable or readable, an abort
// event will be emitted, and RESET_STREAM and STOP_SENDING frames
// will be transmitted as necessary. Once streams have been
// shutdown, a CONNECTION_CLOSE frame will be sent and the
// session will enter the closing period, after which it will
// be destroyed either when the idle timeout expires, the
// QuicSession is silently closed, or destroy is called.
function onSessionClose(code, family) {
// Called when the session needs to be closed and destroyed.
// If silent is true, then the session is going to be closed
// immediately without sending any CONNECTION_CLOSE to the
// connected peer. If silent is false, a CONNECTION_CLOSE
// is going to be sent to the peer.
function onSessionClose(code, family, silent, statelessReset) {
if (this[owner_symbol]) {
this[owner_symbol][kClose](family, code);
} else {
// When there's no owner_symbol, the session was closed
// before it could be fully set up. Just immediately
// close everything down on the native side.
this.destroy(code, family);
if (silent) {
this[owner_symbol][kDestroy](statelessReset, family, code);
} else {
this[owner_symbol][kClose](family, code);
}
return;
}
// When there's no owner_symbol, the session was closed
// before it could be fully set up. Just immediately
// close everything down on the native side.
this.destroy(code, family);
}

// Called by the C++ internals when a QuicSession has been destroyed.
Expand Down Expand Up @@ -481,14 +474,6 @@ function onSessionQlog(str) {
}
}

// Called when an error occurs in a QuicSession. When this happens,
// the only remedy is to destroy the session.
function onSessionError(error) {
if (this[owner_symbol]) {
this[owner_symbol].destroy(error);
}
}

// Called by the C++ internals when a client QuicSession receives
// a version negotiation response from the server.
function onSessionVersionNegotiation(
Expand Down Expand Up @@ -562,14 +547,6 @@ function onStreamHeaders(id, headers, kind, push_id) {
this[owner_symbol][kHeaders](id, headers, kind, push_id);
}

// During a silent close, all currently open QuicStreams are abruptly
// closed. If they are still writable or readable, an abort event will be
// emitted, otherwise the stream is just destroyed. No RESET_STREAM or
// STOP_SENDING is transmitted to the peer.
function onSessionSilentClose(statelessReset, code, family) {
this[owner_symbol][kDestroy](statelessReset, family, code);
}

// When a stream is flow control blocked, causes a blocked event
// to be emitted. This is a purely informational event.
function onStreamBlocked() {
Expand All @@ -579,18 +556,15 @@ function onStreamBlocked() {
// Register the callbacks with the QUIC internal binding.
setCallbacks({
onSocketClose,
onSocketError,
onSocketServerBusy,
onSessionReady,
onSessionCert,
onSessionClientHello,
onSessionClose,
onSessionDestroyed,
onSessionError,
onSessionHandshake,
onSessionKeylog,
onSessionQlog,
onSessionSilentClose,
onSessionStatus,
onSessionTicket,
onSessionVersionNegotiation,
Expand Down
3 changes: 0 additions & 3 deletions src/env.h
Original file line number Diff line number Diff line change
Expand Up @@ -450,20 +450,17 @@ constexpr size_t kFsStatsBufferLength =
#if defined(NODE_EXPERIMENTAL_QUIC) && NODE_EXPERIMENTAL_QUIC
# define QUIC_ENVIRONMENT_STRONG_PERSISTENT_VALUES(V) \
V(quic_on_socket_close_function, v8::Function) \
V(quic_on_socket_error_function, v8::Function) \
V(quic_on_socket_server_busy_function, v8::Function) \
V(quic_on_session_cert_function, v8::Function) \
V(quic_on_session_client_hello_function, v8::Function) \
V(quic_on_session_close_function, v8::Function) \
V(quic_on_session_destroyed_function, v8::Function) \
V(quic_on_session_error_function, v8::Function) \
V(quic_on_session_handshake_function, v8::Function) \
V(quic_on_session_keylog_function, v8::Function) \
V(quic_on_session_path_validation_function, v8::Function) \
V(quic_on_session_use_preferred_address_function, v8::Function) \
V(quic_on_session_qlog_function, v8::Function) \
V(quic_on_session_ready_function, v8::Function) \
V(quic_on_session_silent_close_function, v8::Function) \
V(quic_on_session_status_function, v8::Function) \
V(quic_on_session_ticket_function, v8::Function) \
V(quic_on_session_version_negotiation_function, v8::Function) \
Expand Down
22 changes: 18 additions & 4 deletions src/quic/node_quic.cc
Original file line number Diff line number Diff line change
Expand Up @@ -55,19 +55,16 @@ void QuicSetCallbacks(const FunctionCallbackInfo<Value>& args) {
} while (0)

SETFUNCTION("onSocketClose", socket_close);
SETFUNCTION("onSocketError", socket_error);
SETFUNCTION("onSessionReady", session_ready);
SETFUNCTION("onSessionCert", session_cert);
SETFUNCTION("onSessionClientHello", session_client_hello);
SETFUNCTION("onSessionClose", session_close);
SETFUNCTION("onSessionDestroyed", session_destroyed);
SETFUNCTION("onSessionError", session_error);
SETFUNCTION("onSessionHandshake", session_handshake);
SETFUNCTION("onSessionKeylog", session_keylog);
SETFUNCTION("onSessionUsePreferredAddress", session_use_preferred_address);
SETFUNCTION("onSessionPathValidation", session_path_validation);
SETFUNCTION("onSessionQlog", session_qlog);
SETFUNCTION("onSessionSilentClose", session_silent_close);
SETFUNCTION("onSessionStatus", session_status);
SETFUNCTION("onSessionTicket", session_ticket);
SETFUNCTION("onSessionVersionNegotiation", session_version_negotiation);
Expand Down Expand Up @@ -192,7 +189,6 @@ void Initialize(Local<Object> target,
V(NGTCP2_APP_NOERROR) \
V(NGTCP2_PATH_VALIDATION_RESULT_FAILURE) \
V(NGTCP2_PATH_VALIDATION_RESULT_SUCCESS) \
V(NGTCP2_DEFAULT_MAX_PKTLEN) \
V(NGTCP2_CC_ALGO_CUBIC) \
V(NGTCP2_CC_ALGO_RENO) \
V(QUIC_ERROR_APPLICATION) \
Expand Down Expand Up @@ -235,11 +231,29 @@ void Initialize(Local<Object> target,
QUIC_CONSTANTS(V)
#undef V

NODE_DEFINE_CONSTANT(constants, NGTCP2_DEFAULT_MAX_PKTLEN);
NODE_DEFINE_CONSTANT(constants, NGTCP2_PROTO_VER);
NODE_DEFINE_CONSTANT(constants, NGTCP2_DEFAULT_MAX_ACK_DELAY);
NODE_DEFINE_CONSTANT(constants, NGTCP2_MAX_CIDLEN);
NODE_DEFINE_CONSTANT(constants, NGTCP2_MIN_CIDLEN);

NODE_DEFINE_CONSTANT(constants, NGTCP2_NO_ERROR);
NODE_DEFINE_CONSTANT(constants, NGTCP2_INTERNAL_ERROR);
NODE_DEFINE_CONSTANT(constants, NGTCP2_CONNECTION_REFUSED);
NODE_DEFINE_CONSTANT(constants, NGTCP2_FLOW_CONTROL_ERROR);
NODE_DEFINE_CONSTANT(constants, NGTCP2_STREAM_LIMIT_ERROR);
NODE_DEFINE_CONSTANT(constants, NGTCP2_STREAM_STATE_ERROR);
NODE_DEFINE_CONSTANT(constants, NGTCP2_FINAL_SIZE_ERROR);
NODE_DEFINE_CONSTANT(constants, NGTCP2_FRAME_ENCODING_ERROR);
NODE_DEFINE_CONSTANT(constants, NGTCP2_TRANSPORT_PARAMETER_ERROR);
NODE_DEFINE_CONSTANT(constants, NGTCP2_CONNECTION_ID_LIMIT_ERROR);
NODE_DEFINE_CONSTANT(constants, NGTCP2_PROTOCOL_VIOLATION);
NODE_DEFINE_CONSTANT(constants, NGTCP2_INVALID_TOKEN);
NODE_DEFINE_CONSTANT(constants, NGTCP2_APPLICATION_ERROR);
NODE_DEFINE_CONSTANT(constants, NGTCP2_CRYPTO_BUFFER_EXCEEDED);
NODE_DEFINE_CONSTANT(constants, NGTCP2_KEY_UPDATE_ERROR);
NODE_DEFINE_CONSTANT(constants, NGTCP2_CRYPTO_ERROR);

NODE_DEFINE_CONSTANT(constants, AF_INET);
NODE_DEFINE_CONSTANT(constants, AF_INET6);
NODE_DEFINE_STRING_CONSTANT(constants,
Expand Down
48 changes: 15 additions & 33 deletions src/quic/node_quic_session.cc
Original file line number Diff line number Diff line change
Expand Up @@ -293,9 +293,9 @@ void QuicSessionListener::OnSessionDestroyed() {
previous_listener_->OnSessionDestroyed();
}

void QuicSessionListener::OnSessionClose(QuicError error) {
void QuicSessionListener::OnSessionClose(QuicError error, int flags) {
if (previous_listener_ != nullptr)
previous_listener_->OnSessionClose(error);
previous_listener_->OnSessionClose(error, flags);
}

void QuicSessionListener::OnStreamReady(BaseObjectPtr<QuicStream> stream) {
Expand Down Expand Up @@ -328,13 +328,6 @@ void QuicSessionListener::OnStreamBlocked(int64_t stream_id) {
}
}

void QuicSessionListener::OnSessionSilentClose(
bool stateless_reset,
QuicError error) {
if (previous_listener_ != nullptr)
previous_listener_->OnSessionSilentClose(stateless_reset, error);
}

void QuicSessionListener::OnUsePreferredAddress(
int family,
const PreferredAddress& preferred_address) {
Expand Down Expand Up @@ -525,14 +518,20 @@ void JSQuicSessionListener::OnSessionDestroyed() {
env->quic_on_session_destroyed_function(), 0, nullptr);
}

void JSQuicSessionListener::OnSessionClose(QuicError error) {
void JSQuicSessionListener::OnSessionClose(QuicError error, int flags) {
Environment* env = session()->env();
HandleScope scope(env->isolate());
Context::Scope context_scope(env->context());

Local<Value> argv[] = {
Number::New(env->isolate(), static_cast<double>(error.code)),
Integer::New(env->isolate(), error.family)
Integer::New(env->isolate(), error.family),
flags & SESSION_CLOSE_FLAG_SILENT
? v8::True(env->isolate())
: v8::False(env->isolate()),
flags & SESSION_CLOSE_FLAG_STATELESS_RESET
? v8::True(env->isolate())
: v8::False(env->isolate())
};

// Grab a shared pointer to this to prevent the QuicSession
Expand Down Expand Up @@ -664,26 +663,6 @@ void JSQuicSessionListener::OnSessionTicket(int size, SSL_SESSION* sess) {
arraysize(argv), argv);
}

void JSQuicSessionListener::OnSessionSilentClose(
bool stateless_reset,
QuicError error) {
Environment* env = session()->env();
HandleScope scope(env->isolate());
Context::Scope context_scope(env->context());

Local<Value> argv[] = {
stateless_reset ? v8::True(env->isolate()) : v8::False(env->isolate()),
Number::New(env->isolate(), static_cast<double>(error.code)),
Integer::New(env->isolate(), error.family)
};

// Grab a shared pointer to this to prevent the QuicSession
// from being freed while the MakeCallback is running.
BaseObjectPtr<QuicSession> ptr(session());
session()->MakeCallback(
env->quic_on_session_silent_close_function(), arraysize(argv), argv);
}

void JSQuicSessionListener::OnUsePreferredAddress(
int family,
const PreferredAddress& preferred_address) {
Expand Down Expand Up @@ -2323,7 +2302,7 @@ bool QuicSession::set_socket(QuicSocket* socket, bool nat_rebinding) {
socket->ReceiveStart();

// Step 4: Update ngtcp2
auto& local_address = socket->local_address();
auto local_address = socket->local_address();
if (nat_rebinding) {
ngtcp2_addr addr;
ngtcp2_addr_init(
Expand Down Expand Up @@ -2377,7 +2356,10 @@ void QuicSession::SilentClose() {
err.code,
is_stateless_reset() ? "yes" : "no");

listener()->OnSessionSilentClose(is_stateless_reset(), err);
int flags = QuicSessionListener::SESSION_CLOSE_FLAG_SILENT;
if (is_stateless_reset())
flags |= QuicSessionListener::SESSION_CLOSE_FLAG_STATELESS_RESET;
listener()->OnSessionClose(err, flags);
}
// Begin connection close by serializing the CONNECTION_CLOSE packet.
// There are two variants: one to serialize an application close, the
Expand Down
18 changes: 12 additions & 6 deletions src/quic/node_quic_session.h
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,12 @@ struct QuicSessionStatsTraits {

class QuicSessionListener {
public:
enum SessionCloseFlags {
SESSION_CLOSE_FLAG_NONE,
SESSION_CLOSE_FLAG_SILENT,
SESSION_CLOSE_FLAG_STATELESS_RESET
};

virtual ~QuicSessionListener();

virtual void OnKeylog(const char* str, size_t size);
Expand All @@ -280,7 +286,9 @@ class QuicSessionListener {
int64_t stream_id,
uint64_t app_error_code);
virtual void OnSessionDestroyed();
virtual void OnSessionClose(QuicError error);
virtual void OnSessionClose(
QuicError error,
int flags = SESSION_CLOSE_FLAG_NONE);
virtual void OnStreamReady(BaseObjectPtr<QuicStream> stream);
virtual void OnHandshakeCompleted();
virtual void OnPathValidation(
Expand All @@ -291,9 +299,6 @@ class QuicSessionListener {
int family,
const PreferredAddress& preferred_address);
virtual void OnSessionTicket(int size, SSL_SESSION* session);
virtual void OnSessionSilentClose(
bool stateless_reset,
QuicError error);
virtual void OnStreamBlocked(int64_t stream_id);
virtual void OnVersionNegotiation(
uint32_t supported_version,
Expand Down Expand Up @@ -329,15 +334,16 @@ class JSQuicSessionListener : public QuicSessionListener {
int64_t stream_id,
uint64_t app_error_code) override;
void OnSessionDestroyed() override;
void OnSessionClose(QuicError error) override;
void OnSessionClose(
QuicError error,
int flags = SESSION_CLOSE_FLAG_NONE) override;
void OnStreamReady(BaseObjectPtr<QuicStream> stream) override;
void OnHandshakeCompleted() override;
void OnPathValidation(
ngtcp2_path_validation_result res,
const sockaddr* local,
const sockaddr* remote) override;
void OnSessionTicket(int size, SSL_SESSION* session) override;
void OnSessionSilentClose(bool stateless_reset, QuicError error) override;
void OnUsePreferredAddress(
int family,
const PreferredAddress& preferred_address) override;
Expand Down
8 changes: 2 additions & 6 deletions src/quic/node_quic_socket-inl.h
Original file line number Diff line number Diff line change
Expand Up @@ -79,8 +79,8 @@ void QuicSocket::AssociateStatelessResetToken(
token_map_[token] = session;
}

const SocketAddress& QuicSocket::local_address() {
CHECK(preferred_endpoint_);
SocketAddress QuicSocket::local_address() const {
DCHECK(preferred_endpoint_);
return preferred_endpoint_->local_address();
}

Expand Down Expand Up @@ -221,10 +221,6 @@ void QuicSocket::AddEndpoint(
endpoint_->ReceiveStart();
}

void QuicSocket::SessionReady(BaseObjectPtr<QuicSession> session) {
listener_->OnSessionReady(session);
}

} // namespace quic
} // namespace node

Expand Down
Loading