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