/*
 * include/haproxy/quic_conn-t.h
 *
 * Copyright 2019 HAProxy Technologies, Frederic Lecaille <flecaille@haproxy.com>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation, version 2.1
 * exclusively.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */

#ifndef _HAPROXY_QUIC_CONN_T_H
#define _HAPROXY_QUIC_CONN_T_H

#ifdef USE_QUIC
#ifndef USE_OPENSSL
#error "Must define USE_OPENSSL"
#endif

#include <sys/socket.h>

#include <haproxy/cbuf-t.h>
#include <haproxy/list.h>

#include <haproxy/openssl-compat.h>
#include <haproxy/mux_quic-t.h>
#include <haproxy/ncbmbuf-t.h>
#include <haproxy/quic_cc-t.h>
#include <haproxy/quic_frame-t.h>
#include <haproxy/quic_loss-t.h>
#include <haproxy/quic_openssl_compat-t.h>
#include <haproxy/quic_stats-t.h>
#include <haproxy/quic_tls-t.h>
#include <haproxy/quic_tp-t.h>
#include <haproxy/task.h>

#include <import/ebtree-t.h>

typedef unsigned long long ull;

#define QUIC_PROTOCOL_VERSION_DRAFT_29   0xff00001d /* draft-29 */
#define QUIC_PROTOCOL_VERSION_1          0x00000001 /* V1 */
#define QUIC_PROTOCOL_VERSION_2          0x6b3343cf /* V2 */

#define QUIC_INITIAL_IPV4_MTU      1252 /* (bytes) */
#define QUIC_INITIAL_IPV6_MTU      1232

/* The minimum length of Initial packets. */
#define QUIC_INITIAL_PACKET_MINLEN 1200

/* Lengths of the QUIC CIDs generated by the haproxy implementation. Current
 * value is used to match 64 bits hash produced when deriving ODCID.
 */
#define QUIC_HAP_CID_LEN               8

/* Common definitions for short and long QUIC packet headers. */
/* QUIC connection ID maximum length for version 1. */
#define QUIC_CID_MAXLEN               20 /* bytes */
/* QUIC original destination connection ID minial length */
#define QUIC_ODCID_MINLEN              8 /* bytes */
/*
 * All QUIC packets with long headers are made of at least (in bytes):
 * flags(1), version(4), DCID length(1), DCID(0..20), SCID length(1), SCID(0..20)
 */
#define QUIC_LONG_PACKET_MINLEN            7
/* DCID offset from beginning of a long packet */
#define QUIC_LONG_PACKET_DCID_OFF         (1 + sizeof(uint32_t))
/*
 * All QUIC packets with short headers are made of at least (in bytes):
 * flags(1), DCID(0..20)
 */
#define QUIC_SHORT_PACKET_MINLEN           1
/* DCID offset from beginning of a short packet */
#define QUIC_SHORT_PACKET_DCID_OFF         1

/* Byte 0 of QUIC packets. */
#define QUIC_PACKET_LONG_HEADER_BIT  0x80 /* Long header format if set, short if not. */
#define QUIC_PACKET_FIXED_BIT        0x40 /* Must always be set for all the headers. */

/* Tokens formats */
/* Format for Retry tokens sent by a QUIC server */
#define QUIC_TOKEN_FMT_RETRY 0x9c
/* Format for token sent for new connections after a Retry token was sent */
#define  QUIC_TOKEN_FMT_NEW  0xb7
/* Salt length used to derive retry token secret */
#define QUIC_RETRY_TOKEN_SALTLEN       16 /* bytes */
/* Retry token duration */
#define QUIC_RETRY_DURATION_SEC       10
/* Default Retry threshold */
#define QUIC_DFLT_RETRY_THRESHOLD     100 /* in connection openings */
/* Default ratio value applied to a dynamic Packet reorder threshold. */
#define QUIC_DFLT_REORDER_RATIO        50 /* in percent */
/* Default limit of loss detection on a single frame. If exceeded, connection is closed. */
#define QUIC_DFLT_MAX_FRAME_LOSS       10

