From 732da9850833e36e9203aeadc9e71e7e8aeb41d2 Mon Sep 17 00:00:00 2001 From: M-BELLAHCENE <34917424+M-BELLAHCENE@users.noreply.github.com> Date: Fri, 16 Sep 2022 14:56:16 +0200 Subject: [PATCH 1/9] link fix when using lsquic in a cpp project (#418) Co-authored-by: MBellahcene --- src/liblsquic/lsquic_hash.h | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/liblsquic/lsquic_hash.h b/src/liblsquic/lsquic_hash.h index ccc7c18..325fd1f 100644 --- a/src/liblsquic/lsquic_hash.h +++ b/src/liblsquic/lsquic_hash.h @@ -6,6 +6,10 @@ #ifndef LSQUIC_HASH_H #define LSQUIC_HASH_H +#ifdef __cplusplus +extern "C" { +#endif + struct lsquic_hash; struct lsquic_hash_elem @@ -58,4 +62,9 @@ lsquic_hash_count (struct lsquic_hash *); size_t lsquic_hash_mem_used (const struct lsquic_hash *); + +#ifdef __cplusplus +} +#endif + #endif From c1664a539ba2619f1bd1214033fd19d69863409d Mon Sep 17 00:00:00 2001 From: davidleitw Date: Fri, 16 Sep 2022 21:06:12 +0800 Subject: [PATCH 2/9] Remove redundant include (#414) --- src/liblsquic/lsquic_engine.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/liblsquic/lsquic_engine.c b/src/liblsquic/lsquic_engine.c index 0202e74..734abb9 100644 --- a/src/liblsquic/lsquic_engine.c +++ b/src/liblsquic/lsquic_engine.c @@ -86,7 +86,6 @@ #include "lsquic_handshake.h" #include "lsquic_crand.h" #include "lsquic_ietf.h" -#include "lsquic_handshake.h" #define LSQUIC_LOGGER_MODULE LSQLM_ENGINE #include "lsquic_logger.h" From a4aac3901318dac95a394632d4886a55a5ff2bf7 Mon Sep 17 00:00:00 2001 From: wangfuyu Date: Tue, 20 Sep 2022 22:29:10 +0800 Subject: [PATCH 3/9] m) Fix: ietf connection maybe abort if ack for hsk lost (#422) 1) After handshake done, handshake packets should not be sent or received. 2) IFC_ACK_QUED_HSK will be cancelled from conn->ifc_flags after handshake done, but it maybe set again if ACKs for handshake lost(Function: should_generate_ack). Co-authored-by: ivanfywang --- src/liblsquic/lsquic_full_conn_ietf.c | 2 +- src/liblsquic/lsquic_send_ctl.c | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/liblsquic/lsquic_full_conn_ietf.c b/src/liblsquic/lsquic_full_conn_ietf.c index c8c9575..e409d48 100644 --- a/src/liblsquic/lsquic_full_conn_ietf.c +++ b/src/liblsquic/lsquic_full_conn_ietf.c @@ -1886,7 +1886,7 @@ generate_ack_frame_for_pns (struct ietf_full_conn *conn, &conn->ifc_rechist[pns], now, &has_missing, &packet_out->po_ack2ed, ecn_counts); if (w < 0) { - ABORT_ERROR("generating ACK frame failed: %d", errno); + ABORT_ERROR("%s generating ACK frame failed: %d", lsquic_pns2str[pns], errno); return -1; } CONN_STATS(out.acks, 1); diff --git a/src/liblsquic/lsquic_send_ctl.c b/src/liblsquic/lsquic_send_ctl.c index 70a291e..7d2861d 100644 --- a/src/liblsquic/lsquic_send_ctl.c +++ b/src/liblsquic/lsquic_send_ctl.c @@ -3424,6 +3424,8 @@ lsquic_send_ctl_empty_pns (struct lsquic_send_ctl *ctl, enum packnum_space pns) lsquic_alarmset_unset(ctl->sc_alset, AL_RETX_INIT + pns); + ctl->sc_flags &= ~(SC_LOST_ACK_INIT << pns); + LSQ_DEBUG("emptied %s, destroyed %u packet%.*s", lsquic_pns2str[pns], count, count != 1, "s"); } From d5602cd335d40c345d4b674183f4bedb3138f03d Mon Sep 17 00:00:00 2001 From: M-BELLAHCENE <34917424+M-BELLAHCENE@users.noreply.github.com> Date: Tue, 20 Sep 2022 16:36:21 +0200 Subject: [PATCH 4/9] LSQUIC_TESTS=OFF, LSQUIC_BIN=OFF : Remove getopt.h error : Build will succeed. (#420) * link fix when using lsquic in a cpp project * Update CMakeLists.txt Co-authored-by: MBellahcene --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index db5c8a2..fa9daa2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -232,7 +232,7 @@ IF(CMAKE_SYSTEM_NAME STREQUAL "FreeBSD" OR CMAKE_SYSTEM_NAME STREQUAL "Darwin") ENDIF() IF (CMAKE_SYSTEM_NAME STREQUAL Windows) - FIND_PATH(GETOPT_INCLUDE_DIR NAMES getopt.h) + FIND_PATH(GETOPT_INCLUDE_DIR NAMES getopt.h AND LSQUIC_TESTS AND LSQUIC_BIN) IF (GETOPT_INCLUDE_DIR) INCLUDE_DIRECTORIES(${GETOPT_INCLUDE_DIR}) ELSE() From a5b89b62b554a06728837daec41a554f5cf235e3 Mon Sep 17 00:00:00 2001 From: Pluto Date: Wed, 21 Sep 2022 01:44:39 +0800 Subject: [PATCH 5/9] [fix] assertion failure if poison packet was acked (#416) Description: - Error may occur while processing ack frame, e.g. poison packet was acked by hostile attack. and then conn is supposed to be aborted, shortly but not immediately; - if ack frame processing failed while calling lsquic_engine_packet_in, and IFC_HAVE_SAVED_ACK had been set, then saved ack frame will be processed while ticking connection before it is aborted, that may lead to assert failure; Solution: - close connection if neccessary before processing ack while ci_tick. --- src/liblsquic/lsquic_full_conn.c | 2 ++ src/liblsquic/lsquic_full_conn_ietf.c | 2 ++ 2 files changed, 4 insertions(+) diff --git a/src/liblsquic/lsquic_full_conn.c b/src/liblsquic/lsquic_full_conn.c index 81632dd..4ec7027 100644 --- a/src/liblsquic/lsquic_full_conn.c +++ b/src/liblsquic/lsquic_full_conn.c @@ -3411,6 +3411,8 @@ full_conn_ci_tick (lsquic_conn_t *lconn, lsquic_time_t now) ++conn->fc_stats.n_ticks; #endif + CLOSE_IF_NECESSARY(); + if (LSQ_LOG_ENABLED(LSQ_LOG_DEBUG) && conn->fc_mem_logged_last + 1000000 <= now) { diff --git a/src/liblsquic/lsquic_full_conn_ietf.c b/src/liblsquic/lsquic_full_conn_ietf.c index e409d48..2910a62 100644 --- a/src/liblsquic/lsquic_full_conn_ietf.c +++ b/src/liblsquic/lsquic_full_conn_ietf.c @@ -8201,6 +8201,8 @@ ietf_full_conn_ci_tick (struct lsquic_conn *lconn, lsquic_time_t now) CONN_STATS(n_ticks, 1); + CLOSE_IF_NECESSARY(); + if (conn->ifc_flags & IFC_HAVE_SAVED_ACK) { (void) /* If there is an error, we'll fail shortly */ From 5c669eea5030f4120fba2de699a8d7e1d7d90489 Mon Sep 17 00:00:00 2001 From: wangfuyu Date: Thu, 29 Sep 2022 21:04:15 +0800 Subject: [PATCH 6/9] m) Fix: compile test_rechist error (#425) error: 'for' loop initial declarations are only allowed in C99 mode Co-authored-by: wangfuyu --- tests/test_rechist.c | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/tests/test_rechist.c b/tests/test_rechist.c index 0c56496..abfbf4f 100644 --- a/tests/test_rechist.c +++ b/tests/test_rechist.c @@ -205,31 +205,32 @@ test6 (void) lsquic_rechist_t rechist; char buf[256]; long int time = 12087061905875; - + unsigned i; + lsquic_rechist_init(&rechist, 0, 0); - - for (int i = 0; i <= 3; i++) - lsquic_rechist_received(&rechist, i, (time += (i*10))); + + for (i = 0; i <= 3; i++) + lsquic_rechist_received(&rechist, i, (time += (i * 10))); lsquic_rechist_stop_wait(&rechist, 2); - + lsquic_rechist_received(&rechist, 4, (time += 10)); - + lsquic_rechist_stop_wait(&rechist, 3); - + lsquic_rechist_received(&rechist, 5, (time += 10)); - + lsquic_rechist_stop_wait(&rechist, 3); - + lsquic_rechist_received(&rechist, 6, (time += 10)); - + lsquic_rechist_stop_wait(&rechist, 9); - + lsquic_rechist_received(&rechist, 7, (time += 10)); lsquic_rechist_received(&rechist, 8, (time += 10)); lsquic_rechist_received(&rechist, 9, (time += 10)); rechist2str(&rechist, buf, sizeof(buf)); - + lsquic_rechist_cleanup(&rechist); } From 108c4e7629a8c10b9a73e3d95be0a1652e620fb9 Mon Sep 17 00:00:00 2001 From: M-BELLAHCENE <34917424+M-BELLAHCENE@users.noreply.github.com> Date: Thu, 29 Sep 2022 15:15:30 +0200 Subject: [PATCH 7/9] fix useless getopt.h check (#424) * link fix when using lsquic in a cpp project * Update CMakeLists.txt * Fix getopt.h error when not needed Co-authored-by: MBellahcene --- CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index fa9daa2..984f38f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -231,8 +231,8 @@ IF(CMAKE_SYSTEM_NAME STREQUAL "FreeBSD" OR CMAKE_SYSTEM_NAME STREQUAL "Darwin") link_directories( /usr/local/lib ) ENDIF() -IF (CMAKE_SYSTEM_NAME STREQUAL Windows) - FIND_PATH(GETOPT_INCLUDE_DIR NAMES getopt.h AND LSQUIC_TESTS AND LSQUIC_BIN) +IF (CMAKE_SYSTEM_NAME STREQUAL Windows AND LSQUIC_TESTS AND LSQUIC_BIN) + FIND_PATH(GETOPT_INCLUDE_DIR NAMES getopt.h) IF (GETOPT_INCLUDE_DIR) INCLUDE_DIRECTORIES(${GETOPT_INCLUDE_DIR}) ELSE() From 8391f907f45ea8feaac4edefc78cff5d80c49bca Mon Sep 17 00:00:00 2001 From: wangfuyu Date: Thu, 13 Oct 2022 04:21:29 +0800 Subject: [PATCH 8/9] m) Fix: packet_in pool memory leak (#426) [Reproduce] http_client POST large body request to http_server, like: http_client -H quic.test.com -s ${SERVER_ADDR}:${SERVER_PORT} -p /1KB_char.txt -M POST -P /test/quic-data/html/10KB_char.txt -o version=h3 -n 100 -r 50000000 -R 500 -w 10 -K [Notes] [RFC5116 AEAD] Section 5.1 An authentication tag with a length of 16 octets (128bits) is used. [RFC9001 QUIC-TLS] Section 5.3 These cipher suites have a 16-byte authentication tag and produce an output 16 bytes larger than their input. Co-authored-by: wangfuyu --- src/liblsquic/lsquic_enc_sess_ietf.c | 11 ++++- src/liblsquic/lsquic_engine.c | 46 ++++++++++++++++++ src/liblsquic/lsquic_mm.c | 70 ++++++++++++++++++++++++---- src/liblsquic/lsquic_mm.h | 1 + 4 files changed, 118 insertions(+), 10 deletions(-) diff --git a/src/liblsquic/lsquic_enc_sess_ietf.c b/src/liblsquic/lsquic_enc_sess_ietf.c index 726f96c..ee6d3d4 100644 --- a/src/liblsquic/lsquic_enc_sess_ietf.c +++ b/src/liblsquic/lsquic_enc_sess_ietf.c @@ -2243,7 +2243,16 @@ iquic_esf_decrypt_packet (enc_session_t *enc_session_p, size_t out_sz; enum dec_packin dec_packin; int s; - const size_t dst_sz = packet_in->pi_data_sz; + /* 16Bytes: AEAD authentication tag + * + * [RFC5116 AEAD] Section 5.1 + * An authentication tag with a length of 16 octets (128bits) is used. + * + * [RFC9001 QUIC-TLS] Section 5.3 + * These cipher suites have a 16-byte authentication tag and + * produce an output 16 bytes larger than their input. + */ + const size_t dst_sz = packet_in->pi_data_sz - 16; unsigned char new_secret[EVP_MAX_KEY_LENGTH]; struct crypto_ctx crypto_ctx_buf; char secret_str[EVP_MAX_KEY_LENGTH * 2 + 1]; diff --git a/src/liblsquic/lsquic_engine.c b/src/liblsquic/lsquic_engine.c index 734abb9..7161f20 100644 --- a/src/liblsquic/lsquic_engine.c +++ b/src/liblsquic/lsquic_engine.c @@ -261,6 +261,7 @@ struct lsquic_engine unsigned n_conns; lsquic_time_t deadline; lsquic_time_t resume_sending_at; + lsquic_time_t mem_logged_last; unsigned mini_conns_count; struct lsquic_purga *purga; #if LSQUIC_CONN_STATS @@ -960,6 +961,51 @@ destroy_conn (struct lsquic_engine *engine, struct lsquic_conn *conn, --engine->n_conns; conn->cn_flags |= LSCONN_NEVER_TICKABLE; conn->cn_if->ci_destroy(conn); + + if (LSQ_LOG_ENABLED(LSQ_LOG_DEBUG) /* log period: 10s */ + && ((engine->mem_logged_last + 10000000 <= now) || (engine->n_conns == 0))) + { +#define MAX_MM_STAT_LOG 4096 + unsigned cur = 0; + unsigned ret = 0; + unsigned idx = 0; + char mm_log[MAX_MM_STAT_LOG] = {0}; + struct pool_stats *poolst = NULL; + + engine->mem_logged_last = now; + + ret = snprintf(mm_log + cur, MAX_MM_STAT_LOG - cur, + "%p, conns: %u, mini_conns: %u. mm_stat, used: %zu" + ", pool(calls-objs_all-objs_out-max-avg-var), pib", + engine, engine->n_conns, engine->mini_conns_count, + lsquic_mm_mem_used(&engine->pub.enp_mm)); + cur += ret; + + for (idx = 0; idx < MM_N_IN_BUCKETS && cur < MAX_MM_STAT_LOG; idx++) + { + poolst = &engine->pub.enp_mm.packet_in_bstats[idx]; + ret = snprintf(mm_log + cur, MAX_MM_STAT_LOG - cur, + ": [%u]%u-%u-%u-%u-%u-%u", idx, + poolst->ps_calls, poolst->ps_objs_all, poolst->ps_objs_out, + poolst->ps_max, poolst->ps_max_avg, poolst->ps_max_var); + cur += ret; + } + + ret = snprintf(mm_log + cur, MAX_MM_STAT_LOG - cur, ", pob"); + cur += ret; + + for (idx = 0; idx < MM_N_OUT_BUCKETS && cur < MAX_MM_STAT_LOG; idx++) + { + poolst = &engine->pub.enp_mm.packet_out_bstats[idx]; + ret = snprintf(mm_log + cur, MAX_MM_STAT_LOG - cur, + ": [%u]%u-%u-%u-%u-%u-%u", idx, + poolst->ps_calls, poolst->ps_objs_all, poolst->ps_objs_out, + poolst->ps_max, poolst->ps_max_avg, poolst->ps_max_var); + cur += ret; + } + + LSQ_DEBUG("%s", mm_log); + } } diff --git a/src/liblsquic/lsquic_mm.c b/src/liblsquic/lsquic_mm.c index 3315ebb..6d82a5c 100644 --- a/src/liblsquic/lsquic_mm.c +++ b/src/liblsquic/lsquic_mm.c @@ -192,21 +192,15 @@ void lsquic_mm_put_packet_in (struct lsquic_mm *mm, struct lsquic_packet_in *packet_in) { -#if LSQUIC_USE_POOLS - unsigned idx; - struct packet_in_buf *pib; - assert(0 == packet_in->pi_refcnt); if (packet_in->pi_flags & PI_OWN_DATA) { - pib = (struct packet_in_buf *) packet_in->pi_data; - idx = packet_in_index(packet_in->pi_data_sz); - SLIST_INSERT_HEAD(&mm->packet_in_bufs[idx], pib, next_pib); + lsquic_mm_put_packet_in_buf(mm, packet_in->pi_data, packet_in->pi_data_sz); } + +#if LSQUIC_USE_POOLS TAILQ_INSERT_HEAD(&mm->free_packets_in, packet_in, pi_next); #else - if (packet_in->pi_flags & PI_OWN_DATA) - free(packet_in->pi_data); lsquic_malo_put(packet_in); #endif } @@ -370,6 +364,42 @@ maybe_shrink_packet_out_bufs (struct lsquic_mm *mm, unsigned idx) #endif +/* If average maximum falls under 1/4 of all objects allocated, release + * half of the objects allocated. + */ +static void +maybe_shrink_packet_in_bufs (struct lsquic_mm *mm, unsigned idx) +{ + struct pool_stats *poolst; + struct packet_in_buf *pib; + unsigned n_to_leave; + + poolst = &mm->packet_in_bstats[idx]; + if (poolst->ps_max_avg * 4 < poolst->ps_objs_all) + { + n_to_leave = poolst->ps_objs_all / 2; + while (poolst->ps_objs_all > n_to_leave + && (pib = SLIST_FIRST(&mm->packet_in_bufs[idx]))) + { + SLIST_REMOVE_HEAD(&mm->packet_in_bufs[idx], next_pib); + free(pib); + --poolst->ps_objs_all; + } +#if LSQUIC_LOG_POOL_STATS + LSQ_DEBUG("pib pool #%u; max avg %u; shrank from %u to %u objs", + idx, poolst->ps_max_avg, n_to_leave * 2, poolst->ps_objs_all); +#endif + } +#if LSQUIC_LOG_POOL_STATS + else + { + LSQ_DEBUG("pib pool #%u; max avg %u; objs: %u; won't shrink", + idx, poolst->ps_max_avg, poolst->ps_objs_all); + } +#endif +} + + void lsquic_mm_put_packet_out (struct lsquic_mm *mm, struct lsquic_packet_out *packet_out) @@ -456,9 +486,25 @@ lsquic_mm_get_packet_in_buf (struct lsquic_mm *mm, size_t size) pib = SLIST_FIRST(&mm->packet_in_bufs[idx]); fiu_do_on("mm/packet_in_buf", FAIL_NOMEM); if (pib) + { SLIST_REMOVE_HEAD(&mm->packet_in_bufs[idx], next_pib); + poolst_allocated(&mm->packet_in_bstats[idx], 0); + } else + { pib = malloc(packet_in_sizes[idx]); + if (!pib) + { + return NULL; + } + + poolst_allocated(&mm->packet_in_bstats[idx], 1); + } + + if (poolst_has_new_sample(&mm->packet_in_bstats[idx])) + { + maybe_shrink_packet_in_bufs(mm, idx); + } #else pib = malloc(size); #endif @@ -476,6 +522,12 @@ lsquic_mm_put_packet_in_buf (struct lsquic_mm *mm, void *mem, size_t size) pib = (struct packet_in_buf *) mem; idx = packet_in_index(size); SLIST_INSERT_HEAD(&mm->packet_in_bufs[idx], pib, next_pib); + + poolst_freed(&mm->packet_in_bstats[idx]); + if (poolst_has_new_sample(&mm->packet_in_bstats[idx])) + { + maybe_shrink_packet_in_bufs(mm, idx); + } #else free(mem); #endif diff --git a/src/liblsquic/lsquic_mm.h b/src/liblsquic/lsquic_mm.h index 01c1fbb..f949691 100644 --- a/src/liblsquic/lsquic_mm.h +++ b/src/liblsquic/lsquic_mm.h @@ -44,6 +44,7 @@ struct lsquic_mm { TAILQ_HEAD(, lsquic_packet_in) free_packets_in; SLIST_HEAD(, packet_out_buf) packet_out_bufs[MM_N_OUT_BUCKETS]; struct pool_stats packet_out_bstats[MM_N_OUT_BUCKETS]; + struct pool_stats packet_in_bstats[MM_N_IN_BUCKETS]; SLIST_HEAD(, packet_in_buf) packet_in_bufs[MM_N_IN_BUCKETS]; SLIST_HEAD(, four_k_page) four_k_pages; SLIST_HEAD(, sixteen_k_page) sixteen_k_pages; From def7d956d68f7e7f50209762dc69f344f74cf33b Mon Sep 17 00:00:00 2001 From: wangfuyu Date: Thu, 13 Oct 2022 20:34:04 +0800 Subject: [PATCH 9/9] m) Fix: http1x memory leak (#427) [Reproduce] http_client send GET/POST request with large headers(val_len > 256Bytes) to http_server, like: http_client -H quic.test.com -s ${SERVER_ADDR}:${SERVER_PORT} -p "/test/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" -o version=h3 -n 1 -r 100 -R 100 Co-authored-by: wangfuyu --- src/liblsquic/lsquic_http1x_if.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/liblsquic/lsquic_http1x_if.c b/src/liblsquic/lsquic_http1x_if.c index 8710017..77e78b4 100644 --- a/src/liblsquic/lsquic_http1x_if.c +++ b/src/liblsquic/lsquic_http1x_if.c @@ -527,12 +527,23 @@ h1h_prepare_decode (void *hset, struct lsxpack_header *xhdr, size_t req_space) if (0 == hwc->hwc_header_buf_nalloc || req_space > hwc->hwc_header_buf_nalloc) { - buf = malloc(req_space); + if (0 == hwc->hwc_header_buf_nalloc) + { + buf = malloc(req_space); + } + else + { + buf = realloc(hwc->hwc_xhdr.buf, req_space); + } + if (!buf) { - LSQ_DEBUG("cannot allocate %zd bytes", req_space); + LSQ_WARN("cannot %s %zd bytes", + hwc->hwc_header_buf_nalloc ? "reallocate to" : "allocate", req_space); return NULL; } + + hwc->hwc_xhdr.buf = buf; hwc->hwc_header_buf_nalloc = req_space; } else