lsquic_parse_gquic_common.c revision 7a8b2ece
1229fce07SDmitri Tikhonov/* Copyright (c) 2017 - 2019 LiteSpeed Technologies Inc.  See LICENSE. */
250aadb33SDmitri Tikhonov/*
350aadb33SDmitri Tikhonov * lsquic_parse_gquic_common.c -- Parsing functions common to GQUIC
450aadb33SDmitri Tikhonov */
550aadb33SDmitri Tikhonov
650aadb33SDmitri Tikhonov#include <assert.h>
750aadb33SDmitri Tikhonov#include <errno.h>
850aadb33SDmitri Tikhonov#include <inttypes.h>
950aadb33SDmitri Tikhonov#include <string.h>
1050aadb33SDmitri Tikhonov#include <stdlib.h>
11461e84d8SAmol Deshpande#include <sys/queue.h>
12461e84d8SAmol Deshpande#ifndef WIN32
1350aadb33SDmitri Tikhonov#include <sys/types.h>
14461e84d8SAmol Deshpande#else
15461e84d8SAmol Deshpande#include <vc_compat.h>
16461e84d8SAmol Deshpande#endif
1750aadb33SDmitri Tikhonov
1850aadb33SDmitri Tikhonov#include "lsquic_types.h"
195392f7a3SLiteSpeed Tech#include "lsquic_int_types.h"
2050aadb33SDmitri Tikhonov#include "lsquic_packet_common.h"
219626cfc2SDmitri Tikhonov#include "lsquic_packet_out.h"
225392f7a3SLiteSpeed Tech#include "lsquic_packet_gquic.h"
2350aadb33SDmitri Tikhonov#include "lsquic_packet_in.h"
245392f7a3SLiteSpeed Tech#include "lsquic_packet_out.h"
255392f7a3SLiteSpeed Tech#include "lsquic_parse_common.h"
2650aadb33SDmitri Tikhonov#include "lsquic_parse.h"
279626cfc2SDmitri Tikhonov#include "lsquic_parse_common.h"
289626cfc2SDmitri Tikhonov#include "lsquic_version.h"
2950aadb33SDmitri Tikhonov#include "lsquic.h"
3050aadb33SDmitri Tikhonov
3150aadb33SDmitri Tikhonov#define LSQUIC_LOGGER_MODULE LSQLM_PARSE
3250aadb33SDmitri Tikhonov#include "lsquic_logger.h"
3350aadb33SDmitri Tikhonov
3450aadb33SDmitri Tikhonov#define CHECK_SPACE(need, pstart, pend)  \
3550aadb33SDmitri Tikhonov    do { if ((intptr_t) (need) > ((pend) - (pstart))) { return -1; } } while (0)
3650aadb33SDmitri Tikhonov
3750aadb33SDmitri Tikhonov/* This partially parses `packet_in' and returns 0 if in case it succeeded and
3850aadb33SDmitri Tikhonov * -1 on failure.
3950aadb33SDmitri Tikhonov *
4050aadb33SDmitri Tikhonov * After this function returns 0, connection ID, nonce, and version fields can
4150aadb33SDmitri Tikhonov * be examined.  To finsh parsing the packet, call version-specific
4250aadb33SDmitri Tikhonov * pf_parse_packet_in_finish() routine.
4350aadb33SDmitri Tikhonov */
4450aadb33SDmitri Tikhonovint
455392f7a3SLiteSpeed Techlsquic_gquic_parse_packet_in_begin (lsquic_packet_in_t *packet_in,
465392f7a3SLiteSpeed Tech                size_t length, int is_server, unsigned cid_len,
475392f7a3SLiteSpeed Tech                struct packin_parse_state *state)
4850aadb33SDmitri Tikhonov{
4950aadb33SDmitri Tikhonov    int nbytes;
5050aadb33SDmitri Tikhonov    enum PACKET_PUBLIC_FLAGS public_flags;
5150aadb33SDmitri Tikhonov    const unsigned char *p = packet_in->pi_data;
5250aadb33SDmitri Tikhonov    const unsigned char *const pend = packet_in->pi_data + length;
5350aadb33SDmitri Tikhonov
545392f7a3SLiteSpeed Tech    if (length > GQUIC_MAX_PACKET_SZ)
555392f7a3SLiteSpeed Tech    {
565392f7a3SLiteSpeed Tech        LSQ_DEBUG("Cannot handle packet_in_size(%zd) > %d packet incoming "
575392f7a3SLiteSpeed Tech            "packet's header", length, GQUIC_MAX_PACKET_SZ);
585392f7a3SLiteSpeed Tech        return -1;
595392f7a3SLiteSpeed Tech    }
605392f7a3SLiteSpeed Tech
6150aadb33SDmitri Tikhonov    CHECK_SPACE(1, p, pend);
6250aadb33SDmitri Tikhonov
6350aadb33SDmitri Tikhonov    public_flags = *p++;
6450aadb33SDmitri Tikhonov
6550aadb33SDmitri Tikhonov    if (public_flags & PACKET_PUBLIC_FLAGS_8BYTE_CONNECTION_ID)
6650aadb33SDmitri Tikhonov    {
6750aadb33SDmitri Tikhonov        CHECK_SPACE(8, p, pend);
685392f7a3SLiteSpeed Tech        memset(&packet_in->pi_conn_id, 0, sizeof(packet_in->pi_conn_id));
695392f7a3SLiteSpeed Tech        packet_in->pi_conn_id.len = 8;
705392f7a3SLiteSpeed Tech        memcpy(&packet_in->pi_conn_id.idbuf, p, 8);
7150aadb33SDmitri Tikhonov        packet_in->pi_flags |= PI_CONN_ID;
7250aadb33SDmitri Tikhonov        p += 8;
7350aadb33SDmitri Tikhonov    }
7450aadb33SDmitri Tikhonov
7550aadb33SDmitri Tikhonov    if (public_flags & PACKET_PUBLIC_FLAGS_VERSION)
7650aadb33SDmitri Tikhonov    {
7750aadb33SDmitri Tikhonov        /* It seems that version negotiation packets sent by Google may have
7850aadb33SDmitri Tikhonov         * NONCE bit set.  Ignore it:
7950aadb33SDmitri Tikhonov         */
8050aadb33SDmitri Tikhonov        public_flags &= ~PACKET_PUBLIC_FLAGS_NONCE;
8150aadb33SDmitri Tikhonov
8250aadb33SDmitri Tikhonov        if (is_server)
8350aadb33SDmitri Tikhonov        {
8450aadb33SDmitri Tikhonov            CHECK_SPACE(4, p, pend);
8550aadb33SDmitri Tikhonov            packet_in->pi_quic_ver = p - packet_in->pi_data;
8650aadb33SDmitri Tikhonov            p += 4;
8750aadb33SDmitri Tikhonov        }
8850aadb33SDmitri Tikhonov        else
8950aadb33SDmitri Tikhonov        {   /* OK, we have a version negotiation packet.  We need to verify
9050aadb33SDmitri Tikhonov             * that it has correct structure.  See Section 4.3 of
9150aadb33SDmitri Tikhonov             * [draft-ietf-quic-transport-00].
9250aadb33SDmitri Tikhonov             */
9350aadb33SDmitri Tikhonov            if ((public_flags & ~(PACKET_PUBLIC_FLAGS_VERSION|
9450aadb33SDmitri Tikhonov                                  PACKET_PUBLIC_FLAGS_8BYTE_CONNECTION_ID))
9550aadb33SDmitri Tikhonov                || ((pend - p) & 3))
9650aadb33SDmitri Tikhonov                return -1;
9750aadb33SDmitri Tikhonov            CHECK_SPACE(4, p, pend);
9850aadb33SDmitri Tikhonov            packet_in->pi_quic_ver = p - packet_in->pi_data;
9950aadb33SDmitri Tikhonov            p = pend;
10050aadb33SDmitri Tikhonov        }
10150aadb33SDmitri Tikhonov    }
10250aadb33SDmitri Tikhonov    else
10350aadb33SDmitri Tikhonov    {
10450aadb33SDmitri Tikhonov        /* From [draft-hamilton-quic-transport-protocol-01]:
10550aadb33SDmitri Tikhonov         *    0x40 = MULTIPATH. This bit is reserved for multipath use.
10650aadb33SDmitri Tikhonov         *    0x80 is currently unused, and must be set to 0.
10750aadb33SDmitri Tikhonov         *
10850aadb33SDmitri Tikhonov         * The reference implementation checks that two high bits are not set
10950aadb33SDmitri Tikhonov         * if version flag is not set or if the version is the same.  For our
11050aadb33SDmitri Tikhonov         * purposes, all GQUIC version we support so far have these bits set
11150aadb33SDmitri Tikhonov         * to zero.
11250aadb33SDmitri Tikhonov         */
11350aadb33SDmitri Tikhonov        if (public_flags & (0x80|0x40))
11450aadb33SDmitri Tikhonov            return -1;
11550aadb33SDmitri Tikhonov        packet_in->pi_quic_ver = 0;
11650aadb33SDmitri Tikhonov    }
11750aadb33SDmitri Tikhonov
11850aadb33SDmitri Tikhonov    if (!is_server && (public_flags & PACKET_PUBLIC_FLAGS_NONCE) ==
11950aadb33SDmitri Tikhonov                                            PACKET_PUBLIC_FLAGS_NONCE)
12050aadb33SDmitri Tikhonov    {
12150aadb33SDmitri Tikhonov        CHECK_SPACE(32, p, pend);
12250aadb33SDmitri Tikhonov        packet_in->pi_nonce = p - packet_in->pi_data;
12350aadb33SDmitri Tikhonov        p += 32;
12450aadb33SDmitri Tikhonov    }
12550aadb33SDmitri Tikhonov    else
12650aadb33SDmitri Tikhonov        packet_in->pi_nonce = 0;
12750aadb33SDmitri Tikhonov
12850aadb33SDmitri Tikhonov    state->pps_p = p;
12950aadb33SDmitri Tikhonov
13050aadb33SDmitri Tikhonov    packet_in->pi_packno = 0;
13150aadb33SDmitri Tikhonov    if (0 == (public_flags & (PACKET_PUBLIC_FLAGS_VERSION|PACKET_PUBLIC_FLAGS_RST))
13250aadb33SDmitri Tikhonov        || ((public_flags & PACKET_PUBLIC_FLAGS_VERSION) && is_server))
13350aadb33SDmitri Tikhonov    {
13450aadb33SDmitri Tikhonov        nbytes = twobit_to_1246((public_flags >> 4) & 3);
13550aadb33SDmitri Tikhonov        CHECK_SPACE(nbytes, p, pend);
13650aadb33SDmitri Tikhonov        p += nbytes;
13750aadb33SDmitri Tikhonov        state->pps_nbytes = nbytes;
13850aadb33SDmitri Tikhonov    }
13950aadb33SDmitri Tikhonov    else
14050aadb33SDmitri Tikhonov        state->pps_nbytes = 0;
14150aadb33SDmitri Tikhonov
14250aadb33SDmitri Tikhonov    packet_in->pi_header_sz    = p - packet_in->pi_data;
14350aadb33SDmitri Tikhonov    packet_in->pi_frame_types  = 0;
14450aadb33SDmitri Tikhonov    memset(&packet_in->pi_next, 0, sizeof(packet_in->pi_next));
14550aadb33SDmitri Tikhonov    packet_in->pi_data_sz      = length;
14650aadb33SDmitri Tikhonov    packet_in->pi_refcnt       = 0;
14750aadb33SDmitri Tikhonov    packet_in->pi_received     = 0;
1489626cfc2SDmitri Tikhonov    packet_in->pi_flags       |= PI_GQUIC;
149c7d81ce1SDmitri Tikhonov    packet_in->pi_flags       |= ((public_flags >> 4) & 3) << PIBIT_BITS_SHIFT;
15050aadb33SDmitri Tikhonov
15150aadb33SDmitri Tikhonov    return 0;
15250aadb33SDmitri Tikhonov}
15350aadb33SDmitri Tikhonov
15450aadb33SDmitri Tikhonov
1555392f7a3SLiteSpeed Techstatic const unsigned char simple_prst_payload[] = {
1565392f7a3SLiteSpeed Tech    'P', 'R', 'S', 'T',
1575392f7a3SLiteSpeed Tech    0x01, 0x00, 0x00, 0x00,
1585392f7a3SLiteSpeed Tech    'R', 'N', 'O', 'N',
1595392f7a3SLiteSpeed Tech    0x08, 0x00, 0x00, 0x00,
1605392f7a3SLiteSpeed Tech    1, 2, 3, 4, 5, 6, 7, 8,
1615392f7a3SLiteSpeed Tech};
1625392f7a3SLiteSpeed Tech
1635392f7a3SLiteSpeed Tech
1645392f7a3SLiteSpeed Techtypedef char correct_simple_prst_size[(GQUIC_RESET_SZ ==
1655392f7a3SLiteSpeed Tech                1 + GQUIC_CID_LEN + sizeof(simple_prst_payload)) - 1];
1665392f7a3SLiteSpeed Tech
1675392f7a3SLiteSpeed Tech
1685392f7a3SLiteSpeed Techssize_t
1695392f7a3SLiteSpeed Techlsquic_generate_gquic_reset (const lsquic_cid_t *cidp,
1705392f7a3SLiteSpeed Tech                                        unsigned char *buf, size_t buf_sz)
1715392f7a3SLiteSpeed Tech{
1725392f7a3SLiteSpeed Tech    lsquic_cid_t cid;
1735392f7a3SLiteSpeed Tech
1745392f7a3SLiteSpeed Tech    if (buf_sz < 1 + GQUIC_CID_LEN + sizeof(simple_prst_payload))
1755392f7a3SLiteSpeed Tech    {
1765392f7a3SLiteSpeed Tech        errno = ENOBUFS;
1775392f7a3SLiteSpeed Tech        return -1;
1785392f7a3SLiteSpeed Tech    }
1795392f7a3SLiteSpeed Tech
1805392f7a3SLiteSpeed Tech    if (cidp)
1815392f7a3SLiteSpeed Tech    {
1825392f7a3SLiteSpeed Tech        assert(GQUIC_CID_LEN == cidp->len);
1835392f7a3SLiteSpeed Tech        cid = *cidp;
1845392f7a3SLiteSpeed Tech    }
1855392f7a3SLiteSpeed Tech    else
1865392f7a3SLiteSpeed Tech    {
1875392f7a3SLiteSpeed Tech        memset(&cid, 0, sizeof(cid));
1885392f7a3SLiteSpeed Tech        cid.len = GQUIC_CID_LEN;
1895392f7a3SLiteSpeed Tech    }
1905392f7a3SLiteSpeed Tech
1915392f7a3SLiteSpeed Tech    *buf++ = PACKET_PUBLIC_FLAGS_RST | PACKET_PUBLIC_FLAGS_8BYTE_CONNECTION_ID;
1925392f7a3SLiteSpeed Tech
1935392f7a3SLiteSpeed Tech    memcpy(buf, cid.idbuf, GQUIC_CID_LEN);
1945392f7a3SLiteSpeed Tech    buf += GQUIC_CID_LEN;
1955392f7a3SLiteSpeed Tech
1965392f7a3SLiteSpeed Tech    memcpy(buf, simple_prst_payload, sizeof(simple_prst_payload));
1975392f7a3SLiteSpeed Tech    return 1 + GQUIC_CID_LEN + sizeof(simple_prst_payload);
1985392f7a3SLiteSpeed Tech}
1995392f7a3SLiteSpeed Tech
2005392f7a3SLiteSpeed Tech
2017a8b2eceSDmitri Tikhonovstatic const enum quic_frame_type byte2frame_type_Q035_thru_Q046[0x100] =
20250aadb33SDmitri Tikhonov{
20350aadb33SDmitri Tikhonov    [0x00] = QUIC_FRAME_PADDING,
20450aadb33SDmitri Tikhonov    [0x01] = QUIC_FRAME_RST_STREAM,
20550aadb33SDmitri Tikhonov    [0x02] = QUIC_FRAME_CONNECTION_CLOSE,
20650aadb33SDmitri Tikhonov    [0x03] = QUIC_FRAME_GOAWAY,
20750aadb33SDmitri Tikhonov    [0x04] = QUIC_FRAME_WINDOW_UPDATE,
20850aadb33SDmitri Tikhonov    [0x05] = QUIC_FRAME_BLOCKED,
20950aadb33SDmitri Tikhonov    [0x06] = QUIC_FRAME_STOP_WAITING,
21050aadb33SDmitri Tikhonov    [0x07] = QUIC_FRAME_PING,
21150aadb33SDmitri Tikhonov    [0x08] = QUIC_FRAME_INVALID,
21250aadb33SDmitri Tikhonov    [0x09] = QUIC_FRAME_INVALID,
21350aadb33SDmitri Tikhonov    [0x0A] = QUIC_FRAME_INVALID,
21450aadb33SDmitri Tikhonov    [0x0B] = QUIC_FRAME_INVALID,
21550aadb33SDmitri Tikhonov    [0x0C] = QUIC_FRAME_INVALID,
21650aadb33SDmitri Tikhonov    [0x0D] = QUIC_FRAME_INVALID,
21750aadb33SDmitri Tikhonov    [0x0E] = QUIC_FRAME_INVALID,
21850aadb33SDmitri Tikhonov    [0x0F] = QUIC_FRAME_INVALID,
21950aadb33SDmitri Tikhonov    [0x10] = QUIC_FRAME_INVALID,
22050aadb33SDmitri Tikhonov    [0x11] = QUIC_FRAME_INVALID,
22150aadb33SDmitri Tikhonov    [0x12] = QUIC_FRAME_INVALID,
22250aadb33SDmitri Tikhonov    [0x13] = QUIC_FRAME_INVALID,
22350aadb33SDmitri Tikhonov    [0x14] = QUIC_FRAME_INVALID,
22450aadb33SDmitri Tikhonov    [0x15] = QUIC_FRAME_INVALID,
22550aadb33SDmitri Tikhonov    [0x16] = QUIC_FRAME_INVALID,
22650aadb33SDmitri Tikhonov    [0x17] = QUIC_FRAME_INVALID,
22750aadb33SDmitri Tikhonov    [0x18] = QUIC_FRAME_INVALID,
22850aadb33SDmitri Tikhonov    [0x19] = QUIC_FRAME_INVALID,
22950aadb33SDmitri Tikhonov    [0x1A] = QUIC_FRAME_INVALID,
23050aadb33SDmitri Tikhonov    [0x1B] = QUIC_FRAME_INVALID,
23150aadb33SDmitri Tikhonov    [0x1C] = QUIC_FRAME_INVALID,
23250aadb33SDmitri Tikhonov    [0x1D] = QUIC_FRAME_INVALID,
23350aadb33SDmitri Tikhonov    [0x1E] = QUIC_FRAME_INVALID,
23450aadb33SDmitri Tikhonov    [0x1F] = QUIC_FRAME_INVALID,
23550aadb33SDmitri Tikhonov    [0x20] = QUIC_FRAME_INVALID,
23650aadb33SDmitri Tikhonov    [0x21] = QUIC_FRAME_INVALID,
23750aadb33SDmitri Tikhonov    [0x22] = QUIC_FRAME_INVALID,
23850aadb33SDmitri Tikhonov    [0x23] = QUIC_FRAME_INVALID,
23950aadb33SDmitri Tikhonov    [0x24] = QUIC_FRAME_INVALID,
24050aadb33SDmitri Tikhonov    [0x25] = QUIC_FRAME_INVALID,
24150aadb33SDmitri Tikhonov    [0x26] = QUIC_FRAME_INVALID,
24250aadb33SDmitri Tikhonov    [0x27] = QUIC_FRAME_INVALID,
24350aadb33SDmitri Tikhonov    [0x28] = QUIC_FRAME_INVALID,
24450aadb33SDmitri Tikhonov    [0x29] = QUIC_FRAME_INVALID,
24550aadb33SDmitri Tikhonov    [0x2A] = QUIC_FRAME_INVALID,
24650aadb33SDmitri Tikhonov    [0x2B] = QUIC_FRAME_INVALID,
24750aadb33SDmitri Tikhonov    [0x2C] = QUIC_FRAME_INVALID,
24850aadb33SDmitri Tikhonov    [0x2D] = QUIC_FRAME_INVALID,
24950aadb33SDmitri Tikhonov    [0x2E] = QUIC_FRAME_INVALID,
25050aadb33SDmitri Tikhonov    [0x2F] = QUIC_FRAME_INVALID,
25150aadb33SDmitri Tikhonov    [0x30] = QUIC_FRAME_INVALID,
25250aadb33SDmitri Tikhonov    [0x31] = QUIC_FRAME_INVALID,
25350aadb33SDmitri Tikhonov    [0x32] = QUIC_FRAME_INVALID,
25450aadb33SDmitri Tikhonov    [0x33] = QUIC_FRAME_INVALID,
25550aadb33SDmitri Tikhonov    [0x34] = QUIC_FRAME_INVALID,
25650aadb33SDmitri Tikhonov    [0x35] = QUIC_FRAME_INVALID,
25750aadb33SDmitri Tikhonov    [0x36] = QUIC_FRAME_INVALID,
25850aadb33SDmitri Tikhonov    [0x37] = QUIC_FRAME_INVALID,
25950aadb33SDmitri Tikhonov    [0x38] = QUIC_FRAME_INVALID,
26050aadb33SDmitri Tikhonov    [0x39] = QUIC_FRAME_INVALID,
26150aadb33SDmitri Tikhonov    [0x3A] = QUIC_FRAME_INVALID,
26250aadb33SDmitri Tikhonov    [0x3B] = QUIC_FRAME_INVALID,
26350aadb33SDmitri Tikhonov    [0x3C] = QUIC_FRAME_INVALID,
26450aadb33SDmitri Tikhonov    [0x3D] = QUIC_FRAME_INVALID,
26550aadb33SDmitri Tikhonov    [0x3E] = QUIC_FRAME_INVALID,
26650aadb33SDmitri Tikhonov    [0x3F] = QUIC_FRAME_INVALID,
26750aadb33SDmitri Tikhonov    [0x40] = QUIC_FRAME_ACK,
26850aadb33SDmitri Tikhonov    [0x41] = QUIC_FRAME_ACK,
26950aadb33SDmitri Tikhonov    [0x42] = QUIC_FRAME_ACK,
27050aadb33SDmitri Tikhonov    [0x43] = QUIC_FRAME_ACK,
27150aadb33SDmitri Tikhonov    [0x44] = QUIC_FRAME_ACK,
27250aadb33SDmitri Tikhonov    [0x45] = QUIC_FRAME_ACK,
27350aadb33SDmitri Tikhonov    [0x46] = QUIC_FRAME_ACK,
27450aadb33SDmitri Tikhonov    [0x47] = QUIC_FRAME_ACK,
27550aadb33SDmitri Tikhonov    [0x48] = QUIC_FRAME_ACK,
27650aadb33SDmitri Tikhonov    [0x49] = QUIC_FRAME_ACK,
27750aadb33SDmitri Tikhonov    [0x4A] = QUIC_FRAME_ACK,
27850aadb33SDmitri Tikhonov    [0x4B] = QUIC_FRAME_ACK,
27950aadb33SDmitri Tikhonov    [0x4C] = QUIC_FRAME_ACK,
28050aadb33SDmitri Tikhonov    [0x4D] = QUIC_FRAME_ACK,
28150aadb33SDmitri Tikhonov    [0x4E] = QUIC_FRAME_ACK,
28250aadb33SDmitri Tikhonov    [0x4F] = QUIC_FRAME_ACK,
28350aadb33SDmitri Tikhonov    [0x50] = QUIC_FRAME_ACK,
28450aadb33SDmitri Tikhonov    [0x51] = QUIC_FRAME_ACK,
28550aadb33SDmitri Tikhonov    [0x52] = QUIC_FRAME_ACK,
28650aadb33SDmitri Tikhonov    [0x53] = QUIC_FRAME_ACK,
28750aadb33SDmitri Tikhonov    [0x54] = QUIC_FRAME_ACK,
28850aadb33SDmitri Tikhonov    [0x55] = QUIC_FRAME_ACK,
28950aadb33SDmitri Tikhonov    [0x56] = QUIC_FRAME_ACK,
29050aadb33SDmitri Tikhonov    [0x57] = QUIC_FRAME_ACK,
29150aadb33SDmitri Tikhonov    [0x58] = QUIC_FRAME_ACK,
29250aadb33SDmitri Tikhonov    [0x59] = QUIC_FRAME_ACK,
29350aadb33SDmitri Tikhonov    [0x5A] = QUIC_FRAME_ACK,
29450aadb33SDmitri Tikhonov    [0x5B] = QUIC_FRAME_ACK,
29550aadb33SDmitri Tikhonov    [0x5C] = QUIC_FRAME_ACK,
29650aadb33SDmitri Tikhonov    [0x5D] = QUIC_FRAME_ACK,
29750aadb33SDmitri Tikhonov    [0x5E] = QUIC_FRAME_ACK,
29850aadb33SDmitri Tikhonov    [0x5F] = QUIC_FRAME_ACK,
29950aadb33SDmitri Tikhonov    [0x60] = QUIC_FRAME_ACK,
30050aadb33SDmitri Tikhonov    [0x61] = QUIC_FRAME_ACK,
30150aadb33SDmitri Tikhonov    [0x62] = QUIC_FRAME_ACK,
30250aadb33SDmitri Tikhonov    [0x63] = QUIC_FRAME_ACK,
30350aadb33SDmitri Tikhonov    [0x64] = QUIC_FRAME_ACK,
30450aadb33SDmitri Tikhonov    [0x65] = QUIC_FRAME_ACK,
30550aadb33SDmitri Tikhonov    [0x66] = QUIC_FRAME_ACK,
30650aadb33SDmitri Tikhonov    [0x67] = QUIC_FRAME_ACK,
30750aadb33SDmitri Tikhonov    [0x68] = QUIC_FRAME_ACK,
30850aadb33SDmitri Tikhonov    [0x69] = QUIC_FRAME_ACK,
30950aadb33SDmitri Tikhonov    [0x6A] = QUIC_FRAME_ACK,
31050aadb33SDmitri Tikhonov    [0x6B] = QUIC_FRAME_ACK,
31150aadb33SDmitri Tikhonov    [0x6C] = QUIC_FRAME_ACK,
31250aadb33SDmitri Tikhonov    [0x6D] = QUIC_FRAME_ACK,
31350aadb33SDmitri Tikhonov    [0x6E] = QUIC_FRAME_ACK,
31450aadb33SDmitri Tikhonov    [0x6F] = QUIC_FRAME_ACK,
31550aadb33SDmitri Tikhonov    [0x70] = QUIC_FRAME_ACK,
31650aadb33SDmitri Tikhonov    [0x71] = QUIC_FRAME_ACK,
31750aadb33SDmitri Tikhonov    [0x72] = QUIC_FRAME_ACK,
31850aadb33SDmitri Tikhonov    [0x73] = QUIC_FRAME_ACK,
31950aadb33SDmitri Tikhonov    [0x74] = QUIC_FRAME_ACK,
32050aadb33SDmitri Tikhonov    [0x75] = QUIC_FRAME_ACK,
32150aadb33SDmitri Tikhonov    [0x76] = QUIC_FRAME_ACK,
32250aadb33SDmitri Tikhonov    [0x77] = QUIC_FRAME_ACK,
32350aadb33SDmitri Tikhonov    [0x78] = QUIC_FRAME_ACK,
32450aadb33SDmitri Tikhonov    [0x79] = QUIC_FRAME_ACK,
32550aadb33SDmitri Tikhonov    [0x7A] = QUIC_FRAME_ACK,
32650aadb33SDmitri Tikhonov    [0x7B] = QUIC_FRAME_ACK,
32750aadb33SDmitri Tikhonov    [0x7C] = QUIC_FRAME_ACK,
32850aadb33SDmitri Tikhonov    [0x7D] = QUIC_FRAME_ACK,
32950aadb33SDmitri Tikhonov    [0x7E] = QUIC_FRAME_ACK,
33050aadb33SDmitri Tikhonov    [0x7F] = QUIC_FRAME_ACK,
33150aadb33SDmitri Tikhonov    [0x80] = QUIC_FRAME_STREAM,
33250aadb33SDmitri Tikhonov    [0x81] = QUIC_FRAME_STREAM,
33350aadb33SDmitri Tikhonov    [0x82] = QUIC_FRAME_STREAM,
33450aadb33SDmitri Tikhonov    [0x83] = QUIC_FRAME_STREAM,
33550aadb33SDmitri Tikhonov    [0x84] = QUIC_FRAME_STREAM,
33650aadb33SDmitri Tikhonov    [0x85] = QUIC_FRAME_STREAM,
33750aadb33SDmitri Tikhonov    [0x86] = QUIC_FRAME_STREAM,
33850aadb33SDmitri Tikhonov    [0x87] = QUIC_FRAME_STREAM,
33950aadb33SDmitri Tikhonov    [0x88] = QUIC_FRAME_STREAM,
34050aadb33SDmitri Tikhonov    [0x89] = QUIC_FRAME_STREAM,
34150aadb33SDmitri Tikhonov    [0x8A] = QUIC_FRAME_STREAM,
34250aadb33SDmitri Tikhonov    [0x8B] = QUIC_FRAME_STREAM,
34350aadb33SDmitri Tikhonov    [0x8C] = QUIC_FRAME_STREAM,
34450aadb33SDmitri Tikhonov    [0x8D] = QUIC_FRAME_STREAM,
34550aadb33SDmitri Tikhonov    [0x8E] = QUIC_FRAME_STREAM,
34650aadb33SDmitri Tikhonov    [0x8F] = QUIC_FRAME_STREAM,
34750aadb33SDmitri Tikhonov    [0x90] = QUIC_FRAME_STREAM,
34850aadb33SDmitri Tikhonov    [0x91] = QUIC_FRAME_STREAM,
34950aadb33SDmitri Tikhonov    [0x92] = QUIC_FRAME_STREAM,
35050aadb33SDmitri Tikhonov    [0x93] = QUIC_FRAME_STREAM,
35150aadb33SDmitri Tikhonov    [0x94] = QUIC_FRAME_STREAM,
35250aadb33SDmitri Tikhonov    [0x95] = QUIC_FRAME_STREAM,
35350aadb33SDmitri Tikhonov    [0x96] = QUIC_FRAME_STREAM,
35450aadb33SDmitri Tikhonov    [0x97] = QUIC_FRAME_STREAM,
35550aadb33SDmitri Tikhonov    [0x98] = QUIC_FRAME_STREAM,
35650aadb33SDmitri Tikhonov    [0x99] = QUIC_FRAME_STREAM,
35750aadb33SDmitri Tikhonov    [0x9A] = QUIC_FRAME_STREAM,
35850aadb33SDmitri Tikhonov    [0x9B] = QUIC_FRAME_STREAM,
35950aadb33SDmitri Tikhonov    [0x9C] = QUIC_FRAME_STREAM,
36050aadb33SDmitri Tikhonov    [0x9D] = QUIC_FRAME_STREAM,
36150aadb33SDmitri Tikhonov    [0x9E] = QUIC_FRAME_STREAM,
36250aadb33SDmitri Tikhonov    [0x9F] = QUIC_FRAME_STREAM,
36350aadb33SDmitri Tikhonov    [0xA0] = QUIC_FRAME_STREAM,
36450aadb33SDmitri Tikhonov    [0xA1] = QUIC_FRAME_STREAM,
36550aadb33SDmitri Tikhonov    [0xA2] = QUIC_FRAME_STREAM,
36650aadb33SDmitri Tikhonov    [0xA3] = QUIC_FRAME_STREAM,
36750aadb33SDmitri Tikhonov    [0xA4] = QUIC_FRAME_STREAM,
36850aadb33SDmitri Tikhonov    [0xA5] = QUIC_FRAME_STREAM,
36950aadb33SDmitri Tikhonov    [0xA6] = QUIC_FRAME_STREAM,
37050aadb33SDmitri Tikhonov    [0xA7] = QUIC_FRAME_STREAM,
37150aadb33SDmitri Tikhonov    [0xA8] = QUIC_FRAME_STREAM,
37250aadb33SDmitri Tikhonov    [0xA9] = QUIC_FRAME_STREAM,
37350aadb33SDmitri Tikhonov    [0xAA] = QUIC_FRAME_STREAM,
37450aadb33SDmitri Tikhonov    [0xAB] = QUIC_FRAME_STREAM,
37550aadb33SDmitri Tikhonov    [0xAC] = QUIC_FRAME_STREAM,
37650aadb33SDmitri Tikhonov    [0xAD] = QUIC_FRAME_STREAM,
37750aadb33SDmitri Tikhonov    [0xAE] = QUIC_FRAME_STREAM,
37850aadb33SDmitri Tikhonov    [0xAF] = QUIC_FRAME_STREAM,
37950aadb33SDmitri Tikhonov    [0xB0] = QUIC_FRAME_STREAM,
38050aadb33SDmitri Tikhonov    [0xB1] = QUIC_FRAME_STREAM,
38150aadb33SDmitri Tikhonov    [0xB2] = QUIC_FRAME_STREAM,
38250aadb33SDmitri Tikhonov    [0xB3] = QUIC_FRAME_STREAM,
38350aadb33SDmitri Tikhonov    [0xB4] = QUIC_FRAME_STREAM,
38450aadb33SDmitri Tikhonov    [0xB5] = QUIC_FRAME_STREAM,
38550aadb33SDmitri Tikhonov    [0xB6] = QUIC_FRAME_STREAM,
38650aadb33SDmitri Tikhonov    [0xB7] = QUIC_FRAME_STREAM,
38750aadb33SDmitri Tikhonov    [0xB8] = QUIC_FRAME_STREAM,
38850aadb33SDmitri Tikhonov    [0xB9] = QUIC_FRAME_STREAM,
38950aadb33SDmitri Tikhonov    [0xBA] = QUIC_FRAME_STREAM,
39050aadb33SDmitri Tikhonov    [0xBB] = QUIC_FRAME_STREAM,
39150aadb33SDmitri Tikhonov    [0xBC] = QUIC_FRAME_STREAM,
39250aadb33SDmitri Tikhonov    [0xBD] = QUIC_FRAME_STREAM,
39350aadb33SDmitri Tikhonov    [0xBE] = QUIC_FRAME_STREAM,
39450aadb33SDmitri Tikhonov    [0xBF] = QUIC_FRAME_STREAM,
39550aadb33SDmitri Tikhonov    [0xC0] = QUIC_FRAME_STREAM,
39650aadb33SDmitri Tikhonov    [0xC1] = QUIC_FRAME_STREAM,
39750aadb33SDmitri Tikhonov    [0xC2] = QUIC_FRAME_STREAM,
39850aadb33SDmitri Tikhonov    [0xC3] = QUIC_FRAME_STREAM,
39950aadb33SDmitri Tikhonov    [0xC4] = QUIC_FRAME_STREAM,
40050aadb33SDmitri Tikhonov    [0xC5] = QUIC_FRAME_STREAM,
40150aadb33SDmitri Tikhonov    [0xC6] = QUIC_FRAME_STREAM,
40250aadb33SDmitri Tikhonov    [0xC7] = QUIC_FRAME_STREAM,
40350aadb33SDmitri Tikhonov    [0xC8] = QUIC_FRAME_STREAM,
40450aadb33SDmitri Tikhonov    [0xC9] = QUIC_FRAME_STREAM,
40550aadb33SDmitri Tikhonov    [0xCA] = QUIC_FRAME_STREAM,
40650aadb33SDmitri Tikhonov    [0xCB] = QUIC_FRAME_STREAM,
40750aadb33SDmitri Tikhonov    [0xCC] = QUIC_FRAME_STREAM,
40850aadb33SDmitri Tikhonov    [0xCD] = QUIC_FRAME_STREAM,
40950aadb33SDmitri Tikhonov    [0xCE] = QUIC_FRAME_STREAM,
41050aadb33SDmitri Tikhonov    [0xCF] = QUIC_FRAME_STREAM,
41150aadb33SDmitri Tikhonov    [0xD0] = QUIC_FRAME_STREAM,
41250aadb33SDmitri Tikhonov    [0xD1] = QUIC_FRAME_STREAM,
41350aadb33SDmitri Tikhonov    [0xD2] = QUIC_FRAME_STREAM,
41450aadb33SDmitri Tikhonov    [0xD3] = QUIC_FRAME_STREAM,
41550aadb33SDmitri Tikhonov    [0xD4] = QUIC_FRAME_STREAM,
41650aadb33SDmitri Tikhonov    [0xD5] = QUIC_FRAME_STREAM,
41750aadb33SDmitri Tikhonov    [0xD6] = QUIC_FRAME_STREAM,
41850aadb33SDmitri Tikhonov    [0xD7] = QUIC_FRAME_STREAM,
41950aadb33SDmitri Tikhonov    [0xD8] = QUIC_FRAME_STREAM,
42050aadb33SDmitri Tikhonov    [0xD9] = QUIC_FRAME_STREAM,
42150aadb33SDmitri Tikhonov    [0xDA] = QUIC_FRAME_STREAM,
42250aadb33SDmitri Tikhonov    [0xDB] = QUIC_FRAME_STREAM,
42350aadb33SDmitri Tikhonov    [0xDC] = QUIC_FRAME_STREAM,
42450aadb33SDmitri Tikhonov    [0xDD] = QUIC_FRAME_STREAM,
42550aadb33SDmitri Tikhonov    [0xDE] = QUIC_FRAME_STREAM,
42650aadb33SDmitri Tikhonov    [0xDF] = QUIC_FRAME_STREAM,
42750aadb33SDmitri Tikhonov    [0xE0] = QUIC_FRAME_STREAM,
42850aadb33SDmitri Tikhonov    [0xE1] = QUIC_FRAME_STREAM,
42950aadb33SDmitri Tikhonov    [0xE2] = QUIC_FRAME_STREAM,
43050aadb33SDmitri Tikhonov    [0xE3] = QUIC_FRAME_STREAM,
43150aadb33SDmitri Tikhonov    [0xE4] = QUIC_FRAME_STREAM,
43250aadb33SDmitri Tikhonov    [0xE5] = QUIC_FRAME_STREAM,
43350aadb33SDmitri Tikhonov    [0xE6] = QUIC_FRAME_STREAM,
43450aadb33SDmitri Tikhonov    [0xE7] = QUIC_FRAME_STREAM,
43550aadb33SDmitri Tikhonov    [0xE8] = QUIC_FRAME_STREAM,
43650aadb33SDmitri Tikhonov    [0xE9] = QUIC_FRAME_STREAM,
43750aadb33SDmitri Tikhonov    [0xEA] = QUIC_FRAME_STREAM,
43850aadb33SDmitri Tikhonov    [0xEB] = QUIC_FRAME_STREAM,
43950aadb33SDmitri Tikhonov    [0xEC] = QUIC_FRAME_STREAM,
44050aadb33SDmitri Tikhonov    [0xED] = QUIC_FRAME_STREAM,
44150aadb33SDmitri Tikhonov    [0xEE] = QUIC_FRAME_STREAM,
44250aadb33SDmitri Tikhonov    [0xEF] = QUIC_FRAME_STREAM,
44350aadb33SDmitri Tikhonov    [0xF0] = QUIC_FRAME_STREAM,
44450aadb33SDmitri Tikhonov    [0xF1] = QUIC_FRAME_STREAM,
44550aadb33SDmitri Tikhonov    [0xF2] = QUIC_FRAME_STREAM,
44650aadb33SDmitri Tikhonov    [0xF3] = QUIC_FRAME_STREAM,
44750aadb33SDmitri Tikhonov    [0xF4] = QUIC_FRAME_STREAM,
44850aadb33SDmitri Tikhonov    [0xF5] = QUIC_FRAME_STREAM,
44950aadb33SDmitri Tikhonov    [0xF6] = QUIC_FRAME_STREAM,
45050aadb33SDmitri Tikhonov    [0xF7] = QUIC_FRAME_STREAM,
45150aadb33SDmitri Tikhonov    [0xF8] = QUIC_FRAME_STREAM,
45250aadb33SDmitri Tikhonov    [0xF9] = QUIC_FRAME_STREAM,
45350aadb33SDmitri Tikhonov    [0xFA] = QUIC_FRAME_STREAM,
45450aadb33SDmitri Tikhonov    [0xFB] = QUIC_FRAME_STREAM,
45550aadb33SDmitri Tikhonov    [0xFC] = QUIC_FRAME_STREAM,
45650aadb33SDmitri Tikhonov    [0xFD] = QUIC_FRAME_STREAM,
45750aadb33SDmitri Tikhonov    [0xFE] = QUIC_FRAME_STREAM,
45850aadb33SDmitri Tikhonov    [0xFF] = QUIC_FRAME_STREAM,
45950aadb33SDmitri Tikhonov};
46050aadb33SDmitri Tikhonov
46150aadb33SDmitri Tikhonov
4626aba801dSDmitri Tikhonovenum quic_frame_type
4637a8b2eceSDmitri Tikhonovlsquic_parse_frame_type_gquic_Q035_thru_Q046 (unsigned char b)
46450aadb33SDmitri Tikhonov{
4657a8b2eceSDmitri Tikhonov    return byte2frame_type_Q035_thru_Q046[b];
46650aadb33SDmitri Tikhonov}
46750aadb33SDmitri Tikhonov
46850aadb33SDmitri Tikhonov
469c51ce338SDmitri Tikhonovvoid
4707a8b2eceSDmitri Tikhonovlsquic_turn_on_fin_Q035_thru_Q046 (unsigned char *stream_header)
471c51ce338SDmitri Tikhonov{
472c51ce338SDmitri Tikhonov    /* 1fdoooss */
473c51ce338SDmitri Tikhonov    *stream_header |= 0x40;
474c51ce338SDmitri Tikhonov}
475c51ce338SDmitri Tikhonov
476c51ce338SDmitri Tikhonov
47750aadb33SDmitri Tikhonovsize_t
4785392f7a3SLiteSpeed Techcalc_stream_frame_header_sz_gquic (lsquic_stream_id_t stream_id,
4795392f7a3SLiteSpeed Tech                                    uint64_t offset, unsigned data_sz_IGNORED)
48050aadb33SDmitri Tikhonov{
48150aadb33SDmitri Tikhonov    return
48250aadb33SDmitri Tikhonov        /* Type */
48350aadb33SDmitri Tikhonov        1
48450aadb33SDmitri Tikhonov        /* Stream ID length */
48550aadb33SDmitri Tikhonov      + ((stream_id) > 0x0000FF)
48650aadb33SDmitri Tikhonov      + ((stream_id) > 0x00FFFF)
48750aadb33SDmitri Tikhonov      + ((stream_id) > 0xFFFFFF)
48850aadb33SDmitri Tikhonov      + 1
48950aadb33SDmitri Tikhonov        /* Offset length */
49050aadb33SDmitri Tikhonov      + ((offset) >= (1ULL << 56))
49150aadb33SDmitri Tikhonov      + ((offset) >= (1ULL << 48))
49250aadb33SDmitri Tikhonov      + ((offset) >= (1ULL << 40))
49350aadb33SDmitri Tikhonov      + ((offset) >= (1ULL << 32))
49450aadb33SDmitri Tikhonov      + ((offset) >= (1ULL << 24))
49550aadb33SDmitri Tikhonov      + ((offset) >= (1ULL << 16))
49650aadb33SDmitri Tikhonov      + (((offset) > 0) << 1)
49750aadb33SDmitri Tikhonov        /* Add data length (2) yourself, if necessary */
49850aadb33SDmitri Tikhonov    ;
49950aadb33SDmitri Tikhonov}
50050aadb33SDmitri Tikhonov
50150aadb33SDmitri Tikhonov
5025392f7a3SLiteSpeed Techstatic const char *const ecn2str[4] =
5035392f7a3SLiteSpeed Tech{
5045392f7a3SLiteSpeed Tech    [ECN_NOT_ECT]   = "",
5055392f7a3SLiteSpeed Tech    [ECN_ECT0]      = "ECT(0)",
5065392f7a3SLiteSpeed Tech    [ECN_ECT1]      = "ECT(1)",
5075392f7a3SLiteSpeed Tech    [ECN_CE]        = "CE",
5085392f7a3SLiteSpeed Tech};
5095392f7a3SLiteSpeed Tech
5105392f7a3SLiteSpeed Tech
5115392f7a3SLiteSpeed Tech#define ECN_COUNTS  " ECT(0): 01234567879012345678790;" \
5125392f7a3SLiteSpeed Tech                    " ECT(1): 01234567879012345678790;" \
5135392f7a3SLiteSpeed Tech                    " CE: 01234567879012345678790"
5145392f7a3SLiteSpeed Tech#define RANGES_TRUNCATED " ranges truncated! "
5155392f7a3SLiteSpeed Tech
51650aadb33SDmitri Tikhonovchar *
51750aadb33SDmitri Tikhonovacki2str (const struct ack_info *acki, size_t *sz)
51850aadb33SDmitri Tikhonov{
51950aadb33SDmitri Tikhonov    size_t off, bufsz, nw;
5205392f7a3SLiteSpeed Tech    enum ecn ecn;
52150aadb33SDmitri Tikhonov    unsigned n;
52250aadb33SDmitri Tikhonov    char *buf;
52350aadb33SDmitri Tikhonov
5245392f7a3SLiteSpeed Tech    bufsz = acki->n_ranges * (3 /* [-] */ + 20 /* ~0ULL */ * 2)
5255392f7a3SLiteSpeed Tech        + (acki->flags & AI_ECN ? sizeof(ECN_COUNTS) : 0)
5265392f7a3SLiteSpeed Tech        + (acki->flags & AI_TRUNCATED ? sizeof(RANGES_TRUNCATED) : 0);
52750aadb33SDmitri Tikhonov    buf = malloc(bufsz);
52850aadb33SDmitri Tikhonov    if (!buf)
52950aadb33SDmitri Tikhonov    {
53050aadb33SDmitri Tikhonov        LSQ_WARN("%s: malloc(%zd) failure: %s", __func__, bufsz,
53150aadb33SDmitri Tikhonov                                                        strerror(errno));
53250aadb33SDmitri Tikhonov        return NULL;
53350aadb33SDmitri Tikhonov    }
53450aadb33SDmitri Tikhonov
53550aadb33SDmitri Tikhonov    off = 0;
53650aadb33SDmitri Tikhonov    for (n = 0; n < acki->n_ranges; ++n)
53750aadb33SDmitri Tikhonov    {
53850aadb33SDmitri Tikhonov        nw = snprintf(buf + off, bufsz - off, "[%"PRIu64"-%"PRIu64"]",
53950aadb33SDmitri Tikhonov                acki->ranges[n].high, acki->ranges[n].low);
54050aadb33SDmitri Tikhonov        if (nw > bufsz - off)
54150aadb33SDmitri Tikhonov            break;
54250aadb33SDmitri Tikhonov        off += nw;
54350aadb33SDmitri Tikhonov    }
54450aadb33SDmitri Tikhonov
5455392f7a3SLiteSpeed Tech    if (acki->flags & AI_TRUNCATED)
5465392f7a3SLiteSpeed Tech    {
5475392f7a3SLiteSpeed Tech        nw = snprintf(buf + off, bufsz - off, RANGES_TRUNCATED);
5485392f7a3SLiteSpeed Tech        if (nw > bufsz - off)
5495392f7a3SLiteSpeed Tech        {
5505392f7a3SLiteSpeed Tech            nw = bufsz - off;
5515392f7a3SLiteSpeed Tech            goto end;
5525392f7a3SLiteSpeed Tech        }
5535392f7a3SLiteSpeed Tech        off += nw;
5545392f7a3SLiteSpeed Tech    }
5555392f7a3SLiteSpeed Tech
5565392f7a3SLiteSpeed Tech    if (acki->flags & AI_ECN)
5575392f7a3SLiteSpeed Tech    {
5585392f7a3SLiteSpeed Tech        for (ecn = 1; ecn <= 3; ++ecn)
5595392f7a3SLiteSpeed Tech        {
5605392f7a3SLiteSpeed Tech            nw = snprintf(buf + off, bufsz - off, " %s: %"PRIu64"%.*s",
5615392f7a3SLiteSpeed Tech                        ecn2str[ecn], acki->ecn_counts[ecn], ecn < 3, ";");
5625392f7a3SLiteSpeed Tech            if (nw > bufsz - off)
5635392f7a3SLiteSpeed Tech                break;
5645392f7a3SLiteSpeed Tech            off += nw;
5655392f7a3SLiteSpeed Tech        }
5665392f7a3SLiteSpeed Tech    }
5675392f7a3SLiteSpeed Tech
5685392f7a3SLiteSpeed Tech  end:
56950aadb33SDmitri Tikhonov    *sz = off;
57050aadb33SDmitri Tikhonov    return buf;
57150aadb33SDmitri Tikhonov}
5729626cfc2SDmitri Tikhonov
5739626cfc2SDmitri Tikhonov
5749626cfc2SDmitri Tikhonovsize_t
5759626cfc2SDmitri Tikhonovlsquic_gquic_po_header_sz (enum packet_out_flags flags)
5769626cfc2SDmitri Tikhonov{
5779626cfc2SDmitri Tikhonov    return 1                                                /* Type */
5789626cfc2SDmitri Tikhonov           + (!!(flags & PO_CONN_ID) << 3)                  /* Connection ID */
5799626cfc2SDmitri Tikhonov           + (!!(flags & PO_VERSION) << 2)                  /* Version */
5809626cfc2SDmitri Tikhonov           + (!!(flags & PO_NONCE)   << 5)                  /* Nonce */
581c7d81ce1SDmitri Tikhonov           + gquic_packno_bits2len((flags >> POBIT_SHIFT) & 0x3)  /* Packet number */
5829626cfc2SDmitri Tikhonov           ;
5839626cfc2SDmitri Tikhonov}
5849626cfc2SDmitri Tikhonov
5859626cfc2SDmitri Tikhonov
5869626cfc2SDmitri Tikhonovsize_t
5879626cfc2SDmitri Tikhonovlsquic_gquic_packout_size (const struct lsquic_conn *conn,
5889626cfc2SDmitri Tikhonov                                const struct lsquic_packet_out *packet_out)
5899626cfc2SDmitri Tikhonov{
5909626cfc2SDmitri Tikhonov    return lsquic_gquic_po_header_sz(packet_out->po_flags)
5919626cfc2SDmitri Tikhonov         + packet_out->po_data_sz
5925392f7a3SLiteSpeed Tech         + GQUIC_PACKET_HASH_SZ
5939626cfc2SDmitri Tikhonov         ;
5949626cfc2SDmitri Tikhonov}
5959626cfc2SDmitri Tikhonov
5969626cfc2SDmitri Tikhonov
5979626cfc2SDmitri Tikhonovsize_t
5989626cfc2SDmitri Tikhonovlsquic_gquic_packout_header_size (const struct lsquic_conn *conn,
5995392f7a3SLiteSpeed Tech                                enum packet_out_flags flags, size_t dcid_len)
6009626cfc2SDmitri Tikhonov{
6019626cfc2SDmitri Tikhonov    return lsquic_gquic_po_header_sz(flags);
6029626cfc2SDmitri Tikhonov}
6039626cfc2SDmitri Tikhonov
6049626cfc2SDmitri Tikhonov
6055392f7a3SLiteSpeed Techint
6065392f7a3SLiteSpeed Techlsquic_gquic_gen_ver_nego_pkt (unsigned char *buf, size_t bufsz,
6075392f7a3SLiteSpeed Tech                        const lsquic_cid_t *cid, unsigned version_bitmask)
6085392f7a3SLiteSpeed Tech{
6095392f7a3SLiteSpeed Tech    int sz;
6105392f7a3SLiteSpeed Tech    unsigned char *p = buf;
6115392f7a3SLiteSpeed Tech    unsigned char *const pend = p + bufsz;
6125392f7a3SLiteSpeed Tech
6135392f7a3SLiteSpeed Tech    CHECK_SPACE(1, p, pend);
6145392f7a3SLiteSpeed Tech    *p = PACKET_PUBLIC_FLAGS_VERSION | PACKET_PUBLIC_FLAGS_8BYTE_CONNECTION_ID;
6155392f7a3SLiteSpeed Tech    ++p;
6165392f7a3SLiteSpeed Tech
6175392f7a3SLiteSpeed Tech    if (GQUIC_CID_LEN != cid->len)
6185392f7a3SLiteSpeed Tech        return -1;
6195392f7a3SLiteSpeed Tech
6205392f7a3SLiteSpeed Tech    CHECK_SPACE(GQUIC_CID_LEN, p, pend);
6215392f7a3SLiteSpeed Tech    memcpy(p, cid->idbuf, GQUIC_CID_LEN);
6225392f7a3SLiteSpeed Tech    p += GQUIC_CID_LEN;
6235392f7a3SLiteSpeed Tech
6245392f7a3SLiteSpeed Tech    sz = lsquic_gen_ver_tags(p, pend - p, version_bitmask);
6255392f7a3SLiteSpeed Tech    if (sz < 0)
6265392f7a3SLiteSpeed Tech        return -1;
6275392f7a3SLiteSpeed Tech
6285392f7a3SLiteSpeed Tech    return p + sz - buf;
6295392f7a3SLiteSpeed Tech}
6305392f7a3SLiteSpeed Tech
6315392f7a3SLiteSpeed Tech
632c7d81ce1SDmitri Tikhonovunsigned
633c7d81ce1SDmitri Tikhonovlsquic_gquic_packno_bits2len (enum packno_bits bits)
634c7d81ce1SDmitri Tikhonov{
635c7d81ce1SDmitri Tikhonov    return gquic_packno_bits2len(bits);
636c7d81ce1SDmitri Tikhonov}
637c7d81ce1SDmitri Tikhonov
638c7d81ce1SDmitri Tikhonov
639c7d81ce1SDmitri Tikhonovenum packno_bits
640c7d81ce1SDmitri Tikhonovlsquic_gquic_calc_packno_bits (lsquic_packno_t packno,
641c7d81ce1SDmitri Tikhonov                        lsquic_packno_t least_unacked, uint64_t n_in_flight)
642c7d81ce1SDmitri Tikhonov{
643c7d81ce1SDmitri Tikhonov    uint64_t delta;
644c7d81ce1SDmitri Tikhonov    unsigned bits;
645c7d81ce1SDmitri Tikhonov
646c7d81ce1SDmitri Tikhonov    delta = packno - least_unacked;
647c7d81ce1SDmitri Tikhonov    if (n_in_flight > delta)
648c7d81ce1SDmitri Tikhonov        delta = n_in_flight;
649c7d81ce1SDmitri Tikhonov
650c7d81ce1SDmitri Tikhonov    delta *= 4;
651c7d81ce1SDmitri Tikhonov    bits = (delta > (1ULL <<  8))
652c7d81ce1SDmitri Tikhonov         + (delta > (1ULL << 16))
653c7d81ce1SDmitri Tikhonov         + (delta > (1ULL << 32));
654c7d81ce1SDmitri Tikhonov
655c7d81ce1SDmitri Tikhonov    return bits;
656c7d81ce1SDmitri Tikhonov}
657