Skip to content

Commit 025bb30

Browse files
committed
qir: additional tests
quic-version-negotiation qir-last-tests xr-29
1 parent 9011588 commit 025bb30

27 files changed

Lines changed: 2014 additions & 471 deletions

include/libwebsockets/lws-client.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,10 @@ struct lws_client_connect_info {
227227
* to the client connection.
228228
*/
229229

230+
struct lws *quic_migrate_from_wsi;
231+
/**< If set, this connection acts as a Make-Before-Break migration probe for
232+
* the existing QUIC network connection in quic_migrate_from_wsi. */
233+
230234
uint8_t priority;
231235
/**< 0 means normal priority... otherwise sets the IP priority on
232236
* packets coming from this connection, from 1 - 7. Setting 7

include/libwebsockets/lws-context-vhost.h

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -284,6 +284,12 @@
284284
#define LWS_SERVER_OPTION_QUIC_PAD_CRYPTO (1ll << 49)
285285
/**< (VH) Pad the QUIC handshake crypto data to artificially hit anti-amplification limits */
286286

287+
#define LWS_SERVER_OPTION_QUIC_EARLY_KEY_UPDATE (1ll << 51)
288+
/**< CONTEXT: For testing. Trigger a QUIC early key update */
289+
290+
#define LWS_SERVER_OPTION_QUIC_LATEST_VERSION (1ll << 50)
291+
/**< (CTX) Force client to initiate QUIC connections using the latest supported version (e.g. v2) */
292+
287293
/****** add new things just above ---^ ******/
288294

289295

@@ -1102,7 +1108,11 @@ struct lws_context_creation_info {
11021108
const struct lws_cc_ops *quic_cc_ops;
11031109
/**< CONTEXT: QUIC congestion control algorithm ops to use. If NULL, defaults to &lws_cc_ops_newreno. */
11041110

1105-
void *_unused[1]; /**< dummy */
1111+
const char *quic_preferred_addresses;
1112+
/**< VHOST: Comma-separated list of IPv4 and/or IPv6 preferred addresses (e.g., "1.2.3.4:443,[2001:db8::1]:443")
1113+
* to send to the client during the handshake to facilitate Connection Migration. */
1114+
1115+
void *_unused[0]; /**< dummy */
11061116
};
11071117

11081118
/**

include/libwebsockets/lws-quic.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,7 @@ struct lws_cc_ops {
159159
void (*on_sent)(struct lws *nwsi, size_t bytes);
160160
void (*on_ack)(struct lws *nwsi, size_t bytes_acked, lws_usec_t rtt);
161161
void (*on_loss)(struct lws *nwsi, size_t bytes_lost);
162+
void (*on_discard)(struct lws *nwsi, size_t bytes_discarded);
162163
int (*can_send)(struct lws *nwsi, size_t bytes);
163164
lws_usec_t (*get_pacing_delay)(struct lws *nwsi, size_t bytes_to_send);
164165
};

lib/core-net/client/connect.c

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,10 @@ lws_client_connect_via_info(const struct lws_client_connect_info *i)
208208
wsi->client_proxy_onward = !!(i->ssl_connection & LCCSCF_SECSTREAM_PROXY_ONWARD);
209209
#endif
210210

211+
#if defined(LWS_ROLE_QUIC)
212+
wsi->quic.migrate_from_wsi = i->quic_migrate_from_wsi;
213+
#endif
214+
211215
#if defined(LWS_WITH_SYS_FAULT_INJECTION)
212216
wsi->fic.name = "wsi";
213217
if (i->fic.fi_owner.count)
@@ -250,6 +254,8 @@ lws_client_connect_via_info(const struct lws_client_connect_info *i)
250254
wsi->keep_warm_secs = 5;
251255

252256
wsi->flags = i->ssl_connection;
257+
if (i->context->options & LWS_SERVER_OPTION_ALLOW_EARLY_DATA)
258+
wsi->flags |= LCCSCF_ALLOW_EARLY_DATA;
253259

254260
wsi->c_pri = i->priority;
255261

@@ -347,7 +353,7 @@ lws_client_connect_via_info(const struct lws_client_connect_info *i)
347353
}
348354

349355
#if defined(LWS_WITH_TLS)
350-
wsi->tls.use_ssl = (unsigned int)i->ssl_connection;
356+
wsi->tls.use_ssl = (unsigned int)wsi->flags;
351357
#else
352358
if (i->ssl_connection & LCCSCF_USE_SSL) {
353359
lwsl_wsi_err(wsi, "lws not configured for tls");

lib/core-net/client/connect4.c

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ lws_client_connect_4_established(struct lws *wsi, struct lws *wsi_piggyback,
135135

136136
send_hs:
137137

138-
#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
138+
#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2) || defined(LWS_ROLE_H3)
139139
if (wsi_piggyback &&
140140
!lws_dll2_is_detached(&wsi->dll2_cli_txn_queue)) {
141141
/*
@@ -250,7 +250,11 @@ lws_client_connect_4_established(struct lws *wsi, struct lws *wsi_piggyback,
250250
#if defined(LWS_ROLE_QUIC)
251251
if ((meth && !strcmp(meth, "QUIC")) ||
252252
!strcmp(wsi->role_ops->name, "quic")) {
253-
lwsi_set_state(wsi, LRS_WAITING_SSL);
253+
if (wsi->quic.migrate_from_wsi) {
254+
lwsi_set_state(wsi, LRS_ESTABLISHED);
255+
} else {
256+
lwsi_set_state(wsi, LRS_WAITING_SSL);
257+
}
254258
wsi->hdr_parsing_completed = 1;
255259
lws_callback_on_writable(wsi);
256260
return wsi;

lib/core-net/close.c

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -507,7 +507,14 @@ __lws_close_free_wsi(struct lws *wsi, enum lws_close_status reason,
507507

508508
#if defined(LWS_WITH_CLIENT)
509509
#if defined(LWS_WITH_TLS_SESSIONS) && defined(LWS_WITH_GNUTLS)
510-
lws_tls_session_new_gnutls(wsi);
510+
/*
511+
* For multiplexed connections (H3/H2), the TLS session belongs
512+
* to the network-level WSI, not to individual stream WSIs. Don't
513+
* perform the (expensive) session ticket snapshot on every mux
514+
* substream close — only on the actual network wsi.
515+
*/
516+
if (!wsi->client_mux_substream)
517+
lws_tls_session_new_gnutls(wsi);
511518
#endif
512519

513520
lws_free_set_NULL(wsi->cli_hostname_copy);

lib/core-net/private-lib-core-net.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -540,6 +540,8 @@ struct lws_vhost {
540540

541541
uint64_t options;
542542

543+
const char *quic_preferred_addresses;
544+
543545
struct lws_context *context;
544546
struct lws_vhost *vhost_next;
545547

lib/core-net/service.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -677,8 +677,6 @@ lws_service_flag_pending(struct lws_context *context, int tsi)
677677

678678
if (!lws_is_flowcontrolled(wsi) &&
679679
lwsi_state(wsi) != LRS_DEFERRING_ACTION &&
680-
lwsi_state(wsi) != LRS_ISSUING_FILE &&
681-
lwsi_state(wsi) != LRS_DOING_TRANSACTION &&
682680
lwsi_state(wsi) != LRS_AWAITING_FILE_READ &&
683681
lwsi_state(wsi) != LRS_AWAITING_SSL_ACCEPT) {
684682
forced = 1;

lib/core-net/vhost.c

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -835,8 +835,9 @@ lws_create_vhost(struct lws_context *context,
835835
vh->count_protocols++)
836836
;
837837

838-
vh->options = info->options;
839-
vh->pvo = info->pvo;
838+
vh->options = info->options;
839+
vh->quic_preferred_addresses = info->quic_preferred_addresses;
840+
vh->pvo = info->pvo;
840841
#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
841842
vh->headers = info->headers;
842843
#endif
@@ -879,8 +880,8 @@ lws_create_vhost(struct lws_context *context,
879880
if (info->tls1_3_plus_cipher_list)
880881
vh->tls.cfg_tls1_3_plus_cipher_list = lws_strdup(info->tls1_3_plus_cipher_list);
881882
#if defined(LWS_WITH_CLIENT)
882-
if (info->client_ssl_cipher_list)
883-
vh->tls.cfg_tls_client_cipher_list = lws_strdup(info->client_ssl_cipher_list);
883+
if (info->client_ssl_cipher_list)
884+
vh->tls.cfg_tls_client_cipher_list = lws_strdup(info->client_ssl_cipher_list);
884885
#endif
885886
if (info->tls_ciphers_iana)
886887
vh->tls.cfg_tls_ciphers_iana = lws_strdup(info->tls_ciphers_iana);
@@ -2101,7 +2102,7 @@ lws_vhost_active_conns(struct lws *wsi, struct lws **nwsi, const char *adsin)
21012102
* h2: if in usable state already: just use it without
21022103
* going through the queue
21032104
*/
2104-
if (w->client_h2_alpn && w->client_mux_migrated &&
2105+
if (lwsi_role_h2(w) && w->client_h2_alpn && w->client_mux_migrated &&
21052106
(lwsi_state(w) == LRS_H2_WAITING_TO_SEND_HEADERS ||
21062107
lwsi_state(w) == LRS_ESTABLISHED ||
21072108
lwsi_state(w) == LRS_IDLING)) {
@@ -2130,14 +2131,15 @@ lws_vhost_active_conns(struct lws *wsi, struct lws **nwsi, const char *adsin)
21302131
* h3: if in usable state already: just use it without
21312132
* going through the queue
21322133
*/
2133-
if (lwsi_role_h3(w) && w->client_h2_alpn && w->client_mux_migrated &&
2134+
if ((w->role_ops && !strcmp(w->role_ops->name, "quic")) && w->client_h2_alpn && w->client_mux_migrated &&
21342135
(lwsi_state(w) == LRS_H2_WAITING_TO_SEND_HEADERS ||
21352136
lwsi_state(w) == LRS_ESTABLISHED ||
21362137
lwsi_state(w) == LRS_IDLING)) {
21372138

21382139
lwsl_wsi_info(w, "just join h3 directly 0x%x",
21392140
lwsi_state(w));
21402141

2142+
21412143
if (lwsi_state(w) == LRS_IDLING)
21422144
_lws_generic_transaction_completed_active_conn(&w, 0);
21432145

lib/core-net/wsi.c

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -608,8 +608,7 @@ int lws_has_buffered_out(struct lws *wsi) {
608608
lws_start_foreach_dll_safe(struct lws_dll2 *, d, d1, qn->pending_tx[i].head) {
609609
struct lws_quic_tx_frame *f = lws_container_of(d, struct lws_quic_tx_frame, list);
610610
if (((f->type & 0xf8) == LWS_QUIC_FT_STREAM && f->stream_id == sid) ||
611-
(f->type == LWS_QUIC_FT_STREAM_DATA_BLOCKED && f->stream_id == sid) ||
612-
f->type == LWS_QUIC_FT_DATA_BLOCKED) {
611+
(f->type == LWS_QUIC_FT_STREAM_DATA_BLOCKED && f->stream_id == sid)) {
613612
lwsl_notice("lws_has_buffered_out: %s has pending_tx stream/blocked frame on sid %llu\n", lws_wsi_tag(wsi), (unsigned long long)sid);
614613
return 1;
615614
}
@@ -618,8 +617,7 @@ int lws_has_buffered_out(struct lws *wsi) {
618617
lws_start_foreach_dll_safe(struct lws_dll2 *, d, d1, qn->in_flight[i].head) {
619618
struct lws_quic_tx_frame *f = lws_container_of(d, struct lws_quic_tx_frame, list);
620619
if (((f->type & 0xf8) == LWS_QUIC_FT_STREAM && f->stream_id == sid) ||
621-
(f->type == LWS_QUIC_FT_STREAM_DATA_BLOCKED && f->stream_id == sid) ||
622-
f->type == LWS_QUIC_FT_DATA_BLOCKED) {
620+
(f->type == LWS_QUIC_FT_STREAM_DATA_BLOCKED && f->stream_id == sid)) {
623621
lwsl_notice("lws_has_buffered_out: %s has in_flight stream/blocked frame on sid %llu\n", lws_wsi_tag(wsi), (unsigned long long)sid);
624622
return 1;
625623
}
@@ -1511,7 +1509,7 @@ int lws_wsi_mux_mark_parents_needing_writeable(struct lws *wsi) {
15111509
wsi2 = wsi;
15121510
while (wsi2) {
15131511
wsi2->mux.requested_POLLOUT = 1;
1514-
lwsl_wsi_info(wsi2, "sid %u, pending writable", wsi2->mux.my_sid);
1512+
lwsl_wsi_debug(wsi2, "sid %u, pending writable", wsi2->mux.my_sid);
15151513
wsi2 = wsi2->mux.parent_wsi;
15161514
}
15171515

@@ -1650,6 +1648,8 @@ int lws_wsi_mux_apply_queue(struct lws *wsi) {
16501648

16511649
lwsl_wsi_notice(wsi, "evaluating queued conn %s (state 0x%x, par role %s)",
16521650
lws_wsi_tag(w), lwsi_state(w), wsi->role_ops ? wsi->role_ops->name : "none");
1651+
lwsl_notice("AGY-MUX: parent role=%s, child state=0x%x (expected 0x%x)\n",
1652+
wsi->role_ops ? wsi->role_ops->name : "none", lwsi_state(w), LRS_H2_WAITING_TO_SEND_HEADERS);
16531653

16541654
#if defined(LWS_ROLE_H2)
16551655
if (lwsi_role_h2(wsi) &&
@@ -1669,7 +1669,7 @@ int lws_wsi_mux_apply_queue(struct lws *wsi) {
16691669
#endif
16701670

16711671
#if defined(LWS_ROLE_H3)
1672-
if ((wsi->role_ops && !strcmp(wsi->role_ops->name, "quic")) &&
1672+
if ((wsi->role_ops && (!strcmp(wsi->role_ops->name, "quic") || !strcmp(wsi->role_ops->name, "h3"))) &&
16731673
lwsi_state(w) == LRS_H2_WAITING_TO_SEND_HEADERS) {
16741674

16751675
if (!lws_wsi_h3_can_adopt(wsi)) {

0 commit comments

Comments
 (0)