1a74702c6SGeorge Wang/* Copyright (c) 2017 - 2022 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_parse_common.h" 2550aadb33SDmitri Tikhonov#include "lsquic_parse.h" 269626cfc2SDmitri Tikhonov#include "lsquic_version.h" 2750aadb33SDmitri Tikhonov#include "lsquic.h" 2850aadb33SDmitri Tikhonov 2950aadb33SDmitri Tikhonov#define LSQUIC_LOGGER_MODULE LSQLM_PARSE 3050aadb33SDmitri Tikhonov#include "lsquic_logger.h" 3150aadb33SDmitri Tikhonov 3250aadb33SDmitri Tikhonov#define CHECK_SPACE(need, pstart, pend) \ 3350aadb33SDmitri Tikhonov do { if ((intptr_t) (need) > ((pend) - (pstart))) { return -1; } } while (0) 3450aadb33SDmitri Tikhonov 3550aadb33SDmitri Tikhonov/* This partially parses `packet_in' and returns 0 if in case it succeeded and 3650aadb33SDmitri Tikhonov * -1 on failure. 3750aadb33SDmitri Tikhonov * 3850aadb33SDmitri Tikhonov * After this function returns 0, connection ID, nonce, and version fields can 3950aadb33SDmitri Tikhonov * be examined. To finsh parsing the packet, call version-specific 4050aadb33SDmitri Tikhonov * pf_parse_packet_in_finish() routine. 4150aadb33SDmitri Tikhonov */ 4250aadb33SDmitri Tikhonovint 435392f7a3SLiteSpeed Techlsquic_gquic_parse_packet_in_begin (lsquic_packet_in_t *packet_in, 445392f7a3SLiteSpeed Tech size_t length, int is_server, unsigned cid_len, 455392f7a3SLiteSpeed Tech struct packin_parse_state *state) 4650aadb33SDmitri Tikhonov{ 4750aadb33SDmitri Tikhonov int nbytes; 4850aadb33SDmitri Tikhonov enum PACKET_PUBLIC_FLAGS public_flags; 4950aadb33SDmitri Tikhonov const unsigned char *p = packet_in->pi_data; 5050aadb33SDmitri Tikhonov const unsigned char *const pend = packet_in->pi_data + length; 5150aadb33SDmitri Tikhonov 525392f7a3SLiteSpeed Tech if (length > GQUIC_MAX_PACKET_SZ) 535392f7a3SLiteSpeed Tech { 545392f7a3SLiteSpeed Tech LSQ_DEBUG("Cannot handle packet_in_size(%zd) > %d packet incoming " 555392f7a3SLiteSpeed Tech "packet's header", length, GQUIC_MAX_PACKET_SZ); 565392f7a3SLiteSpeed Tech return -1; 575392f7a3SLiteSpeed Tech } 585392f7a3SLiteSpeed Tech 5950aadb33SDmitri Tikhonov CHECK_SPACE(1, p, pend); 6050aadb33SDmitri Tikhonov 6150aadb33SDmitri Tikhonov public_flags = *p++; 6250aadb33SDmitri Tikhonov 6350aadb33SDmitri Tikhonov if (public_flags & PACKET_PUBLIC_FLAGS_8BYTE_CONNECTION_ID) 6450aadb33SDmitri Tikhonov { 6550aadb33SDmitri Tikhonov CHECK_SPACE(8, p, pend); 665392f7a3SLiteSpeed Tech memset(&packet_in->pi_conn_id, 0, sizeof(packet_in->pi_conn_id)); 675392f7a3SLiteSpeed Tech packet_in->pi_conn_id.len = 8; 685392f7a3SLiteSpeed Tech memcpy(&packet_in->pi_conn_id.idbuf, p, 8); 6950aadb33SDmitri Tikhonov packet_in->pi_flags |= PI_CONN_ID; 7050aadb33SDmitri Tikhonov p += 8; 7150aadb33SDmitri Tikhonov } 7250aadb33SDmitri Tikhonov 7350aadb33SDmitri Tikhonov if (public_flags & PACKET_PUBLIC_FLAGS_VERSION) 7450aadb33SDmitri Tikhonov { 7550aadb33SDmitri Tikhonov /* It seems that version negotiation packets sent by Google may have 7650aadb33SDmitri Tikhonov * NONCE bit set. Ignore it: 7750aadb33SDmitri Tikhonov */ 7850aadb33SDmitri Tikhonov public_flags &= ~PACKET_PUBLIC_FLAGS_NONCE; 7950aadb33SDmitri Tikhonov 8050aadb33SDmitri Tikhonov if (is_server) 8150aadb33SDmitri Tikhonov { 8250aadb33SDmitri Tikhonov CHECK_SPACE(4, p, pend); 8350aadb33SDmitri Tikhonov packet_in->pi_quic_ver = p - packet_in->pi_data; 8450aadb33SDmitri Tikhonov p += 4; 8550aadb33SDmitri Tikhonov } 8650aadb33SDmitri Tikhonov else 8750aadb33SDmitri Tikhonov { /* OK, we have a version negotiation packet. We need to verify 8850aadb33SDmitri Tikhonov * that it has correct structure. See Section 4.3 of 8950aadb33SDmitri Tikhonov * [draft-ietf-quic-transport-00]. 9050aadb33SDmitri Tikhonov */ 9150aadb33SDmitri Tikhonov if ((public_flags & ~(PACKET_PUBLIC_FLAGS_VERSION| 9250aadb33SDmitri Tikhonov PACKET_PUBLIC_FLAGS_8BYTE_CONNECTION_ID)) 9350aadb33SDmitri Tikhonov || ((pend - p) & 3)) 9450aadb33SDmitri Tikhonov return -1; 9550aadb33SDmitri Tikhonov CHECK_SPACE(4, p, pend); 9650aadb33SDmitri Tikhonov packet_in->pi_quic_ver = p - packet_in->pi_data; 9750aadb33SDmitri Tikhonov p = pend; 9850aadb33SDmitri Tikhonov } 9950aadb33SDmitri Tikhonov } 10050aadb33SDmitri Tikhonov else 10150aadb33SDmitri Tikhonov { 10250aadb33SDmitri Tikhonov /* From [draft-hamilton-quic-transport-protocol-01]: 10350aadb33SDmitri Tikhonov * 0x40 = MULTIPATH. This bit is reserved for multipath use. 10450aadb33SDmitri Tikhonov * 0x80 is currently unused, and must be set to 0. 10550aadb33SDmitri Tikhonov * 10650aadb33SDmitri Tikhonov * The reference implementation checks that two high bits are not set 10750aadb33SDmitri Tikhonov * if version flag is not set or if the version is the same. For our 10850aadb33SDmitri Tikhonov * purposes, all GQUIC version we support so far have these bits set 10950aadb33SDmitri Tikhonov * to zero. 11050aadb33SDmitri Tikhonov */ 11150aadb33SDmitri Tikhonov if (public_flags & (0x80|0x40)) 11250aadb33SDmitri Tikhonov return -1; 11350aadb33SDmitri Tikhonov packet_in->pi_quic_ver = 0; 11450aadb33SDmitri Tikhonov } 11550aadb33SDmitri Tikhonov 11650aadb33SDmitri Tikhonov if (!is_server && (public_flags & PACKET_PUBLIC_FLAGS_NONCE) == 11750aadb33SDmitri Tikhonov PACKET_PUBLIC_FLAGS_NONCE) 11850aadb33SDmitri Tikhonov { 11950aadb33SDmitri Tikhonov CHECK_SPACE(32, p, pend); 12050aadb33SDmitri Tikhonov packet_in->pi_nonce = p - packet_in->pi_data; 12150aadb33SDmitri Tikhonov p += 32; 12250aadb33SDmitri Tikhonov } 12350aadb33SDmitri Tikhonov else 12450aadb33SDmitri Tikhonov packet_in->pi_nonce = 0; 12550aadb33SDmitri Tikhonov 12650aadb33SDmitri Tikhonov state->pps_p = p; 12750aadb33SDmitri Tikhonov 12850aadb33SDmitri Tikhonov packet_in->pi_packno = 0; 12950aadb33SDmitri Tikhonov if (0 == (public_flags & (PACKET_PUBLIC_FLAGS_VERSION|PACKET_PUBLIC_FLAGS_RST)) 13050aadb33SDmitri Tikhonov || ((public_flags & PACKET_PUBLIC_FLAGS_VERSION) && is_server)) 13150aadb33SDmitri Tikhonov { 13250aadb33SDmitri Tikhonov nbytes = twobit_to_1246((public_flags >> 4) & 3); 13350aadb33SDmitri Tikhonov CHECK_SPACE(nbytes, p, pend); 13450aadb33SDmitri Tikhonov p += nbytes; 13550aadb33SDmitri Tikhonov state->pps_nbytes = nbytes; 13650aadb33SDmitri Tikhonov } 13750aadb33SDmitri Tikhonov else 13850aadb33SDmitri Tikhonov state->pps_nbytes = 0; 13950aadb33SDmitri Tikhonov 14050aadb33SDmitri Tikhonov packet_in->pi_header_sz = p - packet_in->pi_data; 14150aadb33SDmitri Tikhonov packet_in->pi_frame_types = 0; 14250aadb33SDmitri Tikhonov memset(&packet_in->pi_next, 0, sizeof(packet_in->pi_next)); 14350aadb33SDmitri Tikhonov packet_in->pi_data_sz = length; 14450aadb33SDmitri Tikhonov packet_in->pi_refcnt = 0; 14550aadb33SDmitri Tikhonov packet_in->pi_received = 0; 1469626cfc2SDmitri Tikhonov packet_in->pi_flags |= PI_GQUIC; 147c7d81ce1SDmitri Tikhonov packet_in->pi_flags |= ((public_flags >> 4) & 3) << PIBIT_BITS_SHIFT; 14850aadb33SDmitri Tikhonov 14950aadb33SDmitri Tikhonov return 0; 15050aadb33SDmitri Tikhonov} 15150aadb33SDmitri Tikhonov 15250aadb33SDmitri Tikhonov 1535392f7a3SLiteSpeed Techstatic const unsigned char simple_prst_payload[] = { 1545392f7a3SLiteSpeed Tech 'P', 'R', 'S', 'T', 1555392f7a3SLiteSpeed Tech 0x01, 0x00, 0x00, 0x00, 1565392f7a3SLiteSpeed Tech 'R', 'N', 'O', 'N', 1575392f7a3SLiteSpeed Tech 0x08, 0x00, 0x00, 0x00, 1585392f7a3SLiteSpeed Tech 1, 2, 3, 4, 5, 6, 7, 8, 1595392f7a3SLiteSpeed Tech}; 1605392f7a3SLiteSpeed Tech 1615392f7a3SLiteSpeed Tech 1625392f7a3SLiteSpeed Techtypedef char correct_simple_prst_size[(GQUIC_RESET_SZ == 163fb3e20e0SDmitri Tikhonov 1 + GQUIC_CID_LEN + sizeof(simple_prst_payload)) ? 1 : -1 ]; 1645392f7a3SLiteSpeed Tech 1655392f7a3SLiteSpeed Tech 1665392f7a3SLiteSpeed Techssize_t 1675392f7a3SLiteSpeed Techlsquic_generate_gquic_reset (const lsquic_cid_t *cidp, 1685392f7a3SLiteSpeed Tech unsigned char *buf, size_t buf_sz) 1695392f7a3SLiteSpeed Tech{ 1705392f7a3SLiteSpeed Tech lsquic_cid_t cid; 1715392f7a3SLiteSpeed Tech 1725392f7a3SLiteSpeed Tech if (buf_sz < 1 + GQUIC_CID_LEN + sizeof(simple_prst_payload)) 1735392f7a3SLiteSpeed Tech { 1745392f7a3SLiteSpeed Tech errno = ENOBUFS; 1755392f7a3SLiteSpeed Tech return -1; 1765392f7a3SLiteSpeed Tech } 1775392f7a3SLiteSpeed Tech 1785392f7a3SLiteSpeed Tech if (cidp) 1795392f7a3SLiteSpeed Tech { 1805392f7a3SLiteSpeed Tech assert(GQUIC_CID_LEN == cidp->len); 1815392f7a3SLiteSpeed Tech cid = *cidp; 1825392f7a3SLiteSpeed Tech } 1835392f7a3SLiteSpeed Tech else 1845392f7a3SLiteSpeed Tech { 1855392f7a3SLiteSpeed Tech memset(&cid, 0, sizeof(cid)); 1865392f7a3SLiteSpeed Tech cid.len = GQUIC_CID_LEN; 1875392f7a3SLiteSpeed Tech } 1885392f7a3SLiteSpeed Tech 1895392f7a3SLiteSpeed Tech *buf++ = PACKET_PUBLIC_FLAGS_RST | PACKET_PUBLIC_FLAGS_8BYTE_CONNECTION_ID; 1905392f7a3SLiteSpeed Tech 1915392f7a3SLiteSpeed Tech memcpy(buf, cid.idbuf, GQUIC_CID_LEN); 1925392f7a3SLiteSpeed Tech buf += GQUIC_CID_LEN; 1935392f7a3SLiteSpeed Tech 1945392f7a3SLiteSpeed Tech memcpy(buf, simple_prst_payload, sizeof(simple_prst_payload)); 1955392f7a3SLiteSpeed Tech return 1 + GQUIC_CID_LEN + sizeof(simple_prst_payload); 1965392f7a3SLiteSpeed Tech} 1975392f7a3SLiteSpeed Tech 1985392f7a3SLiteSpeed Tech 1997a8b2eceSDmitri Tikhonovstatic const enum quic_frame_type byte2frame_type_Q035_thru_Q046[0x100] = 20050aadb33SDmitri Tikhonov{ 20150aadb33SDmitri Tikhonov [0x00] = QUIC_FRAME_PADDING, 20250aadb33SDmitri Tikhonov [0x01] = QUIC_FRAME_RST_STREAM, 20350aadb33SDmitri Tikhonov [0x02] = QUIC_FRAME_CONNECTION_CLOSE, 20450aadb33SDmitri Tikhonov [0x03] = QUIC_FRAME_GOAWAY, 20550aadb33SDmitri Tikhonov [0x04] = QUIC_FRAME_WINDOW_UPDATE, 20650aadb33SDmitri Tikhonov [0x05] = QUIC_FRAME_BLOCKED, 20750aadb33SDmitri Tikhonov [0x06] = QUIC_FRAME_STOP_WAITING, 20850aadb33SDmitri Tikhonov [0x07] = QUIC_FRAME_PING, 20950aadb33SDmitri Tikhonov [0x08] = QUIC_FRAME_INVALID, 21050aadb33SDmitri Tikhonov [0x09] = QUIC_FRAME_INVALID, 21150aadb33SDmitri Tikhonov [0x0A] = QUIC_FRAME_INVALID, 21250aadb33SDmitri Tikhonov [0x0B] = QUIC_FRAME_INVALID, 21350aadb33SDmitri Tikhonov [0x0C] = QUIC_FRAME_INVALID, 21450aadb33SDmitri Tikhonov [0x0D] = QUIC_FRAME_INVALID, 21550aadb33SDmitri Tikhonov [0x0E] = QUIC_FRAME_INVALID, 21650aadb33SDmitri Tikhonov [0x0F] = QUIC_FRAME_INVALID, 21750aadb33SDmitri Tikhonov [0x10] = QUIC_FRAME_INVALID, 21850aadb33SDmitri Tikhonov [0x11] = QUIC_FRAME_INVALID, 21950aadb33SDmitri Tikhonov [0x12] = QUIC_FRAME_INVALID, 22050aadb33SDmitri Tikhonov [0x13] = QUIC_FRAME_INVALID, 22150aadb33SDmitri Tikhonov [0x14] = QUIC_FRAME_INVALID, 22250aadb33SDmitri Tikhonov [0x15] = QUIC_FRAME_INVALID, 22350aadb33SDmitri Tikhonov [0x16] = QUIC_FRAME_INVALID, 22450aadb33SDmitri Tikhonov [0x17] = QUIC_FRAME_INVALID, 22550aadb33SDmitri Tikhonov [0x18] = QUIC_FRAME_INVALID, 22650aadb33SDmitri Tikhonov [0x19] = QUIC_FRAME_INVALID, 22750aadb33SDmitri Tikhonov [0x1A] = QUIC_FRAME_INVALID, 22850aadb33SDmitri Tikhonov [0x1B] = QUIC_FRAME_INVALID, 22950aadb33SDmitri Tikhonov [0x1C] = QUIC_FRAME_INVALID, 23050aadb33SDmitri Tikhonov [0x1D] = QUIC_FRAME_INVALID, 23150aadb33SDmitri Tikhonov [0x1E] = QUIC_FRAME_INVALID, 23250aadb33SDmitri Tikhonov [0x1F] = QUIC_FRAME_INVALID, 23350aadb33SDmitri Tikhonov [0x20] = QUIC_FRAME_INVALID, 23450aadb33SDmitri Tikhonov [0x21] = QUIC_FRAME_INVALID, 23550aadb33SDmitri Tikhonov [0x22] = QUIC_FRAME_INVALID, 23650aadb33SDmitri Tikhonov [0x23] = QUIC_FRAME_INVALID, 23750aadb33SDmitri Tikhonov [0x24] = QUIC_FRAME_INVALID, 23850aadb33SDmitri Tikhonov [0x25] = QUIC_FRAME_INVALID, 23950aadb33SDmitri Tikhonov [0x26] = QUIC_FRAME_INVALID, 24050aadb33SDmitri Tikhonov [0x27] = QUIC_FRAME_INVALID, 24150aadb33SDmitri Tikhonov [0x28] = QUIC_FRAME_INVALID, 24250aadb33SDmitri Tikhonov [0x29] = QUIC_FRAME_INVALID, 24350aadb33SDmitri Tikhonov [0x2A] = QUIC_FRAME_INVALID, 24450aadb33SDmitri Tikhonov [0x2B] = QUIC_FRAME_INVALID, 24550aadb33SDmitri Tikhonov [0x2C] = QUIC_FRAME_INVALID, 24650aadb33SDmitri Tikhonov [0x2D] = QUIC_FRAME_INVALID, 24750aadb33SDmitri Tikhonov [0x2E] = QUIC_FRAME_INVALID, 24850aadb33SDmitri Tikhonov [0x2F] = QUIC_FRAME_INVALID, 24950aadb33SDmitri Tikhonov [0x30] = QUIC_FRAME_INVALID, 25050aadb33SDmitri Tikhonov [0x31] = QUIC_FRAME_INVALID, 25150aadb33SDmitri Tikhonov [0x32] = QUIC_FRAME_INVALID, 25250aadb33SDmitri Tikhonov [0x33] = QUIC_FRAME_INVALID, 25350aadb33SDmitri Tikhonov [0x34] = QUIC_FRAME_INVALID, 25450aadb33SDmitri Tikhonov [0x35] = QUIC_FRAME_INVALID, 25550aadb33SDmitri Tikhonov [0x36] = QUIC_FRAME_INVALID, 25650aadb33SDmitri Tikhonov [0x37] = QUIC_FRAME_INVALID, 25750aadb33SDmitri Tikhonov [0x38] = QUIC_FRAME_INVALID, 25850aadb33SDmitri Tikhonov [0x39] = QUIC_FRAME_INVALID, 25950aadb33SDmitri Tikhonov [0x3A] = QUIC_FRAME_INVALID, 26050aadb33SDmitri Tikhonov [0x3B] = QUIC_FRAME_INVALID, 26150aadb33SDmitri Tikhonov [0x3C] = QUIC_FRAME_INVALID, 26250aadb33SDmitri Tikhonov [0x3D] = QUIC_FRAME_INVALID, 26350aadb33SDmitri Tikhonov [0x3E] = QUIC_FRAME_INVALID, 26450aadb33SDmitri Tikhonov [0x3F] = QUIC_FRAME_INVALID, 26550aadb33SDmitri Tikhonov [0x40] = QUIC_FRAME_ACK, 26650aadb33SDmitri Tikhonov [0x41] = QUIC_FRAME_ACK, 26750aadb33SDmitri Tikhonov [0x42] = QUIC_FRAME_ACK, 26850aadb33SDmitri Tikhonov [0x43] = QUIC_FRAME_ACK, 26950aadb33SDmitri Tikhonov [0x44] = QUIC_FRAME_ACK, 27050aadb33SDmitri Tikhonov [0x45] = QUIC_FRAME_ACK, 27150aadb33SDmitri Tikhonov [0x46] = QUIC_FRAME_ACK, 27250aadb33SDmitri Tikhonov [0x47] = QUIC_FRAME_ACK, 27350aadb33SDmitri Tikhonov [0x48] = QUIC_FRAME_ACK, 27450aadb33SDmitri Tikhonov [0x49] = QUIC_FRAME_ACK, 27550aadb33SDmitri Tikhonov [0x4A] = QUIC_FRAME_ACK, 27650aadb33SDmitri Tikhonov [0x4B] = QUIC_FRAME_ACK, 27750aadb33SDmitri Tikhonov [0x4C] = QUIC_FRAME_ACK, 27850aadb33SDmitri Tikhonov [0x4D] = QUIC_FRAME_ACK, 27950aadb33SDmitri Tikhonov [0x4E] = QUIC_FRAME_ACK, 28050aadb33SDmitri Tikhonov [0x4F] = QUIC_FRAME_ACK, 28150aadb33SDmitri Tikhonov [0x50] = QUIC_FRAME_ACK, 28250aadb33SDmitri Tikhonov [0x51] = QUIC_FRAME_ACK, 28350aadb33SDmitri Tikhonov [0x52] = QUIC_FRAME_ACK, 28450aadb33SDmitri Tikhonov [0x53] = QUIC_FRAME_ACK, 28550aadb33SDmitri Tikhonov [0x54] = QUIC_FRAME_ACK, 28650aadb33SDmitri Tikhonov [0x55] = QUIC_FRAME_ACK, 28750aadb33SDmitri Tikhonov [0x56] = QUIC_FRAME_ACK, 28850aadb33SDmitri Tikhonov [0x57] = QUIC_FRAME_ACK, 28950aadb33SDmitri Tikhonov [0x58] = QUIC_FRAME_ACK, 29050aadb33SDmitri Tikhonov [0x59] = QUIC_FRAME_ACK, 29150aadb33SDmitri Tikhonov [0x5A] = QUIC_FRAME_ACK, 29250aadb33SDmitri Tikhonov [0x5B] = QUIC_FRAME_ACK, 29350aadb33SDmitri Tikhonov [0x5C] = QUIC_FRAME_ACK, 29450aadb33SDmitri Tikhonov [0x5D] = QUIC_FRAME_ACK, 29550aadb33SDmitri Tikhonov [0x5E] = QUIC_FRAME_ACK, 29650aadb33SDmitri Tikhonov [0x5F] = QUIC_FRAME_ACK, 29750aadb33SDmitri Tikhonov [0x60] = QUIC_FRAME_ACK, 29850aadb33SDmitri Tikhonov [0x61] = QUIC_FRAME_ACK, 29950aadb33SDmitri Tikhonov [0x62] = QUIC_FRAME_ACK, 30050aadb33SDmitri Tikhonov [0x63] = QUIC_FRAME_ACK, 30150aadb33SDmitri Tikhonov [0x64] = QUIC_FRAME_ACK, 30250aadb33SDmitri Tikhonov [0x65] = QUIC_FRAME_ACK, 30350aadb33SDmitri Tikhonov [0x66] = QUIC_FRAME_ACK, 30450aadb33SDmitri Tikhonov [0x67] = QUIC_FRAME_ACK, 30550aadb33SDmitri Tikhonov [0x68] = QUIC_FRAME_ACK, 30650aadb33SDmitri Tikhonov [0x69] = QUIC_FRAME_ACK, 30750aadb33SDmitri Tikhonov [0x6A] = QUIC_FRAME_ACK, 30850aadb33SDmitri Tikhonov [0x6B] = QUIC_FRAME_ACK, 30950aadb33SDmitri Tikhonov [0x6C] = QUIC_FRAME_ACK, 31050aadb33SDmitri Tikhonov [0x6D] = QUIC_FRAME_ACK, 31150aadb33SDmitri Tikhonov [0x6E] = QUIC_FRAME_ACK, 31250aadb33SDmitri Tikhonov [0x6F] = QUIC_FRAME_ACK, 31350aadb33SDmitri Tikhonov [0x70] = QUIC_FRAME_ACK, 31450aadb33SDmitri Tikhonov [0x71] = QUIC_FRAME_ACK, 31550aadb33SDmitri Tikhonov [0x72] = QUIC_FRAME_ACK, 31650aadb33SDmitri Tikhonov [0x73] = QUIC_FRAME_ACK, 31750aadb33SDmitri Tikhonov [0x74] = QUIC_FRAME_ACK, 31850aadb33SDmitri Tikhonov [0x75] = QUIC_FRAME_ACK, 31950aadb33SDmitri Tikhonov [0x76] = QUIC_FRAME_ACK, 32050aadb33SDmitri Tikhonov [0x77] = QUIC_FRAME_ACK, 32150aadb33SDmitri Tikhonov [0x78] = QUIC_FRAME_ACK, 32250aadb33SDmitri Tikhonov [0x79] = QUIC_FRAME_ACK, 32350aadb33SDmitri Tikhonov [0x7A] = QUIC_FRAME_ACK, 32450aadb33SDmitri Tikhonov [0x7B] = QUIC_FRAME_ACK, 32550aadb33SDmitri Tikhonov [0x7C] = QUIC_FRAME_ACK, 32650aadb33SDmitri Tikhonov [0x7D] = QUIC_FRAME_ACK, 32750aadb33SDmitri Tikhonov [0x7E] = QUIC_FRAME_ACK, 32850aadb33SDmitri Tikhonov [0x7F] = QUIC_FRAME_ACK, 32950aadb33SDmitri Tikhonov [0x80] = QUIC_FRAME_STREAM, 33050aadb33SDmitri Tikhonov [0x81] = QUIC_FRAME_STREAM, 33150aadb33SDmitri Tikhonov [0x82] = QUIC_FRAME_STREAM, 33250aadb33SDmitri Tikhonov [0x83] = QUIC_FRAME_STREAM, 33350aadb33SDmitri Tikhonov [0x84] = QUIC_FRAME_STREAM, 33450aadb33SDmitri Tikhonov [0x85] = QUIC_FRAME_STREAM, 33550aadb33SDmitri Tikhonov [0x86] = QUIC_FRAME_STREAM, 33650aadb33SDmitri Tikhonov [0x87] = QUIC_FRAME_STREAM, 33750aadb33SDmitri Tikhonov [0x88] = QUIC_FRAME_STREAM, 33850aadb33SDmitri Tikhonov [0x89] = QUIC_FRAME_STREAM, 33950aadb33SDmitri Tikhonov [0x8A] = QUIC_FRAME_STREAM, 34050aadb33SDmitri Tikhonov [0x8B] = QUIC_FRAME_STREAM, 34150aadb33SDmitri Tikhonov [0x8C] = QUIC_FRAME_STREAM, 34250aadb33SDmitri Tikhonov [0x8D] = QUIC_FRAME_STREAM, 34350aadb33SDmitri Tikhonov [0x8E] = QUIC_FRAME_STREAM, 34450aadb33SDmitri Tikhonov [0x8F] = QUIC_FRAME_STREAM, 34550aadb33SDmitri Tikhonov [0x90] = QUIC_FRAME_STREAM, 34650aadb33SDmitri Tikhonov [0x91] = QUIC_FRAME_STREAM, 34750aadb33SDmitri Tikhonov [0x92] = QUIC_FRAME_STREAM, 34850aadb33SDmitri Tikhonov [0x93] = QUIC_FRAME_STREAM, 34950aadb33SDmitri Tikhonov [0x94] = QUIC_FRAME_STREAM, 35050aadb33SDmitri Tikhonov [0x95] = QUIC_FRAME_STREAM, 35150aadb33SDmitri Tikhonov [0x96] = QUIC_FRAME_STREAM, 35250aadb33SDmitri Tikhonov [0x97] = QUIC_FRAME_STREAM, 35350aadb33SDmitri Tikhonov [0x98] = QUIC_FRAME_STREAM, 35450aadb33SDmitri Tikhonov [0x99] = QUIC_FRAME_STREAM, 35550aadb33SDmitri Tikhonov [0x9A] = QUIC_FRAME_STREAM, 35650aadb33SDmitri Tikhonov [0x9B] = QUIC_FRAME_STREAM, 35750aadb33SDmitri Tikhonov [0x9C] = QUIC_FRAME_STREAM, 35850aadb33SDmitri Tikhonov [0x9D] = QUIC_FRAME_STREAM, 35950aadb33SDmitri Tikhonov [0x9E] = QUIC_FRAME_STREAM, 36050aadb33SDmitri Tikhonov [0x9F] = QUIC_FRAME_STREAM, 36150aadb33SDmitri Tikhonov [0xA0] = QUIC_FRAME_STREAM, 36250aadb33SDmitri Tikhonov [0xA1] = QUIC_FRAME_STREAM, 36350aadb33SDmitri Tikhonov [0xA2] = QUIC_FRAME_STREAM, 36450aadb33SDmitri Tikhonov [0xA3] = QUIC_FRAME_STREAM, 36550aadb33SDmitri Tikhonov [0xA4] = QUIC_FRAME_STREAM, 36650aadb33SDmitri Tikhonov [0xA5] = QUIC_FRAME_STREAM, 36750aadb33SDmitri Tikhonov [0xA6] = QUIC_FRAME_STREAM, 36850aadb33SDmitri Tikhonov [0xA7] = QUIC_FRAME_STREAM, 36950aadb33SDmitri Tikhonov [0xA8] = QUIC_FRAME_STREAM, 37050aadb33SDmitri Tikhonov [0xA9] = QUIC_FRAME_STREAM, 37150aadb33SDmitri Tikhonov [0xAA] = QUIC_FRAME_STREAM, 37250aadb33SDmitri Tikhonov [0xAB] = QUIC_FRAME_STREAM, 37350aadb33SDmitri Tikhonov [0xAC] = QUIC_FRAME_STREAM, 37450aadb33SDmitri Tikhonov [0xAD] = QUIC_FRAME_STREAM, 37550aadb33SDmitri Tikhonov [0xAE] = QUIC_FRAME_STREAM, 37650aadb33SDmitri Tikhonov [0xAF] = QUIC_FRAME_STREAM, 37750aadb33SDmitri Tikhonov [0xB0] = QUIC_FRAME_STREAM, 37850aadb33SDmitri Tikhonov [0xB1] = QUIC_FRAME_STREAM, 37950aadb33SDmitri Tikhonov [0xB2] = QUIC_FRAME_STREAM, 38050aadb33SDmitri Tikhonov [0xB3] = QUIC_FRAME_STREAM, 38150aadb33SDmitri Tikhonov [0xB4] = QUIC_FRAME_STREAM, 38250aadb33SDmitri Tikhonov [0xB5] = QUIC_FRAME_STREAM, 38350aadb33SDmitri Tikhonov [0xB6] = QUIC_FRAME_STREAM, 38450aadb33SDmitri Tikhonov [0xB7] = QUIC_FRAME_STREAM, 38550aadb33SDmitri Tikhonov [0xB8] = QUIC_FRAME_STREAM, 38650aadb33SDmitri Tikhonov [0xB9] = QUIC_FRAME_STREAM, 38750aadb33SDmitri Tikhonov [0xBA] = QUIC_FRAME_STREAM, 38850aadb33SDmitri Tikhonov [0xBB] = QUIC_FRAME_STREAM, 38950aadb33SDmitri Tikhonov [0xBC] = QUIC_FRAME_STREAM, 39050aadb33SDmitri Tikhonov [0xBD] = QUIC_FRAME_STREAM, 39150aadb33SDmitri Tikhonov [0xBE] = QUIC_FRAME_STREAM, 39250aadb33SDmitri Tikhonov [0xBF] = QUIC_FRAME_STREAM, 39350aadb33SDmitri Tikhonov [0xC0] = QUIC_FRAME_STREAM, 39450aadb33SDmitri Tikhonov [0xC1] = QUIC_FRAME_STREAM, 39550aadb33SDmitri Tikhonov [0xC2] = QUIC_FRAME_STREAM, 39650aadb33SDmitri Tikhonov [0xC3] = QUIC_FRAME_STREAM, 39750aadb33SDmitri Tikhonov [0xC4] = QUIC_FRAME_STREAM, 39850aadb33SDmitri Tikhonov [0xC5] = QUIC_FRAME_STREAM, 39950aadb33SDmitri Tikhonov [0xC6] = QUIC_FRAME_STREAM, 40050aadb33SDmitri Tikhonov [0xC7] = QUIC_FRAME_STREAM, 40150aadb33SDmitri Tikhonov [0xC8] = QUIC_FRAME_STREAM, 40250aadb33SDmitri Tikhonov [0xC9] = QUIC_FRAME_STREAM, 40350aadb33SDmitri Tikhonov [0xCA] = QUIC_FRAME_STREAM, 40450aadb33SDmitri Tikhonov [0xCB] = QUIC_FRAME_STREAM, 40550aadb33SDmitri Tikhonov [0xCC] = QUIC_FRAME_STREAM, 40650aadb33SDmitri Tikhonov [0xCD] = QUIC_FRAME_STREAM, 40750aadb33SDmitri Tikhonov [0xCE] = QUIC_FRAME_STREAM, 40850aadb33SDmitri Tikhonov [0xCF] = QUIC_FRAME_STREAM, 40950aadb33SDmitri Tikhonov [0xD0] = QUIC_FRAME_STREAM, 41050aadb33SDmitri Tikhonov [0xD1] = QUIC_FRAME_STREAM, 41150aadb33SDmitri Tikhonov [0xD2] = QUIC_FRAME_STREAM, 41250aadb33SDmitri Tikhonov [0xD3] = QUIC_FRAME_STREAM, 41350aadb33SDmitri Tikhonov [0xD4] = QUIC_FRAME_STREAM, 41450aadb33SDmitri Tikhonov [0xD5] = QUIC_FRAME_STREAM, 41550aadb33SDmitri Tikhonov [0xD6] = QUIC_FRAME_STREAM, 41650aadb33SDmitri Tikhonov [0xD7] = QUIC_FRAME_STREAM, 41750aadb33SDmitri Tikhonov [0xD8] = QUIC_FRAME_STREAM, 41850aadb33SDmitri Tikhonov [0xD9] = QUIC_FRAME_STREAM, 41950aadb33SDmitri Tikhonov [0xDA] = QUIC_FRAME_STREAM, 42050aadb33SDmitri Tikhonov [0xDB] = QUIC_FRAME_STREAM, 42150aadb33SDmitri Tikhonov [0xDC] = QUIC_FRAME_STREAM, 42250aadb33SDmitri Tikhonov [0xDD] = QUIC_FRAME_STREAM, 42350aadb33SDmitri Tikhonov [0xDE] = QUIC_FRAME_STREAM, 42450aadb33SDmitri Tikhonov [0xDF] = QUIC_FRAME_STREAM, 42550aadb33SDmitri Tikhonov [0xE0] = QUIC_FRAME_STREAM, 42650aadb33SDmitri Tikhonov [0xE1] = QUIC_FRAME_STREAM, 42750aadb33SDmitri Tikhonov [0xE2] = QUIC_FRAME_STREAM, 42850aadb33SDmitri Tikhonov [0xE3] = QUIC_FRAME_STREAM, 42950aadb33SDmitri Tikhonov [0xE4] = QUIC_FRAME_STREAM, 43050aadb33SDmitri Tikhonov [0xE5] = QUIC_FRAME_STREAM, 43150aadb33SDmitri Tikhonov [0xE6] = QUIC_FRAME_STREAM, 43250aadb33SDmitri Tikhonov [0xE7] = QUIC_FRAME_STREAM, 43350aadb33SDmitri Tikhonov [0xE8] = QUIC_FRAME_STREAM, 43450aadb33SDmitri Tikhonov [0xE9] = QUIC_FRAME_STREAM, 43550aadb33SDmitri Tikhonov [0xEA] = QUIC_FRAME_STREAM, 43650aadb33SDmitri Tikhonov [0xEB] = QUIC_FRAME_STREAM, 43750aadb33SDmitri Tikhonov [0xEC] = QUIC_FRAME_STREAM, 43850aadb33SDmitri Tikhonov [0xED] = QUIC_FRAME_STREAM, 43950aadb33SDmitri Tikhonov [0xEE] = QUIC_FRAME_STREAM, 44050aadb33SDmitri Tikhonov [0xEF] = QUIC_FRAME_STREAM, 44150aadb33SDmitri Tikhonov [0xF0] = QUIC_FRAME_STREAM, 44250aadb33SDmitri Tikhonov [0xF1] = QUIC_FRAME_STREAM, 44350aadb33SDmitri Tikhonov [0xF2] = QUIC_FRAME_STREAM, 44450aadb33SDmitri Tikhonov [0xF3] = QUIC_FRAME_STREAM, 44550aadb33SDmitri Tikhonov [0xF4] = QUIC_FRAME_STREAM, 44650aadb33SDmitri Tikhonov [0xF5] = QUIC_FRAME_STREAM, 44750aadb33SDmitri Tikhonov [0xF6] = QUIC_FRAME_STREAM, 44850aadb33SDmitri Tikhonov [0xF7] = QUIC_FRAME_STREAM, 44950aadb33SDmitri Tikhonov [0xF8] = QUIC_FRAME_STREAM, 45050aadb33SDmitri Tikhonov [0xF9] = QUIC_FRAME_STREAM, 45150aadb33SDmitri Tikhonov [0xFA] = QUIC_FRAME_STREAM, 45250aadb33SDmitri Tikhonov [0xFB] = QUIC_FRAME_STREAM, 45350aadb33SDmitri Tikhonov [0xFC] = QUIC_FRAME_STREAM, 45450aadb33SDmitri Tikhonov [0xFD] = QUIC_FRAME_STREAM, 45550aadb33SDmitri Tikhonov [0xFE] = QUIC_FRAME_STREAM, 45650aadb33SDmitri Tikhonov [0xFF] = QUIC_FRAME_STREAM, 45750aadb33SDmitri Tikhonov}; 45850aadb33SDmitri Tikhonov 45950aadb33SDmitri Tikhonov 4606aba801dSDmitri Tikhonovenum quic_frame_type 461feca77f5SDmitri Tikhonovlsquic_parse_frame_type_gquic_Q035_thru_Q046 (const unsigned char *buf, 462feca77f5SDmitri Tikhonov size_t len) 46350aadb33SDmitri Tikhonov{ 464feca77f5SDmitri Tikhonov if (len > 0) 465feca77f5SDmitri Tikhonov return byte2frame_type_Q035_thru_Q046[buf[0]]; 466feca77f5SDmitri Tikhonov else 467feca77f5SDmitri Tikhonov return QUIC_FRAME_INVALID; 46850aadb33SDmitri Tikhonov} 46950aadb33SDmitri Tikhonov 47050aadb33SDmitri Tikhonov 471c51ce338SDmitri Tikhonovvoid 4727a8b2eceSDmitri Tikhonovlsquic_turn_on_fin_Q035_thru_Q046 (unsigned char *stream_header) 473c51ce338SDmitri Tikhonov{ 474c51ce338SDmitri Tikhonov /* 1fdoooss */ 475c51ce338SDmitri Tikhonov *stream_header |= 0x40; 476c51ce338SDmitri Tikhonov} 477c51ce338SDmitri Tikhonov 478c51ce338SDmitri Tikhonov 47950aadb33SDmitri Tikhonovsize_t 480a5fa05f9SDmitri Tikhonovlsquic_calc_stream_frame_header_sz_gquic (lsquic_stream_id_t stream_id, 4815392f7a3SLiteSpeed Tech uint64_t offset, unsigned data_sz_IGNORED) 48250aadb33SDmitri Tikhonov{ 48350aadb33SDmitri Tikhonov return 48450aadb33SDmitri Tikhonov /* Type */ 48550aadb33SDmitri Tikhonov 1 48650aadb33SDmitri Tikhonov /* Stream ID length */ 48750aadb33SDmitri Tikhonov + ((stream_id) > 0x0000FF) 48850aadb33SDmitri Tikhonov + ((stream_id) > 0x00FFFF) 48950aadb33SDmitri Tikhonov + ((stream_id) > 0xFFFFFF) 49050aadb33SDmitri Tikhonov + 1 49150aadb33SDmitri Tikhonov /* Offset length */ 49250aadb33SDmitri Tikhonov + ((offset) >= (1ULL << 56)) 49350aadb33SDmitri Tikhonov + ((offset) >= (1ULL << 48)) 49450aadb33SDmitri Tikhonov + ((offset) >= (1ULL << 40)) 49550aadb33SDmitri Tikhonov + ((offset) >= (1ULL << 32)) 49650aadb33SDmitri Tikhonov + ((offset) >= (1ULL << 24)) 49750aadb33SDmitri Tikhonov + ((offset) >= (1ULL << 16)) 49850aadb33SDmitri Tikhonov + (((offset) > 0) << 1) 49950aadb33SDmitri Tikhonov /* Add data length (2) yourself, if necessary */ 50050aadb33SDmitri Tikhonov ; 50150aadb33SDmitri Tikhonov} 50250aadb33SDmitri Tikhonov 50350aadb33SDmitri Tikhonov 5045392f7a3SLiteSpeed Techstatic const char *const ecn2str[4] = 5055392f7a3SLiteSpeed Tech{ 5065392f7a3SLiteSpeed Tech [ECN_NOT_ECT] = "", 5075392f7a3SLiteSpeed Tech [ECN_ECT0] = "ECT(0)", 5085392f7a3SLiteSpeed Tech [ECN_ECT1] = "ECT(1)", 5095392f7a3SLiteSpeed Tech [ECN_CE] = "CE", 5105392f7a3SLiteSpeed Tech}; 5115392f7a3SLiteSpeed Tech 5125392f7a3SLiteSpeed Tech 513de46bf2fSDmitri Tikhonovvoid 514de46bf2fSDmitri Tikhonovlsquic_acki2str (const struct ack_info *acki, char *buf, size_t bufsz) 51550aadb33SDmitri Tikhonov{ 516de46bf2fSDmitri Tikhonov size_t off, nw; 5175392f7a3SLiteSpeed Tech enum ecn ecn; 51850aadb33SDmitri Tikhonov unsigned n; 51950aadb33SDmitri Tikhonov 52050aadb33SDmitri Tikhonov off = 0; 52150aadb33SDmitri Tikhonov for (n = 0; n < acki->n_ranges; ++n) 52250aadb33SDmitri Tikhonov { 52350aadb33SDmitri Tikhonov nw = snprintf(buf + off, bufsz - off, "[%"PRIu64"-%"PRIu64"]", 52450aadb33SDmitri Tikhonov acki->ranges[n].high, acki->ranges[n].low); 52550aadb33SDmitri Tikhonov if (nw > bufsz - off) 526de46bf2fSDmitri Tikhonov return; 52750aadb33SDmitri Tikhonov off += nw; 52850aadb33SDmitri Tikhonov } 52950aadb33SDmitri Tikhonov 5305392f7a3SLiteSpeed Tech if (acki->flags & AI_TRUNCATED) 5315392f7a3SLiteSpeed Tech { 532de46bf2fSDmitri Tikhonov nw = snprintf(buf + off, bufsz - off, RANGES_TRUNCATED_STR); 5335392f7a3SLiteSpeed Tech if (nw > bufsz - off) 534de46bf2fSDmitri Tikhonov return; 5355392f7a3SLiteSpeed Tech off += nw; 5365392f7a3SLiteSpeed Tech } 5375392f7a3SLiteSpeed Tech 5385392f7a3SLiteSpeed Tech if (acki->flags & AI_ECN) 5395392f7a3SLiteSpeed Tech { 5405392f7a3SLiteSpeed Tech for (ecn = 1; ecn <= 3; ++ecn) 5415392f7a3SLiteSpeed Tech { 5425392f7a3SLiteSpeed Tech nw = snprintf(buf + off, bufsz - off, " %s: %"PRIu64"%.*s", 5435392f7a3SLiteSpeed Tech ecn2str[ecn], acki->ecn_counts[ecn], ecn < 3, ";"); 5445392f7a3SLiteSpeed Tech if (nw > bufsz - off) 545de46bf2fSDmitri Tikhonov return; 5465392f7a3SLiteSpeed Tech off += nw; 5475392f7a3SLiteSpeed Tech } 5485392f7a3SLiteSpeed Tech } 54950aadb33SDmitri Tikhonov} 5509626cfc2SDmitri Tikhonov 5519626cfc2SDmitri Tikhonov 5529626cfc2SDmitri Tikhonovsize_t 5539626cfc2SDmitri Tikhonovlsquic_gquic_po_header_sz (enum packet_out_flags flags) 5549626cfc2SDmitri Tikhonov{ 5559626cfc2SDmitri Tikhonov return 1 /* Type */ 5569626cfc2SDmitri Tikhonov + (!!(flags & PO_CONN_ID) << 3) /* Connection ID */ 5579626cfc2SDmitri Tikhonov + (!!(flags & PO_VERSION) << 2) /* Version */ 5589626cfc2SDmitri Tikhonov + (!!(flags & PO_NONCE) << 5) /* Nonce */ 559c7d81ce1SDmitri Tikhonov + gquic_packno_bits2len((flags >> POBIT_SHIFT) & 0x3) /* Packet number */ 5609626cfc2SDmitri Tikhonov ; 5619626cfc2SDmitri Tikhonov} 5629626cfc2SDmitri Tikhonov 5639626cfc2SDmitri Tikhonov 5649626cfc2SDmitri Tikhonovsize_t 5659626cfc2SDmitri Tikhonovlsquic_gquic_packout_size (const struct lsquic_conn *conn, 5669626cfc2SDmitri Tikhonov const struct lsquic_packet_out *packet_out) 5679626cfc2SDmitri Tikhonov{ 5689626cfc2SDmitri Tikhonov return lsquic_gquic_po_header_sz(packet_out->po_flags) 5699626cfc2SDmitri Tikhonov + packet_out->po_data_sz 5705392f7a3SLiteSpeed Tech + GQUIC_PACKET_HASH_SZ 5719626cfc2SDmitri Tikhonov ; 5729626cfc2SDmitri Tikhonov} 5739626cfc2SDmitri Tikhonov 5749626cfc2SDmitri Tikhonov 5759626cfc2SDmitri Tikhonovsize_t 5769626cfc2SDmitri Tikhonovlsquic_gquic_packout_header_size (const struct lsquic_conn *conn, 5774429f8eaSDmitri Tikhonov enum packet_out_flags flags, size_t dcid_len, 5784429f8eaSDmitri Tikhonov enum header_type unused) 5799626cfc2SDmitri Tikhonov{ 5809626cfc2SDmitri Tikhonov return lsquic_gquic_po_header_sz(flags); 5819626cfc2SDmitri Tikhonov} 5829626cfc2SDmitri Tikhonov 5839626cfc2SDmitri Tikhonov 5845392f7a3SLiteSpeed Techint 5855392f7a3SLiteSpeed Techlsquic_gquic_gen_ver_nego_pkt (unsigned char *buf, size_t bufsz, 5865392f7a3SLiteSpeed Tech const lsquic_cid_t *cid, unsigned version_bitmask) 5875392f7a3SLiteSpeed Tech{ 5885392f7a3SLiteSpeed Tech int sz; 5895392f7a3SLiteSpeed Tech unsigned char *p = buf; 5905392f7a3SLiteSpeed Tech unsigned char *const pend = p + bufsz; 5915392f7a3SLiteSpeed Tech 5925392f7a3SLiteSpeed Tech CHECK_SPACE(1, p, pend); 5935392f7a3SLiteSpeed Tech *p = PACKET_PUBLIC_FLAGS_VERSION | PACKET_PUBLIC_FLAGS_8BYTE_CONNECTION_ID; 5945392f7a3SLiteSpeed Tech ++p; 5955392f7a3SLiteSpeed Tech 5965392f7a3SLiteSpeed Tech if (GQUIC_CID_LEN != cid->len) 5975392f7a3SLiteSpeed Tech return -1; 5985392f7a3SLiteSpeed Tech 5995392f7a3SLiteSpeed Tech CHECK_SPACE(GQUIC_CID_LEN, p, pend); 6005392f7a3SLiteSpeed Tech memcpy(p, cid->idbuf, GQUIC_CID_LEN); 6015392f7a3SLiteSpeed Tech p += GQUIC_CID_LEN; 6025392f7a3SLiteSpeed Tech 6035392f7a3SLiteSpeed Tech sz = lsquic_gen_ver_tags(p, pend - p, version_bitmask); 6045392f7a3SLiteSpeed Tech if (sz < 0) 6055392f7a3SLiteSpeed Tech return -1; 6065392f7a3SLiteSpeed Tech 6075392f7a3SLiteSpeed Tech return p + sz - buf; 6085392f7a3SLiteSpeed Tech} 6095392f7a3SLiteSpeed Tech 6105392f7a3SLiteSpeed Tech 611c7d81ce1SDmitri Tikhonovunsigned 612c7d81ce1SDmitri Tikhonovlsquic_gquic_packno_bits2len (enum packno_bits bits) 613c7d81ce1SDmitri Tikhonov{ 614c7d81ce1SDmitri Tikhonov return gquic_packno_bits2len(bits); 615c7d81ce1SDmitri Tikhonov} 616c7d81ce1SDmitri Tikhonov 617c7d81ce1SDmitri Tikhonov 618c7d81ce1SDmitri Tikhonovenum packno_bits 619c7d81ce1SDmitri Tikhonovlsquic_gquic_calc_packno_bits (lsquic_packno_t packno, 620c7d81ce1SDmitri Tikhonov lsquic_packno_t least_unacked, uint64_t n_in_flight) 621c7d81ce1SDmitri Tikhonov{ 622c7d81ce1SDmitri Tikhonov uint64_t delta; 623c7d81ce1SDmitri Tikhonov unsigned bits; 624c7d81ce1SDmitri Tikhonov 625c7d81ce1SDmitri Tikhonov delta = packno - least_unacked; 626c7d81ce1SDmitri Tikhonov if (n_in_flight > delta) 627c7d81ce1SDmitri Tikhonov delta = n_in_flight; 628c7d81ce1SDmitri Tikhonov 629c7d81ce1SDmitri Tikhonov delta *= 4; 630c7d81ce1SDmitri Tikhonov bits = (delta > (1ULL << 8)) 631c7d81ce1SDmitri Tikhonov + (delta > (1ULL << 16)) 632c7d81ce1SDmitri Tikhonov + (delta > (1ULL << 32)); 633c7d81ce1SDmitri Tikhonov 634c7d81ce1SDmitri Tikhonov return bits; 635c7d81ce1SDmitri Tikhonov} 636de46bf2fSDmitri Tikhonov 637de46bf2fSDmitri Tikhonov 638de46bf2fSDmitri Tikhonov/* `dst' serves both as source and destination. `src' is the new frame */ 639de46bf2fSDmitri Tikhonovint 640de46bf2fSDmitri Tikhonovlsquic_merge_acks (struct ack_info *dst, const struct ack_info *src) 641de46bf2fSDmitri Tikhonov{ 642de46bf2fSDmitri Tikhonov const struct lsquic_packno_range *a, *a_end, *b, *b_end, **p; 643de46bf2fSDmitri Tikhonov struct lsquic_packno_range *out, *out_end; 644de46bf2fSDmitri Tikhonov unsigned i; 64549f1f4f6SDmitri Tikhonov int ok; 646de46bf2fSDmitri Tikhonov struct lsquic_packno_range out_ranges[256]; 647de46bf2fSDmitri Tikhonov 648de46bf2fSDmitri Tikhonov if (!(dst->n_ranges && src->n_ranges)) 649de46bf2fSDmitri Tikhonov return -1; 650de46bf2fSDmitri Tikhonov 651de46bf2fSDmitri Tikhonov a = dst->ranges; 652de46bf2fSDmitri Tikhonov a_end = a + dst->n_ranges; 653de46bf2fSDmitri Tikhonov b = src->ranges; 654de46bf2fSDmitri Tikhonov b_end = b + src->n_ranges; 655de46bf2fSDmitri Tikhonov out = out_ranges; 656de46bf2fSDmitri Tikhonov out_end = out + sizeof(out_ranges) / sizeof(out_ranges[0]); 657de46bf2fSDmitri Tikhonov 658de46bf2fSDmitri Tikhonov if (a->high >= b->high) 659de46bf2fSDmitri Tikhonov *out = *a; 660de46bf2fSDmitri Tikhonov else 661de46bf2fSDmitri Tikhonov *out = *b; 662de46bf2fSDmitri Tikhonov 663de46bf2fSDmitri Tikhonov while (1) 664de46bf2fSDmitri Tikhonov { 665de46bf2fSDmitri Tikhonov if (a < a_end && b < b_end) 666de46bf2fSDmitri Tikhonov { 667de46bf2fSDmitri Tikhonov if (a->high >= b->high) 668de46bf2fSDmitri Tikhonov p = &a; 669de46bf2fSDmitri Tikhonov else 670de46bf2fSDmitri Tikhonov p = &b; 671de46bf2fSDmitri Tikhonov } 672de46bf2fSDmitri Tikhonov else if (a < a_end) 673de46bf2fSDmitri Tikhonov p = &a; 674de46bf2fSDmitri Tikhonov else if (b < b_end) 675de46bf2fSDmitri Tikhonov p = &b; 676de46bf2fSDmitri Tikhonov else 677de46bf2fSDmitri Tikhonov { 678de46bf2fSDmitri Tikhonov ++out; 679de46bf2fSDmitri Tikhonov break; 680de46bf2fSDmitri Tikhonov } 681de46bf2fSDmitri Tikhonov 682de46bf2fSDmitri Tikhonov if ((*p)->high + 1 >= out->low) 683de46bf2fSDmitri Tikhonov out->low = (*p)->low; 684de46bf2fSDmitri Tikhonov else if (out + 1 < out_end) 685de46bf2fSDmitri Tikhonov *++out = **p; 686de46bf2fSDmitri Tikhonov else 687de46bf2fSDmitri Tikhonov return -1; 688de46bf2fSDmitri Tikhonov ++*p; 689de46bf2fSDmitri Tikhonov } 690de46bf2fSDmitri Tikhonov 691de46bf2fSDmitri Tikhonov if (src->flags & AI_ECN) 69249f1f4f6SDmitri Tikhonov { 69349f1f4f6SDmitri Tikhonov /* New ACK frame (src) should not contain ECN counts that are smaller 69449f1f4f6SDmitri Tikhonov * than previous ACK frame, otherwise we cannot merge. 69549f1f4f6SDmitri Tikhonov */ 69649f1f4f6SDmitri Tikhonov ok = 1; 697de46bf2fSDmitri Tikhonov for (i = 0; i < sizeof(src->ecn_counts) 698de46bf2fSDmitri Tikhonov / sizeof(src->ecn_counts[0]); ++i) 69949f1f4f6SDmitri Tikhonov ok &= dst->ecn_counts[i] <= src->ecn_counts[i]; 70049f1f4f6SDmitri Tikhonov if (ok) 70149f1f4f6SDmitri Tikhonov for (i = 0; i < sizeof(src->ecn_counts) 70249f1f4f6SDmitri Tikhonov / sizeof(src->ecn_counts[0]); ++i) 70349f1f4f6SDmitri Tikhonov dst->ecn_counts[i] = src->ecn_counts[i]; 70449f1f4f6SDmitri Tikhonov else 70549f1f4f6SDmitri Tikhonov return -1; 70649f1f4f6SDmitri Tikhonov } 707de46bf2fSDmitri Tikhonov dst->flags |= src->flags; 708de46bf2fSDmitri Tikhonov dst->lack_delta = src->lack_delta; 709de46bf2fSDmitri Tikhonov dst->n_ranges = out - out_ranges; 710de46bf2fSDmitri Tikhonov memcpy(dst->ranges, out_ranges, sizeof(out_ranges[0]) * dst->n_ranges); 711de46bf2fSDmitri Tikhonov 712de46bf2fSDmitri Tikhonov return 0; 713de46bf2fSDmitri Tikhonov} 714