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