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