diff --git a/CMakeLists.txt b/CMakeLists.txt index db5c8a2..984f38f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -231,7 +231,7 @@ IF(CMAKE_SYSTEM_NAME STREQUAL "FreeBSD" OR CMAKE_SYSTEM_NAME STREQUAL "Darwin") link_directories( /usr/local/lib ) ENDIF() -IF (CMAKE_SYSTEM_NAME STREQUAL Windows) +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}) 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 0202e74..7161f20 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" @@ -262,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 @@ -961,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_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 c8c9575..2910a62 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); @@ -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 */ 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 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 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; 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"); } 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); }