2 * nghttp2 - HTTP/2 C Library
4 * Copyright (c) 2012 Tatsuhiro Tsujikawa
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:
14 * The above copyright notice and this permission notice shall be
15 * included in all copies or substantial portions of the Software.
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.
30 #include <sys/types.h>
31 #ifdef HAVE_SYS_SOCKET_H
32 # include <sys/socket.h>
33 #endif // HAVE_SYS_SOCKET_H
36 #endif // HAVE_NETDB_H
40 #endif // HAVE_FCNTL_H
41 #ifdef HAVE_NETINET_IN_H
42 # include <netinet/in.h>
43 #endif // HAVE_NETINET_IN_H
45 # include <ws2tcpip.h>
46 # include <boost/date_time/posix_time/posix_time.hpp>
48 # include <netinet/tcp.h>
50 #ifdef HAVE_ARPA_INET_H
51 # include <arpa/inet.h>
52 #endif // HAVE_ARPA_INET_H
62 #include <openssl/evp.h>
64 #include <nghttp2/nghttp2.h>
66 #include "ssl_compat.h"
75 int nghttp2_inet_pton(int af, const char *src, void *dst) {
76 return inet_pton(af, src, dst);
81 // inet_pton-wrapper for Windows
82 int nghttp2_inet_pton(int af, const char *src, void *dst) {
83 # if _WIN32_WINNT >= 0x0600
84 return InetPtonA(af, src, dst);
86 // the function takes a 'char*', so we need to make a copy
87 char addr[INET6_ADDRSTRLEN + 1];
88 strncpy(addr, src, sizeof(addr));
89 addr[sizeof(addr) - 1] = 0;
91 int size = sizeof(struct in6_addr);
93 if (WSAStringToAddress(addr, af, NULL, (LPSOCKADDR)dst, &size) == 0)
101 const char UPPER_XDIGITS[] = "0123456789ABCDEF";
103 bool in_rfc3986_unreserved_chars(const char c) {
104 static constexpr char unreserved[] = {'-', '.', '_', '~'};
105 return is_alpha(c) || is_digit(c) ||
106 std::find(std::begin(unreserved), std::end(unreserved), c) !=
107 std::end(unreserved);
110 bool in_rfc3986_sub_delims(const char c) {
111 static constexpr char sub_delims[] = {'!', '$', '&', '\'', '(', ')',
112 '*', '+', ',', ';', '='};
113 return std::find(std::begin(sub_delims), std::end(sub_delims), c) !=
114 std::end(sub_delims);
117 std::string percent_encode(const unsigned char *target, size_t len) {
119 for (size_t i = 0; i < len; ++i) {
120 unsigned char c = target[i];
122 if (in_rfc3986_unreserved_chars(c)) {
126 dest += UPPER_XDIGITS[c >> 4];
127 dest += UPPER_XDIGITS[(c & 0x0f)];
133 std::string percent_encode(const std::string &target) {
134 return percent_encode(reinterpret_cast<const unsigned char *>(target.c_str()),
138 std::string percent_encode_path(const std::string &s) {
141 if (in_rfc3986_unreserved_chars(c) || in_rfc3986_sub_delims(c) ||
148 dest += UPPER_XDIGITS[(c >> 4) & 0x0f];
149 dest += UPPER_XDIGITS[(c & 0x0f)];
154 bool in_token(char c) {
155 static constexpr char extra[] = {'!', '#', '$', '%', '&', '\'', '*', '+',
156 '-', '.', '^', '_', '`', '|', '~'};
157 return is_alpha(c) || is_digit(c) ||
158 std::find(std::begin(extra), std::end(extra), c) != std::end(extra);
161 bool in_attr_char(char c) {
162 static constexpr char bad[] = {'*', '\'', '%'};
163 return util::in_token(c) &&
164 std::find(std::begin(bad), std::end(bad), c) == std::end(bad);
167 StringRef percent_encode_token(BlockAllocator &balloc,
168 const StringRef &target) {
169 auto iov = make_byte_ref(balloc, target.size() * 3 + 1);
170 auto p = percent_encode_token(iov.base, target);
174 return StringRef{iov.base, p};
177 size_t percent_encode_tokenlen(const StringRef &target) {
180 for (auto first = std::begin(target); first != std::end(target); ++first) {
183 if (c != '%' && in_token(c)) {
188 // percent-encoded character '%ff'
195 uint32_t hex_to_uint(char c) {
208 StringRef quote_string(BlockAllocator &balloc, const StringRef &target) {
209 auto cnt = std::count(std::begin(target), std::end(target), '"');
212 return make_string_ref(balloc, target);
215 auto iov = make_byte_ref(balloc, target.size() + cnt + 1);
216 auto p = quote_string(iov.base, target);
220 return StringRef{iov.base, p};
223 size_t quote_stringlen(const StringRef &target) {
226 for (auto c : target) {
238 template <typename Iterator>
239 Iterator cpydig(Iterator d, uint32_t n, size_t len) {
240 auto p = d + len - 1;
243 *p-- = (n % 10) + '0';
252 constexpr const char *MONTH[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun",
253 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
254 constexpr const char *DAY_OF_WEEK[] = {"Sun", "Mon", "Tue", "Wed",
255 "Thu", "Fri", "Sat"};
258 std::string http_date(time_t t) {
259 /* Sat, 27 Sep 2014 06:31:15 GMT */
260 std::string res(29, 0);
261 http_date(&res[0], t);
265 char *http_date(char *res, time_t t) {
268 if (gmtime_r(&t, &tms) == nullptr) {
274 auto s = DAY_OF_WEEK[tms.tm_wday];
275 p = std::copy_n(s, 3, p);
278 p = cpydig(p, tms.tm_mday, 2);
280 s = MONTH[tms.tm_mon];
281 p = std::copy_n(s, 3, p);
283 p = cpydig(p, tms.tm_year + 1900, 4);
285 p = cpydig(p, tms.tm_hour, 2);
287 p = cpydig(p, tms.tm_min, 2);
289 p = cpydig(p, tms.tm_sec, 2);
291 p = std::copy_n(s, 4, p);
296 std::string common_log_date(time_t t) {
297 // 03/Jul/2014:00:19:38 +0900
298 std::string res(26, 0);
299 common_log_date(&res[0], t);
303 char *common_log_date(char *res, time_t t) {
306 if (localtime_r(&t, &tms) == nullptr) {
312 p = cpydig(p, tms.tm_mday, 2);
314 auto s = MONTH[tms.tm_mon];
315 p = std::copy_n(s, 3, p);
317 p = cpydig(p, tms.tm_year + 1900, 4);
319 p = cpydig(p, tms.tm_hour, 2);
321 p = cpydig(p, tms.tm_min, 2);
323 p = cpydig(p, tms.tm_sec, 2);
326 #ifdef HAVE_STRUCT_TM_TM_GMTOFF
327 auto gmtoff = tms.tm_gmtoff;
328 #else // !HAVE_STRUCT_TM_TM_GMTOFF
329 auto gmtoff = nghttp2_timegm(&tms) - t;
330 #endif // !HAVE_STRUCT_TM_TM_GMTOFF
338 p = cpydig(p, gmtoff / 3600, 2);
339 p = cpydig(p, (gmtoff % 3600) / 60, 2);
344 std::string iso8601_date(int64_t ms) {
345 // 2014-11-15T12:58:24.741Z
346 // 2014-11-15T12:58:24.741+09:00
347 std::string res(29, 0);
348 auto p = iso8601_date(&res[0], ms);
349 res.resize(p - &res[0]);
353 char *iso8601_date(char *res, int64_t ms) {
354 time_t sec = ms / 1000;
357 if (localtime_r(&sec, &tms) == nullptr) {
363 p = cpydig(p, tms.tm_year + 1900, 4);
365 p = cpydig(p, tms.tm_mon + 1, 2);
367 p = cpydig(p, tms.tm_mday, 2);
369 p = cpydig(p, tms.tm_hour, 2);
371 p = cpydig(p, tms.tm_min, 2);
373 p = cpydig(p, tms.tm_sec, 2);
375 p = cpydig(p, ms % 1000, 3);
377 #ifdef HAVE_STRUCT_TM_TM_GMTOFF
378 auto gmtoff = tms.tm_gmtoff;
379 #else // !HAVE_STRUCT_TM_TM_GMTOFF
380 auto gmtoff = nghttp2_timegm(&tms) - sec;
381 #endif // !HAVE_STRUCT_TM_TM_GMTOFF
391 p = cpydig(p, gmtoff / 3600, 2);
393 p = cpydig(p, (gmtoff % 3600) / 60, 2);
399 char *iso8601_basic_date(char *res, int64_t ms) {
400 time_t sec = ms / 1000;
403 if (localtime_r(&sec, &tms) == nullptr) {
409 p = cpydig(p, tms.tm_year + 1900, 4);
410 p = cpydig(p, tms.tm_mon + 1, 2);
411 p = cpydig(p, tms.tm_mday, 2);
413 p = cpydig(p, tms.tm_hour, 2);
414 p = cpydig(p, tms.tm_min, 2);
415 p = cpydig(p, tms.tm_sec, 2);
417 p = cpydig(p, ms % 1000, 3);
419 #ifdef HAVE_STRUCT_TM_TM_GMTOFF
420 auto gmtoff = tms.tm_gmtoff;
421 #else // !HAVE_STRUCT_TM_TM_GMTOFF
422 auto gmtoff = nghttp2_timegm(&tms) - sec;
423 #endif // !HAVE_STRUCT_TM_TM_GMTOFF
433 p = cpydig(p, gmtoff / 3600, 2);
434 p = cpydig(p, (gmtoff % 3600) / 60, 2);
441 namespace bt = boost::posix_time;
442 // one-time definition of the locale that is used to parse UTC strings
443 // (note that the time_input_facet is ref-counted and deleted automatically)
444 static const std::locale
445 ptime_locale(std::locale::classic(),
446 new bt::time_input_facet("%a, %d %b %Y %H:%M:%S GMT"));
449 time_t parse_http_date(const StringRef &s) {
451 // there is no strptime - use boost
452 std::stringstream sstr(s.str());
453 sstr.imbue(ptime_locale);
459 return boost::posix_time::to_time_t(ltime);
462 char *r = strptime(s.c_str(), "%a, %d %b %Y %H:%M:%S GMT", &tm);
466 return nghttp2_timegm_without_yday(&tm);
470 time_t parse_openssl_asn1_time_print(const StringRef &s) {
472 auto r = strptime(s.c_str(), "%b %d %H:%M:%S %Y GMT", &tm);
476 return nghttp2_timegm_without_yday(&tm);
479 char upcase(char c) {
480 if ('a' <= c && c <= 'z') {
481 return c - 'a' + 'A';
487 std::string format_hex(const unsigned char *s, size_t len) {
491 for (size_t i = 0; i < len; ++i) {
492 unsigned char c = s[i];
494 res[i * 2] = LOWER_XDIGITS[c >> 4];
495 res[i * 2 + 1] = LOWER_XDIGITS[c & 0x0f];
500 StringRef format_hex(BlockAllocator &balloc, const StringRef &s) {
501 auto iov = make_byte_ref(balloc, s.size() * 2 + 1);
506 *p++ = LOWER_XDIGITS[c >> 4];
507 *p++ = LOWER_XDIGITS[c & 0xf];
512 return StringRef{iov.base, p};
515 void to_token68(std::string &base64str) {
516 std::transform(std::begin(base64str), std::end(base64str),
517 std::begin(base64str), [](char c) {
527 base64str.erase(std::find(std::begin(base64str), std::end(base64str), '='),
528 std::end(base64str));
531 StringRef to_base64(BlockAllocator &balloc, const StringRef &token68str) {
532 // At most 3 padding '='
533 auto len = token68str.size() + 3;
534 auto iov = make_byte_ref(balloc, len + 1);
537 p = std::transform(std::begin(token68str), std::end(token68str), p,
549 auto rem = token68str.size() & 0x3;
551 p = std::fill_n(p, 4 - rem, '=');
556 return StringRef{iov.base, p};
560 // Calculates Damerau–Levenshtein distance between c-string a and b
561 // with given costs. swapcost, subcost, addcost and delcost are cost
562 // to swap 2 adjacent characters, substitute characters, add character
563 // and delete character respectively.
564 int levenshtein(const char *a, int alen, const char *b, int blen, int swapcost,
565 int subcost, int addcost, int delcost) {
566 auto dp = std::vector<std::vector<int>>(3, std::vector<int>(blen + 1));
567 for (int i = 0; i <= blen; ++i) {
570 for (int i = 1; i <= alen; ++i) {
572 for (int j = 1; j <= blen; ++j) {
573 dp[0][j] = dp[1][j - 1] + (a[i - 1] == b[j - 1] ? 0 : subcost);
574 if (i >= 2 && j >= 2 && a[i - 1] != b[j - 1] && a[i - 2] == b[j - 1] &&
575 a[i - 1] == b[j - 2]) {
576 dp[0][j] = std::min(dp[0][j], dp[2][j - 2] + swapcost);
578 dp[0][j] = std::min(dp[0][j],
579 std::min(dp[1][j] + delcost, dp[0][j - 1] + addcost));
581 std::rotate(std::begin(dp), std::begin(dp) + 2, std::end(dp));
587 void show_candidates(const char *unkopt, const option *options) {
588 for (; *unkopt == '-'; ++unkopt)
590 if (*unkopt == '\0') {
593 auto unkoptend = unkopt;
594 for (; *unkoptend && *unkoptend != '='; ++unkoptend)
596 auto unkoptlen = unkoptend - unkopt;
597 if (unkoptlen == 0) {
600 int prefix_match = 0;
601 auto cands = std::vector<std::pair<int, const char *>>();
602 for (size_t i = 0; options[i].name != nullptr; ++i) {
603 auto optnamelen = strlen(options[i].name);
604 // Use cost 0 for prefix match
605 if (istarts_with(options[i].name, options[i].name + optnamelen, unkopt,
606 unkopt + unkoptlen)) {
607 if (optnamelen == static_cast<size_t>(unkoptlen)) {
608 // Exact match, then we don't show any condidates.
612 cands.emplace_back(0, options[i].name);
615 // Use cost 0 for suffix match, but match at least 3 characters
616 if (unkoptlen >= 3 &&
617 iends_with(options[i].name, options[i].name + optnamelen, unkopt,
618 unkopt + unkoptlen)) {
619 cands.emplace_back(0, options[i].name);
622 // cost values are borrowed from git, help.c.
624 levenshtein(unkopt, unkoptlen, options[i].name, optnamelen, 0, 2, 1, 3);
625 cands.emplace_back(sim, options[i].name);
627 if (prefix_match == 1 || cands.empty()) {
630 std::sort(std::begin(cands), std::end(cands));
631 int threshold = cands[0].first;
632 // threshold value is a magic value.
636 std::cerr << "\nDid you mean:\n";
637 for (auto &item : cands) {
638 if (item.first > threshold) {
641 std::cerr << "\t--" << item.second << "\n";
645 bool has_uri_field(const http_parser_url &u, http_parser_url_fields field) {
646 return u.field_set & (1 << field);
649 bool fieldeq(const char *uri1, const http_parser_url &u1, const char *uri2,
650 const http_parser_url &u2, http_parser_url_fields field) {
651 if (!has_uri_field(u1, field)) {
652 if (!has_uri_field(u2, field)) {
657 } else if (!has_uri_field(u2, field)) {
660 if (u1.field_data[field].len != u2.field_data[field].len) {
663 return memcmp(uri1 + u1.field_data[field].off,
664 uri2 + u2.field_data[field].off, u1.field_data[field].len) == 0;
667 bool fieldeq(const char *uri, const http_parser_url &u,
668 http_parser_url_fields field, const char *t) {
669 return fieldeq(uri, u, field, StringRef{t});
672 bool fieldeq(const char *uri, const http_parser_url &u,
673 http_parser_url_fields field, const StringRef &t) {
674 if (!has_uri_field(u, field)) {
677 auto &f = u.field_data[field];
678 return StringRef{uri + f.off, f.len} == t;
681 StringRef get_uri_field(const char *uri, const http_parser_url &u,
682 http_parser_url_fields field) {
683 if (!util::has_uri_field(u, field)) {
687 return StringRef{uri + u.field_data[field].off, u.field_data[field].len};
690 uint16_t get_default_port(const char *uri, const http_parser_url &u) {
691 if (util::fieldeq(uri, u, UF_SCHEMA, "https")) {
693 } else if (util::fieldeq(uri, u, UF_SCHEMA, "http")) {
700 bool porteq(const char *uri1, const http_parser_url &u1, const char *uri2,
701 const http_parser_url &u2) {
702 uint16_t port1, port2;
704 util::has_uri_field(u1, UF_PORT) ? u1.port : get_default_port(uri1, u1);
706 util::has_uri_field(u2, UF_PORT) ? u2.port : get_default_port(uri2, u2);
707 return port1 == port2;
710 void write_uri_field(std::ostream &o, const char *uri, const http_parser_url &u,
711 http_parser_url_fields field) {
712 if (util::has_uri_field(u, field)) {
713 o.write(uri + u.field_data[field].off, u.field_data[field].len);
717 bool numeric_host(const char *hostname) {
718 return numeric_host(hostname, AF_INET) || numeric_host(hostname, AF_INET6);
721 bool numeric_host(const char *hostname, int family) {
723 std::array<uint8_t, sizeof(struct in6_addr)> dst;
725 rv = nghttp2_inet_pton(family, hostname, dst.data());
730 std::string numeric_name(const struct sockaddr *sa, socklen_t salen) {
731 std::array<char, NI_MAXHOST> host;
732 auto rv = getnameinfo(sa, salen, host.data(), host.size(), nullptr, 0,
740 std::string to_numeric_addr(const Address *addr) {
741 return to_numeric_addr(&addr->su.sa, addr->len);
744 std::string to_numeric_addr(const struct sockaddr *sa, socklen_t salen) {
745 auto family = sa->sa_family;
747 if (family == AF_UNIX) {
748 return reinterpret_cast<const sockaddr_un *>(sa)->sun_path;
752 std::array<char, NI_MAXHOST> host;
753 std::array<char, NI_MAXSERV> serv;
754 auto rv = getnameinfo(sa, salen, host.data(), host.size(), serv.data(),
755 serv.size(), NI_NUMERICHOST | NI_NUMERICSERV);
760 auto hostlen = strlen(host.data());
761 auto servlen = strlen(serv.data());
765 if (family == AF_INET6) {
766 s.resize(hostlen + servlen + 2 + 1);
769 p = std::copy_n(host.data(), hostlen, p);
772 s.resize(hostlen + servlen + 1);
774 p = std::copy_n(host.data(), hostlen, p);
777 std::copy_n(serv.data(), servlen, p);
782 void set_port(Address &addr, uint16_t port) {
783 switch (addr.su.storage.ss_family) {
785 addr.su.in.sin_port = htons(port);
788 addr.su.in6.sin6_port = htons(port);
793 std::string ascii_dump(const uint8_t *data, size_t len) {
796 for (size_t i = 0; i < len; ++i) {
799 if (c >= 0x20 && c < 0x7f) {
809 char *get_exec_path(int argc, char **const argv, const char *cwd) {
810 if (argc == 0 || cwd == nullptr) {
814 auto argv0 = argv[0];
815 auto len = strlen(argv0);
819 if (argv0[0] == '/') {
820 path = static_cast<char *>(malloc(len + 1));
821 if (path == nullptr) {
824 memcpy(path, argv0, len + 1);
826 auto cwdlen = strlen(cwd);
827 path = static_cast<char *>(malloc(len + 1 + cwdlen + 1));
828 if (path == nullptr) {
831 memcpy(path, cwd, cwdlen);
833 memcpy(path + cwdlen + 1, argv0, len + 1);
839 bool check_path(const std::string &path) {
840 // We don't like '\' in path.
841 return !path.empty() && path[0] == '/' &&
842 path.find('\\') == std::string::npos &&
843 path.find("/../") == std::string::npos &&
844 path.find("/./") == std::string::npos &&
845 !util::ends_with_l(path, "/..") && !util::ends_with_l(path, "/.");
848 int64_t to_time64(const timeval &tv) {
849 return tv.tv_sec * 1000000 + tv.tv_usec;
852 bool check_h2_is_selected(const StringRef &proto) {
853 return streq(NGHTTP2_H2, proto) || streq(NGHTTP2_H2_16, proto) ||
854 streq(NGHTTP2_H2_14, proto);
858 bool select_proto(const unsigned char **out, unsigned char *outlen,
859 const unsigned char *in, unsigned int inlen,
860 const StringRef &key) {
861 for (auto p = in, end = in + inlen; p + key.size() <= end; p += *p + 1) {
862 if (std::equal(std::begin(key), std::end(key), p)) {
872 bool select_h2(const unsigned char **out, unsigned char *outlen,
873 const unsigned char *in, unsigned int inlen) {
874 return select_proto(out, outlen, in, inlen, NGHTTP2_H2_ALPN) ||
875 select_proto(out, outlen, in, inlen, NGHTTP2_H2_16_ALPN) ||
876 select_proto(out, outlen, in, inlen, NGHTTP2_H2_14_ALPN);
879 bool select_protocol(const unsigned char **out, unsigned char *outlen,
880 const unsigned char *in, unsigned int inlen,
881 std::vector<std::string> proto_list) {
882 for (const auto &proto : proto_list) {
883 if (select_proto(out, outlen, in, inlen, StringRef{proto})) {
891 std::vector<unsigned char> get_default_alpn() {
892 auto res = std::vector<unsigned char>(NGHTTP2_H2_ALPN.size() +
893 NGHTTP2_H2_16_ALPN.size() +
894 NGHTTP2_H2_14_ALPN.size());
895 auto p = std::begin(res);
897 p = std::copy_n(std::begin(NGHTTP2_H2_ALPN), NGHTTP2_H2_ALPN.size(), p);
898 p = std::copy_n(std::begin(NGHTTP2_H2_16_ALPN), NGHTTP2_H2_16_ALPN.size(), p);
899 p = std::copy_n(std::begin(NGHTTP2_H2_14_ALPN), NGHTTP2_H2_14_ALPN.size(), p);
904 std::vector<StringRef> split_str(const StringRef &s, char delim) {
906 auto last = std::end(s);
907 StringRef::const_iterator d;
908 for (auto first = std::begin(s); (d = std::find(first, last, delim)) != last;
909 ++len, first = d + 1)
912 auto list = std::vector<StringRef>(len);
915 for (auto first = std::begin(s);; ++len) {
916 auto stop = std::find(first, last, delim);
917 list[len] = StringRef{first, stop};
926 std::vector<StringRef> split_str(const StringRef &s, char delim, size_t n) {
928 return split_str(s, delim);
936 auto last = std::end(s);
937 StringRef::const_iterator d;
938 for (auto first = std::begin(s);
939 len < n && (d = std::find(first, last, delim)) != last;
940 ++len, first = d + 1)
943 auto list = std::vector<StringRef>(len);
946 for (auto first = std::begin(s);; ++len) {
948 list[len] = StringRef{first, last};
952 auto stop = std::find(first, last, delim);
953 list[len] = StringRef{first, stop};
962 std::vector<std::string> parse_config_str_list(const StringRef &s, char delim) {
963 auto sublist = split_str(s, delim);
964 auto res = std::vector<std::string>();
965 res.reserve(sublist.size());
966 for (const auto &s : sublist) {
967 res.emplace_back(std::begin(s), std::end(s));
972 int make_socket_closeonexec(int fd) {
979 while ((flags = fcntl(fd, F_GETFD)) == -1 && errno == EINTR)
981 while ((rv = fcntl(fd, F_SETFD, flags | FD_CLOEXEC)) == -1 && errno == EINTR)
987 int make_socket_nonblocking(int fd) {
993 rv = ioctlsocket(fd, FIONBIO, &mode);
996 while ((flags = fcntl(fd, F_GETFL, 0)) == -1 && errno == EINTR)
998 while ((rv = fcntl(fd, F_SETFL, flags | O_NONBLOCK)) == -1 && errno == EINTR)
1005 int make_socket_nodelay(int fd) {
1007 if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, reinterpret_cast<char *>(&val),
1008 sizeof(val)) == -1) {
1014 int create_nonblock_socket(int family) {
1015 #ifdef SOCK_NONBLOCK
1016 auto fd = socket(family, SOCK_STREAM | SOCK_NONBLOCK | SOCK_CLOEXEC, 0);
1021 #else // !SOCK_NONBLOCK
1022 auto fd = socket(family, SOCK_STREAM, 0);
1028 make_socket_nonblocking(fd);
1029 make_socket_closeonexec(fd);
1030 #endif // !SOCK_NONBLOCK
1032 if (family == AF_INET || family == AF_INET6) {
1033 make_socket_nodelay(fd);
1039 int create_nonblock_udp_socket(int family) {
1040 #ifdef SOCK_NONBLOCK
1041 auto fd = socket(family, SOCK_DGRAM | SOCK_NONBLOCK | SOCK_CLOEXEC, 0);
1046 #else // !SOCK_NONBLOCK
1047 auto fd = socket(family, SOCK_DGRAM, 0);
1053 make_socket_nonblocking(fd);
1054 make_socket_closeonexec(fd);
1055 #endif // !SOCK_NONBLOCK
1060 int bind_any_addr_udp(int fd, int family) {
1065 hints.ai_family = family;
1066 hints.ai_socktype = SOCK_DGRAM;
1067 hints.ai_flags = AI_PASSIVE;
1069 rv = getaddrinfo(nullptr, "0", &hints, &res);
1074 for (rp = res; rp; rp = rp->ai_next) {
1075 if (bind(fd, rp->ai_addr, rp->ai_addrlen) != -1) {
1089 bool check_socket_connected(int fd) {
1091 socklen_t len = sizeof(error);
1092 if (getsockopt(fd, SOL_SOCKET, SO_ERROR, (char *)&error, &len) != 0) {
1099 int get_socket_error(int fd) {
1101 socklen_t len = sizeof(error);
1102 if (getsockopt(fd, SOL_SOCKET, SO_ERROR, (char *)&error, &len) != 0) {
1109 bool ipv6_numeric_addr(const char *host) {
1111 return nghttp2_inet_pton(AF_INET6, host, dst) == 1;
1115 std::pair<int64_t, size_t> parse_uint_digits(const void *ss, size_t len) {
1116 const uint8_t *s = static_cast<const uint8_t *>(ss);
1122 constexpr int64_t max = std::numeric_limits<int64_t>::max();
1123 for (i = 0; i < len; ++i) {
1124 if ('0' <= s[i] && s[i] <= '9') {
1129 if (n > max - (s[i] - '0')) {
1144 int64_t parse_uint_with_unit(const char *s) {
1145 return parse_uint_with_unit(reinterpret_cast<const uint8_t *>(s), strlen(s));
1148 int64_t parse_uint_with_unit(const StringRef &s) {
1149 return parse_uint_with_unit(s.byte(), s.size());
1152 int64_t parse_uint_with_unit(const uint8_t *s, size_t len) {
1155 std::tie(n, i) = parse_uint_digits(s, len);
1182 constexpr int64_t max = std::numeric_limits<int64_t>::max();
1183 if (n > max / mul) {
1189 int64_t parse_uint(const char *s) {
1190 return parse_uint(reinterpret_cast<const uint8_t *>(s), strlen(s));
1193 int64_t parse_uint(const std::string &s) {
1194 return parse_uint(reinterpret_cast<const uint8_t *>(s.c_str()), s.size());
1197 int64_t parse_uint(const StringRef &s) {
1198 return parse_uint(s.byte(), s.size());
1201 int64_t parse_uint(const uint8_t *s, size_t len) {
1204 std::tie(n, i) = parse_uint_digits(s, len);
1205 if (n == -1 || i != len) {
1211 double parse_duration_with_unit(const char *s) {
1212 return parse_duration_with_unit(reinterpret_cast<const uint8_t *>(s),
1216 double parse_duration_with_unit(const StringRef &s) {
1217 return parse_duration_with_unit(s.byte(), s.size());
1220 double parse_duration_with_unit(const uint8_t *s, size_t len) {
1221 constexpr auto max = std::numeric_limits<int64_t>::max();
1225 std::tie(n, i) = parse_uint_digits(s, len);
1230 return static_cast<double>(n);
1239 return static_cast<double>(n);
1247 return static_cast<double>(n) * 60;
1250 if (i + 2 != len || (s[i + 1] != 's' && s[i + 1] != 'S')) {
1254 return static_cast<double>(n) / 1000.;
1261 if (n > max / 3600) {
1264 return static_cast<double>(n) * 3600;
1267 return std::numeric_limits<double>::infinity();
1270 std::string duration_str(double t) {
1274 auto frac = static_cast<int64_t>(t * 1000) % 1000;
1276 return utos(static_cast<int64_t>(t * 1000)) + "ms";
1278 auto v = static_cast<int64_t>(t);
1280 return utos(v) + "s";
1284 return utos(v) + "m";
1287 return utos(v) + "h";
1290 std::string format_duration(const std::chrono::microseconds &u) {
1291 const char *unit = "us";
1297 } else if (t >= 1000) {
1301 return utos(t) + unit;
1303 return dtos(static_cast<double>(t) / d) + unit;
1306 std::string format_duration(double t) {
1307 const char *unit = "us";
1310 } else if (t >= 0.001) {
1315 return utos(static_cast<int64_t>(t)) + unit;
1317 return dtos(t) + unit;
1320 std::string dtos(double n) {
1321 auto m = llround(100. * n);
1322 auto f = utos(m % 100);
1323 return utos(m / 100) + "." + (f.size() == 1 ? "0" : "") + f;
1326 StringRef make_http_hostport(BlockAllocator &balloc, const StringRef &host,
1328 auto iov = make_byte_ref(balloc, host.size() + 2 + 1 + 5 + 1);
1329 return make_http_hostport(iov.base, host, port);
1332 StringRef make_hostport(BlockAllocator &balloc, const StringRef &host,
1334 auto iov = make_byte_ref(balloc, host.size() + 2 + 1 + 5 + 1);
1335 return make_hostport(iov.base, host, port);
1339 void hexdump8(FILE *out, const uint8_t *first, const uint8_t *last) {
1340 auto stop = std::min(first + 8, last);
1341 for (auto k = first; k != stop; ++k) {
1342 fprintf(out, "%02x ", *k);
1344 // each byte needs 3 spaces (2 hex value and space)
1345 for (; stop != first + 8; ++stop) {
1348 // we have extra space after 8 bytes
1353 void hexdump(FILE *out, const uint8_t *src, size_t len) {
1358 auto repeated = false;
1359 std::array<uint8_t, 16> buf{};
1360 auto end = src + len;
1364 std::min(static_cast<size_t>(16), static_cast<size_t>(end - i));
1365 if (nextlen == buflen &&
1366 std::equal(std::begin(buf), std::begin(buf) + buflen, i)) {
1367 // as long as adjacent 16 bytes block are the same, we just
1368 // print single '*'.
1377 fprintf(out, "%08lx", static_cast<unsigned long>(i - src));
1383 hexdump8(out, i, end);
1384 hexdump8(out, i + 8, std::max(i + 8, end));
1386 auto stop = std::min(i + 16, end);
1388 auto p = buf.data();
1389 for (; i != stop; ++i) {
1391 if (0x20 <= *i && *i <= 0x7e) {
1401 void put_uint16be(uint8_t *buf, uint16_t n) {
1402 uint16_t x = htons(n);
1403 memcpy(buf, &x, sizeof(uint16_t));
1406 void put_uint32be(uint8_t *buf, uint32_t n) {
1407 uint32_t x = htonl(n);
1408 memcpy(buf, &x, sizeof(uint32_t));
1411 uint16_t get_uint16(const uint8_t *data) {
1413 memcpy(&n, data, sizeof(uint16_t));
1417 uint32_t get_uint32(const uint8_t *data) {
1419 memcpy(&n, data, sizeof(uint32_t));
1423 uint64_t get_uint64(const uint8_t *data) {
1425 n += static_cast<uint64_t>(data[0]) << 56;
1426 n += static_cast<uint64_t>(data[1]) << 48;
1427 n += static_cast<uint64_t>(data[2]) << 40;
1428 n += static_cast<uint64_t>(data[3]) << 32;
1429 n += static_cast<uint64_t>(data[4]) << 24;
1436 int read_mime_types(std::map<std::string, std::string> &res,
1437 const char *filename) {
1438 std::ifstream infile(filename);
1443 auto delim_pred = [](char c) { return c == ' ' || c == '\t'; };
1446 while (std::getline(infile, line)) {
1447 if (line.empty() || line[0] == '#') {
1451 auto type_end = std::find_if(std::begin(line), std::end(line), delim_pred);
1452 if (type_end == std::begin(line)) {
1456 auto ext_end = type_end;
1458 auto ext_start = std::find_if_not(ext_end, std::end(line), delim_pred);
1459 if (ext_start == std::end(line)) {
1462 ext_end = std::find_if(ext_start, std::end(line), delim_pred);
1463 #ifdef HAVE_STD_MAP_EMPLACE
1464 res.emplace(std::string(ext_start, ext_end),
1465 std::string(std::begin(line), type_end));
1466 #else // !HAVE_STD_MAP_EMPLACE
1467 res.insert(std::make_pair(std::string(ext_start, ext_end),
1468 std::string(std::begin(line), type_end)));
1469 #endif // !HAVE_STD_MAP_EMPLACE
1476 StringRef percent_decode(BlockAllocator &balloc, const StringRef &src) {
1477 auto iov = make_byte_ref(balloc, src.size() * 3 + 1);
1479 for (auto first = std::begin(src); first != std::end(src); ++first) {
1480 if (*first != '%') {
1485 if (first + 1 != std::end(src) && first + 2 != std::end(src) &&
1486 is_hex_digit(*(first + 1)) && is_hex_digit(*(first + 2))) {
1487 *p++ = (hex_to_uint(*(first + 1)) << 4) + hex_to_uint(*(first + 2));
1495 return StringRef{iov.base, p};
1499 double int_pow(double x, size_t y) {
1507 uint32_t hash32(const StringRef &s) {
1508 /* 32 bit FNV-1a: http://isthe.com/chongo/tech/comp/fnv/ */
1509 uint32_t h = 2166136261u;
1512 for (i = 0; i < s.size(); ++i) {
1514 h += (h << 1) + (h << 4) + (h << 7) + (h << 8) + (h << 24);
1520 #if !OPENSSL_1_1_API
1522 EVP_MD_CTX *EVP_MD_CTX_new(void) { return EVP_MD_CTX_create(); }
1526 void EVP_MD_CTX_free(EVP_MD_CTX *ctx) { EVP_MD_CTX_destroy(ctx); }
1528 #endif // !OPENSSL_1_1_API
1531 int message_digest(uint8_t *res, const EVP_MD *meth, const StringRef &s) {
1534 auto ctx = EVP_MD_CTX_new();
1535 if (ctx == nullptr) {
1539 auto ctx_deleter = defer(EVP_MD_CTX_free, ctx);
1541 rv = EVP_DigestInit_ex(ctx, meth, nullptr);
1546 rv = EVP_DigestUpdate(ctx, s.c_str(), s.size());
1551 unsigned int mdlen = EVP_MD_size(meth);
1553 rv = EVP_DigestFinal_ex(ctx, res, &mdlen);
1562 int sha256(uint8_t *res, const StringRef &s) {
1563 return message_digest(res, EVP_sha256(), s);
1566 int sha1(uint8_t *res, const StringRef &s) {
1567 return message_digest(res, EVP_sha1(), s);
1570 bool is_hex_string(const StringRef &s) {
1576 if (!is_hex_digit(c)) {
1584 StringRef decode_hex(BlockAllocator &balloc, const StringRef &s) {
1585 auto iov = make_byte_ref(balloc, s.size() + 1);
1586 auto p = decode_hex(iov.base, s);
1588 return StringRef{iov.base, p};
1591 StringRef extract_host(const StringRef &hostport) {
1592 if (hostport[0] == '[') {
1593 // assume this is IPv6 numeric address
1594 auto p = std::find(std::begin(hostport), std::end(hostport), ']');
1595 if (p == std::end(hostport)) {
1598 if (p + 1 < std::end(hostport) && *(p + 1) != ':') {
1601 return StringRef{std::begin(hostport), p + 1};
1604 auto p = std::find(std::begin(hostport), std::end(hostport), ':');
1605 if (p == std::begin(hostport)) {
1608 return StringRef{std::begin(hostport), p};
1611 std::pair<StringRef, StringRef> split_hostport(const StringRef &hostport) {
1612 if (hostport.empty()) {
1615 if (hostport[0] == '[') {
1616 // assume this is IPv6 numeric address
1617 auto p = std::find(std::begin(hostport), std::end(hostport), ']');
1618 if (p == std::end(hostport)) {
1621 if (p + 1 == std::end(hostport)) {
1622 return {StringRef{std::begin(hostport) + 1, p}, {}};
1624 if (*(p + 1) != ':' || p + 2 == std::end(hostport)) {
1627 return {StringRef{std::begin(hostport) + 1, p},
1628 StringRef{p + 2, std::end(hostport)}};
1631 auto p = std::find(std::begin(hostport), std::end(hostport), ':');
1632 if (p == std::begin(hostport)) {
1635 if (p == std::end(hostport)) {
1636 return {StringRef{std::begin(hostport), p}, {}};
1638 if (p + 1 == std::end(hostport)) {
1642 return {StringRef{std::begin(hostport), p},
1643 StringRef{p + 1, std::end(hostport)}};
1646 std::mt19937 make_mt19937() {
1647 std::random_device rd;
1648 return std::mt19937(rd());
1651 int daemonize(int nochdir, int noclose) {
1657 } else if (pid > 0) {
1658 _exit(EXIT_SUCCESS);
1660 if (setsid() == -1) {
1666 } else if (pid > 0) {
1667 _exit(EXIT_SUCCESS);
1670 if (chdir("/") == -1) {
1675 if (freopen("/dev/null", "r", stdin) == nullptr) {
1678 if (freopen("/dev/null", "w", stdout) == nullptr) {
1681 if (freopen("/dev/null", "w", stderr) == nullptr) {
1687 return daemon(nochdir, noclose);
1688 #endif // !__APPLE__
1692 int msghdr_get_local_addr(Address &dest, msghdr *msg, int family) {
1695 for (auto cmsg = CMSG_FIRSTHDR(msg); cmsg; cmsg = CMSG_NXTHDR(msg, cmsg)) {
1696 if (cmsg->cmsg_level == IPPROTO_IP && cmsg->cmsg_type == IP_PKTINFO) {
1697 auto pktinfo = reinterpret_cast<in_pktinfo *>(CMSG_DATA(cmsg));
1698 dest.len = sizeof(dest.su.in);
1699 auto &sa = dest.su.in;
1700 sa.sin_family = AF_INET;
1701 sa.sin_addr = pktinfo->ipi_addr;
1709 for (auto cmsg = CMSG_FIRSTHDR(msg); cmsg; cmsg = CMSG_NXTHDR(msg, cmsg)) {
1710 if (cmsg->cmsg_level == IPPROTO_IPV6 && cmsg->cmsg_type == IPV6_PKTINFO) {
1711 auto pktinfo = reinterpret_cast<in6_pktinfo *>(CMSG_DATA(cmsg));
1712 dest.len = sizeof(dest.su.in6);
1713 auto &sa = dest.su.in6;
1714 sa.sin6_family = AF_INET6;
1715 sa.sin6_addr = pktinfo->ipi6_addr;
1725 #endif // ENABLE_HTTP3
1729 } // namespace nghttp2