lsquic_version.c revision fb3e20e0
1/* Copyright (c) 2017 - 2020 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#if LSQUIC_USE_Q098
19    [LSQVER_098] = { 'Q', '0', '9', '8', },
20#endif
21    [LSQVER_ID27] = { 0xFF, 0, 0, 27, },
22    [LSQVER_ID28] = { 0xFF, 0, 0, 28, },
23    [LSQVER_VERNEG] = { 0xFA, 0xFA, 0xFA, 0xFA, },
24};
25
26
27uint32_t
28lsquic_ver2tag (unsigned version)
29{
30    lsquic_ver_tag_t tag;
31    if (version < N_LSQVER)
32    {
33        memcpy(&tag, version_tags[version], 4);
34        return tag;
35    }
36    else
37        return 0;
38}
39
40
41enum lsquic_version
42lsquic_tag2ver (uint32_t ver_tag)
43{
44    unsigned n;
45    for (n = 0; n < sizeof(version_tags) / sizeof(version_tags[0]); ++n)
46        if (0 == memcmp(version_tags[n], &ver_tag, sizeof(ver_tag)))
47            return n;
48    return -1;
49}
50
51
52const char *const lsquic_ver2str[N_LSQVER] = {
53    [LSQVER_043] = "Q043",
54    [LSQVER_046] = "Q046",
55    [LSQVER_050] = "Q050",
56#if LSQUIC_USE_Q098
57    [LSQVER_098] = "Q098",
58#endif
59    [LSQVER_ID27] = "FF00001B",
60    [LSQVER_ID28] = "FF00001C",
61    [LSQVER_VERNEG] = "FAFAFAFA",
62};
63
64
65enum lsquic_version
66lsquic_str2ver (const char *str, size_t len)
67{
68    enum lsquic_version ver;
69    uint32_t tag;
70
71    if (len == sizeof(tag) && 'Q' == str[0])
72    {
73        memcpy(&tag, str, sizeof(tag));
74        return lsquic_tag2ver(tag);
75    }
76
77    for (ver = 0; ver < N_LSQVER; ++ver)
78        if (strlen(lsquic_ver2str[ver]) == len
79            && strncasecmp(lsquic_ver2str[ver], str, len) == 0)
80        {
81            return ver;
82        }
83
84    return -1;
85}
86
87
88int
89lsquic_gen_ver_tags (unsigned char *buf, size_t bufsz, unsigned version_bitmask)
90{
91    unsigned n;
92    lsquic_ver_tag_t tag;
93    unsigned char *p = buf;
94    unsigned char *const pend = p + bufsz;
95    for (n = 0; version_bitmask; ++n)
96    {
97        if (version_bitmask & (1 << n))
98        {
99            if (p + 4 > pend)
100                return -1;
101            version_bitmask &= ~(1 << n);
102            tag = lsquic_ver2tag(n);
103            if (0 == tag)
104                return -1;
105            memcpy(p, &tag, 4);
106            p += 4;
107        }
108    }
109    return p - buf;
110}
111