12c593315Sopenharmony_ci/* 22c593315Sopenharmony_ci * nghttp2 - HTTP/2 C Library 32c593315Sopenharmony_ci * 42c593315Sopenharmony_ci * Copyright (c) 2015 Tatsuhiro Tsujikawa 52c593315Sopenharmony_ci * 62c593315Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining 72c593315Sopenharmony_ci * a copy of this software and associated documentation files (the 82c593315Sopenharmony_ci * "Software"), to deal in the Software without restriction, including 92c593315Sopenharmony_ci * without limitation the rights to use, copy, modify, merge, publish, 102c593315Sopenharmony_ci * distribute, sublicense, and/or sell copies of the Software, and to 112c593315Sopenharmony_ci * permit persons to whom the Software is furnished to do so, subject to 122c593315Sopenharmony_ci * the following conditions: 132c593315Sopenharmony_ci * 142c593315Sopenharmony_ci * The above copyright notice and this permission notice shall be 152c593315Sopenharmony_ci * included in all copies or substantial portions of the Software. 162c593315Sopenharmony_ci * 172c593315Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 182c593315Sopenharmony_ci * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 192c593315Sopenharmony_ci * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 202c593315Sopenharmony_ci * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 212c593315Sopenharmony_ci * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 222c593315Sopenharmony_ci * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 232c593315Sopenharmony_ci * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 242c593315Sopenharmony_ci */ 252c593315Sopenharmony_ci#include "shrpx_connection.h" 262c593315Sopenharmony_ci 272c593315Sopenharmony_ci#ifdef HAVE_UNISTD_H 282c593315Sopenharmony_ci# include <unistd.h> 292c593315Sopenharmony_ci#endif // HAVE_UNISTD_H 302c593315Sopenharmony_ci#include <netinet/tcp.h> 312c593315Sopenharmony_ci 322c593315Sopenharmony_ci#include <limits> 332c593315Sopenharmony_ci 342c593315Sopenharmony_ci#include <openssl/err.h> 352c593315Sopenharmony_ci 362c593315Sopenharmony_ci#include "shrpx_tls.h" 372c593315Sopenharmony_ci#include "shrpx_memcached_request.h" 382c593315Sopenharmony_ci#include "shrpx_log.h" 392c593315Sopenharmony_ci#include "memchunk.h" 402c593315Sopenharmony_ci#include "util.h" 412c593315Sopenharmony_ci#include "ssl_compat.h" 422c593315Sopenharmony_ci 432c593315Sopenharmony_ciusing namespace nghttp2; 442c593315Sopenharmony_ciusing namespace std::chrono_literals; 452c593315Sopenharmony_ci 462c593315Sopenharmony_cinamespace shrpx { 472c593315Sopenharmony_ci 482c593315Sopenharmony_ci#if !LIBRESSL_3_5_API && !LIBRESSL_2_7_API && !OPENSSL_1_1_API 492c593315Sopenharmony_ci 502c593315Sopenharmony_civoid *BIO_get_data(BIO *bio) { return bio->ptr; } 512c593315Sopenharmony_civoid BIO_set_data(BIO *bio, void *ptr) { bio->ptr = ptr; } 522c593315Sopenharmony_civoid BIO_set_init(BIO *bio, int init) { bio->init = init; } 532c593315Sopenharmony_ci 542c593315Sopenharmony_ci#endif // !LIBRESSL_3_5_API && !LIBRESSL_2_7_API && !OPENSSL_1_1_API 552c593315Sopenharmony_ci 562c593315Sopenharmony_ciConnection::Connection(struct ev_loop *loop, int fd, SSL *ssl, 572c593315Sopenharmony_ci MemchunkPool *mcpool, ev_tstamp write_timeout, 582c593315Sopenharmony_ci ev_tstamp read_timeout, 592c593315Sopenharmony_ci const RateLimitConfig &write_limit, 602c593315Sopenharmony_ci const RateLimitConfig &read_limit, IOCb writecb, 612c593315Sopenharmony_ci IOCb readcb, TimerCb timeoutcb, void *data, 622c593315Sopenharmony_ci size_t tls_dyn_rec_warmup_threshold, 632c593315Sopenharmony_ci ev_tstamp tls_dyn_rec_idle_timeout, Proto proto) 642c593315Sopenharmony_ci : 652c593315Sopenharmony_ci#ifdef ENABLE_HTTP3 662c593315Sopenharmony_ci conn_ref{nullptr, this}, 672c593315Sopenharmony_ci#endif // ENABLE_HTTP3 682c593315Sopenharmony_ci tls{DefaultMemchunks(mcpool), DefaultPeekMemchunks(mcpool), 692c593315Sopenharmony_ci DefaultMemchunks(mcpool)}, 702c593315Sopenharmony_ci wlimit(loop, &wev, write_limit.rate, write_limit.burst), 712c593315Sopenharmony_ci rlimit(loop, &rev, read_limit.rate, read_limit.burst, this), 722c593315Sopenharmony_ci loop(loop), 732c593315Sopenharmony_ci data(data), 742c593315Sopenharmony_ci fd(fd), 752c593315Sopenharmony_ci tls_dyn_rec_warmup_threshold(tls_dyn_rec_warmup_threshold), 762c593315Sopenharmony_ci tls_dyn_rec_idle_timeout(util::duration_from(tls_dyn_rec_idle_timeout)), 772c593315Sopenharmony_ci proto(proto), 782c593315Sopenharmony_ci read_timeout(read_timeout) { 792c593315Sopenharmony_ci 802c593315Sopenharmony_ci ev_io_init(&wev, writecb, fd, EV_WRITE); 812c593315Sopenharmony_ci ev_io_init(&rev, readcb, proto == Proto::HTTP3 ? 0 : fd, EV_READ); 822c593315Sopenharmony_ci 832c593315Sopenharmony_ci wev.data = this; 842c593315Sopenharmony_ci rev.data = this; 852c593315Sopenharmony_ci 862c593315Sopenharmony_ci ev_timer_init(&wt, timeoutcb, 0., write_timeout); 872c593315Sopenharmony_ci ev_timer_init(&rt, timeoutcb, 0., read_timeout); 882c593315Sopenharmony_ci 892c593315Sopenharmony_ci wt.data = this; 902c593315Sopenharmony_ci rt.data = this; 912c593315Sopenharmony_ci 922c593315Sopenharmony_ci if (ssl) { 932c593315Sopenharmony_ci set_ssl(ssl); 942c593315Sopenharmony_ci } 952c593315Sopenharmony_ci} 962c593315Sopenharmony_ci 972c593315Sopenharmony_ciConnection::~Connection() { disconnect(); } 982c593315Sopenharmony_ci 992c593315Sopenharmony_civoid Connection::disconnect() { 1002c593315Sopenharmony_ci if (tls.ssl) { 1012c593315Sopenharmony_ci if (proto != Proto::HTTP3) { 1022c593315Sopenharmony_ci SSL_set_shutdown(tls.ssl, 1032c593315Sopenharmony_ci SSL_get_shutdown(tls.ssl) | SSL_RECEIVED_SHUTDOWN); 1042c593315Sopenharmony_ci ERR_clear_error(); 1052c593315Sopenharmony_ci 1062c593315Sopenharmony_ci if (tls.cached_session) { 1072c593315Sopenharmony_ci SSL_SESSION_free(tls.cached_session); 1082c593315Sopenharmony_ci tls.cached_session = nullptr; 1092c593315Sopenharmony_ci } 1102c593315Sopenharmony_ci 1112c593315Sopenharmony_ci if (tls.cached_session_lookup_req) { 1122c593315Sopenharmony_ci tls.cached_session_lookup_req->canceled = true; 1132c593315Sopenharmony_ci tls.cached_session_lookup_req = nullptr; 1142c593315Sopenharmony_ci } 1152c593315Sopenharmony_ci 1162c593315Sopenharmony_ci SSL_shutdown(tls.ssl); 1172c593315Sopenharmony_ci } 1182c593315Sopenharmony_ci 1192c593315Sopenharmony_ci SSL_free(tls.ssl); 1202c593315Sopenharmony_ci tls.ssl = nullptr; 1212c593315Sopenharmony_ci 1222c593315Sopenharmony_ci tls.wbuf.reset(); 1232c593315Sopenharmony_ci tls.rbuf.reset(); 1242c593315Sopenharmony_ci tls.last_write_idle = {}; 1252c593315Sopenharmony_ci tls.warmup_writelen = 0; 1262c593315Sopenharmony_ci tls.last_writelen = 0; 1272c593315Sopenharmony_ci tls.last_readlen = 0; 1282c593315Sopenharmony_ci tls.handshake_state = TLSHandshakeState::NORMAL; 1292c593315Sopenharmony_ci tls.initial_handshake_done = false; 1302c593315Sopenharmony_ci tls.reneg_started = false; 1312c593315Sopenharmony_ci tls.sct_requested = false; 1322c593315Sopenharmony_ci tls.early_data_finish = false; 1332c593315Sopenharmony_ci } 1342c593315Sopenharmony_ci 1352c593315Sopenharmony_ci if (proto != Proto::HTTP3 && fd != -1) { 1362c593315Sopenharmony_ci shutdown(fd, SHUT_WR); 1372c593315Sopenharmony_ci close(fd); 1382c593315Sopenharmony_ci fd = -1; 1392c593315Sopenharmony_ci } 1402c593315Sopenharmony_ci 1412c593315Sopenharmony_ci // Stop watchers here because they could be activated in 1422c593315Sopenharmony_ci // SSL_shutdown(). 1432c593315Sopenharmony_ci ev_timer_stop(loop, &rt); 1442c593315Sopenharmony_ci ev_timer_stop(loop, &wt); 1452c593315Sopenharmony_ci 1462c593315Sopenharmony_ci rlimit.stopw(); 1472c593315Sopenharmony_ci wlimit.stopw(); 1482c593315Sopenharmony_ci} 1492c593315Sopenharmony_ci 1502c593315Sopenharmony_civoid Connection::prepare_client_handshake() { 1512c593315Sopenharmony_ci SSL_set_connect_state(tls.ssl); 1522c593315Sopenharmony_ci // This prevents SSL_read_early_data from being called. 1532c593315Sopenharmony_ci tls.early_data_finish = true; 1542c593315Sopenharmony_ci} 1552c593315Sopenharmony_ci 1562c593315Sopenharmony_civoid Connection::prepare_server_handshake() { 1572c593315Sopenharmony_ci auto &tlsconf = get_config()->tls; 1582c593315Sopenharmony_ci if (proto != Proto::HTTP3 && !tlsconf.session_cache.memcached.host.empty()) { 1592c593315Sopenharmony_ci auto bio = BIO_new(tlsconf.bio_method); 1602c593315Sopenharmony_ci BIO_set_data(bio, this); 1612c593315Sopenharmony_ci SSL_set_bio(tls.ssl, bio, bio); 1622c593315Sopenharmony_ci } 1632c593315Sopenharmony_ci 1642c593315Sopenharmony_ci SSL_set_accept_state(tls.ssl); 1652c593315Sopenharmony_ci tls.server_handshake = true; 1662c593315Sopenharmony_ci} 1672c593315Sopenharmony_ci 1682c593315Sopenharmony_ci// BIO implementation is inspired by openldap implementation: 1692c593315Sopenharmony_ci// http://www.openldap.org/devel/cvsweb.cgi/~checkout~/libraries/libldap/tls_o.c 1702c593315Sopenharmony_cinamespace { 1712c593315Sopenharmony_ciint shrpx_bio_write(BIO *b, const char *buf, int len) { 1722c593315Sopenharmony_ci if (buf == nullptr || len <= 0) { 1732c593315Sopenharmony_ci return 0; 1742c593315Sopenharmony_ci } 1752c593315Sopenharmony_ci 1762c593315Sopenharmony_ci auto conn = static_cast<Connection *>(BIO_get_data(b)); 1772c593315Sopenharmony_ci auto &wbuf = conn->tls.wbuf; 1782c593315Sopenharmony_ci 1792c593315Sopenharmony_ci BIO_clear_retry_flags(b); 1802c593315Sopenharmony_ci 1812c593315Sopenharmony_ci if (conn->tls.initial_handshake_done) { 1822c593315Sopenharmony_ci // After handshake finished, send |buf| of length |len| to the 1832c593315Sopenharmony_ci // socket directly. 1842c593315Sopenharmony_ci 1852c593315Sopenharmony_ci // Only when TLS session was prematurely ended before server sent 1862c593315Sopenharmony_ci // all handshake message, this condition is true. This could be 1872c593315Sopenharmony_ci // alert from SSL_shutdown(). Since connection is already down, 1882c593315Sopenharmony_ci // just return error. 1892c593315Sopenharmony_ci if (wbuf.rleft()) { 1902c593315Sopenharmony_ci return -1; 1912c593315Sopenharmony_ci } 1922c593315Sopenharmony_ci auto nwrite = conn->write_clear(buf, len); 1932c593315Sopenharmony_ci if (nwrite < 0) { 1942c593315Sopenharmony_ci return -1; 1952c593315Sopenharmony_ci } 1962c593315Sopenharmony_ci 1972c593315Sopenharmony_ci if (nwrite == 0) { 1982c593315Sopenharmony_ci BIO_set_retry_write(b); 1992c593315Sopenharmony_ci return -1; 2002c593315Sopenharmony_ci } 2012c593315Sopenharmony_ci 2022c593315Sopenharmony_ci return nwrite; 2032c593315Sopenharmony_ci } 2042c593315Sopenharmony_ci 2052c593315Sopenharmony_ci wbuf.append(buf, len); 2062c593315Sopenharmony_ci 2072c593315Sopenharmony_ci return len; 2082c593315Sopenharmony_ci} 2092c593315Sopenharmony_ci} // namespace 2102c593315Sopenharmony_ci 2112c593315Sopenharmony_cinamespace { 2122c593315Sopenharmony_ciint shrpx_bio_read(BIO *b, char *buf, int len) { 2132c593315Sopenharmony_ci if (buf == nullptr || len <= 0) { 2142c593315Sopenharmony_ci return 0; 2152c593315Sopenharmony_ci } 2162c593315Sopenharmony_ci 2172c593315Sopenharmony_ci auto conn = static_cast<Connection *>(BIO_get_data(b)); 2182c593315Sopenharmony_ci auto &rbuf = conn->tls.rbuf; 2192c593315Sopenharmony_ci 2202c593315Sopenharmony_ci BIO_clear_retry_flags(b); 2212c593315Sopenharmony_ci 2222c593315Sopenharmony_ci if (conn->tls.initial_handshake_done && rbuf.rleft() == 0) { 2232c593315Sopenharmony_ci auto nread = conn->read_clear(buf, len); 2242c593315Sopenharmony_ci if (nread < 0) { 2252c593315Sopenharmony_ci return -1; 2262c593315Sopenharmony_ci } 2272c593315Sopenharmony_ci if (nread == 0) { 2282c593315Sopenharmony_ci BIO_set_retry_read(b); 2292c593315Sopenharmony_ci return -1; 2302c593315Sopenharmony_ci } 2312c593315Sopenharmony_ci return nread; 2322c593315Sopenharmony_ci } 2332c593315Sopenharmony_ci 2342c593315Sopenharmony_ci if (rbuf.rleft() == 0) { 2352c593315Sopenharmony_ci BIO_set_retry_read(b); 2362c593315Sopenharmony_ci return -1; 2372c593315Sopenharmony_ci } 2382c593315Sopenharmony_ci 2392c593315Sopenharmony_ci return rbuf.remove(buf, len); 2402c593315Sopenharmony_ci} 2412c593315Sopenharmony_ci} // namespace 2422c593315Sopenharmony_ci 2432c593315Sopenharmony_cinamespace { 2442c593315Sopenharmony_ciint shrpx_bio_puts(BIO *b, const char *str) { 2452c593315Sopenharmony_ci return shrpx_bio_write(b, str, strlen(str)); 2462c593315Sopenharmony_ci} 2472c593315Sopenharmony_ci} // namespace 2482c593315Sopenharmony_ci 2492c593315Sopenharmony_cinamespace { 2502c593315Sopenharmony_ciint shrpx_bio_gets(BIO *b, char *buf, int len) { return -1; } 2512c593315Sopenharmony_ci} // namespace 2522c593315Sopenharmony_ci 2532c593315Sopenharmony_cinamespace { 2542c593315Sopenharmony_cilong shrpx_bio_ctrl(BIO *b, int cmd, long num, void *ptr) { 2552c593315Sopenharmony_ci switch (cmd) { 2562c593315Sopenharmony_ci case BIO_CTRL_FLUSH: 2572c593315Sopenharmony_ci return 1; 2582c593315Sopenharmony_ci } 2592c593315Sopenharmony_ci 2602c593315Sopenharmony_ci return 0; 2612c593315Sopenharmony_ci} 2622c593315Sopenharmony_ci} // namespace 2632c593315Sopenharmony_ci 2642c593315Sopenharmony_cinamespace { 2652c593315Sopenharmony_ciint shrpx_bio_create(BIO *b) { 2662c593315Sopenharmony_ci#if OPENSSL_1_1_API || LIBRESSL_3_5_API 2672c593315Sopenharmony_ci BIO_set_init(b, 1); 2682c593315Sopenharmony_ci#else // !OPENSSL_1_1_API && !LIBRESSL_3_5_API 2692c593315Sopenharmony_ci b->init = 1; 2702c593315Sopenharmony_ci b->num = 0; 2712c593315Sopenharmony_ci b->ptr = nullptr; 2722c593315Sopenharmony_ci b->flags = 0; 2732c593315Sopenharmony_ci#endif // !OPENSSL_1_1_API && !LIBRESSL_3_5_API 2742c593315Sopenharmony_ci return 1; 2752c593315Sopenharmony_ci} 2762c593315Sopenharmony_ci} // namespace 2772c593315Sopenharmony_ci 2782c593315Sopenharmony_cinamespace { 2792c593315Sopenharmony_ciint shrpx_bio_destroy(BIO *b) { 2802c593315Sopenharmony_ci if (b == nullptr) { 2812c593315Sopenharmony_ci return 0; 2822c593315Sopenharmony_ci } 2832c593315Sopenharmony_ci 2842c593315Sopenharmony_ci#if !OPENSSL_1_1_API && !LIBRESSL_3_5_API 2852c593315Sopenharmony_ci b->ptr = nullptr; 2862c593315Sopenharmony_ci b->init = 0; 2872c593315Sopenharmony_ci b->flags = 0; 2882c593315Sopenharmony_ci#endif // !OPENSSL_1_1_API && !LIBRESSL_3_5_API 2892c593315Sopenharmony_ci 2902c593315Sopenharmony_ci return 1; 2912c593315Sopenharmony_ci} 2922c593315Sopenharmony_ci} // namespace 2932c593315Sopenharmony_ci 2942c593315Sopenharmony_ci#if OPENSSL_1_1_API || LIBRESSL_3_5_API 2952c593315Sopenharmony_ci 2962c593315Sopenharmony_ciBIO_METHOD *create_bio_method() { 2972c593315Sopenharmony_ci auto meth = BIO_meth_new(BIO_TYPE_FD, "nghttpx-bio"); 2982c593315Sopenharmony_ci BIO_meth_set_write(meth, shrpx_bio_write); 2992c593315Sopenharmony_ci BIO_meth_set_read(meth, shrpx_bio_read); 3002c593315Sopenharmony_ci BIO_meth_set_puts(meth, shrpx_bio_puts); 3012c593315Sopenharmony_ci BIO_meth_set_gets(meth, shrpx_bio_gets); 3022c593315Sopenharmony_ci BIO_meth_set_ctrl(meth, shrpx_bio_ctrl); 3032c593315Sopenharmony_ci BIO_meth_set_create(meth, shrpx_bio_create); 3042c593315Sopenharmony_ci BIO_meth_set_destroy(meth, shrpx_bio_destroy); 3052c593315Sopenharmony_ci 3062c593315Sopenharmony_ci return meth; 3072c593315Sopenharmony_ci} 3082c593315Sopenharmony_ci 3092c593315Sopenharmony_ci#else // !OPENSSL_1_1_API && !LIBRESSL_3_5_API 3102c593315Sopenharmony_ci 3112c593315Sopenharmony_ciBIO_METHOD *create_bio_method() { 3122c593315Sopenharmony_ci static auto meth = new BIO_METHOD{ 3132c593315Sopenharmony_ci BIO_TYPE_FD, "nghttpx-bio", shrpx_bio_write, 3142c593315Sopenharmony_ci shrpx_bio_read, shrpx_bio_puts, shrpx_bio_gets, 3152c593315Sopenharmony_ci shrpx_bio_ctrl, shrpx_bio_create, shrpx_bio_destroy, 3162c593315Sopenharmony_ci }; 3172c593315Sopenharmony_ci 3182c593315Sopenharmony_ci return meth; 3192c593315Sopenharmony_ci} 3202c593315Sopenharmony_ci 3212c593315Sopenharmony_ci#endif // !OPENSSL_1_1_API && !LIBRESSL_3_5_API 3222c593315Sopenharmony_ci 3232c593315Sopenharmony_civoid Connection::set_ssl(SSL *ssl) { 3242c593315Sopenharmony_ci tls.ssl = ssl; 3252c593315Sopenharmony_ci 3262c593315Sopenharmony_ci SSL_set_app_data(tls.ssl, this); 3272c593315Sopenharmony_ci} 3282c593315Sopenharmony_ci 3292c593315Sopenharmony_cinamespace { 3302c593315Sopenharmony_ci// We should buffer at least full encrypted TLS record here. 3312c593315Sopenharmony_ci// Theoretically, peer can send client hello in several TLS records, 3322c593315Sopenharmony_ci// which could exceed this limit, but it is not portable, and we don't 3332c593315Sopenharmony_ci// have to handle such exotic behaviour. 3342c593315Sopenharmony_cibool read_buffer_full(DefaultPeekMemchunks &rbuf) { 3352c593315Sopenharmony_ci return rbuf.rleft_buffered() >= 20_k; 3362c593315Sopenharmony_ci} 3372c593315Sopenharmony_ci} // namespace 3382c593315Sopenharmony_ci 3392c593315Sopenharmony_ciint Connection::tls_handshake() { 3402c593315Sopenharmony_ci wlimit.stopw(); 3412c593315Sopenharmony_ci ev_timer_stop(loop, &wt); 3422c593315Sopenharmony_ci 3432c593315Sopenharmony_ci auto &tlsconf = get_config()->tls; 3442c593315Sopenharmony_ci 3452c593315Sopenharmony_ci if (!tls.server_handshake || tlsconf.session_cache.memcached.host.empty()) { 3462c593315Sopenharmony_ci return tls_handshake_simple(); 3472c593315Sopenharmony_ci } 3482c593315Sopenharmony_ci 3492c593315Sopenharmony_ci std::array<uint8_t, 16_k> buf; 3502c593315Sopenharmony_ci 3512c593315Sopenharmony_ci if (ev_is_active(&rev)) { 3522c593315Sopenharmony_ci auto nread = read_clear(buf.data(), buf.size()); 3532c593315Sopenharmony_ci if (nread < 0) { 3542c593315Sopenharmony_ci if (LOG_ENABLED(INFO)) { 3552c593315Sopenharmony_ci LOG(INFO) << "tls: handshake read error"; 3562c593315Sopenharmony_ci } 3572c593315Sopenharmony_ci return -1; 3582c593315Sopenharmony_ci } 3592c593315Sopenharmony_ci tls.rbuf.append(buf.data(), nread); 3602c593315Sopenharmony_ci if (read_buffer_full(tls.rbuf)) { 3612c593315Sopenharmony_ci rlimit.stopw(); 3622c593315Sopenharmony_ci } 3632c593315Sopenharmony_ci } 3642c593315Sopenharmony_ci 3652c593315Sopenharmony_ci if (tls.initial_handshake_done) { 3662c593315Sopenharmony_ci return write_tls_pending_handshake(); 3672c593315Sopenharmony_ci } 3682c593315Sopenharmony_ci 3692c593315Sopenharmony_ci switch (tls.handshake_state) { 3702c593315Sopenharmony_ci case TLSHandshakeState::WAIT_FOR_SESSION_CACHE: 3712c593315Sopenharmony_ci return SHRPX_ERR_INPROGRESS; 3722c593315Sopenharmony_ci case TLSHandshakeState::GOT_SESSION_CACHE: { 3732c593315Sopenharmony_ci // Use the same trick invented by @kazuho in h2o project. 3742c593315Sopenharmony_ci 3752c593315Sopenharmony_ci // Discard all outgoing data. 3762c593315Sopenharmony_ci tls.wbuf.reset(); 3772c593315Sopenharmony_ci // Rewind buffered incoming data to replay client hello. 3782c593315Sopenharmony_ci tls.rbuf.disable_peek(false); 3792c593315Sopenharmony_ci 3802c593315Sopenharmony_ci auto ssl_ctx = SSL_get_SSL_CTX(tls.ssl); 3812c593315Sopenharmony_ci auto ssl_opts = SSL_get_options(tls.ssl); 3822c593315Sopenharmony_ci SSL_free(tls.ssl); 3832c593315Sopenharmony_ci 3842c593315Sopenharmony_ci auto ssl = tls::create_ssl(ssl_ctx); 3852c593315Sopenharmony_ci if (!ssl) { 3862c593315Sopenharmony_ci return -1; 3872c593315Sopenharmony_ci } 3882c593315Sopenharmony_ci if (ssl_opts & SSL_OP_NO_TICKET) { 3892c593315Sopenharmony_ci SSL_set_options(ssl, SSL_OP_NO_TICKET); 3902c593315Sopenharmony_ci } 3912c593315Sopenharmony_ci 3922c593315Sopenharmony_ci set_ssl(ssl); 3932c593315Sopenharmony_ci 3942c593315Sopenharmony_ci prepare_server_handshake(); 3952c593315Sopenharmony_ci 3962c593315Sopenharmony_ci tls.handshake_state = TLSHandshakeState::NORMAL; 3972c593315Sopenharmony_ci break; 3982c593315Sopenharmony_ci } 3992c593315Sopenharmony_ci case TLSHandshakeState::CANCEL_SESSION_CACHE: 4002c593315Sopenharmony_ci tls.handshake_state = TLSHandshakeState::NORMAL; 4012c593315Sopenharmony_ci break; 4022c593315Sopenharmony_ci default: 4032c593315Sopenharmony_ci break; 4042c593315Sopenharmony_ci } 4052c593315Sopenharmony_ci 4062c593315Sopenharmony_ci int rv; 4072c593315Sopenharmony_ci 4082c593315Sopenharmony_ci ERR_clear_error(); 4092c593315Sopenharmony_ci 4102c593315Sopenharmony_ci#if OPENSSL_1_1_1_API && !defined(OPENSSL_IS_BORINGSSL) 4112c593315Sopenharmony_ci if (!tls.server_handshake || tls.early_data_finish) { 4122c593315Sopenharmony_ci rv = SSL_do_handshake(tls.ssl); 4132c593315Sopenharmony_ci } else { 4142c593315Sopenharmony_ci for (;;) { 4152c593315Sopenharmony_ci size_t nread; 4162c593315Sopenharmony_ci 4172c593315Sopenharmony_ci rv = SSL_read_early_data(tls.ssl, buf.data(), buf.size(), &nread); 4182c593315Sopenharmony_ci if (rv == SSL_READ_EARLY_DATA_ERROR) { 4192c593315Sopenharmony_ci // If we have early data, and server sends ServerHello, assume 4202c593315Sopenharmony_ci // that handshake is completed in server side, and start 4212c593315Sopenharmony_ci // processing request. If we don't exit handshake code here, 4222c593315Sopenharmony_ci // server waits for EndOfEarlyData and Finished message from 4232c593315Sopenharmony_ci // client, which voids the purpose of 0-RTT data. The left 4242c593315Sopenharmony_ci // over of handshake is done through write_tls or read_tls. 4252c593315Sopenharmony_ci if (tlsconf.no_postpone_early_data && 4262c593315Sopenharmony_ci (tls.handshake_state == TLSHandshakeState::WRITE_STARTED || 4272c593315Sopenharmony_ci tls.wbuf.rleft()) && 4282c593315Sopenharmony_ci tls.earlybuf.rleft()) { 4292c593315Sopenharmony_ci rv = 1; 4302c593315Sopenharmony_ci } 4312c593315Sopenharmony_ci 4322c593315Sopenharmony_ci break; 4332c593315Sopenharmony_ci } 4342c593315Sopenharmony_ci 4352c593315Sopenharmony_ci if (LOG_ENABLED(INFO)) { 4362c593315Sopenharmony_ci LOG(INFO) << "tls: read early data " << nread << " bytes"; 4372c593315Sopenharmony_ci } 4382c593315Sopenharmony_ci 4392c593315Sopenharmony_ci tls.earlybuf.append(buf.data(), nread); 4402c593315Sopenharmony_ci 4412c593315Sopenharmony_ci if (rv == SSL_READ_EARLY_DATA_FINISH) { 4422c593315Sopenharmony_ci if (LOG_ENABLED(INFO)) { 4432c593315Sopenharmony_ci LOG(INFO) << "tls: read all early data; total " 4442c593315Sopenharmony_ci << tls.earlybuf.rleft() << " bytes"; 4452c593315Sopenharmony_ci } 4462c593315Sopenharmony_ci tls.early_data_finish = true; 4472c593315Sopenharmony_ci // The same reason stated above. 4482c593315Sopenharmony_ci if (tlsconf.no_postpone_early_data && 4492c593315Sopenharmony_ci (tls.handshake_state == TLSHandshakeState::WRITE_STARTED || 4502c593315Sopenharmony_ci tls.wbuf.rleft()) && 4512c593315Sopenharmony_ci tls.earlybuf.rleft()) { 4522c593315Sopenharmony_ci rv = 1; 4532c593315Sopenharmony_ci } else { 4542c593315Sopenharmony_ci ERR_clear_error(); 4552c593315Sopenharmony_ci rv = SSL_do_handshake(tls.ssl); 4562c593315Sopenharmony_ci } 4572c593315Sopenharmony_ci break; 4582c593315Sopenharmony_ci } 4592c593315Sopenharmony_ci } 4602c593315Sopenharmony_ci } 4612c593315Sopenharmony_ci#else // !(OPENSSL_1_1_1_API && !defined(OPENSSL_IS_BORINGSSL)) 4622c593315Sopenharmony_ci rv = SSL_do_handshake(tls.ssl); 4632c593315Sopenharmony_ci#endif // !(OPENSSL_1_1_1_API && !defined(OPENSSL_IS_BORINGSSL)) 4642c593315Sopenharmony_ci 4652c593315Sopenharmony_ci if (rv <= 0) { 4662c593315Sopenharmony_ci auto err = SSL_get_error(tls.ssl, rv); 4672c593315Sopenharmony_ci switch (err) { 4682c593315Sopenharmony_ci case SSL_ERROR_WANT_READ: 4692c593315Sopenharmony_ci if (read_buffer_full(tls.rbuf)) { 4702c593315Sopenharmony_ci if (LOG_ENABLED(INFO)) { 4712c593315Sopenharmony_ci LOG(INFO) << "tls: handshake message is too large"; 4722c593315Sopenharmony_ci } 4732c593315Sopenharmony_ci return -1; 4742c593315Sopenharmony_ci } 4752c593315Sopenharmony_ci break; 4762c593315Sopenharmony_ci case SSL_ERROR_WANT_WRITE: 4772c593315Sopenharmony_ci break; 4782c593315Sopenharmony_ci case SSL_ERROR_SSL: { 4792c593315Sopenharmony_ci if (LOG_ENABLED(INFO)) { 4802c593315Sopenharmony_ci LOG(INFO) << "tls: handshake libssl error: " 4812c593315Sopenharmony_ci << ERR_error_string(ERR_get_error(), nullptr); 4822c593315Sopenharmony_ci } 4832c593315Sopenharmony_ci 4842c593315Sopenharmony_ci struct iovec iov[1]; 4852c593315Sopenharmony_ci auto iovcnt = tls.wbuf.riovec(iov, 1); 4862c593315Sopenharmony_ci auto nwrite = writev_clear(iov, iovcnt); 4872c593315Sopenharmony_ci if (nwrite > 0) { 4882c593315Sopenharmony_ci tls.wbuf.drain(nwrite); 4892c593315Sopenharmony_ci } 4902c593315Sopenharmony_ci 4912c593315Sopenharmony_ci return SHRPX_ERR_NETWORK; 4922c593315Sopenharmony_ci } 4932c593315Sopenharmony_ci default: 4942c593315Sopenharmony_ci if (LOG_ENABLED(INFO)) { 4952c593315Sopenharmony_ci LOG(INFO) << "tls: handshake libssl error " << err; 4962c593315Sopenharmony_ci } 4972c593315Sopenharmony_ci return SHRPX_ERR_NETWORK; 4982c593315Sopenharmony_ci } 4992c593315Sopenharmony_ci } 5002c593315Sopenharmony_ci 5012c593315Sopenharmony_ci if (tls.handshake_state == TLSHandshakeState::WAIT_FOR_SESSION_CACHE) { 5022c593315Sopenharmony_ci if (LOG_ENABLED(INFO)) { 5032c593315Sopenharmony_ci LOG(INFO) << "tls: handshake is still in progress"; 5042c593315Sopenharmony_ci } 5052c593315Sopenharmony_ci return SHRPX_ERR_INPROGRESS; 5062c593315Sopenharmony_ci } 5072c593315Sopenharmony_ci 5082c593315Sopenharmony_ci // Don't send handshake data if handshake was completed in OpenSSL 5092c593315Sopenharmony_ci // routine. We have to check HTTP/2 requirement if HTTP/2 was 5102c593315Sopenharmony_ci // negotiated before sending finished message to the peer. 5112c593315Sopenharmony_ci if ((rv != 1 5122c593315Sopenharmony_ci#ifdef OPENSSL_IS_BORINGSSL 5132c593315Sopenharmony_ci || SSL_in_init(tls.ssl) 5142c593315Sopenharmony_ci#endif // OPENSSL_IS_BORINGSSL 5152c593315Sopenharmony_ci ) && 5162c593315Sopenharmony_ci tls.wbuf.rleft()) { 5172c593315Sopenharmony_ci // First write indicates that resumption stuff has done. 5182c593315Sopenharmony_ci if (tls.handshake_state != TLSHandshakeState::WRITE_STARTED) { 5192c593315Sopenharmony_ci tls.handshake_state = TLSHandshakeState::WRITE_STARTED; 5202c593315Sopenharmony_ci // If peek has already disabled, this is noop. 5212c593315Sopenharmony_ci tls.rbuf.disable_peek(true); 5222c593315Sopenharmony_ci } 5232c593315Sopenharmony_ci std::array<struct iovec, 4> iov; 5242c593315Sopenharmony_ci auto iovcnt = tls.wbuf.riovec(iov.data(), iov.size()); 5252c593315Sopenharmony_ci auto nwrite = writev_clear(iov.data(), iovcnt); 5262c593315Sopenharmony_ci if (nwrite < 0) { 5272c593315Sopenharmony_ci if (LOG_ENABLED(INFO)) { 5282c593315Sopenharmony_ci LOG(INFO) << "tls: handshake write error"; 5292c593315Sopenharmony_ci } 5302c593315Sopenharmony_ci return -1; 5312c593315Sopenharmony_ci } 5322c593315Sopenharmony_ci tls.wbuf.drain(nwrite); 5332c593315Sopenharmony_ci 5342c593315Sopenharmony_ci if (tls.wbuf.rleft()) { 5352c593315Sopenharmony_ci wlimit.startw(); 5362c593315Sopenharmony_ci ev_timer_again(loop, &wt); 5372c593315Sopenharmony_ci } 5382c593315Sopenharmony_ci } 5392c593315Sopenharmony_ci 5402c593315Sopenharmony_ci if (!read_buffer_full(tls.rbuf)) { 5412c593315Sopenharmony_ci // We may have stopped reading 5422c593315Sopenharmony_ci rlimit.startw(); 5432c593315Sopenharmony_ci } 5442c593315Sopenharmony_ci 5452c593315Sopenharmony_ci if (rv != 1) { 5462c593315Sopenharmony_ci if (LOG_ENABLED(INFO)) { 5472c593315Sopenharmony_ci LOG(INFO) << "tls: handshake is still in progress"; 5482c593315Sopenharmony_ci } 5492c593315Sopenharmony_ci return SHRPX_ERR_INPROGRESS; 5502c593315Sopenharmony_ci } 5512c593315Sopenharmony_ci 5522c593315Sopenharmony_ci#ifdef OPENSSL_IS_BORINGSSL 5532c593315Sopenharmony_ci if (!tlsconf.no_postpone_early_data && SSL_in_early_data(tls.ssl) && 5542c593315Sopenharmony_ci SSL_in_init(tls.ssl)) { 5552c593315Sopenharmony_ci auto nread = SSL_read(tls.ssl, buf.data(), buf.size()); 5562c593315Sopenharmony_ci if (nread <= 0) { 5572c593315Sopenharmony_ci auto err = SSL_get_error(tls.ssl, nread); 5582c593315Sopenharmony_ci switch (err) { 5592c593315Sopenharmony_ci case SSL_ERROR_WANT_READ: 5602c593315Sopenharmony_ci case SSL_ERROR_WANT_WRITE: 5612c593315Sopenharmony_ci break; 5622c593315Sopenharmony_ci case SSL_ERROR_ZERO_RETURN: 5632c593315Sopenharmony_ci return SHRPX_ERR_EOF; 5642c593315Sopenharmony_ci case SSL_ERROR_SSL: 5652c593315Sopenharmony_ci if (LOG_ENABLED(INFO)) { 5662c593315Sopenharmony_ci LOG(INFO) << "SSL_read: " 5672c593315Sopenharmony_ci << ERR_error_string(ERR_get_error(), nullptr); 5682c593315Sopenharmony_ci } 5692c593315Sopenharmony_ci return SHRPX_ERR_NETWORK; 5702c593315Sopenharmony_ci default: 5712c593315Sopenharmony_ci if (LOG_ENABLED(INFO)) { 5722c593315Sopenharmony_ci LOG(INFO) << "SSL_read: SSL_get_error returned " << err; 5732c593315Sopenharmony_ci } 5742c593315Sopenharmony_ci return SHRPX_ERR_NETWORK; 5752c593315Sopenharmony_ci } 5762c593315Sopenharmony_ci } else { 5772c593315Sopenharmony_ci tls.earlybuf.append(buf.data(), nread); 5782c593315Sopenharmony_ci } 5792c593315Sopenharmony_ci 5802c593315Sopenharmony_ci if (SSL_in_init(tls.ssl)) { 5812c593315Sopenharmony_ci return SHRPX_ERR_INPROGRESS; 5822c593315Sopenharmony_ci } 5832c593315Sopenharmony_ci } 5842c593315Sopenharmony_ci#endif // OPENSSL_IS_BORINGSSL 5852c593315Sopenharmony_ci 5862c593315Sopenharmony_ci // Handshake was done 5872c593315Sopenharmony_ci 5882c593315Sopenharmony_ci rv = check_http2_requirement(); 5892c593315Sopenharmony_ci if (rv != 0) { 5902c593315Sopenharmony_ci return -1; 5912c593315Sopenharmony_ci } 5922c593315Sopenharmony_ci 5932c593315Sopenharmony_ci // Just in case 5942c593315Sopenharmony_ci tls.rbuf.disable_peek(true); 5952c593315Sopenharmony_ci 5962c593315Sopenharmony_ci tls.initial_handshake_done = true; 5972c593315Sopenharmony_ci 5982c593315Sopenharmony_ci return write_tls_pending_handshake(); 5992c593315Sopenharmony_ci} 6002c593315Sopenharmony_ci 6012c593315Sopenharmony_ciint Connection::tls_handshake_simple() { 6022c593315Sopenharmony_ci wlimit.stopw(); 6032c593315Sopenharmony_ci ev_timer_stop(loop, &wt); 6042c593315Sopenharmony_ci 6052c593315Sopenharmony_ci if (tls.initial_handshake_done) { 6062c593315Sopenharmony_ci return write_tls_pending_handshake(); 6072c593315Sopenharmony_ci } 6082c593315Sopenharmony_ci 6092c593315Sopenharmony_ci if (SSL_get_fd(tls.ssl) == -1) { 6102c593315Sopenharmony_ci SSL_set_fd(tls.ssl, fd); 6112c593315Sopenharmony_ci } 6122c593315Sopenharmony_ci 6132c593315Sopenharmony_ci int rv; 6142c593315Sopenharmony_ci#if OPENSSL_1_1_1_API || defined(OPENSSL_IS_BORINGSSL) 6152c593315Sopenharmony_ci auto &tlsconf = get_config()->tls; 6162c593315Sopenharmony_ci std::array<uint8_t, 16_k> buf; 6172c593315Sopenharmony_ci#endif // OPENSSL_1_1_1_API || defined(OPENSSL_IS_BORINGSSL) 6182c593315Sopenharmony_ci 6192c593315Sopenharmony_ci ERR_clear_error(); 6202c593315Sopenharmony_ci 6212c593315Sopenharmony_ci#if OPENSSL_1_1_1_API && !defined(OPENSSL_IS_BORINGSSL) 6222c593315Sopenharmony_ci if (!tls.server_handshake || tls.early_data_finish) { 6232c593315Sopenharmony_ci rv = SSL_do_handshake(tls.ssl); 6242c593315Sopenharmony_ci } else { 6252c593315Sopenharmony_ci for (;;) { 6262c593315Sopenharmony_ci size_t nread; 6272c593315Sopenharmony_ci 6282c593315Sopenharmony_ci rv = SSL_read_early_data(tls.ssl, buf.data(), buf.size(), &nread); 6292c593315Sopenharmony_ci if (rv == SSL_READ_EARLY_DATA_ERROR) { 6302c593315Sopenharmony_ci // If we have early data, and server sends ServerHello, assume 6312c593315Sopenharmony_ci // that handshake is completed in server side, and start 6322c593315Sopenharmony_ci // processing request. If we don't exit handshake code here, 6332c593315Sopenharmony_ci // server waits for EndOfEarlyData and Finished message from 6342c593315Sopenharmony_ci // client, which voids the purpose of 0-RTT data. The left 6352c593315Sopenharmony_ci // over of handshake is done through write_tls or read_tls. 6362c593315Sopenharmony_ci if (tlsconf.no_postpone_early_data && tls.earlybuf.rleft()) { 6372c593315Sopenharmony_ci rv = 1; 6382c593315Sopenharmony_ci } 6392c593315Sopenharmony_ci 6402c593315Sopenharmony_ci break; 6412c593315Sopenharmony_ci } 6422c593315Sopenharmony_ci 6432c593315Sopenharmony_ci if (LOG_ENABLED(INFO)) { 6442c593315Sopenharmony_ci LOG(INFO) << "tls: read early data " << nread << " bytes"; 6452c593315Sopenharmony_ci } 6462c593315Sopenharmony_ci 6472c593315Sopenharmony_ci tls.earlybuf.append(buf.data(), nread); 6482c593315Sopenharmony_ci 6492c593315Sopenharmony_ci if (rv == SSL_READ_EARLY_DATA_FINISH) { 6502c593315Sopenharmony_ci if (LOG_ENABLED(INFO)) { 6512c593315Sopenharmony_ci LOG(INFO) << "tls: read all early data; total " 6522c593315Sopenharmony_ci << tls.earlybuf.rleft() << " bytes"; 6532c593315Sopenharmony_ci } 6542c593315Sopenharmony_ci tls.early_data_finish = true; 6552c593315Sopenharmony_ci // The same reason stated above. 6562c593315Sopenharmony_ci if (tlsconf.no_postpone_early_data && tls.earlybuf.rleft()) { 6572c593315Sopenharmony_ci rv = 1; 6582c593315Sopenharmony_ci } else { 6592c593315Sopenharmony_ci ERR_clear_error(); 6602c593315Sopenharmony_ci rv = SSL_do_handshake(tls.ssl); 6612c593315Sopenharmony_ci } 6622c593315Sopenharmony_ci break; 6632c593315Sopenharmony_ci } 6642c593315Sopenharmony_ci } 6652c593315Sopenharmony_ci } 6662c593315Sopenharmony_ci#else // !(OPENSSL_1_1_1_API && !defined(OPENSSL_IS_BORINGSSL)) 6672c593315Sopenharmony_ci rv = SSL_do_handshake(tls.ssl); 6682c593315Sopenharmony_ci#endif // !(OPENSSL_1_1_1_API && !defined(OPENSSL_IS_BORINGSSL)) 6692c593315Sopenharmony_ci 6702c593315Sopenharmony_ci if (rv <= 0) { 6712c593315Sopenharmony_ci auto err = SSL_get_error(tls.ssl, rv); 6722c593315Sopenharmony_ci switch (err) { 6732c593315Sopenharmony_ci case SSL_ERROR_WANT_READ: 6742c593315Sopenharmony_ci if (read_buffer_full(tls.rbuf)) { 6752c593315Sopenharmony_ci if (LOG_ENABLED(INFO)) { 6762c593315Sopenharmony_ci LOG(INFO) << "tls: handshake message is too large"; 6772c593315Sopenharmony_ci } 6782c593315Sopenharmony_ci return -1; 6792c593315Sopenharmony_ci } 6802c593315Sopenharmony_ci break; 6812c593315Sopenharmony_ci case SSL_ERROR_WANT_WRITE: 6822c593315Sopenharmony_ci wlimit.startw(); 6832c593315Sopenharmony_ci ev_timer_again(loop, &wt); 6842c593315Sopenharmony_ci break; 6852c593315Sopenharmony_ci case SSL_ERROR_SSL: { 6862c593315Sopenharmony_ci if (LOG_ENABLED(INFO)) { 6872c593315Sopenharmony_ci LOG(INFO) << "tls: handshake libssl error: " 6882c593315Sopenharmony_ci << ERR_error_string(ERR_get_error(), nullptr); 6892c593315Sopenharmony_ci } 6902c593315Sopenharmony_ci return SHRPX_ERR_NETWORK; 6912c593315Sopenharmony_ci } 6922c593315Sopenharmony_ci default: 6932c593315Sopenharmony_ci if (LOG_ENABLED(INFO)) { 6942c593315Sopenharmony_ci LOG(INFO) << "tls: handshake libssl error " << err; 6952c593315Sopenharmony_ci } 6962c593315Sopenharmony_ci return SHRPX_ERR_NETWORK; 6972c593315Sopenharmony_ci } 6982c593315Sopenharmony_ci } 6992c593315Sopenharmony_ci 7002c593315Sopenharmony_ci if (rv != 1) { 7012c593315Sopenharmony_ci if (LOG_ENABLED(INFO)) { 7022c593315Sopenharmony_ci LOG(INFO) << "tls: handshake is still in progress"; 7032c593315Sopenharmony_ci } 7042c593315Sopenharmony_ci return SHRPX_ERR_INPROGRESS; 7052c593315Sopenharmony_ci } 7062c593315Sopenharmony_ci 7072c593315Sopenharmony_ci#ifdef OPENSSL_IS_BORINGSSL 7082c593315Sopenharmony_ci if (!tlsconf.no_postpone_early_data && SSL_in_early_data(tls.ssl) && 7092c593315Sopenharmony_ci SSL_in_init(tls.ssl)) { 7102c593315Sopenharmony_ci auto nread = SSL_read(tls.ssl, buf.data(), buf.size()); 7112c593315Sopenharmony_ci if (nread <= 0) { 7122c593315Sopenharmony_ci auto err = SSL_get_error(tls.ssl, nread); 7132c593315Sopenharmony_ci switch (err) { 7142c593315Sopenharmony_ci case SSL_ERROR_WANT_READ: 7152c593315Sopenharmony_ci case SSL_ERROR_WANT_WRITE: 7162c593315Sopenharmony_ci break; 7172c593315Sopenharmony_ci case SSL_ERROR_ZERO_RETURN: 7182c593315Sopenharmony_ci return SHRPX_ERR_EOF; 7192c593315Sopenharmony_ci case SSL_ERROR_SSL: 7202c593315Sopenharmony_ci if (LOG_ENABLED(INFO)) { 7212c593315Sopenharmony_ci LOG(INFO) << "SSL_read: " 7222c593315Sopenharmony_ci << ERR_error_string(ERR_get_error(), nullptr); 7232c593315Sopenharmony_ci } 7242c593315Sopenharmony_ci return SHRPX_ERR_NETWORK; 7252c593315Sopenharmony_ci default: 7262c593315Sopenharmony_ci if (LOG_ENABLED(INFO)) { 7272c593315Sopenharmony_ci LOG(INFO) << "SSL_read: SSL_get_error returned " << err; 7282c593315Sopenharmony_ci } 7292c593315Sopenharmony_ci return SHRPX_ERR_NETWORK; 7302c593315Sopenharmony_ci } 7312c593315Sopenharmony_ci } else { 7322c593315Sopenharmony_ci tls.earlybuf.append(buf.data(), nread); 7332c593315Sopenharmony_ci } 7342c593315Sopenharmony_ci 7352c593315Sopenharmony_ci if (SSL_in_init(tls.ssl)) { 7362c593315Sopenharmony_ci return SHRPX_ERR_INPROGRESS; 7372c593315Sopenharmony_ci } 7382c593315Sopenharmony_ci } 7392c593315Sopenharmony_ci#endif // OPENSSL_IS_BORINGSSL 7402c593315Sopenharmony_ci 7412c593315Sopenharmony_ci // Handshake was done 7422c593315Sopenharmony_ci 7432c593315Sopenharmony_ci rv = check_http2_requirement(); 7442c593315Sopenharmony_ci if (rv != 0) { 7452c593315Sopenharmony_ci return -1; 7462c593315Sopenharmony_ci } 7472c593315Sopenharmony_ci 7482c593315Sopenharmony_ci tls.initial_handshake_done = true; 7492c593315Sopenharmony_ci 7502c593315Sopenharmony_ci return write_tls_pending_handshake(); 7512c593315Sopenharmony_ci} 7522c593315Sopenharmony_ci 7532c593315Sopenharmony_ciint Connection::write_tls_pending_handshake() { 7542c593315Sopenharmony_ci // Send handshake data left in the buffer 7552c593315Sopenharmony_ci while (tls.wbuf.rleft()) { 7562c593315Sopenharmony_ci std::array<struct iovec, 4> iov; 7572c593315Sopenharmony_ci auto iovcnt = tls.wbuf.riovec(iov.data(), iov.size()); 7582c593315Sopenharmony_ci auto nwrite = writev_clear(iov.data(), iovcnt); 7592c593315Sopenharmony_ci if (nwrite < 0) { 7602c593315Sopenharmony_ci if (LOG_ENABLED(INFO)) { 7612c593315Sopenharmony_ci LOG(INFO) << "tls: handshake write error"; 7622c593315Sopenharmony_ci } 7632c593315Sopenharmony_ci return -1; 7642c593315Sopenharmony_ci } 7652c593315Sopenharmony_ci if (nwrite == 0) { 7662c593315Sopenharmony_ci wlimit.startw(); 7672c593315Sopenharmony_ci ev_timer_again(loop, &wt); 7682c593315Sopenharmony_ci 7692c593315Sopenharmony_ci return SHRPX_ERR_INPROGRESS; 7702c593315Sopenharmony_ci } 7712c593315Sopenharmony_ci tls.wbuf.drain(nwrite); 7722c593315Sopenharmony_ci } 7732c593315Sopenharmony_ci 7742c593315Sopenharmony_ci#ifdef OPENSSL_IS_BORINGSSL 7752c593315Sopenharmony_ci if (!SSL_in_init(tls.ssl)) { 7762c593315Sopenharmony_ci // This will send a session ticket. 7772c593315Sopenharmony_ci auto nwrite = SSL_write(tls.ssl, "", 0); 7782c593315Sopenharmony_ci if (nwrite < 0) { 7792c593315Sopenharmony_ci auto err = SSL_get_error(tls.ssl, nwrite); 7802c593315Sopenharmony_ci switch (err) { 7812c593315Sopenharmony_ci case SSL_ERROR_WANT_READ: 7822c593315Sopenharmony_ci if (LOG_ENABLED(INFO)) { 7832c593315Sopenharmony_ci LOG(INFO) << "Close connection due to TLS renegotiation"; 7842c593315Sopenharmony_ci } 7852c593315Sopenharmony_ci return SHRPX_ERR_NETWORK; 7862c593315Sopenharmony_ci case SSL_ERROR_WANT_WRITE: 7872c593315Sopenharmony_ci break; 7882c593315Sopenharmony_ci case SSL_ERROR_SSL: 7892c593315Sopenharmony_ci if (LOG_ENABLED(INFO)) { 7902c593315Sopenharmony_ci LOG(INFO) << "SSL_write: " 7912c593315Sopenharmony_ci << ERR_error_string(ERR_get_error(), nullptr); 7922c593315Sopenharmony_ci } 7932c593315Sopenharmony_ci return SHRPX_ERR_NETWORK; 7942c593315Sopenharmony_ci default: 7952c593315Sopenharmony_ci if (LOG_ENABLED(INFO)) { 7962c593315Sopenharmony_ci LOG(INFO) << "SSL_write: SSL_get_error returned " << err; 7972c593315Sopenharmony_ci } 7982c593315Sopenharmony_ci return SHRPX_ERR_NETWORK; 7992c593315Sopenharmony_ci } 8002c593315Sopenharmony_ci } 8012c593315Sopenharmony_ci } 8022c593315Sopenharmony_ci#endif // OPENSSL_IS_BORINGSSL 8032c593315Sopenharmony_ci 8042c593315Sopenharmony_ci // We have to start read watcher, since later stage of code expects 8052c593315Sopenharmony_ci // this. 8062c593315Sopenharmony_ci rlimit.startw(); 8072c593315Sopenharmony_ci 8082c593315Sopenharmony_ci // We may have whole request in tls.rbuf. This means that we don't 8092c593315Sopenharmony_ci // get notified further read event. This is especially true for 8102c593315Sopenharmony_ci // HTTP/1.1. 8112c593315Sopenharmony_ci handle_tls_pending_read(); 8122c593315Sopenharmony_ci 8132c593315Sopenharmony_ci if (LOG_ENABLED(INFO)) { 8142c593315Sopenharmony_ci LOG(INFO) << "SSL/TLS handshake completed"; 8152c593315Sopenharmony_ci nghttp2::tls::TLSSessionInfo tls_info{}; 8162c593315Sopenharmony_ci if (nghttp2::tls::get_tls_session_info(&tls_info, tls.ssl)) { 8172c593315Sopenharmony_ci LOG(INFO) << "cipher=" << tls_info.cipher 8182c593315Sopenharmony_ci << " protocol=" << tls_info.protocol 8192c593315Sopenharmony_ci << " resumption=" << (tls_info.session_reused ? "yes" : "no") 8202c593315Sopenharmony_ci << " session_id=" 8212c593315Sopenharmony_ci << util::format_hex(tls_info.session_id, 8222c593315Sopenharmony_ci tls_info.session_id_length); 8232c593315Sopenharmony_ci } 8242c593315Sopenharmony_ci } 8252c593315Sopenharmony_ci 8262c593315Sopenharmony_ci return 0; 8272c593315Sopenharmony_ci} 8282c593315Sopenharmony_ci 8292c593315Sopenharmony_ciint Connection::check_http2_requirement() { 8302c593315Sopenharmony_ci const unsigned char *next_proto = nullptr; 8312c593315Sopenharmony_ci unsigned int next_proto_len; 8322c593315Sopenharmony_ci 8332c593315Sopenharmony_ci#ifndef OPENSSL_NO_NEXTPROTONEG 8342c593315Sopenharmony_ci SSL_get0_next_proto_negotiated(tls.ssl, &next_proto, &next_proto_len); 8352c593315Sopenharmony_ci#endif // !OPENSSL_NO_NEXTPROTONEG 8362c593315Sopenharmony_ci#if OPENSSL_VERSION_NUMBER >= 0x10002000L 8372c593315Sopenharmony_ci if (next_proto == nullptr) { 8382c593315Sopenharmony_ci SSL_get0_alpn_selected(tls.ssl, &next_proto, &next_proto_len); 8392c593315Sopenharmony_ci } 8402c593315Sopenharmony_ci#endif // OPENSSL_VERSION_NUMBER >= 0x10002000L 8412c593315Sopenharmony_ci if (next_proto == nullptr || 8422c593315Sopenharmony_ci !util::check_h2_is_selected(StringRef{next_proto, next_proto_len})) { 8432c593315Sopenharmony_ci return 0; 8442c593315Sopenharmony_ci } 8452c593315Sopenharmony_ci if (!nghttp2::tls::check_http2_tls_version(tls.ssl)) { 8462c593315Sopenharmony_ci if (LOG_ENABLED(INFO)) { 8472c593315Sopenharmony_ci LOG(INFO) << "TLSv1.2 was not negotiated. HTTP/2 must not be used."; 8482c593315Sopenharmony_ci } 8492c593315Sopenharmony_ci return -1; 8502c593315Sopenharmony_ci } 8512c593315Sopenharmony_ci 8522c593315Sopenharmony_ci auto check_block_list = false; 8532c593315Sopenharmony_ci if (tls.server_handshake) { 8542c593315Sopenharmony_ci check_block_list = !get_config()->tls.no_http2_cipher_block_list; 8552c593315Sopenharmony_ci } else { 8562c593315Sopenharmony_ci check_block_list = !get_config()->tls.client.no_http2_cipher_block_list; 8572c593315Sopenharmony_ci } 8582c593315Sopenharmony_ci 8592c593315Sopenharmony_ci if (check_block_list && 8602c593315Sopenharmony_ci nghttp2::tls::check_http2_cipher_block_list(tls.ssl)) { 8612c593315Sopenharmony_ci if (LOG_ENABLED(INFO)) { 8622c593315Sopenharmony_ci LOG(INFO) << "The negotiated cipher suite is in HTTP/2 cipher suite " 8632c593315Sopenharmony_ci "block list. HTTP/2 must not be used."; 8642c593315Sopenharmony_ci } 8652c593315Sopenharmony_ci return -1; 8662c593315Sopenharmony_ci } 8672c593315Sopenharmony_ci 8682c593315Sopenharmony_ci return 0; 8692c593315Sopenharmony_ci} 8702c593315Sopenharmony_ci 8712c593315Sopenharmony_cinamespace { 8722c593315Sopenharmony_ciconstexpr size_t SHRPX_SMALL_WRITE_LIMIT = 1300; 8732c593315Sopenharmony_ci} // namespace 8742c593315Sopenharmony_ci 8752c593315Sopenharmony_cisize_t Connection::get_tls_write_limit() { 8762c593315Sopenharmony_ci 8772c593315Sopenharmony_ci if (tls_dyn_rec_warmup_threshold == 0) { 8782c593315Sopenharmony_ci return std::numeric_limits<ssize_t>::max(); 8792c593315Sopenharmony_ci } 8802c593315Sopenharmony_ci 8812c593315Sopenharmony_ci auto t = std::chrono::steady_clock::now(); 8822c593315Sopenharmony_ci 8832c593315Sopenharmony_ci if (tls.last_write_idle.time_since_epoch().count() >= 0 && 8842c593315Sopenharmony_ci t - tls.last_write_idle > tls_dyn_rec_idle_timeout) { 8852c593315Sopenharmony_ci // Time out, use small record size 8862c593315Sopenharmony_ci tls.warmup_writelen = 0; 8872c593315Sopenharmony_ci return SHRPX_SMALL_WRITE_LIMIT; 8882c593315Sopenharmony_ci } 8892c593315Sopenharmony_ci 8902c593315Sopenharmony_ci if (tls.warmup_writelen >= tls_dyn_rec_warmup_threshold) { 8912c593315Sopenharmony_ci return std::numeric_limits<ssize_t>::max(); 8922c593315Sopenharmony_ci } 8932c593315Sopenharmony_ci 8942c593315Sopenharmony_ci return SHRPX_SMALL_WRITE_LIMIT; 8952c593315Sopenharmony_ci} 8962c593315Sopenharmony_ci 8972c593315Sopenharmony_civoid Connection::update_tls_warmup_writelen(size_t n) { 8982c593315Sopenharmony_ci if (tls.warmup_writelen < tls_dyn_rec_warmup_threshold) { 8992c593315Sopenharmony_ci tls.warmup_writelen += n; 9002c593315Sopenharmony_ci } 9012c593315Sopenharmony_ci} 9022c593315Sopenharmony_ci 9032c593315Sopenharmony_civoid Connection::start_tls_write_idle() { 9042c593315Sopenharmony_ci if (tls.last_write_idle.time_since_epoch().count() < 0) { 9052c593315Sopenharmony_ci tls.last_write_idle = std::chrono::steady_clock::now(); 9062c593315Sopenharmony_ci } 9072c593315Sopenharmony_ci} 9082c593315Sopenharmony_ci 9092c593315Sopenharmony_cissize_t Connection::write_tls(const void *data, size_t len) { 9102c593315Sopenharmony_ci // SSL_write requires the same arguments (buf pointer and its 9112c593315Sopenharmony_ci // length) on SSL_ERROR_WANT_READ or SSL_ERROR_WANT_WRITE. 9122c593315Sopenharmony_ci // get_write_limit() may return smaller length than previously 9132c593315Sopenharmony_ci // passed to SSL_write, which violates OpenSSL assumption. To avoid 9142c593315Sopenharmony_ci // this, we keep last length passed to SSL_write to 9152c593315Sopenharmony_ci // tls.last_writelen if SSL_write indicated I/O blocking. 9162c593315Sopenharmony_ci if (tls.last_writelen == 0) { 9172c593315Sopenharmony_ci len = std::min(len, wlimit.avail()); 9182c593315Sopenharmony_ci len = std::min(len, get_tls_write_limit()); 9192c593315Sopenharmony_ci if (len == 0) { 9202c593315Sopenharmony_ci return 0; 9212c593315Sopenharmony_ci } 9222c593315Sopenharmony_ci } else { 9232c593315Sopenharmony_ci len = tls.last_writelen; 9242c593315Sopenharmony_ci tls.last_writelen = 0; 9252c593315Sopenharmony_ci } 9262c593315Sopenharmony_ci 9272c593315Sopenharmony_ci tls.last_write_idle = std::chrono::steady_clock::time_point(-1s); 9282c593315Sopenharmony_ci 9292c593315Sopenharmony_ci auto &tlsconf = get_config()->tls; 9302c593315Sopenharmony_ci auto via_bio = 9312c593315Sopenharmony_ci tls.server_handshake && !tlsconf.session_cache.memcached.host.empty(); 9322c593315Sopenharmony_ci 9332c593315Sopenharmony_ci ERR_clear_error(); 9342c593315Sopenharmony_ci 9352c593315Sopenharmony_ci#if OPENSSL_1_1_1_API && !defined(OPENSSL_IS_BORINGSSL) 9362c593315Sopenharmony_ci int rv; 9372c593315Sopenharmony_ci if (SSL_is_init_finished(tls.ssl)) { 9382c593315Sopenharmony_ci rv = SSL_write(tls.ssl, data, len); 9392c593315Sopenharmony_ci } else { 9402c593315Sopenharmony_ci size_t nwrite; 9412c593315Sopenharmony_ci rv = SSL_write_early_data(tls.ssl, data, len, &nwrite); 9422c593315Sopenharmony_ci // Use the same semantics with SSL_write. 9432c593315Sopenharmony_ci if (rv == 1) { 9442c593315Sopenharmony_ci rv = nwrite; 9452c593315Sopenharmony_ci } 9462c593315Sopenharmony_ci } 9472c593315Sopenharmony_ci#else // !(OPENSSL_1_1_1_API && !defined(OPENSSL_IS_BORINGSSL)) 9482c593315Sopenharmony_ci auto rv = SSL_write(tls.ssl, data, len); 9492c593315Sopenharmony_ci#endif // !(OPENSSL_1_1_1_API && !defined(OPENSSL_IS_BORINGSSL)) 9502c593315Sopenharmony_ci 9512c593315Sopenharmony_ci if (rv <= 0) { 9522c593315Sopenharmony_ci auto err = SSL_get_error(tls.ssl, rv); 9532c593315Sopenharmony_ci switch (err) { 9542c593315Sopenharmony_ci case SSL_ERROR_WANT_READ: 9552c593315Sopenharmony_ci if (LOG_ENABLED(INFO)) { 9562c593315Sopenharmony_ci LOG(INFO) << "Close connection due to TLS renegotiation"; 9572c593315Sopenharmony_ci } 9582c593315Sopenharmony_ci return SHRPX_ERR_NETWORK; 9592c593315Sopenharmony_ci case SSL_ERROR_WANT_WRITE: 9602c593315Sopenharmony_ci tls.last_writelen = len; 9612c593315Sopenharmony_ci // starting write watcher and timer is done in write_clear via 9622c593315Sopenharmony_ci // bio otherwise. 9632c593315Sopenharmony_ci if (!via_bio) { 9642c593315Sopenharmony_ci wlimit.startw(); 9652c593315Sopenharmony_ci ev_timer_again(loop, &wt); 9662c593315Sopenharmony_ci } 9672c593315Sopenharmony_ci 9682c593315Sopenharmony_ci return 0; 9692c593315Sopenharmony_ci case SSL_ERROR_SSL: 9702c593315Sopenharmony_ci if (LOG_ENABLED(INFO)) { 9712c593315Sopenharmony_ci LOG(INFO) << "SSL_write: " 9722c593315Sopenharmony_ci << ERR_error_string(ERR_get_error(), nullptr); 9732c593315Sopenharmony_ci } 9742c593315Sopenharmony_ci return SHRPX_ERR_NETWORK; 9752c593315Sopenharmony_ci default: 9762c593315Sopenharmony_ci if (LOG_ENABLED(INFO)) { 9772c593315Sopenharmony_ci LOG(INFO) << "SSL_write: SSL_get_error returned " << err; 9782c593315Sopenharmony_ci } 9792c593315Sopenharmony_ci return SHRPX_ERR_NETWORK; 9802c593315Sopenharmony_ci } 9812c593315Sopenharmony_ci } 9822c593315Sopenharmony_ci 9832c593315Sopenharmony_ci if (!via_bio) { 9842c593315Sopenharmony_ci wlimit.drain(rv); 9852c593315Sopenharmony_ci 9862c593315Sopenharmony_ci if (ev_is_active(&wt)) { 9872c593315Sopenharmony_ci ev_timer_again(loop, &wt); 9882c593315Sopenharmony_ci } 9892c593315Sopenharmony_ci } 9902c593315Sopenharmony_ci 9912c593315Sopenharmony_ci update_tls_warmup_writelen(rv); 9922c593315Sopenharmony_ci 9932c593315Sopenharmony_ci return rv; 9942c593315Sopenharmony_ci} 9952c593315Sopenharmony_ci 9962c593315Sopenharmony_cissize_t Connection::read_tls(void *data, size_t len) { 9972c593315Sopenharmony_ci ERR_clear_error(); 9982c593315Sopenharmony_ci 9992c593315Sopenharmony_ci#if OPENSSL_1_1_1_API 10002c593315Sopenharmony_ci if (tls.earlybuf.rleft()) { 10012c593315Sopenharmony_ci return tls.earlybuf.remove(data, len); 10022c593315Sopenharmony_ci } 10032c593315Sopenharmony_ci#endif // OPENSSL_1_1_1_API 10042c593315Sopenharmony_ci 10052c593315Sopenharmony_ci // SSL_read requires the same arguments (buf pointer and its 10062c593315Sopenharmony_ci // length) on SSL_ERROR_WANT_READ or SSL_ERROR_WANT_WRITE. 10072c593315Sopenharmony_ci // rlimit_.avail() or rlimit_.avail() may return different length 10082c593315Sopenharmony_ci // than the length previously passed to SSL_read, which violates 10092c593315Sopenharmony_ci // OpenSSL assumption. To avoid this, we keep last length passed 10102c593315Sopenharmony_ci // to SSL_read to tls_last_readlen_ if SSL_read indicated I/O 10112c593315Sopenharmony_ci // blocking. 10122c593315Sopenharmony_ci if (tls.last_readlen == 0) { 10132c593315Sopenharmony_ci len = std::min(len, rlimit.avail()); 10142c593315Sopenharmony_ci if (len == 0) { 10152c593315Sopenharmony_ci return 0; 10162c593315Sopenharmony_ci } 10172c593315Sopenharmony_ci } else { 10182c593315Sopenharmony_ci len = tls.last_readlen; 10192c593315Sopenharmony_ci tls.last_readlen = 0; 10202c593315Sopenharmony_ci } 10212c593315Sopenharmony_ci 10222c593315Sopenharmony_ci auto &tlsconf = get_config()->tls; 10232c593315Sopenharmony_ci auto via_bio = 10242c593315Sopenharmony_ci tls.server_handshake && !tlsconf.session_cache.memcached.host.empty(); 10252c593315Sopenharmony_ci 10262c593315Sopenharmony_ci#if OPENSSL_1_1_1_API && !defined(OPENSSL_IS_BORINGSSL) 10272c593315Sopenharmony_ci if (!tls.early_data_finish) { 10282c593315Sopenharmony_ci // TLSv1.3 handshake is still going on. 10292c593315Sopenharmony_ci size_t nread; 10302c593315Sopenharmony_ci auto rv = SSL_read_early_data(tls.ssl, data, len, &nread); 10312c593315Sopenharmony_ci if (rv == SSL_READ_EARLY_DATA_ERROR) { 10322c593315Sopenharmony_ci auto err = SSL_get_error(tls.ssl, rv); 10332c593315Sopenharmony_ci switch (err) { 10342c593315Sopenharmony_ci case SSL_ERROR_WANT_READ: 10352c593315Sopenharmony_ci tls.last_readlen = len; 10362c593315Sopenharmony_ci return 0; 10372c593315Sopenharmony_ci case SSL_ERROR_SSL: 10382c593315Sopenharmony_ci if (LOG_ENABLED(INFO)) { 10392c593315Sopenharmony_ci LOG(INFO) << "SSL_read: " 10402c593315Sopenharmony_ci << ERR_error_string(ERR_get_error(), nullptr); 10412c593315Sopenharmony_ci } 10422c593315Sopenharmony_ci return SHRPX_ERR_NETWORK; 10432c593315Sopenharmony_ci default: 10442c593315Sopenharmony_ci if (LOG_ENABLED(INFO)) { 10452c593315Sopenharmony_ci LOG(INFO) << "SSL_read: SSL_get_error returned " << err; 10462c593315Sopenharmony_ci } 10472c593315Sopenharmony_ci return SHRPX_ERR_NETWORK; 10482c593315Sopenharmony_ci } 10492c593315Sopenharmony_ci } 10502c593315Sopenharmony_ci 10512c593315Sopenharmony_ci if (LOG_ENABLED(INFO)) { 10522c593315Sopenharmony_ci LOG(INFO) << "tls: read early data " << nread << " bytes"; 10532c593315Sopenharmony_ci } 10542c593315Sopenharmony_ci 10552c593315Sopenharmony_ci if (rv == SSL_READ_EARLY_DATA_FINISH) { 10562c593315Sopenharmony_ci if (LOG_ENABLED(INFO)) { 10572c593315Sopenharmony_ci LOG(INFO) << "tls: read all early data"; 10582c593315Sopenharmony_ci } 10592c593315Sopenharmony_ci tls.early_data_finish = true; 10602c593315Sopenharmony_ci // We may have stopped write watcher in write_tls. 10612c593315Sopenharmony_ci wlimit.startw(); 10622c593315Sopenharmony_ci } 10632c593315Sopenharmony_ci 10642c593315Sopenharmony_ci if (!via_bio) { 10652c593315Sopenharmony_ci rlimit.drain(nread); 10662c593315Sopenharmony_ci } 10672c593315Sopenharmony_ci 10682c593315Sopenharmony_ci return nread; 10692c593315Sopenharmony_ci } 10702c593315Sopenharmony_ci#endif // OPENSSL_1_1_1_API && !defined(OPENSSL_IS_BORINGSSL) 10712c593315Sopenharmony_ci 10722c593315Sopenharmony_ci auto rv = SSL_read(tls.ssl, data, len); 10732c593315Sopenharmony_ci 10742c593315Sopenharmony_ci if (rv <= 0) { 10752c593315Sopenharmony_ci auto err = SSL_get_error(tls.ssl, rv); 10762c593315Sopenharmony_ci switch (err) { 10772c593315Sopenharmony_ci case SSL_ERROR_WANT_READ: 10782c593315Sopenharmony_ci tls.last_readlen = len; 10792c593315Sopenharmony_ci return 0; 10802c593315Sopenharmony_ci case SSL_ERROR_WANT_WRITE: 10812c593315Sopenharmony_ci if (LOG_ENABLED(INFO)) { 10822c593315Sopenharmony_ci LOG(INFO) << "Close connection due to TLS renegotiation"; 10832c593315Sopenharmony_ci } 10842c593315Sopenharmony_ci return SHRPX_ERR_NETWORK; 10852c593315Sopenharmony_ci case SSL_ERROR_ZERO_RETURN: 10862c593315Sopenharmony_ci return SHRPX_ERR_EOF; 10872c593315Sopenharmony_ci case SSL_ERROR_SSL: 10882c593315Sopenharmony_ci if (LOG_ENABLED(INFO)) { 10892c593315Sopenharmony_ci LOG(INFO) << "SSL_read: " << ERR_error_string(ERR_get_error(), nullptr); 10902c593315Sopenharmony_ci } 10912c593315Sopenharmony_ci return SHRPX_ERR_NETWORK; 10922c593315Sopenharmony_ci default: 10932c593315Sopenharmony_ci if (LOG_ENABLED(INFO)) { 10942c593315Sopenharmony_ci LOG(INFO) << "SSL_read: SSL_get_error returned " << err; 10952c593315Sopenharmony_ci } 10962c593315Sopenharmony_ci return SHRPX_ERR_NETWORK; 10972c593315Sopenharmony_ci } 10982c593315Sopenharmony_ci } 10992c593315Sopenharmony_ci 11002c593315Sopenharmony_ci if (!via_bio) { 11012c593315Sopenharmony_ci rlimit.drain(rv); 11022c593315Sopenharmony_ci } 11032c593315Sopenharmony_ci 11042c593315Sopenharmony_ci return rv; 11052c593315Sopenharmony_ci} 11062c593315Sopenharmony_ci 11072c593315Sopenharmony_cissize_t Connection::write_clear(const void *data, size_t len) { 11082c593315Sopenharmony_ci len = std::min(len, wlimit.avail()); 11092c593315Sopenharmony_ci if (len == 0) { 11102c593315Sopenharmony_ci return 0; 11112c593315Sopenharmony_ci } 11122c593315Sopenharmony_ci 11132c593315Sopenharmony_ci ssize_t nwrite; 11142c593315Sopenharmony_ci while ((nwrite = write(fd, data, len)) == -1 && errno == EINTR) 11152c593315Sopenharmony_ci ; 11162c593315Sopenharmony_ci if (nwrite == -1) { 11172c593315Sopenharmony_ci if (errno == EAGAIN || errno == EWOULDBLOCK) { 11182c593315Sopenharmony_ci wlimit.startw(); 11192c593315Sopenharmony_ci ev_timer_again(loop, &wt); 11202c593315Sopenharmony_ci return 0; 11212c593315Sopenharmony_ci } 11222c593315Sopenharmony_ci return SHRPX_ERR_NETWORK; 11232c593315Sopenharmony_ci } 11242c593315Sopenharmony_ci 11252c593315Sopenharmony_ci wlimit.drain(nwrite); 11262c593315Sopenharmony_ci 11272c593315Sopenharmony_ci if (ev_is_active(&wt)) { 11282c593315Sopenharmony_ci ev_timer_again(loop, &wt); 11292c593315Sopenharmony_ci } 11302c593315Sopenharmony_ci 11312c593315Sopenharmony_ci return nwrite; 11322c593315Sopenharmony_ci} 11332c593315Sopenharmony_ci 11342c593315Sopenharmony_cissize_t Connection::writev_clear(struct iovec *iov, int iovcnt) { 11352c593315Sopenharmony_ci iovcnt = limit_iovec(iov, iovcnt, wlimit.avail()); 11362c593315Sopenharmony_ci if (iovcnt == 0) { 11372c593315Sopenharmony_ci return 0; 11382c593315Sopenharmony_ci } 11392c593315Sopenharmony_ci 11402c593315Sopenharmony_ci ssize_t nwrite; 11412c593315Sopenharmony_ci while ((nwrite = writev(fd, iov, iovcnt)) == -1 && errno == EINTR) 11422c593315Sopenharmony_ci ; 11432c593315Sopenharmony_ci if (nwrite == -1) { 11442c593315Sopenharmony_ci if (errno == EAGAIN || errno == EWOULDBLOCK) { 11452c593315Sopenharmony_ci wlimit.startw(); 11462c593315Sopenharmony_ci ev_timer_again(loop, &wt); 11472c593315Sopenharmony_ci return 0; 11482c593315Sopenharmony_ci } 11492c593315Sopenharmony_ci return SHRPX_ERR_NETWORK; 11502c593315Sopenharmony_ci } 11512c593315Sopenharmony_ci 11522c593315Sopenharmony_ci wlimit.drain(nwrite); 11532c593315Sopenharmony_ci 11542c593315Sopenharmony_ci if (ev_is_active(&wt)) { 11552c593315Sopenharmony_ci ev_timer_again(loop, &wt); 11562c593315Sopenharmony_ci } 11572c593315Sopenharmony_ci 11582c593315Sopenharmony_ci return nwrite; 11592c593315Sopenharmony_ci} 11602c593315Sopenharmony_ci 11612c593315Sopenharmony_cissize_t Connection::read_clear(void *data, size_t len) { 11622c593315Sopenharmony_ci len = std::min(len, rlimit.avail()); 11632c593315Sopenharmony_ci if (len == 0) { 11642c593315Sopenharmony_ci return 0; 11652c593315Sopenharmony_ci } 11662c593315Sopenharmony_ci 11672c593315Sopenharmony_ci ssize_t nread; 11682c593315Sopenharmony_ci while ((nread = read(fd, data, len)) == -1 && errno == EINTR) 11692c593315Sopenharmony_ci ; 11702c593315Sopenharmony_ci if (nread == -1) { 11712c593315Sopenharmony_ci if (errno == EAGAIN || errno == EWOULDBLOCK) { 11722c593315Sopenharmony_ci return 0; 11732c593315Sopenharmony_ci } 11742c593315Sopenharmony_ci return SHRPX_ERR_NETWORK; 11752c593315Sopenharmony_ci } 11762c593315Sopenharmony_ci 11772c593315Sopenharmony_ci if (nread == 0) { 11782c593315Sopenharmony_ci return SHRPX_ERR_EOF; 11792c593315Sopenharmony_ci } 11802c593315Sopenharmony_ci 11812c593315Sopenharmony_ci rlimit.drain(nread); 11822c593315Sopenharmony_ci 11832c593315Sopenharmony_ci return nread; 11842c593315Sopenharmony_ci} 11852c593315Sopenharmony_ci 11862c593315Sopenharmony_cissize_t Connection::read_nolim_clear(void *data, size_t len) { 11872c593315Sopenharmony_ci ssize_t nread; 11882c593315Sopenharmony_ci while ((nread = read(fd, data, len)) == -1 && errno == EINTR) 11892c593315Sopenharmony_ci ; 11902c593315Sopenharmony_ci if (nread == -1) { 11912c593315Sopenharmony_ci if (errno == EAGAIN || errno == EWOULDBLOCK) { 11922c593315Sopenharmony_ci return 0; 11932c593315Sopenharmony_ci } 11942c593315Sopenharmony_ci return SHRPX_ERR_NETWORK; 11952c593315Sopenharmony_ci } 11962c593315Sopenharmony_ci 11972c593315Sopenharmony_ci if (nread == 0) { 11982c593315Sopenharmony_ci return SHRPX_ERR_EOF; 11992c593315Sopenharmony_ci } 12002c593315Sopenharmony_ci 12012c593315Sopenharmony_ci return nread; 12022c593315Sopenharmony_ci} 12032c593315Sopenharmony_ci 12042c593315Sopenharmony_cissize_t Connection::peek_clear(void *data, size_t len) { 12052c593315Sopenharmony_ci ssize_t nread; 12062c593315Sopenharmony_ci while ((nread = recv(fd, data, len, MSG_PEEK)) == -1 && errno == EINTR) 12072c593315Sopenharmony_ci ; 12082c593315Sopenharmony_ci if (nread == -1) { 12092c593315Sopenharmony_ci if (errno == EAGAIN || errno == EWOULDBLOCK) { 12102c593315Sopenharmony_ci return 0; 12112c593315Sopenharmony_ci } 12122c593315Sopenharmony_ci return SHRPX_ERR_NETWORK; 12132c593315Sopenharmony_ci } 12142c593315Sopenharmony_ci 12152c593315Sopenharmony_ci if (nread == 0) { 12162c593315Sopenharmony_ci return SHRPX_ERR_EOF; 12172c593315Sopenharmony_ci } 12182c593315Sopenharmony_ci 12192c593315Sopenharmony_ci return nread; 12202c593315Sopenharmony_ci} 12212c593315Sopenharmony_ci 12222c593315Sopenharmony_civoid Connection::handle_tls_pending_read() { 12232c593315Sopenharmony_ci if (!ev_is_active(&rev)) { 12242c593315Sopenharmony_ci return; 12252c593315Sopenharmony_ci } 12262c593315Sopenharmony_ci rlimit.handle_tls_pending_read(); 12272c593315Sopenharmony_ci} 12282c593315Sopenharmony_ci 12292c593315Sopenharmony_ciint Connection::get_tcp_hint(TCPHint *hint) const { 12302c593315Sopenharmony_ci#if defined(TCP_INFO) && defined(TCP_NOTSENT_LOWAT) 12312c593315Sopenharmony_ci struct tcp_info tcp_info; 12322c593315Sopenharmony_ci socklen_t tcp_info_len = sizeof(tcp_info); 12332c593315Sopenharmony_ci int rv; 12342c593315Sopenharmony_ci 12352c593315Sopenharmony_ci rv = getsockopt(fd, IPPROTO_TCP, TCP_INFO, &tcp_info, &tcp_info_len); 12362c593315Sopenharmony_ci 12372c593315Sopenharmony_ci if (rv != 0) { 12382c593315Sopenharmony_ci return -1; 12392c593315Sopenharmony_ci } 12402c593315Sopenharmony_ci 12412c593315Sopenharmony_ci auto avail_packets = tcp_info.tcpi_snd_cwnd > tcp_info.tcpi_unacked 12422c593315Sopenharmony_ci ? tcp_info.tcpi_snd_cwnd - tcp_info.tcpi_unacked 12432c593315Sopenharmony_ci : 0; 12442c593315Sopenharmony_ci 12452c593315Sopenharmony_ci // http://www.slideshare.net/kazuho/programming-tcp-for-responsiveness 12462c593315Sopenharmony_ci 12472c593315Sopenharmony_ci // TODO 29 (5 (header) + 8 (explicit nonce) + 16 (tag)) is TLS 12482c593315Sopenharmony_ci // overhead for AES-GCM. For CHACHA20_POLY1305, it is 21 since it 12492c593315Sopenharmony_ci // does not need 8 bytes explicit nonce. 12502c593315Sopenharmony_ci // 12512c593315Sopenharmony_ci // For TLSv1.3, AES-GCM and CHACHA20_POLY1305 overhead are now 22 12522c593315Sopenharmony_ci // bytes (5 (header) + 1 (ContentType) + 16 (tag)). 12532c593315Sopenharmony_ci size_t tls_overhead; 12542c593315Sopenharmony_ci# ifdef TLS1_3_VERSION 12552c593315Sopenharmony_ci if (SSL_version(tls.ssl) == TLS1_3_VERSION) { 12562c593315Sopenharmony_ci tls_overhead = 22; 12572c593315Sopenharmony_ci } else 12582c593315Sopenharmony_ci# endif // TLS1_3_VERSION 12592c593315Sopenharmony_ci { 12602c593315Sopenharmony_ci tls_overhead = 29; 12612c593315Sopenharmony_ci } 12622c593315Sopenharmony_ci 12632c593315Sopenharmony_ci auto writable_size = 12642c593315Sopenharmony_ci (avail_packets + 2) * (tcp_info.tcpi_snd_mss - tls_overhead); 12652c593315Sopenharmony_ci if (writable_size > 16_k) { 12662c593315Sopenharmony_ci writable_size = writable_size & ~(16_k - 1); 12672c593315Sopenharmony_ci } else { 12682c593315Sopenharmony_ci if (writable_size < 536) { 12692c593315Sopenharmony_ci LOG(INFO) << "writable_size is too small: " << writable_size; 12702c593315Sopenharmony_ci } 12712c593315Sopenharmony_ci // TODO is this required? 12722c593315Sopenharmony_ci writable_size = std::max(writable_size, static_cast<size_t>(536 * 2)); 12732c593315Sopenharmony_ci } 12742c593315Sopenharmony_ci 12752c593315Sopenharmony_ci // if (LOG_ENABLED(INFO)) { 12762c593315Sopenharmony_ci // LOG(INFO) << "snd_cwnd=" << tcp_info.tcpi_snd_cwnd 12772c593315Sopenharmony_ci // << ", unacked=" << tcp_info.tcpi_unacked 12782c593315Sopenharmony_ci // << ", snd_mss=" << tcp_info.tcpi_snd_mss 12792c593315Sopenharmony_ci // << ", rtt=" << tcp_info.tcpi_rtt << "us" 12802c593315Sopenharmony_ci // << ", rcv_space=" << tcp_info.tcpi_rcv_space 12812c593315Sopenharmony_ci // << ", writable=" << writable_size; 12822c593315Sopenharmony_ci // } 12832c593315Sopenharmony_ci 12842c593315Sopenharmony_ci hint->write_buffer_size = writable_size; 12852c593315Sopenharmony_ci // TODO tcpi_rcv_space is considered as rwin, is that correct? 12862c593315Sopenharmony_ci hint->rwin = tcp_info.tcpi_rcv_space; 12872c593315Sopenharmony_ci 12882c593315Sopenharmony_ci return 0; 12892c593315Sopenharmony_ci#else // !defined(TCP_INFO) || !defined(TCP_NOTSENT_LOWAT) 12902c593315Sopenharmony_ci return -1; 12912c593315Sopenharmony_ci#endif // !defined(TCP_INFO) || !defined(TCP_NOTSENT_LOWAT) 12922c593315Sopenharmony_ci} 12932c593315Sopenharmony_ci 12942c593315Sopenharmony_civoid Connection::again_rt(ev_tstamp t) { 12952c593315Sopenharmony_ci read_timeout = t; 12962c593315Sopenharmony_ci rt.repeat = t; 12972c593315Sopenharmony_ci ev_timer_again(loop, &rt); 12982c593315Sopenharmony_ci last_read = std::chrono::steady_clock::now(); 12992c593315Sopenharmony_ci} 13002c593315Sopenharmony_ci 13012c593315Sopenharmony_civoid Connection::again_rt() { 13022c593315Sopenharmony_ci rt.repeat = read_timeout; 13032c593315Sopenharmony_ci ev_timer_again(loop, &rt); 13042c593315Sopenharmony_ci last_read = std::chrono::steady_clock::now(); 13052c593315Sopenharmony_ci} 13062c593315Sopenharmony_ci 13072c593315Sopenharmony_cibool Connection::expired_rt() { 13082c593315Sopenharmony_ci auto delta = read_timeout - util::ev_tstamp_from( 13092c593315Sopenharmony_ci std::chrono::steady_clock::now() - last_read); 13102c593315Sopenharmony_ci if (delta < 1e-9) { 13112c593315Sopenharmony_ci return true; 13122c593315Sopenharmony_ci } 13132c593315Sopenharmony_ci rt.repeat = delta; 13142c593315Sopenharmony_ci ev_timer_again(loop, &rt); 13152c593315Sopenharmony_ci return false; 13162c593315Sopenharmony_ci} 13172c593315Sopenharmony_ci 13182c593315Sopenharmony_ci} // namespace shrpx 1319