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 73namespace nghttp2 { 74 75namespace util { 76 77#ifndef _WIN32 78namespace { 79int nghttp2_inet_pton(int af, const char *src, void *dst) { 80 return inet_pton(af, src, dst); 81} 82} // namespace 83#else // _WIN32 84namespace { 85// inet_pton-wrapper for Windows 86int 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 105const char UPPER_XDIGITS[] = "0123456789ABCDEF"; 106 107bool 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 119bool 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 138std::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 154std::string percent_encode(const std::string &target) { 155 return percent_encode(reinterpret_cast<const unsigned char *>(target.c_str()), 156 target.size()); 157} 158 159bool 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 182bool 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 193StringRef 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 203size_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 221uint32_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 234StringRef 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 249size_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 263namespace { 264template <typename Iterator> 265Iterator 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 277namespace { 278constexpr const char *MONTH[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", 279 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; 280constexpr const char *DAY_OF_WEEK[] = {"Sun", "Mon", "Tue", "Wed", 281 "Thu", "Fri", "Sat"}; 282} // namespace 283 284std::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 291char *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 322std::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 329char *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 370std::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 379char *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 425char *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 466time_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 484time_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 493char upcase(char c) { 494 if ('a' <= c && c <= 'z') { 495 return c - 'a' + 'A'; 496 } else { 497 return c; 498 } 499} 500 501std::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 514StringRef 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 529void 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 545StringRef 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 573namespace { 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. 578int 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 601void 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 659bool has_uri_field(const http_parser_url &u, http_parser_url_fields field) { 660 return u.field_set & (1 << field); 661} 662 663bool 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 681bool 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 686bool 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 695StringRef 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 704uint16_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 714bool 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 724void 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 731bool numeric_host(const char *hostname) { 732 return numeric_host(hostname, AF_INET) || numeric_host(hostname, AF_INET6); 733} 734 735bool 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 744std::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 754std::string to_numeric_addr(const Address *addr) { 755 return to_numeric_addr(&addr->su.sa, addr->len); 756} 757 758std::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 796void 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 807std::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 823char *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 853bool 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 862int64_t to_time64(const timeval &tv) { 863 return tv.tv_sec * 1000000 + tv.tv_usec; 864} 865 866bool 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 871namespace { 872bool 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 886bool 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 893bool 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 905std::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 918std::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 940std::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 976std::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 986int 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 1001int 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 1019int 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 1028int 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 1053int 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 1074int 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 1103bool 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 1113int 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 1123bool ipv6_numeric_addr(const char *host) { 1124 uint8_t dst[16]; 1125 return nghttp2_inet_pton(AF_INET6, host, dst) == 1; 1126} 1127 1128namespace { 1129std::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 1158int64_t parse_uint_with_unit(const char *s) { 1159 return parse_uint_with_unit(reinterpret_cast<const uint8_t *>(s), strlen(s)); 1160} 1161 1162int64_t parse_uint_with_unit(const StringRef &s) { 1163 return parse_uint_with_unit(s.byte(), s.size()); 1164} 1165 1166int64_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 1203int64_t parse_uint(const char *s) { 1204 return parse_uint(reinterpret_cast<const uint8_t *>(s), strlen(s)); 1205} 1206 1207int64_t parse_uint(const std::string &s) { 1208 return parse_uint(reinterpret_cast<const uint8_t *>(s.c_str()), s.size()); 1209} 1210 1211int64_t parse_uint(const StringRef &s) { 1212 return parse_uint(s.byte(), s.size()); 1213} 1214 1215int64_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 1225double parse_duration_with_unit(const char *s) { 1226 return parse_duration_with_unit(reinterpret_cast<const uint8_t *>(s), 1227 strlen(s)); 1228} 1229 1230double parse_duration_with_unit(const StringRef &s) { 1231 return parse_duration_with_unit(s.byte(), s.size()); 1232} 1233 1234double 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 } 1280fail: 1281 return std::numeric_limits<double>::infinity(); 1282} 1283 1284std::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 1304std::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 1320std::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 1334std::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 1340StringRef 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 1346StringRef 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 1352namespace { 1353void 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 1367void 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 1415void put_uint16be(uint8_t *buf, uint16_t n) { 1416 uint16_t x = htons(n); 1417 memcpy(buf, &x, sizeof(uint16_t)); 1418} 1419 1420void put_uint32be(uint8_t *buf, uint32_t n) { 1421 uint32_t x = htonl(n); 1422 memcpy(buf, &x, sizeof(uint32_t)); 1423} 1424 1425uint16_t get_uint16(const uint8_t *data) { 1426 uint16_t n; 1427 memcpy(&n, data, sizeof(uint16_t)); 1428 return ntohs(n); 1429} 1430 1431uint32_t get_uint32(const uint8_t *data) { 1432 uint32_t n; 1433 memcpy(&n, data, sizeof(uint32_t)); 1434 return ntohl(n); 1435} 1436 1437uint64_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 1450int 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 1490StringRef 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 1513double int_pow(double x, size_t y) { 1514 auto res = 1.; 1515 for (; y; --y) { 1516 res *= x; 1517 } 1518 return res; 1519} 1520 1521uint32_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 1535namespace { 1536EVP_MD_CTX *EVP_MD_CTX_new(void) { return EVP_MD_CTX_create(); } 1537} // namespace 1538 1539namespace { 1540void EVP_MD_CTX_free(EVP_MD_CTX *ctx) { EVP_MD_CTX_destroy(ctx); } 1541} // namespace 1542#endif // !OPENSSL_1_1_API 1543 1544namespace { 1545int 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 1576int sha256(uint8_t *res, const StringRef &s) { 1577 return message_digest(res, EVP_sha256(), s); 1578} 1579 1580int sha1(uint8_t *res, const StringRef &s) { 1581 return message_digest(res, EVP_sha1(), s); 1582} 1583 1584bool 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 1598StringRef 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 1605StringRef 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 1625std::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 1660std::mt19937 make_mt19937() { 1661 std::random_device rd; 1662 return std::mt19937(rd()); 1663} 1664 1665int 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 1705StringRef 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 1719int 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 1755uint8_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 1789size_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