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