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