Bump ngtcp2 and nghttp3
This commit is contained in:
parent
e6cf62664d
commit
3849337b42
|
@ -119,7 +119,7 @@ jobs:
|
|||
- name: Build nghttp3
|
||||
if: matrix.http3 == 'http3'
|
||||
run: |
|
||||
git clone --depth 1 -b v0.4.1 https://github.com/ngtcp2/nghttp3
|
||||
git clone --depth 1 -b v0.5.0 https://github.com/ngtcp2/nghttp3
|
||||
cd nghttp3
|
||||
autoreconf -i
|
||||
./configure --prefix=$PWD/build --enable-lib-only
|
||||
|
@ -128,7 +128,7 @@ jobs:
|
|||
- name: Build ngtcp2
|
||||
if: matrix.http3 == 'http3'
|
||||
run: |
|
||||
git clone --depth 1 -b v0.5.0 https://github.com/ngtcp2/ngtcp2
|
||||
git clone --depth 1 -b v0.6.0 https://github.com/ngtcp2/ngtcp2
|
||||
cd ngtcp2
|
||||
autoreconf -i
|
||||
./configure --prefix=$PWD/build --enable-lib-only PKG_CONFIG_PATH="../openssl/build/lib/pkgconfig"
|
||||
|
|
|
@ -154,7 +154,7 @@ following libraries are required:
|
|||
<https://github.com/quictls/openssl/tree/OpenSSL_1_1_1o+quic>`_; or
|
||||
`BoringSSL <https://boringssl.googlesource.com/boringssl/>`_ (commit
|
||||
36a41bf0bf2dd3176f8780e09c03585351f29963)
|
||||
* `ngtcp2 <https://github.com/ngtcp2/ngtcp2>`_ >= 0.5.0
|
||||
* `ngtcp2 <https://github.com/ngtcp2/ngtcp2>`_ >= 0.6.0
|
||||
* `nghttp3 <https://github.com/ngtcp2/nghttp3>`_ >= 0.4.0
|
||||
|
||||
Use ``--enable-http3`` configure option to enable HTTP/3 feature for
|
||||
|
@ -366,7 +366,7 @@ Build nghttp3:
|
|||
|
||||
.. code-block:: text
|
||||
|
||||
$ git clone --depth 1 -b v0.4.1 https://github.com/ngtcp2/nghttp3
|
||||
$ git clone --depth 1 -b v0.5.0 https://github.com/ngtcp2/nghttp3
|
||||
$ cd nghttp3
|
||||
$ autoreconf -i
|
||||
$ ./configure --prefix=$PWD/build --enable-lib-only
|
||||
|
@ -378,7 +378,7 @@ Build ngtcp2:
|
|||
|
||||
.. code-block:: text
|
||||
|
||||
$ git clone --depth 1 -b v0.5.0 https://github.com/ngtcp2/ngtcp2
|
||||
$ git clone --depth 1 -b v0.6.0 https://github.com/ngtcp2/ngtcp2
|
||||
$ cd ngtcp2
|
||||
$ autoreconf -i
|
||||
$ ./configure --prefix=$PWD/build --enable-lib-only \
|
||||
|
|
|
@ -540,7 +540,7 @@ fi
|
|||
# ngtcp2 (for src)
|
||||
have_libngtcp2=no
|
||||
if test "x${request_libngtcp2}" != "xno"; then
|
||||
PKG_CHECK_MODULES([LIBNGTCP2], [libngtcp2 >= 0.5.0], [have_libngtcp2=yes],
|
||||
PKG_CHECK_MODULES([LIBNGTCP2], [libngtcp2 >= 0.6.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.5.0],
|
||||
[libngtcp2_crypto_openssl >= 0.6.0],
|
||||
[have_libngtcp2_crypto_openssl=yes],
|
||||
[have_libngtcp2_crypto_openssl=no])
|
||||
if test "x${have_libngtcp2_crypto_openssl}" = "xno"; then
|
||||
|
|
|
@ -15,7 +15,7 @@ RUN git clone --depth 1 -b OpenSSL_1_1_1o+quic https://github.com/quictls/openss
|
|||
cd .. && \
|
||||
rm -rf openssl
|
||||
|
||||
RUN git clone --depth 1 -b v0.4.1 https://github.com/ngtcp2/nghttp3 && \
|
||||
RUN git clone --depth 1 -b v0.5.0 https://github.com/ngtcp2/nghttp3 && \
|
||||
cd nghttp3 && \
|
||||
autoreconf -i && \
|
||||
./configure --enable-lib-only && \
|
||||
|
@ -24,7 +24,7 @@ RUN git clone --depth 1 -b v0.4.1 https://github.com/ngtcp2/nghttp3 && \
|
|||
cd .. && \
|
||||
rm -rf nghttp3
|
||||
|
||||
RUN git clone --depth 1 -b v0.5.0 https://github.com/ngtcp2/ngtcp2 && \
|
||||
RUN git clone --depth 1 -b v0.6.0 https://github.com/ngtcp2/ngtcp2 && \
|
||||
cd ngtcp2 && \
|
||||
autoreconf -i && \
|
||||
./configure --enable-lib-only \
|
||||
|
|
|
@ -51,8 +51,13 @@
|
|||
#include <openssl/err.h>
|
||||
|
||||
#ifdef ENABLE_HTTP3
|
||||
# include <ngtcp2/ngtcp2.h>
|
||||
#endif // ENABLE_HTTP3
|
||||
# ifdef HAVE_LIBNGTCP2_CRYPTO_OPENSSL
|
||||
# include <ngtcp2/ngtcp2_crypto_openssl.h>
|
||||
# endif // HAVE_LIBNGTCP2_CRYPTO_OPENSSL
|
||||
# ifdef HAVE_LIBNGTCP2_CRYPTO_BORINGSSL
|
||||
# include <ngtcp2/ngtcp2_crypto_boringssl.h>
|
||||
# endif // HAVE_LIBNGTCP2_CRYPTO_BORINGSSL
|
||||
#endif // ENABLE_HTTP3
|
||||
|
||||
#include "url-parser/url_parser.h"
|
||||
|
||||
|
@ -724,12 +729,17 @@ void Client::disconnect() {
|
|||
ev_io_stop(worker->loop, &wev);
|
||||
ev_io_stop(worker->loop, &rev);
|
||||
if (ssl) {
|
||||
SSL_set_shutdown(ssl, SSL_get_shutdown(ssl) | SSL_RECEIVED_SHUTDOWN);
|
||||
ERR_clear_error();
|
||||
|
||||
if (SSL_shutdown(ssl) != 1) {
|
||||
if (config.is_quic()) {
|
||||
SSL_free(ssl);
|
||||
ssl = nullptr;
|
||||
} else {
|
||||
SSL_set_shutdown(ssl, SSL_get_shutdown(ssl) | SSL_RECEIVED_SHUTDOWN);
|
||||
ERR_clear_error();
|
||||
|
||||
if (SSL_shutdown(ssl) != 1) {
|
||||
SSL_free(ssl);
|
||||
ssl = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (fd != -1) {
|
||||
|
@ -2878,9 +2888,21 @@ int main(int argc, char **argv) {
|
|||
|
||||
if (config.is_quic()) {
|
||||
#ifdef ENABLE_HTTP3
|
||||
SSL_CTX_set_min_proto_version(ssl_ctx, TLS1_3_VERSION);
|
||||
SSL_CTX_set_max_proto_version(ssl_ctx, TLS1_3_VERSION);
|
||||
#endif // ENABLE_HTTP3
|
||||
# ifdef HAVE_LIBNGTCP2_CRYPTO_OPENSSL
|
||||
if (ngtcp2_crypto_openssl_configure_client_context(ssl_ctx) != 0) {
|
||||
std::cerr << "ngtcp2_crypto_openssl_configure_client_context failed"
|
||||
<< std::endl;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
# endif // HAVE_LIBNGTCP2_CRYPTO_OPENSSL
|
||||
# ifdef HAVE_LIBNGTCP2_CRYPTO_BORINGSSL
|
||||
if (ngtcp2_crypto_boringssl_configure_client_context(ssl_ctx) != 0) {
|
||||
std::cerr << "ngtcp2_crypto_boringssl_configure_client_context failed"
|
||||
<< std::endl;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
# endif // HAVE_LIBNGTCP2_CRYPTO_BORINGSSL
|
||||
#endif // ENABLE_HTTP3
|
||||
} else if (nghttp2::tls::ssl_ctx_set_proto_versions(
|
||||
ssl_ctx, nghttp2::tls::NGHTTP2_TLS_MIN_VERSION,
|
||||
nghttp2::tls::NGHTTP2_TLS_MAX_VERSION) != 0) {
|
||||
|
|
|
@ -339,10 +339,10 @@ struct Client {
|
|||
SSL *ssl;
|
||||
#ifdef ENABLE_HTTP3
|
||||
struct {
|
||||
ngtcp2_crypto_conn_ref conn_ref;
|
||||
ev_timer pkt_timer;
|
||||
ngtcp2_conn *conn;
|
||||
ngtcp2_connection_close_error last_error;
|
||||
uint8_t tls_alert;
|
||||
bool close_requested;
|
||||
FILE *qlog_file;
|
||||
|
||||
|
@ -495,17 +495,12 @@ struct Client {
|
|||
int quic_stream_stop_sending(int64_t stream_id, uint64_t app_error_code);
|
||||
int quic_extend_max_local_streams();
|
||||
|
||||
int quic_on_rx_secret(ngtcp2_crypto_level level, const uint8_t *secret,
|
||||
size_t secretlen);
|
||||
int quic_on_tx_secret(ngtcp2_crypto_level level, const uint8_t *secret,
|
||||
size_t secretlen);
|
||||
void quic_set_tls_alert(uint8_t alert);
|
||||
|
||||
int quic_write_client_handshake(ngtcp2_crypto_level level,
|
||||
const uint8_t *data, size_t datalen);
|
||||
int quic_pkt_timeout();
|
||||
void quic_restart_pkt_timer();
|
||||
void quic_write_qlog(const void *data, size_t datalen);
|
||||
int quic_make_http3_session();
|
||||
#endif // ENABLE_HTTP3
|
||||
};
|
||||
|
||||
|
|
|
@ -243,127 +243,6 @@ ngtcp2_tstamp timestamp(struct ev_loop *loop) {
|
|||
}
|
||||
} // namespace
|
||||
|
||||
#ifdef HAVE_LIBNGTCP2_CRYPTO_OPENSSL
|
||||
namespace {
|
||||
int set_encryption_secrets(SSL *ssl, OSSL_ENCRYPTION_LEVEL ossl_level,
|
||||
const uint8_t *rx_secret, const uint8_t *tx_secret,
|
||||
size_t secret_len) {
|
||||
auto c = static_cast<Client *>(SSL_get_app_data(ssl));
|
||||
auto level = ngtcp2_crypto_openssl_from_ossl_encryption_level(ossl_level);
|
||||
|
||||
if (c->quic_on_rx_secret(level, rx_secret, secret_len) != 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (c->quic_on_tx_secret(level, tx_secret, secret_len) != 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
namespace {
|
||||
int add_handshake_data(SSL *ssl, OSSL_ENCRYPTION_LEVEL ossl_level,
|
||||
const uint8_t *data, size_t len) {
|
||||
auto c = static_cast<Client *>(SSL_get_app_data(ssl));
|
||||
if (c->quic_write_client_handshake(
|
||||
ngtcp2_crypto_openssl_from_ossl_encryption_level(ossl_level), data,
|
||||
len) != 0) {
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
namespace {
|
||||
int flush_flight(SSL *ssl) { return 1; }
|
||||
} // namespace
|
||||
|
||||
namespace {
|
||||
int send_alert(SSL *ssl, enum ssl_encryption_level_t level, uint8_t alert) {
|
||||
auto c = static_cast<Client *>(SSL_get_app_data(ssl));
|
||||
c->quic_set_tls_alert(alert);
|
||||
return 1;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
namespace {
|
||||
auto quic_method = SSL_QUIC_METHOD{
|
||||
set_encryption_secrets,
|
||||
add_handshake_data,
|
||||
flush_flight,
|
||||
send_alert,
|
||||
};
|
||||
} // namespace
|
||||
#endif // HAVE_LIBNGTCP2_CRYPTO_OPENSSL
|
||||
|
||||
#ifdef HAVE_LIBNGTCP2_CRYPTO_BORINGSSL
|
||||
namespace {
|
||||
int set_read_secret(SSL *ssl, ssl_encryption_level_t ssl_level,
|
||||
const SSL_CIPHER *cipher, const uint8_t *secret,
|
||||
size_t secretlen) {
|
||||
auto c = static_cast<Client *>(SSL_get_app_data(ssl));
|
||||
|
||||
if (c->quic_on_rx_secret(
|
||||
ngtcp2_crypto_boringssl_from_ssl_encryption_level(ssl_level), secret,
|
||||
secretlen) != 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
namespace {
|
||||
int set_write_secret(SSL *ssl, ssl_encryption_level_t ssl_level,
|
||||
const SSL_CIPHER *cipher, const uint8_t *secret,
|
||||
size_t secretlen) {
|
||||
auto c = static_cast<Client *>(SSL_get_app_data(ssl));
|
||||
|
||||
if (c->quic_on_tx_secret(
|
||||
ngtcp2_crypto_boringssl_from_ssl_encryption_level(ssl_level), secret,
|
||||
secretlen) != 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
namespace {
|
||||
int add_handshake_data(SSL *ssl, ssl_encryption_level_t ssl_level,
|
||||
const uint8_t *data, size_t len) {
|
||||
auto c = static_cast<Client *>(SSL_get_app_data(ssl));
|
||||
if (c->quic_write_client_handshake(
|
||||
ngtcp2_crypto_boringssl_from_ssl_encryption_level(ssl_level), data,
|
||||
len) != 0) {
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
namespace {
|
||||
int flush_flight(SSL *ssl) { return 1; }
|
||||
} // namespace
|
||||
|
||||
namespace {
|
||||
int send_alert(SSL *ssl, ssl_encryption_level_t level, uint8_t alert) {
|
||||
auto c = static_cast<Client *>(SSL_get_app_data(ssl));
|
||||
c->quic_set_tls_alert(alert);
|
||||
return 1;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
namespace {
|
||||
auto quic_method = SSL_QUIC_METHOD{
|
||||
set_read_secret, set_write_secret, add_handshake_data,
|
||||
flush_flight, send_alert,
|
||||
};
|
||||
} // namespace
|
||||
#endif // HAVE_LIBNGTCP2_CRYPTO_BORINGSSL
|
||||
|
||||
// qlog write callback -- excerpted from ngtcp2/examples/client_base.cc
|
||||
namespace {
|
||||
void qlog_write_cb(void *user_data, uint32_t flags, const void *data,
|
||||
|
@ -385,6 +264,39 @@ void rand(uint8_t *dest, size_t destlen, const ngtcp2_rand_ctx *rand_ctx) {
|
|||
}
|
||||
} // namespace
|
||||
|
||||
namespace {
|
||||
int recv_rx_key(ngtcp2_conn *conn, ngtcp2_crypto_level level, void *user_data) {
|
||||
if (level != NGTCP2_CRYPTO_LEVEL_APPLICATION) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
auto c = static_cast<Client *>(user_data);
|
||||
|
||||
if (c->quic_make_http3_session() != 0) {
|
||||
return NGTCP2_ERR_CALLBACK_FAILURE;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
int Client::quic_make_http3_session() {
|
||||
auto s = std::make_unique<Http3Session>(this);
|
||||
if (s->init_conn() == -1) {
|
||||
return -1;
|
||||
}
|
||||
session = std::move(s);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
namespace {
|
||||
ngtcp2_conn *get_conn(ngtcp2_crypto_conn_ref *conn_ref) {
|
||||
auto c = static_cast<Client *>(conn_ref->user_data);
|
||||
return c->quic.conn;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
int Client::quic_init(const sockaddr *local_addr, socklen_t local_addrlen,
|
||||
const sockaddr *remote_addr, socklen_t remote_addrlen) {
|
||||
int rv;
|
||||
|
@ -392,9 +304,11 @@ int Client::quic_init(const sockaddr *local_addr, socklen_t local_addrlen,
|
|||
if (!ssl) {
|
||||
ssl = SSL_new(worker->ssl_ctx);
|
||||
|
||||
SSL_set_app_data(ssl, this);
|
||||
quic.conn_ref.get_conn = get_conn;
|
||||
quic.conn_ref.user_data = this;
|
||||
|
||||
SSL_set_app_data(ssl, &quic.conn_ref);
|
||||
SSL_set_connect_state(ssl);
|
||||
SSL_set_quic_method(ssl, &quic_method);
|
||||
SSL_set_quic_use_legacy_codepoint(ssl, 0);
|
||||
}
|
||||
|
||||
|
@ -435,6 +349,9 @@ int Client::quic_init(const sockaddr *local_addr, socklen_t local_addrlen,
|
|||
nullptr, // lost_datagram
|
||||
ngtcp2_crypto_get_path_challenge_data_cb,
|
||||
h2load::stream_stop_sending,
|
||||
nullptr, // version_negotiation
|
||||
h2load::recv_rx_key,
|
||||
nullptr, // recv_tx_key
|
||||
};
|
||||
|
||||
ngtcp2_cid scid, dcid;
|
||||
|
@ -546,42 +463,6 @@ void Client::quic_close_connection() {
|
|||
ps.path.remote.addrlen, buf.data(), nwrite, 0);
|
||||
}
|
||||
|
||||
int Client::quic_on_rx_secret(ngtcp2_crypto_level level, const uint8_t *secret,
|
||||
size_t secretlen) {
|
||||
if (ngtcp2_crypto_derive_and_install_rx_key(quic.conn, nullptr, nullptr,
|
||||
nullptr, level, secret,
|
||||
secretlen) != 0) {
|
||||
std::cerr << "ngtcp2_crypto_derive_and_install_rx_key() failed"
|
||||
<< std::endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (level == NGTCP2_CRYPTO_LEVEL_APPLICATION) {
|
||||
auto s = std::make_unique<Http3Session>(this);
|
||||
if (s->init_conn() == -1) {
|
||||
return -1;
|
||||
}
|
||||
session = std::move(s);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Client::quic_on_tx_secret(ngtcp2_crypto_level level, const uint8_t *secret,
|
||||
size_t secretlen) {
|
||||
if (ngtcp2_crypto_derive_and_install_tx_key(quic.conn, nullptr, nullptr,
|
||||
nullptr, level, secret,
|
||||
secretlen) != 0) {
|
||||
std::cerr << "ngtcp2_crypto_derive_and_install_tx_key() failed"
|
||||
<< std::endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Client::quic_set_tls_alert(uint8_t alert) { quic.tls_alert = alert; }
|
||||
|
||||
int Client::quic_write_client_handshake(ngtcp2_crypto_level level,
|
||||
const uint8_t *data, size_t datalen) {
|
||||
int rv;
|
||||
|
@ -670,7 +551,8 @@ int Client::read_quic() {
|
|||
if (!quic.last_error.error_code) {
|
||||
if (rv == NGTCP2_ERR_CRYPTO) {
|
||||
ngtcp2_connection_close_error_set_transport_error_tls_alert(
|
||||
&quic.last_error, quic.tls_alert, nullptr, 0);
|
||||
&quic.last_error, ngtcp2_conn_get_tls_alert(quic.conn), nullptr,
|
||||
0);
|
||||
} else {
|
||||
ngtcp2_connection_close_error_set_transport_error_liberr(
|
||||
&quic.last_error, rv, nullptr, 0);
|
||||
|
|
|
@ -60,7 +60,11 @@ Connection::Connection(struct ev_loop *loop, int fd, SSL *ssl,
|
|||
IOCb readcb, TimerCb timeoutcb, void *data,
|
||||
size_t tls_dyn_rec_warmup_threshold,
|
||||
ev_tstamp tls_dyn_rec_idle_timeout, Proto proto)
|
||||
: tls{DefaultMemchunks(mcpool), DefaultPeekMemchunks(mcpool),
|
||||
:
|
||||
#ifdef ENABLE_HTTP3
|
||||
conn_ref{nullptr, this},
|
||||
#endif // ENABLE_HTTP3
|
||||
tls{DefaultMemchunks(mcpool), DefaultPeekMemchunks(mcpool),
|
||||
DefaultMemchunks(mcpool)},
|
||||
wlimit(loop, &wev, write_limit.rate, write_limit.burst),
|
||||
rlimit(loop, &rev, read_limit.rate, read_limit.burst, this),
|
||||
|
@ -97,21 +101,24 @@ Connection::~Connection() { disconnect(); }
|
|||
|
||||
void Connection::disconnect() {
|
||||
if (tls.ssl) {
|
||||
SSL_set_shutdown(tls.ssl,
|
||||
SSL_get_shutdown(tls.ssl) | SSL_RECEIVED_SHUTDOWN);
|
||||
ERR_clear_error();
|
||||
if (proto != Proto::HTTP3) {
|
||||
SSL_set_shutdown(tls.ssl,
|
||||
SSL_get_shutdown(tls.ssl) | SSL_RECEIVED_SHUTDOWN);
|
||||
ERR_clear_error();
|
||||
|
||||
if (tls.cached_session) {
|
||||
SSL_SESSION_free(tls.cached_session);
|
||||
tls.cached_session = nullptr;
|
||||
if (tls.cached_session) {
|
||||
SSL_SESSION_free(tls.cached_session);
|
||||
tls.cached_session = nullptr;
|
||||
}
|
||||
|
||||
if (tls.cached_session_lookup_req) {
|
||||
tls.cached_session_lookup_req->canceled = true;
|
||||
tls.cached_session_lookup_req = nullptr;
|
||||
}
|
||||
|
||||
SSL_shutdown(tls.ssl);
|
||||
}
|
||||
|
||||
if (tls.cached_session_lookup_req) {
|
||||
tls.cached_session_lookup_req->canceled = true;
|
||||
tls.cached_session_lookup_req = nullptr;
|
||||
}
|
||||
|
||||
SSL_shutdown(tls.ssl);
|
||||
SSL_free(tls.ssl);
|
||||
tls.ssl = nullptr;
|
||||
|
||||
|
|
|
@ -33,6 +33,10 @@
|
|||
|
||||
#include <openssl/ssl.h>
|
||||
|
||||
#ifdef ENABLE_HTTP3
|
||||
# include <ngtcp2/ngtcp2_crypto.h>
|
||||
#endif // ENABLE_HTTP3
|
||||
|
||||
#include "shrpx_rate_limit.h"
|
||||
#include "shrpx_error.h"
|
||||
#include "memchunk.h"
|
||||
|
@ -155,6 +159,10 @@ struct Connection {
|
|||
// Returns true if read timer expired.
|
||||
bool expired_rt();
|
||||
|
||||
#ifdef ENABLE_HTTP3
|
||||
// This must be the first member of Connection.
|
||||
ngtcp2_crypto_conn_ref conn_ref;
|
||||
#endif // ENABLE_HTTP3
|
||||
TLSConnection tls;
|
||||
ev_io wev;
|
||||
ev_io rev;
|
||||
|
@ -178,6 +186,11 @@ struct Connection {
|
|||
ev_tstamp read_timeout;
|
||||
};
|
||||
|
||||
#ifdef ENABLE_HTTP3
|
||||
static_assert(std::is_standard_layout<Connection>::value,
|
||||
"Conneciton is not standard layout");
|
||||
#endif // ENABLE_HTTP3
|
||||
|
||||
// Creates BIO_method shared by all SSL objects.
|
||||
BIO_METHOD *create_bio_method();
|
||||
|
||||
|
|
|
@ -100,12 +100,20 @@ size_t downstream_queue_size(Worker *worker) {
|
|||
}
|
||||
} // namespace
|
||||
|
||||
namespace {
|
||||
ngtcp2_conn *get_conn(ngtcp2_crypto_conn_ref *conn_ref) {
|
||||
auto conn = static_cast<Connection *>(conn_ref->user_data);
|
||||
auto handler = static_cast<ClientHandler *>(conn->data);
|
||||
auto upstream = static_cast<Http3Upstream *>(handler->get_upstream());
|
||||
return upstream->get_conn();
|
||||
}
|
||||
} // namespace
|
||||
|
||||
Http3Upstream::Http3Upstream(ClientHandler *handler)
|
||||
: handler_{handler},
|
||||
qlog_fd_{-1},
|
||||
hashed_scid_{},
|
||||
conn_{nullptr},
|
||||
tls_alert_{0},
|
||||
httpconn_{nullptr},
|
||||
downstream_queue_{downstream_queue_size(handler->get_worker()),
|
||||
!get_config()->http2_proxy},
|
||||
|
@ -113,6 +121,9 @@ Http3Upstream::Http3Upstream(ClientHandler *handler)
|
|||
tx_{
|
||||
.data = std::unique_ptr<uint8_t[]>(new uint8_t[64_k]),
|
||||
} {
|
||||
auto conn = handler_->get_connection();
|
||||
conn->conn_ref.get_conn = shrpx::get_conn;
|
||||
|
||||
ev_timer_init(&timer_, timeoutcb, 0., 0.);
|
||||
timer_.data = this;
|
||||
|
||||
|
@ -493,6 +504,21 @@ int Http3Upstream::handshake_completed() {
|
|||
return 0;
|
||||
}
|
||||
|
||||
namespace {
|
||||
int recv_tx_key(ngtcp2_conn *conn, ngtcp2_crypto_level level, void *user_data) {
|
||||
if (level != NGTCP2_CRYPTO_LEVEL_APPLICATION) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
auto upstream = static_cast<Http3Upstream *>(user_data);
|
||||
if (upstream->setup_httpconn() != 0) {
|
||||
return NGTCP2_ERR_CALLBACK_FAILURE;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
int Http3Upstream::init(const UpstreamAddr *faddr, const Address &remote_addr,
|
||||
const Address &local_addr,
|
||||
const ngtcp2_pkt_hd &initial_hd,
|
||||
|
@ -540,6 +566,9 @@ int Http3Upstream::init(const UpstreamAddr *faddr, const Address &remote_addr,
|
|||
nullptr, // lost_datagram
|
||||
ngtcp2_crypto_get_path_challenge_data_cb,
|
||||
shrpx::stream_stop_sending,
|
||||
nullptr, // version_negotiation
|
||||
nullptr, // recv_rx_key
|
||||
shrpx::recv_tx_key,
|
||||
};
|
||||
|
||||
auto config = get_config();
|
||||
|
@ -1795,7 +1824,7 @@ int Http3Upstream::on_read(const UpstreamAddr *faddr,
|
|||
case NGTCP2_ERR_CRYPTO:
|
||||
if (!last_error_.error_code) {
|
||||
ngtcp2_connection_close_error_set_transport_error_tls_alert(
|
||||
&last_error_, tls_alert_, nullptr, 0);
|
||||
&last_error_, ngtcp2_conn_get_tls_alert(conn_), nullptr, 0);
|
||||
}
|
||||
break;
|
||||
case NGTCP2_ERR_DROP_CONN:
|
||||
|
@ -1944,47 +1973,6 @@ int Http3Upstream::handle_error() {
|
|||
return -1;
|
||||
}
|
||||
|
||||
int Http3Upstream::on_rx_secret(ngtcp2_crypto_level level,
|
||||
const uint8_t *secret, size_t secretlen) {
|
||||
if (ngtcp2_crypto_derive_and_install_rx_key(conn_, nullptr, nullptr, nullptr,
|
||||
level, secret, secretlen) != 0) {
|
||||
ULOG(ERROR, this) << "ngtcp2_crypto_derive_and_install_rx_key failed";
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Http3Upstream::on_tx_secret(ngtcp2_crypto_level level,
|
||||
const uint8_t *secret, size_t secretlen) {
|
||||
if (ngtcp2_crypto_derive_and_install_tx_key(conn_, nullptr, nullptr, nullptr,
|
||||
level, secret, secretlen) != 0) {
|
||||
ULOG(ERROR, this) << "ngtcp2_crypto_derive_and_install_tx_key failed";
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (level == NGTCP2_CRYPTO_LEVEL_APPLICATION && setup_httpconn() != 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Http3Upstream::add_crypto_data(ngtcp2_crypto_level level,
|
||||
const uint8_t *data, size_t datalen) {
|
||||
int rv = ngtcp2_conn_submit_crypto_data(conn_, level, data, datalen);
|
||||
|
||||
if (rv != 0) {
|
||||
ULOG(ERROR, this) << "ngtcp2_conn_submit_crypto_data: "
|
||||
<< ngtcp2_strerror(rv);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Http3Upstream::set_tls_alert(uint8_t alert) { tls_alert_ = alert; }
|
||||
|
||||
int Http3Upstream::handle_expiry() {
|
||||
int rv;
|
||||
|
||||
|
@ -2646,11 +2634,10 @@ int Http3Upstream::setup_httpconn() {
|
|||
return -1;
|
||||
}
|
||||
|
||||
ngtcp2_transport_params params;
|
||||
ngtcp2_conn_get_local_transport_params(conn_, ¶ms);
|
||||
auto params = ngtcp2_conn_get_local_transport_params(conn_);
|
||||
|
||||
nghttp3_conn_set_max_client_streams_bidi(httpconn_,
|
||||
params.initial_max_streams_bidi);
|
||||
params->initial_max_streams_bidi);
|
||||
|
||||
int64_t ctrl_stream_id;
|
||||
|
||||
|
@ -2933,4 +2920,6 @@ int Http3Upstream::open_qlog_file(const StringRef &dir,
|
|||
return fd;
|
||||
}
|
||||
|
||||
ngtcp2_conn *Http3Upstream::get_conn() const { return conn_; }
|
||||
|
||||
} // namespace shrpx
|
||||
|
|
|
@ -97,16 +97,6 @@ public:
|
|||
|
||||
int write_streams();
|
||||
|
||||
int on_rx_secret(ngtcp2_crypto_level level, const uint8_t *secret,
|
||||
size_t secretlen);
|
||||
int on_tx_secret(ngtcp2_crypto_level level, const uint8_t *secret,
|
||||
size_t secretlen);
|
||||
|
||||
int add_crypto_data(ngtcp2_crypto_level level, const uint8_t *data,
|
||||
size_t datalen);
|
||||
|
||||
void set_tls_alert(uint8_t alert);
|
||||
|
||||
int handle_error();
|
||||
|
||||
int handle_expiry();
|
||||
|
@ -162,6 +152,8 @@ public:
|
|||
int send_blocked_packet();
|
||||
void signal_write_upstream_addr(const UpstreamAddr *faddr);
|
||||
|
||||
ngtcp2_conn *get_conn() const;
|
||||
|
||||
private:
|
||||
ClientHandler *handler_;
|
||||
ev_timer timer_;
|
||||
|
@ -171,7 +163,6 @@ private:
|
|||
ngtcp2_cid hashed_scid_;
|
||||
ngtcp2_conn *conn_;
|
||||
ngtcp2_connection_close_error last_error_;
|
||||
uint8_t tls_alert_;
|
||||
nghttp3_conn *httpconn_;
|
||||
DownstreamQueue downstream_queue_;
|
||||
bool retry_close_;
|
||||
|
|
159
src/shrpx_tls.cc
159
src/shrpx_tls.cc
|
@ -1219,149 +1219,6 @@ SSL_CTX *create_ssl_context(const char *private_key_file, const char *cert_file,
|
|||
}
|
||||
|
||||
#ifdef ENABLE_HTTP3
|
||||
# ifdef HAVE_LIBNGTCP2_CRYPTO_OPENSSL
|
||||
namespace {
|
||||
int quic_set_encryption_secrets(SSL *ssl, OSSL_ENCRYPTION_LEVEL ossl_level,
|
||||
const uint8_t *rx_secret,
|
||||
const uint8_t *tx_secret, size_t secretlen) {
|
||||
auto conn = static_cast<Connection *>(SSL_get_app_data(ssl));
|
||||
auto handler = static_cast<ClientHandler *>(conn->data);
|
||||
auto upstream = static_cast<Http3Upstream *>(handler->get_upstream());
|
||||
auto level = ngtcp2_crypto_openssl_from_ossl_encryption_level(ossl_level);
|
||||
|
||||
if (upstream->on_rx_secret(level, rx_secret, secretlen) != 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (tx_secret && upstream->on_tx_secret(level, tx_secret, secretlen) != 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
namespace {
|
||||
int quic_add_handshake_data(SSL *ssl, OSSL_ENCRYPTION_LEVEL ossl_level,
|
||||
const uint8_t *data, size_t len) {
|
||||
auto conn = static_cast<Connection *>(SSL_get_app_data(ssl));
|
||||
auto handler = static_cast<ClientHandler *>(conn->data);
|
||||
auto upstream = static_cast<Http3Upstream *>(handler->get_upstream());
|
||||
auto level = ngtcp2_crypto_openssl_from_ossl_encryption_level(ossl_level);
|
||||
|
||||
upstream->add_crypto_data(level, data, len);
|
||||
|
||||
return 1;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
namespace {
|
||||
int quic_flush_flight(SSL *ssl) { return 1; }
|
||||
} // namespace
|
||||
|
||||
namespace {
|
||||
int quic_send_alert(SSL *ssl, OSSL_ENCRYPTION_LEVEL ossl_level, uint8_t alert) {
|
||||
auto conn = static_cast<Connection *>(SSL_get_app_data(ssl));
|
||||
auto handler = static_cast<ClientHandler *>(conn->data);
|
||||
auto upstream = static_cast<Http3Upstream *>(handler->get_upstream());
|
||||
|
||||
if (!upstream) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
upstream->set_tls_alert(alert);
|
||||
|
||||
return 1;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
namespace {
|
||||
auto quic_method = SSL_QUIC_METHOD{
|
||||
quic_set_encryption_secrets,
|
||||
quic_add_handshake_data,
|
||||
quic_flush_flight,
|
||||
quic_send_alert,
|
||||
};
|
||||
} // namespace
|
||||
# endif // HAVE_LIBNGTCP2_CRYPTO_OPENSSL
|
||||
|
||||
# ifdef HAVE_LIBNGTCP2_CRYPTO_BORINGSSL
|
||||
namespace {
|
||||
int quic_set_read_secret(SSL *ssl, ssl_encryption_level_t ssl_level,
|
||||
const SSL_CIPHER *cipher, const uint8_t *secret,
|
||||
size_t secretlen) {
|
||||
auto conn = static_cast<Connection *>(SSL_get_app_data(ssl));
|
||||
auto handler = static_cast<ClientHandler *>(conn->data);
|
||||
auto upstream = static_cast<Http3Upstream *>(handler->get_upstream());
|
||||
auto level = ngtcp2_crypto_boringssl_from_ssl_encryption_level(ssl_level);
|
||||
|
||||
if (upstream->on_rx_secret(level, secret, secretlen) != 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
namespace {
|
||||
int quic_set_write_secret(SSL *ssl, ssl_encryption_level_t ssl_level,
|
||||
const SSL_CIPHER *cipher, const uint8_t *secret,
|
||||
size_t secretlen) {
|
||||
auto conn = static_cast<Connection *>(SSL_get_app_data(ssl));
|
||||
auto handler = static_cast<ClientHandler *>(conn->data);
|
||||
auto upstream = static_cast<Http3Upstream *>(handler->get_upstream());
|
||||
auto level = ngtcp2_crypto_boringssl_from_ssl_encryption_level(ssl_level);
|
||||
|
||||
if (upstream->on_tx_secret(level, secret, secretlen) != 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
namespace {
|
||||
int quic_add_handshake_data(SSL *ssl, ssl_encryption_level_t ssl_level,
|
||||
const uint8_t *data, size_t len) {
|
||||
auto conn = static_cast<Connection *>(SSL_get_app_data(ssl));
|
||||
auto handler = static_cast<ClientHandler *>(conn->data);
|
||||
auto upstream = static_cast<Http3Upstream *>(handler->get_upstream());
|
||||
auto level = ngtcp2_crypto_boringssl_from_ssl_encryption_level(ssl_level);
|
||||
|
||||
upstream->add_crypto_data(level, data, len);
|
||||
|
||||
return 1;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
namespace {
|
||||
int quic_flush_flight(SSL *ssl) { return 1; }
|
||||
} // namespace
|
||||
|
||||
namespace {
|
||||
int quic_send_alert(SSL *ssl, ssl_encryption_level_t level, uint8_t alert) {
|
||||
auto conn = static_cast<Connection *>(SSL_get_app_data(ssl));
|
||||
auto handler = static_cast<ClientHandler *>(conn->data);
|
||||
auto upstream = static_cast<Http3Upstream *>(handler->get_upstream());
|
||||
|
||||
if (!upstream) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
upstream->set_tls_alert(alert);
|
||||
|
||||
return 1;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
namespace {
|
||||
auto quic_method = SSL_QUIC_METHOD{
|
||||
quic_set_read_secret, quic_set_write_secret, quic_add_handshake_data,
|
||||
quic_flush_flight, quic_send_alert,
|
||||
};
|
||||
} // namespace
|
||||
# endif // HAVE_LIBNGTCP2_CRYPTO_BORINGSSL
|
||||
|
||||
SSL_CTX *create_quic_ssl_context(const char *private_key_file,
|
||||
const char *cert_file,
|
||||
const std::vector<uint8_t> &sct_data
|
||||
|
@ -1396,8 +1253,18 @@ SSL_CTX *create_quic_ssl_context(const char *private_key_file,
|
|||
|
||||
SSL_CTX_set_options(ssl_ctx, ssl_opts);
|
||||
|
||||
SSL_CTX_set_min_proto_version(ssl_ctx, TLS1_3_VERSION);
|
||||
SSL_CTX_set_max_proto_version(ssl_ctx, TLS1_3_VERSION);
|
||||
# ifdef HAVE_LIBNGTCP2_CRYPTO_OPENSSL
|
||||
if (ngtcp2_crypto_openssl_configure_server_context(ssl_ctx) != 0) {
|
||||
LOG(FATAL) << "ngtcp2_crypto_openssl_configure_server_context failed";
|
||||
DIE();
|
||||
}
|
||||
# endif // HAVE_LIBNGTCP2_CRYPTO_OPENSSL
|
||||
# ifdef HAVE_LIBNGTCP2_CRYPTO_BORINGSSL
|
||||
if (ngtcp2_crypto_boringssl_configure_server_context(ssl_ctx) != 0) {
|
||||
LOG(FATAL) << "ngtcp2_crypto_boringssl_configure_server_context failed";
|
||||
DIE();
|
||||
}
|
||||
# endif // HAVE_LIBNGTCP2_CRYPTO_BORINGSSL
|
||||
|
||||
const unsigned char sid_ctx[] = "shrpx";
|
||||
SSL_CTX_set_session_id_context(ssl_ctx, sid_ctx, sizeof(sid_ctx) - 1);
|
||||
|
@ -1638,8 +1505,6 @@ SSL_CTX *create_quic_ssl_context(const char *private_key_file,
|
|||
SSL_CTX_set_psk_server_callback(ssl_ctx, psk_server_cb);
|
||||
# endif // !LIBRESSL_NO_PSK
|
||||
|
||||
SSL_CTX_set_quic_method(ssl_ctx, &quic_method);
|
||||
|
||||
return ssl_ctx;
|
||||
}
|
||||
#endif // ENABLE_HTTP3
|
||||
|
|
Loading…
Reference in New Issue