1 /*
2 * ngtcp2
3 *
4 * Copyright (c) 2017 ngtcp2 contributors
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining
7 * a copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sublicense, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be
15 * included in all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
21 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 */
25 #include "ngtcp2_conv.h"
26
27 #include <string.h>
28 #include <assert.h>
29
30 #include "ngtcp2_str.h"
31 #include "ngtcp2_pkt.h"
32
ngtcp2_get_uint64(const uint8_t * p)33 uint64_t ngtcp2_get_uint64(const uint8_t *p) {
34 uint64_t n;
35 memcpy(&n, p, 8);
36 return ngtcp2_ntohl64(n);
37 }
38
ngtcp2_get_uint48(const uint8_t * p)39 uint64_t ngtcp2_get_uint48(const uint8_t *p) {
40 uint64_t n = 0;
41 memcpy(((uint8_t *)&n) + 2, p, 6);
42 return ngtcp2_ntohl64(n);
43 }
44
ngtcp2_get_uint32(const uint8_t * p)45 uint32_t ngtcp2_get_uint32(const uint8_t *p) {
46 uint32_t n;
47 memcpy(&n, p, 4);
48 return ngtcp2_ntohl(n);
49 }
50
ngtcp2_get_uint24(const uint8_t * p)51 uint32_t ngtcp2_get_uint24(const uint8_t *p) {
52 uint32_t n = 0;
53 memcpy(((uint8_t *)&n) + 1, p, 3);
54 return ngtcp2_ntohl(n);
55 }
56
ngtcp2_get_uint16(const uint8_t * p)57 uint16_t ngtcp2_get_uint16(const uint8_t *p) {
58 uint16_t n;
59 memcpy(&n, p, 2);
60 return ngtcp2_ntohs(n);
61 }
62
ngtcp2_get_varint(size_t * plen,const uint8_t * p)63 uint64_t ngtcp2_get_varint(size_t *plen, const uint8_t *p) {
64 union {
65 char b[8];
66 uint16_t n16;
67 uint32_t n32;
68 uint64_t n64;
69 } n;
70
71 *plen = (size_t)(1u << (*p >> 6));
72
73 switch (*plen) {
74 case 1:
75 return *p;
76 case 2:
77 memcpy(&n, p, 2);
78 n.b[0] &= 0x3f;
79 return ngtcp2_ntohs(n.n16);
80 case 4:
81 memcpy(&n, p, 4);
82 n.b[0] &= 0x3f;
83 return ngtcp2_ntohl(n.n32);
84 case 8:
85 memcpy(&n, p, 8);
86 n.b[0] &= 0x3f;
87 return ngtcp2_ntohl64(n.n64);
88 default:
89 assert(0);
90 }
91
92 return 0;
93 }
94
ngtcp2_get_pkt_num(const uint8_t * p,size_t pkt_numlen)95 int64_t ngtcp2_get_pkt_num(const uint8_t *p, size_t pkt_numlen) {
96 switch (pkt_numlen) {
97 case 1:
98 return *p;
99 case 2:
100 return (int64_t)ngtcp2_get_uint16(p);
101 case 3:
102 return (int64_t)ngtcp2_get_uint24(p);
103 case 4:
104 return (int64_t)ngtcp2_get_uint32(p);
105 default:
106 assert(0);
107 abort();
108 }
109 }
110
ngtcp2_put_uint64be(uint8_t * p,uint64_t n)111 uint8_t *ngtcp2_put_uint64be(uint8_t *p, uint64_t n) {
112 n = ngtcp2_htonl64(n);
113 return ngtcp2_cpymem(p, (const uint8_t *)&n, sizeof(n));
114 }
115
ngtcp2_put_uint48be(uint8_t * p,uint64_t n)116 uint8_t *ngtcp2_put_uint48be(uint8_t *p, uint64_t n) {
117 n = ngtcp2_htonl64(n);
118 return ngtcp2_cpymem(p, ((const uint8_t *)&n) + 2, 6);
119 }
120
ngtcp2_put_uint32be(uint8_t * p,uint32_t n)121 uint8_t *ngtcp2_put_uint32be(uint8_t *p, uint32_t n) {
122 n = ngtcp2_htonl(n);
123 return ngtcp2_cpymem(p, (const uint8_t *)&n, sizeof(n));
124 }
125
ngtcp2_put_uint24be(uint8_t * p,uint32_t n)126 uint8_t *ngtcp2_put_uint24be(uint8_t *p, uint32_t n) {
127 n = ngtcp2_htonl(n);
128 return ngtcp2_cpymem(p, ((const uint8_t *)&n) + 1, 3);
129 }
130
ngtcp2_put_uint16be(uint8_t * p,uint16_t n)131 uint8_t *ngtcp2_put_uint16be(uint8_t *p, uint16_t n) {
132 n = ngtcp2_htons(n);
133 return ngtcp2_cpymem(p, (const uint8_t *)&n, sizeof(n));
134 }
135
ngtcp2_put_varint(uint8_t * p,uint64_t n)136 uint8_t *ngtcp2_put_varint(uint8_t *p, uint64_t n) {
137 uint8_t *rv;
138 if (n < 64) {
139 *p++ = (uint8_t)n;
140 return p;
141 }
142 if (n < 16384) {
143 rv = ngtcp2_put_uint16be(p, (uint16_t)n);
144 *p |= 0x40;
145 return rv;
146 }
147 if (n < 1073741824) {
148 rv = ngtcp2_put_uint32be(p, (uint32_t)n);
149 *p |= 0x80;
150 return rv;
151 }
152 assert(n < 4611686018427387904ULL);
153 rv = ngtcp2_put_uint64be(p, n);
154 *p |= 0xc0;
155 return rv;
156 }
157
ngtcp2_put_varint14(uint8_t * p,uint16_t n)158 uint8_t *ngtcp2_put_varint14(uint8_t *p, uint16_t n) {
159 uint8_t *rv;
160
161 assert(n < 16384);
162
163 rv = ngtcp2_put_uint16be(p, n);
164 *p |= 0x40;
165
166 return rv;
167 }
168
ngtcp2_put_pkt_num(uint8_t * p,int64_t pkt_num,size_t len)169 uint8_t *ngtcp2_put_pkt_num(uint8_t *p, int64_t pkt_num, size_t len) {
170 switch (len) {
171 case 1:
172 *p++ = (uint8_t)pkt_num;
173 return p;
174 case 2:
175 ngtcp2_put_uint16be(p, (uint16_t)pkt_num);
176 return p + 2;
177 case 3:
178 ngtcp2_put_uint24be(p, (uint32_t)pkt_num);
179 return p + 3;
180 case 4:
181 ngtcp2_put_uint32be(p, (uint32_t)pkt_num);
182 return p + 4;
183 default:
184 assert(0);
185 abort();
186 }
187 }
188
ngtcp2_get_varint_len(const uint8_t * p)189 size_t ngtcp2_get_varint_len(const uint8_t *p) {
190 return (size_t)(1u << (*p >> 6));
191 }
192
ngtcp2_put_varint_len(uint64_t n)193 size_t ngtcp2_put_varint_len(uint64_t n) {
194 if (n < 64) {
195 return 1;
196 }
197 if (n < 16384) {
198 return 2;
199 }
200 if (n < 1073741824) {
201 return 4;
202 }
203 assert(n < 4611686018427387904ULL);
204 return 8;
205 }
206
ngtcp2_nth_server_bidi_id(uint64_t n)207 int64_t ngtcp2_nth_server_bidi_id(uint64_t n) {
208 if (n == 0) {
209 return 0;
210 }
211
212 if ((NGTCP2_MAX_VARINT >> 2) < n - 1) {
213 return NGTCP2_MAX_SERVER_STREAM_ID_BIDI;
214 }
215
216 return (int64_t)(((n - 1) << 2) | 0x01);
217 }
218
ngtcp2_nth_client_bidi_id(uint64_t n)219 int64_t ngtcp2_nth_client_bidi_id(uint64_t n) {
220 if (n == 0) {
221 return 0;
222 }
223
224 if ((NGTCP2_MAX_VARINT >> 2) < n - 1) {
225 return NGTCP2_MAX_CLIENT_STREAM_ID_BIDI;
226 }
227
228 return (int64_t)((n - 1) << 2);
229 }
230
ngtcp2_nth_server_uni_id(uint64_t n)231 int64_t ngtcp2_nth_server_uni_id(uint64_t n) {
232 if (n == 0) {
233 return 0;
234 }
235
236 if ((NGTCP2_MAX_VARINT >> 2) < n - 1) {
237 return NGTCP2_MAX_SERVER_STREAM_ID_UNI;
238 }
239
240 return (int64_t)(((n - 1) << 2) | 0x03);
241 }
242
ngtcp2_nth_client_uni_id(uint64_t n)243 int64_t ngtcp2_nth_client_uni_id(uint64_t n) {
244 if (n == 0) {
245 return 0;
246 }
247
248 if ((NGTCP2_MAX_VARINT >> 2) < n - 1) {
249 return NGTCP2_MAX_CLIENT_STREAM_ID_UNI;
250 }
251
252 return (int64_t)(((n - 1) << 2) | 0x02);
253 }
254
ngtcp2_ord_stream_id(int64_t stream_id)255 uint64_t ngtcp2_ord_stream_id(int64_t stream_id) {
256 return (uint64_t)(stream_id >> 2) + 1;
257 }
258