Skip to content

Commit b4b5aed

Browse files
committed
he-wait-for-h3-increase-initially
1 parent c7deea5 commit b4b5aed

18 files changed

Lines changed: 135 additions & 74 deletions

File tree

AGENTS.md

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@ Our work should follow the existing usage of apis in the project as much as poss
1616
We will be working on the same sources, do not build into ./build since I will be using it; make
1717
your own ./build-agy or whatever.
1818

19+
Use cmake .. --fresh in order to force the build dir to align with your options no matter what
20+
was in there before.
21+
1922
While the idea is you should modify and test sources towards some goal, please do NOT modify the
2023
git state unless directly asked.
2124

@@ -69,8 +72,8 @@ cross-platform, and not include shellscripts, instead use cmake / ctest commands
6972
commands for the platform.
7073

7174
minimal-examples-lowlevel/http-client/minimal-http-client-post/CMakeLists.txt shows how to use the fixtures
72-
stuff to magic peers into being while being sensitive to parallel CI using `$ENV{SAI_INSTANCE_IDX}` to make
73-
unique ports.
75+
stuff to magic peers into being while being sensitive to parallel CI using a CMake unique socket allocator
76+
function to make unique ports.
7477

7578
In the case you can build and run ctest meaningfully, please do confirm the build passes before completing
7679
work on your goal.

