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