Skip to content

Commit 86e67aa

Browse files
committed
quic: updates to implement for h3-29
PR-URL: #34033 Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Jiawen Geng <technicalcute@gmail.com> Reviewed-By: Daniel Bevenius <daniel.bevenius@gmail.com>
1 parent ec7ad1d commit 86e67aa

24 files changed

+227
-337
lines changed

doc/api/quic.md

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1539,9 +1539,11 @@ added: REPLACEME
15391539
`object.passphrase` if provided, or `options.passphrase` if it is not.
15401540
* `activeConnectionIdLimit` {number} Must be a value between `2` and `8`
15411541
(inclusive). Default: `2`.
1542+
* `congestionAlgorithm` {string} Must be either `'reno'` or `'cubic'`.
1543+
**Default**: `'reno'`.
15421544
* `maxAckDelay` {number}
15431545
* `maxData` {number}
1544-
* `maxPacketSize` {number}
1546+
* `maxUdpPayloadSize` {number}
15451547
* `maxStreamDataBidiLocal` {number}
15461548
* `maxStreamDataBidiRemote` {number}
15471549
* `maxStreamDataUni` {number}
@@ -1706,9 +1708,11 @@ added: REPLACEME
17061708
`object.passphrase` is optional. Encrypted keys will be decrypted with
17071709
`object.passphrase` if provided, or `options.passphrase` if it is not.
17081710
* `activeConnectionIdLimit` {number}
1711+
* `congestionAlgorithm` {string} Must be either `'reno'` or `'cubic'`.
1712+
**Default**: `'reno'`.
17091713
* `maxAckDelay` {number}
17101714
* `maxData` {number}
1711-
* `maxPacketSize` {number}
1715+
* `maxUdpPayloadSize` {number}
17121716
* `maxStreamsBidi` {number}
17131717
* `maxStreamsUni` {number}
17141718
* `maxStreamDataBidiLocal` {number}