CMakeLists.txt

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -264,10 +264,9 @@ option(LWS_WITH_OPENHITLS "Use openHITLS replacement for OpenSSL. When setting t
264264
option(LWS_WITH_CYASSL "Use CyaSSL replacement for OpenSSL. When setting this, you also need to specify LWS_CYASSL_LIBRARIES and LWS_CYASSL_INCLUDE_DIRS" OFF)
265265
option(LWS_WITH_WOLFSSL "Use wolfSSL replacement for OpenSSL. When setting this, you also may need to specify LWS_WOLFSSL_LIBRARIES and LWS_WOLFSSL_INCLUDE_DIRS" OFF)
266266

267-
if (LWS_WITH_HTTP3 AND LWS_WITH_SSL AND NOT (LWS_WITH_BORINGSSL OR LWS_WITH_AWSLC OR LWS_WITH_MBEDTLS OR LWS_WITH_WOLFSSL OR LWS_WITH_CYASSL OR LWS_WITH_GNUTLS OR LWS_WITH_BEARSSL OR LWS_WITH_SCHANNEL OR ESP_PLATFORM OR LWS_WITH_ESP32 OR LWS_WITH_OPENHITLS))
268-
option(LWS_WITH_GNUTLS "Use GnuTLS for SSL" ON)
269-
else()
270-
set(LWS_WITH_GNUTLS OFF CACHE BOOL "Use GnuTLS for SSL" FORCE)
267+
option(LWS_WITH_GNUTLS "Use GnuTLS for SSL" OFF)
268+
if (LWS_WITH_HTTP3 AND LWS_WITH_SSL AND NOT (LWS_WITH_BORINGSSL OR LWS_WITH_AWSLC OR LWS_WITH_MBEDTLS OR LWS_WITH_WOLFSSL OR LWS_WITH_CYASSL OR LWS_WITH_BEARSSL OR LWS_WITH_SCHANNEL OR ESP_PLATFORM OR LWS_WITH_ESP32 OR LWS_WITH_OPENHITLS))
269+
set(LWS_WITH_GNUTLS ON CACHE BOOL "Use GnuTLS for SSL" FORCE)
271270
endif()
272271

273272
if (LWS_WITH_BEARSSL)

lib/core-net/client/connect2.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -377,6 +377,9 @@ lws_client_connect_2_dnsreq_MAY_CLOSE_WSI(struct lws *wsi)
377377
if (wsi->udp) {
378378
struct lws_client_connect_info i;
379379
wsi->tried_quic = 1;
380+
#if defined(LWS_ROLE_QUIC)
381+
wsi->quic.quic_race_start_us = lws_now_usecs();
382+
#endif
380383
memset(&i, 0, sizeof(i));
381384
i.method = "QUIC";
382385
i.alpn = "h3";

lib/core-net/client/connect3.c

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -82,9 +82,11 @@ lws_client_h3_grace_cb(lws_sorted_usec_list_t *sul)
8282

8383
/* Mark H3 as FAILED in cache with 5s TTL */
8484
if (wsi->a.context->h3_cap_cache && wsi->stash && wsi->stash->cis[CIS_HOST]) {
85-
lws_h3_state_t state = LWS_H3_STATE_FAILED_IGNORE;
85+
lws_h3_cap_info_t cap;
86+
memset(&cap, 0, sizeof(cap));
87+
cap.state = LWS_H3_STATE_FAILED_IGNORE;
8688
lws_cache_write_through(wsi->a.context->h3_cap_cache, wsi->stash->cis[CIS_HOST],
87-
(const uint8_t *)&state, sizeof(state),
89+
(const uint8_t *)&cap, sizeof(cap),
8890
lws_now_usecs() + (5000000ll), NULL);
8991
}
9092

@@ -102,12 +104,6 @@ lws_client_h3_grace_cb(lws_sorted_usec_list_t *sul)
102104
if (lws_rops_fidx(wsi->role_ops, LWS_ROPS_close_kill_connection))
103105
lws_rops_func_fidx(wsi->role_ops, LWS_ROPS_close_kill_connection).close_kill_connection(wsi, LWS_CLOSE_STATUS_NOSTATUS);
104106

105-
const struct lws_role_ops *r = lws_role_by_name("h2");
106-
if (!r) r = lws_role_by_name("h1");
107-
if (r) {
108-
lws_role_transition(wsi, LWSIFR_CLIENT, LRS_WAITING_CONNECT, r);
109-
}
110-
111107
/* Promote the first parallel TCP connection */
112108
int first_valid = -1;
113109
for (int i = 0; i < wsi->parallel_count; i++) {
@@ -117,6 +113,11 @@ lws_client_h3_grace_cb(lws_sorted_usec_list_t *sul)
117113
}
118114
}
119115
if (first_valid != -1) {
116+
const struct lws_role_ops *r = lws_role_by_name("h2");
117+
if (!r) r = lws_role_by_name("h1");
118+
if (r) {
119+
lws_role_transition(wsi, LWSIFR_CLIENT, LRS_WAITING_CONNECT, r);
120+
}
120121
wsi->desc.sockfd = wsi->parallel_conns[first_valid].desc.sockfd;
121122
wsi->position_in_fds_table = wsi->parallel_conns[first_valid].position_in_fds_table;
122123
wsi->parallel_conns[first_valid].is_valid = 0;
@@ -410,7 +411,7 @@ lws_client_connect_3_connect(struct lws *wsi, const char *ads,
410411
lws_sockfd_type check_fd = pollfd ? pollfd->fd : LWS_SOCK_INVALID;
411412

412413
int is_quic_race = (wsi->role_ops && !strcmp(wsi->role_ops->name, "quic") && wsi->sul_h3_grace.list.owner);
413-
if ((lwsi_state(wsi) == LRS_WAITING_CONNECT || is_quic_race) &&
414+
if ((lwsi_state(wsi) == LRS_WAITING_CONNECT || (is_quic_race && pollfd != NULL)) &&
414415
(lws_socket_is_valid(wsi->desc.sockfd) || wsi->parallel_count > 0)) {
415416
if (lwsi_state(wsi) == LRS_WAITING_CONNECT && !wsi->sul_connect_timeout.list.owner)
416417
/* no ongoing timeout for one */
@@ -1005,14 +1006,17 @@ lws_client_connect_3_connect(struct lws *wsi, const char *ads,
10051006
return wsi;
10061007
} else if (!is_parallel && wsi->role_ops && !strcmp(wsi->role_ops->name, "quic")) {
10071008
/* QUIC connect immediately succeeds. Schedule grace and happy eyeballs. */
1008-
uint32_t grace_us = 200000;
1009+
uint32_t grace_us = LWS_QUIC_GRACE_DEFAULT_US;
10091010
if (wsi->a.context->h3_cap_cache && wsi->stash && wsi->stash->cis[CIS_HOST]) {
10101011
const void *item = NULL;
10111012
size_t item_len = 0;
1012-
if (!lws_cache_item_get(wsi->a.context->h3_cap_cache, wsi->stash->cis[CIS_HOST], &item, &item_len)) {
1013-
lws_h3_state_t state = *(lws_h3_state_t *)item;
1014-
if (state == LWS_H3_STATE_KNOWN_GOOD || state == LWS_H3_STATE_HTTPS_RECORD_EXISTS)
1015-
grace_us = 3000000;
1013+
if (!lws_cache_item_get(wsi->a.context->h3_cap_cache, wsi->stash->cis[CIS_HOST], &item, &item_len) &&
1014+
item_len == sizeof(lws_h3_cap_info_t)) {
1015+
const lws_h3_cap_info_t *cap = (const lws_h3_cap_info_t *)item;
1016+
if (cap->state == LWS_H3_STATE_KNOWN_GOOD)
1017+
grace_us = cap->latency_us + LWS_QUIC_GRACE_MARGIN_US;
1018+
else if (cap->state == LWS_H3_STATE_HTTPS_RECORD_EXISTS)
1019+
grace_us = LWS_QUIC_GRACE_DEFAULT_US;
10161020
}
10171021
}
10181022
lwsl_wsi_notice(wsi, "QUIC socket created, starting grace timer %uus", (unsigned int)grace_us);

lib/core-net/close.c

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -335,14 +335,11 @@ lws_inform_client_conn_fail(struct lws *wsi, void *arg, size_t len)
335335
return;
336336

337337
#if defined(LWS_ROLE_H3) || defined(LWS_ROLE_QUIC)
338-
if (wsi->udp && wsi->tried_quic && wsi->role_ops && !strcmp(wsi->role_ops->name, "quic")) {
339-
const char *path = lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_URI);
340-
const char *host = lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_HOST);
341-
const char *ads = wsi->cli_hostname_copy;
338+
if (wsi->tried_quic && wsi->role_ops && !strcmp(wsi->role_ops->name, "quic")) {
339+
const char *path = wsi->stash ? wsi->stash->cis[CIS_PATH] : lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_URI);
340+
const char *host = wsi->stash ? wsi->stash->cis[CIS_HOST] : lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_HOST);
341+
const char *ads = wsi->stash ? wsi->stash->cis[CIS_ADDRESS] : wsi->cli_hostname_copy;
342342

343-
if (!ads && wsi->stash)
344-
ads = wsi->stash->cis[CIS_ADDRESS];
345-
346343
if (wsi->dns_sorted_list.count) {
347344
struct lws_dll2 *d = lws_dll2_get_head(&wsi->dns_sorted_list);
348345
lws_dns_sort_t *ds = lws_container_of(d, lws_dns_sort_t, list);
@@ -361,6 +358,8 @@ lws_inform_client_conn_fail(struct lws *wsi, void *arg, size_t len)
361358
}
362359
}
363360

361+
if (!ads) ads = host;
362+
364363
if (ads && host && path) {
365364
wsi->tried_quic = 0;
366365
lwsl_wsi_notice(wsi, "QUIC connection failed, falling back to TCP");

lib/core/context.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1626,7 +1626,7 @@ lws_create_context(const struct lws_context_creation_info *info)
16261626
cci.name = "H3CAP";
16271627
cci.max_footprint = 4096;
16281628
cci.max_items = 256;
1629-
cci.max_payload = 8; /* Just an enum */
1629+
cci.max_payload = sizeof(lws_h3_cap_info_t);
16301630

16311631
context->h3_cap_cache = lws_cache_create(&cci);
16321632
if (!context->h3_cap_cache) {

lib/core/private-lib-core.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -443,6 +443,14 @@ typedef enum {
443443
LWS_H3_STATE_FAILED_IGNORE
444444
} lws_h3_state_t;
445445

446+
#define LWS_QUIC_GRACE_DEFAULT_US 2000000
447+
#define LWS_QUIC_GRACE_MARGIN_US 200000
448+
449+
typedef struct {
450+
lws_h3_state_t state;
451+
uint32_t latency_us;
452+
} lws_h3_cap_info_t;
453+
446454
/*
447455
* the rest is managed per-context, that includes
448456
*

lib/roles/h1/ops-h1.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -744,6 +744,7 @@ rops_handle_POLLIN_h1(struct lws_context_per_thread *pt, struct lws *wsi,
744744
return LWS_HPI_RET_PLEASE_CLOSE_ME;
745745
}
746746

747+
lwsl_notice("Calling lws_http_client_socket_service: state %x\n", lwsi_state(wsi));
747748
if (lws_http_client_socket_service(wsi, pollfd))
748749
return LWS_HPI_RET_WSI_ALREADY_DIED;
749750
#endif

lib/roles/http/server/server.c

Lines changed: 28 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -581,30 +581,35 @@ _lws_vhost_init_server(const struct lws_context_creation_info *info,
581581

582582
check_quic:
583583
#if defined(LWS_ROLE_QUIC)
584-
if (!vhost->context->lws_stub &&
585-
LWS_SSL_ENABLED(vhost) &&
586-
!lws_vhost_foreach_listen_wsi(vhost->context, &a, check_extant_quic)) {
587-
584+
{
585+
const char *alpn = vhost->tls.alpn ? vhost->tls.alpn : vhost->context->tls.alpn_default;
586+
if (!vhost->context->lws_stub &&
587+
LWS_SSL_ENABLED(vhost) &&
588+
alpn &&
589+
(strstr(alpn, "h3") || strstr(alpn, "lws-quic")) &&
590+
!lws_vhost_foreach_listen_wsi(vhost->context, &a, check_extant_quic)) {
591+
588592
#if defined(LWS_WITH_IPV6)
589-
if (LWS_IPV6_ENABLED(vhost)) {
590-
const char *ads6 = vhost->iface ? vhost->iface : "::";
591-
if (!lws_create_adopt_udp(vhost, ads6, vhost->listen_port,
592-
LWS_CAUDP_BIND, "quic", vhost->iface, NULL,
593-
NULL, NULL, "quic_listen")) {
594-
lwsl_vhost_err(vhost, "Failed to bind QUIC IPv6 UDP listener");
595-
}
596-
}
597-
#endif
598-
if (!vhost->iface || !LWS_IPV6_ENABLED(vhost) ||
599-
(vhost->options & LWS_SERVER_OPTION_IPV6_V6ONLY_VALUE)) {
600-
const char *ads4 = vhost->iface ? vhost->iface : "0.0.0.0";
601-
if (!lws_create_adopt_udp(vhost, ads4, vhost->listen_port,
602-
LWS_CAUDP_BIND, "quic", vhost->iface, NULL,
603-
NULL, NULL, "quic_listen")) {
604-
lwsl_vhost_err(vhost, "Failed to bind QUIC IPv4 UDP listener");
605-
}
606-
}
607-
}
593+
if (LWS_IPV6_ENABLED(vhost)) {
594+
const char *ads6 = vhost->iface ? vhost->iface : "::";
595+
if (!lws_create_adopt_udp(vhost, ads6, vhost->listen_port,
596+
LWS_CAUDP_BIND, "quic", vhost->iface, NULL,
597+
NULL, NULL, "quic_listen")) {
598+
lwsl_vhost_err(vhost, "Failed to bind QUIC IPv6 UDP listener");
599+
}
600+
}
601+
#endif
602+
if (!vhost->iface || !LWS_IPV6_ENABLED(vhost) ||
603+
(vhost->options & LWS_SERVER_OPTION_IPV6_V6ONLY_VALUE)) {
604+
const char *ads4 = vhost->iface ? vhost->iface : "0.0.0.0";
605+
if (!lws_create_adopt_udp(vhost, ads4, vhost->listen_port,
606+
LWS_CAUDP_BIND, "quic", vhost->iface, NULL,
607+
NULL, NULL, "quic_listen")) {
608+
lwsl_vhost_err(vhost, "Failed to bind QUIC IPv4 UDP listener");
609+
}
610+
}
611+
}
612+
}
608613
#endif
609614
return 0;
610615
}

lib/roles/quic/ops-quic.c

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2259,6 +2259,11 @@ rops_alpn_negotiated_quic(struct lws *wsi, const char *alpn)
22592259
struct lws *nwsi;
22602260
const struct lws_role_ops *role;
22612261

2262+
#if defined(LWS_WITH_CLIENT)
2263+
if (lwsi_role_client(wsi))
2264+
lws_sul_cancel(&wsi->sul_h3_grace);
2265+
#endif
2266+
22622267
if (strcmp(alpn, "h3") && strcmp(alpn, "lws-quic"))
22632268
return 0;
22642269

@@ -2373,11 +2378,9 @@ rops_alpn_negotiated_quic(struct lws *wsi, const char *alpn)
23732378

23742379
#if defined(LWS_WITH_CLIENT)
23752380
/*
2376-
* QUIC succeeded! Resolve the race by cancelling the grace timer
2377-
* and killing parallel TCP connections.
2381+
* QUIC succeeded! Resolve the race by killing parallel TCP connections.
23782382
*/
23792383
if (lwsi_role_client(wsi)) {
2380-
lws_sul_cancel(&wsi->sul_h3_grace);
23812384

23822385
for (int i = 0; i < wsi->parallel_count; i++) {
23832386
if (wsi->parallel_conns[i].is_valid) {
@@ -2387,9 +2390,12 @@ rops_alpn_negotiated_quic(struct lws *wsi, const char *alpn)
23872390
wsi->parallel_count = 0;
23882391

23892392
if (wsi->a.context->h3_cap_cache && wsi->stash && wsi->stash->cis[CIS_HOST]) {
2390-
lws_h3_state_t state = LWS_H3_STATE_KNOWN_GOOD;
2391-
lws_cache_write_through(wsi->a.context->h3_cap_cache, wsi->stash->cis[CIS_HOST],
2392-
(const uint8_t *)&state, sizeof(state),
2393+
lws_h3_cap_info_t cap;
2394+
cap.state = LWS_H3_STATE_KNOWN_GOOD;
2395+
cap.latency_us = (uint32_t)(lws_now_usecs() - wsi->quic.quic_race_start_us);
2396+
2397+
lws_cache_write_through(wsi->a.context->h3_cap_cache, wsi->stash->cis[CIS_HOST],
2398+
(const uint8_t *)&cap, sizeof(cap),
23932399
lws_now_usecs() + (3600ll * LWS_US_PER_SEC), NULL);
23942400
}
23952401
}

0 commit comments

Comments
 (0)