lsquic_parse_Q046.c revision 55cd0b38
1/* Copyright (c) 2017 - 2019 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_packet_common.h"
19#include "lsquic_packet_in.h"
20#include "lsquic_packet_out.h"
21#include "lsquic_parse.h"
22#include "lsquic_parse_common.h"
23#include "lsquic_version.h"
24#include "lsquic.h"
25#include "lsquic_parse_gquic_be.h"
26#include "lsquic_byteswap.h"
27#include "lsquic_conn.h"
28
29#define LSQUIC_LOGGER_MODULE LSQLM_PARSE
30#include "lsquic_logger.h"
31
32
33
34
35static unsigned
36gquic_Q046_packno_bits2len (enum packno_bits bits)
37{
38    return bits + 1;
39}
40
41
42#define iquic_packno_bits2len gquic_Q046_packno_bits2len
43
44
45static enum packno_bits
46gquic_Q046_calc_packno_bits (lsquic_packno_t packno,
47                    lsquic_packno_t least_unacked, uint64_t n_in_flight)
48{
49    uint64_t delta;
50    unsigned bits;
51
52    delta = packno - least_unacked;
53    if (n_in_flight > delta)
54        delta = n_in_flight;
55
56    delta *= 4;
57    bits = (delta >= (1ULL <<  8))
58         + (delta >= (1ULL << 16))
59         + (delta >= (1ULL << 24))
60         ;
61
62    return bits;
63}
64
65
66static unsigned
67write_packno (unsigned char *p, lsquic_packno_t packno, enum packno_bits bits)
68{
69    unsigned char *const begin = p;
70
71    switch (bits)
72    {
73    case IQUIC_PACKNO_LEN_4:
74        *p++ = packno >> 24;
75        /* fall-through */
76    case IQUIC_PACKNO_LEN_3:
77        *p++ = packno >> 16;
78        /* fall-through */
79    case IQUIC_PACKNO_LEN_2:
80        *p++ = packno >> 8;
81        /* fall-through */
82    default:
83        *p++ = packno;
84    }
85
86    return p - begin;
87}
88
89
90static int
91gen_short_pkt_header (const struct lsquic_conn *lconn,
92            const struct lsquic_packet_out *packet_out, unsigned char *buf,
93                                                                size_t bufsz)
94{
95    unsigned packno_len, need;
96    enum packno_bits bits;
97
98    bits = lsquic_packet_out_packno_bits(packet_out);
99    packno_len = iquic_packno_bits2len(bits);
100
101    need = 1 + 8 /* CID */ + packno_len;
102
103    if (need > bufsz)
104        return -1;
105
106    *buf++ = 0x40 | bits;
107
108    memcpy(buf, &lconn->cn_cid, 8);
109    buf += 8;
110
111    (void) write_packno(buf, packet_out->po_packno, bits);
112
113    return need;
114}
115
116
117static size_t
118gquic_Q046_packout_header_size_long (const struct lsquic_conn *lconn,
119                                                enum packet_out_flags flags)
120{
121    return GQUIC_IETF_LONG_HEADER_SIZE;
122}
123
124
125/* [draft-ietf-quic-transport-17] Section-17.2 */
126static const unsigned char header_type_to_bin[] = {
127    [HETY_INITIAL]      = 0x0,
128    [HETY_0RTT]         = 0x1,
129    [HETY_HANDSHAKE]    = 0x2,
130    [HETY_RETRY]        = 0x3,
131};
132
133
134static int
135gen_long_pkt_header (const struct lsquic_conn *lconn,
136            const struct lsquic_packet_out *packet_out, unsigned char *buf,
137                                                                size_t bufsz)
138{
139    enum packno_bits packno_bits;
140    lsquic_ver_tag_t ver_tag;
141    unsigned char *p;
142    size_t need;
143
144    need = gquic_Q046_packout_header_size_long(lconn, packet_out->po_flags);
145    if (need > bufsz)
146    {
147        errno = EINVAL;
148        return -1;
149    }
150
151    p = buf;
152    packno_bits = IQUIC_PACKNO_LEN_4;
153    *p++ = 0x80 | 0x40
154         | (header_type_to_bin[ packet_out->po_header_type ] << 4)
155         | packno_bits;
156    ver_tag = lsquic_ver2tag(lconn->cn_version);
157    memcpy(p, &ver_tag, sizeof(ver_tag));
158    p += sizeof(ver_tag);
159
160    *p++ = 0x50;
161
162    memcpy(p, &lconn->cn_cid, 8);
163    p += 8;
164
165    p += write_packno(p, packet_out->po_packno, packno_bits);
166
167
168    assert(need == (unsigned int)(p - buf));
169    return p - buf;
170}
171
172
173static int
174gquic_Q046_gen_reg_pkt_header (const struct lsquic_conn *lconn,
175            const struct lsquic_packet_out *packet_out, unsigned char *buf,
176                                                                size_t bufsz)
177{
178    if (0 == (packet_out->po_flags & PO_LONGHEAD))
179        return gen_short_pkt_header(lconn, packet_out, buf, bufsz);
180    else
181        return gen_long_pkt_header(lconn, packet_out, buf, bufsz);
182}
183
184
185static size_t
186gquic_Q046_packout_header_size_short (const struct lsquic_conn *lconn,
187                                            enum packet_out_flags flags)
188{
189    enum packno_bits bits;
190    size_t sz;
191
192    bits = (flags >> POBIT_SHIFT) & 0x3;
193    sz = 1; /* Type */
194    sz += 8; /* CID */
195    sz += iquic_packno_bits2len(bits);
196
197    return sz;
198}
199
200
201static size_t
202gquic_Q046_packout_header_size (const struct lsquic_conn *lconn,
203                                enum packet_out_flags flags)
204{
205    if (0 == (flags & PO_LONGHEAD))
206        return gquic_Q046_packout_header_size_short(lconn, flags);
207    else
208        return gquic_Q046_packout_header_size_long(lconn, flags);
209}
210
211
212static size_t
213gquic_Q046_packout_size (const struct lsquic_conn *lconn,
214                                const struct lsquic_packet_out *packet_out)
215{
216    size_t sz;
217
218    if (0 == (packet_out->po_flags & PO_LONGHEAD))
219        sz = gquic_Q046_packout_header_size_short(lconn, packet_out->po_flags);
220    else
221        sz = gquic_Q046_packout_header_size_long(lconn, packet_out->po_flags);
222
223    sz += packet_out->po_data_sz;
224    sz += QUIC_PACKET_HASH_SZ;
225
226    return sz;
227}
228
229
230const struct parse_funcs lsquic_parse_funcs_gquic_Q046 =
231{
232    .pf_gen_reg_pkt_header            =  gquic_Q046_gen_reg_pkt_header,
233    .pf_parse_packet_in_finish        =  gquic_be_parse_packet_in_finish,
234    .pf_gen_stream_frame              =  gquic_be_gen_stream_frame,
235    .pf_calc_stream_frame_header_sz   =  calc_stream_frame_header_sz_gquic,
236    .pf_parse_stream_frame            =  gquic_be_parse_stream_frame,
237    .pf_parse_ack_frame               =  gquic_be_parse_ack_frame,
238    .pf_gen_ack_frame                 =  gquic_be_gen_ack_frame,
239    .pf_gen_stop_waiting_frame        =  gquic_be_gen_stop_waiting_frame,
240    .pf_parse_stop_waiting_frame      =  gquic_be_parse_stop_waiting_frame,
241    .pf_skip_stop_waiting_frame       =  gquic_be_skip_stop_waiting_frame,
242    .pf_gen_window_update_frame       =  gquic_be_gen_window_update_frame,
243    .pf_parse_window_update_frame     =  gquic_be_parse_window_update_frame,
244    .pf_gen_blocked_frame             =  gquic_be_gen_blocked_frame,
245    .pf_parse_blocked_frame           =  gquic_be_parse_blocked_frame,
246    .pf_gen_rst_frame                 =  gquic_be_gen_rst_frame,
247    .pf_parse_rst_frame               =  gquic_be_parse_rst_frame,
248    .pf_gen_connect_close_frame       =  gquic_be_gen_connect_close_frame,
249    .pf_parse_connect_close_frame     =  gquic_be_parse_connect_close_frame,
250    .pf_gen_goaway_frame              =  gquic_be_gen_goaway_frame,
251    .pf_parse_goaway_frame            =  gquic_be_parse_goaway_frame,
252    .pf_gen_ping_frame                =  gquic_be_gen_ping_frame,
253#ifndef NDEBUG
254    .pf_write_float_time16            =  gquic_be_write_float_time16,
255    .pf_read_float_time16             =  gquic_be_read_float_time16,
256#endif
257    .pf_parse_frame_type              =  parse_frame_type_gquic_Q035_thru_Q039,
258    .pf_turn_on_fin                   =  lsquic_turn_on_fin_Q035_thru_Q039,
259    .pf_packout_size                  =  gquic_Q046_packout_size,
260    .pf_packout_header_size           =  gquic_Q046_packout_header_size,
261    .pf_calc_packno_bits              =  gquic_Q046_calc_packno_bits,
262    .pf_packno_bits2len               =  gquic_Q046_packno_bits2len,
263};
264