lsquic_parse_gquic_common.c revision 7a8b2ece
1/* Copyright (c) 2017 - 2019 LiteSpeed Technologies Inc.  See LICENSE. */
2/*
3 * lsquic_parse_gquic_common.c -- Parsing functions common to GQUIC
4 */
5
6#include <assert.h>
7#include <errno.h>
8#include <inttypes.h>
9#include <string.h>
10#include <stdlib.h>
11#include <sys/queue.h>
12#ifndef WIN32
13#include <sys/types.h>
14#else
15#include <vc_compat.h>
16#endif
17
18#include "lsquic_types.h"
19#include "lsquic_int_types.h"
20#include "lsquic_packet_common.h"
21#include "lsquic_packet_out.h"
22#include "lsquic_packet_gquic.h"
23#include "lsquic_packet_in.h"
24#include "lsquic_packet_out.h"
25#include "lsquic_parse_common.h"
26#include "lsquic_parse.h"
27#include "lsquic_parse_common.h"
28#include "lsquic_version.h"
29#include "lsquic.h"
30
31#define LSQUIC_LOGGER_MODULE LSQLM_PARSE
32#include "lsquic_logger.h"
33
34#define CHECK_SPACE(need, pstart, pend)  \
35    do { if ((intptr_t) (need) > ((pend) - (pstart))) { return -1; } } while (0)
36
37/* This partially parses `packet_in' and returns 0 if in case it succeeded and
38 * -1 on failure.
39 *
40 * After this function returns 0, connection ID, nonce, and version fields can
41 * be examined.  To finsh parsing the packet, call version-specific
42 * pf_parse_packet_in_finish() routine.
43 */
44int
45lsquic_gquic_parse_packet_in_begin (lsquic_packet_in_t *packet_in,
46                size_t length, int is_server, unsigned cid_len,
47                struct packin_parse_state *state)
48{
49    int nbytes;
50    enum PACKET_PUBLIC_FLAGS public_flags;
51    const unsigned char *p = packet_in->pi_data;
52    const unsigned char *const pend = packet_in->pi_data + length;
53
54    if (length > GQUIC_MAX_PACKET_SZ)
55    {
56        LSQ_DEBUG("Cannot handle packet_in_size(%zd) > %d packet incoming "
57            "packet's header", length, GQUIC_MAX_PACKET_SZ);
58        return -1;
59    }
60
61    CHECK_SPACE(1, p, pend);
62
63    public_flags = *p++;
64
65    if (public_flags & PACKET_PUBLIC_FLAGS_8BYTE_CONNECTION_ID)
66    {
67        CHECK_SPACE(8, p, pend);
68        memset(&packet_in->pi_conn_id, 0, sizeof(packet_in->pi_conn_id));
69        packet_in->pi_conn_id.len = 8;
70        memcpy(&packet_in->pi_conn_id.idbuf, p, 8);
71        packet_in->pi_flags |= PI_CONN_ID;
72        p += 8;
73    }
74
75    if (public_flags & PACKET_PUBLIC_FLAGS_VERSION)
76    {
77        /* It seems that version negotiation packets sent by Google may have
78         * NONCE bit set.  Ignore it:
79         */
80        public_flags &= ~PACKET_PUBLIC_FLAGS_NONCE;
81
82        if (is_server)
83        {
84            CHECK_SPACE(4, p, pend);
85            packet_in->pi_quic_ver = p - packet_in->pi_data;
86            p += 4;
87        }
88        else
89        {   /* OK, we have a version negotiation packet.  We need to verify
90             * that it has correct structure.  See Section 4.3 of
91             * [draft-ietf-quic-transport-00].
92             */
93            if ((public_flags & ~(PACKET_PUBLIC_FLAGS_VERSION|
94                                  PACKET_PUBLIC_FLAGS_8BYTE_CONNECTION_ID))
95                || ((pend - p) & 3))
96                return -1;
97            CHECK_SPACE(4, p, pend);
98            packet_in->pi_quic_ver = p - packet_in->pi_data;
99            p = pend;
100        }
101    }
102    else
103    {
104        /* From [draft-hamilton-quic-transport-protocol-01]:
105         *    0x40 = MULTIPATH. This bit is reserved for multipath use.
106         *    0x80 is currently unused, and must be set to 0.
107         *
108         * The reference implementation checks that two high bits are not set
109         * if version flag is not set or if the version is the same.  For our
110         * purposes, all GQUIC version we support so far have these bits set
111         * to zero.
112         */
113        if (public_flags & (0x80|0x40))
114            return -1;
115        packet_in->pi_quic_ver = 0;
116    }
117
118    if (!is_server && (public_flags & PACKET_PUBLIC_FLAGS_NONCE) ==
119                                            PACKET_PUBLIC_FLAGS_NONCE)
120    {
121        CHECK_SPACE(32, p, pend);
122        packet_in->pi_nonce = p - packet_in->pi_data;
123        p += 32;
124    }
125    else
126        packet_in->pi_nonce = 0;
127
128    state->pps_p = p;
129
130    packet_in->pi_packno = 0;
131    if (0 == (public_flags & (PACKET_PUBLIC_FLAGS_VERSION|PACKET_PUBLIC_FLAGS_RST))
132        || ((public_flags & PACKET_PUBLIC_FLAGS_VERSION) && is_server))
133    {
134        nbytes = twobit_to_1246((public_flags >> 4) & 3);
135        CHECK_SPACE(nbytes, p, pend);
136        p += nbytes;
137        state->pps_nbytes = nbytes;
138    }
139    else
140        state->pps_nbytes = 0;
141
142    packet_in->pi_header_sz    = p - packet_in->pi_data;
143    packet_in->pi_frame_types  = 0;
144    memset(&packet_in->pi_next, 0, sizeof(packet_in->pi_next));
145    packet_in->pi_data_sz      = length;
146    packet_in->pi_refcnt       = 0;
147    packet_in->pi_received     = 0;
148    packet_in->pi_flags       |= PI_GQUIC;
149    packet_in->pi_flags       |= ((public_flags >> 4) & 3) << PIBIT_BITS_SHIFT;
150
151    return 0;
152}
153
154
155static const unsigned char simple_prst_payload[] = {
156    'P', 'R', 'S', 'T',
157    0x01, 0x00, 0x00, 0x00,
158    'R', 'N', 'O', 'N',
159    0x08, 0x00, 0x00, 0x00,
160    1, 2, 3, 4, 5, 6, 7, 8,
161};
162
163
164typedef char correct_simple_prst_size[(GQUIC_RESET_SZ ==
165                1 + GQUIC_CID_LEN + sizeof(simple_prst_payload)) - 1];
166
167
168ssize_t
169lsquic_generate_gquic_reset (const lsquic_cid_t *cidp,
170                                        unsigned char *buf, size_t buf_sz)
171{
172    lsquic_cid_t cid;
173
174    if (buf_sz < 1 + GQUIC_CID_LEN + sizeof(simple_prst_payload))
175    {
176        errno = ENOBUFS;
177        return -1;
178    }
179
180    if (cidp)
181    {
182        assert(GQUIC_CID_LEN == cidp->len);
183        cid = *cidp;
184    }
185    else
186    {
187        memset(&cid, 0, sizeof(cid));
188        cid.len = GQUIC_CID_LEN;
189    }
190
191    *buf++ = PACKET_PUBLIC_FLAGS_RST | PACKET_PUBLIC_FLAGS_8BYTE_CONNECTION_ID;
192
193    memcpy(buf, cid.idbuf, GQUIC_CID_LEN);
194    buf += GQUIC_CID_LEN;
195
196    memcpy(buf, simple_prst_payload, sizeof(simple_prst_payload));
197    return 1 + GQUIC_CID_LEN + sizeof(simple_prst_payload);
198}
199
200
201static const enum quic_frame_type byte2frame_type_Q035_thru_Q046[0x100] =
202{
203    [0x00] = QUIC_FRAME_PADDING,
204    [0x01] = QUIC_FRAME_RST_STREAM,
205    [0x02] = QUIC_FRAME_CONNECTION_CLOSE,
206    [0x03] = QUIC_FRAME_GOAWAY,
207    [0x04] = QUIC_FRAME_WINDOW_UPDATE,
208    [0x05] = QUIC_FRAME_BLOCKED,
209    [0x06] = QUIC_FRAME_STOP_WAITING,
210    [0x07] = QUIC_FRAME_PING,
211    [0x08] = QUIC_FRAME_INVALID,
212    [0x09] = QUIC_FRAME_INVALID,
213    [0x0A] = QUIC_FRAME_INVALID,
214    [0x0B] = QUIC_FRAME_INVALID,
215    [0x0C] = QUIC_FRAME_INVALID,
216    [0x0D] = QUIC_FRAME_INVALID,
217    [0x0E] = QUIC_FRAME_INVALID,
218    [0x0F] = QUIC_FRAME_INVALID,
219    [0x10] = QUIC_FRAME_INVALID,
220    [0x11] = QUIC_FRAME_INVALID,
221    [0x12] = QUIC_FRAME_INVALID,
222    [0x13] = QUIC_FRAME_INVALID,
223    [0x14] = QUIC_FRAME_INVALID,
224    [0x15] = QUIC_FRAME_INVALID,
225    [0x16] = QUIC_FRAME_INVALID,
226    [0x17] = QUIC_FRAME_INVALID,
227    [0x18] = QUIC_FRAME_INVALID,
228    [0x19] = QUIC_FRAME_INVALID,
229    [0x1A] = QUIC_FRAME_INVALID,
230    [0x1B] = QUIC_FRAME_INVALID,
231    [0x1C] = QUIC_FRAME_INVALID,
232    [0x1D] = QUIC_FRAME_INVALID,
233    [0x1E] = QUIC_FRAME_INVALID,
234    [0x1F] = QUIC_FRAME_INVALID,
235    [0x20] = QUIC_FRAME_INVALID,
236    [0x21] = QUIC_FRAME_INVALID,
237    [0x22] = QUIC_FRAME_INVALID,
238    [0x23] = QUIC_FRAME_INVALID,
239    [0x24] = QUIC_FRAME_INVALID,
240    [0x25] = QUIC_FRAME_INVALID,
241    [0x26] = QUIC_FRAME_INVALID,
242    [0x27] = QUIC_FRAME_INVALID,
243    [0x28] = QUIC_FRAME_INVALID,
244    [0x29] = QUIC_FRAME_INVALID,
245    [0x2A] = QUIC_FRAME_INVALID,
246    [0x2B] = QUIC_FRAME_INVALID,
247    [0x2C] = QUIC_FRAME_INVALID,
248    [0x2D] = QUIC_FRAME_INVALID,
249    [0x2E] = QUIC_FRAME_INVALID,
250    [0x2F] = QUIC_FRAME_INVALID,
251    [0x30] = QUIC_FRAME_INVALID,
252    [0x31] = QUIC_FRAME_INVALID,
253    [0x32] = QUIC_FRAME_INVALID,
254    [0x33] = QUIC_FRAME_INVALID,
255    [0x34] = QUIC_FRAME_INVALID,
256    [0x35] = QUIC_FRAME_INVALID,
257    [0x36] = QUIC_FRAME_INVALID,
258    [0x37] = QUIC_FRAME_INVALID,
259    [0x38] = QUIC_FRAME_INVALID,
260    [0x39] = QUIC_FRAME_INVALID,
261    [0x3A] = QUIC_FRAME_INVALID,
262    [0x3B] = QUIC_FRAME_INVALID,
263    [0x3C] = QUIC_FRAME_INVALID,
264    [0x3D] = QUIC_FRAME_INVALID,
265    [0x3E] = QUIC_FRAME_INVALID,
266    [0x3F] = QUIC_FRAME_INVALID,
267    [0x40] = QUIC_FRAME_ACK,
268    [0x41] = QUIC_FRAME_ACK,
269    [0x42] = QUIC_FRAME_ACK,
270    [0x43] = QUIC_FRAME_ACK,
271    [0x44] = QUIC_FRAME_ACK,
272    [0x45] = QUIC_FRAME_ACK,
273    [0x46] = QUIC_FRAME_ACK,
274    [0x47] = QUIC_FRAME_ACK,
275    [0x48] = QUIC_FRAME_ACK,
276    [0x49] = QUIC_FRAME_ACK,
277    [0x4A] = QUIC_FRAME_ACK,
278    [0x4B] = QUIC_FRAME_ACK,
279    [0x4C] = QUIC_FRAME_ACK,
280    [0x4D] = QUIC_FRAME_ACK,
281    [0x4E] = QUIC_FRAME_ACK,
282    [0x4F] = QUIC_FRAME_ACK,
283    [0x50] = QUIC_FRAME_ACK,
284    [0x51] = QUIC_FRAME_ACK,
285    [0x52] = QUIC_FRAME_ACK,
286    [0x53] = QUIC_FRAME_ACK,
287    [0x54] = QUIC_FRAME_ACK,
288    [0x55] = QUIC_FRAME_ACK,
289    [0x56] = QUIC_FRAME_ACK,
290    [0x57] = QUIC_FRAME_ACK,
291    [0x58] = QUIC_FRAME_ACK,
292    [0x59] = QUIC_FRAME_ACK,
293    [0x5A] = QUIC_FRAME_ACK,
294    [0x5B] = QUIC_FRAME_ACK,
295    [0x5C] = QUIC_FRAME_ACK,
296    [0x5D] = QUIC_FRAME_ACK,
297    [0x5E] = QUIC_FRAME_ACK,
298    [0x5F] = QUIC_FRAME_ACK,
299    [0x60] = QUIC_FRAME_ACK,
300    [0x61] = QUIC_FRAME_ACK,
301    [0x62] = QUIC_FRAME_ACK,
302    [0x63] = QUIC_FRAME_ACK,
303    [0x64] = QUIC_FRAME_ACK,
304    [0x65] = QUIC_FRAME_ACK,
305    [0x66] = QUIC_FRAME_ACK,
306    [0x67] = QUIC_FRAME_ACK,
307    [0x68] = QUIC_FRAME_ACK,
308    [0x69] = QUIC_FRAME_ACK,
309    [0x6A] = QUIC_FRAME_ACK,
310    [0x6B] = QUIC_FRAME_ACK,
311    [0x6C] = QUIC_FRAME_ACK,
312    [0x6D] = QUIC_FRAME_ACK,
313    [0x6E] = QUIC_FRAME_ACK,
314    [0x6F] = QUIC_FRAME_ACK,
315    [0x70] = QUIC_FRAME_ACK,
316    [0x71] = QUIC_FRAME_ACK,
317    [0x72] = QUIC_FRAME_ACK,
318    [0x73] = QUIC_FRAME_ACK,
319    [0x74] = QUIC_FRAME_ACK,
320    [0x75] = QUIC_FRAME_ACK,
321    [0x76] = QUIC_FRAME_ACK,
322    [0x77] = QUIC_FRAME_ACK,
323    [0x78] = QUIC_FRAME_ACK,
324    [0x79] = QUIC_FRAME_ACK,
325    [0x7A] = QUIC_FRAME_ACK,
326    [0x7B] = QUIC_FRAME_ACK,
327    [0x7C] = QUIC_FRAME_ACK,
328    [0x7D] = QUIC_FRAME_ACK,
329    [0x7E] = QUIC_FRAME_ACK,
330    [0x7F] = QUIC_FRAME_ACK,
331    [0x80] = QUIC_FRAME_STREAM,
332    [0x81] = QUIC_FRAME_STREAM,
333    [0x82] = QUIC_FRAME_STREAM,
334    [0x83] = QUIC_FRAME_STREAM,
335    [0x84] = QUIC_FRAME_STREAM,
336    [0x85] = QUIC_FRAME_STREAM,
337    [0x86] = QUIC_FRAME_STREAM,
338    [0x87] = QUIC_FRAME_STREAM,
339    [0x88] = QUIC_FRAME_STREAM,
340    [0x89] = QUIC_FRAME_STREAM,
341    [0x8A] = QUIC_FRAME_STREAM,
342    [0x8B] = QUIC_FRAME_STREAM,
343    [0x8C] = QUIC_FRAME_STREAM,
344    [0x8D] = QUIC_FRAME_STREAM,
345    [0x8E] = QUIC_FRAME_STREAM,
346    [0x8F] = QUIC_FRAME_STREAM,
347    [0x90] = QUIC_FRAME_STREAM,
348    [0x91] = QUIC_FRAME_STREAM,
349    [0x92] = QUIC_FRAME_STREAM,
350    [0x93] = QUIC_FRAME_STREAM,
351    [0x94] = QUIC_FRAME_STREAM,
352    [0x95] = QUIC_FRAME_STREAM,
353    [0x96] = QUIC_FRAME_STREAM,
354    [0x97] = QUIC_FRAME_STREAM,
355    [0x98] = QUIC_FRAME_STREAM,
356    [0x99] = QUIC_FRAME_STREAM,
357    [0x9A] = QUIC_FRAME_STREAM,
358    [0x9B] = QUIC_FRAME_STREAM,
359    [0x9C] = QUIC_FRAME_STREAM,
360    [0x9D] = QUIC_FRAME_STREAM,
361    [0x9E] = QUIC_FRAME_STREAM,
362    [0x9F] = QUIC_FRAME_STREAM,
363    [0xA0] = QUIC_FRAME_STREAM,
364    [0xA1] = QUIC_FRAME_STREAM,
365    [0xA2] = QUIC_FRAME_STREAM,
366    [0xA3] = QUIC_FRAME_STREAM,
367    [0xA4] = QUIC_FRAME_STREAM,
368    [0xA5] = QUIC_FRAME_STREAM,
369    [0xA6] = QUIC_FRAME_STREAM,
370    [0xA7] = QUIC_FRAME_STREAM,
371    [0xA8] = QUIC_FRAME_STREAM,
372    [0xA9] = QUIC_FRAME_STREAM,
373    [0xAA] = QUIC_FRAME_STREAM,
374    [0xAB] = QUIC_FRAME_STREAM,
375    [0xAC] = QUIC_FRAME_STREAM,
376    [0xAD] = QUIC_FRAME_STREAM,
377    [0xAE] = QUIC_FRAME_STREAM,
378    [0xAF] = QUIC_FRAME_STREAM,
379    [0xB0] = QUIC_FRAME_STREAM,
380    [0xB1] = QUIC_FRAME_STREAM,
381    [0xB2] = QUIC_FRAME_STREAM,
382    [0xB3] = QUIC_FRAME_STREAM,
383    [0xB4] = QUIC_FRAME_STREAM,
384    [0xB5] = QUIC_FRAME_STREAM,
385    [0xB6] = QUIC_FRAME_STREAM,
386    [0xB7] = QUIC_FRAME_STREAM,
387    [0xB8] = QUIC_FRAME_STREAM,
388    [0xB9] = QUIC_FRAME_STREAM,
389    [0xBA] = QUIC_FRAME_STREAM,
390    [0xBB] = QUIC_FRAME_STREAM,
391    [0xBC] = QUIC_FRAME_STREAM,
392    [0xBD] = QUIC_FRAME_STREAM,
393    [0xBE] = QUIC_FRAME_STREAM,
394    [0xBF] = QUIC_FRAME_STREAM,
395    [0xC0] = QUIC_FRAME_STREAM,
396    [0xC1] = QUIC_FRAME_STREAM,
397    [0xC2] = QUIC_FRAME_STREAM,
398    [0xC3] = QUIC_FRAME_STREAM,
399    [0xC4] = QUIC_FRAME_STREAM,
400    [0xC5] = QUIC_FRAME_STREAM,
401    [0xC6] = QUIC_FRAME_STREAM,
402    [0xC7] = QUIC_FRAME_STREAM,
403    [0xC8] = QUIC_FRAME_STREAM,
404    [0xC9] = QUIC_FRAME_STREAM,
405    [0xCA] = QUIC_FRAME_STREAM,
406    [0xCB] = QUIC_FRAME_STREAM,
407    [0xCC] = QUIC_FRAME_STREAM,
408    [0xCD] = QUIC_FRAME_STREAM,
409    [0xCE] = QUIC_FRAME_STREAM,
410    [0xCF] = QUIC_FRAME_STREAM,
411    [0xD0] = QUIC_FRAME_STREAM,
412    [0xD1] = QUIC_FRAME_STREAM,
413    [0xD2] = QUIC_FRAME_STREAM,
414    [0xD3] = QUIC_FRAME_STREAM,
415    [0xD4] = QUIC_FRAME_STREAM,
416    [0xD5] = QUIC_FRAME_STREAM,
417    [0xD6] = QUIC_FRAME_STREAM,
418    [0xD7] = QUIC_FRAME_STREAM,
419    [0xD8] = QUIC_FRAME_STREAM,
420    [0xD9] = QUIC_FRAME_STREAM,
421    [0xDA] = QUIC_FRAME_STREAM,
422    [0xDB] = QUIC_FRAME_STREAM,
423    [0xDC] = QUIC_FRAME_STREAM,
424    [0xDD] = QUIC_FRAME_STREAM,
425    [0xDE] = QUIC_FRAME_STREAM,
426    [0xDF] = QUIC_FRAME_STREAM,
427    [0xE0] = QUIC_FRAME_STREAM,
428    [0xE1] = QUIC_FRAME_STREAM,
429    [0xE2] = QUIC_FRAME_STREAM,
430    [0xE3] = QUIC_FRAME_STREAM,
431    [0xE4] = QUIC_FRAME_STREAM,
432    [0xE5] = QUIC_FRAME_STREAM,
433    [0xE6] = QUIC_FRAME_STREAM,
434    [0xE7] = QUIC_FRAME_STREAM,
435    [0xE8] = QUIC_FRAME_STREAM,
436    [0xE9] = QUIC_FRAME_STREAM,
437    [0xEA] = QUIC_FRAME_STREAM,
438    [0xEB] = QUIC_FRAME_STREAM,
439    [0xEC] = QUIC_FRAME_STREAM,
440    [0xED] = QUIC_FRAME_STREAM,
441    [0xEE] = QUIC_FRAME_STREAM,
442    [0xEF] = QUIC_FRAME_STREAM,
443    [0xF0] = QUIC_FRAME_STREAM,
444    [0xF1] = QUIC_FRAME_STREAM,
445    [0xF2] = QUIC_FRAME_STREAM,
446    [0xF3] = QUIC_FRAME_STREAM,
447    [0xF4] = QUIC_FRAME_STREAM,
448    [0xF5] = QUIC_FRAME_STREAM,
449    [0xF6] = QUIC_FRAME_STREAM,
450    [0xF7] = QUIC_FRAME_STREAM,
451    [0xF8] = QUIC_FRAME_STREAM,
452    [0xF9] = QUIC_FRAME_STREAM,
453    [0xFA] = QUIC_FRAME_STREAM,
454    [0xFB] = QUIC_FRAME_STREAM,
455    [0xFC] = QUIC_FRAME_STREAM,
456    [0xFD] = QUIC_FRAME_STREAM,
457    [0xFE] = QUIC_FRAME_STREAM,
458    [0xFF] = QUIC_FRAME_STREAM,
459};
460
461
462enum quic_frame_type
463lsquic_parse_frame_type_gquic_Q035_thru_Q046 (unsigned char b)
464{
465    return byte2frame_type_Q035_thru_Q046[b];
466}
467
468
469void
470lsquic_turn_on_fin_Q035_thru_Q046 (unsigned char *stream_header)
471{
472    /* 1fdoooss */
473    *stream_header |= 0x40;
474}
475
476
477size_t
478calc_stream_frame_header_sz_gquic (lsquic_stream_id_t stream_id,
479                                    uint64_t offset, unsigned data_sz_IGNORED)
480{
481    return
482        /* Type */
483        1
484        /* Stream ID length */
485      + ((stream_id) > 0x0000FF)
486      + ((stream_id) > 0x00FFFF)
487      + ((stream_id) > 0xFFFFFF)
488      + 1
489        /* Offset length */
490      + ((offset) >= (1ULL << 56))
491      + ((offset) >= (1ULL << 48))
492      + ((offset) >= (1ULL << 40))
493      + ((offset) >= (1ULL << 32))
494      + ((offset) >= (1ULL << 24))
495      + ((offset) >= (1ULL << 16))
496      + (((offset) > 0) << 1)
497        /* Add data length (2) yourself, if necessary */
498    ;
499}
500
501
502static const char *const ecn2str[4] =
503{
504    [ECN_NOT_ECT]   = "",
505    [ECN_ECT0]      = "ECT(0)",
506    [ECN_ECT1]      = "ECT(1)",
507    [ECN_CE]        = "CE",
508};
509
510
511#define ECN_COUNTS  " ECT(0): 01234567879012345678790;" \
512                    " ECT(1): 01234567879012345678790;" \
513                    " CE: 01234567879012345678790"
514#define RANGES_TRUNCATED " ranges truncated! "
515
516char *
517acki2str (const struct ack_info *acki, size_t *sz)
518{
519    size_t off, bufsz, nw;
520    enum ecn ecn;
521    unsigned n;
522    char *buf;
523
524    bufsz = acki->n_ranges * (3 /* [-] */ + 20 /* ~0ULL */ * 2)
525        + (acki->flags & AI_ECN ? sizeof(ECN_COUNTS) : 0)
526        + (acki->flags & AI_TRUNCATED ? sizeof(RANGES_TRUNCATED) : 0);
527    buf = malloc(bufsz);
528    if (!buf)
529    {
530        LSQ_WARN("%s: malloc(%zd) failure: %s", __func__, bufsz,
531                                                        strerror(errno));
532        return NULL;
533    }
534
535    off = 0;
536    for (n = 0; n < acki->n_ranges; ++n)
537    {
538        nw = snprintf(buf + off, bufsz - off, "[%"PRIu64"-%"PRIu64"]",
539                acki->ranges[n].high, acki->ranges[n].low);
540        if (nw > bufsz - off)
541            break;
542        off += nw;
543    }
544
545    if (acki->flags & AI_TRUNCATED)
546    {
547        nw = snprintf(buf + off, bufsz - off, RANGES_TRUNCATED);
548        if (nw > bufsz - off)
549        {
550            nw = bufsz - off;
551            goto end;
552        }
553        off += nw;
554    }
555
556    if (acki->flags & AI_ECN)
557    {
558        for (ecn = 1; ecn <= 3; ++ecn)
559        {
560            nw = snprintf(buf + off, bufsz - off, " %s: %"PRIu64"%.*s",
561                        ecn2str[ecn], acki->ecn_counts[ecn], ecn < 3, ";");
562            if (nw > bufsz - off)
563                break;
564            off += nw;
565        }
566    }
567
568  end:
569    *sz = off;
570    return buf;
571}
572
573
574size_t
575lsquic_gquic_po_header_sz (enum packet_out_flags flags)
576{
577    return 1                                                /* Type */
578           + (!!(flags & PO_CONN_ID) << 3)                  /* Connection ID */
579           + (!!(flags & PO_VERSION) << 2)                  /* Version */
580           + (!!(flags & PO_NONCE)   << 5)                  /* Nonce */
581           + gquic_packno_bits2len((flags >> POBIT_SHIFT) & 0x3)  /* Packet number */
582           ;
583}
584
585
586size_t
587lsquic_gquic_packout_size (const struct lsquic_conn *conn,
588                                const struct lsquic_packet_out *packet_out)
589{
590    return lsquic_gquic_po_header_sz(packet_out->po_flags)
591         + packet_out->po_data_sz
592         + GQUIC_PACKET_HASH_SZ
593         ;
594}
595
596
597size_t
598lsquic_gquic_packout_header_size (const struct lsquic_conn *conn,
599                                enum packet_out_flags flags, size_t dcid_len)
600{
601    return lsquic_gquic_po_header_sz(flags);
602}
603
604
605int
606lsquic_gquic_gen_ver_nego_pkt (unsigned char *buf, size_t bufsz,
607                        const lsquic_cid_t *cid, unsigned version_bitmask)
608{
609    int sz;
610    unsigned char *p = buf;
611    unsigned char *const pend = p + bufsz;
612
613    CHECK_SPACE(1, p, pend);
614    *p = PACKET_PUBLIC_FLAGS_VERSION | PACKET_PUBLIC_FLAGS_8BYTE_CONNECTION_ID;
615    ++p;
616
617    if (GQUIC_CID_LEN != cid->len)
618        return -1;
619
620    CHECK_SPACE(GQUIC_CID_LEN, p, pend);
621    memcpy(p, cid->idbuf, GQUIC_CID_LEN);
622    p += GQUIC_CID_LEN;
623
624    sz = lsquic_gen_ver_tags(p, pend - p, version_bitmask);
625    if (sz < 0)
626        return -1;
627
628    return p + sz - buf;
629}
630
631
632unsigned
633lsquic_gquic_packno_bits2len (enum packno_bits bits)
634{
635    return gquic_packno_bits2len(bits);
636}
637
638
639enum packno_bits
640lsquic_gquic_calc_packno_bits (lsquic_packno_t packno,
641                        lsquic_packno_t least_unacked, uint64_t n_in_flight)
642{
643    uint64_t delta;
644    unsigned bits;
645
646    delta = packno - least_unacked;
647    if (n_in_flight > delta)
648        delta = n_in_flight;
649
650    delta *= 4;
651    bits = (delta > (1ULL <<  8))
652         + (delta > (1ULL << 16))
653         + (delta > (1ULL << 32));
654
655    return bits;
656}
657