/*
 *  0                   1                   2                   3
 *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
 * +-+-+-+-+-+-+-+-+
 * |1|1|T|T|X|X|X|X|
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 * |                         Version (32)                          |
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 * | DCID Len (8)  |
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 * |               Destination Connection ID (0..160)            ...
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 * | SCID Len (8)  |
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 * |                 Source Connection ID (0..160)               ...
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 *                      Long Header Packet Format
 */

/* Two bits (T) for QUIC packet types. */
#define QUIC_PACKET_TYPE_BITMASK     0x03
#define QUIC_PACKET_TYPE_SHIFT       4

enum quic_pkt_type {
	QUIC_PACKET_TYPE_INITIAL,
	QUIC_PACKET_TYPE_0RTT,
	QUIC_PACKET_TYPE_HANDSHAKE,
	QUIC_PACKET_TYPE_RETRY,
	/*
	 * The following one is not defined by the RFC but we define it for our
	 * own convenience.
	 */
	QUIC_PACKET_TYPE_SHORT,

	/* unknown type */
	QUIC_PACKET_TYPE_UNKNOWN
};

/* Packet number field length. */
#define QUIC_PACKET_PNL_BITMASK      0x03
#define QUIC_PACKET_PN_MAXLEN        4

/*
 *  0                   1                   2                   3
 *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
 * +-+-+-+-+-+-+-+-+
 * |0|1|S|R|R|K|P|P|
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 * |                Destination Connection ID (0..160)           ...
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 * |                     Packet Number (8/16/24/32)              ...
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 * |                     Protected Payload (*)                   ...
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 *                      Short Header Packet Format
 */

/* Bit (S) of short header. */
#define QUIC_PACKET_SPIN_BIT         0x20

/* Reserved Bits (R):  The next two bits of byte 0 are reserved.
 * These bits are protected using header protection
 * (see Section 5.4 of [QUIC-TLS]). The value included
 * prior to protection MUST be set to 0. An endpoint MUST treat
 * receipt of a packet that has a non-zero value for these bits,
 * after removing both packet and header protection, as a connection
 * error of type PROTOCOL_VIOLATION. Discarding such a packet after
 * only removing header protection can expose the endpoint to attacks
 * (see Section 9.3 of [QUIC-TLS]).
 */
#define QUIC_PACKET_RESERVED_BITS    0x18 /* (protected) */

#define QUIC_PACKET_KEY_PHASE_BIT    0x04 /* (protected) */

/* The maximum number of QUIC packets stored by the fd I/O handler by QUIC
 * connection. Must be a power of two.
 */
#define QUIC_CONN_MAX_PACKET  64

/* RFC 9000 10.3. Stateless Reset
 *
 * To entities other than its intended recipient, a Stateless Reset will
 * appear to be a packet with a short header. For the Stateless Reset to
 * appear as a valid QUIC packet, the Unpredictable Bits field needs to
 * include at least 38 bits of data (or 5 bytes, less the two fixed
 * bits).
 */
#define QUIC_STATELESS_RESET_PACKET_MINLEN     (5 + QUIC_STATELESS_RESET_TOKEN_LEN)

