Skip to content
This repository has been archived by the owner on Aug 11, 2020. It is now read-only.

quic: multiple refactors #207

Closed
wants to merge 15 commits into from
Closed
Show file tree
Hide file tree
Changes from all 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
666 changes: 583 additions & 83 deletions doc/api/quic.md

Large diffs are not rendered by default.

70 changes: 59 additions & 11 deletions lib/internal/quic/core.js
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,20 @@ const {
IDX_QUIC_SESSION_STATE_KEYLOG_ENABLED,
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_BYTES_IN_FLIGHT,
IDX_QUIC_SESSION_STATS_CREATED_AT,
IDX_QUIC_SESSION_STATS_HANDSHAKE_START_AT,
IDX_QUIC_SESSION_STATS_BYTES_RECEIVED,
IDX_QUIC_SESSION_STATS_BYTES_SENT,
IDX_QUIC_SESSION_STATS_BIDI_STREAM_COUNT,
IDX_QUIC_SESSION_STATS_UNI_STREAM_COUNT,
IDX_QUIC_SESSION_STATS_STREAMS_IN_COUNT,
IDX_QUIC_SESSION_STATS_STREAMS_OUT_COUNT,
IDX_QUIC_SESSION_STATS_KEYUPDATE_COUNT,
IDX_QUIC_SESSION_STATS_LOSS_RETRANSMIT_COUNT,
IDX_QUIC_SESSION_STATS_ACK_DELAY_RETRANSMIT_COUNT,
IDX_QUIC_SESSION_STATS_MAX_BYTES_IN_FLIGHT,
ERR_INVALID_REMOTE_TRANSPORT_PARAMS,
ERR_INVALID_TLS_SESSION_TICKET,
NGTCP2_PATH_VALIDATION_RESULT_FAILURE,
Expand Down Expand Up @@ -534,8 +548,8 @@ function onStreamError(streamHandle, error) {
// received for the stream. Not all QuicStreams
// will support headers. The headers argument
// here is an Array of name-value pairs.
function onStreamHeaders(headers, kind) {
this[owner_symbol][kHeaders](headers, kind);
function onStreamHeaders(id, headers, kind) {
this[owner_symbol][kHeaders](id, headers, kind);
}

function onSessionSilentClose(statelessReset, code, family) {
Expand Down Expand Up @@ -1491,6 +1505,14 @@ class QuicSession extends EventEmitter {
stream.destroy();
}

[kHeaders](id, headers, kind) {
const stream = this.#streams.get(id);
if (stream === undefined)
return;

stream[kHeaders](headers, kind);
}

[kStreamReset](id, code, finalSize) {
const stream = this.#streams.get(id);
if (stream === undefined)
Expand Down Expand Up @@ -1670,6 +1692,16 @@ class QuicSession extends EventEmitter {
return this.#socket ? this.#socket.address : {};
}

get maxDataLeft() {
return this[kHandle] ?
this[kHandle].state[IDX_QUIC_SESSION_STATE_MAX_DATA_LEFT] : 0;
}

get bytesInFlight() {
return this[kHandle] ?
this[kHandle].state[IDX_QUIC_SESSION_STATE_BYTES_IN_FLIGHT] : 0;
}

get authenticated() {
// Specifically check for null. Undefined means the check has not
// been performed yet, another other value other than null means
Expand Down Expand Up @@ -1745,6 +1777,7 @@ class QuicSession extends EventEmitter {
};
}


get socket() {
return this.#socket;
}
Expand Down Expand Up @@ -1797,50 +1830,65 @@ class QuicSession extends EventEmitter {
get duration() {
const now = process.hrtime.bigint();
const stats = this.#stats || this[kHandle].stats;
return now - stats[0];
return now - stats[IDX_QUIC_SESSION_STATS_CREATED_AT];
}

get handshakeDuration() {
const stats = this.#stats || this[kHandle].stats;
const end =
this.handshakeComplete ?
stats[4] : process.hrtime.bigint();
return end - stats[1];
return end - stats[IDX_QUIC_SESSION_STATS_HANDSHAKE_START_AT];
}

get bytesReceived() {
const stats = this.#stats || this[kHandle].stats;
return stats[8];
return stats[IDX_QUIC_SESSION_STATS_BYTES_RECEIVED];
}

get bytesSent() {
const stats = this.#stats || this[kHandle].stats;
return stats[9];
return stats[IDX_QUIC_SESSION_STATS_BYTES_SENT];
}

get bidiStreamCount() {
const stats = this.#stats || this[kHandle].stats;
return stats[10];
return stats[IDX_QUIC_SESSION_STATS_BIDI_STREAM_COUNT];
}

get uniStreamCount() {
const stats = this.#stats || this[kHandle].stats;
return stats[11];
return stats[IDX_QUIC_SESSION_STATS_UNI_STREAM_COUNT];
}

get maxInFlightBytes() {
const stats = this.#stats || this[kHandle].stats;
return stats[IDX_QUIC_SESSION_STATS_MAX_BYTES_IN_FLIGHT];
}

get lossRetransmitCount() {
const stats = this.#stats || this[kHandle].stats;
return stats[IDX_QUIC_SESSION_STATS_LOSS_RETRANSMIT_COUNT];
}

get ackDelayRetransmitCount() {
const stats = this.#stats || this[kHandle].stats;
return stats[IDX_QUIC_SESSION_STATS_ACK_DELAY_RETRANSMIT_COUNT];
}

get peerInitiatedStreamCount() {
const stats = this.#stats || this[kHandle].stats;
return stats[12];
return stats[IDX_QUIC_SESSION_STATS_STREAMS_IN_COUNT];
}

get selfInitiatedStreamCount() {
const stats = this.#stats || this[kHandle].stats;
return stats[13];
return stats[IDX_QUIC_SESSION_STATS_STREAMS_OUT_COUNT];
}

get keyUpdateCount() {
const stats = this.#stats || this[kHandle].stats;
return stats[14];
return stats[IDX_QUIC_SESSION_STATS_KEYUPDATE_COUNT];
}

get minRTT() {
Expand Down
2 changes: 1 addition & 1 deletion node.gyp
Original file line number Diff line number Diff line change
Expand Up @@ -841,14 +841,14 @@
'src/node_quic_socket.h',
'src/node_quic_stream.h',
'src/node_quic_util.h',
'src/node_quic_util-inl.h',
'src/node_quic_state.h',
'src/node_quic_default_application.h',
'src/node_quic_http3_application.h',
'src/node_quic_crypto.cc',
'src/node_quic_session.cc',
'src/node_quic_socket.cc',
'src/node_quic_stream.cc',
'src/node_quic_util.cc',
'src/node_quic.cc',
'src/node_quic_default_application.cc',
'src/node_quic_http3_application.cc'
Expand Down
13 changes: 13 additions & 0 deletions src/js_udp_wrap.cc
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#include "udp_wrap.h"
#include "async_wrap-inl.h"
#include "node_errors.h"
#include "node_sockaddr-inl.h"

namespace node {

Expand All @@ -27,6 +28,8 @@ class JSUDPWrap final : public UDPWrapBase, public AsyncWrap {
const sockaddr* addr) override;
int GetPeerName(sockaddr* name, int* namelen) override;
int GetSockName(sockaddr* name, int* namelen) override;
SocketAddress* GetPeerName(SocketAddress* addr = nullptr) override;
SocketAddress* GetSockName(SocketAddress* addr = nullptr) override;
int GetSockaddr(sockaddr* name, int* namelen, bool peer);
AsyncWrap* GetAsyncWrap() override { return this; }

Expand Down Expand Up @@ -120,6 +123,16 @@ int JSUDPWrap::GetSockName(sockaddr* name, int* namelen) {
return GetSockaddr(name, namelen, false);
}

SocketAddress* JSUDPWrap::GetPeerName(SocketAddress* addr) {
// TODO(jasnell): Maybe turn this into a real JS-based method.
return SocketAddress::New("127.0.0.1", 1337, AF_INET, addr);
}

SocketAddress* JSUDPWrap::GetSockName(SocketAddress* addr) {
// TODO(jasnell): Maybe turn this into a real JS-based method.
return SocketAddress::New("127.0.0.1", 1337, AF_INET, addr);
}

int JSUDPWrap::GetSockaddr(sockaddr* name, int* namelen, bool peer) {
// TODO(addaleax): Maybe turn this into a real JS-based method.
sockaddr_in addr_in;
Expand Down
32 changes: 31 additions & 1 deletion src/node_quic.cc
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@
#include "node_quic_socket.h"
#include "node_quic_stream.h"
#include "node_quic_state.h"
#include "node_quic_util.h"
#include "node_quic_util-inl.h"
#include "node_sockaddr-inl.h"

#include <memory>
#include <utility>
Expand Down Expand Up @@ -147,6 +148,8 @@ void Initialize(Local<Object> target,
NODE_DEFINE_CONSTANT(constants, IDX_QUIC_SESSION_STATE_KEYLOG_ENABLED);
NODE_DEFINE_CONSTANT(constants, IDX_QUIC_SESSION_STATE_MAX_STREAMS_BIDI);
NODE_DEFINE_CONSTANT(constants, IDX_QUIC_SESSION_STATE_MAX_STREAMS_UNI);
NODE_DEFINE_CONSTANT(constants, IDX_QUIC_SESSION_STATE_MAX_DATA_LEFT);
NODE_DEFINE_CONSTANT(constants, IDX_QUIC_SESSION_STATE_BYTES_IN_FLIGHT);
NODE_DEFINE_CONSTANT(constants, MAX_RETRYTOKEN_EXPIRATION);
NODE_DEFINE_CONSTANT(constants, MIN_RETRYTOKEN_EXPIRATION);
NODE_DEFINE_CONSTANT(constants, NGTCP2_MAX_CIDLEN);
Expand Down Expand Up @@ -184,6 +187,33 @@ void Initialize(Local<Object> target,
NODE_DEFINE_CONSTANT(constants, IDX_QUIC_SESSION_MAX_CRYPTO_BUFFER);
NODE_DEFINE_CONSTANT(constants, IDX_QUIC_SESSION_CONFIG_COUNT);

NODE_DEFINE_CONSTANT(constants, IDX_QUIC_SESSION_STATS_CREATED_AT);
NODE_DEFINE_CONSTANT(constants, IDX_QUIC_SESSION_STATS_HANDSHAKE_START_AT);
NODE_DEFINE_CONSTANT(constants, IDX_QUIC_SESSION_STATS_HANDSHAKE_SEND_AT);
NODE_DEFINE_CONSTANT(constants, IDX_QUIC_SESSION_STATS_HANDSHAKE_CONTINUE_AT);
NODE_DEFINE_CONSTANT(constants,
IDX_QUIC_SESSION_STATS_HANDSHAKE_COMPLETED_AT);
NODE_DEFINE_CONSTANT(constants, IDX_QUIC_SESSION_STATS_HANDSHAKE_ACKED_AT);
NODE_DEFINE_CONSTANT(constants, IDX_QUIC_SESSION_STATS_SENT_AT);
NODE_DEFINE_CONSTANT(constants, IDX_QUIC_SESSION_STATS_RECEIVED_AT);
NODE_DEFINE_CONSTANT(constants, IDX_QUIC_SESSION_STATS_CLOSING_AT);
NODE_DEFINE_CONSTANT(constants, IDX_QUIC_SESSION_STATS_BYTES_RECEIVED);
NODE_DEFINE_CONSTANT(constants, IDX_QUIC_SESSION_STATS_BYTES_SENT);
NODE_DEFINE_CONSTANT(constants, IDX_QUIC_SESSION_STATS_BIDI_STREAM_COUNT);
NODE_DEFINE_CONSTANT(constants, IDX_QUIC_SESSION_STATS_UNI_STREAM_COUNT);
NODE_DEFINE_CONSTANT(constants, IDX_QUIC_SESSION_STATS_STREAMS_IN_COUNT);
NODE_DEFINE_CONSTANT(constants, IDX_QUIC_SESSION_STATS_STREAMS_OUT_COUNT);
NODE_DEFINE_CONSTANT(constants, IDX_QUIC_SESSION_STATS_KEYUPDATE_COUNT);
NODE_DEFINE_CONSTANT(constants, IDX_QUIC_SESSION_STATS_RETRY_COUNT);
NODE_DEFINE_CONSTANT(constants, IDX_QUIC_SESSION_STATS_LOSS_RETRANSMIT_COUNT);
NODE_DEFINE_CONSTANT(constants,
IDX_QUIC_SESSION_STATS_ACK_DELAY_RETRANSMIT_COUNT);
NODE_DEFINE_CONSTANT(constants,
IDX_QUIC_SESSION_STATS_PATH_VALIDATION_SUCCESS_COUNT);
NODE_DEFINE_CONSTANT(constants,
IDX_QUIC_SESSION_STATS_PATH_VALIDATION_FAILURE_COUNT);
NODE_DEFINE_CONSTANT(constants, IDX_QUIC_SESSION_STATS_MAX_BYTES_IN_FLIGHT);

NODE_DEFINE_CONSTANT(constants, IDX_HTTP3_QPACK_MAX_TABLE_CAPACITY);
NODE_DEFINE_CONSTANT(constants, IDX_HTTP3_QPACK_BLOCKED_STREAMS);
NODE_DEFINE_CONSTANT(constants, IDX_HTTP3_MAX_HEADER_LIST_SIZE);
Expand Down
11 changes: 6 additions & 5 deletions src/node_quic_crypto.cc
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
#include "node_crypto.h"
#include "node_crypto_common.h"
#include "node_quic_session-inl.h"
#include "node_quic_util.h"
#include "node_quic_util-inl.h"
#include "node_sockaddr-inl.h"
#include "node_url.h"
#include "string_bytes.h"
#include "v8.h"
Expand Down Expand Up @@ -144,7 +145,7 @@ bool GenerateRetryToken(
ngtcp2_crypto_ctx ctx;
ngtcp2_crypto_ctx_initial(&ctx);

const size_t addrlen = SocketAddress::GetAddressLen(addr);
const size_t addrlen = SocketAddress::GetLength(addr);
size_t ivlen = ngtcp2_crypto_packet_protection_ivlen(&ctx.aead);

uint64_t now = uv_hrtime();
Expand Down Expand Up @@ -203,7 +204,7 @@ bool InvalidRetryToken(
ngtcp2_crypto_ctx_initial(&ctx);

size_t ivlen = ngtcp2_crypto_packet_protection_ivlen(&ctx.aead);
const size_t addrlen = SocketAddress::GetAddressLen(addr);
const size_t addrlen = SocketAddress::GetLength(addr);

if (hd->tokenlen < TOKEN_RAND_DATALEN)
return true;
Expand Down Expand Up @@ -420,7 +421,7 @@ int VerifyHostnameIdentity(
// check. It's possible that the X509_check_ip_asc covers this. If so,
// we can remove this check.

if (SocketAddress::numeric_host(hostname)) {
if (SocketAddress::is_numeric_host(hostname)) {
auto ips = altnames.equal_range("ip");
for (auto ip = ips.first; ip != ips.second; ++ip) {
if (ip->second.compare(hostname) == 0) {
Expand Down Expand Up @@ -638,7 +639,7 @@ void SetHostname(SSL* ssl, const std::string& hostname) {
// TODO(@jasnell): Need to determine if setting localhost
// here is the right thing to do.
if (hostname.length() == 0 ||
SocketAddress::numeric_host(hostname.c_str())) {
SocketAddress::is_numeric_host(hostname.c_str())) {
SSL_set_tlsext_host_name(ssl, "localhost");
} else {
SSL_set_tlsext_host_name(ssl, hostname.c_str());
Expand Down
2 changes: 2 additions & 0 deletions src/node_quic_default_application.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
#include "node_quic_default_application.h"
#include "node_quic_session-inl.h"
#include "node_quic_stream.h"
#include "node_quic_util-inl.h"
#include "node_sockaddr-inl.h"
#include <ngtcp2/ngtcp2.h>

namespace node {
Expand Down
21 changes: 6 additions & 15 deletions src/node_quic_http3_application.cc
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@
#include "node_quic_http3_application.h"
#include "node_quic_session-inl.h"
#include "node_quic_stream.h"
#include "node_quic_util.h"
#include "node_quic_util-inl.h"
#include "node_sockaddr-inl.h"
#include "node_http_common-inl.h"

#include <nghttp3/nghttp3.h>
Expand Down Expand Up @@ -536,7 +537,9 @@ ssize_t Http3Application::H3ReadData(
// available to send but there might be later, so return WOULDBLOCK
// to tell nghttp3 to hold off attempting to serialize any more
// data for this stream until it is resumed.
return count == 0 ? NGHTTP3_ERR_WOULDBLOCK : count;
if (count == 0)
return NGHTTP3_ERR_WOULDBLOCK;
return count;
}

// Outgoing data is retained in memory until it is acknowledged.
Expand All @@ -553,19 +556,7 @@ void Http3Application::H3AckedStreamData(
void Http3Application::H3StreamClose(
int64_t stream_id,
uint64_t app_error_code) {
Environment* env = Session()->env();
Local<Value> argv[] = {
Number::New(env->isolate(), static_cast<double>(stream_id)),
Number::New(env->isolate(), static_cast<double>(app_error_code))
};

// 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_stream_close_function(),
arraysize(argv),
argv);
Session()->Listener()->OnStreamClose(stream_id, app_error_code);
}

QuicStream* Http3Application::FindOrCreateStream(int64_t stream_id) {
Expand Down
2 changes: 1 addition & 1 deletion src/node_quic_http3_application.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ constexpr size_t DEFAULT_MAX_PUSHES = 65535;

using Http3ConnectionPointer = DeleteFnPtr<nghttp3_conn, nghttp3_conn_del>;

class Http3Header : public QuicStream::Header {
class Http3Header : public QuicHeader {
public:
Http3Header(int32_t token, nghttp3_rcbuf* name, nghttp3_rcbuf* value);
Http3Header(Http3Header&& other) noexcept :
Expand Down
6 changes: 3 additions & 3 deletions src/node_quic_session-inl.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,12 +39,12 @@ void QuicSession::SetLastError(QuicError error) {
last_error_ = error;
}

void QuicSession::SetLastError(QuicErrorFamily family, uint64_t code) {
void QuicSession::SetLastError(int32_t family, uint64_t code) {
SetLastError({ family, code });
}

void QuicSession::SetLastError(QuicErrorFamily family, int code) {
SetLastError(family, ngtcp2_err_infer_quic_transport_error_code(code));
void QuicSession::SetLastError(int32_t family, int code) {
SetLastError({ family, code });
}

bool QuicSession::IsInClosingPeriod() {
Expand Down
Loading