1a74702c6SGeorge Wang/* Copyright (c) 2017 - 2022 LiteSpeed Technologies Inc. See LICENSE. */ 25392f7a3SLiteSpeed Tech/* 35392f7a3SLiteSpeed Tech * lsquic_varint.c -- routines dealing with IETF QUIC varint. 45392f7a3SLiteSpeed Tech */ 55392f7a3SLiteSpeed Tech 65392f7a3SLiteSpeed Tech#include <assert.h> 75392f7a3SLiteSpeed Tech#include <stdint.h> 85392f7a3SLiteSpeed Tech#include <string.h> 95392f7a3SLiteSpeed Tech 105392f7a3SLiteSpeed Tech#include "lsquic_byteswap.h" 115392f7a3SLiteSpeed Tech#include "lsquic_varint.h" 125392f7a3SLiteSpeed Tech 135392f7a3SLiteSpeed Tech/* Returns number of bytes read from p (1, 2, 4, or 8), or a negative 145392f7a3SLiteSpeed Tech * value on error. 155392f7a3SLiteSpeed Tech */ 165392f7a3SLiteSpeed Techint 175392f7a3SLiteSpeed Techlsquic_varint_read (const unsigned char *p, const unsigned char *end, 185392f7a3SLiteSpeed Tech uint64_t *valp) 195392f7a3SLiteSpeed Tech{ 205392f7a3SLiteSpeed Tech uint64_t val; 215392f7a3SLiteSpeed Tech 225392f7a3SLiteSpeed Tech if (p >= end) 235392f7a3SLiteSpeed Tech return -1; 245392f7a3SLiteSpeed Tech 255392f7a3SLiteSpeed Tech switch (*p >> 6) 265392f7a3SLiteSpeed Tech { 275392f7a3SLiteSpeed Tech case 0: 285392f7a3SLiteSpeed Tech *valp = *p; 295392f7a3SLiteSpeed Tech return 1; 305392f7a3SLiteSpeed Tech case 1: 315392f7a3SLiteSpeed Tech if (p + 1 >= end) 325392f7a3SLiteSpeed Tech return -1; 335392f7a3SLiteSpeed Tech *valp = (p[0] & VINT_MASK) << 8 345392f7a3SLiteSpeed Tech | p[1] 355392f7a3SLiteSpeed Tech ; 365392f7a3SLiteSpeed Tech return 2; 375392f7a3SLiteSpeed Tech case 2: 385392f7a3SLiteSpeed Tech if (p + 3 >= end) 395392f7a3SLiteSpeed Tech return -1; 405392f7a3SLiteSpeed Tech *valp = (p[0] & VINT_MASK) << 24 415392f7a3SLiteSpeed Tech | p[1] << 16 425392f7a3SLiteSpeed Tech | p[2] << 8 435392f7a3SLiteSpeed Tech | p[3] << 0 445392f7a3SLiteSpeed Tech ; 455392f7a3SLiteSpeed Tech return 4; 465392f7a3SLiteSpeed Tech default: 475392f7a3SLiteSpeed Tech if (p + 7 >= end) 485392f7a3SLiteSpeed Tech return -1; 495392f7a3SLiteSpeed Tech memcpy(&val, p, 8); 505392f7a3SLiteSpeed Tech#if __BYTE_ORDER == __LITTLE_ENDIAN 515392f7a3SLiteSpeed Tech val = bswap_64(val); 525392f7a3SLiteSpeed Tech#endif 535392f7a3SLiteSpeed Tech val &= (1ULL << 62) - 1; 545392f7a3SLiteSpeed Tech *valp = val; 555392f7a3SLiteSpeed Tech return 8; 565392f7a3SLiteSpeed Tech } 575392f7a3SLiteSpeed Tech} 585392f7a3SLiteSpeed Tech 595392f7a3SLiteSpeed Tech 605392f7a3SLiteSpeed Techint 615392f7a3SLiteSpeed Techlsquic_varint_read_nb (const unsigned char **pp, const unsigned char *end, 625392f7a3SLiteSpeed Tech struct varint_read_state *state) 635392f7a3SLiteSpeed Tech{ 645392f7a3SLiteSpeed Tech const unsigned char *p = *pp; 655392f7a3SLiteSpeed Tech 665392f7a3SLiteSpeed Tech if (p >= end) 675392f7a3SLiteSpeed Tech return -1; 685392f7a3SLiteSpeed Tech 695392f7a3SLiteSpeed Tech switch (state->pos ? state->pos : *p >> 6) 705392f7a3SLiteSpeed Tech { 715392f7a3SLiteSpeed Tech case 0: 725392f7a3SLiteSpeed Tech state->val = *p++; 735392f7a3SLiteSpeed Tech *pp = p; 745392f7a3SLiteSpeed Tech return 0; 755392f7a3SLiteSpeed Tech case 1: 765392f7a3SLiteSpeed Tech state->val = (*p++ & VINT_MASK) << 8; 77747be414SDmitri Tikhonov if (p >= end) { state->pos = 1000; break; } 78747be414SDmitri Tikhonov /* fall through */ 79747be414SDmitri Tikhonov case 1000: 805392f7a3SLiteSpeed Tech state->val |= *p++; 815392f7a3SLiteSpeed Tech *pp = p; 825392f7a3SLiteSpeed Tech return 0; 835392f7a3SLiteSpeed Tech case 2: 845392f7a3SLiteSpeed Tech if (p + 3 < end) 855392f7a3SLiteSpeed Tech { 865392f7a3SLiteSpeed Tech state->val = (p[0] & VINT_MASK) << 24 875392f7a3SLiteSpeed Tech | p[1] << 16 885392f7a3SLiteSpeed Tech | p[2] << 8 895392f7a3SLiteSpeed Tech | p[3] << 0 905392f7a3SLiteSpeed Tech ; 915392f7a3SLiteSpeed Tech *pp += 4; 925392f7a3SLiteSpeed Tech return 0; 935392f7a3SLiteSpeed Tech } 945392f7a3SLiteSpeed Tech state->val = (*p++ & VINT_MASK) << 24; 95747be414SDmitri Tikhonov if (p >= end) { state->pos = 1001; break; } 96747be414SDmitri Tikhonov /* fall through */ 97747be414SDmitri Tikhonov case 1001: 985392f7a3SLiteSpeed Tech state->val |= *p++ << 16; 99747be414SDmitri Tikhonov if (p >= end) { state->pos = 1002; break; } 100747be414SDmitri Tikhonov /* fall through */ 101747be414SDmitri Tikhonov case 1002: 1025392f7a3SLiteSpeed Tech state->val |= *p++ << 8; 103747be414SDmitri Tikhonov if (p >= end) { state->pos = 1003; break; } 104747be414SDmitri Tikhonov /* fall through */ 105747be414SDmitri Tikhonov case 1003: 1065392f7a3SLiteSpeed Tech state->val |= *p++; 1075392f7a3SLiteSpeed Tech *pp = p; 1085392f7a3SLiteSpeed Tech return 0; 1095392f7a3SLiteSpeed Tech case 3: 1105392f7a3SLiteSpeed Tech if (p + 7 < end) 1115392f7a3SLiteSpeed Tech { 1125392f7a3SLiteSpeed Tech memcpy(&state->val, p, 8); 1135392f7a3SLiteSpeed Tech#if __BYTE_ORDER == __LITTLE_ENDIAN 1145392f7a3SLiteSpeed Tech state->val = bswap_64(state->val); 1155392f7a3SLiteSpeed Tech#endif 1165392f7a3SLiteSpeed Tech state->val &= (1ULL << 62) - 1; 1175392f7a3SLiteSpeed Tech *pp += 8; 1185392f7a3SLiteSpeed Tech return 0; 1195392f7a3SLiteSpeed Tech } 1205392f7a3SLiteSpeed Tech state->val = (uint64_t) (*p++ & VINT_MASK) << 56; 121747be414SDmitri Tikhonov if (p >= end) { state->pos = 1004; break; } 122747be414SDmitri Tikhonov /* fall through */ 123747be414SDmitri Tikhonov case 1004: 1245392f7a3SLiteSpeed Tech state->val |= (uint64_t) *p++ << 48; 125747be414SDmitri Tikhonov if (p >= end) { state->pos = 1005; break; } 126747be414SDmitri Tikhonov /* fall through */ 127747be414SDmitri Tikhonov case 1005: 1285392f7a3SLiteSpeed Tech state->val |= (uint64_t) *p++ << 40; 129747be414SDmitri Tikhonov if (p >= end) { state->pos = 1006; break; } 130747be414SDmitri Tikhonov /* fall through */ 131747be414SDmitri Tikhonov case 1006: 1325392f7a3SLiteSpeed Tech state->val |= (uint64_t) *p++ << 32; 133747be414SDmitri Tikhonov if (p >= end) { state->pos = 1007; break; } 134747be414SDmitri Tikhonov /* fall through */ 135747be414SDmitri Tikhonov case 1007: 1365392f7a3SLiteSpeed Tech state->val |= (uint64_t) *p++ << 24; 137747be414SDmitri Tikhonov if (p >= end) { state->pos = 1008; break; } 138747be414SDmitri Tikhonov /* fall through */ 139747be414SDmitri Tikhonov case 1008: 1405392f7a3SLiteSpeed Tech state->val |= (uint64_t) *p++ << 16; 141747be414SDmitri Tikhonov if (p >= end) { state->pos = 1009; break; } 142747be414SDmitri Tikhonov /* fall through */ 143747be414SDmitri Tikhonov case 1009: 1445392f7a3SLiteSpeed Tech state->val |= (uint64_t) *p++ << 8; 145747be414SDmitri Tikhonov if (p >= end) { state->pos = 1010; break; } 146747be414SDmitri Tikhonov /* fall through */ 147747be414SDmitri Tikhonov case 1010: 1485392f7a3SLiteSpeed Tech state->val |= *p++; 1495392f7a3SLiteSpeed Tech *pp = p; 1505392f7a3SLiteSpeed Tech return 0; 1515392f7a3SLiteSpeed Tech default: 1525392f7a3SLiteSpeed Tech assert(0); 1535392f7a3SLiteSpeed Tech } 1545392f7a3SLiteSpeed Tech 1555392f7a3SLiteSpeed Tech *pp = p; 1565392f7a3SLiteSpeed Tech return -1; 1575392f7a3SLiteSpeed Tech} 1585392f7a3SLiteSpeed Tech 1595392f7a3SLiteSpeed Tech 1605392f7a3SLiteSpeed Techint 1615392f7a3SLiteSpeed Techlsquic_varint_read_two (const unsigned char **begin, const unsigned char *end, 1625392f7a3SLiteSpeed Tech struct varint_read2_state *state) 1635392f7a3SLiteSpeed Tech{ 1645392f7a3SLiteSpeed Tech const unsigned char *p = *begin; 1655392f7a3SLiteSpeed Tech int s; 1665392f7a3SLiteSpeed Tech 1675392f7a3SLiteSpeed Tech while (p < end) 1685392f7a3SLiteSpeed Tech { 1695392f7a3SLiteSpeed Tech switch (state->vr2s_state) 1705392f7a3SLiteSpeed Tech { 1715392f7a3SLiteSpeed Tech case VR2S_READ_ONE_BEGIN: 1725392f7a3SLiteSpeed Tech state->vr2s_varint_state.pos = 0; 1735392f7a3SLiteSpeed Tech state->vr2s_state = VR2S_READ_ONE_CONTINUE; 1745392f7a3SLiteSpeed Tech goto cont; 1755392f7a3SLiteSpeed Tech case VR2S_READ_TWO_BEGIN: 1765392f7a3SLiteSpeed Tech state->vr2s_varint_state.pos = 0; 1775392f7a3SLiteSpeed Tech state->vr2s_state = VR2S_READ_TWO_CONTINUE; 1785392f7a3SLiteSpeed Tech goto cont; 1795392f7a3SLiteSpeed Tech cont: case VR2S_READ_ONE_CONTINUE: 1805392f7a3SLiteSpeed Tech case VR2S_READ_TWO_CONTINUE: 1815392f7a3SLiteSpeed Tech s = lsquic_varint_read_nb(&p, end, &state->vr2s_varint_state); 1825392f7a3SLiteSpeed Tech if (s == 0) 1835392f7a3SLiteSpeed Tech { 1845392f7a3SLiteSpeed Tech if (state->vr2s_state == VR2S_READ_TWO_CONTINUE) 1855392f7a3SLiteSpeed Tech goto done; 1865392f7a3SLiteSpeed Tech state->vr2s_one = state->vr2s_varint_state.val; 1875392f7a3SLiteSpeed Tech state->vr2s_state = VR2S_READ_TWO_BEGIN; 1885392f7a3SLiteSpeed Tech break; 1895392f7a3SLiteSpeed Tech } 1905392f7a3SLiteSpeed Tech else 1915392f7a3SLiteSpeed Tech goto more; 1925392f7a3SLiteSpeed Tech } 1935392f7a3SLiteSpeed Tech } 1945392f7a3SLiteSpeed Tech 1955392f7a3SLiteSpeed Tech more: 1965392f7a3SLiteSpeed Tech *begin = p; 1975392f7a3SLiteSpeed Tech return -1; 1985392f7a3SLiteSpeed Tech 1995392f7a3SLiteSpeed Tech done: 2005392f7a3SLiteSpeed Tech *begin = p; 2015392f7a3SLiteSpeed Tech return 0; 2025392f7a3SLiteSpeed Tech} 203