1/* Copyright (c) 2017 - 2022 LiteSpeed Technologies Inc.  See LICENSE. */
2#include <string.h>
3
4#include "lsquic.h"
5#include "lsquic_int_types.h"
6#include "lsquic_version.h"
7
8#if _MSC_VER
9#include "vc_compat.h"
10#endif
11
12
13static const unsigned char version_tags[N_LSQVER][4] =
14{
15    [LSQVER_043] = { 'Q', '0', '4', '3', },
16    [LSQVER_046] = { 'Q', '0', '4', '6', },
17    [LSQVER_050] = { 'Q', '0', '5', '0', },
18    [LSQVER_ID27] = { 0xFF, 0, 0, 27, },
19    [LSQVER_ID29] = { 0xFF, 0, 0, 29, },
20    [LSQVER_I001] = {    0, 0, 0, 1, },
21    [LSQVER_VERNEG] = { 0xFA, 0xFA, 0xFA, 0xFA, },
22};
23
24
25uint32_t
26lsquic_ver2tag (unsigned version)
27{
28    lsquic_ver_tag_t tag;
29    if (version < N_LSQVER)
30    {
31        memcpy(&tag, version_tags[version], 4);
32        return tag;
33    }
34    else
35        return 0;
36}
37
38
39enum lsquic_version
40lsquic_tag2ver (uint32_t ver_tag)
41{
42    unsigned n;
43    for (n = 0; n < sizeof(version_tags) / sizeof(version_tags[0]); ++n)
44        if (0 == memcmp(version_tags[n], &ver_tag, sizeof(ver_tag)))
45            return n;
46    return -1;
47}
48
49
50const char *const lsquic_ver2str[N_LSQVER] = {
51    [LSQVER_043] = "Q043",
52    [LSQVER_046] = "Q046",
53    [LSQVER_050] = "Q050",
54    [LSQVER_ID27] = "FF00001B",
55    [LSQVER_ID29] = "FF00001D",
56    [LSQVER_I001] = "00000001",
57    [LSQVER_VERNEG] = "FAFAFAFA",
58};
59
60
61const char *const lsquic_ver2altstr[N_LSQVER] = {
62    [LSQVER_043] = NULL,
63    [LSQVER_046] = NULL,
64    [LSQVER_050] = NULL,
65    [LSQVER_ID27] = "h3-27",
66    [LSQVER_ID29] = "h3-29",
67    [LSQVER_I001] = "h3",
68    [LSQVER_VERNEG] = "VERNEG",
69};
70
71
72enum lsquic_version
73lsquic_str2ver (const char *str, size_t len)
74{
75    enum lsquic_version ver;
76    uint32_t tag;
77
78    if (len == sizeof(tag) && 'Q' == str[0])
79    {
80        memcpy(&tag, str, sizeof(tag));
81        return lsquic_tag2ver(tag);
82    }
83
84    for (ver = 0; ver < N_LSQVER; ++ver)
85    {
86        if (strlen(lsquic_ver2str[ver]) == len
87            && strncasecmp(lsquic_ver2str[ver], str, len) == 0)
88        {
89            return ver;
90        }
91        if (lsquic_ver2altstr[ver] && strlen(lsquic_ver2altstr[ver]) == len
92            && strncasecmp(lsquic_ver2altstr[ver], str, len) == 0)
93        {
94            return ver;
95        }
96    }
97    return -1;
98}
99
100
101int
102lsquic_gen_ver_tags (unsigned char *buf, size_t bufsz, unsigned version_bitmask)
103{
104    unsigned n;
105    lsquic_ver_tag_t tag;
106    unsigned char *p = buf;
107    unsigned char *const pend = p + bufsz;
108    for (n = 0; version_bitmask; ++n)
109    {
110        if (version_bitmask & (1 << n))
111        {
112            if (p + 4 > pend)
113                return -1;
114            version_bitmask &= ~(1 << n);
115            tag = lsquic_ver2tag(n);
116            if (0 == tag)
117                return -1;
118            memcpy(p, &tag, 4);
119            p += 4;
120        }
121    }
122    return p - buf;
123}
124