#define           QUIC_EV_CONN_NEW       (1ULL << 0)
#define           QUIC_EV_CONN_INIT      (1ULL << 1)
#define           QUIC_EV_CONN_ISEC      (1ULL << 2)
#define           QUIC_EV_CONN_RSEC      (1ULL << 3)
#define           QUIC_EV_CONN_WSEC      (1ULL << 4)
#define           QUIC_EV_CONN_RWSEC     (1ULL << 5)
#define           QUIC_EV_CONN_LPKT      (1ULL << 6)
#define           QUIC_EV_CONN_SPKT      (1ULL << 7)
#define           QUIC_EV_CONN_ENCPKT    (1ULL << 8)
#define           QUIC_EV_CONN_TXPKT     (1ULL << 9)
#define           QUIC_EV_CONN_PAPKT     (1ULL << 10)
#define           QUIC_EV_CONN_PAPKTS    (1ULL << 11)
#define           QUIC_EV_CONN_IO_CB     (1ULL << 12)
#define           QUIC_EV_CONN_RMHP      (1ULL << 13)
#define           QUIC_EV_CONN_PRSHPKT   (1ULL << 14)
#define           QUIC_EV_CONN_PRSAPKT   (1ULL << 15)
#define           QUIC_EV_CONN_PRSFRM    (1ULL << 16)
#define           QUIC_EV_CONN_PRSAFRM   (1ULL << 17)
#define           QUIC_EV_CONN_BFRM      (1ULL << 18)
#define           QUIC_EV_CONN_PHPKTS    (1ULL << 19)
#define           QUIC_EV_CONN_TRMHP     (1ULL << 20)
#define           QUIC_EV_CONN_ELRMHP    (1ULL << 21)
#define           QUIC_EV_CONN_RXPKT     (1ULL << 22)
#define           QUIC_EV_CONN_SSLDATA   (1ULL << 23)
#define           QUIC_EV_CONN_RXCDATA   (1ULL << 24)
#define           QUIC_EV_CONN_ADDDATA   (1ULL << 25)
#define           QUIC_EV_CONN_FFLIGHT   (1ULL << 26)
#define           QUIC_EV_CONN_SSLALERT  (1ULL << 27)
#define           QUIC_EV_CONN_PSTRM     (1ULL << 28)
#define           QUIC_EV_CONN_RTTUPDT   (1ULL << 29)
#define           QUIC_EV_CONN_CC        (1ULL << 30)
#define           QUIC_EV_CONN_SPPKTS    (1ULL << 31)
#define           QUIC_EV_CONN_PKTLOSS   (1ULL << 32)
#define           QUIC_EV_CONN_STIMER    (1ULL << 33)
#define           QUIC_EV_CONN_PTIMER    (1ULL << 34)
#define           QUIC_EV_CONN_SPTO      (1ULL << 35)
#define           QUIC_EV_CONN_BCFRMS    (1ULL << 36)
#define           QUIC_EV_CONN_XPRTSEND  (1ULL << 37)
#define           QUIC_EV_CONN_XPRTRECV  (1ULL << 38)
#define           QUIC_EV_CONN_FREED     (1ULL << 39)
#define           QUIC_EV_CONN_CLOSE     (1ULL << 40)
#define           QUIC_EV_CONN_ACKSTRM   (1ULL << 41)
#define           QUIC_EV_CONN_FRMLIST   (1ULL << 42)
#define           QUIC_EV_STATELESS_RST  (1ULL << 43)
#define           QUIC_EV_TRANSP_PARAMS  (1ULL << 44)
#define           QUIC_EV_CONN_IDLE_TIMER (1ULL << 45)
#define           QUIC_EV_CONN_SUB       (1ULL << 46)
#define           QUIC_EV_CONN_ELEVELSEL (1ULL << 47)
#define           QUIC_EV_CONN_RCV       (1ULL << 48)
#define           QUIC_EV_CONN_KILL      (1ULL << 49)
#define           QUIC_EV_CONN_KP        (1ULL << 50)
#define           QUIC_EV_CONN_SSL_COMPAT (1ULL << 51)
#define           QUIC_EV_CONN_SET_AFFINITY (1ULL << 52)

/* Similar to kernel min()/max() definitions. */
#define QUIC_MIN(a, b) ({ \
    typeof(a) _a = (a);   \
    typeof(b) _b = (b);   \
    (void) (&_a == &_b);  \
    _a < _b ? _a : _b; })

