1 /*
2 * nghttp2 - HTTP/2 C Library
3 *
4 * Copyright (c) 2015 Tatsuhiro Tsujikawa
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining
7 * a copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sublicense, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be
15 * included in all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
21 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 */
25 #include "shrpx_connection.h"
26
27 #ifdef HAVE_UNISTD_H
28 # include <unistd.h>
29 #endif // HAVE_UNISTD_H
30 #include <netinet/tcp.h>
31
32 #include <limits>
33
34 #include "ssl_compat.h"
35
36 #ifdef NGHTTP2_OPENSSL_IS_WOLFSSL
37 # include <wolfssl/options.h>
38 # include <wolfssl/openssl/err.h>
39 #else // !NGHTTP2_OPENSSL_IS_WOLFSSL
40 # include <openssl/err.h>
41 #endif // !NGHTTP2_OPENSSL_IS_WOLFSSL
42
43 #include "shrpx_tls.h"
44 #include "shrpx_memcached_request.h"
45 #include "shrpx_log.h"
46 #include "memchunk.h"
47 #include "util.h"
48
49 using namespace nghttp2;
50 using namespace std::chrono_literals;
51
52 namespace shrpx {
53
Connection(struct ev_loop * loop,int fd,SSL * ssl,MemchunkPool * mcpool,ev_tstamp write_timeout,ev_tstamp read_timeout,const RateLimitConfig & write_limit,const RateLimitConfig & read_limit,IOCb writecb,IOCb readcb,TimerCb timeoutcb,void * data,size_t tls_dyn_rec_warmup_threshold,ev_tstamp tls_dyn_rec_idle_timeout,Proto proto)54 Connection::Connection(struct ev_loop *loop, int fd, SSL *ssl,
55 MemchunkPool *mcpool, ev_tstamp write_timeout,
56 ev_tstamp read_timeout,
57 const RateLimitConfig &write_limit,
58 const RateLimitConfig &read_limit, IOCb writecb,
59 IOCb readcb, TimerCb timeoutcb, void *data,
60 size_t tls_dyn_rec_warmup_threshold,
61 ev_tstamp tls_dyn_rec_idle_timeout, Proto proto)
62 :
63 #ifdef ENABLE_HTTP3
64 conn_ref{nullptr, this},
65 #endif // ENABLE_HTTP3
66 tls{DefaultMemchunks(mcpool), DefaultPeekMemchunks(mcpool),
67 DefaultMemchunks(mcpool)},
68 wlimit(loop, &wev, write_limit.rate, write_limit.burst),
69 rlimit(loop, &rev, read_limit.rate, read_limit.burst, this),
70 loop(loop),
71 data(data),
72 fd(fd),
73 tls_dyn_rec_warmup_threshold(tls_dyn_rec_warmup_threshold),
74 tls_dyn_rec_idle_timeout(util::duration_from(tls_dyn_rec_idle_timeout)),
75 proto(proto),
76 read_timeout(read_timeout) {
77
78 ev_io_init(&wev, writecb, fd, EV_WRITE);
79 ev_io_init(&rev, readcb, proto == Proto::HTTP3 ? 0 : fd, EV_READ);
80
81 wev.data = this;
82 rev.data = this;
83
84 ev_timer_init(&wt, timeoutcb, 0., write_timeout);
85 ev_timer_init(&rt, timeoutcb, 0., read_timeout);
86
87 wt.data = this;
88 rt.data = this;
89
90 if (ssl) {
91 set_ssl(ssl);
92 }
93 }
94
~Connection()95 Connection::~Connection() { disconnect(); }
96
disconnect()97 void Connection::disconnect() {
98 if (tls.ssl) {
99 if (proto != Proto::HTTP3) {
100 SSL_set_shutdown(tls.ssl,
101 SSL_get_shutdown(tls.ssl) | SSL_RECEIVED_SHUTDOWN);
102 ERR_clear_error();
103
104 if (tls.cached_session) {
105 SSL_SESSION_free(tls.cached_session);
106 tls.cached_session = nullptr;
107 }
108
109 if (tls.cached_session_lookup_req) {
110 tls.cached_session_lookup_req->canceled = true;
111 tls.cached_session_lookup_req = nullptr;
112 }
113
114 SSL_shutdown(tls.ssl);
115 }
116
117 SSL_free(tls.ssl);
118 tls.ssl = nullptr;
119
120 tls.wbuf.reset();
121 tls.rbuf.reset();
122 tls.last_write_idle = {};
123 tls.warmup_writelen = 0;
124 tls.last_writelen = 0;
125 tls.last_readlen = 0;
126 tls.handshake_state = TLSHandshakeState::NORMAL;
127 tls.initial_handshake_done = false;
128 tls.reneg_started = false;
129 tls.sct_requested = false;
130 tls.early_data_finish = false;
131 }
132
133 if (proto != Proto::HTTP3 && fd != -1) {
134 shutdown(fd, SHUT_WR);
135 close(fd);
136 fd = -1;
137 }
138
139 // Stop watchers here because they could be activated in
140 // SSL_shutdown().
141 ev_timer_stop(loop, &rt);
142 ev_timer_stop(loop, &wt);
143
144 rlimit.stopw();
145 wlimit.stopw();
146 }
147
prepare_client_handshake()148 void Connection::prepare_client_handshake() {
149 SSL_set_connect_state(tls.ssl);
150 // This prevents SSL_read_early_data from being called.
151 tls.early_data_finish = true;
152 }
153
prepare_server_handshake()154 void Connection::prepare_server_handshake() {
155 #if defined(NGHTTP2_GENUINE_OPENSSL) || \
156 defined(NGHTTP2_OPENSSL_IS_BORINGSSL) || \
157 defined(NGHTTP2_OPENSSL_IS_LIBRESSL)
158 auto &tlsconf = get_config()->tls;
159 if (proto != Proto::HTTP3 && !tlsconf.session_cache.memcached.host.empty()) {
160 auto bio = BIO_new(tlsconf.bio_method);
161 BIO_set_data(bio, this);
162 SSL_set_bio(tls.ssl, bio, bio);
163 }
164 #endif // NGHTTP2_GENUINE_OPENSSL || NGHTTP2_OPENSSL_IS_BORINGSSL ||
165 // NGHTTP2_OPENSSL_IS_LIBRESSL
166
167 SSL_set_accept_state(tls.ssl);
168 tls.server_handshake = true;
169 }
170
171 #if defined(NGHTTP2_GENUINE_OPENSSL) || \
172 defined(NGHTTP2_OPENSSL_IS_BORINGSSL) || \
173 defined(NGHTTP2_OPENSSL_IS_LIBRESSL)
174 // BIO implementation is inspired by openldap implementation:
175 // http://www.openldap.org/devel/cvsweb.cgi/~checkout~/libraries/libldap/tls_o.c
176 namespace {
shrpx_bio_write(BIO * b,const char * buf,int len)177 int shrpx_bio_write(BIO *b, const char *buf, int len) {
178 if (buf == nullptr || len <= 0) {
179 return 0;
180 }
181
182 auto conn = static_cast<Connection *>(BIO_get_data(b));
183 auto &wbuf = conn->tls.wbuf;
184
185 BIO_clear_retry_flags(b);
186
187 if (conn->tls.initial_handshake_done) {
188 // After handshake finished, send |buf| of length |len| to the
189 // socket directly.
190
191 // Only when TLS session was prematurely ended before server sent
192 // all handshake message, this condition is true. This could be
193 // alert from SSL_shutdown(). Since connection is already down,
194 // just return error.
195 if (wbuf.rleft()) {
196 return -1;
197 }
198 auto nwrite = conn->write_clear(buf, len);
199 if (nwrite < 0) {
200 return -1;
201 }
202
203 if (nwrite == 0) {
204 BIO_set_retry_write(b);
205 return -1;
206 }
207
208 return nwrite;
209 }
210
211 wbuf.append(buf, len);
212
213 return len;
214 }
215 } // namespace
216
217 namespace {
shrpx_bio_read(BIO * b,char * buf,int len)218 int shrpx_bio_read(BIO *b, char *buf, int len) {
219 if (buf == nullptr || len <= 0) {
220 return 0;
221 }
222
223 auto conn = static_cast<Connection *>(BIO_get_data(b));
224 auto &rbuf = conn->tls.rbuf;
225
226 BIO_clear_retry_flags(b);
227
228 if (conn->tls.initial_handshake_done && rbuf.rleft() == 0) {
229 auto nread = conn->read_clear(buf, len);
230 if (nread < 0) {
231 return -1;
232 }
233 if (nread == 0) {
234 BIO_set_retry_read(b);
235 return -1;
236 }
237 return nread;
238 }
239
240 if (rbuf.rleft() == 0) {
241 BIO_set_retry_read(b);
242 return -1;
243 }
244
245 return rbuf.remove(buf, len);
246 }
247 } // namespace
248
249 namespace {
shrpx_bio_puts(BIO * b,const char * str)250 int shrpx_bio_puts(BIO *b, const char *str) {
251 return shrpx_bio_write(b, str, strlen(str));
252 }
253 } // namespace
254
255 namespace {
shrpx_bio_gets(BIO * b,char * buf,int len)256 int shrpx_bio_gets(BIO *b, char *buf, int len) { return -1; }
257 } // namespace
258
259 namespace {
shrpx_bio_ctrl(BIO * b,int cmd,long num,void * ptr)260 long shrpx_bio_ctrl(BIO *b, int cmd, long num, void *ptr) {
261 switch (cmd) {
262 case BIO_CTRL_FLUSH:
263 return 1;
264 }
265
266 return 0;
267 }
268 } // namespace
269
270 namespace {
shrpx_bio_create(BIO * b)271 int shrpx_bio_create(BIO *b) {
272 BIO_set_init(b, 1);
273
274 return 1;
275 }
276 } // namespace
277
278 namespace {
shrpx_bio_destroy(BIO * b)279 int shrpx_bio_destroy(BIO *b) {
280 if (b == nullptr) {
281 return 0;
282 }
283
284 return 1;
285 }
286 } // namespace
287
create_bio_method()288 BIO_METHOD *create_bio_method() {
289 auto meth = BIO_meth_new(BIO_TYPE_FD, "nghttpx-bio");
290 BIO_meth_set_write(meth, shrpx_bio_write);
291 BIO_meth_set_read(meth, shrpx_bio_read);
292 BIO_meth_set_puts(meth, shrpx_bio_puts);
293 BIO_meth_set_gets(meth, shrpx_bio_gets);
294 BIO_meth_set_ctrl(meth, shrpx_bio_ctrl);
295 BIO_meth_set_create(meth, shrpx_bio_create);
296 BIO_meth_set_destroy(meth, shrpx_bio_destroy);
297
298 return meth;
299 }
300 #endif // NGHTTP2_GENUINE_OPENSSL || NGHTTP2_OPENSSL_IS_BORINGSSL ||
301 // NGHTTP2_OPENSSL_IS_LIBRESSL
302
set_ssl(SSL * ssl)303 void Connection::set_ssl(SSL *ssl) {
304 tls.ssl = ssl;
305
306 SSL_set_app_data(tls.ssl, this);
307 }
308
309 namespace {
310 // We should buffer at least full encrypted TLS record here.
311 // Theoretically, peer can send client hello in several TLS records,
312 // which could exceed this limit, but it is not portable, and we don't
313 // have to handle such exotic behaviour.
read_buffer_full(DefaultPeekMemchunks & rbuf)314 bool read_buffer_full(DefaultPeekMemchunks &rbuf) {
315 return rbuf.rleft_buffered() >= 20_k;
316 }
317 } // namespace
318
tls_handshake()319 int Connection::tls_handshake() {
320 wlimit.stopw();
321 ev_timer_stop(loop, &wt);
322
323 #ifdef NGHTTP2_OPENSSL_IS_WOLFSSL
324 return tls_handshake_simple();
325 #else // !NGHTTP2_OPENSSL_IS_WOLFSSL
326 auto &tlsconf = get_config()->tls;
327
328 if (!tls.server_handshake || tlsconf.session_cache.memcached.host.empty()) {
329 return tls_handshake_simple();
330 }
331
332 std::array<uint8_t, 16_k> buf;
333
334 if (ev_is_active(&rev)) {
335 auto nread = read_clear(buf.data(), buf.size());
336 if (nread < 0) {
337 if (LOG_ENABLED(INFO)) {
338 LOG(INFO) << "tls: handshake read error";
339 }
340 return -1;
341 }
342 tls.rbuf.append(buf.data(), nread);
343 if (read_buffer_full(tls.rbuf)) {
344 rlimit.stopw();
345 }
346 }
347
348 if (tls.initial_handshake_done) {
349 return write_tls_pending_handshake();
350 }
351
352 switch (tls.handshake_state) {
353 case TLSHandshakeState::WAIT_FOR_SESSION_CACHE:
354 return SHRPX_ERR_INPROGRESS;
355 case TLSHandshakeState::GOT_SESSION_CACHE: {
356 // Use the same trick invented by @kazuho in h2o project.
357
358 // Discard all outgoing data.
359 tls.wbuf.reset();
360 // Rewind buffered incoming data to replay client hello.
361 tls.rbuf.disable_peek(false);
362
363 auto ssl_ctx = SSL_get_SSL_CTX(tls.ssl);
364 auto ssl_opts = SSL_get_options(tls.ssl);
365 SSL_free(tls.ssl);
366
367 auto ssl = tls::create_ssl(ssl_ctx);
368 if (!ssl) {
369 return -1;
370 }
371 if (ssl_opts & SSL_OP_NO_TICKET) {
372 SSL_set_options(ssl, SSL_OP_NO_TICKET);
373 }
374
375 set_ssl(ssl);
376
377 prepare_server_handshake();
378
379 tls.handshake_state = TLSHandshakeState::NORMAL;
380 break;
381 }
382 case TLSHandshakeState::CANCEL_SESSION_CACHE:
383 tls.handshake_state = TLSHandshakeState::NORMAL;
384 break;
385 default:
386 break;
387 }
388
389 int rv;
390
391 ERR_clear_error();
392
393 # ifdef NGHTTP2_GENUINE_OPENSSL
394 if (!tls.server_handshake || tls.early_data_finish) {
395 rv = SSL_do_handshake(tls.ssl);
396 } else {
397 for (;;) {
398 size_t nread;
399
400 rv = SSL_read_early_data(tls.ssl, buf.data(), buf.size(), &nread);
401 if (rv == SSL_READ_EARLY_DATA_ERROR) {
402 // If we have early data, and server sends ServerHello, assume
403 // that handshake is completed in server side, and start
404 // processing request. If we don't exit handshake code here,
405 // server waits for EndOfEarlyData and Finished message from
406 // client, which voids the purpose of 0-RTT data. The left
407 // over of handshake is done through write_tls or read_tls.
408 if (tlsconf.no_postpone_early_data &&
409 (tls.handshake_state == TLSHandshakeState::WRITE_STARTED ||
410 tls.wbuf.rleft()) &&
411 tls.earlybuf.rleft()) {
412 rv = 1;
413 }
414
415 break;
416 }
417
418 if (LOG_ENABLED(INFO)) {
419 LOG(INFO) << "tls: read early data " << nread << " bytes";
420 }
421
422 tls.earlybuf.append(buf.data(), nread);
423
424 if (rv == SSL_READ_EARLY_DATA_FINISH) {
425 if (LOG_ENABLED(INFO)) {
426 LOG(INFO) << "tls: read all early data; total "
427 << tls.earlybuf.rleft() << " bytes";
428 }
429 tls.early_data_finish = true;
430 // The same reason stated above.
431 if (tlsconf.no_postpone_early_data &&
432 (tls.handshake_state == TLSHandshakeState::WRITE_STARTED ||
433 tls.wbuf.rleft()) &&
434 tls.earlybuf.rleft()) {
435 rv = 1;
436 } else {
437 ERR_clear_error();
438 rv = SSL_do_handshake(tls.ssl);
439 }
440 break;
441 }
442 }
443 }
444 # else // !NGHTTP2_GENUINE_OPENSSL
445 rv = SSL_do_handshake(tls.ssl);
446 # endif // !NGHTTP2_GENUINE_OPENSSL
447
448 if (rv <= 0) {
449 auto err = SSL_get_error(tls.ssl, rv);
450 switch (err) {
451 case SSL_ERROR_WANT_READ:
452 if (read_buffer_full(tls.rbuf)) {
453 if (LOG_ENABLED(INFO)) {
454 LOG(INFO) << "tls: handshake message is too large";
455 }
456 return -1;
457 }
458 break;
459 case SSL_ERROR_WANT_WRITE:
460 break;
461 case SSL_ERROR_SSL: {
462 if (LOG_ENABLED(INFO)) {
463 LOG(INFO) << "tls: handshake libssl error: "
464 << ERR_error_string(ERR_get_error(), nullptr);
465 }
466
467 struct iovec iov[1];
468 auto iovcnt = tls.wbuf.riovec(iov, 1);
469 auto nwrite = writev_clear(iov, iovcnt);
470 if (nwrite > 0) {
471 tls.wbuf.drain(nwrite);
472 }
473
474 return SHRPX_ERR_NETWORK;
475 }
476 default:
477 if (LOG_ENABLED(INFO)) {
478 LOG(INFO) << "tls: handshake libssl error " << err;
479 }
480 return SHRPX_ERR_NETWORK;
481 }
482 }
483
484 if (tls.handshake_state == TLSHandshakeState::WAIT_FOR_SESSION_CACHE) {
485 if (LOG_ENABLED(INFO)) {
486 LOG(INFO) << "tls: handshake is still in progress";
487 }
488 return SHRPX_ERR_INPROGRESS;
489 }
490
491 // Don't send handshake data if handshake was completed in OpenSSL
492 // routine. We have to check HTTP/2 requirement if HTTP/2 was
493 // negotiated before sending finished message to the peer.
494 if ((rv != 1
495 # ifdef NGHTTP2_OPENSSL_IS_BORINGSSL
496 || SSL_in_init(tls.ssl)
497 # endif // NGHTTP2_OPENSSL_IS_BORINGSSL
498 ) &&
499 tls.wbuf.rleft()) {
500 // First write indicates that resumption stuff has done.
501 if (tls.handshake_state != TLSHandshakeState::WRITE_STARTED) {
502 tls.handshake_state = TLSHandshakeState::WRITE_STARTED;
503 // If peek has already disabled, this is noop.
504 tls.rbuf.disable_peek(true);
505 }
506 std::array<struct iovec, 4> iov;
507 auto iovcnt = tls.wbuf.riovec(iov.data(), iov.size());
508 auto nwrite = writev_clear(iov.data(), iovcnt);
509 if (nwrite < 0) {
510 if (LOG_ENABLED(INFO)) {
511 LOG(INFO) << "tls: handshake write error";
512 }
513 return -1;
514 }
515 tls.wbuf.drain(nwrite);
516
517 if (tls.wbuf.rleft()) {
518 wlimit.startw();
519 ev_timer_again(loop, &wt);
520 }
521 }
522
523 if (!read_buffer_full(tls.rbuf)) {
524 // We may have stopped reading
525 rlimit.startw();
526 }
527
528 if (rv != 1) {
529 if (LOG_ENABLED(INFO)) {
530 LOG(INFO) << "tls: handshake is still in progress";
531 }
532 return SHRPX_ERR_INPROGRESS;
533 }
534
535 # ifdef NGHTTP2_OPENSSL_IS_BORINGSSL
536 if (!tlsconf.no_postpone_early_data && SSL_in_early_data(tls.ssl) &&
537 SSL_in_init(tls.ssl)) {
538 auto nread = SSL_read(tls.ssl, buf.data(), buf.size());
539 if (nread <= 0) {
540 auto err = SSL_get_error(tls.ssl, nread);
541 switch (err) {
542 case SSL_ERROR_WANT_READ:
543 case SSL_ERROR_WANT_WRITE:
544 break;
545 case SSL_ERROR_ZERO_RETURN:
546 return SHRPX_ERR_EOF;
547 case SSL_ERROR_SSL:
548 if (LOG_ENABLED(INFO)) {
549 LOG(INFO) << "SSL_read: "
550 << ERR_error_string(ERR_get_error(), nullptr);
551 }
552 return SHRPX_ERR_NETWORK;
553 default:
554 if (LOG_ENABLED(INFO)) {
555 LOG(INFO) << "SSL_read: SSL_get_error returned " << err;
556 }
557 return SHRPX_ERR_NETWORK;
558 }
559 } else {
560 tls.earlybuf.append(buf.data(), nread);
561 }
562
563 if (SSL_in_init(tls.ssl)) {
564 return SHRPX_ERR_INPROGRESS;
565 }
566 }
567 # endif // NGHTTP2_OPENSSL_IS_BORINGSSL
568
569 // Handshake was done
570
571 rv = check_http2_requirement();
572 if (rv != 0) {
573 return -1;
574 }
575
576 // Just in case
577 tls.rbuf.disable_peek(true);
578
579 tls.initial_handshake_done = true;
580
581 return write_tls_pending_handshake();
582 #endif // !NGHTTP2_OPENSSL_IS_WOLFSSL
583 }
584
tls_handshake_simple()585 int Connection::tls_handshake_simple() {
586 wlimit.stopw();
587 ev_timer_stop(loop, &wt);
588
589 if (tls.initial_handshake_done) {
590 return write_tls_pending_handshake();
591 }
592
593 if (SSL_get_fd(tls.ssl) == -1) {
594 SSL_set_fd(tls.ssl, fd);
595 }
596
597 int rv;
598 #if defined(NGHTTP2_GENUINE_OPENSSL) || \
599 defined(NGHTTP2_OPENSSL_IS_BORINGSSL) || \
600 (defined(NGHTTP2_OPENSSL_IS_WOLFSSL) && defined(WOLFSSL_EARLY_DATA))
601 auto &tlsconf = get_config()->tls;
602 std::array<uint8_t, 16_k> buf;
603 #endif // NGHTTP2_GENUINE_OPENSSL || NGHTTP2_OPENSSL_IS_BORINGSSL ||
604 // (NGHTTP2_OPENSSL_IS_WOLFSSL && WOLFSSL_EARLY_DATA)
605
606 ERR_clear_error();
607
608 #ifdef NGHTTP2_GENUINE_OPENSSL
609 if (!tls.server_handshake || tls.early_data_finish) {
610 rv = SSL_do_handshake(tls.ssl);
611 } else {
612 for (;;) {
613 size_t nread;
614
615 rv = SSL_read_early_data(tls.ssl, buf.data(), buf.size(), &nread);
616 if (rv == SSL_READ_EARLY_DATA_ERROR) {
617 // If we have early data, and server sends ServerHello, assume
618 // that handshake is completed in server side, and start
619 // processing request. If we don't exit handshake code here,
620 // server waits for EndOfEarlyData and Finished message from
621 // client, which voids the purpose of 0-RTT data. The left
622 // over of handshake is done through write_tls or read_tls.
623 if (tlsconf.no_postpone_early_data && tls.earlybuf.rleft()) {
624 rv = 1;
625 }
626
627 break;
628 }
629
630 if (LOG_ENABLED(INFO)) {
631 LOG(INFO) << "tls: read early data " << nread << " bytes";
632 }
633
634 tls.earlybuf.append(buf.data(), nread);
635
636 if (rv == SSL_READ_EARLY_DATA_FINISH) {
637 if (LOG_ENABLED(INFO)) {
638 LOG(INFO) << "tls: read all early data; total "
639 << tls.earlybuf.rleft() << " bytes";
640 }
641 tls.early_data_finish = true;
642 // The same reason stated above.
643 if (tlsconf.no_postpone_early_data && tls.earlybuf.rleft()) {
644 rv = 1;
645 } else {
646 ERR_clear_error();
647 rv = SSL_do_handshake(tls.ssl);
648 }
649 break;
650 }
651 }
652 }
653 #elif defined(NGHTTP2_OPENSSL_IS_WOLFSSL) && defined(WOLFSSL_EARLY_DATA)
654 if (!tls.server_handshake || tls.early_data_finish) {
655 rv = SSL_do_handshake(tls.ssl);
656 } else {
657 for (;;) {
658 size_t nread = 0;
659
660 rv = SSL_read_early_data(tls.ssl, buf.data(), buf.size(), &nread);
661 if (rv < 0) {
662 if (SSL_get_error(tls.ssl, rv) == SSL_ERROR_WANT_READ) {
663 if (tlsconf.no_postpone_early_data && tls.earlybuf.rleft()) {
664 rv = 1;
665 }
666
667 break;
668 }
669
670 /* It looks like we are here if there is no early data. */
671 tls.early_data_finish = true;
672
673 ERR_clear_error();
674 rv = SSL_do_handshake(tls.ssl);
675
676 break;
677 }
678
679 if (LOG_ENABLED(INFO)) {
680 LOG(INFO) << "tls: read early data " << nread << " bytes";
681 }
682
683 tls.earlybuf.append(buf.data(), nread);
684
685 if (rv == 0) {
686 if (LOG_ENABLED(INFO)) {
687 LOG(INFO) << "tls: read all early data; total "
688 << tls.earlybuf.rleft() << " bytes";
689 }
690 tls.early_data_finish = true;
691 // The same reason stated above.
692 if (tlsconf.no_postpone_early_data && tls.earlybuf.rleft()) {
693 rv = 1;
694 } else {
695 ERR_clear_error();
696 rv = SSL_do_handshake(tls.ssl);
697 }
698 break;
699 }
700 }
701 }
702 #else // !NGHTTP2_GENUINE_OPENSSL && !(NGHTTP2_OPENSSL_IS_WOLFSSL &&
703 // WOLFSSL_EARLY_DATA)
704 rv = SSL_do_handshake(tls.ssl);
705 #endif // !NGHTTP2_GENUINE_OPENSSL && !(NGHTTP2_OPENSSL_IS_WOLFSSL &&
706 // WOLFSSL_EARLY_DATA)
707
708 if (rv <= 0) {
709 auto err = SSL_get_error(tls.ssl, rv);
710 switch (err) {
711 case SSL_ERROR_WANT_READ:
712 if (read_buffer_full(tls.rbuf)) {
713 if (LOG_ENABLED(INFO)) {
714 LOG(INFO) << "tls: handshake message is too large";
715 }
716 return -1;
717 }
718 break;
719 case SSL_ERROR_WANT_WRITE:
720 wlimit.startw();
721 ev_timer_again(loop, &wt);
722 break;
723 case SSL_ERROR_SSL: {
724 if (LOG_ENABLED(INFO)) {
725 LOG(INFO) << "tls: handshake libssl error: "
726 << ERR_error_string(ERR_get_error(), nullptr);
727 }
728 return SHRPX_ERR_NETWORK;
729 }
730 default:
731 if (LOG_ENABLED(INFO)) {
732 LOG(INFO) << "tls: handshake libssl error " << err;
733 }
734 return SHRPX_ERR_NETWORK;
735 }
736 }
737
738 if (rv != 1) {
739 if (LOG_ENABLED(INFO)) {
740 LOG(INFO) << "tls: handshake is still in progress";
741 }
742 return SHRPX_ERR_INPROGRESS;
743 }
744
745 #ifdef NGHTTP2_OPENSSL_IS_BORINGSSL
746 if (!tlsconf.no_postpone_early_data && SSL_in_early_data(tls.ssl) &&
747 SSL_in_init(tls.ssl)) {
748 auto nread = SSL_read(tls.ssl, buf.data(), buf.size());
749 if (nread <= 0) {
750 auto err = SSL_get_error(tls.ssl, nread);
751 switch (err) {
752 case SSL_ERROR_WANT_READ:
753 case SSL_ERROR_WANT_WRITE:
754 break;
755 case SSL_ERROR_ZERO_RETURN:
756 return SHRPX_ERR_EOF;
757 case SSL_ERROR_SSL:
758 if (LOG_ENABLED(INFO)) {
759 LOG(INFO) << "SSL_read: "
760 << ERR_error_string(ERR_get_error(), nullptr);
761 }
762 return SHRPX_ERR_NETWORK;
763 default:
764 if (LOG_ENABLED(INFO)) {
765 LOG(INFO) << "SSL_read: SSL_get_error returned " << err;
766 }
767 return SHRPX_ERR_NETWORK;
768 }
769 } else {
770 tls.earlybuf.append(buf.data(), nread);
771 }
772
773 if (SSL_in_init(tls.ssl)) {
774 return SHRPX_ERR_INPROGRESS;
775 }
776 }
777 #endif // NGHTTP2_OPENSSL_IS_BORINGSSL
778
779 // Handshake was done
780
781 rv = check_http2_requirement();
782 if (rv != 0) {
783 return -1;
784 }
785
786 tls.initial_handshake_done = true;
787
788 return write_tls_pending_handshake();
789 }
790
write_tls_pending_handshake()791 int Connection::write_tls_pending_handshake() {
792 // Send handshake data left in the buffer
793 while (tls.wbuf.rleft()) {
794 std::array<struct iovec, 4> iov;
795 auto iovcnt = tls.wbuf.riovec(iov.data(), iov.size());
796 auto nwrite = writev_clear(iov.data(), iovcnt);
797 if (nwrite < 0) {
798 if (LOG_ENABLED(INFO)) {
799 LOG(INFO) << "tls: handshake write error";
800 }
801 return -1;
802 }
803 if (nwrite == 0) {
804 wlimit.startw();
805 ev_timer_again(loop, &wt);
806
807 return SHRPX_ERR_INPROGRESS;
808 }
809 tls.wbuf.drain(nwrite);
810 }
811
812 #ifdef NGHTTP2_OPENSSL_IS_BORINGSSL
813 if (!SSL_in_init(tls.ssl)) {
814 // This will send a session ticket.
815 auto nwrite = SSL_write(tls.ssl, "", 0);
816 if (nwrite < 0) {
817 auto err = SSL_get_error(tls.ssl, nwrite);
818 switch (err) {
819 case SSL_ERROR_WANT_READ:
820 if (LOG_ENABLED(INFO)) {
821 LOG(INFO) << "Close connection due to TLS renegotiation";
822 }
823 return SHRPX_ERR_NETWORK;
824 case SSL_ERROR_WANT_WRITE:
825 break;
826 case SSL_ERROR_SSL:
827 if (LOG_ENABLED(INFO)) {
828 LOG(INFO) << "SSL_write: "
829 << ERR_error_string(ERR_get_error(), nullptr);
830 }
831 return SHRPX_ERR_NETWORK;
832 default:
833 if (LOG_ENABLED(INFO)) {
834 LOG(INFO) << "SSL_write: SSL_get_error returned " << err;
835 }
836 return SHRPX_ERR_NETWORK;
837 }
838 }
839 }
840 #endif // NGHTTP2_OPENSSL_IS_BORINGSSL
841
842 // We have to start read watcher, since later stage of code expects
843 // this.
844 rlimit.startw();
845
846 // We may have whole request in tls.rbuf. This means that we don't
847 // get notified further read event. This is especially true for
848 // HTTP/1.1.
849 handle_tls_pending_read();
850
851 if (LOG_ENABLED(INFO)) {
852 LOG(INFO) << "SSL/TLS handshake completed";
853 nghttp2::tls::TLSSessionInfo tls_info{};
854 if (nghttp2::tls::get_tls_session_info(&tls_info, tls.ssl)) {
855 LOG(INFO) << "cipher=" << tls_info.cipher
856 << " protocol=" << tls_info.protocol
857 << " resumption=" << (tls_info.session_reused ? "yes" : "no")
858 << " session_id="
859 << util::format_hex(std::span{tls_info.session_id,
860 tls_info.session_id_length});
861 }
862 }
863
864 return 0;
865 }
866
check_http2_requirement()867 int Connection::check_http2_requirement() {
868 const unsigned char *next_proto = nullptr;
869 unsigned int next_proto_len;
870
871 SSL_get0_alpn_selected(tls.ssl, &next_proto, &next_proto_len);
872 if (next_proto == nullptr ||
873 !util::check_h2_is_selected(StringRef{next_proto, next_proto_len})) {
874 return 0;
875 }
876 if (!nghttp2::tls::check_http2_tls_version(tls.ssl)) {
877 if (LOG_ENABLED(INFO)) {
878 LOG(INFO) << "TLSv1.2 was not negotiated. HTTP/2 must not be used.";
879 }
880 return -1;
881 }
882
883 auto check_block_list = false;
884 if (tls.server_handshake) {
885 check_block_list = !get_config()->tls.no_http2_cipher_block_list;
886 } else {
887 check_block_list = !get_config()->tls.client.no_http2_cipher_block_list;
888 }
889
890 if (check_block_list &&
891 nghttp2::tls::check_http2_cipher_block_list(tls.ssl)) {
892 if (LOG_ENABLED(INFO)) {
893 LOG(INFO) << "The negotiated cipher suite is in HTTP/2 cipher suite "
894 "block list. HTTP/2 must not be used.";
895 }
896 return -1;
897 }
898
899 return 0;
900 }
901
902 namespace {
903 constexpr size_t SHRPX_SMALL_WRITE_LIMIT = 1300;
904 } // namespace
905
get_tls_write_limit()906 size_t Connection::get_tls_write_limit() {
907 if (tls_dyn_rec_warmup_threshold == 0) {
908 return std::numeric_limits<ssize_t>::max();
909 }
910
911 auto t = std::chrono::steady_clock::now();
912
913 if (tls.last_write_idle.time_since_epoch().count() >= 0 &&
914 t - tls.last_write_idle > tls_dyn_rec_idle_timeout) {
915 // Time out, use small record size
916 tls.warmup_writelen = 0;
917 return SHRPX_SMALL_WRITE_LIMIT;
918 }
919
920 if (tls.warmup_writelen >= tls_dyn_rec_warmup_threshold) {
921 return std::numeric_limits<ssize_t>::max();
922 }
923
924 return SHRPX_SMALL_WRITE_LIMIT;
925 }
926
update_tls_warmup_writelen(size_t n)927 void Connection::update_tls_warmup_writelen(size_t n) {
928 if (tls.warmup_writelen < tls_dyn_rec_warmup_threshold) {
929 tls.warmup_writelen += n;
930 }
931 }
932
start_tls_write_idle()933 void Connection::start_tls_write_idle() {
934 if (tls.last_write_idle.time_since_epoch().count() < 0) {
935 tls.last_write_idle = std::chrono::steady_clock::now();
936 }
937 }
938
write_tls(const void * data,size_t len)939 nghttp2_ssize Connection::write_tls(const void *data, size_t len) {
940 // SSL_write requires the same arguments (buf pointer and its
941 // length) on SSL_ERROR_WANT_READ or SSL_ERROR_WANT_WRITE.
942 // get_write_limit() may return smaller length than previously
943 // passed to SSL_write, which violates OpenSSL assumption. To avoid
944 // this, we keep last length passed to SSL_write to
945 // tls.last_writelen if SSL_write indicated I/O blocking.
946 if (tls.last_writelen == 0) {
947 len = std::min(len, wlimit.avail());
948 len = std::min(len, get_tls_write_limit());
949 if (len == 0) {
950 return 0;
951 }
952 } else {
953 len = tls.last_writelen;
954 tls.last_writelen = 0;
955 }
956
957 tls.last_write_idle = std::chrono::steady_clock::time_point(-1s);
958
959 auto &tlsconf = get_config()->tls;
960 auto via_bio =
961 tls.server_handshake && !tlsconf.session_cache.memcached.host.empty();
962
963 ERR_clear_error();
964
965 #ifdef NGHTTP2_GENUINE_OPENSSL
966 int rv;
967 if (SSL_is_init_finished(tls.ssl)) {
968 rv = SSL_write(tls.ssl, data, len);
969 } else {
970 size_t nwrite;
971 rv = SSL_write_early_data(tls.ssl, data, len, &nwrite);
972 // Use the same semantics with SSL_write.
973 if (rv == 1) {
974 rv = nwrite;
975 }
976 }
977 #else // !NGHTTP2_GENUINE_OPENSSL
978 auto rv = SSL_write(tls.ssl, data, len);
979 #endif // !NGHTTP2_GENUINE_OPENSSL
980
981 if (rv <= 0) {
982 auto err = SSL_get_error(tls.ssl, rv);
983 switch (err) {
984 case SSL_ERROR_WANT_READ:
985 if (LOG_ENABLED(INFO)) {
986 LOG(INFO) << "Close connection due to TLS renegotiation";
987 }
988 return SHRPX_ERR_NETWORK;
989 case SSL_ERROR_WANT_WRITE:
990 tls.last_writelen = len;
991 // starting write watcher and timer is done in write_clear via
992 // bio otherwise.
993 if (!via_bio) {
994 wlimit.startw();
995 ev_timer_again(loop, &wt);
996 }
997
998 return 0;
999 case SSL_ERROR_SSL:
1000 if (LOG_ENABLED(INFO)) {
1001 LOG(INFO) << "SSL_write: "
1002 << ERR_error_string(ERR_get_error(), nullptr);
1003 }
1004 return SHRPX_ERR_NETWORK;
1005 default:
1006 if (LOG_ENABLED(INFO)) {
1007 LOG(INFO) << "SSL_write: SSL_get_error returned " << err;
1008 }
1009 return SHRPX_ERR_NETWORK;
1010 }
1011 }
1012
1013 if (!via_bio) {
1014 wlimit.drain(rv);
1015
1016 if (ev_is_active(&wt)) {
1017 ev_timer_again(loop, &wt);
1018 }
1019 }
1020
1021 update_tls_warmup_writelen(rv);
1022
1023 return rv;
1024 }
1025
read_tls(void * data,size_t len)1026 nghttp2_ssize Connection::read_tls(void *data, size_t len) {
1027 ERR_clear_error();
1028
1029 #if defined(NGHTTP2_GENUINE_OPENSSL) || \
1030 defined(NGHTTP2_OPENSSL_IS_BORINGSSL) || defined(NGHTTP2_OPENSSL_IS_WOLFSSL)
1031 if (tls.earlybuf.rleft()) {
1032 return tls.earlybuf.remove(data, len);
1033 }
1034 #endif // NGHTTP2_GENUINE_OPENSSL || NGHTTP2_OPENSSL_IS_BORINGSSL ||
1035 // defined(NGHTTP2_OPENSSL_IS_WOLFSSL)
1036
1037 // SSL_read requires the same arguments (buf pointer and its
1038 // length) on SSL_ERROR_WANT_READ or SSL_ERROR_WANT_WRITE.
1039 // rlimit_.avail() or rlimit_.avail() may return different length
1040 // than the length previously passed to SSL_read, which violates
1041 // OpenSSL assumption. To avoid this, we keep last length passed
1042 // to SSL_read to tls_last_readlen_ if SSL_read indicated I/O
1043 // blocking.
1044 if (tls.last_readlen == 0) {
1045 len = std::min(len, rlimit.avail());
1046 if (len == 0) {
1047 return 0;
1048 }
1049 } else {
1050 len = tls.last_readlen;
1051 tls.last_readlen = 0;
1052 }
1053
1054 auto &tlsconf = get_config()->tls;
1055 auto via_bio =
1056 tls.server_handshake && !tlsconf.session_cache.memcached.host.empty();
1057
1058 #ifdef NGHTTP2_GENUINE_OPENSSL
1059 if (!tls.early_data_finish) {
1060 // TLSv1.3 handshake is still going on.
1061 size_t nread;
1062 auto rv = SSL_read_early_data(tls.ssl, data, len, &nread);
1063 if (rv == SSL_READ_EARLY_DATA_ERROR) {
1064 auto err = SSL_get_error(tls.ssl, rv);
1065 switch (err) {
1066 case SSL_ERROR_WANT_READ:
1067 tls.last_readlen = len;
1068 return 0;
1069 case SSL_ERROR_SSL:
1070 if (LOG_ENABLED(INFO)) {
1071 LOG(INFO) << "SSL_read: "
1072 << ERR_error_string(ERR_get_error(), nullptr);
1073 }
1074 return SHRPX_ERR_NETWORK;
1075 default:
1076 if (LOG_ENABLED(INFO)) {
1077 LOG(INFO) << "SSL_read: SSL_get_error returned " << err;
1078 }
1079 return SHRPX_ERR_NETWORK;
1080 }
1081 }
1082
1083 if (LOG_ENABLED(INFO)) {
1084 LOG(INFO) << "tls: read early data " << nread << " bytes";
1085 }
1086
1087 if (rv == SSL_READ_EARLY_DATA_FINISH) {
1088 if (LOG_ENABLED(INFO)) {
1089 LOG(INFO) << "tls: read all early data";
1090 }
1091 tls.early_data_finish = true;
1092 // We may have stopped write watcher in write_tls.
1093 wlimit.startw();
1094 }
1095
1096 if (!via_bio) {
1097 rlimit.drain(nread);
1098 }
1099
1100 return nread;
1101 }
1102 #endif // NGHTTP2_GENUINE_OPENSSL
1103
1104 #if defined(NGHTTP2_OPENSSL_IS_WOLFSSL) && defined(WOLFSSL_EARLY_DATA)
1105 if (!tls.early_data_finish) {
1106 // TLSv1.3 handshake is still going on.
1107 size_t nread = 0;
1108 auto rv = SSL_read_early_data(tls.ssl, data, len, &nread);
1109 if (rv < 0) {
1110 auto err = SSL_get_error(tls.ssl, rv);
1111 switch (err) {
1112 case SSL_ERROR_WANT_READ:
1113 tls.last_readlen = len;
1114 return 0;
1115 case SSL_ERROR_SSL:
1116 if (LOG_ENABLED(INFO)) {
1117 LOG(INFO) << "SSL_read: "
1118 << ERR_error_string(ERR_get_error(), nullptr);
1119 }
1120 return SHRPX_ERR_NETWORK;
1121 default:
1122 if (LOG_ENABLED(INFO)) {
1123 LOG(INFO) << "SSL_read: SSL_get_error returned " << err;
1124 }
1125 return SHRPX_ERR_NETWORK;
1126 }
1127 }
1128
1129 if (LOG_ENABLED(INFO)) {
1130 LOG(INFO) << "tls: read early data " << nread << " bytes";
1131 }
1132
1133 if (rv == 0) {
1134 if (LOG_ENABLED(INFO)) {
1135 LOG(INFO) << "tls: read all early data";
1136 }
1137 tls.early_data_finish = true;
1138 // We may have stopped write watcher in write_tls.
1139 wlimit.startw();
1140 }
1141
1142 if (!via_bio) {
1143 rlimit.drain(nread);
1144 }
1145
1146 return nread;
1147 }
1148 #endif // NGHTTP2_OPENSSL_IS_WOLFSSL && WOLFSSL_EARLY_DATA
1149
1150 auto rv = SSL_read(tls.ssl, data, len);
1151
1152 if (rv <= 0) {
1153 auto err = SSL_get_error(tls.ssl, rv);
1154 switch (err) {
1155 case SSL_ERROR_WANT_READ:
1156 tls.last_readlen = len;
1157 return 0;
1158 case SSL_ERROR_WANT_WRITE:
1159 if (LOG_ENABLED(INFO)) {
1160 LOG(INFO) << "Close connection due to TLS renegotiation";
1161 }
1162 return SHRPX_ERR_NETWORK;
1163 case SSL_ERROR_ZERO_RETURN:
1164 return SHRPX_ERR_EOF;
1165 case SSL_ERROR_SSL:
1166 if (LOG_ENABLED(INFO)) {
1167 LOG(INFO) << "SSL_read: " << ERR_error_string(ERR_get_error(), nullptr);
1168 }
1169 return SHRPX_ERR_NETWORK;
1170 default:
1171 if (LOG_ENABLED(INFO)) {
1172 LOG(INFO) << "SSL_read: SSL_get_error returned " << err;
1173 }
1174 return SHRPX_ERR_NETWORK;
1175 }
1176 }
1177
1178 if (!via_bio) {
1179 rlimit.drain(rv);
1180 }
1181
1182 return rv;
1183 }
1184
write_clear(const void * data,size_t len)1185 nghttp2_ssize Connection::write_clear(const void *data, size_t len) {
1186 len = std::min(len, wlimit.avail());
1187 if (len == 0) {
1188 return 0;
1189 }
1190
1191 ssize_t nwrite;
1192 while ((nwrite = write(fd, data, len)) == -1 && errno == EINTR)
1193 ;
1194 if (nwrite == -1) {
1195 if (errno == EAGAIN || errno == EWOULDBLOCK) {
1196 wlimit.startw();
1197 ev_timer_again(loop, &wt);
1198 return 0;
1199 }
1200 return SHRPX_ERR_NETWORK;
1201 }
1202
1203 wlimit.drain(nwrite);
1204
1205 if (ev_is_active(&wt)) {
1206 ev_timer_again(loop, &wt);
1207 }
1208
1209 return nwrite;
1210 }
1211
writev_clear(struct iovec * iov,int iovcnt)1212 nghttp2_ssize Connection::writev_clear(struct iovec *iov, int iovcnt) {
1213 iovcnt = limit_iovec(iov, iovcnt, wlimit.avail());
1214 if (iovcnt == 0) {
1215 return 0;
1216 }
1217
1218 ssize_t nwrite;
1219 while ((nwrite = writev(fd, iov, iovcnt)) == -1 && errno == EINTR)
1220 ;
1221 if (nwrite == -1) {
1222 if (errno == EAGAIN || errno == EWOULDBLOCK) {
1223 wlimit.startw();
1224 ev_timer_again(loop, &wt);
1225 return 0;
1226 }
1227 return SHRPX_ERR_NETWORK;
1228 }
1229
1230 wlimit.drain(nwrite);
1231
1232 if (ev_is_active(&wt)) {
1233 ev_timer_again(loop, &wt);
1234 }
1235
1236 return nwrite;
1237 }
1238
read_clear(void * data,size_t len)1239 nghttp2_ssize Connection::read_clear(void *data, size_t len) {
1240 len = std::min(len, rlimit.avail());
1241 if (len == 0) {
1242 return 0;
1243 }
1244
1245 ssize_t nread;
1246 while ((nread = read(fd, data, len)) == -1 && errno == EINTR)
1247 ;
1248 if (nread == -1) {
1249 if (errno == EAGAIN || errno == EWOULDBLOCK) {
1250 return 0;
1251 }
1252 return SHRPX_ERR_NETWORK;
1253 }
1254
1255 if (nread == 0) {
1256 return SHRPX_ERR_EOF;
1257 }
1258
1259 rlimit.drain(nread);
1260
1261 return nread;
1262 }
1263
read_nolim_clear(void * data,size_t len)1264 nghttp2_ssize Connection::read_nolim_clear(void *data, size_t len) {
1265 ssize_t nread;
1266 while ((nread = read(fd, data, len)) == -1 && errno == EINTR)
1267 ;
1268 if (nread == -1) {
1269 if (errno == EAGAIN || errno == EWOULDBLOCK) {
1270 return 0;
1271 }
1272 return SHRPX_ERR_NETWORK;
1273 }
1274
1275 if (nread == 0) {
1276 return SHRPX_ERR_EOF;
1277 }
1278
1279 return nread;
1280 }
1281
peek_clear(void * data,size_t len)1282 nghttp2_ssize Connection::peek_clear(void *data, size_t len) {
1283 ssize_t nread;
1284 while ((nread = recv(fd, data, len, MSG_PEEK)) == -1 && errno == EINTR)
1285 ;
1286 if (nread == -1) {
1287 if (errno == EAGAIN || errno == EWOULDBLOCK) {
1288 return 0;
1289 }
1290 return SHRPX_ERR_NETWORK;
1291 }
1292
1293 if (nread == 0) {
1294 return SHRPX_ERR_EOF;
1295 }
1296
1297 return nread;
1298 }
1299
handle_tls_pending_read()1300 void Connection::handle_tls_pending_read() {
1301 if (!ev_is_active(&rev)) {
1302 return;
1303 }
1304 rlimit.handle_tls_pending_read();
1305 }
1306
get_tcp_hint(TCPHint * hint) const1307 int Connection::get_tcp_hint(TCPHint *hint) const {
1308 #if defined(TCP_INFO) && defined(TCP_NOTSENT_LOWAT)
1309 struct tcp_info tcp_info;
1310 socklen_t tcp_info_len = sizeof(tcp_info);
1311 int rv;
1312
1313 rv = getsockopt(fd, IPPROTO_TCP, TCP_INFO, &tcp_info, &tcp_info_len);
1314
1315 if (rv != 0) {
1316 return -1;
1317 }
1318
1319 auto avail_packets = tcp_info.tcpi_snd_cwnd > tcp_info.tcpi_unacked
1320 ? tcp_info.tcpi_snd_cwnd - tcp_info.tcpi_unacked
1321 : 0;
1322
1323 // http://www.slideshare.net/kazuho/programming-tcp-for-responsiveness
1324
1325 // TODO 29 (5 (header) + 8 (explicit nonce) + 16 (tag)) is TLS
1326 // overhead for AES-GCM. For CHACHA20_POLY1305, it is 21 since it
1327 // does not need 8 bytes explicit nonce.
1328 //
1329 // For TLSv1.3, AES-GCM and CHACHA20_POLY1305 overhead are now 22
1330 // bytes (5 (header) + 1 (ContentType) + 16 (tag)).
1331 size_t tls_overhead;
1332 # ifdef TLS1_3_VERSION
1333 if (SSL_version(tls.ssl) == TLS1_3_VERSION) {
1334 tls_overhead = 22;
1335 } else
1336 # endif // TLS1_3_VERSION
1337 {
1338 tls_overhead = 29;
1339 }
1340
1341 auto writable_size =
1342 (avail_packets + 2) * (tcp_info.tcpi_snd_mss - tls_overhead);
1343 if (writable_size > 16_k) {
1344 writable_size = writable_size & ~(16_k - 1);
1345 } else {
1346 if (writable_size < 536) {
1347 LOG(INFO) << "writable_size is too small: " << writable_size;
1348 }
1349 // TODO is this required?
1350 writable_size = std::max(writable_size, static_cast<size_t>(536 * 2));
1351 }
1352
1353 // if (LOG_ENABLED(INFO)) {
1354 // LOG(INFO) << "snd_cwnd=" << tcp_info.tcpi_snd_cwnd
1355 // << ", unacked=" << tcp_info.tcpi_unacked
1356 // << ", snd_mss=" << tcp_info.tcpi_snd_mss
1357 // << ", rtt=" << tcp_info.tcpi_rtt << "us"
1358 // << ", rcv_space=" << tcp_info.tcpi_rcv_space
1359 // << ", writable=" << writable_size;
1360 // }
1361
1362 hint->write_buffer_size = writable_size;
1363 // TODO tcpi_rcv_space is considered as rwin, is that correct?
1364 hint->rwin = tcp_info.tcpi_rcv_space;
1365
1366 return 0;
1367 #else // !defined(TCP_INFO) || !defined(TCP_NOTSENT_LOWAT)
1368 return -1;
1369 #endif // !defined(TCP_INFO) || !defined(TCP_NOTSENT_LOWAT)
1370 }
1371
again_rt(ev_tstamp t)1372 void Connection::again_rt(ev_tstamp t) {
1373 read_timeout = t;
1374 rt.repeat = t;
1375 ev_timer_again(loop, &rt);
1376 last_read = std::chrono::steady_clock::now();
1377 }
1378
again_rt()1379 void Connection::again_rt() {
1380 rt.repeat = read_timeout;
1381 ev_timer_again(loop, &rt);
1382 last_read = std::chrono::steady_clock::now();
1383 }
1384
expired_rt()1385 bool Connection::expired_rt() {
1386 auto delta = read_timeout - util::ev_tstamp_from(
1387 std::chrono::steady_clock::now() - last_read);
1388 if (delta < 1e-9) {
1389 return true;
1390 }
1391 rt.repeat = delta;
1392 ev_timer_again(loop, &rt);
1393 return false;
1394 }
1395
1396 } // namespace shrpx
1397