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