• 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 #include "util.h"
26 
27 #ifdef HAVE_TIME_H
28 #  include <time.h>
29 #endif // HAVE_TIME_H
30 #include <sys/types.h>
31 #ifdef HAVE_SYS_SOCKET_H
32 #  include <sys/socket.h>
33 #endif // HAVE_SYS_SOCKET_H
34 #ifdef HAVE_NETDB_H
35 #  include <netdb.h>
36 #endif // HAVE_NETDB_H
37 #include <sys/stat.h>
38 #ifdef HAVE_FCNTL_H
39 #  include <fcntl.h>
40 #endif // HAVE_FCNTL_H
41 #ifdef HAVE_NETINET_IN_H
42 #  include <netinet/in.h>
43 #endif // HAVE_NETINET_IN_H
44 #ifdef _WIN32
45 #  include <ws2tcpip.h>
46 #  include <boost/date_time/posix_time/posix_time.hpp>
47 #else // !_WIN32
48 #  include <netinet/tcp.h>
49 #endif // !_WIN32
50 #ifdef HAVE_ARPA_INET_H
51 #  include <arpa/inet.h>
52 #endif // HAVE_ARPA_INET_H
53 
54 #include <cmath>
55 #include <cerrno>
56 #include <cassert>
57 #include <cstdio>
58 #include <cstring>
59 #include <iostream>
60 #include <fstream>
61 
62 #include <openssl/evp.h>
63 
64 #include <nghttp2/nghttp2.h>
65 
66 #include "ssl_compat.h"
67 #include "timegm.h"
68 
69 namespace nghttp2 {
70 
71 namespace util {
72 
73 #ifndef _WIN32
74 namespace {
nghttp2_inet_pton(int af,const char * src,void * dst)75 int nghttp2_inet_pton(int af, const char *src, void *dst) {
76   return inet_pton(af, src, dst);
77 }
78 } // namespace
79 #else // _WIN32
80 namespace {
81 // inet_pton-wrapper for Windows
82 int nghttp2_inet_pton(int af, const char *src, void *dst) {
83 #  if _WIN32_WINNT >= 0x0600
84   return InetPtonA(af, src, dst);
85 #  else
86   // the function takes a 'char*', so we need to make a copy
87   char addr[INET6_ADDRSTRLEN + 1];
88   strncpy(addr, src, sizeof(addr));
89   addr[sizeof(addr) - 1] = 0;
90 
91   int size = sizeof(struct in6_addr);
92 
93   if (WSAStringToAddress(addr, af, NULL, (LPSOCKADDR)dst, &size) == 0)
94     return 1;
95   return 0;
96 #  endif
97 }
98 } // namespace
99 #endif // _WIN32
100 
101 const char UPPER_XDIGITS[] = "0123456789ABCDEF";
102 
in_rfc3986_unreserved_chars(const char c)103 bool in_rfc3986_unreserved_chars(const char c) {
104   static constexpr char unreserved[] = {'-', '.', '_', '~'};
105   return is_alpha(c) || is_digit(c) ||
106          std::find(std::begin(unreserved), std::end(unreserved), c) !=
107              std::end(unreserved);
108 }
109 
in_rfc3986_sub_delims(const char c)110 bool in_rfc3986_sub_delims(const char c) {
111   static constexpr char sub_delims[] = {'!', '$', '&', '\'', '(', ')',
112                                         '*', '+', ',', ';',  '='};
113   return std::find(std::begin(sub_delims), std::end(sub_delims), c) !=
114          std::end(sub_delims);
115 }
116 
percent_encode(const unsigned char * target,size_t len)117 std::string percent_encode(const unsigned char *target, size_t len) {
118   std::string dest;
119   for (size_t i = 0; i < len; ++i) {
120     unsigned char c = target[i];
121 
122     if (in_rfc3986_unreserved_chars(c)) {
123       dest += c;
124     } else {
125       dest += '%';
126       dest += UPPER_XDIGITS[c >> 4];
127       dest += UPPER_XDIGITS[(c & 0x0f)];
128     }
129   }
130   return dest;
131 }
132 
percent_encode(const std::string & target)133 std::string percent_encode(const std::string &target) {
134   return percent_encode(reinterpret_cast<const unsigned char *>(target.c_str()),
135                         target.size());
136 }
137 
percent_encode_path(const std::string & s)138 std::string percent_encode_path(const std::string &s) {
139   std::string dest;
140   for (auto c : s) {
141     if (in_rfc3986_unreserved_chars(c) || in_rfc3986_sub_delims(c) ||
142         c == '/') {
143       dest += c;
144       continue;
145     }
146 
147     dest += '%';
148     dest += UPPER_XDIGITS[(c >> 4) & 0x0f];
149     dest += UPPER_XDIGITS[(c & 0x0f)];
150   }
151   return dest;
152 }
153 
in_token(char c)154 bool in_token(char c) {
155   static constexpr char extra[] = {'!', '#', '$', '%', '&', '\'', '*', '+',
156                                    '-', '.', '^', '_', '`', '|',  '~'};
157   return is_alpha(c) || is_digit(c) ||
158          std::find(std::begin(extra), std::end(extra), c) != std::end(extra);
159 }
160 
in_attr_char(char c)161 bool in_attr_char(char c) {
162   static constexpr char bad[] = {'*', '\'', '%'};
163   return util::in_token(c) &&
164          std::find(std::begin(bad), std::end(bad), c) == std::end(bad);
165 }
166 
percent_encode_token(BlockAllocator & balloc,const StringRef & target)167 StringRef percent_encode_token(BlockAllocator &balloc,
168                                const StringRef &target) {
169   auto iov = make_byte_ref(balloc, target.size() * 3 + 1);
170   auto p = iov.base;
171 
172   for (auto first = std::begin(target); first != std::end(target); ++first) {
173     uint8_t c = *first;
174 
175     if (c != '%' && in_token(c)) {
176       *p++ = c;
177       continue;
178     }
179 
180     *p++ = '%';
181     *p++ = UPPER_XDIGITS[c >> 4];
182     *p++ = UPPER_XDIGITS[(c & 0x0f)];
183   }
184 
185   *p = '\0';
186 
187   return StringRef{iov.base, p};
188 }
189 
hex_to_uint(char c)190 uint32_t hex_to_uint(char c) {
191   if (c <= '9') {
192     return c - '0';
193   }
194   if (c <= 'Z') {
195     return c - 'A' + 10;
196   }
197   if (c <= 'z') {
198     return c - 'a' + 10;
199   }
200   return 256;
201 }
202 
quote_string(BlockAllocator & balloc,const StringRef & target)203 StringRef quote_string(BlockAllocator &balloc, const StringRef &target) {
204   auto cnt = std::count(std::begin(target), std::end(target), '"');
205 
206   if (cnt == 0) {
207     return make_string_ref(balloc, target);
208   }
209 
210   auto iov = make_byte_ref(balloc, target.size() + cnt + 1);
211   auto p = iov.base;
212 
213   for (auto c : target) {
214     if (c == '"') {
215       *p++ = '\\';
216       *p++ = '"';
217     } else {
218       *p++ = c;
219     }
220   }
221   *p = '\0';
222 
223   return StringRef{iov.base, p};
224 }
225 
226 namespace {
227 template <typename Iterator>
cpydig(Iterator d,uint32_t n,size_t len)228 Iterator cpydig(Iterator d, uint32_t n, size_t len) {
229   auto p = d + len - 1;
230 
231   do {
232     *p-- = (n % 10) + '0';
233     n /= 10;
234   } while (p >= d);
235 
236   return d + len;
237 }
238 } // namespace
239 
240 namespace {
241 constexpr const char *MONTH[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun",
242                                  "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
243 constexpr const char *DAY_OF_WEEK[] = {"Sun", "Mon", "Tue", "Wed",
244                                        "Thu", "Fri", "Sat"};
245 } // namespace
246 
http_date(time_t t)247 std::string http_date(time_t t) {
248   /* Sat, 27 Sep 2014 06:31:15 GMT */
249   std::string res(29, 0);
250   http_date(&res[0], t);
251   return res;
252 }
253 
http_date(char * res,time_t t)254 char *http_date(char *res, time_t t) {
255   struct tm tms;
256 
257   if (gmtime_r(&t, &tms) == nullptr) {
258     return res;
259   }
260 
261   auto p = res;
262 
263   auto s = DAY_OF_WEEK[tms.tm_wday];
264   p = std::copy_n(s, 3, p);
265   *p++ = ',';
266   *p++ = ' ';
267   p = cpydig(p, tms.tm_mday, 2);
268   *p++ = ' ';
269   s = MONTH[tms.tm_mon];
270   p = std::copy_n(s, 3, p);
271   *p++ = ' ';
272   p = cpydig(p, tms.tm_year + 1900, 4);
273   *p++ = ' ';
274   p = cpydig(p, tms.tm_hour, 2);
275   *p++ = ':';
276   p = cpydig(p, tms.tm_min, 2);
277   *p++ = ':';
278   p = cpydig(p, tms.tm_sec, 2);
279   s = " GMT";
280   p = std::copy_n(s, 4, p);
281 
282   return p;
283 }
284 
common_log_date(time_t t)285 std::string common_log_date(time_t t) {
286   // 03/Jul/2014:00:19:38 +0900
287   std::string res(26, 0);
288   common_log_date(&res[0], t);
289   return res;
290 }
291 
common_log_date(char * res,time_t t)292 char *common_log_date(char *res, time_t t) {
293   struct tm tms;
294 
295   if (localtime_r(&t, &tms) == nullptr) {
296     return res;
297   }
298 
299   auto p = res;
300 
301   p = cpydig(p, tms.tm_mday, 2);
302   *p++ = '/';
303   auto s = MONTH[tms.tm_mon];
304   p = std::copy_n(s, 3, p);
305   *p++ = '/';
306   p = cpydig(p, tms.tm_year + 1900, 4);
307   *p++ = ':';
308   p = cpydig(p, tms.tm_hour, 2);
309   *p++ = ':';
310   p = cpydig(p, tms.tm_min, 2);
311   *p++ = ':';
312   p = cpydig(p, tms.tm_sec, 2);
313   *p++ = ' ';
314 
315 #ifdef HAVE_STRUCT_TM_TM_GMTOFF
316   auto gmtoff = tms.tm_gmtoff;
317 #else  // !HAVE_STRUCT_TM_TM_GMTOFF
318   auto gmtoff = nghttp2_timegm(&tms) - t;
319 #endif // !HAVE_STRUCT_TM_TM_GMTOFF
320   if (gmtoff >= 0) {
321     *p++ = '+';
322   } else {
323     *p++ = '-';
324     gmtoff = -gmtoff;
325   }
326 
327   p = cpydig(p, gmtoff / 3600, 2);
328   p = cpydig(p, (gmtoff % 3600) / 60, 2);
329 
330   return p;
331 }
332 
iso8601_date(int64_t ms)333 std::string iso8601_date(int64_t ms) {
334   // 2014-11-15T12:58:24.741Z
335   // 2014-11-15T12:58:24.741+09:00
336   std::string res(29, 0);
337   auto p = iso8601_date(&res[0], ms);
338   res.resize(p - &res[0]);
339   return res;
340 }
341 
iso8601_date(char * res,int64_t ms)342 char *iso8601_date(char *res, int64_t ms) {
343   time_t sec = ms / 1000;
344 
345   tm tms;
346   if (localtime_r(&sec, &tms) == nullptr) {
347     return res;
348   }
349 
350   auto p = res;
351 
352   p = cpydig(p, tms.tm_year + 1900, 4);
353   *p++ = '-';
354   p = cpydig(p, tms.tm_mon + 1, 2);
355   *p++ = '-';
356   p = cpydig(p, tms.tm_mday, 2);
357   *p++ = 'T';
358   p = cpydig(p, tms.tm_hour, 2);
359   *p++ = ':';
360   p = cpydig(p, tms.tm_min, 2);
361   *p++ = ':';
362   p = cpydig(p, tms.tm_sec, 2);
363   *p++ = '.';
364   p = cpydig(p, ms % 1000, 3);
365 
366 #ifdef HAVE_STRUCT_TM_TM_GMTOFF
367   auto gmtoff = tms.tm_gmtoff;
368 #else  // !HAVE_STRUCT_TM_TM_GMTOFF
369   auto gmtoff = nghttp2_timegm(&tms) - sec;
370 #endif // !HAVE_STRUCT_TM_TM_GMTOFF
371   if (gmtoff == 0) {
372     *p++ = 'Z';
373   } else {
374     if (gmtoff > 0) {
375       *p++ = '+';
376     } else {
377       *p++ = '-';
378       gmtoff = -gmtoff;
379     }
380     p = cpydig(p, gmtoff / 3600, 2);
381     *p++ = ':';
382     p = cpydig(p, (gmtoff % 3600) / 60, 2);
383   }
384 
385   return p;
386 }
387 
388 #ifdef _WIN32
389 namespace bt = boost::posix_time;
390 // one-time definition of the locale that is used to parse UTC strings
391 // (note that the time_input_facet is ref-counted and deleted automatically)
392 static const std::locale
393     ptime_locale(std::locale::classic(),
394                  new bt::time_input_facet("%a, %d %b %Y %H:%M:%S GMT"));
395 #endif //_WIN32
396 
parse_http_date(const StringRef & s)397 time_t parse_http_date(const StringRef &s) {
398 #ifdef _WIN32
399   // there is no strptime - use boost
400   std::stringstream sstr(s.str());
401   sstr.imbue(ptime_locale);
402   bt::ptime ltime;
403   sstr >> ltime;
404   if (!sstr)
405     return 0;
406 
407   return boost::posix_time::to_time_t(ltime);
408 #else  // !_WIN32
409   tm tm{};
410   char *r = strptime(s.c_str(), "%a, %d %b %Y %H:%M:%S GMT", &tm);
411   if (r == 0) {
412     return 0;
413   }
414   return nghttp2_timegm_without_yday(&tm);
415 #endif // !_WIN32
416 }
417 
parse_openssl_asn1_time_print(const StringRef & s)418 time_t parse_openssl_asn1_time_print(const StringRef &s) {
419   tm tm{};
420   auto r = strptime(s.c_str(), "%b %d %H:%M:%S %Y GMT", &tm);
421   if (r == nullptr) {
422     return 0;
423   }
424   return nghttp2_timegm_without_yday(&tm);
425 }
426 
upcase(char c)427 char upcase(char c) {
428   if ('a' <= c && c <= 'z') {
429     return c - 'a' + 'A';
430   } else {
431     return c;
432   }
433 }
434 
format_hex(const unsigned char * s,size_t len)435 std::string format_hex(const unsigned char *s, size_t len) {
436   std::string res;
437   res.resize(len * 2);
438 
439   for (size_t i = 0; i < len; ++i) {
440     unsigned char c = s[i];
441 
442     res[i * 2] = LOWER_XDIGITS[c >> 4];
443     res[i * 2 + 1] = LOWER_XDIGITS[c & 0x0f];
444   }
445   return res;
446 }
447 
format_hex(BlockAllocator & balloc,const StringRef & s)448 StringRef format_hex(BlockAllocator &balloc, const StringRef &s) {
449   auto iov = make_byte_ref(balloc, s.size() * 2 + 1);
450   auto p = iov.base;
451 
452   for (auto cc : s) {
453     uint8_t c = cc;
454     *p++ = LOWER_XDIGITS[c >> 4];
455     *p++ = LOWER_XDIGITS[c & 0xf];
456   }
457 
458   *p = '\0';
459 
460   return StringRef{iov.base, p};
461 }
462 
to_token68(std::string & base64str)463 void to_token68(std::string &base64str) {
464   std::transform(std::begin(base64str), std::end(base64str),
465                  std::begin(base64str), [](char c) {
466                    switch (c) {
467                    case '+':
468                      return '-';
469                    case '/':
470                      return '_';
471                    default:
472                      return c;
473                    }
474                  });
475   base64str.erase(std::find(std::begin(base64str), std::end(base64str), '='),
476                   std::end(base64str));
477 }
478 
to_base64(BlockAllocator & balloc,const StringRef & token68str)479 StringRef to_base64(BlockAllocator &balloc, const StringRef &token68str) {
480   // At most 3 padding '='
481   auto len = token68str.size() + 3;
482   auto iov = make_byte_ref(balloc, len + 1);
483   auto p = iov.base;
484 
485   p = std::transform(std::begin(token68str), std::end(token68str), p,
486                      [](char c) {
487                        switch (c) {
488                        case '-':
489                          return '+';
490                        case '_':
491                          return '/';
492                        default:
493                          return c;
494                        }
495                      });
496 
497   auto rem = token68str.size() & 0x3;
498   if (rem) {
499     p = std::fill_n(p, 4 - rem, '=');
500   }
501 
502   *p = '\0';
503 
504   return StringRef{iov.base, p};
505 }
506 
507 namespace {
508 // Calculates Damerau–Levenshtein distance between c-string a and b
509 // with given costs.  swapcost, subcost, addcost and delcost are cost
510 // to swap 2 adjacent characters, substitute characters, add character
511 // and delete character respectively.
levenshtein(const char * a,int alen,const char * b,int blen,int swapcost,int subcost,int addcost,int delcost)512 int levenshtein(const char *a, int alen, const char *b, int blen, int swapcost,
513                 int subcost, int addcost, int delcost) {
514   auto dp = std::vector<std::vector<int>>(3, std::vector<int>(blen + 1));
515   for (int i = 0; i <= blen; ++i) {
516     dp[1][i] = i;
517   }
518   for (int i = 1; i <= alen; ++i) {
519     dp[0][0] = i;
520     for (int j = 1; j <= blen; ++j) {
521       dp[0][j] = dp[1][j - 1] + (a[i - 1] == b[j - 1] ? 0 : subcost);
522       if (i >= 2 && j >= 2 && a[i - 1] != b[j - 1] && a[i - 2] == b[j - 1] &&
523           a[i - 1] == b[j - 2]) {
524         dp[0][j] = std::min(dp[0][j], dp[2][j - 2] + swapcost);
525       }
526       dp[0][j] = std::min(dp[0][j],
527                           std::min(dp[1][j] + delcost, dp[0][j - 1] + addcost));
528     }
529     std::rotate(std::begin(dp), std::begin(dp) + 2, std::end(dp));
530   }
531   return dp[1][blen];
532 }
533 } // namespace
534 
show_candidates(const char * unkopt,const option * options)535 void show_candidates(const char *unkopt, const option *options) {
536   for (; *unkopt == '-'; ++unkopt)
537     ;
538   if (*unkopt == '\0') {
539     return;
540   }
541   auto unkoptend = unkopt;
542   for (; *unkoptend && *unkoptend != '='; ++unkoptend)
543     ;
544   auto unkoptlen = unkoptend - unkopt;
545   if (unkoptlen == 0) {
546     return;
547   }
548   int prefix_match = 0;
549   auto cands = std::vector<std::pair<int, const char *>>();
550   for (size_t i = 0; options[i].name != nullptr; ++i) {
551     auto optnamelen = strlen(options[i].name);
552     // Use cost 0 for prefix match
553     if (istarts_with(options[i].name, options[i].name + optnamelen, unkopt,
554                      unkopt + unkoptlen)) {
555       if (optnamelen == static_cast<size_t>(unkoptlen)) {
556         // Exact match, then we don't show any condidates.
557         return;
558       }
559       ++prefix_match;
560       cands.emplace_back(0, options[i].name);
561       continue;
562     }
563     // Use cost 0 for suffix match, but match at least 3 characters
564     if (unkoptlen >= 3 &&
565         iends_with(options[i].name, options[i].name + optnamelen, unkopt,
566                    unkopt + unkoptlen)) {
567       cands.emplace_back(0, options[i].name);
568       continue;
569     }
570     // cost values are borrowed from git, help.c.
571     int sim =
572         levenshtein(unkopt, unkoptlen, options[i].name, optnamelen, 0, 2, 1, 3);
573     cands.emplace_back(sim, options[i].name);
574   }
575   if (prefix_match == 1 || cands.empty()) {
576     return;
577   }
578   std::sort(std::begin(cands), std::end(cands));
579   int threshold = cands[0].first;
580   // threshold value is a magic value.
581   if (threshold > 6) {
582     return;
583   }
584   std::cerr << "\nDid you mean:\n";
585   for (auto &item : cands) {
586     if (item.first > threshold) {
587       break;
588     }
589     std::cerr << "\t--" << item.second << "\n";
590   }
591 }
592 
has_uri_field(const http_parser_url & u,http_parser_url_fields field)593 bool has_uri_field(const http_parser_url &u, http_parser_url_fields field) {
594   return u.field_set & (1 << field);
595 }
596 
fieldeq(const char * uri1,const http_parser_url & u1,const char * uri2,const http_parser_url & u2,http_parser_url_fields field)597 bool fieldeq(const char *uri1, const http_parser_url &u1, const char *uri2,
598              const http_parser_url &u2, http_parser_url_fields field) {
599   if (!has_uri_field(u1, field)) {
600     if (!has_uri_field(u2, field)) {
601       return true;
602     } else {
603       return false;
604     }
605   } else if (!has_uri_field(u2, field)) {
606     return false;
607   }
608   if (u1.field_data[field].len != u2.field_data[field].len) {
609     return false;
610   }
611   return memcmp(uri1 + u1.field_data[field].off,
612                 uri2 + u2.field_data[field].off, u1.field_data[field].len) == 0;
613 }
614 
fieldeq(const char * uri,const http_parser_url & u,http_parser_url_fields field,const char * t)615 bool fieldeq(const char *uri, const http_parser_url &u,
616              http_parser_url_fields field, const char *t) {
617   return fieldeq(uri, u, field, StringRef{t});
618 }
619 
fieldeq(const char * uri,const http_parser_url & u,http_parser_url_fields field,const StringRef & t)620 bool fieldeq(const char *uri, const http_parser_url &u,
621              http_parser_url_fields field, const StringRef &t) {
622   if (!has_uri_field(u, field)) {
623     return t.empty();
624   }
625   auto &f = u.field_data[field];
626   return StringRef{uri + f.off, f.len} == t;
627 }
628 
get_uri_field(const char * uri,const http_parser_url & u,http_parser_url_fields field)629 StringRef get_uri_field(const char *uri, const http_parser_url &u,
630                         http_parser_url_fields field) {
631   if (!util::has_uri_field(u, field)) {
632     return StringRef{};
633   }
634 
635   return StringRef{uri + u.field_data[field].off, u.field_data[field].len};
636 }
637 
get_default_port(const char * uri,const http_parser_url & u)638 uint16_t get_default_port(const char *uri, const http_parser_url &u) {
639   if (util::fieldeq(uri, u, UF_SCHEMA, "https")) {
640     return 443;
641   } else if (util::fieldeq(uri, u, UF_SCHEMA, "http")) {
642     return 80;
643   } else {
644     return 443;
645   }
646 }
647 
porteq(const char * uri1,const http_parser_url & u1,const char * uri2,const http_parser_url & u2)648 bool porteq(const char *uri1, const http_parser_url &u1, const char *uri2,
649             const http_parser_url &u2) {
650   uint16_t port1, port2;
651   port1 =
652       util::has_uri_field(u1, UF_PORT) ? u1.port : get_default_port(uri1, u1);
653   port2 =
654       util::has_uri_field(u2, UF_PORT) ? u2.port : get_default_port(uri2, u2);
655   return port1 == port2;
656 }
657 
write_uri_field(std::ostream & o,const char * uri,const http_parser_url & u,http_parser_url_fields field)658 void write_uri_field(std::ostream &o, const char *uri, const http_parser_url &u,
659                      http_parser_url_fields field) {
660   if (util::has_uri_field(u, field)) {
661     o.write(uri + u.field_data[field].off, u.field_data[field].len);
662   }
663 }
664 
numeric_host(const char * hostname)665 bool numeric_host(const char *hostname) {
666   return numeric_host(hostname, AF_INET) || numeric_host(hostname, AF_INET6);
667 }
668 
numeric_host(const char * hostname,int family)669 bool numeric_host(const char *hostname, int family) {
670   int rv;
671   std::array<uint8_t, sizeof(struct in6_addr)> dst;
672 
673   rv = nghttp2_inet_pton(family, hostname, dst.data());
674 
675   return rv == 1;
676 }
677 
numeric_name(const struct sockaddr * sa,socklen_t salen)678 std::string numeric_name(const struct sockaddr *sa, socklen_t salen) {
679   std::array<char, NI_MAXHOST> host;
680   auto rv = getnameinfo(sa, salen, host.data(), host.size(), nullptr, 0,
681                         NI_NUMERICHOST);
682   if (rv != 0) {
683     return "unknown";
684   }
685   return host.data();
686 }
687 
to_numeric_addr(const Address * addr)688 std::string to_numeric_addr(const Address *addr) {
689   auto family = addr->su.storage.ss_family;
690 #ifndef _WIN32
691   if (family == AF_UNIX) {
692     return addr->su.un.sun_path;
693   }
694 #endif // !_WIN32
695 
696   std::array<char, NI_MAXHOST> host;
697   std::array<char, NI_MAXSERV> serv;
698   auto rv =
699       getnameinfo(&addr->su.sa, addr->len, host.data(), host.size(),
700                   serv.data(), serv.size(), NI_NUMERICHOST | NI_NUMERICSERV);
701   if (rv != 0) {
702     return "unknown";
703   }
704 
705   auto hostlen = strlen(host.data());
706   auto servlen = strlen(serv.data());
707 
708   std::string s;
709   char *p;
710   if (family == AF_INET6) {
711     s.resize(hostlen + servlen + 2 + 1);
712     p = &s[0];
713     *p++ = '[';
714     p = std::copy_n(host.data(), hostlen, p);
715     *p++ = ']';
716   } else {
717     s.resize(hostlen + servlen + 1);
718     p = &s[0];
719     p = std::copy_n(host.data(), hostlen, p);
720   }
721   *p++ = ':';
722   std::copy_n(serv.data(), servlen, p);
723 
724   return s;
725 }
726 
set_port(Address & addr,uint16_t port)727 void set_port(Address &addr, uint16_t port) {
728   switch (addr.su.storage.ss_family) {
729   case AF_INET:
730     addr.su.in.sin_port = htons(port);
731     break;
732   case AF_INET6:
733     addr.su.in6.sin6_port = htons(port);
734     break;
735   }
736 }
737 
ascii_dump(const uint8_t * data,size_t len)738 std::string ascii_dump(const uint8_t *data, size_t len) {
739   std::string res;
740 
741   for (size_t i = 0; i < len; ++i) {
742     auto c = data[i];
743 
744     if (c >= 0x20 && c < 0x7f) {
745       res += c;
746     } else {
747       res += '.';
748     }
749   }
750 
751   return res;
752 }
753 
get_exec_path(int argc,char ** const argv,const char * cwd)754 char *get_exec_path(int argc, char **const argv, const char *cwd) {
755   if (argc == 0 || cwd == nullptr) {
756     return nullptr;
757   }
758 
759   auto argv0 = argv[0];
760   auto len = strlen(argv0);
761 
762   char *path;
763 
764   if (argv0[0] == '/') {
765     path = static_cast<char *>(malloc(len + 1));
766     if (path == nullptr) {
767       return nullptr;
768     }
769     memcpy(path, argv0, len + 1);
770   } else {
771     auto cwdlen = strlen(cwd);
772     path = static_cast<char *>(malloc(len + 1 + cwdlen + 1));
773     if (path == nullptr) {
774       return nullptr;
775     }
776     memcpy(path, cwd, cwdlen);
777     path[cwdlen] = '/';
778     memcpy(path + cwdlen + 1, argv0, len + 1);
779   }
780 
781   return path;
782 }
783 
check_path(const std::string & path)784 bool check_path(const std::string &path) {
785   // We don't like '\' in path.
786   return !path.empty() && path[0] == '/' &&
787          path.find('\\') == std::string::npos &&
788          path.find("/../") == std::string::npos &&
789          path.find("/./") == std::string::npos &&
790          !util::ends_with_l(path, "/..") && !util::ends_with_l(path, "/.");
791 }
792 
to_time64(const timeval & tv)793 int64_t to_time64(const timeval &tv) {
794   return tv.tv_sec * 1000000 + tv.tv_usec;
795 }
796 
check_h2_is_selected(const StringRef & proto)797 bool check_h2_is_selected(const StringRef &proto) {
798   return streq(NGHTTP2_H2, proto) || streq(NGHTTP2_H2_16, proto) ||
799          streq(NGHTTP2_H2_14, proto);
800 }
801 
802 namespace {
select_proto(const unsigned char ** out,unsigned char * outlen,const unsigned char * in,unsigned int inlen,const StringRef & key)803 bool select_proto(const unsigned char **out, unsigned char *outlen,
804                   const unsigned char *in, unsigned int inlen,
805                   const StringRef &key) {
806   for (auto p = in, end = in + inlen; p + key.size() <= end; p += *p + 1) {
807     if (std::equal(std::begin(key), std::end(key), p)) {
808       *out = p + 1;
809       *outlen = *p;
810       return true;
811     }
812   }
813   return false;
814 }
815 } // namespace
816 
select_h2(const unsigned char ** out,unsigned char * outlen,const unsigned char * in,unsigned int inlen)817 bool select_h2(const unsigned char **out, unsigned char *outlen,
818                const unsigned char *in, unsigned int inlen) {
819   return select_proto(out, outlen, in, inlen, NGHTTP2_H2_ALPN) ||
820          select_proto(out, outlen, in, inlen, NGHTTP2_H2_16_ALPN) ||
821          select_proto(out, outlen, in, inlen, NGHTTP2_H2_14_ALPN);
822 }
823 
select_protocol(const unsigned char ** out,unsigned char * outlen,const unsigned char * in,unsigned int inlen,std::vector<std::string> proto_list)824 bool select_protocol(const unsigned char **out, unsigned char *outlen,
825                      const unsigned char *in, unsigned int inlen,
826                      std::vector<std::string> proto_list) {
827   for (const auto &proto : proto_list) {
828     if (select_proto(out, outlen, in, inlen, StringRef{proto})) {
829       return true;
830     }
831   }
832 
833   return false;
834 }
835 
get_default_alpn()836 std::vector<unsigned char> get_default_alpn() {
837   auto res = std::vector<unsigned char>(NGHTTP2_H2_ALPN.size() +
838                                         NGHTTP2_H2_16_ALPN.size() +
839                                         NGHTTP2_H2_14_ALPN.size());
840   auto p = std::begin(res);
841 
842   p = std::copy_n(std::begin(NGHTTP2_H2_ALPN), NGHTTP2_H2_ALPN.size(), p);
843   p = std::copy_n(std::begin(NGHTTP2_H2_16_ALPN), NGHTTP2_H2_16_ALPN.size(), p);
844   p = std::copy_n(std::begin(NGHTTP2_H2_14_ALPN), NGHTTP2_H2_14_ALPN.size(), p);
845 
846   return res;
847 }
848 
split_str(const StringRef & s,char delim)849 std::vector<StringRef> split_str(const StringRef &s, char delim) {
850   size_t len = 1;
851   auto last = std::end(s);
852   StringRef::const_iterator d;
853   for (auto first = std::begin(s); (d = std::find(first, last, delim)) != last;
854        ++len, first = d + 1)
855     ;
856 
857   auto list = std::vector<StringRef>(len);
858 
859   len = 0;
860   for (auto first = std::begin(s);; ++len) {
861     auto stop = std::find(first, last, delim);
862     list[len] = StringRef{first, stop};
863     if (stop == last) {
864       break;
865     }
866     first = stop + 1;
867   }
868   return list;
869 }
870 
parse_config_str_list(const StringRef & s,char delim)871 std::vector<std::string> parse_config_str_list(const StringRef &s, char delim) {
872   auto sublist = split_str(s, delim);
873   auto res = std::vector<std::string>();
874   res.reserve(sublist.size());
875   for (const auto &s : sublist) {
876     res.emplace_back(std::begin(s), std::end(s));
877   }
878   return res;
879 }
880 
make_socket_closeonexec(int fd)881 int make_socket_closeonexec(int fd) {
882 #ifdef _WIN32
883   (void)fd;
884   return 0;
885 #else  // !_WIN32
886   int flags;
887   int rv;
888   while ((flags = fcntl(fd, F_GETFD)) == -1 && errno == EINTR)
889     ;
890   while ((rv = fcntl(fd, F_SETFD, flags | FD_CLOEXEC)) == -1 && errno == EINTR)
891     ;
892   return rv;
893 #endif // !_WIN32
894 }
895 
make_socket_nonblocking(int fd)896 int make_socket_nonblocking(int fd) {
897   int rv;
898 
899 #ifdef _WIN32
900   u_long mode = 1;
901 
902   rv = ioctlsocket(fd, FIONBIO, &mode);
903 #else  // !_WIN32
904   int flags;
905   while ((flags = fcntl(fd, F_GETFL, 0)) == -1 && errno == EINTR)
906     ;
907   while ((rv = fcntl(fd, F_SETFL, flags | O_NONBLOCK)) == -1 && errno == EINTR)
908     ;
909 #endif // !_WIN32
910 
911   return rv;
912 }
913 
make_socket_nodelay(int fd)914 int make_socket_nodelay(int fd) {
915   int val = 1;
916   if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, reinterpret_cast<char *>(&val),
917                  sizeof(val)) == -1) {
918     return -1;
919   }
920   return 0;
921 }
922 
create_nonblock_socket(int family)923 int create_nonblock_socket(int family) {
924 #ifdef SOCK_NONBLOCK
925   auto fd = socket(family, SOCK_STREAM | SOCK_NONBLOCK | SOCK_CLOEXEC, 0);
926 
927   if (fd == -1) {
928     return -1;
929   }
930 #else  // !SOCK_NONBLOCK
931   auto fd = socket(family, SOCK_STREAM, 0);
932 
933   if (fd == -1) {
934     return -1;
935   }
936 
937   make_socket_nonblocking(fd);
938   make_socket_closeonexec(fd);
939 #endif // !SOCK_NONBLOCK
940 
941   if (family == AF_INET || family == AF_INET6) {
942     make_socket_nodelay(fd);
943   }
944 
945   return fd;
946 }
947 
check_socket_connected(int fd)948 bool check_socket_connected(int fd) {
949   int error;
950   socklen_t len = sizeof(error);
951   if (getsockopt(fd, SOL_SOCKET, SO_ERROR, (char *)&error, &len) != 0) {
952     return false;
953   }
954 
955   return error == 0;
956 }
957 
get_socket_error(int fd)958 int get_socket_error(int fd) {
959   int error;
960   socklen_t len = sizeof(error);
961   if (getsockopt(fd, SOL_SOCKET, SO_ERROR, (char *)&error, &len) != 0) {
962     return -1;
963   }
964 
965   return error;
966 }
967 
ipv6_numeric_addr(const char * host)968 bool ipv6_numeric_addr(const char *host) {
969   uint8_t dst[16];
970   return nghttp2_inet_pton(AF_INET6, host, dst) == 1;
971 }
972 
973 namespace {
parse_uint_digits(const void * ss,size_t len)974 std::pair<int64_t, size_t> parse_uint_digits(const void *ss, size_t len) {
975   const uint8_t *s = static_cast<const uint8_t *>(ss);
976   int64_t n = 0;
977   size_t i;
978   if (len == 0) {
979     return {-1, 0};
980   }
981   constexpr int64_t max = std::numeric_limits<int64_t>::max();
982   for (i = 0; i < len; ++i) {
983     if ('0' <= s[i] && s[i] <= '9') {
984       if (n > max / 10) {
985         return {-1, 0};
986       }
987       n *= 10;
988       if (n > max - (s[i] - '0')) {
989         return {-1, 0};
990       }
991       n += s[i] - '0';
992       continue;
993     }
994     break;
995   }
996   if (i == 0) {
997     return {-1, 0};
998   }
999   return {n, i};
1000 }
1001 } // namespace
1002 
parse_uint_with_unit(const char * s)1003 int64_t parse_uint_with_unit(const char *s) {
1004   return parse_uint_with_unit(reinterpret_cast<const uint8_t *>(s), strlen(s));
1005 }
1006 
parse_uint_with_unit(const StringRef & s)1007 int64_t parse_uint_with_unit(const StringRef &s) {
1008   return parse_uint_with_unit(s.byte(), s.size());
1009 }
1010 
parse_uint_with_unit(const uint8_t * s,size_t len)1011 int64_t parse_uint_with_unit(const uint8_t *s, size_t len) {
1012   int64_t n;
1013   size_t i;
1014   std::tie(n, i) = parse_uint_digits(s, len);
1015   if (n == -1) {
1016     return -1;
1017   }
1018   if (i == len) {
1019     return n;
1020   }
1021   if (i + 1 != len) {
1022     return -1;
1023   }
1024   int mul = 1;
1025   switch (s[i]) {
1026   case 'K':
1027   case 'k':
1028     mul = 1 << 10;
1029     break;
1030   case 'M':
1031   case 'm':
1032     mul = 1 << 20;
1033     break;
1034   case 'G':
1035   case 'g':
1036     mul = 1 << 30;
1037     break;
1038   default:
1039     return -1;
1040   }
1041   constexpr int64_t max = std::numeric_limits<int64_t>::max();
1042   if (n > max / mul) {
1043     return -1;
1044   }
1045   return n * mul;
1046 }
1047 
parse_uint(const char * s)1048 int64_t parse_uint(const char *s) {
1049   return parse_uint(reinterpret_cast<const uint8_t *>(s), strlen(s));
1050 }
1051 
parse_uint(const std::string & s)1052 int64_t parse_uint(const std::string &s) {
1053   return parse_uint(reinterpret_cast<const uint8_t *>(s.c_str()), s.size());
1054 }
1055 
parse_uint(const StringRef & s)1056 int64_t parse_uint(const StringRef &s) {
1057   return parse_uint(s.byte(), s.size());
1058 }
1059 
parse_uint(const uint8_t * s,size_t len)1060 int64_t parse_uint(const uint8_t *s, size_t len) {
1061   int64_t n;
1062   size_t i;
1063   std::tie(n, i) = parse_uint_digits(s, len);
1064   if (n == -1 || i != len) {
1065     return -1;
1066   }
1067   return n;
1068 }
1069 
parse_duration_with_unit(const char * s)1070 double parse_duration_with_unit(const char *s) {
1071   return parse_duration_with_unit(reinterpret_cast<const uint8_t *>(s),
1072                                   strlen(s));
1073 }
1074 
parse_duration_with_unit(const StringRef & s)1075 double parse_duration_with_unit(const StringRef &s) {
1076   return parse_duration_with_unit(s.byte(), s.size());
1077 }
1078 
parse_duration_with_unit(const uint8_t * s,size_t len)1079 double parse_duration_with_unit(const uint8_t *s, size_t len) {
1080   constexpr auto max = std::numeric_limits<int64_t>::max();
1081   int64_t n;
1082   size_t i;
1083 
1084   std::tie(n, i) = parse_uint_digits(s, len);
1085   if (n == -1) {
1086     goto fail;
1087   }
1088   if (i == len) {
1089     return static_cast<double>(n);
1090   }
1091   switch (s[i]) {
1092   case 'S':
1093   case 's':
1094     // seconds
1095     if (i + 1 != len) {
1096       goto fail;
1097     }
1098     return static_cast<double>(n);
1099   case 'M':
1100   case 'm':
1101     if (i + 1 == len) {
1102       // minutes
1103       if (n > max / 60) {
1104         goto fail;
1105       }
1106       return static_cast<double>(n) * 60;
1107     }
1108 
1109     if (i + 2 != len || (s[i + 1] != 's' && s[i + 1] != 'S')) {
1110       goto fail;
1111     }
1112     // milliseconds
1113     return static_cast<double>(n) / 1000.;
1114   case 'H':
1115   case 'h':
1116     // hours
1117     if (i + 1 != len) {
1118       goto fail;
1119     }
1120     if (n > max / 3600) {
1121       goto fail;
1122     }
1123     return static_cast<double>(n) * 3600;
1124   }
1125 fail:
1126   return std::numeric_limits<double>::infinity();
1127 }
1128 
duration_str(double t)1129 std::string duration_str(double t) {
1130   if (t == 0.) {
1131     return "0";
1132   }
1133   auto frac = static_cast<int64_t>(t * 1000) % 1000;
1134   if (frac > 0) {
1135     return utos(static_cast<int64_t>(t * 1000)) + "ms";
1136   }
1137   auto v = static_cast<int64_t>(t);
1138   if (v % 60) {
1139     return utos(v) + "s";
1140   }
1141   v /= 60;
1142   if (v % 60) {
1143     return utos(v) + "m";
1144   }
1145   v /= 60;
1146   return utos(v) + "h";
1147 }
1148 
format_duration(const std::chrono::microseconds & u)1149 std::string format_duration(const std::chrono::microseconds &u) {
1150   const char *unit = "us";
1151   int d = 0;
1152   auto t = u.count();
1153   if (t >= 1000000) {
1154     d = 1000000;
1155     unit = "s";
1156   } else if (t >= 1000) {
1157     d = 1000;
1158     unit = "ms";
1159   } else {
1160     return utos(t) + unit;
1161   }
1162   return dtos(static_cast<double>(t) / d) + unit;
1163 }
1164 
format_duration(double t)1165 std::string format_duration(double t) {
1166   const char *unit = "us";
1167   if (t >= 1.) {
1168     unit = "s";
1169   } else if (t >= 0.001) {
1170     t *= 1000.;
1171     unit = "ms";
1172   } else {
1173     t *= 1000000.;
1174     return utos(static_cast<int64_t>(t)) + unit;
1175   }
1176   return dtos(t) + unit;
1177 }
1178 
dtos(double n)1179 std::string dtos(double n) {
1180   auto m = llround(100. * n);
1181   auto f = utos(m % 100);
1182   return utos(m / 100) + "." + (f.size() == 1 ? "0" : "") + f;
1183 }
1184 
make_http_hostport(BlockAllocator & balloc,const StringRef & host,uint16_t port)1185 StringRef make_http_hostport(BlockAllocator &balloc, const StringRef &host,
1186                              uint16_t port) {
1187   if (port != 80 && port != 443) {
1188     return make_hostport(balloc, host, port);
1189   }
1190 
1191   auto ipv6 = ipv6_numeric_addr(host.c_str());
1192 
1193   auto iov = make_byte_ref(balloc, host.size() + (ipv6 ? 2 : 0) + 1);
1194   auto p = iov.base;
1195 
1196   if (ipv6) {
1197     *p++ = '[';
1198   }
1199 
1200   p = std::copy(std::begin(host), std::end(host), p);
1201 
1202   if (ipv6) {
1203     *p++ = ']';
1204   }
1205 
1206   *p = '\0';
1207 
1208   return StringRef{iov.base, p};
1209 }
1210 
make_hostport(const StringRef & host,uint16_t port)1211 std::string make_hostport(const StringRef &host, uint16_t port) {
1212   auto ipv6 = ipv6_numeric_addr(host.c_str());
1213   auto serv = utos(port);
1214 
1215   std::string hostport;
1216   hostport.resize(host.size() + (ipv6 ? 2 : 0) + 1 + serv.size());
1217 
1218   auto p = &hostport[0];
1219 
1220   if (ipv6) {
1221     *p++ = '[';
1222   }
1223 
1224   p = std::copy_n(host.c_str(), host.size(), p);
1225 
1226   if (ipv6) {
1227     *p++ = ']';
1228   }
1229 
1230   *p++ = ':';
1231   std::copy_n(serv.c_str(), serv.size(), p);
1232 
1233   return hostport;
1234 }
1235 
make_hostport(BlockAllocator & balloc,const StringRef & host,uint16_t port)1236 StringRef make_hostport(BlockAllocator &balloc, const StringRef &host,
1237                         uint16_t port) {
1238   auto ipv6 = ipv6_numeric_addr(host.c_str());
1239   auto serv = utos(port);
1240 
1241   auto iov =
1242       make_byte_ref(balloc, host.size() + (ipv6 ? 2 : 0) + 1 + serv.size());
1243   auto p = iov.base;
1244 
1245   if (ipv6) {
1246     *p++ = '[';
1247   }
1248 
1249   p = std::copy(std::begin(host), std::end(host), p);
1250 
1251   if (ipv6) {
1252     *p++ = ']';
1253   }
1254 
1255   *p++ = ':';
1256 
1257   p = std::copy(std::begin(serv), std::end(serv), p);
1258 
1259   *p = '\0';
1260 
1261   return StringRef{iov.base, p};
1262 }
1263 
1264 namespace {
hexdump8(FILE * out,const uint8_t * first,const uint8_t * last)1265 void hexdump8(FILE *out, const uint8_t *first, const uint8_t *last) {
1266   auto stop = std::min(first + 8, last);
1267   for (auto k = first; k != stop; ++k) {
1268     fprintf(out, "%02x ", *k);
1269   }
1270   // each byte needs 3 spaces (2 hex value and space)
1271   for (; stop != first + 8; ++stop) {
1272     fputs("   ", out);
1273   }
1274   // we have extra space after 8 bytes
1275   fputc(' ', out);
1276 }
1277 } // namespace
1278 
hexdump(FILE * out,const uint8_t * src,size_t len)1279 void hexdump(FILE *out, const uint8_t *src, size_t len) {
1280   if (len == 0) {
1281     return;
1282   }
1283   size_t buflen = 0;
1284   auto repeated = false;
1285   std::array<uint8_t, 16> buf{};
1286   auto end = src + len;
1287   auto i = src;
1288   for (;;) {
1289     auto nextlen =
1290         std::min(static_cast<size_t>(16), static_cast<size_t>(end - i));
1291     if (nextlen == buflen &&
1292         std::equal(std::begin(buf), std::begin(buf) + buflen, i)) {
1293       // as long as adjacent 16 bytes block are the same, we just
1294       // print single '*'.
1295       if (!repeated) {
1296         repeated = true;
1297         fputs("*\n", out);
1298       }
1299       i += nextlen;
1300       continue;
1301     }
1302     repeated = false;
1303     fprintf(out, "%08lx", static_cast<unsigned long>(i - src));
1304     if (i == end) {
1305       fputc('\n', out);
1306       break;
1307     }
1308     fputs("  ", out);
1309     hexdump8(out, i, end);
1310     hexdump8(out, i + 8, std::max(i + 8, end));
1311     fputc('|', out);
1312     auto stop = std::min(i + 16, end);
1313     buflen = stop - i;
1314     auto p = buf.data();
1315     for (; i != stop; ++i) {
1316       *p++ = *i;
1317       if (0x20 <= *i && *i <= 0x7e) {
1318         fputc(*i, out);
1319       } else {
1320         fputc('.', out);
1321       }
1322     }
1323     fputs("|\n", out);
1324   }
1325 }
1326 
put_uint16be(uint8_t * buf,uint16_t n)1327 void put_uint16be(uint8_t *buf, uint16_t n) {
1328   uint16_t x = htons(n);
1329   memcpy(buf, &x, sizeof(uint16_t));
1330 }
1331 
put_uint32be(uint8_t * buf,uint32_t n)1332 void put_uint32be(uint8_t *buf, uint32_t n) {
1333   uint32_t x = htonl(n);
1334   memcpy(buf, &x, sizeof(uint32_t));
1335 }
1336 
get_uint16(const uint8_t * data)1337 uint16_t get_uint16(const uint8_t *data) {
1338   uint16_t n;
1339   memcpy(&n, data, sizeof(uint16_t));
1340   return ntohs(n);
1341 }
1342 
get_uint32(const uint8_t * data)1343 uint32_t get_uint32(const uint8_t *data) {
1344   uint32_t n;
1345   memcpy(&n, data, sizeof(uint32_t));
1346   return ntohl(n);
1347 }
1348 
get_uint64(const uint8_t * data)1349 uint64_t get_uint64(const uint8_t *data) {
1350   uint64_t n = 0;
1351   n += static_cast<uint64_t>(data[0]) << 56;
1352   n += static_cast<uint64_t>(data[1]) << 48;
1353   n += static_cast<uint64_t>(data[2]) << 40;
1354   n += static_cast<uint64_t>(data[3]) << 32;
1355   n += static_cast<uint64_t>(data[4]) << 24;
1356   n += data[5] << 16;
1357   n += data[6] << 8;
1358   n += data[7];
1359   return n;
1360 }
1361 
read_mime_types(std::map<std::string,std::string> & res,const char * filename)1362 int read_mime_types(std::map<std::string, std::string> &res,
1363                     const char *filename) {
1364   std::ifstream infile(filename);
1365   if (!infile) {
1366     return -1;
1367   }
1368 
1369   auto delim_pred = [](char c) { return c == ' ' || c == '\t'; };
1370 
1371   std::string line;
1372   while (std::getline(infile, line)) {
1373     if (line.empty() || line[0] == '#') {
1374       continue;
1375     }
1376 
1377     auto type_end = std::find_if(std::begin(line), std::end(line), delim_pred);
1378     if (type_end == std::begin(line)) {
1379       continue;
1380     }
1381 
1382     auto ext_end = type_end;
1383     for (;;) {
1384       auto ext_start = std::find_if_not(ext_end, std::end(line), delim_pred);
1385       if (ext_start == std::end(line)) {
1386         break;
1387       }
1388       ext_end = std::find_if(ext_start, std::end(line), delim_pred);
1389 #ifdef HAVE_STD_MAP_EMPLACE
1390       res.emplace(std::string(ext_start, ext_end),
1391                   std::string(std::begin(line), type_end));
1392 #else  // !HAVE_STD_MAP_EMPLACE
1393       res.insert(std::make_pair(std::string(ext_start, ext_end),
1394                                 std::string(std::begin(line), type_end)));
1395 #endif // !HAVE_STD_MAP_EMPLACE
1396     }
1397   }
1398 
1399   return 0;
1400 }
1401 
percent_decode(BlockAllocator & balloc,const StringRef & src)1402 StringRef percent_decode(BlockAllocator &balloc, const StringRef &src) {
1403   auto iov = make_byte_ref(balloc, src.size() * 3 + 1);
1404   auto p = iov.base;
1405   for (auto first = std::begin(src); first != std::end(src); ++first) {
1406     if (*first != '%') {
1407       *p++ = *first;
1408       continue;
1409     }
1410 
1411     if (first + 1 != std::end(src) && first + 2 != std::end(src) &&
1412         is_hex_digit(*(first + 1)) && is_hex_digit(*(first + 2))) {
1413       *p++ = (hex_to_uint(*(first + 1)) << 4) + hex_to_uint(*(first + 2));
1414       first += 2;
1415       continue;
1416     }
1417 
1418     *p++ = *first;
1419   }
1420   *p = '\0';
1421   return StringRef{iov.base, p};
1422 }
1423 
1424 // Returns x**y
int_pow(double x,size_t y)1425 double int_pow(double x, size_t y) {
1426   auto res = 1.;
1427   for (; y; --y) {
1428     res *= x;
1429   }
1430   return res;
1431 }
1432 
hash32(const StringRef & s)1433 uint32_t hash32(const StringRef &s) {
1434   /* 32 bit FNV-1a: http://isthe.com/chongo/tech/comp/fnv/ */
1435   uint32_t h = 2166136261u;
1436   size_t i;
1437 
1438   for (i = 0; i < s.size(); ++i) {
1439     h ^= s[i];
1440     h += (h << 1) + (h << 4) + (h << 7) + (h << 8) + (h << 24);
1441   }
1442 
1443   return h;
1444 }
1445 
1446 #if !OPENSSL_1_1_API
1447 namespace {
EVP_MD_CTX_new(void)1448 EVP_MD_CTX *EVP_MD_CTX_new(void) { return EVP_MD_CTX_create(); }
1449 } // namespace
1450 
1451 namespace {
EVP_MD_CTX_free(EVP_MD_CTX * ctx)1452 void EVP_MD_CTX_free(EVP_MD_CTX *ctx) { EVP_MD_CTX_destroy(ctx); }
1453 } // namespace
1454 #endif // !OPENSSL_1_1_API
1455 
1456 namespace {
message_digest(uint8_t * res,const EVP_MD * meth,const StringRef & s)1457 int message_digest(uint8_t *res, const EVP_MD *meth, const StringRef &s) {
1458   int rv;
1459 
1460   auto ctx = EVP_MD_CTX_new();
1461   if (ctx == nullptr) {
1462     return -1;
1463   }
1464 
1465   auto ctx_deleter = defer(EVP_MD_CTX_free, ctx);
1466 
1467   rv = EVP_DigestInit_ex(ctx, meth, nullptr);
1468   if (rv != 1) {
1469     return -1;
1470   }
1471 
1472   rv = EVP_DigestUpdate(ctx, s.c_str(), s.size());
1473   if (rv != 1) {
1474     return -1;
1475   }
1476 
1477   unsigned int mdlen = EVP_MD_size(meth);
1478 
1479   rv = EVP_DigestFinal_ex(ctx, res, &mdlen);
1480   if (rv != 1) {
1481     return -1;
1482   }
1483 
1484   return 0;
1485 }
1486 } // namespace
1487 
sha256(uint8_t * res,const StringRef & s)1488 int sha256(uint8_t *res, const StringRef &s) {
1489   return message_digest(res, EVP_sha256(), s);
1490 }
1491 
sha1(uint8_t * res,const StringRef & s)1492 int sha1(uint8_t *res, const StringRef &s) {
1493   return message_digest(res, EVP_sha1(), s);
1494 }
1495 
is_hex_string(const StringRef & s)1496 bool is_hex_string(const StringRef &s) {
1497   if (s.size() % 2) {
1498     return false;
1499   }
1500 
1501   for (auto c : s) {
1502     if (!is_hex_digit(c)) {
1503       return false;
1504     }
1505   }
1506 
1507   return true;
1508 }
1509 
decode_hex(BlockAllocator & balloc,const StringRef & s)1510 StringRef decode_hex(BlockAllocator &balloc, const StringRef &s) {
1511   auto iov = make_byte_ref(balloc, s.size() + 1);
1512   auto p = iov.base;
1513   for (auto it = std::begin(s); it != std::end(s); it += 2) {
1514     *p++ = (hex_to_uint(*it) << 4) | hex_to_uint(*(it + 1));
1515   }
1516   *p = '\0';
1517   return StringRef{iov.base, p};
1518 }
1519 
extract_host(const StringRef & hostport)1520 StringRef extract_host(const StringRef &hostport) {
1521   if (hostport[0] == '[') {
1522     // assume this is IPv6 numeric address
1523     auto p = std::find(std::begin(hostport), std::end(hostport), ']');
1524     if (p == std::end(hostport)) {
1525       return StringRef{};
1526     }
1527     if (p + 1 < std::end(hostport) && *(p + 1) != ':') {
1528       return StringRef{};
1529     }
1530     return StringRef{std::begin(hostport), p + 1};
1531   }
1532 
1533   auto p = std::find(std::begin(hostport), std::end(hostport), ':');
1534   if (p == std::begin(hostport)) {
1535     return StringRef{};
1536   }
1537   return StringRef{std::begin(hostport), p};
1538 }
1539 
split_hostport(const StringRef & hostport)1540 std::pair<StringRef, StringRef> split_hostport(const StringRef &hostport) {
1541   if (hostport.empty()) {
1542     return {};
1543   }
1544   if (hostport[0] == '[') {
1545     // assume this is IPv6 numeric address
1546     auto p = std::find(std::begin(hostport), std::end(hostport), ']');
1547     if (p == std::end(hostport)) {
1548       return {};
1549     }
1550     if (p + 1 == std::end(hostport)) {
1551       return {StringRef{std::begin(hostport) + 1, p}, {}};
1552     }
1553     if (*(p + 1) != ':' || p + 2 == std::end(hostport)) {
1554       return {};
1555     }
1556     return {StringRef{std::begin(hostport) + 1, p},
1557             StringRef{p + 2, std::end(hostport)}};
1558   }
1559 
1560   auto p = std::find(std::begin(hostport), std::end(hostport), ':');
1561   if (p == std::begin(hostport)) {
1562     return {};
1563   }
1564   if (p == std::end(hostport)) {
1565     return {StringRef{std::begin(hostport), p}, {}};
1566   }
1567   if (p + 1 == std::end(hostport)) {
1568     return {};
1569   }
1570 
1571   return {StringRef{std::begin(hostport), p},
1572           StringRef{p + 1, std::end(hostport)}};
1573 }
1574 
make_mt19937()1575 std::mt19937 make_mt19937() {
1576   std::random_device rd;
1577   return std::mt19937(rd());
1578 }
1579 
daemonize(int nochdir,int noclose)1580 int daemonize(int nochdir, int noclose) {
1581 #if defined(__APPLE__)
1582   pid_t pid;
1583   pid = fork();
1584   if (pid == -1) {
1585     return -1;
1586   } else if (pid > 0) {
1587     _exit(EXIT_SUCCESS);
1588   }
1589   if (setsid() == -1) {
1590     return -1;
1591   }
1592   pid = fork();
1593   if (pid == -1) {
1594     return -1;
1595   } else if (pid > 0) {
1596     _exit(EXIT_SUCCESS);
1597   }
1598   if (nochdir == 0) {
1599     if (chdir("/") == -1) {
1600       return -1;
1601     }
1602   }
1603   if (noclose == 0) {
1604     if (freopen("/dev/null", "r", stdin) == nullptr) {
1605       return -1;
1606     }
1607     if (freopen("/dev/null", "w", stdout) == nullptr) {
1608       return -1;
1609     }
1610     if (freopen("/dev/null", "w", stderr) == nullptr) {
1611       return -1;
1612     }
1613   }
1614   return 0;
1615 #else  // !defined(__APPLE__)
1616   return daemon(nochdir, noclose);
1617 #endif // !defined(__APPLE__)
1618 }
1619 
1620 } // namespace util
1621 
1622 } // namespace nghttp2
1623