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