lib/internal/quic/core.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ const {
130130
constants: {
131131
AF_INET,
132132
AF_INET6,
133-
IDX_QUIC_SESSION_MAX_PACKET_SIZE_DEFAULT,
133+
NGTCP2_DEFAULT_MAX_PKTLEN,
134134
IDX_QUIC_SESSION_STATE_MAX_STREAMS_BIDI,
135135
IDX_QUIC_SESSION_STATE_MAX_STREAMS_UNI,
136136
IDX_QUIC_SESSION_STATE_MAX_DATA_LEFT,
@@ -1633,7 +1633,7 @@ class QuicSession extends EventEmitter {
16331633
#earlyData = false;
16341634
#handshakeComplete = false;
16351635
#idleTimeout = false;
1636-
#maxPacketLength = IDX_QUIC_SESSION_MAX_PACKET_SIZE_DEFAULT;
1636+
#maxPacketLength = NGTCP2_DEFAULT_MAX_PKTLEN;
16371637
#servername = undefined;
16381638
#socket = undefined;
16391639
#statelessReset = false;

lib/internal/quic/util.js

Lines changed: 37 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ const {
3535
constants: {
3636
AF_INET,
3737
AF_INET6,
38-
NGTCP2_ALPN_H3,
38+
NGHTTP3_ALPN_H3,
3939
DEFAULT_RETRYTOKEN_EXPIRATION,
4040
DEFAULT_MAX_CONNECTIONS,
4141
DEFAULT_MAX_CONNECTIONS_PER_HOST,
@@ -49,7 +49,8 @@ const {
4949
IDX_QUIC_SESSION_MAX_STREAMS_UNI,
5050
IDX_QUIC_SESSION_MAX_IDLE_TIMEOUT,
5151
IDX_QUIC_SESSION_MAX_ACK_DELAY,
52-
IDX_QUIC_SESSION_MAX_PACKET_SIZE,
52+
IDX_QUIC_SESSION_MAX_UDP_PAYLOAD_SIZE,
53+
IDX_QUIC_SESSION_CC_ALGO,
5354
IDX_QUIC_SESSION_CONFIG_COUNT,
5455
IDX_QUIC_SESSION_STATE_CERT_ENABLED,
5556
IDX_QUIC_SESSION_STATE_CLIENT_HELLO_ENABLED,
@@ -68,6 +69,8 @@ const {
6869
NGTCP2_NO_ERROR,
6970
NGTCP2_MAX_CIDLEN,
7071
NGTCP2_MIN_CIDLEN,
72+
NGTCP2_CC_ALGO_CUBIC,
73+
NGTCP2_CC_ALGO_RENO,
7174
QUIC_PREFERRED_ADDRESS_IGNORE,
7275
QUIC_PREFERRED_ADDRESS_USE,
7376
QUIC_ERROR_APPLICATION,
@@ -167,11 +170,12 @@ function validateTransportParams(params) {
167170
maxStreamsBidi,
168171
maxStreamsUni,
169172
idleTimeout,
170-
maxPacketSize,
173+
maxUdpPayloadSize,
171174
maxAckDelay,
172175
preferredAddress,
173176
rejectUnauthorized,
174177
requestCert,
178+
congestionAlgorithm = 'reno',
175179
h3: {
176180
qpackMaxTableCapacity,
177181
qpackBlockedStreams,
@@ -231,10 +235,10 @@ function validateTransportParams(params) {
231235
'options.idleTimeout',
232236
/* min */ 0);
233237
}
234-
if (maxPacketSize !== undefined) {
238+
if (maxUdpPayloadSize !== undefined) {
235239
validateInteger(
236-
maxPacketSize,
237-
'options.maxPacketSize',
240+
maxUdpPayloadSize,
241+
'options.maxUdpPayloadSize',
238242
/* min */ 0);
239243
}
240244
if (maxAckDelay !== undefined) {
@@ -279,6 +283,23 @@ function validateTransportParams(params) {
279283
'options.h3.maxHeaderLength',
280284
/* min */ 0);
281285
}
286+
let ccAlgo = NGTCP2_CC_ALGO_RENO;
287+
if (congestionAlgorithm !== undefined) {
288+
validateString(congestionAlgorithm, 'options.conjestionAlgorithm');
289+
switch (congestionAlgorithm) {
290+
case 'reno':
291+
// This is the default
292+
break;
293+
case 'cubic':
294+
ccAlgo = NGTCP2_CC_ALGO_CUBIC;
295+
break;
296+
default:
297+
throw new ERR_INVALID_ARG_VALUE(
298+
'options.congestionAlgorithm',
299+
congestionAlgorithm,
300+
'is not supported');
301+
}
302+
}
282303

283304
validatePreferredAddress(preferredAddress);
284305

@@ -291,11 +312,12 @@ function validateTransportParams(params) {
291312
maxStreamsBidi,
292313
maxStreamsUni,
293314
idleTimeout,
294-
maxPacketSize,
315+
maxUdpPayloadSize,
295316
maxAckDelay,
296317
preferredAddress,
297318
rejectUnauthorized,
298319
requestCert,
320+
congestionAlgorithm: ccAlgo,
299321
h3: {
300322
qpackMaxTableCapacity,
301323
qpackBlockedStreams,
@@ -549,7 +571,7 @@ function validateQuicSocketOptions(options = {}) {
549571
function validateQuicSocketListenOptions(options = {}) {
550572
validateObject(options);
551573
const {
552-
alpn = NGTCP2_ALPN_H3,
574+
alpn = NGHTTP3_ALPN_H3,
553575
defaultEncoding,
554576
highWaterMark,
555577
requestCert,
@@ -656,8 +678,9 @@ function setTransportParams(config) {
656678
maxStreamsBidi,
657679
maxStreamsUni,
658680
idleTimeout,
659-
maxPacketSize,
681+
maxUdpPayloadSize,
660682
maxAckDelay,
683+
congestionAlgorithm,
661684
h3: {
662685
qpackMaxTableCapacity,
663686
qpackBlockedStreams,
@@ -698,8 +721,11 @@ function setTransportParams(config) {
698721
maxAckDelay,
699722
IDX_QUIC_SESSION_MAX_ACK_DELAY) |
700723
setConfigField(sessionConfig,
701-
maxPacketSize,
702-
IDX_QUIC_SESSION_MAX_PACKET_SIZE);
724+
maxUdpPayloadSize,
725+
IDX_QUIC_SESSION_MAX_UDP_PAYLOAD_SIZE) |
726+
setConfigField(sessionConfig,
727+
congestionAlgorithm,
728+
IDX_QUIC_SESSION_CC_ALGO);
703729

704730
sessionConfig[IDX_QUIC_SESSION_CONFIG_COUNT] = flags;
705731

src/env.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -335,7 +335,7 @@ constexpr size_t kFsStatsBufferLength =
335335
V(psk_string, "psk") \
336336
V(pubkey_string, "pubkey") \
337337
V(query_string, "query") \
338-
V(quic_alpn_string, "h3-27") \
338+
V(http3_alpn_string, "h3-29") \
339339
V(rate_string, "rate") \
340340
V(raw_string, "raw") \
341341
V(read_host_object_string, "_readHostObject") \

src/quic/node_quic.cc

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include "node_quic_state.h"
1313
#include "node_quic_util-inl.h"
1414
#include "node_sockaddr-inl.h"
15+
#include "nghttp3/nghttp3.h"
1516

1617
#include <memory>
1718
#include <utility>
@@ -169,10 +170,11 @@ void Initialize(Local<Object> target,
169170
V(IDX_QUIC_SESSION_MAX_STREAM_DATA_UNI) \
170171
V(IDX_QUIC_SESSION_MAX_STREAMS_BIDI) \
171172
V(IDX_QUIC_SESSION_MAX_STREAMS_UNI) \
172-
V(IDX_QUIC_SESSION_MAX_PACKET_SIZE) \
173+
V(IDX_QUIC_SESSION_MAX_UDP_PAYLOAD_SIZE) \
173174
V(IDX_QUIC_SESSION_ACK_DELAY_EXPONENT) \
174175
V(IDX_QUIC_SESSION_DISABLE_MIGRATION) \
175176
V(IDX_QUIC_SESSION_MAX_ACK_DELAY) \
177+
V(IDX_QUIC_SESSION_CC_ALGO) \
176178
V(IDX_QUIC_SESSION_CONFIG_COUNT) \
177179
V(IDX_QUIC_SESSION_STATE_CERT_ENABLED) \
178180
V(IDX_QUIC_SESSION_STATE_CLIENT_HELLO_ENABLED) \
@@ -190,6 +192,9 @@ void Initialize(Local<Object> target,
190192
V(NGTCP2_APP_NOERROR) \
191193
V(NGTCP2_PATH_VALIDATION_RESULT_FAILURE) \
192194
V(NGTCP2_PATH_VALIDATION_RESULT_SUCCESS) \
195+
V(NGTCP2_DEFAULT_MAX_PKTLEN) \
196+
V(NGTCP2_CC_ALGO_CUBIC) \
197+
V(NGTCP2_CC_ALGO_RENO) \
193198
V(QUIC_ERROR_APPLICATION) \
194199
V(QUIC_ERROR_CRYPTO) \
195200
V(QUIC_ERROR_SESSION) \
@@ -238,8 +243,8 @@ void Initialize(Local<Object> target,
238243
NODE_DEFINE_CONSTANT(constants, AF_INET);
239244
NODE_DEFINE_CONSTANT(constants, AF_INET6);
240245
NODE_DEFINE_STRING_CONSTANT(constants,
241-
NODE_STRINGIFY_HELPER(NGTCP2_ALPN_H3),
242-
NGTCP2_ALPN_H3);
246+
NODE_STRINGIFY_HELPER(NGHTTP3_ALPN_H3),
247+
NGHTTP3_ALPN_H3);
243248

244249
target->Set(context, env->constants_string(), constants).FromJust();
245250
}

src/quic/node_quic_crypto.cc

Lines changed: 10 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
#include <ngtcp2/ngtcp2.h>
1515
#include <ngtcp2/ngtcp2_crypto.h>
16+
#include <nghttp3/nghttp3.h> // NGHTTP3_ALPN_H3
1617
#include <openssl/bio.h>
1718
#include <openssl/err.h>
1819
#include <openssl/evp.h>
@@ -231,7 +232,6 @@ std::unique_ptr<QuicPacket> GenerateRetryPacket(
231232
cid.set_length(kScidLen);
232233

233234
size_t pktlen = tokenlen + (2 * NGTCP2_MAX_CIDLEN) + scid.length() + 8;
234-
CHECK_LE(pktlen, NGTCP2_MAX_PKT_SIZE);
235235

236236
auto packet = QuicPacket::Create("retry", pktlen);
237237
ssize_t nwrite =
@@ -258,23 +258,23 @@ std::unique_ptr<QuicPacket> GenerateRetryPacket(
258258
// is successful, ocid will be updated to the original connection ID encoded
259259
// in the encrypted token.
260260
bool InvalidRetryToken(
261-
const ngtcp2_pkt_hd& hd,
261+
const ngtcp2_vec& token,
262262
const SocketAddress& addr,
263263
QuicCID* ocid,
264264
const uint8_t* token_secret,
265265
uint64_t verification_expiration) {
266266

267-
if (hd.tokenlen < kTokenRandLen)
267+
if (token.len < kTokenRandLen)
268268
return true;
269269

270270
ngtcp2_crypto_ctx ctx;
271271
ngtcp2_crypto_ctx_initial(&ctx);
272272

273273
size_t ivlen = ngtcp2_crypto_packet_protection_ivlen(&ctx.aead);
274274

275-
size_t ciphertextlen = hd.tokenlen - kTokenRandLen;
276-
const uint8_t* ciphertext = hd.token;
277-
const uint8_t* rand_data = hd.token + ciphertextlen;
275+
size_t ciphertextlen = token.len - kTokenRandLen;
276+
const uint8_t* ciphertext = token.base;
277+
const uint8_t* rand_data = token.base + ciphertextlen;
278278

279279
uint8_t token_key[kCryptoTokenKeylen];
280280
uint8_t token_iv[kCryptoTokenIvlen];
@@ -559,10 +559,10 @@ Local<Value> GetALPNProtocol(const QuicSession& session) {
559559
QuicCryptoContext* ctx = session.crypto_context();
560560
Environment* env = session.env();
561561
std::string alpn = ctx->selected_alpn();
562-
// This supposed to be `NGTCP2_ALPN_H3 + 1`
562+
// This supposed to be `NGHTTP3_ALPN_H3 + 1`
563563
// Details see https://github.com/nodejs/node/issues/33959
564-
if (alpn == &NGTCP2_ALPN_H3[1]) {
565-
return env->quic_alpn_string();
564+
if (alpn == &NGHTTP3_ALPN_H3[1]) {
565+
return env->http3_alpn_string();
566566
} else {
567567
return ToV8Value(
568568
env->context(),
@@ -800,6 +800,7 @@ void InitializeTLS(QuicSession* session, const crypto::SSLPointer& ssl) {
800800
UNREACHABLE();
801801
}
802802

803+
ngtcp2_conn_set_tls_native_handle(session->connection(), ssl.get());
803804
SetTransportParams(session, ssl);
804805
}
805806

@@ -859,33 +860,6 @@ void InitializeSecureContext(
859860
SSL_CTX_set_quic_method(**sc, &quic_method);
860861
}
861862

862-
bool DeriveAndInstallInitialKey(
863-
const QuicSession& session,
864-
const QuicCID& dcid) {
865-
uint8_t initial_secret[NGTCP2_CRYPTO_INITIAL_SECRETLEN];
866-
uint8_t rx_secret[NGTCP2_CRYPTO_INITIAL_SECRETLEN];
867-
uint8_t tx_secret[NGTCP2_CRYPTO_INITIAL_SECRETLEN];
868-
uint8_t rx_key[NGTCP2_CRYPTO_INITIAL_KEYLEN];
869-
uint8_t tx_key[NGTCP2_CRYPTO_INITIAL_KEYLEN];
870-
uint8_t rx_hp[NGTCP2_CRYPTO_INITIAL_KEYLEN];
871-
uint8_t tx_hp[NGTCP2_CRYPTO_INITIAL_KEYLEN];
872-
uint8_t rx_iv[NGTCP2_CRYPTO_INITIAL_IVLEN];
873-
uint8_t tx_iv[NGTCP2_CRYPTO_INITIAL_IVLEN];
874-
return NGTCP2_OK(ngtcp2_crypto_derive_and_install_initial_key(
875-
session.connection(),
876-
rx_secret,
877-
tx_secret,
878-
initial_secret,
879-
rx_key,
880-
rx_iv,
881-
rx_hp,
882-
tx_key,
883-
tx_iv,
884-
tx_hp,
885-
dcid.cid(),
886-
session.crypto_context()->side()));
887-
}
888-
889863
ngtcp2_crypto_level from_ossl_level(OSSL_ENCRYPTION_LEVEL ossl_level) {
890864
switch (ossl_level) {
891865
case ssl_encryption_initial:

src/quic/node_quic_crypto.h

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -44,13 +44,6 @@ void InitializeSecureContext(
4444
// with the session.
4545
void InitializeTLS(QuicSession* session, const crypto::SSLPointer& ssl);
4646

47-
// Called when the client QuicSession is created and
48-
// when the server QuicSession first receives the
49-
// client hello.
50-
bool DeriveAndInstallInitialKey(
51-
const QuicSession& session,
52-
const QuicCID& dcid);
53-
5447
// Generates a stateless reset token using HKDF with the
5548
// cid and token secret as input. The token secret is
5649
// either provided by user code when a QuicSocket is
@@ -101,7 +94,7 @@ uint32_t GenerateFlowLabel(
10194
// the ocid will be updated to the original CID value encoded
10295
// within the successfully validated, encrypted token.
10396
bool InvalidRetryToken(
104-
const ngtcp2_pkt_hd& hd,
97+
const ngtcp2_vec& token,
10598
const SocketAddress& addr,
10699
QuicCID* ocid,
107100
const uint8_t* token_secret,

src/quic/node_quic_default_application.cc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -81,8 +81,8 @@ void DefaultApplication::ResumeStream(int64_t stream_id) {
8181
}
8282

8383
bool DefaultApplication::ReceiveStreamData(
84+
uint32_t flags,
8485
int64_t stream_id,
85-
int fin,
8686
const uint8_t* data,
8787
size_t datalen,
8888
uint64_t offset) {
@@ -110,7 +110,7 @@ bool DefaultApplication::ReceiveStreamData(
110110
}
111111
CHECK(stream);
112112

113-
stream->ReceiveData(fin, data, datalen, offset);
113+
stream->ReceiveData(flags, data, datalen, offset);
114114
return true;
115115
}
116116

src/quic/node_quic_default_application.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,8 @@ class DefaultApplication final : public QuicApplication {
2929
}
3030

3131
bool ReceiveStreamData(
32+
uint32_t flags,
3233
int64_t stream_id,
33-
int fin,
3434
const uint8_t* data,
3535
size_t datalen,
3636
uint64_t offset) override;

0 commit comments

Comments
 (0)