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