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