lsquic_engine.c revision 72585dc9
1/* Copyright (c) 2017 - 2020 LiteSpeed Technologies Inc. See LICENSE. */ 2/* 3 * lsquic_engine.c - QUIC engine 4 */ 5 6#include <assert.h> 7#include <errno.h> 8#include <inttypes.h> 9#include <limits.h> 10#include <stdint.h> 11#include <stdio.h> 12#include <stdlib.h> 13#include <string.h> 14#include <sys/queue.h> 15#include <time.h> 16#ifndef WIN32 17#include <sys/time.h> 18#include <netinet/in.h> 19#include <sys/types.h> 20#include <sys/stat.h> 21#include <fcntl.h> 22#include <unistd.h> 23#include <netdb.h> 24#endif 25 26#ifndef NDEBUG 27#include <sys/types.h> 28#include <regex.h> /* For code that loses packets */ 29#endif 30 31#if LOG_PACKET_CHECKSUM 32#include <zlib.h> 33#endif 34 35#include <openssl/aead.h> 36 37#include "lsquic.h" 38#include "lsquic_types.h" 39#include "lsquic_int_types.h" 40#include "lsquic_sizes.h" 41#include "lsquic_parse_common.h" 42#include "lsquic_parse.h" 43#include "lsquic_packet_in.h" 44#include "lsquic_packet_out.h" 45#include "lsquic_senhist.h" 46#include "lsquic_rtt.h" 47#include "lsquic_cubic.h" 48#include "lsquic_pacer.h" 49#include "lsquic_bw_sampler.h" 50#include "lsquic_minmax.h" 51#include "lsquic_bbr.h" 52#include "lsquic_send_ctl.h" 53#include "lsquic_set.h" 54#include "lsquic_conn_flow.h" 55#include "lsquic_sfcw.h" 56#include "lsquic_hash.h" 57#include "lsquic_conn.h" 58#include "lsquic_full_conn.h" 59#include "lsquic_util.h" 60#include "lsquic_qtags.h" 61#include "lsquic_enc_sess.h" 62#include "lsquic_mm.h" 63#include "lsquic_engine_public.h" 64#include "lsquic_eng_hist.h" 65#include "lsquic_ev_log.h" 66#include "lsquic_version.h" 67#include "lsquic_pr_queue.h" 68#include "lsquic_mini_conn.h" 69#include "lsquic_mini_conn_ietf.h" 70#include "lsquic_stock_shi.h" 71#include "lsquic_purga.h" 72#include "lsquic_tokgen.h" 73#include "lsquic_attq.h" 74#include "lsquic_min_heap.h" 75#include "lsquic_http1x_if.h" 76#include "lsquic_handshake.h" 77#include "lsquic_crand.h" 78#include "lsquic_ietf.h" 79 80#define LSQUIC_LOGGER_MODULE LSQLM_ENGINE 81#include "lsquic_logger.h" 82 83#ifndef LSQUIC_DEBUG_NEXT_ADV_TICK 84#define LSQUIC_DEBUG_NEXT_ADV_TICK 1 85#endif 86 87#if LSQUIC_DEBUG_NEXT_ADV_TICK 88#include "lsquic_alarmset.h" 89#endif 90 91#define MIN(a, b) ((a) < (b) ? (a) : (b)) 92 93/* The batch of outgoing packets grows and shrinks dynamically */ 94#define MAX_OUT_BATCH_SIZE 1024 95#define MIN_OUT_BATCH_SIZE 4 96#define INITIAL_OUT_BATCH_SIZE 32 97 98struct out_batch 99{ 100 lsquic_conn_t *conns [MAX_OUT_BATCH_SIZE]; 101 struct lsquic_out_spec outs [MAX_OUT_BATCH_SIZE]; 102 unsigned pack_off[MAX_OUT_BATCH_SIZE]; 103 lsquic_packet_out_t *packets[MAX_OUT_BATCH_SIZE * 2]; 104 struct iovec iov [MAX_OUT_BATCH_SIZE * 2]; 105}; 106 107typedef struct lsquic_conn * (*conn_iter_f)(struct lsquic_engine *); 108 109static void 110process_connections (struct lsquic_engine *engine, conn_iter_f iter, 111 lsquic_time_t now); 112 113static void 114engine_incref_conn (lsquic_conn_t *conn, enum lsquic_conn_flags flag); 115 116static lsquic_conn_t * 117engine_decref_conn (lsquic_engine_t *engine, lsquic_conn_t *conn, 118 enum lsquic_conn_flags flag); 119 120static void 121force_close_conn (lsquic_engine_t *engine, lsquic_conn_t *conn); 122 123#if LSQUIC_COUNT_ENGINE_CALLS 124#define ENGINE_CALLS_INCR(e) do { ++(e)->n_engine_calls; } while (0) 125#else 126#define ENGINE_CALLS_INCR(e) 127#endif 128 129/* Nested calls to LSQUIC are not supported */ 130#define ENGINE_IN(e) do { \ 131 assert(!((e)->pub.enp_flags & ENPUB_PROC)); \ 132 (e)->pub.enp_flags |= ENPUB_PROC; \ 133 ENGINE_CALLS_INCR(e); \ 134} while (0) 135 136#define ENGINE_OUT(e) do { \ 137 assert((e)->pub.enp_flags & ENPUB_PROC); \ 138 (e)->pub.enp_flags &= ~ENPUB_PROC; \ 139} while (0) 140 141/* A connection can be referenced from one of six places: 142 * 143 * 1. A hash is used to find connections in order to dispatch an incoming 144 * packet. Connections can be hashed by CIDs or by address. In the 145 * former case, each connection has one or more mappings in the hash 146 * table. IETF QUIC connections have up to eight (in our implementation) 147 * source CIDs and each of those would have a mapping. In client mode, 148 * depending on QUIC versions and options selected, it is may be 149 * necessary to hash connections by address, in which case incoming 150 * packets are delivered to connections based on the address. 151 * 152 * 2. Outgoing queue. 153 * 154 * 3. Tickable queue 155 * 156 * 4. Advisory Tick Time queue. 157 * 158 * 5. Closing connections queue. This is a transient queue -- it only 159 * exists for the duration of process_connections() function call. 160 * 161 * 6. Ticked connections queue. Another transient queue, similar to (5). 162 * 163 * The idea is to destroy the connection when it is no longer referenced. 164 * For example, a connection tick may return TICK_SEND|TICK_CLOSE. In 165 * that case, the connection is referenced from two places: (2) and (5). 166 * After its packets are sent, it is only referenced in (5), and at the 167 * end of the function call, when it is removed from (5), reference count 168 * goes to zero and the connection is destroyed. If not all packets can 169 * be sent, at the end of the function call, the connection is referenced 170 * by (2) and will only be removed once all outgoing packets have been 171 * sent. 172 */ 173#define CONN_REF_FLAGS (LSCONN_HASHED \ 174 |LSCONN_HAS_OUTGOING \ 175 |LSCONN_TICKABLE \ 176 |LSCONN_TICKED \ 177 |LSCONN_CLOSING \ 178 |LSCONN_ATTQ) 179 180 181 182 183struct cid_update_batch 184{ 185 lsquic_cids_update_f cub_update_cids; 186 void *cub_update_ctx; 187 unsigned cub_count; 188 lsquic_cid_t cub_cids[20]; 189 void *cub_peer_ctxs[20]; 190}; 191 192static void 193cub_init (struct cid_update_batch *, lsquic_cids_update_f, void *); 194 195 196struct lsquic_engine 197{ 198 struct lsquic_engine_public pub; 199 enum { 200 ENG_SERVER = LSENG_SERVER, 201 ENG_HTTP = LSENG_HTTP, 202 ENG_COOLDOWN = (1 << 7), /* Cooldown: no new connections */ 203 ENG_PAST_DEADLINE 204 = (1 << 8), /* Previous call to a processing 205 * function went past time threshold. 206 */ 207 ENG_CONNS_BY_ADDR 208 = (1 << 9), /* Connections are hashed by address */ 209#ifndef NDEBUG 210 ENG_COALESCE = (1 << 24), /* Packet coalescing is enabled */ 211 ENG_LOSE_PACKETS= (1 << 25), /* Lose *some* outgoing packets */ 212 ENG_DTOR = (1 << 26), /* Engine destructor */ 213#endif 214 } flags; 215 lsquic_packets_out_f packets_out; 216 void *packets_out_ctx; 217 lsquic_cids_update_f report_new_scids; 218 lsquic_cids_update_f report_live_scids; 219 lsquic_cids_update_f report_old_scids; 220 void *scids_ctx; 221 struct lsquic_hash *conns_hash; 222 struct min_heap conns_tickable; 223 struct min_heap conns_out; 224 struct eng_hist history; 225 unsigned batch_size; 226 struct pr_queue *pr_queue; 227 struct attq *attq; 228 /* Track time last time a packet was sent to give new connections 229 * priority lower than that of existing connections. 230 */ 231 lsquic_time_t last_sent; 232#ifndef NDEBUG 233 regex_t lose_packets_re; 234 const char *lose_packets_str; 235#endif 236 unsigned n_conns; 237 lsquic_time_t deadline; 238 lsquic_time_t resume_sending_at; 239 unsigned mini_conns_count; 240 struct lsquic_purga *purga; 241#if LSQUIC_CONN_STATS 242 struct { 243 unsigned conns; 244 } stats; 245 struct conn_stats conn_stats_sum; 246 FILE *stats_fh; 247#endif 248 struct cid_update_batch new_scids; 249 struct out_batch out_batch; 250#if LSQUIC_COUNT_ENGINE_CALLS 251 unsigned long n_engine_calls; 252#endif 253#if LSQUIC_DEBUG_NEXT_ADV_TICK 254 uintptr_t last_logged_conn; 255 unsigned last_logged_ae_why; 256 int last_tick_diff; 257#endif 258 struct crand crand; 259 EVP_AEAD_CTX retry_aead_ctx; 260}; 261 262 263void 264lsquic_engine_init_settings (struct lsquic_engine_settings *settings, 265 unsigned flags) 266{ 267 memset(settings, 0, sizeof(*settings)); 268 settings->es_versions = LSQUIC_DF_VERSIONS; 269 if (flags & ENG_SERVER) 270 { 271 settings->es_cfcw = LSQUIC_DF_CFCW_SERVER; 272 settings->es_sfcw = LSQUIC_DF_SFCW_SERVER; 273 settings->es_init_max_data 274 = LSQUIC_DF_INIT_MAX_DATA_SERVER; 275 settings->es_init_max_stream_data_bidi_remote 276 = LSQUIC_DF_INIT_MAX_STREAM_DATA_BIDI_REMOTE_SERVER; 277 settings->es_init_max_stream_data_bidi_local 278 = LSQUIC_DF_INIT_MAX_STREAM_DATA_BIDI_LOCAL_SERVER; 279 settings->es_init_max_stream_data_uni 280 = LSQUIC_DF_INIT_MAX_STREAM_DATA_UNI_SERVER; 281 settings->es_init_max_streams_uni 282 = LSQUIC_DF_INIT_MAX_STREAMS_UNI_SERVER; 283 settings->es_ping_period = 0; 284 } 285 else 286 { 287 settings->es_cfcw = LSQUIC_DF_CFCW_CLIENT; 288 settings->es_sfcw = LSQUIC_DF_SFCW_CLIENT; 289 settings->es_init_max_data 290 = LSQUIC_DF_INIT_MAX_DATA_CLIENT; 291 settings->es_init_max_stream_data_bidi_remote 292 = LSQUIC_DF_INIT_MAX_STREAM_DATA_BIDI_REMOTE_CLIENT; 293 settings->es_init_max_stream_data_bidi_local 294 = LSQUIC_DF_INIT_MAX_STREAM_DATA_BIDI_LOCAL_CLIENT; 295 settings->es_init_max_stream_data_uni 296 = LSQUIC_DF_INIT_MAX_STREAM_DATA_UNI_CLIENT; 297 settings->es_init_max_streams_uni 298 = LSQUIC_DF_INIT_MAX_STREAMS_UNI_CLIENT; 299 settings->es_ping_period = LSQUIC_DF_PING_PERIOD; 300 } 301 settings->es_max_streams_in = LSQUIC_DF_MAX_STREAMS_IN; 302 settings->es_idle_conn_to = LSQUIC_DF_IDLE_CONN_TO; 303 settings->es_idle_timeout = LSQUIC_DF_IDLE_TIMEOUT; 304 settings->es_handshake_to = LSQUIC_DF_HANDSHAKE_TO; 305 settings->es_silent_close = LSQUIC_DF_SILENT_CLOSE; 306 settings->es_max_header_list_size 307 = LSQUIC_DF_MAX_HEADER_LIST_SIZE; 308 settings->es_ua = LSQUIC_DF_UA; 309 settings->es_ecn = LSQUIC_DF_ECN; 310 311 settings->es_pdmd = QTAG_X509; 312 settings->es_aead = QTAG_AESG; 313 settings->es_kexs = QTAG_C255; 314 settings->es_support_push = LSQUIC_DF_SUPPORT_PUSH; 315 settings->es_support_tcid0 = LSQUIC_DF_SUPPORT_TCID0; 316 settings->es_support_nstp = LSQUIC_DF_SUPPORT_NSTP; 317 settings->es_honor_prst = LSQUIC_DF_HONOR_PRST; 318 settings->es_progress_check = LSQUIC_DF_PROGRESS_CHECK; 319 settings->es_rw_once = LSQUIC_DF_RW_ONCE; 320 settings->es_proc_time_thresh= LSQUIC_DF_PROC_TIME_THRESH; 321 settings->es_pace_packets = LSQUIC_DF_PACE_PACKETS; 322 settings->es_clock_granularity = LSQUIC_DF_CLOCK_GRANULARITY; 323 settings->es_max_inchoate = LSQUIC_DF_MAX_INCHOATE; 324 settings->es_send_prst = LSQUIC_DF_SEND_PRST; 325 settings->es_sttl = LSQUIC_DF_STTL; 326 settings->es_init_max_streams_bidi 327 = LSQUIC_DF_INIT_MAX_STREAMS_BIDI; 328 settings->es_scid_len = LSQUIC_DF_SCID_LEN; 329 settings->es_scid_iss_rate = LSQUIC_DF_SCID_ISS_RATE; 330 settings->es_qpack_dec_max_size = LSQUIC_DF_QPACK_DEC_MAX_SIZE; 331 settings->es_qpack_dec_max_blocked = LSQUIC_DF_QPACK_DEC_MAX_BLOCKED; 332 settings->es_qpack_enc_max_size = LSQUIC_DF_QPACK_ENC_MAX_SIZE; 333 settings->es_qpack_enc_max_blocked = LSQUIC_DF_QPACK_ENC_MAX_BLOCKED; 334 settings->es_allow_migration = LSQUIC_DF_ALLOW_MIGRATION; 335 settings->es_ql_bits = LSQUIC_DF_QL_BITS; 336 settings->es_spin = LSQUIC_DF_SPIN; 337 settings->es_delayed_acks = LSQUIC_DF_DELAYED_ACKS; 338 settings->es_timestamps = LSQUIC_DF_TIMESTAMPS; 339} 340 341 342/* Note: if returning an error, err_buf must be valid if non-NULL */ 343int 344lsquic_engine_check_settings (const struct lsquic_engine_settings *settings, 345 unsigned flags, 346 char *err_buf, size_t err_buf_sz) 347{ 348 if (settings->es_cfcw < LSQUIC_MIN_FCW || 349 settings->es_sfcw < LSQUIC_MIN_FCW) 350 { 351 if (err_buf) 352 snprintf(err_buf, err_buf_sz, "%s", 353 "flow control window set too low"); 354 return -1; 355 } 356 if (0 == (settings->es_versions & LSQUIC_SUPPORTED_VERSIONS)) 357 { 358 if (err_buf) 359 snprintf(err_buf, err_buf_sz, "%s", 360 "No supported QUIC versions specified"); 361 return -1; 362 } 363 if (settings->es_versions & ~LSQUIC_SUPPORTED_VERSIONS) 364 { 365 if (err_buf) 366 snprintf(err_buf, err_buf_sz, "%s", 367 "one or more unsupported QUIC version is specified"); 368 return -1; 369 } 370 if (flags & ENG_SERVER) 371 { 372 if (settings->es_handshake_to > 373 MAX_MINI_CONN_LIFESPAN_IN_USEC) 374 { 375 if (err_buf) 376 snprintf(err_buf, err_buf_sz, "handshake timeout %lu" 377 " usec is too large. The maximum for server is %u usec", 378 settings->es_handshake_to, MAX_MINI_CONN_LIFESPAN_IN_USEC); 379 return -1; 380 } 381 } 382 if (settings->es_idle_timeout > 600) 383 { 384 if (err_buf) 385 snprintf(err_buf, err_buf_sz, "%s", 386 "The maximum value of idle timeout is 600 seconds"); 387 return -1; 388 } 389 if (settings->es_scid_len > MAX_CID_LEN) 390 { 391 if (err_buf) 392 snprintf(err_buf, err_buf_sz, "Source connection ID cannot be %u " 393 "bytes long; it must be between 0 and %u.", 394 settings->es_scid_len, MAX_CID_LEN); 395 return -1; 396 } 397 398 if (settings->es_cc_algo > 2) 399 { 400 if (err_buf) 401 snprintf(err_buf, err_buf_sz, "Invalid congestion control " 402 "algorithm value %u", settings->es_cc_algo); 403 return -1; 404 } 405 406 if (!(settings->es_ql_bits >= 0 && settings->es_ql_bits <= 2)) 407 { 408 if (err_buf) 409 snprintf(err_buf, err_buf_sz, "Invalid QL bits value %d ", 410 settings->es_ql_bits); 411 return -1; 412 } 413 414 if (!(settings->es_spin == 0 || settings->es_spin == 1)) 415 { 416 if (err_buf) 417 snprintf(err_buf, err_buf_sz, "Invalid spin value %d", 418 settings->es_spin); 419 return -1; 420 } 421 422 return 0; 423} 424 425 426static void 427free_packet (void *ctx, void *conn_ctx, void *packet_data, char is_ipv6) 428{ 429 free(packet_data); 430} 431 432 433static void * 434malloc_buf (void *ctx, void *conn_ctx, unsigned short size, char is_ipv6) 435{ 436 return malloc(size); 437} 438 439 440static const struct lsquic_packout_mem_if stock_pmi = 441{ 442 malloc_buf, free_packet, free_packet, 443}; 444 445 446static int 447hash_conns_by_addr (const struct lsquic_engine *engine) 448{ 449 if (engine->flags & ENG_SERVER) 450 return 0; 451 if (engine->pub.enp_settings.es_versions & LSQUIC_FORCED_TCID0_VERSIONS) 452 return 1; 453 if ((engine->pub.enp_settings.es_versions & LSQUIC_GQUIC_HEADER_VERSIONS) 454 && engine->pub.enp_settings.es_support_tcid0) 455 return 1; 456 if (engine->pub.enp_settings.es_scid_len == 0) 457 return 1; 458 return 0; 459} 460 461 462lsquic_engine_t * 463lsquic_engine_new (unsigned flags, 464 const struct lsquic_engine_api *api) 465{ 466 lsquic_engine_t *engine; 467 size_t alpn_len; 468 char err_buf[100]; 469 470 if (!api->ea_packets_out) 471 { 472 LSQ_ERROR("packets_out callback is not specified"); 473 return NULL; 474 } 475 476 if (!api->ea_stream_if) 477 { 478 LSQ_ERROR("stream interface is not specified"); 479 return NULL; 480 } 481 482 if (!(flags & LSENG_HTTP) && api->ea_alpn) 483 { 484 alpn_len = strlen(api->ea_alpn); 485 if (alpn_len < 1 || alpn_len > 255) 486 { 487 LSQ_ERROR("ALPN string length invalid: %zd bytes", alpn_len); 488 return NULL; 489 } 490 } 491 else 492 alpn_len = 0; 493 494 if (api->ea_settings && 495 0 != lsquic_engine_check_settings(api->ea_settings, flags, 496 err_buf, sizeof(err_buf))) 497 { 498 LSQ_ERROR("cannot create engine: %s", err_buf); 499 return NULL; 500 } 501 502 engine = calloc(1, sizeof(*engine)); 503 if (!engine) 504 return NULL; 505 if (0 != lsquic_mm_init(&engine->pub.enp_mm)) 506 { 507 free(engine); 508 return NULL; 509 } 510 if (api->ea_settings) 511 engine->pub.enp_settings = *api->ea_settings; 512 else 513 lsquic_engine_init_settings(&engine->pub.enp_settings, flags); 514 int tag_buf_len; 515 tag_buf_len = lsquic_gen_ver_tags(engine->pub.enp_ver_tags_buf, 516 sizeof(engine->pub.enp_ver_tags_buf), 517 engine->pub.enp_settings.es_versions); 518 if (tag_buf_len <= 0) 519 { 520 LSQ_ERROR("cannot generate version tags buffer"); 521 free(engine); 522 return NULL; 523 } 524 engine->pub.enp_ver_tags_len = tag_buf_len; 525 engine->pub.enp_flags = ENPUB_CAN_SEND; 526 engine->pub.enp_stream_if = api->ea_stream_if; 527 engine->pub.enp_stream_if_ctx = api->ea_stream_if_ctx; 528 529 engine->flags = flags; 530#ifndef NDEBUG 531 engine->flags |= ENG_COALESCE; 532#endif 533 engine->packets_out = api->ea_packets_out; 534 engine->packets_out_ctx = api->ea_packets_out_ctx; 535 engine->report_new_scids = api->ea_new_scids; 536 engine->report_live_scids = api->ea_live_scids; 537 engine->report_old_scids = api->ea_old_scids; 538 engine->scids_ctx = api->ea_cids_update_ctx; 539 cub_init(&engine->new_scids, engine->report_new_scids, engine->scids_ctx); 540 engine->pub.enp_lookup_cert = api->ea_lookup_cert; 541 engine->pub.enp_cert_lu_ctx = api->ea_cert_lu_ctx; 542 engine->pub.enp_get_ssl_ctx = api->ea_get_ssl_ctx; 543 if (api->ea_shi) 544 { 545 engine->pub.enp_shi = api->ea_shi; 546 engine->pub.enp_shi_ctx = api->ea_shi_ctx; 547 } 548 else 549 { 550 engine->pub.enp_shi = &stock_shi; 551 engine->pub.enp_shi_ctx = lsquic_stock_shared_hash_new(); 552 if (!engine->pub.enp_shi_ctx) 553 { 554 free(engine); 555 return NULL; 556 } 557 } 558 if (api->ea_hsi_if) 559 { 560 engine->pub.enp_hsi_if = api->ea_hsi_if; 561 engine->pub.enp_hsi_ctx = api->ea_hsi_ctx; 562 } 563 else 564 { 565 engine->pub.enp_hsi_if = lsquic_http1x_if; 566 engine->pub.enp_hsi_ctx = NULL; 567 } 568 if (api->ea_pmi) 569 { 570 engine->pub.enp_pmi = api->ea_pmi; 571 engine->pub.enp_pmi_ctx = api->ea_pmi_ctx; 572 } 573 else 574 { 575 engine->pub.enp_pmi = &stock_pmi; 576 engine->pub.enp_pmi_ctx = NULL; 577 } 578 engine->pub.enp_verify_cert = api->ea_verify_cert; 579 engine->pub.enp_verify_ctx = api->ea_verify_ctx; 580 engine->pub.enp_kli = api->ea_keylog_if; 581 engine->pub.enp_kli_ctx = api->ea_keylog_ctx; 582 engine->pub.enp_engine = engine; 583 if (hash_conns_by_addr(engine)) 584 engine->flags |= ENG_CONNS_BY_ADDR; 585 engine->conns_hash = lsquic_hash_create(); 586 engine->pub.enp_tokgen = lsquic_tg_new(&engine->pub); 587 if (!engine->pub.enp_tokgen) 588 return NULL; 589 engine->pub.enp_crand = &engine->crand; 590 if (flags & ENG_SERVER) 591 { 592 engine->pr_queue = lsquic_prq_create( 593 10000 /* TODO: make configurable */, MAX_OUT_BATCH_SIZE, 594 &engine->pub); 595 if (!engine->pr_queue) 596 { 597 lsquic_tg_destroy(engine->pub.enp_tokgen); 598 return NULL; 599 } 600 engine->purga = lsquic_purga_new(30 * 1000 * 1000, 601 engine->report_old_scids, engine->scids_ctx); 602 if (!engine->purga) 603 { 604 lsquic_tg_destroy(engine->pub.enp_tokgen); 605 lsquic_prq_destroy(engine->pr_queue); 606 return NULL; 607 } 608 } 609 engine->attq = lsquic_attq_create(); 610 eng_hist_init(&engine->history); 611 engine->batch_size = INITIAL_OUT_BATCH_SIZE; 612 if (engine->pub.enp_settings.es_honor_prst) 613 { 614 engine->pub.enp_srst_hash = lsquic_hash_create(); 615 if (!engine->pub.enp_srst_hash) 616 { 617 lsquic_engine_destroy(engine); 618 return NULL; 619 } 620 } 621 622 if (alpn_len) 623 { 624 engine->pub.enp_alpn = malloc(alpn_len + 1); 625 if (!engine->pub.enp_alpn) 626 { 627 lsquic_engine_destroy(engine); 628 return NULL; 629 } 630 engine->pub.enp_alpn[0] = alpn_len; 631 memcpy(engine->pub.enp_alpn + 1, api->ea_alpn, alpn_len); 632 } 633 634 if (flags & LSENG_HTTP) 635 engine->pub.enp_flags |= ENPUB_HTTP; 636 637#ifndef NDEBUG 638 { 639 const char *env; 640 env = getenv("LSQUIC_LOSE_PACKETS_RE"); 641 if (env) 642 { 643 if (0 != regcomp(&engine->lose_packets_re, env, 644 REG_EXTENDED|REG_NOSUB)) 645 { 646 LSQ_ERROR("could not compile lost packet regex `%s'", env); 647 return NULL; 648 } 649 engine->flags |= ENG_LOSE_PACKETS; 650 engine->lose_packets_str = env; 651 LSQ_WARN("will lose packets that match the following regex: %s", 652 env); 653 } 654 env = getenv("LSQUIC_COALESCE"); 655 if (env) 656 { 657 engine->flags &= ~ENG_COALESCE; 658 if (atoi(env)) 659 { 660 engine->flags |= ENG_COALESCE; 661 LSQ_NOTICE("will coalesce packets"); 662 } 663 else 664 LSQ_NOTICE("will not coalesce packets"); 665 } 666 } 667#endif 668#if LSQUIC_CONN_STATS 669 engine->stats_fh = api->ea_stats_fh; 670#endif 671 if (1 != EVP_AEAD_CTX_init(&engine->retry_aead_ctx, EVP_aead_aes_128_gcm(), 672 IETF_RETRY_KEY_BUF, IETF_RETRY_KEY_SZ, 16, NULL)) 673 { 674 LSQ_ERROR("could not initialize retry AEAD ctx"); 675 lsquic_engine_destroy(engine); 676 return NULL; 677 } 678 engine->pub.enp_retry_aead_ctx = &engine->retry_aead_ctx; 679 680 LSQ_INFO("instantiated engine"); 681 return engine; 682} 683 684 685#if LOG_PACKET_CHECKSUM 686static void 687log_packet_checksum (const lsquic_cid_t *cid, const char *direction, 688 const unsigned char *buf, size_t bufsz) 689{ 690 EV_LOG_CONN_EVENT(cid, "packet %s checksum: %08X", direction, 691 (uint32_t) crc32(0, buf, bufsz)); 692} 693 694 695#endif 696 697 698static void 699grow_batch_size (struct lsquic_engine *engine) 700{ 701 engine->batch_size <<= engine->batch_size < MAX_OUT_BATCH_SIZE; 702} 703 704 705static void 706shrink_batch_size (struct lsquic_engine *engine) 707{ 708 engine->batch_size >>= engine->batch_size > MIN_OUT_BATCH_SIZE; 709} 710 711 712struct cce_cid_iter 713{ 714 const struct lsquic_conn *conn; 715 unsigned todo, n; 716}; 717 718 719static struct conn_cid_elem * 720cce_iter_next (struct cce_cid_iter *citer) 721{ 722 struct conn_cid_elem *cce; 723 724 while (citer->todo) 725 if (citer->todo & (1 << citer->n)) 726 { 727 citer->todo &= ~(1 << citer->n); 728 cce = &citer->conn->cn_cces[ citer->n++ ]; 729 if (!(cce->cce_flags & CCE_PORT)) 730 return cce; 731 } 732 else 733 ++citer->n; 734 735 return NULL; 736} 737 738 739static struct conn_cid_elem * 740cce_iter_first (struct cce_cid_iter *citer, const struct lsquic_conn *conn) 741{ 742 citer->conn = conn; 743 citer->todo = conn->cn_cces_mask; 744 citer->n = 0; 745 return cce_iter_next(citer); 746} 747 748 749#if LSQUIC_CONN_STATS 750void 751update_stats_sum (struct lsquic_engine *engine, struct lsquic_conn *conn) 752{ 753 unsigned long *const dst = (unsigned long *) &engine->conn_stats_sum; 754 const unsigned long *src; 755 const struct conn_stats *stats; 756 unsigned i; 757 758 if (conn->cn_if->ci_get_stats && (stats = conn->cn_if->ci_get_stats(conn))) 759 { 760 ++engine->stats.conns; 761 src = (unsigned long *) stats; 762 for (i = 0; i < sizeof(*stats) / sizeof(unsigned long); ++i) 763 dst[i] += src[i]; 764 } 765} 766 767 768#endif 769 770 771/* Wrapper to make sure important things occur before the connection is 772 * really destroyed. 773 */ 774static void 775destroy_conn (struct lsquic_engine *engine, struct lsquic_conn *conn, 776 lsquic_time_t now) 777{ 778 struct cce_cid_iter citer; 779 const struct conn_cid_elem *cce; 780 lsquic_time_t drain_time; 781 struct purga_el *puel; 782 783 engine->mini_conns_count -= !!(conn->cn_flags & LSCONN_MINI); 784 if (engine->purga 785 /* Blacklist all CIDs except for promoted mini connections */ 786 && (conn->cn_flags & (LSCONN_MINI|LSCONN_PROMOTED)) 787 != (LSCONN_MINI|LSCONN_PROMOTED)) 788 { 789 if (!(conn->cn_flags & LSCONN_IMMED_CLOSE) 790 && conn->cn_if->ci_drain_time && 791 (drain_time = conn->cn_if->ci_drain_time(conn), drain_time)) 792 { 793 for (cce = cce_iter_first(&citer, conn); cce; 794 cce = cce_iter_next(&citer)) 795 { 796 puel = lsquic_purga_add(engine->purga, &cce->cce_cid, 797 lsquic_conn_get_peer_ctx(conn, NULL), 798 PUTY_CONN_DRAIN, now); 799 if (puel) 800 puel->puel_time = now + drain_time; 801 } 802 } 803 else 804 { 805 for (cce = cce_iter_first(&citer, conn); cce; 806 cce = cce_iter_next(&citer)) 807 { 808 puel = lsquic_purga_add(engine->purga, &cce->cce_cid, 809 lsquic_conn_get_peer_ctx(conn, NULL), 810 PUTY_CONN_DELETED, now); 811 if (puel) 812 { 813 puel->puel_time = now; 814 puel->puel_count = 0; 815 } 816 } 817 } 818 } 819#if LSQUIC_CONN_STATS 820 update_stats_sum(engine, conn); 821#endif 822 --engine->n_conns; 823 conn->cn_flags |= LSCONN_NEVER_TICKABLE; 824 conn->cn_if->ci_destroy(conn); 825} 826 827 828static int 829maybe_grow_conn_heaps (struct lsquic_engine *engine) 830{ 831 struct min_heap_elem *els; 832 unsigned count; 833 834 if (engine->n_conns < lsquic_mh_nalloc(&engine->conns_tickable)) 835 return 0; /* Nothing to do */ 836 837 if (lsquic_mh_nalloc(&engine->conns_tickable)) 838 count = lsquic_mh_nalloc(&engine->conns_tickable) * 2 * 2; 839 else 840 count = 8; 841 842 els = malloc(sizeof(els[0]) * count); 843 if (!els) 844 { 845 LSQ_ERROR("%s: malloc failed", __func__); 846 return -1; 847 } 848 849 LSQ_DEBUG("grew heaps to %u elements", count / 2); 850 memcpy(&els[0], engine->conns_tickable.mh_elems, 851 sizeof(els[0]) * lsquic_mh_count(&engine->conns_tickable)); 852 memcpy(&els[count / 2], engine->conns_out.mh_elems, 853 sizeof(els[0]) * lsquic_mh_count(&engine->conns_out)); 854 free(engine->conns_tickable.mh_elems); 855 engine->conns_tickable.mh_elems = els; 856 engine->conns_out.mh_elems = &els[count / 2]; 857 engine->conns_tickable.mh_nalloc = count / 2; 858 engine->conns_out.mh_nalloc = count / 2; 859 return 0; 860} 861 862 863static void 864remove_cces_from_hash (struct lsquic_hash *hash, struct lsquic_conn *conn, 865 unsigned todo) 866{ 867 unsigned n; 868 869 for (n = 0; todo; todo &= ~(1 << n++)) 870 if ((todo & (1 << n)) && 871 (conn->cn_cces[n].cce_hash_el.qhe_flags & QHE_HASHED)) 872 lsquic_hash_erase(hash, &conn->cn_cces[n].cce_hash_el); 873} 874 875 876static void 877remove_all_cces_from_hash (struct lsquic_hash *hash, struct lsquic_conn *conn) 878{ 879 remove_cces_from_hash(hash, conn, conn->cn_cces_mask); 880} 881 882 883static void 884cub_add (struct cid_update_batch *cub, const lsquic_cid_t *cid, void *peer_ctx); 885 886 887static int 888insert_conn_into_hash (struct lsquic_engine *engine, struct lsquic_conn *conn, 889 void *peer_ctx) 890{ 891 struct conn_cid_elem *cce; 892 unsigned todo, done, n; 893 894 for (todo = conn->cn_cces_mask, done = 0, n = 0; todo; todo &= ~(1 << n++)) 895 if (todo & (1 << n)) 896 { 897 cce = &conn->cn_cces[n]; 898 assert(!(cce->cce_hash_el.qhe_flags & QHE_HASHED)); 899 if (lsquic_hash_insert(engine->conns_hash, cce->cce_cid.idbuf, 900 cce->cce_cid.len, conn, &cce->cce_hash_el)) 901 done |= 1 << n; 902 else 903 goto err; 904 if ((engine->flags & ENG_SERVER) && 0 == (cce->cce_flags & CCE_REG)) 905 { 906 cce->cce_flags |= CCE_REG; 907 cub_add(&engine->new_scids, &cce->cce_cid, peer_ctx); 908 } 909 } 910 911 return 0; 912 913 err: 914 remove_cces_from_hash(engine->conns_hash, conn, done); 915 return -1; 916} 917 918 919static lsquic_conn_t * 920new_full_conn_server (lsquic_engine_t *engine, lsquic_conn_t *mini_conn, 921 lsquic_time_t now) 922{ 923 const lsquic_cid_t *cid; 924 server_conn_ctor_f ctor; 925 lsquic_conn_t *conn; 926 unsigned flags; 927 if (0 != maybe_grow_conn_heaps(engine)) 928 return NULL; 929 flags = engine->flags & (ENG_SERVER|ENG_HTTP); 930 931 if (mini_conn->cn_flags & LSCONN_IETF) 932 ctor = lsquic_ietf_full_conn_server_new; 933 else 934 ctor = lsquic_gquic_full_conn_server_new; 935 936 conn = ctor(&engine->pub, flags, mini_conn); 937 if (!conn) 938 { 939 /* Otherwise, full_conn_server_new prints its own warnings */ 940 if (ENOMEM == errno) 941 { 942 cid = lsquic_conn_log_cid(mini_conn); 943 LSQ_WARNC("could not allocate full connection for %"CID_FMT": %s", 944 CID_BITS(cid), strerror(errno)); 945 } 946 return NULL; 947 } 948 ++engine->n_conns; 949 if (0 != insert_conn_into_hash(engine, conn, lsquic_conn_get_peer_ctx(conn, NULL))) 950 { 951 cid = lsquic_conn_log_cid(conn); 952 LSQ_WARNC("cannot add connection %"CID_FMT" to hash - destroy", 953 CID_BITS(cid)); 954 destroy_conn(engine, conn, now); 955 return NULL; 956 } 957 assert(!(conn->cn_flags & CONN_REF_FLAGS)); 958 conn->cn_flags |= LSCONN_HASHED; 959 return conn; 960} 961 962 963static enum 964{ 965 VER_NOT_SPECIFIED, 966 VER_SUPPORTED, 967 VER_UNSUPPORTED, 968} 969 970 971version_matches (lsquic_engine_t *engine, const lsquic_packet_in_t *packet_in, 972 enum lsquic_version *pversion) 973{ 974 lsquic_ver_tag_t ver_tag; 975 enum lsquic_version version; 976 977 if (!packet_in->pi_quic_ver) 978 { 979 LSQ_DEBUG("packet does not specify version"); 980 return VER_NOT_SPECIFIED; 981 } 982 983 memcpy(&ver_tag, packet_in->pi_data + packet_in->pi_quic_ver, sizeof(ver_tag)); 984 version = lsquic_tag2ver(ver_tag); 985 if (version < N_LSQVER) 986 { 987 if (engine->pub.enp_settings.es_versions & (1 << version)) 988 { 989 LSQ_DEBUG("client-supplied version %s is supported", 990 lsquic_ver2str[version]); 991 *pversion = version; 992 return VER_SUPPORTED; 993 } 994 else 995 LSQ_DEBUG("client-supplied version %s is not supported", 996 lsquic_ver2str[version]); 997 } 998 else 999 LSQ_DEBUG("client-supplied version tag 0x%08X is not recognized", 1000 ver_tag); 1001 1002 return VER_UNSUPPORTED; 1003} 1004 1005 1006static void 1007schedule_req_packet (struct lsquic_engine *engine, enum packet_req_type type, 1008 const struct lsquic_packet_in *packet_in, const struct sockaddr *sa_local, 1009 const struct sockaddr *sa_peer, void *peer_ctx) 1010{ 1011 assert(engine->pr_queue); 1012 if (0 == lsquic_prq_new_req(engine->pr_queue, type, packet_in, peer_ctx, 1013 sa_local, sa_peer)) 1014 LSQ_DEBUGC("scheduled %s packet for cid %"CID_FMT, 1015 lsquic_preqt2str[type], CID_BITS(&packet_in->pi_conn_id)); 1016 else 1017 LSQ_DEBUG("cannot schedule %s packet", lsquic_preqt2str[type]); 1018} 1019 1020 1021static unsigned short 1022sa2port (const struct sockaddr *sa) 1023{ 1024 if (sa->sa_family == AF_INET) 1025 { 1026 struct sockaddr_in *const sa4 = (void *) sa; 1027 return sa4->sin_port; 1028 } 1029 else 1030 { 1031 struct sockaddr_in6 *const sa6 = (void *) sa; 1032 return sa6->sin6_port; 1033 } 1034} 1035 1036 1037static struct lsquic_hash_elem * 1038find_conn_by_addr (struct lsquic_hash *hash, const struct sockaddr *sa) 1039{ 1040 unsigned short port; 1041 1042 port = sa2port(sa); 1043 return lsquic_hash_find(hash, &port, sizeof(port)); 1044} 1045 1046 1047static lsquic_conn_t * 1048find_conn (lsquic_engine_t *engine, lsquic_packet_in_t *packet_in, 1049 struct packin_parse_state *ppstate, const struct sockaddr *sa_local) 1050{ 1051 struct lsquic_hash_elem *el; 1052 lsquic_conn_t *conn; 1053 1054 if (engine->flags & ENG_CONNS_BY_ADDR) 1055 el = find_conn_by_addr(engine->conns_hash, sa_local); 1056 else if (packet_in->pi_flags & PI_CONN_ID) 1057 el = lsquic_hash_find(engine->conns_hash, 1058 packet_in->pi_conn_id.idbuf, packet_in->pi_conn_id.len); 1059 else 1060 { 1061 LSQ_DEBUG("packet header does not have connection ID: discarding"); 1062 return NULL; 1063 } 1064 1065 if (!el) 1066 return NULL; 1067 1068 conn = lsquic_hashelem_getdata(el); 1069 conn->cn_pf->pf_parse_packet_in_finish(packet_in, ppstate); 1070 if ((engine->flags & ENG_CONNS_BY_ADDR) 1071 && !(conn->cn_flags & LSCONN_IETF) 1072 && (packet_in->pi_flags & PI_CONN_ID) 1073 && !LSQUIC_CIDS_EQ(CN_SCID(conn), &packet_in->pi_conn_id)) 1074 { 1075 LSQ_DEBUG("connection IDs do not match"); 1076 return NULL; 1077 } 1078 1079 return conn; 1080} 1081 1082 1083static lsquic_conn_t * 1084find_or_create_conn (lsquic_engine_t *engine, lsquic_packet_in_t *packet_in, 1085 struct packin_parse_state *ppstate, const struct sockaddr *sa_local, 1086 const struct sockaddr *sa_peer, void *peer_ctx, size_t packet_in_size) 1087{ 1088 struct lsquic_hash_elem *el; 1089 struct purga_el *puel; 1090 lsquic_conn_t *conn; 1091 1092 if (!(packet_in->pi_flags & PI_CONN_ID)) 1093 { 1094 LSQ_DEBUG("packet header does not have connection ID: discarding"); 1095 return NULL; 1096 } 1097 el = lsquic_hash_find(engine->conns_hash, 1098 packet_in->pi_conn_id.idbuf, packet_in->pi_conn_id.len); 1099 1100 if (el) 1101 { 1102 conn = lsquic_hashelem_getdata(el); 1103 conn->cn_pf->pf_parse_packet_in_finish(packet_in, ppstate); 1104 return conn; 1105 } 1106 1107 if (engine->flags & ENG_COOLDOWN) 1108 { /* Do not create incoming connections during cooldown */ 1109 LSQ_DEBUG("dropping inbound packet for unknown connection (cooldown)"); 1110 return NULL; 1111 } 1112 1113 if (engine->mini_conns_count >= engine->pub.enp_settings.es_max_inchoate) 1114 { 1115 LSQ_DEBUG("reached limit of %u inchoate connections", 1116 engine->pub.enp_settings.es_max_inchoate); 1117 return NULL; 1118 } 1119 1120 1121 if (engine->purga 1122 && (puel = lsquic_purga_contains(engine->purga, 1123 &packet_in->pi_conn_id), puel)) 1124 { 1125 switch (puel->puel_type) 1126 { 1127 case PUTY_CID_RETIRED: 1128 LSQ_DEBUGC("CID %"CID_FMT" was retired, ignore packet", 1129 CID_BITS(&packet_in->pi_conn_id)); 1130 return NULL; 1131 case PUTY_CONN_DRAIN: 1132 LSQ_DEBUG("drain till: %"PRIu64"; now: %"PRIu64, 1133 puel->puel_time, packet_in->pi_received); 1134 if (puel->puel_time > packet_in->pi_received) 1135 { 1136 LSQ_DEBUGC("CID %"CID_FMT" is in drain state, ignore packet", 1137 CID_BITS(&packet_in->pi_conn_id)); 1138 return NULL; 1139 } 1140 LSQ_DEBUGC("CID %"CID_FMT" goes from drain state to deleted", 1141 CID_BITS(&packet_in->pi_conn_id)); 1142 puel->puel_type = PUTY_CONN_DELETED; 1143 puel->puel_count = 0; 1144 puel->puel_time = 0; 1145 /* fall-through */ 1146 case PUTY_CONN_DELETED: 1147 LSQ_DEBUGC("Connection with CID %"CID_FMT" was deleted", 1148 CID_BITS(&packet_in->pi_conn_id)); 1149 if (puel->puel_time < packet_in->pi_received) 1150 { 1151 puel->puel_time = packet_in->pi_received 1152 /* Exponential back-off */ 1153 + 1000000ull * (1 << MIN(puel->puel_count, 4)); 1154 ++puel->puel_count; 1155 goto maybe_send_prst; 1156 } 1157 return NULL; 1158 default: 1159 assert(0); 1160 return NULL; 1161 } 1162 } 1163 1164 if (engine->pub.enp_settings.es_send_prst 1165 && !(packet_in->pi_flags & PI_GQUIC) 1166 && HETY_NOT_SET == packet_in->pi_header_type) 1167 goto maybe_send_prst; 1168 1169 if (0 != maybe_grow_conn_heaps(engine)) 1170 return NULL; 1171 1172 const struct parse_funcs *pf; 1173 enum lsquic_version version; 1174 switch (version_matches(engine, packet_in, &version)) 1175 { 1176 case VER_UNSUPPORTED: 1177 if (engine->flags & ENG_SERVER) 1178 schedule_req_packet(engine, PACKET_REQ_VERNEG, packet_in, 1179 sa_local, sa_peer, peer_ctx); 1180 return NULL; 1181 case VER_NOT_SPECIFIED: 1182 maybe_send_prst: 1183 if ((engine->flags & ENG_SERVER) && 1184 engine->pub.enp_settings.es_send_prst) 1185 schedule_req_packet(engine, PACKET_REQ_PUBRES, packet_in, 1186 sa_local, sa_peer, peer_ctx); 1187 return NULL; 1188 case VER_SUPPORTED: 1189 pf = select_pf_by_ver(version); 1190 pf->pf_parse_packet_in_finish(packet_in, ppstate); 1191 break; 1192 } 1193 1194 1195 if ((1 << version) & LSQUIC_IETF_VERSIONS) 1196 { 1197 conn = lsquic_mini_conn_ietf_new(&engine->pub, packet_in, version, 1198 sa_peer->sa_family == AF_INET, NULL, packet_in_size); 1199 } 1200 else 1201 { 1202 conn = lsquic_mini_conn_new(&engine->pub, packet_in, version); 1203 } 1204 if (!conn) 1205 return NULL; 1206 ++engine->mini_conns_count; 1207 ++engine->n_conns; 1208 if (0 != insert_conn_into_hash(engine, conn, peer_ctx)) 1209 { 1210 const lsquic_cid_t *cid = lsquic_conn_log_cid(conn); 1211 LSQ_WARNC("cannot add connection %"CID_FMT" to hash - destroy", 1212 CID_BITS(cid)); 1213 destroy_conn(engine, conn, packet_in->pi_received); 1214 return NULL; 1215 } 1216 assert(!(conn->cn_flags & CONN_REF_FLAGS)); 1217 conn->cn_flags |= LSCONN_HASHED; 1218 eng_hist_inc(&engine->history, packet_in->pi_received, sl_new_mini_conns); 1219 conn->cn_last_sent = engine->last_sent; 1220 return conn; 1221} 1222 1223 1224lsquic_conn_t * 1225lsquic_engine_find_conn (const struct lsquic_engine_public *engine, 1226 const lsquic_cid_t *cid) 1227{ 1228 struct lsquic_hash_elem *el; 1229 lsquic_conn_t *conn = NULL; 1230 el = lsquic_hash_find(engine->enp_engine->conns_hash, cid->idbuf, cid->len); 1231 1232 if (el) 1233 conn = lsquic_hashelem_getdata(el); 1234 return conn; 1235} 1236 1237 1238#if !defined(NDEBUG) && __GNUC__ 1239__attribute__((weak)) 1240#endif 1241void 1242lsquic_engine_add_conn_to_tickable (struct lsquic_engine_public *enpub, 1243 lsquic_conn_t *conn) 1244{ 1245 if (0 == (enpub->enp_flags & ENPUB_PROC) && 1246 0 == (conn->cn_flags & (LSCONN_TICKABLE|LSCONN_NEVER_TICKABLE))) 1247 { 1248 lsquic_engine_t *engine = (lsquic_engine_t *) enpub; 1249 lsquic_mh_insert(&engine->conns_tickable, conn, conn->cn_last_ticked); 1250 engine_incref_conn(conn, LSCONN_TICKABLE); 1251 } 1252} 1253 1254 1255void 1256lsquic_engine_add_conn_to_attq (struct lsquic_engine_public *enpub, 1257 lsquic_conn_t *conn, lsquic_time_t tick_time, unsigned why) 1258{ 1259 lsquic_engine_t *const engine = (lsquic_engine_t *) enpub; 1260 if (conn->cn_flags & LSCONN_TICKABLE) 1261 { 1262 /* Optimization: no need to add the connection to the Advisory Tick 1263 * Time Queue: it is about to be ticked, after which it its next tick 1264 * time may be queried again. 1265 */; 1266 } 1267 else if (conn->cn_flags & LSCONN_ATTQ) 1268 { 1269 if (lsquic_conn_adv_time(conn) != tick_time) 1270 { 1271 lsquic_attq_remove(engine->attq, conn); 1272 if (0 != lsquic_attq_add(engine->attq, conn, tick_time, why)) 1273 engine_decref_conn(engine, conn, LSCONN_ATTQ); 1274 } 1275 } 1276 else if (0 == lsquic_attq_add(engine->attq, conn, tick_time, why)) 1277 engine_incref_conn(conn, LSCONN_ATTQ); 1278} 1279 1280 1281static struct lsquic_conn * 1282find_conn_by_srst (struct lsquic_engine *engine, 1283 const struct lsquic_packet_in *packet_in) 1284{ 1285 struct lsquic_hash_elem *el; 1286 struct lsquic_conn *conn; 1287 1288 if (packet_in->pi_data_sz < IQUIC_MIN_SRST_SIZE 1289 || (packet_in->pi_data[0] & 0xC0) != 0x40) 1290 return NULL; 1291 1292 el = lsquic_hash_find(engine->pub.enp_srst_hash, 1293 packet_in->pi_data + packet_in->pi_data_sz - IQUIC_SRESET_TOKEN_SZ, 1294 IQUIC_SRESET_TOKEN_SZ); 1295 if (!el) 1296 return NULL; 1297 1298 conn = lsquic_hashelem_getdata(el); 1299 return conn; 1300} 1301 1302 1303/* Return 0 if packet is being processed by a real connection (mini or full), 1304 * otherwise return 1. 1305 */ 1306static int 1307process_packet_in (lsquic_engine_t *engine, lsquic_packet_in_t *packet_in, 1308 struct packin_parse_state *ppstate, const struct sockaddr *sa_local, 1309 const struct sockaddr *sa_peer, void *peer_ctx, size_t packet_in_size) 1310{ 1311 lsquic_conn_t *conn; 1312 const unsigned char *packet_in_data; 1313 1314 if (lsquic_packet_in_is_gquic_prst(packet_in) 1315 && !engine->pub.enp_settings.es_honor_prst) 1316 { 1317 lsquic_mm_put_packet_in(&engine->pub.enp_mm, packet_in); 1318 LSQ_DEBUG("public reset packet: discarding"); 1319 return 1; 1320 } 1321 1322 if (engine->flags & ENG_SERVER) 1323 conn = find_or_create_conn(engine, packet_in, ppstate, sa_local, 1324 sa_peer, peer_ctx, packet_in_size); 1325 else 1326 conn = find_conn(engine, packet_in, ppstate, sa_local); 1327 1328 if (!conn) 1329 { 1330 if (engine->pub.enp_settings.es_honor_prst 1331 && packet_in_size == packet_in->pi_data_sz /* Full UDP packet */ 1332 && !(packet_in->pi_flags & PI_GQUIC) 1333 && engine->pub.enp_srst_hash 1334 && (conn = find_conn_by_srst(engine, packet_in))) 1335 { 1336 LSQ_DEBUGC("got stateless reset for connection %"CID_FMT, 1337 CID_BITS(lsquic_conn_log_cid(conn))); 1338 conn->cn_if->ci_stateless_reset(conn); 1339 if (!(conn->cn_flags & LSCONN_TICKABLE) 1340 && conn->cn_if->ci_is_tickable(conn)) 1341 { 1342 lsquic_mh_insert(&engine->conns_tickable, conn, 1343 conn->cn_last_ticked); 1344 engine_incref_conn(conn, LSCONN_TICKABLE); 1345 } 1346 /* Even though the connection processes this packet, we return 1347 * 1 so that the caller does not add reset packet's random 1348 * bytes to the list of valid CIDs. 1349 */ 1350 } 1351 lsquic_mm_put_packet_in(&engine->pub.enp_mm, packet_in); 1352 return 1; 1353 } 1354 1355 if (0 == (conn->cn_flags & LSCONN_TICKABLE)) 1356 { 1357 lsquic_mh_insert(&engine->conns_tickable, conn, conn->cn_last_ticked); 1358 engine_incref_conn(conn, LSCONN_TICKABLE); 1359 } 1360 packet_in->pi_path_id = lsquic_conn_record_sockaddr(conn, peer_ctx, 1361 sa_local, sa_peer); 1362 lsquic_packet_in_upref(packet_in); 1363#if LOG_PACKET_CHECKSUM 1364 log_packet_checksum(lsquic_conn_log_cid(conn), "in", packet_in->pi_data, 1365 packet_in->pi_data_sz); 1366#endif 1367 /* Note on QLog: 1368 * For the PACKET_RX QLog event, we are interested in logging these things: 1369 * - raw packet (however it comes in, encrypted or not) 1370 * - frames (list of frame names) 1371 * - packet type and number 1372 * - packet rx timestamp 1373 * 1374 * Since only some of these items are available at this code 1375 * juncture, we will wait until after the packet has been 1376 * decrypted (if necessary) and parsed to call the log functions. 1377 * 1378 * Once the PACKET_RX event is finally logged, the timestamp 1379 * will come from packet_in->pi_received. For correct sequential 1380 * ordering of QLog events, be sure to process the QLogs downstream. 1381 * (Hint: Use the qlog_parser.py tool in tools/ for full QLog processing.) 1382 */ 1383 packet_in_data = packet_in->pi_data; 1384 packet_in_size = packet_in->pi_data_sz; 1385 conn->cn_if->ci_packet_in(conn, packet_in); 1386 QLOG_PACKET_RX(lsquic_conn_log_cid(conn), packet_in, packet_in_data, packet_in_size); 1387 lsquic_packet_in_put(&engine->pub.enp_mm, packet_in); 1388 return 0; 1389} 1390 1391 1392void 1393lsquic_engine_destroy (lsquic_engine_t *engine) 1394{ 1395 struct lsquic_hash_elem *el; 1396 lsquic_conn_t *conn; 1397 1398 LSQ_DEBUG("destroying engine"); 1399#ifndef NDEBUG 1400 engine->flags |= ENG_DTOR; 1401#endif 1402 1403 while ((conn = lsquic_mh_pop(&engine->conns_out))) 1404 { 1405 assert(conn->cn_flags & LSCONN_HAS_OUTGOING); 1406 (void) engine_decref_conn(engine, conn, LSCONN_HAS_OUTGOING); 1407 } 1408 1409 while ((conn = lsquic_mh_pop(&engine->conns_tickable))) 1410 { 1411 assert(conn->cn_flags & LSCONN_TICKABLE); 1412 (void) engine_decref_conn(engine, conn, LSCONN_TICKABLE); 1413 } 1414 1415 for (el = lsquic_hash_first(engine->conns_hash); el; 1416 el = lsquic_hash_next(engine->conns_hash)) 1417 { 1418 conn = lsquic_hashelem_getdata(el); 1419 force_close_conn(engine, conn); 1420 } 1421 lsquic_hash_destroy(engine->conns_hash); 1422 1423 assert(0 == engine->n_conns); 1424 assert(0 == engine->mini_conns_count); 1425 if (engine->pr_queue) 1426 lsquic_prq_destroy(engine->pr_queue); 1427 if (engine->purga) 1428 lsquic_purga_destroy(engine->purga); 1429 lsquic_attq_destroy(engine->attq); 1430 1431 assert(0 == lsquic_mh_count(&engine->conns_out)); 1432 assert(0 == lsquic_mh_count(&engine->conns_tickable)); 1433 if (engine->pub.enp_shi == &stock_shi) 1434 lsquic_stock_shared_hash_destroy(engine->pub.enp_shi_ctx); 1435 lsquic_mm_cleanup(&engine->pub.enp_mm); 1436 free(engine->conns_tickable.mh_elems); 1437#ifndef NDEBUG 1438 if (engine->flags & ENG_LOSE_PACKETS) 1439 regfree(&engine->lose_packets_re); 1440#endif 1441 if (engine->pub.enp_tokgen) 1442 lsquic_tg_destroy(engine->pub.enp_tokgen); 1443#if LSQUIC_CONN_STATS 1444 if (engine->stats_fh) 1445 { 1446 const struct conn_stats *const stats = &engine->conn_stats_sum; 1447 fprintf(engine->stats_fh, "Aggregate connection stats collected by engine:\n"); 1448 fprintf(engine->stats_fh, "Connections: %u\n", engine->stats.conns); 1449 fprintf(engine->stats_fh, "Ticks: %lu\n", stats->n_ticks); 1450 fprintf(engine->stats_fh, "In:\n"); 1451 fprintf(engine->stats_fh, " Total bytes: %lu\n", stats->in.bytes); 1452 fprintf(engine->stats_fh, " packets: %lu\n", stats->in.packets); 1453 fprintf(engine->stats_fh, " undecryptable packets: %lu\n", stats->in.undec_packets); 1454 fprintf(engine->stats_fh, " duplicate packets: %lu\n", stats->in.dup_packets); 1455 fprintf(engine->stats_fh, " error packets: %lu\n", stats->in.err_packets); 1456 fprintf(engine->stats_fh, " STREAM frame count: %lu\n", stats->in.stream_frames); 1457 fprintf(engine->stats_fh, " STREAM payload size: %lu\n", stats->in.stream_data_sz); 1458 fprintf(engine->stats_fh, " Header bytes: %lu; uncompressed: %lu; ratio %.3lf\n", 1459 stats->in.headers_comp, stats->in.headers_uncomp, 1460 stats->in.headers_uncomp ? 1461 (double) stats->in.headers_comp / (double) stats->in.headers_uncomp 1462 : 0); 1463 fprintf(engine->stats_fh, " ACK frames: %lu\n", stats->in.n_acks); 1464 fprintf(engine->stats_fh, " ACK frames processed: %lu\n", stats->in.n_acks_proc); 1465 fprintf(engine->stats_fh, " ACK frames merged to new: %lu\n", stats->in.n_acks_merged[0]); 1466 fprintf(engine->stats_fh, " ACK frames merged to old: %lu\n", stats->in.n_acks_merged[1]); 1467 fprintf(engine->stats_fh, "Out:\n"); 1468 fprintf(engine->stats_fh, " Total bytes: %lu\n", stats->out.bytes); 1469 fprintf(engine->stats_fh, " packets: %lu\n", stats->out.packets); 1470 fprintf(engine->stats_fh, " acked via loss record: %lu\n", stats->out.acked_via_loss); 1471 fprintf(engine->stats_fh, " acks: %lu\n", stats->out.acks); 1472 fprintf(engine->stats_fh, " retx packets: %lu\n", stats->out.retx_packets); 1473 fprintf(engine->stats_fh, " STREAM frame count: %lu\n", stats->out.stream_frames); 1474 fprintf(engine->stats_fh, " STREAM payload size: %lu\n", stats->out.stream_data_sz); 1475 fprintf(engine->stats_fh, " Header bytes: %lu; uncompressed: %lu; ratio %.3lf\n", 1476 stats->out.headers_comp, stats->out.headers_uncomp, 1477 stats->out.headers_uncomp ? 1478 (double) stats->out.headers_comp / (double) stats->out.headers_uncomp 1479 : 0); 1480 fprintf(engine->stats_fh, " ACKs: %lu\n", stats->out.acks); 1481 } 1482#endif 1483 if (engine->pub.enp_srst_hash) 1484 lsquic_hash_destroy(engine->pub.enp_srst_hash); 1485#if LSQUIC_COUNT_ENGINE_CALLS 1486 LSQ_NOTICE("number of calls into the engine: %lu", engine->n_engine_calls); 1487#endif 1488 if (engine->pub.enp_retry_aead_ctx) 1489 EVP_AEAD_CTX_cleanup(engine->pub.enp_retry_aead_ctx); 1490 free(engine->pub.enp_alpn); 1491 free(engine); 1492} 1493 1494 1495static struct conn_cid_elem * 1496find_free_cce (struct lsquic_conn *conn) 1497{ 1498 struct conn_cid_elem *cce; 1499 1500 for (cce = conn->cn_cces; cce < END_OF_CCES(conn); ++cce) 1501 if (!(conn->cn_cces_mask & (1 << (cce - conn->cn_cces)))) 1502 return cce; 1503 1504 return NULL; 1505} 1506 1507 1508static int 1509add_conn_to_hash (struct lsquic_engine *engine, struct lsquic_conn *conn, 1510 const struct sockaddr *local_sa, void *peer_ctx) 1511{ 1512 struct conn_cid_elem *cce; 1513 1514 if (engine->flags & ENG_CONNS_BY_ADDR) 1515 { 1516 cce = find_free_cce(conn); 1517 if (!cce) 1518 { 1519 LSQ_ERROR("cannot find free CCE"); 1520 return -1; 1521 } 1522 cce->cce_port = sa2port(local_sa); 1523 cce->cce_flags = CCE_PORT; 1524 if (lsquic_hash_insert(engine->conns_hash, &cce->cce_port, 1525 sizeof(cce->cce_port), conn, &cce->cce_hash_el)) 1526 { 1527 conn->cn_cces_mask |= 1 << (cce - conn->cn_cces); 1528 return 0; 1529 } 1530 else 1531 return -1; 1532 1533 } 1534 else 1535 return insert_conn_into_hash(engine, conn, peer_ctx); 1536} 1537 1538 1539lsquic_conn_t * 1540lsquic_engine_connect (lsquic_engine_t *engine, enum lsquic_version version, 1541 const struct sockaddr *local_sa, 1542 const struct sockaddr *peer_sa, 1543 void *peer_ctx, lsquic_conn_ctx_t *conn_ctx, 1544 const char *hostname, unsigned short max_packet_size, 1545 const unsigned char *zero_rtt, size_t zero_rtt_len, 1546 const unsigned char *token, size_t token_sz) 1547{ 1548 lsquic_conn_t *conn; 1549 unsigned flags, versions; 1550 int is_ipv4; 1551 1552 ENGINE_IN(engine); 1553 1554 if (engine->flags & ENG_SERVER) 1555 { 1556 LSQ_ERROR("`%s' must only be called in client mode", __func__); 1557 goto err; 1558 } 1559 1560 if (engine->flags & ENG_CONNS_BY_ADDR 1561 && find_conn_by_addr(engine->conns_hash, local_sa)) 1562 { 1563 LSQ_ERROR("cannot have more than one connection on the same port"); 1564 goto err; 1565 } 1566 1567 if (0 != maybe_grow_conn_heaps(engine)) 1568 return NULL; 1569 flags = engine->flags & (ENG_SERVER|ENG_HTTP); 1570 is_ipv4 = peer_sa->sa_family == AF_INET; 1571 if (zero_rtt && zero_rtt_len) 1572 { 1573 version = lsquic_zero_rtt_version(zero_rtt, zero_rtt_len); 1574 if (version >= N_LSQVER) 1575 { 1576 LSQ_INFO("zero-rtt version is bad, won't use"); 1577 zero_rtt = NULL; 1578 zero_rtt_len = 0; 1579 } 1580 } 1581 if (version >= N_LSQVER) 1582 { 1583 if (version > N_LSQVER) 1584 LSQ_WARN("invalid version specified, engine will pick"); 1585 versions = engine->pub.enp_settings.es_versions; 1586 } 1587 else 1588 versions = 1u << version; 1589 if (versions & LSQUIC_IETF_VERSIONS) 1590 conn = lsquic_ietf_full_conn_client_new(&engine->pub, versions, 1591 flags, hostname, max_packet_size, 1592 is_ipv4, zero_rtt, zero_rtt_len, token, token_sz); 1593 else 1594 conn = lsquic_gquic_full_conn_client_new(&engine->pub, versions, 1595 flags, hostname, max_packet_size, is_ipv4, 1596 zero_rtt, zero_rtt_len); 1597 if (!conn) 1598 goto err; 1599 EV_LOG_CREATE_CONN(lsquic_conn_log_cid(conn), local_sa, peer_sa); 1600 EV_LOG_VER_NEG(lsquic_conn_log_cid(conn), "proposed", 1601 lsquic_ver2str[conn->cn_version]); 1602 ++engine->n_conns; 1603 lsquic_conn_record_sockaddr(conn, peer_ctx, local_sa, peer_sa); 1604 if (0 != add_conn_to_hash(engine, conn, local_sa, peer_ctx)) 1605 { 1606 const lsquic_cid_t *cid = lsquic_conn_log_cid(conn); 1607 LSQ_WARNC("cannot add connection %"CID_FMT" to hash - destroy", 1608 CID_BITS(cid)); 1609 destroy_conn(engine, conn, lsquic_time_now()); 1610 goto err; 1611 } 1612 assert(!(conn->cn_flags & 1613 (CONN_REF_FLAGS 1614 & ~LSCONN_TICKABLE /* This flag may be set as effect of user 1615 callbacks */ 1616 ))); 1617 conn->cn_flags |= LSCONN_HASHED; 1618 lsquic_mh_insert(&engine->conns_tickable, conn, conn->cn_last_ticked); 1619 engine_incref_conn(conn, LSCONN_TICKABLE); 1620 lsquic_conn_set_ctx(conn, conn_ctx); 1621 conn->cn_if->ci_client_call_on_new(conn); 1622 end: 1623 ENGINE_OUT(engine); 1624 return conn; 1625 err: 1626 conn = NULL; 1627 goto end; 1628} 1629 1630 1631static void 1632remove_conn_from_hash (lsquic_engine_t *engine, lsquic_conn_t *conn) 1633{ 1634 remove_all_cces_from_hash(engine->conns_hash, conn); 1635 (void) engine_decref_conn(engine, conn, LSCONN_HASHED); 1636} 1637 1638 1639static void 1640refflags2str (enum lsquic_conn_flags flags, char s[7]) 1641{ 1642 *s = 'C'; s += !!(flags & LSCONN_CLOSING); 1643 *s = 'H'; s += !!(flags & LSCONN_HASHED); 1644 *s = 'O'; s += !!(flags & LSCONN_HAS_OUTGOING); 1645 *s = 'T'; s += !!(flags & LSCONN_TICKABLE); 1646 *s = 'A'; s += !!(flags & LSCONN_ATTQ); 1647 *s = 'K'; s += !!(flags & LSCONN_TICKED); 1648 *s = '\0'; 1649} 1650 1651 1652static void 1653engine_incref_conn (lsquic_conn_t *conn, enum lsquic_conn_flags flag) 1654{ 1655 char str[2][7]; 1656 assert(flag & CONN_REF_FLAGS); 1657 assert(!(conn->cn_flags & flag)); 1658 conn->cn_flags |= flag; 1659 LSQ_DEBUGC("incref conn %"CID_FMT", '%s' -> '%s'", 1660 CID_BITS(lsquic_conn_log_cid(conn)), 1661 (refflags2str(conn->cn_flags & ~flag, str[0]), str[0]), 1662 (refflags2str(conn->cn_flags, str[1]), str[1])); 1663} 1664 1665 1666static lsquic_conn_t * 1667engine_decref_conn (lsquic_engine_t *engine, lsquic_conn_t *conn, 1668 enum lsquic_conn_flags flags) 1669{ 1670 char str[2][7]; 1671 lsquic_time_t now; 1672 assert(flags & CONN_REF_FLAGS); 1673 assert(conn->cn_flags & flags); 1674#ifndef NDEBUG 1675 if (flags & LSCONN_CLOSING) 1676 assert(0 == (conn->cn_flags & LSCONN_HASHED)); 1677#endif 1678 conn->cn_flags &= ~flags; 1679 LSQ_DEBUGC("decref conn %"CID_FMT", '%s' -> '%s'", 1680 CID_BITS(lsquic_conn_log_cid(conn)), 1681 (refflags2str(conn->cn_flags | flags, str[0]), str[0]), 1682 (refflags2str(conn->cn_flags, str[1]), str[1])); 1683 if (0 == (conn->cn_flags & CONN_REF_FLAGS)) 1684 { 1685 now = lsquic_time_now(); 1686 if (conn->cn_flags & LSCONN_MINI) 1687 eng_hist_inc(&engine->history, now, sl_del_mini_conns); 1688 else 1689 eng_hist_inc(&engine->history, now, sl_del_full_conns); 1690 destroy_conn(engine, conn, now); 1691 return NULL; 1692 } 1693 else 1694 return conn; 1695} 1696 1697 1698/* This is not a general-purpose function. Only call from engine dtor. */ 1699static void 1700force_close_conn (lsquic_engine_t *engine, lsquic_conn_t *conn) 1701{ 1702 assert(engine->flags & ENG_DTOR); 1703 const enum lsquic_conn_flags flags = conn->cn_flags; 1704 assert(conn->cn_flags & CONN_REF_FLAGS); 1705 assert(!(flags & LSCONN_HAS_OUTGOING)); /* Should be removed already */ 1706 assert(!(flags & LSCONN_TICKABLE)); /* Should be removed already */ 1707 assert(!(flags & LSCONN_CLOSING)); /* It is in transient queue? */ 1708 if (flags & LSCONN_ATTQ) 1709 { 1710 lsquic_attq_remove(engine->attq, conn); 1711 (void) engine_decref_conn(engine, conn, LSCONN_ATTQ); 1712 } 1713 if (flags & LSCONN_HASHED) 1714 remove_conn_from_hash(engine, conn); 1715} 1716 1717 1718/* Iterator for tickable connections (those on the Tickable Queue). Before 1719 * a connection is returned, it is removed from the Advisory Tick Time queue 1720 * if necessary. 1721 */ 1722static lsquic_conn_t * 1723conn_iter_next_tickable (struct lsquic_engine *engine) 1724{ 1725 lsquic_conn_t *conn; 1726 1727 if (engine->flags & ENG_SERVER) 1728 while (1) 1729 { 1730 conn = lsquic_mh_pop(&engine->conns_tickable); 1731 if (conn && (conn->cn_flags & LSCONN_SKIP_ON_PROC)) 1732 (void) engine_decref_conn(engine, conn, LSCONN_TICKABLE); 1733 else 1734 break; 1735 } 1736 else 1737 conn = lsquic_mh_pop(&engine->conns_tickable); 1738 1739 if (conn) 1740 conn = engine_decref_conn(engine, conn, LSCONN_TICKABLE); 1741 if (conn && (conn->cn_flags & LSCONN_ATTQ)) 1742 { 1743 lsquic_attq_remove(engine->attq, conn); 1744 conn = engine_decref_conn(engine, conn, LSCONN_ATTQ); 1745 } 1746 1747 return conn; 1748} 1749 1750 1751static void 1752cub_init (struct cid_update_batch *cub, lsquic_cids_update_f update, 1753 void *update_ctx) 1754{ 1755 cub->cub_update_cids = update; 1756 cub->cub_update_ctx = update_ctx; 1757 cub->cub_count = 0; 1758} 1759 1760 1761static void 1762cub_flush (struct cid_update_batch *cub) 1763{ 1764 if (cub->cub_count > 0 && cub->cub_update_cids) 1765 cub->cub_update_cids(cub->cub_update_ctx, cub->cub_peer_ctxs, 1766 cub->cub_cids, cub->cub_count); 1767 cub->cub_count = 0; 1768} 1769 1770 1771static void 1772cub_add (struct cid_update_batch *cub, const lsquic_cid_t *cid, void *peer_ctx) 1773{ 1774 cub->cub_cids [ cub->cub_count ] = *cid; 1775 cub->cub_peer_ctxs[ cub->cub_count ] = peer_ctx; 1776 ++cub->cub_count; 1777 if (cub->cub_count == sizeof(cub->cub_cids) / sizeof(cub->cub_cids[0])) 1778 cub_flush(cub); 1779} 1780 1781 1782/* Process registered CIDs */ 1783static void 1784cub_add_cids_from_cces (struct cid_update_batch *cub, struct lsquic_conn *conn) 1785{ 1786 struct cce_cid_iter citer; 1787 struct conn_cid_elem *cce; 1788 void *peer_ctx; 1789 1790 peer_ctx = lsquic_conn_get_peer_ctx(conn, NULL); 1791 for (cce = cce_iter_first(&citer, conn); cce; cce = cce_iter_next(&citer)) 1792 if (cce->cce_flags & CCE_REG) 1793 cub_add(cub, &cce->cce_cid, peer_ctx); 1794} 1795 1796 1797static void 1798drop_all_mini_conns (lsquic_engine_t *engine) 1799{ 1800 struct lsquic_hash_elem *el; 1801 lsquic_conn_t *conn; 1802 struct cid_update_batch cub; 1803 1804 cub_init(&cub, engine->report_old_scids, engine->scids_ctx); 1805 1806 for (el = lsquic_hash_first(engine->conns_hash); el; 1807 el = lsquic_hash_next(engine->conns_hash)) 1808 { 1809 conn = lsquic_hashelem_getdata(el); 1810 if (conn->cn_flags & LSCONN_MINI) 1811 { 1812 /* If promoted, why is it still in this hash? */ 1813 assert(!(conn->cn_flags & LSCONN_PROMOTED)); 1814 if (!(conn->cn_flags & LSCONN_PROMOTED)) 1815 cub_add_cids_from_cces(&cub, conn); 1816 remove_conn_from_hash(engine, conn); 1817 } 1818 } 1819 1820 cub_flush(&cub); 1821} 1822 1823 1824void 1825lsquic_engine_process_conns (lsquic_engine_t *engine) 1826{ 1827 lsquic_conn_t *conn; 1828 lsquic_time_t now; 1829 1830 ENGINE_IN(engine); 1831 1832 now = lsquic_time_now(); 1833 while ((conn = lsquic_attq_pop(engine->attq, now))) 1834 { 1835 conn = engine_decref_conn(engine, conn, LSCONN_ATTQ); 1836 if (conn && !(conn->cn_flags & LSCONN_TICKABLE)) 1837 { 1838 lsquic_mh_insert(&engine->conns_tickable, conn, conn->cn_last_ticked); 1839 engine_incref_conn(conn, LSCONN_TICKABLE); 1840 } 1841 } 1842 1843 process_connections(engine, conn_iter_next_tickable, now); 1844 ENGINE_OUT(engine); 1845} 1846 1847 1848static void 1849release_or_return_enc_data (struct lsquic_engine *engine, 1850 void (*pmi_rel_or_ret) (void *, void *, void *, char), 1851 struct lsquic_conn *conn, struct lsquic_packet_out *packet_out) 1852{ 1853 pmi_rel_or_ret(engine->pub.enp_pmi_ctx, packet_out->po_path->np_peer_ctx, 1854 packet_out->po_enc_data, lsquic_packet_out_ipv6(packet_out)); 1855 packet_out->po_flags &= ~PO_ENCRYPTED; 1856 packet_out->po_enc_data = NULL; 1857} 1858 1859 1860static void 1861release_enc_data (struct lsquic_engine *engine, struct lsquic_conn *conn, 1862 struct lsquic_packet_out *packet_out) 1863{ 1864 release_or_return_enc_data(engine, engine->pub.enp_pmi->pmi_release, 1865 conn, packet_out); 1866} 1867 1868 1869static void 1870return_enc_data (struct lsquic_engine *engine, struct lsquic_conn *conn, 1871 struct lsquic_packet_out *packet_out) 1872{ 1873 release_or_return_enc_data(engine, engine->pub.enp_pmi->pmi_return, 1874 conn, packet_out); 1875} 1876 1877 1878static int 1879copy_packet (struct lsquic_engine *engine, struct lsquic_conn *conn, 1880 struct lsquic_packet_out *packet_out) 1881{ 1882 int ipv6; 1883 1884 ipv6 = NP_IS_IPv6(packet_out->po_path); 1885 if (packet_out->po_flags & PO_ENCRYPTED) 1886 { 1887 if (ipv6 == lsquic_packet_out_ipv6(packet_out) 1888 && packet_out->po_data_sz == packet_out->po_enc_data_sz 1889 && 0 == memcmp(packet_out->po_data, packet_out->po_enc_data, 1890 packet_out->po_data_sz)) 1891 return 0; 1892 if (ipv6 == lsquic_packet_out_ipv6(packet_out) 1893 && packet_out->po_data_sz <= packet_out->po_enc_data_sz) 1894 goto copy; 1895 return_enc_data(engine, conn, packet_out); 1896 } 1897 1898 packet_out->po_enc_data = engine->pub.enp_pmi->pmi_allocate( 1899 engine->pub.enp_pmi_ctx, packet_out->po_path->np_peer_ctx, 1900 packet_out->po_data_sz, ipv6); 1901 if (!packet_out->po_enc_data) 1902 { 1903 LSQ_DEBUG("could not allocate memory for outgoing unencrypted packet " 1904 "of size %hu", packet_out->po_data_sz); 1905 return -1; 1906 } 1907 1908 copy: 1909 memcpy(packet_out->po_enc_data, packet_out->po_data, 1910 packet_out->po_data_sz); 1911 packet_out->po_enc_data_sz = packet_out->po_data_sz; 1912 packet_out->po_sent_sz = packet_out->po_data_sz; 1913 packet_out->po_flags &= ~PO_IPv6; 1914 packet_out->po_flags |= PO_ENCRYPTED|PO_SENT_SZ|(ipv6 << POIPv6_SHIFT); 1915 1916 return 0; 1917} 1918 1919 1920STAILQ_HEAD(conns_stailq, lsquic_conn); 1921TAILQ_HEAD(conns_tailq, lsquic_conn); 1922 1923 1924struct conns_out_iter 1925{ 1926 struct min_heap *coi_heap; 1927 struct pr_queue *coi_prq; 1928 TAILQ_HEAD(, lsquic_conn) coi_active_list, 1929 coi_inactive_list; 1930 lsquic_conn_t *coi_next; 1931#ifndef NDEBUG 1932 lsquic_time_t coi_last_sent; 1933#endif 1934}; 1935 1936 1937static void 1938coi_init (struct conns_out_iter *iter, struct lsquic_engine *engine) 1939{ 1940 iter->coi_heap = &engine->conns_out; 1941 iter->coi_prq = engine->pr_queue; 1942 iter->coi_next = NULL; 1943 TAILQ_INIT(&iter->coi_active_list); 1944 TAILQ_INIT(&iter->coi_inactive_list); 1945#ifndef NDEBUG 1946 iter->coi_last_sent = 0; 1947#endif 1948} 1949 1950 1951static lsquic_conn_t * 1952coi_next (struct conns_out_iter *iter) 1953{ 1954 lsquic_conn_t *conn; 1955 1956 if (lsquic_mh_count(iter->coi_heap) > 0) 1957 { 1958 conn = lsquic_mh_pop(iter->coi_heap); 1959 TAILQ_INSERT_TAIL(&iter->coi_active_list, conn, cn_next_out); 1960 conn->cn_flags |= LSCONN_COI_ACTIVE; 1961#ifndef NDEBUG 1962 if (iter->coi_last_sent) 1963 assert(iter->coi_last_sent <= conn->cn_last_sent); 1964 iter->coi_last_sent = conn->cn_last_sent; 1965#endif 1966 return conn; 1967 } 1968 else if (iter->coi_prq && (conn = lsquic_prq_next_conn(iter->coi_prq))) 1969 { 1970 return conn; 1971 } 1972 else if (!TAILQ_EMPTY(&iter->coi_active_list)) 1973 { 1974 iter->coi_prq = NULL; /* Save function call in previous conditional */ 1975 conn = iter->coi_next; 1976 if (!conn) 1977 conn = TAILQ_FIRST(&iter->coi_active_list); 1978 if (conn) 1979 iter->coi_next = TAILQ_NEXT(conn, cn_next_out); 1980 return conn; 1981 } 1982 else 1983 return NULL; 1984} 1985 1986 1987static void 1988coi_deactivate (struct conns_out_iter *iter, lsquic_conn_t *conn) 1989{ 1990 if (!(conn->cn_flags & LSCONN_EVANESCENT)) 1991 { 1992 assert(!TAILQ_EMPTY(&iter->coi_active_list)); 1993 TAILQ_REMOVE(&iter->coi_active_list, conn, cn_next_out); 1994 conn->cn_flags &= ~LSCONN_COI_ACTIVE; 1995 TAILQ_INSERT_TAIL(&iter->coi_inactive_list, conn, cn_next_out); 1996 conn->cn_flags |= LSCONN_COI_INACTIVE; 1997 } 1998} 1999 2000 2001static void 2002coi_reactivate (struct conns_out_iter *iter, lsquic_conn_t *conn) 2003{ 2004 assert(conn->cn_flags & LSCONN_COI_INACTIVE); 2005 TAILQ_REMOVE(&iter->coi_inactive_list, conn, cn_next_out); 2006 conn->cn_flags &= ~LSCONN_COI_INACTIVE; 2007 TAILQ_INSERT_TAIL(&iter->coi_active_list, conn, cn_next_out); 2008 conn->cn_flags |= LSCONN_COI_ACTIVE; 2009} 2010 2011 2012static void 2013coi_reheap (struct conns_out_iter *iter, lsquic_engine_t *engine) 2014{ 2015 lsquic_conn_t *conn; 2016 while ((conn = TAILQ_FIRST(&iter->coi_active_list))) 2017 { 2018 TAILQ_REMOVE(&iter->coi_active_list, conn, cn_next_out); 2019 conn->cn_flags &= ~LSCONN_COI_ACTIVE; 2020 if ((conn->cn_flags & CONN_REF_FLAGS) != LSCONN_HAS_OUTGOING 2021 && !(conn->cn_flags & LSCONN_IMMED_CLOSE)) 2022 lsquic_mh_insert(iter->coi_heap, conn, conn->cn_last_sent); 2023 else /* Closed connection gets one shot at sending packets */ 2024 (void) engine_decref_conn(engine, conn, LSCONN_HAS_OUTGOING); 2025 } 2026 while ((conn = TAILQ_FIRST(&iter->coi_inactive_list))) 2027 { 2028 TAILQ_REMOVE(&iter->coi_inactive_list, conn, cn_next_out); 2029 conn->cn_flags &= ~LSCONN_COI_INACTIVE; 2030 (void) engine_decref_conn(engine, conn, LSCONN_HAS_OUTGOING); 2031 } 2032} 2033 2034 2035#ifndef NDEBUG 2036static void 2037lose_matching_packets (const lsquic_engine_t *engine, struct out_batch *batch, 2038 unsigned n) 2039{ 2040 const lsquic_cid_t *cid; 2041 struct iovec *iov; 2042 unsigned i; 2043 char packno_str[22]; 2044 2045 for (i = 0; i < n; ++i) 2046 { 2047 snprintf(packno_str, sizeof(packno_str), "%"PRIu64, 2048 batch->packets[i]->po_packno); 2049 if (0 == regexec(&engine->lose_packets_re, packno_str, 0, NULL, 0)) 2050 { 2051 for (iov = batch->outs[i].iov; iov < 2052 batch->outs[i].iov + batch->outs[i].iovlen; ++iov) 2053 batch->outs[i].iov->iov_len -= 1; 2054 cid = lsquic_conn_log_cid(batch->conns[i]); 2055 LSQ_WARNC("losing packet %s for connection %"CID_FMT, packno_str, 2056 CID_BITS(cid)); 2057 } 2058 } 2059} 2060 2061 2062#endif 2063 2064 2065#ifdef NDEBUG 2066#define CONST_BATCH const 2067#else 2068#define CONST_BATCH 2069#endif 2070 2071 2072struct send_batch_ctx { 2073 struct conns_stailq *closed_conns; 2074 struct conns_tailq *ticked_conns; 2075 struct conns_out_iter *conns_iter; 2076 CONST_BATCH struct out_batch *batch; 2077}; 2078 2079 2080static void 2081close_conn_immediately (struct lsquic_engine *engine, 2082 const struct send_batch_ctx *sb_ctx, struct lsquic_conn *conn) 2083{ 2084 conn->cn_flags |= LSCONN_IMMED_CLOSE; 2085 if (!(conn->cn_flags & LSCONN_CLOSING)) 2086 { 2087 STAILQ_INSERT_TAIL(sb_ctx->closed_conns, conn, cn_next_closed_conn); 2088 engine_incref_conn(conn, LSCONN_CLOSING); 2089 if (conn->cn_flags & LSCONN_HASHED) 2090 remove_conn_from_hash(engine, conn); 2091 } 2092 if (conn->cn_flags & LSCONN_TICKED) 2093 { 2094 TAILQ_REMOVE(sb_ctx->ticked_conns, conn, cn_next_ticked); 2095 engine_decref_conn(engine, conn, LSCONN_TICKED); 2096 } 2097} 2098 2099 2100static void 2101close_conn_on_send_error (struct lsquic_engine *engine, 2102 const struct send_batch_ctx *sb_ctx, int n, int e_val) 2103{ 2104 const struct out_batch *batch = sb_ctx->batch; 2105 struct lsquic_conn *const conn = batch->conns[n]; 2106 char buf[2][INET6_ADDRSTRLEN + sizeof(":65535")]; 2107 2108 LSQ_WARNC("error sending packet for %s connection %"CID_FMT" - close it; " 2109 "src: %s; dst: %s; errno: %d", 2110 conn->cn_flags & LSCONN_EVANESCENT ? "evanecsent" : 2111 conn->cn_flags & LSCONN_MINI ? "mini" : "regular", 2112 CID_BITS(lsquic_conn_log_cid(conn)), 2113 SA2STR(batch->outs[n].local_sa, buf[0]), 2114 SA2STR(batch->outs[n].dest_sa, buf[1]), 2115 e_val); 2116 if (conn->cn_flags & LSCONN_EVANESCENT) 2117 lsquic_prq_drop(conn); 2118 else 2119 close_conn_immediately(engine, sb_ctx, conn); 2120} 2121 2122 2123static unsigned 2124send_batch (lsquic_engine_t *engine, const struct send_batch_ctx *sb_ctx, 2125 unsigned n_to_send) 2126{ 2127 int n_sent, i, e_val; 2128 lsquic_time_t now; 2129 unsigned off; 2130 size_t count; 2131 CONST_BATCH struct out_batch *const batch = sb_ctx->batch; 2132 struct lsquic_packet_out *CONST_BATCH *packet_out, *CONST_BATCH *end; 2133 2134#ifndef NDEBUG 2135 if (engine->flags & ENG_LOSE_PACKETS) 2136 lose_matching_packets(engine, batch, n_to_send); 2137#endif 2138 /* Set sent time before the write to avoid underestimating RTT */ 2139 now = lsquic_time_now(); 2140 for (i = 0; i < (int) n_to_send; ++i) 2141 { 2142 off = batch->pack_off[i]; 2143 count = batch->outs[i].iovlen; 2144 assert(count > 0); 2145 packet_out = &batch->packets[off]; 2146 end = packet_out + count; 2147 do 2148 (*packet_out)->po_sent = now; 2149 while (++packet_out < end); 2150 } 2151 n_sent = engine->packets_out(engine->packets_out_ctx, batch->outs, 2152 n_to_send); 2153 e_val = errno; 2154 if (n_sent < (int) n_to_send) 2155 { 2156 engine->pub.enp_flags &= ~ENPUB_CAN_SEND; 2157 engine->resume_sending_at = now + 1000000; 2158 LSQ_DEBUG("cannot send packets"); 2159 EV_LOG_GENERIC_EVENT("cannot send packets"); 2160 if (!(EAGAIN == e_val || EWOULDBLOCK == e_val)) 2161 close_conn_on_send_error(engine, sb_ctx, 2162 n_sent < 0 ? 0 : n_sent, e_val); 2163 } 2164 if (n_sent >= 0) 2165 LSQ_DEBUG("packets out returned %d (out of %u)", n_sent, n_to_send); 2166 else 2167 { 2168 LSQ_DEBUG("packets out returned an error: %s", strerror(e_val)); 2169 n_sent = 0; 2170 } 2171 if (n_sent > 0) 2172 engine->last_sent = now + n_sent; 2173 for (i = 0; i < n_sent; ++i) 2174 { 2175 eng_hist_inc(&engine->history, now, sl_packets_out); 2176 /* `i' is added to maintain relative order */ 2177 batch->conns[i]->cn_last_sent = now + i; 2178 2179 off = batch->pack_off[i]; 2180 count = batch->outs[i].iovlen; 2181 assert(count > 0); 2182 packet_out = &batch->packets[off]; 2183 end = packet_out + count; 2184 do 2185 { 2186#if LOG_PACKET_CHECKSUM 2187 log_packet_checksum(lsquic_conn_log_cid(batch->conns[i]), "out", 2188 batch->outs[i].iov[packet_out - &batch->packets[off]].iov_base, 2189 batch->outs[i].iov[packet_out - &batch->packets[off]].iov_len); 2190#endif 2191 EV_LOG_PACKET_SENT(lsquic_conn_log_cid(batch->conns[i]), 2192 *packet_out); 2193 /* Release packet out buffer as soon as the packet is sent 2194 * successfully. If not successfully sent, we hold on to 2195 * this buffer until the packet sending is attempted again 2196 * or until it times out and regenerated. 2197 */ 2198 if ((*packet_out)->po_flags & PO_ENCRYPTED) 2199 release_enc_data(engine, batch->conns[i], *packet_out); 2200 batch->conns[i]->cn_if->ci_packet_sent(batch->conns[i], 2201 *packet_out); 2202 } 2203 while (++packet_out < end); 2204 } 2205 if (LSQ_LOG_ENABLED_EXT(LSQ_LOG_DEBUG, LSQLM_EVENT)) 2206 for ( ; i < (int) n_to_send; ++i) 2207 { 2208 off = batch->pack_off[i]; 2209 count = batch->outs[i].iovlen; 2210 assert(count > 0); 2211 packet_out = &batch->packets[off]; 2212 end = packet_out + count; 2213 do 2214 EV_LOG_PACKET_NOT_SENT(lsquic_conn_log_cid(batch->conns[i]), 2215 *packet_out); 2216 while (++packet_out < end); 2217 } 2218 /* Return packets to the connection in reverse order so that the packet 2219 * ordering is maintained. 2220 */ 2221 for (i = (int) n_to_send - 1; i >= n_sent; --i) 2222 { 2223 off = batch->pack_off[i]; 2224 count = batch->outs[i].iovlen; 2225 assert(count > 0); 2226 packet_out = &batch->packets[off + count - 1]; 2227 end = &batch->packets[off - 1]; 2228 do 2229 batch->conns[i]->cn_if->ci_packet_not_sent(batch->conns[i], 2230 *packet_out); 2231 while (--packet_out > end); 2232 if (!(batch->conns[i]->cn_flags & (LSCONN_COI_ACTIVE|LSCONN_EVANESCENT))) 2233 coi_reactivate(sb_ctx->conns_iter, batch->conns[i]); 2234 } 2235 return n_sent; 2236} 2237 2238 2239/* Return 1 if went past deadline, 0 otherwise */ 2240static int 2241check_deadline (lsquic_engine_t *engine) 2242{ 2243 if (engine->pub.enp_settings.es_proc_time_thresh && 2244 lsquic_time_now() > engine->deadline) 2245 { 2246 LSQ_INFO("went past threshold of %u usec, stop sending", 2247 engine->pub.enp_settings.es_proc_time_thresh); 2248 engine->flags |= ENG_PAST_DEADLINE; 2249 return 1; 2250 } 2251 else 2252 return 0; 2253} 2254 2255 2256static size_t 2257iov_size (const struct iovec *iov, const struct iovec *const end) 2258{ 2259 size_t size; 2260 2261 assert(iov < end); 2262 2263 size = 0; 2264 do 2265 size += iov->iov_len; 2266 while (++iov < end); 2267 2268 return size; 2269} 2270 2271 2272static void 2273send_packets_out (struct lsquic_engine *engine, 2274 struct conns_tailq *ticked_conns, 2275 struct conns_stailq *closed_conns) 2276{ 2277 unsigned n, w, n_sent, n_batches_sent; 2278 lsquic_packet_out_t *packet_out; 2279 struct lsquic_packet_out **packet; 2280 lsquic_conn_t *conn; 2281 struct out_batch *const batch = &engine->out_batch; 2282 struct iovec *iov, *packet_iov; 2283 struct conns_out_iter conns_iter; 2284 int shrink, deadline_exceeded; 2285 const struct send_batch_ctx sb_ctx = { 2286 closed_conns, 2287 ticked_conns, 2288 &conns_iter, 2289 &engine->out_batch, 2290 }; 2291 2292 coi_init(&conns_iter, engine); 2293 n_batches_sent = 0; 2294 n_sent = 0, n = 0; 2295 shrink = 0; 2296 deadline_exceeded = 0; 2297 iov = batch->iov; 2298 packet = batch->packets; 2299 2300 while ((conn = coi_next(&conns_iter))) 2301 { 2302 packet_out = conn->cn_if->ci_next_packet_to_send(conn, 0); 2303 if (!packet_out) { 2304 /* Evanescent connection always has a packet to send: */ 2305 assert(!(conn->cn_flags & LSCONN_EVANESCENT)); 2306 LSQ_DEBUGC("batched all outgoing packets for %s conn %"CID_FMT, 2307 (conn->cn_flags & LSCONN_MINI ? "mini" : "full"), 2308 CID_BITS(lsquic_conn_log_cid(conn))); 2309 coi_deactivate(&conns_iter, conn); 2310 continue; 2311 } 2312 batch->outs[n].iov = packet_iov = iov; 2313 next_coa: 2314 if (!(packet_out->po_flags & (PO_ENCRYPTED|PO_NOENCRYPT))) 2315 { 2316 switch (conn->cn_esf_c->esf_encrypt_packet(conn->cn_enc_session, 2317 &engine->pub, conn, packet_out)) 2318 { 2319 case ENCPA_NOMEM: 2320 /* Send what we have and wait for a more opportune moment */ 2321 conn->cn_if->ci_packet_not_sent(conn, packet_out); 2322 goto end_for; 2323 case ENCPA_BADCRYPT: 2324 /* This is pretty bad: close connection immediately */ 2325 conn->cn_if->ci_packet_not_sent(conn, packet_out); 2326 LSQ_INFOC("conn %"CID_FMT" has unsendable packets", 2327 CID_BITS(lsquic_conn_log_cid(conn))); 2328 if (!(conn->cn_flags & LSCONN_EVANESCENT)) 2329 { 2330 close_conn_immediately(engine, &sb_ctx, conn); 2331 coi_deactivate(&conns_iter, conn); 2332 } 2333 continue; 2334 case ENCPA_OK: 2335 break; 2336 } 2337 } 2338 else if ((packet_out->po_flags & PO_NOENCRYPT) 2339 && engine->pub.enp_pmi != &stock_pmi) 2340 { 2341 if (0 != copy_packet(engine, conn, packet_out)) 2342 { 2343 /* Copy can only fail if packet could not be allocated */ 2344 conn->cn_if->ci_packet_not_sent(conn, packet_out); 2345 goto end_for; 2346 } 2347 } 2348 LSQ_DEBUGC("batched packet %"PRIu64" for connection %"CID_FMT, 2349 packet_out->po_packno, CID_BITS(lsquic_conn_log_cid(conn))); 2350 if (packet_out->po_flags & PO_ENCRYPTED) 2351 { 2352 iov->iov_base = packet_out->po_enc_data; 2353 iov->iov_len = packet_out->po_enc_data_sz; 2354 } 2355 else 2356 { 2357 iov->iov_base = packet_out->po_data; 2358 iov->iov_len = packet_out->po_data_sz; 2359 } 2360 if (packet_iov == iov) 2361 { 2362 batch->pack_off[n] = packet - batch->packets; 2363 batch->outs [n].ecn = lsquic_packet_out_ecn(packet_out); 2364 batch->outs [n].peer_ctx = packet_out->po_path->np_peer_ctx; 2365 batch->outs [n].local_sa = NP_LOCAL_SA(packet_out->po_path); 2366 batch->outs [n].dest_sa = NP_PEER_SA(packet_out->po_path); 2367 batch->conns [n] = conn; 2368 } 2369 *packet = packet_out; 2370 ++packet; 2371 ++iov; 2372 if ((conn->cn_flags & LSCONN_IETF) 2373 && ((1 << packet_out->po_header_type) 2374 & ((1 << HETY_INITIAL)|(1 << HETY_HANDSHAKE)|(1 << HETY_0RTT))) 2375#ifndef NDEBUG 2376 && (engine->flags & ENG_COALESCE) 2377#endif 2378 && iov < batch->iov + sizeof(batch->iov) / sizeof(batch->iov[0])) 2379 { 2380 const size_t size = iov_size(packet_iov, iov); 2381 packet_out = conn->cn_if->ci_next_packet_to_send(conn, size); 2382 if (packet_out) 2383 goto next_coa; 2384 } 2385 batch->outs [n].iovlen = iov - packet_iov; 2386 ++n; 2387 if (n == engine->batch_size 2388 || iov >= batch->iov + sizeof(batch->iov) / sizeof(batch->iov[0])) 2389 { 2390 w = send_batch(engine, &sb_ctx, n); 2391 n = 0; 2392 iov = batch->iov; 2393 packet = batch->packets; 2394 ++n_batches_sent; 2395 n_sent += w; 2396 if (w < engine->batch_size) 2397 { 2398 shrink = 1; 2399 break; 2400 } 2401 deadline_exceeded = check_deadline(engine); 2402 if (deadline_exceeded) 2403 break; 2404 grow_batch_size(engine); 2405 } 2406 } 2407 end_for: 2408 2409 if (n > 0) { 2410 w = send_batch(engine, &sb_ctx, n); 2411 n_sent += w; 2412 shrink = w < n; 2413 ++n_batches_sent; 2414 } 2415 2416 if (shrink) 2417 shrink_batch_size(engine); 2418 else if (n_batches_sent > 1) 2419 { 2420 deadline_exceeded = check_deadline(engine); 2421 if (!deadline_exceeded) 2422 grow_batch_size(engine); 2423 } 2424 2425 coi_reheap(&conns_iter, engine); 2426 2427 LSQ_DEBUG("%s: sent %u packet%.*s", __func__, n_sent, n_sent != 1, "s"); 2428} 2429 2430 2431int 2432lsquic_engine_has_unsent_packets (lsquic_engine_t *engine) 2433{ 2434 return lsquic_mh_count(&engine->conns_out) > 0 2435 || (engine->pr_queue && lsquic_prq_have_pending(engine->pr_queue)) 2436 ; 2437} 2438 2439 2440static void 2441reset_deadline (lsquic_engine_t *engine, lsquic_time_t now) 2442{ 2443 engine->deadline = now + engine->pub.enp_settings.es_proc_time_thresh; 2444 engine->flags &= ~ENG_PAST_DEADLINE; 2445} 2446 2447 2448static void 2449check_tickable_conns_again (struct lsquic_engine *engine) 2450{ 2451 struct lsquic_hash_elem *el; 2452 struct lsquic_conn *conn; 2453 unsigned count; 2454 2455 count = 0; 2456 for (el = lsquic_hash_first(engine->conns_hash); el; 2457 el = lsquic_hash_next(engine->conns_hash)) 2458 { 2459 conn = lsquic_hashelem_getdata(el); 2460 if (!(conn->cn_flags & LSCONN_TICKABLE) 2461 && conn->cn_if->ci_is_tickable(conn)) 2462 { 2463 lsquic_mh_insert(&engine->conns_tickable, conn, 2464 conn->cn_last_ticked); 2465 engine_incref_conn(conn, LSCONN_TICKABLE); 2466 ++count; 2467 } 2468 } 2469 LSQ_DEBUG("%u connection%s tickable again after sending has been " 2470 "re-enabled", count, count == 1 ? " is" : "s are"); 2471} 2472 2473 2474void 2475lsquic_engine_send_unsent_packets (lsquic_engine_t *engine) 2476{ 2477 lsquic_conn_t *conn; 2478 struct conns_stailq closed_conns; 2479 struct conns_tailq ticked_conns = TAILQ_HEAD_INITIALIZER(ticked_conns); 2480 struct cid_update_batch cub; 2481 2482 ENGINE_IN(engine); 2483 cub_init(&cub, engine->report_old_scids, engine->scids_ctx); 2484 STAILQ_INIT(&closed_conns); 2485 reset_deadline(engine, lsquic_time_now()); 2486 if (!(engine->pub.enp_flags & ENPUB_CAN_SEND)) 2487 { 2488 LSQ_DEBUG("can send again"); 2489 EV_LOG_GENERIC_EVENT("can send again"); 2490 engine->pub.enp_flags |= ENPUB_CAN_SEND; 2491 check_tickable_conns_again(engine); 2492 } 2493 2494 send_packets_out(engine, &ticked_conns, &closed_conns); 2495 2496 while ((conn = STAILQ_FIRST(&closed_conns))) { 2497 STAILQ_REMOVE_HEAD(&closed_conns, cn_next_closed_conn); 2498 if ((conn->cn_flags & (LSCONN_MINI|LSCONN_PROMOTED)) == LSCONN_MINI) 2499 cub_add_cids_from_cces(&cub, conn); 2500 (void) engine_decref_conn(engine, conn, LSCONN_CLOSING); 2501 } 2502 2503 cub_flush(&cub); 2504 ENGINE_OUT(engine); 2505} 2506 2507 2508static lsquic_conn_t * 2509next_new_full_conn (struct conns_stailq *new_full_conns) 2510{ 2511 lsquic_conn_t *conn; 2512 2513 conn = STAILQ_FIRST(new_full_conns); 2514 if (conn) 2515 STAILQ_REMOVE_HEAD(new_full_conns, cn_next_new_full); 2516 return conn; 2517} 2518 2519 2520static void 2521process_connections (lsquic_engine_t *engine, conn_iter_f next_conn, 2522 lsquic_time_t now) 2523{ 2524 lsquic_conn_t *conn; 2525 enum tick_st tick_st; 2526 unsigned i, why; 2527 lsquic_time_t next_tick_time; 2528 struct conns_stailq closed_conns; 2529 struct conns_tailq ticked_conns; 2530 struct conns_stailq new_full_conns; 2531 struct cid_update_batch cub_old, cub_live; 2532 cub_init(&cub_old, engine->report_old_scids, engine->scids_ctx); 2533 cub_init(&cub_live, engine->report_live_scids, engine->scids_ctx); 2534 2535 eng_hist_tick(&engine->history, now); 2536 2537 STAILQ_INIT(&closed_conns); 2538 TAILQ_INIT(&ticked_conns); 2539 reset_deadline(engine, now); 2540 STAILQ_INIT(&new_full_conns); 2541 2542 if (!(engine->pub.enp_flags & ENPUB_CAN_SEND) 2543 && now > engine->resume_sending_at) 2544 { 2545 LSQ_NOTICE("failsafe activated: resume sending packets again after " 2546 "timeout"); 2547 EV_LOG_GENERIC_EVENT("resume sending packets again after timeout"); 2548 engine->pub.enp_flags |= ENPUB_CAN_SEND; 2549 } 2550 2551 i = 0; 2552 while ((conn = next_conn(engine)) 2553 || (conn = next_new_full_conn(&new_full_conns))) 2554 { 2555 tick_st = conn->cn_if->ci_tick(conn, now); 2556 conn->cn_last_ticked = now + i /* Maintain relative order */ ++; 2557 if (tick_st & TICK_PROMOTE) 2558 { 2559 lsquic_conn_t *new_conn; 2560 EV_LOG_CONN_EVENT(lsquic_conn_log_cid(conn), 2561 "scheduled for promotion"); 2562 assert(conn->cn_flags & LSCONN_MINI); 2563 new_conn = new_full_conn_server(engine, conn, now); 2564 if (new_conn) 2565 { 2566 STAILQ_INSERT_TAIL(&new_full_conns, new_conn, cn_next_new_full); 2567 new_conn->cn_last_sent = engine->last_sent; 2568 eng_hist_inc(&engine->history, now, sl_new_full_conns); 2569 conn->cn_flags |= LSCONN_PROMOTED; 2570 } 2571 tick_st |= TICK_CLOSE; /* Destroy mini connection */ 2572 } 2573 if (tick_st & TICK_SEND) 2574 { 2575 if (!(conn->cn_flags & LSCONN_HAS_OUTGOING)) 2576 { 2577 lsquic_mh_insert(&engine->conns_out, conn, conn->cn_last_sent); 2578 engine_incref_conn(conn, LSCONN_HAS_OUTGOING); 2579 } 2580 } 2581 if (tick_st & TICK_CLOSE) 2582 { 2583 STAILQ_INSERT_TAIL(&closed_conns, conn, cn_next_closed_conn); 2584 engine_incref_conn(conn, LSCONN_CLOSING); 2585 if (conn->cn_flags & LSCONN_HASHED) 2586 remove_conn_from_hash(engine, conn); 2587 } 2588 else 2589 { 2590 TAILQ_INSERT_TAIL(&ticked_conns, conn, cn_next_ticked); 2591 engine_incref_conn(conn, LSCONN_TICKED); 2592 if ((engine->flags & ENG_SERVER) && conn->cn_if->ci_report_live 2593 && conn->cn_if->ci_report_live(conn, now)) 2594 cub_add_cids_from_cces(&cub_live, conn); 2595 } 2596 } 2597 2598 if ((engine->pub.enp_flags & ENPUB_CAN_SEND) 2599 && lsquic_engine_has_unsent_packets(engine)) 2600 send_packets_out(engine, &ticked_conns, &closed_conns); 2601 2602 while ((conn = STAILQ_FIRST(&closed_conns))) { 2603 STAILQ_REMOVE_HEAD(&closed_conns, cn_next_closed_conn); 2604 if ((conn->cn_flags & (LSCONN_MINI|LSCONN_PROMOTED)) == LSCONN_MINI) 2605 cub_add_cids_from_cces(&cub_old, conn); 2606 (void) engine_decref_conn(engine, conn, LSCONN_CLOSING); 2607 } 2608 2609 while ((conn = TAILQ_FIRST(&ticked_conns))) 2610 { 2611 TAILQ_REMOVE(&ticked_conns, conn, cn_next_ticked); 2612 engine_decref_conn(engine, conn, LSCONN_TICKED); 2613 if (!(conn->cn_flags & LSCONN_TICKABLE) 2614 && conn->cn_if->ci_is_tickable(conn)) 2615 { 2616 /* Floyd heapification is not faster, don't bother. */ 2617 lsquic_mh_insert(&engine->conns_tickable, conn, conn->cn_last_ticked); 2618 engine_incref_conn(conn, LSCONN_TICKABLE); 2619 } 2620 else if (!(conn->cn_flags & LSCONN_ATTQ)) 2621 { 2622 next_tick_time = conn->cn_if->ci_next_tick_time(conn, &why); 2623 if (next_tick_time) 2624 { 2625 if (0 == lsquic_attq_add(engine->attq, conn, next_tick_time, 2626 why)) 2627 engine_incref_conn(conn, LSCONN_ATTQ); 2628 } 2629 else 2630 /* In all other cases, the idle timeout would make the next 2631 * tick time non-zero: 2632 */ 2633 assert((conn->cn_flags & LSCONN_IETF) 2634 && engine->pub.enp_settings.es_idle_timeout == 0); 2635 } 2636 } 2637 2638 cub_flush(&engine->new_scids); 2639 cub_flush(&cub_live); 2640 cub_flush(&cub_old); 2641} 2642 2643 2644/* Return 0 if packet is being processed by a real connection, 1 if the 2645 * packet was processed, but not by a connection, and -1 on error. 2646 */ 2647int 2648lsquic_engine_packet_in (lsquic_engine_t *engine, 2649 const unsigned char *packet_in_data, size_t packet_in_size, 2650 const struct sockaddr *sa_local, const struct sockaddr *sa_peer, 2651 void *peer_ctx, int ecn) 2652{ 2653 const unsigned char *const packet_begin = packet_in_data; 2654 const unsigned char *const packet_end = packet_in_data + packet_in_size; 2655 struct packin_parse_state ppstate; 2656 lsquic_packet_in_t *packet_in; 2657 int (*parse_packet_in_begin) (struct lsquic_packet_in *, size_t length, 2658 int is_server, unsigned cid_len, struct packin_parse_state *); 2659 unsigned n_zeroes; 2660 int s, is_ietf; 2661 lsquic_cid_t cid; 2662 2663 ENGINE_CALLS_INCR(engine); 2664 2665 if (engine->flags & ENG_SERVER) 2666 parse_packet_in_begin = lsquic_parse_packet_in_server_begin; 2667 else if (engine->flags & ENG_CONNS_BY_ADDR) 2668 { 2669 struct lsquic_hash_elem *el; 2670 const struct lsquic_conn *conn; 2671 el = find_conn_by_addr(engine->conns_hash, sa_local); 2672 if (!el) 2673 return -1; 2674 conn = lsquic_hashelem_getdata(el); 2675 if ((1 << conn->cn_version) & LSQUIC_GQUIC_HEADER_VERSIONS) 2676 parse_packet_in_begin = lsquic_gquic_parse_packet_in_begin; 2677 else if ((1 << conn->cn_version) & LSQUIC_IETF_VERSIONS) 2678 parse_packet_in_begin = lsquic_ietf_v1_parse_packet_in_begin; 2679 else if (conn->cn_version == LSQVER_050) 2680 parse_packet_in_begin = lsquic_Q050_parse_packet_in_begin; 2681 else 2682 { 2683 assert(conn->cn_version == LSQVER_046 2684#if LSQUIC_USE_Q098 2685 || conn->cn_version == LSQVER_098 2686#endif 2687 2688 ); 2689 parse_packet_in_begin = lsquic_Q046_parse_packet_in_begin; 2690 } 2691 } 2692 else 2693 parse_packet_in_begin = lsquic_parse_packet_in_begin; 2694 2695 n_zeroes = 0; 2696 is_ietf = 0; 2697 do 2698 { 2699 packet_in = lsquic_mm_get_packet_in(&engine->pub.enp_mm); 2700 if (!packet_in) 2701 return -1; 2702 /* Library does not modify packet_in_data, it is not referenced after 2703 * this function returns and subsequent release of pi_data is guarded 2704 * by PI_OWN_DATA flag. 2705 */ 2706 packet_in->pi_data = (unsigned char *) packet_in_data; 2707 if (0 != parse_packet_in_begin(packet_in, packet_end - packet_in_data, 2708 engine->flags & ENG_SERVER, 2709 engine->pub.enp_settings.es_scid_len, &ppstate)) 2710 { 2711 LSQ_DEBUG("Cannot parse incoming packet's header"); 2712 lsquic_mm_put_packet_in(&engine->pub.enp_mm, packet_in); 2713 s = 1; 2714 break; 2715 } 2716 2717 /* [draft-ietf-quic-transport-27] Section 12.2: 2718 * " Receivers SHOULD ignore any subsequent packets with a different 2719 * " Destination Connection ID than the first packet in the datagram. 2720 */ 2721 if (is_ietf && packet_in_data > packet_begin) 2722 { 2723 if (!((packet_in->pi_flags & (PI_GQUIC|PI_CONN_ID)) == PI_CONN_ID 2724 && LSQUIC_CIDS_EQ(&packet_in->pi_dcid, &cid))) 2725 { 2726 packet_in_data += packet_in->pi_data_sz; 2727 continue; 2728 } 2729 } 2730 2731 is_ietf = 0 == (packet_in->pi_flags & PI_GQUIC); 2732 packet_in_data += packet_in->pi_data_sz; 2733 if (is_ietf && packet_in_data < packet_end) 2734 cid = packet_in->pi_dcid; 2735 packet_in->pi_received = lsquic_time_now(); 2736 packet_in->pi_flags |= (3 & ecn) << PIBIT_ECN_SHIFT; 2737 eng_hist_inc(&engine->history, packet_in->pi_received, sl_packets_in); 2738 s = process_packet_in(engine, packet_in, &ppstate, sa_local, sa_peer, 2739 peer_ctx, packet_in_size); 2740 n_zeroes += s == 0; 2741 } 2742 while (0 == s && packet_in_data < packet_end); 2743 2744 return n_zeroes > 0 ? 0 : s; 2745} 2746 2747 2748#if __GNUC__ && !defined(NDEBUG) 2749__attribute__((weak)) 2750#endif 2751unsigned 2752lsquic_engine_quic_versions (const lsquic_engine_t *engine) 2753{ 2754 return engine->pub.enp_settings.es_versions; 2755} 2756 2757 2758void 2759lsquic_engine_cooldown (lsquic_engine_t *engine) 2760{ 2761 struct lsquic_hash_elem *el; 2762 lsquic_conn_t *conn; 2763 2764 if (engine->flags & ENG_COOLDOWN) 2765 /* AFAICT, there is no harm in calling this function more than once, 2766 * but log it just in case, as it may indicate an error in the caller. 2767 */ 2768 LSQ_INFO("cooldown called again"); 2769 engine->flags |= ENG_COOLDOWN; 2770 LSQ_INFO("entering cooldown mode"); 2771 if (engine->flags & ENG_SERVER) 2772 drop_all_mini_conns(engine); 2773 for (el = lsquic_hash_first(engine->conns_hash); el; 2774 el = lsquic_hash_next(engine->conns_hash)) 2775 { 2776 conn = lsquic_hashelem_getdata(el); 2777 lsquic_conn_going_away(conn); 2778 } 2779} 2780 2781 2782int 2783lsquic_engine_earliest_adv_tick (lsquic_engine_t *engine, int *diff) 2784{ 2785 const struct attq_elem *next_attq; 2786 lsquic_time_t now, next_time; 2787#if LSQUIC_DEBUG_NEXT_ADV_TICK 2788 const struct lsquic_conn *conn; 2789 const enum lsq_log_level L = LSQ_LOG_DEBUG; /* Easy toggle */ 2790#endif 2791 2792 ENGINE_CALLS_INCR(engine); 2793 2794 if ((engine->flags & ENG_PAST_DEADLINE) 2795 && lsquic_mh_count(&engine->conns_out)) 2796 { 2797#if LSQUIC_DEBUG_NEXT_ADV_TICK 2798 conn = lsquic_mh_peek(&engine->conns_out); 2799 engine->last_logged_conn = 0; 2800 LSQ_LOGC(L, "next advisory tick is now: went past deadline last time " 2801 "and have %u outgoing connection%.*s (%"CID_FMT" first)", 2802 lsquic_mh_count(&engine->conns_out), 2803 lsquic_mh_count(&engine->conns_out) != 1, "s", 2804 CID_BITS(lsquic_conn_log_cid(conn))); 2805#endif 2806 *diff = 0; 2807 return 1; 2808 } 2809 2810 if (engine->pr_queue && lsquic_prq_have_pending(engine->pr_queue)) 2811 { 2812#if LSQUIC_DEBUG_NEXT_ADV_TICK 2813 engine->last_logged_conn = 0; 2814 LSQ_LOG(L, "next advisory tick is now: have pending PRQ elements"); 2815#endif 2816 *diff = 0; 2817 return 1; 2818 } 2819 2820 if (lsquic_mh_count(&engine->conns_tickable)) 2821 { 2822#if LSQUIC_DEBUG_NEXT_ADV_TICK 2823 conn = lsquic_mh_peek(&engine->conns_tickable); 2824 engine->last_logged_conn = 0; 2825 LSQ_LOGC(L, "next advisory tick is now: have %u tickable " 2826 "connection%.*s (%"CID_FMT" first)", 2827 lsquic_mh_count(&engine->conns_tickable), 2828 lsquic_mh_count(&engine->conns_tickable) != 1, "s", 2829 CID_BITS(lsquic_conn_log_cid(conn))); 2830#endif 2831 *diff = 0; 2832 return 1; 2833 } 2834 2835 next_attq = lsquic_attq_next(engine->attq); 2836 if (engine->pub.enp_flags & ENPUB_CAN_SEND) 2837 { 2838 if (next_attq) 2839 next_time = next_attq->ae_adv_time; 2840 else 2841 return 0; 2842 } 2843 else 2844 { 2845 if (next_attq) 2846 { 2847 next_time = next_attq->ae_adv_time; 2848 if (engine->resume_sending_at < next_time) 2849 { 2850 next_time = engine->resume_sending_at; 2851 next_attq = NULL; 2852 } 2853 } 2854 else 2855 next_time = engine->resume_sending_at; 2856 } 2857 2858 now = lsquic_time_now(); 2859 *diff = (int) ((int64_t) next_time - (int64_t) now); 2860#if LSQUIC_DEBUG_NEXT_ADV_TICK 2861 if (next_attq) 2862 { 2863 /* Deduplicate consecutive log messages about the same reason for the 2864 * same connection. 2865 * If diff is always zero or diff reset to a higher value, event is 2866 * still logged. 2867 */ 2868 if (!((unsigned) next_attq->ae_why == engine->last_logged_ae_why 2869 && (uintptr_t) next_attq->ae_conn 2870 == engine->last_logged_conn 2871 && *diff < engine->last_tick_diff)) 2872 { 2873 engine->last_logged_conn = (uintptr_t) next_attq->ae_conn; 2874 engine->last_logged_ae_why = (unsigned) next_attq->ae_why; 2875 engine->last_tick_diff = *diff; 2876 LSQ_LOGC(L, "next advisory tick is %d usec away: conn %"CID_FMT 2877 ": %s", *diff, CID_BITS(lsquic_conn_log_cid(next_attq->ae_conn)), 2878 lsquic_attq_why2str(next_attq->ae_why)); 2879 } 2880 } 2881 else 2882 LSQ_LOG(L, "next advisory tick is %d usec away: resume sending", *diff); 2883#endif 2884 return 1; 2885} 2886 2887 2888unsigned 2889lsquic_engine_count_attq (lsquic_engine_t *engine, int from_now) 2890{ 2891 lsquic_time_t now; 2892 ENGINE_CALLS_INCR(engine); 2893 now = lsquic_time_now(); 2894 if (from_now < 0) 2895 now -= from_now; 2896 else 2897 now += from_now; 2898 return lsquic_attq_count_before(engine->attq, now); 2899} 2900 2901 2902int 2903lsquic_engine_add_cid (struct lsquic_engine_public *enpub, 2904 struct lsquic_conn *conn, unsigned cce_idx) 2905{ 2906 struct lsquic_engine *const engine = (struct lsquic_engine *) enpub; 2907 struct conn_cid_elem *const cce = &conn->cn_cces[cce_idx]; 2908 void *peer_ctx; 2909 2910 assert(cce_idx < conn->cn_n_cces); 2911 assert(conn->cn_cces_mask & (1 << cce_idx)); 2912 assert(!(cce->cce_hash_el.qhe_flags & QHE_HASHED)); 2913 2914 if (lsquic_hash_insert(engine->conns_hash, cce->cce_cid.idbuf, 2915 cce->cce_cid.len, conn, &cce->cce_hash_el)) 2916 { 2917 LSQ_DEBUGC("add %"CID_FMT" to the list of SCIDs", 2918 CID_BITS(&cce->cce_cid)); 2919 peer_ctx = lsquic_conn_get_peer_ctx(conn, NULL); 2920 cce->cce_flags |= CCE_REG; 2921 cub_add(&engine->new_scids, &cce->cce_cid, peer_ctx); 2922 return 0; 2923 } 2924 else 2925 { 2926 LSQ_WARNC("could not add new cid %"CID_FMT" to the SCID hash", 2927 CID_BITS(&cce->cce_cid)); 2928 return -1; 2929 } 2930} 2931 2932 2933void 2934lsquic_engine_retire_cid (struct lsquic_engine_public *enpub, 2935 struct lsquic_conn *conn, unsigned cce_idx, lsquic_time_t now) 2936{ 2937 struct lsquic_engine *const engine = (struct lsquic_engine *) enpub; 2938 struct conn_cid_elem *const cce = &conn->cn_cces[cce_idx]; 2939 void *peer_ctx; 2940 2941 assert(cce_idx < conn->cn_n_cces); 2942 2943 if (cce->cce_hash_el.qhe_flags & QHE_HASHED) 2944 lsquic_hash_erase(engine->conns_hash, &cce->cce_hash_el); 2945 2946 if (engine->purga) 2947 { 2948 peer_ctx = lsquic_conn_get_peer_ctx(conn, NULL); 2949 lsquic_purga_add(engine->purga, &cce->cce_cid, peer_ctx, 2950 PUTY_CID_RETIRED, now); 2951 } 2952 conn->cn_cces_mask &= ~(1u << cce_idx); 2953 LSQ_DEBUGC("retire CID %"CID_FMT, CID_BITS(&cce->cce_cid)); 2954} 2955 2956 2957