lsquic_parse_Q046.c revision b8fa6195
1/* Copyright (c) 2017 - 2020 LiteSpeed Technologies Inc.  See LICENSE. */
2/*
3 * lsquic_parse_Q046.c -- Parsing functions specific to GQUIC Q046
4 */
5
6#include <assert.h>
7#include <errno.h>
8#include <inttypes.h>
9#include <string.h>
10#include <sys/queue.h>
11#ifndef WIN32
12#include <sys/types.h>
13#else
14#include <vc_compat.h>
15#endif
16
17#include "lsquic_types.h"
18#include "lsquic_int_types.h"
19#include "lsquic_packet_common.h"
20#include "lsquic_packet_in.h"
21#include "lsquic_packet_out.h"
22#include "lsquic_parse.h"
23#include "lsquic_parse_common.h"
24#include "lsquic_version.h"
25#include "lsquic.h"
26#include "lsquic_parse_gquic_be.h"
27#include "lsquic_byteswap.h"
28#include "lsquic_hash.h"
29#include "lsquic_conn.h"
30
31#define LSQUIC_LOGGER_MODULE LSQLM_PARSE
32#include "lsquic_logger.h"
33
34
35static unsigned
36gquic_Q046_packno_bits2len (enum packno_bits bits)
37{
38    return bits + 1;
39}
40
41#define iquic_packno_bits2len gquic_Q046_packno_bits2len
42
43
44static enum packno_bits
45gquic_Q046_calc_packno_bits (lsquic_packno_t packno,
46                    lsquic_packno_t least_unacked, uint64_t n_in_flight)
47{
48    uint64_t delta;
49    unsigned bits;
50
51    delta = packno - least_unacked;
52    if (n_in_flight > delta)
53        delta = n_in_flight;
54
55    delta *= 4;
56    bits = (delta >= (1ULL <<  8))
57         + (delta >= (1ULL << 16))
58         + (delta >= (1ULL << 24))
59         ;
60
61    return bits;
62}
63
64
65static unsigned
66write_packno (unsigned char *p, lsquic_packno_t packno, enum packno_bits bits)
67{
68    unsigned char *const begin = p;
69
70    switch (bits)
71    {
72    case IQUIC_PACKNO_LEN_4:
73        *p++ = packno >> 24;
74        /* fall-through */
75    case IQUIC_PACKNO_LEN_3:
76        *p++ = packno >> 16;
77        /* fall-through */
78    case IQUIC_PACKNO_LEN_2:
79        *p++ = packno >> 8;
80        /* fall-through */
81    default:
82        *p++ = packno;
83    }
84
85    return p - begin;
86}
87
88
89static int
90gen_short_pkt_header (const struct lsquic_conn *lconn,
91            const struct lsquic_packet_out *packet_out, unsigned char *buf,
92                                                                size_t bufsz)
93{
94    unsigned packno_len, need;
95    enum packno_bits bits;
96
97    bits = lsquic_packet_out_packno_bits(packet_out);
98    packno_len = iquic_packno_bits2len(bits);
99
100    if (lconn->cn_flags & LSCONN_SERVER)
101        need = 1 + packno_len;
102    else
103        need = 1 + 8 /* CID */ + packno_len;
104
105    if (need > bufsz)
106        return -1;
107
108    *buf++ = 0x40 | bits;
109
110    if (0 == (lconn->cn_flags & LSCONN_SERVER))
111    {
112        memcpy(buf, lconn->cn_cid.idbuf, 8);
113        buf += 8;
114    }
115
116    (void) write_packno(buf, packet_out->po_packno, bits);
117
118    return need;
119}
120
121
122static size_t
123gquic_Q046_packout_header_size_long (const struct lsquic_conn *lconn,
124                                                enum packet_out_flags flags)
125{
126    if ((lconn->cn_flags & LSCONN_SERVER) && (flags & PO_NONCE))
127        return GQUIC_IETF_LONG_HEADER_SIZE + 32;
128    return GQUIC_IETF_LONG_HEADER_SIZE;
129}
130
131
132/* [draft-ietf-quic-transport-17] Section-17.2 */
133static const unsigned char header_type_to_bin[] = {
134    [HETY_INITIAL]      = 0x0,
135    [HETY_0RTT]         = 0x1,
136    [HETY_HANDSHAKE]    = 0x2,
137    [HETY_RETRY]        = 0x3,
138};
139
140
141static int
142gen_long_pkt_header (const struct lsquic_conn *lconn,
143            const struct lsquic_packet_out *packet_out, unsigned char *buf,
144                                                                size_t bufsz)
145{
146    enum packno_bits packno_bits;
147    lsquic_ver_tag_t ver_tag;
148    unsigned char *p;
149    size_t need;
150
151    need = gquic_Q046_packout_header_size_long(lconn, packet_out->po_flags);
152    if (need > bufsz)
153    {
154        errno = EINVAL;
155        return -1;
156    }
157
158    p = buf;
159    packno_bits = IQUIC_PACKNO_LEN_4;
160    *p++ = 0x80 | 0x40
161         | (header_type_to_bin[ packet_out->po_header_type ] << 4)
162         | packno_bits;
163    ver_tag = lsquic_ver2tag(lconn->cn_version);
164    memcpy(p, &ver_tag, sizeof(ver_tag));
165    p += sizeof(ver_tag);
166
167    if (lconn->cn_flags & LSCONN_SERVER)
168        *p++ = 0x05;
169    else
170        *p++ = 0x50;
171
172    memcpy(p, lconn->cn_cid.idbuf, 8);
173    p += 8;
174
175    p += write_packno(p, packet_out->po_packno, packno_bits);
176
177    if (packet_out->po_nonce)
178    {
179        memcpy(p, packet_out->po_nonce, 32);
180        p += 32;
181    }
182
183    assert(need == (unsigned int)(p - buf));
184    return p - buf;
185}
186
187
188static int
189gquic_Q046_gen_reg_pkt_header (const struct lsquic_conn *lconn,
190            const struct lsquic_packet_out *packet_out, unsigned char *buf,
191                                                                size_t bufsz)
192{
193    if (0 == (packet_out->po_flags & PO_LONGHEAD))
194        return gen_short_pkt_header(lconn, packet_out, buf, bufsz);
195    else
196        return gen_long_pkt_header(lconn, packet_out, buf, bufsz);
197}
198
199
200static size_t
201gquic_Q046_packout_header_size_short (const struct lsquic_conn *lconn,
202                                            enum packet_out_flags flags)
203{
204    enum packno_bits bits;
205    size_t sz;
206
207    bits = (flags >> POBIT_SHIFT) & 0x3;
208    sz = 1; /* Type */
209    sz += (lconn->cn_flags & LSCONN_SERVER) ? 0 : 8;
210    sz += iquic_packno_bits2len(bits);
211
212    return sz;
213}
214
215
216static size_t
217gquic_Q046_packout_header_size (const struct lsquic_conn *lconn,
218                            enum packet_out_flags flags, size_t dcid_len_unused)
219{
220    if (0 == (flags & PO_LONGHEAD))
221        return gquic_Q046_packout_header_size_short(lconn, flags);
222    else
223        return gquic_Q046_packout_header_size_long(lconn, flags);
224}
225
226
227static size_t
228gquic_Q046_packout_size (const struct lsquic_conn *lconn,
229                                const struct lsquic_packet_out *packet_out)
230{
231    size_t sz;
232
233    if (0 == (packet_out->po_flags & PO_LONGHEAD))
234        sz = gquic_Q046_packout_header_size_short(lconn, packet_out->po_flags);
235    else
236        sz = gquic_Q046_packout_header_size_long(lconn, packet_out->po_flags);
237
238    sz += packet_out->po_data_sz;
239    sz += GQUIC_PACKET_HASH_SZ;
240
241    return sz;
242}
243
244
245static void
246gquic_Q046_parse_packet_in_finish (struct lsquic_packet_in *packet_in,
247                                            struct packin_parse_state *state)
248{
249    lsquic_packno_t packno;
250
251    if (packet_in->pi_header_type == HETY_NOT_SET
252            /* We can't check in the beginning because we don't know whether
253             * this is Q046 or ID-18.  This is a bit hacky.
254             */
255            && state->pps_p + state->pps_nbytes
256                                <= packet_in->pi_data + packet_in->pi_data_sz)
257    {
258        READ_UINT(packno, 64, state->pps_p, state->pps_nbytes);
259        packet_in->pi_packno = packno;
260        packet_in->pi_header_sz += state->pps_nbytes;
261    }
262}
263
264
265static int
266gquic_Q046_gen_crypto_frame (unsigned char *buf, size_t buf_len,
267        lsquic_stream_id_t stream_id, uint64_t offset, int fin, size_t size,
268        gsf_read_f gsf_read, void *stream)
269{
270    assert(0);
271    return -1;
272}
273
274
275static int
276gquic_Q046_parse_crypto_frame (const unsigned char *buf, size_t rem_packet_sz,
277                                            struct stream_frame *stream_frame)
278{
279    assert(0);
280    return -1;
281}
282
283
284static void
285gquic_Q046_packno_info (const struct lsquic_conn *lconn,
286        const struct lsquic_packet_out *packet_out, unsigned *packno_off,
287        unsigned *packno_len)
288{
289    assert(0);
290}
291
292
293/* No simple PRST for Q046 */
294static ssize_t
295gquic_Q046_generate_simple_prst (const lsquic_cid_t *cidp, unsigned char *buf,
296                                                                size_t buf_sz)
297{
298    return -1;
299}
300
301
302static unsigned
303gquic_Q046_handshake_done_frame_size (void)
304{
305    return 0;
306}
307
308
309static int
310gquic_Q046_gen_handshake_done_frame (unsigned char *buf, size_t buf_len)
311{
312    return -1;
313}
314
315
316static int
317gquic_Q046_parse_handshake_done_frame (const unsigned char *buf, size_t buf_len)
318{
319    return -1;
320}
321
322
323const struct parse_funcs lsquic_parse_funcs_gquic_Q046 =
324{
325    .pf_gen_reg_pkt_header            =  gquic_Q046_gen_reg_pkt_header,
326    .pf_parse_packet_in_finish        =  gquic_Q046_parse_packet_in_finish,
327    .pf_gen_stream_frame              =  lsquic_gquic_be_gen_stream_frame,
328    .pf_calc_stream_frame_header_sz   =  lsquic_calc_stream_frame_header_sz_gquic,
329    .pf_parse_stream_frame            =  lsquic_gquic_be_parse_stream_frame,
330    .pf_parse_ack_frame               =  lsquic_gquic_be_parse_ack_frame,
331    .pf_gen_ack_frame                 =  lsquic_gquic_be_gen_ack_frame,
332    .pf_gen_stop_waiting_frame        =  lsquic_gquic_be_gen_stop_waiting_frame,
333    .pf_parse_stop_waiting_frame      =  lsquic_gquic_be_parse_stop_waiting_frame,
334    .pf_skip_stop_waiting_frame       =  lsquic_gquic_be_skip_stop_waiting_frame,
335    .pf_gen_window_update_frame       =  lsquic_gquic_be_gen_window_update_frame,
336    .pf_parse_window_update_frame     =  lsquic_gquic_be_parse_window_update_frame,
337    .pf_gen_blocked_frame             =  lsquic_gquic_be_gen_blocked_frame,
338    .pf_parse_blocked_frame           =  lsquic_gquic_be_parse_blocked_frame,
339    .pf_gen_rst_frame                 =  lsquic_gquic_be_gen_rst_frame,
340    .pf_parse_rst_frame               =  lsquic_gquic_be_parse_rst_frame,
341    .pf_connect_close_frame_size      =  lsquic_gquic_be_connect_close_frame_size,
342    .pf_gen_connect_close_frame       =  lsquic_gquic_be_gen_connect_close_frame,
343    .pf_parse_connect_close_frame     =  lsquic_gquic_be_parse_connect_close_frame,
344    .pf_gen_goaway_frame              =  lsquic_gquic_be_gen_goaway_frame,
345    .pf_parse_goaway_frame            =  lsquic_gquic_be_parse_goaway_frame,
346    .pf_gen_ping_frame                =  lsquic_gquic_be_gen_ping_frame,
347#ifndef NDEBUG
348    .pf_write_float_time16            =  lsquic_gquic_be_write_float_time16,
349    .pf_read_float_time16             =  lsquic_gquic_be_read_float_time16,
350#endif
351    .pf_generate_simple_prst          =  gquic_Q046_generate_simple_prst,
352    .pf_parse_frame_type              =  lsquic_parse_frame_type_gquic_Q035_thru_Q046,
353    .pf_turn_on_fin                   =  lsquic_turn_on_fin_Q035_thru_Q046,
354    .pf_packout_size                  =  gquic_Q046_packout_size,
355    .pf_packout_max_header_size       =  gquic_Q046_packout_header_size,
356    .pf_calc_packno_bits              =  gquic_Q046_calc_packno_bits,
357    .pf_packno_bits2len               =  gquic_Q046_packno_bits2len,
358    .pf_gen_crypto_frame              =  gquic_Q046_gen_crypto_frame,
359    .pf_parse_crypto_frame            =  gquic_Q046_parse_crypto_frame,
360    .pf_packno_info                   =  gquic_Q046_packno_info,
361    .pf_gen_handshake_done_frame      =  gquic_Q046_gen_handshake_done_frame,
362    .pf_parse_handshake_done_frame    =  gquic_Q046_parse_handshake_done_frame,
363    .pf_handshake_done_frame_size     =  gquic_Q046_handshake_done_frame_size,
364};
365