#define QUIC_MAX(a, b) ({ \
    typeof(a) _a = (a);   \
    typeof(b) _b = (b);   \
    (void) (&_a == &_b);  \
    _a > _b ? _a : _b; })

/* Size of the internal buffer of QUIC TX ring buffers (must be a power of 2) */
#define QUIC_TX_RING_BUFSZ  (1UL << 12)
/* Size of the QUIC RX buffer for the connections */
#define QUIC_CONN_RX_BUFSZ (1UL << 16)

extern struct trace_source trace_quic;
extern struct pool_head *pool_head_quic_tx_ring;
extern struct pool_head *pool_head_quic_rx_packet;
extern struct pool_head *pool_head_quic_tx_packet;
extern struct pool_head *pool_head_quic_frame;
extern struct pool_head *pool_head_quic_dgram;

struct quic_version {
	uint32_t num;
	const unsigned char *initial_salt;
	size_t initial_salt_len;
	const unsigned char *key_label;
	size_t key_label_len;
	const unsigned char *iv_label;
	size_t iv_label_len;
	const unsigned char *hp_label;
	size_t hp_label_len;
	const unsigned char *ku_label;
	size_t ku_label_len;
	/* Retry tag */
	const unsigned char *retry_tag_key;
	const unsigned char *retry_tag_nonce;
};

extern const struct quic_version quic_versions[];
extern const size_t quic_versions_nb;
extern const struct quic_version *preferred_version;

/* QUIC connection id data.
 *
 * This struct is used by ebmb_node structs as last member of flexible arrays.
 * So do not change the order of the member of quic_cid struct.
 * <data> member must be the first one.
 */
struct quic_cid {
	unsigned char data[QUIC_CID_MAXLEN];
	unsigned char len; /* size of QUIC CID */
};

/* QUIC connection id attached to a QUIC connection.
 *
 * This structure is used to match received packets DCIDs with the
 * corresponding QUIC connection.
 */
struct quic_connection_id {
	struct eb64_node seq_num;
	uint64_t retire_prior_to;
	unsigned char stateless_reset_token[QUIC_STATELESS_RESET_TOKEN_LEN];

	struct ebmb_node node; /* node for receiver tree, cid.data as key */
	struct quic_cid cid;   /* CID data */

	struct quic_conn *qc;  /* QUIC connection using this CID */
	uint tid;              /* Attached Thread ID for the connection. */
};

/* Structure to hold a range of ACKs sent in ACK frames. */
struct quic_arng {
	int64_t first;
	int64_t last;
};

/* Structure to hold a range of ACKs to be store as a node in a tree of
 * ACK ranges.
 */
struct quic_arng_node {
	struct eb64_node first;
	uint64_t last;
};

/* Flag the packet number space as having received a packet */
#define QUIC_FL_PKTNS_PKT_RECEIVED  (1UL << 0)
/* Flag the packet number space as requiring an ACK frame to be sent. */
#define QUIC_FL_PKTNS_ACK_REQUIRED  (1UL << 1)
/* Flag the packet number space as needing probing */
#define QUIC_FL_PKTNS_PROBE_NEEDED  (1UL << 2)
/* Flag the packet number space as having received a packet with a new largest
 * packet number, to be acknowledege
 */
#define QUIC_FL_PKTNS_NEW_LARGEST_PN (1UL << 3)

/* The maximum number of dgrams which may be sent upon PTO expirations. */
#define QUIC_MAX_NB_PTO_DGRAMS         2

/* QUIC datagram */
struct quic_dgram {
	void *owner;
	unsigned char *buf;
	size_t len;
	unsigned char *dcid;
	size_t dcid_len;
	struct sockaddr_storage saddr;
	struct sockaddr_storage daddr;
	struct quic_conn *qc;

	struct list recv_list; /* elemt to quic_receiver_buf <dgram_list>. */
	struct mt_list handler_list; /* elem to quic_dghdlr <dgrams>. */
};

