1/* Copyright (c) 2017 - 2022 LiteSpeed Technologies Inc. See LICENSE. */ 2/* 3 * lsquic_packet_in.h 4 */ 5 6#ifndef LSQUIC_PACKET_IN_H 7#define LSQUIC_PACKET_IN_H 1 8 9 10struct lsquic_packet_in; 11struct lsquic_cid; 12 13 14struct data_frame 15{ 16 const unsigned char *df_data; /* Pointer to data */ 17 uint64_t df_offset; /* Stream offset */ 18 uint16_t df_read_off; /* Read offset */ 19 uint16_t df_size; /* Size of df_data */ 20 signed char df_fin; /* FIN? */ 21}; 22 23 24typedef struct stream_frame 25{ 26 /* Stream frames are stored in a list inside "di nocopy" (if "di nocopy" 27 * is used). 28 */ 29 TAILQ_ENTRY(stream_frame) next_frame; 30 31 /* `data_frame.df_data' points somewhere into the packet payload. The 32 * packet object is reference-counted. When the frame is freed, the 33 * packet is released via lsquic_packet_in_put(). 34 */ 35 struct lsquic_packet_in *packet_in; 36 37 struct data_frame data_frame; 38 39 lsquic_stream_id_t stream_id; /* Parsed from packet */ 40} stream_frame_t; 41 42 43#define DF_OFF(frame) (frame)->data_frame.df_offset 44#define DF_ROFF(frame) (DF_OFF(frame) + (frame)->data_frame.df_read_off) 45#define DF_FIN(frame) (frame)->data_frame.df_fin 46#define DF_SIZE(frame) (frame)->data_frame.df_size 47#define DF_END(frame) (DF_OFF(frame) + DF_SIZE(frame)) 48 49 50typedef struct lsquic_packet_in 51{ 52 TAILQ_ENTRY(lsquic_packet_in) pi_next; 53 lsquic_time_t pi_received; /* Time received */ 54 lsquic_cid_t pi_dcid; 55#define pi_conn_id pi_dcid 56 lsquic_packno_t pi_packno; 57 enum quic_ft_bit pi_frame_types; 58 unsigned short pi_header_sz; /* Points to payload */ 59 unsigned short pi_data_sz; /* Data plus header */ 60 /* A packet may be referred to by one or more frames and packets_in 61 * list. 62 */ 63 unsigned short pi_refcnt; 64 unsigned short pi_hsk_stream; /* Offset to handshake stream 65 * frame, only valid if 66 * PI_HSK_STREAM is set. 67 */ 68 enum { 69 PI_DECRYPTED = (1 << 0), 70 PI_OWN_DATA = (1 << 1), /* We own pi_data */ 71 PI_CONN_ID = (1 << 2), /* pi_conn_id is set */ 72 PI_HSK_STREAM = (1 << 3), /* Has handshake data (mini only) */ 73 PI_FROM_MINI = (1 << 4), /* Handed off by mini connection */ 74#define PIBIT_ENC_LEV_SHIFT 5 75 PI_ENC_LEV_BIT_0= (1 << 5), /* Encodes encryption level */ 76 PI_ENC_LEV_BIT_1= (1 << 6), /* (see enum enc_level). */ 77 PI_GQUIC = (1 << 7), 78 PI_UNUSED_8 = (1 << 8), /* <-- hole, reuse me! */ 79#define PIBIT_ECN_SHIFT 9 80 PI_ECN_BIT_0 = (1 << 9), 81 PI_ECN_BIT_1 = (1 <<10), 82#define PIBIT_SPIN_SHIFT 11 83 PI_SPIN_BIT = (1 <<11), 84#define PIBIT_BITS_SHIFT 12 85 PI_BITS_BIT_0 = (1 <<12), 86 PI_BITS_BIT_1 = (1 <<13), 87 /* Square bit and loss bit flags are used for logging */ 88 PI_LOG_QL_BITS = (1 <<14), 89 PI_SQUARE_BIT = (1 <<15), 90 PI_LOSS_BIT = (1 <<16), 91 } pi_flags; 92 /* pi_token and pi_token_size are set in Initial and Retry packets */ 93 unsigned short pi_token_size; /* Size of the token */ 94 unsigned char pi_token; /* Offset to token */ 95 /* pi_odcid and pi_odcid_len are only set in Retry packets for I-D < 25 */ 96 unsigned char pi_odcid; /* Offset to Original DCID */ 97 unsigned char pi_odcid_len; /* Size of ODCID */ 98 unsigned char pi_scid_off; /* Offset to SCID */ 99 unsigned char pi_scid_len; /* Size of SCID */ 100 unsigned char pi_quic_ver; /* Offset to QUIC version */ 101 unsigned char pi_nonce; /* Offset to nonce */ 102 enum header_type pi_header_type:8; 103 unsigned char pi_path_id; 104 /* If PI_OWN_DATA flag is not set, `pi_data' points to user-supplied 105 * packet data, which is NOT TO BE MODIFIED. 106 */ 107 unsigned char *pi_data; 108} lsquic_packet_in_t; 109 110 111#define lsquic_packet_in_public_flags(p) ((p)->pi_data[0]) 112 113#define lsquic_packet_in_is_gquic_prst(p) \ 114 (((p)->pi_flags & PI_GQUIC) \ 115 && (lsquic_packet_in_public_flags(p) & PACKET_PUBLIC_FLAGS_RST)) 116 117#define lsquic_packet_in_is_verneg(p) \ 118 (((p)->pi_flags & PI_GQUIC) ? \ 119 lsquic_packet_in_public_flags(p) & PACKET_PUBLIC_FLAGS_VERSION : \ 120 (p)->pi_header_type == HETY_VERNEG) 121 122#define lsquic_packet_in_packno_bits(p) \ 123 (((p)->pi_flags >> PIBIT_BITS_SHIFT) & 3) 124 125#define lsquic_packet_in_upref(p) (++(p)->pi_refcnt) 126 127#define lsquic_packet_in_get(p) (lsquic_packet_in_upref(p), (p)) 128 129#define lsquic_packet_in_nonce(p) \ 130 ((p)->pi_nonce ? (p)->pi_data + (p)->pi_nonce : NULL) 131 132#define lsquic_packet_in_enc_level(p) \ 133 (((p)->pi_flags >> PIBIT_ENC_LEV_SHIFT) & 0x3) 134 135#define lsquic_packet_in_ecn(p) \ 136 (((p)->pi_flags >> PIBIT_ECN_SHIFT) & 0x3) 137 138#define lsquic_packet_in_spin_bit(p) (((p)->pi_flags & PI_SPIN_BIT) > 0) 139 140/* PATH_CHALLENGE, PATH_RESPONSE, NEW_CONNECTION_ID, and PADDING frames 141 * are "probing frames", and all other frames are "non-probing frames". 142 * A packet containing only probing frames is a "probing packet", and a 143 * packet containing any other frame is a "non-probing packet". 144 * 145 * [draft-ietf-quic-transport-20], Section 9.1 146 */ 147#define lsquic_packet_in_non_probing(p) \ 148 (!!((p)->pi_frame_types & ~(QUIC_FTBIT_PATH_CHALLENGE \ 149 |QUIC_FTBIT_PATH_RESPONSE|QUIC_FTBIT_PADDING \ 150 |QUIC_FTBIT_NEW_CONNECTION_ID))) 151 152/* The version iterator is used on a version negotiation packet only. 153 * The iterator functions return 1 when next version is returned and 154 * 0 when there are no more versions. 155 */ 156struct ver_iter 157{ 158 const struct lsquic_packet_in *packet_in; 159 unsigned off; 160}; 161 162int 163lsquic_packet_in_ver_first (const lsquic_packet_in_t *packet_in, 164 struct ver_iter *, lsquic_ver_tag_t *ver_tag); 165 166int 167lsquic_packet_in_ver_next (struct ver_iter *, lsquic_ver_tag_t *ver_tag); 168 169size_t 170lsquic_packet_in_mem_used (const struct lsquic_packet_in *); 171 172void 173lsquic_scid_from_packet_in (const struct lsquic_packet_in *, 174 struct lsquic_cid *); 175 176#endif 177