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