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