diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index aca359c9..7c0e1deb 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -116,7 +116,7 @@ jobs: - name: Build nghttp3 if: matrix.http3 == 'http3' run: | - git clone --depth 1 -b v0.2.0 https://github.com/ngtcp2/nghttp3 + git clone --depth 1 -b v0.3.0 https://github.com/ngtcp2/nghttp3 cd nghttp3 autoreconf -i ./configure --prefix=$PWD/build --enable-lib-only @@ -125,7 +125,7 @@ jobs: - name: Build ngtcp2 if: matrix.http3 == 'http3' run: | - git clone --depth 1 -b v0.2.1 https://github.com/ngtcp2/ngtcp2 + git clone --depth 1 -b v0.3.0 https://github.com/ngtcp2/ngtcp2 cd ngtcp2 autoreconf -i ./configure --prefix=$PWD/build --enable-lib-only PKG_CONFIG_PATH="../openssl/build/lib/pkgconfig" diff --git a/README.rst b/README.rst index 6e9ef143..110bd2fd 100644 --- a/README.rst +++ b/README.rst @@ -154,7 +154,7 @@ following libraries are required: `_; or `BoringSSL `_ (commit 36a41bf0bf2dd3176f8780e09c03585351f29963) -* `ngtcp2 `_ >= 0.2.0 +* `ngtcp2 `_ >= 0.3.0 * `nghttp3 `_ >= 0.2.0 Use ``--enable-http3`` configure option to enable HTTP/3 feature for @@ -378,7 +378,7 @@ Build ngtcp2: .. code-block:: text - $ git clone --depth 1 -b v0.2.1 https://github.com/ngtcp2/ngtcp2 + $ git clone --depth 1 -b v0.3.0 https://github.com/ngtcp2/ngtcp2 $ cd ngtcp2 $ autoreconf -i $ ./configure --prefix=$PWD/build --enable-lib-only \ diff --git a/configure.ac b/configure.ac index be5e5a63..e387f728 100644 --- a/configure.ac +++ b/configure.ac @@ -540,7 +540,7 @@ fi # ngtcp2 (for src) have_libngtcp2=no if test "x${request_libngtcp2}" != "xno"; then - PKG_CHECK_MODULES([LIBNGTCP2], [libngtcp2 >= 0.2.0], [have_libngtcp2=yes], + PKG_CHECK_MODULES([LIBNGTCP2], [libngtcp2 >= 0.3.0], [have_libngtcp2=yes], [have_libngtcp2=no]) if test "x${have_libngtcp2}" = "xno"; then AC_MSG_NOTICE($LIBNGTCP2_PKG_ERRORS) @@ -557,7 +557,7 @@ have_libngtcp2_crypto_openssl=no if test "x${have_ssl_is_quic}" = "xyes" && test "x${request_libngtcp2}" != "xno"; then PKG_CHECK_MODULES([LIBNGTCP2_CRYPTO_OPENSSL], - [libngtcp2_crypto_openssl >= 0.2.0], + [libngtcp2_crypto_openssl >= 0.3.0], [have_libngtcp2_crypto_openssl=yes], [have_libngtcp2_crypto_openssl=no]) if test "x${have_libngtcp2_crypto_openssl}" = "xno"; then diff --git a/src/h2load.cc b/src/h2load.cc index e2234597..00a11c2a 100644 --- a/src/h2load.cc +++ b/src/h2load.cc @@ -499,6 +499,8 @@ Client::Client(uint32_t id, Worker *worker, size_t req_todo) if (config.is_quic()) { quic.tx.data = std::make_unique(64_k); } + + ngtcp2_connection_close_error_default(&quic.last_error); #endif // ENABLE_HTTP3 } diff --git a/src/h2load.h b/src/h2load.h index 60bcb3c4..df0d06a1 100644 --- a/src/h2load.h +++ b/src/h2load.h @@ -339,7 +339,7 @@ struct Client { struct { ev_timer pkt_timer; ngtcp2_conn *conn; - quic::Error last_error; + ngtcp2_connection_close_error last_error; bool close_requested; FILE *qlog_file; diff --git a/src/h2load_http3_session.cc b/src/h2load_http3_session.cc index 6ca1e419..0e87573d 100644 --- a/src/h2load_http3_session.cc +++ b/src/h2load_http3_session.cc @@ -370,7 +370,9 @@ ssize_t Http3Session::read_stream(uint32_t flags, int64_t stream_id, if (nconsumed < 0) { std::cerr << "nghttp3_conn_read_stream: " << nghttp3_strerror(nconsumed) << std::endl; - client_->quic.last_error = quic::err_application(nconsumed); + ngtcp2_connection_close_error_set_application_error( + &client_->quic.last_error, + nghttp3_err_infer_quic_app_error_code(nconsumed), nullptr, 0); return -1; } return nconsumed; @@ -381,7 +383,9 @@ ssize_t Http3Session::write_stream(int64_t &stream_id, int &fin, auto sveccnt = nghttp3_conn_writev_stream(conn_, &stream_id, &fin, vec, veccnt); if (sveccnt < 0) { - client_->quic.last_error = quic::err_application(sveccnt); + ngtcp2_connection_close_error_set_application_error( + &client_->quic.last_error, + nghttp3_err_infer_quic_app_error_code(sveccnt), nullptr, 0); return -1; } return sveccnt; @@ -390,7 +394,9 @@ ssize_t Http3Session::write_stream(int64_t &stream_id, int &fin, int Http3Session::block_stream(int64_t stream_id) { auto rv = nghttp3_conn_block_stream(conn_, stream_id); if (rv != 0) { - client_->quic.last_error = quic::err_application(rv); + ngtcp2_connection_close_error_set_application_error( + &client_->quic.last_error, nghttp3_err_infer_quic_app_error_code(rv), + nullptr, 0); return -1; } return 0; @@ -399,7 +405,9 @@ int Http3Session::block_stream(int64_t stream_id) { int Http3Session::shutdown_stream_write(int64_t stream_id) { auto rv = nghttp3_conn_shutdown_stream_write(conn_, stream_id); if (rv != 0) { - client_->quic.last_error = quic::err_application(rv); + ngtcp2_connection_close_error_set_application_error( + &client_->quic.last_error, nghttp3_err_infer_quic_app_error_code(rv), + nullptr, 0); return -1; } return 0; @@ -408,7 +416,9 @@ int Http3Session::shutdown_stream_write(int64_t stream_id) { int Http3Session::add_write_offset(int64_t stream_id, size_t ndatalen) { auto rv = nghttp3_conn_add_write_offset(conn_, stream_id, ndatalen); if (rv != 0) { - client_->quic.last_error = quic::err_application(rv); + ngtcp2_connection_close_error_set_application_error( + &client_->quic.last_error, nghttp3_err_infer_quic_app_error_code(rv), + nullptr, 0); return -1; } return 0; @@ -417,7 +427,9 @@ int Http3Session::add_write_offset(int64_t stream_id, size_t ndatalen) { int Http3Session::add_ack_offset(int64_t stream_id, size_t datalen) { auto rv = nghttp3_conn_add_ack_offset(conn_, stream_id, datalen); if (rv != 0) { - client_->quic.last_error = quic::err_application(rv); + ngtcp2_connection_close_error_set_application_error( + &client_->quic.last_error, nghttp3_err_infer_quic_app_error_code(rv), + nullptr, 0); return -1; } return 0; diff --git a/src/h2load_quic.cc b/src/h2load_quic.cc index 86579496..8c22f1ce 100644 --- a/src/h2load_quic.cc +++ b/src/h2load_quic.cc @@ -465,7 +465,6 @@ int Client::quic_init(const sockaddr *local_addr, socklen_t local_addrlen, } if (config->max_udp_payload_size) { settings.max_udp_payload_size = config->max_udp_payload_size; - settings.no_udp_payload_size_shaping = 1; } ngtcp2_transport_params params; @@ -525,29 +524,14 @@ void Client::quic_close_connection() { } std::array buf; - ngtcp2_ssize nwrite; ngtcp2_path_storage ps; ngtcp2_path_storage_zero(&ps); - switch (quic.last_error.type) { - case quic::ErrorType::TransportVersionNegotiation: - return; - case quic::ErrorType::Transport: - nwrite = ngtcp2_conn_write_connection_close( - quic.conn, &ps.path, nullptr, buf.data(), buf.size(), - quic.last_error.code, nullptr, 0, timestamp(worker->loop)); - break; - case quic::ErrorType::Application: - nwrite = ngtcp2_conn_write_application_close( - quic.conn, &ps.path, nullptr, buf.data(), buf.size(), - quic.last_error.code, nullptr, 0, timestamp(worker->loop)); - break; - default: - assert(0); - abort(); - } + auto nwrite = ngtcp2_conn_write_connection_close( + quic.conn, &ps.path, nullptr, buf.data(), buf.size(), &quic.last_error, + timestamp(worker->loop)); - if (nwrite < 0) { + if (nwrite <= 0) { return; } @@ -590,7 +574,8 @@ int Client::quic_on_tx_secret(ngtcp2_crypto_level level, const uint8_t *secret, } void Client::quic_set_tls_alert(uint8_t alert) { - quic.last_error = quic::err_transport_tls(alert); + ngtcp2_connection_close_error_set_transport_error_tls_alert( + &quic.last_error, alert, nullptr, 0); } void Client::quic_write_client_handshake(ngtcp2_crypto_level level, @@ -617,7 +602,8 @@ int Client::quic_pkt_timeout() { rv = ngtcp2_conn_handle_expiry(quic.conn, now); if (rv != 0) { - quic.last_error = quic::err_transport(NGTCP2_ERR_INTERNAL); + ngtcp2_connection_close_error_set_transport_error_liberr(&quic.last_error, + rv, nullptr, 0); return -1; } @@ -668,8 +654,9 @@ int Client::read_quic() { if (rv != 0) { std::cerr << "ngtcp2_conn_read_pkt: " << ngtcp2_strerror(rv) << std::endl; - if (!quic.last_error.code) { - quic.last_error = quic::err_transport(rv); + if (!quic.last_error.error_code) { + ngtcp2_connection_close_error_set_transport_error_liberr( + &quic.last_error, rv, nullptr, 0); } return -1; @@ -705,8 +692,7 @@ int Client::write_quic() { std::array vec; size_t pktcnt = 0; - auto max_udp_payload_size = - ngtcp2_conn_get_path_max_udp_payload_size(quic.conn); + auto max_udp_payload_size = ngtcp2_conn_get_max_udp_payload_size(quic.conn); size_t max_pktcnt = #ifdef UDP_SEGMENT worker->config->no_udp_gso @@ -770,7 +756,8 @@ int Client::write_quic() { continue; } - quic.last_error = quic::err_transport(nwrite); + ngtcp2_connection_close_error_set_transport_error_liberr( + &quic.last_error, nwrite, nullptr, 0); return -1; } else if (ndatalen >= 0 && s->add_write_offset(stream_id, ndatalen) != 0) { return -1; diff --git a/src/shrpx_http3_upstream.cc b/src/shrpx_http3_upstream.cc index 86f18aee..a15662b2 100644 --- a/src/shrpx_http3_upstream.cc +++ b/src/shrpx_http3_upstream.cc @@ -118,7 +118,6 @@ size_t downstream_queue_size(Worker *worker) { Http3Upstream::Http3Upstream(ClientHandler *handler) : handler_{handler}, - max_udp_payload_size_{SHRPX_QUIC_MAX_UDP_PAYLOAD_SIZE}, qlog_fd_{-1}, hashed_scid_{}, conn_{nullptr}, @@ -134,6 +133,8 @@ Http3Upstream::Http3Upstream(ClientHandler *handler) ev_timer_init(&timer_, timeoutcb, 0., 0.); timer_.data = this; + ngtcp2_connection_close_error_default(&last_error_); + auto config = get_config(); auto &quicconf = config->quic; @@ -300,7 +301,9 @@ int Http3Upstream::recv_stream_data(uint32_t flags, int64_t stream_id, if (nconsumed < 0) { ULOG(ERROR, this) << "nghttp3_conn_read_stream: " << nghttp3_strerror(nconsumed); - last_error_ = quic::err_application(nconsumed); + ngtcp2_connection_close_error_set_application_error( + &last_error_, nghttp3_err_infer_quic_app_error_code(nconsumed), nullptr, + 0); return -1; } @@ -344,7 +347,8 @@ int Http3Upstream::stream_close(int64_t stream_id, uint64_t app_error_code) { break; default: ULOG(ERROR, this) << "nghttp3_conn_close_stream: " << nghttp3_strerror(rv); - last_error_ = quic::err_application(rv); + ngtcp2_connection_close_error_set_application_error( + &last_error_, nghttp3_err_infer_quic_app_error_code(rv), nullptr, 0); return -1; } @@ -600,7 +604,6 @@ int Http3Upstream::init(const UpstreamAddr *faddr, const Address &remote_addr, settings.max_window = http3conf.upstream.max_connection_window_size; settings.max_stream_window = http3conf.upstream.max_window_size; settings.max_udp_payload_size = SHRPX_QUIC_MAX_UDP_PAYLOAD_SIZE; - settings.assume_symmetric_path = 1; settings.rand_ctx.native_handle = &worker->get_randgen(); settings.token = ngtcp2_vec{const_cast(token), tokenlen}; @@ -727,8 +730,7 @@ int Http3Upstream::on_write() { int Http3Upstream::write_streams() { std::array vec; - auto max_udp_payload_size = std::min( - max_udp_payload_size_, ngtcp2_conn_get_path_max_udp_payload_size(conn_)); + auto max_udp_payload_size = ngtcp2_conn_get_max_udp_payload_size(conn_); size_t max_pktcnt = std::min(static_cast(64_k), ngtcp2_conn_get_send_quantum(conn_)) / max_udp_payload_size; @@ -764,7 +766,9 @@ int Http3Upstream::write_streams() { if (sveccnt < 0) { ULOG(ERROR, this) << "nghttp3_conn_writev_stream: " << nghttp3_strerror(sveccnt); - last_error_ = quic::err_application(sveccnt); + ngtcp2_connection_close_error_set_application_error( + &last_error_, nghttp3_err_infer_quic_app_error_code(sveccnt), + nullptr, 0); return handle_error(); } } @@ -789,7 +793,9 @@ int Http3Upstream::write_streams() { if (rv != 0) { ULOG(ERROR, this) << "nghttp3_conn_block_stream: " << nghttp3_strerror(rv); - last_error_ = quic::err_application(rv); + ngtcp2_connection_close_error_set_application_error( + &last_error_, nghttp3_err_infer_quic_app_error_code(rv), nullptr, + 0); return handle_error(); } continue; @@ -799,7 +805,9 @@ int Http3Upstream::write_streams() { if (rv != 0) { ULOG(ERROR, this) << "nghttp3_conn_shutdown_stream_write: " << nghttp3_strerror(rv); - last_error_ = quic::err_application(rv); + ngtcp2_connection_close_error_set_application_error( + &last_error_, nghttp3_err_infer_quic_app_error_code(rv), nullptr, + 0); return handle_error(); } continue; @@ -809,7 +817,9 @@ int Http3Upstream::write_streams() { if (rv != 0) { ULOG(ERROR, this) << "nghttp3_conn_add_write_offset: " << nghttp3_strerror(rv); - last_error_ = quic::err_application(rv); + ngtcp2_connection_close_error_set_application_error( + &last_error_, nghttp3_err_infer_quic_app_error_code(rv), nullptr, + 0); return handle_error(); } continue; @@ -820,7 +830,8 @@ int Http3Upstream::write_streams() { ULOG(ERROR, this) << "ngtcp2_conn_writev_stream: " << ngtcp2_strerror(nwrite); - last_error_ = quic::err_transport(nwrite); + ngtcp2_connection_close_error_set_transport_error_liberr( + &last_error_, nwrite, nullptr, 0); return handle_error(); } else if (ndatalen >= 0) { @@ -828,7 +839,9 @@ int Http3Upstream::write_streams() { if (rv != 0) { ULOG(ERROR, this) << "nghttp3_conn_add_write_offset: " << nghttp3_strerror(rv); - last_error_ = quic::err_application(rv); + ngtcp2_connection_close_error_set_application_error( + &last_error_, nghttp3_err_infer_quic_app_error_code(rv), nullptr, + 0); return handle_error(); } } @@ -1506,9 +1519,12 @@ void Http3Upstream::on_handler_delete() { ngtcp2_path_storage_zero(&ps); + ngtcp2_connection_close_error ccerr; + ngtcp2_connection_close_error_default(&ccerr); + auto nwrite = ngtcp2_conn_write_connection_close( - conn_, &ps.path, &pi, conn_close_.data(), conn_close_.size(), - NGTCP2_NO_ERROR, nullptr, 0, quic_timestamp()); + conn_, &ps.path, &pi, conn_close_.data(), conn_close_.size(), &ccerr, + quic_timestamp()); if (nwrite < 0) { if (nwrite != NGTCP2_ERR_INVALID_STATE) { ULOG(ERROR, this) << "ngtcp2_conn_write_connection_close: " @@ -1804,13 +1820,15 @@ int Http3Upstream::on_read(const UpstreamAddr *faddr, // If rv indicates transport_parameters related error, we should // send TRANSPORT_PARAMETER_ERROR even if last_error_.code is // already set. This is because OpenSSL might set Alert. - last_error_ = quic::err_transport(rv); + ngtcp2_connection_close_error_set_transport_error_liberr(&last_error_, rv, + nullptr, 0); break; case NGTCP2_ERR_DROP_CONN: return -1; default: - if (!last_error_.code) { - last_error_ = quic::err_transport(rv); + if (!last_error_.error_code) { + ngtcp2_connection_close_error_set_transport_error_liberr( + &last_error_, rv, nullptr, 0); } } @@ -1838,7 +1856,7 @@ int Http3Upstream::send_packet(const UpstreamAddr *faddr, // large. case -EINVAL: case -EMSGSIZE: - max_udp_payload_size_ = NGTCP2_MAX_UDP_PAYLOAD_SIZE; + // Let the packet lost. break; case -EAGAIN: #if EAGAIN != EWOULDBLOCK @@ -1930,30 +1948,21 @@ int Http3Upstream::handle_error() { conn_close_.resize(SHRPX_QUIC_CONN_CLOSE_PKTLEN); - ngtcp2_ssize nwrite; - - if (last_error_.type == quic::ErrorType::Transport) { - nwrite = ngtcp2_conn_write_connection_close( - conn_, &ps.path, &pi, conn_close_.data(), conn_close_.size(), - last_error_.code, nullptr, 0, ts); - if (nwrite < 0) { - ULOG(ERROR, this) << "ngtcp2_conn_write_connection_close: " - << ngtcp2_strerror(nwrite); - return -1; - } - } else { - nwrite = ngtcp2_conn_write_application_close( - conn_, &ps.path, &pi, conn_close_.data(), conn_close_.size(), - last_error_.code, nullptr, 0, ts); - if (nwrite < 0) { - ULOG(ERROR, this) << "ngtcp2_conn_write_application_close: " - << ngtcp2_strerror(nwrite); - return -1; - } + auto nwrite = ngtcp2_conn_write_connection_close( + conn_, &ps.path, &pi, conn_close_.data(), conn_close_.size(), + &last_error_, ts); + if (nwrite < 0) { + ULOG(ERROR, this) << "ngtcp2_conn_write_connection_close: " + << ngtcp2_strerror(nwrite); + return -1; } conn_close_.resize(nwrite); + if (nwrite == 0) { + return -1; + } + send_packet(static_cast(ps.path.user_data), ps.path.remote.addr, ps.path.remote.addrlen, ps.path.local.addr, ps.path.local.addrlen, pi, conn_close_.data(), nwrite, 0); @@ -2010,7 +2019,8 @@ int Http3Upstream::handle_expiry() { rv = ngtcp2_conn_handle_expiry(conn_, ts); if (rv != 0) { ULOG(ERROR, this) << "ngtcp2_conn_handle_expiry: " << ngtcp2_strerror(rv); - last_error_ = quic::err_transport(rv); + ngtcp2_connection_close_error_set_transport_error_liberr(&last_error_, rv, + nullptr, 0); return handle_error(); } diff --git a/src/shrpx_http3_upstream.h b/src/shrpx_http3_upstream.h index 3759ede2..253dea5e 100644 --- a/src/shrpx_http3_upstream.h +++ b/src/shrpx_http3_upstream.h @@ -171,11 +171,10 @@ private: ev_timer idle_timer_; ev_timer shutdown_timer_; ev_prepare prep_; - size_t max_udp_payload_size_; int qlog_fd_; ngtcp2_cid hashed_scid_; ngtcp2_conn *conn_; - quic::Error last_error_; + ngtcp2_connection_close_error last_error_; uint8_t tls_alert_; nghttp3_conn *httpconn_; DownstreamQueue downstream_queue_;