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 "server.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 constexpr size_t MAX_DYNBUFLEN = 10 * 1024 * 1024;
73 } // namespace
74 
75 namespace {
76 auto randgen = util::make_mt19937();
77 } // namespace
78 
79 Config config{};
80 
Stream(int64_t stream_id,Handler * handler)81 Stream::Stream(int64_t stream_id, Handler *handler)
82     : stream_id(stream_id),
83       handler(handler),
84       data(nullptr),
85       datalen(0),
86       dynresp(false),
87       dyndataleft(0),
88       dynbuflen(0) {}
89 
90 namespace {
91 constexpr char NGTCP2_SERVER[] = "nghttp3/ngtcp2 server";
92 } // namespace
93 
94 namespace {
make_status_body(unsigned int status_code)95 std::string make_status_body(unsigned int status_code) {
96   auto status_string = std::to_string(status_code);
97   auto reason_phrase = http::get_reason_phrase(status_code);
98 
99   std::string body;
100   body = "<html><head><title>";
101   body += status_string;
102   body += ' ';
103   body += reason_phrase;
104   body += "</title></head><body><h1>";
105   body += status_string;
106   body += ' ';
107   body += reason_phrase;
108   body += "</h1><hr><address>";
109   body += NGTCP2_SERVER;
110   body += " at port ";
111   body += std::to_string(config.port);
112   body += "</address>";
113   body += "</body></html>";
114   return body;
115 }
116 } // namespace
117 
118 struct Request {
119   std::string path;
120   struct {
121     int32_t urgency;
122     int inc;
123   } pri;
124 };
125 
126 namespace {
request_path(const std::string_view & uri,bool is_connect)127 Request request_path(const std::string_view &uri, bool is_connect) {
128   http_parser_url u;
129   Request req;
130 
131   req.pri.urgency = -1;
132   req.pri.inc = -1;
133 
134   http_parser_url_init(&u);
135 
136   if (auto rv = http_parser_parse_url(uri.data(), uri.size(), is_connect, &u);
137       rv != 0) {
138     return req;
139   }
140 
141   if (u.field_set & (1 << UF_PATH)) {
142     req.path = std::string(uri.data() + u.field_data[UF_PATH].off,
143                            u.field_data[UF_PATH].len);
144     if (req.path.find('%') != std::string::npos) {
145       req.path = util::percent_decode(std::begin(req.path), std::end(req.path));
146     }
147     if (!req.path.empty() && req.path.back() == '/') {
148       req.path += "index.html";
149     }
150   } else {
151     req.path = "/index.html";
152   }
153 
154   req.path = util::normalize_path(req.path);
155   if (req.path == "/") {
156     req.path = "/index.html";
157   }
158 
159   if (u.field_set & (1 << UF_QUERY)) {
160     static constexpr char urgency_prefix[] = "u=";
161     static constexpr char inc_prefix[] = "i=";
162     auto q = std::string(uri.data() + u.field_data[UF_QUERY].off,
163                          u.field_data[UF_QUERY].len);
164     for (auto p = std::begin(q); p != std::end(q);) {
165       if (util::istarts_with(p, std::end(q), std::begin(urgency_prefix),
166                              std::end(urgency_prefix) - 1)) {
167         auto urgency_start = p + sizeof(urgency_prefix) - 1;
168         auto urgency_end = std::find(urgency_start, std::end(q), '&');
169         if (urgency_start + 1 == urgency_end && '0' <= *urgency_start &&
170             *urgency_start <= '7') {
171           req.pri.urgency = *urgency_start - '0';
172         }
173         if (urgency_end == std::end(q)) {
174           break;
175         }
176         p = urgency_end + 1;
177         continue;
178       }
179       if (util::istarts_with(p, std::end(q), std::begin(inc_prefix),
180                              std::end(inc_prefix) - 1)) {
181         auto inc_start = p + sizeof(inc_prefix) - 1;
182         auto inc_end = std::find(inc_start, std::end(q), '&');
183         if (inc_start + 1 == inc_end &&
184             (*inc_start == '0' || *inc_start == '1')) {
185           req.pri.inc = *inc_start - '0';
186         }
187         if (inc_end == std::end(q)) {
188           break;
189         }
190         p = inc_end + 1;
191         continue;
192       }
193 
194       p = std::find(p, std::end(q), '&');
195       if (p == std::end(q)) {
196         break;
197       }
198       ++p;
199     }
200   }
201   return req;
202 }
203 } // namespace
204 
205 enum FileEntryFlag {
206   FILE_ENTRY_TYPE_DIR = 0x1,
207 };
208 
209 struct FileEntry {
210   uint64_t len;
211   void *map;
212   int fd;
213   uint8_t flags;
214 };
215 
216 namespace {
217 std::unordered_map<std::string, FileEntry> file_cache;
218 } // namespace
219 
open_file(const std::string & path)220 std::pair<FileEntry, int> Stream::open_file(const std::string &path) {
221   auto it = file_cache.find(path);
222   if (it != std::end(file_cache)) {
223     return {(*it).second, 0};
224   }
225 
226   auto fd = open(path.c_str(), O_RDONLY);
227   if (fd == -1) {
228     return {{}, -1};
229   }
230 
231   struct stat st {};
232   if (fstat(fd, &st) != 0) {
233     close(fd);
234     return {{}, -1};
235   }
236 
237   FileEntry fe{};
238   if (st.st_mode & S_IFDIR) {
239     fe.flags |= FILE_ENTRY_TYPE_DIR;
240     fe.fd = -1;
241     close(fd);
242   } else {
243     fe.fd = fd;
244     fe.len = st.st_size;
245     fe.map = mmap(nullptr, fe.len, PROT_READ, MAP_SHARED, fd, 0);
246     if (fe.map == MAP_FAILED) {
247       std::cerr << "mmap: " << strerror(errno) << std::endl;
248       close(fd);
249       return {{}, -1};
250     }
251   }
252 
253   file_cache.emplace(path, fe);
254 
255   return {std::move(fe), 0};
256 }
257 
map_file(const FileEntry & fe)258 void Stream::map_file(const FileEntry &fe) {
259   data = static_cast<uint8_t *>(fe.map);
260   datalen = fe.len;
261 }
262 
find_dyn_length(const std::string_view & path)263 int64_t Stream::find_dyn_length(const std::string_view &path) {
264   assert(path[0] == '/');
265 
266   if (path.size() == 1) {
267     return -1;
268   }
269 
270   uint64_t n = 0;
271 
272   for (auto it = std::begin(path) + 1; it != std::end(path); ++it) {
273     if (*it < '0' || '9' < *it) {
274       return -1;
275     }
276     auto d = *it - '0';
277     if (n > (((1ull << 62) - 1) - d) / 10) {
278       return -1;
279     }
280     n = n * 10 + d;
281     if (n > config.max_dyn_length) {
282       return -1;
283     }
284   }
285 
286   return static_cast<int64_t>(n);
287 }
288 
289 namespace {
read_data(nghttp3_conn * conn,int64_t stream_id,nghttp3_vec * vec,size_t veccnt,uint32_t * pflags,void * user_data,void * stream_user_data)290 nghttp3_ssize read_data(nghttp3_conn *conn, int64_t stream_id, nghttp3_vec *vec,
291                         size_t veccnt, uint32_t *pflags, void *user_data,
292                         void *stream_user_data) {
293   auto stream = static_cast<Stream *>(stream_user_data);
294 
295   vec[0].base = stream->data;
296   vec[0].len = stream->datalen;
297   *pflags |= NGHTTP3_DATA_FLAG_EOF;
298   if (config.send_trailers) {
299     *pflags |= NGHTTP3_DATA_FLAG_NO_END_STREAM;
300   }
301 
302   return 1;
303 }
304 } // namespace
305 
306 auto dyn_buf = std::make_unique<std::array<uint8_t, 16_k>>();
307 
308 namespace {
dyn_read_data(nghttp3_conn * conn,int64_t stream_id,nghttp3_vec * vec,size_t veccnt,uint32_t * pflags,void * user_data,void * stream_user_data)309 nghttp3_ssize dyn_read_data(nghttp3_conn *conn, int64_t stream_id,
310                             nghttp3_vec *vec, size_t veccnt, uint32_t *pflags,
311                             void *user_data, void *stream_user_data) {
312   auto stream = static_cast<Stream *>(stream_user_data);
313 
314   if (stream->dynbuflen > MAX_DYNBUFLEN) {
315     return NGHTTP3_ERR_WOULDBLOCK;
316   }
317 
318   auto len =
319       std::min(dyn_buf->size(), static_cast<size_t>(stream->dyndataleft));
320 
321   vec[0].base = dyn_buf->data();
322   vec[0].len = len;
323 
324   stream->dynbuflen += len;
325   stream->dyndataleft -= len;
326 
327   if (stream->dyndataleft == 0) {
328     *pflags |= NGHTTP3_DATA_FLAG_EOF;
329     if (config.send_trailers) {
330       *pflags |= NGHTTP3_DATA_FLAG_NO_END_STREAM;
331       auto stream_id_str = std::to_string(stream_id);
332       std::array<nghttp3_nv, 1> trailers{
333           util::make_nv("x-ngtcp2-stream-id", stream_id_str),
334       };
335 
336       if (auto rv = nghttp3_conn_submit_trailers(
337               conn, stream_id, trailers.data(), trailers.size());
338           rv != 0) {
339         std::cerr << "nghttp3_conn_submit_trailers: " << nghttp3_strerror(rv)
340                   << std::endl;
341         return NGHTTP3_ERR_CALLBACK_FAILURE;
342       }
343     }
344   }
345 
346   return 1;
347 }
348 } // namespace
349 
http_acked_stream_data(uint64_t datalen)350 void Stream::http_acked_stream_data(uint64_t datalen) {
351   if (!dynresp) {
352     return;
353   }
354 
355   assert(dynbuflen >= datalen);
356 
357   dynbuflen -= datalen;
358 }
359 
send_status_response(nghttp3_conn * httpconn,unsigned int status_code,const std::vector<HTTPHeader> & extra_headers)360 int Stream::send_status_response(nghttp3_conn *httpconn,
361                                  unsigned int status_code,
362                                  const std::vector<HTTPHeader> &extra_headers) {
363   status_resp_body = make_status_body(status_code);
364 
365   auto status_code_str = std::to_string(status_code);
366   auto content_length_str = std::to_string(status_resp_body.size());
367 
368   std::vector<nghttp3_nv> nva(4 + extra_headers.size());
369   nva[0] = util::make_nv(":status", status_code_str);
370   nva[1] = util::make_nv("server", NGTCP2_SERVER);
371   nva[2] = util::make_nv("content-type", "text/html; charset=utf-8");
372   nva[3] = util::make_nv("content-length", content_length_str);
373   for (size_t i = 0; i < extra_headers.size(); ++i) {
374     auto &hdr = extra_headers[i];
375     auto &nv = nva[4 + i];
376     nv = util::make_nv(hdr.name, hdr.value);
377   }
378 
379   data = (uint8_t *)status_resp_body.data();
380   datalen = status_resp_body.size();
381 
382   nghttp3_data_reader dr{};
383   dr.read_data = read_data;
384 
385   if (auto rv = nghttp3_conn_submit_response(httpconn, stream_id, nva.data(),
386                                              nva.size(), &dr);
387       rv != 0) {
388     std::cerr << "nghttp3_conn_submit_response: " << nghttp3_strerror(rv)
389               << std::endl;
390     return -1;
391   }
392 
393   if (config.send_trailers) {
394     auto stream_id_str = std::to_string(stream_id);
395     std::array<nghttp3_nv, 1> trailers{
396         util::make_nv("x-ngtcp2-stream-id", stream_id_str),
397     };
398 
399     if (auto rv = nghttp3_conn_submit_trailers(
400             httpconn, stream_id, trailers.data(), trailers.size());
401         rv != 0) {
402       std::cerr << "nghttp3_conn_submit_trailers: " << nghttp3_strerror(rv)
403                 << std::endl;
404       return -1;
405     }
406   }
407 
408   handler->shutdown_read(stream_id, NGHTTP3_H3_NO_ERROR);
409 
410   return 0;
411 }
412 
send_redirect_response(nghttp3_conn * httpconn,unsigned int status_code,const std::string_view & path)413 int Stream::send_redirect_response(nghttp3_conn *httpconn,
414                                    unsigned int status_code,
415                                    const std::string_view &path) {
416   return send_status_response(httpconn, status_code, {{"location", path}});
417 }
418 
start_response(nghttp3_conn * httpconn)419 int Stream::start_response(nghttp3_conn *httpconn) {
420   // TODO This should be handled by nghttp3
421   if (uri.empty() || method.empty()) {
422     return send_status_response(httpconn, 400);
423   }
424 
425   auto req = request_path(uri, method == "CONNECT");
426   if (req.path.empty()) {
427     return send_status_response(httpconn, 400);
428   }
429 
430   auto dyn_len = find_dyn_length(req.path);
431 
432   int64_t content_length = -1;
433   nghttp3_data_reader dr{};
434   std::string content_type = "text/plain";
435 
436   if (dyn_len == -1) {
437     auto path = config.htdocs + req.path;
438     auto [fe, rv] = open_file(path);
439     if (rv != 0) {
440       send_status_response(httpconn, 404);
441       return 0;
442     }
443 
444     if (fe.flags & FILE_ENTRY_TYPE_DIR) {
445       send_redirect_response(httpconn, 308,
446                              path.substr(config.htdocs.size() - 1) + '/');
447       return 0;
448     }
449 
450     content_length = fe.len;
451 
452     if (method != "HEAD") {
453       map_file(fe);
454     }
455 
456     dr.read_data = read_data;
457 
458     auto ext = std::end(req.path) - 1;
459     for (; ext != std::begin(req.path) && *ext != '.' && *ext != '/'; --ext)
460       ;
461     if (*ext == '.') {
462       ++ext;
463       auto it = config.mime_types.find(std::string{ext, std::end(req.path)});
464       if (it != std::end(config.mime_types)) {
465         content_type = (*it).second;
466       }
467     }
468   } else {
469     content_length = dyn_len;
470     dynresp = true;
471     dr.read_data = dyn_read_data;
472 
473     if (method != "HEAD") {
474       datalen = dyn_len;
475       dyndataleft = dyn_len;
476     }
477 
478     content_type = "application/octet-stream";
479   }
480 
481   auto content_length_str = std::to_string(content_length);
482 
483   std::array<nghttp3_nv, 5> nva{
484       util::make_nv(":status", "200"),
485       util::make_nv("server", NGTCP2_SERVER),
486       util::make_nv("content-type", content_type),
487       util::make_nv("content-length", content_length_str),
488   };
489 
490   size_t nvlen = 4;
491 
492   std::string prival;
493 
494   if (req.pri.urgency != -1 || req.pri.inc != -1) {
495     nghttp3_pri pri;
496 
497     if (auto rv = nghttp3_conn_get_stream_priority(httpconn, &pri, stream_id);
498         rv != 0) {
499       std::cerr << "nghttp3_conn_get_stream_priority: " << nghttp3_strerror(rv)
500                 << std::endl;
501       return -1;
502     }
503 
504     if (req.pri.urgency != -1) {
505       pri.urgency = req.pri.urgency;
506     }
507     if (req.pri.inc != -1) {
508       pri.inc = req.pri.inc;
509     }
510 
511     if (auto rv = nghttp3_conn_set_stream_priority(httpconn, stream_id, &pri);
512         rv != 0) {
513       std::cerr << "nghttp3_conn_set_stream_priority: " << nghttp3_strerror(rv)
514                 << std::endl;
515       return -1;
516     }
517 
518     prival = "u=";
519     prival += pri.urgency + '0';
520     prival += ",i";
521     if (!pri.inc) {
522       prival += "=?0";
523     }
524 
525     nva[nvlen++] = util::make_nv("priority", prival);
526   }
527 
528   if (!config.quiet) {
529     debug::print_http_response_headers(stream_id, nva.data(), nvlen);
530   }
531 
532   if (auto rv = nghttp3_conn_submit_response(httpconn, stream_id, nva.data(),
533                                              nvlen, &dr);
534       rv != 0) {
535     std::cerr << "nghttp3_conn_submit_response: " << nghttp3_strerror(rv)
536               << std::endl;
537     return -1;
538   }
539 
540   if (config.send_trailers && dyn_len == -1) {
541     auto stream_id_str = std::to_string(stream_id);
542     std::array<nghttp3_nv, 1> trailers{
543         util::make_nv("x-ngtcp2-stream-id", stream_id_str),
544     };
545 
546     if (auto rv = nghttp3_conn_submit_trailers(
547             httpconn, stream_id, trailers.data(), trailers.size());
548         rv != 0) {
549       std::cerr << "nghttp3_conn_submit_trailers: " << nghttp3_strerror(rv)
550                 << std::endl;
551       return -1;
552     }
553   }
554 
555   return 0;
556 }
557 
558 namespace {
writecb(struct ev_loop * loop,ev_io * w,int revents)559 void writecb(struct ev_loop *loop, ev_io *w, int revents) {
560   ev_io_stop(loop, w);
561 
562   auto h = static_cast<Handler *>(w->data);
563   auto s = h->server();
564 
565   switch (h->on_write()) {
566   case 0:
567   case NETWORK_ERR_CLOSE_WAIT:
568     return;
569   default:
570     s->remove(h);
571   }
572 }
573 } // namespace
574 
575 namespace {
timeoutcb(struct ev_loop * loop,ev_timer * w,int revents)576 void timeoutcb(struct ev_loop *loop, ev_timer *w, int revents) {
577   auto h = static_cast<Handler *>(w->data);
578   auto s = h->server();
579 
580   if (ngtcp2_conn_is_in_closing_period(h->conn())) {
581     if (!config.quiet) {
582       std::cerr << "Closing Period is over" << std::endl;
583     }
584 
585     s->remove(h);
586     return;
587   }
588   if (h->draining()) {
589     if (!config.quiet) {
590       std::cerr << "Draining Period is over" << std::endl;
591     }
592 
593     s->remove(h);
594     return;
595   }
596 
597   if (!config.quiet) {
598     std::cerr << "Timeout" << std::endl;
599   }
600 
601   h->start_draining_period();
602 }
603 } // namespace
604 
605 namespace {
retransmitcb(struct ev_loop * loop,ev_timer * w,int revents)606 void retransmitcb(struct ev_loop *loop, ev_timer *w, int revents) {
607   int rv;
608 
609   auto h = static_cast<Handler *>(w->data);
610   auto s = h->server();
611 
612   if (!config.quiet) {
613     std::cerr << "Timer expired" << std::endl;
614   }
615 
616   rv = h->handle_expiry();
617   if (rv != 0) {
618     goto fail;
619   }
620 
621   rv = h->on_write();
622   if (rv != 0) {
623     goto fail;
624   }
625 
626   return;
627 
628 fail:
629   switch (rv) {
630   case NETWORK_ERR_CLOSE_WAIT:
631     ev_timer_stop(loop, w);
632     return;
633   default:
634     s->remove(h);
635     return;
636   }
637 }
638 } // namespace
639 
Handler(struct ev_loop * loop,Server * server)640 Handler::Handler(struct ev_loop *loop, Server *server)
641     : loop_(loop),
642       server_(server),
643       qlog_(nullptr),
644       scid_{},
645       httpconn_{nullptr},
646       nkey_update_(0),
647       draining_(false) {
648   ev_io_init(&wev_, writecb, 0, EV_WRITE);
649   wev_.data = this;
650   ev_timer_init(&timer_, timeoutcb, 0.,
651                 static_cast<double>(config.timeout) / NGTCP2_SECONDS);
652   timer_.data = this;
653   ev_timer_init(&rttimer_, retransmitcb, 0., 0.);
654   rttimer_.data = this;
655 
__anon50ca2e3d0e02() 656   application_tx_key_cb_ = [this]() { return setup_httpconn(); };
657 }
658 
~Handler()659 Handler::~Handler() {
660   if (!config.quiet) {
661     std::cerr << scid_ << " Closing QUIC connection " << std::endl;
662   }
663 
664   ev_timer_stop(loop_, &rttimer_);
665   ev_timer_stop(loop_, &timer_);
666   ev_io_stop(loop_, &wev_);
667 
668   if (httpconn_) {
669     nghttp3_conn_del(httpconn_);
670   }
671 
672   if (qlog_) {
673     fclose(qlog_);
674   }
675 }
676 
677 namespace {
handshake_completed(ngtcp2_conn * conn,void * user_data)678 int handshake_completed(ngtcp2_conn *conn, void *user_data) {
679   auto h = static_cast<Handler *>(user_data);
680 
681   if (!config.quiet) {
682     debug::handshake_completed(conn, user_data);
683   }
684 
685   if (h->handshake_completed() != 0) {
686     return NGTCP2_ERR_CALLBACK_FAILURE;
687   }
688 
689   return 0;
690 }
691 } // namespace
692 
handshake_completed()693 int Handler::handshake_completed() {
694   if (!config.quiet) {
695     std::cerr << "Negotiated cipher suite is " << tls_session_.get_cipher_name()
696               << std::endl;
697     std::cerr << "Negotiated ALPN is " << tls_session_.get_selected_alpn()
698               << std::endl;
699   }
700 
701   if (tls_session_.send_session_ticket() != 0) {
702     std::cerr << "Unable to send session ticket" << std::endl;
703   }
704 
705   std::array<uint8_t, NGTCP2_CRYPTO_MAX_REGULAR_TOKENLEN> token;
706 
707   auto path = ngtcp2_conn_get_path(conn_);
708   auto t = std::chrono::duration_cast<std::chrono::nanoseconds>(
709                std::chrono::system_clock::now().time_since_epoch())
710                .count();
711 
712   auto tokenlen = ngtcp2_crypto_generate_regular_token(
713       token.data(), config.static_secret.data(), config.static_secret.size(),
714       path->remote.addr, path->remote.addrlen, t);
715   if (tokenlen < 0) {
716     if (!config.quiet) {
717       std::cerr << "Unable to generate token" << std::endl;
718     }
719     return 0;
720   }
721 
722   if (auto rv = ngtcp2_conn_submit_new_token(conn_, token.data(), tokenlen);
723       rv != 0) {
724     if (!config.quiet) {
725       std::cerr << "ngtcp2_conn_submit_new_token: " << ngtcp2_strerror(rv)
726                 << std::endl;
727     }
728     return -1;
729   }
730 
731   return 0;
732 }
733 
734 namespace {
do_hp_mask(uint8_t * dest,const ngtcp2_crypto_cipher * hp,const ngtcp2_crypto_cipher_ctx * hp_ctx,const uint8_t * sample)735 int do_hp_mask(uint8_t *dest, const ngtcp2_crypto_cipher *hp,
736                const ngtcp2_crypto_cipher_ctx *hp_ctx, const uint8_t *sample) {
737   if (ngtcp2_crypto_hp_mask(dest, hp, hp_ctx, sample) != 0) {
738     return NGTCP2_ERR_CALLBACK_FAILURE;
739   }
740 
741   if (!config.quiet && config.show_secret) {
742     debug::print_hp_mask(dest, NGTCP2_HP_MASKLEN, sample, NGTCP2_HP_SAMPLELEN);
743   }
744 
745   return 0;
746 }
747 } // namespace
748 
749 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)750 int recv_crypto_data(ngtcp2_conn *conn, ngtcp2_crypto_level crypto_level,
751                      uint64_t offset, const uint8_t *data, size_t datalen,
752                      void *user_data) {
753   if (!config.quiet && !config.no_quic_dump) {
754     debug::print_crypto_data(crypto_level, data, datalen);
755   }
756 
757   return ngtcp2_crypto_recv_crypto_data_cb(conn, crypto_level, offset, data,
758                                            datalen, user_data);
759 }
760 } // namespace
761 
762 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)763 int recv_stream_data(ngtcp2_conn *conn, uint32_t flags, int64_t stream_id,
764                      uint64_t offset, const uint8_t *data, size_t datalen,
765                      void *user_data, void *stream_user_data) {
766   auto h = static_cast<Handler *>(user_data);
767 
768   if (h->recv_stream_data(flags, stream_id, data, datalen) != 0) {
769     return NGTCP2_ERR_CALLBACK_FAILURE;
770   }
771 
772   return 0;
773 }
774 } // namespace
775 
776 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)777 int acked_stream_data_offset(ngtcp2_conn *conn, int64_t stream_id,
778                              uint64_t offset, uint64_t datalen, void *user_data,
779                              void *stream_user_data) {
780   auto h = static_cast<Handler *>(user_data);
781   if (h->acked_stream_data_offset(stream_id, datalen) != 0) {
782     return NGTCP2_ERR_CALLBACK_FAILURE;
783   }
784   return 0;
785 }
786 } // namespace
787 
acked_stream_data_offset(int64_t stream_id,uint64_t datalen)788 int Handler::acked_stream_data_offset(int64_t stream_id, uint64_t datalen) {
789   if (!httpconn_) {
790     return 0;
791   }
792 
793   if (auto rv = nghttp3_conn_add_ack_offset(httpconn_, stream_id, datalen);
794       rv != 0) {
795     std::cerr << "nghttp3_conn_add_ack_offset: " << nghttp3_strerror(rv)
796               << std::endl;
797     return -1;
798   }
799 
800   return 0;
801 }
802 
803 namespace {
stream_open(ngtcp2_conn * conn,int64_t stream_id,void * user_data)804 int stream_open(ngtcp2_conn *conn, int64_t stream_id, void *user_data) {
805   auto h = static_cast<Handler *>(user_data);
806   h->on_stream_open(stream_id);
807   return 0;
808 }
809 } // namespace
810 
on_stream_open(int64_t stream_id)811 void Handler::on_stream_open(int64_t stream_id) {
812   if (!ngtcp2_is_bidi_stream(stream_id)) {
813     return;
814   }
815   auto it = streams_.find(stream_id);
816   (void)it;
817   assert(it == std::end(streams_));
818   streams_.emplace(stream_id, std::make_unique<Stream>(stream_id, this));
819 }
820 
821 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)822 int stream_close(ngtcp2_conn *conn, uint32_t flags, int64_t stream_id,
823                  uint64_t app_error_code, void *user_data,
824                  void *stream_user_data) {
825   auto h = static_cast<Handler *>(user_data);
826 
827   if (!(flags & NGTCP2_STREAM_CLOSE_FLAG_APP_ERROR_CODE_SET)) {
828     app_error_code = NGHTTP3_H3_NO_ERROR;
829   }
830 
831   if (h->on_stream_close(stream_id, app_error_code) != 0) {
832     return NGTCP2_ERR_CALLBACK_FAILURE;
833   }
834   return 0;
835 }
836 } // namespace
837 
838 namespace {
stream_reset(ngtcp2_conn * conn,int64_t stream_id,uint64_t final_size,uint64_t app_error_code,void * user_data,void * stream_user_data)839 int stream_reset(ngtcp2_conn *conn, int64_t stream_id, uint64_t final_size,
840                  uint64_t app_error_code, void *user_data,
841                  void *stream_user_data) {
842   auto h = static_cast<Handler *>(user_data);
843   if (h->on_stream_reset(stream_id) != 0) {
844     return NGTCP2_ERR_CALLBACK_FAILURE;
845   }
846   return 0;
847 }
848 } // namespace
849 
on_stream_reset(int64_t stream_id)850 int Handler::on_stream_reset(int64_t stream_id) {
851   if (httpconn_) {
852     if (auto rv = nghttp3_conn_shutdown_stream_read(httpconn_, stream_id);
853         rv != 0) {
854       std::cerr << "nghttp3_conn_shutdown_stream_read: " << nghttp3_strerror(rv)
855                 << std::endl;
856       return -1;
857     }
858   }
859   return 0;
860 }
861 
862 namespace {
stream_stop_sending(ngtcp2_conn * conn,int64_t stream_id,uint64_t app_error_code,void * user_data,void * stream_user_data)863 int stream_stop_sending(ngtcp2_conn *conn, int64_t stream_id,
864                         uint64_t app_error_code, void *user_data,
865                         void *stream_user_data) {
866   auto h = static_cast<Handler *>(user_data);
867   if (h->on_stream_stop_sending(stream_id) != 0) {
868     return NGTCP2_ERR_CALLBACK_FAILURE;
869   }
870   return 0;
871 }
872 } // namespace
873 
on_stream_stop_sending(int64_t stream_id)874 int Handler::on_stream_stop_sending(int64_t stream_id) {
875   if (!httpconn_) {
876     return 0;
877   }
878 
879   if (auto rv = nghttp3_conn_shutdown_stream_read(httpconn_, stream_id);
880       rv != 0) {
881     std::cerr << "nghttp3_conn_shutdown_stream_read: " << nghttp3_strerror(rv)
882               << std::endl;
883     return -1;
884   }
885 
886   return 0;
887 }
888 
889 namespace {
rand(uint8_t * dest,size_t destlen,const ngtcp2_rand_ctx * rand_ctx)890 void rand(uint8_t *dest, size_t destlen, const ngtcp2_rand_ctx *rand_ctx) {
891   auto dis = std::uniform_int_distribution<uint8_t>(0, 255);
892   std::generate(dest, dest + destlen, [&dis]() { return dis(randgen); });
893 }
894 } // namespace
895 
896 namespace {
get_new_connection_id(ngtcp2_conn * conn,ngtcp2_cid * cid,uint8_t * token,size_t cidlen,void * user_data)897 int get_new_connection_id(ngtcp2_conn *conn, ngtcp2_cid *cid, uint8_t *token,
898                           size_t cidlen, void *user_data) {
899   if (util::generate_secure_random(cid->data, cidlen) != 0) {
900     return NGTCP2_ERR_CALLBACK_FAILURE;
901   }
902 
903   cid->datalen = cidlen;
904   if (ngtcp2_crypto_generate_stateless_reset_token(
905           token, config.static_secret.data(), config.static_secret.size(),
906           cid) != 0) {
907     return NGTCP2_ERR_CALLBACK_FAILURE;
908   }
909 
910   auto h = static_cast<Handler *>(user_data);
911   h->server()->associate_cid(cid, h);
912 
913   return 0;
914 }
915 } // namespace
916 
917 namespace {
remove_connection_id(ngtcp2_conn * conn,const ngtcp2_cid * cid,void * user_data)918 int remove_connection_id(ngtcp2_conn *conn, const ngtcp2_cid *cid,
919                          void *user_data) {
920   auto h = static_cast<Handler *>(user_data);
921   h->server()->dissociate_cid(cid);
922   return 0;
923 }
924 } // namespace
925 
926 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)927 int update_key(ngtcp2_conn *conn, uint8_t *rx_secret, uint8_t *tx_secret,
928                ngtcp2_crypto_aead_ctx *rx_aead_ctx, uint8_t *rx_iv,
929                ngtcp2_crypto_aead_ctx *tx_aead_ctx, uint8_t *tx_iv,
930                const uint8_t *current_rx_secret,
931                const uint8_t *current_tx_secret, size_t secretlen,
932                void *user_data) {
933   auto h = static_cast<Handler *>(user_data);
934   if (h->update_key(rx_secret, tx_secret, rx_aead_ctx, rx_iv, tx_aead_ctx,
935                     tx_iv, current_rx_secret, current_tx_secret,
936                     secretlen) != 0) {
937     return NGTCP2_ERR_CALLBACK_FAILURE;
938   }
939   return 0;
940 }
941 } // namespace
942 
943 namespace {
path_validation(ngtcp2_conn * conn,uint32_t flags,const ngtcp2_path * path,ngtcp2_path_validation_result res,void * user_data)944 int path_validation(ngtcp2_conn *conn, uint32_t flags, const ngtcp2_path *path,
945                     ngtcp2_path_validation_result res, void *user_data) {
946   if (!config.quiet) {
947     debug::path_validation(path, res);
948   }
949   return 0;
950 }
951 } // namespace
952 
953 namespace {
extend_max_remote_streams_bidi(ngtcp2_conn * conn,uint64_t max_streams,void * user_data)954 int extend_max_remote_streams_bidi(ngtcp2_conn *conn, uint64_t max_streams,
955                                    void *user_data) {
956   auto h = static_cast<Handler *>(user_data);
957   h->extend_max_remote_streams_bidi(max_streams);
958   return 0;
959 }
960 } // namespace
961 
extend_max_remote_streams_bidi(uint64_t max_streams)962 void Handler::extend_max_remote_streams_bidi(uint64_t max_streams) {
963   if (!httpconn_) {
964     return;
965   }
966 
967   nghttp3_conn_set_max_client_streams_bidi(httpconn_, max_streams);
968 }
969 
970 namespace {
http_recv_data(nghttp3_conn * conn,int64_t stream_id,const uint8_t * data,size_t datalen,void * user_data,void * stream_user_data)971 int http_recv_data(nghttp3_conn *conn, int64_t stream_id, const uint8_t *data,
972                    size_t datalen, void *user_data, void *stream_user_data) {
973   if (!config.quiet && !config.no_http_dump) {
974     debug::print_http_data(stream_id, data, datalen);
975   }
976   auto h = static_cast<Handler *>(user_data);
977   h->http_consume(stream_id, datalen);
978   return 0;
979 }
980 } // namespace
981 
982 namespace {
http_deferred_consume(nghttp3_conn * conn,int64_t stream_id,size_t nconsumed,void * user_data,void * stream_user_data)983 int http_deferred_consume(nghttp3_conn *conn, int64_t stream_id,
984                           size_t nconsumed, void *user_data,
985                           void *stream_user_data) {
986   auto h = static_cast<Handler *>(user_data);
987   h->http_consume(stream_id, nconsumed);
988   return 0;
989 }
990 } // namespace
991 
http_consume(int64_t stream_id,size_t nconsumed)992 void Handler::http_consume(int64_t stream_id, size_t nconsumed) {
993   ngtcp2_conn_extend_max_stream_offset(conn_, stream_id, nconsumed);
994   ngtcp2_conn_extend_max_offset(conn_, nconsumed);
995 }
996 
997 namespace {
http_begin_request_headers(nghttp3_conn * conn,int64_t stream_id,void * user_data,void * stream_user_data)998 int http_begin_request_headers(nghttp3_conn *conn, int64_t stream_id,
999                                void *user_data, void *stream_user_data) {
1000   if (!config.quiet) {
1001     debug::print_http_begin_request_headers(stream_id);
1002   }
1003 
1004   auto h = static_cast<Handler *>(user_data);
1005   h->http_begin_request_headers(stream_id);
1006   return 0;
1007 }
1008 } // namespace
1009 
http_begin_request_headers(int64_t stream_id)1010 void Handler::http_begin_request_headers(int64_t stream_id) {
1011   auto it = streams_.find(stream_id);
1012   assert(it != std::end(streams_));
1013   auto &stream = (*it).second;
1014 
1015   nghttp3_conn_set_stream_user_data(httpconn_, stream_id, stream.get());
1016 }
1017 
1018 namespace {
http_recv_request_header(nghttp3_conn * conn,int64_t stream_id,int32_t token,nghttp3_rcbuf * name,nghttp3_rcbuf * value,uint8_t flags,void * user_data,void * stream_user_data)1019 int http_recv_request_header(nghttp3_conn *conn, int64_t stream_id,
1020                              int32_t token, nghttp3_rcbuf *name,
1021                              nghttp3_rcbuf *value, uint8_t flags,
1022                              void *user_data, void *stream_user_data) {
1023   if (!config.quiet) {
1024     debug::print_http_header(stream_id, name, value, flags);
1025   }
1026 
1027   auto h = static_cast<Handler *>(user_data);
1028   auto stream = static_cast<Stream *>(stream_user_data);
1029   h->http_recv_request_header(stream, token, name, value);
1030   return 0;
1031 }
1032 } // namespace
1033 
http_recv_request_header(Stream * stream,int32_t token,nghttp3_rcbuf * name,nghttp3_rcbuf * value)1034 void Handler::http_recv_request_header(Stream *stream, int32_t token,
1035                                        nghttp3_rcbuf *name,
1036                                        nghttp3_rcbuf *value) {
1037   auto v = nghttp3_rcbuf_get_buf(value);
1038 
1039   switch (token) {
1040   case NGHTTP3_QPACK_TOKEN__PATH:
1041     stream->uri = std::string{v.base, v.base + v.len};
1042     break;
1043   case NGHTTP3_QPACK_TOKEN__METHOD:
1044     stream->method = std::string{v.base, v.base + v.len};
1045     break;
1046   case NGHTTP3_QPACK_TOKEN__AUTHORITY:
1047     stream->authority = std::string{v.base, v.base + v.len};
1048     break;
1049   }
1050 }
1051 
1052 namespace {
http_end_request_headers(nghttp3_conn * conn,int64_t stream_id,void * user_data,void * stream_user_data)1053 int http_end_request_headers(nghttp3_conn *conn, int64_t stream_id,
1054                              void *user_data, void *stream_user_data) {
1055   if (!config.quiet) {
1056     debug::print_http_end_headers(stream_id);
1057   }
1058 
1059   auto h = static_cast<Handler *>(user_data);
1060   auto stream = static_cast<Stream *>(stream_user_data);
1061   if (h->http_end_request_headers(stream) != 0) {
1062     return NGHTTP3_ERR_CALLBACK_FAILURE;
1063   }
1064   return 0;
1065 }
1066 } // namespace
1067 
http_end_request_headers(Stream * stream)1068 int Handler::http_end_request_headers(Stream *stream) {
1069   if (config.early_response) {
1070     if (start_response(stream) != 0) {
1071       return -1;
1072     }
1073 
1074     shutdown_read(stream->stream_id, NGHTTP3_H3_NO_ERROR);
1075   }
1076   return 0;
1077 }
1078 
1079 namespace {
http_end_stream(nghttp3_conn * conn,int64_t stream_id,void * user_data,void * stream_user_data)1080 int http_end_stream(nghttp3_conn *conn, int64_t stream_id, void *user_data,
1081                     void *stream_user_data) {
1082   auto h = static_cast<Handler *>(user_data);
1083   auto stream = static_cast<Stream *>(stream_user_data);
1084   if (h->http_end_stream(stream) != 0) {
1085     return NGHTTP3_ERR_CALLBACK_FAILURE;
1086   }
1087   return 0;
1088 }
1089 } // namespace
1090 
http_end_stream(Stream * stream)1091 int Handler::http_end_stream(Stream *stream) {
1092   if (!config.early_response) {
1093     return start_response(stream);
1094   }
1095   return 0;
1096 }
1097 
start_response(Stream * stream)1098 int Handler::start_response(Stream *stream) {
1099   return stream->start_response(httpconn_);
1100 }
1101 
1102 namespace {
http_acked_stream_data(nghttp3_conn * conn,int64_t stream_id,uint64_t datalen,void * user_data,void * stream_user_data)1103 int http_acked_stream_data(nghttp3_conn *conn, int64_t stream_id,
1104                            uint64_t datalen, void *user_data,
1105                            void *stream_user_data) {
1106   auto h = static_cast<Handler *>(user_data);
1107   auto stream = static_cast<Stream *>(stream_user_data);
1108   h->http_acked_stream_data(stream, datalen);
1109   return 0;
1110 }
1111 } // namespace
1112 
http_acked_stream_data(Stream * stream,uint64_t datalen)1113 void Handler::http_acked_stream_data(Stream *stream, uint64_t datalen) {
1114   stream->http_acked_stream_data(datalen);
1115 
1116   if (stream->dynresp && stream->dynbuflen < MAX_DYNBUFLEN - 16384) {
1117     if (auto rv = nghttp3_conn_resume_stream(httpconn_, stream->stream_id);
1118         rv != 0) {
1119       // TODO Handle error
1120       std::cerr << "nghttp3_conn_resume_stream: " << nghttp3_strerror(rv)
1121                 << std::endl;
1122     }
1123   }
1124 }
1125 
1126 namespace {
http_stream_close(nghttp3_conn * conn,int64_t stream_id,uint64_t app_error_code,void * conn_user_data,void * stream_user_data)1127 int http_stream_close(nghttp3_conn *conn, int64_t stream_id,
1128                       uint64_t app_error_code, void *conn_user_data,
1129                       void *stream_user_data) {
1130   auto h = static_cast<Handler *>(conn_user_data);
1131   h->http_stream_close(stream_id, app_error_code);
1132   return 0;
1133 }
1134 } // namespace
1135 
http_stream_close(int64_t stream_id,uint64_t app_error_code)1136 void Handler::http_stream_close(int64_t stream_id, uint64_t app_error_code) {
1137   auto it = streams_.find(stream_id);
1138   if (it == std::end(streams_)) {
1139     return;
1140   }
1141 
1142   if (!config.quiet) {
1143     std::cerr << "HTTP stream " << stream_id << " closed with error code "
1144               << app_error_code << std::endl;
1145   }
1146 
1147   streams_.erase(it);
1148 
1149   if (ngtcp2_is_bidi_stream(stream_id)) {
1150     assert(!ngtcp2_conn_is_local_stream(conn_, stream_id));
1151     ngtcp2_conn_extend_max_streams_bidi(conn_, 1);
1152   }
1153 }
1154 
1155 namespace {
http_stop_sending(nghttp3_conn * conn,int64_t stream_id,uint64_t app_error_code,void * user_data,void * stream_user_data)1156 int http_stop_sending(nghttp3_conn *conn, int64_t stream_id,
1157                       uint64_t app_error_code, void *user_data,
1158                       void *stream_user_data) {
1159   auto h = static_cast<Handler *>(user_data);
1160   if (h->http_stop_sending(stream_id, app_error_code) != 0) {
1161     return NGHTTP3_ERR_CALLBACK_FAILURE;
1162   }
1163   return 0;
1164 }
1165 } // namespace
1166 
http_stop_sending(int64_t stream_id,uint64_t app_error_code)1167 int Handler::http_stop_sending(int64_t stream_id, uint64_t app_error_code) {
1168   if (auto rv =
1169           ngtcp2_conn_shutdown_stream_read(conn_, stream_id, app_error_code);
1170       rv != 0) {
1171     std::cerr << "ngtcp2_conn_shutdown_stream_read: " << ngtcp2_strerror(rv)
1172               << std::endl;
1173     if (rv == NGTCP2_ERR_STREAM_NOT_FOUND) {
1174       return 0;
1175     }
1176     return -1;
1177   }
1178   return 0;
1179 }
1180 
1181 namespace {
http_reset_stream(nghttp3_conn * conn,int64_t stream_id,uint64_t app_error_code,void * user_data,void * stream_user_data)1182 int http_reset_stream(nghttp3_conn *conn, int64_t stream_id,
1183                       uint64_t app_error_code, void *user_data,
1184                       void *stream_user_data) {
1185   auto h = static_cast<Handler *>(user_data);
1186   if (h->http_reset_stream(stream_id, app_error_code) != 0) {
1187     return NGHTTP3_ERR_CALLBACK_FAILURE;
1188   }
1189   return 0;
1190 }
1191 } // namespace
1192 
http_reset_stream(int64_t stream_id,uint64_t app_error_code)1193 int Handler::http_reset_stream(int64_t stream_id, uint64_t app_error_code) {
1194   if (auto rv =
1195           ngtcp2_conn_shutdown_stream_write(conn_, stream_id, app_error_code);
1196       rv != 0) {
1197     std::cerr << "ngtcp2_conn_shutdown_stream_write: " << ngtcp2_strerror(rv)
1198               << std::endl;
1199     if (rv == NGTCP2_ERR_STREAM_NOT_FOUND) {
1200       return 0;
1201     }
1202     return -1;
1203   }
1204   return 0;
1205 }
1206 
setup_httpconn()1207 int Handler::setup_httpconn() {
1208   if (httpconn_) {
1209     return 0;
1210   }
1211 
1212   if (ngtcp2_conn_get_max_local_streams_uni(conn_) < 3) {
1213     std::cerr << "peer does not allow at least 3 unidirectional streams."
1214               << std::endl;
1215     return -1;
1216   }
1217 
1218   nghttp3_callbacks callbacks{
1219       ::http_acked_stream_data, // acked_stream_data
1220       ::http_stream_close,
1221       ::http_recv_data,
1222       ::http_deferred_consume,
1223       ::http_begin_request_headers,
1224       ::http_recv_request_header,
1225       ::http_end_request_headers,
1226       nullptr, // begin_trailers
1227       nullptr, // recv_trailer
1228       nullptr, // end_trailers
1229       ::http_stop_sending,
1230       ::http_end_stream,
1231       ::http_reset_stream,
1232   };
1233   nghttp3_settings settings;
1234   nghttp3_settings_default(&settings);
1235   settings.qpack_max_table_capacity = 4096;
1236   settings.qpack_blocked_streams = 100;
1237 
1238   auto mem = nghttp3_mem_default();
1239 
1240   if (auto rv =
1241           nghttp3_conn_server_new(&httpconn_, &callbacks, &settings, mem, this);
1242       rv != 0) {
1243     std::cerr << "nghttp3_conn_server_new: " << nghttp3_strerror(rv)
1244               << std::endl;
1245     return -1;
1246   }
1247 
1248   ngtcp2_transport_params params;
1249   ngtcp2_conn_get_local_transport_params(conn_, &params);
1250 
1251   nghttp3_conn_set_max_client_streams_bidi(httpconn_,
1252                                            params.initial_max_streams_bidi);
1253 
1254   int64_t ctrl_stream_id;
1255 
1256   if (auto rv = ngtcp2_conn_open_uni_stream(conn_, &ctrl_stream_id, nullptr);
1257       rv != 0) {
1258     std::cerr << "ngtcp2_conn_open_uni_stream: " << ngtcp2_strerror(rv)
1259               << std::endl;
1260     return -1;
1261   }
1262 
1263   if (auto rv = nghttp3_conn_bind_control_stream(httpconn_, ctrl_stream_id);
1264       rv != 0) {
1265     std::cerr << "nghttp3_conn_bind_control_stream: " << nghttp3_strerror(rv)
1266               << std::endl;
1267     return -1;
1268   }
1269 
1270   if (!config.quiet) {
1271     fprintf(stderr, "http: control stream=%" PRIx64 "\n", ctrl_stream_id);
1272   }
1273 
1274   int64_t qpack_enc_stream_id, qpack_dec_stream_id;
1275 
1276   if (auto rv =
1277           ngtcp2_conn_open_uni_stream(conn_, &qpack_enc_stream_id, nullptr);
1278       rv != 0) {
1279     std::cerr << "ngtcp2_conn_open_uni_stream: " << ngtcp2_strerror(rv)
1280               << std::endl;
1281     return -1;
1282   }
1283 
1284   if (auto rv =
1285           ngtcp2_conn_open_uni_stream(conn_, &qpack_dec_stream_id, nullptr);
1286       rv != 0) {
1287     std::cerr << "ngtcp2_conn_open_uni_stream: " << ngtcp2_strerror(rv)
1288               << std::endl;
1289     return -1;
1290   }
1291 
1292   if (auto rv = nghttp3_conn_bind_qpack_streams(httpconn_, qpack_enc_stream_id,
1293                                                 qpack_dec_stream_id);
1294       rv != 0) {
1295     std::cerr << "nghttp3_conn_bind_qpack_streams: " << nghttp3_strerror(rv)
1296               << std::endl;
1297     return -1;
1298   }
1299 
1300   if (!config.quiet) {
1301     fprintf(stderr,
1302             "http: QPACK streams encoder=%" PRIx64 " decoder=%" PRIx64 "\n",
1303             qpack_enc_stream_id, qpack_dec_stream_id);
1304   }
1305 
1306   return 0;
1307 }
1308 
1309 namespace {
extend_max_stream_data(ngtcp2_conn * conn,int64_t stream_id,uint64_t max_data,void * user_data,void * stream_user_data)1310 int extend_max_stream_data(ngtcp2_conn *conn, int64_t stream_id,
1311                            uint64_t max_data, void *user_data,
1312                            void *stream_user_data) {
1313   auto h = static_cast<Handler *>(user_data);
1314   if (h->extend_max_stream_data(stream_id, max_data) != 0) {
1315     return NGTCP2_ERR_CALLBACK_FAILURE;
1316   }
1317   return 0;
1318 }
1319 } // namespace
1320 
extend_max_stream_data(int64_t stream_id,uint64_t max_data)1321 int Handler::extend_max_stream_data(int64_t stream_id, uint64_t max_data) {
1322   if (auto rv = nghttp3_conn_unblock_stream(httpconn_, stream_id); rv != 0) {
1323     std::cerr << "nghttp3_conn_unblock_stream: " << nghttp3_strerror(rv)
1324               << std::endl;
1325     return -1;
1326   }
1327   return 0;
1328 }
1329 
1330 namespace {
write_qlog(void * user_data,uint32_t flags,const void * data,size_t datalen)1331 void write_qlog(void *user_data, uint32_t flags, const void *data,
1332                 size_t datalen) {
1333   auto h = static_cast<Handler *>(user_data);
1334   h->write_qlog(data, datalen);
1335 }
1336 } // namespace
1337 
write_qlog(const void * data,size_t datalen)1338 void Handler::write_qlog(const void *data, size_t datalen) {
1339   assert(qlog_);
1340   fwrite(data, 1, datalen, qlog_);
1341 }
1342 
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)1343 int Handler::init(const Endpoint &ep, const Address &local_addr,
1344                   const sockaddr *sa, socklen_t salen, const ngtcp2_cid *dcid,
1345                   const ngtcp2_cid *scid, const ngtcp2_cid *ocid,
1346                   const uint8_t *token, size_t tokenlen, uint32_t version,
1347                   const TLSServerContext &tls_ctx) {
1348   auto callbacks = ngtcp2_callbacks{
1349       nullptr, // client_initial
1350       ngtcp2_crypto_recv_client_initial_cb,
1351       ::recv_crypto_data,
1352       ::handshake_completed,
1353       nullptr, // recv_version_negotiation
1354       ngtcp2_crypto_encrypt_cb,
1355       ngtcp2_crypto_decrypt_cb,
1356       do_hp_mask,
1357       ::recv_stream_data,
1358       ::acked_stream_data_offset,
1359       stream_open,
1360       stream_close,
1361       nullptr, // recv_stateless_reset
1362       nullptr, // recv_retry
1363       nullptr, // extend_max_streams_bidi
1364       nullptr, // extend_max_streams_uni
1365       rand,
1366       get_new_connection_id,
1367       remove_connection_id,
1368       ::update_key,
1369       path_validation,
1370       nullptr, // select_preferred_addr
1371       ::stream_reset,
1372       ::extend_max_remote_streams_bidi,
1373       nullptr, // extend_max_remote_streams_uni
1374       ::extend_max_stream_data,
1375       nullptr, // dcid_status
1376       nullptr, // handshake_confirmed
1377       nullptr, // recv_new_token
1378       ngtcp2_crypto_delete_crypto_aead_ctx_cb,
1379       ngtcp2_crypto_delete_crypto_cipher_ctx_cb,
1380       nullptr, // recv_datagram
1381       nullptr, // ack_datagram
1382       nullptr, // lost_datagram
1383       ngtcp2_crypto_get_path_challenge_data_cb,
1384       stream_stop_sending,
1385   };
1386 
1387   scid_.datalen = NGTCP2_SV_SCIDLEN;
1388   if (util::generate_secure_random(scid_.data, scid_.datalen) != 0) {
1389     std::cerr << "Could not generate connection ID" << std::endl;
1390     return -1;
1391   }
1392 
1393   ngtcp2_settings settings;
1394   ngtcp2_settings_default(&settings);
1395   settings.log_printf = config.quiet ? nullptr : debug::log_printf;
1396   settings.initial_ts = util::timestamp(loop_);
1397   settings.token = ngtcp2_vec{const_cast<uint8_t *>(token), tokenlen};
1398   settings.cc_algo = config.cc_algo;
1399   settings.initial_rtt = config.initial_rtt;
1400   settings.max_window = config.max_window;
1401   settings.max_stream_window = config.max_stream_window;
1402   if (config.max_udp_payload_size) {
1403     settings.max_udp_payload_size = config.max_udp_payload_size;
1404     settings.no_udp_payload_size_shaping = 1;
1405   } else {
1406     settings.max_udp_payload_size = server_max_udp_payload_size;
1407     settings.assume_symmetric_path = 1;
1408   }
1409   if (!config.qlog_dir.empty()) {
1410     auto path = std::string{config.qlog_dir};
1411     path += '/';
1412     path += util::format_hex(scid_.data, scid_.datalen);
1413     path += ".sqlog";
1414     qlog_ = fopen(path.c_str(), "w");
1415     if (qlog_ == nullptr) {
1416       std::cerr << "Could not open qlog file " << std::quoted(path) << ": "
1417                 << strerror(errno) << std::endl;
1418       return -1;
1419     }
1420     settings.qlog.write = ::write_qlog;
1421     settings.qlog.odcid = *scid;
1422   }
1423 
1424   ngtcp2_transport_params params;
1425   ngtcp2_transport_params_default(&params);
1426   params.initial_max_stream_data_bidi_local = config.max_stream_data_bidi_local;
1427   params.initial_max_stream_data_bidi_remote =
1428       config.max_stream_data_bidi_remote;
1429   params.initial_max_stream_data_uni = config.max_stream_data_uni;
1430   params.initial_max_data = config.max_data;
1431   params.initial_max_streams_bidi = config.max_streams_bidi;
1432   params.initial_max_streams_uni = config.max_streams_uni;
1433   params.max_idle_timeout = config.timeout;
1434   params.stateless_reset_token_present = 1;
1435   params.active_connection_id_limit = 7;
1436 
1437   if (ocid) {
1438     params.original_dcid = *ocid;
1439     params.retry_scid = *scid;
1440     params.retry_scid_present = 1;
1441   } else {
1442     params.original_dcid = *scid;
1443   }
1444 
1445   if (util::generate_secure_random(params.stateless_reset_token,
1446                                    sizeof(params.stateless_reset_token)) != 0) {
1447     std::cerr << "Could not generate stateless reset token" << std::endl;
1448     return -1;
1449   }
1450 
1451   if (config.preferred_ipv4_addr.len || config.preferred_ipv6_addr.len) {
1452     params.preferred_address_present = 1;
1453     if (config.preferred_ipv4_addr.len) {
1454       auto &dest = params.preferred_address.ipv4_addr;
1455       const auto &addr = config.preferred_ipv4_addr;
1456       assert(sizeof(dest) == sizeof(addr.su.in.sin_addr));
1457       memcpy(&dest, &addr.su.in.sin_addr, sizeof(dest));
1458       params.preferred_address.ipv4_port = htons(addr.su.in.sin_port);
1459       params.preferred_address.ipv4_present = 1;
1460     }
1461     if (config.preferred_ipv6_addr.len) {
1462       auto &dest = params.preferred_address.ipv6_addr;
1463       const auto &addr = config.preferred_ipv6_addr;
1464       assert(sizeof(dest) == sizeof(addr.su.in6.sin6_addr));
1465       memcpy(&dest, &addr.su.in6.sin6_addr, sizeof(dest));
1466       params.preferred_address.ipv6_port = htons(addr.su.in6.sin6_port);
1467       params.preferred_address.ipv6_present = 1;
1468     }
1469 
1470     auto &token = params.preferred_address.stateless_reset_token;
1471     if (util::generate_secure_random(token, sizeof(token)) != 0) {
1472       std::cerr << "Could not generate preferred address stateless reset token"
1473                 << std::endl;
1474       return -1;
1475     }
1476 
1477     params.preferred_address.cid.datalen = NGTCP2_SV_SCIDLEN;
1478     if (util::generate_secure_random(params.preferred_address.cid.data,
1479                                      params.preferred_address.cid.datalen) !=
1480         0) {
1481       std::cerr << "Could not generate preferred address connection ID"
1482                 << std::endl;
1483       return -1;
1484     }
1485   }
1486 
1487   auto path = ngtcp2_path{
1488       {
1489           const_cast<sockaddr *>(&local_addr.su.sa),
1490           local_addr.len,
1491       },
1492       {
1493           const_cast<sockaddr *>(sa),
1494           salen,
1495       },
1496       const_cast<Endpoint *>(&ep),
1497   };
1498   if (auto rv =
1499           ngtcp2_conn_server_new(&conn_, dcid, &scid_, &path, version,
1500                                  &callbacks, &settings, &params, nullptr, this);
1501       rv != 0) {
1502     std::cerr << "ngtcp2_conn_server_new: " << ngtcp2_strerror(rv) << std::endl;
1503     return -1;
1504   }
1505 
1506   if (tls_session_.init(tls_ctx, this) != 0) {
1507     return -1;
1508   }
1509 
1510   tls_session_.enable_keylog();
1511 
1512   ngtcp2_conn_set_tls_native_handle(conn_, tls_session_.get_native_handle());
1513 
1514   ev_io_set(&wev_, ep.fd, EV_WRITE);
1515   ev_timer_again(loop_, &timer_);
1516 
1517   return 0;
1518 }
1519 
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)1520 int Handler::feed_data(const Endpoint &ep, const Address &local_addr,
1521                        const sockaddr *sa, socklen_t salen,
1522                        const ngtcp2_pkt_info *pi, uint8_t *data,
1523                        size_t datalen) {
1524   auto path = ngtcp2_path{
1525       {
1526           const_cast<sockaddr *>(&local_addr.su.sa),
1527           local_addr.len,
1528       },
1529       {
1530           const_cast<sockaddr *>(sa),
1531           salen,
1532       },
1533       const_cast<Endpoint *>(&ep),
1534   };
1535 
1536   if (auto rv = ngtcp2_conn_read_pkt(conn_, &path, pi, data, datalen,
1537                                      util::timestamp(loop_));
1538       rv != 0) {
1539     std::cerr << "ngtcp2_conn_read_pkt: " << ngtcp2_strerror(rv) << std::endl;
1540     switch (rv) {
1541     case NGTCP2_ERR_DRAINING:
1542       start_draining_period();
1543       return NETWORK_ERR_CLOSE_WAIT;
1544     case NGTCP2_ERR_RETRY:
1545       return NETWORK_ERR_RETRY;
1546     case NGTCP2_ERR_REQUIRED_TRANSPORT_PARAM:
1547     case NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM:
1548     case NGTCP2_ERR_TRANSPORT_PARAM:
1549       // If rv indicates transport_parameters related error, we should
1550       // send TRANSPORT_PARAMETER_ERROR even if last_error_.code is
1551       // already set.  This is because OpenSSL might set Alert.
1552       last_error_ = quic_err_transport(rv);
1553       break;
1554     case NGTCP2_ERR_DROP_CONN:
1555       return NETWORK_ERR_DROP_CONN;
1556     default:
1557       if (!last_error_.code) {
1558         last_error_ = quic_err_transport(rv);
1559       }
1560     }
1561     return handle_error();
1562   }
1563 
1564   return 0;
1565 }
1566 
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)1567 int Handler::on_read(const Endpoint &ep, const Address &local_addr,
1568                      const sockaddr *sa, socklen_t salen,
1569                      const ngtcp2_pkt_info *pi, uint8_t *data, size_t datalen) {
1570   if (auto rv = feed_data(ep, local_addr, sa, salen, pi, data, datalen);
1571       rv != 0) {
1572     return rv;
1573   }
1574 
1575   reset_idle_timer();
1576 
1577   return 0;
1578 }
1579 
reset_idle_timer()1580 void Handler::reset_idle_timer() {
1581   auto now = util::timestamp(loop_);
1582   auto idle_expiry = ngtcp2_conn_get_idle_expiry(conn_);
1583   timer_.repeat =
1584       idle_expiry > now
1585           ? static_cast<ev_tstamp>(idle_expiry - now) / NGTCP2_SECONDS
1586           : 1e-9;
1587 
1588   if (!config.quiet) {
1589     std::cerr << "Set idle timer=" << std::fixed << timer_.repeat << "s"
1590               << std::defaultfloat << std::endl;
1591   }
1592 
1593   ev_timer_again(loop_, &timer_);
1594 }
1595 
handle_expiry()1596 int Handler::handle_expiry() {
1597   auto now = util::timestamp(loop_);
1598   if (auto rv = ngtcp2_conn_handle_expiry(conn_, now); rv != 0) {
1599     std::cerr << "ngtcp2_conn_handle_expiry: " << ngtcp2_strerror(rv)
1600               << std::endl;
1601     last_error_ = quic_err_transport(rv);
1602     return handle_error();
1603   }
1604 
1605   return 0;
1606 }
1607 
on_write()1608 int Handler::on_write() {
1609   if (ngtcp2_conn_is_in_closing_period(conn_) ||
1610       ngtcp2_conn_is_in_draining_period(conn_)) {
1611     return 0;
1612   }
1613 
1614   if (auto rv = write_streams(); rv != 0) {
1615     return rv;
1616   }
1617 
1618   schedule_retransmit();
1619 
1620   return 0;
1621 }
1622 
write_streams()1623 int Handler::write_streams() {
1624   std::array<nghttp3_vec, 16> vec;
1625   ngtcp2_path_storage ps, prev_ps;
1626   uint32_t prev_ecn = 0;
1627   size_t pktcnt = 0;
1628   auto max_udp_payload_size = ngtcp2_conn_get_path_max_udp_payload_size(conn_);
1629   size_t max_pktcnt =
1630       std::min(static_cast<size_t>(64_k), ngtcp2_conn_get_send_quantum(conn_)) /
1631       max_udp_payload_size;
1632   std::array<uint8_t, 64_k> buf;
1633   uint8_t *bufpos = buf.data();
1634   ngtcp2_pkt_info pi;
1635   auto ts = util::timestamp(loop_);
1636 
1637   ngtcp2_path_storage_zero(&ps);
1638   ngtcp2_path_storage_zero(&prev_ps);
1639 
1640   if (config.cc_algo != NGTCP2_CC_ALGO_BBR) {
1641     /* If bbr is chosen, pacing is enabled.  No need to cap the number
1642        of datagrams to send. */
1643     max_pktcnt =
1644         std::min(max_pktcnt, static_cast<size_t>(config.max_gso_dgrams));
1645   }
1646 
1647   for (;;) {
1648     int64_t stream_id = -1;
1649     int fin = 0;
1650     nghttp3_ssize sveccnt = 0;
1651 
1652     if (httpconn_ && ngtcp2_conn_get_max_data_left(conn_)) {
1653       sveccnt = nghttp3_conn_writev_stream(httpconn_, &stream_id, &fin,
1654                                            vec.data(), vec.size());
1655       if (sveccnt < 0) {
1656         std::cerr << "nghttp3_conn_writev_stream: " << nghttp3_strerror(sveccnt)
1657                   << std::endl;
1658         last_error_ = quic_err_app(sveccnt);
1659         return handle_error();
1660       }
1661     }
1662 
1663     ngtcp2_ssize ndatalen;
1664     auto v = vec.data();
1665     auto vcnt = static_cast<size_t>(sveccnt);
1666 
1667     uint32_t flags = NGTCP2_WRITE_STREAM_FLAG_MORE;
1668     if (fin) {
1669       flags |= NGTCP2_WRITE_STREAM_FLAG_FIN;
1670     }
1671 
1672     auto nwrite = ngtcp2_conn_writev_stream(
1673         conn_, &ps.path, &pi, bufpos, max_udp_payload_size, &ndatalen, flags,
1674         stream_id, reinterpret_cast<const ngtcp2_vec *>(v), vcnt, ts);
1675     if (nwrite < 0) {
1676       switch (nwrite) {
1677       case NGTCP2_ERR_STREAM_DATA_BLOCKED:
1678         assert(ndatalen == -1);
1679         if (auto rv = nghttp3_conn_block_stream(httpconn_, stream_id);
1680             rv != 0) {
1681           std::cerr << "nghttp3_conn_block_stream: " << nghttp3_strerror(rv)
1682                     << std::endl;
1683           last_error_ = quic_err_app(rv);
1684           return handle_error();
1685         }
1686         continue;
1687       case NGTCP2_ERR_STREAM_SHUT_WR:
1688         assert(ndatalen == -1);
1689         if (auto rv = nghttp3_conn_shutdown_stream_write(httpconn_, stream_id);
1690             rv != 0) {
1691           std::cerr << "nghttp3_conn_shutdown_stream_write: "
1692                     << nghttp3_strerror(rv) << std::endl;
1693           last_error_ = quic_err_app(rv);
1694           return handle_error();
1695         }
1696         continue;
1697       case NGTCP2_ERR_WRITE_MORE:
1698         assert(ndatalen >= 0);
1699         if (auto rv =
1700                 nghttp3_conn_add_write_offset(httpconn_, stream_id, ndatalen);
1701             rv != 0) {
1702           std::cerr << "nghttp3_conn_add_write_offset: " << nghttp3_strerror(rv)
1703                     << std::endl;
1704           last_error_ = quic_err_app(rv);
1705           return handle_error();
1706         }
1707         continue;
1708       }
1709 
1710       assert(ndatalen == -1);
1711 
1712       std::cerr << "ngtcp2_conn_writev_stream: " << ngtcp2_strerror(nwrite)
1713                 << std::endl;
1714       last_error_ = quic_err_transport(nwrite);
1715       return handle_error();
1716     } else if (ndatalen >= 0) {
1717       if (auto rv =
1718               nghttp3_conn_add_write_offset(httpconn_, stream_id, ndatalen);
1719           rv != 0) {
1720         std::cerr << "nghttp3_conn_add_write_offset: " << nghttp3_strerror(rv)
1721                   << std::endl;
1722         last_error_ = quic_err_app(rv);
1723         return handle_error();
1724       }
1725     }
1726 
1727     if (nwrite == 0) {
1728       if (bufpos - buf.data()) {
1729         server_->send_packet(*static_cast<Endpoint *>(prev_ps.path.user_data),
1730                              prev_ps.path.local, prev_ps.path.remote, prev_ecn,
1731                              buf.data(), bufpos - buf.data(),
1732                              max_udp_payload_size);
1733         reset_idle_timer();
1734       }
1735       // We are congestion limited.
1736       ngtcp2_conn_update_pkt_tx_time(conn_, ts);
1737       return 0;
1738     }
1739 
1740     bufpos += nwrite;
1741 
1742 #if NGTCP2_ENABLE_UDP_GSO
1743     if (pktcnt == 0) {
1744       ngtcp2_path_copy(&prev_ps.path, &ps.path);
1745       prev_ecn = pi.ecn;
1746     } else if (!ngtcp2_path_eq(&prev_ps.path, &ps.path) || prev_ecn != pi.ecn) {
1747       server_->send_packet(*static_cast<Endpoint *>(prev_ps.path.user_data),
1748                            prev_ps.path.local, prev_ps.path.remote, prev_ecn,
1749                            buf.data(), bufpos - buf.data() - nwrite,
1750                            max_udp_payload_size);
1751 
1752       server_->send_packet(*static_cast<Endpoint *>(ps.path.user_data),
1753                            ps.path.local, ps.path.remote, pi.ecn,
1754                            bufpos - nwrite, nwrite, max_udp_payload_size);
1755 
1756       ngtcp2_conn_update_pkt_tx_time(conn_, ts);
1757       reset_idle_timer();
1758       ev_io_start(loop_, &wev_);
1759       return 0;
1760     }
1761 
1762     if (++pktcnt == max_pktcnt ||
1763         static_cast<size_t>(nwrite) < max_udp_payload_size) {
1764       server_->send_packet(*static_cast<Endpoint *>(ps.path.user_data),
1765                            ps.path.local, ps.path.remote, pi.ecn, buf.data(),
1766                            bufpos - buf.data(), max_udp_payload_size);
1767       ngtcp2_conn_update_pkt_tx_time(conn_, ts);
1768       reset_idle_timer();
1769       ev_io_start(loop_, &wev_);
1770       return 0;
1771     }
1772 #else  // !NGTCP2_ENABLE_UDP_GSO
1773     reset_idle_timer();
1774 
1775     server_->send_packet(*static_cast<Endpoint *>(ps.path.user_data),
1776                          ps.path.local, ps.path.remote, pi.ecn, buf.data(),
1777                          bufpos - buf.data(), 0);
1778     if (++pktcnt == max_pktcnt) {
1779       ngtcp2_conn_update_pkt_tx_time(conn_, ts);
1780       ev_io_start(loop_, &wev_);
1781       return 0;
1782     }
1783 
1784     bufpos = buf.data();
1785 #endif // !NGTCP2_ENABLE_UDP_GSO
1786   }
1787 }
1788 
signal_write()1789 void Handler::signal_write() { ev_io_start(loop_, &wev_); }
1790 
draining() const1791 bool Handler::draining() const { return draining_; }
1792 
start_draining_period()1793 void Handler::start_draining_period() {
1794   draining_ = true;
1795 
1796   ev_timer_stop(loop_, &rttimer_);
1797 
1798   timer_.repeat =
1799       static_cast<ev_tstamp>(ngtcp2_conn_get_pto(conn_)) / NGTCP2_SECONDS * 3;
1800   ev_timer_again(loop_, &timer_);
1801 
1802   if (!config.quiet) {
1803     std::cerr << "Draining period has started (" << timer_.repeat << " seconds)"
1804               << std::endl;
1805   }
1806 }
1807 
start_closing_period()1808 int Handler::start_closing_period() {
1809   if (!conn_ || ngtcp2_conn_is_in_closing_period(conn_)) {
1810     return 0;
1811   }
1812 
1813   ev_timer_stop(loop_, &rttimer_);
1814 
1815   timer_.repeat =
1816       static_cast<ev_tstamp>(ngtcp2_conn_get_pto(conn_)) / NGTCP2_SECONDS * 3;
1817   ev_timer_again(loop_, &timer_);
1818 
1819   if (!config.quiet) {
1820     std::cerr << "Closing period has started (" << timer_.repeat << " seconds)"
1821               << std::endl;
1822   }
1823 
1824   conn_closebuf_ = std::make_unique<Buffer>(NGTCP2_MAX_UDP_PAYLOAD_SIZE);
1825 
1826   ngtcp2_path_storage ps;
1827 
1828   ngtcp2_path_storage_zero(&ps);
1829 
1830   ngtcp2_pkt_info pi;
1831   if (last_error_.type == QUICErrorType::Transport) {
1832     auto n = ngtcp2_conn_write_connection_close(
1833         conn_, &ps.path, &pi, conn_closebuf_->wpos(), conn_closebuf_->left(),
1834         last_error_.code, util::timestamp(loop_));
1835     if (n < 0) {
1836       std::cerr << "ngtcp2_conn_write_connection_close: " << ngtcp2_strerror(n)
1837                 << std::endl;
1838       return -1;
1839     }
1840     conn_closebuf_->push(n);
1841   } else {
1842     auto n = ngtcp2_conn_write_application_close(
1843         conn_, &ps.path, &pi, conn_closebuf_->wpos(), conn_closebuf_->left(),
1844         last_error_.code, util::timestamp(loop_));
1845     if (n < 0) {
1846       std::cerr << "ngtcp2_conn_write_application_close: " << ngtcp2_strerror(n)
1847                 << std::endl;
1848       return -1;
1849     }
1850     conn_closebuf_->push(n);
1851   }
1852 
1853   return 0;
1854 }
1855 
handle_error()1856 int Handler::handle_error() {
1857   if (start_closing_period() != 0) {
1858     return -1;
1859   }
1860 
1861   if (auto rv = send_conn_close(); rv != NETWORK_ERR_OK) {
1862     return rv;
1863   }
1864 
1865   return NETWORK_ERR_CLOSE_WAIT;
1866 }
1867 
send_conn_close()1868 int Handler::send_conn_close() {
1869   if (!config.quiet) {
1870     std::cerr << "Closing Period: TX CONNECTION_CLOSE" << std::endl;
1871   }
1872 
1873   assert(conn_closebuf_ && conn_closebuf_->size());
1874   assert(conn_);
1875 
1876   auto path = ngtcp2_conn_get_path(conn_);
1877 
1878   return server_->send_packet(
1879       *static_cast<Endpoint *>(path->user_data), path->local, path->remote,
1880       /* ecn = */ 0, conn_closebuf_->rpos(), conn_closebuf_->size(), 0);
1881 }
1882 
schedule_retransmit()1883 void Handler::schedule_retransmit() {
1884   auto expiry = ngtcp2_conn_get_expiry(conn_);
1885   auto now = util::timestamp(loop_);
1886   auto t = expiry < now ? 1e-9
1887                         : static_cast<ev_tstamp>(expiry - now) / NGTCP2_SECONDS;
1888   if (!config.quiet) {
1889     std::cerr << "Set timer=" << std::fixed << t << "s" << std::defaultfloat
1890               << std::endl;
1891   }
1892   rttimer_.repeat = t;
1893   ev_timer_again(loop_, &rttimer_);
1894 }
1895 
recv_stream_data(uint32_t flags,int64_t stream_id,const uint8_t * data,size_t datalen)1896 int Handler::recv_stream_data(uint32_t flags, int64_t stream_id,
1897                               const uint8_t *data, size_t datalen) {
1898   if (!config.quiet && !config.no_quic_dump) {
1899     debug::print_stream_data(stream_id, data, datalen);
1900   }
1901 
1902   if (!httpconn_) {
1903     return 0;
1904   }
1905 
1906   auto nconsumed = nghttp3_conn_read_stream(
1907       httpconn_, stream_id, data, datalen, flags & NGTCP2_STREAM_DATA_FLAG_FIN);
1908   if (nconsumed < 0) {
1909     std::cerr << "nghttp3_conn_read_stream: " << nghttp3_strerror(nconsumed)
1910               << std::endl;
1911     last_error_ = quic_err_app(nconsumed);
1912     return -1;
1913   }
1914 
1915   ngtcp2_conn_extend_max_stream_offset(conn_, stream_id, nconsumed);
1916   ngtcp2_conn_extend_max_offset(conn_, nconsumed);
1917 
1918   return 0;
1919 }
1920 
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)1921 int Handler::update_key(uint8_t *rx_secret, uint8_t *tx_secret,
1922                         ngtcp2_crypto_aead_ctx *rx_aead_ctx, uint8_t *rx_iv,
1923                         ngtcp2_crypto_aead_ctx *tx_aead_ctx, uint8_t *tx_iv,
1924                         const uint8_t *current_rx_secret,
1925                         const uint8_t *current_tx_secret, size_t secretlen) {
1926   auto crypto_ctx = ngtcp2_conn_get_crypto_ctx(conn_);
1927   auto aead = &crypto_ctx->aead;
1928   auto keylen = ngtcp2_crypto_aead_keylen(aead);
1929   auto ivlen = ngtcp2_crypto_packet_protection_ivlen(aead);
1930 
1931   ++nkey_update_;
1932 
1933   std::array<uint8_t, 64> rx_key, tx_key;
1934 
1935   if (ngtcp2_crypto_update_key(conn_, rx_secret, tx_secret, rx_aead_ctx,
1936                                rx_key.data(), rx_iv, tx_aead_ctx, tx_key.data(),
1937                                tx_iv, current_rx_secret, current_tx_secret,
1938                                secretlen) != 0) {
1939     return -1;
1940   }
1941 
1942   if (!config.quiet && config.show_secret) {
1943     std::cerr << "application_traffic rx secret " << nkey_update_ << std::endl;
1944     debug::print_secrets(rx_secret, secretlen, rx_key.data(), keylen, rx_iv,
1945                          ivlen);
1946     std::cerr << "application_traffic tx secret " << nkey_update_ << std::endl;
1947     debug::print_secrets(tx_secret, secretlen, tx_key.data(), keylen, tx_iv,
1948                          ivlen);
1949   }
1950 
1951   return 0;
1952 }
1953 
server() const1954 Server *Handler::server() const { return server_; }
1955 
on_stream_close(int64_t stream_id,uint64_t app_error_code)1956 int Handler::on_stream_close(int64_t stream_id, uint64_t app_error_code) {
1957   if (!config.quiet) {
1958     std::cerr << "QUIC stream " << stream_id << " closed" << std::endl;
1959   }
1960 
1961   if (httpconn_) {
1962     if (app_error_code == 0) {
1963       app_error_code = NGHTTP3_H3_NO_ERROR;
1964     }
1965     auto rv = nghttp3_conn_close_stream(httpconn_, stream_id, app_error_code);
1966     switch (rv) {
1967     case 0:
1968       break;
1969     case NGHTTP3_ERR_STREAM_NOT_FOUND:
1970       if (ngtcp2_is_bidi_stream(stream_id)) {
1971         assert(!ngtcp2_conn_is_local_stream(conn_, stream_id));
1972         ngtcp2_conn_extend_max_streams_bidi(conn_, 1);
1973       }
1974       break;
1975     default:
1976       std::cerr << "nghttp3_conn_close_stream: " << nghttp3_strerror(rv)
1977                 << std::endl;
1978       last_error_ = quic_err_app(rv);
1979       return -1;
1980     }
1981   }
1982 
1983   return 0;
1984 }
1985 
shutdown_read(int64_t stream_id,int app_error_code)1986 void Handler::shutdown_read(int64_t stream_id, int app_error_code) {
1987   ngtcp2_conn_shutdown_stream_read(conn_, stream_id, app_error_code);
1988 }
1989 
1990 namespace {
sreadcb(struct ev_loop * loop,ev_io * w,int revents)1991 void sreadcb(struct ev_loop *loop, ev_io *w, int revents) {
1992   auto ep = static_cast<Endpoint *>(w->data);
1993 
1994   ep->server->on_read(*ep);
1995 }
1996 } // namespace
1997 
1998 namespace {
siginthandler(struct ev_loop * loop,ev_signal * watcher,int revents)1999 void siginthandler(struct ev_loop *loop, ev_signal *watcher, int revents) {
2000   ev_break(loop, EVBREAK_ALL);
2001 }
2002 } // namespace
2003 
Server(struct ev_loop * loop,const TLSServerContext & tls_ctx)2004 Server::Server(struct ev_loop *loop, const TLSServerContext &tls_ctx)
2005     : loop_(loop), tls_ctx_(tls_ctx) {
2006   ev_signal_init(&sigintev_, siginthandler, SIGINT);
2007 }
2008 
~Server()2009 Server::~Server() {
2010   disconnect();
2011   close();
2012 }
2013 
disconnect()2014 void Server::disconnect() {
2015   config.tx_loss_prob = 0;
2016 
2017   for (auto &ep : endpoints_) {
2018     ev_io_stop(loop_, &ep.rev);
2019   }
2020 
2021   ev_signal_stop(loop_, &sigintev_);
2022 
2023   while (!handlers_.empty()) {
2024     auto it = std::begin(handlers_);
2025     auto &h = (*it).second;
2026 
2027     h->handle_error();
2028 
2029     remove(h);
2030   }
2031 }
2032 
close()2033 void Server::close() {
2034   for (auto &ep : endpoints_) {
2035     ::close(ep.fd);
2036   }
2037 
2038   endpoints_.clear();
2039 }
2040 
2041 namespace {
create_sock(Address & local_addr,const char * addr,const char * port,int family)2042 int create_sock(Address &local_addr, const char *addr, const char *port,
2043                 int family) {
2044   addrinfo hints{};
2045   addrinfo *res, *rp;
2046   int val = 1;
2047 
2048   hints.ai_family = family;
2049   hints.ai_socktype = SOCK_DGRAM;
2050   hints.ai_flags = AI_PASSIVE;
2051 
2052   if (strcmp(addr, "*") == 0) {
2053     addr = nullptr;
2054   }
2055 
2056   if (auto rv = getaddrinfo(addr, port, &hints, &res); rv != 0) {
2057     std::cerr << "getaddrinfo: " << gai_strerror(rv) << std::endl;
2058     return -1;
2059   }
2060 
2061   auto res_d = defer(freeaddrinfo, res);
2062 
2063   int fd = -1;
2064 
2065   for (rp = res; rp; rp = rp->ai_next) {
2066     fd = util::create_nonblock_socket(rp->ai_family, rp->ai_socktype,
2067                                       rp->ai_protocol);
2068     if (fd == -1) {
2069       continue;
2070     }
2071 
2072     if (rp->ai_family == AF_INET6) {
2073       if (setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &val,
2074                      static_cast<socklen_t>(sizeof(val))) == -1) {
2075         close(fd);
2076         continue;
2077       }
2078 
2079       if (setsockopt(fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, &val,
2080                      static_cast<socklen_t>(sizeof(val))) == -1) {
2081         close(fd);
2082         continue;
2083       }
2084     } else if (setsockopt(fd, IPPROTO_IP, IP_PKTINFO, &val,
2085                           static_cast<socklen_t>(sizeof(val))) == -1) {
2086       close(fd);
2087       continue;
2088     }
2089 
2090     if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &val,
2091                    static_cast<socklen_t>(sizeof(val))) == -1) {
2092       close(fd);
2093       continue;
2094     }
2095 
2096     fd_set_recv_ecn(fd, rp->ai_family);
2097 
2098     if (bind(fd, rp->ai_addr, rp->ai_addrlen) != -1) {
2099       break;
2100     }
2101 
2102     close(fd);
2103   }
2104 
2105   if (!rp) {
2106     std::cerr << "Could not bind" << std::endl;
2107     return -1;
2108   }
2109 
2110   socklen_t len = sizeof(local_addr.su.storage);
2111   if (getsockname(fd, &local_addr.su.sa, &len) == -1) {
2112     std::cerr << "getsockname: " << strerror(errno) << std::endl;
2113     close(fd);
2114     return -1;
2115   }
2116   local_addr.len = len;
2117   local_addr.ifindex = 0;
2118 
2119   return fd;
2120 }
2121 
2122 } // namespace
2123 
2124 namespace {
add_endpoint(std::vector<Endpoint> & endpoints,const char * addr,const char * port,int af)2125 int add_endpoint(std::vector<Endpoint> &endpoints, const char *addr,
2126                  const char *port, int af) {
2127   Address dest;
2128   auto fd = create_sock(dest, addr, port, af);
2129   if (fd == -1) {
2130     return -1;
2131   }
2132 
2133   endpoints.emplace_back();
2134   auto &ep = endpoints.back();
2135   ep.addr = dest;
2136   ep.fd = fd;
2137   ev_io_init(&ep.rev, sreadcb, 0, EV_READ);
2138 
2139   return 0;
2140 }
2141 } // namespace
2142 
2143 namespace {
add_endpoint(std::vector<Endpoint> & endpoints,const Address & addr)2144 int add_endpoint(std::vector<Endpoint> &endpoints, const Address &addr) {
2145   auto fd = util::create_nonblock_socket(addr.su.sa.sa_family, SOCK_DGRAM, 0);
2146   if (fd == -1) {
2147     std::cerr << "socket: " << strerror(errno) << std::endl;
2148     return -1;
2149   }
2150 
2151   int val = 1;
2152   if (addr.su.sa.sa_family == AF_INET6) {
2153     if (setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &val,
2154                    static_cast<socklen_t>(sizeof(val))) == -1) {
2155       std::cerr << "setsockopt: " << strerror(errno) << std::endl;
2156       close(fd);
2157       return -1;
2158     }
2159 
2160     if (setsockopt(fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, &val,
2161                    static_cast<socklen_t>(sizeof(val))) == -1) {
2162       std::cerr << "setsockopt: " << strerror(errno) << std::endl;
2163       close(fd);
2164       return -1;
2165     }
2166   } else if (setsockopt(fd, IPPROTO_IP, IP_PKTINFO, &val,
2167                         static_cast<socklen_t>(sizeof(val))) == -1) {
2168     std::cerr << "setsockopt: " << strerror(errno) << std::endl;
2169     close(fd);
2170     return -1;
2171   }
2172 
2173   if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &val,
2174                  static_cast<socklen_t>(sizeof(val))) == -1) {
2175     close(fd);
2176     return -1;
2177   }
2178 
2179   fd_set_recv_ecn(fd, addr.su.sa.sa_family);
2180 
2181   if (bind(fd, &addr.su.sa, addr.len) == -1) {
2182     std::cerr << "bind: " << strerror(errno) << std::endl;
2183     close(fd);
2184     return -1;
2185   }
2186 
2187   endpoints.emplace_back(Endpoint{});
2188   auto &ep = endpoints.back();
2189   ep.addr = addr;
2190   ep.fd = fd;
2191   ev_io_init(&ep.rev, sreadcb, 0, EV_READ);
2192 
2193   return 0;
2194 }
2195 } // namespace
2196 
init(const char * addr,const char * port)2197 int Server::init(const char *addr, const char *port) {
2198   endpoints_.reserve(4);
2199 
2200   auto ready = false;
2201   if (!util::numeric_host(addr, AF_INET6) &&
2202       add_endpoint(endpoints_, addr, port, AF_INET) == 0) {
2203     ready = true;
2204   }
2205   if (!util::numeric_host(addr, AF_INET) &&
2206       add_endpoint(endpoints_, addr, port, AF_INET6) == 0) {
2207     ready = true;
2208   }
2209   if (!ready) {
2210     return -1;
2211   }
2212 
2213   if (config.preferred_ipv4_addr.len &&
2214       add_endpoint(endpoints_, config.preferred_ipv4_addr) != 0) {
2215     return -1;
2216   }
2217   if (config.preferred_ipv6_addr.len &&
2218       add_endpoint(endpoints_, config.preferred_ipv6_addr) != 0) {
2219     return -1;
2220   }
2221 
2222   for (auto &ep : endpoints_) {
2223     ep.server = this;
2224     ep.rev.data = &ep;
2225 
2226     ev_io_set(&ep.rev, ep.fd, EV_READ);
2227 
2228     ev_io_start(loop_, &ep.rev);
2229   }
2230 
2231   ev_signal_start(loop_, &sigintev_);
2232 
2233   return 0;
2234 }
2235 
on_read(Endpoint & ep)2236 int Server::on_read(Endpoint &ep) {
2237   sockaddr_union su;
2238   std::array<uint8_t, 64_k> buf;
2239   ngtcp2_pkt_hd hd;
2240   size_t pktcnt = 0;
2241   ngtcp2_pkt_info pi;
2242 
2243   iovec msg_iov;
2244   msg_iov.iov_base = buf.data();
2245   msg_iov.iov_len = buf.size();
2246 
2247   msghdr msg{};
2248   msg.msg_name = &su;
2249   msg.msg_iov = &msg_iov;
2250   msg.msg_iovlen = 1;
2251 
2252   uint8_t
2253       msg_ctrl[CMSG_SPACE(sizeof(uint8_t)) + CMSG_SPACE(sizeof(in6_pktinfo))];
2254   msg.msg_control = msg_ctrl;
2255 
2256   for (; pktcnt < 10;) {
2257     msg.msg_namelen = sizeof(su);
2258     msg.msg_controllen = sizeof(msg_ctrl);
2259 
2260     auto nread = recvmsg(ep.fd, &msg, 0);
2261     if (nread == -1) {
2262       if (!(errno == EAGAIN || errno == ENOTCONN)) {
2263         std::cerr << "recvmsg: " << strerror(errno) << std::endl;
2264       }
2265       return 0;
2266     }
2267 
2268     ++pktcnt;
2269 
2270     pi.ecn = msghdr_get_ecn(&msg, su.storage.ss_family);
2271     auto local_addr = msghdr_get_local_addr(&msg, su.storage.ss_family);
2272     if (!local_addr) {
2273       std::cerr << "Unable to obtain local address" << std::endl;
2274       continue;
2275     }
2276 
2277     set_port(*local_addr, ep.addr);
2278 
2279     if (!config.quiet) {
2280       std::array<char, IF_NAMESIZE> ifname;
2281       std::cerr << "Received packet: local="
2282                 << util::straddr(&local_addr->su.sa, local_addr->len)
2283                 << " remote=" << util::straddr(&su.sa, msg.msg_namelen)
2284                 << " if=" << if_indextoname(local_addr->ifindex, ifname.data())
2285                 << " ecn=0x" << std::hex << pi.ecn << std::dec << " " << nread
2286                 << " bytes" << std::endl;
2287     }
2288 
2289     if (debug::packet_lost(config.rx_loss_prob)) {
2290       if (!config.quiet) {
2291         std::cerr << "** Simulated incoming packet loss **" << std::endl;
2292       }
2293       continue;
2294     }
2295 
2296     if (nread == 0) {
2297       continue;
2298     }
2299 
2300     uint32_t version;
2301     const uint8_t *dcid, *scid;
2302     size_t dcidlen, scidlen;
2303 
2304     switch (auto rv = ngtcp2_pkt_decode_version_cid(&version, &dcid, &dcidlen,
2305                                                     &scid, &scidlen, buf.data(),
2306                                                     nread, NGTCP2_SV_SCIDLEN);
2307             rv) {
2308     case 0:
2309       break;
2310     case NGTCP2_ERR_VERSION_NEGOTIATION:
2311       send_version_negotiation(version, scid, scidlen, dcid, dcidlen, ep,
2312                                *local_addr, &su.sa, msg.msg_namelen);
2313       continue;
2314     default:
2315       std::cerr << "Could not decode version and CID from QUIC packet header: "
2316                 << ngtcp2_strerror(rv) << std::endl;
2317       continue;
2318     }
2319 
2320     auto dcid_key = util::make_cid_key(dcid, dcidlen);
2321 
2322     auto handler_it = handlers_.find(dcid_key);
2323     if (handler_it == std::end(handlers_)) {
2324       switch (auto rv = ngtcp2_accept(&hd, buf.data(), nread); rv) {
2325       case 0:
2326         break;
2327       case NGTCP2_ERR_RETRY:
2328         send_retry(&hd, ep, *local_addr, &su.sa, msg.msg_namelen);
2329         continue;
2330       case NGTCP2_ERR_VERSION_NEGOTIATION:
2331         if (!config.quiet) {
2332           std::cerr << "Unsupported version: Send Version Negotiation"
2333                     << std::endl;
2334         }
2335         send_version_negotiation(hd.version, hd.scid.data, hd.scid.datalen,
2336                                  hd.dcid.data, hd.dcid.datalen, ep, *local_addr,
2337                                  &su.sa, msg.msg_namelen);
2338         continue;
2339       default:
2340         if (!config.quiet) {
2341           std::cerr << "Unexpected packet received: length=" << nread
2342                     << std::endl;
2343         }
2344         continue;
2345       }
2346 
2347       ngtcp2_cid ocid;
2348       ngtcp2_cid *pocid = nullptr;
2349 
2350       assert(hd.type == NGTCP2_PKT_INITIAL);
2351 
2352       if (config.validate_addr || hd.token.len) {
2353         std::cerr << "Perform stateless address validation" << std::endl;
2354         if (hd.token.len == 0) {
2355           send_retry(&hd, ep, *local_addr, &su.sa, msg.msg_namelen);
2356           continue;
2357         }
2358 
2359         if (hd.token.base[0] != NGTCP2_CRYPTO_TOKEN_MAGIC_RETRY &&
2360             hd.dcid.datalen < NGTCP2_MIN_INITIAL_DCIDLEN) {
2361           send_stateless_connection_close(&hd, ep, *local_addr, &su.sa,
2362                                           msg.msg_namelen);
2363           continue;
2364         }
2365 
2366         switch (hd.token.base[0]) {
2367         case NGTCP2_CRYPTO_TOKEN_MAGIC_RETRY:
2368           if (verify_retry_token(&ocid, &hd, &su.sa, msg.msg_namelen) != 0) {
2369             send_stateless_connection_close(&hd, ep, *local_addr, &su.sa,
2370                                             msg.msg_namelen);
2371             continue;
2372           }
2373           pocid = &ocid;
2374           break;
2375         case NGTCP2_CRYPTO_TOKEN_MAGIC_REGULAR:
2376           if (verify_token(&hd, &su.sa, msg.msg_namelen) != 0) {
2377             if (config.validate_addr) {
2378               send_retry(&hd, ep, *local_addr, &su.sa, msg.msg_namelen);
2379               continue;
2380             }
2381 
2382             hd.token.base = nullptr;
2383             hd.token.len = 0;
2384           }
2385           break;
2386         default:
2387           if (!config.quiet) {
2388             std::cerr << "Ignore unrecognized token" << std::endl;
2389           }
2390           if (config.validate_addr) {
2391             send_retry(&hd, ep, *local_addr, &su.sa, msg.msg_namelen);
2392             continue;
2393           }
2394 
2395           hd.token.base = nullptr;
2396           hd.token.len = 0;
2397           break;
2398         }
2399       }
2400 
2401       auto h = std::make_unique<Handler>(loop_, this);
2402       if (h->init(ep, *local_addr, &su.sa, msg.msg_namelen, &hd.scid, &hd.dcid,
2403                   pocid, hd.token.base, hd.token.len, hd.version,
2404                   tls_ctx_) != 0) {
2405         continue;
2406       }
2407 
2408       switch (h->on_read(ep, *local_addr, &su.sa, msg.msg_namelen, &pi,
2409                          buf.data(), nread)) {
2410       case 0:
2411         break;
2412       case NETWORK_ERR_RETRY:
2413         send_retry(&hd, ep, *local_addr, &su.sa, msg.msg_namelen);
2414         continue;
2415       default:
2416         continue;
2417       }
2418 
2419       switch (h->on_write()) {
2420       case 0:
2421         break;
2422       default:
2423         continue;
2424       }
2425 
2426       std::array<ngtcp2_cid, 2> scids;
2427       auto conn = h->conn();
2428 
2429       auto num_scid = ngtcp2_conn_get_num_scid(conn);
2430 
2431       assert(num_scid <= scids.size());
2432 
2433       ngtcp2_conn_get_scid(conn, scids.data());
2434 
2435       for (size_t i = 0; i < num_scid; ++i) {
2436         handlers_.emplace(util::make_cid_key(&scids[i]), h.get());
2437       }
2438 
2439       handlers_.emplace(dcid_key, h.get());
2440 
2441       h.release();
2442 
2443       continue;
2444     }
2445 
2446     auto h = (*handler_it).second;
2447     if (ngtcp2_conn_is_in_closing_period(h->conn())) {
2448       // TODO do exponential backoff.
2449       switch (h->send_conn_close()) {
2450       case 0:
2451         break;
2452       default:
2453         remove(h);
2454       }
2455       continue;
2456     }
2457     if (h->draining()) {
2458       continue;
2459     }
2460 
2461     if (auto rv = h->on_read(ep, *local_addr, &su.sa, msg.msg_namelen, &pi,
2462                              buf.data(), nread);
2463         rv != 0) {
2464       if (rv != NETWORK_ERR_CLOSE_WAIT) {
2465         remove(h);
2466       }
2467       continue;
2468     }
2469 
2470     h->signal_write();
2471   }
2472 
2473   return 0;
2474 }
2475 
2476 namespace {
generate_reserved_version(const sockaddr * sa,socklen_t salen,uint32_t version)2477 uint32_t generate_reserved_version(const sockaddr *sa, socklen_t salen,
2478                                    uint32_t version) {
2479   uint32_t h = 0x811C9DC5u;
2480   const uint8_t *p = (const uint8_t *)sa;
2481   const uint8_t *ep = p + salen;
2482   for (; p != ep; ++p) {
2483     h ^= *p;
2484     h *= 0x01000193u;
2485   }
2486   version = htonl(version);
2487   p = (const uint8_t *)&version;
2488   ep = p + sizeof(version);
2489   for (; p != ep; ++p) {
2490     h ^= *p;
2491     h *= 0x01000193u;
2492   }
2493   h &= 0xf0f0f0f0u;
2494   h |= 0x0a0a0a0au;
2495   return h;
2496 }
2497 } // namespace
2498 
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)2499 int Server::send_version_negotiation(uint32_t version, const uint8_t *dcid,
2500                                      size_t dcidlen, const uint8_t *scid,
2501                                      size_t scidlen, Endpoint &ep,
2502                                      const Address &local_addr,
2503                                      const sockaddr *sa, socklen_t salen) {
2504   Buffer buf{NGTCP2_MAX_UDP_PAYLOAD_SIZE};
2505   std::array<uint32_t, 16> sv;
2506 
2507   static_assert(sv.size() >= 2 + (NGTCP2_PROTO_VER_DRAFT_MAX -
2508                                   NGTCP2_PROTO_VER_DRAFT_MIN + 1));
2509 
2510   sv[0] = generate_reserved_version(sa, salen, version);
2511   sv[1] = NGTCP2_PROTO_VER_V1;
2512 
2513   size_t svlen = 2;
2514   for (auto v = NGTCP2_PROTO_VER_DRAFT_MIN; v <= NGTCP2_PROTO_VER_DRAFT_MAX;
2515        ++v) {
2516     sv[svlen++] = v;
2517   }
2518 
2519   auto nwrite = ngtcp2_pkt_write_version_negotiation(
2520       buf.wpos(), buf.left(),
2521       std::uniform_int_distribution<uint8_t>(
2522           0, std::numeric_limits<uint8_t>::max())(randgen),
2523       dcid, dcidlen, scid, scidlen, sv.data(), svlen);
2524   if (nwrite < 0) {
2525     std::cerr << "ngtcp2_pkt_write_version_negotiation: "
2526               << ngtcp2_strerror(nwrite) << std::endl;
2527     return -1;
2528   }
2529 
2530   buf.push(nwrite);
2531 
2532   ngtcp2_addr laddr{
2533       const_cast<sockaddr *>(&local_addr.su.sa),
2534       local_addr.len,
2535   };
2536   ngtcp2_addr raddr{
2537       const_cast<sockaddr *>(sa),
2538       salen,
2539   };
2540 
2541   if (send_packet(ep, laddr, raddr, /* ecn = */ 0, buf.rpos(), buf.size(), 0) !=
2542       NETWORK_ERR_OK) {
2543     return -1;
2544   }
2545 
2546   return 0;
2547 }
2548 
send_retry(const ngtcp2_pkt_hd * chd,Endpoint & ep,const Address & local_addr,const sockaddr * sa,socklen_t salen)2549 int Server::send_retry(const ngtcp2_pkt_hd *chd, Endpoint &ep,
2550                        const Address &local_addr, const sockaddr *sa,
2551                        socklen_t salen) {
2552   std::array<char, NI_MAXHOST> host;
2553   std::array<char, NI_MAXSERV> port;
2554 
2555   if (auto rv = getnameinfo(sa, salen, host.data(), host.size(), port.data(),
2556                             port.size(), NI_NUMERICHOST | NI_NUMERICSERV);
2557       rv != 0) {
2558     std::cerr << "getnameinfo: " << gai_strerror(rv) << std::endl;
2559     return -1;
2560   }
2561 
2562   if (!config.quiet) {
2563     std::cerr << "Sending Retry packet to [" << host.data()
2564               << "]:" << port.data() << std::endl;
2565   }
2566 
2567   ngtcp2_cid scid;
2568 
2569   scid.datalen = NGTCP2_SV_SCIDLEN;
2570   if (util::generate_secure_random(scid.data, scid.datalen) != 0) {
2571     return -1;
2572   }
2573 
2574   std::array<uint8_t, NGTCP2_CRYPTO_MAX_RETRY_TOKENLEN> token;
2575 
2576   auto t = std::chrono::duration_cast<std::chrono::nanoseconds>(
2577                std::chrono::system_clock::now().time_since_epoch())
2578                .count();
2579 
2580   auto tokenlen = ngtcp2_crypto_generate_retry_token(
2581       token.data(), config.static_secret.data(), config.static_secret.size(),
2582       sa, salen, &scid, &chd->dcid, t);
2583   if (tokenlen < 0) {
2584     return -1;
2585   }
2586 
2587   if (!config.quiet) {
2588     std::cerr << "Generated address validation token:" << std::endl;
2589     util::hexdump(stderr, token.data(), tokenlen);
2590   }
2591 
2592   Buffer buf{NGTCP2_MAX_UDP_PAYLOAD_SIZE};
2593 
2594   auto nwrite = ngtcp2_crypto_write_retry(buf.wpos(), buf.left(), chd->version,
2595                                           &chd->scid, &scid, &chd->dcid,
2596                                           token.data(), tokenlen);
2597   if (nwrite < 0) {
2598     std::cerr << "ngtcp2_crypto_write_retry failed" << std::endl;
2599     return -1;
2600   }
2601 
2602   buf.push(nwrite);
2603 
2604   ngtcp2_addr laddr{
2605       const_cast<sockaddr *>(&local_addr.su.sa),
2606       local_addr.len,
2607   };
2608   ngtcp2_addr raddr{
2609       const_cast<sockaddr *>(sa),
2610       salen,
2611   };
2612 
2613   if (send_packet(ep, laddr, raddr, /* ecn = */ 0, buf.rpos(), buf.size(), 0) !=
2614       NETWORK_ERR_OK) {
2615     return -1;
2616   }
2617 
2618   return 0;
2619 }
2620 
send_stateless_connection_close(const ngtcp2_pkt_hd * chd,Endpoint & ep,const Address & local_addr,const sockaddr * sa,socklen_t salen)2621 int Server::send_stateless_connection_close(const ngtcp2_pkt_hd *chd,
2622                                             Endpoint &ep,
2623                                             const Address &local_addr,
2624                                             const sockaddr *sa,
2625                                             socklen_t salen) {
2626   Buffer buf{NGTCP2_MAX_UDP_PAYLOAD_SIZE};
2627 
2628   auto nwrite = ngtcp2_crypto_write_connection_close(
2629       buf.wpos(), buf.left(), chd->version, &chd->scid, &chd->dcid,
2630       NGTCP2_INVALID_TOKEN);
2631   if (nwrite < 0) {
2632     std::cerr << "ngtcp2_crypto_write_connection_close failed" << std::endl;
2633     return -1;
2634   }
2635 
2636   buf.push(nwrite);
2637 
2638   ngtcp2_addr laddr{
2639       const_cast<sockaddr *>(&local_addr.su.sa),
2640       local_addr.len,
2641   };
2642   ngtcp2_addr raddr{
2643       const_cast<sockaddr *>(sa),
2644       salen,
2645   };
2646 
2647   if (send_packet(ep, laddr, raddr, /* ecn = */ 0, buf.rpos(), buf.size(), 0) !=
2648       NETWORK_ERR_OK) {
2649     return -1;
2650   }
2651 
2652   return 0;
2653 }
2654 
verify_retry_token(ngtcp2_cid * ocid,const ngtcp2_pkt_hd * hd,const sockaddr * sa,socklen_t salen)2655 int Server::verify_retry_token(ngtcp2_cid *ocid, const ngtcp2_pkt_hd *hd,
2656                                const sockaddr *sa, socklen_t salen) {
2657   std::array<char, NI_MAXHOST> host;
2658   std::array<char, NI_MAXSERV> port;
2659 
2660   if (auto rv = getnameinfo(sa, salen, host.data(), host.size(), port.data(),
2661                             port.size(), NI_NUMERICHOST | NI_NUMERICSERV);
2662       rv != 0) {
2663     std::cerr << "getnameinfo: " << gai_strerror(rv) << std::endl;
2664     return -1;
2665   }
2666 
2667   if (!config.quiet) {
2668     std::cerr << "Verifying Retry token from [" << host.data()
2669               << "]:" << port.data() << std::endl;
2670     util::hexdump(stderr, hd->token.base, hd->token.len);
2671   }
2672 
2673   auto t = std::chrono::duration_cast<std::chrono::nanoseconds>(
2674                std::chrono::system_clock::now().time_since_epoch())
2675                .count();
2676 
2677   if (ngtcp2_crypto_verify_retry_token(
2678           ocid, hd->token.base, hd->token.len, config.static_secret.data(),
2679           config.static_secret.size(), sa, salen, &hd->dcid,
2680           10 * NGTCP2_SECONDS, t) != 0) {
2681     std::cerr << "Could not verify Retry token" << std::endl;
2682 
2683     return -1;
2684   }
2685 
2686   if (!config.quiet) {
2687     std::cerr << "Token was successfully validated" << std::endl;
2688   }
2689 
2690   return 0;
2691 }
2692 
verify_token(const ngtcp2_pkt_hd * hd,const sockaddr * sa,socklen_t salen)2693 int Server::verify_token(const ngtcp2_pkt_hd *hd, const sockaddr *sa,
2694                          socklen_t salen) {
2695   std::array<char, NI_MAXHOST> host;
2696   std::array<char, NI_MAXSERV> port;
2697 
2698   if (auto rv = getnameinfo(sa, salen, host.data(), host.size(), port.data(),
2699                             port.size(), NI_NUMERICHOST | NI_NUMERICSERV);
2700       rv != 0) {
2701     std::cerr << "getnameinfo: " << gai_strerror(rv) << std::endl;
2702     return -1;
2703   }
2704 
2705   if (!config.quiet) {
2706     std::cerr << "Verifying token from [" << host.data() << "]:" << port.data()
2707               << std::endl;
2708     util::hexdump(stderr, hd->token.base, hd->token.len);
2709   }
2710 
2711   auto t = std::chrono::duration_cast<std::chrono::nanoseconds>(
2712                std::chrono::system_clock::now().time_since_epoch())
2713                .count();
2714 
2715   if (ngtcp2_crypto_verify_regular_token(hd->token.base, hd->token.len,
2716                                          config.static_secret.data(),
2717                                          config.static_secret.size(), sa, salen,
2718                                          3600 * NGTCP2_SECONDS, t) != 0) {
2719     if (!config.quiet) {
2720       std::cerr << "Could not verify token" << std::endl;
2721     }
2722     return -1;
2723   }
2724 
2725   if (!config.quiet) {
2726     std::cerr << "Token was successfully validated" << std::endl;
2727   }
2728 
2729   return 0;
2730 }
2731 
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)2732 int Server::send_packet(Endpoint &ep, const ngtcp2_addr &local_addr,
2733                         const ngtcp2_addr &remote_addr, unsigned int ecn,
2734                         const uint8_t *data, size_t datalen, size_t gso_size) {
2735   if (debug::packet_lost(config.tx_loss_prob)) {
2736     if (!config.quiet) {
2737       std::cerr << "** Simulated outgoing packet loss **" << std::endl;
2738     }
2739     return NETWORK_ERR_OK;
2740   }
2741 
2742   iovec msg_iov;
2743   msg_iov.iov_base = const_cast<uint8_t *>(data);
2744   msg_iov.iov_len = datalen;
2745 
2746   msghdr msg{};
2747   msg.msg_name = const_cast<sockaddr *>(remote_addr.addr);
2748   msg.msg_namelen = remote_addr.addrlen;
2749   msg.msg_iov = &msg_iov;
2750   msg.msg_iovlen = 1;
2751 
2752   uint8_t msg_ctrl[
2753 #if NGTCP2_ENABLE_UDP_GSO
2754       CMSG_SPACE(sizeof(uint16_t)) +
2755 #endif // NGTCP2_ENABLE_UDP_GSO
2756       CMSG_SPACE(sizeof(in6_pktinfo))];
2757 
2758   memset(msg_ctrl, 0, sizeof(msg_ctrl));
2759 
2760   msg.msg_control = msg_ctrl;
2761   msg.msg_controllen = sizeof(msg_ctrl);
2762 
2763   size_t controllen = 0;
2764 
2765   auto cm = CMSG_FIRSTHDR(&msg);
2766 
2767   switch (local_addr.addr->sa_family) {
2768   case AF_INET: {
2769     controllen += CMSG_SPACE(sizeof(in_pktinfo));
2770     cm->cmsg_level = IPPROTO_IP;
2771     cm->cmsg_type = IP_PKTINFO;
2772     cm->cmsg_len = CMSG_LEN(sizeof(in_pktinfo));
2773     auto pktinfo = reinterpret_cast<in_pktinfo *>(CMSG_DATA(cm));
2774     memset(pktinfo, 0, sizeof(in_pktinfo));
2775     auto addrin = reinterpret_cast<sockaddr_in *>(local_addr.addr);
2776     pktinfo->ipi_spec_dst = addrin->sin_addr;
2777     break;
2778   }
2779   case AF_INET6: {
2780     controllen += CMSG_SPACE(sizeof(in6_pktinfo));
2781     cm->cmsg_level = IPPROTO_IPV6;
2782     cm->cmsg_type = IPV6_PKTINFO;
2783     cm->cmsg_len = CMSG_LEN(sizeof(in6_pktinfo));
2784     auto pktinfo = reinterpret_cast<in6_pktinfo *>(CMSG_DATA(cm));
2785     memset(pktinfo, 0, sizeof(in6_pktinfo));
2786     auto addrin = reinterpret_cast<sockaddr_in6 *>(local_addr.addr);
2787     pktinfo->ipi6_addr = addrin->sin6_addr;
2788     break;
2789   }
2790   default:
2791     assert(0);
2792   }
2793 
2794 #if NGTCP2_ENABLE_UDP_GSO
2795   if (gso_size && datalen > gso_size) {
2796     controllen += CMSG_SPACE(sizeof(uint16_t));
2797     cm = CMSG_NXTHDR(&msg, cm);
2798     cm->cmsg_level = SOL_UDP;
2799     cm->cmsg_type = UDP_SEGMENT;
2800     cm->cmsg_len = CMSG_LEN(sizeof(uint16_t));
2801     *(reinterpret_cast<uint16_t *>(CMSG_DATA(cm))) = gso_size;
2802   }
2803 #endif // NGTCP2_ENABLE_UDP_GSO
2804 
2805   msg.msg_controllen = controllen;
2806 
2807   if (ep.ecn != ecn) {
2808     ep.ecn = ecn;
2809     fd_set_ecn(ep.fd, ep.addr.su.storage.ss_family, ecn);
2810   }
2811 
2812   ssize_t nwrite = 0;
2813 
2814   do {
2815     nwrite = sendmsg(ep.fd, &msg, 0);
2816   } while (nwrite == -1 && errno == EINTR);
2817 
2818   if (nwrite == -1) {
2819     std::cerr << "sendmsg: " << strerror(errno) << std::endl;
2820     // TODO We have packet which is expected to fail to send (e.g.,
2821     // path validation to old path).
2822     return NETWORK_ERR_OK;
2823   }
2824 
2825   if (!config.quiet) {
2826     std::cerr << "Sent packet: local="
2827               << util::straddr(local_addr.addr, local_addr.addrlen)
2828               << " remote="
2829               << util::straddr(remote_addr.addr, remote_addr.addrlen)
2830               << " ecn=0x" << std::hex << ecn << std::dec << " " << nwrite
2831               << " bytes" << std::endl;
2832   }
2833 
2834   return NETWORK_ERR_OK;
2835 }
2836 
associate_cid(const ngtcp2_cid * cid,Handler * h)2837 void Server::associate_cid(const ngtcp2_cid *cid, Handler *h) {
2838   handlers_.emplace(util::make_cid_key(cid), h);
2839 }
2840 
dissociate_cid(const ngtcp2_cid * cid)2841 void Server::dissociate_cid(const ngtcp2_cid *cid) {
2842   handlers_.erase(util::make_cid_key(cid));
2843 }
2844 
remove(const Handler * h)2845 void Server::remove(const Handler *h) {
2846   auto conn = h->conn();
2847 
2848   handlers_.erase(
2849       util::make_cid_key(ngtcp2_conn_get_client_initial_dcid(conn)));
2850 
2851   std::vector<ngtcp2_cid> cids(ngtcp2_conn_get_num_scid(conn));
2852   ngtcp2_conn_get_scid(conn, cids.data());
2853 
2854   for (auto &cid : cids) {
2855     handlers_.erase(util::make_cid_key(&cid));
2856   }
2857 
2858   delete h;
2859 }
2860 
2861 namespace {
parse_host_port(Address & dest,int af,const char * first,const char * last)2862 int parse_host_port(Address &dest, int af, const char *first,
2863                     const char *last) {
2864   if (std::distance(first, last) == 0) {
2865     return -1;
2866   }
2867 
2868   const char *host_begin, *host_end, *it;
2869   if (*first == '[') {
2870     host_begin = first + 1;
2871     it = std::find(host_begin, last, ']');
2872     if (it == last) {
2873       return -1;
2874     }
2875     host_end = it;
2876     ++it;
2877     if (it == last || *it != ':') {
2878       return -1;
2879     }
2880   } else {
2881     host_begin = first;
2882     it = std::find(host_begin, last, ':');
2883     if (it == last) {
2884       return -1;
2885     }
2886     host_end = it;
2887   }
2888 
2889   if (++it == last) {
2890     return -1;
2891   }
2892   auto svc_begin = it;
2893 
2894   std::array<char, NI_MAXHOST> host;
2895   *std::copy(host_begin, host_end, std::begin(host)) = '\0';
2896 
2897   addrinfo hints{}, *res;
2898   hints.ai_family = af;
2899   hints.ai_socktype = SOCK_DGRAM;
2900 
2901   if (auto rv = getaddrinfo(host.data(), svc_begin, &hints, &res); rv != 0) {
2902     std::cerr << "getaddrinfo: [" << host.data() << "]:" << svc_begin << ": "
2903               << gai_strerror(rv) << std::endl;
2904     return -1;
2905   }
2906 
2907   dest.len = res->ai_addrlen;
2908   memcpy(&dest.su, res->ai_addr, res->ai_addrlen);
2909 
2910   freeaddrinfo(res);
2911 
2912   return 0;
2913 }
2914 } // namespace
2915 
2916 namespace {
print_usage()2917 void print_usage() {
2918   std::cerr << "Usage: server [OPTIONS] <ADDR> <PORT> <PRIVATE_KEY_FILE> "
2919                "<CERTIFICATE_FILE>"
2920             << std::endl;
2921 }
2922 } // namespace
2923 
2924 namespace {
config_set_default(Config & config)2925 void config_set_default(Config &config) {
2926   config = Config{};
2927   config.tx_loss_prob = 0.;
2928   config.rx_loss_prob = 0.;
2929   config.ciphers = util::crypto_default_ciphers();
2930   config.groups = util::crypto_default_groups();
2931   config.timeout = 30 * NGTCP2_SECONDS;
2932   {
2933     auto path = realpath(".", nullptr);
2934     assert(path);
2935     config.htdocs = path;
2936     free(path);
2937   }
2938   config.mime_types_file = "/etc/mime.types";
2939   config.max_data = 1_m;
2940   config.max_stream_data_bidi_local = 256_k;
2941   config.max_stream_data_bidi_remote = 256_k;
2942   config.max_stream_data_uni = 256_k;
2943   config.max_window = 6_m;
2944   config.max_stream_window = 6_m;
2945   config.max_streams_bidi = 100;
2946   config.max_streams_uni = 3;
2947   config.max_dyn_length = 20_m;
2948   config.cc_algo = NGTCP2_CC_ALGO_CUBIC;
2949   config.initial_rtt = NGTCP2_DEFAULT_INITIAL_RTT;
2950   config.max_gso_dgrams = 10;
2951 }
2952 } // namespace
2953 
2954 namespace {
print_help()2955 void print_help() {
2956   print_usage();
2957 
2958   config_set_default(config);
2959 
2960   std::cout << R"(
2961   <ADDR>      Address to listen to.  '*' binds to any address.
2962   <PORT>      Port
2963   <PRIVATE_KEY_FILE>
2964               Path to private key file
2965   <CERTIFICATE_FILE>
2966               Path to certificate file
2967 Options:
2968   -t, --tx-loss=<P>
2969               The probability of losing outgoing packets.  <P> must be
2970               [0.0, 1.0],  inclusive.  0.0 means no  packet loss.  1.0
2971               means 100% packet loss.
2972   -r, --rx-loss=<P>
2973               The probability of losing incoming packets.  <P> must be
2974               [0.0, 1.0],  inclusive.  0.0 means no  packet loss.  1.0
2975               means 100% packet loss.
2976   --ciphers=<CIPHERS>
2977               Specify the cipher suite list to enable.
2978               Default: )"
2979             << config.ciphers << R"(
2980   --groups=<GROUPS>
2981               Specify the supported groups.
2982               Default: )"
2983             << config.groups << R"(
2984   -d, --htdocs=<PATH>
2985               Specify document root.  If this option is not specified,
2986               the document root is the current working directory.
2987   -q, --quiet Suppress debug output.
2988   -s, --show-secret
2989               Print out secrets unless --quiet is used.
2990   --timeout=<DURATION>
2991               Specify idle timeout.
2992               Default: )"
2993             << util::format_duration(config.timeout) << R"(
2994   -V, --validate-addr
2995               Perform address validation.
2996   --preferred-ipv4-addr=<ADDR>:<PORT>
2997               Specify preferred IPv4 address and port.
2998   --preferred-ipv6-addr=<ADDR>:<PORT>
2999               Specify preferred IPv6 address and port.  A numeric IPv6
3000               address  must   be  enclosed  by  '['   and  ']'  (e.g.,
3001               [::1]:8443)
3002   --mime-types-file=<PATH>
3003               Path  to file  that contains  MIME media  types and  the
3004               extensions.
3005               Default: )"
3006             << config.mime_types_file << R"(
3007   --early-response
3008               Start  sending response  when  it  receives HTTP  header
3009               fields  without  waiting  for  request  body.   If  HTTP
3010               response data is written  before receiving request body,
3011               STOP_SENDING is sent.
3012   --verify-client
3013               Request a  client certificate.   At the moment,  we just
3014               request a certificate and no verification is done.
3015   --qlog-dir=<PATH>
3016               Path to  the directory where  qlog file is  stored.  The
3017               file name  of each qlog  is the Source Connection  ID of
3018               server.
3019   --no-quic-dump
3020               Disables printing QUIC STREAM and CRYPTO frame data out.
3021   --no-http-dump
3022               Disables printing HTTP response body out.
3023   --max-data=<SIZE>
3024               The initial connection-level flow control window.
3025               Default: )"
3026             << util::format_uint_iec(config.max_data) << R"(
3027   --max-stream-data-bidi-local=<SIZE>
3028               The  initial  stream-level  flow control  window  for  a
3029               bidirectional stream that the local endpoint initiates.
3030               Default: )"
3031             << util::format_uint_iec(config.max_stream_data_bidi_local) << R"(
3032   --max-stream-data-bidi-remote=<SIZE>
3033               The  initial  stream-level  flow control  window  for  a
3034               bidirectional stream that the remote endpoint initiates.
3035               Default: )"
3036             << util::format_uint_iec(config.max_stream_data_bidi_remote) << R"(
3037   --max-stream-data-uni=<SIZE>
3038               The  initial  stream-level  flow control  window  for  a
3039               unidirectional stream.
3040               Default: )"
3041             << util::format_uint_iec(config.max_stream_data_uni) << R"(
3042   --max-streams-bidi=<N>
3043               The number of the concurrent bidirectional streams.
3044               Default: )"
3045             << config.max_streams_bidi << R"(
3046   --max-streams-uni=<N>
3047               The number of the concurrent unidirectional streams.
3048               Default: )"
3049             << config.max_streams_uni << R"(
3050   --max-dyn-length=<SIZE>
3051               The maximum length of a dynamically generated content.
3052               Default: )"
3053             << util::format_uint_iec(config.max_dyn_length) << R"(
3054   --cc=(cubic|reno|bbr)
3055               The name of congestion controller algorithm.
3056               Default: )"
3057             << util::strccalgo(config.cc_algo) << R"(
3058   --initial-rtt=<DURATION>
3059               Set an initial RTT.
3060               Default: )"
3061             << util::format_duration(config.initial_rtt) << R"(
3062   --max-udp-payload-size=<SIZE>
3063               Override maximum UDP payload size that server transmits.
3064   --send-trailers
3065               Send trailer fields.
3066   --max-window=<SIZE>
3067               Maximum connection-level flow  control window size.  The
3068               window auto-tuning is enabled if nonzero value is given,
3069               and window size is scaled up to this value.
3070               Default: )"
3071             << util::format_uint_iec(config.max_window) << R"(
3072   --max-stream-window=<SIZE>
3073               Maximum stream-level flow control window size.  The
3074               window auto-tuning is enabled if nonzero value is given,
3075               and window size is scaled up to this value.
3076               Default: )"
3077             << util::format_uint_iec(config.max_stream_window) << R"(
3078   --max-gso-dgrams=<N>
3079               Maximum  number of  UDP  datagrams that  are  sent in  a
3080               single GSO sendmsg call.
3081               Default: )"
3082             << config.max_gso_dgrams << R"(
3083   -h, --help  Display this help and exit.
3084 
3085 ---
3086 
3087   The <SIZE> argument is an integer and an optional unit (e.g., 10K is
3088   10 * 1024).  Units are K, M and G (powers of 1024).
3089 
3090   The <DURATION> argument is an integer and an optional unit (e.g., 1s
3091   is 1 second and 500ms is 500  milliseconds).  Units are h, m, s, ms,
3092   us, or ns (hours,  minutes, seconds, milliseconds, microseconds, and
3093   nanoseconds respectively).  If  a unit is omitted, a  second is used
3094   as unit.)" << std::endl;
3095 }
3096 } // namespace
3097 
3098 std::ofstream keylog_file;
3099 
main(int argc,char ** argv)3100 int main(int argc, char **argv) {
3101   config_set_default(config);
3102 
3103   for (;;) {
3104     static int flag = 0;
3105     constexpr static option long_opts[] = {
3106         {"help", no_argument, nullptr, 'h'},
3107         {"tx-loss", required_argument, nullptr, 't'},
3108         {"rx-loss", required_argument, nullptr, 'r'},
3109         {"htdocs", required_argument, nullptr, 'd'},
3110         {"quiet", no_argument, nullptr, 'q'},
3111         {"show-secret", no_argument, nullptr, 's'},
3112         {"validate-addr", no_argument, nullptr, 'V'},
3113         {"ciphers", required_argument, &flag, 1},
3114         {"groups", required_argument, &flag, 2},
3115         {"timeout", required_argument, &flag, 3},
3116         {"preferred-ipv4-addr", required_argument, &flag, 4},
3117         {"preferred-ipv6-addr", required_argument, &flag, 5},
3118         {"mime-types-file", required_argument, &flag, 6},
3119         {"early-response", no_argument, &flag, 7},
3120         {"verify-client", no_argument, &flag, 8},
3121         {"qlog-dir", required_argument, &flag, 9},
3122         {"no-quic-dump", no_argument, &flag, 10},
3123         {"no-http-dump", no_argument, &flag, 11},
3124         {"max-data", required_argument, &flag, 12},
3125         {"max-stream-data-bidi-local", required_argument, &flag, 13},
3126         {"max-stream-data-bidi-remote", required_argument, &flag, 14},
3127         {"max-stream-data-uni", required_argument, &flag, 15},
3128         {"max-streams-bidi", required_argument, &flag, 16},
3129         {"max-streams-uni", required_argument, &flag, 17},
3130         {"max-dyn-length", required_argument, &flag, 18},
3131         {"cc", required_argument, &flag, 19},
3132         {"initial-rtt", required_argument, &flag, 20},
3133         {"max-udp-payload-size", required_argument, &flag, 21},
3134         {"send-trailers", no_argument, &flag, 22},
3135         {"max-window", required_argument, &flag, 23},
3136         {"max-stream-window", required_argument, &flag, 24},
3137         {"max-gso-dgrams", required_argument, &flag, 25},
3138         {nullptr, 0, nullptr, 0}};
3139 
3140     auto optidx = 0;
3141     auto c = getopt_long(argc, argv, "d:hqr:st:V", long_opts, &optidx);
3142     if (c == -1) {
3143       break;
3144     }
3145     switch (c) {
3146     case 'd': {
3147       // --htdocs
3148       auto path = realpath(optarg, nullptr);
3149       if (path == nullptr) {
3150         std::cerr << "path: invalid path " << std::quoted(optarg) << std::endl;
3151         exit(EXIT_FAILURE);
3152       }
3153       config.htdocs = path;
3154       free(path);
3155       break;
3156     }
3157     case 'h':
3158       // --help
3159       print_help();
3160       exit(EXIT_SUCCESS);
3161     case 'q':
3162       // --quiet
3163       config.quiet = true;
3164       break;
3165     case 'r':
3166       // --rx-loss
3167       config.rx_loss_prob = strtod(optarg, nullptr);
3168       break;
3169     case 's':
3170       // --show-secret
3171       config.show_secret = true;
3172       break;
3173     case 't':
3174       // --tx-loss
3175       config.tx_loss_prob = strtod(optarg, nullptr);
3176       break;
3177     case 'V':
3178       // --validate-addr
3179       config.validate_addr = true;
3180       break;
3181     case '?':
3182       print_usage();
3183       exit(EXIT_FAILURE);
3184     case 0:
3185       switch (flag) {
3186       case 1:
3187         // --ciphers
3188         config.ciphers = optarg;
3189         break;
3190       case 2:
3191         // --groups
3192         config.groups = optarg;
3193         break;
3194       case 3:
3195         // --timeout
3196         if (auto t = util::parse_duration(optarg); !t) {
3197           std::cerr << "timeout: invalid argument" << std::endl;
3198           exit(EXIT_FAILURE);
3199         } else {
3200           config.timeout = *t;
3201         }
3202         break;
3203       case 4:
3204         // --preferred-ipv4-addr
3205         if (parse_host_port(config.preferred_ipv4_addr, AF_INET, optarg,
3206                             optarg + strlen(optarg)) != 0) {
3207           std::cerr << "preferred-ipv4-addr: could not use "
3208                     << std::quoted(optarg) << std::endl;
3209           exit(EXIT_FAILURE);
3210         }
3211         break;
3212       case 5:
3213         // --preferred-ipv6-addr
3214         if (parse_host_port(config.preferred_ipv6_addr, AF_INET6, optarg,
3215                             optarg + strlen(optarg)) != 0) {
3216           std::cerr << "preferred-ipv6-addr: could not use "
3217                     << std::quoted(optarg) << std::endl;
3218           exit(EXIT_FAILURE);
3219         }
3220         break;
3221       case 6:
3222         // --mime-types-file
3223         config.mime_types_file = optarg;
3224         break;
3225       case 7:
3226         // --early-response
3227         config.early_response = true;
3228         break;
3229       case 8:
3230         // --verify-client
3231         config.verify_client = true;
3232         break;
3233       case 9:
3234         // --qlog-dir
3235         config.qlog_dir = optarg;
3236         break;
3237       case 10:
3238         // --no-quic-dump
3239         config.no_quic_dump = true;
3240         break;
3241       case 11:
3242         // --no-http-dump
3243         config.no_http_dump = true;
3244         break;
3245       case 12:
3246         // --max-data
3247         if (auto n = util::parse_uint_iec(optarg); !n) {
3248           std::cerr << "max-data: invalid argument" << std::endl;
3249           exit(EXIT_FAILURE);
3250         } else {
3251           config.max_data = *n;
3252         }
3253         break;
3254       case 13:
3255         // --max-stream-data-bidi-local
3256         if (auto n = util::parse_uint_iec(optarg); !n) {
3257           std::cerr << "max-stream-data-bidi-local: invalid argument"
3258                     << std::endl;
3259           exit(EXIT_FAILURE);
3260         } else {
3261           config.max_stream_data_bidi_local = *n;
3262         }
3263         break;
3264       case 14:
3265         // --max-stream-data-bidi-remote
3266         if (auto n = util::parse_uint_iec(optarg); !n) {
3267           std::cerr << "max-stream-data-bidi-remote: invalid argument"
3268                     << std::endl;
3269           exit(EXIT_FAILURE);
3270         } else {
3271           config.max_stream_data_bidi_remote = *n;
3272         }
3273         break;
3274       case 15:
3275         // --max-stream-data-uni
3276         if (auto n = util::parse_uint_iec(optarg); !n) {
3277           std::cerr << "max-stream-data-uni: invalid argument" << std::endl;
3278           exit(EXIT_FAILURE);
3279         } else {
3280           config.max_stream_data_uni = *n;
3281         }
3282         break;
3283       case 16:
3284         // --max-streams-bidi
3285         if (auto n = util::parse_uint(optarg); !n) {
3286           std::cerr << "max-streams-bidi: invalid argument" << std::endl;
3287           exit(EXIT_FAILURE);
3288         } else {
3289           config.max_streams_bidi = *n;
3290         }
3291         break;
3292       case 17:
3293         // --max-streams-uni
3294         if (auto n = util::parse_uint(optarg); !n) {
3295           std::cerr << "max-streams-uni: invalid argument" << std::endl;
3296           exit(EXIT_FAILURE);
3297         } else {
3298           config.max_streams_uni = *n;
3299         }
3300         break;
3301       case 18:
3302         // --max-dyn-length
3303         if (auto n = util::parse_uint_iec(optarg); !n) {
3304           std::cerr << "max-dyn-length: invalid argument" << std::endl;
3305           exit(EXIT_FAILURE);
3306         } else {
3307           config.max_dyn_length = *n;
3308         }
3309         break;
3310       case 19:
3311         // --cc
3312         if (strcmp("cubic", optarg) == 0) {
3313           config.cc_algo = NGTCP2_CC_ALGO_CUBIC;
3314           break;
3315         }
3316         if (strcmp("reno", optarg) == 0) {
3317           config.cc_algo = NGTCP2_CC_ALGO_RENO;
3318           break;
3319         }
3320         if (strcmp("bbr", optarg) == 0) {
3321           config.cc_algo = NGTCP2_CC_ALGO_BBR;
3322           break;
3323         }
3324         std::cerr << "cc: specify cubic, reno, or bbr" << std::endl;
3325         exit(EXIT_FAILURE);
3326       case 20:
3327         // --initial-rtt
3328         if (auto t = util::parse_duration(optarg); !t) {
3329           std::cerr << "initial-rtt: invalid argument" << std::endl;
3330           exit(EXIT_FAILURE);
3331         } else {
3332           config.initial_rtt = *t;
3333         }
3334         break;
3335       case 21:
3336         // --max-udp-payload-size
3337         if (auto n = util::parse_uint_iec(optarg); !n) {
3338           std::cerr << "max-udp-payload-size: invalid argument" << std::endl;
3339           exit(EXIT_FAILURE);
3340         } else if (*n > 64_k) {
3341           std::cerr << "max-udp-payload-size: must not exceed 65536"
3342                     << std::endl;
3343           exit(EXIT_FAILURE);
3344         } else {
3345           config.max_udp_payload_size = *n;
3346         }
3347         break;
3348       case 22:
3349         // --send-trailers
3350         config.send_trailers = true;
3351         break;
3352       case 23:
3353         // --max-window
3354         if (auto n = util::parse_uint_iec(optarg); !n) {
3355           std::cerr << "max-window: invalid argument" << std::endl;
3356           exit(EXIT_FAILURE);
3357         } else {
3358           config.max_window = *n;
3359         }
3360         break;
3361       case 24:
3362         // --max-stream-window
3363         if (auto n = util::parse_uint_iec(optarg); !n) {
3364           std::cerr << "max-stream-window: invalid argument" << std::endl;
3365           exit(EXIT_FAILURE);
3366         } else {
3367           config.max_stream_window = *n;
3368         }
3369         break;
3370       case 25:
3371         // --max-gso-dgrams
3372         if (auto n = util::parse_uint(optarg); !n) {
3373           std::cerr << "max-gso-dgrams: invalid argument" << std::endl;
3374           exit(EXIT_FAILURE);
3375         } else {
3376           config.max_gso_dgrams = *n;
3377         }
3378         break;
3379       }
3380       break;
3381     default:
3382       break;
3383     };
3384   }
3385 
3386   if (argc - optind < 4) {
3387     std::cerr << "Too few arguments" << std::endl;
3388     print_usage();
3389     exit(EXIT_FAILURE);
3390   }
3391 
3392   auto addr = argv[optind++];
3393   auto port = argv[optind++];
3394   auto private_key_file = argv[optind++];
3395   auto cert_file = argv[optind++];
3396 
3397   if (auto n = util::parse_uint(port); !n) {
3398     std::cerr << "port: invalid port number" << std::endl;
3399     exit(EXIT_FAILURE);
3400   } else if (*n > 65535) {
3401     std::cerr << "port: must not exceed 65535" << std::endl;
3402     exit(EXIT_FAILURE);
3403   } else {
3404     config.port = *n;
3405   }
3406 
3407   if (auto mt = util::read_mime_types(config.mime_types_file); !mt) {
3408     std::cerr << "mime-types-file: Could not read MIME media types file "
3409               << std::quoted(config.mime_types_file) << std::endl;
3410   } else {
3411     config.mime_types = std::move(*mt);
3412   }
3413 
3414   TLSServerContext tls_ctx;
3415 
3416   if (tls_ctx.init(private_key_file, cert_file, AppProtocol::H3) != 0) {
3417     exit(EXIT_FAILURE);
3418   }
3419 
3420   if (config.htdocs.back() != '/') {
3421     config.htdocs += '/';
3422   }
3423 
3424   std::cerr << "Using document root " << config.htdocs << std::endl;
3425 
3426   auto ev_loop_d = defer(ev_loop_destroy, EV_DEFAULT);
3427 
3428   auto keylog_filename = getenv("SSLKEYLOGFILE");
3429   if (keylog_filename) {
3430     keylog_file.open(keylog_filename, std::ios_base::app);
3431     if (keylog_file) {
3432       tls_ctx.enable_keylog();
3433     }
3434   }
3435 
3436   if (util::generate_secret(config.static_secret.data(),
3437                             config.static_secret.size()) != 0) {
3438     std::cerr << "Unable to generate static secret" << std::endl;
3439     exit(EXIT_FAILURE);
3440   }
3441 
3442   Server s(EV_DEFAULT, tls_ctx);
3443   if (s.init(addr, port) != 0) {
3444     exit(EXIT_FAILURE);
3445   }
3446 
3447   ev_run(EV_DEFAULT, 0);
3448 
3449   s.disconnect();
3450   s.close();
3451 
3452   return EXIT_SUCCESS;
3453 }
3454