/* The QUIC packet numbers are 62-bits integers */
#define QUIC_MAX_PACKET_NUM      ((1ULL << 62) - 1)

/* Maximum number of ack-eliciting received packets since the last
 * ACK frame was sent
 */
#define QUIC_MAX_RX_AEPKTS_SINCE_LAST_ACK       2
#define QUIC_ACK_DELAY   (QUIC_TP_DFLT_MAX_ACK_DELAY - 5)
/* Flag a received packet as being an ack-eliciting packet. */
#define QUIC_FL_RX_PACKET_ACK_ELICITING (1UL << 0)
/* Packet is the first one in the containing datagram. */
#define QUIC_FL_RX_PACKET_DGRAM_FIRST   (1UL << 1)
/* Spin bit set */
#define QUIC_FL_RX_PACKET_SPIN_BIT   (1UL << 2)

struct quic_rx_packet {
	struct list list;
	struct list qc_rx_pkt_list;

	/* QUIC version used in packet. */
	const struct quic_version *version;

	unsigned char type;
	/* Initial desctination connection ID. */
	struct quic_cid dcid;
	struct quic_cid scid;
	/* Packet number offset : only valid for Initial/Handshake/0-RTT/1-RTT. */
	size_t pn_offset;
	/* Packet number */
	int64_t pn;
	/* Packet number length */
	uint32_t pnl;
	uint64_t token_len;
	unsigned char *token;
	/* Packet length */
	uint64_t len;
	/* Packet length before decryption */
	uint64_t raw_len;
	/* Additional authenticated data length */
	size_t aad_len;
	unsigned char *data;
	struct eb64_node pn_node;
	volatile unsigned int refcnt;
	/* Source address of this packet. */
	struct sockaddr_storage saddr;
	unsigned int flags;
	unsigned int time_received;
};

enum quic_rx_ret_frm {
	QUIC_RX_RET_FRM_DONE = 0, /* frame handled correctly */
	QUIC_RX_RET_FRM_DUP,      /* frame ignored as already handled previously */
	QUIC_RX_RET_FRM_AGAIN,    /* frame cannot be handled temporarily, caller may retry during another parsing round */
	QUIC_RX_RET_FRM_FATAL,    /* error during frame handling, packet must not be acknowledged */
};

/* QUIC datagram handler */
struct quic_dghdlr {
	struct mt_list dgrams;
	struct tasklet *task;
};

/* Structure to store enough information about the RX CRYPTO frames. */
struct quic_rx_crypto_frm {
	struct eb64_node offset_node;
	uint64_t len;
	const unsigned char *data;
	struct quic_rx_packet *pkt;
};

/* Flag a sent packet as being an ack-eliciting packet. */
#define QUIC_FL_TX_PACKET_ACK_ELICITING (1UL << 0)
/* Flag a sent packet as containing a PADDING frame. */
#define QUIC_FL_TX_PACKET_PADDING       (1UL << 1)
/* Flag a sent packet as being in flight. */
#define QUIC_FL_TX_PACKET_IN_FLIGHT     (QUIC_FL_TX_PACKET_ACK_ELICITING | QUIC_FL_TX_PACKET_PADDING)
/* Flag a sent packet as containing a CONNECTION_CLOSE frame */
#define QUIC_FL_TX_PACKET_CC            (1UL << 2)
/* Flag a sent packet as containing an ACK frame */
#define QUIC_FL_TX_PACKET_ACK           (1UL << 3)
/* Flag a sent packet as being coalesced to another one in the same datagram */
#define QUIC_FL_TX_PACKET_COALESCED     (1UL << 4)
/* Flag a sent packet as being probing with old data */
#define QUIC_FL_TX_PACKET_PROBE_WITH_OLD_DATA (1UL << 5)

