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