lsquic_parse_gquic_common.c revision 7d09751d
17d09751dSDmitri Tikhonov/* Copyright (c) 2017 - 2020 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 511de46bf2fSDmitri Tikhonovvoid 512de46bf2fSDmitri Tikhonovlsquic_acki2str (const struct ack_info *acki, char *buf, size_t bufsz) 51350aadb33SDmitri Tikhonov{ 514de46bf2fSDmitri Tikhonov size_t off, nw; 5155392f7a3SLiteSpeed Tech enum ecn ecn; 51650aadb33SDmitri Tikhonov unsigned n; 51750aadb33SDmitri Tikhonov 51850aadb33SDmitri Tikhonov off = 0; 51950aadb33SDmitri Tikhonov for (n = 0; n < acki->n_ranges; ++n) 52050aadb33SDmitri Tikhonov { 52150aadb33SDmitri Tikhonov nw = snprintf(buf + off, bufsz - off, "[%"PRIu64"-%"PRIu64"]", 52250aadb33SDmitri Tikhonov acki->ranges[n].high, acki->ranges[n].low); 52350aadb33SDmitri Tikhonov if (nw > bufsz - off) 524de46bf2fSDmitri Tikhonov return; 52550aadb33SDmitri Tikhonov off += nw; 52650aadb33SDmitri Tikhonov } 52750aadb33SDmitri Tikhonov 5285392f7a3SLiteSpeed Tech if (acki->flags & AI_TRUNCATED) 5295392f7a3SLiteSpeed Tech { 530de46bf2fSDmitri Tikhonov nw = snprintf(buf + off, bufsz - off, RANGES_TRUNCATED_STR); 5315392f7a3SLiteSpeed Tech if (nw > bufsz - off) 532de46bf2fSDmitri Tikhonov return; 5335392f7a3SLiteSpeed Tech off += nw; 5345392f7a3SLiteSpeed Tech } 5355392f7a3SLiteSpeed Tech 5365392f7a3SLiteSpeed Tech if (acki->flags & AI_ECN) 5375392f7a3SLiteSpeed Tech { 5385392f7a3SLiteSpeed Tech for (ecn = 1; ecn <= 3; ++ecn) 5395392f7a3SLiteSpeed Tech { 5405392f7a3SLiteSpeed Tech nw = snprintf(buf + off, bufsz - off, " %s: %"PRIu64"%.*s", 5415392f7a3SLiteSpeed Tech ecn2str[ecn], acki->ecn_counts[ecn], ecn < 3, ";"); 5425392f7a3SLiteSpeed Tech if (nw > bufsz - off) 543de46bf2fSDmitri Tikhonov return; 5445392f7a3SLiteSpeed Tech off += nw; 5455392f7a3SLiteSpeed Tech } 5465392f7a3SLiteSpeed Tech } 54750aadb33SDmitri Tikhonov} 5489626cfc2SDmitri Tikhonov 5499626cfc2SDmitri Tikhonov 5509626cfc2SDmitri Tikhonovsize_t 5519626cfc2SDmitri Tikhonovlsquic_gquic_po_header_sz (enum packet_out_flags flags) 5529626cfc2SDmitri Tikhonov{ 5539626cfc2SDmitri Tikhonov return 1 /* Type */ 5549626cfc2SDmitri Tikhonov + (!!(flags & PO_CONN_ID) << 3) /* Connection ID */ 5559626cfc2SDmitri Tikhonov + (!!(flags & PO_VERSION) << 2) /* Version */ 5569626cfc2SDmitri Tikhonov + (!!(flags & PO_NONCE) << 5) /* Nonce */ 557c7d81ce1SDmitri Tikhonov + gquic_packno_bits2len((flags >> POBIT_SHIFT) & 0x3) /* Packet number */ 5589626cfc2SDmitri Tikhonov ; 5599626cfc2SDmitri Tikhonov} 5609626cfc2SDmitri Tikhonov 5619626cfc2SDmitri Tikhonov 5629626cfc2SDmitri Tikhonovsize_t 5639626cfc2SDmitri Tikhonovlsquic_gquic_packout_size (const struct lsquic_conn *conn, 5649626cfc2SDmitri Tikhonov const struct lsquic_packet_out *packet_out) 5659626cfc2SDmitri Tikhonov{ 5669626cfc2SDmitri Tikhonov return lsquic_gquic_po_header_sz(packet_out->po_flags) 5679626cfc2SDmitri Tikhonov + packet_out->po_data_sz 5685392f7a3SLiteSpeed Tech + GQUIC_PACKET_HASH_SZ 5699626cfc2SDmitri Tikhonov ; 5709626cfc2SDmitri Tikhonov} 5719626cfc2SDmitri Tikhonov 5729626cfc2SDmitri Tikhonov 5739626cfc2SDmitri Tikhonovsize_t 5749626cfc2SDmitri Tikhonovlsquic_gquic_packout_header_size (const struct lsquic_conn *conn, 5755392f7a3SLiteSpeed Tech enum packet_out_flags flags, size_t dcid_len) 5769626cfc2SDmitri Tikhonov{ 5779626cfc2SDmitri Tikhonov return lsquic_gquic_po_header_sz(flags); 5789626cfc2SDmitri Tikhonov} 5799626cfc2SDmitri Tikhonov 5809626cfc2SDmitri Tikhonov 5815392f7a3SLiteSpeed Techint 5825392f7a3SLiteSpeed Techlsquic_gquic_gen_ver_nego_pkt (unsigned char *buf, size_t bufsz, 5835392f7a3SLiteSpeed Tech const lsquic_cid_t *cid, unsigned version_bitmask) 5845392f7a3SLiteSpeed Tech{ 5855392f7a3SLiteSpeed Tech int sz; 5865392f7a3SLiteSpeed Tech unsigned char *p = buf; 5875392f7a3SLiteSpeed Tech unsigned char *const pend = p + bufsz; 5885392f7a3SLiteSpeed Tech 5895392f7a3SLiteSpeed Tech CHECK_SPACE(1, p, pend); 5905392f7a3SLiteSpeed Tech *p = PACKET_PUBLIC_FLAGS_VERSION | PACKET_PUBLIC_FLAGS_8BYTE_CONNECTION_ID; 5915392f7a3SLiteSpeed Tech ++p; 5925392f7a3SLiteSpeed Tech 5935392f7a3SLiteSpeed Tech if (GQUIC_CID_LEN != cid->len) 5945392f7a3SLiteSpeed Tech return -1; 5955392f7a3SLiteSpeed Tech 5965392f7a3SLiteSpeed Tech CHECK_SPACE(GQUIC_CID_LEN, p, pend); 5975392f7a3SLiteSpeed Tech memcpy(p, cid->idbuf, GQUIC_CID_LEN); 5985392f7a3SLiteSpeed Tech p += GQUIC_CID_LEN; 5995392f7a3SLiteSpeed Tech 6005392f7a3SLiteSpeed Tech sz = lsquic_gen_ver_tags(p, pend - p, version_bitmask); 6015392f7a3SLiteSpeed Tech if (sz < 0) 6025392f7a3SLiteSpeed Tech return -1; 6035392f7a3SLiteSpeed Tech 6045392f7a3SLiteSpeed Tech return p + sz - buf; 6055392f7a3SLiteSpeed Tech} 6065392f7a3SLiteSpeed Tech 6075392f7a3SLiteSpeed Tech 608c7d81ce1SDmitri Tikhonovunsigned 609c7d81ce1SDmitri Tikhonovlsquic_gquic_packno_bits2len (enum packno_bits bits) 610c7d81ce1SDmitri Tikhonov{ 611c7d81ce1SDmitri Tikhonov return gquic_packno_bits2len(bits); 612c7d81ce1SDmitri Tikhonov} 613c7d81ce1SDmitri Tikhonov 614c7d81ce1SDmitri Tikhonov 615c7d81ce1SDmitri Tikhonovenum packno_bits 616c7d81ce1SDmitri Tikhonovlsquic_gquic_calc_packno_bits (lsquic_packno_t packno, 617c7d81ce1SDmitri Tikhonov lsquic_packno_t least_unacked, uint64_t n_in_flight) 618c7d81ce1SDmitri Tikhonov{ 619c7d81ce1SDmitri Tikhonov uint64_t delta; 620c7d81ce1SDmitri Tikhonov unsigned bits; 621c7d81ce1SDmitri Tikhonov 622c7d81ce1SDmitri Tikhonov delta = packno - least_unacked; 623c7d81ce1SDmitri Tikhonov if (n_in_flight > delta) 624c7d81ce1SDmitri Tikhonov delta = n_in_flight; 625c7d81ce1SDmitri Tikhonov 626c7d81ce1SDmitri Tikhonov delta *= 4; 627c7d81ce1SDmitri Tikhonov bits = (delta > (1ULL << 8)) 628c7d81ce1SDmitri Tikhonov + (delta > (1ULL << 16)) 629c7d81ce1SDmitri Tikhonov + (delta > (1ULL << 32)); 630c7d81ce1SDmitri Tikhonov 631c7d81ce1SDmitri Tikhonov return bits; 632c7d81ce1SDmitri Tikhonov} 633de46bf2fSDmitri Tikhonov 634de46bf2fSDmitri Tikhonov 635de46bf2fSDmitri Tikhonov/* `dst' serves both as source and destination. `src' is the new frame */ 636de46bf2fSDmitri Tikhonovint 637de46bf2fSDmitri Tikhonovlsquic_merge_acks (struct ack_info *dst, const struct ack_info *src) 638de46bf2fSDmitri Tikhonov{ 639de46bf2fSDmitri Tikhonov const struct lsquic_packno_range *a, *a_end, *b, *b_end, **p; 640de46bf2fSDmitri Tikhonov struct lsquic_packno_range *out, *out_end; 641de46bf2fSDmitri Tikhonov unsigned i; 642de46bf2fSDmitri Tikhonov struct lsquic_packno_range out_ranges[256]; 643de46bf2fSDmitri Tikhonov 644de46bf2fSDmitri Tikhonov if (!(dst->n_ranges && src->n_ranges)) 645de46bf2fSDmitri Tikhonov return -1; 646de46bf2fSDmitri Tikhonov 647de46bf2fSDmitri Tikhonov a = dst->ranges; 648de46bf2fSDmitri Tikhonov a_end = a + dst->n_ranges; 649de46bf2fSDmitri Tikhonov b = src->ranges; 650de46bf2fSDmitri Tikhonov b_end = b + src->n_ranges; 651de46bf2fSDmitri Tikhonov out = out_ranges; 652de46bf2fSDmitri Tikhonov out_end = out + sizeof(out_ranges) / sizeof(out_ranges[0]); 653de46bf2fSDmitri Tikhonov 654de46bf2fSDmitri Tikhonov if (a->high >= b->high) 655de46bf2fSDmitri Tikhonov *out = *a; 656de46bf2fSDmitri Tikhonov else 657de46bf2fSDmitri Tikhonov *out = *b; 658de46bf2fSDmitri Tikhonov 659de46bf2fSDmitri Tikhonov while (1) 660de46bf2fSDmitri Tikhonov { 661de46bf2fSDmitri Tikhonov if (a < a_end && b < b_end) 662de46bf2fSDmitri Tikhonov { 663de46bf2fSDmitri Tikhonov if (a->high >= b->high) 664de46bf2fSDmitri Tikhonov p = &a; 665de46bf2fSDmitri Tikhonov else 666de46bf2fSDmitri Tikhonov p = &b; 667de46bf2fSDmitri Tikhonov } 668de46bf2fSDmitri Tikhonov else if (a < a_end) 669de46bf2fSDmitri Tikhonov p = &a; 670de46bf2fSDmitri Tikhonov else if (b < b_end) 671de46bf2fSDmitri Tikhonov p = &b; 672de46bf2fSDmitri Tikhonov else 673de46bf2fSDmitri Tikhonov { 674de46bf2fSDmitri Tikhonov ++out; 675de46bf2fSDmitri Tikhonov break; 676de46bf2fSDmitri Tikhonov } 677de46bf2fSDmitri Tikhonov 678de46bf2fSDmitri Tikhonov if ((*p)->high + 1 >= out->low) 679de46bf2fSDmitri Tikhonov out->low = (*p)->low; 680de46bf2fSDmitri Tikhonov else if (out + 1 < out_end) 681de46bf2fSDmitri Tikhonov *++out = **p; 682de46bf2fSDmitri Tikhonov else 683de46bf2fSDmitri Tikhonov return -1; 684de46bf2fSDmitri Tikhonov ++*p; 685de46bf2fSDmitri Tikhonov } 686de46bf2fSDmitri Tikhonov 687de46bf2fSDmitri Tikhonov if (src->flags & AI_ECN) 688de46bf2fSDmitri Tikhonov for (i = 0; i < sizeof(src->ecn_counts) 689de46bf2fSDmitri Tikhonov / sizeof(src->ecn_counts[0]); ++i) 690de46bf2fSDmitri Tikhonov dst->ecn_counts[i] += src->ecn_counts[i]; 691de46bf2fSDmitri Tikhonov dst->flags |= src->flags; 692de46bf2fSDmitri Tikhonov dst->lack_delta = src->lack_delta; 693de46bf2fSDmitri Tikhonov dst->n_ranges = out - out_ranges; 694de46bf2fSDmitri Tikhonov memcpy(dst->ranges, out_ranges, sizeof(out_ranges[0]) * dst->n_ranges); 695de46bf2fSDmitri Tikhonov 696de46bf2fSDmitri Tikhonov return 0; 697de46bf2fSDmitri Tikhonov} 698