1a74702c6SGeorge Wang/* Copyright (c) 2017 - 2022 LiteSpeed Technologies Inc.  See LICENSE. */
25392f7a3SLiteSpeed Tech/*
35392f7a3SLiteSpeed Tech * lsquic_mini_conn.h -- Mini-connection
45392f7a3SLiteSpeed Tech *
55392f7a3SLiteSpeed Tech * Before a connection is established, the server keeps a "mini" connection
65392f7a3SLiteSpeed Tech * object where it keeps track of stream 1 offsets and so on.
75392f7a3SLiteSpeed Tech */
85392f7a3SLiteSpeed Tech
95392f7a3SLiteSpeed Tech#ifndef LSQUIC_MINI_CONN_H
105392f7a3SLiteSpeed Tech#define LSQUIC_MINI_CONN_H
115392f7a3SLiteSpeed Tech
125392f7a3SLiteSpeed Tech#include <stdint.h>
135392f7a3SLiteSpeed Tech#include <sys/queue.h>
145392f7a3SLiteSpeed Tech
155392f7a3SLiteSpeed Tech#define MAX_MINI_CONN_LIFESPAN_IN_USEC \
165392f7a3SLiteSpeed Tech    ((1 << (sizeof(((struct mini_conn *) 0)->mc_largest_recv) * 8)) - 1)
175392f7a3SLiteSpeed Tech
185392f7a3SLiteSpeed Techstruct lsquic_packet_in;
195392f7a3SLiteSpeed Techstruct lsquic_packet_out;
205392f7a3SLiteSpeed Techstruct lsquic_engine_public;
215392f7a3SLiteSpeed Tech
225392f7a3SLiteSpeed Tech#ifndef LSQUIC_KEEP_MINICONN_HISTORY
232f2f4363SDmitri Tikhonov#   if !defined(NDEBUG) && !defined(_MSC_VER)
2449f1f4f6SDmitri Tikhonov#       define LSQUIC_KEEP_MINICONN_HISTORY 1
255392f7a3SLiteSpeed Tech#   else
265392f7a3SLiteSpeed Tech#       define LSQUIC_KEEP_MINICONN_HISTORY 0
275392f7a3SLiteSpeed Tech#   endif
285392f7a3SLiteSpeed Tech#endif
295392f7a3SLiteSpeed Tech
305392f7a3SLiteSpeed Tech#if LSQUIC_KEEP_MINICONN_HISTORY
315392f7a3SLiteSpeed Tech
325392f7a3SLiteSpeed Tech#define MCHIST_BITS 4
335392f7a3SLiteSpeed Tech#define MCHIST_MASK ((1 << MCHIST_BITS) - 1)
345392f7a3SLiteSpeed Techtypedef unsigned char mchist_idx_t;
355392f7a3SLiteSpeed Tech
365392f7a3SLiteSpeed Techenum miniconn_history_event
375392f7a3SLiteSpeed Tech{
385392f7a3SLiteSpeed Tech    MCHE_EMPTY              =  '\0',
395392f7a3SLiteSpeed Tech    MCHE_PLUS               =  '+',
405392f7a3SLiteSpeed Tech    MCHE_HANDLE_1RTT        =  '1',
4149f1f4f6SDmitri Tikhonov    MCHE_HANDLE_SREJ        =  '2',
425392f7a3SLiteSpeed Tech    MCHE_PACKET2LARGE_IN    =  'a',
435392f7a3SLiteSpeed Tech    MCHE_CONN_CLOSE         =  'c',
445392f7a3SLiteSpeed Tech    MCHE_CREATED            =  'C',
455392f7a3SLiteSpeed Tech    MCHE_2HSK_1STREAM       =  'd',
465392f7a3SLiteSpeed Tech    MCHE_DUP_HSK            =  'D',
475392f7a3SLiteSpeed Tech    MCHE_HANDLE_ERROR       =  'e',
485392f7a3SLiteSpeed Tech    MCHE_EFRAME             =  'f',
495392f7a3SLiteSpeed Tech    MCHE_UNDECR_DEFER       =  'F',
505392f7a3SLiteSpeed Tech    MCHE_HANDLE_NOT_ENOUGH  =  'g',
515392f7a3SLiteSpeed Tech    MCHE_NEW_HSK            =  'H',
525392f7a3SLiteSpeed Tech    MCHE_INVALID_FRAME      =  'I',
535392f7a3SLiteSpeed Tech    MCHE_DECRYPTED          =  'K',
545392f7a3SLiteSpeed Tech    MCHE_PACKET_LOST        =  'L',
555392f7a3SLiteSpeed Tech    MCHE_HELLO_TOO_MUCH     =  'm',
565392f7a3SLiteSpeed Tech    MCHE_ENOMEM             =  'M',
575392f7a3SLiteSpeed Tech    MCHE_NEW_PACKET_OUT     =  'N',
585392f7a3SLiteSpeed Tech    MCHE_HELLO_HOLE         =  'o',
595392f7a3SLiteSpeed Tech    MCHE_PACKET_DUP_IN      =  'p',
605392f7a3SLiteSpeed Tech    MCHE_UNDECR_DROP        =  'P',
615392f7a3SLiteSpeed Tech    MCHE_PRST_IN            =  'R',
625392f7a3SLiteSpeed Tech    MCHE_HANDLE_SHLO        =  's',
635392f7a3SLiteSpeed Tech    MCHE_NEW_ENC_SESS       =  'S',
645392f7a3SLiteSpeed Tech    MCHE_PACKET_SENT        =  'T',
655392f7a3SLiteSpeed Tech    MCHE_HAHDLE_UNKNOWN     =  'u',
665392f7a3SLiteSpeed Tech    MCHE_UNSENT_ACKED       =  'U',
675392f7a3SLiteSpeed Tech    MCHE_HANDLE_DELAYED     =  'y',
685392f7a3SLiteSpeed Tech    MCHE_PACKET_DELAYED     =  'Y',
695392f7a3SLiteSpeed Tech    MCHE_PACKET0_IN         =  'z',
705392f7a3SLiteSpeed Tech    MCHE_OUT_OF_PACKNOS     =  '#',
715392f7a3SLiteSpeed Tech};
725392f7a3SLiteSpeed Tech
735392f7a3SLiteSpeed Tech#endif
745392f7a3SLiteSpeed Tech
755392f7a3SLiteSpeed Tech#ifndef LSQUIC_RECORD_INORD_HIST
765392f7a3SLiteSpeed Tech#   if __GNUC__
7749f1f4f6SDmitri Tikhonov#       define LSQUIC_RECORD_INORD_HIST 1
785392f7a3SLiteSpeed Tech#   else
795392f7a3SLiteSpeed Tech#       define LSQUIC_RECORD_INORD_HIST 0
805392f7a3SLiteSpeed Tech#   endif
815392f7a3SLiteSpeed Tech#endif
825392f7a3SLiteSpeed Tech
835392f7a3SLiteSpeed Techtypedef uint64_t mconn_packno_set_t;
845392f7a3SLiteSpeed Tech
855392f7a3SLiteSpeed Tech#define MINICONN_MAX_PACKETS (sizeof(mconn_packno_set_t) * 8)
865392f7a3SLiteSpeed Tech
875392f7a3SLiteSpeed TechTAILQ_HEAD(head_packet_in, lsquic_packet_in);
885392f7a3SLiteSpeed Tech
895392f7a3SLiteSpeed Techstruct mini_conn {
905392f7a3SLiteSpeed Tech    struct lsquic_conn     mc_conn;
915392f7a3SLiteSpeed Tech    struct conn_cid_elem   mc_cces[1];
925392f7a3SLiteSpeed Tech    struct head_packet_in  mc_deferred,
935392f7a3SLiteSpeed Tech                           mc_packets_in;
945392f7a3SLiteSpeed Tech    TAILQ_HEAD(, lsquic_packet_out)
955392f7a3SLiteSpeed Tech                           mc_packets_out;
965392f7a3SLiteSpeed Tech    struct lsquic_engine_public
975392f7a3SLiteSpeed Tech                          *mc_enpub;
985392f7a3SLiteSpeed Tech    lsquic_time_t          mc_created;
995392f7a3SLiteSpeed Tech    struct lsquic_rtt_stats
1005392f7a3SLiteSpeed Tech                           mc_rtt_stats;
1015392f7a3SLiteSpeed Tech    mconn_packno_set_t     mc_received_packnos,
1025392f7a3SLiteSpeed Tech                           mc_sent_packnos,
1035392f7a3SLiteSpeed Tech                           mc_deferred_packnos,                                 /* Informational */
1045392f7a3SLiteSpeed Tech                           mc_dropped_packnos,                                  /* Informational */
1055392f7a3SLiteSpeed Tech                           mc_lost_packnos, /* Packets that were deemed lost */ /* Informational */
1065392f7a3SLiteSpeed Tech                           mc_acked_packnos;
1075392f7a3SLiteSpeed Tech#if LSQUIC_RECORD_INORD_HIST
1085392f7a3SLiteSpeed Tech    unsigned long long     mc_inord_hist[2];                                    /* Informational */
1095392f7a3SLiteSpeed Tech#endif
1105392f7a3SLiteSpeed Tech    uint32_t               mc_error_code;   /* From CONNECTION_CLOSE frame */   /* Informational */
1115392f7a3SLiteSpeed Tech    unsigned short         mc_n_ticks;  /* Number of times mini conn ticked. */ /* Informational */
1125392f7a3SLiteSpeed Tech    unsigned short         mc_read_off, /* Read offset for stream 1 */
1135392f7a3SLiteSpeed Tech                           mc_write_off;/* Write offset for stream 1 */
1145392f7a3SLiteSpeed Tech    unsigned char          mc_max_ack_packno,
1155392f7a3SLiteSpeed Tech                           mc_cutoff,
1165392f7a3SLiteSpeed Tech                           mc_cur_packno;
1175392f7a3SLiteSpeed Tech    unsigned char          mc_hsk_count;
1187a8b2eceSDmitri Tikhonov#define MINI_CONN_MAX_DEFERRED 10
1197a8b2eceSDmitri Tikhonov    unsigned char          mc_n_deferred;
1205392f7a3SLiteSpeed Tech#if LSQUIC_RECORD_INORD_HIST
1215392f7a3SLiteSpeed Tech    unsigned char          mc_inord_idx;
1225392f7a3SLiteSpeed Tech#endif
1235392f7a3SLiteSpeed Tech    /* mc_largest_recv is the timestamp of when packet with the largest
1245392f7a3SLiteSpeed Tech     * number was received; it is necessary to generate ACK frames.  24
1255392f7a3SLiteSpeed Tech     * bits holds about 16.5 seconds worth of microseconds, which is
1265392f7a3SLiteSpeed Tech     * larger than the maximum amount of time a mini connection object
1275392f7a3SLiteSpeed Tech     * is allowed to live.  To get the timestamp, add this value to
1285392f7a3SLiteSpeed Tech     * mc_created.
1295392f7a3SLiteSpeed Tech     */
1305392f7a3SLiteSpeed Tech    unsigned char          mc_largest_recv[3];
1315392f7a3SLiteSpeed Tech    enum {
1325392f7a3SLiteSpeed Tech        MC_HAVE_NEW_HSK  = (1 << 0),
1335392f7a3SLiteSpeed Tech        MC_PROMOTE       = (1 << 1),
1345392f7a3SLiteSpeed Tech        MC_HAVE_SHLO     = (1 << 2),
1357a8b2eceSDmitri Tikhonov        MC_WR_OFF_RESET  = (1 << 3),
1365392f7a3SLiteSpeed Tech        MC_ERROR         = (1 << 4),
1375392f7a3SLiteSpeed Tech        MC_UNSENT_ACK    = (1 << 5),
1385392f7a3SLiteSpeed Tech        MC_GEN_ACK       = (1 << 6),
1395392f7a3SLiteSpeed Tech        MC_HSK_ERR       = (1 << 7),
1405392f7a3SLiteSpeed Tech        MC_OO_PACKNOS    = (1 << 8),
1415392f7a3SLiteSpeed Tech        MC_STOP_WAIT_ON  = (1 << 9),
1425392f7a3SLiteSpeed Tech    }                      mc_flags:16;
1435392f7a3SLiteSpeed Tech    struct network_path    mc_path;
1445392f7a3SLiteSpeed Tech#if LSQUIC_KEEP_MINICONN_HISTORY
1455392f7a3SLiteSpeed Tech    mchist_idx_t           mc_hist_idx;
1465392f7a3SLiteSpeed Tech    unsigned char          mc_hist_buf[1 << MCHIST_BITS];
1475392f7a3SLiteSpeed Tech#endif
1485392f7a3SLiteSpeed Tech};
1495392f7a3SLiteSpeed Tech
1505392f7a3SLiteSpeed Techlsquic_conn_t *
151a5fa05f9SDmitri Tikhonovlsquic_mini_conn_new (struct lsquic_engine_public *,
152a5fa05f9SDmitri Tikhonov            const struct lsquic_packet_in *, enum lsquic_version version);
1535392f7a3SLiteSpeed Tech
1545392f7a3SLiteSpeed Tech/* Packet numbers start with 1.  By subtracting 1, we can utilize the full
1555392f7a3SLiteSpeed Tech * length of the bitmask.
1565392f7a3SLiteSpeed Tech */
1575392f7a3SLiteSpeed Tech#define MCONN_PACKET_MASK(packno) (1ULL << (packno - 1))
1585392f7a3SLiteSpeed Tech
1595392f7a3SLiteSpeed Tech#endif
160