/* Structure to store enough information about TX QUIC packets. */
struct quic_tx_packet {
	/* List entry point. */
	struct list list;
	/* Packet length */
	size_t len;
	/* This is not the packet length but the length of outstanding data
	 * for in flight TX packet.
	 */
	size_t in_flight_len;
	struct eb64_node pn_node;
	/* The list of frames of this packet. */
	struct list frms;
	/* The time this packet was sent (ms). */
	unsigned int time_sent;
	/* Packet number spakce. */
	struct quic_pktns *pktns;
	/* Flags. */
	unsigned int flags;
	/* Reference counter */
	int refcnt;
	/* Next packet in the same datagram */
	struct quic_tx_packet *next;
	/* Previous packet in the same datagram */
	struct quic_tx_packet *prev;
	/* Largest acknowledged packet number if this packet contains an ACK frame */
	int64_t largest_acked_pn;
	unsigned char type;
};

#define QUIC_CRYPTO_BUF_SHIFT  10
#define QUIC_CRYPTO_BUF_MASK   ((1UL << QUIC_CRYPTO_BUF_SHIFT) - 1)
/* The maximum allowed size of CRYPTO data buffer provided by the TLS stack. */
#define QUIC_CRYPTO_BUF_SZ    (1UL << QUIC_CRYPTO_BUF_SHIFT) /* 1 KB */

/* The maximum number of bytes of CRYPTO data in flight during handshakes. */
#define QUIC_CRYPTO_IN_FLIGHT_MAX 4096

/*
 * CRYPTO buffer struct.
 * Such buffers are used to send CRYPTO data.
 */
struct quic_crypto_buf {
	unsigned char data[QUIC_CRYPTO_BUF_SZ];
	size_t sz;
};

/* Crypto data stream (one by encryption level) */
struct quic_cstream {
	struct {
		uint64_t offset;       /* absolute current base offset of ncbuf */
		struct ncbmbuf ncbuf;  /* receive buffer - can handle out-of-order offset frames */
	} rx;
	struct {
		uint64_t offset;      /* last offset of data ready to be sent */
		uint64_t sent_offset; /* last offset sent by transport layer */
		struct buffer buf;    /* transmit buffer before sending via xprt */
	} tx;

	struct qc_stream_desc *desc;
};

struct quic_path {
	/* Control congestion. */
	struct quic_cc cc;
	/* Packet loss detection information. */
	struct quic_loss loss;

	/* MTU. */
	size_t mtu;
	/* Congestion window. */
	uint64_t cwnd;
	/* The current maximum congestion window value reached. */
	uint64_t cwnd_last_max;
	/* Min limit on congestion window size. */
	uint64_t limit_min;
	/* Prepared data to be sent (in bytes). */
	uint64_t prep_in_flight;
	/* Outstanding data (in bytes). */
	uint64_t in_flight;
	/* Number of in flight ack-eliciting packets. */
	uint64_t ifae_pkts;
};

/* QUIC ring buffer */
struct qring {
	struct cbuf *cbuf;
	struct mt_list mt_list;
};

/* Status of the connection/mux layer. This defines how to handle app data.
 *
 * During a standard quic_conn lifetime it transitions like this :
 * QC_MUX_NULL -> QC_MUX_READY -> QC_MUX_RELEASED
 */
enum qc_mux_state {
	QC_MUX_NULL,     /* not allocated, data should be buffered */
	QC_MUX_READY,    /* allocated, ready to handle data */
	QC_MUX_RELEASED, /* released, data can be dropped */
};

