1a74702c6SGeorge Wang/* Copyright (c) 2017 - 2022 LiteSpeed Technologies Inc. See LICENSE. */ 250aadb33SDmitri Tikhonov#include <string.h> 350aadb33SDmitri Tikhonov 450aadb33SDmitri Tikhonov#include "lsquic.h" 550aadb33SDmitri Tikhonov#include "lsquic_int_types.h" 650aadb33SDmitri Tikhonov#include "lsquic_version.h" 750aadb33SDmitri Tikhonov 8fb3e20e0SDmitri Tikhonov#if _MSC_VER 9fb3e20e0SDmitri Tikhonov#include "vc_compat.h" 10fb3e20e0SDmitri Tikhonov#endif 11fb3e20e0SDmitri Tikhonov 1250aadb33SDmitri Tikhonov 1350aadb33SDmitri Tikhonovstatic const unsigned char version_tags[N_LSQVER][4] = 1450aadb33SDmitri Tikhonov{ 15c95974e9SDmitri Tikhonov [LSQVER_043] = { 'Q', '0', '4', '3', }, 16c7d81ce1SDmitri Tikhonov [LSQVER_046] = { 'Q', '0', '4', '6', }, 177a8b2eceSDmitri Tikhonov [LSQVER_050] = { 'Q', '0', '5', '0', }, 18bc520ef7SDmitri Tikhonov [LSQVER_ID27] = { 0xFF, 0, 0, 27, }, 194051ae3aSDmitri Tikhonov [LSQVER_ID29] = { 0xFF, 0, 0, 29, }, 2026e8f082SDmitri Tikhonov [LSQVER_I001] = { 0, 0, 0, 1, }, 215392f7a3SLiteSpeed Tech [LSQVER_VERNEG] = { 0xFA, 0xFA, 0xFA, 0xFA, }, 2250aadb33SDmitri Tikhonov}; 2350aadb33SDmitri Tikhonov 2450aadb33SDmitri Tikhonov 2550aadb33SDmitri Tikhonovuint32_t 2650aadb33SDmitri Tikhonovlsquic_ver2tag (unsigned version) 2750aadb33SDmitri Tikhonov{ 2850aadb33SDmitri Tikhonov lsquic_ver_tag_t tag; 2950aadb33SDmitri Tikhonov if (version < N_LSQVER) 3050aadb33SDmitri Tikhonov { 3150aadb33SDmitri Tikhonov memcpy(&tag, version_tags[version], 4); 3250aadb33SDmitri Tikhonov return tag; 3350aadb33SDmitri Tikhonov } 3450aadb33SDmitri Tikhonov else 3550aadb33SDmitri Tikhonov return 0; 3650aadb33SDmitri Tikhonov} 3750aadb33SDmitri Tikhonov 3850aadb33SDmitri Tikhonov 3950aadb33SDmitri Tikhonovenum lsquic_version 4050aadb33SDmitri Tikhonovlsquic_tag2ver (uint32_t ver_tag) 4150aadb33SDmitri Tikhonov{ 4250aadb33SDmitri Tikhonov unsigned n; 4350aadb33SDmitri Tikhonov for (n = 0; n < sizeof(version_tags) / sizeof(version_tags[0]); ++n) 4450aadb33SDmitri Tikhonov if (0 == memcmp(version_tags[n], &ver_tag, sizeof(ver_tag))) 4550aadb33SDmitri Tikhonov return n; 4650aadb33SDmitri Tikhonov return -1; 4750aadb33SDmitri Tikhonov} 4850aadb33SDmitri Tikhonov 4950aadb33SDmitri Tikhonov 505392f7a3SLiteSpeed Techconst char *const lsquic_ver2str[N_LSQVER] = { 515392f7a3SLiteSpeed Tech [LSQVER_043] = "Q043", 525392f7a3SLiteSpeed Tech [LSQVER_046] = "Q046", 537a8b2eceSDmitri Tikhonov [LSQVER_050] = "Q050", 54bc520ef7SDmitri Tikhonov [LSQVER_ID27] = "FF00001B", 554051ae3aSDmitri Tikhonov [LSQVER_ID29] = "FF00001D", 5626e8f082SDmitri Tikhonov [LSQVER_I001] = "00000001", 575392f7a3SLiteSpeed Tech [LSQVER_VERNEG] = "FAFAFAFA", 585392f7a3SLiteSpeed Tech}; 595392f7a3SLiteSpeed Tech 605392f7a3SLiteSpeed Tech 61082507cdSGeorge Wangconst char *const lsquic_ver2altstr[N_LSQVER] = { 62082507cdSGeorge Wang [LSQVER_043] = NULL, 63082507cdSGeorge Wang [LSQVER_046] = NULL, 64082507cdSGeorge Wang [LSQVER_050] = NULL, 65082507cdSGeorge Wang [LSQVER_ID27] = "h3-27", 66082507cdSGeorge Wang [LSQVER_ID29] = "h3-29", 67082507cdSGeorge Wang [LSQVER_I001] = "h3", 68082507cdSGeorge Wang [LSQVER_VERNEG] = "VERNEG", 69082507cdSGeorge Wang}; 70082507cdSGeorge Wang 71082507cdSGeorge Wang 7250aadb33SDmitri Tikhonovenum lsquic_version 7350aadb33SDmitri Tikhonovlsquic_str2ver (const char *str, size_t len) 7450aadb33SDmitri Tikhonov{ 755392f7a3SLiteSpeed Tech enum lsquic_version ver; 7650aadb33SDmitri Tikhonov uint32_t tag; 7750aadb33SDmitri Tikhonov 7850aadb33SDmitri Tikhonov if (len == sizeof(tag) && 'Q' == str[0]) 7950aadb33SDmitri Tikhonov { 8050aadb33SDmitri Tikhonov memcpy(&tag, str, sizeof(tag)); 8150aadb33SDmitri Tikhonov return lsquic_tag2ver(tag); 8250aadb33SDmitri Tikhonov } 8350aadb33SDmitri Tikhonov 845392f7a3SLiteSpeed Tech for (ver = 0; ver < N_LSQVER; ++ver) 85082507cdSGeorge Wang { 865392f7a3SLiteSpeed Tech if (strlen(lsquic_ver2str[ver]) == len 875392f7a3SLiteSpeed Tech && strncasecmp(lsquic_ver2str[ver], str, len) == 0) 885392f7a3SLiteSpeed Tech { 895392f7a3SLiteSpeed Tech return ver; 905392f7a3SLiteSpeed Tech } 91082507cdSGeorge Wang if (lsquic_ver2altstr[ver] && strlen(lsquic_ver2altstr[ver]) == len 92082507cdSGeorge Wang && strncasecmp(lsquic_ver2altstr[ver], str, len) == 0) 93082507cdSGeorge Wang { 94082507cdSGeorge Wang return ver; 95082507cdSGeorge Wang } 96082507cdSGeorge Wang } 975392f7a3SLiteSpeed Tech return -1; 985392f7a3SLiteSpeed Tech} 9950aadb33SDmitri Tikhonov 10050aadb33SDmitri Tikhonov 1015392f7a3SLiteSpeed Techint 1025392f7a3SLiteSpeed Techlsquic_gen_ver_tags (unsigned char *buf, size_t bufsz, unsigned version_bitmask) 1035392f7a3SLiteSpeed Tech{ 1045392f7a3SLiteSpeed Tech unsigned n; 1055392f7a3SLiteSpeed Tech lsquic_ver_tag_t tag; 1065392f7a3SLiteSpeed Tech unsigned char *p = buf; 1075392f7a3SLiteSpeed Tech unsigned char *const pend = p + bufsz; 1085392f7a3SLiteSpeed Tech for (n = 0; version_bitmask; ++n) 1095392f7a3SLiteSpeed Tech { 1105392f7a3SLiteSpeed Tech if (version_bitmask & (1 << n)) 1115392f7a3SLiteSpeed Tech { 1125392f7a3SLiteSpeed Tech if (p + 4 > pend) 1135392f7a3SLiteSpeed Tech return -1; 1145392f7a3SLiteSpeed Tech version_bitmask &= ~(1 << n); 1155392f7a3SLiteSpeed Tech tag = lsquic_ver2tag(n); 1165392f7a3SLiteSpeed Tech if (0 == tag) 1175392f7a3SLiteSpeed Tech return -1; 1185392f7a3SLiteSpeed Tech memcpy(p, &tag, 4); 1195392f7a3SLiteSpeed Tech p += 4; 1205392f7a3SLiteSpeed Tech } 1215392f7a3SLiteSpeed Tech } 1225392f7a3SLiteSpeed Tech return p - buf; 1235392f7a3SLiteSpeed Tech} 124