Skip to content

Commit 4aea61d

Browse files
committed
quic: add getters for local and remote transport parameters
Signed-off-by: James M Snell <jasnell@gmail.com> PR-URL: nodejs#63267 Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
1 parent 1d9b449 commit 4aea61d

8 files changed

Lines changed: 465 additions & 1 deletion

File tree

doc/api/quic.md

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -853,6 +853,17 @@ added: v23.8.0
853853

854854
True if `session.destroy()` has been called. Read only.
855855

856+
### `session.localTransportParams`
857+
858+
<!-- YAML
859+
added: REPLACEME
860+
-->
861+
862+
* Type: {quic.TransportParams|null}
863+
864+
The transport parameters advertised by the local endpoint during the handshake.
865+
Returns `null` if the session has been destroyed. Read only.
866+
856867
### `session.endpoint`
857868

858869
<!-- YAML
@@ -1146,6 +1157,19 @@ added: v23.8.0
11461157

11471158
The local and remote socket addresses associated with the session. Read only.
11481159

1160+
### `session.remoteTransportParams`
1161+
1162+
<!-- YAML
1163+
added: REPLACEME
1164+
-->
1165+
1166+
* Type: {quic.TransportParams|null|undefined}
1167+
1168+
The transport parameters advertised by the remote peer during the handshake.
1169+
Returns `null` if the session has been destroyed, `undefined` if the handshake
1170+
has not yet completed and the remote parameters are not yet available. Read
1171+
only.
1172+
11491173
### `session.sendDatagram(datagram[, encoding])`
11501174

11511175
<!-- YAML
@@ -2953,6 +2977,37 @@ won't have need to specify.
29532977
added: v23.8.0
29542978
-->
29552979

2980+
The `TransportParams` type represents the QUIC transport parameters that are
2981+
negotiated during session establishment. These parameters are used when
2982+
creating a session. The negotiated values can be observed via the
2983+
`session.localTransportParams` and `session.remoteTransportParams` properties.
2984+
2985+
#### `transportParams.initialSCID`
2986+
2987+
<!-- YAML
2988+
added: REPLACEME
2989+
-->
2990+
2991+
* Type: {string}
2992+
2993+
The initial source connection ID (SCID) specified. This field is ignored on
2994+
creation of the session and is provided for informational purposes only when
2995+
available in the `session.localTransportParams` and
2996+
`session.remoteTransportParams` properties.
2997+
2998+
#### `transportParams.originalDCID`
2999+
3000+
<!-- YAML
3001+
added: REPLACEME
3002+
-->
3003+
3004+
* Type: {string}
3005+
3006+
The original destination connection ID (DCID) specified. This field is
3007+
ignored on creation of the session and is provided for informational
3008+
purposes only when available in the `session.localTransportParams` and
3009+
`session.remoteTransportParams` properties.
3010+
29563011
#### `transportParams.preferredAddressIpv4`
29573012

29583013
<!-- YAML
@@ -3066,6 +3121,19 @@ will not send datagrams larger than this value. The actual maximum size of
30663121
a datagram that can be _sent_ is determined by the peer's
30673122
`maxDatagramFrameSize`, not this endpoint's value.
30683123

3124+
#### `transportParams.retrySCID`
3125+
3126+
<!-- YAML
3127+
added: REPLACEME
3128+
-->
3129+
3130+
* Type: {string}
3131+
3132+
The retry connection ID specified. This field is ignored on creation
3133+
of the session and is provided for informational purposes only when
3134+
available in the `session.localTransportParams` and
3135+
`session.remoteTransportParams` properties.
3136+
30693137
## Callbacks
30703138

30713139
### Callback error handling

lib/internal/quic/quic.js

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2626,6 +2626,8 @@ class QuicSession {
26262626
certificate: undefined,
26272627
peerCertificate: undefined,
26282628
ephemeralKeyInfo: undefined,
2629+
localTransportParams: undefined,
2630+
remoteTransportParams: undefined,
26292631
};
26302632

