• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * nghttp2 - HTTP/2 C Library
3  *
4  * Copyright (c) 2012 Tatsuhiro Tsujikawa
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 #ifndef UTIL_H
26 #define UTIL_H
27 
28 #include "nghttp2_config.h"
29 
30 #ifdef HAVE_UNISTD_H
31 #  include <unistd.h>
32 #endif // HAVE_UNISTD_H
33 #include <getopt.h>
34 #ifdef HAVE_NETDB_H
35 #  include <netdb.h>
36 #endif // HAVE_NETDB_H
37 
38 #include <cmath>
39 #include <cstring>
40 #include <cassert>
41 #include <vector>
42 #include <string>
43 #include <algorithm>
44 #include <sstream>
45 #include <memory>
46 #include <chrono>
47 #include <map>
48 #include <random>
49 
50 #include "url-parser/url_parser.h"
51 
52 #include "template.h"
53 #include "network.h"
54 #include "allocator.h"
55 
56 namespace nghttp2 {
57 
58 constexpr auto NGHTTP2_H2_ALPN = StringRef::from_lit("\x2h2");
59 constexpr auto NGHTTP2_H2 = StringRef::from_lit("h2");
60 
61 // The additional HTTP/2 protocol ALPN protocol identifier we also
62 // supports for our applications to make smooth migration into final
63 // h2 ALPN ID.
64 constexpr auto NGHTTP2_H2_16_ALPN = StringRef::from_lit("\x5h2-16");
65 constexpr auto NGHTTP2_H2_16 = StringRef::from_lit("h2-16");
66 
67 constexpr auto NGHTTP2_H2_14_ALPN = StringRef::from_lit("\x5h2-14");
68 constexpr auto NGHTTP2_H2_14 = StringRef::from_lit("h2-14");
69 
70 constexpr auto NGHTTP2_H1_1_ALPN = StringRef::from_lit("\x8http/1.1");
71 constexpr auto NGHTTP2_H1_1 = StringRef::from_lit("http/1.1");
72 
73 constexpr size_t NGHTTP2_MAX_UINT64_DIGITS = str_size("18446744073709551615");
74 
75 namespace util {
76 
is_alpha(const char c)77 inline bool is_alpha(const char c) {
78   return ('A' <= c && c <= 'Z') || ('a' <= c && c <= 'z');
79 }
80 
is_digit(const char c)81 inline bool is_digit(const char c) { return '0' <= c && c <= '9'; }
82 
is_hex_digit(const char c)83 inline bool is_hex_digit(const char c) {
84   return is_digit(c) || ('A' <= c && c <= 'F') || ('a' <= c && c <= 'f');
85 }
86 
87 // Returns true if |s| is hex string.
88 bool is_hex_string(const StringRef &s);
89 
90 bool in_rfc3986_unreserved_chars(const char c);
91 
92 bool in_rfc3986_sub_delims(const char c);
93 
94 // Returns true if |c| is in token (HTTP-p1, Section 3.2.6)
95 bool in_token(char c);
96 
97 bool in_attr_char(char c);
98 
99 // Returns integer corresponding to hex notation |c|.  If
100 // is_hex_digit(c) is false, it returns 256.
101 uint32_t hex_to_uint(char c);
102 
103 std::string percent_encode(const unsigned char *target, size_t len);
104 
105 std::string percent_encode(const std::string &target);
106 
107 // percent-encode path component of URI |s|.
108 std::string percent_encode_path(const std::string &s);
109 
110 template <typename InputIt>
percent_decode(InputIt first,InputIt last)111 std::string percent_decode(InputIt first, InputIt last) {
112   std::string result;
113   result.resize(last - first);
114   auto p = std::begin(result);
115   for (; first != last; ++first) {
116     if (*first != '%') {
117       *p++ = *first;
118       continue;
119     }
120 
121     if (first + 1 != last && first + 2 != last && is_hex_digit(*(first + 1)) &&
122         is_hex_digit(*(first + 2))) {
123       *p++ = (hex_to_uint(*(first + 1)) << 4) + hex_to_uint(*(first + 2));
124       first += 2;
125       continue;
126     }
127 
128     *p++ = *first;
129   }
130   result.resize(p - std::begin(result));
131   return result;
132 }
133 
134 StringRef percent_decode(BlockAllocator &balloc, const StringRef &src);
135 
136 // Percent encode |target| if character is not in token or '%'.
137 StringRef percent_encode_token(BlockAllocator &balloc, const StringRef &target);
138 
139 // Returns quotedString version of |target|.  Currently, this function
140 // just replace '"' with '\"'.
141 StringRef quote_string(BlockAllocator &balloc, const StringRef &target);
142 
143 std::string format_hex(const unsigned char *s, size_t len);
144 
format_hex(const unsigned char (& s)[N])145 template <size_t N> std::string format_hex(const unsigned char (&s)[N]) {
146   return format_hex(s, N);
147 }
148 
format_hex(const std::array<uint8_t,N> & s)149 template <size_t N> std::string format_hex(const std::array<uint8_t, N> &s) {
150   return format_hex(s.data(), s.size());
151 }
152 
153 StringRef format_hex(BlockAllocator &balloc, const StringRef &s);
154 
155 static constexpr char LOWER_XDIGITS[] = "0123456789abcdef";
156 
157 template <typename OutputIt>
format_hex(OutputIt it,const StringRef & s)158 OutputIt format_hex(OutputIt it, const StringRef &s) {
159   for (auto cc : s) {
160     uint8_t c = cc;
161     *it++ = LOWER_XDIGITS[c >> 4];
162     *it++ = LOWER_XDIGITS[c & 0xf];
163   }
164 
165   return it;
166 }
167 
168 // decode_hex decodes hex string |s|, returns the decoded byte string.
169 // This function assumes |s| is hex string, that is is_hex_string(s)
170 // == true.
171 StringRef decode_hex(BlockAllocator &balloc, const StringRef &s);
172 
173 // Returns given time |t| from epoch in HTTP Date format (e.g., Mon,
174 // 10 Oct 2016 10:25:58 GMT).
175 std::string http_date(time_t t);
176 // Writes given time |t| from epoch in HTTP Date format into the
177 // buffer pointed by |res|.  The buffer must be at least 29 bytes
178 // long.  This function returns the one beyond the last position.
179 char *http_date(char *res, time_t t);
180 
181 // Returns given time |t| from epoch in Common Log format (e.g.,
182 // 03/Jul/2014:00:19:38 +0900)
183 std::string common_log_date(time_t t);
184 // Writes given time |t| from epoch in Common Log format into the
185 // buffer pointed by |res|.  The buffer must be at least 26 bytes
186 // long.  This function returns the one beyond the last position.
187 char *common_log_date(char *res, time_t t);
188 
189 // Returns given millisecond |ms| from epoch in ISO 8601 format (e.g.,
190 // 2014-11-15T12:58:24.741Z or 2014-11-15T12:58:24.741+09:00)
191 std::string iso8601_date(int64_t ms);
192 // Writes given time |t| from epoch in ISO 8601 format into the buffer
193 // pointed by |res|.  The buffer must be at least 29 bytes long.  This
194 // function returns the one beyond the last position.
195 char *iso8601_date(char *res, int64_t ms);
196 
197 time_t parse_http_date(const StringRef &s);
198 
199 // Parses time formatted as "MMM DD HH:MM:SS YYYY [GMT]" (e.g., Feb 3
200 // 00:55:52 2015 GMT), which is specifically used by OpenSSL
201 // ASN1_TIME_print().
202 time_t parse_openssl_asn1_time_print(const StringRef &s);
203 
204 char upcase(char c);
205 
lowcase(char c)206 inline char lowcase(char c) {
207   constexpr static unsigned char tbl[] = {
208       0,   1,   2,   3,   4,   5,   6,   7,   8,   9,   10,  11,  12,  13,  14,
209       15,  16,  17,  18,  19,  20,  21,  22,  23,  24,  25,  26,  27,  28,  29,
210       30,  31,  32,  33,  34,  35,  36,  37,  38,  39,  40,  41,  42,  43,  44,
211       45,  46,  47,  48,  49,  50,  51,  52,  53,  54,  55,  56,  57,  58,  59,
212       60,  61,  62,  63,  64,  'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j',
213       'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y',
214       'z', 91,  92,  93,  94,  95,  96,  97,  98,  99,  100, 101, 102, 103, 104,
215       105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119,
216       120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134,
217       135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149,
218       150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164,
219       165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179,
220       180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194,
221       195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209,
222       210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224,
223       225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239,
224       240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254,
225       255,
226   };
227   return tbl[static_cast<unsigned char>(c)];
228 }
229 
230 template <typename InputIterator1, typename InputIterator2>
starts_with(InputIterator1 first1,InputIterator1 last1,InputIterator2 first2,InputIterator2 last2)231 bool starts_with(InputIterator1 first1, InputIterator1 last1,
232                  InputIterator2 first2, InputIterator2 last2) {
233   if (last1 - first1 < last2 - first2) {
234     return false;
235   }
236   return std::equal(first2, last2, first1);
237 }
238 
starts_with(const S & a,const T & b)239 template <typename S, typename T> bool starts_with(const S &a, const T &b) {
240   return starts_with(a.begin(), a.end(), b.begin(), b.end());
241 }
242 
243 struct CaseCmp {
operatorCaseCmp244   bool operator()(char lhs, char rhs) const {
245     return lowcase(lhs) == lowcase(rhs);
246   }
247 };
248 
249 template <typename InputIterator1, typename InputIterator2>
istarts_with(InputIterator1 first1,InputIterator1 last1,InputIterator2 first2,InputIterator2 last2)250 bool istarts_with(InputIterator1 first1, InputIterator1 last1,
251                   InputIterator2 first2, InputIterator2 last2) {
252   if (last1 - first1 < last2 - first2) {
253     return false;
254   }
255   return std::equal(first2, last2, first1, CaseCmp());
256 }
257 
istarts_with(const S & a,const T & b)258 template <typename S, typename T> bool istarts_with(const S &a, const T &b) {
259   return istarts_with(a.begin(), a.end(), b.begin(), b.end());
260 }
261 
262 template <typename T, typename CharT, size_t N>
istarts_with_l(const T & a,const CharT (& b)[N])263 bool istarts_with_l(const T &a, const CharT (&b)[N]) {
264   return istarts_with(a.begin(), a.end(), b, b + N - 1);
265 }
266 
267 template <typename InputIterator1, typename InputIterator2>
ends_with(InputIterator1 first1,InputIterator1 last1,InputIterator2 first2,InputIterator2 last2)268 bool ends_with(InputIterator1 first1, InputIterator1 last1,
269                InputIterator2 first2, InputIterator2 last2) {
270   if (last1 - first1 < last2 - first2) {
271     return false;
272   }
273   return std::equal(first2, last2, last1 - (last2 - first2));
274 }
275 
ends_with(const T & a,const S & b)276 template <typename T, typename S> bool ends_with(const T &a, const S &b) {
277   return ends_with(a.begin(), a.end(), b.begin(), b.end());
278 }
279 
280 template <typename T, typename CharT, size_t N>
ends_with_l(const T & a,const CharT (& b)[N])281 bool ends_with_l(const T &a, const CharT (&b)[N]) {
282   return ends_with(a.begin(), a.end(), b, b + N - 1);
283 }
284 
285 template <typename InputIterator1, typename InputIterator2>
iends_with(InputIterator1 first1,InputIterator1 last1,InputIterator2 first2,InputIterator2 last2)286 bool iends_with(InputIterator1 first1, InputIterator1 last1,
287                 InputIterator2 first2, InputIterator2 last2) {
288   if (last1 - first1 < last2 - first2) {
289     return false;
290   }
291   return std::equal(first2, last2, last1 - (last2 - first2), CaseCmp());
292 }
293 
iends_with(const T & a,const S & b)294 template <typename T, typename S> bool iends_with(const T &a, const S &b) {
295   return iends_with(a.begin(), a.end(), b.begin(), b.end());
296 }
297 
298 template <typename T, typename CharT, size_t N>
iends_with_l(const T & a,const CharT (& b)[N])299 bool iends_with_l(const T &a, const CharT (&b)[N]) {
300   return iends_with(a.begin(), a.end(), b, b + N - 1);
301 }
302 
303 template <typename InputIt1, typename InputIt2>
strieq(InputIt1 first1,InputIt1 last1,InputIt2 first2,InputIt2 last2)304 bool strieq(InputIt1 first1, InputIt1 last1, InputIt2 first2, InputIt2 last2) {
305   if (std::distance(first1, last1) != std::distance(first2, last2)) {
306     return false;
307   }
308 
309   return std::equal(first1, last1, first2, CaseCmp());
310 }
311 
strieq(const T & a,const S & b)312 template <typename T, typename S> bool strieq(const T &a, const S &b) {
313   return strieq(a.begin(), a.end(), b.begin(), b.end());
314 }
315 
316 template <typename CharT, typename InputIt, size_t N>
strieq_l(const CharT (& a)[N],InputIt b,size_t blen)317 bool strieq_l(const CharT (&a)[N], InputIt b, size_t blen) {
318   return strieq(a, a + (N - 1), b, b + blen);
319 }
320 
321 template <typename CharT, size_t N, typename T>
strieq_l(const CharT (& a)[N],const T & b)322 bool strieq_l(const CharT (&a)[N], const T &b) {
323   return strieq(a, a + (N - 1), b.begin(), b.end());
324 }
325 
326 template <typename InputIt1, typename InputIt2>
streq(InputIt1 first1,InputIt1 last1,InputIt2 first2,InputIt2 last2)327 bool streq(InputIt1 first1, InputIt1 last1, InputIt2 first2, InputIt2 last2) {
328   if (std::distance(first1, last1) != std::distance(first2, last2)) {
329     return false;
330   }
331   return std::equal(first1, last1, first2);
332 }
333 
streq(const T & a,const S & b)334 template <typename T, typename S> bool streq(const T &a, const S &b) {
335   return streq(a.begin(), a.end(), b.begin(), b.end());
336 }
337 
338 template <typename CharT, typename InputIt, size_t N>
streq_l(const CharT (& a)[N],InputIt b,size_t blen)339 bool streq_l(const CharT (&a)[N], InputIt b, size_t blen) {
340   return streq(a, a + (N - 1), b, b + blen);
341 }
342 
343 template <typename CharT, size_t N, typename T>
streq_l(const CharT (& a)[N],const T & b)344 bool streq_l(const CharT (&a)[N], const T &b) {
345   return streq(a, a + (N - 1), b.begin(), b.end());
346 }
347 
348 // Returns true if |a| contains |b|.  If both |a| and |b| are empty,
349 // this function returns false.
strifind(const S & a,const T & b)350 template <typename S, typename T> bool strifind(const S &a, const T &b) {
351   return std::search(a.begin(), a.end(), b.begin(), b.end(), CaseCmp()) !=
352          a.end();
353 }
354 
inp_strlower(InputIt first,InputIt last)355 template <typename InputIt> void inp_strlower(InputIt first, InputIt last) {
356   std::transform(first, last, first, lowcase);
357 }
358 
359 // Lowercase |s| in place.
inp_strlower(std::string & s)360 inline void inp_strlower(std::string &s) {
361   inp_strlower(std::begin(s), std::end(s));
362 }
363 
364 // Returns string representation of |n| with 2 fractional digits.
365 std::string dtos(double n);
366 
utos(T n)367 template <typename T> std::string utos(T n) {
368   std::string res;
369   if (n == 0) {
370     res = "0";
371     return res;
372   }
373   size_t nlen = 0;
374   for (auto t = n; t; t /= 10, ++nlen)
375     ;
376   res.resize(nlen);
377   for (; n; n /= 10) {
378     res[--nlen] = (n % 10) + '0';
379   }
380   return res;
381 }
382 
utos(OutputIt dst,T n)383 template <typename T, typename OutputIt> OutputIt utos(OutputIt dst, T n) {
384   if (n == 0) {
385     *dst++ = '0';
386     return dst;
387   }
388   size_t nlen = 0;
389   for (auto t = n; t; t /= 10, ++nlen)
390     ;
391   auto p = dst + nlen;
392   auto res = p;
393   for (; n; n /= 10) {
394     *--p = (n % 10) + '0';
395   }
396   return res;
397 }
398 
399 template <typename T>
make_string_ref_uint(BlockAllocator & balloc,T n)400 StringRef make_string_ref_uint(BlockAllocator &balloc, T n) {
401   auto iov = make_byte_ref(balloc, NGHTTP2_MAX_UINT64_DIGITS + 1);
402   auto p = iov.base;
403   p = util::utos(p, n);
404   *p = '\0';
405   return StringRef{iov.base, p};
406 }
407 
utos_unit(T n)408 template <typename T> std::string utos_unit(T n) {
409   char u = 0;
410   if (n >= (1 << 30)) {
411     u = 'G';
412     n /= (1 << 30);
413   } else if (n >= (1 << 20)) {
414     u = 'M';
415     n /= (1 << 20);
416   } else if (n >= (1 << 10)) {
417     u = 'K';
418     n /= (1 << 10);
419   }
420   if (u == 0) {
421     return utos(n);
422   }
423   return utos(n) + u;
424 }
425 
426 // Like utos_unit(), but 2 digits fraction part is followed.
utos_funit(T n)427 template <typename T> std::string utos_funit(T n) {
428   char u = 0;
429   int b = 0;
430   if (n >= (1 << 30)) {
431     u = 'G';
432     b = 30;
433   } else if (n >= (1 << 20)) {
434     u = 'M';
435     b = 20;
436   } else if (n >= (1 << 10)) {
437     u = 'K';
438     b = 10;
439   }
440   if (b == 0) {
441     return utos(n);
442   }
443   return dtos(static_cast<double>(n) / (1 << b)) + u;
444 }
445 
446 extern const char UPPER_XDIGITS[];
447 
utox(T n)448 template <typename T> std::string utox(T n) {
449   std::string res;
450   if (n == 0) {
451     res = "0";
452     return res;
453   }
454   int i = 0;
455   T t = n;
456   for (; t; t /= 16, ++i)
457     ;
458   res.resize(i);
459   --i;
460   for (; n; --i, n /= 16) {
461     res[i] = UPPER_XDIGITS[(n & 0x0f)];
462   }
463   return res;
464 }
465 
466 void to_token68(std::string &base64str);
467 
468 StringRef to_base64(BlockAllocator &balloc, const StringRef &token68str);
469 
470 void show_candidates(const char *unkopt, const option *options);
471 
472 bool has_uri_field(const http_parser_url &u, http_parser_url_fields field);
473 
474 bool fieldeq(const char *uri1, const http_parser_url &u1, const char *uri2,
475              const http_parser_url &u2, http_parser_url_fields field);
476 
477 bool fieldeq(const char *uri, const http_parser_url &u,
478              http_parser_url_fields field, const char *t);
479 
480 bool fieldeq(const char *uri, const http_parser_url &u,
481              http_parser_url_fields field, const StringRef &t);
482 
483 StringRef get_uri_field(const char *uri, const http_parser_url &u,
484                         http_parser_url_fields field);
485 
486 uint16_t get_default_port(const char *uri, const http_parser_url &u);
487 
488 bool porteq(const char *uri1, const http_parser_url &u1, const char *uri2,
489             const http_parser_url &u2);
490 
491 void write_uri_field(std::ostream &o, const char *uri, const http_parser_url &u,
492                      http_parser_url_fields field);
493 
494 bool numeric_host(const char *hostname);
495 
496 bool numeric_host(const char *hostname, int family);
497 
498 // Returns numeric address string of |addr|.  If getnameinfo() is
499 // failed, "unknown" is returned.
500 std::string numeric_name(const struct sockaddr *sa, socklen_t salen);
501 
502 // Returns string representation of numeric address and port of
503 // |addr|.  If address family is AF_UNIX, this return path to UNIX
504 // domain socket.  Otherwise, the format is like <HOST>:<PORT>.  For
505 // IPv6 address, address is enclosed by square brackets ([]).
506 std::string to_numeric_addr(const Address *addr);
507 
508 // Sets |port| to |addr|.
509 void set_port(Address &addr, uint16_t port);
510 
511 // Returns ASCII dump of |data| of length |len|.  Only ASCII printable
512 // characters are preserved.  Other characters are replaced with ".".
513 std::string ascii_dump(const uint8_t *data, size_t len);
514 
515 // Returns absolute path of executable path.  If argc == 0 or |cwd| is
516 // nullptr, this function returns nullptr.  If argv[0] starts with
517 // '/', this function returns argv[0].  Oterwise return cwd + "/" +
518 // argv[0].  If non-null is returned, it is NULL-terminated string and
519 // dynamically allocated by malloc.  The caller is responsible to free
520 // it.
521 char *get_exec_path(int argc, char **const argv, const char *cwd);
522 
523 // Validates path so that it does not contain directory traversal
524 // vector.  Returns true if path is safe.  The |path| must start with
525 // "/" otherwise returns false.  This function should be called after
526 // percent-decode was performed.
527 bool check_path(const std::string &path);
528 
529 // Returns the |tv| value as 64 bit integer using a microsecond as an
530 // unit.
531 int64_t to_time64(const timeval &tv);
532 
533 // Returns true if ALPN ID |proto| is supported HTTP/2 protocol
534 // identifier.
535 bool check_h2_is_selected(const StringRef &proto);
536 
537 // Selects h2 protocol ALPN ID if one of supported h2 versions are
538 // present in |in| of length inlen.  Returns true if h2 version is
539 // selected.
540 bool select_h2(const unsigned char **out, unsigned char *outlen,
541                const unsigned char *in, unsigned int inlen);
542 
543 // Selects protocol ALPN ID if one of identifiers contained in |protolist| is
544 // present in |in| of length inlen.  Returns true if identifier is
545 // selected.
546 bool select_protocol(const unsigned char **out, unsigned char *outlen,
547                      const unsigned char *in, unsigned int inlen,
548                      std::vector<std::string> proto_list);
549 
550 // Returns default ALPN protocol list, which only contains supported
551 // HTTP/2 protocol identifier.
552 std::vector<unsigned char> get_default_alpn();
553 
554 // Parses delimited strings in |s| and returns the array of substring,
555 // delimited by |delim|.  The any white spaces around substring are
556 // treated as a part of substring.
557 std::vector<std::string> parse_config_str_list(const StringRef &s,
558                                                char delim = ',');
559 
560 // Parses delimited strings in |s| and returns Substrings in |s|
561 // delimited by |delim|.  The any white spaces around substring are
562 // treated as a part of substring.
563 std::vector<StringRef> split_str(const StringRef &s, char delim);
564 
565 // Writes given time |tp| in Common Log format (e.g.,
566 // 03/Jul/2014:00:19:38 +0900) in buffer pointed by |out|.  The buffer
567 // must be at least 27 bytes, including terminal NULL byte.  Expected
568 // type of |tp| is std::chrono::time_point.  This function returns
569 // StringRef wrapping the buffer pointed by |out|, and this string is
570 // terminated by NULL.
format_common_log(char * out,const T & tp)571 template <typename T> StringRef format_common_log(char *out, const T &tp) {
572   auto t =
573       std::chrono::duration_cast<std::chrono::seconds>(tp.time_since_epoch());
574   auto p = common_log_date(out, t.count());
575   *p = '\0';
576   return StringRef{out, p};
577 }
578 
579 // Returns given time |tp| in ISO 8601 format (e.g.,
580 // 2014-11-15T12:58:24.741Z or 2014-11-15T12:58:24.741+09:00).
581 // Expected type of |tp| is std::chrono::time_point
format_iso8601(const T & tp)582 template <typename T> std::string format_iso8601(const T &tp) {
583   auto t = std::chrono::duration_cast<std::chrono::milliseconds>(
584       tp.time_since_epoch());
585   return iso8601_date(t.count());
586 }
587 
588 // Writes given time |tp| in ISO 8601 format (e.g.,
589 // 2014-11-15T12:58:24.741Z or 2014-11-15T12:58:24.741+09:00) in
590 // buffer pointed by |out|.  The buffer must be at least 30 bytes,
591 // including terminal NULL byte.  Expected type of |tp| is
592 // std::chrono::time_point.  This function returns StringRef wrapping
593 // the buffer pointed by |out|, and this string is terminated by NULL.
format_iso8601(char * out,const T & tp)594 template <typename T> StringRef format_iso8601(char *out, const T &tp) {
595   auto t = std::chrono::duration_cast<std::chrono::milliseconds>(
596       tp.time_since_epoch());
597   auto p = iso8601_date(out, t.count());
598   *p = '\0';
599   return StringRef{out, p};
600 }
601 
602 // Writes given time |tp| in HTTP Date format (e.g., Mon, 10 Oct 2016
603 // 10:25:58 GMT) in buffer pointed by |out|.  The buffer must be at
604 // least 30 bytes, including terminal NULL byte.  Expected type of
605 // |tp| is std::chrono::time_point.  This function returns StringRef
606 // wrapping the buffer pointed by |out|, and this string is terminated
607 // by NULL.
format_http_date(char * out,const T & tp)608 template <typename T> StringRef format_http_date(char *out, const T &tp) {
609   auto t =
610       std::chrono::duration_cast<std::chrono::seconds>(tp.time_since_epoch());
611   auto p = http_date(out, t.count());
612   *p = '\0';
613   return StringRef{out, p};
614 }
615 
616 // Return the system precision of the template parameter |Clock| as
617 // a nanosecond value of type |Rep|
clock_precision()618 template <typename Clock, typename Rep> Rep clock_precision() {
619   std::chrono::duration<Rep, std::nano> duration = typename Clock::duration(1);
620 
621   return duration.count();
622 }
623 
624 int make_socket_closeonexec(int fd);
625 int make_socket_nonblocking(int fd);
626 int make_socket_nodelay(int fd);
627 
628 int create_nonblock_socket(int family);
629 
630 bool check_socket_connected(int fd);
631 
632 // Returns the error code (errno) by inspecting SO_ERROR of given
633 // |fd|.  This function returns the error code if it succeeds, or -1.
634 // Returning 0 means no error.
635 int get_socket_error(int fd);
636 
637 // Returns true if |host| is IPv6 numeric address (e.g., ::1)
638 bool ipv6_numeric_addr(const char *host);
639 
640 // Parses NULL terminated string |s| as unsigned integer and returns
641 // the parsed integer.  Additionally, if |s| ends with 'k', 'm', 'g'
642 // and its upper case characters, multiply the integer by 1024, 1024 *
643 // 1024 and 1024 * 1024 respectively.  If there is an error, returns
644 // -1.
645 int64_t parse_uint_with_unit(const char *s);
646 // The following overload does not require |s| is NULL terminated.
647 int64_t parse_uint_with_unit(const uint8_t *s, size_t len);
648 int64_t parse_uint_with_unit(const StringRef &s);
649 
650 // Parses NULL terminated string |s| as unsigned integer and returns
651 // the parsed integer.  If there is an error, returns -1.
652 int64_t parse_uint(const char *s);
653 // The following overload does not require |s| is NULL terminated.
654 int64_t parse_uint(const uint8_t *s, size_t len);
655 int64_t parse_uint(const std::string &s);
656 int64_t parse_uint(const StringRef &s);
657 
658 // Parses NULL terminated string |s| as unsigned integer and returns
659 // the parsed integer casted to double.  If |s| ends with "s", the
660 // parsed value's unit is a second.  If |s| ends with "ms", the unit
661 // is millisecond.  Similarly, it also supports 'm' and 'h' for
662 // minutes and hours respectively.  If none of them are given, the
663 // unit is second.  This function returns
664 // std::numeric_limits<double>::infinity() if error occurs.
665 double parse_duration_with_unit(const char *s);
666 // The following overload does not require |s| is NULL terminated.
667 double parse_duration_with_unit(const uint8_t *s, size_t len);
668 double parse_duration_with_unit(const StringRef &s);
669 
670 // Returns string representation of time duration |t|.  If t has
671 // fractional part (at least more than or equal to 1e-3), |t| is
672 // multiplied by 1000 and the unit "ms" is appended.  Otherwise, |t|
673 // is left as is and "s" is appended.
674 std::string duration_str(double t);
675 
676 // Returns string representation of time duration |t|.  It appends
677 // unit after the formatting.  The available units are s, ms and us.
678 // The unit which is equal to or less than |t| is used and 2
679 // fractional digits follow.
680 std::string format_duration(const std::chrono::microseconds &u);
681 
682 // Just like above, but this takes |t| as seconds.
683 std::string format_duration(double t);
684 
685 // Creates "host:port" string using given |host| and |port|.  If
686 // |host| is numeric IPv6 address (e.g., ::1), it is enclosed by "["
687 // and "]".  If |port| is 80 or 443, port part is omitted.
688 StringRef make_http_hostport(BlockAllocator &balloc, const StringRef &host,
689                              uint16_t port);
690 
691 // Just like make_http_hostport(), but doesn't treat 80 and 443
692 // specially.
693 std::string make_hostport(const StringRef &host, uint16_t port);
694 
695 StringRef make_hostport(BlockAllocator &balloc, const StringRef &host,
696                         uint16_t port);
697 
698 // Dumps |src| of length |len| in the format similar to `hexdump -C`.
699 void hexdump(FILE *out, const uint8_t *src, size_t len);
700 
701 // Copies 2 byte unsigned integer |n| in host byte order to |buf| in
702 // network byte order.
703 void put_uint16be(uint8_t *buf, uint16_t n);
704 
705 // Copies 4 byte unsigned integer |n| in host byte order to |buf| in
706 // network byte order.
707 void put_uint32be(uint8_t *buf, uint32_t n);
708 
709 // Retrieves 2 byte unsigned integer stored in |data| in network byte
710 // order and returns it in host byte order.
711 uint16_t get_uint16(const uint8_t *data);
712 
713 // Retrieves 4 byte unsigned integer stored in |data| in network byte
714 // order and returns it in host byte order.
715 uint32_t get_uint32(const uint8_t *data);
716 
717 // Retrieves 8 byte unsigned integer stored in |data| in network byte
718 // order and returns it in host byte order.
719 uint64_t get_uint64(const uint8_t *data);
720 
721 // Reads mime types file (see /etc/mime.types), and stores extension
722 // -> MIME type map in |res|.  This function returns 0 if it succeeds,
723 // or -1.
724 int read_mime_types(std::map<std::string, std::string> &res,
725                     const char *filename);
726 
727 // Fills random alpha and digit byte to the range [|first|, |last|).
728 // Returns the one beyond the |last|.
729 template <typename OutputIt, typename Generator>
random_alpha_digit(OutputIt first,OutputIt last,Generator & gen)730 OutputIt random_alpha_digit(OutputIt first, OutputIt last, Generator &gen) {
731   // If we use uint8_t instead char, gcc 6.2.0 complains by shouting
732   // char-array initialized from wide string.
733   static constexpr char s[] =
734       "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
735   std::uniform_int_distribution<> dis(0, 26 * 2 + 10 - 1);
736   for (; first != last; ++first) {
737     *first = s[dis(gen)];
738   }
739   return first;
740 }
741 
742 // Fills random bytes to the range [|first|, |last|).
743 template <typename OutputIt, typename Generator>
random_bytes(OutputIt first,OutputIt last,Generator & gen)744 void random_bytes(OutputIt first, OutputIt last, Generator &gen) {
745   std::uniform_int_distribution<> dis(0, 255);
746   std::generate(first, last, [&dis, &gen]() { return dis(gen); });
747 }
748 
749 template <typename OutputIterator, typename CharT, size_t N>
copy_lit(OutputIterator it,CharT (& s)[N])750 OutputIterator copy_lit(OutputIterator it, CharT (&s)[N]) {
751   return std::copy_n(s, N - 1, it);
752 }
753 
754 // Returns x**y
755 double int_pow(double x, size_t y);
756 
757 uint32_t hash32(const StringRef &s);
758 
759 // Computes SHA-256 of |s|, and stores it in |buf|.  This function
760 // returns 0 if it succeeds, or -1.
761 int sha256(uint8_t *buf, const StringRef &s);
762 
763 // Computes SHA-1 of |s|, and stores it in |buf|.  This function
764 // returns 0 if it succeeds, or -1.
765 int sha1(uint8_t *buf, const StringRef &s);
766 
767 // Returns host from |hostport|.  If host cannot be found in
768 // |hostport|, returns empty string.  The returned string might not be
769 // NULL-terminated.
770 StringRef extract_host(const StringRef &hostport);
771 
772 // split_hostport splits host and port in |hostport|.  Unlike
773 // extract_host, square brackets enclosing host name is stripped.  If
774 // port is not available, it returns empty string in the second
775 // string.  The returned string might not be NULL-terminated.  On any
776 // error, it returns a pair which has empty strings.
777 std::pair<StringRef, StringRef> split_hostport(const StringRef &hostport);
778 
779 // Returns new std::mt19937 object.
780 std::mt19937 make_mt19937();
781 
782 // daemonize calls daemon(3).  If __APPLE__ is defined, it implements
783 // daemon() using fork().
784 int daemonize(int nochdir, int noclose);
785 
786 } // namespace util
787 
788 } // namespace nghttp2
789 
790 #endif // UTIL_H
791