lsquic_mini_conn.c revision 0adf085a
1/* Copyright (c) 2017 - 2019 LiteSpeed Technologies Inc. See LICENSE. */ 2/* 3 * lsquic_mini_conn.c -- Mini connection. 4 * 5 * Mini connection is only used in server mode -- this assumption is relied 6 * upon by the code in this file. 7 * 8 * The purpose of this connection is to process incoming handshakes using 9 * minimal amount of resources until we confirm that the client is sending 10 * valid data. Here, we only process Stream 1 data; other packets are 11 * spooled, if necessary. When mini connection is promoted to full 12 * connection, the state, including spooled incoming packets, is transferred 13 * to the full connection. 14 * 15 * Note that mini connections do not retransmit lost packets. This is to 16 * minimize the effect of magnification attacks. Clients like Chrome and 17 * Opera fall back to using TCP if QUIC handshake times out. 18 */ 19 20 21#include <assert.h> 22#include <errno.h> 23#include <inttypes.h> 24#include <stdlib.h> 25#include <string.h> 26#include <sys/queue.h> 27 28#include "lsquic.h" 29#include "lsquic_int_types.h" 30#include "lsquic_hash.h" 31#include "lsquic_conn.h" 32#include "lsquic_rtt.h" 33#include "lsquic_mini_conn.h" 34#include "lsquic_mm.h" 35#include "lsquic_malo.h" 36#include "lsquic_packet_common.h" 37#include "lsquic_packet_gquic.h" 38#include "lsquic_packet_in.h" 39#include "lsquic_packet_out.h" 40#include "lsquic_util.h" 41#include "lsquic_str.h" 42#include "lsquic_enc_sess.h" 43#include "lsquic_parse.h" 44#include "lsquic_engine_public.h" 45#include "lsquic_sfcw.h" 46#include "lsquic_varint.h" 47#include "lsquic_hq.h" 48#include "lsquic_varint.h" 49#include "lsquic_stream.h" 50#include "lsquic_rechist.h" 51#include "lsquic_ev_log.h" 52#include "lsquic_qtags.h" 53#include "lsquic_attq.h" 54#include "lsquic_alarmset.h" 55 56#define LSQUIC_LOGGER_MODULE LSQLM_MINI_CONN 57#define LSQUIC_LOG_CONN_ID lsquic_conn_log_cid(&mc->mc_conn) 58#include "lsquic_logger.h" 59 60 61static const struct conn_iface mini_conn_iface_standard; 62#if LSQUIC_ENABLE_HANDSHAKE_DISABLE 63static const struct conn_iface mini_conn_iface_disable_handshake; 64#endif 65 66#if LSQUIC_KEEP_MINICONN_HISTORY 67 68static void 69mchist_append (struct mini_conn *mc, enum miniconn_history_event mh_event) 70{ 71 enum miniconn_history_event prev_event; 72 mchist_idx_t idx; 73 int plus; 74 75 idx = (mc->mc_hist_idx - 1) & MCHIST_MASK; 76 plus = MCHE_PLUS == mc->mc_hist_buf[ idx ]; 77 idx = (idx - plus) & MCHIST_MASK; 78 prev_event = mc->mc_hist_buf[ idx ]; 79 80 if (!(prev_event == mh_event && plus)) 81 { 82 if (prev_event == mh_event) 83 mh_event = MCHE_PLUS; 84 mc->mc_hist_buf[ MCHIST_MASK & mc->mc_hist_idx++ ] = mh_event; 85 } 86} 87 88 89# define MCHIST_APPEND(mc, event) mchist_append(mc, event) 90#else 91# define MCHIST_APPEND(mc, event) 92#endif 93 94static void 95process_deferred_packets (struct mini_conn *mc); 96 97 98/* If this is not true, highest_bit_set() may be broken */ 99typedef char packno_set_is_unsigned_long[ 100 (sizeof(unsigned long long) == sizeof(mconn_packno_set_t)) - 1]; 101 102static unsigned 103highest_bit_set (unsigned long long sz) 104{ 105#if __GNUC__ 106 unsigned clz = __builtin_clzll(sz); 107 return 63 - clz; 108#else 109 unsigned long y; 110 unsigned n; 111 n = 64; 112 y = sz >> 32; if (y) { n -= 32; sz = y; } 113 y = sz >> 16; if (y) { n -= 16; sz = y; } 114 y = sz >> 8; if (y) { n -= 8; sz = y; } 115 y = sz >> 4; if (y) { n -= 4; sz = y; } 116 y = sz >> 2; if (y) { n -= 2; sz = y; } 117 y = sz >> 1; if (y) return 63 - n + 2; 118 return 63 - n + sz; 119#endif 120} 121 122 123static unsigned 124lowest_bit_set (unsigned v) 125{ 126#if __GNUC__ 127 return __builtin_ctz(v); 128#else 129 unsigned n; 130 n = 0; 131 if (0 == (v & ((1 << 16) - 1))) { n += 16; v >>= 16; } 132 if (0 == (v & ((1 << 8) - 1))) { n += 8; v >>= 8; } 133 if (0 == (v & ((1 << 4) - 1))) { n += 4; v >>= 4; } 134 if (0 == (v & ((1 << 2) - 1))) { n += 2; v >>= 2; } 135 if (0 == (v & ((1 << 1) - 1))) { n += 1; } 136 return n; 137#endif 138} 139 140 141static void 142mini_destroy_packet (struct mini_conn *mc, struct lsquic_packet_out *packet_out) 143{ 144 lsquic_packet_out_destroy(packet_out, mc->mc_enpub, 145 mc->mc_path.np_peer_ctx); 146} 147 148 149static int 150packet_in_is_ok (const struct lsquic_packet_in *packet_in) 151{ 152 if (packet_in->pi_data_sz > GQUIC_MAX_PACKET_SZ) 153 { 154 LSQ_LOG1(LSQ_LOG_DEBUG, "incoming packet too large: %hu bytes", 155 packet_in->pi_data_sz); 156 return 0; 157 } 158 if (packet_in->pi_data_sz < 200) /* TODO: 64 packets now */ 159 { /* mini connection is limited to 32 packets, yet it must send out REJ 160 * and SHLO, which are about 4 KB combined. 161 */ 162 LSQ_LOG1(LSQ_LOG_DEBUG, "incoming packet too small: %hu bytes", 163 packet_in->pi_data_sz); 164 return 0; 165 } 166 return 1; 167} 168 169 170lsquic_conn_t * 171mini_conn_new (struct lsquic_engine_public *enp, 172 const struct lsquic_packet_in *packet_in, 173 enum lsquic_version version) 174{ 175 struct mini_conn *mc; 176 const struct conn_iface *conn_iface; 177 178#if LSQUIC_ENABLE_HANDSHAKE_DISABLE 179 if (getenv("LSQUIC_DISABLE_HANDSHAKE")) 180 conn_iface = &mini_conn_iface_disable_handshake; 181 else 182#endif 183 { 184 if (!packet_in_is_ok(packet_in)) 185 return NULL; 186 conn_iface = &mini_conn_iface_standard; 187 } 188 189 mc = lsquic_malo_get(enp->enp_mm.malo.mini_conn); 190 if (!mc) 191 { 192 LSQ_LOG1(LSQ_LOG_WARN, "cannot allocate mini connection: %s", 193 strerror(errno)); 194 return NULL; 195 } 196 197 memset(mc, 0, sizeof(*mc)); 198 TAILQ_INIT(&mc->mc_deferred); 199 TAILQ_INIT(&mc->mc_packets_in); 200 TAILQ_INIT(&mc->mc_packets_out); 201 mc->mc_enpub = enp; 202 mc->mc_created = packet_in->pi_received; 203#if LSQUIC_ENABLE_HANDSHAKE_DISABLE 204 if (conn_iface == &mini_conn_iface_disable_handshake) 205 mc->mc_path.np_pack_size = 1370; 206 else 207#endif 208 mc->mc_path.np_pack_size = packet_in->pi_data_sz; 209 mc->mc_conn.cn_cces = mc->mc_cces; 210 mc->mc_conn.cn_cces_mask = 1; 211 mc->mc_conn.cn_n_cces = sizeof(mc->mc_cces) / sizeof(mc->mc_cces[0]); 212 mc->mc_conn.cn_version = version; 213 mc->mc_conn.cn_pf = select_pf_by_ver(version); 214 mc->mc_conn.cn_esf_c = select_esf_common_by_ver(version); 215 mc->mc_conn.cn_esf.g = select_esf_gquic_by_ver(version); 216 mc->mc_conn.cn_cid = packet_in->pi_conn_id; 217 mc->mc_conn.cn_flags = LSCONN_MINI | LSCONN_SERVER; 218 mc->mc_conn.cn_if = conn_iface; 219 LSQ_DEBUG("created mini connection object"); 220 MCHIST_APPEND(mc, MCHE_CREATED); 221 return &mc->mc_conn; 222} 223 224 225static int 226in_acked_range (const struct ack_info *acki, lsquic_packno_t n) /* This is a copy */ 227{ 228 int in_range = 0; 229 unsigned i; 230 for (i = 0; i < acki->n_ranges; ++i) 231 in_range += acki->ranges[i].high >= n 232 && acki->ranges[i].low <= n; 233 return in_range > 0; 234} 235 236 237static void 238take_rtt_sample (struct mini_conn *mc, const lsquic_packet_out_t *packet_out, 239 lsquic_time_t now, lsquic_time_t lack_delta) 240{ 241 assert(packet_out->po_sent); 242 lsquic_time_t measured_rtt = now - packet_out->po_sent; 243 if (lack_delta < measured_rtt) 244 { 245 lsquic_rtt_stats_update(&mc->mc_rtt_stats, measured_rtt, lack_delta); 246 LSQ_DEBUG("srtt: %"PRIu64" usec, var: %"PRIu64, 247 lsquic_rtt_stats_get_srtt(&mc->mc_rtt_stats), 248 lsquic_rtt_stats_get_rttvar(&mc->mc_rtt_stats)); 249 } 250} 251 252 253static unsigned 254process_ack_frame (struct mini_conn *mc, lsquic_packet_in_t *packet_in, 255 const unsigned char *p, size_t len) 256{ 257 int parsed_len; 258 int n_newly_acked; 259 unsigned n; 260 lsquic_packet_out_t *packet_out, *next; 261 struct ack_info *acki; 262 lsquic_packno_t packno; 263 lsquic_time_t warn_time; 264 char buf[200]; 265 266 acki = mc->mc_enpub->enp_mm.acki; 267 parsed_len = mc->mc_conn.cn_pf->pf_parse_ack_frame(p, len, acki, 0); 268 if (parsed_len < 0) 269 return 0; 270 if (empty_ack_frame(acki)) 271 { 272 LSQ_DEBUG("Ignore empty ACK frame"); 273 return parsed_len; 274 } 275 if (packet_in->pi_packno <= mc->mc_max_ack_packno) 276 { 277 LSQ_DEBUG("Ignore old ack (max %u)", mc->mc_max_ack_packno); 278 return parsed_len; 279 } 280 281 /* Verify ACK frame and update list of acked packet numbers: */ 282 for (n = 0; n < acki->n_ranges; ++n) 283 for (packno = acki->ranges[n].low; packno <= acki->ranges[n].high; 284 ++packno) 285 if (packno > MINICONN_MAX_PACKETS || 286 0 == (MCONN_PACKET_MASK(packno) & mc->mc_sent_packnos)) 287 { 288 warn_time = lsquic_time_now(); 289 if (0 == mc->mc_enpub->enp_last_warning[WT_ACKPARSE_MINI] 290 || mc->mc_enpub->enp_last_warning[WT_ACKPARSE_MINI] 291 + WARNING_INTERVAL < warn_time) 292 { 293 mc->mc_enpub->enp_last_warning[WT_ACKPARSE_MINI] 294 = warn_time; 295 lsquic_hexdump(p, len, buf, sizeof(buf)); 296 LSQ_WARN("packet %"PRIu64" was never sent; ACK " 297 "frame:\n%s", packno, buf); 298 } 299 else 300 LSQ_DEBUG("packet %"PRIu64" was never sent", packno); 301 MCHIST_APPEND(mc, MCHE_UNSENT_ACKED); 302 return 0; 303 } 304 else 305 mc->mc_acked_packnos |= MCONN_PACKET_MASK(packno); 306 307 EV_LOG_ACK_FRAME_IN(LSQUIC_LOG_CONN_ID, acki); 308 n_newly_acked = 0; 309 for (packet_out = TAILQ_FIRST(&mc->mc_packets_out); packet_out; 310 packet_out = next) 311 { 312 next = TAILQ_NEXT(packet_out, po_next); 313 if (in_acked_range(acki, packet_out->po_packno)) 314 { 315 ++n_newly_acked; 316 LSQ_DEBUG("Got ACK for packet %"PRIu64, packet_out->po_packno); 317 if (packet_out->po_packno == largest_acked(acki)) 318 take_rtt_sample(mc, packet_out, packet_in->pi_received, 319 acki->lack_delta); 320 TAILQ_REMOVE(&mc->mc_packets_out, packet_out, po_next); 321 mini_destroy_packet(mc, packet_out); 322 } 323 } 324 325 if (n_newly_acked > 0) 326 mc->mc_hsk_count = 0; 327 328 return parsed_len; 329} 330 331 332static unsigned 333process_blocked_frame (struct mini_conn *mc, lsquic_packet_in_t *packet_in, 334 const unsigned char *p, size_t len) 335{ 336 lsquic_stream_id_t stream_id; 337 int parsed_len; 338 parsed_len = mc->mc_conn.cn_pf->pf_parse_blocked_frame(p, len, &stream_id); 339 if (parsed_len < 0) 340 return 0; 341 EV_LOG_BLOCKED_FRAME_IN(LSQUIC_LOG_CONN_ID, stream_id); 342 LSQ_DEBUG("Peer reports stream %"PRIu64" as blocked", stream_id); 343 return parsed_len; 344} 345 346 347static mconn_packno_set_t 348drop_packets_out (struct mini_conn *mc) 349{ 350 struct lsquic_packet_out *packet_out; 351 mconn_packno_set_t in_flight = 0; 352 353 while ((packet_out = TAILQ_FIRST(&mc->mc_packets_out))) 354 { 355 TAILQ_REMOVE(&mc->mc_packets_out, packet_out, po_next); 356 if (packet_out->po_flags & PO_SENT) 357 in_flight |= MCONN_PACKET_MASK(packet_out->po_packno); 358 mini_destroy_packet(mc, packet_out); 359 } 360 361 return in_flight; 362} 363 364 365static unsigned 366process_connection_close_frame (struct mini_conn *mc, 367 lsquic_packet_in_t *packet_in, const unsigned char *p, size_t len) 368{ 369 uint64_t error_code; 370 uint16_t reason_len; 371 uint8_t reason_off; 372 int parsed_len; 373 374 (void) drop_packets_out(mc); 375 parsed_len = mc->mc_conn.cn_pf->pf_parse_connect_close_frame(p, len, 376 NULL, &error_code, &reason_len, &reason_off); 377 if (parsed_len < 0) 378 return 0; 379 mc->mc_error_code = (uint64_t) error_code; 380 EV_LOG_CONNECTION_CLOSE_FRAME_IN(LSQUIC_LOG_CONN_ID, error_code, 381 (int) reason_len, (const char *) p + reason_off); 382 if (error_code != 25 /* No recent network activity */ 383 && error_code != 62 /* An active session exists for the given IP */ 384 && error_code != 27 ) /* Write failed with error: -142 (Unknown error)*/ 385 { 386 LSQ_WARN("Received CONNECTION_CLOSE frame (code: %"PRIu64"; reason: %.*s)", 387 error_code, (int) reason_len, (const char *) p + reason_off); 388 } 389 MCHIST_APPEND(mc, MCHE_CONN_CLOSE); 390 return 0; /* This shuts down the connection */ 391} 392 393 394static unsigned 395process_goaway_frame (struct mini_conn *mc, lsquic_packet_in_t *packet_in, 396 const unsigned char *p, size_t len) 397{ 398 lsquic_stream_id_t stream_id; 399 uint32_t error_code; 400 uint16_t reason_length; 401 const char *reason; 402 int parsed_len; 403 parsed_len = mc->mc_conn.cn_pf->pf_parse_goaway_frame(p, len, &error_code, &stream_id, 404 &reason_length, &reason); 405 if (parsed_len < 0) 406 return 0; 407 EV_LOG_GOAWAY_FRAME_IN(LSQUIC_LOG_CONN_ID, error_code, stream_id, 408 reason_length, reason); 409 LSQ_DEBUG("received GOAWAY frame, last good stream ID: %"PRIu64", " 410 "error code: 0x%X, reason: `%.*s'", stream_id, error_code, 411 reason_length, reason); 412 if (stream_id != 0) /* This is odd. We warn: */ 413 LSQ_WARN("stream ID is %"PRIu64" in GOAWAY frame", stream_id); 414 mc->mc_conn.cn_flags |= LSCONN_PEER_GOING_AWAY; 415 return parsed_len; 416} 417 418 419static unsigned 420process_invalid_frame (struct mini_conn *mc, lsquic_packet_in_t *packet_in, 421 const unsigned char *p, size_t len) 422{ 423 LSQ_INFO("invalid frame"); 424 MCHIST_APPEND(mc, MCHE_INVALID_FRAME); 425 return 0; 426} 427 428 429static unsigned 430count_zero_bytes (const unsigned char *p, size_t len) 431{ 432 const unsigned char *const end = p + len; 433 while (p < end && 0 == *p) 434 ++p; 435 return len - (end - p); 436} 437 438 439static unsigned 440process_padding_frame (struct mini_conn *mc, lsquic_packet_in_t *packet_in, 441 const unsigned char *p, size_t len) 442{ 443 len = (size_t) count_zero_bytes(p, len); 444 EV_LOG_PADDING_FRAME_IN(LSQUIC_LOG_CONN_ID, len); 445 return len; 446} 447 448 449static unsigned 450process_ping_frame (struct mini_conn *mc, lsquic_packet_in_t *packet_in, 451 const unsigned char *p, size_t len) 452{ 453 EV_LOG_PING_FRAME_IN(LSQUIC_LOG_CONN_ID); 454 return 1; 455} 456 457 458static unsigned 459process_rst_stream_frame (struct mini_conn *mc, lsquic_packet_in_t *packet_in, 460 const unsigned char *p, size_t len) 461{ 462 lsquic_stream_id_t stream_id; 463 uint64_t offset, error_code; 464 int parsed_len; 465 parsed_len = mc->mc_conn.cn_pf->pf_parse_rst_frame(p, len, &stream_id, &offset, &error_code); 466 if (parsed_len < 0) 467 return 0; 468 EV_LOG_RST_STREAM_FRAME_IN(LSQUIC_LOG_CONN_ID, stream_id, offset, 469 error_code); 470 LSQ_DEBUG("Got RST_STREAM; stream: %"PRIu64"; offset: 0x%"PRIX64, stream_id, 471 offset); 472 if (LSQUIC_GQUIC_STREAM_HANDSHAKE == stream_id) 473 { 474 LSQ_INFO("handshake stream reset, closing connection"); 475 return 0; 476 } 477 else 478 return parsed_len; 479} 480 481 482static unsigned 483process_stop_waiting_frame (struct mini_conn *mc, lsquic_packet_in_t *packet_in, 484 const unsigned char *p, size_t len) 485{ 486 lsquic_packno_t least; 487 enum packno_bits bits = lsquic_packet_in_packno_bits(packet_in); 488 int parsed_len; 489 parsed_len = mc->mc_conn.cn_pf->pf_parse_stop_waiting_frame(p, len, packet_in->pi_packno, bits, 490 &least); 491 if (parsed_len < 0) 492 return 0; 493 EV_LOG_STOP_WAITING_FRAME_IN(LSQUIC_LOG_CONN_ID, least); 494 LSQ_DEBUG("Got STOP_WAITING frame, least unacked: %"PRIu64, least); 495 if (least > MINICONN_MAX_PACKETS) 496 return 0; 497 else 498 { 499 mc->mc_cutoff = least; 500 return parsed_len; 501 } 502} 503 504 505static unsigned 506process_stream_frame (struct mini_conn *mc, lsquic_packet_in_t *packet_in, 507 const unsigned char *p, size_t len) 508{ 509 stream_frame_t stream_frame; 510 int parsed_len; 511 parsed_len = mc->mc_conn.cn_pf->pf_parse_stream_frame(p, len, &stream_frame); 512 if (parsed_len < 0) 513 return 0; 514 EV_LOG_STREAM_FRAME_IN(LSQUIC_LOG_CONN_ID, &stream_frame); 515 LSQ_DEBUG("Got stream frame for stream #%"PRIu64, stream_frame.stream_id); 516 if (LSQUIC_GQUIC_STREAM_HANDSHAKE == stream_frame.stream_id) 517 { 518 if (packet_in->pi_flags & PI_HSK_STREAM) 519 { /* This is not supported for simplicity. The spec recommends 520 * not putting more than one stream frame from the same stream 521 * into a single packet. If this changes and clients actually 522 * do that, we can revisit this code. 523 */ 524 LSQ_INFO("two handshake stream frames in single incoming packet"); 525 MCHIST_APPEND(mc, MCHE_2HSK_1STREAM); 526 return 0; 527 } 528 if (stream_frame.data_frame.df_offset >= mc->mc_read_off) 529 { 530 packet_in->pi_flags |= PI_HSK_STREAM; 531 packet_in->pi_hsk_stream = p - packet_in->pi_data; 532 mc->mc_flags |= MC_HAVE_NEW_HSK; 533 MCHIST_APPEND(mc, MCHE_NEW_HSK); 534 if (0 == stream_frame.data_frame.df_offset) 535 /* First CHLO message: update maximum packet size */ 536 mc->mc_path.np_pack_size = packet_in->pi_data_sz; 537 } 538 else 539 { 540 LSQ_DEBUG("drop duplicate frame"); 541 MCHIST_APPEND(mc, MCHE_DUP_HSK); 542 } 543 } 544 return parsed_len; 545} 546 547 548static unsigned 549process_window_update_frame (struct mini_conn *mc, 550 lsquic_packet_in_t *packet_in, const unsigned char *p, size_t len) 551{ 552 lsquic_stream_id_t stream_id; 553 uint64_t offset; 554 int parsed_len; 555 parsed_len = mc->mc_conn.cn_pf->pf_parse_window_update_frame(p, len, &stream_id, &offset); 556 if (parsed_len < 0) 557 return 0; 558 EV_LOG_WINDOW_UPDATE_FRAME_IN(LSQUIC_LOG_CONN_ID, stream_id, offset); 559 if (LSQUIC_GQUIC_STREAM_HANDSHAKE == stream_id) 560 /* This should not happen: why would the client send us WINDOW_UPDATE 561 * on stream 1? 562 */ 563 LSQ_WARN("client sent WINDOW_UPDATE for handshake stream, " 564 "offset %"PRIu64, offset); 565 return parsed_len; 566} 567 568 569typedef unsigned (*process_frame_f)( 570 struct mini_conn *, lsquic_packet_in_t *, const unsigned char *p, size_t); 571 572 573static process_frame_f const process_frames[N_QUIC_FRAMES] = 574{ 575 [QUIC_FRAME_ACK] = process_ack_frame, 576 [QUIC_FRAME_BLOCKED] = process_blocked_frame, 577 [QUIC_FRAME_CONNECTION_CLOSE] = process_connection_close_frame, 578 [QUIC_FRAME_GOAWAY] = process_goaway_frame, 579 [QUIC_FRAME_INVALID] = process_invalid_frame, 580 [QUIC_FRAME_PADDING] = process_padding_frame, 581 [QUIC_FRAME_PING] = process_ping_frame, 582 [QUIC_FRAME_RST_STREAM] = process_rst_stream_frame, 583 [QUIC_FRAME_STOP_WAITING] = process_stop_waiting_frame, 584 [QUIC_FRAME_STREAM] = process_stream_frame, 585 [QUIC_FRAME_WINDOW_UPDATE] = process_window_update_frame, 586}; 587 588 589static unsigned 590process_packet_frame (struct mini_conn *mc, lsquic_packet_in_t *packet_in, 591 const unsigned char *p, size_t len) 592{ 593 enum quic_frame_type type = mc->mc_conn.cn_pf->pf_parse_frame_type(p[0]); 594 packet_in->pi_frame_types |= 1 << type; 595 return process_frames[type](mc, packet_in, p, len); 596} 597 598 599static void 600record_largest_recv (struct mini_conn *mc, lsquic_time_t t) 601{ 602 if (t < mc->mc_created) 603 { 604 LSQ_WARN("largest received predates creation"); 605 return; 606 } 607 t -= mc->mc_created; 608 mc->mc_largest_recv[0] = t; 609 mc->mc_largest_recv[1] = t >> 8; 610 mc->mc_largest_recv[2] = t >> 16; 611 LSQ_DEBUG("recorded largest received timestamp as %"PRIu64" usec since " 612 "creation", t); 613} 614 615 616static enum dec_packin 617conn_decrypt_packet (struct mini_conn *conn, lsquic_packet_in_t *packet_in) 618{ 619#if LSQUIC_ENABLE_HANDSHAKE_DISABLE 620 if (getenv("LSQUIC_DISABLE_HANDSHAKE")) 621 { 622 (void) lsquic_conn_copy_and_release_pi_data(&conn->mc_conn, 623 conn->mc_enpub, packet_in); 624 packet_in->pi_flags |= PI_DECRYPTED; 625 return 0; 626 } 627 else 628#endif 629 return conn->mc_conn.cn_esf_c->esf_decrypt_packet( 630 conn->mc_conn.cn_enc_session, conn->mc_enpub, 631 &conn->mc_conn, packet_in); 632} 633 634 635static enum { PRP_KEEP, PRP_DEFER, PRP_DROP, PRP_ERROR } 636process_regular_packet (struct mini_conn *mc, lsquic_packet_in_t *packet_in) 637{ 638 const unsigned char *p, *pend; 639 unsigned len; 640 641 /* Decrypt packet if necessary */ 642 if (0 == (packet_in->pi_flags & PI_DECRYPTED)) 643 { 644 if (DECPI_OK == conn_decrypt_packet(mc, packet_in)) 645 MCHIST_APPEND(mc, MCHE_DECRYPTED); 646 else if (mc->mc_conn.cn_esf.g->esf_have_key_gt_one( 647 mc->mc_conn.cn_enc_session)) 648 { 649 LSQ_INFO("could not decrypt packet: drop"); 650 mc->mc_dropped_packnos |= MCONN_PACKET_MASK(packet_in->pi_packno); 651 MCHIST_APPEND(mc, MCHE_UNDECR_DROP); 652 return PRP_DROP; 653 } 654 else if ((packet_in->pi_flags & PI_OWN_DATA) || 655 0 == lsquic_conn_copy_and_release_pi_data(&mc->mc_conn, 656 mc->mc_enpub, packet_in)) 657 { 658 assert(packet_in->pi_flags & PI_OWN_DATA); 659 LSQ_INFO("could not decrypt packet: defer"); 660 mc->mc_deferred_packnos |= MCONN_PACKET_MASK(packet_in->pi_packno); 661 MCHIST_APPEND(mc, MCHE_UNDECR_DEFER); 662 return PRP_DEFER; 663 } 664 else 665 { 666 MCHIST_APPEND(mc, MCHE_ENOMEM); 667 return PRP_ERROR; /* Memory allocation must have failed */ 668 } 669 } 670 671 /* Update receive history before processing the packet: if there is an 672 * error, the connection is terminated and recording this packet number 673 * is helpful when it is printed along with other diagnostics in dtor. 674 */ 675 if (0 == mc->mc_received_packnos || 676 packet_in->pi_packno > highest_bit_set(mc->mc_received_packnos) + 1) 677 record_largest_recv(mc, packet_in->pi_received); 678 mc->mc_received_packnos |= MCONN_PACKET_MASK(packet_in->pi_packno); 679 680 /* Parse and process frames */ 681 p = packet_in->pi_data + packet_in->pi_header_sz; 682 pend = packet_in->pi_data + packet_in->pi_data_sz; 683 while (p < pend) 684 { 685 len = process_packet_frame(mc, packet_in, p, pend - p); 686 if (len > 0) 687 p += len; 688 else 689 { 690 if (mc->mc_conn.cn_pf->pf_parse_frame_type(p[0]) != 691 QUIC_FRAME_CONNECTION_CLOSE) 692 LSQ_WARN("error parsing frame: packno %"PRIu64"; sz: %u; type: " 693 "0x%X", packet_in->pi_packno, packet_in->pi_data_sz, p[0]); 694 MCHIST_APPEND(mc, MCHE_EFRAME); 695 return PRP_ERROR; 696 } 697 } 698 699 mc->mc_flags |= MC_GEN_ACK; 700 701 return PRP_KEEP; 702} 703 704 705struct hsk_chunk 706{ 707 lsquic_packet_in_t *hsk_packet_in; 708 const unsigned char *hsk_data; 709 unsigned hsk_off; 710 unsigned hsk_sz; 711}; 712 713 714static int 715compare_hsk_chunks (const void *ap, const void *bp) 716{ 717 const struct hsk_chunk *a = ap; 718 const struct hsk_chunk *b = bp; 719 return (a->hsk_off > b->hsk_off) - (b->hsk_off > a->hsk_off); 720} 721 722 723struct mini_stream_ctx 724{ 725 const unsigned char *buf; 726 size_t bufsz; 727 size_t off; 728}; 729 730 731static int 732mini_stream_has_data (const struct mini_stream_ctx *ms_ctx) 733{ 734 return ms_ctx->off < ms_ctx->bufsz; 735} 736 737 738static size_t 739mini_stream_read (void *stream, void *buf, size_t len, int *reached_fin) 740{ 741 struct mini_stream_ctx *ms_ctx = stream; 742 size_t avail = ms_ctx->bufsz - ms_ctx->off; 743 if (avail < len) 744 len = avail; 745 memcpy(buf, ms_ctx->buf + ms_ctx->off, len); 746 ms_ctx->off += len; 747 *reached_fin = 0; 748 return len; 749} 750 751 752static size_t 753mini_stream_size (void *stream) 754{ 755 struct mini_stream_ctx *ms_ctx = stream; 756 size_t avail = ms_ctx->bufsz - ms_ctx->off; 757 return avail; 758} 759 760 761static int 762mini_stream_fin (void *stream) 763{ /* There is never a FIN on the handshake stream */ 764 return 0; 765} 766 767 768static lsquic_packno_t 769next_packno (struct mini_conn *mc) 770{ 771 if (mc->mc_cur_packno < MINICONN_MAX_PACKETS) 772 { 773 return ++mc->mc_cur_packno; 774 } 775 else 776 { 777 if (!(mc->mc_flags & MC_OO_PACKNOS)) 778 { 779 MCHIST_APPEND(mc, MCHE_OUT_OF_PACKNOS); 780 mc->mc_flags |= MC_OO_PACKNOS; 781 LSQ_DEBUG("ran out of outgoing packet numbers"); 782 } 783 return MINICONN_MAX_PACKETS + 1; 784 } 785} 786 787 788static lsquic_packet_out_t * 789allocate_packet_out (struct mini_conn *mc, const unsigned char *nonce) 790{ 791 lsquic_packet_out_t *packet_out; 792 lsquic_packno_t packno; 793 packno = next_packno(mc); 794 if (packno > MINICONN_MAX_PACKETS) 795 { 796 LSQ_DEBUG("ran out of outgoing packet numbers, won't allocate packet"); 797 return NULL; 798 } 799 packet_out = lsquic_packet_out_new(&mc->mc_enpub->enp_mm, NULL, 1, 800 &mc->mc_conn, GQUIC_PACKNO_LEN_1, NULL, nonce, &mc->mc_path); 801 if (!packet_out) 802 { 803 LSQ_WARN("could not allocate packet: %s", strerror(errno)); 804 return NULL; 805 } 806 packet_out->po_loss_chain = packet_out; 807 packet_out->po_packno = packno; 808 packet_out->po_flags |= PO_MINI; 809 if (mc->mc_flags & MC_HAVE_SHLO) 810 { 811 packet_out->po_flags |= PO_HELLO; 812 packet_out->po_header_type = HETY_0RTT; 813 } 814 lsquic_packet_out_set_pns(packet_out, PNS_APP); 815 TAILQ_INSERT_TAIL(&mc->mc_packets_out, packet_out, po_next); 816 LSQ_DEBUG("allocated packet #%"PRIu64", nonce: %d", packno, !!nonce); 817 MCHIST_APPEND(mc, MCHE_NEW_PACKET_OUT); 818 EV_LOG_PACKET_CREATED(LSQUIC_LOG_CONN_ID, packet_out); 819 return packet_out; 820} 821 822 823static int 824packetize_response (struct mini_conn *mc, const unsigned char *buf, 825 size_t bufsz, const unsigned char *nonce) 826{ 827 struct mini_stream_ctx ms_ctx; 828 lsquic_packet_out_t *packet_out; 829 size_t cur_off; 830 int len; 831 832 LSQ_DEBUG("Packetizing %zd bytes of handshake response", bufsz); 833 834 ms_ctx.buf = buf; 835 ms_ctx.bufsz = bufsz; 836 ms_ctx.off = 0; 837 838 do 839 { 840 packet_out = allocate_packet_out(mc, nonce); 841 if (!packet_out) 842 return -1; 843 cur_off = ms_ctx.off; 844 len = mc->mc_conn.cn_pf->pf_gen_stream_frame(packet_out->po_data + packet_out->po_data_sz, 845 lsquic_packet_out_avail(packet_out), 846 LSQUIC_GQUIC_STREAM_HANDSHAKE, mc->mc_write_off, mini_stream_fin(&ms_ctx), 847 mini_stream_size(&ms_ctx), mini_stream_read, &ms_ctx); 848 if (len < 0) 849 { 850 LSQ_WARN("cannot generate stream frame (avail: %u)", 851 lsquic_packet_out_avail(packet_out)); 852 return -1; 853 } 854 mc->mc_write_off += ms_ctx.off - cur_off; 855 EV_LOG_GENERATED_STREAM_FRAME(LSQUIC_LOG_CONN_ID, mc->mc_conn.cn_pf, 856 packet_out->po_data + packet_out->po_data_sz, len); 857 packet_out->po_data_sz += len; 858 packet_out->po_frame_types |= 1 << QUIC_FRAME_STREAM; 859 if (0 == lsquic_packet_out_avail(packet_out)) 860 packet_out->po_flags |= PO_STREAM_END; 861 } 862 while (mini_stream_has_data(&ms_ctx)); 863 864 /* PAD the last packet with NULs. ACK and STOP_WAITING go into a separate 865 * packet. 866 */ 867 if (lsquic_packet_out_avail(packet_out)) 868 { 869 EV_LOG_CONN_EVENT(LSQUIC_LOG_CONN_ID, "generated PADDING frame %u " 870 "bytes long", lsquic_packet_out_avail(packet_out)); 871 memset(packet_out->po_data + packet_out->po_data_sz, 0, 872 lsquic_packet_out_avail(packet_out)); 873 packet_out->po_data_sz += lsquic_packet_out_avail(packet_out); 874 packet_out->po_frame_types |= 1 << QUIC_FRAME_PADDING; 875 } 876 877 return 0; 878} 879 880 881static int 882continue_handshake (struct mini_conn *mc) 883{ 884 lsquic_packet_in_t *packet_in; 885 unsigned n_hsk_chunks = 0, n_contig, n, bufsz, off; 886 int s, rv; 887 size_t out_len; 888 enum handshake_error he; 889 unsigned char *buf_in_16k, *buf_out; 890 const unsigned char *buf_in; 891 time_t t; 892 stream_frame_t frame; 893 struct hsk_chunk hsk_chunks[MINICONN_MAX_PACKETS], *hsk_chunk; 894 unsigned char nonce_buf[32]; 895 int nonce_set = 0; 896 897 /* Get handshake stream data from each packet that contains a handshake 898 * stream frame and place them into `hsk_chunks' array. 899 */ 900 TAILQ_FOREACH(packet_in, &mc->mc_packets_in, pi_next) 901 { 902 assert(n_hsk_chunks < sizeof(hsk_chunks) / sizeof(hsk_chunks[0])); 903 if (0 == (packet_in->pi_flags & PI_HSK_STREAM)) 904 continue; 905 s = mc->mc_conn.cn_pf->pf_parse_stream_frame(packet_in->pi_data + packet_in->pi_hsk_stream, 906 packet_in->pi_data_sz - packet_in->pi_hsk_stream, &frame); 907 if (-1 == s) 908 { 909 LSQ_WARN("cannot process hsk stream frame in packet %"PRIu64, 910 packet_in->pi_packno); 911 return -1; 912 } 913 hsk_chunk = &hsk_chunks[ n_hsk_chunks++ ]; 914 hsk_chunk->hsk_packet_in = packet_in; 915 hsk_chunk->hsk_data = frame.data_frame.df_data; 916 hsk_chunk->hsk_off = frame.data_frame.df_offset; 917 hsk_chunk->hsk_sz = frame.data_frame.df_size; 918 } 919 assert(n_hsk_chunks > 0); 920 921 if (n_hsk_chunks > 1) 922 { 923 /* Sort handshake stream data */ 924 qsort(hsk_chunks, n_hsk_chunks, sizeof(hsk_chunks[0]), 925 compare_hsk_chunks); 926 /* Figure out how many packets contain handshake stream data in a 927 * contiguous buffer and how large this data is. 928 */ 929 for (n = 1, n_contig = 1, bufsz = hsk_chunks[0].hsk_sz; 930 n < n_hsk_chunks; ++n) 931 if (hsk_chunks[n - 1].hsk_off + hsk_chunks[n - 1].hsk_sz == 932 hsk_chunks[n].hsk_off) 933 { 934 ++n_contig; 935 bufsz += hsk_chunks[n].hsk_sz; 936 } 937 else 938 break; 939 } 940 else 941 { 942 n_contig = 1; 943 bufsz = hsk_chunks[0].hsk_sz; 944 } 945 946 /* Handshake handler expects to start reading at a particular offset. 947 */ 948 if (hsk_chunks[0].hsk_off != mc->mc_read_off) 949 { 950 LSQ_DEBUG("smallest hsk offset is %u, need %hu", 951 hsk_chunks[0].hsk_off, mc->mc_read_off); 952 MCHIST_APPEND(mc, MCHE_HELLO_HOLE); 953 return 0; 954 } 955 956 LSQ_DEBUG("# of contiguous stream frames: %u out of %u; offset: %u; " 957 "total size: %u", n_contig, n_hsk_chunks, hsk_chunks[0].hsk_off, bufsz); 958 959 if (bufsz > 16 * 1024) 960 { 961 LSQ_INFO("too much contiguous handshake data (%u bytes); max: %u", 962 bufsz, 16 * 1024); 963 MCHIST_APPEND(mc, MCHE_HELLO_TOO_MUCH); 964 return -1; 965 } 966 967 /* From here on, since we need to clean up, we use `rv' and `goto end' 968 * to handle error conditions and cleanup. 969 */ 970 rv = -1; 971 if (n_contig > 1) 972 { 973 buf_in = buf_in_16k = lsquic_mm_get_16k(&mc->mc_enpub->enp_mm); 974 if (!buf_in) 975 { 976 LSQ_WARN("could not allocate in buffer: %s", strerror(errno)); 977 buf_out = NULL; 978 goto end; 979 } 980 /* Create a single contiguous buffer to pass to lsquic_enc_session_handle_chlo */ 981 off = 0; 982 for (n = 0; n < n_contig; ++n) 983 { 984 memcpy(buf_in_16k + off, hsk_chunks[n].hsk_data, 985 hsk_chunks[n].hsk_sz); 986 off += hsk_chunks[n].hsk_sz; 987 } 988 assert(off == bufsz); 989 } 990 else 991 { 992 buf_in_16k = NULL; 993 buf_in = hsk_chunks[0].hsk_data; 994 } 995 996 buf_out = lsquic_mm_get_16k(&mc->mc_enpub->enp_mm); 997 if (!buf_out) 998 { 999 LSQ_WARN("could not allocate out buffer: %s", strerror(errno)); 1000 goto end; 1001 } 1002 out_len = 16 * 1024; 1003 1004 /* Allocate enc_session for the server if first time around: */ 1005 if (!mc->mc_conn.cn_enc_session) 1006 { 1007 mc->mc_conn.cn_enc_session = 1008 mc->mc_conn.cn_esf.g->esf_create_server(mc->mc_conn.cn_cid, 1009 mc->mc_enpub); 1010 if (!mc->mc_conn.cn_enc_session) 1011 { 1012 LSQ_WARN("cannot create new enc session"); 1013 goto end; 1014 } 1015 MCHIST_APPEND(mc, MCHE_NEW_ENC_SESS); 1016 } 1017 1018 t = time(NULL); 1019 he = mc->mc_conn.cn_esf.g->esf_handle_chlo(mc->mc_conn.cn_enc_session, 1020 mc->mc_conn.cn_version, 1021 buf_in, bufsz, t, NP_PEER_SA(&mc->mc_path), 1022 NP_LOCAL_SA(&mc->mc_path), 1023 buf_out, &out_len, nonce_buf, &nonce_set); 1024 1025 if (HS_SHLO == he) 1026 mc->mc_flags |= MC_HAVE_SHLO; 1027 else 1028 mc->mc_flags &= ~MC_HAVE_SHLO; 1029 1030 MCHIST_APPEND(mc, he == DATA_NOT_ENOUGH ? MCHE_HANDLE_NOT_ENOUGH : 1031 he == HS_SHLO ? MCHE_HANDLE_SHLO : 1032 he == HS_1RTT ? MCHE_HANDLE_1RTT : 1033 he == HS_2RTT ? MCHE_HANDLE_2RTT : 1034 he == HS_ERROR ? MCHE_HANDLE_ERROR : 1035 MCHE_HAHDLE_UNKNOWN); 1036 1037 if ((HS_SHLO == he || HS_1RTT == he) && !mc->mc_rtt_stats.srtt) 1038 { 1039 uint32_t irtt; 1040 if (0 == mc->mc_conn.cn_esf.g->esf_get_peer_setting( 1041 mc->mc_conn.cn_enc_session, QTAG_IRTT, &irtt)) 1042 { 1043 /* Do not allow the client to specify unreasonable values: 1044 * smaller than 10ms or larger than 15s. Per reference 1045 * implementation. 1046 */ 1047 if (irtt > 15 * 1000 * 1000) 1048 irtt = 15 * 1000 * 1000; 1049 else if (irtt < 10 * 1000) 1050 irtt = 10 * 1000; 1051 lsquic_rtt_stats_update(&mc->mc_rtt_stats, irtt, 0); 1052 LSQ_DEBUG("Set initial SRTT to %"PRIu32" usec based on client-" 1053 "supplied IRTT value", irtt); 1054 } 1055 } 1056 1057 switch (he) 1058 { 1059 case DATA_NOT_ENOUGH: 1060 LSQ_DEBUG("lsquic_enc_session_handle_chlo needs more data"); 1061 break; 1062 case HS_SHLO: 1063 mc->mc_conn.cn_flags |= LSCONN_HANDSHAKE_DONE; 1064 mc->mc_flags |= MC_PROMOTE; 1065 LSQ_DEBUG("lsquic_enc_session_handle_chlo returned %d, promote", he); 1066 /* Fall through */ 1067 case HS_1RTT: 1068 assert(out_len > 0); 1069 if (mc->mc_conn.cn_version < LSQVER_046 1070 && !mc->mc_conn.cn_esf.g->esf_get_peer_option( 1071 mc->mc_conn.cn_enc_session, QTAG_NSTP)) 1072 mc->mc_flags |= MC_STOP_WAIT_ON; 1073 if (0 != packetize_response(mc, buf_out, out_len, 1074 nonce_set ? nonce_buf : NULL)) 1075 goto end; 1076 mc->mc_read_off += bufsz; 1077 for (n = 0; n < n_contig; ++n) 1078 hsk_chunks[n].hsk_packet_in->pi_flags &= ~PI_HSK_STREAM; 1079 LSQ_DEBUG("read offset is now %hu", mc->mc_read_off); 1080 break; 1081 default: 1082 LSQ_WARN("unexpected return value from lsquic_enc_session_handle_chlo: %u", he); 1083 /* fallthru */ 1084 case HS_ERROR: 1085#if !LSQUIC_KEEP_ENC_SESS_HISTORY 1086 mc->mc_conn.cn_esf.g->esf_destroy(mc->mc_conn.cn_enc_session); 1087 mc->mc_conn.cn_enc_session = NULL; 1088#endif 1089 mc->mc_flags |= MC_HSK_ERR; 1090 LSQ_INFO("lsquic_enc_session_handle_chlo returned an error (%d)", he); 1091 goto end; 1092 } 1093 1094 rv = 0; 1095 1096 end: 1097 mc->mc_flags &= ~MC_HAVE_SHLO; 1098 if (buf_in_16k) 1099 lsquic_mm_put_16k(&mc->mc_enpub->enp_mm, buf_in_16k); 1100 if (buf_out) 1101 lsquic_mm_put_16k(&mc->mc_enpub->enp_mm, buf_out); 1102 return rv; 1103} 1104 1105 1106struct mini_rechist 1107{ 1108 const struct mini_conn *mc; 1109 mconn_packno_set_t cur_set; 1110 int cur_idx; 1111 struct lsquic_packno_range range; /* We return a pointer to this */ 1112}; 1113 1114 1115static void 1116mini_rechist_init (struct mini_rechist *rechist, const struct mini_conn *mc) 1117{ 1118 rechist->mc = mc; 1119 rechist->cur_set = 0; 1120 rechist->cur_idx = 0; 1121} 1122 1123 1124static lsquic_time_t 1125mini_rechist_largest_recv (void *rechist_ctx) 1126{ 1127 struct mini_rechist *rechist = rechist_ctx; 1128 const struct mini_conn *mc = rechist->mc; 1129 lsquic_time_t delta = mc->mc_largest_recv[0] 1130 + (mc->mc_largest_recv[1] << 8) 1131 + (mc->mc_largest_recv[2] << 16); 1132 LSQ_DEBUG("%s: largest received: %"PRIu64" usec since creation", 1133 __func__, delta); 1134 return mc->mc_created + delta; 1135} 1136 1137 1138static const struct lsquic_packno_range * 1139mini_rechist_next (void *rechist_ctx) 1140{ 1141 struct mini_rechist *rechist = rechist_ctx; 1142 const struct mini_conn *mc = rechist->mc; 1143 mconn_packno_set_t packnos; 1144 int i; 1145 1146 packnos = rechist->cur_set; 1147 if (0 == packnos) 1148 return NULL; 1149 1150 /* There may be a faster way to do this, but for now, we just want 1151 * correctness. 1152 */ 1153 for (i = rechist->cur_idx; i >= 0; --i) 1154 if (packnos & (1ULL << i)) 1155 { 1156 rechist->range.low = i + 1; 1157 rechist->range.high = i + 1; 1158 break; 1159 } 1160 assert(i >= 0); /* We must have hit at least one bit */ 1161 --i; 1162 for ( ; i >= 0 && (packnos & (1ULL << i)); --i) 1163 rechist->range.low = i + 1; 1164 if (i >= 0) 1165 { 1166 rechist->cur_set = packnos & ((1ULL << i) - 1); 1167 rechist->cur_idx = i; 1168 } 1169 else 1170 rechist->cur_set = 0; 1171 LSQ_DEBUG("%s: return [%"PRIu64", %"PRIu64"]", __func__, 1172 rechist->range.low, rechist->range.high); 1173 return &rechist->range; 1174} 1175 1176 1177static const struct lsquic_packno_range * 1178mini_rechist_first (void *rechist_ctx) 1179{ 1180 struct mini_rechist *rechist = rechist_ctx; 1181 rechist->cur_set = rechist->mc->mc_received_packnos; 1182 rechist->cur_idx = highest_bit_set(rechist->cur_set); 1183 return mini_rechist_next(rechist_ctx); 1184} 1185 1186 1187static lsquic_packno_t 1188least_unacked (const struct mini_conn *mc) 1189{ 1190 mconn_packno_set_t unacked; 1191 lsquic_packno_t packno; 1192 unacked = mc->mc_sent_packnos & ~mc->mc_acked_packnos; 1193 if (unacked) 1194 packno = lowest_bit_set(unacked) + 1; 1195 else 1196 packno = highest_bit_set(mc->mc_sent_packnos) + 2; 1197 LSQ_DEBUG("%s: least unacked: %"PRIu64, __func__, packno); 1198 return packno; 1199} 1200 1201 1202static int 1203generate_ack_and_stop_waiting (struct mini_conn *mc, lsquic_time_t now) 1204{ 1205 lsquic_packet_out_t *packet_out; 1206 struct mini_rechist rechist; 1207 int len, not_used_has_missing; 1208 lsquic_packno_t lunack; 1209 1210 /* Chrome's quic_server places ACK and STOP_WAITING frames into a separate 1211 * packet. 1212 */ 1213 packet_out = allocate_packet_out(mc, NULL); 1214 if (!packet_out) 1215 return -1; 1216 1217 /* Generate ACK frame */ 1218 mini_rechist_init(&rechist, mc); 1219 len = mc->mc_conn.cn_pf->pf_gen_ack_frame(packet_out->po_data + packet_out->po_data_sz, 1220 lsquic_packet_out_avail(packet_out), mini_rechist_first, 1221 mini_rechist_next, mini_rechist_largest_recv, &rechist, 1222 now, ¬_used_has_missing, &packet_out->po_ack2ed, NULL); 1223 if (len < 0) 1224 { 1225 LSQ_WARN("could not generate ACK frame"); 1226 return -1; 1227 } 1228 EV_LOG_GENERATED_ACK_FRAME(LSQUIC_LOG_CONN_ID, mc->mc_conn.cn_pf, 1229 packet_out->po_data + packet_out->po_data_sz, len); 1230 packet_out->po_frame_types |= 1 << QUIC_FRAME_ACK; 1231 packet_out->po_data_sz += len; 1232 packet_out->po_regen_sz += len; 1233 LSQ_DEBUG("wrote ACK frame of size %d", len); 1234 1235 /* Generate STOP_WAITING frame */ 1236 if ((mc->mc_flags & MC_STOP_WAIT_ON) && mc->mc_sent_packnos) 1237 { 1238 lunack = least_unacked(mc); 1239 len = mc->mc_conn.cn_pf->pf_gen_stop_waiting_frame(packet_out->po_data + 1240 packet_out->po_data_sz, 1241 lsquic_packet_out_avail(packet_out), packet_out->po_packno, 1242 lsquic_packet_out_packno_bits(packet_out), lunack); 1243 if (len < 0) 1244 { 1245 LSQ_WARN("could not generate STOP_WAITING frame"); 1246 return -1; 1247 } 1248 packet_out->po_data_sz += len; 1249 packet_out->po_regen_sz += len; 1250 packet_out->po_frame_types |= 1 << QUIC_FRAME_STOP_WAITING; 1251 LSQ_DEBUG("wrote STOP_WAITING frame of size %d", len); 1252 EV_LOG_GENERATED_STOP_WAITING_FRAME(LSQUIC_LOG_CONN_ID, lunack); 1253 } 1254 else if (mc->mc_flags & MC_STOP_WAIT_ON) 1255 LSQ_DEBUG("nothing sent: no need to generate STOP_WAITING frame"); 1256 1257 mc->mc_flags |= MC_UNSENT_ACK; 1258 return 0; 1259} 1260 1261 1262static int 1263calc_retx_timeout (const struct mini_conn *mc) 1264{ 1265 lsquic_time_t to; 1266 to = lsquic_rtt_stats_get_srtt(&mc->mc_rtt_stats); 1267 if (to) 1268 { 1269 to += to / 2; 1270 if (to < 10000) 1271 to = 10000; 1272 } 1273 else 1274 to = 300000; 1275 return to << mc->mc_hsk_count; 1276} 1277 1278 1279static void 1280return_enc_data (struct mini_conn *mc, struct lsquic_packet_out *packet_out) 1281{ 1282 mc->mc_enpub->enp_pmi->pmi_return(mc->mc_enpub->enp_pmi_ctx, 1283 mc->mc_path.np_peer_ctx, packet_out->po_enc_data, 1284 lsquic_packet_out_ipv6(packet_out)); 1285 packet_out->po_flags &= ~PO_ENCRYPTED; 1286 packet_out->po_enc_data = NULL; 1287} 1288 1289 1290static int 1291repackage_packet (struct mini_conn *mc, lsquic_packet_out_t *packet_out) 1292{ 1293 const lsquic_packno_t oldno = packet_out->po_packno; 1294 const lsquic_packno_t packno = next_packno(mc); 1295 if (packno > MINICONN_MAX_PACKETS) 1296 return -1; 1297 1298 LSQ_DEBUG("Packet %"PRIu64" repackaged for resending as packet %"PRIu64, 1299 oldno, packno); 1300 EV_LOG_CONN_EVENT(LSQUIC_LOG_CONN_ID, "packet %"PRIu64" repackaged for " 1301 "resending as packet %"PRIu64, oldno, packno); 1302 packet_out->po_packno = packno; 1303 packet_out->po_flags &= ~PO_SENT; 1304 if (packet_out->po_flags & PO_ENCRYPTED) 1305 return_enc_data(mc, packet_out); 1306 TAILQ_INSERT_TAIL(&mc->mc_packets_out, packet_out, po_next); 1307 return 0; 1308} 1309 1310 1311static int 1312handle_losses_and_have_unsent (struct mini_conn *mc, lsquic_time_t now) 1313{ 1314 TAILQ_HEAD(, lsquic_packet_out) lost_packets = 1315 TAILQ_HEAD_INITIALIZER(lost_packets); 1316 lsquic_packet_out_t *packet_out, *next; 1317 lsquic_time_t retx_to = 0; 1318 unsigned n_to_send = 0; 1319 1320 for (packet_out = TAILQ_FIRST(&mc->mc_packets_out); packet_out; 1321 packet_out = next) 1322 { 1323 next = TAILQ_NEXT(packet_out, po_next); 1324 if (packet_out->po_flags & PO_SENT) 1325 { 1326 if (0 == retx_to) 1327 retx_to = calc_retx_timeout(mc); 1328 if (packet_out->po_sent + retx_to < now) 1329 { 1330 LSQ_DEBUG("packet %"PRIu64" has been lost (rto: %"PRIu64")", 1331 packet_out->po_packno, retx_to); 1332 TAILQ_REMOVE(&mc->mc_packets_out, packet_out, po_next); 1333 TAILQ_INSERT_TAIL(&lost_packets, packet_out, po_next); 1334 mc->mc_lost_packnos |= MCONN_PACKET_MASK(packet_out->po_packno); 1335 MCHIST_APPEND(mc, MCHE_PACKET_LOST); 1336 } 1337 } 1338 else 1339 ++n_to_send; 1340 } 1341 1342 mc->mc_hsk_count += !TAILQ_EMPTY(&lost_packets); 1343 1344 while ((packet_out = TAILQ_FIRST(&lost_packets))) 1345 { 1346 TAILQ_REMOVE(&lost_packets, packet_out, po_next); 1347 if ((packet_out->po_frame_types & GQUIC_FRAME_RETRANSMITTABLE_MASK) 1348 && 0 == repackage_packet(mc, packet_out)) 1349 ++n_to_send; 1350 else 1351 mini_destroy_packet(mc, packet_out); 1352 } 1353 1354 return n_to_send > 0; 1355} 1356 1357 1358static int 1359warning_is_warranted (const struct mini_conn *mc) 1360{ 1361 return (mc->mc_flags & (MC_HSK_ERR|MC_OO_PACKNOS)) 1362 || 0x1C /* QUIC_HANDSHAKE_FAILED */ == mc->mc_error_code 1363 || 0x1D /* QUIC_CRYPTO_TAGS_OUT_OF_ORDER */ == mc->mc_error_code 1364 || 0x1E /* QUIC_CRYPTO_TOO_MANY_ENTRIES */ == mc->mc_error_code 1365 || 0x1F /* QUIC_CRYPTO_INVALID_VALUE_LENGTH */ == mc->mc_error_code 1366 || 0x21 /* QUIC_INVALID_CRYPTO_MESSAGE_TYPE */ == mc->mc_error_code 1367 || 0x22 /* QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER */ == mc->mc_error_code 1368 || 0x23 /* QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND */ == mc->mc_error_code 1369 || 0x24 /* QUIC_CRYPTO_MESSAGE_PARAMETER_NO_OVERLAP */ == mc->mc_error_code 1370 || 0x29 /* QUIC_CRYPTO_TOO_MANY_REJECTS */ == mc->mc_error_code 1371 || 0x2A /* QUIC_PROOF_INVALID */ == mc->mc_error_code 1372 || 0x2B /* QUIC_CRYPTO_DUPLICATE_TAG */ == mc->mc_error_code 1373 || 0x2C /* QUIC_CRYPTO_ENCRYPTION_LEVEL_INCORRECT */ == mc->mc_error_code 1374 || 0x2D /* QUIC_CRYPTO_SERVER_CONFIG_EXPIRED */ == mc->mc_error_code 1375 || 0x35 /* QUIC_CRYPTO_SYMMETRIC_KEY_SETUP_FAILED */ == mc->mc_error_code 1376 ; 1377} 1378 1379 1380#if LSQUIC_KEEP_ENC_SESS_HISTORY 1381static void 1382maybe_log_enc_sess_history (const struct mini_conn *mc) 1383{ 1384 char eshist[ESHIST_STR_SIZE]; 1385 enum lsq_log_level log_level; 1386 const char *ua; 1387 1388 if (warning_is_warranted(mc)) 1389 log_level = LSQ_LOG_WARN; 1390 else 1391 log_level = LSQ_LOG_DEBUG; 1392 1393 if (mc->mc_conn.cn_enc_session) 1394 { 1395 mc->mc_conn.cn_esf.g->esf_get_hist(mc->mc_conn.cn_enc_session, eshist); 1396 ua = mc->mc_conn.cn_esf.g->esf_get_ua(mc->mc_conn.cn_enc_session); 1397 LSQ_LOG1(log_level, "enc hist %s; User-Agent: %s", eshist, 1398 ua ? ua : "<not set>"); 1399 } 1400 else 1401 LSQ_LOG1(log_level, "enc session gone: no history to log"); 1402} 1403 1404 1405#endif 1406 1407 1408 1409 1410static int 1411have_packets_to_send (struct mini_conn *mc, lsquic_time_t now) 1412{ 1413 return handle_losses_and_have_unsent(mc, now); 1414} 1415 1416 1417static enum tick_st 1418mini_conn_ci_tick (struct lsquic_conn *lconn, lsquic_time_t now) 1419{ 1420 struct mini_conn *mc = (struct mini_conn *) lconn; 1421 enum tick_st tick; 1422 1423 ++mc->mc_n_ticks; 1424 1425 if (mc->mc_created + mc->mc_enpub->enp_settings.es_handshake_to < now) 1426 { 1427 LSQ_DEBUG("connection expired: closing"); 1428 tick = TICK_CLOSE; 1429 goto end; 1430 } 1431 1432 if (mc->mc_flags & MC_ERROR) 1433 { 1434 tick = TICK_CLOSE; 1435 goto end; 1436 } 1437 1438 1439 if ((mc->mc_flags & (MC_UNSENT_ACK|MC_GEN_ACK)) == MC_GEN_ACK) 1440 { 1441 if (0 != generate_ack_and_stop_waiting(mc, now)) 1442 { 1443 mc->mc_flags |= MC_ERROR; 1444 tick = TICK_CLOSE; 1445 goto end; 1446 } 1447 else 1448 mc->mc_flags &= ~MC_GEN_ACK; 1449 } 1450 1451 if (have_packets_to_send(mc, now)) 1452 tick = TICK_SEND; 1453 else 1454 tick = TICK_QUIET; 1455 1456 if (mc->mc_flags & MC_PROMOTE) 1457 tick |= TICK_PROMOTE; 1458 1459 end: 1460#if LSQUIC_KEEP_ENC_SESS_HISTORY 1461 if (tick & (TICK_CLOSE|TICK_PROMOTE)) 1462 maybe_log_enc_sess_history(mc); 1463#endif 1464 1465 return tick; 1466} 1467 1468 1469static void 1470process_packet (struct mini_conn *mc, struct lsquic_packet_in *packet_in) 1471{ 1472 switch (process_regular_packet(mc, packet_in)) 1473 { 1474 case PRP_KEEP: 1475 assert(packet_in->pi_flags & PI_OWN_DATA); 1476 lsquic_packet_in_upref(packet_in); 1477 TAILQ_INSERT_TAIL(&mc->mc_packets_in, packet_in, pi_next); 1478 if (mc->mc_flags & MC_HAVE_NEW_HSK) 1479 { 1480 if (0 != continue_handshake(mc)) 1481 mc->mc_flags |= MC_ERROR; 1482 mc->mc_flags &= ~MC_HAVE_NEW_HSK; 1483 } 1484 break; 1485 case PRP_DEFER: 1486 assert(packet_in->pi_flags & PI_OWN_DATA); 1487 lsquic_packet_in_upref(packet_in); 1488 TAILQ_INSERT_TAIL(&mc->mc_deferred, packet_in, pi_next); 1489 break; 1490 case PRP_ERROR: 1491 mc->mc_flags |= MC_ERROR; 1492 break; 1493 case PRP_DROP: 1494 break; 1495 } 1496} 1497 1498 1499/* Keep deferred list ordered by packet number, so that we can process all 1500 * of them in a single pass. 1501 */ 1502static void 1503insert_into_deferred (struct mini_conn *mc, lsquic_packet_in_t *new_packet) 1504{ 1505 lsquic_packet_in_t *packet_in; 1506 1507 lsquic_packet_in_upref(new_packet); 1508 1509 TAILQ_FOREACH(packet_in, &mc->mc_deferred, pi_next) 1510 if (packet_in->pi_packno > new_packet->pi_packno) 1511 break; 1512 1513 if (packet_in) 1514 TAILQ_INSERT_BEFORE(packet_in, new_packet, pi_next); 1515 else 1516 TAILQ_INSERT_TAIL(&mc->mc_deferred, new_packet, pi_next); 1517} 1518 1519 1520static void 1521process_deferred_packets (struct mini_conn *mc) 1522{ 1523 lsquic_packet_in_t *last, *packet_in; 1524 int reached_last; 1525 1526 last = TAILQ_LAST(&mc->mc_deferred, head_packet_in); 1527 do 1528 { 1529 packet_in = TAILQ_FIRST(&mc->mc_deferred); 1530 TAILQ_REMOVE(&mc->mc_deferred, packet_in, pi_next); 1531 process_packet(mc, packet_in); 1532 reached_last = packet_in == last; 1533 lsquic_packet_in_put(&mc->mc_enpub->enp_mm, packet_in); 1534 } 1535 while (!reached_last); 1536} 1537 1538 1539#if LSQUIC_RECORD_INORD_HIST 1540/* Packet number is encoded as a sequence of 1-bits and stored in mc_inord_hist 1541 * separated by 0 bits. For example, sequence of packet numbers 3, 2, 1 would 1542 * be encoded as (starting with LSB) 1110110100000000... This is not the most 1543 * space-efficient scheme, but it is simple to implement and should suffice for 1544 * our purposes. 1545 */ 1546static void 1547record_inord_packno (struct mini_conn *mc, lsquic_packno_t packno) 1548{ 1549 int n_avail; 1550 lsquic_packno_t mask; 1551 1552 for ( ; mc->mc_inord_idx < sizeof(mc->mc_inord_hist) / 1553 sizeof(mc->mc_inord_hist[0]); ++mc->mc_inord_idx) 1554 { 1555 if (mc->mc_inord_hist[ mc->mc_inord_idx ]) 1556 n_avail = __builtin_clzll(mc->mc_inord_hist[ mc->mc_inord_idx ]) - 1; 1557 else 1558 n_avail = sizeof(mc->mc_inord_hist[ mc->mc_inord_idx ]) * 8; 1559 if (n_avail >= (int) packno) 1560 { 1561 mask = (1ULL << (int) packno) - 1; 1562 mask <<= sizeof(mc->mc_inord_hist[ mc->mc_inord_idx ]) * 8 - n_avail; 1563 mc->mc_inord_hist[ mc->mc_inord_idx ] |= mask; 1564 return; /* Success */ 1565 } 1566 } 1567} 1568 1569 1570static void 1571inord_to_str (const struct mini_conn *mc, char *buf, size_t bufsz) 1572{ 1573 unsigned long long hist; 1574 size_t off; 1575 ssize_t nw; 1576 unsigned n; 1577 int n_trail; 1578 1579 off = 0; 1580 for (n = 0; n < sizeof(mc->mc_inord_hist) / 1581 sizeof(mc->mc_inord_hist[0]); ++n) 1582 { 1583 hist = mc->mc_inord_hist[n]; 1584 while (hist) 1585 { 1586 n_trail = __builtin_ctzll(~hist); 1587 nw = snprintf(buf + off, bufsz - off, 1588 /* No spaces are included on purpose: this makes it a single 1589 * field and thus easy to process log using standard command- 1590 * line tools, such as sork -k, for example. 1591 */ 1592 (off ? ",%d" : "%d"), n_trail); 1593 if ((size_t) nw > bufsz - off || nw < 0) 1594 break; 1595 off += nw; 1596 hist >>= n_trail + 1; 1597 } 1598 } 1599 buf[ bufsz - 1 ] = '\0'; /* CYA */ 1600} 1601 1602 1603#endif 1604 1605 1606static void 1607mini_conn_ci_packet_in (struct lsquic_conn *lconn, 1608 struct lsquic_packet_in *packet_in) 1609{ 1610 struct mini_conn *mc = (struct mini_conn *) lconn; 1611 1612#if LSQUIC_RECORD_INORD_HIST 1613 record_inord_packno(mc, packet_in->pi_packno); 1614#endif 1615#if 0 1616 /* A convenient way to test lsquic_is_valid_hs_packet(): */ 1617 if (!(mc->mc_sent_packnos)) 1618 assert(lsquic_is_valid_hs_packet(NULL, packet_in->pi_data, 1619 packet_in->pi_data_sz)); 1620#endif 1621 1622 if (mc->mc_flags & MC_ERROR) 1623 { 1624 LSQ_DEBUG("error state: ignore packet %"PRIu64, packet_in->pi_packno); 1625 return; 1626 } 1627 1628 if (lsquic_packet_in_is_gquic_prst(packet_in)) 1629 { 1630 LSQ_INFO("received reset packet"); 1631 mc->mc_flags |= MC_ERROR; 1632 MCHIST_APPEND(mc, MCHE_PRST_IN); 1633 return; 1634 } 1635 1636 LSQ_DEBUG("packet in: %"PRIu64, packet_in->pi_packno); 1637 EV_LOG_PACKET_IN(LSQUIC_LOG_CONN_ID, packet_in); 1638 1639 1640 /* Check receive history */ 1641 if (0 == packet_in->pi_packno) 1642 { 1643 LSQ_DEBUG("invalid packet number 0"); 1644 mc->mc_flags |= MC_ERROR; 1645 MCHIST_APPEND(mc, MCHE_PACKET0_IN); 1646 return; 1647 } 1648 if (packet_in->pi_packno > MINICONN_MAX_PACKETS) 1649 { 1650 LSQ_DEBUG("packet number %"PRIu64" is too large (max %zd)", 1651 packet_in->pi_packno, MINICONN_MAX_PACKETS); 1652 mc->mc_flags |= MC_ERROR; 1653 MCHIST_APPEND(mc, MCHE_PACKET2LARGE_IN); 1654 return; 1655 } 1656 if (MCONN_PACKET_MASK(packet_in->pi_packno) & mc->mc_received_packnos) 1657 { 1658 LSQ_DEBUG("duplicate packet %"PRIu64", ignoring", packet_in->pi_packno); 1659 MCHIST_APPEND(mc, MCHE_PACKET_DUP_IN); 1660 return; 1661 } 1662 1663 if (TAILQ_EMPTY(&mc->mc_deferred)) 1664 process_packet(mc, packet_in); 1665 else 1666 { 1667 insert_into_deferred(mc, packet_in); 1668 process_deferred_packets(mc); 1669 } 1670} 1671 1672 1673static struct lsquic_packet_out * 1674mini_conn_ci_next_packet_to_send (struct lsquic_conn *lconn, size_t size) 1675{ 1676 struct mini_conn *mc = (struct mini_conn *) lconn; 1677 lsquic_packet_out_t *packet_out; 1678 1679 assert(0 == size); 1680 TAILQ_FOREACH(packet_out, &mc->mc_packets_out, po_next) 1681 { 1682 if (packet_out->po_flags & PO_SENT) 1683 continue; 1684 packet_out->po_flags |= PO_SENT; 1685 LSQ_DEBUG("packet_to_send: %"PRIu64, packet_out->po_packno); 1686 return packet_out; 1687 } 1688 return NULL; 1689} 1690 1691 1692static void 1693mini_conn_ci_packet_sent (struct lsquic_conn *lconn, 1694 struct lsquic_packet_out *packet_out) 1695{ 1696 struct mini_conn *mc = (struct mini_conn *) lconn; 1697 mc->mc_sent_packnos |= MCONN_PACKET_MASK(packet_out->po_packno); 1698 if (packet_out->po_frame_types & (1 << QUIC_FRAME_ACK)) 1699 { 1700 assert(mc->mc_flags & MC_UNSENT_ACK); 1701 mc->mc_flags &= ~MC_UNSENT_ACK; 1702 } 1703 LSQ_DEBUG("%s: packet %"PRIu64" sent", __func__, packet_out->po_packno); 1704 MCHIST_APPEND(mc, MCHE_PACKET_SENT); 1705} 1706 1707 1708static void 1709mini_conn_ci_packet_not_sent (struct lsquic_conn *lconn, 1710 struct lsquic_packet_out *packet_out) 1711{ 1712 struct mini_conn *mc = (struct mini_conn *) lconn; 1713 packet_out->po_flags &= ~PO_SENT; 1714 LSQ_DEBUG("%s: packet %"PRIu64" not sent", __func__, packet_out->po_packno); 1715 MCHIST_APPEND(mc, MCHE_PACKET_DELAYED); 1716} 1717 1718 1719static void 1720mini_conn_ci_destroy (struct lsquic_conn *lconn) 1721{ 1722 assert(!(lconn->cn_flags & LSCONN_HASHED)); 1723 struct mini_conn *mc = (struct mini_conn *) lconn; 1724 lsquic_packet_in_t *packet_in; 1725 mconn_packno_set_t still_deferred = 0, in_flight; 1726 enum lsq_log_level log_level; 1727#if LSQUIC_RECORD_INORD_HIST 1728 char inord_str[0x100]; 1729#endif 1730 while ((packet_in = TAILQ_FIRST(&mc->mc_packets_in))) 1731 { 1732 TAILQ_REMOVE(&mc->mc_packets_in, packet_in, pi_next); 1733 lsquic_packet_in_put(&mc->mc_enpub->enp_mm, packet_in); 1734 } 1735 while ((packet_in = TAILQ_FIRST(&mc->mc_deferred))) 1736 { 1737 TAILQ_REMOVE(&mc->mc_deferred, packet_in, pi_next); 1738 still_deferred |= MCONN_PACKET_MASK(packet_in->pi_packno); 1739 lsquic_packet_in_put(&mc->mc_enpub->enp_mm, packet_in); 1740 } 1741 if (TAILQ_EMPTY(&mc->mc_packets_out)) 1742 in_flight = ~0ull; /* Indicates that packets were dropped before */ 1743 else 1744 in_flight = drop_packets_out(mc); 1745 if (mc->mc_conn.cn_enc_session) 1746 mc->mc_conn.cn_esf.g->esf_destroy(mc->mc_conn.cn_enc_session); 1747 log_level = warning_is_warranted(mc) ? LSQ_LOG_WARN : LSQ_LOG_DEBUG; 1748#if LSQUIC_RECORD_INORD_HIST 1749 if (LSQ_LOG_ENABLED(log_level)) 1750 inord_to_str(mc, inord_str, sizeof(inord_str)); 1751#endif 1752#if LSQUIC_KEEP_MINICONN_HISTORY 1753 const unsigned hist_idx = MCHIST_MASK & mc->mc_hist_idx; 1754 if (MCHE_EMPTY == mc->mc_hist_buf[ hist_idx ]) 1755 LSQ_LOG(log_level, "destroyed. Diagnostics: conn flags: 0x%X, " 1756 "mc flags: 0x%X, " 1757#if LSQUIC_RECORD_INORD_HIST 1758 "incoming-history (trunc: %d) %s, " 1759#endif 1760 "received: %"PRIX64", sent: %"PRIX64", lost: %"PRIX64", " 1761 "deferred: %"PRIX64", still-deferred: %"PRIX64", " 1762 "dropped: %"PRIX64", in-flight: %"PRIX64", acked: %"PRIX64", " 1763 "error_code: 0x%X, ticks: %hu, pack size: %hu, " 1764 "lifetime: %"PRIu64" usec, version: %s, " 1765 "mc hist: %.*s", mc->mc_conn.cn_flags, 1766 mc->mc_flags, 1767#if LSQUIC_RECORD_INORD_HIST 1768 mc->mc_inord_idx >= sizeof(mc->mc_inord_hist) / 1769 sizeof(mc->mc_inord_hist[0]), inord_str, 1770#endif 1771 mc->mc_received_packnos, mc->mc_sent_packnos, mc->mc_lost_packnos, 1772 mc->mc_deferred_packnos, still_deferred, 1773 mc->mc_dropped_packnos, in_flight, mc->mc_acked_packnos, 1774 mc->mc_error_code, mc->mc_n_ticks, mc->mc_conn.cn_pack_size, 1775 lsquic_time_now() - mc->mc_created, 1776 lsquic_ver2str[mc->mc_conn.cn_version], 1777 (int) hist_idx, mc->mc_hist_buf); 1778 else 1779 LSQ_LOG(log_level, "destroyed. Diagnostics: conn flags: 0x%X, " 1780 "mc flags: 0x%X, " 1781#if LSQUIC_RECORD_INORD_HIST 1782 "incoming-history (trunc: %d) %s, " 1783#endif 1784 "received: %"PRIX64", sent: %"PRIX64", lost: %"PRIX64", " 1785 "deferred: %"PRIX64", still-deferred: %"PRIX64", " 1786 "dropped: %"PRIX64", in-flight: %"PRIX64", acked: %"PRIX64", " 1787 "error_code: 0x%X, ticks: %hu, pack size: %hu, " 1788 "lifetime: %"PRIu64" usec, version: %s, " 1789 "mc hist: %.*s%.*s", mc->mc_conn.cn_flags, 1790 mc->mc_flags, 1791#if LSQUIC_RECORD_INORD_HIST 1792 mc->mc_inord_idx >= sizeof(mc->mc_inord_hist) / 1793 sizeof(mc->mc_inord_hist[0]), inord_str, 1794#endif 1795 mc->mc_received_packnos, mc->mc_sent_packnos, mc->mc_lost_packnos, 1796 mc->mc_deferred_packnos, still_deferred, 1797 mc->mc_dropped_packnos, in_flight, mc->mc_acked_packnos, 1798 mc->mc_error_code, mc->mc_n_ticks, mc->mc_conn.cn_pack_size, 1799 lsquic_time_now() - mc->mc_created, 1800 lsquic_ver2str[mc->mc_conn.cn_version], 1801 (int) (sizeof(mc->mc_hist_buf) - hist_idx), 1802 mc->mc_hist_buf + hist_idx, (int) hist_idx, mc->mc_hist_buf); 1803#else 1804 LSQ_LOG(log_level, "destroyed. Diagnostics: conn flags: 0x%X, " 1805 "mc flags: 0x%X, " 1806#if LSQUIC_RECORD_INORD_HIST 1807 "incoming-history (trunc: %d) %s, " 1808#endif 1809 "received: %"PRIX64", sent: %"PRIX64", lost: %"PRIX64", " 1810 "deferred: %"PRIX64", still-deferred: %"PRIX64", " 1811 "dropped: %"PRIX64", in-flight: %"PRIX64", acked: %"PRIX64", " 1812 "error_code: 0x%X, ticks: %hu, pack size: %hu, " 1813 "lifetime: %"PRIu64" usec", 1814 mc->mc_conn.cn_flags, 1815 mc->mc_flags, 1816#if LSQUIC_RECORD_INORD_HIST 1817 mc->mc_inord_idx >= sizeof(mc->mc_inord_hist) / 1818 sizeof(mc->mc_inord_hist[0]), inord_str, 1819#endif 1820 mc->mc_received_packnos, mc->mc_sent_packnos, mc->mc_lost_packnos, 1821 mc->mc_deferred_packnos, still_deferred, 1822 mc->mc_dropped_packnos, in_flight, mc->mc_acked_packnos, 1823 mc->mc_error_code, mc->mc_n_ticks, mc->mc_path.np_pack_size, 1824 lsquic_time_now() - mc->mc_created); 1825#endif 1826 EV_LOG_CONN_EVENT(LSQUIC_LOG_CONN_ID, "mini connection destroyed"); 1827 lsquic_malo_put(mc); 1828} 1829 1830 1831#if LSQUIC_ENABLE_HANDSHAKE_DISABLE 1832static void 1833mini_conn_ci_packet_in_disable_handshake (struct lsquic_conn *lconn, 1834 struct lsquic_packet_in *packet_in) 1835{ 1836 struct mini_conn *mc = (struct mini_conn *) lconn; 1837 if (0 == (mc->mc_flags & MC_ERROR)) 1838 { 1839 if (packet_in->pi_packno > MINICONN_MAX_PACKETS) 1840 mc->mc_flags |= MC_ERROR; 1841 else if (!(mc->mc_received_packnos & 1842 MCONN_PACKET_MASK(packet_in->pi_packno))) 1843 { 1844 lsquic_packet_in_upref(packet_in); 1845 TAILQ_INSERT_TAIL(&mc->mc_packets_in, packet_in, pi_next); 1846 mc->mc_received_packnos |= MCONN_PACKET_MASK(packet_in->pi_packno); 1847 } 1848 } 1849} 1850 1851 1852static enum tick_st 1853mini_conn_ci_tick_disable_handshake (struct lsquic_conn *lconn, 1854 lsquic_time_t now) 1855{ 1856 struct mini_conn *mc = (struct mini_conn *) lconn; 1857 LSQ_WARN("handshake disabled, promote me now"); 1858 lconn->cn_flags |= LSCONN_HANDSHAKE_DONE; 1859 mc->mc_conn.cn_enc_session = 1860 mc->mc_conn.cn_esf.g->esf_create_server(lconn->cn_cid, mc->mc_enpub, 0); 1861 mc->mc_conn.cn_esf.g->esf_set_handshake_completed(mc->mc_conn.cn_enc_session); 1862 return TICK_PROMOTE; 1863} 1864 1865 1866#endif 1867 1868 1869static struct lsquic_engine * 1870mini_conn_ci_get_engine (struct lsquic_conn *lconn) 1871{ 1872 struct mini_conn *mc = (struct mini_conn *) lconn; 1873 return mc->mc_enpub->enp_engine; 1874} 1875 1876 1877static void 1878mini_conn_ci_hsk_done (struct lsquic_conn *lconn, enum lsquic_hsk_status status) 1879{ 1880 assert(0); 1881} 1882 1883 1884static int 1885mini_conn_ci_is_tickable (struct lsquic_conn *lconn) 1886{ 1887 /* A mini connection is never tickable: Either there are incoming 1888 * packets, in which case, the connection is going to be ticked, or 1889 * there is an alarm pending, in which case it will be handled via 1890 * the attq. 1891 */ 1892 return 0; 1893} 1894 1895 1896static lsquic_time_t 1897mini_conn_ci_next_tick_time (struct lsquic_conn *lconn, unsigned *why) 1898{ 1899 struct mini_conn *mc = (struct mini_conn *) lconn; 1900 lsquic_packet_out_t *packet_out; 1901 lsquic_time_t exp_time, retx_time; 1902 1903 exp_time = mc->mc_created + mc->mc_enpub->enp_settings.es_handshake_to; 1904 1905 TAILQ_FOREACH(packet_out, &mc->mc_packets_out, po_next) 1906 if (packet_out->po_flags & PO_SENT) 1907 { 1908 retx_time = packet_out->po_sent + calc_retx_timeout(mc); 1909 if (retx_time < exp_time) 1910 { 1911 *why = N_AEWS + AL_RETX_HSK; 1912 return retx_time; 1913 } 1914 else 1915 { 1916 *why = AEW_MINI_EXPIRE; 1917 return exp_time; 1918 } 1919 } 1920 1921 *why = AEW_MINI_EXPIRE; 1922 return exp_time; 1923} 1924 1925 1926static void 1927mini_conn_ci_client_call_on_new (struct lsquic_conn *lconn) 1928{ 1929 assert(0); 1930} 1931 1932 1933static void 1934mini_conn_ci_internal_error (struct lsquic_conn *lconn, 1935 const char *format, ...) 1936{ 1937 struct mini_conn *mc = (struct mini_conn *) lconn; 1938 LSQ_INFO("internal error reported"); 1939 mc->mc_flags |= MC_ERROR; 1940} 1941 1942 1943/* This function should not be called, as this is specific to IETF QUIC */ 1944static void 1945mini_conn_ci_abort_error (struct lsquic_conn *lconn, int is_app, 1946 unsigned error_code, const char *fmt, ...) 1947{ 1948 struct mini_conn *mc = (struct mini_conn *) lconn; 1949 assert(0); 1950 LSQ_WARN("(GQUIC) abort error is called unexpectedly"); 1951 mc->mc_flags |= MC_ERROR; 1952} 1953 1954 1955static void 1956mini_conn_ci_tls_alert (struct lsquic_conn *lconn, uint8_t alert) 1957{ 1958 assert(0); 1959} 1960 1961 1962static unsigned char 1963mini_conn_ci_record_addrs (struct lsquic_conn *lconn, void *peer_ctx, 1964 const struct sockaddr *local_sa, const struct sockaddr *peer_sa) 1965{ 1966 struct mini_conn *mc = (struct mini_conn *) lconn; 1967 struct lsquic_packet_out *packet_out; 1968 size_t len; 1969 1970 1971 if (NP_IS_IPv6(&mc->mc_path) != (AF_INET6 == peer_sa->sa_family)) 1972 TAILQ_FOREACH(packet_out, &mc->mc_packets_out, po_next) 1973 if ((packet_out->po_flags & (PO_SENT|PO_ENCRYPTED)) == PO_ENCRYPTED) 1974 return_enc_data(mc, packet_out); 1975 1976 len = local_sa->sa_family == AF_INET ? sizeof(struct sockaddr_in) 1977 : sizeof(struct sockaddr_in6); 1978 1979 memcpy(mc->mc_path.np_peer_addr, peer_sa, len); 1980 memcpy(mc->mc_path.np_local_addr, local_sa, len); 1981 mc->mc_path.np_peer_ctx = peer_ctx; 1982 return 0; 1983} 1984 1985 1986static struct network_path * 1987mini_conn_ci_get_path (struct lsquic_conn *lconn, const struct sockaddr *sa) 1988{ 1989 struct mini_conn *mc = (struct mini_conn *) lconn; 1990 1991 return &mc->mc_path; 1992} 1993 1994 1995static const struct conn_iface mini_conn_iface_standard = { 1996 .ci_abort_error = mini_conn_ci_abort_error, 1997 .ci_client_call_on_new = mini_conn_ci_client_call_on_new, 1998 .ci_destroy = mini_conn_ci_destroy, 1999 .ci_get_engine = mini_conn_ci_get_engine, 2000 .ci_get_path = mini_conn_ci_get_path, 2001 .ci_hsk_done = mini_conn_ci_hsk_done, 2002 .ci_internal_error = mini_conn_ci_internal_error, 2003 .ci_is_tickable = mini_conn_ci_is_tickable, 2004 .ci_next_packet_to_send = mini_conn_ci_next_packet_to_send, 2005 .ci_next_tick_time = mini_conn_ci_next_tick_time, 2006 .ci_packet_in = mini_conn_ci_packet_in, 2007 .ci_packet_not_sent = mini_conn_ci_packet_not_sent, 2008 .ci_packet_sent = mini_conn_ci_packet_sent, 2009 .ci_record_addrs = mini_conn_ci_record_addrs, 2010 .ci_tick = mini_conn_ci_tick, 2011 .ci_tls_alert = mini_conn_ci_tls_alert, 2012}; 2013 2014 2015#if LSQUIC_ENABLE_HANDSHAKE_DISABLE 2016static const struct conn_iface mini_conn_iface_disable_handshake = { 2017 .ci_abort_error = mini_conn_ci_abort_error, 2018 .ci_client_call_on_new = mini_conn_ci_client_call_on_new, 2019 .ci_destroy = mini_conn_ci_destroy, 2020 .ci_get_engine = mini_conn_ci_get_engine, 2021 .ci_hsk_done = mini_conn_ci_hsk_done, 2022 .ci_internal_error = mini_conn_ci_internal_error, 2023 .ci_is_tickable = mini_conn_ci_is_tickable, 2024 .ci_next_packet_to_send = mini_conn_ci_next_packet_to_send, 2025 .ci_next_tick_time = mini_conn_ci_next_tick_time, 2026 .ci_packet_in = mini_conn_ci_packet_in_disable_handshake, 2027 .ci_packet_not_sent = mini_conn_ci_packet_not_sent, 2028 .ci_packet_sent = mini_conn_ci_packet_sent, 2029 .ci_tick = mini_conn_ci_tick_disable_handshake, 2030 .ci_tls_alert = mini_conn_ci_tls_alert, 2031}; 2032#endif 2033 2034typedef char largest_recv_holds_at_least_16_seconds[ 2035 ((1 << (sizeof(((struct mini_conn *) 0)->mc_largest_recv) * 8)) / 1000000 2036 >= 16) - 1]; 2037 2038typedef char max_lifespan_smaller_than_largest_recv[ 2039 ((1 << (sizeof(((struct mini_conn *) 0)->mc_largest_recv) * 8)) > 2040 MAX_MINI_CONN_LIFESPAN_IN_USEC) - 1]; 2041