/* Copyright (c) 2017 - 2019 LiteSpeed Technologies Inc. See LICENSE. */ /* * lsquic_mini_conn.h -- Mini-connection * * Before a connection is established, the server keeps a "mini" connection * object where it keeps track of stream 1 offsets and so on. */ #ifndef LSQUIC_MINI_CONN_H #define LSQUIC_MINI_CONN_H #include #include #define MAX_MINI_CONN_LIFESPAN_IN_USEC \ ((1 << (sizeof(((struct mini_conn *) 0)->mc_largest_recv) * 8)) - 1) struct lsquic_packet_in; struct lsquic_packet_out; struct lsquic_engine_public; #ifndef LSQUIC_KEEP_MINICONN_HISTORY # ifndef NDEBUG # define LSQUIC_KEEP_MINICONN_HISTORY 0 /* XXX */ # else # define LSQUIC_KEEP_MINICONN_HISTORY 0 # endif #endif #if LSQUIC_KEEP_MINICONN_HISTORY #define MCHIST_BITS 4 #define MCHIST_MASK ((1 << MCHIST_BITS) - 1) typedef unsigned char mchist_idx_t; enum miniconn_history_event { MCHE_EMPTY = '\0', MCHE_PLUS = '+', MCHE_HANDLE_1RTT = '1', MCHE_HANDLE_2RTT = '2', MCHE_PACKET2LARGE_IN = 'a', MCHE_CONN_CLOSE = 'c', MCHE_CREATED = 'C', MCHE_2HSK_1STREAM = 'd', MCHE_DUP_HSK = 'D', MCHE_HANDLE_ERROR = 'e', MCHE_EFRAME = 'f', MCHE_UNDECR_DEFER = 'F', MCHE_HANDLE_NOT_ENOUGH = 'g', MCHE_NEW_HSK = 'H', MCHE_INVALID_FRAME = 'I', MCHE_DECRYPTED = 'K', MCHE_PACKET_LOST = 'L', MCHE_HELLO_TOO_MUCH = 'm', MCHE_ENOMEM = 'M', MCHE_NEW_PACKET_OUT = 'N', MCHE_HELLO_HOLE = 'o', MCHE_PACKET_DUP_IN = 'p', MCHE_UNDECR_DROP = 'P', MCHE_PRST_IN = 'R', MCHE_HANDLE_SHLO = 's', MCHE_NEW_ENC_SESS = 'S', MCHE_PACKET_SENT = 'T', MCHE_HAHDLE_UNKNOWN = 'u', MCHE_UNSENT_ACKED = 'U', MCHE_HANDLE_DELAYED = 'y', MCHE_PACKET_DELAYED = 'Y', MCHE_PACKET0_IN = 'z', MCHE_OUT_OF_PACKNOS = '#', }; #endif #ifndef LSQUIC_RECORD_INORD_HIST # if __GNUC__ # define LSQUIC_RECORD_INORD_HIST 0 /* XXX */ # else # define LSQUIC_RECORD_INORD_HIST 0 # endif #endif typedef uint64_t mconn_packno_set_t; #define MINICONN_MAX_PACKETS (sizeof(mconn_packno_set_t) * 8) TAILQ_HEAD(head_packet_in, lsquic_packet_in); struct mini_conn { struct lsquic_conn mc_conn; struct conn_cid_elem mc_cces[1]; struct head_packet_in mc_deferred, mc_packets_in; TAILQ_HEAD(, lsquic_packet_out) mc_packets_out; struct lsquic_engine_public *mc_enpub; lsquic_time_t mc_created; struct lsquic_rtt_stats mc_rtt_stats; mconn_packno_set_t mc_received_packnos, mc_sent_packnos, mc_deferred_packnos, /* Informational */ mc_dropped_packnos, /* Informational */ mc_lost_packnos, /* Packets that were deemed lost */ /* Informational */ mc_acked_packnos; #if LSQUIC_RECORD_INORD_HIST unsigned long long mc_inord_hist[2]; /* Informational */ #endif uint32_t mc_error_code; /* From CONNECTION_CLOSE frame */ /* Informational */ unsigned short mc_n_ticks; /* Number of times mini conn ticked. */ /* Informational */ unsigned short mc_read_off, /* Read offset for stream 1 */ mc_write_off;/* Write offset for stream 1 */ unsigned char mc_max_ack_packno, /* XXX: mc_max_ack_packno is never set */ mc_cutoff, mc_cur_packno; unsigned char mc_hsk_count; #if LSQUIC_RECORD_INORD_HIST unsigned char mc_inord_idx; #endif /* mc_largest_recv is the timestamp of when packet with the largest * number was received; it is necessary to generate ACK frames. 24 * bits holds about 16.5 seconds worth of microseconds, which is * larger than the maximum amount of time a mini connection object * is allowed to live. To get the timestamp, add this value to * mc_created. */ unsigned char mc_largest_recv[3]; enum { MC_HAVE_NEW_HSK = (1 << 0), MC_PROMOTE = (1 << 1), MC_HAVE_SHLO = (1 << 2), MC_UNUSED_3 = (1 << 3), MC_ERROR = (1 << 4), MC_UNSENT_ACK = (1 << 5), MC_GEN_ACK = (1 << 6), MC_HSK_ERR = (1 << 7), MC_OO_PACKNOS = (1 << 8), MC_STOP_WAIT_ON = (1 << 9), } mc_flags:16; struct network_path mc_path; #if LSQUIC_KEEP_MINICONN_HISTORY mchist_idx_t mc_hist_idx; unsigned char mc_hist_buf[1 << MCHIST_BITS]; #endif }; lsquic_conn_t * mini_conn_new (struct lsquic_engine_public *, const struct lsquic_packet_in *, enum lsquic_version version); /* Packet numbers start with 1. By subtracting 1, we can utilize the full * length of the bitmask. */ #define MCONN_PACKET_MASK(packno) (1ULL << (packno - 1)) #endif