lsquic_mini_conn_ietf.c revision 5392f7a3
1/* Copyright (c) 2017 - 2019 LiteSpeed Technologies Inc. See LICENSE. */ 2/* 3 * lsquic_mini_conn_ietf.c -- Mini connection used by the IETF QUIC 4 */ 5 6#include <assert.h> 7#include <errno.h> 8#include <inttypes.h> 9#include <stddef.h> 10#include <stdint.h> 11#include <string.h> 12#include <sys/queue.h> 13#include <stdlib.h> 14 15#include "lsquic.h" 16#include "lsquic_int_types.h" 17#include "lsquic_sizes.h" 18#include "lsquic_hash.h" 19#include "lsquic_conn.h" 20#include "lsquic_mm.h" 21#include "lsquic_malo.h" 22#include "lsquic_engine_public.h" 23#include "lsquic_packet_common.h" 24#include "lsquic_packet_in.h" 25#include "lsquic_packet_out.h" 26#include "lsquic_parse.h" 27#include "lsquic_rtt.h" 28#include "lsquic_util.h" 29#include "lsquic_enc_sess.h" 30#include "lsquic_mini_conn_ietf.h" 31#include "lsquic_ev_log.h" 32#include "lsquic_trans_params.h" 33#include "lsquic_ietf.h" 34#include "lsquic_packet_ietf.h" 35 36#define LSQUIC_LOGGER_MODULE LSQLM_MINI_CONN 37#define LSQUIC_LOG_CONN_ID lsquic_conn_log_cid(&conn->imc_conn) 38#include "lsquic_logger.h" 39 40#define MIN(a, b) ((a) < (b) ? (a) : (b)) 41#define MAX(a, b) ((a) > (b) ? (a) : (b)) 42 43static const struct conn_iface mini_conn_ietf_iface; 44 45static unsigned highest_bit_set (unsigned long long); 46 47 48static const enum header_type el2hety[] = 49{ 50 [ENC_LEV_INIT] = HETY_HANDSHAKE, 51 [ENC_LEV_CLEAR] = HETY_INITIAL, 52 [ENC_LEV_FORW] = HETY_NOT_SET, 53 [ENC_LEV_EARLY] = 0, /* Invalid */ 54}; 55 56 57static void 58imico_destroy_packet (struct ietf_mini_conn *conn, 59 struct lsquic_packet_out *packet_out) 60{ 61 lsquic_packet_out_destroy(packet_out, conn->imc_enpub, 62 conn->imc_path.np_peer_ctx); 63} 64 65 66static struct lsquic_packet_out * 67imico_get_packet_out (struct ietf_mini_conn *conn, 68 enum header_type header_type, size_t need) 69{ 70 struct lsquic_packet_out *packet_out; 71 72 if (need) 73 TAILQ_FOREACH(packet_out, &conn->imc_packets_out, po_next) 74 if (!(packet_out->po_flags & PO_SENT) 75 && packet_out->po_header_type == header_type 76 && lsquic_packet_out_avail(packet_out) >= need) 77 return packet_out; 78 79 if (conn->imc_next_packno >= MAX_PACKETS) 80 { 81 LSQ_DEBUG("ran out of outgoing packet numbers, won't allocate packet"); 82 return NULL; 83 } 84 85 packet_out = lsquic_packet_out_new(&conn->imc_enpub->enp_mm, NULL, 1, 86 &conn->imc_conn, IQUIC_PACKNO_LEN_1, NULL, NULL, &conn->imc_path); 87 if (!packet_out) 88 { 89 LSQ_WARN("could not allocate packet: %s", strerror(errno)); 90 return NULL; 91 } 92 93 packet_out->po_header_type = header_type; 94 packet_out->po_packno = conn->imc_next_packno++; 95 packet_out->po_flags |= PO_MINI; 96 lsquic_packet_out_set_pns(packet_out, lsquic_hety2pns[header_type]); 97 if (conn->imc_enpub->enp_settings.es_ecn) 98 packet_out->po_lflags |= ECN_ECT0 << POECN_SHIFT; 99 TAILQ_INSERT_TAIL(&conn->imc_packets_out, packet_out, po_next); 100 packet_out->po_loss_chain = packet_out; 101 return packet_out; 102} 103 104 105static struct ietf_mini_conn * 106cryst_get_conn (const struct mini_crypto_stream *cryst) 107{ 108 return (void *) 109 ((unsigned char *) (cryst - cryst->mcs_enc_level) 110 - offsetof(struct ietf_mini_conn, imc_streams)); 111} 112 113 114struct msg_ctx 115{ 116 const unsigned char *buf; 117 const unsigned char *const end; 118}; 119 120 121static size_t 122read_from_msg_ctx (void *ctx, void *buf, size_t len) 123{ 124 struct msg_ctx *msg_ctx = ctx; 125 if (len > (uintptr_t) (msg_ctx->end - msg_ctx->buf)) 126 len = msg_ctx->end - msg_ctx->buf; 127 memcpy(buf, msg_ctx->buf, len); 128 msg_ctx->buf += len; 129 return len; 130} 131 132 133static ssize_t 134imico_stream_write (void *stream, const void *bufp, size_t bufsz) 135{ 136 struct mini_crypto_stream *const cryst = stream; 137 struct ietf_mini_conn *const conn = cryst_get_conn(cryst); 138 struct lsquic_conn *const lconn = &conn->imc_conn; 139 const struct parse_funcs *const pf = lconn->cn_pf; 140 struct msg_ctx msg_ctx = { bufp, (unsigned char *) bufp + bufsz, }; 141 struct lsquic_packet_out *packet_out; 142 size_t header_sz, need; 143 const unsigned char *p; 144 int len; 145 146 if (PNS_INIT == lsquic_enclev2pns[ cryst->mcs_enc_level ] 147 && (conn->imc_flags & IMC_IGNORE_INIT)) 148 { 149 LSQ_WARN("trying to write at the ignored Initial level"); 150 return bufsz; 151 } 152 153 while (msg_ctx.buf < msg_ctx.end) 154 { 155 header_sz = lconn->cn_pf->pf_calc_crypto_frame_header_sz( 156 cryst->mcs_write_off); 157 need = header_sz + 1; 158 packet_out = imico_get_packet_out(conn, 159 el2hety[ cryst->mcs_enc_level ], need); 160 if (!packet_out) 161 return -1; 162 163 p = msg_ctx.buf; 164 len = pf->pf_gen_crypto_frame(packet_out->po_data + packet_out->po_data_sz, 165 lsquic_packet_out_avail(packet_out), cryst->mcs_write_off, 166 msg_ctx.end - msg_ctx.buf, read_from_msg_ctx, &msg_ctx); 167 if (len < 0) 168 return len; 169 EV_LOG_GENERATED_CRYPTO_FRAME(LSQUIC_LOG_CONN_ID, pf, 170 packet_out->po_data + packet_out->po_data_sz, len); 171 packet_out->po_data_sz += len; 172 packet_out->po_frame_types |= 1 << QUIC_FRAME_CRYPTO; 173 packet_out->po_flags |= PO_HELLO; 174 cryst->mcs_write_off += msg_ctx.buf - p; 175 } 176 177 assert(msg_ctx.buf == msg_ctx.end); 178 return bufsz; 179} 180 181 182static int 183imico_stream_flush (void *stream) 184{ 185 return 0; 186} 187 188 189static ssize_t 190imico_stream_readf (void *stream, 191 size_t (*readf)(void *, const unsigned char *, size_t, int), void *ctx) 192{ 193 struct mini_crypto_stream *const cryst = stream; 194 struct ietf_mini_conn *const conn = cryst_get_conn(cryst); 195 struct stream_frame *frame = conn->imc_last_in.frame; 196 size_t nread; 197 198 if (cryst->mcs_enc_level == conn->imc_last_in.enc_level 199 && frame && cryst->mcs_read_off == DF_ROFF(frame)) 200 { 201 nread = readf(ctx, frame->data_frame.df_data 202 + frame->data_frame.df_read_off, DF_SIZE(frame) 203 - frame->data_frame.df_read_off, DF_FIN(frame)); 204 cryst->mcs_read_off += nread; 205 frame->data_frame.df_read_off += nread; 206 LSQ_DEBUG("read %zu bytes at offset %"PRIu64" on enc level %u", nread, 207 DF_ROFF(frame), cryst->mcs_enc_level); 208 return nread; 209 } 210 else 211 { 212 errno = EWOULDBLOCK; 213 return -1; 214 } 215} 216 217 218static int 219imico_stream_wantX (struct mini_crypto_stream *cryst, int bit, int is_want) 220{ 221 int old; 222 223 old = (cryst->mcs_flags & (1 << bit)) > 0; 224 cryst->mcs_flags &= ~(1 << bit); 225 cryst->mcs_flags |= !!is_want << bit; 226 return old; 227} 228 229 230static int 231imico_stream_wantwrite (void *stream, int is_want) 232{ 233 return imico_stream_wantX(stream, MCSBIT_WANTWRITE, is_want); 234} 235 236 237static int 238imico_stream_wantread (void *stream, int is_want) 239{ 240 return imico_stream_wantX(stream, MCSBIT_WANTREAD, is_want); 241} 242 243 244static enum enc_level 245imico_stream_enc_level (void *stream) 246{ 247 struct mini_crypto_stream *const cryst = stream; 248 return cryst->mcs_enc_level; 249} 250 251 252static const struct crypto_stream_if crypto_stream_if = 253{ 254 .csi_write = imico_stream_write, 255 .csi_flush = imico_stream_flush, 256 .csi_readf = imico_stream_readf, 257 .csi_wantwrite = imico_stream_wantwrite, 258 .csi_wantread = imico_stream_wantread, 259 .csi_enc_level = imico_stream_enc_level, 260}; 261 262 263static int 264is_first_packet_ok (const struct lsquic_packet_in *packet_in) 265{ 266 /* TODO: Move decryption of the first packet into this function? */ 267 return 1; /* TODO */ 268} 269 270 271struct lsquic_conn * 272lsquic_mini_conn_ietf_new (struct lsquic_engine_public *enpub, 273 const struct lsquic_packet_in *packet_in, 274 enum lsquic_version version, int is_ipv4, const lsquic_cid_t *odcid) 275{ 276 struct ietf_mini_conn *conn; 277 enc_session_t *enc_sess; 278 enum enc_level i; 279 const struct enc_session_funcs_iquic *esfi; 280 281 if (!is_first_packet_ok(packet_in)) 282 return NULL; 283 284 conn = lsquic_malo_get(enpub->enp_mm.malo.mini_conn_ietf); 285 if (!conn) 286 { 287 LSQ_LOG1(LSQ_LOG_WARN, "cannot allocate mini connection: %s", 288 strerror(errno)); 289 return NULL; 290 } 291 memset(conn, 0, sizeof(*conn)); 292 conn->imc_conn.cn_if = &mini_conn_ietf_iface; 293 conn->imc_conn.cn_cces = conn->imc_cces; 294 conn->imc_conn.cn_n_cces = sizeof(conn->imc_cces) 295 / sizeof(conn->imc_cces[0]); 296 conn->imc_cces[0].cce_cid = packet_in->pi_dcid; 297 conn->imc_cces[0].cce_flags = CCE_USED; 298 conn->imc_conn.cn_cces_mask = 1; 299 lsquic_scid_from_packet_in(packet_in, &conn->imc_path.np_dcid); 300 LSQ_DEBUGC("recv SCID from client %"CID_FMT, CID_BITS(&conn->imc_cces[0].cce_cid)); 301 LSQ_DEBUGC("recv DCID from client %"CID_FMT, CID_BITS(&conn->imc_path.np_dcid)); 302 303 /* Generate new SCID. Since is not the original SCID, it is given 304 * a sequence number (0) and therefore can be retired by the client. 305 */ 306 lsquic_generate_cid(&conn->imc_conn.cn_cces[1].cce_cid, 307 enpub->enp_settings.es_scid_len); 308 LSQ_DEBUGC("generated SCID %"CID_FMT" at index %u, switching to it", 309 CID_BITS(&conn->imc_conn.cn_cces[1].cce_cid), 1); 310 conn->imc_conn.cn_cces[1].cce_flags = CCE_SEQNO | CCE_USED; 311 conn->imc_conn.cn_cces_mask |= 1u << 1; 312 conn->imc_conn.cn_cur_cce_idx = 1; 313 314 conn->imc_conn.cn_flags = LSCONN_MINI|LSCONN_IETF|LSCONN_SERVER; 315 316 for (i = 0; i < N_ENC_LEVS; ++i) 317 { 318 conn->imc_streams[i].mcs_enc_level = i; 319 conn->imc_stream_ps[i] = &conn->imc_streams[i]; 320 } 321 322 esfi = select_esf_iquic_by_ver(version); 323 enc_sess = esfi->esfi_create_server(enpub, &conn->imc_conn, 324 &packet_in->pi_dcid, conn->imc_stream_ps, &crypto_stream_if, 325 odcid); 326 if (!enc_sess) 327 { 328 lsquic_malo_put(conn); 329 return NULL; 330 } 331 332 conn->imc_enpub = enpub; 333 conn->imc_created = packet_in->pi_received; 334 conn->imc_path.np_pack_size = is_ipv4 ? IQUIC_MAX_IPv4_PACKET_SZ 335 : IQUIC_MAX_IPv6_PACKET_SZ; 336#ifndef NDEBUG 337 if (getenv("LSQUIC_CN_PACK_SIZE")) 338 conn->imc_path.np_pack_size = atoi(getenv("LSQUIC_CN_PACK_SIZE")); 339#endif 340 conn->imc_conn.cn_version = version; 341 conn->imc_conn.cn_pf = select_pf_by_ver(version); 342 conn->imc_conn.cn_esf.i = esfi; 343 conn->imc_conn.cn_enc_session = enc_sess; 344 conn->imc_conn.cn_esf_c = select_esf_common_by_ver(version); 345 TAILQ_INIT(&conn->imc_packets_out); 346 TAILQ_INIT(&conn->imc_app_packets); 347 348 LSQ_DEBUG("created mini connection object %p; max packet size=%hu", 349 conn, conn->imc_path.np_pack_size); 350 return &conn->imc_conn; 351} 352 353 354static void 355ietf_mini_conn_ci_client_call_on_new (struct lsquic_conn *lconn) 356{ 357 assert(0); 358} 359 360 361static void 362ietf_mini_conn_ci_destroy (struct lsquic_conn *lconn) 363{ 364 struct ietf_mini_conn *conn = (struct ietf_mini_conn *) lconn; 365 struct lsquic_packet_out *packet_out; 366 struct lsquic_packet_in *packet_in; 367 368 while ((packet_out = TAILQ_FIRST(&conn->imc_packets_out))) 369 { 370 TAILQ_REMOVE(&conn->imc_packets_out, packet_out, po_next); 371 imico_destroy_packet(conn, packet_out); 372 } 373 while ((packet_in = TAILQ_FIRST(&conn->imc_app_packets))) 374 { 375 TAILQ_REMOVE(&conn->imc_app_packets, packet_in, pi_next); 376 lsquic_packet_in_put(&conn->imc_enpub->enp_mm, packet_in); 377 } 378 if (lconn->cn_enc_session) 379 lconn->cn_esf.i->esfi_destroy(lconn->cn_enc_session); 380 LSQ_DEBUG("ietf_mini_conn_ci_destroyed"); 381 lsquic_malo_put(conn); 382} 383 384 385static struct lsquic_engine * 386ietf_mini_conn_ci_get_engine (struct lsquic_conn *lconn) 387{ 388 struct ietf_mini_conn *conn = (struct ietf_mini_conn *) lconn; 389 return conn->imc_enpub->enp_engine; 390} 391 392 393static void 394ietf_mini_conn_ci_hsk_done (struct lsquic_conn *lconn, 395 enum lsquic_hsk_status status) 396{ 397 struct ietf_mini_conn *conn = (struct ietf_mini_conn *) lconn; 398 399 switch (status) 400 { 401 case LSQ_HSK_OK: 402 case LSQ_HSK_0RTT_OK: 403 conn->imc_flags |= IMC_HSK_OK; 404 conn->imc_conn.cn_flags |= LSCONN_HANDSHAKE_DONE; 405 LSQ_DEBUG("handshake OK"); 406 break; 407 default: 408 assert(0); 409 /* fall-through */ 410 case LSQ_HSK_FAIL: 411 conn->imc_flags |= IMC_HSK_FAILED|IMC_ERROR; 412 LSQ_INFO("handshake failed"); 413 break; 414 } 415} 416 417 418static void 419ietf_mini_conn_ci_tls_alert (struct lsquic_conn *lconn, uint8_t alert) 420{ 421 struct ietf_mini_conn *conn = (struct ietf_mini_conn *) lconn; 422 LSQ_DEBUG("got TLS alert %"PRIu8, alert); 423 conn->imc_flags |= IMC_ERROR|IMC_TLS_ALERT; 424 conn->imc_tls_alert = alert; 425} 426 427 428static int 429ietf_mini_conn_ci_is_tickable (struct lsquic_conn *lconn) 430{ 431 /* A mini connection is never tickable: Either there are incoming 432 * packets, in which case, the connection is going to be ticked, or 433 * there is an alarm pending, in which case it will be handled via 434 * the attq. 435 */ 436 return 0; 437} 438 439 440static int 441imico_can_send (const struct ietf_mini_conn *conn, size_t size) 442{ 443 return (conn->imc_flags & IMC_ADDR_VALIDATED) 444 || conn->imc_bytes_in * 3 >= conn->imc_bytes_out + size 445 ; 446} 447 448 449static struct lsquic_packet_out * 450ietf_mini_conn_ci_next_packet_to_send (struct lsquic_conn *lconn, size_t size) 451{ 452 struct ietf_mini_conn *conn = (struct ietf_mini_conn *) lconn; 453 struct lsquic_packet_out *packet_out; 454 size_t packet_size; 455 456 TAILQ_FOREACH(packet_out, &conn->imc_packets_out, po_next) 457 { 458 if (packet_out->po_flags & PO_SENT) 459 continue; 460 packet_size = lsquic_packet_out_total_sz(lconn, packet_out); 461 if (size == 0 || packet_size + size <= conn->imc_path.np_pack_size) 462 { 463 if (!imico_can_send(conn, packet_size + IQUIC_TAG_LEN)) 464 { 465 LSQ_DEBUG("cannot send packet %"PRIu64" of size %zu: client " 466 "address has not been validated", packet_out->po_packno, 467 packet_size + IQUIC_TAG_LEN); 468 return NULL; 469 } 470 packet_out->po_flags |= PO_SENT; 471 conn->imc_bytes_out += packet_size + IQUIC_TAG_LEN; 472 if (size == 0) 473 LSQ_DEBUG("packet_to_send: %"PRIu64, packet_out->po_packno); 474 else 475 LSQ_DEBUG("packet_to_send: %"PRIu64" (coalesced)", 476 packet_out->po_packno); 477 return packet_out; 478 } 479 else 480 return NULL; 481 } 482 483 return NULL; 484} 485 486 487static int 488imico_calc_retx_timeout (const struct ietf_mini_conn *conn) 489{ 490 lsquic_time_t to; 491 to = lsquic_rtt_stats_get_srtt(&conn->imc_rtt_stats); 492 if (to) 493 { 494 to += to / 2; 495 if (to < 10000) 496 to = 10000; 497 } 498 else 499 to = 300000; 500 return to << conn->imc_hsk_count; 501} 502 503 504static lsquic_time_t 505ietf_mini_conn_ci_next_tick_time (struct lsquic_conn *lconn) 506{ 507 struct ietf_mini_conn *conn = (struct ietf_mini_conn *) lconn; 508 const struct lsquic_packet_out *packet_out; 509 lsquic_time_t exp_time, retx_time; 510 511 exp_time = conn->imc_created + 512 conn->imc_enpub->enp_settings.es_handshake_to; 513 514 TAILQ_FOREACH(packet_out, &conn->imc_packets_out, po_next) 515 if (packet_out->po_flags & PO_SENT) 516 { 517 retx_time = packet_out->po_sent + imico_calc_retx_timeout(conn); 518 if (retx_time < exp_time) 519 return retx_time; 520 else 521 return exp_time; 522 } 523 524 return exp_time; 525} 526 527 528#define IMICO_PROC_FRAME_ARGS \ 529 struct ietf_mini_conn *conn, struct lsquic_packet_in *packet_in, \ 530 const unsigned char *p, size_t len 531 532 533static void 534imico_dispatch_stream_events (struct ietf_mini_conn *conn) 535{ 536 enum enc_level i; 537 538 for (i = 0; i < N_ENC_LEVS; ++i) 539 if ((conn->imc_streams[i].mcs_flags & (MCS_CREATED|MCS_WANTREAD)) 540 == (MCS_CREATED|MCS_WANTREAD)) 541 { 542 LSQ_DEBUG("dispatch read events on level #%u", i); 543 lsquic_mini_cry_sm_if.on_read((void *) &conn->imc_streams[i], 544 conn->imc_conn.cn_enc_session); 545 } 546 547 for (i = 0; i < N_ENC_LEVS; ++i) 548 if ((conn->imc_streams[i].mcs_flags & (MCS_CREATED|MCS_WANTWRITE)) 549 == (MCS_CREATED|MCS_WANTWRITE)) 550 { 551 LSQ_DEBUG("dispatch write events on level #%u", i); 552 lsquic_mini_cry_sm_if.on_write((void *) &conn->imc_streams[i], 553 conn->imc_conn.cn_enc_session); 554 } 555} 556 557 558static unsigned 559imico_process_stream_frame (IMICO_PROC_FRAME_ARGS) 560{ 561 LSQ_WARN("%s: TODO", __func__); 562 return 0; 563} 564 565 566static unsigned 567imico_process_crypto_frame (IMICO_PROC_FRAME_ARGS) 568{ 569 int parsed_len; 570 enum enc_level enc_level, i; 571 struct stream_frame stream_frame; 572 const struct transport_params *params; 573 574 parsed_len = conn->imc_conn.cn_pf->pf_parse_crypto_frame(p, len, 575 &stream_frame); 576 if (parsed_len < 0) 577 return 0; 578 579 enc_level = lsquic_packet_in_enc_level(packet_in); 580 EV_LOG_CRYPTO_FRAME_IN(LSQUIC_LOG_CONN_ID, &stream_frame, enc_level); 581 582 if (!(conn->imc_streams[enc_level].mcs_flags & MCS_CREATED) 583 || conn->imc_streams[enc_level].mcs_read_off < 584 stream_frame.data_frame.df_offset 585 + stream_frame.data_frame.df_size) 586 LSQ_DEBUG("Got CRYPTO frame for enc level #%u", enc_level); 587 else 588 { 589 LSQ_DEBUG("Got duplicate CRYPTO frame for enc level #%u -- ignore", 590 enc_level); 591 return parsed_len; 592 } 593 594 if (!(conn->imc_flags & IMC_ENC_SESS_INITED)) 595 { 596 if (0 != conn->imc_conn.cn_esf.i->esfi_init_server( 597 conn->imc_conn.cn_enc_session)) 598 return -1; 599 conn->imc_flags |= IMC_ENC_SESS_INITED; 600 } 601 602 if (!(conn->imc_streams[enc_level].mcs_flags & MCS_CREATED)) 603 { 604 LSQ_DEBUG("creating stream on level #%u", enc_level); 605 conn->imc_streams[enc_level].mcs_flags |= MCS_CREATED; 606 lsquic_mini_cry_sm_if.on_new_stream(conn->imc_conn.cn_enc_session, 607 (void *) &conn->imc_streams[enc_level]); 608 } 609 610 /* Assume that receiving a CRYPTO frame at a higher level means that we 611 * no longer want to read from a lower level. 612 */ 613 for (i = 0; i < enc_level; ++i) 614 conn->imc_streams[i].mcs_flags &= ~MCS_WANTREAD; 615 616 conn->imc_last_in.frame = &stream_frame; 617 conn->imc_last_in.enc_level = enc_level; 618 imico_dispatch_stream_events(conn); 619 conn->imc_last_in.frame = NULL; 620 621 622 if (enc_level == ENC_LEV_CLEAR && stream_frame.data_frame.df_offset == 0 623 /* Assume that we have ClientHello at offset zero and that it has 624 * transport parameters. 625 */ 626 && (conn->imc_flags & (IMC_ENC_SESS_INITED|IMC_HAVE_TP)) 627 == IMC_ENC_SESS_INITED) 628 { 629 params = conn->imc_conn.cn_esf.i->esfi_get_peer_transport_params( 630 conn->imc_conn.cn_enc_session); 631 if (params) 632 { 633 conn->imc_flags |= IMC_HAVE_TP; 634 conn->imc_ack_exp = params->tp_ack_delay_exponent; 635 } 636 else 637 { 638 conn->imc_flags |= IMC_BAD_TRANS_PARAMS; 639 return 0; 640 } 641 } 642 643 return parsed_len; 644} 645 646 647static ptrdiff_t 648imico_count_zero_bytes (const unsigned char *p, size_t len) 649{ 650 const unsigned char *const end = p + len; 651 while (p < end && 0 == *p) 652 ++p; 653 return len - (end - p); 654} 655 656 657static unsigned 658imico_process_padding_frame (IMICO_PROC_FRAME_ARGS) 659{ 660 len = (size_t) imico_count_zero_bytes(p, len); 661 EV_LOG_PADDING_FRAME_IN(LSQUIC_LOG_CONN_ID, len); 662 return len; 663} 664 665 666static void 667imico_take_rtt_sample (struct ietf_mini_conn *conn, 668 const struct lsquic_packet_out *packet_out, 669 lsquic_time_t now, lsquic_time_t lack_delta) 670{ 671 assert(packet_out->po_sent); 672 lsquic_time_t measured_rtt = now - packet_out->po_sent; 673 if (lack_delta < measured_rtt) 674 { 675 lsquic_rtt_stats_update(&conn->imc_rtt_stats, measured_rtt, lack_delta); 676 LSQ_DEBUG("srtt: %"PRIu64" usec, var: %"PRIu64, 677 lsquic_rtt_stats_get_srtt(&conn->imc_rtt_stats), 678 lsquic_rtt_stats_get_rttvar(&conn->imc_rtt_stats)); 679 } 680} 681 682 683static unsigned 684imico_process_ack_frame (IMICO_PROC_FRAME_ARGS) 685{ 686 int parsed_len; 687 unsigned n; 688 lsquic_packet_out_t *packet_out, *next; 689 struct ack_info *acki; 690 lsquic_packno_t packno; 691 lsquic_time_t warn_time; 692 packno_set_t acked; 693 enum packnum_space pns; 694 uint8_t ack_exp; 695 696 if (conn->imc_flags & IMC_HAVE_TP) 697 ack_exp = conn->imc_ack_exp; 698 else 699 ack_exp = TP_DEF_ACK_DELAY_EXP; /* Odd: no transport params yet? */ 700 acki = conn->imc_enpub->enp_mm.acki; 701 parsed_len = conn->imc_conn.cn_pf->pf_parse_ack_frame(p, len, acki, 702 ack_exp); 703 if (parsed_len < 0) 704 return 0; 705 706 pns = lsquic_hety2pns[ packet_in->pi_header_type ]; 707 acked = 0; 708 709 for (n = 0; n < acki->n_ranges; ++n) 710 { 711 if (acki->ranges[n].high <= MAX_PACKETS) 712 { 713 acked |= (1ULL << acki->ranges[n].high) 714 | ((1ULL << acki->ranges[n].high) - 1); 715 acked &= ~((1ULL << acki->ranges[n].low) - 1); 716 } 717 else 718 { 719 packno = acki->ranges[n].high; 720 goto err_never_sent; 721 } 722 } 723 if (acked & ~conn->imc_sent_packnos) 724 { 725 packno = highest_bit_set(acked & ~conn->imc_sent_packnos); 726 goto err_never_sent; 727 } 728 729 EV_LOG_ACK_FRAME_IN(LSQUIC_LOG_CONN_ID, acki); 730 for (packet_out = TAILQ_FIRST(&conn->imc_packets_out); packet_out; 731 packet_out = next) 732 { 733 next = TAILQ_NEXT(packet_out, po_next); 734 if ((1ULL << packet_out->po_packno) & acked) 735 { 736 assert(lsquic_packet_out_pns(packet_out) == pns); 737 LSQ_DEBUG("Got ACK for packet %"PRIu64, packet_out->po_packno); 738 if (packet_out->po_packno == largest_acked(acki)) 739 imico_take_rtt_sample(conn, packet_out, 740 packet_in->pi_received, acki->lack_delta); 741 TAILQ_REMOVE(&conn->imc_packets_out, packet_out, po_next); 742 imico_destroy_packet(conn, packet_out); 743 } 744 } 745 746 if (conn->imc_sent_packnos & ~conn->imc_acked_packnos[pns] & acked) 747 { 748 LSQ_DEBUG("Newly acked packets, reset handshake count"); 749 conn->imc_hsk_count = 0; 750 } 751 752 conn->imc_acked_packnos[pns] |= acked; 753 754 return parsed_len; 755 756 err_never_sent: 757 warn_time = lsquic_time_now(); 758 if (0 == conn->imc_enpub->enp_last_warning[WT_ACKPARSE_MINI] 759 || conn->imc_enpub->enp_last_warning[WT_ACKPARSE_MINI] 760 + WARNING_INTERVAL < warn_time) 761 { 762 conn->imc_enpub->enp_last_warning[WT_ACKPARSE_MINI] = warn_time; 763 LSQ_WARN("packet %"PRIu64" (pns: %u) was never sent", packno, pns); 764 } 765 else 766 LSQ_DEBUG("packet %"PRIu64" (pns: %u) was never sent", packno, pns); 767 return 0; 768} 769 770 771static unsigned 772imico_process_invalid_frame (IMICO_PROC_FRAME_ARGS) 773{ 774 LSQ_DEBUG("invalid frame %u (%s)", p[0], 775 frame_type_2_str[ conn->imc_conn.cn_pf->pf_parse_frame_type(p[0]) ]); 776 return 0; 777} 778 779 780static unsigned (*const imico_process_frames[N_QUIC_FRAMES]) 781 (IMICO_PROC_FRAME_ARGS) = 782{ 783 [QUIC_FRAME_PADDING] = imico_process_padding_frame, 784 [QUIC_FRAME_STREAM] = imico_process_stream_frame, 785 [QUIC_FRAME_CRYPTO] = imico_process_crypto_frame, 786 [QUIC_FRAME_ACK] = imico_process_ack_frame, 787 /* XXX: Some of them are invalid, while others are unexpected. We treat 788 * them the same: handshake cannot proceed. 789 */ 790 [QUIC_FRAME_RST_STREAM] = imico_process_invalid_frame, 791 [QUIC_FRAME_CONNECTION_CLOSE] = imico_process_invalid_frame, 792 [QUIC_FRAME_MAX_DATA] = imico_process_invalid_frame, 793 [QUIC_FRAME_MAX_STREAM_DATA] = imico_process_invalid_frame, 794 [QUIC_FRAME_MAX_STREAMS] = imico_process_invalid_frame, 795 [QUIC_FRAME_PING] = imico_process_invalid_frame, 796 [QUIC_FRAME_BLOCKED] = imico_process_invalid_frame, 797 [QUIC_FRAME_STREAM_BLOCKED] = imico_process_invalid_frame, 798 [QUIC_FRAME_STREAMS_BLOCKED] = imico_process_invalid_frame, 799 [QUIC_FRAME_NEW_CONNECTION_ID] = imico_process_invalid_frame, 800 [QUIC_FRAME_STOP_SENDING] = imico_process_invalid_frame, 801 [QUIC_FRAME_PATH_CHALLENGE] = imico_process_invalid_frame, 802 [QUIC_FRAME_PATH_RESPONSE] = imico_process_invalid_frame, 803}; 804 805 806static unsigned 807imico_process_packet_frame (struct ietf_mini_conn *conn, 808 struct lsquic_packet_in *packet_in, const unsigned char *p, size_t len) 809{ 810 enum enc_level enc_level = lsquic_packet_in_enc_level(packet_in); 811 enum quic_frame_type type = conn->imc_conn.cn_pf->pf_parse_frame_type(p[0]); 812 if (lsquic_legal_frames_by_level[enc_level] & (1 << type)) 813 { 814 packet_in->pi_frame_types |= 1 << type; 815 return imico_process_frames[type](conn, packet_in, p, len); 816 } 817 else 818 { 819 LSQ_DEBUG("invalid frame %u at encryption level %s", type, 820 lsquic_enclev2str[enc_level]); 821 return 0; 822 } 823} 824 825 826static int 827imico_parse_regular_packet (struct ietf_mini_conn *conn, 828 struct lsquic_packet_in *packet_in) 829{ 830 const unsigned char *p, *pend; 831 unsigned len; 832 833 p = packet_in->pi_data + packet_in->pi_header_sz; 834 pend = packet_in->pi_data + packet_in->pi_data_sz; 835 836 while (p < pend) 837 { 838 len = imico_process_packet_frame(conn, packet_in, p, pend - p); 839 if (len > 0) 840 p += len; 841 else 842 return -1; 843 } 844 845 return 0; 846} 847 848 849static unsigned 850highest_bit_set (unsigned long long sz) 851{ 852#if __GNUC__ 853 unsigned clz = __builtin_clzll(sz); 854 return 63 - clz; 855#else 856 unsigned long y; 857 unsigned n; 858 n = 64; 859 y = sz >> 32; if (y) { n -= 32; sz = y; } 860 y = sz >> 16; if (y) { n -= 16; sz = y; } 861 y = sz >> 8; if (y) { n -= 8; sz = y; } 862 y = sz >> 4; if (y) { n -= 4; sz = y; } 863 y = sz >> 2; if (y) { n -= 2; sz = y; } 864 y = sz >> 1; if (y) return 63 - n + 2; 865 return 63 - n + sz; 866#endif 867} 868 869 870static void 871ignore_init (struct ietf_mini_conn *conn) 872{ 873 struct lsquic_packet_out *packet_out, *next; 874 unsigned count; 875 876 conn->imc_flags |= IMC_IGNORE_INIT; 877 conn->imc_flags &= ~(IMC_QUEUED_ACK_INIT << PNS_INIT); 878 879 count = 0; 880 for (packet_out = TAILQ_FIRST(&conn->imc_packets_out); packet_out; 881 packet_out = next) 882 { 883 next = TAILQ_NEXT(packet_out, po_next); 884 if (PNS_INIT == lsquic_packet_out_pns(packet_out)) 885 { 886 TAILQ_REMOVE(&conn->imc_packets_out, packet_out, po_next); 887 imico_destroy_packet(conn, packet_out); 888 ++count; 889 } 890 } 891 892 LSQ_DEBUG("henceforth, no Initial packets shall be sent or received; " 893 "destroyed %u packet%.*s", count, count != 1, "s"); 894} 895 896 897/* Only a single packet is supported */ 898static void 899ietf_mini_conn_ci_packet_in (struct lsquic_conn *lconn, 900 struct lsquic_packet_in *packet_in) 901{ 902 struct ietf_mini_conn *conn = (struct ietf_mini_conn *) lconn; 903 enum dec_packin dec_packin; 904 enum packnum_space pns; 905 906 907 pns = lsquic_hety2pns[ packet_in->pi_header_type ]; 908 if (pns == PNS_INIT && (conn->imc_flags & IMC_IGNORE_INIT)) 909 { 910 LSQ_DEBUG("ignore init packet"); /* Don't bother decrypting */ 911 return; 912 } 913 914 dec_packin = lconn->cn_esf_c->esf_decrypt_packet(lconn->cn_enc_session, 915 conn->imc_enpub, lconn, packet_in); 916 if (dec_packin != DECPI_OK) 917 { 918 /* TODO: handle reordering perhaps? */ 919 LSQ_DEBUG("could not decrypt packet"); 920 return; 921 } 922 923 EV_LOG_PACKET_IN(LSQUIC_LOG_CONN_ID, packet_in); 924 conn->imc_bytes_in += packet_in->pi_data_sz + IQUIC_TAG_LEN; 925 926 if (pns == PNS_APP) 927 { 928 lsquic_packet_in_upref(packet_in); 929 TAILQ_INSERT_TAIL(&conn->imc_app_packets, packet_in, pi_next); 930 LSQ_DEBUG("delay processing of packet %"PRIu64" in pns %u", 931 packet_in->pi_packno, pns); 932 return; 933 } 934 else if (pns == PNS_HSK) 935 conn->imc_flags |= IMC_ADDR_VALIDATED; 936 937 if (((conn->imc_flags >> IMCBIT_PNS_BIT_SHIFT) & 3) < pns) 938 { 939 conn->imc_flags &= ~(3 << IMCBIT_PNS_BIT_SHIFT); 940 conn->imc_flags |= pns << IMCBIT_PNS_BIT_SHIFT; 941 } 942 943 if (pns == PNS_HSK && !(conn->imc_flags & IMC_IGNORE_INIT)) 944 ignore_init(conn); 945 946 if (conn->imc_recvd_packnos[pns] & (1ULL << packet_in->pi_packno)) 947 { 948 LSQ_DEBUG("duplicate packet %"PRIu64, packet_in->pi_packno); 949 return; 950 } 951 952 /* Update receive history before processing the packet: if there is an 953 * error, the connection is terminated and recording this packet number 954 * is helpful when it is printed along with other diagnostics in dtor. 955 */ 956 if (0 == conn->imc_recvd_packnos[pns] || 957 packet_in->pi_packno > highest_bit_set(conn->imc_recvd_packnos[pns])) 958 conn->imc_largest_recvd[pns] = packet_in->pi_received; 959 conn->imc_recvd_packnos[pns] |= 1ULL << packet_in->pi_packno; 960 conn->imc_flags |= IMC_QUEUED_ACK_INIT << pns; 961 962 if (0 != imico_parse_regular_packet(conn, packet_in)) 963 conn->imc_flags |= IMC_ERROR; 964 965 ++conn->imc_ecn_counts_in[pns][ lsquic_packet_in_ecn(packet_in) ]; 966 conn->imc_incoming_ecn <<= 1; 967 conn->imc_incoming_ecn |= lsquic_packet_in_ecn(packet_in) != ECN_NOT_ECT; 968} 969 970 971static void 972ietf_mini_conn_ci_packet_sent (struct lsquic_conn *lconn, 973 struct lsquic_packet_out *packet_out) 974{ 975 struct ietf_mini_conn *conn = (struct ietf_mini_conn *) lconn; 976 conn->imc_sent_packnos |= 1ULL << packet_out->po_packno; 977#if 0 978 if (packet_out->po_frame_types & (1 << QUIC_FRAME_ACK)) 979 { 980 assert(mc->mc_flags & MC_UNSENT_ACK); 981 mc->mc_flags &= ~MC_UNSENT_ACK; 982 } 983#endif 984 ++conn->imc_ecn_counts_out[ lsquic_packet_out_pns(packet_out) ] 985 [ lsquic_packet_out_ecn(packet_out) ]; 986 LSQ_DEBUG("%s: packet %"PRIu64" sent", __func__, packet_out->po_packno); 987} 988 989 990static void 991ietf_mini_conn_ci_packet_not_sent (struct lsquic_conn *lconn, 992 struct lsquic_packet_out *packet_out) 993{ 994 struct ietf_mini_conn *conn = (struct ietf_mini_conn *) lconn; 995 size_t packet_size; 996 997 packet_out->po_flags &= ~PO_SENT; 998 packet_size = lsquic_packet_out_total_sz(lconn, packet_out); 999 conn->imc_bytes_out -= packet_size + IQUIC_TAG_LEN; 1000 LSQ_DEBUG("%s: packet %"PRIu64" not sent", __func__, packet_out->po_packno); 1001} 1002 1003 1004static void 1005imico_return_enc_data (struct ietf_mini_conn *conn, 1006 struct lsquic_packet_out *packet_out) 1007{ 1008 conn->imc_enpub->enp_pmi->pmi_return(conn->imc_enpub->enp_pmi_ctx, 1009 conn->imc_path.np_peer_ctx, packet_out->po_enc_data, 1010 lsquic_packet_out_ipv6(packet_out)); 1011 packet_out->po_flags &= ~PO_ENCRYPTED; 1012 packet_out->po_enc_data = NULL; 1013} 1014 1015 1016static int 1017imico_repackage_packet (struct ietf_mini_conn *conn, 1018 struct lsquic_packet_out *packet_out) 1019{ 1020 const lsquic_packno_t oldno = packet_out->po_packno; 1021 const lsquic_packno_t packno = conn->imc_next_packno++; 1022 if (packno > MAX_PACKETS) 1023 return -1; 1024 1025 LSQ_DEBUG("Packet %"PRIu64" repackaged for resending as packet %"PRIu64, 1026 oldno, packno); 1027 EV_LOG_CONN_EVENT(LSQUIC_LOG_CONN_ID, "packet %"PRIu64" repackaged for " 1028 "resending as packet %"PRIu64, oldno, packno); 1029 packet_out->po_packno = packno; 1030 packet_out->po_flags &= ~PO_SENT; 1031 if (packet_out->po_flags & PO_ENCRYPTED) 1032 imico_return_enc_data(conn, packet_out); 1033 TAILQ_INSERT_TAIL(&conn->imc_packets_out, packet_out, po_next); 1034 return 0; 1035} 1036 1037 1038static int 1039imico_handle_losses_and_have_unsent (struct ietf_mini_conn *conn, 1040 lsquic_time_t now) 1041{ 1042 TAILQ_HEAD(, lsquic_packet_out) lost_packets = 1043 TAILQ_HEAD_INITIALIZER(lost_packets); 1044 lsquic_packet_out_t *packet_out, *next; 1045 lsquic_time_t retx_to = 0; 1046 unsigned n_to_send = 0; 1047 1048 for (packet_out = TAILQ_FIRST(&conn->imc_packets_out); packet_out; 1049 packet_out = next) 1050 { 1051 next = TAILQ_NEXT(packet_out, po_next); 1052 if (packet_out->po_flags & PO_SENT) 1053 { 1054 if (0 == retx_to) 1055 retx_to = imico_calc_retx_timeout(conn); 1056 if (packet_out->po_sent + retx_to < now) 1057 { 1058 LSQ_DEBUG("packet %"PRIu64" has been lost (rto: %"PRIu64")", 1059 packet_out->po_packno, retx_to); 1060 TAILQ_REMOVE(&conn->imc_packets_out, packet_out, po_next); 1061 TAILQ_INSERT_TAIL(&lost_packets, packet_out, po_next); 1062 } 1063 } 1064 else 1065 ++n_to_send; 1066 } 1067 1068 conn->imc_hsk_count += !TAILQ_EMPTY(&lost_packets); 1069 1070 while ((packet_out = TAILQ_FIRST(&lost_packets))) 1071 { 1072 TAILQ_REMOVE(&lost_packets, packet_out, po_next); 1073 if ((packet_out->po_frame_types & IQUIC_FRAME_RETX_MASK) 1074 && 0 == imico_repackage_packet(conn, packet_out)) 1075 ++n_to_send; 1076 else 1077 imico_destroy_packet(conn, packet_out); 1078 } 1079 1080 return n_to_send > 0; 1081} 1082 1083 1084static int 1085imico_have_packets_to_send (struct ietf_mini_conn *conn, lsquic_time_t now) 1086{ 1087 return imico_handle_losses_and_have_unsent(conn, now); 1088} 1089 1090 1091struct ietf_mini_rechist 1092{ 1093 const struct ietf_mini_conn *conn; 1094 packno_set_t cur_set; 1095 struct lsquic_packno_range range; /* We return a pointer to this */ 1096 int cur_idx; 1097 enum packnum_space pns; 1098}; 1099 1100 1101static void 1102imico_rechist_init (struct ietf_mini_rechist *rechist, 1103 const struct ietf_mini_conn *conn, enum packnum_space pns) 1104{ 1105 rechist->conn = conn; 1106 rechist->pns = pns; 1107 rechist->cur_set = 0; 1108 rechist->cur_idx = 0; 1109} 1110 1111 1112static lsquic_time_t 1113imico_rechist_largest_recv (void *rechist_ctx) 1114{ 1115 struct ietf_mini_rechist *rechist = rechist_ctx; 1116 return rechist->conn->imc_largest_recvd[ rechist->pns ]; 1117} 1118 1119 1120static const struct lsquic_packno_range * 1121imico_rechist_next (void *rechist_ctx) 1122{ 1123 struct ietf_mini_rechist *rechist = rechist_ctx; 1124 const struct ietf_mini_conn *conn = rechist->conn; 1125 packno_set_t packnos; 1126 int i; 1127 1128 packnos = rechist->cur_set; 1129 if (0 == packnos) 1130 return NULL; 1131 1132 /* There may be a faster way to do this, but for now, we just want 1133 * correctness. 1134 */ 1135 for (i = rechist->cur_idx; i >= 0; --i) 1136 if (packnos & (1ULL << i)) 1137 { 1138 rechist->range.low = i; 1139 rechist->range.high = i; 1140 break; 1141 } 1142 assert(i >= 0); /* We must have hit at least one bit */ 1143 --i; 1144 for ( ; i >= 0 && (packnos & (1ULL << i)); --i) 1145 rechist->range.low = i; 1146 if (i >= 0) 1147 { 1148 rechist->cur_set = packnos & ((1ULL << i) - 1); 1149 rechist->cur_idx = i; 1150 } 1151 else 1152 rechist->cur_set = 0; 1153 LSQ_DEBUG("%s: return [%"PRIu64", %"PRIu64"]", __func__, 1154 rechist->range.low, rechist->range.high); 1155 return &rechist->range; 1156} 1157 1158 1159static const struct lsquic_packno_range * 1160imico_rechist_first (void *rechist_ctx) 1161{ 1162 struct ietf_mini_rechist *rechist = rechist_ctx; 1163 rechist->cur_set = rechist->conn->imc_recvd_packnos[ rechist->pns ]; 1164 rechist->cur_idx = highest_bit_set(rechist->cur_set); 1165 return imico_rechist_next(rechist_ctx); 1166} 1167 1168 1169static const enum header_type pns2hety[] = 1170{ 1171 [PNS_INIT] = HETY_INITIAL, 1172 [PNS_HSK] = HETY_HANDSHAKE, 1173 [PNS_APP] = HETY_NOT_SET, 1174}; 1175 1176 1177static int 1178imico_generate_ack (struct ietf_mini_conn *conn, enum packnum_space pns, 1179 lsquic_time_t now) 1180{ 1181 struct lsquic_packet_out *packet_out; 1182 enum header_type header_type; 1183 struct ietf_mini_rechist rechist; 1184 int not_used_has_missing, len; 1185 uint64_t ecn_counts_buf[4]; 1186 const uint64_t *ecn_counts; 1187 1188 header_type = pns2hety[pns]; 1189 1190 if (conn->imc_incoming_ecn) 1191 { 1192 ecn_counts_buf[0] = conn->imc_ecn_counts_in[pns][0]; 1193 ecn_counts_buf[1] = conn->imc_ecn_counts_in[pns][1]; 1194 ecn_counts_buf[2] = conn->imc_ecn_counts_in[pns][2]; 1195 ecn_counts_buf[3] = conn->imc_ecn_counts_in[pns][3]; 1196 ecn_counts = ecn_counts_buf; 1197 } 1198 else 1199 ecn_counts = NULL; 1200 1201 packet_out = imico_get_packet_out(conn, header_type, 0); 1202 if (!packet_out) 1203 return -1; 1204 1205 /* Generate ACK frame */ 1206 imico_rechist_init(&rechist, conn, pns); 1207 len = conn->imc_conn.cn_pf->pf_gen_ack_frame( 1208 packet_out->po_data + packet_out->po_data_sz, 1209 lsquic_packet_out_avail(packet_out), imico_rechist_first, 1210 imico_rechist_next, imico_rechist_largest_recv, &rechist, 1211 now, ¬_used_has_missing, &packet_out->po_ack2ed, ecn_counts); 1212 if (len < 0) 1213 { 1214 LSQ_WARN("could not generate ACK frame"); 1215 return -1; 1216 } 1217 EV_LOG_GENERATED_ACK_FRAME(LSQUIC_LOG_CONN_ID, conn->imc_conn.cn_pf, 1218 packet_out->po_data + packet_out->po_data_sz, len); 1219 packet_out->po_frame_types |= 1 << QUIC_FRAME_ACK; 1220 packet_out->po_data_sz += len; 1221 packet_out->po_regen_sz += len; 1222 conn->imc_flags &= ~(IMC_QUEUED_ACK_INIT << pns); 1223 LSQ_DEBUG("wrote ACK frame of size %d", len); 1224 return 0; 1225} 1226 1227 1228static int 1229imico_generate_acks (struct ietf_mini_conn *conn, lsquic_time_t now) 1230{ 1231 enum packnum_space pns; 1232 1233 for (pns = PNS_INIT; pns < N_PNS; ++pns) 1234 if (conn->imc_flags & (IMC_QUEUED_ACK_INIT << pns) 1235 && !(pns == PNS_INIT && (conn->imc_flags & IMC_IGNORE_INIT))) 1236 if (0 != imico_generate_ack(conn, pns, now)) 1237 return -1; 1238 1239 return 0; 1240} 1241 1242 1243static void 1244imico_generate_conn_close (struct ietf_mini_conn *conn) 1245{ 1246 struct lsquic_packet_out *packet_out; 1247 enum header_type header_type; 1248 enum packnum_space pns; 1249 unsigned error_code; 1250 const char *reason; 1251 size_t need; 1252 int sz, rlen, is_app; 1253 char reason_buf[0x20]; 1254 1255 pns = (conn->imc_flags >> IMCBIT_PNS_BIT_SHIFT) & 3; 1256 header_type = pns2hety[pns]; 1257 need = 30; /* Guess */ /* TODO: calculate, don't guess */ 1258 packet_out = imico_get_packet_out(conn, header_type, need); 1259 if (!packet_out) 1260 return; 1261 1262 if (conn->imc_flags & IMC_ABORT_ERROR) 1263 { 1264 is_app = !!(conn->imc_flags & IMC_ABORT_ISAPP); 1265 error_code = conn->imc_error_code; 1266 reason = NULL; 1267 rlen = 0; 1268 } 1269 else if (conn->imc_flags & IMC_TLS_ALERT) 1270 { 1271 is_app = 0; 1272 error_code = 0x100 + conn->imc_tls_alert; 1273 if (ALERT_NO_APPLICATION_PROTOCOL == conn->imc_tls_alert) 1274 reason = "no suitable application protocol"; 1275 else 1276 { 1277 snprintf(reason_buf, sizeof(reason_buf), "TLS alert %"PRIu8, 1278 conn->imc_tls_alert); 1279 reason = reason_buf; 1280 } 1281 rlen = strlen(reason); 1282 } 1283 else if (conn->imc_flags & IMC_BAD_TRANS_PARAMS) 1284 { 1285 is_app = 0; 1286 error_code = TEC_NO_ERROR; 1287 reason = "bad transport parameters"; 1288 rlen = 24; 1289 } 1290 else if (conn->imc_flags & IMC_HSK_FAILED) 1291 { 1292 is_app = 0; 1293 error_code = TEC_NO_ERROR; 1294 reason = "handshake failed"; 1295 rlen = 16; 1296 } 1297 else 1298 { 1299 is_app = 0; 1300 error_code = TEC_INTERNAL_ERROR; 1301 reason = NULL; 1302 rlen = 0; 1303 } 1304 1305 sz = conn->imc_conn.cn_pf->pf_gen_connect_close_frame( 1306 packet_out->po_data + packet_out->po_data_sz, 1307 lsquic_packet_out_avail(packet_out), is_app, error_code, reason, 1308 rlen); 1309 if (sz >= 0) 1310 { 1311 packet_out->po_frame_types |= 1 << QUIC_FRAME_CONNECTION_CLOSE; 1312 packet_out->po_data_sz += sz; 1313 LSQ_DEBUG("generated CONNECTION_CLOSE frame"); 1314 } 1315 else 1316 LSQ_WARN("could not generate CONNECTION_CLOSE frame"); 1317} 1318 1319 1320static enum tick_st 1321ietf_mini_conn_ci_tick (struct lsquic_conn *lconn, lsquic_time_t now) 1322{ 1323 struct ietf_mini_conn *conn = (struct ietf_mini_conn *) lconn; 1324 enum tick_st tick; 1325 1326 if (conn->imc_created + conn->imc_enpub->enp_settings.es_handshake_to < now) 1327 { 1328 LSQ_DEBUG("connection expired: closing"); 1329 return TICK_CLOSE; 1330 } 1331 1332 if (conn->imc_flags & 1333 (IMC_QUEUED_ACK_INIT|IMC_QUEUED_ACK_HSK|IMC_QUEUED_ACK_APP)) 1334 { 1335 if (0 != imico_generate_acks(conn, now)) 1336 { 1337 conn->imc_flags |= IMC_ERROR; 1338 return TICK_CLOSE; 1339 } 1340 } 1341 1342 1343 tick = 0; 1344 1345 if (conn->imc_flags & IMC_ERROR) 1346 { 1347 imico_generate_conn_close(conn); 1348 tick |= TICK_CLOSE; 1349 } 1350 else if (conn->imc_flags & IMC_HSK_OK) 1351 tick |= TICK_PROMOTE; 1352 1353 if (imico_have_packets_to_send(conn, now)) 1354 tick |= TICK_SEND; 1355 else 1356 tick |= TICK_QUIET; 1357 1358 LSQ_DEBUG("Return TICK %d", tick); 1359 return tick; 1360} 1361 1362 1363static void 1364ietf_mini_conn_ci_internal_error (struct lsquic_conn *lconn, 1365 const char *format, ...) 1366{ 1367 struct ietf_mini_conn *conn = (struct ietf_mini_conn *) lconn; 1368 LSQ_INFO("internal error reported"); 1369 conn->imc_flags |= IMC_ERROR; 1370} 1371 1372 1373static void 1374ietf_mini_conn_ci_abort_error (struct lsquic_conn *lconn, int is_app, 1375 unsigned error_code, const char *fmt, ...) 1376{ 1377 struct ietf_mini_conn *conn = (struct ietf_mini_conn *) lconn; 1378 va_list ap; 1379 const char *err_str, *percent; 1380 char err_buf[0x100]; 1381 1382 percent = strchr(fmt, '%'); 1383 if (percent) 1384 { 1385 va_start(ap, fmt); 1386 vsnprintf(err_buf, sizeof(err_buf), fmt, ap); 1387 va_end(ap); 1388 err_str = err_buf; 1389 } 1390 else 1391 err_str = fmt; 1392 LSQ_INFO("abort error: is_app: %d; error code: %u; error str: %s", 1393 is_app, error_code, err_str); 1394 conn->imc_flags |= IMC_ERROR|IMC_ABORT_ERROR; 1395 if (is_app) 1396 conn->imc_flags |= IMC_ABORT_ISAPP; 1397 conn->imc_error_code = error_code; 1398} 1399 1400 1401static struct network_path * 1402ietf_mini_conn_ci_get_path (struct lsquic_conn *lconn, 1403 const struct sockaddr *sa) 1404{ 1405 struct ietf_mini_conn *conn = (struct ietf_mini_conn *) lconn; 1406 1407 return &conn->imc_path; 1408} 1409 1410 1411static const lsquic_cid_t * 1412ietf_mini_conn_ci_get_log_cid (const struct lsquic_conn *lconn) 1413{ 1414 struct ietf_mini_conn *conn = (struct ietf_mini_conn *) lconn; 1415 1416 if (conn->imc_path.np_dcid.len) 1417 return &conn->imc_path.np_dcid; 1418 else 1419 return CN_SCID(lconn); 1420} 1421 1422 1423static unsigned char 1424ietf_mini_conn_ci_record_addrs (struct lsquic_conn *lconn, void *peer_ctx, 1425 const struct sockaddr *local_sa, const struct sockaddr *peer_sa) 1426{ 1427 struct ietf_mini_conn *conn = (struct ietf_mini_conn *) lconn; 1428 struct lsquic_packet_out *packet_out; 1429 1430 if (NP_IS_IPv6(&conn->imc_path) != (AF_INET6 == peer_sa->sa_family)) 1431 TAILQ_FOREACH(packet_out, &conn->imc_packets_out, po_next) 1432 if ((packet_out->po_flags & (PO_SENT|PO_ENCRYPTED)) == PO_ENCRYPTED) 1433 imico_return_enc_data(conn, packet_out); 1434 1435 memcpy(conn->imc_path.np_peer_addr, peer_sa, 1436 sizeof(conn->imc_path.np_peer_addr)); 1437 memcpy(conn->imc_path.np_local_addr, local_sa, 1438 sizeof(conn->imc_path.np_local_addr)); 1439 conn->imc_path.np_peer_ctx = peer_ctx; 1440 return 0; 1441} 1442 1443 1444static const struct conn_iface mini_conn_ietf_iface = { 1445 .ci_abort_error = ietf_mini_conn_ci_abort_error, 1446 .ci_client_call_on_new = ietf_mini_conn_ci_client_call_on_new, 1447 .ci_destroy = ietf_mini_conn_ci_destroy, 1448 .ci_get_engine = ietf_mini_conn_ci_get_engine, 1449 .ci_get_log_cid = ietf_mini_conn_ci_get_log_cid, 1450 .ci_get_path = ietf_mini_conn_ci_get_path, 1451 .ci_hsk_done = ietf_mini_conn_ci_hsk_done, 1452 .ci_internal_error = ietf_mini_conn_ci_internal_error, 1453 .ci_is_tickable = ietf_mini_conn_ci_is_tickable, 1454 .ci_next_packet_to_send = ietf_mini_conn_ci_next_packet_to_send, 1455 .ci_next_tick_time = ietf_mini_conn_ci_next_tick_time, 1456 .ci_packet_in = ietf_mini_conn_ci_packet_in, 1457 .ci_packet_not_sent = ietf_mini_conn_ci_packet_not_sent, 1458 .ci_packet_sent = ietf_mini_conn_ci_packet_sent, 1459 .ci_record_addrs = ietf_mini_conn_ci_record_addrs, 1460 .ci_tick = ietf_mini_conn_ci_tick, 1461 .ci_tls_alert = ietf_mini_conn_ci_tls_alert, 1462}; 1463