/* Counters at QUIC connection level */
struct quic_conn_cntrs {
	long long dropped_pkt;           /* total number of dropped packets */
	long long dropped_pkt_bufoverrun;/* total number of dropped packets because of buffer overrun */
	long long dropped_parsing;       /* total number of dropped packets upon parsing errors */
	long long socket_full;           /* total number of EAGAIN errors on sendto() calls */
	long long sendto_err;            /* total number of errors on sendto() calls, EAGAIN excepted */
	long long sendto_err_unknown;    /* total number of errors on sendto() calls which are currently not supported */
	long long sent_pkt;              /* total number of sent packets */
	long long lost_pkt;              /* total number of lost packets */
	long long conn_migration_done;   /* total number of connection migration handled */
	/* Streams related counters */
	long long data_blocked;              /* total number of times DATA_BLOCKED frame was received */
	long long stream_data_blocked;       /* total number of times STREAM_DATA_BLOCKED frame was received */
	long long streams_blocked_bidi;      /* total number of times STREAMS_BLOCKED_BIDI frame was received */
	long long streams_blocked_uni;       /* total number of times STREAMS_BLOCKED_UNI frame was received */
};

/* The number of buffers for outgoing packets (must be a power of two). */
#define QUIC_CONN_TX_BUFS_NB 8

/* Flags at connection level */
#define QUIC_FL_CONN_ANTI_AMPLIFICATION_REACHED  (1U << 0)
#define QUIC_FL_CONN_SPIN_BIT                    (1U << 1) /* Spin bit set by remote peer */
#define QUIC_FL_CONN_NEED_POST_HANDSHAKE_FRMS    (1U << 2) /* HANDSHAKE_DONE must be sent */
#define QUIC_FL_CONN_LISTENER                    (1U << 3)
#define QUIC_FL_CONN_ACCEPT_REGISTERED           (1U << 4)
#define QUIC_FL_CONN_TX_MUX_CONTEXT              (1U << 5) /* sending in progress from the MUX layer */
#define QUIC_FL_CONN_IDLE_TIMER_RESTARTED_AFTER_READ (1U << 6)
#define QUIC_FL_CONN_RETRANS_NEEDED              (1U << 7)
#define QUIC_FL_CONN_RETRANS_OLD_DATA            (1U << 8) /* retransmission in progress for probing with already sent data */
#define QUIC_FL_CONN_TLS_ALERT                   (1U << 9)
#define QUIC_FL_CONN_AFFINITY_CHANGED            (1U << 10) /* qc_finalize_affinity_rebind() must be called to finalize affinity rebind */
/* gap here */
#define QUIC_FL_CONN_HALF_OPEN_CNT_DECREMENTED   (1U << 11) /* The half-open connection counter was decremented */
#define QUIC_FL_CONN_HANDSHAKE_SPEED_UP          (1U << 12) /* Handshake speeding up was done */
#define QUIC_FL_CONN_ACK_TIMER_FIRED             (1U << 13) /* idle timer triggered for acknowledgements */
#define QUIC_FL_CONN_IO_TO_REQUEUE               (1U << 14) /* IO handler must be requeued on new thread after connection migration */
#define QUIC_FL_CONN_TO_KILL                     (1U << 24) /* Unusable connection, to be killed */
#define QUIC_FL_CONN_TX_TP_RECEIVED              (1U << 25) /* Peer transport parameters have been received (used for the transmitting part) */
#define QUIC_FL_CONN_FINALIZED                   (1U << 26) /* QUIC connection finalized (functional, ready to send/receive) */
/* gap here */
#define QUIC_FL_CONN_EXP_TIMER                   (1U << 28) /* timer has expired, quic-conn can be freed */
#define QUIC_FL_CONN_CLOSING                     (1U << 29) /* closing state, entered on CONNECTION_CLOSE emission */
#define QUIC_FL_CONN_DRAINING                    (1U << 30) /* draining state, entered on CONNECTION_CLOSE reception */
#define QUIC_FL_CONN_IMMEDIATE_CLOSE             (1U << 31) /* A CONNECTION_CLOSE must be sent */

