Skip to content

Commit 91dd5d5

Browse files
committed
quic: implement keepAlive option and ping support
Signed-off-by: James M Snell <jasnell@gmail.com>
1 parent c754433 commit 91dd5d5

5 files changed

Lines changed: 36 additions & 7 deletions

File tree

doc/api/quic.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1403,6 +1403,20 @@ added: v23.8.0
14031403
Specifies the maximum number of milliseconds a TLS handshake is permitted to take
14041404
to complete before timing out.
14051405

1406+
#### `sessionOptions.keepAlive`
1407+
1408+
<!-- YAML
1409+
added: REPLACEME
1410+
-->
1411+
1412+
* Type: {bigint|number}
1413+
* **Default:** `0` (disabled)
1414+
1415+
Specifies the keep-alive timeout in milliseconds. When set to a non-zero
1416+
value, PING frames will be sent automatically to keep the connection alive
1417+
before the idle timeout fires. The value should be less than the effective
1418+
idle timeout (`maxIdleTimeout` transport parameter) to be useful.
1419+
14061420
#### `sessionOptions.servername` (client only)
14071421

14081422
<!-- YAML

lib/internal/quic/quic.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -271,6 +271,8 @@ const onSessionHandshakeChannel = dc.channel('quic.session.handshake');
271271
* @property {boolean} [qlog] Enable qlog
272272
* @property {ArrayBufferView} [sessionTicket] The session ticket
273273
* @property {bigint|number} [handshakeTimeout] The handshake timeout
274+
* @property {bigint|number} [keepAlive] The keep-alive timeout in milliseconds. When set,
275+
* PING frames will be sent automatically to prevent idle timeout.
274276
* @property {bigint|number} [maxStreamWindow] The maximum stream window
275277
* @property {bigint|number} [maxWindow] The maximum window
276278
* @property {bigint|number} [maxPayloadSize] The maximum payload size
@@ -2480,6 +2482,7 @@ function processSessionOptions(options, config = { __proto__: null }) {
24802482
maxPayloadSize,
24812483
unacknowledgedPacketThreshold = 0,
24822484
handshakeTimeout,
2485+
keepAlive,
24832486
maxStreamWindow,
24842487
maxWindow,
24852488
cc,
@@ -2514,6 +2517,7 @@ function processSessionOptions(options, config = { __proto__: null }) {
25142517
maxPayloadSize,
25152518
unacknowledgedPacketThreshold,
25162519
handshakeTimeout,
2520+
keepAlive,
25172521
maxStreamWindow,
25182522
maxWindow,
25192523
sessionTicket,

src/quic/bindingdata.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ class Packet;
7777
V(groups, "groups") \
7878
V(handshake_timeout, "handshakeTimeout") \
7979
V(http3_alpn, &NGHTTP3_ALPN_H3[1]) \
80+
V(keep_alive_timeout, "keepAlive") \
8081
V(initial_max_data, "initialMaxData") \
8182
V(initial_max_stream_data_bidi_local, "initialMaxStreamDataBidiLocal") \
8283
V(initial_max_stream_data_bidi_remote, "initialMaxStreamDataBidiRemote") \

src/quic/session.cc

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -209,7 +209,7 @@ void ngtcp2_debug_log(void* user_data, const char* fmt, ...) {
209209
va_end(ap);
210210
}
211211

212-
template <typename Opt, PreferredAddress::Policy Opt::*member>
212+
template <typename Opt, PreferredAddress::Policy Opt::* member>
213213
bool SetOption(Environment* env,
214214
Opt* options,
215215
const Local<Object>& object,
@@ -224,7 +224,7 @@ bool SetOption(Environment* env,
224224
return true;
225225
}
226226

227-
template <typename Opt, TLSContext::Options Opt::*member>
227+
template <typename Opt, TLSContext::Options Opt::* member>
228228
bool SetOption(Environment* env,
229229
Opt* options,
230230
const Local<Object>& object,
@@ -239,7 +239,7 @@ bool SetOption(Environment* env,
239239
return true;
240240
}
241241

242-
template <typename Opt, TransportParams::Options Opt::*member>
242+
template <typename Opt, TransportParams::Options Opt::* member>
243243
bool SetOption(Environment* env,
244244
Opt* options,
245245
const Local<Object>& object,
@@ -254,7 +254,7 @@ bool SetOption(Environment* env,
254254
return true;
255255
}
256256

257-
template <typename Opt, ngtcp2_cc_algo Opt::*member>
257+
template <typename Opt, ngtcp2_cc_algo Opt::* member>
258258
bool SetOption(Environment* env,
259259
Opt* options,
260260
const Local<Object>& object,
@@ -437,9 +437,9 @@ Maybe<Session::Options> Session::Options::From(Environment* env,
437437

438438
if (!SET(version) || !SET(min_version) || !SET(preferred_address_strategy) ||
439439
!SET(transport_params) || !SET(tls_options) || !SET(qlog) ||
440-
!SET(handshake_timeout) || !SET(max_stream_window) || !SET(max_window) ||
441-
!SET(max_payload_size) || !SET(unacknowledged_packet_threshold) ||
442-
!SET(cc_algorithm)) {
440+
!SET(handshake_timeout) || !SET(keep_alive_timeout) ||
441+
!SET(max_stream_window) || !SET(max_window) || !SET(max_payload_size) ||
442+
!SET(unacknowledged_packet_threshold) || !SET(cc_algorithm)) {
443443
return Nothing<Options>();
444444
}
445445

@@ -1321,6 +1321,11 @@ Session::Session(Endpoint* endpoint,
13211321
if (app) SetApplication(std::move(app));
13221322
}
13231323

1324+
if (config.options.keep_alive_timeout > 0) {
1325+
ngtcp2_conn_set_keep_alive_timeout(
1326+
*this, config.options.keep_alive_timeout * NGTCP2_MILLISECONDS);
1327+
}
1328+
13241329
MakeWeak();
13251330
Debug(this, "Session created.");
13261331
auto& binding = BindingData::Get(env());

src/quic/session.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,11 @@ class Session final : public AsyncWrap, private SessionTicket::AppData::Source {
151151
// completion of the tls handshake.
152152
uint64_t handshake_timeout = UINT64_MAX;
153153

154+
// The keep-alive timeout in milliseconds. When set to a non-zero value,
155+
// ngtcp2 will automatically send PING frames to keep the connection alive
156+
// before the idle timeout fires. Set to 0 to disable (default).
157+
uint64_t keep_alive_timeout = 0;
158+
154159
// Maximum initial flow control window size for a stream.
155160
uint64_t max_stream_window = 0;
156161

0 commit comments

Comments
 (0)