1 /*
2 * ngtcp2
3 *
4 * Copyright (c) 2017 ngtcp2 contributors
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 <chrono>
26 #include <cstdlib>
27 #include <cassert>
28 #include <cstring>
29 #include <iostream>
30 #include <algorithm>
31 #include <memory>
32 #include <fstream>
33 #include <iomanip>
34
35 #include <unistd.h>
36 #include <getopt.h>
37 #include <sys/types.h>
38 #include <sys/socket.h>
39 #include <netdb.h>
40 #include <sys/stat.h>
41 #include <fcntl.h>
42 #include <sys/mman.h>
43 #include <netinet/udp.h>
44 #include <net/if.h>
45
46 #include <http-parser/http_parser.h>
47
48 #include "h09server.h"
49 #include "network.h"
50 #include "debug.h"
51 #include "util.h"
52 #include "shared.h"
53 #include "http.h"
54 #include "template.h"
55
56 using namespace ngtcp2;
57 using namespace std::literals;
58
59 #ifndef NGTCP2_ENABLE_UDP_GSO
60 # ifdef UDP_SEGMENT
61 # define NGTCP2_ENABLE_UDP_GSO 1
62 # else // !UDP_SEGMENT
63 # define NGTCP2_ENABLE_UDP_GSO 0
64 # endif // !UDP_SEGMENT
65 #endif // NGTCP2_ENABLE_UDP_GSO
66
67 namespace {
68 constexpr size_t NGTCP2_SV_SCIDLEN = 18;
69 } // namespace
70
71 namespace {
72 auto randgen = util::make_mt19937();
73 } // namespace
74
75 Config config{};
76
Stream(int64_t stream_id,Handler * handler)77 Stream::Stream(int64_t stream_id, Handler *handler)
78 : stream_id(stream_id), handler(handler), eos(false) {
79 nghttp3_buf_init(&respbuf);
80 htp.data = this;
81 http_parser_init(&htp, HTTP_REQUEST);
82 }
83
84 namespace {
85 constexpr char NGTCP2_SERVER[] = "ngtcp2 server";
86 } // namespace
87
88 namespace {
make_status_body(unsigned int status_code)89 std::string make_status_body(unsigned int status_code) {
90 auto status_string = std::to_string(status_code);
91 auto reason_phrase = http::get_reason_phrase(status_code);
92
93 std::string body;
94 body = "<html><head><title>";
95 body += status_string;
96 body += ' ';
97 body += reason_phrase;
98 body += "</title></head><body><h1>";
99 body += status_string;
100 body += ' ';
101 body += reason_phrase;
102 body += "</h1><hr><address>";
103 body += NGTCP2_SERVER;
104 body += " at port ";
105 body += std::to_string(config.port);
106 body += "</address>";
107 body += "</body></html>";
108 return body;
109 }
110 } // namespace
111
112 struct Request {
113 std::string path;
114 struct {
115 int32_t urgency;
116 int inc;
117 } pri;
118 };
119
120 namespace {
request_path(const std::string_view & uri)121 Request request_path(const std::string_view &uri) {
122 http_parser_url u;
123 Request req;
124
125 req.pri.urgency = -1;
126 req.pri.inc = -1;
127
128 http_parser_url_init(&u);
129
130 if (auto rv = http_parser_parse_url(uri.data(), uri.size(),
131 /* is_connect = */ 0, &u);
132 rv != 0) {
133 return req;
134 }
135
136 if (u.field_set & (1 << UF_PATH)) {
137 req.path = std::string(uri.data() + u.field_data[UF_PATH].off,
138 u.field_data[UF_PATH].len);
139 if (req.path.find('%') != std::string::npos) {
140 req.path = util::percent_decode(std::begin(req.path), std::end(req.path));
141 }
142 if (!req.path.empty() && req.path.back() == '/') {
143 req.path += "index.html";
144 }
145 } else {
146 req.path = "/index.html";
147 }
148
149 req.path = util::normalize_path(req.path);
150 if (req.path == "/") {
151 req.path = "/index.html";
152 }
153
154 if (u.field_set & (1 << UF_QUERY)) {
155 static constexpr char urgency_prefix[] = "u=";
156 static constexpr char inc_prefix[] = "i=";
157 auto q = std::string(uri.data() + u.field_data[UF_QUERY].off,
158 u.field_data[UF_QUERY].len);
159 for (auto p = std::begin(q); p != std::end(q);) {
160 if (util::istarts_with(p, std::end(q), std::begin(urgency_prefix),
161 std::end(urgency_prefix) - 1)) {
162 auto urgency_start = p + sizeof(urgency_prefix) - 1;
163 auto urgency_end = std::find(urgency_start, std::end(q), '&');
164 if (urgency_start + 1 == urgency_end && '0' <= *urgency_start &&
165 *urgency_start <= '7') {
166 req.pri.urgency = *urgency_start - '0';
167 }
168 if (urgency_end == std::end(q)) {
169 break;
170 }
171 p = urgency_end + 1;
172 continue;
173 }
174 if (util::istarts_with(p, std::end(q), std::begin(inc_prefix),
175 std::end(inc_prefix) - 1)) {
176 auto inc_start = p + sizeof(inc_prefix) - 1;
177 auto inc_end = std::find(inc_start, std::end(q), '&');
178 if (inc_start + 1 == inc_end &&
179 (*inc_start == '0' || *inc_start == '1')) {
180 req.pri.inc = *inc_start - '0';
181 }
182 if (inc_end == std::end(q)) {
183 break;
184 }
185 p = inc_end + 1;
186 continue;
187 }
188
189 p = std::find(p, std::end(q), '&');
190 if (p == std::end(q)) {
191 break;
192 }
193 ++p;
194 }
195 }
196 return req;
197 }
198 } // namespace
199
200 enum FileEntryFlag {
201 FILE_ENTRY_TYPE_DIR = 0x1,
202 };
203
204 struct FileEntry {
205 uint64_t len;
206 void *map;
207 int fd;
208 uint8_t flags;
209 };
210
211 namespace {
212 std::unordered_map<std::string, FileEntry> file_cache;
213 } // namespace
214
open_file(const std::string & path)215 std::pair<FileEntry, int> Stream::open_file(const std::string &path) {
216 auto it = file_cache.find(path);
217 if (it != std::end(file_cache)) {
218 return {(*it).second, 0};
219 }
220
221 auto fd = open(path.c_str(), O_RDONLY);
222 if (fd == -1) {
223 return {{}, -1};
224 }
225
226 struct stat st {};
227 if (fstat(fd, &st) != 0) {
228 close(fd);
229 return {{}, -1};
230 }
231
232 FileEntry fe{};
233 if (st.st_mode & S_IFDIR) {
234 fe.flags |= FILE_ENTRY_TYPE_DIR;
235 fe.fd = -1;
236 close(fd);
237 } else {
238 fe.fd = fd;
239 fe.len = st.st_size;
240 fe.map = mmap(nullptr, fe.len, PROT_READ, MAP_SHARED, fd, 0);
241 if (fe.map == MAP_FAILED) {
242 std::cerr << "mmap: " << strerror(errno) << std::endl;
243 close(fd);
244 return {{}, -1};
245 }
246 }
247
248 file_cache.emplace(path, fe);
249
250 return {std::move(fe), 0};
251 }
252
map_file(const FileEntry & fe)253 void Stream::map_file(const FileEntry &fe) {
254 respbuf.begin = respbuf.pos = static_cast<uint8_t *>(fe.map);
255 respbuf.end = respbuf.last = respbuf.begin + fe.len;
256 }
257
send_status_response(unsigned int status_code)258 int Stream::send_status_response(unsigned int status_code) {
259 status_resp_body = make_status_body(status_code);
260
261 respbuf.begin = respbuf.pos =
262 reinterpret_cast<uint8_t *>(status_resp_body.data());
263 respbuf.end = respbuf.last = respbuf.begin + status_resp_body.size();
264
265 handler->add_sendq(this);
266 handler->shutdown_read(stream_id, 0);
267
268 return 0;
269 }
270
start_response()271 int Stream::start_response() {
272 if (uri.empty()) {
273 return send_status_response(400);
274 }
275
276 auto req = request_path(uri);
277 if (req.path.empty()) {
278 return send_status_response(400);
279 }
280
281 auto path = config.htdocs + req.path;
282 auto [fe, rv] = open_file(path);
283 if (rv != 0) {
284 send_status_response(404);
285 return 0;
286 }
287
288 if (fe.flags & FILE_ENTRY_TYPE_DIR) {
289 send_status_response(308);
290 return 0;
291 }
292
293 map_file(fe);
294
295 if (!config.quiet) {
296 std::array<nghttp3_nv, 1> nva{
297 util::make_nv(":status", "200"),
298 };
299
300 debug::print_http_response_headers(stream_id, nva.data(), nva.size());
301 }
302
303 handler->add_sendq(this);
304
305 return 0;
306 }
307
308 namespace {
writecb(struct ev_loop * loop,ev_io * w,int revents)309 void writecb(struct ev_loop *loop, ev_io *w, int revents) {
310 ev_io_stop(loop, w);
311
312 auto h = static_cast<Handler *>(w->data);
313 auto s = h->server();
314
315 switch (h->on_write()) {
316 case 0:
317 case NETWORK_ERR_CLOSE_WAIT:
318 return;
319 default:
320 s->remove(h);
321 }
322 }
323 } // namespace
324
325 namespace {
timeoutcb(struct ev_loop * loop,ev_timer * w,int revents)326 void timeoutcb(struct ev_loop *loop, ev_timer *w, int revents) {
327 auto h = static_cast<Handler *>(w->data);
328 auto s = h->server();
329
330 if (ngtcp2_conn_is_in_closing_period(h->conn())) {
331 if (!config.quiet) {
332 std::cerr << "Closing Period is over" << std::endl;
333 }
334
335 s->remove(h);
336 return;
337 }
338 if (h->draining()) {
339 if (!config.quiet) {
340 std::cerr << "Draining Period is over" << std::endl;
341 }
342
343 s->remove(h);
344 return;
345 }
346
347 if (!config.quiet) {
348 std::cerr << "Timeout" << std::endl;
349 }
350
351 h->start_draining_period();
352 }
353 } // namespace
354
355 namespace {
retransmitcb(struct ev_loop * loop,ev_timer * w,int revents)356 void retransmitcb(struct ev_loop *loop, ev_timer *w, int revents) {
357 int rv;
358
359 auto h = static_cast<Handler *>(w->data);
360 auto s = h->server();
361
362 if (!config.quiet) {
363 std::cerr << "Timer expired" << std::endl;
364 }
365
366 rv = h->handle_expiry();
367 if (rv != 0) {
368 goto fail;
369 }
370
371 rv = h->on_write();
372 if (rv != 0) {
373 goto fail;
374 }
375
376 return;
377
378 fail:
379 switch (rv) {
380 case NETWORK_ERR_CLOSE_WAIT:
381 ev_timer_stop(loop, w);
382 return;
383 default:
384 s->remove(h);
385 return;
386 }
387 }
388 } // namespace
389
Handler(struct ev_loop * loop,Server * server)390 Handler::Handler(struct ev_loop *loop, Server *server)
391 : loop_(loop),
392 server_(server),
393 qlog_(nullptr),
394 scid_{},
395 nkey_update_(0),
396 draining_(false) {
397 ev_io_init(&wev_, writecb, 0, EV_WRITE);
398 wev_.data = this;
399 ev_timer_init(&timer_, timeoutcb, 0.,
400 static_cast<double>(config.timeout) / NGTCP2_SECONDS);
401 timer_.data = this;
402 ev_timer_init(&rttimer_, retransmitcb, 0., 0.);
403 rttimer_.data = this;
404 }
405
~Handler()406 Handler::~Handler() {
407 if (!config.quiet) {
408 std::cerr << scid_ << " Closing QUIC connection " << std::endl;
409 }
410
411 ev_timer_stop(loop_, &rttimer_);
412 ev_timer_stop(loop_, &timer_);
413 ev_io_stop(loop_, &wev_);
414
415 if (qlog_) {
416 fclose(qlog_);
417 }
418 }
419
420 namespace {
handshake_completed(ngtcp2_conn * conn,void * user_data)421 int handshake_completed(ngtcp2_conn *conn, void *user_data) {
422 auto h = static_cast<Handler *>(user_data);
423
424 if (!config.quiet) {
425 debug::handshake_completed(conn, user_data);
426 }
427
428 if (h->handshake_completed() != 0) {
429 return NGTCP2_ERR_CALLBACK_FAILURE;
430 }
431
432 return 0;
433 }
434 } // namespace
435
handshake_completed()436 int Handler::handshake_completed() {
437 if (!config.quiet) {
438 std::cerr << "Negotiated cipher suite is " << tls_session_.get_cipher_name()
439 << std::endl;
440 std::cerr << "Negotiated ALPN is " << tls_session_.get_selected_alpn()
441 << std::endl;
442 }
443
444 std::array<uint8_t, NGTCP2_CRYPTO_MAX_REGULAR_TOKENLEN> token;
445
446 auto path = ngtcp2_conn_get_path(conn_);
447 auto t = std::chrono::duration_cast<std::chrono::nanoseconds>(
448 std::chrono::system_clock::now().time_since_epoch())
449 .count();
450
451 auto tokenlen = ngtcp2_crypto_generate_regular_token(
452 token.data(), config.static_secret.data(), config.static_secret.size(),
453 path->remote.addr, path->remote.addrlen, t);
454 if (tokenlen < 0) {
455 if (!config.quiet) {
456 std::cerr << "Unable to generate token" << std::endl;
457 }
458 return 0;
459 }
460
461 if (auto rv = ngtcp2_conn_submit_new_token(conn_, token.data(), tokenlen);
462 rv != 0) {
463 if (!config.quiet) {
464 std::cerr << "ngtcp2_conn_submit_new_token: " << ngtcp2_strerror(rv)
465 << std::endl;
466 }
467 return -1;
468 }
469
470 return 0;
471 }
472
473 namespace {
do_hp_mask(uint8_t * dest,const ngtcp2_crypto_cipher * hp,const ngtcp2_crypto_cipher_ctx * hp_ctx,const uint8_t * sample)474 int do_hp_mask(uint8_t *dest, const ngtcp2_crypto_cipher *hp,
475 const ngtcp2_crypto_cipher_ctx *hp_ctx, const uint8_t *sample) {
476 if (ngtcp2_crypto_hp_mask(dest, hp, hp_ctx, sample) != 0) {
477 return NGTCP2_ERR_CALLBACK_FAILURE;
478 }
479
480 if (!config.quiet && config.show_secret) {
481 debug::print_hp_mask(dest, NGTCP2_HP_MASKLEN, sample, NGTCP2_HP_SAMPLELEN);
482 }
483
484 return 0;
485 }
486 } // namespace
487
488 namespace {
recv_crypto_data(ngtcp2_conn * conn,ngtcp2_crypto_level crypto_level,uint64_t offset,const uint8_t * data,size_t datalen,void * user_data)489 int recv_crypto_data(ngtcp2_conn *conn, ngtcp2_crypto_level crypto_level,
490 uint64_t offset, const uint8_t *data, size_t datalen,
491 void *user_data) {
492 if (!config.quiet && !config.no_quic_dump) {
493 debug::print_crypto_data(crypto_level, data, datalen);
494 }
495
496 return ngtcp2_crypto_recv_crypto_data_cb(conn, crypto_level, offset, data,
497 datalen, user_data);
498 }
499 } // namespace
500
501 namespace {
recv_stream_data(ngtcp2_conn * conn,uint32_t flags,int64_t stream_id,uint64_t offset,const uint8_t * data,size_t datalen,void * user_data,void * stream_user_data)502 int recv_stream_data(ngtcp2_conn *conn, uint32_t flags, int64_t stream_id,
503 uint64_t offset, const uint8_t *data, size_t datalen,
504 void *user_data, void *stream_user_data) {
505 auto h = static_cast<Handler *>(user_data);
506
507 if (h->recv_stream_data(flags, stream_id, data, datalen) != 0) {
508 return NGTCP2_ERR_CALLBACK_FAILURE;
509 }
510
511 return 0;
512 }
513 } // namespace
514
515 namespace {
acked_stream_data_offset(ngtcp2_conn * conn,int64_t stream_id,uint64_t offset,uint64_t datalen,void * user_data,void * stream_user_data)516 int acked_stream_data_offset(ngtcp2_conn *conn, int64_t stream_id,
517 uint64_t offset, uint64_t datalen, void *user_data,
518 void *stream_user_data) {
519 auto h = static_cast<Handler *>(user_data);
520 if (h->acked_stream_data_offset(stream_id, offset, datalen) != 0) {
521 return NGTCP2_ERR_CALLBACK_FAILURE;
522 }
523 return 0;
524 }
525 } // namespace
526
acked_stream_data_offset(int64_t stream_id,uint64_t offset,uint64_t datalen)527 int Handler::acked_stream_data_offset(int64_t stream_id, uint64_t offset,
528 uint64_t datalen) {
529 auto it = streams_.find(stream_id);
530 assert(it != std::end(streams_));
531 auto &stream = (*it).second;
532 (void)stream;
533
534 assert(static_cast<uint64_t>(stream->respbuf.end - stream->respbuf.begin) >=
535 offset + datalen);
536
537 return 0;
538 }
539
540 namespace {
stream_open(ngtcp2_conn * conn,int64_t stream_id,void * user_data)541 int stream_open(ngtcp2_conn *conn, int64_t stream_id, void *user_data) {
542 auto h = static_cast<Handler *>(user_data);
543 h->on_stream_open(stream_id);
544 return 0;
545 }
546 } // namespace
547
on_stream_open(int64_t stream_id)548 void Handler::on_stream_open(int64_t stream_id) {
549 if (!ngtcp2_is_bidi_stream(stream_id)) {
550 return;
551 }
552 auto it = streams_.find(stream_id);
553 (void)it;
554 assert(it == std::end(streams_));
555 streams_.emplace(stream_id, std::make_unique<Stream>(stream_id, this));
556 }
557
558 namespace {
stream_close(ngtcp2_conn * conn,uint32_t flags,int64_t stream_id,uint64_t app_error_code,void * user_data,void * stream_user_data)559 int stream_close(ngtcp2_conn *conn, uint32_t flags, int64_t stream_id,
560 uint64_t app_error_code, void *user_data,
561 void *stream_user_data) {
562 auto h = static_cast<Handler *>(user_data);
563 if (h->on_stream_close(stream_id, app_error_code) != 0) {
564 return NGTCP2_ERR_CALLBACK_FAILURE;
565 }
566 return 0;
567 }
568 } // namespace
569
570 namespace {
rand(uint8_t * dest,size_t destlen,const ngtcp2_rand_ctx * rand_ctx)571 void rand(uint8_t *dest, size_t destlen, const ngtcp2_rand_ctx *rand_ctx) {
572 auto dis = std::uniform_int_distribution<uint8_t>(0, 255);
573 std::generate(dest, dest + destlen, [&dis]() { return dis(randgen); });
574 }
575 } // namespace
576
577 namespace {
get_new_connection_id(ngtcp2_conn * conn,ngtcp2_cid * cid,uint8_t * token,size_t cidlen,void * user_data)578 int get_new_connection_id(ngtcp2_conn *conn, ngtcp2_cid *cid, uint8_t *token,
579 size_t cidlen, void *user_data) {
580 if (util::generate_secure_random(cid->data, cidlen) != 0) {
581 return NGTCP2_ERR_CALLBACK_FAILURE;
582 }
583
584 cid->datalen = cidlen;
585 if (ngtcp2_crypto_generate_stateless_reset_token(
586 token, config.static_secret.data(), config.static_secret.size(),
587 cid) != 0) {
588 return NGTCP2_ERR_CALLBACK_FAILURE;
589 }
590
591 auto h = static_cast<Handler *>(user_data);
592 h->server()->associate_cid(cid, h);
593
594 return 0;
595 }
596 } // namespace
597
598 namespace {
remove_connection_id(ngtcp2_conn * conn,const ngtcp2_cid * cid,void * user_data)599 int remove_connection_id(ngtcp2_conn *conn, const ngtcp2_cid *cid,
600 void *user_data) {
601 auto h = static_cast<Handler *>(user_data);
602 h->server()->dissociate_cid(cid);
603 return 0;
604 }
605 } // namespace
606
607 namespace {
update_key(ngtcp2_conn * conn,uint8_t * rx_secret,uint8_t * tx_secret,ngtcp2_crypto_aead_ctx * rx_aead_ctx,uint8_t * rx_iv,ngtcp2_crypto_aead_ctx * tx_aead_ctx,uint8_t * tx_iv,const uint8_t * current_rx_secret,const uint8_t * current_tx_secret,size_t secretlen,void * user_data)608 int update_key(ngtcp2_conn *conn, uint8_t *rx_secret, uint8_t *tx_secret,
609 ngtcp2_crypto_aead_ctx *rx_aead_ctx, uint8_t *rx_iv,
610 ngtcp2_crypto_aead_ctx *tx_aead_ctx, uint8_t *tx_iv,
611 const uint8_t *current_rx_secret,
612 const uint8_t *current_tx_secret, size_t secretlen,
613 void *user_data) {
614 auto h = static_cast<Handler *>(user_data);
615 if (h->update_key(rx_secret, tx_secret, rx_aead_ctx, rx_iv, tx_aead_ctx,
616 tx_iv, current_rx_secret, current_tx_secret,
617 secretlen) != 0) {
618 return NGTCP2_ERR_CALLBACK_FAILURE;
619 }
620 return 0;
621 }
622 } // namespace
623
624 namespace {
path_validation(ngtcp2_conn * conn,uint32_t flags,const ngtcp2_path * path,ngtcp2_path_validation_result res,void * user_data)625 int path_validation(ngtcp2_conn *conn, uint32_t flags, const ngtcp2_path *path,
626 ngtcp2_path_validation_result res, void *user_data) {
627 if (!config.quiet) {
628 debug::path_validation(path, res);
629 }
630 return 0;
631 }
632 } // namespace
633
634 namespace {
extend_max_stream_data(ngtcp2_conn * conn,int64_t stream_id,uint64_t max_data,void * user_data,void * stream_user_data)635 int extend_max_stream_data(ngtcp2_conn *conn, int64_t stream_id,
636 uint64_t max_data, void *user_data,
637 void *stream_user_data) {
638 auto h = static_cast<Handler *>(user_data);
639 if (h->extend_max_stream_data(stream_id, max_data) != 0) {
640 return NGTCP2_ERR_CALLBACK_FAILURE;
641 }
642 return 0;
643 }
644 } // namespace
645
extend_max_stream_data(int64_t stream_id,uint64_t max_data)646 int Handler::extend_max_stream_data(int64_t stream_id, uint64_t max_data) {
647 auto it = streams_.find(stream_id);
648 assert(it != std::end(streams_));
649 auto &stream = (*it).second;
650
651 if (nghttp3_buf_len(&stream->respbuf)) {
652 sendq_.emplace(stream.get());
653 }
654
655 return 0;
656 }
657
658 namespace {
write_qlog(void * user_data,uint32_t flags,const void * data,size_t datalen)659 void write_qlog(void *user_data, uint32_t flags, const void *data,
660 size_t datalen) {
661 auto h = static_cast<Handler *>(user_data);
662 h->write_qlog(data, datalen);
663 }
664 } // namespace
665
write_qlog(const void * data,size_t datalen)666 void Handler::write_qlog(const void *data, size_t datalen) {
667 assert(qlog_);
668 fwrite(data, 1, datalen, qlog_);
669 }
670
init(const Endpoint & ep,const Address & local_addr,const sockaddr * sa,socklen_t salen,const ngtcp2_cid * dcid,const ngtcp2_cid * scid,const ngtcp2_cid * ocid,const uint8_t * token,size_t tokenlen,uint32_t version,const TLSServerContext & tls_ctx)671 int Handler::init(const Endpoint &ep, const Address &local_addr,
672 const sockaddr *sa, socklen_t salen, const ngtcp2_cid *dcid,
673 const ngtcp2_cid *scid, const ngtcp2_cid *ocid,
674 const uint8_t *token, size_t tokenlen, uint32_t version,
675 const TLSServerContext &tls_ctx) {
676 auto callbacks = ngtcp2_callbacks{
677 nullptr, // client_initial
678 ngtcp2_crypto_recv_client_initial_cb,
679 ::recv_crypto_data,
680 ::handshake_completed,
681 nullptr, // recv_version_negotiation
682 ngtcp2_crypto_encrypt_cb,
683 ngtcp2_crypto_decrypt_cb,
684 do_hp_mask,
685 ::recv_stream_data,
686 ::acked_stream_data_offset,
687 stream_open,
688 stream_close,
689 nullptr, // recv_stateless_reset
690 nullptr, // recv_retry
691 nullptr, // extend_max_streams_bidi
692 nullptr, // extend_max_streams_uni
693 rand,
694 get_new_connection_id,
695 remove_connection_id,
696 ::update_key,
697 path_validation,
698 nullptr, // select_preferred_addr
699 nullptr, // stream_reset
700 nullptr, // extend_max_remote_streams_bidi
701 nullptr, // extend_max_remote_streams_uni
702 ::extend_max_stream_data,
703 nullptr, // dcid_status
704 nullptr, // handshake_confirmed
705 nullptr, // recv_new_token
706 ngtcp2_crypto_delete_crypto_aead_ctx_cb,
707 ngtcp2_crypto_delete_crypto_cipher_ctx_cb,
708 nullptr, // recv_datagram
709 nullptr, // ack_datagram
710 nullptr, // lost_datagram
711 ngtcp2_crypto_get_path_challenge_data_cb,
712 };
713
714 scid_.datalen = NGTCP2_SV_SCIDLEN;
715 if (util::generate_secure_random(scid_.data, scid_.datalen) != 0) {
716 std::cerr << "Could not generate connection ID" << std::endl;
717 return -1;
718 }
719
720 ngtcp2_settings settings;
721 ngtcp2_settings_default(&settings);
722 settings.log_printf = config.quiet ? nullptr : debug::log_printf;
723 settings.initial_ts = util::timestamp(loop_);
724 settings.token = ngtcp2_vec{const_cast<uint8_t *>(token), tokenlen};
725 settings.cc_algo = config.cc_algo;
726 settings.initial_rtt = config.initial_rtt;
727 if (config.max_udp_payload_size) {
728 settings.max_udp_payload_size = config.max_udp_payload_size;
729 settings.no_udp_payload_size_shaping = 1;
730 } else {
731 settings.max_udp_payload_size = server_max_udp_payload_size;
732 settings.assume_symmetric_path = 1;
733 }
734 if (!config.qlog_dir.empty()) {
735 auto path = std::string{config.qlog_dir};
736 path += '/';
737 path += util::format_hex(scid_.data, scid_.datalen);
738 path += ".sqlog";
739 qlog_ = fopen(path.c_str(), "w");
740 if (qlog_ == nullptr) {
741 std::cerr << "Could not open qlog file " << std::quoted(path) << ": "
742 << strerror(errno) << std::endl;
743 return -1;
744 }
745 settings.qlog.write = ::write_qlog;
746 settings.qlog.odcid = *scid;
747 }
748
749 ngtcp2_transport_params params;
750 ngtcp2_transport_params_default(¶ms);
751 params.initial_max_stream_data_bidi_local = config.max_stream_data_bidi_local;
752 params.initial_max_stream_data_bidi_remote =
753 config.max_stream_data_bidi_remote;
754 params.initial_max_stream_data_uni = config.max_stream_data_uni;
755 params.initial_max_data = config.max_data;
756 params.initial_max_streams_bidi = config.max_streams_bidi;
757 params.initial_max_streams_uni = 0;
758 params.max_idle_timeout = config.timeout;
759 params.stateless_reset_token_present = 1;
760 params.active_connection_id_limit = 7;
761
762 if (ocid) {
763 params.original_dcid = *ocid;
764 params.retry_scid = *scid;
765 params.retry_scid_present = 1;
766 } else {
767 params.original_dcid = *scid;
768 }
769
770 if (util::generate_secure_random(params.stateless_reset_token,
771 sizeof(params.stateless_reset_token)) != 0) {
772 std::cerr << "Could not generate stateless reset token" << std::endl;
773 return -1;
774 }
775
776 if (config.preferred_ipv4_addr.len || config.preferred_ipv6_addr.len) {
777 params.preferred_address_present = 1;
778 if (config.preferred_ipv4_addr.len) {
779 auto &dest = params.preferred_address.ipv4_addr;
780 const auto &addr = config.preferred_ipv4_addr;
781 assert(sizeof(dest) == sizeof(addr.su.in.sin_addr));
782 memcpy(&dest, &addr.su.in.sin_addr, sizeof(dest));
783 params.preferred_address.ipv4_port = htons(addr.su.in.sin_port);
784 params.preferred_address.ipv4_present = 1;
785 }
786 if (config.preferred_ipv6_addr.len) {
787 auto &dest = params.preferred_address.ipv6_addr;
788 const auto &addr = config.preferred_ipv6_addr;
789 assert(sizeof(dest) == sizeof(addr.su.in6.sin6_addr));
790 memcpy(&dest, &addr.su.in6.sin6_addr, sizeof(dest));
791 params.preferred_address.ipv6_port = htons(addr.su.in6.sin6_port);
792 params.preferred_address.ipv6_present = 1;
793 }
794
795 auto &token = params.preferred_address.stateless_reset_token;
796 if (util::generate_secure_random(token, sizeof(token)) != 0) {
797 std::cerr << "Could not generate preferred address stateless reset token"
798 << std::endl;
799 return -1;
800 }
801
802 params.preferred_address.cid.datalen = NGTCP2_SV_SCIDLEN;
803 if (util::generate_secure_random(params.preferred_address.cid.data,
804 params.preferred_address.cid.datalen) !=
805 0) {
806 std::cerr << "Could not generate preferred address connection ID"
807 << std::endl;
808 return -1;
809 }
810 }
811
812 auto path = ngtcp2_path{
813 {
814 const_cast<sockaddr *>(&local_addr.su.sa),
815 local_addr.len,
816 },
817 {
818 const_cast<sockaddr *>(sa),
819 salen,
820 },
821 const_cast<Endpoint *>(&ep),
822 };
823 if (auto rv =
824 ngtcp2_conn_server_new(&conn_, dcid, &scid_, &path, version,
825 &callbacks, &settings, ¶ms, nullptr, this);
826 rv != 0) {
827 std::cerr << "ngtcp2_conn_server_new: " << ngtcp2_strerror(rv) << std::endl;
828 return -1;
829 }
830
831 if (tls_session_.init(tls_ctx, this) != 0) {
832 return -1;
833 }
834
835 tls_session_.enable_keylog();
836
837 ngtcp2_conn_set_tls_native_handle(conn_, tls_session_.get_native_handle());
838
839 ev_io_set(&wev_, ep.fd, EV_WRITE);
840 ev_timer_again(loop_, &timer_);
841
842 return 0;
843 }
844
feed_data(const Endpoint & ep,const Address & local_addr,const sockaddr * sa,socklen_t salen,const ngtcp2_pkt_info * pi,uint8_t * data,size_t datalen)845 int Handler::feed_data(const Endpoint &ep, const Address &local_addr,
846 const sockaddr *sa, socklen_t salen,
847 const ngtcp2_pkt_info *pi, uint8_t *data,
848 size_t datalen) {
849 auto path = ngtcp2_path{
850 {
851 const_cast<sockaddr *>(&local_addr.su.sa),
852 local_addr.len,
853 },
854 {
855 const_cast<sockaddr *>(sa),
856 salen,
857 },
858 const_cast<Endpoint *>(&ep),
859 };
860
861 if (auto rv = ngtcp2_conn_read_pkt(conn_, &path, pi, data, datalen,
862 util::timestamp(loop_));
863 rv != 0) {
864 std::cerr << "ngtcp2_conn_read_pkt: " << ngtcp2_strerror(rv) << std::endl;
865 switch (rv) {
866 case NGTCP2_ERR_DRAINING:
867 start_draining_period();
868 return NETWORK_ERR_CLOSE_WAIT;
869 case NGTCP2_ERR_RETRY:
870 return NETWORK_ERR_RETRY;
871 case NGTCP2_ERR_REQUIRED_TRANSPORT_PARAM:
872 case NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM:
873 case NGTCP2_ERR_TRANSPORT_PARAM:
874 // If rv indicates transport_parameters related error, we should
875 // send TRANSPORT_PARAMETER_ERROR even if last_error_.code is
876 // already set. This is because OpenSSL might set Alert.
877 last_error_ = quic_err_transport(rv);
878 break;
879 case NGTCP2_ERR_DROP_CONN:
880 return NETWORK_ERR_DROP_CONN;
881 default:
882 if (!last_error_.code) {
883 last_error_ = quic_err_transport(rv);
884 }
885 }
886 return handle_error();
887 }
888
889 return 0;
890 }
891
on_read(const Endpoint & ep,const Address & local_addr,const sockaddr * sa,socklen_t salen,const ngtcp2_pkt_info * pi,uint8_t * data,size_t datalen)892 int Handler::on_read(const Endpoint &ep, const Address &local_addr,
893 const sockaddr *sa, socklen_t salen,
894 const ngtcp2_pkt_info *pi, uint8_t *data, size_t datalen) {
895 if (auto rv = feed_data(ep, local_addr, sa, salen, pi, data, datalen);
896 rv != 0) {
897 return rv;
898 }
899
900 reset_idle_timer();
901
902 return 0;
903 }
904
reset_idle_timer()905 void Handler::reset_idle_timer() {
906 auto now = util::timestamp(loop_);
907 auto idle_expiry = ngtcp2_conn_get_idle_expiry(conn_);
908 timer_.repeat =
909 idle_expiry > now
910 ? static_cast<ev_tstamp>(idle_expiry - now) / NGTCP2_SECONDS
911 : 1e-9;
912
913 if (!config.quiet) {
914 std::cerr << "Set idle timer=" << std::fixed << timer_.repeat << "s"
915 << std::defaultfloat << std::endl;
916 }
917
918 ev_timer_again(loop_, &timer_);
919 }
920
handle_expiry()921 int Handler::handle_expiry() {
922 auto now = util::timestamp(loop_);
923 if (auto rv = ngtcp2_conn_handle_expiry(conn_, now); rv != 0) {
924 std::cerr << "ngtcp2_conn_handle_expiry: " << ngtcp2_strerror(rv)
925 << std::endl;
926 last_error_ = quic_err_transport(rv);
927 return handle_error();
928 }
929
930 return 0;
931 }
932
on_write()933 int Handler::on_write() {
934 if (ngtcp2_conn_is_in_closing_period(conn_) ||
935 ngtcp2_conn_is_in_draining_period(conn_)) {
936 return 0;
937 }
938
939 if (auto rv = write_streams(); rv != 0) {
940 return rv;
941 }
942
943 schedule_retransmit();
944
945 return 0;
946 }
947
write_streams()948 int Handler::write_streams() {
949 ngtcp2_vec vec;
950 ngtcp2_path_storage ps, prev_ps;
951 uint32_t prev_ecn = 0;
952 size_t pktcnt = 0;
953 auto max_udp_payload_size = ngtcp2_conn_get_path_max_udp_payload_size(conn_);
954 size_t max_pktcnt =
955 std::min(static_cast<size_t>(64_k), ngtcp2_conn_get_send_quantum(conn_)) /
956 max_udp_payload_size;
957 std::array<uint8_t, 64_k> buf;
958 uint8_t *bufpos = buf.data();
959 ngtcp2_pkt_info pi;
960 auto ts = util::timestamp(loop_);
961
962 ngtcp2_path_storage_zero(&ps);
963 ngtcp2_path_storage_zero(&prev_ps);
964
965 if (config.cc_algo != NGTCP2_CC_ALGO_BBR) {
966 /* If bbr is chosen, pacing is enabled. No need to cap the number
967 of datagrams to send. */
968 max_pktcnt =
969 std::min(max_pktcnt, static_cast<size_t>(config.max_gso_dgrams));
970 }
971
972 for (;;) {
973 int64_t stream_id = -1;
974 size_t vcnt = 0;
975 uint32_t flags = NGTCP2_WRITE_STREAM_FLAG_MORE;
976 Stream *stream = nullptr;
977
978 if (!sendq_.empty() && ngtcp2_conn_get_max_data_left(conn_)) {
979 stream = *std::begin(sendq_);
980
981 stream_id = stream->stream_id;
982 vec.base = stream->respbuf.pos;
983 vec.len = nghttp3_buf_len(&stream->respbuf);
984 vcnt = 1;
985 flags |= NGTCP2_WRITE_STREAM_FLAG_FIN;
986 }
987
988 ngtcp2_ssize ndatalen;
989
990 auto nwrite = ngtcp2_conn_writev_stream(conn_, &ps.path, &pi, bufpos,
991 max_udp_payload_size, &ndatalen,
992 flags, stream_id, &vec, vcnt, ts);
993 if (nwrite < 0) {
994 switch (nwrite) {
995 case NGTCP2_ERR_STREAM_DATA_BLOCKED:
996 case NGTCP2_ERR_STREAM_SHUT_WR:
997 assert(ndatalen == -1);
998 sendq_.erase(std::begin(sendq_));
999 continue;
1000 case NGTCP2_ERR_WRITE_MORE:
1001 assert(ndatalen >= 0);
1002 stream->respbuf.pos += ndatalen;
1003 if (nghttp3_buf_len(&stream->respbuf) == 0) {
1004 sendq_.erase(std::begin(sendq_));
1005 }
1006 continue;
1007 }
1008
1009 assert(ndatalen == -1);
1010
1011 std::cerr << "ngtcp2_conn_writev_stream: " << ngtcp2_strerror(nwrite)
1012 << std::endl;
1013 last_error_ = quic_err_transport(nwrite);
1014 return handle_error();
1015 } else if (ndatalen >= 0) {
1016 stream->respbuf.pos += ndatalen;
1017 if (nghttp3_buf_len(&stream->respbuf) == 0) {
1018 sendq_.erase(std::begin(sendq_));
1019 }
1020 }
1021
1022 if (nwrite == 0) {
1023 if (bufpos - buf.data()) {
1024 server_->send_packet(*static_cast<Endpoint *>(prev_ps.path.user_data),
1025 prev_ps.path.local, prev_ps.path.remote, prev_ecn,
1026 buf.data(), bufpos - buf.data(),
1027 max_udp_payload_size);
1028 reset_idle_timer();
1029 }
1030 // We are congestion limited.
1031 ngtcp2_conn_update_pkt_tx_time(conn_, ts);
1032 return 0;
1033 }
1034
1035 bufpos += nwrite;
1036
1037 #if NGTCP2_ENABLE_UDP_GSO
1038 if (pktcnt == 0) {
1039 ngtcp2_path_copy(&prev_ps.path, &ps.path);
1040 prev_ecn = pi.ecn;
1041 } else if (!ngtcp2_path_eq(&prev_ps.path, &ps.path) || prev_ecn != pi.ecn) {
1042 server_->send_packet(*static_cast<Endpoint *>(prev_ps.path.user_data),
1043 prev_ps.path.local, prev_ps.path.remote, prev_ecn,
1044 buf.data(), bufpos - buf.data() - nwrite,
1045 max_udp_payload_size);
1046
1047 server_->send_packet(*static_cast<Endpoint *>(ps.path.user_data),
1048 ps.path.local, ps.path.remote, pi.ecn,
1049 bufpos - nwrite, nwrite, max_udp_payload_size);
1050 ngtcp2_conn_update_pkt_tx_time(conn_, ts);
1051 reset_idle_timer();
1052 ev_io_start(loop_, &wev_);
1053 return 0;
1054 }
1055
1056 if (++pktcnt == max_pktcnt ||
1057 static_cast<size_t>(nwrite) < max_udp_payload_size) {
1058 server_->send_packet(*static_cast<Endpoint *>(ps.path.user_data),
1059 ps.path.local, ps.path.remote, pi.ecn, buf.data(),
1060 bufpos - buf.data(), max_udp_payload_size);
1061 ngtcp2_conn_update_pkt_tx_time(conn_, ts);
1062 reset_idle_timer();
1063 ev_io_start(loop_, &wev_);
1064 return 0;
1065 }
1066 #else // !NGTCP2_ENABLE_UDP_GSO
1067 reset_idle_timer();
1068
1069 server_->send_packet(*static_cast<Endpoint *>(ps.path.user_data),
1070 ps.path.local, ps.path.remote, pi.ecn, buf.data(),
1071 bufpos - buf.data(), 0);
1072 if (++pktcnt == max_pktcnt) {
1073 ngtcp2_conn_update_pkt_tx_time(conn_, ts);
1074 ev_io_start(loop_, &wev_);
1075 return 0;
1076 }
1077
1078 bufpos = buf.data();
1079 #endif // !NGTCP2_ENABLE_UDP_GSO
1080 }
1081 }
1082
signal_write()1083 void Handler::signal_write() { ev_io_start(loop_, &wev_); }
1084
draining() const1085 bool Handler::draining() const { return draining_; }
1086
start_draining_period()1087 void Handler::start_draining_period() {
1088 draining_ = true;
1089
1090 ev_timer_stop(loop_, &rttimer_);
1091
1092 timer_.repeat =
1093 static_cast<ev_tstamp>(ngtcp2_conn_get_pto(conn_)) / NGTCP2_SECONDS * 3;
1094 ev_timer_again(loop_, &timer_);
1095
1096 if (!config.quiet) {
1097 std::cerr << "Draining period has started (" << timer_.repeat << " seconds)"
1098 << std::endl;
1099 }
1100 }
1101
start_closing_period()1102 int Handler::start_closing_period() {
1103 if (!conn_ || ngtcp2_conn_is_in_closing_period(conn_)) {
1104 return 0;
1105 }
1106
1107 ev_timer_stop(loop_, &rttimer_);
1108
1109 timer_.repeat =
1110 static_cast<ev_tstamp>(ngtcp2_conn_get_pto(conn_)) / NGTCP2_SECONDS * 3;
1111 ev_timer_again(loop_, &timer_);
1112
1113 if (!config.quiet) {
1114 std::cerr << "Closing period has started (" << timer_.repeat << " seconds)"
1115 << std::endl;
1116 }
1117
1118 conn_closebuf_ = std::make_unique<Buffer>(NGTCP2_MAX_UDP_PAYLOAD_SIZE);
1119
1120 ngtcp2_path_storage ps;
1121
1122 ngtcp2_path_storage_zero(&ps);
1123
1124 ngtcp2_pkt_info pi;
1125 if (last_error_.type == QUICErrorType::Transport) {
1126 auto n = ngtcp2_conn_write_connection_close(
1127 conn_, &ps.path, &pi, conn_closebuf_->wpos(), conn_closebuf_->left(),
1128 last_error_.code, util::timestamp(loop_));
1129 if (n < 0) {
1130 std::cerr << "ngtcp2_conn_write_connection_close: " << ngtcp2_strerror(n)
1131 << std::endl;
1132 return -1;
1133 }
1134 conn_closebuf_->push(n);
1135 } else {
1136 auto n = ngtcp2_conn_write_application_close(
1137 conn_, &ps.path, &pi, conn_closebuf_->wpos(), conn_closebuf_->left(),
1138 last_error_.code, util::timestamp(loop_));
1139 if (n < 0) {
1140 std::cerr << "ngtcp2_conn_write_application_close: " << ngtcp2_strerror(n)
1141 << std::endl;
1142 return -1;
1143 }
1144 conn_closebuf_->push(n);
1145 }
1146
1147 return 0;
1148 }
1149
handle_error()1150 int Handler::handle_error() {
1151 if (start_closing_period() != 0) {
1152 return -1;
1153 }
1154
1155 if (auto rv = send_conn_close(); rv != NETWORK_ERR_OK) {
1156 return rv;
1157 }
1158
1159 return NETWORK_ERR_CLOSE_WAIT;
1160 }
1161
send_conn_close()1162 int Handler::send_conn_close() {
1163 if (!config.quiet) {
1164 std::cerr << "Closing Period: TX CONNECTION_CLOSE" << std::endl;
1165 }
1166
1167 assert(conn_closebuf_ && conn_closebuf_->size());
1168 assert(conn_);
1169
1170 auto path = ngtcp2_conn_get_path(conn_);
1171
1172 return server_->send_packet(
1173 *static_cast<Endpoint *>(path->user_data), path->local, path->remote,
1174 /* ecn = */ 0, conn_closebuf_->rpos(), conn_closebuf_->size(), 0);
1175 }
1176
schedule_retransmit()1177 void Handler::schedule_retransmit() {
1178 auto expiry = ngtcp2_conn_get_expiry(conn_);
1179 auto now = util::timestamp(loop_);
1180 auto t = expiry < now ? 1e-9
1181 : static_cast<ev_tstamp>(expiry - now) / NGTCP2_SECONDS;
1182 if (!config.quiet) {
1183 std::cerr << "Set timer=" << std::fixed << t << "s" << std::defaultfloat
1184 << std::endl;
1185 }
1186 rttimer_.repeat = t;
1187 ev_timer_again(loop_, &rttimer_);
1188 }
1189
1190 namespace {
on_msg_begin(http_parser * htp)1191 int on_msg_begin(http_parser *htp) {
1192 auto s = static_cast<Stream *>(htp->data);
1193 if (s->eos) {
1194 return -1;
1195 }
1196 return 0;
1197 }
1198 } // namespace
1199
1200 namespace {
on_url_cb(http_parser * htp,const char * data,size_t datalen)1201 int on_url_cb(http_parser *htp, const char *data, size_t datalen) {
1202 auto s = static_cast<Stream *>(htp->data);
1203 s->uri.append(data, datalen);
1204 return 0;
1205 }
1206 } // namespace
1207
1208 namespace {
on_msg_complete(http_parser * htp)1209 int on_msg_complete(http_parser *htp) {
1210 auto s = static_cast<Stream *>(htp->data);
1211 s->eos = true;
1212 if (s->start_response() != 0) {
1213 return -1;
1214 }
1215 return 0;
1216 }
1217 } // namespace
1218
1219 auto htp_settings = http_parser_settings{
1220 on_msg_begin, // on_message_begin
1221 on_url_cb, // on_url
1222 nullptr, // on_status
1223 nullptr, // on_header_field
1224 nullptr, // on_header_value
1225 nullptr, // on_headers_complete
1226 nullptr, // on_body
1227 on_msg_complete, // on_message_complete
1228 nullptr, // on_chunk_header,
1229 nullptr, // on_chunk_complete
1230 };
1231
recv_stream_data(uint32_t flags,int64_t stream_id,const uint8_t * data,size_t datalen)1232 int Handler::recv_stream_data(uint32_t flags, int64_t stream_id,
1233 const uint8_t *data, size_t datalen) {
1234 if (!config.quiet && !config.no_quic_dump) {
1235 debug::print_stream_data(stream_id, data, datalen);
1236 }
1237
1238 auto it = streams_.find(stream_id);
1239 assert(it != std::end(streams_));
1240 auto &stream = (*it).second;
1241
1242 if (!stream->eos) {
1243 auto nread =
1244 http_parser_execute(&stream->htp, &htp_settings,
1245 reinterpret_cast<const char *>(data), datalen);
1246 if (nread != datalen) {
1247 if (auto rv = ngtcp2_conn_shutdown_stream(conn_, stream_id,
1248 /* app error code */ 1);
1249 rv != 0) {
1250 std::cerr << "ngtcp2_conn_shutdown_stream: " << ngtcp2_strerror(rv)
1251 << std::endl;
1252 last_error_ = quic_err_transport(NGTCP2_ERR_INTERNAL);
1253 return -1;
1254 }
1255 }
1256 }
1257
1258 ngtcp2_conn_extend_max_stream_offset(conn_, stream_id, datalen);
1259 ngtcp2_conn_extend_max_offset(conn_, datalen);
1260
1261 return 0;
1262 }
1263
update_key(uint8_t * rx_secret,uint8_t * tx_secret,ngtcp2_crypto_aead_ctx * rx_aead_ctx,uint8_t * rx_iv,ngtcp2_crypto_aead_ctx * tx_aead_ctx,uint8_t * tx_iv,const uint8_t * current_rx_secret,const uint8_t * current_tx_secret,size_t secretlen)1264 int Handler::update_key(uint8_t *rx_secret, uint8_t *tx_secret,
1265 ngtcp2_crypto_aead_ctx *rx_aead_ctx, uint8_t *rx_iv,
1266 ngtcp2_crypto_aead_ctx *tx_aead_ctx, uint8_t *tx_iv,
1267 const uint8_t *current_rx_secret,
1268 const uint8_t *current_tx_secret, size_t secretlen) {
1269 auto crypto_ctx = ngtcp2_conn_get_crypto_ctx(conn_);
1270 auto aead = &crypto_ctx->aead;
1271 auto keylen = ngtcp2_crypto_aead_keylen(aead);
1272 auto ivlen = ngtcp2_crypto_packet_protection_ivlen(aead);
1273
1274 ++nkey_update_;
1275
1276 std::array<uint8_t, 64> rx_key, tx_key;
1277
1278 if (ngtcp2_crypto_update_key(conn_, rx_secret, tx_secret, rx_aead_ctx,
1279 rx_key.data(), rx_iv, tx_aead_ctx, tx_key.data(),
1280 tx_iv, current_rx_secret, current_tx_secret,
1281 secretlen) != 0) {
1282 return -1;
1283 }
1284
1285 if (!config.quiet && config.show_secret) {
1286 std::cerr << "application_traffic rx secret " << nkey_update_ << std::endl;
1287 debug::print_secrets(rx_secret, secretlen, rx_key.data(), keylen, rx_iv,
1288 ivlen);
1289 std::cerr << "application_traffic tx secret " << nkey_update_ << std::endl;
1290 debug::print_secrets(tx_secret, secretlen, tx_key.data(), keylen, tx_iv,
1291 ivlen);
1292 }
1293
1294 return 0;
1295 }
1296
server() const1297 Server *Handler::server() const { return server_; }
1298
on_stream_close(int64_t stream_id,uint64_t app_error_code)1299 int Handler::on_stream_close(int64_t stream_id, uint64_t app_error_code) {
1300 if (!config.quiet) {
1301 std::cerr << "QUIC stream " << stream_id << " closed" << std::endl;
1302 }
1303
1304 auto it = streams_.find(stream_id);
1305 assert(it != std::end(streams_));
1306 auto &stream = (*it).second;
1307
1308 sendq_.erase(stream.get());
1309
1310 if (!config.quiet) {
1311 std::cerr << "HTTP stream " << stream_id << " closed with error code "
1312 << app_error_code << std::endl;
1313 }
1314
1315 streams_.erase(it);
1316
1317 if (ngtcp2_is_bidi_stream(stream_id)) {
1318 assert(!ngtcp2_conn_is_local_stream(conn_, stream_id));
1319 ngtcp2_conn_extend_max_streams_bidi(conn_, 1);
1320 }
1321
1322 return 0;
1323 }
1324
shutdown_read(int64_t stream_id,int app_error_code)1325 void Handler::shutdown_read(int64_t stream_id, int app_error_code) {
1326 ngtcp2_conn_shutdown_stream_read(conn_, stream_id, app_error_code);
1327 }
1328
add_sendq(Stream * stream)1329 void Handler::add_sendq(Stream *stream) { sendq_.emplace(stream); }
1330
1331 namespace {
sreadcb(struct ev_loop * loop,ev_io * w,int revents)1332 void sreadcb(struct ev_loop *loop, ev_io *w, int revents) {
1333 auto ep = static_cast<Endpoint *>(w->data);
1334
1335 ep->server->on_read(*ep);
1336 }
1337 } // namespace
1338
1339 namespace {
siginthandler(struct ev_loop * loop,ev_signal * watcher,int revents)1340 void siginthandler(struct ev_loop *loop, ev_signal *watcher, int revents) {
1341 ev_break(loop, EVBREAK_ALL);
1342 }
1343 } // namespace
1344
Server(struct ev_loop * loop,const TLSServerContext & tls_ctx)1345 Server::Server(struct ev_loop *loop, const TLSServerContext &tls_ctx)
1346 : loop_(loop), tls_ctx_(tls_ctx) {
1347 ev_signal_init(&sigintev_, siginthandler, SIGINT);
1348 }
1349
~Server()1350 Server::~Server() {
1351 disconnect();
1352 close();
1353 }
1354
disconnect()1355 void Server::disconnect() {
1356 config.tx_loss_prob = 0;
1357
1358 for (auto &ep : endpoints_) {
1359 ev_io_stop(loop_, &ep.rev);
1360 }
1361
1362 ev_signal_stop(loop_, &sigintev_);
1363
1364 while (!handlers_.empty()) {
1365 auto it = std::begin(handlers_);
1366 auto &h = (*it).second;
1367
1368 h->handle_error();
1369
1370 remove(h);
1371 }
1372 }
1373
close()1374 void Server::close() {
1375 for (auto &ep : endpoints_) {
1376 ::close(ep.fd);
1377 }
1378
1379 endpoints_.clear();
1380 }
1381
1382 namespace {
create_sock(Address & local_addr,const char * addr,const char * port,int family)1383 int create_sock(Address &local_addr, const char *addr, const char *port,
1384 int family) {
1385 addrinfo hints{};
1386 addrinfo *res, *rp;
1387 int val = 1;
1388
1389 hints.ai_family = family;
1390 hints.ai_socktype = SOCK_DGRAM;
1391 hints.ai_flags = AI_PASSIVE;
1392
1393 if (strcmp(addr, "*") == 0) {
1394 addr = nullptr;
1395 }
1396
1397 if (auto rv = getaddrinfo(addr, port, &hints, &res); rv != 0) {
1398 std::cerr << "getaddrinfo: " << gai_strerror(rv) << std::endl;
1399 return -1;
1400 }
1401
1402 auto res_d = defer(freeaddrinfo, res);
1403
1404 int fd = -1;
1405
1406 for (rp = res; rp; rp = rp->ai_next) {
1407 fd = util::create_nonblock_socket(rp->ai_family, rp->ai_socktype,
1408 rp->ai_protocol);
1409 if (fd == -1) {
1410 continue;
1411 }
1412
1413 if (rp->ai_family == AF_INET6) {
1414 if (setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &val,
1415 static_cast<socklen_t>(sizeof(val))) == -1) {
1416 close(fd);
1417 continue;
1418 }
1419
1420 if (setsockopt(fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, &val,
1421 static_cast<socklen_t>(sizeof(val))) == -1) {
1422 close(fd);
1423 continue;
1424 }
1425 } else if (setsockopt(fd, IPPROTO_IP, IP_PKTINFO, &val,
1426 static_cast<socklen_t>(sizeof(val))) == -1) {
1427 close(fd);
1428 continue;
1429 }
1430
1431 if (bind(fd, rp->ai_addr, rp->ai_addrlen) != -1) {
1432 break;
1433 }
1434
1435 close(fd);
1436 }
1437
1438 if (!rp) {
1439 std::cerr << "Could not bind" << std::endl;
1440 return -1;
1441 }
1442
1443 if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &val,
1444 static_cast<socklen_t>(sizeof(val))) == -1) {
1445 close(fd);
1446 return -1;
1447 }
1448
1449 fd_set_recv_ecn(fd, rp->ai_family);
1450
1451 socklen_t len = sizeof(local_addr.su.storage);
1452 if (getsockname(fd, &local_addr.su.sa, &len) == -1) {
1453 std::cerr << "getsockname: " << strerror(errno) << std::endl;
1454 close(fd);
1455 return -1;
1456 }
1457 local_addr.len = len;
1458 local_addr.ifindex = 0;
1459
1460 return fd;
1461 }
1462
1463 } // namespace
1464
1465 namespace {
add_endpoint(std::vector<Endpoint> & endpoints,const char * addr,const char * port,int af)1466 int add_endpoint(std::vector<Endpoint> &endpoints, const char *addr,
1467 const char *port, int af) {
1468 Address dest;
1469 auto fd = create_sock(dest, addr, port, af);
1470 if (fd == -1) {
1471 return -1;
1472 }
1473
1474 endpoints.emplace_back();
1475 auto &ep = endpoints.back();
1476 ep.addr = dest;
1477 ep.fd = fd;
1478 ev_io_init(&ep.rev, sreadcb, 0, EV_READ);
1479
1480 return 0;
1481 }
1482 } // namespace
1483
1484 namespace {
add_endpoint(std::vector<Endpoint> & endpoints,const Address & addr)1485 int add_endpoint(std::vector<Endpoint> &endpoints, const Address &addr) {
1486 auto fd = util::create_nonblock_socket(addr.su.sa.sa_family, SOCK_DGRAM, 0);
1487 if (fd == -1) {
1488 std::cerr << "socket: " << strerror(errno) << std::endl;
1489 return -1;
1490 }
1491
1492 int val = 1;
1493 if (addr.su.sa.sa_family == AF_INET6) {
1494 if (setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &val,
1495 static_cast<socklen_t>(sizeof(val))) == -1) {
1496 std::cerr << "setsockopt: " << strerror(errno) << std::endl;
1497 close(fd);
1498 return -1;
1499 }
1500
1501 if (setsockopt(fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, &val,
1502 static_cast<socklen_t>(sizeof(val))) == -1) {
1503 std::cerr << "setsockopt: " << strerror(errno) << std::endl;
1504 close(fd);
1505 return -1;
1506 }
1507 } else if (setsockopt(fd, IPPROTO_IP, IP_PKTINFO, &val,
1508 static_cast<socklen_t>(sizeof(val))) == -1) {
1509 std::cerr << "setsockopt: " << strerror(errno) << std::endl;
1510 close(fd);
1511 return -1;
1512 }
1513
1514 if (bind(fd, &addr.su.sa, addr.len) == -1) {
1515 std::cerr << "bind: " << strerror(errno) << std::endl;
1516 close(fd);
1517 return -1;
1518 }
1519
1520 if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &val,
1521 static_cast<socklen_t>(sizeof(val))) == -1) {
1522 close(fd);
1523 return -1;
1524 }
1525
1526 fd_set_recv_ecn(fd, addr.su.sa.sa_family);
1527
1528 endpoints.emplace_back(Endpoint{});
1529 auto &ep = endpoints.back();
1530 ep.addr = addr;
1531 ep.fd = fd;
1532 ev_io_init(&ep.rev, sreadcb, 0, EV_READ);
1533
1534 return 0;
1535 }
1536 } // namespace
1537
init(const char * addr,const char * port)1538 int Server::init(const char *addr, const char *port) {
1539 endpoints_.reserve(4);
1540
1541 auto ready = false;
1542 if (!util::numeric_host(addr, AF_INET6) &&
1543 add_endpoint(endpoints_, addr, port, AF_INET) == 0) {
1544 ready = true;
1545 }
1546 if (!util::numeric_host(addr, AF_INET) &&
1547 add_endpoint(endpoints_, addr, port, AF_INET6) == 0) {
1548 ready = true;
1549 }
1550 if (!ready) {
1551 return -1;
1552 }
1553
1554 if (config.preferred_ipv4_addr.len &&
1555 add_endpoint(endpoints_, config.preferred_ipv4_addr) != 0) {
1556 return -1;
1557 }
1558 if (config.preferred_ipv6_addr.len &&
1559 add_endpoint(endpoints_, config.preferred_ipv6_addr) != 0) {
1560 return -1;
1561 }
1562
1563 for (auto &ep : endpoints_) {
1564 ep.server = this;
1565 ep.rev.data = &ep;
1566
1567 ev_io_set(&ep.rev, ep.fd, EV_READ);
1568
1569 ev_io_start(loop_, &ep.rev);
1570 }
1571
1572 ev_signal_start(loop_, &sigintev_);
1573
1574 return 0;
1575 }
1576
on_read(Endpoint & ep)1577 int Server::on_read(Endpoint &ep) {
1578 sockaddr_union su;
1579 std::array<uint8_t, 64_k> buf;
1580 ngtcp2_pkt_hd hd;
1581 size_t pktcnt = 0;
1582 ngtcp2_pkt_info pi;
1583
1584 iovec msg_iov;
1585 msg_iov.iov_base = buf.data();
1586 msg_iov.iov_len = buf.size();
1587
1588 msghdr msg{};
1589 msg.msg_name = &su;
1590 msg.msg_iov = &msg_iov;
1591 msg.msg_iovlen = 1;
1592
1593 uint8_t
1594 msg_ctrl[CMSG_SPACE(sizeof(uint8_t)) + CMSG_SPACE(sizeof(in6_pktinfo))];
1595 msg.msg_control = msg_ctrl;
1596
1597 for (; pktcnt < 10;) {
1598 msg.msg_namelen = sizeof(su);
1599 msg.msg_controllen = sizeof(msg_ctrl);
1600
1601 auto nread = recvmsg(ep.fd, &msg, 0);
1602 if (nread == -1) {
1603 if (!(errno == EAGAIN || errno == ENOTCONN)) {
1604 std::cerr << "recvmsg: " << strerror(errno) << std::endl;
1605 }
1606 return 0;
1607 }
1608
1609 ++pktcnt;
1610
1611 pi.ecn = msghdr_get_ecn(&msg, su.storage.ss_family);
1612 auto local_addr = msghdr_get_local_addr(&msg, su.storage.ss_family);
1613 if (!local_addr) {
1614 std::cerr << "Unable to obtain local address" << std::endl;
1615 continue;
1616 }
1617
1618 set_port(*local_addr, ep.addr);
1619
1620 if (!config.quiet) {
1621 std::array<char, IF_NAMESIZE> ifname;
1622 std::cerr << "Received packet: local="
1623 << util::straddr(&local_addr->su.sa, local_addr->len)
1624 << " remote=" << util::straddr(&su.sa, msg.msg_namelen)
1625 << " if=" << if_indextoname(local_addr->ifindex, ifname.data())
1626 << " ecn=0x" << std::hex << pi.ecn << std::dec << " " << nread
1627 << " bytes" << std::endl;
1628 }
1629
1630 if (debug::packet_lost(config.rx_loss_prob)) {
1631 if (!config.quiet) {
1632 std::cerr << "** Simulated incoming packet loss **" << std::endl;
1633 }
1634 continue;
1635 }
1636
1637 if (nread == 0) {
1638 continue;
1639 }
1640
1641 uint32_t version;
1642 const uint8_t *dcid, *scid;
1643 size_t dcidlen, scidlen;
1644
1645 switch (auto rv = ngtcp2_pkt_decode_version_cid(&version, &dcid, &dcidlen,
1646 &scid, &scidlen, buf.data(),
1647 nread, NGTCP2_SV_SCIDLEN);
1648 rv) {
1649 case 0:
1650 break;
1651 case NGTCP2_ERR_VERSION_NEGOTIATION:
1652 send_version_negotiation(version, scid, scidlen, dcid, dcidlen, ep,
1653 *local_addr, &su.sa, msg.msg_namelen);
1654 continue;
1655 default:
1656 std::cerr << "Could not decode version and CID from QUIC packet header: "
1657 << ngtcp2_strerror(rv) << std::endl;
1658 continue;
1659 }
1660
1661 auto dcid_key = util::make_cid_key(dcid, dcidlen);
1662
1663 auto handler_it = handlers_.find(dcid_key);
1664 if (handler_it == std::end(handlers_)) {
1665 switch (auto rv = ngtcp2_accept(&hd, buf.data(), nread); rv) {
1666 case 0:
1667 break;
1668 case NGTCP2_ERR_RETRY:
1669 send_retry(&hd, ep, *local_addr, &su.sa, msg.msg_namelen);
1670 continue;
1671 case NGTCP2_ERR_VERSION_NEGOTIATION:
1672 if (!config.quiet) {
1673 std::cerr << "Unsupported version: Send Version Negotiation"
1674 << std::endl;
1675 }
1676 send_version_negotiation(hd.version, hd.scid.data, hd.scid.datalen,
1677 hd.dcid.data, hd.dcid.datalen, ep, *local_addr,
1678 &su.sa, msg.msg_namelen);
1679 continue;
1680 default:
1681 if (!config.quiet) {
1682 std::cerr << "Unexpected packet received: length=" << nread
1683 << std::endl;
1684 }
1685 continue;
1686 }
1687
1688 ngtcp2_cid ocid;
1689 ngtcp2_cid *pocid = nullptr;
1690
1691 assert(hd.type == NGTCP2_PKT_INITIAL);
1692
1693 if (config.validate_addr || hd.token.len) {
1694 std::cerr << "Perform stateless address validation" << std::endl;
1695 if (hd.token.len == 0) {
1696 send_retry(&hd, ep, *local_addr, &su.sa, msg.msg_namelen);
1697 continue;
1698 }
1699
1700 if (hd.token.base[0] != NGTCP2_CRYPTO_TOKEN_MAGIC_RETRY &&
1701 hd.dcid.datalen < NGTCP2_MIN_INITIAL_DCIDLEN) {
1702 send_stateless_connection_close(&hd, ep, *local_addr, &su.sa,
1703 msg.msg_namelen);
1704 continue;
1705 }
1706
1707 switch (hd.token.base[0]) {
1708 case NGTCP2_CRYPTO_TOKEN_MAGIC_RETRY:
1709 if (verify_retry_token(&ocid, &hd, &su.sa, msg.msg_namelen) != 0) {
1710 send_stateless_connection_close(&hd, ep, *local_addr, &su.sa,
1711 msg.msg_namelen);
1712 continue;
1713 }
1714 pocid = &ocid;
1715 break;
1716 case NGTCP2_CRYPTO_TOKEN_MAGIC_REGULAR:
1717 if (verify_token(&hd, &su.sa, msg.msg_namelen) != 0) {
1718 if (config.validate_addr) {
1719 send_retry(&hd, ep, *local_addr, &su.sa, msg.msg_namelen);
1720 continue;
1721 }
1722
1723 hd.token.base = nullptr;
1724 hd.token.len = 0;
1725 }
1726 break;
1727 default:
1728 if (!config.quiet) {
1729 std::cerr << "Ignore unrecognized token" << std::endl;
1730 }
1731 if (config.validate_addr) {
1732 send_retry(&hd, ep, *local_addr, &su.sa, msg.msg_namelen);
1733 continue;
1734 }
1735
1736 hd.token.base = nullptr;
1737 hd.token.len = 0;
1738 break;
1739 }
1740 }
1741
1742 auto h = std::make_unique<Handler>(loop_, this);
1743 if (h->init(ep, *local_addr, &su.sa, msg.msg_namelen, &hd.scid, &hd.dcid,
1744 pocid, hd.token.base, hd.token.len, hd.version,
1745 tls_ctx_) != 0) {
1746 continue;
1747 }
1748
1749 switch (h->on_read(ep, *local_addr, &su.sa, msg.msg_namelen, &pi,
1750 buf.data(), nread)) {
1751 case 0:
1752 break;
1753 case NETWORK_ERR_RETRY:
1754 send_retry(&hd, ep, *local_addr, &su.sa, msg.msg_namelen);
1755 continue;
1756 default:
1757 continue;
1758 }
1759
1760 switch (h->on_write()) {
1761 case 0:
1762 break;
1763 default:
1764 continue;
1765 }
1766
1767 std::array<ngtcp2_cid, 2> scids;
1768 auto conn = h->conn();
1769
1770 auto num_scid = ngtcp2_conn_get_num_scid(conn);
1771
1772 assert(num_scid <= scids.size());
1773
1774 ngtcp2_conn_get_scid(conn, scids.data());
1775
1776 for (size_t i = 0; i < num_scid; ++i) {
1777 handlers_.emplace(util::make_cid_key(&scids[i]), h.get());
1778 }
1779
1780 handlers_.emplace(dcid_key, h.get());
1781
1782 h.release();
1783
1784 continue;
1785 }
1786
1787 auto h = (*handler_it).second;
1788 if (ngtcp2_conn_is_in_closing_period(h->conn())) {
1789 // TODO do exponential backoff.
1790 switch (h->send_conn_close()) {
1791 case 0:
1792 break;
1793 default:
1794 remove(h);
1795 }
1796 continue;
1797 }
1798 if (h->draining()) {
1799 continue;
1800 }
1801
1802 if (auto rv = h->on_read(ep, *local_addr, &su.sa, msg.msg_namelen, &pi,
1803 buf.data(), nread);
1804 rv != 0) {
1805 if (rv != NETWORK_ERR_CLOSE_WAIT) {
1806 remove(h);
1807 }
1808 continue;
1809 }
1810
1811 h->signal_write();
1812 }
1813
1814 return 0;
1815 }
1816
1817 namespace {
generate_reserved_version(const sockaddr * sa,socklen_t salen,uint32_t version)1818 uint32_t generate_reserved_version(const sockaddr *sa, socklen_t salen,
1819 uint32_t version) {
1820 uint32_t h = 0x811C9DC5u;
1821 const uint8_t *p = (const uint8_t *)sa;
1822 const uint8_t *ep = p + salen;
1823 for (; p != ep; ++p) {
1824 h ^= *p;
1825 h *= 0x01000193u;
1826 }
1827 version = htonl(version);
1828 p = (const uint8_t *)&version;
1829 ep = p + sizeof(version);
1830 for (; p != ep; ++p) {
1831 h ^= *p;
1832 h *= 0x01000193u;
1833 }
1834 h &= 0xf0f0f0f0u;
1835 h |= 0x0a0a0a0au;
1836 return h;
1837 }
1838 } // namespace
1839
send_version_negotiation(uint32_t version,const uint8_t * dcid,size_t dcidlen,const uint8_t * scid,size_t scidlen,Endpoint & ep,const Address & local_addr,const sockaddr * sa,socklen_t salen)1840 int Server::send_version_negotiation(uint32_t version, const uint8_t *dcid,
1841 size_t dcidlen, const uint8_t *scid,
1842 size_t scidlen, Endpoint &ep,
1843 const Address &local_addr,
1844 const sockaddr *sa, socklen_t salen) {
1845 Buffer buf{NGTCP2_MAX_UDP_PAYLOAD_SIZE};
1846 std::array<uint32_t, 16> sv;
1847
1848 static_assert(sv.size() >= 2 + (NGTCP2_PROTO_VER_DRAFT_MAX -
1849 NGTCP2_PROTO_VER_DRAFT_MIN + 1));
1850
1851 sv[0] = generate_reserved_version(sa, salen, version);
1852 sv[1] = NGTCP2_PROTO_VER_V1;
1853
1854 size_t svlen = 2;
1855 for (auto v = NGTCP2_PROTO_VER_DRAFT_MIN; v <= NGTCP2_PROTO_VER_DRAFT_MAX;
1856 ++v) {
1857 sv[svlen++] = v;
1858 }
1859
1860 auto nwrite = ngtcp2_pkt_write_version_negotiation(
1861 buf.wpos(), buf.left(),
1862 std::uniform_int_distribution<uint8_t>(
1863 0, std::numeric_limits<uint8_t>::max())(randgen),
1864 dcid, dcidlen, scid, scidlen, sv.data(), svlen);
1865 if (nwrite < 0) {
1866 std::cerr << "ngtcp2_pkt_write_version_negotiation: "
1867 << ngtcp2_strerror(nwrite) << std::endl;
1868 return -1;
1869 }
1870
1871 buf.push(nwrite);
1872
1873 ngtcp2_addr laddr{
1874 const_cast<sockaddr *>(&local_addr.su.sa),
1875 local_addr.len,
1876 };
1877 ngtcp2_addr raddr{
1878 const_cast<sockaddr *>(sa),
1879 salen,
1880 };
1881
1882 if (send_packet(ep, laddr, raddr, /* ecn = */ 0, buf.rpos(), buf.size(), 0) !=
1883 NETWORK_ERR_OK) {
1884 return -1;
1885 }
1886
1887 return 0;
1888 }
1889
send_retry(const ngtcp2_pkt_hd * chd,Endpoint & ep,const Address & local_addr,const sockaddr * sa,socklen_t salen)1890 int Server::send_retry(const ngtcp2_pkt_hd *chd, Endpoint &ep,
1891 const Address &local_addr, const sockaddr *sa,
1892 socklen_t salen) {
1893 std::array<char, NI_MAXHOST> host;
1894 std::array<char, NI_MAXSERV> port;
1895
1896 if (auto rv = getnameinfo(sa, salen, host.data(), host.size(), port.data(),
1897 port.size(), NI_NUMERICHOST | NI_NUMERICSERV);
1898 rv != 0) {
1899 std::cerr << "getnameinfo: " << gai_strerror(rv) << std::endl;
1900 return -1;
1901 }
1902
1903 if (!config.quiet) {
1904 std::cerr << "Sending Retry packet to [" << host.data()
1905 << "]:" << port.data() << std::endl;
1906 }
1907
1908 ngtcp2_cid scid;
1909
1910 scid.datalen = NGTCP2_SV_SCIDLEN;
1911 if (util::generate_secure_random(scid.data, scid.datalen) != 0) {
1912 return -1;
1913 }
1914
1915 std::array<uint8_t, NGTCP2_CRYPTO_MAX_RETRY_TOKENLEN> token;
1916
1917 auto t = std::chrono::duration_cast<std::chrono::nanoseconds>(
1918 std::chrono::system_clock::now().time_since_epoch())
1919 .count();
1920
1921 auto tokenlen = ngtcp2_crypto_generate_retry_token(
1922 token.data(), config.static_secret.data(), config.static_secret.size(),
1923 sa, salen, &scid, &chd->dcid, t);
1924 if (tokenlen < 0) {
1925 return -1;
1926 }
1927
1928 if (!config.quiet) {
1929 std::cerr << "Generated address validation token:" << std::endl;
1930 util::hexdump(stderr, token.data(), tokenlen);
1931 }
1932
1933 Buffer buf{NGTCP2_MAX_UDP_PAYLOAD_SIZE};
1934
1935 auto nwrite = ngtcp2_crypto_write_retry(buf.wpos(), buf.left(), chd->version,
1936 &chd->scid, &scid, &chd->dcid,
1937 token.data(), tokenlen);
1938 if (nwrite < 0) {
1939 std::cerr << "ngtcp2_crypto_write_retry failed" << std::endl;
1940 return -1;
1941 }
1942
1943 buf.push(nwrite);
1944
1945 ngtcp2_addr laddr{
1946 const_cast<sockaddr *>(&local_addr.su.sa),
1947 local_addr.len,
1948 };
1949 ngtcp2_addr raddr{
1950 const_cast<sockaddr *>(sa),
1951 salen,
1952 };
1953
1954 if (send_packet(ep, laddr, raddr, /* ecn = */ 0, buf.rpos(), buf.size(), 0) !=
1955 NETWORK_ERR_OK) {
1956 return -1;
1957 }
1958
1959 return 0;
1960 }
1961
send_stateless_connection_close(const ngtcp2_pkt_hd * chd,Endpoint & ep,const Address & local_addr,const sockaddr * sa,socklen_t salen)1962 int Server::send_stateless_connection_close(const ngtcp2_pkt_hd *chd,
1963 Endpoint &ep,
1964 const Address &local_addr,
1965 const sockaddr *sa,
1966 socklen_t salen) {
1967 Buffer buf{NGTCP2_MAX_UDP_PAYLOAD_SIZE};
1968
1969 auto nwrite = ngtcp2_crypto_write_connection_close(
1970 buf.wpos(), buf.left(), chd->version, &chd->scid, &chd->dcid,
1971 NGTCP2_INVALID_TOKEN);
1972 if (nwrite < 0) {
1973 std::cerr << "ngtcp2_crypto_write_connection_close failed" << std::endl;
1974 return -1;
1975 }
1976
1977 buf.push(nwrite);
1978
1979 ngtcp2_addr laddr{
1980 const_cast<sockaddr *>(&local_addr.su.sa),
1981 local_addr.len,
1982 };
1983 ngtcp2_addr raddr{
1984 const_cast<sockaddr *>(sa),
1985 salen,
1986 };
1987
1988 if (send_packet(ep, laddr, raddr, /* ecn = */ 0, buf.rpos(), buf.size(), 0) !=
1989 NETWORK_ERR_OK) {
1990 return -1;
1991 }
1992
1993 return 0;
1994 }
1995
verify_retry_token(ngtcp2_cid * ocid,const ngtcp2_pkt_hd * hd,const sockaddr * sa,socklen_t salen)1996 int Server::verify_retry_token(ngtcp2_cid *ocid, const ngtcp2_pkt_hd *hd,
1997 const sockaddr *sa, socklen_t salen) {
1998 std::array<char, NI_MAXHOST> host;
1999 std::array<char, NI_MAXSERV> port;
2000
2001 if (auto rv = getnameinfo(sa, salen, host.data(), host.size(), port.data(),
2002 port.size(), NI_NUMERICHOST | NI_NUMERICSERV);
2003 rv != 0) {
2004 std::cerr << "getnameinfo: " << gai_strerror(rv) << std::endl;
2005 return -1;
2006 }
2007
2008 if (!config.quiet) {
2009 std::cerr << "Verifying Retry token from [" << host.data()
2010 << "]:" << port.data() << std::endl;
2011 util::hexdump(stderr, hd->token.base, hd->token.len);
2012 }
2013
2014 auto t = std::chrono::duration_cast<std::chrono::nanoseconds>(
2015 std::chrono::system_clock::now().time_since_epoch())
2016 .count();
2017
2018 if (ngtcp2_crypto_verify_retry_token(
2019 ocid, hd->token.base, hd->token.len, config.static_secret.data(),
2020 config.static_secret.size(), sa, salen, &hd->dcid,
2021 10 * NGTCP2_SECONDS, t) != 0) {
2022 std::cerr << "Could not verify Retry token" << std::endl;
2023
2024 return -1;
2025 }
2026
2027 if (!config.quiet) {
2028 std::cerr << "Token was successfully validated" << std::endl;
2029 }
2030
2031 return 0;
2032 }
2033
verify_token(const ngtcp2_pkt_hd * hd,const sockaddr * sa,socklen_t salen)2034 int Server::verify_token(const ngtcp2_pkt_hd *hd, const sockaddr *sa,
2035 socklen_t salen) {
2036 std::array<char, NI_MAXHOST> host;
2037 std::array<char, NI_MAXSERV> port;
2038
2039 if (auto rv = getnameinfo(sa, salen, host.data(), host.size(), port.data(),
2040 port.size(), NI_NUMERICHOST | NI_NUMERICSERV);
2041 rv != 0) {
2042 std::cerr << "getnameinfo: " << gai_strerror(rv) << std::endl;
2043 return -1;
2044 }
2045
2046 if (!config.quiet) {
2047 std::cerr << "Verifying token from [" << host.data() << "]:" << port.data()
2048 << std::endl;
2049 util::hexdump(stderr, hd->token.base, hd->token.len);
2050 }
2051
2052 auto t = std::chrono::duration_cast<std::chrono::nanoseconds>(
2053 std::chrono::system_clock::now().time_since_epoch())
2054 .count();
2055
2056 if (ngtcp2_crypto_verify_regular_token(hd->token.base, hd->token.len,
2057 config.static_secret.data(),
2058 config.static_secret.size(), sa, salen,
2059 3600 * NGTCP2_SECONDS, t) != 0) {
2060 std::cerr << "Could not verify token" << std::endl;
2061
2062 return -1;
2063 }
2064
2065 if (!config.quiet) {
2066 std::cerr << "Token was successfully validated" << std::endl;
2067 }
2068
2069 return 0;
2070 }
2071
send_packet(Endpoint & ep,const ngtcp2_addr & local_addr,const ngtcp2_addr & remote_addr,unsigned int ecn,const uint8_t * data,size_t datalen,size_t gso_size)2072 int Server::send_packet(Endpoint &ep, const ngtcp2_addr &local_addr,
2073 const ngtcp2_addr &remote_addr, unsigned int ecn,
2074 const uint8_t *data, size_t datalen, size_t gso_size) {
2075 if (debug::packet_lost(config.tx_loss_prob)) {
2076 if (!config.quiet) {
2077 std::cerr << "** Simulated outgoing packet loss **" << std::endl;
2078 }
2079 return NETWORK_ERR_OK;
2080 }
2081
2082 iovec msg_iov;
2083 msg_iov.iov_base = const_cast<uint8_t *>(data);
2084 msg_iov.iov_len = datalen;
2085
2086 msghdr msg{};
2087 msg.msg_name = const_cast<sockaddr *>(remote_addr.addr);
2088 msg.msg_namelen = remote_addr.addrlen;
2089 msg.msg_iov = &msg_iov;
2090 msg.msg_iovlen = 1;
2091
2092 uint8_t msg_ctrl[
2093 #if NGTCP2_ENABLE_UDP_GSO
2094 CMSG_SPACE(sizeof(uint16_t)) +
2095 #endif // NGTCP2_ENABLE_UDP_GSO
2096 CMSG_SPACE(sizeof(in6_pktinfo))];
2097
2098 memset(msg_ctrl, 0, sizeof(msg_ctrl));
2099
2100 msg.msg_control = msg_ctrl;
2101 msg.msg_controllen = sizeof(msg_ctrl);
2102
2103 size_t controllen = 0;
2104
2105 auto cm = CMSG_FIRSTHDR(&msg);
2106
2107 switch (local_addr.addr->sa_family) {
2108 case AF_INET: {
2109 controllen += CMSG_SPACE(sizeof(in_pktinfo));
2110 cm->cmsg_level = IPPROTO_IP;
2111 cm->cmsg_type = IP_PKTINFO;
2112 cm->cmsg_len = CMSG_LEN(sizeof(in_pktinfo));
2113 auto pktinfo = reinterpret_cast<in_pktinfo *>(CMSG_DATA(cm));
2114 memset(pktinfo, 0, sizeof(in_pktinfo));
2115 auto addrin = reinterpret_cast<sockaddr_in *>(local_addr.addr);
2116 pktinfo->ipi_spec_dst = addrin->sin_addr;
2117 break;
2118 }
2119 case AF_INET6: {
2120 controllen += CMSG_SPACE(sizeof(in6_pktinfo));
2121 cm->cmsg_level = IPPROTO_IPV6;
2122 cm->cmsg_type = IPV6_PKTINFO;
2123 cm->cmsg_len = CMSG_LEN(sizeof(in6_pktinfo));
2124 auto pktinfo = reinterpret_cast<in6_pktinfo *>(CMSG_DATA(cm));
2125 memset(pktinfo, 0, sizeof(in6_pktinfo));
2126 auto addrin = reinterpret_cast<sockaddr_in6 *>(local_addr.addr);
2127 pktinfo->ipi6_addr = addrin->sin6_addr;
2128 break;
2129 }
2130 default:
2131 assert(0);
2132 }
2133
2134 #if NGTCP2_ENABLE_UDP_GSO
2135 if (gso_size && datalen > gso_size) {
2136 controllen += CMSG_SPACE(sizeof(uint16_t));
2137 cm = CMSG_NXTHDR(&msg, cm);
2138 cm->cmsg_level = SOL_UDP;
2139 cm->cmsg_type = UDP_SEGMENT;
2140 cm->cmsg_len = CMSG_LEN(sizeof(uint16_t));
2141 *(reinterpret_cast<uint16_t *>(CMSG_DATA(cm))) = gso_size;
2142 }
2143 #endif // NGTCP2_ENABLE_UDP_GSO
2144
2145 msg.msg_controllen = controllen;
2146
2147 if (ep.ecn != ecn) {
2148 ep.ecn = ecn;
2149 fd_set_ecn(ep.fd, ep.addr.su.storage.ss_family, ecn);
2150 }
2151
2152 ssize_t nwrite = 0;
2153
2154 do {
2155 nwrite = sendmsg(ep.fd, &msg, 0);
2156 } while (nwrite == -1 && errno == EINTR);
2157
2158 if (nwrite == -1) {
2159 std::cerr << "sendmsg: " << strerror(errno) << std::endl;
2160 // TODO We have packet which is expected to fail to send (e.g.,
2161 // path validation to old path).
2162 return NETWORK_ERR_OK;
2163 }
2164
2165 if (!config.quiet) {
2166 std::cerr << "Sent packet: local="
2167 << util::straddr(local_addr.addr, local_addr.addrlen)
2168 << " remote="
2169 << util::straddr(remote_addr.addr, remote_addr.addrlen)
2170 << " ecn=0x" << std::hex << ecn << std::dec << " " << nwrite
2171 << " bytes" << std::endl;
2172 }
2173
2174 return NETWORK_ERR_OK;
2175 }
2176
associate_cid(const ngtcp2_cid * cid,Handler * h)2177 void Server::associate_cid(const ngtcp2_cid *cid, Handler *h) {
2178 handlers_.emplace(util::make_cid_key(cid), h);
2179 }
2180
dissociate_cid(const ngtcp2_cid * cid)2181 void Server::dissociate_cid(const ngtcp2_cid *cid) {
2182 handlers_.erase(util::make_cid_key(cid));
2183 }
2184
remove(const Handler * h)2185 void Server::remove(const Handler *h) {
2186 auto conn = h->conn();
2187
2188 handlers_.erase(
2189 util::make_cid_key(ngtcp2_conn_get_client_initial_dcid(conn)));
2190
2191 std::vector<ngtcp2_cid> cids(ngtcp2_conn_get_num_scid(conn));
2192 ngtcp2_conn_get_scid(conn, cids.data());
2193
2194 for (auto &cid : cids) {
2195 handlers_.erase(util::make_cid_key(&cid));
2196 }
2197
2198 delete h;
2199 }
2200
2201 namespace {
parse_host_port(Address & dest,int af,const char * first,const char * last)2202 int parse_host_port(Address &dest, int af, const char *first,
2203 const char *last) {
2204 if (std::distance(first, last) == 0) {
2205 return -1;
2206 }
2207
2208 const char *host_begin, *host_end, *it;
2209 if (*first == '[') {
2210 host_begin = first + 1;
2211 it = std::find(host_begin, last, ']');
2212 if (it == last) {
2213 return -1;
2214 }
2215 host_end = it;
2216 ++it;
2217 if (it == last || *it != ':') {
2218 return -1;
2219 }
2220 } else {
2221 host_begin = first;
2222 it = std::find(host_begin, last, ':');
2223 if (it == last) {
2224 return -1;
2225 }
2226 host_end = it;
2227 }
2228
2229 if (++it == last) {
2230 return -1;
2231 }
2232 auto svc_begin = it;
2233
2234 std::array<char, NI_MAXHOST> host;
2235 *std::copy(host_begin, host_end, std::begin(host)) = '\0';
2236
2237 addrinfo hints{}, *res;
2238 hints.ai_family = af;
2239 hints.ai_socktype = SOCK_DGRAM;
2240
2241 if (auto rv = getaddrinfo(host.data(), svc_begin, &hints, &res); rv != 0) {
2242 std::cerr << "getaddrinfo: [" << host.data() << "]:" << svc_begin << ": "
2243 << gai_strerror(rv) << std::endl;
2244 return -1;
2245 }
2246
2247 dest.len = res->ai_addrlen;
2248 memcpy(&dest.su, res->ai_addr, res->ai_addrlen);
2249
2250 freeaddrinfo(res);
2251
2252 return 0;
2253 }
2254 } // namespace
2255
2256 namespace {
print_usage()2257 void print_usage() {
2258 std::cerr << "Usage: server [OPTIONS] <ADDR> <PORT> <PRIVATE_KEY_FILE> "
2259 "<CERTIFICATE_FILE>"
2260 << std::endl;
2261 }
2262 } // namespace
2263
2264 namespace {
config_set_default(Config & config)2265 void config_set_default(Config &config) {
2266 config = Config{};
2267 config.tx_loss_prob = 0.;
2268 config.rx_loss_prob = 0.;
2269 config.ciphers = util::crypto_default_ciphers();
2270 config.groups = util::crypto_default_groups();
2271 config.timeout = 30 * NGTCP2_SECONDS;
2272 {
2273 auto path = realpath(".", nullptr);
2274 assert(path);
2275 config.htdocs = path;
2276 free(path);
2277 }
2278 config.mime_types_file = "/etc/mime.types";
2279 config.max_data = 1_m;
2280 config.max_stream_data_bidi_local = 256_k;
2281 config.max_stream_data_bidi_remote = 256_k;
2282 config.max_stream_data_uni = 256_k;
2283 config.max_streams_bidi = 100;
2284 config.max_streams_uni = 3;
2285 config.max_dyn_length = 20_m;
2286 config.cc_algo = NGTCP2_CC_ALGO_CUBIC;
2287 config.initial_rtt = NGTCP2_DEFAULT_INITIAL_RTT;
2288 config.max_gso_dgrams = 10;
2289 }
2290 } // namespace
2291
2292 namespace {
print_help()2293 void print_help() {
2294 print_usage();
2295
2296 config_set_default(config);
2297
2298 std::cout << R"(
2299 <ADDR> Address to listen to. '*' binds to any address.
2300 <PORT> Port
2301 <PRIVATE_KEY_FILE>
2302 Path to private key file
2303 <CERTIFICATE_FILE>
2304 Path to certificate file
2305 Options:
2306 -t, --tx-loss=<P>
2307 The probability of losing outgoing packets. <P> must be
2308 [0.0, 1.0], inclusive. 0.0 means no packet loss. 1.0
2309 means 100% packet loss.
2310 -r, --rx-loss=<P>
2311 The probability of losing incoming packets. <P> must be
2312 [0.0, 1.0], inclusive. 0.0 means no packet loss. 1.0
2313 means 100% packet loss.
2314 --ciphers=<CIPHERS>
2315 Specify the cipher suite list to enable.
2316 Default: )"
2317 << config.ciphers << R"(
2318 --groups=<GROUPS>
2319 Specify the supported groups.
2320 Default: )"
2321 << config.groups << R"(
2322 -d, --htdocs=<PATH>
2323 Specify document root. If this option is not specified,
2324 the document root is the current working directory.
2325 -q, --quiet Suppress debug output.
2326 -s, --show-secret
2327 Print out secrets unless --quiet is used.
2328 --timeout=<DURATION>
2329 Specify idle timeout.
2330 Default: )"
2331 << util::format_duration(config.timeout) << R"(
2332 -V, --validate-addr
2333 Perform address validation.
2334 --preferred-ipv4-addr=<ADDR>:<PORT>
2335 Specify preferred IPv4 address and port.
2336 --preferred-ipv6-addr=<ADDR>:<PORT>
2337 Specify preferred IPv6 address and port. A numeric IPv6
2338 address must be enclosed by '[' and ']' (e.g.,
2339 [::1]:8443)
2340 --mime-types-file=<PATH>
2341 Path to file that contains MIME media types and the
2342 extensions.
2343 Default: )"
2344 << config.mime_types_file << R"(
2345 --early-response
2346 Start sending response when it receives HTTP header
2347 fields without waiting for request body. If HTTP
2348 response data is written before receiving request body,
2349 STOP_SENDING is sent.
2350 --verify-client
2351 Request a client certificate. At the moment, we just
2352 request a certificate and no verification is done.
2353 --qlog-dir=<PATH>
2354 Path to the directory where qlog file is stored. The
2355 file name of each qlog is the Source Connection ID of
2356 server.
2357 --no-quic-dump
2358 Disables printing QUIC STREAM and CRYPTO frame data out.
2359 --no-http-dump
2360 Disables printing HTTP response body out.
2361 --max-data=<SIZE>
2362 The initial connection-level flow control window.
2363 Default: )"
2364 << util::format_uint_iec(config.max_data) << R"(
2365 --max-stream-data-bidi-local=<SIZE>
2366 The initial stream-level flow control window for a
2367 bidirectional stream that the local endpoint initiates.
2368 Default: )"
2369 << util::format_uint_iec(config.max_stream_data_bidi_local) << R"(
2370 --max-stream-data-bidi-remote=<SIZE>
2371 The initial stream-level flow control window for a
2372 bidirectional stream that the remote endpoint initiates.
2373 Default: )"
2374 << util::format_uint_iec(config.max_stream_data_bidi_remote) << R"(
2375 --max-stream-data-uni=<SIZE>
2376 The initial stream-level flow control window for a
2377 unidirectional stream.
2378 Default: )"
2379 << util::format_uint_iec(config.max_stream_data_uni) << R"(
2380 --max-streams-bidi=<N>
2381 The number of the concurrent bidirectional streams.
2382 Default: )"
2383 << config.max_streams_bidi << R"(
2384 --max-streams-uni=<N>
2385 The number of the concurrent unidirectional streams.
2386 Default: )"
2387 << config.max_streams_uni << R"(
2388 --max-dyn-length=<SIZE>
2389 The maximum length of a dynamically generated content.
2390 Default: )"
2391 << util::format_uint_iec(config.max_dyn_length) << R"(
2392 --cc=(cubic|reno|bbr)
2393 The name of congestion controller algorithm.
2394 Default: )"
2395 << util::strccalgo(config.cc_algo) << R"(
2396 --initial-rtt=<DURATION>
2397 Set an initial RTT.
2398 Default: )"
2399 << util::format_duration(config.initial_rtt) << R"(
2400 --max-udp-payload-size=<SIZE>
2401 Override maximum UDP payload size that server transmits.
2402 --send-trailers
2403 Send trailer fields.
2404 --max-gso-dgrams=<N>
2405 Maximum number of UDP datagrams that are sent in a
2406 single GSO sendmsg call.
2407 Default: )"
2408 << config.max_gso_dgrams << R"(
2409 -h, --help Display this help and exit.
2410
2411 ---
2412
2413 The <SIZE> argument is an integer and an optional unit (e.g., 10K is
2414 10 * 1024). Units are K, M and G (powers of 1024).
2415
2416 The <DURATION> argument is an integer and an optional unit (e.g., 1s
2417 is 1 second and 500ms is 500 milliseconds). Units are h, m, s, ms,
2418 us, or ns (hours, minutes, seconds, milliseconds, microseconds, and
2419 nanoseconds respectively). If a unit is omitted, a second is used
2420 as unit.)" << std::endl;
2421 }
2422 } // namespace
2423
2424 std::ofstream keylog_file;
2425
main(int argc,char ** argv)2426 int main(int argc, char **argv) {
2427 config_set_default(config);
2428
2429 for (;;) {
2430 static int flag = 0;
2431 constexpr static option long_opts[] = {
2432 {"help", no_argument, nullptr, 'h'},
2433 {"tx-loss", required_argument, nullptr, 't'},
2434 {"rx-loss", required_argument, nullptr, 'r'},
2435 {"htdocs", required_argument, nullptr, 'd'},
2436 {"quiet", no_argument, nullptr, 'q'},
2437 {"show-secret", no_argument, nullptr, 's'},
2438 {"validate-addr", no_argument, nullptr, 'V'},
2439 {"ciphers", required_argument, &flag, 1},
2440 {"groups", required_argument, &flag, 2},
2441 {"timeout", required_argument, &flag, 3},
2442 {"preferred-ipv4-addr", required_argument, &flag, 4},
2443 {"preferred-ipv6-addr", required_argument, &flag, 5},
2444 {"mime-types-file", required_argument, &flag, 6},
2445 {"early-response", no_argument, &flag, 7},
2446 {"verify-client", no_argument, &flag, 8},
2447 {"qlog-dir", required_argument, &flag, 9},
2448 {"no-quic-dump", no_argument, &flag, 10},
2449 {"no-http-dump", no_argument, &flag, 11},
2450 {"max-data", required_argument, &flag, 12},
2451 {"max-stream-data-bidi-local", required_argument, &flag, 13},
2452 {"max-stream-data-bidi-remote", required_argument, &flag, 14},
2453 {"max-stream-data-uni", required_argument, &flag, 15},
2454 {"max-streams-bidi", required_argument, &flag, 16},
2455 {"max-streams-uni", required_argument, &flag, 17},
2456 {"max-dyn-length", required_argument, &flag, 18},
2457 {"cc", required_argument, &flag, 19},
2458 {"initial-rtt", required_argument, &flag, 20},
2459 {"max-udp-payload-size", required_argument, &flag, 21},
2460 {"send-trailers", no_argument, &flag, 22},
2461 {"max-gso-dgrams", required_argument, &flag, 25},
2462 {nullptr, 0, nullptr, 0}};
2463
2464 auto optidx = 0;
2465 auto c = getopt_long(argc, argv, "d:hqr:st:V", long_opts, &optidx);
2466 if (c == -1) {
2467 break;
2468 }
2469 switch (c) {
2470 case 'd': {
2471 // --htdocs
2472 auto path = realpath(optarg, nullptr);
2473 if (path == nullptr) {
2474 std::cerr << "path: invalid path " << std::quoted(optarg) << std::endl;
2475 exit(EXIT_FAILURE);
2476 }
2477 config.htdocs = path;
2478 free(path);
2479 break;
2480 }
2481 case 'h':
2482 // --help
2483 print_help();
2484 exit(EXIT_SUCCESS);
2485 case 'q':
2486 // --quiet
2487 config.quiet = true;
2488 break;
2489 case 'r':
2490 // --rx-loss
2491 config.rx_loss_prob = strtod(optarg, nullptr);
2492 break;
2493 case 's':
2494 // --show-secret
2495 config.show_secret = true;
2496 break;
2497 case 't':
2498 // --tx-loss
2499 config.tx_loss_prob = strtod(optarg, nullptr);
2500 break;
2501 case 'V':
2502 // --validate-addr
2503 config.validate_addr = true;
2504 break;
2505 case '?':
2506 print_usage();
2507 exit(EXIT_FAILURE);
2508 case 0:
2509 switch (flag) {
2510 case 1:
2511 // --ciphers
2512 config.ciphers = optarg;
2513 break;
2514 case 2:
2515 // --groups
2516 config.groups = optarg;
2517 break;
2518 case 3:
2519 // --timeout
2520 if (auto t = util::parse_duration(optarg); !t) {
2521 std::cerr << "timeout: invalid argument" << std::endl;
2522 exit(EXIT_FAILURE);
2523 } else {
2524 config.timeout = *t;
2525 }
2526 break;
2527 case 4:
2528 // --preferred-ipv4-addr
2529 if (parse_host_port(config.preferred_ipv4_addr, AF_INET, optarg,
2530 optarg + strlen(optarg)) != 0) {
2531 std::cerr << "preferred-ipv4-addr: could not use "
2532 << std::quoted(optarg) << std::endl;
2533 exit(EXIT_FAILURE);
2534 }
2535 break;
2536 case 5:
2537 // --preferred-ipv6-addr
2538 if (parse_host_port(config.preferred_ipv6_addr, AF_INET6, optarg,
2539 optarg + strlen(optarg)) != 0) {
2540 std::cerr << "preferred-ipv6-addr: could not use "
2541 << std::quoted(optarg) << std::endl;
2542 exit(EXIT_FAILURE);
2543 }
2544 break;
2545 case 6:
2546 // --mime-types-file
2547 config.mime_types_file = optarg;
2548 break;
2549 case 7:
2550 // --early-response
2551 config.early_response = true;
2552 break;
2553 case 8:
2554 // --verify-client
2555 config.verify_client = true;
2556 break;
2557 case 9:
2558 // --qlog-dir
2559 config.qlog_dir = optarg;
2560 break;
2561 case 10:
2562 // --no-quic-dump
2563 config.no_quic_dump = true;
2564 break;
2565 case 11:
2566 // --no-http-dump
2567 config.no_http_dump = true;
2568 break;
2569 case 12:
2570 // --max-data
2571 if (auto n = util::parse_uint_iec(optarg); !n) {
2572 std::cerr << "max-data: invalid argument" << std::endl;
2573 exit(EXIT_FAILURE);
2574 } else {
2575 config.max_data = *n;
2576 }
2577 break;
2578 case 13:
2579 // --max-stream-data-bidi-local
2580 if (auto n = util::parse_uint_iec(optarg); !n) {
2581 std::cerr << "max-stream-data-bidi-local: invalid argument"
2582 << std::endl;
2583 exit(EXIT_FAILURE);
2584 } else {
2585 config.max_stream_data_bidi_local = *n;
2586 }
2587 break;
2588 case 14:
2589 // --max-stream-data-bidi-remote
2590 if (auto n = util::parse_uint_iec(optarg); !n) {
2591 std::cerr << "max-stream-data-bidi-remote: invalid argument"
2592 << std::endl;
2593 exit(EXIT_FAILURE);
2594 } else {
2595 config.max_stream_data_bidi_remote = *n;
2596 }
2597 break;
2598 case 15:
2599 // --max-stream-data-uni
2600 if (auto n = util::parse_uint_iec(optarg); !n) {
2601 std::cerr << "max-stream-data-uni: invalid argument" << std::endl;
2602 exit(EXIT_FAILURE);
2603 } else {
2604 config.max_stream_data_uni = *n;
2605 }
2606 break;
2607 case 16:
2608 // --max-streams-bidi
2609 if (auto n = util::parse_uint(optarg); !n) {
2610 std::cerr << "max-streams-bidi: invalid argument" << std::endl;
2611 exit(EXIT_FAILURE);
2612 } else {
2613 config.max_streams_bidi = *n;
2614 }
2615 break;
2616 case 17:
2617 // --max-streams-uni
2618 if (auto n = util::parse_uint(optarg); !n) {
2619 std::cerr << "max-streams-uni: invalid argument" << std::endl;
2620 exit(EXIT_FAILURE);
2621 } else {
2622 config.max_streams_uni = *n;
2623 }
2624 break;
2625 case 18:
2626 // --max-dyn-length
2627 if (auto n = util::parse_uint_iec(optarg); !n) {
2628 std::cerr << "max-dyn-length: invalid argument" << std::endl;
2629 exit(EXIT_FAILURE);
2630 } else {
2631 config.max_dyn_length = *n;
2632 }
2633 break;
2634 case 19:
2635 // --cc
2636 if (strcmp("cubic", optarg) == 0) {
2637 config.cc_algo = NGTCP2_CC_ALGO_CUBIC;
2638 break;
2639 }
2640 if (strcmp("reno", optarg) == 0) {
2641 config.cc_algo = NGTCP2_CC_ALGO_RENO;
2642 break;
2643 }
2644 if (strcmp("bbr", optarg) == 0) {
2645 config.cc_algo = NGTCP2_CC_ALGO_BBR;
2646 break;
2647 }
2648 std::cerr << "cc: specify cubic, reno, or bbr" << std::endl;
2649 exit(EXIT_FAILURE);
2650 case 20:
2651 // --initial-rtt
2652 if (auto t = util::parse_duration(optarg); !t) {
2653 std::cerr << "initial-rtt: invalid argument" << std::endl;
2654 exit(EXIT_FAILURE);
2655 } else {
2656 config.initial_rtt = *t;
2657 }
2658 break;
2659 case 21:
2660 // --max-udp-payload-size
2661 if (auto n = util::parse_uint_iec(optarg); !n) {
2662 std::cerr << "max-udp-payload-size: invalid argument" << std::endl;
2663 exit(EXIT_FAILURE);
2664 } else if (*n > 64_k) {
2665 std::cerr << "max-udp-payload-size: must not exceed 65536"
2666 << std::endl;
2667 exit(EXIT_FAILURE);
2668 } else {
2669 config.max_udp_payload_size = *n;
2670 }
2671 break;
2672 case 22:
2673 // --send-trailers
2674 config.send_trailers = true;
2675 break;
2676 case 25:
2677 // --max-gso-dgrams
2678 if (auto n = util::parse_uint(optarg); !n) {
2679 std::cerr << "max-gso-dgrams: invalid argument" << std::endl;
2680 exit(EXIT_FAILURE);
2681 } else {
2682 config.max_gso_dgrams = *n;
2683 }
2684 break;
2685 }
2686 break;
2687 default:
2688 break;
2689 };
2690 }
2691
2692 if (argc - optind < 4) {
2693 std::cerr << "Too few arguments" << std::endl;
2694 print_usage();
2695 exit(EXIT_FAILURE);
2696 }
2697
2698 auto addr = argv[optind++];
2699 auto port = argv[optind++];
2700 auto private_key_file = argv[optind++];
2701 auto cert_file = argv[optind++];
2702
2703 if (auto n = util::parse_uint(port); !n) {
2704 std::cerr << "port: invalid port number" << std::endl;
2705 exit(EXIT_FAILURE);
2706 } else if (*n > 65535) {
2707 std::cerr << "port: must not exceed 65535" << std::endl;
2708 exit(EXIT_FAILURE);
2709 } else {
2710 config.port = *n;
2711 }
2712
2713 if (auto mt = util::read_mime_types(config.mime_types_file); !mt) {
2714 std::cerr << "mime-types-file: Could not read MIME media types file "
2715 << std::quoted(config.mime_types_file) << std::endl;
2716 } else {
2717 config.mime_types = std::move(*mt);
2718 }
2719
2720 TLSServerContext tls_ctx;
2721
2722 if (tls_ctx.init(private_key_file, cert_file, AppProtocol::HQ) != 0) {
2723 exit(EXIT_FAILURE);
2724 }
2725
2726 if (config.htdocs.back() != '/') {
2727 config.htdocs += '/';
2728 }
2729
2730 std::cerr << "Using document root " << config.htdocs << std::endl;
2731
2732 auto ev_loop_d = defer(ev_loop_destroy, EV_DEFAULT);
2733
2734 auto keylog_filename = getenv("SSLKEYLOGFILE");
2735 if (keylog_filename) {
2736 keylog_file.open(keylog_filename, std::ios_base::app);
2737 if (keylog_file) {
2738 tls_ctx.enable_keylog();
2739 }
2740 }
2741
2742 if (util::generate_secret(config.static_secret.data(),
2743 config.static_secret.size()) != 0) {
2744 std::cerr << "Unable to generate static secret" << std::endl;
2745 exit(EXIT_FAILURE);
2746 }
2747
2748 Server s(EV_DEFAULT, tls_ctx);
2749 if (s.init(addr, port) != 0) {
2750 exit(EXIT_FAILURE);
2751 }
2752
2753 ev_run(EV_DEFAULT, 0);
2754
2755 s.disconnect();
2756 s.close();
2757
2758 return EXIT_SUCCESS;
2759 }
2760