1 /*
2  * nghttp3
3  *
4  * Copyright (c) 2019 nghttp3 contributors
5  * Copyright (c) 2017 ngtcp2 contributors
6  *
7  * Permission is hereby granted, free of charge, to any person obtaining
8  * a copy of this software and associated documentation files (the
9  * "Software"), to deal in the Software without restriction, including
10  * without limitation the rights to use, copy, modify, merge, publish,
11  * distribute, sublicense, and/or sell copies of the Software, and to
12  * permit persons to whom the Software is furnished to do so, subject to
13  * the following conditions:
14  *
15  * The above copyright notice and this permission notice shall be
16  * included in all copies or substantial portions of the Software.
17  *
18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
22  * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
23  * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
24  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25  */
26 #ifndef NGHTTP3_CONV_H
27 #define NGHTTP3_CONV_H
28 
29 #ifdef HAVE_CONFIG_H
30 #  include <config.h>
31 #endif /* HAVE_CONFIG_H */
32 
33 #ifdef HAVE_ARPA_INET_H
34 #  include <arpa/inet.h>
35 #endif /* HAVE_ARPA_INET_H */
36 
37 #ifdef HAVE_NETINET_IN_H
38 #  include <netinet/in.h>
39 #endif /* HAVE_NETINET_IN_H */
40 
41 #ifdef HAVE_BYTESWAP_H
42 #  include <byteswap.h>
43 #endif /* HAVE_BYTESWAP_H */
44 
45 #ifdef HAVE_ENDIAN_H
46 #  include <endian.h>
47 #endif /* HAVE_ENDIAN_H */
48 
49 #ifdef HAVE_SYS_ENDIAN_H
50 #  include <sys/endian.h>
51 #endif /* HAVE_SYS_ENDIAN_H */
52 
53 #include <nghttp3/nghttp3.h>
54 
55 #if defined(HAVE_BSWAP_64) ||                                                  \
56     (defined(HAVE_DECL_BSWAP_64) && HAVE_DECL_BSWAP_64 > 0)
57 #  define nghttp3_bswap64 bswap_64
58 #else /* !HAVE_BSWAP_64 */
59 #  define nghttp3_bswap64(N)                                                   \
60     ((uint64_t)(ntohl((uint32_t)(N))) << 32 | ntohl((uint32_t)((N) >> 32)))
61 #endif /* !HAVE_BSWAP_64 */
62 
63 #if defined(HAVE_BE64TOH) ||                                                   \
64     (defined(HAVE_DECL_BE64TOH) && HAVE_DECL_BE64TOH > 0)
65 #  define nghttp3_ntohl64(N) be64toh(N)
66 #  define nghttp3_htonl64(N) htobe64(N)
67 #else /* !HAVE_BE64TOH */
68 #  if defined(WORDS_BIGENDIAN)
69 #    define nghttp3_ntohl64(N) (N)
70 #    define nghttp3_htonl64(N) (N)
71 #  else /* !WORDS_BIGENDIAN */
72 #    define nghttp3_ntohl64(N) nghttp3_bswap64(N)
73 #    define nghttp3_htonl64(N) nghttp3_bswap64(N)
74 #  endif /* !WORDS_BIGENDIAN */
75 #endif   /* !HAVE_BE64TOH */
76 
77 #if defined(WIN32)
78 /* Windows requires ws2_32 library for ntonl family of functions.  We
79    define inline functions for those functions so that we don't have
80    dependency on that lib. */
81 
82 #  ifdef _MSC_VER
83 #    define STIN static __inline
84 #  else
85 #    define STIN static inline
86 #  endif
87 
htonl(uint32_t hostlong)88 STIN uint32_t htonl(uint32_t hostlong) {
89   uint32_t res;
90   unsigned char *p = (unsigned char *)&res;
91   *p++ = hostlong >> 24;
92   *p++ = (hostlong >> 16) & 0xffu;
93   *p++ = (hostlong >> 8) & 0xffu;
94   *p = hostlong & 0xffu;
95   return res;
96 }
97 
htons(uint16_t hostshort)98 STIN uint16_t htons(uint16_t hostshort) {
99   uint16_t res;
100   unsigned char *p = (unsigned char *)&res;
101   *p++ = hostshort >> 8;
102   *p = hostshort & 0xffu;
103   return res;
104 }
105 
ntohl(uint32_t netlong)106 STIN uint32_t ntohl(uint32_t netlong) {
107   uint32_t res;
108   unsigned char *p = (unsigned char *)&netlong;
109   res = *p++ << 24;
110   res += *p++ << 16;
111   res += *p++ << 8;
112   res += *p;
113   return res;
114 }
115 
ntohs(uint16_t netshort)116 STIN uint16_t ntohs(uint16_t netshort) {
117   uint16_t res;
118   unsigned char *p = (unsigned char *)&netshort;
119   res = *p++ << 8;
120   res += *p;
121   return res;
122 }
123 
124 #endif /* WIN32 */
125 
126 /*
127  * nghttp3_get_varint reads variable-length integer from |p|, and
128  * returns it in host byte order.  The number of bytes read is stored
129  * in |*plen|.
130  */
131 int64_t nghttp3_get_varint(size_t *plen, const uint8_t *p);
132 
133 /*
134  * nghttp3_get_varint_fb reads first byte of encoded variable-length
135  * integer from |p|.
136  */
137 int64_t nghttp3_get_varint_fb(const uint8_t *p);
138 
139 /*
140  * nghttp3_get_varint_len returns the required number of bytes to read
141  * variable-length integer starting at |p|.
142  */
143 size_t nghttp3_get_varint_len(const uint8_t *p);
144 
145 /*
146  * nghttp3_put_uint64be writes |n| in host byte order in |p| in
147  * network byte order.  It returns the one beyond of the last written
148  * position.
149  */
150 uint8_t *nghttp3_put_uint64be(uint8_t *p, uint64_t n);
151 
152 /*
153  * nghttp3_put_uint48be writes |n| in host byte order in |p| in
154  * network byte order.  It writes only least significant 48 bits.  It
155  * returns the one beyond of the last written position.
156  */
157 uint8_t *nghttp3_put_uint48be(uint8_t *p, uint64_t n);
158 
159 /*
160  * nghttp3_put_uint32be writes |n| in host byte order in |p| in
161  * network byte order.  It returns the one beyond of the last written
162  * position.
163  */
164 uint8_t *nghttp3_put_uint32be(uint8_t *p, uint32_t n);
165 
166 /*
167  * nghttp3_put_uint24be writes |n| in host byte order in |p| in
168  * network byte order.  It writes only least significant 24 bits.  It
169  * returns the one beyond of the last written position.
170  */
171 uint8_t *nghttp3_put_uint24be(uint8_t *p, uint32_t n);
172 
173 /*
174  * nghttp3_put_uint16be writes |n| in host byte order in |p| in
175  * network byte order.  It returns the one beyond of the last written
176  * position.
177  */
178 uint8_t *nghttp3_put_uint16be(uint8_t *p, uint16_t n);
179 
180 /*
181  * nghttp3_put_varint writes |n| in |p| using variable-length integer
182  * encoding.  It returns the one beyond of the last written position.
183  */
184 uint8_t *nghttp3_put_varint(uint8_t *p, int64_t n);
185 
186 /*
187  * nghttp3_put_varint_len returns the required number of bytes to
188  * encode |n|.
189  */
190 size_t nghttp3_put_varint_len(int64_t n);
191 
192 /*
193  * nghttp3_ord_stream_id returns the ordinal number of |stream_id|.
194  */
195 uint64_t nghttp3_ord_stream_id(int64_t stream_id);
196 
197 /*
198  * NGHTTP3_PRI_INC_MASK is a bit mask to retrieve incremental bit from
199  * a value produced by nghttp3_pri_to_uint8.
200  */
201 #define NGHTTP3_PRI_INC_MASK (1 << 7)
202 
203 /*
204  * nghttp3_pri_to_uint8 encodes |pri| into uint8_t variable.
205  */
206 uint8_t nghttp3_pri_to_uint8(const nghttp3_pri *pri);
207 
208 /*
209  * nghttp3_pri_uint8_urgency extracts urgency from |PRI| which is
210  * supposed to be constructed by nghttp3_pri_to_uint8.
211  */
212 #define nghttp3_pri_uint8_urgency(PRI)                                         \
213   ((uint32_t)((PRI) & ~NGHTTP3_PRI_INC_MASK))
214 
215 /*
216  * nghttp3_pri_uint8_inc extracts inc from |PRI| which is supposed to
217  * be constructed by nghttp3_pri_to_uint8.
218  */
219 #define nghttp3_pri_uint8_inc(PRI) (((PRI)&NGHTTP3_PRI_INC_MASK) != 0)
220 
221 #endif /* NGHTTP3_CONV_H */
222