lsquic_parse_Q046.c revision 4429f8ea
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, unsigned *packno_off_UNUSED, unsigned *packno_len_UNUSED)
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                            enum header_type unused)
220{
221    if (0 == (flags & PO_LONGHEAD))
222        return gquic_Q046_packout_header_size_short(lconn, flags);
223    else
224        return gquic_Q046_packout_header_size_long(lconn, flags);
225}
226
227
228static size_t
229gquic_Q046_packout_size (const struct lsquic_conn *lconn,
230                                const struct lsquic_packet_out *packet_out)
231{
232    size_t sz;
233
234    if (0 == (packet_out->po_flags & PO_LONGHEAD))
235        sz = gquic_Q046_packout_header_size_short(lconn, packet_out->po_flags);
236    else
237        sz = gquic_Q046_packout_header_size_long(lconn, packet_out->po_flags);
238
239    sz += packet_out->po_data_sz;
240    sz += GQUIC_PACKET_HASH_SZ;
241
242    return sz;
243}
244
245
246static void
247gquic_Q046_parse_packet_in_finish (struct lsquic_packet_in *packet_in,
248                                            struct packin_parse_state *state)
249{
250    lsquic_packno_t packno;
251
252    if (packet_in->pi_header_type == HETY_NOT_SET
253            /* We can't check in the beginning because we don't know whether
254             * this is Q046 or ID-18.  This is a bit hacky.
255             */
256            && state->pps_p + state->pps_nbytes
257                                <= packet_in->pi_data + packet_in->pi_data_sz)
258    {
259        READ_UINT(packno, 64, state->pps_p, state->pps_nbytes);
260        packet_in->pi_packno = packno;
261        packet_in->pi_header_sz += state->pps_nbytes;
262    }
263}
264
265
266static int
267gquic_Q046_gen_crypto_frame (unsigned char *buf, size_t buf_len,
268        lsquic_stream_id_t stream_id, uint64_t offset, int fin, size_t size,
269        gsf_read_f gsf_read, void *stream)
270{
271    assert(0);
272    return -1;
273}
274
275
276static int
277gquic_Q046_parse_crypto_frame (const unsigned char *buf, size_t rem_packet_sz,
278                                            struct stream_frame *stream_frame)
279{
280    assert(0);
281    return -1;
282}
283
284
285/* No simple PRST for Q046 */
286static ssize_t
287gquic_Q046_generate_simple_prst (const lsquic_cid_t *cidp, unsigned char *buf,
288                                                                size_t buf_sz)
289{
290    return -1;
291}
292
293
294static unsigned
295gquic_Q046_handshake_done_frame_size (void)
296{
297    return 0;
298}
299
300
301static int
302gquic_Q046_gen_handshake_done_frame (unsigned char *buf, size_t buf_len)
303{
304    return -1;
305}
306
307
308static int
309gquic_Q046_parse_handshake_done_frame (const unsigned char *buf, size_t buf_len)
310{
311    return -1;
312}
313
314
315const struct parse_funcs lsquic_parse_funcs_gquic_Q046 =
316{
317    .pf_gen_reg_pkt_header            =  gquic_Q046_gen_reg_pkt_header,
318    .pf_parse_packet_in_finish        =  gquic_Q046_parse_packet_in_finish,
319    .pf_gen_stream_frame              =  lsquic_gquic_be_gen_stream_frame,
320    .pf_calc_stream_frame_header_sz   =  lsquic_calc_stream_frame_header_sz_gquic,
321    .pf_parse_stream_frame            =  lsquic_gquic_be_parse_stream_frame,
322    .pf_dec_stream_frame_size         =  lsquic_gquic_be_dec_stream_frame_size,
323    .pf_parse_ack_frame               =  lsquic_gquic_be_parse_ack_frame,
324    .pf_gen_ack_frame                 =  lsquic_gquic_be_gen_ack_frame,
325    .pf_gen_stop_waiting_frame        =  lsquic_gquic_be_gen_stop_waiting_frame,
326    .pf_parse_stop_waiting_frame      =  lsquic_gquic_be_parse_stop_waiting_frame,
327    .pf_skip_stop_waiting_frame       =  lsquic_gquic_be_skip_stop_waiting_frame,
328    .pf_gen_window_update_frame       =  lsquic_gquic_be_gen_window_update_frame,
329    .pf_parse_window_update_frame     =  lsquic_gquic_be_parse_window_update_frame,
330    .pf_gen_blocked_frame             =  lsquic_gquic_be_gen_blocked_frame,
331    .pf_parse_blocked_frame           =  lsquic_gquic_be_parse_blocked_frame,
332    .pf_gen_rst_frame                 =  lsquic_gquic_be_gen_rst_frame,
333    .pf_parse_rst_frame               =  lsquic_gquic_be_parse_rst_frame,
334    .pf_connect_close_frame_size      =  lsquic_gquic_be_connect_close_frame_size,
335    .pf_gen_connect_close_frame       =  lsquic_gquic_be_gen_connect_close_frame,
336    .pf_parse_connect_close_frame     =  lsquic_gquic_be_parse_connect_close_frame,
337    .pf_gen_goaway_frame              =  lsquic_gquic_be_gen_goaway_frame,
338    .pf_parse_goaway_frame            =  lsquic_gquic_be_parse_goaway_frame,
339    .pf_gen_ping_frame                =  lsquic_gquic_be_gen_ping_frame,
340#ifndef NDEBUG
341    .pf_write_float_time16            =  lsquic_gquic_be_write_float_time16,
342    .pf_read_float_time16             =  lsquic_gquic_be_read_float_time16,
343#endif
344    .pf_generate_simple_prst          =  gquic_Q046_generate_simple_prst,
345    .pf_parse_frame_type              =  lsquic_parse_frame_type_gquic_Q035_thru_Q046,
346    .pf_turn_on_fin                   =  lsquic_turn_on_fin_Q035_thru_Q046,
347    .pf_packout_size                  =  gquic_Q046_packout_size,
348    .pf_packout_max_header_size       =  gquic_Q046_packout_header_size,
349    .pf_calc_packno_bits              =  gquic_Q046_calc_packno_bits,
350    .pf_packno_bits2len               =  gquic_Q046_packno_bits2len,
351    .pf_gen_crypto_frame              =  gquic_Q046_gen_crypto_frame,
352    .pf_parse_crypto_frame            =  gquic_Q046_parse_crypto_frame,
353    .pf_gen_handshake_done_frame      =  gquic_Q046_gen_handshake_done_frame,
354    .pf_parse_handshake_done_frame    =  gquic_Q046_parse_handshake_done_frame,
355    .pf_handshake_done_frame_size     =  gquic_Q046_handshake_done_frame_size,
356};
357