26312633
static {
@@ -2676,6 +2678,45 @@ class QuicSession {
26762678
debug('session created');
26772679
}
26782680

2681+
get localTransportParams() {
2682+
if (this.#inner.localTransportParams !== undefined) {
2683+
return this.#inner.localTransportParams;
2684+
}
2685+
// If the handle is already gone, we cannot retrieve the transport params.
2686+
if (this.destroyed) return null;
2687+
const params = this.#handle.localTransportParams();
2688+
if (params.preferredAddressIpv4 !== undefined) {
2689+
params.preferredAddressIpv4 = new InternalSocketAddress(params.preferredAddressIpv4);
2690+
}
2691+
if (params.preferredAddressIpv6 !== undefined) {
2692+
params.preferredAddressIpv6 = new InternalSocketAddress(params.preferredAddressIpv6);
2693+
}
2694+
return this.#inner.localTransportParams = params;
2695+
}
2696+
2697+
get remoteTransportParams() {
2698+
if (this.#inner.remoteTransportParams !== undefined) {
2699+
return this.#inner.remoteTransportParams;
2700+
}
2701+
// If the handle is already gone, we cannot retrieve the transport params.
2702+
if (this.destroyed) return null;
2703+
const params = this.#handle.remoteTransportParams();
2704+
// If params is undefined, the transport parameters have not yet been received.
2705+
// Note the distinction between this and the case where the handle is gone.
2706+
// If the handle is gone, we return null because we know the transport
2707+
// parameters will be unavailable. If the transport parameters have not yet
2708+
// been received, we return undefined to indicate that they may still become
2709+
// available in the future.
2710+
if (params === undefined) return undefined;
2711+
if (params.preferredAddressIpv4 !== undefined) {
2712+
params.preferredAddressIpv4 = new InternalSocketAddress(params.preferredAddressIpv4);
2713+
}
2714+
if (params.preferredAddressIpv6 !== undefined) {
2715+
params.preferredAddressIpv6 = new InternalSocketAddress(params.preferredAddressIpv6);
2716+
}
2717+
return this.#inner.remoteTransportParams = params;
2718+
}
2719+
26792720
/** @type {boolean} */
26802721
get #isClosedOrClosing() {
26812722
return this.#handle === undefined || this.#inner.isPendingClose;

src/quic/bindingdata.cc

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
namespace node {
2121

2222
using mem::kReserveSizeAndAlign;
23+
using v8::DictionaryTemplate;
2324
using v8::Function;
2425
using v8::FunctionTemplate;
2526
using v8::HandleScope;
@@ -377,6 +378,16 @@ QUIC_CONSTRUCTORS(V)
377378

378379
#undef V
379380

381+
void BindingData::set_transport_params_template(
382+
Local<DictionaryTemplate> tmpl) {
383+
transport_params_template_.Reset(env()->isolate(), tmpl);
384+
}
385+
386+
Local<DictionaryTemplate> BindingData::transport_params_template() const {
387+
return PersistentToLocal::Default(env()->isolate(),
388+
transport_params_template_);
389+
}
390+
380391
#define V(name, _) \
381392
void BindingData::set_##name##_callback(Local<Function> fn) { \
382393
name##_callback_.Reset(env()->isolate(), fn); \

src/quic/bindingdata.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -303,6 +303,9 @@ class BindingData final
303303
QUIC_CONSTRUCTORS(V)
304304
#undef V
305305

306+
void set_transport_params_template(v8::Local<v8::DictionaryTemplate> tmpl);
307+
v8::Local<v8::DictionaryTemplate> transport_params_template() const;
308+
306309
#define V(name, _) \
307310
void set_##name##_callback(v8::Local<v8::Function> fn); \
308311
v8::Local<v8::Function> name##_callback() const;
@@ -321,6 +324,8 @@ class BindingData final
321324
QUIC_CONSTRUCTORS(V)
322325
#undef V
323326

327+
v8::Global<v8::DictionaryTemplate> transport_params_template_;
328+
324329
#define V(name, _) v8::Global<v8::Function> name##_callback_;
325330
QUIC_JS_CALLBACKS(V)
326331
#undef V

src/quic/session.cc

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,9 @@ uint64_t MaxDatagramPayload(uint64_t max_frame_size) {
190190
V(SilentClose, silentClose, SIDE_EFFECT) \
191191
V(UpdateKey, updateKey, SIDE_EFFECT) \
192192
V(OpenStream, openStream, SIDE_EFFECT) \
193-
V(SendDatagram, sendDatagram, SIDE_EFFECT)
193+
V(SendDatagram, sendDatagram, SIDE_EFFECT) \
194+
V(LocalTransportParams, localTransportParams, NO_SIDE_EFFECT) \
195+
V(RemoteTransportParams, remoteTransportParams, NO_SIDE_EFFECT) \
194196

195197
struct Session::State final {
196198
#define V(_, name, type) type name;
@@ -1163,6 +1165,36 @@ struct Session::Impl final : public MemoryRetainer {
11631165
BigInt::New(env->isolate(), session->SendDatagram(std::move(store))));
11641166
}
11651167

1168+
JS_METHOD(LocalTransportParams) {
1169+
auto env = Environment::GetCurrent(args);
1170+
Session* session;
1171+
ASSIGN_OR_RETURN_UNWRAP(&session, args.This());
1172+
1173+
ngtcp2_conn* conn = *session;
1174+
TransportParams params(ngtcp2_conn_get_local_transport_params(conn));
1175+
Local<Object> obj;
1176+
if (params.ToObject(env).ToLocal(&obj)) {
1177+
args.GetReturnValue().Set(obj);
1178+
}
1179+
}
1180+
1181+
JS_METHOD(RemoteTransportParams) {
1182+
auto env = Environment::GetCurrent(args);
1183+
Session* session;
1184+
ASSIGN_OR_RETURN_UNWRAP(&session, args.This());
1185+
1186+
ngtcp2_conn* conn = *session;
1187+
auto params = ngtcp2_conn_get_remote_transport_params(conn);
1188+
if (params == nullptr) {
1189+
// Remote transport parameters are not yet available.
1190+
return args.GetReturnValue().SetUndefined();
1191+
}
1192+
TransportParams tp(params);
1193+
Local<Object> obj;
1194+
if (tp.ToObject(env).ToLocal(&obj)) {
1195+
args.GetReturnValue().Set(obj);
1196+
}
1197+
}
11661198
// Internal ngtcp2 callbacks
11671199

11681200
static int on_acknowledge_stream_data_offset(ngtcp2_conn* conn,

0 commit comments

Comments
 (0)