struct quic_conn {
	const struct quic_version *original_version;
	const struct quic_version *negotiated_version;
	/* Negotiated version Initial TLS context */
	struct quic_tls_ctx negotiated_ictx;
	/* Connection owned socket FD. */
	int fd;
	/* QUIC transport parameters TLS extension */
	int tps_tls_ext;
	int state;
	enum qc_mux_state mux_state; /* status of the connection/mux layer */
	struct quic_err err;
	unsigned char enc_params[QUIC_TP_MAX_ENCLEN]; /* encoded QUIC transport parameters */
	size_t enc_params_len;

	struct quic_cid odcid; /* First DCID used by client on its Initial packet. */
	struct quic_cid dcid; /* DCID of our endpoint - not updated when a new DCID is used */
	struct quic_cid scid; /* first SCID of our endpoint - not updated when a new SCID is used */
	struct eb_root cids; /* tree of quic_connection_id - used to match a received packet DCID with a connection */
	uint64_t next_cid_seq_num;

	struct quic_enc_level els[QUIC_TLS_ENC_LEVEL_MAX];
	struct quic_pktns pktns[QUIC_TLS_PKTNS_MAX];

	struct ssl_sock_ctx *xprt_ctx;
#ifdef USE_QUIC_OPENSSL_COMPAT
	struct quic_openssl_compat openssl_compat;
#endif

	struct sockaddr_storage local_addr;
	struct sockaddr_storage peer_addr;

	/* Used only to reach the tasklet for the I/O handler from this quic_conn object. */
	struct connection *conn;

	struct {
		/* The remaining frames to send. */
		struct list frms_to_send;

		/* The size of the previous array. */
		size_t nb_buf;
		/* Writer index. */
		int wbuf;
		/* Reader index. */
		int rbuf;
		/* Number of sent bytes. */
		uint64_t bytes;
		/* Number of bytes for prepared packets */
		uint64_t prep_bytes;
		/* Transport parameters sent by the peer */
		struct quic_transport_params params;
		/* Send buffer used to write datagrams. */
		struct buffer buf;
	} tx;
	struct {
		/* Number of received bytes. */
		uint64_t bytes;
		/* Transport parameters the peer will receive */
		struct quic_transport_params params;
		/* RX buffer */
		struct buffer buf;
		struct list pkt_list;
		struct {
			/* Number of open or closed streams */
			uint64_t nb_streams;
		} strms[QCS_MAX_TYPES];
	} rx;
	struct {
		struct quic_tls_kp prv_rx;
		struct quic_tls_kp nxt_rx;
		struct quic_tls_kp nxt_tx;
	} ku;
	unsigned int max_ack_delay;
	unsigned int max_idle_timeout;
	struct quic_path paths[1];
	struct quic_path *path;

	struct listener *li; /* only valid for frontend connections */
	struct mt_list accept_list; /* chaining element used for accept, only valid for frontend connections */

	struct eb_root streams_by_id; /* qc_stream_desc tree */
	int stream_buf_count; /* total count of allocated stream buffers for this connection */

	struct wait_event wait_event;
	struct wait_event *subs;

	/* MUX */
	struct qcc *qcc;
	struct task *timer_task;
	unsigned int timer;
	/* Idle timer task */
	struct task *idle_timer_task;
	unsigned int idle_expire;
	unsigned int ack_expire;
	unsigned int flags;

	/* When in closing state, number of packet before sending CC */
	unsigned int nb_pkt_for_cc;
	/* When in closing state, number of packet since receiving CC */
	unsigned int nb_pkt_since_cc;

	const struct qcc_app_ops *app_ops;
	/* QUIC connection level counters */
	struct quic_conn_cntrs cntrs;
	/* Proxy counters */
	struct quic_counters *prx_counters;

	struct list el_th_ctx; /* list elem in ha_thread_ctx */
	struct list back_refs; /* list head of CLI context currently dumping this connection. */
	unsigned int qc_epoch; /* delimiter for newer instances started after "show quic". */
};

#endif /* USE_QUIC */
#endif /* _HAPROXY_QUIC_CONN_T_H */
