blob: 6767e2ef595ba2b22956c04560b3b5a74c0782e6 [file] [log] [blame]
Tatsuhiro Tsujikawa94931782017-06-24 12:20:52 +09001/*
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 */
Daniel Bevenius3ced23e2019-11-01 10:21:35 +010025#include <chrono>
Tatsuhiro Tsujikawa94931782017-06-24 12:20:52 +090026#include <cstdlib>
27#include <cassert>
Tatsuhiro Tsujikawa67279592019-11-20 20:43:07 +090028#include <cstring>
Tatsuhiro Tsujikawa94931782017-06-24 12:20:52 +090029#include <iostream>
30#include <algorithm>
Tatsuhiro Tsujikawa20a655b2017-06-30 22:04:15 +090031#include <memory>
Peter Wu7c9fbb42018-03-20 21:28:22 +010032#include <fstream>
Tatsuhiro Tsujikawa287e2e02020-09-06 21:09:06 +090033#include <future>
34#include <thread>
Tatsuhiro Tsujikawa94931782017-06-24 12:20:52 +090035
36#include <unistd.h>
37#include <getopt.h>
38#include <sys/types.h>
39#include <sys/socket.h>
40#include <netdb.h>
Tatsuhiro Tsujikawae85b4a52017-08-19 20:10:45 +090041#include <sys/stat.h>
42#include <fcntl.h>
Tatsuhiro Tsujikawa29e2d352017-09-17 13:04:36 +090043#include <sys/mman.h>
Tatsuhiro Tsujikawa67279592019-11-20 20:43:07 +090044#include <netinet/udp.h>
Tatsuhiro Tsujikawa287e2e02020-09-06 21:09:06 +090045#include <signal.h>
46
47#include <linux/bpf.h>
48
49enum bpf_stats_type {};
50
51#include <bpf/libbpf.h>
52#include <bpf/bpf.h>
Tatsuhiro Tsujikawa94931782017-06-24 12:20:52 +090053
54#include <openssl/bio.h>
Tatsuhiro Tsujikawa20a655b2017-06-30 22:04:15 +090055#include <openssl/err.h>
Tatsuhiro Tsujikawa94931782017-06-24 12:20:52 +090056
Tatsuhiro Tsujikawa9ea17af2019-03-25 14:37:26 +090057#include <http-parser/http_parser.h>
58
Tatsuhiro Tsujikawa94931782017-06-24 12:20:52 +090059#include "server.h"
Tatsuhiro Tsujikawa94931782017-06-24 12:20:52 +090060#include "network.h"
Tatsuhiro Tsujikawac7790f02017-06-24 18:07:16 +090061#include "debug.h"
Tatsuhiro Tsujikawaad502c02017-06-24 19:11:45 +090062#include "util.h"
Tatsuhiro Tsujikawa88e5b652017-08-06 15:30:51 +090063#include "shared.h"
Tatsuhiro Tsujikawae85b4a52017-08-19 20:10:45 +090064#include "http.h"
Peter Wu894ed232018-09-16 12:27:48 +020065#include "keylog.h"
Daniel Bevenius62919e22019-10-28 14:50:45 +010066#include "template.h"
Tatsuhiro Tsujikawa94931782017-06-24 12:20:52 +090067
68using namespace ngtcp2;
Tatsuhiro Tsujikawa8a0b5632020-05-13 21:15:47 +090069using namespace std::literals;
Tatsuhiro Tsujikawa94931782017-06-24 12:20:52 +090070
Tatsuhiro Tsujikawac2358772019-12-01 11:01:31 +090071#ifndef NGTCP2_ENABLE_UDP_GSO
72# ifdef UDP_SEGMENT
73# define NGTCP2_ENABLE_UDP_GSO 1
74# else // !UDP_SEGMENT
75# define NGTCP2_ENABLE_UDP_GSO 0
76# endif // !UDP_SEGMENT
77#endif // NGTCP2_ENABLE_UDP_GSO
Tatsuhiro Tsujikawa67279592019-11-20 20:43:07 +090078
Tatsuhiro Tsujikawa94931782017-06-24 12:20:52 +090079namespace {
Tatsuhiro Tsujikawa0faf9742018-04-23 01:10:59 +090080constexpr size_t NGTCP2_SV_SCIDLEN = 18;
81} // namespace
82
83namespace {
Tatsuhiro Tsujikawa4b3157d2018-12-11 00:29:56 +090084constexpr size_t TOKEN_RAND_DATALEN = 16;
85} // namespace
86
87namespace {
Tatsuhiro Tsujikawaaf5662c2020-09-29 01:08:53 +090088constexpr size_t MAX_DYNBUFLEN = 10 * 1024 * 1024;
Tatsuhiro Tsujikawadec083a2019-06-15 17:48:42 +090089} // namespace
90
91namespace {
Tatsuhiro Tsujikawaad502c02017-06-24 19:11:45 +090092auto randgen = util::make_mt19937();
93} // namespace
94
95namespace {
Tatsuhiro Tsujikawa40331c12020-05-26 13:39:41 +090096// RETRY_TOKEN_MAGIC is the magic byte of Retry token. Sent in
97// plaintext.
98constexpr uint8_t RETRY_TOKEN_MAGIC = 0xb6;
99constexpr size_t MAX_RETRY_TOKENLEN =
100 /* magic */ 1 + sizeof(uint64_t) + NGTCP2_MAX_CIDLEN +
101 /* aead tag */ 16 + TOKEN_RAND_DATALEN;
102
103// TOKEN_MAGIC is the magic byte of token which is sent in NEW_TOKEN
104// frame. Sent in plaintext.
105constexpr uint8_t TOKEN_MAGIC = 0x36;
106constexpr size_t MAX_TOKENLEN =
107 /* magic */ 1 + sizeof(uint64_t) + /* aead tag */ 16 + TOKEN_RAND_DATALEN;
108} // namespace
109
110namespace {
Tatsuhiro Tsujikawab4ac5942017-07-17 00:19:21 +0900111Config config{};
112} // namespace
113
Tatsuhiro Tsujikawa287e2e02020-09-06 21:09:06 +0900114namespace {
115int prog_fd;
116int reuseport_array;
117} // namespace
118
Tatsuhiro Tsujikawa4ecd51e2017-07-30 14:28:23 +0900119Buffer::Buffer(const uint8_t *data, size_t datalen)
Tatsuhiro Tsujikawa3dcddef2019-10-27 18:28:50 +0900120 : buf{data, data + datalen}, begin(buf.data()), tail(begin + datalen) {}
Amir Livneh65f98e52019-10-24 08:47:31 -0400121Buffer::Buffer(size_t datalen) : buf(datalen), begin(buf.data()), tail(begin) {}
Tatsuhiro Tsujikawa4ecd51e2017-07-30 14:28:23 +0900122
Tatsuhiro Tsujikawa287e2e02020-09-06 21:09:06 +0900123namespace {
124void sha256(uint8_t *dest, const uint8_t *kpad, const uint8_t *b, size_t blen) {
125 auto ctx = EVP_MD_CTX_new();
126 assert(ctx);
127
128 auto ctx_deleter = defer(EVP_MD_CTX_free, ctx);
129
130 unsigned int mdlen = 32;
131 if (!EVP_DigestInit_ex(ctx, EVP_sha256(), nullptr) ||
132 !EVP_DigestUpdate(ctx, kpad, 64) || !EVP_DigestUpdate(ctx, b, blen) ||
133 !EVP_DigestFinal_ex(ctx, dest, &mdlen)) {
134 assert(0);
135 }
136}
137} // namespace
138
139namespace {
140constexpr size_t HMACLEN = 4;
141std::array<uint8_t, 64> kopad, kipad;
142} // namespace
143
144namespace {
145void hmac256_32(uint32_t *dest, const uint8_t *src, size_t srclen) {
146 uint8_t h[32];
147
148 sha256(h, kipad.data(), src, srclen);
149 sha256(h, kopad.data(), h, sizeof(h));
150
151 memcpy(dest, h, HMACLEN);
152}
153} // namespace
154
155namespace {
156void generate_authenticated_cid(uint8_t *dest, size_t destlen,
157 uint32_t svindex) {
158 // - Connection ID is NGTCP2_SV_SCIDLEN bytes in total.
159 // Connection
160 //
161 // - ID is authenticated with HMAC-SHA256-32 to reliably embed
162 // svindex in it.
163 //
164 // - The last 4 bytes are digest. Thus 14 bytes are available.
165 //
166 // - For now, encode svindex in the first (most significant) byte.
167
168 assert(destlen == NGTCP2_SV_SCIDLEN);
169 assert(svindex < 256);
170
171 auto dis = std::uniform_int_distribution<uint8_t>(0, 255);
172 auto f = [&dis]() { return dis(randgen); };
173 auto len = NGTCP2_SV_SCIDLEN - HMACLEN;
174
175 std::generate_n(dest, len, f);
176 // TODO Encode svindex elsewhere other than first byte.
177 dest[0] = static_cast<uint8_t>(svindex);
178
179 uint32_t hmac;
180 hmac256_32(&hmac, dest, len);
181
182 memcpy(dest + len, &hmac, sizeof(hmac));
183}
184} // namespace
185
Tatsuhiro Tsujikawa7558be42019-08-25 18:50:46 +0900186int Handler::on_key(ngtcp2_crypto_level level, const uint8_t *rx_secret,
187 const uint8_t *tx_secret, size_t secretlen) {
Tatsuhiro Tsujikawac6f570b2019-08-29 09:49:17 +0900188 std::array<uint8_t, 64> rx_key, rx_iv, rx_hp_key, tx_key, tx_iv, tx_hp_key;
Tatsuhiro Tsujikawa9a95ec22019-08-24 22:16:37 +0900189
Tatsuhiro Tsujikawa32e70312020-03-28 22:53:11 +0900190 if (ngtcp2_crypto_derive_and_install_rx_key(
Tatsuhiro Tsujikawa15833a12020-05-23 09:24:31 +0900191 conn_, rx_key.data(), rx_iv.data(), rx_hp_key.data(), level,
Tatsuhiro Tsujikawa32e70312020-03-28 22:53:11 +0900192 rx_secret, secretlen) != 0) {
193 return -1;
194 }
Tatsuhiro Tsujikawafb753752020-05-21 18:10:40 +0900195 if (ngtcp2_crypto_derive_and_install_tx_key(
Tatsuhiro Tsujikawa15833a12020-05-23 09:24:31 +0900196 conn_, tx_key.data(), tx_iv.data(), tx_hp_key.data(), level,
Tatsuhiro Tsujikawa32e70312020-03-28 22:53:11 +0900197 tx_secret, secretlen) != 0) {
Tatsuhiro Tsujikawa4f0d2522018-12-20 10:56:39 +0900198 return -1;
199 }
200
Tatsuhiro Tsujikawac6f570b2019-08-29 09:49:17 +0900201 auto crypto_ctx = ngtcp2_conn_get_crypto_ctx(conn_);
202 auto aead = &crypto_ctx->aead;
203 auto keylen = ngtcp2_crypto_aead_keylen(aead);
204 auto ivlen = ngtcp2_crypto_packet_protection_ivlen(aead);
205
Tatsuhiro Tsujikawacf382c42019-08-25 23:53:50 +0900206 const char *title = nullptr;
Tatsuhiro Tsujikawa7558be42019-08-25 18:50:46 +0900207 switch (level) {
208 case NGTCP2_CRYPTO_LEVEL_EARLY:
Tatsuhiro Tsujikawacf382c42019-08-25 23:53:50 +0900209 title = "early_traffic";
Tatsuhiro Tsujikawa7558be42019-08-25 18:50:46 +0900210 keylog::log_secret(ssl_, keylog::QUIC_CLIENT_EARLY_TRAFFIC_SECRET,
211 rx_secret, secretlen);
Tatsuhiro Tsujikawa19cce622018-06-02 23:03:35 +0900212 break;
Tatsuhiro Tsujikawa7558be42019-08-25 18:50:46 +0900213 case NGTCP2_CRYPTO_LEVEL_HANDSHAKE:
Tatsuhiro Tsujikawacf382c42019-08-25 23:53:50 +0900214 title = "handshake_traffic";
Tatsuhiro Tsujikawa7558be42019-08-25 18:50:46 +0900215 keylog::log_secret(ssl_, keylog::QUIC_CLIENT_HANDSHAKE_TRAFFIC_SECRET,
216 rx_secret, secretlen);
217 keylog::log_secret(ssl_, keylog::QUIC_SERVER_HANDSHAKE_TRAFFIC_SECRET,
218 tx_secret, secretlen);
Tatsuhiro Tsujikawa19cce622018-06-02 23:03:35 +0900219 break;
Tatsuhiro Tsujikawa76232e92020-12-01 14:56:28 +0900220 case NGTCP2_CRYPTO_LEVEL_APPLICATION:
Tatsuhiro Tsujikawacf382c42019-08-25 23:53:50 +0900221 title = "application_traffic";
Tatsuhiro Tsujikawa7558be42019-08-25 18:50:46 +0900222 keylog::log_secret(ssl_, keylog::QUIC_CLIENT_TRAFFIC_SECRET_0, rx_secret,
223 secretlen);
224 keylog::log_secret(ssl_, keylog::QUIC_SERVER_TRAFFIC_SECRET_0, tx_secret,
225 secretlen);
Tatsuhiro Tsujikawa19cce622018-06-02 23:03:35 +0900226 break;
Tatsuhiro Tsujikawa589ca012018-08-29 12:12:56 +0900227 default:
Tatsuhiro Tsujikawa7558be42019-08-25 18:50:46 +0900228 assert(0);
Tatsuhiro Tsujikawa589ca012018-08-29 12:12:56 +0900229 }
Tatsuhiro Tsujikawa19cce622018-06-02 23:03:35 +0900230
Tatsuhiro Tsujikawa735626b2019-08-27 19:17:18 +0900231 if (!config.quiet && config.show_secret) {
Tatsuhiro Tsujikawacf382c42019-08-25 23:53:50 +0900232 std::cerr << title << " rx secret" << std::endl;
Tatsuhiro Tsujikawa7558be42019-08-25 18:50:46 +0900233 debug::print_secrets(rx_secret, secretlen, rx_key.data(), keylen,
Tatsuhiro Tsujikawac6f570b2019-08-29 09:49:17 +0900234 rx_iv.data(), ivlen, rx_hp_key.data(), keylen);
Tatsuhiro Tsujikawa7558be42019-08-25 18:50:46 +0900235 if (tx_secret) {
Tatsuhiro Tsujikawacf382c42019-08-25 23:53:50 +0900236 std::cerr << title << " tx secret" << std::endl;
Tatsuhiro Tsujikawa7558be42019-08-25 18:50:46 +0900237 debug::print_secrets(tx_secret, secretlen, tx_key.data(), keylen,
Tatsuhiro Tsujikawac6f570b2019-08-29 09:49:17 +0900238 tx_iv.data(), ivlen, tx_hp_key.data(), keylen);
Tatsuhiro Tsujikawa7558be42019-08-25 18:50:46 +0900239 }
240 }
Tatsuhiro Tsujikawa19cce622018-06-02 23:03:35 +0900241
Tatsuhiro Tsujikawa76232e92020-12-01 14:56:28 +0900242 if (level == NGTCP2_CRYPTO_LEVEL_APPLICATION && setup_httpconn() != 0) {
Tatsuhiro Tsujikawa94931782017-06-24 12:20:52 +0900243 return -1;
244 }
245
Tatsuhiro Tsujikawa94931782017-06-24 12:20:52 +0900246 return 0;
247}
Tatsuhiro Tsujikawa94931782017-06-24 12:20:52 +0900248
Tatsuhiro Tsujikawae09d48a2019-04-03 00:44:40 +0900249Stream::Stream(int64_t stream_id, Handler *handler)
250 : stream_id(stream_id),
251 handler(handler),
Tatsuhiro Tsujikawae09d48a2019-04-03 00:44:40 +0900252 data(nullptr),
Tatsuhiro Tsujikawa40bab9a2019-04-03 21:00:00 +0900253 datalen(0),
254 dynresp(false),
255 dyndataleft(0),
Tatsuhiro Tsujikawa8cd22a82020-08-14 18:27:30 +0900256 dynbuflen(0) {}
Tatsuhiro Tsujikawae85b4a52017-08-19 20:10:45 +0900257
Tatsuhiro Tsujikawae85b4a52017-08-19 20:10:45 +0900258namespace {
Tatsuhiro Tsujikawa191845d2019-04-01 22:21:50 +0900259constexpr char NGTCP2_SERVER[] = "nghttp3/ngtcp2 server";
Tatsuhiro Tsujikawae85b4a52017-08-19 20:10:45 +0900260} // namespace
261
262namespace {
263std::string make_status_body(unsigned int status_code) {
264 auto status_string = std::to_string(status_code);
265 auto reason_phrase = http::get_reason_phrase(status_code);
266
267 std::string body;
268 body = "<html><head><title>";
269 body += status_string;
270 body += ' ';
271 body += reason_phrase;
272 body += "</title></head><body><h1>";
273 body += status_string;
274 body += ' ';
275 body += reason_phrase;
276 body += "</h1><hr><address>";
277 body += NGTCP2_SERVER;
278 body += " at port ";
279 body += std::to_string(config.port);
280 body += "</address>";
281 body += "</body></html>";
282 return body;
283}
284} // namespace
285
Tatsuhiro Tsujikawa48e19982019-04-14 09:54:36 +0900286struct Request {
287 std::string path;
288 std::vector<std::string> pushes;
Tatsuhiro Tsujikawa5a3c90c2020-04-06 23:35:21 +0900289 struct {
290 int32_t urgency;
291 int inc;
292 } pri;
Tatsuhiro Tsujikawa48e19982019-04-14 09:54:36 +0900293};
294
Tatsuhiro Tsujikawae85b4a52017-08-19 20:10:45 +0900295namespace {
Tatsuhiro Tsujikawa23f6cc32019-11-22 18:06:58 +0900296Request request_path(const std::string_view &uri, bool is_connect) {
Tatsuhiro Tsujikawae85b4a52017-08-19 20:10:45 +0900297 http_parser_url u;
Tatsuhiro Tsujikawa48e19982019-04-14 09:54:36 +0900298 Request req;
Tatsuhiro Tsujikawae85b4a52017-08-19 20:10:45 +0900299
Tatsuhiro Tsujikawa5a3c90c2020-04-06 23:35:21 +0900300 req.pri.urgency = -1;
301 req.pri.inc = -1;
302
Tatsuhiro Tsujikawae85b4a52017-08-19 20:10:45 +0900303 http_parser_url_init(&u);
304
Tatsuhiro Tsujikawa3dd351e2019-11-22 18:17:40 +0900305 if (auto rv = http_parser_parse_url(uri.data(), uri.size(), is_connect, &u);
306 rv != 0) {
Tatsuhiro Tsujikawa48e19982019-04-14 09:54:36 +0900307 return req;
Tatsuhiro Tsujikawae85b4a52017-08-19 20:10:45 +0900308 }
309
310 if (u.field_set & (1 << UF_PATH)) {
Tatsuhiro Tsujikawa23f6cc32019-11-22 18:06:58 +0900311 req.path = std::string(uri.data() + u.field_data[UF_PATH].off,
Tatsuhiro Tsujikawa48e19982019-04-14 09:54:36 +0900312 u.field_data[UF_PATH].len);
Tatsuhiro Tsujikawa1448a8e2020-08-14 19:04:15 +0900313 if (req.path.find('%') != std::string::npos) {
314 req.path = util::percent_decode(std::begin(req.path), std::end(req.path));
315 }
Tatsuhiro Tsujikawa48e19982019-04-14 09:54:36 +0900316 if (!req.path.empty() && req.path.back() == '/') {
317 req.path += "index.html";
Tatsuhiro Tsujikawaea74bf12017-08-20 00:13:42 +0900318 }
Tatsuhiro Tsujikawa48e19982019-04-14 09:54:36 +0900319 } else {
320 req.path = "/index.html";
Tatsuhiro Tsujikawae85b4a52017-08-19 20:10:45 +0900321 }
322
Tatsuhiro Tsujikawa38eed2c2020-08-17 01:04:50 +0900323 req.path = util::normalize_path(req.path);
324 if (req.path == "/") {
325 req.path = "/index.html";
326 }
327
Tatsuhiro Tsujikawa48e19982019-04-14 09:54:36 +0900328 if (u.field_set & (1 << UF_QUERY)) {
329 static constexpr char push_prefix[] = "push=";
Tatsuhiro Tsujikawa5a3c90c2020-04-06 23:35:21 +0900330 static constexpr char urgency_prefix[] = "u=";
331 static constexpr char inc_prefix[] = "i=";
Tatsuhiro Tsujikawa23f6cc32019-11-22 18:06:58 +0900332 auto q = std::string(uri.data() + u.field_data[UF_QUERY].off,
Tatsuhiro Tsujikawa48e19982019-04-14 09:54:36 +0900333 u.field_data[UF_QUERY].len);
334 for (auto p = std::begin(q); p != std::end(q);) {
Tatsuhiro Tsujikawa5a3c90c2020-04-06 23:35:21 +0900335 if (util::istarts_with(p, std::end(q), std::begin(push_prefix),
336 std::end(push_prefix) - 1)) {
337 auto path_start = p + sizeof(push_prefix) - 1;
338 auto path_end = std::find(path_start, std::end(q), '&');
339 if (path_start != path_end && *path_start == '/') {
340 req.pushes.emplace_back(path_start, path_end);
341 }
342 if (path_end == std::end(q)) {
Tatsuhiro Tsujikawa48e19982019-04-14 09:54:36 +0900343 break;
344 }
Tatsuhiro Tsujikawa5a3c90c2020-04-06 23:35:21 +0900345 p = path_end + 1;
346 continue;
347 }
348 if (util::istarts_with(p, std::end(q), std::begin(urgency_prefix),
349 std::end(urgency_prefix) - 1)) {
350 auto urgency_start = p + sizeof(urgency_prefix) - 1;
351 auto urgency_end = std::find(urgency_start, std::end(q), '&');
352 if (urgency_start + 1 == urgency_end && '0' <= *urgency_start &&
353 *urgency_start <= '7') {
354 req.pri.urgency = *urgency_start - '0';
355 }
356 if (urgency_end == std::end(q)) {
357 break;
358 }
359 p = urgency_end + 1;
360 continue;
361 }
362 if (util::istarts_with(p, std::end(q), std::begin(inc_prefix),
363 std::end(inc_prefix) - 1)) {
364 auto inc_start = p + sizeof(inc_prefix) - 1;
365 auto inc_end = std::find(inc_start, std::end(q), '&');
366 if (inc_start + 1 == inc_end &&
367 (*inc_start == '0' || *inc_start == '1')) {
368 req.pri.inc = *inc_start - '0';
369 }
370 if (inc_end == std::end(q)) {
371 break;
372 }
373 p = inc_end + 1;
Tatsuhiro Tsujikawa48e19982019-04-14 09:54:36 +0900374 continue;
375 }
376
Tatsuhiro Tsujikawa5a3c90c2020-04-06 23:35:21 +0900377 p = std::find(p, std::end(q), '&');
378 if (p == std::end(q)) {
Tatsuhiro Tsujikawa48e19982019-04-14 09:54:36 +0900379 break;
380 }
Tatsuhiro Tsujikawa5a3c90c2020-04-06 23:35:21 +0900381 ++p;
Tatsuhiro Tsujikawa48e19982019-04-14 09:54:36 +0900382 }
383 }
384 return req;
Tatsuhiro Tsujikawae85b4a52017-08-19 20:10:45 +0900385}
386} // namespace
387
Tatsuhiro Tsujikawa8cd22a82020-08-14 18:27:30 +0900388enum FileEntryFlag {
389 FILE_ENTRY_TYPE_DIR = 0x1,
390};
391
392struct FileEntry {
393 uint64_t len;
394 void *map;
395 int fd;
396 uint8_t flags;
397};
398
399namespace {
400std::unordered_map<std::string, FileEntry> file_cache;
401} // namespace
402
403std::pair<FileEntry, int> Stream::open_file(const std::string &path) {
404 auto it = file_cache.find(path);
405 if (it != std::end(file_cache)) {
406 return {(*it).second, 0};
Tatsuhiro Tsujikawae85b4a52017-08-19 20:10:45 +0900407 }
408
Tatsuhiro Tsujikawa8cd22a82020-08-14 18:27:30 +0900409 auto fd = open(path.c_str(), O_RDONLY);
410 if (fd == -1) {
411 return {{}, -1};
412 }
413
414 struct stat st {};
415 if (fstat(fd, &st) != 0) {
416 close(fd);
417 return {{}, -1};
418 }
419
420 FileEntry fe{};
421 if (st.st_mode & S_IFDIR) {
422 fe.flags |= FILE_ENTRY_TYPE_DIR;
423 fe.fd = -1;
424 close(fd);
425 } else {
426 fe.fd = fd;
427 fe.len = st.st_size;
428 fe.map = mmap(nullptr, fe.len, PROT_READ, MAP_SHARED, fd, 0);
429 if (fe.map == MAP_FAILED) {
430 std::cerr << "mmap: " << strerror(errno) << std::endl;
431 close(fd);
432 return {{}, -1};
433 }
434 }
435
436 file_cache.emplace(path, fe);
437
438 return {std::move(fe), 0};
Tatsuhiro Tsujikawae85b4a52017-08-19 20:10:45 +0900439}
440
Tatsuhiro Tsujikawa8cd22a82020-08-14 18:27:30 +0900441void Stream::map_file(const FileEntry &fe) {
442 data = static_cast<uint8_t *>(fe.map);
443 datalen = fe.len;
Tatsuhiro Tsujikawae85b4a52017-08-19 20:10:45 +0900444}
445
Tatsuhiro Tsujikawa23f6cc32019-11-22 18:06:58 +0900446int64_t Stream::find_dyn_length(const std::string_view &path) {
Tatsuhiro Tsujikawa40bab9a2019-04-03 21:00:00 +0900447 assert(path[0] == '/');
448
Tatsuhiro Tsujikawa38eed2c2020-08-17 01:04:50 +0900449 if (path.size() == 1) {
450 return -1;
451 }
452
Tatsuhiro Tsujikawa28d70192019-11-22 19:14:55 +0900453 uint64_t n = 0;
Tatsuhiro Tsujikawa40bab9a2019-04-03 21:00:00 +0900454
455 for (auto it = std::begin(path) + 1; it != std::end(path); ++it) {
456 if (*it < '0' || '9' < *it) {
457 return -1;
458 }
Tatsuhiro Tsujikawab3f61f22019-11-22 13:42:26 +0900459 auto d = *it - '0';
Tatsuhiro Tsujikawa28d70192019-11-22 19:14:55 +0900460 if (n > (((1ull << 62) - 1) - d) / 10) {
Tatsuhiro Tsujikawab3f61f22019-11-22 13:42:26 +0900461 return -1;
462 }
463 n = n * 10 + d;
464 if (n > config.max_dyn_length) {
Tatsuhiro Tsujikawa40bab9a2019-04-03 21:00:00 +0900465 return -1;
466 }
467 }
468
Tatsuhiro Tsujikawa28d70192019-11-22 19:14:55 +0900469 return static_cast<int64_t>(n);
Tatsuhiro Tsujikawa40bab9a2019-04-03 21:00:00 +0900470}
471
Tatsuhiro Tsujikawa9ea17af2019-03-25 14:37:26 +0900472namespace {
Tatsuhiro Tsujikawa77bd2a32019-11-09 17:56:25 +0900473nghttp3_ssize read_data(nghttp3_conn *conn, int64_t stream_id, nghttp3_vec *vec,
474 size_t veccnt, uint32_t *pflags, void *user_data,
475 void *stream_user_data) {
Tatsuhiro Tsujikawa9ea17af2019-03-25 14:37:26 +0900476 auto stream = static_cast<Stream *>(stream_user_data);
Tatsuhiro Tsujikawa29e2d352017-09-17 13:04:36 +0900477
Tatsuhiro Tsujikawaf77d7182019-09-03 19:19:42 +0900478 vec[0].base = stream->data;
479 vec[0].len = stream->datalen;
Tatsuhiro Tsujikawae529af12020-07-25 17:12:11 +0900480 *pflags |= NGHTTP3_DATA_FLAG_EOF;
481 if (config.send_trailers) {
482 *pflags |= NGHTTP3_DATA_FLAG_NO_END_STREAM;
483 }
Tatsuhiro Tsujikawa9ea17af2019-03-25 14:37:26 +0900484
Tatsuhiro Tsujikawaf77d7182019-09-03 19:19:42 +0900485 return 1;
Tatsuhiro Tsujikawa9ea17af2019-03-25 14:37:26 +0900486}
487} // namespace
488
Tatsuhiro Tsujikawa5c730832019-11-22 22:10:46 +0900489auto dyn_buf = std::make_unique<std::array<uint8_t, 16_k>>();
490
Tatsuhiro Tsujikawa40bab9a2019-04-03 21:00:00 +0900491namespace {
Tatsuhiro Tsujikawa77bd2a32019-11-09 17:56:25 +0900492nghttp3_ssize dyn_read_data(nghttp3_conn *conn, int64_t stream_id,
493 nghttp3_vec *vec, size_t veccnt, uint32_t *pflags,
494 void *user_data, void *stream_user_data) {
Tatsuhiro Tsujikawa40bab9a2019-04-03 21:00:00 +0900495 auto stream = static_cast<Stream *>(stream_user_data);
496
Tatsuhiro Tsujikawadec083a2019-06-15 17:48:42 +0900497 if (stream->dynbuflen > MAX_DYNBUFLEN) {
498 return NGHTTP3_ERR_WOULDBLOCK;
499 }
500
Tatsuhiro Tsujikawa5c730832019-11-22 22:10:46 +0900501 auto len =
502 std::min(dyn_buf->size(), static_cast<size_t>(stream->dyndataleft));
Tatsuhiro Tsujikawa40bab9a2019-04-03 21:00:00 +0900503
Tatsuhiro Tsujikawa5c730832019-11-22 22:10:46 +0900504 vec[0].base = dyn_buf->data();
Tatsuhiro Tsujikawaf77d7182019-09-03 19:19:42 +0900505 vec[0].len = len;
Tatsuhiro Tsujikawa40bab9a2019-04-03 21:00:00 +0900506
507 stream->dynbuflen += len;
Tatsuhiro Tsujikawa40bab9a2019-04-03 21:00:00 +0900508 stream->dyndataleft -= len;
509
510 if (stream->dyndataleft == 0) {
Tatsuhiro Tsujikawae529af12020-07-25 17:12:11 +0900511 *pflags |= NGHTTP3_DATA_FLAG_EOF;
512 if (config.send_trailers) {
513 *pflags |= NGHTTP3_DATA_FLAG_NO_END_STREAM;
514 auto stream_id_str = std::to_string(stream_id);
515 std::array<nghttp3_nv, 1> trailers{
516 util::make_nv("x-ngtcp2-stream-id", stream_id_str),
517 };
Tatsuhiro Tsujikawa5f536b92019-04-03 22:19:08 +0900518
Tatsuhiro Tsujikawae529af12020-07-25 17:12:11 +0900519 if (auto rv = nghttp3_conn_submit_trailers(
520 conn, stream_id, trailers.data(), trailers.size());
521 rv != 0) {
522 std::cerr << "nghttp3_conn_submit_trailers: " << nghttp3_strerror(rv)
523 << std::endl;
524 return NGHTTP3_ERR_CALLBACK_FAILURE;
525 }
Tatsuhiro Tsujikawa5f536b92019-04-03 22:19:08 +0900526 }
Tatsuhiro Tsujikawa40bab9a2019-04-03 21:00:00 +0900527 }
528
Tatsuhiro Tsujikawaf77d7182019-09-03 19:19:42 +0900529 return 1;
Tatsuhiro Tsujikawa40bab9a2019-04-03 21:00:00 +0900530}
531} // namespace
532
Tatsuhiro Tsujikawa44bce162019-04-03 22:39:36 +0900533void Stream::http_acked_stream_data(size_t datalen) {
534 if (!dynresp) {
535 return;
536 }
537
Tatsuhiro Tsujikawa44bce162019-04-03 22:39:36 +0900538 assert(dynbuflen >= datalen);
Tatsuhiro Tsujikawa44bce162019-04-03 22:39:36 +0900539
Tatsuhiro Tsujikawa5c730832019-11-22 22:10:46 +0900540 dynbuflen -= datalen;
Tatsuhiro Tsujikawa44bce162019-04-03 22:39:36 +0900541}
542
Tatsuhiro Tsujikawa53bf2242019-04-04 09:15:35 +0900543int Stream::send_status_response(nghttp3_conn *httpconn,
544 unsigned int status_code,
545 const std::vector<HTTPHeader> &extra_headers) {
Tatsuhiro Tsujikawa9ea17af2019-03-25 14:37:26 +0900546 status_resp_body = make_status_body(status_code);
547
548 auto status_code_str = std::to_string(status_code);
549 auto content_length_str = std::to_string(status_resp_body.size());
550
551 std::vector<nghttp3_nv> nva(4 + extra_headers.size());
552 nva[0] = util::make_nv(":status", status_code_str);
553 nva[1] = util::make_nv("server", NGTCP2_SERVER);
Tatsuhiro Tsujikawabe53b562019-04-01 22:22:38 +0900554 nva[2] = util::make_nv("content-type", "text/html; charset=utf-8");
Tatsuhiro Tsujikawa9ea17af2019-03-25 14:37:26 +0900555 nva[3] = util::make_nv("content-length", content_length_str);
Tatsuhiro Tsujikawac0949522019-03-25 21:07:30 +0900556 for (size_t i = 0; i < extra_headers.size(); ++i) {
Tatsuhiro Tsujikawa9ea17af2019-03-25 14:37:26 +0900557 auto &hdr = extra_headers[i];
558 auto &nv = nva[4 + i];
559 nv = util::make_nv(hdr.name, hdr.value);
Tatsuhiro Tsujikawade763ae2017-09-06 23:26:36 +0900560 }
Tatsuhiro Tsujikawae85b4a52017-08-19 20:10:45 +0900561
Tatsuhiro Tsujikawa9ea17af2019-03-25 14:37:26 +0900562 data = (uint8_t *)status_resp_body.data();
563 datalen = status_resp_body.size();
564
565 nghttp3_data_reader dr{};
566 dr.read_data = read_data;
567
Tatsuhiro Tsujikawa3dd351e2019-11-22 18:17:40 +0900568 if (auto rv = nghttp3_conn_submit_response(httpconn, stream_id, nva.data(),
569 nva.size(), &dr);
570 rv != 0) {
Tatsuhiro Tsujikawa9ea17af2019-03-25 14:37:26 +0900571 std::cerr << "nghttp3_conn_submit_response: " << nghttp3_strerror(rv)
572 << std::endl;
Tatsuhiro Tsujikawa53bf2242019-04-04 09:15:35 +0900573 return -1;
Tatsuhiro Tsujikawa65901f72017-08-19 23:56:41 +0900574 }
Tatsuhiro Tsujikawae09d48a2019-04-03 00:44:40 +0900575
Tatsuhiro Tsujikawae529af12020-07-25 17:12:11 +0900576 if (config.send_trailers) {
577 auto stream_id_str = std::to_string(stream_id);
578 std::array<nghttp3_nv, 1> trailers{
579 util::make_nv("x-ngtcp2-stream-id", stream_id_str),
580 };
Tatsuhiro Tsujikawae69d8a52019-04-03 18:52:47 +0900581
Tatsuhiro Tsujikawae529af12020-07-25 17:12:11 +0900582 if (auto rv = nghttp3_conn_submit_trailers(
583 httpconn, stream_id, trailers.data(), trailers.size());
584 rv != 0) {
585 std::cerr << "nghttp3_conn_submit_trailers: " << nghttp3_strerror(rv)
586 << std::endl;
587 return -1;
588 }
Tatsuhiro Tsujikawae69d8a52019-04-03 18:52:47 +0900589 }
590
Tatsuhiro Tsujikawafa53c4e2020-01-29 21:26:44 +0900591 handler->shutdown_read(stream_id, NGHTTP3_H3_NO_ERROR);
Tatsuhiro Tsujikawa53bf2242019-04-04 09:15:35 +0900592
593 return 0;
Tatsuhiro Tsujikawae85b4a52017-08-19 20:10:45 +0900594}
595
Tatsuhiro Tsujikawa53bf2242019-04-04 09:15:35 +0900596int Stream::send_redirect_response(nghttp3_conn *httpconn,
597 unsigned int status_code,
Tatsuhiro Tsujikawa23f6cc32019-11-22 18:06:58 +0900598 const std::string_view &path) {
Tatsuhiro Tsujikawa53bf2242019-04-04 09:15:35 +0900599 return send_status_response(httpconn, status_code, {{"location", path}});
Tatsuhiro Tsujikawaed5d80f2017-08-20 12:10:08 +0900600}
601
Tatsuhiro Tsujikawa9ea17af2019-03-25 14:37:26 +0900602int Stream::start_response(nghttp3_conn *httpconn) {
603 // TODO This should be handled by nghttp3
604 if (uri.empty() || method.empty()) {
Tatsuhiro Tsujikawa53bf2242019-04-04 09:15:35 +0900605 return send_status_response(httpconn, 400);
Tatsuhiro Tsujikawa9ea17af2019-03-25 14:37:26 +0900606 }
Tatsuhiro Tsujikawade763ae2017-09-06 23:26:36 +0900607
Tatsuhiro Tsujikawa48e19982019-04-14 09:54:36 +0900608 auto req = request_path(uri, method == "CONNECT");
Tatsuhiro Tsujikawa60b902b2019-04-16 21:07:59 +0900609 if (req.path.empty()) {
610 return send_status_response(httpconn, 400);
611 }
612
Tatsuhiro Tsujikawa48e19982019-04-14 09:54:36 +0900613 auto dyn_len = find_dyn_length(req.path);
Tatsuhiro Tsujikawaed5d80f2017-08-20 12:10:08 +0900614
615 int64_t content_length = -1;
Tatsuhiro Tsujikawa40bab9a2019-04-03 21:00:00 +0900616 nghttp3_data_reader dr{};
Tatsuhiro Tsujikawa219dc882019-07-27 19:31:12 +0900617 std::string content_type = "text/plain";
Tatsuhiro Tsujikawaed5d80f2017-08-20 12:10:08 +0900618
Tatsuhiro Tsujikawa40bab9a2019-04-03 21:00:00 +0900619 if (dyn_len == -1) {
Tatsuhiro Tsujikawa38eed2c2020-08-17 01:04:50 +0900620 auto path = config.htdocs + req.path;
Tatsuhiro Tsujikawa8cd22a82020-08-14 18:27:30 +0900621 auto [fe, rv] = open_file(path);
622 if (rv != 0) {
Tatsuhiro Tsujikawa40bab9a2019-04-03 21:00:00 +0900623 send_status_response(httpconn, 404);
Tatsuhiro Tsujikawaed5d80f2017-08-20 12:10:08 +0900624 return 0;
625 }
Tatsuhiro Tsujikawa40bab9a2019-04-03 21:00:00 +0900626
Tatsuhiro Tsujikawa8cd22a82020-08-14 18:27:30 +0900627 if (fe.flags & FILE_ENTRY_TYPE_DIR) {
628 send_redirect_response(httpconn, 308,
629 path.substr(config.htdocs.size() - 1) + '/');
Tatsuhiro Tsujikawa40bab9a2019-04-03 21:00:00 +0900630 return 0;
631 }
632
Tatsuhiro Tsujikawa8cd22a82020-08-14 18:27:30 +0900633 content_length = fe.len;
634
635 if (method != "HEAD") {
636 map_file(fe);
Tatsuhiro Tsujikawa40bab9a2019-04-03 21:00:00 +0900637 }
638
639 dr.read_data = read_data;
Tatsuhiro Tsujikawa219dc882019-07-27 19:31:12 +0900640
641 auto ext = std::end(req.path) - 1;
642 for (; ext != std::begin(req.path) && *ext != '.' && *ext != '/'; --ext)
643 ;
644 if (*ext == '.') {
645 ++ext;
646 auto it = config.mime_types.find(std::string{ext, std::end(req.path)});
647 if (it != std::end(config.mime_types)) {
648 content_type = (*it).second;
649 }
650 }
651
Tatsuhiro Tsujikawa29e2d352017-09-17 13:04:36 +0900652 } else {
Tatsuhiro Tsujikawa40bab9a2019-04-03 21:00:00 +0900653 content_length = dyn_len;
654 datalen = dyn_len;
655 dynresp = true;
656 dyndataleft = dyn_len;
Tatsuhiro Tsujikawa29e2d352017-09-17 13:04:36 +0900657
Tatsuhiro Tsujikawa40bab9a2019-04-03 21:00:00 +0900658 dr.read_data = dyn_read_data;
Tatsuhiro Tsujikawa219dc882019-07-27 19:31:12 +0900659
660 content_type = "application/octet-stream";
Tatsuhiro Tsujikawae85b4a52017-08-19 20:10:45 +0900661 }
662
Tatsuhiro Tsujikawa58d696c2019-04-14 16:33:15 +0900663 if ((stream_id & 0x3) == 0 && !authority.empty()) {
Tatsuhiro Tsujikawa48e19982019-04-14 09:54:36 +0900664 for (const auto &push : req.pushes) {
665 if (handler->push_content(stream_id, authority, push) != 0) {
666 return -1;
667 }
668 }
669 }
670
Tatsuhiro Tsujikawa9ea17af2019-03-25 14:37:26 +0900671 auto content_length_str = std::to_string(content_length);
672
Tatsuhiro Tsujikawa5a3c90c2020-04-06 23:35:21 +0900673 std::array<nghttp3_nv, 5> nva{
Tatsuhiro Tsujikawa9ea17af2019-03-25 14:37:26 +0900674 util::make_nv(":status", "200"),
675 util::make_nv("server", NGTCP2_SERVER),
Tatsuhiro Tsujikawa219dc882019-07-27 19:31:12 +0900676 util::make_nv("content-type", content_type),
Tatsuhiro Tsujikawa9ea17af2019-03-25 14:37:26 +0900677 util::make_nv("content-length", content_length_str),
678 };
679
Tatsuhiro Tsujikawa5a3c90c2020-04-06 23:35:21 +0900680 size_t nvlen = 4;
681
682 std::string prival;
683
684 if (req.pri.urgency != -1 || req.pri.inc != -1) {
685 nghttp3_pri pri;
686
687 if (auto rv = nghttp3_conn_get_stream_priority(httpconn, &pri, stream_id);
688 rv != 0) {
689 std::cerr << "nghttp3_conn_get_stream_priority: " << nghttp3_strerror(rv)
690 << std::endl;
691 return -1;
692 }
693
694 if (req.pri.urgency != -1) {
695 pri.urgency = req.pri.urgency;
696 }
697 if (req.pri.inc != -1) {
698 pri.inc = req.pri.inc;
699 }
700
701 if (auto rv = nghttp3_conn_set_stream_priority(httpconn, stream_id, &pri);
702 rv != 0) {
703 std::cerr << "nghttp3_conn_set_stream_priority: " << nghttp3_strerror(rv)
704 << std::endl;
705 return -1;
706 }
707
708 prival = "u=";
709 prival += pri.urgency + '0';
710 prival += ",i";
711 if (!pri.inc) {
712 prival += "=?0";
713 }
714
715 nva[nvlen++] = util::make_nv("priority", prival);
716 }
717
Tatsuhiro Tsujikawa015d5a72019-04-14 13:27:06 +0900718 if (!config.quiet) {
Tatsuhiro Tsujikawa5a3c90c2020-04-06 23:35:21 +0900719 debug::print_http_response_headers(stream_id, nva.data(), nvlen);
Tatsuhiro Tsujikawa015d5a72019-04-14 13:27:06 +0900720 }
721
Tatsuhiro Tsujikawa3dd351e2019-11-22 18:17:40 +0900722 if (auto rv = nghttp3_conn_submit_response(httpconn, stream_id, nva.data(),
Tatsuhiro Tsujikawa5a3c90c2020-04-06 23:35:21 +0900723 nvlen, &dr);
Tatsuhiro Tsujikawa3dd351e2019-11-22 18:17:40 +0900724 rv != 0) {
Tatsuhiro Tsujikawa9ea17af2019-03-25 14:37:26 +0900725 std::cerr << "nghttp3_conn_submit_response: " << nghttp3_strerror(rv)
726 << std::endl;
Tatsuhiro Tsujikawa53bf2242019-04-04 09:15:35 +0900727 return -1;
Tatsuhiro Tsujikawa9ea17af2019-03-25 14:37:26 +0900728 }
729
Tatsuhiro Tsujikawae529af12020-07-25 17:12:11 +0900730 if (config.send_trailers && dyn_len == -1) {
Tatsuhiro Tsujikawa5f536b92019-04-03 22:19:08 +0900731 auto stream_id_str = std::to_string(stream_id);
732 std::array<nghttp3_nv, 1> trailers{
733 util::make_nv("x-ngtcp2-stream-id", stream_id_str),
734 };
Tatsuhiro Tsujikawa40bab9a2019-04-03 21:00:00 +0900735
Tatsuhiro Tsujikawa3dd351e2019-11-22 18:17:40 +0900736 if (auto rv = nghttp3_conn_submit_trailers(
737 httpconn, stream_id, trailers.data(), trailers.size());
738 rv != 0) {
Tatsuhiro Tsujikawa5f536b92019-04-03 22:19:08 +0900739 std::cerr << "nghttp3_conn_submit_trailers: " << nghttp3_strerror(rv)
740 << std::endl;
Tatsuhiro Tsujikawa53bf2242019-04-04 09:15:35 +0900741 return -1;
Tatsuhiro Tsujikawa5f536b92019-04-03 22:19:08 +0900742 }
743
Tatsuhiro Tsujikawafa53c4e2020-01-29 21:26:44 +0900744 handler->shutdown_read(stream_id, NGHTTP3_H3_NO_ERROR);
Tatsuhiro Tsujikawa40bab9a2019-04-03 21:00:00 +0900745 }
Tatsuhiro Tsujikawae69d8a52019-04-03 18:52:47 +0900746
Tatsuhiro Tsujikawae85b4a52017-08-19 20:10:45 +0900747 return 0;
748}
Tatsuhiro Tsujikawad5031772017-07-14 22:37:02 +0900749
750namespace {
Tatsuhiro Tsujikawabb38b832019-05-14 23:22:00 +0900751void writecb(struct ev_loop *loop, ev_io *w, int revents) {
752 ev_io_stop(loop, w);
753
754 auto h = static_cast<Handler *>(w->data);
755 auto s = h->server();
756
Tatsuhiro Tsujikawa3dd351e2019-11-22 18:17:40 +0900757 switch (h->on_write()) {
Tatsuhiro Tsujikawabb38b832019-05-14 23:22:00 +0900758 case 0:
759 case NETWORK_ERR_CLOSE_WAIT:
Tatsuhiro Tsujikawabb38b832019-05-14 23:22:00 +0900760 return;
761 default:
762 s->remove(h);
763 }
764}
765} // namespace
766
767namespace {
Tatsuhiro Tsujikawabb2ef442017-06-25 17:03:18 +0900768void timeoutcb(struct ev_loop *loop, ev_timer *w, int revents) {
769 auto h = static_cast<Handler *>(w->data);
Tatsuhiro Tsujikawa963adcb2017-09-26 23:04:23 +0900770 auto s = h->server();
771
Tatsuhiro Tsujikawae1247852018-07-26 19:29:56 +0900772 if (ngtcp2_conn_is_in_closing_period(h->conn())) {
Tatsuhiro Tsujikawae3187962017-12-15 00:12:19 +0900773 if (!config.quiet) {
Tatsuhiro Tsujikawae3187962017-12-15 00:12:19 +0900774 std::cerr << "Closing Period is over" << std::endl;
775 }
776
777 s->remove(h);
778 return;
779 }
780 if (h->draining()) {
Tatsuhiro Tsujikawa53809ad2017-10-01 22:38:43 +0900781 if (!config.quiet) {
Tatsuhiro Tsujikawa53809ad2017-10-01 22:38:43 +0900782 std::cerr << "Draining Period is over" << std::endl;
783 }
Tatsuhiro Tsujikawa963adcb2017-09-26 23:04:23 +0900784
785 s->remove(h);
786 return;
787 }
Tatsuhiro Tsujikawabb2ef442017-06-25 17:03:18 +0900788
Tatsuhiro Tsujikawa53809ad2017-10-01 22:38:43 +0900789 if (!config.quiet) {
Tatsuhiro Tsujikawa53809ad2017-10-01 22:38:43 +0900790 std::cerr << "Timeout" << std::endl;
791 }
Tatsuhiro Tsujikawabb2ef442017-06-25 17:03:18 +0900792
Tatsuhiro Tsujikawae3187962017-12-15 00:12:19 +0900793 h->start_draining_period();
Tatsuhiro Tsujikawabb2ef442017-06-25 17:03:18 +0900794}
795} // namespace
796
Tatsuhiro Tsujikawad5031772017-07-14 22:37:02 +0900797namespace {
798void retransmitcb(struct ev_loop *loop, ev_timer *w, int revents) {
nickfajones3200cdc2017-08-25 15:19:35 +0800799 int rv;
Tatsuhiro Tsujikawad5031772017-07-14 22:37:02 +0900800
nickfajones3200cdc2017-08-25 15:19:35 +0800801 auto h = static_cast<Handler *>(w->data);
802 auto s = h->server();
803
Tatsuhiro Tsujikawa8bdd6192019-03-19 23:56:13 +0900804 if (!config.quiet) {
805 std::cerr << "Timer expired" << std::endl;
806 }
Tatsuhiro Tsujikawaddc4f1a2018-03-29 15:38:31 +0900807
Tatsuhiro Tsujikawa74dfb302019-08-10 17:22:28 +0900808 rv = h->handle_expiry();
809 if (rv != 0) {
810 goto fail;
Tatsuhiro Tsujikawadc0fbf82019-07-15 15:52:06 +0900811 }
812
813 rv = h->on_write();
Tatsuhiro Tsujikawa74dfb302019-08-10 17:22:28 +0900814 if (rv != 0) {
815 goto fail;
816 }
817
Tatsuhiro Tsujikawa74dfb302019-08-10 17:22:28 +0900818 return;
819
820fail:
Tatsuhiro Tsujikawadc0fbf82019-07-15 15:52:06 +0900821 switch (rv) {
Tatsuhiro Tsujikawadc0fbf82019-07-15 15:52:06 +0900822 case NETWORK_ERR_CLOSE_WAIT:
Tatsuhiro Tsujikawadc0fbf82019-07-15 15:52:06 +0900823 ev_timer_stop(loop, w);
824 return;
825 default:
826 s->remove(h);
827 return;
Tatsuhiro Tsujikawad5031772017-07-14 22:37:02 +0900828 }
829}
830} // namespace
831
Tatsuhiro Tsujikawaf10fea52017-09-27 22:49:27 +0900832Handler::Handler(struct ev_loop *loop, SSL_CTX *ssl_ctx, Server *server,
Tatsuhiro Tsujikawa6a20dfd2018-04-18 17:32:50 +0900833 const ngtcp2_cid *rcid)
Tatsuhiro Tsujikawae43a8c42019-02-23 18:00:22 +0900834 : endpoint_{nullptr},
835 remote_addr_{},
Tatsuhiro Tsujikawa34e02792017-06-25 16:55:56 +0900836 max_pktlen_(0),
837 loop_(loop),
Tatsuhiro Tsujikawa94931782017-06-24 12:20:52 +0900838 ssl_ctx_(ssl_ctx),
839 ssl_(nullptr),
Tatsuhiro Tsujikawad5031772017-07-14 22:37:02 +0900840 server_(server),
Tatsuhiro Tsujikawa22d9c6d2019-10-15 23:26:02 +0900841 qlog_(nullptr),
Tatsuhiro Tsujikawa543b8de2019-04-06 11:56:07 +0900842 crypto_{},
Tatsuhiro Tsujikawa9c91b392017-06-26 01:14:48 +0900843 conn_(nullptr),
Tatsuhiro Tsujikawae43a8c42019-02-23 18:00:22 +0900844 scid_{},
845 pscid_{},
Tatsuhiro Tsujikawa6a20dfd2018-04-18 17:32:50 +0900846 rcid_(*rcid),
Tatsuhiro Tsujikawa9ea17af2019-03-25 14:37:26 +0900847 httpconn_{nullptr},
Tatsuhiro Tsujikawa9ea17af2019-03-25 14:37:26 +0900848 last_error_{QUICErrorType::Transport, 0},
Tatsuhiro Tsujikawabb8bfae2019-01-26 17:32:19 +0900849 nkey_update_(0),
Tatsuhiro Tsujikawaa6e102c2018-07-12 09:56:23 +0900850 draining_(false) {
Tatsuhiro Tsujikawabb38b832019-05-14 23:22:00 +0900851 ev_io_init(&wev_, writecb, 0, EV_WRITE);
852 wev_.data = this;
Tatsuhiro Tsujikawa283ac462019-11-22 12:53:34 +0900853 ev_timer_init(&timer_, timeoutcb, 0.,
854 static_cast<double>(config.timeout) / NGTCP2_SECONDS);
Tatsuhiro Tsujikawabb2ef442017-06-25 17:03:18 +0900855 timer_.data = this;
Tatsuhiro Tsujikawad5031772017-07-14 22:37:02 +0900856 ev_timer_init(&rttimer_, retransmitcb, 0., 0.);
857 rttimer_.data = this;
Tatsuhiro Tsujikawa94931782017-06-24 12:20:52 +0900858}
859
860Handler::~Handler() {
Tatsuhiro Tsujikawa53809ad2017-10-01 22:38:43 +0900861 if (!config.quiet) {
Tatsuhiro Tsujikawa1720afc2020-03-24 18:12:32 +0900862 std::cerr << scid_ << " Closing QUIC connection " << std::endl;
Tatsuhiro Tsujikawa53809ad2017-10-01 22:38:43 +0900863 }
Tatsuhiro Tsujikawabb2ef442017-06-25 17:03:18 +0900864
Tatsuhiro Tsujikawad5031772017-07-14 22:37:02 +0900865 ev_timer_stop(loop_, &rttimer_);
Tatsuhiro Tsujikawabb2ef442017-06-25 17:03:18 +0900866 ev_timer_stop(loop_, &timer_);
Tatsuhiro Tsujikawabb38b832019-05-14 23:22:00 +0900867 ev_io_stop(loop_, &wev_);
Tatsuhiro Tsujikawabb2ef442017-06-25 17:03:18 +0900868
Tatsuhiro Tsujikawa9ea17af2019-03-25 14:37:26 +0900869 if (httpconn_) {
870 nghttp3_conn_del(httpconn_);
871 }
872
Tatsuhiro Tsujikawa94931782017-06-24 12:20:52 +0900873 if (conn_) {
874 ngtcp2_conn_del(conn_);
875 }
876
877 if (ssl_) {
878 SSL_free(ssl_);
879 }
Tatsuhiro Tsujikawa22d9c6d2019-10-15 23:26:02 +0900880
881 if (qlog_) {
882 fclose(qlog_);
883 }
Tatsuhiro Tsujikawa94931782017-06-24 12:20:52 +0900884}
885
886namespace {
Tatsuhiro Tsujikawa9c91b392017-06-26 01:14:48 +0900887int handshake_completed(ngtcp2_conn *conn, void *user_data) {
888 auto h = static_cast<Handler *>(user_data);
889
Tatsuhiro Tsujikawa53809ad2017-10-01 22:38:43 +0900890 if (!config.quiet) {
891 debug::handshake_completed(conn, user_data);
892 }
Tatsuhiro Tsujikawa9c91b392017-06-26 01:14:48 +0900893
Tatsuhiro Tsujikawa3db05952019-04-03 23:47:12 +0900894 if (h->handshake_completed() != 0) {
895 return NGTCP2_ERR_CALLBACK_FAILURE;
Tatsuhiro Tsujikawa9ea17af2019-03-25 14:37:26 +0900896 }
Tatsuhiro Tsujikawa97f43c12017-12-04 15:46:18 +0900897
Tatsuhiro Tsujikawa9c91b392017-06-26 01:14:48 +0900898 return 0;
899}
900} // namespace
901
Tatsuhiro Tsujikawa9fcb7c52019-08-26 00:25:35 +0900902int Handler::handshake_completed() {
903 if (!config.quiet) {
904 std::cerr << "Negotiated cipher suite is " << SSL_get_cipher_name(ssl_)
905 << std::endl;
906
907 const unsigned char *alpn = nullptr;
908 unsigned int alpnlen;
909
910 SSL_get0_alpn_selected(ssl_, &alpn, &alpnlen);
911 if (alpn) {
912 std::cerr << "Negotiated ALPN is ";
913 std::cerr.write(reinterpret_cast<const char *>(alpn), alpnlen);
914 std::cerr << std::endl;
915 }
916 }
917
Tatsuhiro Tsujikawa1b94c862020-05-27 08:32:46 +0900918 std::array<uint8_t, MAX_TOKENLEN> token;
919 size_t tokenlen = token.size();
Tatsuhiro Tsujikawa40331c12020-05-26 13:39:41 +0900920
Amir Livneh8daa2592020-06-20 04:44:50 -0400921 if (server_->generate_token(token.data(), tokenlen, &remote_addr_.su.sa) !=
922 0) {
Tatsuhiro Tsujikawa40331c12020-05-26 13:39:41 +0900923 if (!config.quiet) {
924 std::cerr << "Unable to generate token" << std::endl;
925 }
926 return 0;
927 }
928
Tatsuhiro Tsujikawa1b94c862020-05-27 08:32:46 +0900929 if (auto rv = ngtcp2_conn_submit_new_token(conn_, token.data(), tokenlen);
930 rv != 0) {
Tatsuhiro Tsujikawa40331c12020-05-26 13:39:41 +0900931 if (!config.quiet) {
932 std::cerr << "ngtcp2_conn_submit_new_token: " << ngtcp2_strerror(rv)
933 << std::endl;
934 }
935 return -1;
936 }
937
Tatsuhiro Tsujikawa9fcb7c52019-08-26 00:25:35 +0900938 return 0;
939}
Tatsuhiro Tsujikawa3db05952019-04-03 23:47:12 +0900940
Tatsuhiro Tsujikawa9c91b392017-06-26 01:14:48 +0900941namespace {
Tatsuhiro Tsujikawaf2361242020-03-03 23:29:22 +0900942int do_hp_mask(uint8_t *dest, const ngtcp2_crypto_cipher *hp,
Tatsuhiro Tsujikawa700bab42020-06-27 22:09:25 +0900943 const ngtcp2_crypto_cipher_ctx *hp_ctx, const uint8_t *sample) {
944 if (ngtcp2_crypto_hp_mask(dest, hp, hp_ctx, sample) != 0) {
Tatsuhiro Tsujikawa43327f12018-05-24 18:11:27 +0900945 return NGTCP2_ERR_CALLBACK_FAILURE;
946 }
947
Tatsuhiro Tsujikawac25b7012018-12-24 11:02:09 +0900948 if (!config.quiet && config.show_secret) {
Tatsuhiro Tsujikawae3588462019-08-24 23:55:06 +0900949 debug::print_hp_mask(dest, NGTCP2_HP_MASKLEN, sample, NGTCP2_HP_SAMPLELEN);
Tatsuhiro Tsujikawac25b7012018-12-24 11:02:09 +0900950 }
951
Tatsuhiro Tsujikawae3588462019-08-24 23:55:06 +0900952 return 0;
Tatsuhiro Tsujikawa43327f12018-05-24 18:11:27 +0900953}
954} // namespace
955
956namespace {
Tatsuhiro Tsujikawa0ea9f4b2019-03-24 09:43:54 +0900957int recv_crypto_data(ngtcp2_conn *conn, ngtcp2_crypto_level crypto_level,
958 uint64_t offset, const uint8_t *data, size_t datalen,
959 void *user_data) {
Tatsuhiro Tsujikawac60626b2019-11-09 18:47:23 +0900960 if (!config.quiet && !config.no_quic_dump) {
Tatsuhiro Tsujikawa0ea9f4b2019-03-24 09:43:54 +0900961 debug::print_crypto_data(crypto_level, data, datalen);
Tatsuhiro Tsujikawaf9153df2018-02-18 10:08:10 +0900962 }
963
Tatsuhiro Tsujikawa94931782017-06-24 12:20:52 +0900964 auto h = static_cast<Handler *>(user_data);
965
Tatsuhiro Tsujikawa7558be42019-08-25 18:50:46 +0900966 if (h->recv_crypto_data(crypto_level, data, datalen) != 0) {
Tatsuhiro Tsujikawabfec8192020-02-04 00:18:08 +0900967 if (auto err = ngtcp2_conn_get_tls_error(conn); err) {
968 return err;
969 }
Tatsuhiro Tsujikawad20a2fb2019-04-06 18:04:53 +0900970 return NGTCP2_ERR_CRYPTO;
971 }
Tatsuhiro Tsujikawa94931782017-06-24 12:20:52 +0900972
Tatsuhiro Tsujikawa9fcb7c52019-08-26 00:25:35 +0900973 return 0;
Tatsuhiro Tsujikawa94931782017-06-24 12:20:52 +0900974}
975} // namespace
976
Tatsuhiro Tsujikawafabb20c2017-07-20 23:31:51 +0900977namespace {
Tatsuhiro Tsujikawa7e9a9172020-06-07 19:57:12 +0900978int recv_stream_data(ngtcp2_conn *conn, uint32_t flags, int64_t stream_id,
Tatsuhiro Tsujikawa6f21ed22018-03-24 19:56:02 +0900979 uint64_t offset, const uint8_t *data, size_t datalen,
980 void *user_data, void *stream_user_data) {
Tatsuhiro Tsujikawafabb20c2017-07-20 23:31:51 +0900981 auto h = static_cast<Handler *>(user_data);
982
Tatsuhiro Tsujikawa7e9a9172020-06-07 19:57:12 +0900983 if (h->recv_stream_data(flags, stream_id, data, datalen) != 0) {
Tatsuhiro Tsujikawafabb20c2017-07-20 23:31:51 +0900984 return NGTCP2_ERR_CALLBACK_FAILURE;
985 }
986
987 return 0;
988}
989} // namespace
990
Tatsuhiro Tsujikawaa7d6c8c2017-07-29 23:04:42 +0900991namespace {
Tatsuhiro Tsujikawa543b8de2019-04-06 11:56:07 +0900992int acked_crypto_offset(ngtcp2_conn *conn, ngtcp2_crypto_level crypto_level,
Tatsuhiro Tsujikawacbc1bb02020-05-02 18:14:15 +0900993 uint64_t offset, uint64_t datalen, void *user_data) {
Tatsuhiro Tsujikawa87344712018-06-30 18:42:12 +0900994 auto h = static_cast<Handler *>(user_data);
Tatsuhiro Tsujikawa543b8de2019-04-06 11:56:07 +0900995 h->remove_tx_crypto_data(crypto_level, offset, datalen);
Tatsuhiro Tsujikawa87344712018-06-30 18:42:12 +0900996 return 0;
997}
998} // namespace
999
1000namespace {
Tatsuhiro Tsujikawaca921e52019-02-27 22:49:36 +09001001int acked_stream_data_offset(ngtcp2_conn *conn, int64_t stream_id,
Tatsuhiro Tsujikawacbc1bb02020-05-02 18:14:15 +09001002 uint64_t offset, uint64_t datalen, void *user_data,
Tatsuhiro Tsujikawaa7d6c8c2017-07-29 23:04:42 +09001003 void *stream_user_data) {
1004 auto h = static_cast<Handler *>(user_data);
Tatsuhiro Tsujikawa9ea17af2019-03-25 14:37:26 +09001005 if (h->acked_stream_data_offset(stream_id, datalen) != 0) {
Tatsuhiro Tsujikawae85b4a52017-08-19 20:10:45 +09001006 return NGTCP2_ERR_CALLBACK_FAILURE;
1007 }
Tatsuhiro Tsujikawaa7d6c8c2017-07-29 23:04:42 +09001008 return 0;
1009}
1010} // namespace
1011
Tatsuhiro Tsujikawacbc1bb02020-05-02 18:14:15 +09001012int Handler::acked_stream_data_offset(int64_t stream_id, uint64_t datalen) {
Tatsuhiro Tsujikawa9ea17af2019-03-25 14:37:26 +09001013 if (!httpconn_) {
1014 return 0;
1015 }
1016
Tatsuhiro Tsujikawa3dd351e2019-11-22 18:17:40 +09001017 if (auto rv = nghttp3_conn_add_ack_offset(httpconn_, stream_id, datalen);
1018 rv != 0) {
Tatsuhiro Tsujikawa66405c42019-09-14 21:25:28 +09001019 std::cerr << "nghttp3_conn_add_ack_offset: " << nghttp3_strerror(rv)
Tatsuhiro Tsujikawa9ea17af2019-03-25 14:37:26 +09001020 << std::endl;
1021 return -1;
1022 }
1023
1024 return 0;
1025}
1026
1027namespace {
1028int stream_open(ngtcp2_conn *conn, int64_t stream_id, void *user_data) {
1029 auto h = static_cast<Handler *>(user_data);
1030 h->on_stream_open(stream_id);
1031 return 0;
1032}
1033} // namespace
1034
1035void Handler::on_stream_open(int64_t stream_id) {
Tatsuhiro Tsujikawae317a1f2020-02-12 10:21:40 +09001036 if (!ngtcp2_is_bidi_stream(stream_id)) {
1037 return;
1038 }
Tatsuhiro Tsujikawa9ea17af2019-03-25 14:37:26 +09001039 auto it = streams_.find(stream_id);
1040 assert(it == std::end(streams_));
Tatsuhiro Tsujikawae09d48a2019-04-03 00:44:40 +09001041 streams_.emplace(stream_id, std::make_unique<Stream>(stream_id, this));
Tatsuhiro Tsujikawa9ea17af2019-03-25 14:37:26 +09001042}
1043
Tatsuhiro Tsujikawa23f6cc32019-11-22 18:06:58 +09001044int Handler::push_content(int64_t stream_id, const std::string_view &authority,
1045 const std::string_view &path) {
Tatsuhiro Tsujikawa48e19982019-04-14 09:54:36 +09001046 auto nva = std::array<nghttp3_nv, 4>{
1047 util::make_nv(":method", "GET"),
1048 util::make_nv(":scheme", "https"),
1049 util::make_nv(":authority", authority),
1050 util::make_nv(":path", path),
1051 };
1052
1053 int64_t push_id;
Tatsuhiro Tsujikawaf47f0022019-11-22 18:35:11 +09001054 if (auto rv = nghttp3_conn_submit_push_promise(httpconn_, &push_id, stream_id,
1055 nva.data(), nva.size());
1056 rv != 0) {
Tatsuhiro Tsujikawa48e19982019-04-14 09:54:36 +09001057 std::cerr << "nghttp3_conn_submit_push_promise: " << nghttp3_strerror(rv)
1058 << std::endl;
1059 if (rv != NGHTTP3_ERR_PUSH_ID_BLOCKED) {
1060 return -1;
1061 }
1062 return 0;
1063 }
1064
Tatsuhiro Tsujikawa015d5a72019-04-14 13:27:06 +09001065 if (!config.quiet) {
1066 debug::print_http_push_promise(stream_id, push_id, nva.data(), nva.size());
1067 }
1068
Tatsuhiro Tsujikawa48e19982019-04-14 09:54:36 +09001069 int64_t push_stream_id;
Tatsuhiro Tsujikawaf47f0022019-11-22 18:35:11 +09001070 if (auto rv = ngtcp2_conn_open_uni_stream(conn_, &push_stream_id, nullptr);
1071 rv != 0) {
Tatsuhiro Tsujikawa48e19982019-04-14 09:54:36 +09001072 std::cerr << "ngtcp2_conn_open_uni_stream: " << ngtcp2_strerror(rv)
1073 << std::endl;
1074 if (rv != NGTCP2_ERR_STREAM_ID_BLOCKED) {
1075 return -1;
1076 }
1077 return 0;
1078 }
1079
Tatsuhiro Tsujikawa015d5a72019-04-14 13:27:06 +09001080 if (!config.quiet) {
1081 debug::push_stream(push_id, push_stream_id);
1082 }
1083
Tatsuhiro Tsujikawa48e19982019-04-14 09:54:36 +09001084 Stream *stream;
1085 {
1086 auto p = std::make_unique<Stream>(push_stream_id, this);
1087 stream = p.get();
1088 streams_.emplace(push_stream_id, std::move(p));
1089 }
1090
Tatsuhiro Tsujikawaf47f0022019-11-22 18:35:11 +09001091 if (auto rv =
1092 nghttp3_conn_bind_push_stream(httpconn_, push_id, push_stream_id);
1093 rv != 0) {
Tatsuhiro Tsujikawa48e19982019-04-14 09:54:36 +09001094 std::cerr << "nghttp3_conn_bind_push_stream: " << nghttp3_strerror(rv)
1095 << std::endl;
1096 return -1;
1097 }
1098
1099 stream->uri = path;
1100 stream->method = "GET";
1101 stream->authority = authority;
1102
1103 nghttp3_conn_set_stream_user_data(httpconn_, push_stream_id, stream);
1104
1105 stream->start_response(httpconn_);
1106
1107 return 0;
1108}
1109
Tatsuhiro Tsujikawa1bcac1e2017-08-04 22:50:22 +09001110namespace {
Tatsuhiro Tsujikawa1522d942019-07-11 23:09:33 +09001111int stream_close(ngtcp2_conn *conn, int64_t stream_id, uint64_t app_error_code,
Tatsuhiro Tsujikawa1bcac1e2017-08-04 22:50:22 +09001112 void *user_data, void *stream_user_data) {
1113 auto h = static_cast<Handler *>(user_data);
Tatsuhiro Tsujikawab54327c2019-06-10 10:07:47 +09001114 if (h->on_stream_close(stream_id, app_error_code) != 0) {
Tatsuhiro Tsujikawa53bf2242019-04-04 09:15:35 +09001115 return NGTCP2_ERR_CALLBACK_FAILURE;
1116 }
Tatsuhiro Tsujikawa1bcac1e2017-08-04 22:50:22 +09001117 return 0;
1118}
1119} // namespace
1120
Tatsuhiro Tsujikawa1ca92c32018-04-04 00:31:23 +09001121namespace {
Tatsuhiro Tsujikawa9ea17af2019-03-25 14:37:26 +09001122int stream_reset(ngtcp2_conn *conn, int64_t stream_id, uint64_t final_size,
Tatsuhiro Tsujikawa1522d942019-07-11 23:09:33 +09001123 uint64_t app_error_code, void *user_data,
Tatsuhiro Tsujikawa9ea17af2019-03-25 14:37:26 +09001124 void *stream_user_data) {
1125 auto h = static_cast<Handler *>(user_data);
Tatsuhiro Tsujikawa53bf2242019-04-04 09:15:35 +09001126 if (h->on_stream_reset(stream_id) != 0) {
1127 return NGTCP2_ERR_CALLBACK_FAILURE;
1128 }
Tatsuhiro Tsujikawa9ea17af2019-03-25 14:37:26 +09001129 return 0;
1130}
1131} // namespace
1132
Tatsuhiro Tsujikawa53bf2242019-04-04 09:15:35 +09001133int Handler::on_stream_reset(int64_t stream_id) {
Tatsuhiro Tsujikawa9ea17af2019-03-25 14:37:26 +09001134 if (httpconn_) {
Tatsuhiro Tsujikawa3dd351e2019-11-22 18:17:40 +09001135 if (auto rv = nghttp3_conn_reset_stream(httpconn_, stream_id); rv != 0) {
Tatsuhiro Tsujikawa53bf2242019-04-04 09:15:35 +09001136 std::cerr << "nghttp3_conn_reset_stream: " << nghttp3_strerror(rv)
1137 << std::endl;
1138 return -1;
1139 }
Tatsuhiro Tsujikawa9ea17af2019-03-25 14:37:26 +09001140 }
Tatsuhiro Tsujikawa53bf2242019-04-04 09:15:35 +09001141 return 0;
Tatsuhiro Tsujikawa9ea17af2019-03-25 14:37:26 +09001142}
1143
1144namespace {
Tatsuhiro Tsujikawa803e2032020-08-23 11:08:30 +09001145int rand(uint8_t *dest, size_t destlen, const ngtcp2_rand_ctx *rand_ctx,
1146 ngtcp2_rand_usage usage) {
Tatsuhiro Tsujikawa1ca92c32018-04-04 00:31:23 +09001147 auto dis = std::uniform_int_distribution<uint8_t>(0, 255);
1148 std::generate(dest, dest + destlen, [&dis]() { return dis(randgen); });
1149 return 0;
1150}
1151} // namespace
1152
Tatsuhiro Tsujikawad67f91c2019-01-06 18:15:40 +09001153namespace {
1154int get_new_connection_id(ngtcp2_conn *conn, ngtcp2_cid *cid, uint8_t *token,
1155 size_t cidlen, void *user_data) {
Tatsuhiro Tsujikawa287e2e02020-09-06 21:09:06 +09001156 auto h = static_cast<Handler *>(user_data);
1157 auto server = h->server();
Tatsuhiro Tsujikawad67f91c2019-01-06 18:15:40 +09001158
Tatsuhiro Tsujikawad67f91c2019-01-06 18:15:40 +09001159 cid->datalen = cidlen;
Tatsuhiro Tsujikawa287e2e02020-09-06 21:09:06 +09001160 generate_authenticated_cid(cid->data, cidlen, server->get_svindex());
1161
Tatsuhiro Tsujikawafe5fc7c2020-01-12 12:11:35 +09001162 auto md = ngtcp2_crypto_md{const_cast<EVP_MD *>(EVP_sha256())};
1163 if (ngtcp2_crypto_generate_stateless_reset_token(
1164 token, &md, config.static_secret.data(), config.static_secret.size(),
1165 cid) != 0) {
1166 return NGTCP2_ERR_CALLBACK_FAILURE;
1167 }
Tatsuhiro Tsujikawad67f91c2019-01-06 18:15:40 +09001168
Tatsuhiro Tsujikawa287e2e02020-09-06 21:09:06 +09001169 server->associate_cid(cid, h);
Tatsuhiro Tsujikawad67f91c2019-01-06 18:15:40 +09001170
1171 return 0;
1172}
1173} // namespace
1174
1175namespace {
1176int remove_connection_id(ngtcp2_conn *conn, const ngtcp2_cid *cid,
1177 void *user_data) {
1178 auto h = static_cast<Handler *>(user_data);
1179 h->server()->dissociate_cid(cid);
1180 return 0;
1181}
1182} // namespace
1183
Tatsuhiro Tsujikawabb8bfae2019-01-26 17:32:19 +09001184namespace {
Tatsuhiro Tsujikawa42ce09c2019-12-12 16:52:36 +09001185int update_key(ngtcp2_conn *conn, uint8_t *rx_secret, uint8_t *tx_secret,
Tatsuhiro Tsujikawa700bab42020-06-27 22:09:25 +09001186 ngtcp2_crypto_aead_ctx *rx_aead_ctx, uint8_t *rx_iv,
1187 ngtcp2_crypto_aead_ctx *tx_aead_ctx, uint8_t *tx_iv,
Tatsuhiro Tsujikawa42ce09c2019-12-12 16:52:36 +09001188 const uint8_t *current_rx_secret,
1189 const uint8_t *current_tx_secret, size_t secretlen,
1190 void *user_data) {
Tatsuhiro Tsujikawabb8bfae2019-01-26 17:32:19 +09001191 auto h = static_cast<Handler *>(user_data);
Tatsuhiro Tsujikawa700bab42020-06-27 22:09:25 +09001192 if (h->update_key(rx_secret, tx_secret, rx_aead_ctx, rx_iv, tx_aead_ctx,
1193 tx_iv, current_rx_secret, current_tx_secret,
1194 secretlen) != 0) {
Tatsuhiro Tsujikawabb8bfae2019-01-26 17:32:19 +09001195 return NGTCP2_ERR_CALLBACK_FAILURE;
1196 }
1197 return 0;
1198}
1199} // namespace
1200
Tatsuhiro Tsujikawa009f7372019-01-30 00:17:32 +09001201namespace {
1202int path_validation(ngtcp2_conn *conn, const ngtcp2_path *path,
1203 ngtcp2_path_validation_result res, void *user_data) {
1204 if (!config.quiet) {
1205 debug::path_validation(path, res);
1206 }
1207 return 0;
1208}
1209} // namespace
1210
Tatsuhiro Tsujikawa9ea17af2019-03-25 14:37:26 +09001211namespace {
1212int extend_max_remote_streams_bidi(ngtcp2_conn *conn, uint64_t max_streams,
1213 void *user_data) {
1214 auto h = static_cast<Handler *>(user_data);
1215 h->extend_max_remote_streams_bidi(max_streams);
1216 return 0;
1217}
1218} // namespace
1219
1220void Handler::extend_max_remote_streams_bidi(uint64_t max_streams) {
1221 if (!httpconn_) {
1222 return;
1223 }
1224
1225 nghttp3_conn_set_max_client_streams_bidi(httpconn_, max_streams);
1226}
1227
1228namespace {
1229int http_recv_data(nghttp3_conn *conn, int64_t stream_id, const uint8_t *data,
1230 size_t datalen, void *user_data, void *stream_user_data) {
Tatsuhiro Tsujikawac60626b2019-11-09 18:47:23 +09001231 if (!config.quiet && !config.no_http_dump) {
Tatsuhiro Tsujikawa9ea17af2019-03-25 14:37:26 +09001232 debug::print_http_data(stream_id, data, datalen);
1233 }
1234 auto h = static_cast<Handler *>(user_data);
1235 h->http_consume(stream_id, datalen);
1236 return 0;
1237}
1238} // namespace
1239
1240namespace {
1241int http_deferred_consume(nghttp3_conn *conn, int64_t stream_id,
1242 size_t nconsumed, void *user_data,
1243 void *stream_user_data) {
1244 auto h = static_cast<Handler *>(user_data);
1245 h->http_consume(stream_id, nconsumed);
1246 return 0;
1247}
1248} // namespace
1249
1250void Handler::http_consume(int64_t stream_id, size_t nconsumed) {
1251 ngtcp2_conn_extend_max_stream_offset(conn_, stream_id, nconsumed);
1252 ngtcp2_conn_extend_max_offset(conn_, nconsumed);
1253}
1254
1255namespace {
1256int http_begin_request_headers(nghttp3_conn *conn, int64_t stream_id,
1257 void *user_data, void *stream_user_data) {
1258 if (!config.quiet) {
1259 debug::print_http_begin_request_headers(stream_id);
1260 }
1261
1262 auto h = static_cast<Handler *>(user_data);
1263 h->http_begin_request_headers(stream_id);
1264 return 0;
1265}
1266} // namespace
1267
1268void Handler::http_begin_request_headers(int64_t stream_id) {
1269 auto it = streams_.find(stream_id);
1270 assert(it != std::end(streams_));
1271 auto &stream = (*it).second;
1272
1273 nghttp3_conn_set_stream_user_data(httpconn_, stream_id, stream.get());
1274}
1275
1276namespace {
1277int http_recv_request_header(nghttp3_conn *conn, int64_t stream_id,
1278 int32_t token, nghttp3_rcbuf *name,
1279 nghttp3_rcbuf *value, uint8_t flags,
1280 void *user_data, void *stream_user_data) {
1281 if (!config.quiet) {
1282 debug::print_http_header(stream_id, name, value, flags);
1283 }
1284
1285 auto h = static_cast<Handler *>(user_data);
Tatsuhiro Tsujikawac0235d32020-07-05 18:56:46 +09001286 auto stream = static_cast<Stream *>(stream_user_data);
1287 h->http_recv_request_header(stream, token, name, value);
Tatsuhiro Tsujikawa9ea17af2019-03-25 14:37:26 +09001288 return 0;
1289}
1290} // namespace
1291
Tatsuhiro Tsujikawac0235d32020-07-05 18:56:46 +09001292void Handler::http_recv_request_header(Stream *stream, int32_t token,
Tatsuhiro Tsujikawa9ea17af2019-03-25 14:37:26 +09001293 nghttp3_rcbuf *name,
1294 nghttp3_rcbuf *value) {
Tatsuhiro Tsujikawa9ea17af2019-03-25 14:37:26 +09001295 auto v = nghttp3_rcbuf_get_buf(value);
1296
1297 switch (token) {
1298 case NGHTTP3_QPACK_TOKEN__PATH:
1299 stream->uri = std::string{v.base, v.base + v.len};
1300 break;
1301 case NGHTTP3_QPACK_TOKEN__METHOD:
1302 stream->method = std::string{v.base, v.base + v.len};
1303 break;
Tatsuhiro Tsujikawa48e19982019-04-14 09:54:36 +09001304 case NGHTTP3_QPACK_TOKEN__AUTHORITY:
1305 stream->authority = std::string{v.base, v.base + v.len};
1306 break;
Tatsuhiro Tsujikawa9ea17af2019-03-25 14:37:26 +09001307 }
1308}
1309
1310namespace {
1311int http_end_request_headers(nghttp3_conn *conn, int64_t stream_id,
1312 void *user_data, void *stream_user_data) {
1313 if (!config.quiet) {
1314 debug::print_http_end_headers(stream_id);
1315 }
1316
1317 auto h = static_cast<Handler *>(user_data);
Tatsuhiro Tsujikawac0235d32020-07-05 18:56:46 +09001318 auto stream = static_cast<Stream *>(stream_user_data);
1319 if (h->http_end_request_headers(stream) != 0) {
Tatsuhiro Tsujikawa53bf2242019-04-04 09:15:35 +09001320 return NGHTTP3_ERR_CALLBACK_FAILURE;
1321 }
Tatsuhiro Tsujikawa9ea17af2019-03-25 14:37:26 +09001322 return 0;
1323}
1324} // namespace
1325
Tatsuhiro Tsujikawac0235d32020-07-05 18:56:46 +09001326int Handler::http_end_request_headers(Stream *stream) {
Tatsuhiro Tsujikawa8217c612019-08-24 00:02:34 +09001327 if (config.early_response) {
Tatsuhiro Tsujikawac0235d32020-07-05 18:56:46 +09001328 return start_response(stream);
Tatsuhiro Tsujikawa8217c612019-08-24 00:02:34 +09001329 }
1330 return 0;
1331}
1332
1333namespace {
1334int http_end_stream(nghttp3_conn *conn, int64_t stream_id, void *user_data,
1335 void *stream_user_data) {
1336 auto h = static_cast<Handler *>(user_data);
Tatsuhiro Tsujikawac0235d32020-07-05 18:56:46 +09001337 auto stream = static_cast<Stream *>(stream_user_data);
1338 if (h->http_end_stream(stream) != 0) {
Tatsuhiro Tsujikawa8217c612019-08-24 00:02:34 +09001339 return NGHTTP3_ERR_CALLBACK_FAILURE;
1340 }
1341 return 0;
1342}
1343} // namespace
1344
Tatsuhiro Tsujikawac0235d32020-07-05 18:56:46 +09001345int Handler::http_end_stream(Stream *stream) {
Tatsuhiro Tsujikawa8217c612019-08-24 00:02:34 +09001346 if (!config.early_response) {
Tatsuhiro Tsujikawac0235d32020-07-05 18:56:46 +09001347 return start_response(stream);
Tatsuhiro Tsujikawa8217c612019-08-24 00:02:34 +09001348 }
1349 return 0;
1350}
1351
Tatsuhiro Tsujikawac0235d32020-07-05 18:56:46 +09001352int Handler::start_response(Stream *stream) {
Tatsuhiro Tsujikawa53bf2242019-04-04 09:15:35 +09001353 return stream->start_response(httpconn_);
Tatsuhiro Tsujikawa9ea17af2019-03-25 14:37:26 +09001354}
1355
Tatsuhiro Tsujikawa40bab9a2019-04-03 21:00:00 +09001356namespace {
1357int http_acked_stream_data(nghttp3_conn *conn, int64_t stream_id,
1358 size_t datalen, void *user_data,
1359 void *stream_user_data) {
1360 auto h = static_cast<Handler *>(user_data);
Tatsuhiro Tsujikawac0235d32020-07-05 18:56:46 +09001361 auto stream = static_cast<Stream *>(stream_user_data);
1362 h->http_acked_stream_data(stream, datalen);
Tatsuhiro Tsujikawa40bab9a2019-04-03 21:00:00 +09001363 return 0;
1364}
1365} // namespace
1366
Tatsuhiro Tsujikawac0235d32020-07-05 18:56:46 +09001367void Handler::http_acked_stream_data(Stream *stream, size_t datalen) {
Tatsuhiro Tsujikawa44bce162019-04-03 22:39:36 +09001368 stream->http_acked_stream_data(datalen);
Tatsuhiro Tsujikawadec083a2019-06-15 17:48:42 +09001369
Tatsuhiro Tsujikawa8cd22a82020-08-14 18:27:30 +09001370 if (stream->dynresp && stream->dynbuflen < MAX_DYNBUFLEN - 16384) {
Tatsuhiro Tsujikawac0235d32020-07-05 18:56:46 +09001371 if (auto rv = nghttp3_conn_resume_stream(httpconn_, stream->stream_id);
1372 rv != 0) {
Tatsuhiro Tsujikawadec083a2019-06-15 17:48:42 +09001373 // TODO Handle error
1374 std::cerr << "nghttp3_conn_resume_stream: " << nghttp3_strerror(rv)
1375 << std::endl;
1376 }
1377 }
Tatsuhiro Tsujikawa40bab9a2019-04-03 21:00:00 +09001378}
1379
Tatsuhiro Tsujikawa7efbb042020-02-12 09:14:11 +09001380namespace {
1381int http_stream_close(nghttp3_conn *conn, int64_t stream_id,
1382 uint64_t app_error_code, void *conn_user_data,
1383 void *stream_user_data) {
1384 auto h = static_cast<Handler *>(conn_user_data);
1385 h->http_stream_close(stream_id, app_error_code);
1386 return 0;
1387}
1388} // namespace
1389
1390void Handler::http_stream_close(int64_t stream_id, uint64_t app_error_code) {
1391 auto it = streams_.find(stream_id);
1392 if (it == std::end(streams_)) {
1393 return;
1394 }
1395
1396 if (!config.quiet) {
Tatsuhiro Tsujikawae2e8d042020-02-12 10:35:36 +09001397 std::cerr << "HTTP stream " << stream_id << " closed with error code "
Tatsuhiro Tsujikawa7efbb042020-02-12 09:14:11 +09001398 << app_error_code << std::endl;
1399 }
1400
1401 streams_.erase(it);
Tatsuhiro Tsujikawae317a1f2020-02-12 10:21:40 +09001402
1403 if (ngtcp2_is_bidi_stream(stream_id)) {
1404 assert(!ngtcp2_conn_is_local_stream(conn_, stream_id));
1405 ngtcp2_conn_extend_max_streams_bidi(conn_, 1);
1406 }
Tatsuhiro Tsujikawa7efbb042020-02-12 09:14:11 +09001407}
1408
Tatsuhiro Tsujikawa97906092020-10-26 23:19:13 +09001409namespace {
1410int http_send_stop_sending(nghttp3_conn *conn, int64_t stream_id,
1411 uint64_t app_error_code, void *user_data,
1412 void *stream_user_data) {
1413 auto h = static_cast<Handler *>(user_data);
1414 if (h->http_send_stop_sending(stream_id, app_error_code) != 0) {
1415 return NGHTTP3_ERR_CALLBACK_FAILURE;
1416 }
1417 return 0;
1418}
1419} // namespace
1420
1421int Handler::http_send_stop_sending(int64_t stream_id,
1422 uint64_t app_error_code) {
1423 if (auto rv =
1424 ngtcp2_conn_shutdown_stream_read(conn_, stream_id, app_error_code);
1425 rv != 0) {
1426 std::cerr << "ngtcp2_conn_shutdown_stream_read: " << ngtcp2_strerror(rv)
1427 << std::endl;
1428 return -1;
1429 if (rv == NGTCP2_ERR_STREAM_NOT_FOUND) {
1430 return 0;
1431 }
1432 return -1;
1433 }
1434 return 0;
1435}
1436
1437namespace {
1438int http_reset_stream(nghttp3_conn *conn, int64_t stream_id,
1439 uint64_t app_error_code, void *user_data,
1440 void *stream_user_data) {
1441 auto h = static_cast<Handler *>(user_data);
1442 if (h->http_reset_stream(stream_id, app_error_code) != 0) {
1443 return NGHTTP3_ERR_CALLBACK_FAILURE;
1444 }
1445 return 0;
1446}
1447} // namespace
1448
1449int Handler::http_reset_stream(int64_t stream_id, uint64_t app_error_code) {
1450 if (auto rv =
1451 ngtcp2_conn_shutdown_stream_write(conn_, stream_id, app_error_code);
1452 rv != 0) {
1453 std::cerr << "ngtcp2_conn_shutdown_stream_write: " << ngtcp2_strerror(rv)
1454 << std::endl;
1455 return -1;
1456 if (rv == NGTCP2_ERR_STREAM_NOT_FOUND) {
1457 return 0;
1458 }
1459 return -1;
1460 }
1461 return 0;
1462}
1463
Tatsuhiro Tsujikawa9ea17af2019-03-25 14:37:26 +09001464int Handler::setup_httpconn() {
Tatsuhiro Tsujikawa9ea17af2019-03-25 14:37:26 +09001465 if (httpconn_) {
1466 return 0;
1467 }
1468
1469 if (ngtcp2_conn_get_max_local_streams_uni(conn_) < 3) {
1470 std::cerr << "peer does not allow at least 3 unidirectional streams."
1471 << std::endl;
1472 return -1;
1473 }
1474
1475 nghttp3_conn_callbacks callbacks{
Tatsuhiro Tsujikawa40bab9a2019-04-03 21:00:00 +09001476 ::http_acked_stream_data, // acked_stream_data
Tatsuhiro Tsujikawa7efbb042020-02-12 09:14:11 +09001477 ::http_stream_close,
Tatsuhiro Tsujikawa9ea17af2019-03-25 14:37:26 +09001478 ::http_recv_data,
1479 ::http_deferred_consume,
1480 ::http_begin_request_headers,
1481 ::http_recv_request_header,
1482 ::http_end_request_headers,
1483 nullptr, // begin_trailers
1484 nullptr, // recv_trailer
1485 nullptr, // end_trailers
1486 nullptr, // begin_push_promise
1487 nullptr, // recv_push_promise
1488 nullptr, // end_push_promise
Tatsuhiro Tsujikawa8217c612019-08-24 00:02:34 +09001489 nullptr, // cancel_push
Tatsuhiro Tsujikawa97906092020-10-26 23:19:13 +09001490 ::http_send_stop_sending,
Tatsuhiro Tsujikawa8217c612019-08-24 00:02:34 +09001491 nullptr, // push_stream
1492 ::http_end_stream,
Tatsuhiro Tsujikawa97906092020-10-26 23:19:13 +09001493 ::http_reset_stream,
Tatsuhiro Tsujikawa9ea17af2019-03-25 14:37:26 +09001494 };
1495 nghttp3_conn_settings settings;
1496 nghttp3_conn_settings_default(&settings);
1497 settings.qpack_max_table_capacity = 4096;
1498 settings.qpack_blocked_streams = 100;
Tatsuhiro Tsujikawa9ea17af2019-03-25 14:37:26 +09001499
1500 auto mem = nghttp3_mem_default();
1501
Tatsuhiro Tsujikawaf47f0022019-11-22 18:35:11 +09001502 if (auto rv =
1503 nghttp3_conn_server_new(&httpconn_, &callbacks, &settings, mem, this);
1504 rv != 0) {
Tatsuhiro Tsujikawa9ea17af2019-03-25 14:37:26 +09001505 std::cerr << "nghttp3_conn_server_new: " << nghttp3_strerror(rv)
1506 << std::endl;
1507 return -1;
1508 }
1509
Tatsuhiro Tsujikawa963134c2019-07-20 19:53:41 +09001510 ngtcp2_transport_params params;
1511 ngtcp2_conn_get_local_transport_params(conn_, &params);
1512
1513 nghttp3_conn_set_max_client_streams_bidi(httpconn_,
1514 params.initial_max_streams_bidi);
1515
Tatsuhiro Tsujikawa9ea17af2019-03-25 14:37:26 +09001516 int64_t ctrl_stream_id;
1517
Tatsuhiro Tsujikawaf47f0022019-11-22 18:35:11 +09001518 if (auto rv = ngtcp2_conn_open_uni_stream(conn_, &ctrl_stream_id, nullptr);
1519 rv != 0) {
Tatsuhiro Tsujikawa9ea17af2019-03-25 14:37:26 +09001520 std::cerr << "ngtcp2_conn_open_uni_stream: " << ngtcp2_strerror(rv)
1521 << std::endl;
1522 return -1;
1523 }
1524
Tatsuhiro Tsujikawaf47f0022019-11-22 18:35:11 +09001525 if (auto rv = nghttp3_conn_bind_control_stream(httpconn_, ctrl_stream_id);
1526 rv != 0) {
Tatsuhiro Tsujikawa9ea17af2019-03-25 14:37:26 +09001527 std::cerr << "nghttp3_conn_bind_control_stream: " << nghttp3_strerror(rv)
1528 << std::endl;
1529 return -1;
1530 }
1531
1532 if (!config.quiet) {
1533 fprintf(stderr, "http: control stream=%" PRIx64 "\n", ctrl_stream_id);
1534 }
1535
1536 int64_t qpack_enc_stream_id, qpack_dec_stream_id;
1537
Tatsuhiro Tsujikawaf47f0022019-11-22 18:35:11 +09001538 if (auto rv =
1539 ngtcp2_conn_open_uni_stream(conn_, &qpack_enc_stream_id, nullptr);
1540 rv != 0) {
Tatsuhiro Tsujikawa9ea17af2019-03-25 14:37:26 +09001541 std::cerr << "ngtcp2_conn_open_uni_stream: " << ngtcp2_strerror(rv)
1542 << std::endl;
1543 return -1;
1544 }
1545
Tatsuhiro Tsujikawaf47f0022019-11-22 18:35:11 +09001546 if (auto rv =
1547 ngtcp2_conn_open_uni_stream(conn_, &qpack_dec_stream_id, nullptr);
1548 rv != 0) {
Tatsuhiro Tsujikawa9ea17af2019-03-25 14:37:26 +09001549 std::cerr << "ngtcp2_conn_open_uni_stream: " << ngtcp2_strerror(rv)
1550 << std::endl;
1551 return -1;
1552 }
1553
Tatsuhiro Tsujikawaf47f0022019-11-22 18:35:11 +09001554 if (auto rv = nghttp3_conn_bind_qpack_streams(httpconn_, qpack_enc_stream_id,
1555 qpack_dec_stream_id);
1556 rv != 0) {
Tatsuhiro Tsujikawa9ea17af2019-03-25 14:37:26 +09001557 std::cerr << "nghttp3_conn_bind_qpack_streams: " << nghttp3_strerror(rv)
1558 << std::endl;
1559 return -1;
1560 }
1561
1562 if (!config.quiet) {
1563 fprintf(stderr,
1564 "http: QPACK streams encoder=%" PRIx64 " decoder=%" PRIx64 "\n",
1565 qpack_enc_stream_id, qpack_dec_stream_id);
1566 }
1567
1568 return 0;
1569}
1570
Tatsuhiro Tsujikawa87b41f32019-04-01 21:56:12 +09001571namespace {
1572int extend_max_stream_data(ngtcp2_conn *conn, int64_t stream_id,
1573 uint64_t max_data, void *user_data,
1574 void *stream_user_data) {
1575 auto h = static_cast<Handler *>(user_data);
Tatsuhiro Tsujikawa53bf2242019-04-04 09:15:35 +09001576 if (h->extend_max_stream_data(stream_id, max_data) != 0) {
1577 return NGTCP2_ERR_CALLBACK_FAILURE;
1578 }
Tatsuhiro Tsujikawa87b41f32019-04-01 21:56:12 +09001579 return 0;
1580}
1581} // namespace
1582
1583int Handler::extend_max_stream_data(int64_t stream_id, uint64_t max_data) {
Tatsuhiro Tsujikawa3dd351e2019-11-22 18:17:40 +09001584 if (auto rv = nghttp3_conn_unblock_stream(httpconn_, stream_id); rv != 0) {
Tatsuhiro Tsujikawa53bf2242019-04-04 09:15:35 +09001585 std::cerr << "nghttp3_conn_unblock_stream: " << nghttp3_strerror(rv)
1586 << std::endl;
1587 return -1;
1588 }
Tatsuhiro Tsujikawa87b41f32019-04-01 21:56:12 +09001589 return 0;
1590}
1591
Tatsuhiro Tsujikawa22d9c6d2019-10-15 23:26:02 +09001592namespace {
Tatsuhiro Tsujikawa7eaa3672020-07-04 18:19:34 +09001593void write_qlog(void *user_data, uint32_t flags, const void *data,
1594 size_t datalen) {
Tatsuhiro Tsujikawa22d9c6d2019-10-15 23:26:02 +09001595 auto h = static_cast<Handler *>(user_data);
1596 h->write_qlog(data, datalen);
1597}
1598} // namespace
1599
1600void Handler::write_qlog(const void *data, size_t datalen) {
1601 assert(qlog_);
1602 fwrite(data, 1, datalen, qlog_);
1603}
1604
Tatsuhiro Tsujikawa2b9d5452019-02-26 23:42:52 +09001605int Handler::init(const Endpoint &ep, const sockaddr *sa, socklen_t salen,
Tatsuhiro Tsujikawa22d9c6d2019-10-15 23:26:02 +09001606 const ngtcp2_cid *dcid, const ngtcp2_cid *scid,
Tatsuhiro Tsujikawa29555a92019-11-04 18:42:46 +09001607 const ngtcp2_cid *ocid, const uint8_t *token, size_t tokenlen,
1608 uint32_t version) {
Tatsuhiro Tsujikawa2b9d5452019-02-26 23:42:52 +09001609 endpoint_ = const_cast<Endpoint *>(&ep);
Tatsuhiro Tsujikawae43a8c42019-02-23 18:00:22 +09001610
Tatsuhiro Tsujikawa34e02792017-06-25 16:55:56 +09001611 remote_addr_.len = salen;
1612 memcpy(&remote_addr_.su.sa, sa, salen);
1613
Tatsuhiro Tsujikawa3af33c62020-06-29 16:32:10 +09001614 if (config.max_udp_payload_size) {
1615 max_pktlen_ = config.max_udp_payload_size;
1616 } else {
1617 switch (remote_addr_.su.storage.ss_family) {
1618 case AF_INET:
1619 max_pktlen_ = NGTCP2_MAX_PKTLEN_IPV4;
1620 break;
1621 case AF_INET6:
1622 max_pktlen_ = NGTCP2_MAX_PKTLEN_IPV6;
1623 break;
1624 default:
1625 return -1;
1626 }
Tatsuhiro Tsujikawa34e02792017-06-25 16:55:56 +09001627 }
1628
Tatsuhiro Tsujikawa94931782017-06-24 12:20:52 +09001629 ssl_ = SSL_new(ssl_ctx_);
Tatsuhiro Tsujikawa94931782017-06-24 12:20:52 +09001630 SSL_set_app_data(ssl_, this);
1631 SSL_set_accept_state(ssl_);
Tatsuhiro Tsujikawa7558be42019-08-25 18:50:46 +09001632 SSL_set_quic_early_data_enabled(ssl_, 1);
Tatsuhiro Tsujikawa94931782017-06-24 12:20:52 +09001633
1634 auto callbacks = ngtcp2_conn_callbacks{
Daniel Beveniusbdff1602019-02-28 10:56:41 +01001635 nullptr, // client_initial
Tatsuhiro Tsujikawafb753752020-05-21 18:10:40 +09001636 ngtcp2_crypto_recv_client_initial_cb,
Tatsuhiro Tsujikawa7558be42019-08-25 18:50:46 +09001637 ::recv_crypto_data,
Tatsuhiro Tsujikawa3db05952019-04-03 23:47:12 +09001638 ::handshake_completed,
Daniel Beveniusbdff1602019-02-28 10:56:41 +01001639 nullptr, // recv_version_negotiation
Tatsuhiro Tsujikawa312eeb42019-08-28 19:28:29 +09001640 ngtcp2_crypto_encrypt_cb,
1641 ngtcp2_crypto_decrypt_cb,
Tatsuhiro Tsujikawad8ef7a42018-12-20 21:31:05 +09001642 do_hp_mask,
Tatsuhiro Tsujikawafabb20c2017-07-20 23:31:51 +09001643 ::recv_stream_data,
Tatsuhiro Tsujikawa87344712018-06-30 18:42:12 +09001644 acked_crypto_offset,
Tatsuhiro Tsujikawa9ea17af2019-03-25 14:37:26 +09001645 ::acked_stream_data_offset,
1646 stream_open,
Tatsuhiro Tsujikawa1bcac1e2017-08-04 22:50:22 +09001647 stream_close,
Tatsuhiro Tsujikawad6cb10a2018-03-08 17:32:30 +09001648 nullptr, // recv_stateless_reset
Tatsuhiro Tsujikawa7f83e102018-08-19 17:16:28 +09001649 nullptr, // recv_retry
Tatsuhiro Tsujikawa42dd21f2018-12-22 19:41:16 +09001650 nullptr, // extend_max_streams_bidi
1651 nullptr, // extend_max_streams_uni
Tatsuhiro Tsujikawa1ca92c32018-04-04 00:31:23 +09001652 rand,
Tatsuhiro Tsujikawad67f91c2019-01-06 18:15:40 +09001653 get_new_connection_id,
1654 remove_connection_id,
Tatsuhiro Tsujikawabb8bfae2019-01-26 17:32:19 +09001655 ::update_key,
Tatsuhiro Tsujikawa009f7372019-01-30 00:17:32 +09001656 path_validation,
Tatsuhiro Tsujikawa6b1b9b62019-03-22 00:20:24 +09001657 nullptr, // select_preferred_addr
Tatsuhiro Tsujikawa9ea17af2019-03-25 14:37:26 +09001658 ::stream_reset,
Daniel Bevenius9e493312019-11-01 13:27:42 +01001659 ::extend_max_remote_streams_bidi,
Tatsuhiro Tsujikawa700bab42020-06-27 22:09:25 +09001660 nullptr, // extend_max_remote_streams_uni
Tatsuhiro Tsujikawa87b41f32019-04-01 21:56:12 +09001661 ::extend_max_stream_data,
Tatsuhiro Tsujikawa700bab42020-06-27 22:09:25 +09001662 nullptr, // dcid_status
1663 nullptr, // handshake_confirmed
1664 nullptr, // recv_new_token
1665 ngtcp2_crypto_delete_crypto_aead_ctx_cb,
1666 ngtcp2_crypto_delete_crypto_cipher_ctx_cb,
Tatsuhiro Tsujikawa94931782017-06-24 12:20:52 +09001667 };
1668
Tatsuhiro Tsujikawa22d9c6d2019-10-15 23:26:02 +09001669 auto dis = std::uniform_int_distribution<uint8_t>(0, 255);
1670
1671 scid_.datalen = NGTCP2_SV_SCIDLEN;
Tatsuhiro Tsujikawa287e2e02020-09-06 21:09:06 +09001672 generate_authenticated_cid(scid_.data, NGTCP2_SV_SCIDLEN,
1673 server_->get_svindex());
Tatsuhiro Tsujikawa22d9c6d2019-10-15 23:26:02 +09001674
Tatsuhiro Tsujikawa4762dc32019-03-03 12:12:03 +09001675 ngtcp2_settings settings;
1676 ngtcp2_settings_default(&settings);
Tatsuhiro Tsujikawa0999d322018-04-01 22:41:19 +09001677 settings.log_printf = config.quiet ? nullptr : debug::log_printf;
Tatsuhiro Tsujikawa4f1b66a2018-03-30 22:32:41 +09001678 settings.initial_ts = util::timestamp(loop_);
Tatsuhiro Tsujikawa29555a92019-11-04 18:42:46 +09001679 settings.token = ngtcp2_vec{const_cast<uint8_t *>(token), tokenlen};
Tatsuhiro Tsujikawa4ddbefd2020-05-22 20:41:33 +09001680 settings.max_udp_payload_size = max_pktlen_;
Tatsuhiro Tsujikawa8a0b5632020-05-13 21:15:47 +09001681 settings.cc_algo =
1682 config.cc == "cubic" ? NGTCP2_CC_ALGO_CUBIC : NGTCP2_CC_ALGO_RENO;
Tatsuhiro Tsujikawa8d292bb2020-06-27 00:04:19 +09001683 settings.initial_rtt = config.initial_rtt;
Tatsuhiro Tsujikawa64a3e862020-10-02 18:48:13 +09001684 settings.max_window = config.max_window;
1685 settings.max_stream_window = config.max_stream_window;
Tatsuhiro Tsujikawa22d9c6d2019-10-15 23:26:02 +09001686 if (!config.qlog_dir.empty()) {
Tatsuhiro Tsujikawa23f6cc32019-11-22 18:06:58 +09001687 auto path = std::string{config.qlog_dir};
Tatsuhiro Tsujikawa22d9c6d2019-10-15 23:26:02 +09001688 path += '/';
1689 path += util::format_hex(scid_.data, scid_.datalen);
1690 path += ".qlog";
1691 qlog_ = fopen(path.c_str(), "w");
1692 if (qlog_ == nullptr) {
1693 std::cerr << "Could not open qlog file " << path << ": "
1694 << strerror(errno) << std::endl;
1695 return -1;
1696 }
1697 settings.qlog.write = ::write_qlog;
1698 settings.qlog.odcid = *scid;
1699 }
Tatsuhiro Tsujikawa8afd3a62019-10-02 20:51:07 +09001700 auto &params = settings.transport_params;
Tatsuhiro Tsujikawad700f522019-11-22 13:12:49 +09001701 params.initial_max_stream_data_bidi_local = config.max_stream_data_bidi_local;
1702 params.initial_max_stream_data_bidi_remote =
1703 config.max_stream_data_bidi_remote;
Tatsuhiro Tsujikawa2a75c902019-11-22 13:17:43 +09001704 params.initial_max_stream_data_uni = config.max_stream_data_uni;
Tatsuhiro Tsujikawaefd379a2019-11-22 13:03:33 +09001705 params.initial_max_data = config.max_data;
Tatsuhiro Tsujikawaff1f9fe2019-11-22 13:28:33 +09001706 params.initial_max_streams_bidi = config.max_streams_bidi;
1707 params.initial_max_streams_uni = config.max_streams_uni;
Tatsuhiro Tsujikawa9c3c6102020-01-23 19:17:12 +09001708 params.max_idle_timeout = config.timeout;
Tatsuhiro Tsujikawa8afd3a62019-10-02 20:51:07 +09001709 params.stateless_reset_token_present = 1;
1710 params.active_connection_id_limit = 7;
1711
1712 if (ocid) {
Tatsuhiro Tsujikawafb753752020-05-21 18:10:40 +09001713 params.original_dcid = *ocid;
1714 params.retry_scid = *scid;
1715 params.retry_scid_present = 1;
Tatsuhiro Tsujikawa7ab6c562020-07-25 16:52:31 +09001716 } else {
1717 params.original_dcid = *scid;
Tatsuhiro Tsujikawa8afd3a62019-10-02 20:51:07 +09001718 }
Tatsuhiro Tsujikawabd2f3e72017-07-19 22:50:27 +09001719
Tatsuhiro Tsujikawa8afd3a62019-10-02 20:51:07 +09001720 std::generate(std::begin(params.stateless_reset_token),
1721 std::end(params.stateless_reset_token),
Tatsuhiro Tsujikawa7d7d5302017-08-20 14:12:08 +09001722 [&dis]() { return dis(randgen); });
1723
Tatsuhiro Tsujikawae43a8c42019-02-23 18:00:22 +09001724 if (config.preferred_ipv4_addr.len || config.preferred_ipv6_addr.len) {
Tatsuhiro Tsujikawa8afd3a62019-10-02 20:51:07 +09001725 params.preferred_address_present = 1;
Tatsuhiro Tsujikawae43a8c42019-02-23 18:00:22 +09001726 if (config.preferred_ipv4_addr.len) {
Tatsuhiro Tsujikawa8afd3a62019-10-02 20:51:07 +09001727 auto &dest = params.preferred_address.ipv4_addr;
Tatsuhiro Tsujikawae43a8c42019-02-23 18:00:22 +09001728 const auto &addr = config.preferred_ipv4_addr;
1729 assert(sizeof(dest) == sizeof(addr.su.in.sin_addr));
1730 memcpy(&dest, &addr.su.in.sin_addr, sizeof(dest));
Tatsuhiro Tsujikawa8afd3a62019-10-02 20:51:07 +09001731 params.preferred_address.ipv4_port = htons(addr.su.in.sin_port);
Tatsuhiro Tsujikawae43a8c42019-02-23 18:00:22 +09001732 }
1733 if (config.preferred_ipv6_addr.len) {
Tatsuhiro Tsujikawa8afd3a62019-10-02 20:51:07 +09001734 auto &dest = params.preferred_address.ipv6_addr;
Tatsuhiro Tsujikawae43a8c42019-02-23 18:00:22 +09001735 const auto &addr = config.preferred_ipv6_addr;
1736 assert(sizeof(dest) == sizeof(addr.su.in6.sin6_addr));
1737 memcpy(&dest, &addr.su.in6.sin6_addr, sizeof(dest));
Tatsuhiro Tsujikawa8afd3a62019-10-02 20:51:07 +09001738 params.preferred_address.ipv6_port = htons(addr.su.in6.sin6_port);
Tatsuhiro Tsujikawae43a8c42019-02-23 18:00:22 +09001739 }
1740
Tatsuhiro Tsujikawa8afd3a62019-10-02 20:51:07 +09001741 auto &token = params.preferred_address.stateless_reset_token;
Tatsuhiro Tsujikawae43a8c42019-02-23 18:00:22 +09001742 std::generate(std::begin(token), std::end(token),
1743 [&dis]() { return dis(randgen); });
1744
1745 pscid_.datalen = NGTCP2_SV_SCIDLEN;
1746 std::generate(pscid_.data, pscid_.data + pscid_.datalen,
1747 [&dis]() { return dis(randgen); });
Tatsuhiro Tsujikawa8afd3a62019-10-02 20:51:07 +09001748 params.preferred_address.cid = pscid_;
Tatsuhiro Tsujikawae43a8c42019-02-23 18:00:22 +09001749 }
1750
Tatsuhiro Tsujikawaf18bb852020-07-14 22:28:06 +09001751 auto path = ngtcp2_path{{ep.addr.len, const_cast<sockaddr *>(&ep.addr.su.sa),
1752 const_cast<Endpoint *>(&ep)},
1753 {salen, const_cast<sockaddr *>(sa)}};
Tatsuhiro Tsujikawaf47f0022019-11-22 18:35:11 +09001754 if (auto rv = ngtcp2_conn_server_new(&conn_, dcid, &scid_, &path, version,
1755 &callbacks, &settings, nullptr, this);
1756 rv != 0) {
Tatsuhiro Tsujikawaad592ae2017-06-29 00:52:10 +09001757 std::cerr << "ngtcp2_conn_server_new: " << ngtcp2_strerror(rv) << std::endl;
Tatsuhiro Tsujikawa94931782017-06-24 12:20:52 +09001758 return -1;
1759 }
1760
Tatsuhiro Tsujikawa97cdf2a2020-05-23 15:34:05 +09001761 ngtcp2_conn_set_tls_native_handle(conn_, ssl_);
Tatsuhiro Tsujikawa7558be42019-08-25 18:50:46 +09001762
Amir Livnehb1deecb2019-12-11 21:43:43 -08001763 ev_io_set(&wev_, endpoint_->fd, EV_WRITE);
Tatsuhiro Tsujikawafabb20c2017-07-20 23:31:51 +09001764 ev_timer_again(loop_, &timer_);
Tatsuhiro Tsujikawa94931782017-06-24 12:20:52 +09001765
1766 return 0;
1767}
1768
Tatsuhiro Tsujikawa7558be42019-08-25 18:50:46 +09001769void Handler::write_server_handshake(ngtcp2_crypto_level level,
1770 const uint8_t *data, size_t datalen) {
1771 auto &crypto = crypto_[level];
Tatsuhiro Tsujikawa543b8de2019-04-06 11:56:07 +09001772 crypto.data.emplace_back(data, datalen);
Tatsuhiro Tsujikawa04527852018-07-08 18:46:47 +09001773
Tatsuhiro Tsujikawa543b8de2019-04-06 11:56:07 +09001774 auto &buf = crypto.data.back();
Tatsuhiro Tsujikawa04527852018-07-08 18:46:47 +0900