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 #include "ngtcp2_net.h"
33
ngtcp2_get_uint64(const uint8_t * p)34 uint64_t ngtcp2_get_uint64(const uint8_t *p) {
35 uint64_t n;
36 memcpy(&n, p, 8);
37 return ngtcp2_ntohl64(n);
38 }
39
ngtcp2_get_uint48(const uint8_t * p)40 uint64_t ngtcp2_get_uint48(const uint8_t *p) {
41 uint64_t n = 0;
42 memcpy(((uint8_t *)&n) + 2, p, 6);
43 return ngtcp2_ntohl64(n);
44 }
45
ngtcp2_get_uint32(const uint8_t * p)46 uint32_t ngtcp2_get_uint32(const uint8_t *p) {
47 uint32_t n;
48 memcpy(&n, p, 4);
49 return ngtcp2_ntohl(n);
50 }
51
ngtcp2_get_uint24(const uint8_t * p)52 uint32_t ngtcp2_get_uint24(const uint8_t *p) {
53 uint32_t n = 0;
54 memcpy(((uint8_t *)&n) + 1, p, 3);
55 return ngtcp2_ntohl(n);
56 }
57
ngtcp2_get_uint16(const uint8_t * p)58 uint16_t ngtcp2_get_uint16(const uint8_t *p) {
59 uint16_t n;
60 memcpy(&n, p, 2);
61 return ngtcp2_ntohs(n);
62 }
63
ngtcp2_get_varint(size_t * plen,const uint8_t * p)64 uint64_t ngtcp2_get_varint(size_t *plen, const uint8_t *p) {
65 union {
66 char b[8];
67 uint16_t n16;
68 uint32_t n32;
69 uint64_t n64;
70 } n;
71
72 *plen = (size_t)(1u << (*p >> 6));
73
74 switch (*plen) {
75 case 1:
76 return *p;
77 case 2:
78 memcpy(&n, p, 2);
79 n.b[0] &= 0x3f;
80 return ngtcp2_ntohs(n.n16);
81 case 4:
82 memcpy(&n, p, 4);
83 n.b[0] &= 0x3f;
84 return ngtcp2_ntohl(n.n32);
85 case 8:
86 memcpy(&n, p, 8);
87 n.b[0] &= 0x3f;
88 return ngtcp2_ntohl64(n.n64);
89 default:
90 assert(0);
91 }
92
93 return 0;
94 }
95
ngtcp2_get_pkt_num(const uint8_t * p,size_t pkt_numlen)96 int64_t ngtcp2_get_pkt_num(const uint8_t *p, size_t pkt_numlen) {
97 switch (pkt_numlen) {
98 case 1:
99 return *p;
100 case 2:
101 return (int64_t)ngtcp2_get_uint16(p);
102 case 3:
103 return (int64_t)ngtcp2_get_uint24(p);
104 case 4:
105 return (int64_t)ngtcp2_get_uint32(p);
106 default:
107 assert(0);
108 abort();
109 }
110 }
111
ngtcp2_put_uint64be(uint8_t * p,uint64_t n)112 uint8_t *ngtcp2_put_uint64be(uint8_t *p, uint64_t n) {
113 n = ngtcp2_htonl64(n);
114 return ngtcp2_cpymem(p, (const uint8_t *)&n, sizeof(n));
115 }
116
ngtcp2_put_uint48be(uint8_t * p,uint64_t n)117 uint8_t *ngtcp2_put_uint48be(uint8_t *p, uint64_t n) {
118 n = ngtcp2_htonl64(n);
119 return ngtcp2_cpymem(p, ((const uint8_t *)&n) + 2, 6);
120 }
121
ngtcp2_put_uint32be(uint8_t * p,uint32_t n)122 uint8_t *ngtcp2_put_uint32be(uint8_t *p, uint32_t n) {
123 n = ngtcp2_htonl(n);
124 return ngtcp2_cpymem(p, (const uint8_t *)&n, sizeof(n));
125 }
126
ngtcp2_put_uint24be(uint8_t * p,uint32_t n)127 uint8_t *ngtcp2_put_uint24be(uint8_t *p, uint32_t n) {
128 n = ngtcp2_htonl(n);
129 return ngtcp2_cpymem(p, ((const uint8_t *)&n) + 1, 3);
130 }
131
ngtcp2_put_uint16be(uint8_t * p,uint16_t n)132 uint8_t *ngtcp2_put_uint16be(uint8_t *p, uint16_t n) {
133 n = ngtcp2_htons(n);
134 return ngtcp2_cpymem(p, (const uint8_t *)&n, sizeof(n));
135 }
136
ngtcp2_put_varint(uint8_t * p,uint64_t n)137 uint8_t *ngtcp2_put_varint(uint8_t *p, uint64_t n) {
138 uint8_t *rv;
139 if (n < 64) {
140 *p++ = (uint8_t)n;
141 return p;
142 }
143 if (n < 16384) {
144 rv = ngtcp2_put_uint16be(p, (uint16_t)n);
145 *p |= 0x40;
146 return rv;
147 }
148 if (n < 1073741824) {
149 rv = ngtcp2_put_uint32be(p, (uint32_t)n);
150 *p |= 0x80;
151 return rv;
152 }
153 assert(n < 4611686018427387904ULL);
154 rv = ngtcp2_put_uint64be(p, n);
155 *p |= 0xc0;
156 return rv;
157 }
158
ngtcp2_put_varint30(uint8_t * p,uint32_t n)159 uint8_t *ngtcp2_put_varint30(uint8_t *p, uint32_t n) {
160 uint8_t *rv;
161
162 assert(n < 1073741824);
163
164 rv = ngtcp2_put_uint32be(p, n);
165 *p |= 0x80;
166
167 return rv;
168 }
169
ngtcp2_put_pkt_num(uint8_t * p,int64_t pkt_num,size_t len)170 uint8_t *ngtcp2_put_pkt_num(uint8_t *p, int64_t pkt_num, size_t len) {
171 switch (len) {
172 case 1:
173 *p++ = (uint8_t)pkt_num;
174 return p;
175 case 2:
176 ngtcp2_put_uint16be(p, (uint16_t)pkt_num);
177 return p + 2;
178 case 3:
179 ngtcp2_put_uint24be(p, (uint32_t)pkt_num);
180 return p + 3;
181 case 4:
182 ngtcp2_put_uint32be(p, (uint32_t)pkt_num);
183 return p + 4;
184 default:
185 assert(0);
186 abort();
187 }
188 }
189
ngtcp2_get_varint_len(const uint8_t * p)190 size_t ngtcp2_get_varint_len(const uint8_t *p) {
191 return (size_t)(1u << (*p >> 6));
192 }
193
ngtcp2_put_varint_len(uint64_t n)194 size_t ngtcp2_put_varint_len(uint64_t n) {
195 if (n < 64) {
196 return 1;
197 }
198 if (n < 16384) {
199 return 2;
200 }
201 if (n < 1073741824) {
202 return 4;
203 }
204 assert(n < 4611686018427387904ULL);
205 return 8;
206 }
207
ngtcp2_nth_server_bidi_id(uint64_t n)208 int64_t ngtcp2_nth_server_bidi_id(uint64_t n) {
209 if (n == 0) {
210 return 0;
211 }
212
213 if ((NGTCP2_MAX_VARINT >> 2) < n - 1) {
214 return NGTCP2_MAX_SERVER_STREAM_ID_BIDI;
215 }
216
217 return (int64_t)(((n - 1) << 2) | 0x01);
218 }
219
ngtcp2_nth_client_bidi_id(uint64_t n)220 int64_t ngtcp2_nth_client_bidi_id(uint64_t n) {
221 if (n == 0) {
222 return 0;
223 }
224
225 if ((NGTCP2_MAX_VARINT >> 2) < n - 1) {
226 return NGTCP2_MAX_CLIENT_STREAM_ID_BIDI;
227 }
228
229 return (int64_t)((n - 1) << 2);
230 }
231
ngtcp2_nth_server_uni_id(uint64_t n)232 int64_t ngtcp2_nth_server_uni_id(uint64_t n) {
233 if (n == 0) {
234 return 0;
235 }
236
237 if ((NGTCP2_MAX_VARINT >> 2) < n - 1) {
238 return NGTCP2_MAX_SERVER_STREAM_ID_UNI;
239 }
240
241 return (int64_t)(((n - 1) << 2) | 0x03);
242 }
243
ngtcp2_nth_client_uni_id(uint64_t n)244 int64_t ngtcp2_nth_client_uni_id(uint64_t n) {
245 if (n == 0) {
246 return 0;
247 }
248
249 if ((NGTCP2_MAX_VARINT >> 2) < n - 1) {
250 return NGTCP2_MAX_CLIENT_STREAM_ID_UNI;
251 }
252
253 return (int64_t)(((n - 1) << 2) | 0x02);
254 }
255
ngtcp2_ord_stream_id(int64_t stream_id)256 uint64_t ngtcp2_ord_stream_id(int64_t stream_id) {
257 return (uint64_t)(stream_id >> 2) + 1;
258 }
259