tizen 2.4 release
[external/nghttp2.git] / src / util.cc
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 <time.h>
28 #include <sys/types.h>
29 #include <sys/socket.h>
30 #include <netdb.h>
31 #include <sys/stat.h>
32 #include <fcntl.h>
33 #include <netinet/in.h>
34 #include <netinet/tcp.h>
35 #include <arpa/inet.h>
36
37 #include <cmath>
38 #include <cerrno>
39 #include <cassert>
40 #include <cstdio>
41 #include <cstring>
42 #include <iostream>
43
44 #include <nghttp2/nghttp2.h>
45
46 #include "timegm.h"
47
48 namespace nghttp2 {
49
50 namespace util {
51
52 const char DEFAULT_STRIP_CHARSET[] = "\r\n\t ";
53
54 const char UPPER_XDIGITS[] = "0123456789ABCDEF";
55
56 bool isAlpha(const char c) {
57   return ('A' <= c && c <= 'Z') || ('a' <= c && c <= 'z');
58 }
59
60 bool isDigit(const char c) { return '0' <= c && c <= '9'; }
61
62 bool isHexDigit(const char c) {
63   return isDigit(c) || ('A' <= c && c <= 'F') || ('a' <= c && c <= 'f');
64 }
65
66 bool inRFC3986UnreservedChars(const char c) {
67   static const char unreserved[] = {'-', '.', '_', '~'};
68   return isAlpha(c) || isDigit(c) ||
69          std::find(&unreserved[0], &unreserved[4], c) != &unreserved[4];
70 }
71
72 std::string percentEncode(const unsigned char *target, size_t len) {
73   std::string dest;
74   for (size_t i = 0; i < len; ++i) {
75     unsigned char c = target[i];
76
77     if (inRFC3986UnreservedChars(c)) {
78       dest += c;
79     } else {
80       dest += "%";
81       dest += UPPER_XDIGITS[c >> 4];
82       dest += UPPER_XDIGITS[(c & 0x0f)];
83     }
84   }
85   return dest;
86 }
87
88 std::string percentEncode(const std::string &target) {
89   return percentEncode(reinterpret_cast<const unsigned char *>(target.c_str()),
90                        target.size());
91 }
92
93 bool in_token(char c) {
94   static const char extra[] = {'!', '#', '$', '%', '&', '\'', '*', '+',
95                                '-', '.', '^', '_', '`', '|',  '~'};
96
97   return isAlpha(c) || isDigit(c) ||
98          std::find(&extra[0], &extra[sizeof(extra)], c) !=
99              &extra[sizeof(extra)];
100 }
101
102 bool in_attr_char(char c) {
103   static const char bad[] = {'*', '\'', '%'};
104   return util::in_token(c) &&
105          std::find(std::begin(bad), std::end(bad) - 1, c) == std::end(bad) - 1;
106 }
107
108 std::string percent_encode_token(const std::string &target) {
109   auto len = target.size();
110   std::string dest;
111
112   for (size_t i = 0; i < len; ++i) {
113     unsigned char c = target[i];
114
115     if (c != '%' && in_token(c)) {
116       dest += c;
117     } else {
118       dest += "%";
119       dest += UPPER_XDIGITS[c >> 4];
120       dest += UPPER_XDIGITS[(c & 0x0f)];
121     }
122   }
123   return dest;
124 }
125
126 std::string percentDecode(std::string::const_iterator first,
127                           std::string::const_iterator last) {
128   std::string result;
129   for (; first != last; ++first) {
130     if (*first == '%') {
131       if (first + 1 != last && first + 2 != last && isHexDigit(*(first + 1)) &&
132           isHexDigit(*(first + 2))) {
133         std::string numstr(first + 1, first + 3);
134         result += strtol(numstr.c_str(), 0, 16);
135         first += 2;
136       } else {
137         result += *first;
138       }
139     } else {
140       result += *first;
141     }
142   }
143   return result;
144 }
145
146 std::string quote_string(const std::string &target) {
147   auto cnt = std::count(std::begin(target), std::end(target), '"');
148
149   if (cnt == 0) {
150     return target;
151   }
152
153   std::string res;
154   res.reserve(target.size() + cnt);
155
156   for (auto c : target) {
157     if (c == '"') {
158       res += "\\\"";
159     } else {
160       res += c;
161     }
162   }
163
164   return res;
165 }
166
167 namespace {
168 template <typename Iterator>
169 Iterator cpydig(Iterator d, uint32_t n, size_t len) {
170   auto p = d + len - 1;
171
172   do {
173     *p-- = (n % 10) + '0';
174     n /= 10;
175   } while (p >= d);
176
177   return d + len;
178 }
179 } // namespace
180
181 namespace {
182 const char *MONTH[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun",
183                        "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
184 const char *DAY_OF_WEEK[] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
185 } // namespace
186
187 std::string http_date(time_t t) {
188   struct tm tms;
189   std::string res;
190
191   if (gmtime_r(&t, &tms) == nullptr) {
192     return res;
193   }
194
195   /* Sat, 27 Sep 2014 06:31:15 GMT */
196   res.resize(29);
197
198   auto p = std::begin(res);
199
200   auto s = DAY_OF_WEEK[tms.tm_wday];
201   p = std::copy_n(s, 3, p);
202   *p++ = ',';
203   *p++ = ' ';
204   p = cpydig(p, tms.tm_mday, 2);
205   *p++ = ' ';
206   s = MONTH[tms.tm_mon];
207   p = std::copy_n(s, 3, p);
208   *p++ = ' ';
209   p = cpydig(p, tms.tm_year + 1900, 4);
210   *p++ = ' ';
211   p = cpydig(p, tms.tm_hour, 2);
212   *p++ = ':';
213   p = cpydig(p, tms.tm_min, 2);
214   *p++ = ':';
215   p = cpydig(p, tms.tm_sec, 2);
216   s = " GMT";
217   p = std::copy_n(s, 4, p);
218
219   return res;
220 }
221
222 std::string common_log_date(time_t t) {
223   struct tm tms;
224
225   if (localtime_r(&t, &tms) == nullptr) {
226     return "";
227   }
228
229 #ifdef HAVE_STRUCT_TM_TM_GMTOFF
230   // Format data like this:
231   // 03/Jul/2014:00:19:38 +0900
232   std::string res;
233   res.resize(26);
234
235   auto p = std::begin(res);
236
237   p = cpydig(p, tms.tm_mday, 2);
238   *p++ = '/';
239   auto s = MONTH[tms.tm_mon];
240   p = std::copy_n(s, 3, p);
241   *p++ = '/';
242   p = cpydig(p, tms.tm_year + 1900, 4);
243   *p++ = ':';
244   p = cpydig(p, tms.tm_hour, 2);
245   *p++ = ':';
246   p = cpydig(p, tms.tm_min, 2);
247   *p++ = ':';
248   p = cpydig(p, tms.tm_sec, 2);
249   *p++ = ' ';
250
251   auto gmtoff = tms.tm_gmtoff;
252   if (gmtoff >= 0) {
253     *p++ = '+';
254   } else {
255     *p++ = '-';
256     gmtoff = -gmtoff;
257   }
258
259   p = cpydig(p, gmtoff / 3600, 2);
260   p = cpydig(p, (gmtoff % 3600) / 60, 2);
261
262   return res;
263 #else  // !HAVE_STRUCT_TM_TM_GMTOFF
264   char buf[32];
265
266   strftime(buf, sizeof(buf), "%d/%b/%Y:%T %z", &tms);
267
268   return buf;
269 #endif // !HAVE_STRUCT_TM_TM_GMTOFF
270 }
271
272 std::string iso8601_date(int64_t ms) {
273   time_t sec = ms / 1000;
274
275   tm tms;
276   if (localtime_r(&sec, &tms) == nullptr) {
277     return "";
278   }
279
280 #ifdef HAVE_STRUCT_TM_TM_GMTOFF
281   // Format data like this:
282   // 2014-11-15T12:58:24.741Z
283   // 2014-11-15T12:58:24.741+09:00
284   std::string res;
285   res.resize(29);
286
287   auto p = std::begin(res);
288
289   p = cpydig(p, tms.tm_year + 1900, 4);
290   *p++ = '-';
291   p = cpydig(p, tms.tm_mon + 1, 2);
292   *p++ = '-';
293   p = cpydig(p, tms.tm_mday, 2);
294   *p++ = 'T';
295   p = cpydig(p, tms.tm_hour, 2);
296   *p++ = ':';
297   p = cpydig(p, tms.tm_min, 2);
298   *p++ = ':';
299   p = cpydig(p, tms.tm_sec, 2);
300   *p++ = '.';
301   p = cpydig(p, ms % 1000, 3);
302
303   auto gmtoff = tms.tm_gmtoff;
304   if (gmtoff == 0) {
305     *p++ = 'Z';
306   } else {
307     if (gmtoff > 0) {
308       *p++ = '+';
309     } else {
310       *p++ = '-';
311       gmtoff = -gmtoff;
312     }
313     p = cpydig(p, gmtoff / 3600, 2);
314     *p++ = ':';
315     p = cpydig(p, (gmtoff % 3600) / 60, 2);
316   }
317
318   res.resize(p - std::begin(res));
319
320   return res;
321 #else  // !HAVE_STRUCT_TM_TM_GMTOFF
322   char buf[128];
323
324   auto nwrite = strftime(buf, sizeof(buf), "%Y-%m-%dT%H:%M:%S", &tms);
325   nwrite += snprintf(&buf[nwrite], sizeof(buf) - nwrite, ".%03d",
326                      static_cast<int>(ms % 1000));
327   auto nzone = strftime(&buf[nwrite], sizeof(buf) - nwrite, "%z", &tms);
328
329   // %z of strftime writes +hhmm or -hhmm not Z, +hh:mm or -hh:mm.  Do
330   // %nothing if nzone is not 5.  we don't know how to cope with this.
331   if (nzone == 5) {
332     if (memcmp(&buf[nwrite], "+0000", 5) == 0) {
333       // 0000 should be Z
334       memcpy(&buf[nwrite], "Z", 2);
335     } else {
336       // Move mm part to right by 1 including terminal \0
337       memmove(&buf[nwrite + 4], &buf[nwrite + 3], 3);
338       // Insert ':' between hh and mm
339       buf[nwrite + 3] = ':';
340     }
341   }
342   return buf;
343 #endif // !HAVE_STRUCT_TM_TM_GMTOFF
344 }
345
346 time_t parse_http_date(const std::string &s) {
347   tm tm;
348   memset(&tm, 0, sizeof(tm));
349   char *r = strptime(s.c_str(), "%a, %d %b %Y %H:%M:%S GMT", &tm);
350   if (r == 0) {
351     return 0;
352   }
353   return timegm(&tm);
354 }
355
356 bool startsWith(const std::string &a, const std::string &b) {
357   return startsWith(a.begin(), a.end(), b.begin(), b.end());
358 }
359
360 bool istartsWith(const std::string &a, const std::string &b) {
361   return istartsWith(a.begin(), a.end(), b.begin(), b.end());
362 }
363
364 namespace {
365 void streq_advance(const char **ap, const char **bp) {
366   for (; **ap && **bp && lowcase(**ap) == lowcase(**bp); ++*ap, ++*bp)
367     ;
368 }
369 } // namespace
370
371 bool istartsWith(const char *a, const char *b) {
372   if (!a || !b) {
373     return false;
374   }
375   streq_advance(&a, &b);
376   return !*b;
377 }
378
379 bool istartsWith(const char *a, size_t n, const char *b) {
380   return istartsWith(a, a + n, b, b + strlen(b));
381 }
382
383 bool endsWith(const std::string &a, const std::string &b) {
384   return endsWith(a.begin(), a.end(), b.begin(), b.end());
385 }
386
387 bool strieq(const std::string &a, const std::string &b) {
388   if (a.size() != b.size()) {
389     return false;
390   }
391   for (size_t i = 0; i < a.size(); ++i) {
392     if (lowcase(a[i]) != lowcase(b[i])) {
393       return false;
394     }
395   }
396   return true;
397 }
398
399 bool strieq(const char *a, const char *b) {
400   if (!a || !b) {
401     return false;
402   }
403   for (; *a && *b && lowcase(*a) == lowcase(*b); ++a, ++b)
404     ;
405   return !*a && !*b;
406 }
407
408 bool strieq(const char *a, const uint8_t *b, size_t bn) {
409   if (!a || !b) {
410     return false;
411   }
412   const uint8_t *blast = b + bn;
413   for (; *a && b != blast && lowcase(*a) == lowcase(*b); ++a, ++b)
414     ;
415   return !*a && b == blast;
416 }
417
418 bool strieq(const char *a, const char *b, size_t bn) {
419   return strieq(a, reinterpret_cast<const uint8_t *>(b), bn);
420 }
421
422 int strcompare(const char *a, const uint8_t *b, size_t bn) {
423   assert(a && b);
424   const uint8_t *blast = b + bn;
425   for (; *a && b != blast; ++a, ++b) {
426     if (*a < *b) {
427       return -1;
428     } else if (*a > *b) {
429       return 1;
430     }
431   }
432   if (!*a && b == blast) {
433     return 0;
434   } else if (b == blast) {
435     return 1;
436   } else {
437     return -1;
438   }
439 }
440
441 bool strifind(const char *a, const char *b) {
442   if (!a || !b) {
443     return false;
444   }
445   for (size_t i = 0; a[i]; ++i) {
446     const char *ap = &a[i], *bp = b;
447     for (; *ap && *bp && lowcase(*ap) == lowcase(*bp); ++ap, ++bp)
448       ;
449     if (!*bp) {
450       return true;
451     }
452   }
453   return false;
454 }
455
456 char upcase(char c) {
457   if ('a' <= c && c <= 'z') {
458     return c - 'a' + 'A';
459   } else {
460     return c;
461   }
462 }
463
464 namespace {
465 const char LOWER_XDIGITS[] = "0123456789abcdef";
466 } // namespace
467
468 std::string format_hex(const unsigned char *s, size_t len) {
469   std::string res;
470   res.resize(len * 2);
471
472   for (size_t i = 0; i < len; ++i) {
473     unsigned char c = s[i];
474
475     res[i * 2] = LOWER_XDIGITS[c >> 4];
476     res[i * 2 + 1] = LOWER_XDIGITS[c & 0x0f];
477   }
478   return res;
479 }
480
481 void to_token68(std::string &base64str) {
482   for (auto i = std::begin(base64str); i != std::end(base64str); ++i) {
483     switch (*i) {
484     case '+':
485       *i = '-';
486       break;
487     case '/':
488       *i = '_';
489       break;
490     case '=':
491       base64str.erase(i, std::end(base64str));
492       return;
493     }
494   }
495   return;
496 }
497
498 void to_base64(std::string &token68str) {
499   for (auto i = std::begin(token68str); i != std::end(token68str); ++i) {
500     switch (*i) {
501     case '-':
502       *i = '+';
503       break;
504     case '_':
505       *i = '/';
506       break;
507     }
508   }
509   if (token68str.size() & 0x3) {
510     token68str.append(4 - (token68str.size() & 0x3), '=');
511   }
512   return;
513 }
514
515 void inp_strlower(std::string &s) {
516   for (auto i = std::begin(s); i != std::end(s); ++i) {
517     if ('A' <= *i && *i <= 'Z') {
518       *i = (*i) - 'A' + 'a';
519     }
520   }
521 }
522
523 namespace {
524 // Calculates Damerau–Levenshtein distance between c-string a and b
525 // with given costs.  swapcost, subcost, addcost and delcost are cost
526 // to swap 2 adjacent characters, substitute characters, add character
527 // and delete character respectively.
528 int levenshtein(const char *a, int alen, const char *b, int blen, int swapcost,
529                 int subcost, int addcost, int delcost) {
530   auto dp = std::vector<std::vector<int>>(3, std::vector<int>(blen + 1));
531   for (int i = 0; i <= blen; ++i) {
532     dp[1][i] = i;
533   }
534   for (int i = 1; i <= alen; ++i) {
535     dp[0][0] = i;
536     for (int j = 1; j <= blen; ++j) {
537       dp[0][j] = dp[1][j - 1] + (a[i - 1] == b[j - 1] ? 0 : subcost);
538       if (i >= 2 && j >= 2 && a[i - 1] != b[j - 1] && a[i - 2] == b[j - 1] &&
539           a[i - 1] == b[j - 2]) {
540         dp[0][j] = std::min(dp[0][j], dp[2][j - 2] + swapcost);
541       }
542       dp[0][j] = std::min(dp[0][j],
543                           std::min(dp[1][j] + delcost, dp[0][j - 1] + addcost));
544     }
545     std::rotate(std::begin(dp), std::begin(dp) + 2, std::end(dp));
546   }
547   return dp[1][blen];
548 }
549 } // namespace
550
551 void show_candidates(const char *unkopt, option *options) {
552   for (; *unkopt == '-'; ++unkopt)
553     ;
554   if (*unkopt == '\0') {
555     return;
556   }
557   auto unkoptend = unkopt;
558   for (; *unkoptend && *unkoptend != '='; ++unkoptend)
559     ;
560   auto unkoptlen = unkoptend - unkopt;
561   if (unkoptlen == 0) {
562     return;
563   }
564   int prefix_match = 0;
565   auto cands = std::vector<std::pair<int, const char *>>();
566   for (size_t i = 0; options[i].name != nullptr; ++i) {
567     auto optnamelen = strlen(options[i].name);
568     // Use cost 0 for prefix match
569     if (istartsWith(options[i].name, options[i].name + optnamelen, unkopt,
570                     unkopt + unkoptlen)) {
571       if (optnamelen == static_cast<size_t>(unkoptlen)) {
572         // Exact match, then we don't show any condidates.
573         return;
574       }
575       ++prefix_match;
576       cands.emplace_back(0, options[i].name);
577       continue;
578     }
579     // Use cost 0 for suffix match, but match at least 3 characters
580     if (unkoptlen >= 3 &&
581         iendsWith(options[i].name, options[i].name + optnamelen, unkopt,
582                   unkopt + unkoptlen)) {
583       cands.emplace_back(0, options[i].name);
584       continue;
585     }
586     // cost values are borrowed from git, help.c.
587     int sim =
588         levenshtein(unkopt, unkoptlen, options[i].name, optnamelen, 0, 2, 1, 3);
589     cands.emplace_back(sim, options[i].name);
590   }
591   if (prefix_match == 1 || cands.empty()) {
592     return;
593   }
594   std::sort(std::begin(cands), std::end(cands));
595   int threshold = cands[0].first;
596   // threshold value is a magic value.
597   if (threshold > 6) {
598     return;
599   }
600   std::cerr << "\nDid you mean:\n";
601   for (auto &item : cands) {
602     if (item.first > threshold) {
603       break;
604     }
605     std::cerr << "\t--" << item.second << "\n";
606   }
607 }
608
609 bool has_uri_field(const http_parser_url &u, http_parser_url_fields field) {
610   return u.field_set & (1 << field);
611 }
612
613 bool fieldeq(const char *uri1, const http_parser_url &u1, const char *uri2,
614              const http_parser_url &u2, http_parser_url_fields field) {
615   if (!has_uri_field(u1, field)) {
616     if (!has_uri_field(u2, field)) {
617       return true;
618     } else {
619       return false;
620     }
621   } else if (!has_uri_field(u2, field)) {
622     return false;
623   }
624   if (u1.field_data[field].len != u2.field_data[field].len) {
625     return false;
626   }
627   return memcmp(uri1 + u1.field_data[field].off,
628                 uri2 + u2.field_data[field].off, u1.field_data[field].len) == 0;
629 }
630
631 bool fieldeq(const char *uri, const http_parser_url &u,
632              http_parser_url_fields field, const char *t) {
633   if (!has_uri_field(u, field)) {
634     if (!t[0]) {
635       return true;
636     } else {
637       return false;
638     }
639   } else if (!t[0]) {
640     return false;
641   }
642   int i, len = u.field_data[field].len;
643   const char *p = uri + u.field_data[field].off;
644   for (i = 0; i < len && t[i] && p[i] == t[i]; ++i)
645     ;
646   return i == len && !t[i];
647 }
648
649 std::string get_uri_field(const char *uri, const http_parser_url &u,
650                           http_parser_url_fields field) {
651   if (util::has_uri_field(u, field)) {
652     return std::string(uri + u.field_data[field].off, u.field_data[field].len);
653   } else {
654     return "";
655   }
656 }
657
658 uint16_t get_default_port(const char *uri, const http_parser_url &u) {
659   if (util::fieldeq(uri, u, UF_SCHEMA, "https")) {
660     return 443;
661   } else if (util::fieldeq(uri, u, UF_SCHEMA, "http")) {
662     return 80;
663   } else {
664     return 443;
665   }
666 }
667
668 bool porteq(const char *uri1, const http_parser_url &u1, const char *uri2,
669             const http_parser_url &u2) {
670   uint16_t port1, port2;
671   port1 =
672       util::has_uri_field(u1, UF_PORT) ? u1.port : get_default_port(uri1, u1);
673   port2 =
674       util::has_uri_field(u2, UF_PORT) ? u2.port : get_default_port(uri2, u2);
675   return port1 == port2;
676 }
677
678 void write_uri_field(std::ostream &o, const char *uri, const http_parser_url &u,
679                      http_parser_url_fields field) {
680   if (util::has_uri_field(u, field)) {
681     o.write(uri + u.field_data[field].off, u.field_data[field].len);
682   }
683 }
684
685 bool numeric_host(const char *hostname) {
686   struct addrinfo hints;
687   struct addrinfo *res;
688   memset(&hints, 0, sizeof(hints));
689   hints.ai_family = AF_UNSPEC;
690   hints.ai_flags = AI_NUMERICHOST;
691   if (getaddrinfo(hostname, nullptr, &hints, &res)) {
692     return false;
693   }
694   freeaddrinfo(res);
695   return true;
696 }
697
698 int reopen_log_file(const char *path) {
699 #if defined(__ANDROID__) || defined(ANDROID)
700   int fd;
701
702   if (strcmp("/proc/self/fd/1", path) == 0 ||
703       strcmp("/proc/self/fd/2", path) == 0) {
704
705     // We will get permission denied error when O_APPEND is used for
706     // these paths.
707     fd =
708         open(path, O_WRONLY | O_CREAT | O_CLOEXEC, S_IRUSR | S_IWUSR | S_IRGRP);
709   } else {
710     fd = open(path, O_WRONLY | O_APPEND | O_CREAT | O_CLOEXEC,
711               S_IRUSR | S_IWUSR | S_IRGRP);
712   }
713 #elif defined O_CLOEXEC
714
715   auto fd = open(path, O_WRONLY | O_APPEND | O_CREAT | O_CLOEXEC,
716                  S_IRUSR | S_IWUSR | S_IRGRP);
717 #else // !O_CLOEXEC
718
719   auto fd =
720       open(path, O_WRONLY | O_APPEND | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP);
721
722   // We get race condition if execve is called at the same time.
723   if (fd != -1) {
724     make_socket_closeonexec(fd);
725   }
726
727 #endif // !O_CLOEXEC
728
729   if (fd == -1) {
730     return -1;
731   }
732
733   return fd;
734 }
735
736 std::string ascii_dump(const uint8_t *data, size_t len) {
737   std::string res;
738
739   for (size_t i = 0; i < len; ++i) {
740     auto c = data[i];
741
742     if (c >= 0x20 && c < 0x7f) {
743       res += c;
744     } else {
745       res += ".";
746     }
747   }
748
749   return res;
750 }
751
752 char *get_exec_path(int argc, char **const argv, const char *cwd) {
753   if (argc == 0 || cwd == nullptr) {
754     return nullptr;
755   }
756
757   auto argv0 = argv[0];
758   auto len = strlen(argv0);
759
760   char *path;
761
762   if (argv0[0] == '/') {
763     path = static_cast<char *>(malloc(len + 1));
764     memcpy(path, argv0, len + 1);
765   } else {
766     auto cwdlen = strlen(cwd);
767     path = static_cast<char *>(malloc(len + 1 + cwdlen + 1));
768     memcpy(path, cwd, cwdlen);
769     path[cwdlen] = '/';
770     memcpy(path + cwdlen + 1, argv0, len + 1);
771   }
772
773   return path;
774 }
775
776 bool check_path(const std::string &path) {
777   // We don't like '\' in path.
778   return !path.empty() && path[0] == '/' &&
779          path.find('\\') == std::string::npos &&
780          path.find("/../") == std::string::npos &&
781          path.find("/./") == std::string::npos &&
782          !util::endsWith(path, "/..") && !util::endsWith(path, "/.");
783 }
784
785 int64_t to_time64(const timeval &tv) {
786   return tv.tv_sec * 1000000 + tv.tv_usec;
787 }
788
789 bool check_h2_is_selected(const unsigned char *proto, size_t len) {
790   return streq(NGHTTP2_PROTO_VERSION_ID, NGHTTP2_PROTO_VERSION_ID_LEN, proto,
791                len) ||
792          streq(NGHTTP2_H2_16_ID, NGHTTP2_H2_16_ID_LEN, proto, len);
793 }
794
795 namespace {
796 bool select_h2(const unsigned char **out, unsigned char *outlen,
797                const unsigned char *in, unsigned int inlen, const char *key,
798                unsigned int keylen) {
799   for (auto p = in, end = in + inlen; p + keylen <= end; p += *p + 1) {
800     if (memcmp(key, p, keylen) == 0) {
801       *out = p + 1;
802       *outlen = *p;
803       return true;
804     }
805   }
806   return false;
807 }
808 } // namespace
809
810 bool select_h2(const unsigned char **out, unsigned char *outlen,
811                const unsigned char *in, unsigned int inlen) {
812   return select_h2(out, outlen, in, inlen, NGHTTP2_H2_16_ALPN,
813                    NGHTTP2_H2_16_ALPN_LEN) ||
814          select_h2(out, outlen, in, inlen, NGHTTP2_PROTO_ALPN,
815                    NGHTTP2_PROTO_ALPN_LEN);
816 }
817
818 std::vector<unsigned char> get_default_alpn() {
819   auto res = std::vector<unsigned char>(NGHTTP2_PROTO_ALPN_LEN +
820                                         NGHTTP2_H2_16_ALPN_LEN);
821   auto p = std::begin(res);
822
823   p = std::copy_n(NGHTTP2_H2_16_ALPN, NGHTTP2_H2_16_ALPN_LEN, p);
824   p = std::copy_n(NGHTTP2_PROTO_ALPN, NGHTTP2_PROTO_ALPN_LEN, p);
825
826   return res;
827 }
828
829 int make_socket_closeonexec(int fd) {
830   int flags;
831   int rv;
832   while ((flags = fcntl(fd, F_GETFD)) == -1 && errno == EINTR)
833     ;
834   while ((rv = fcntl(fd, F_SETFD, flags | FD_CLOEXEC)) == -1 && errno == EINTR)
835     ;
836   return rv;
837 }
838
839 int make_socket_nonblocking(int fd) {
840   int flags;
841   int rv;
842   while ((flags = fcntl(fd, F_GETFL, 0)) == -1 && errno == EINTR)
843     ;
844   while ((rv = fcntl(fd, F_SETFL, flags | O_NONBLOCK)) == -1 && errno == EINTR)
845     ;
846   return rv;
847 }
848
849 int make_socket_nodelay(int fd) {
850   int val = 1;
851   if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, reinterpret_cast<char *>(&val),
852                  sizeof(val)) == -1) {
853     return -1;
854   }
855   return 0;
856 }
857
858 int create_nonblock_socket(int family) {
859 #ifdef SOCK_NONBLOCK
860   auto fd = socket(family, SOCK_STREAM | SOCK_NONBLOCK | SOCK_CLOEXEC, 0);
861
862   if (fd == -1) {
863     return -1;
864   }
865 #else  // !SOCK_NONBLOCK
866   auto fd = socket(family, SOCK_STREAM, 0);
867
868   if (fd == -1) {
869     return -1;
870   }
871
872   make_socket_nonblocking(fd);
873   make_socket_closeonexec(fd);
874 #endif // !SOCK_NONBLOCK
875
876   make_socket_nodelay(fd);
877
878   return fd;
879 }
880
881 bool check_socket_connected(int fd) {
882   int error;
883   socklen_t len = sizeof(error);
884   if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &error, &len) == 0) {
885     if (error != 0) {
886       return false;
887     }
888   }
889   return true;
890 }
891
892 bool ipv6_numeric_addr(const char *host) {
893   uint8_t dst[16];
894   return inet_pton(AF_INET6, host, dst) == 1;
895 }
896
897 namespace {
898 std::pair<int64_t, size_t> parse_uint_digits(const void *ss, size_t len) {
899   const uint8_t *s = static_cast<const uint8_t *>(ss);
900   int64_t n = 0;
901   size_t i;
902   if (len == 0) {
903     return {-1, 0};
904   }
905   constexpr int64_t max = std::numeric_limits<int64_t>::max();
906   for (i = 0; i < len; ++i) {
907     if ('0' <= s[i] && s[i] <= '9') {
908       if (n > max / 10) {
909         return {-1, 0};
910       }
911       n *= 10;
912       if (n > max - (s[i] - '0')) {
913         return {-1, 0};
914       }
915       n += s[i] - '0';
916       continue;
917     }
918     break;
919   }
920   if (i == 0) {
921     return {-1, 0};
922   }
923   return {n, i};
924 }
925 } // namespace
926
927 int64_t parse_uint_with_unit(const char *s) {
928   int64_t n;
929   size_t i;
930   auto len = strlen(s);
931   std::tie(n, i) = parse_uint_digits(s, len);
932   if (n == -1) {
933     return -1;
934   }
935   if (i == len) {
936     return n;
937   }
938   if (i + 1 != len) {
939     return -1;
940   }
941   int mul = 1;
942   switch (s[i]) {
943   case 'K':
944   case 'k':
945     mul = 1 << 10;
946     break;
947   case 'M':
948   case 'm':
949     mul = 1 << 20;
950     break;
951   case 'G':
952   case 'g':
953     mul = 1 << 30;
954     break;
955   default:
956     return -1;
957   }
958   constexpr int64_t max = std::numeric_limits<int64_t>::max();
959   if (n > max / mul) {
960     return -1;
961   }
962   return n * mul;
963 }
964
965 int64_t parse_uint(const char *s) {
966   return parse_uint(reinterpret_cast<const uint8_t *>(s), strlen(s));
967 }
968
969 int64_t parse_uint(const std::string &s) {
970   return parse_uint(reinterpret_cast<const uint8_t *>(s.c_str()), s.size());
971 }
972
973 int64_t parse_uint(const uint8_t *s, size_t len) {
974   int64_t n;
975   size_t i;
976   std::tie(n, i) = parse_uint_digits(s, len);
977   if (n == -1 || i != len) {
978     return -1;
979   }
980   return n;
981 }
982
983 double parse_duration_with_unit(const char *s) {
984   int64_t n;
985   size_t i;
986   auto len = strlen(s);
987   std::tie(n, i) = parse_uint_digits(s, len);
988   if (n == -1) {
989     goto fail;
990   }
991   if (i == len) {
992     return static_cast<double>(n);
993   }
994   switch (s[i]) {
995   case 'S':
996   case 's':
997     if (i + 1 != len) {
998       goto fail;
999     }
1000     return static_cast<double>(n);
1001     break;
1002   case 'M':
1003   case 'm':
1004     if (i + 2 != len || (s[i + 1] != 's' && s[i + 1] != 'S')) {
1005       goto fail;
1006     }
1007     return static_cast<double>(n) / 1000.;
1008   }
1009 fail:
1010   return std::numeric_limits<double>::infinity();
1011 }
1012
1013 std::string duration_str(double t) {
1014   if (t == 0.) {
1015     return "0";
1016   }
1017   auto frac = static_cast<int64_t>(t * 1000) % 1000;
1018   if (frac > 0) {
1019     return utos(static_cast<int64_t>(t * 1000)) + "ms";
1020   }
1021   return utos(static_cast<int64_t>(t)) + "s";
1022 }
1023
1024 std::string format_duration(const std::chrono::microseconds &u) {
1025   const char *unit = "us";
1026   int d = 0;
1027   auto t = u.count();
1028   if (t >= 1000000) {
1029     d = 1000000;
1030     unit = "s";
1031   } else if (t >= 1000) {
1032     d = 1000;
1033     unit = "ms";
1034   } else {
1035     return utos(t) + unit;
1036   }
1037   return dtos(static_cast<double>(t) / d) + unit;
1038 }
1039
1040 std::string dtos(double n) {
1041   auto f = utos(static_cast<int64_t>(round(100. * n)) % 100);
1042   return utos(static_cast<int64_t>(n)) + "." + (f.size() == 1 ? "0" : "") + f;
1043 }
1044
1045 } // namespace util
1046
1047 } // namespace nghttp2