diff --git a/README.rst b/README.rst index cdb64208..309fd2eb 100644 --- a/README.rst +++ b/README.rst @@ -16,20 +16,20 @@ An experimental high level C++ library is also available. We have Python bindings of this library, but we do not have full code coverage yet. -h2load IETF QUIC ----------------- +Running h2load against HTTP/3 endpoint +-------------------------------------- -In order to build h2load with IETF QUIC, you have to build ngtcp2, -nghttp3 and my patched OpenSSL. +In order to build h2load with HTTP/3 support, you have to build +ngtcp2, nghttp3 and my patched OpenSSL. https://github.com/ngtcp2/ngtcp2/tree/draft-20#build-from-git describes how to build these three software. -To run h2load against IETF QUIC server, specify h3-20 ALPN with +To run h2load against HTTP/3 server, specify h3-22 ALPN with ``--npn-list`` option like so: .. code-block:: text - $ h2load --npn-list h3-20 https://localhost:4433 + $ h2load --npn-list h3-22 https://localhost:4433 Development Status ------------------ diff --git a/src/h2load.h b/src/h2load.h index 289926c9..2d8f9c8a 100644 --- a/src/h2load.h +++ b/src/h2load.h @@ -465,8 +465,8 @@ struct Client { size_t keylen, const uint8_t *sample, size_t samplelen); int quic_recv_stream_data(int64_t stream_id, int fin, const uint8_t *data, size_t datalen); - int quic_stream_close(int64_t stream_id, uint16_t app_error_code); - int quic_stream_reset(int64_t stream_id, uint16_t app_error_code); + int quic_stream_close(int64_t stream_id, uint64_t app_error_code); + int quic_stream_reset(int64_t stream_id, uint64_t app_error_code); int quic_extend_max_local_streams(); int quic_tls_handshake(bool initial = false); diff --git a/src/h2load_http3_session.cc b/src/h2load_http3_session.cc index 2ab22c0c..b84ca393 100644 --- a/src/h2load_http3_session.cc +++ b/src/h2load_http3_session.cc @@ -76,7 +76,7 @@ int64_t Http3Session::submit_request_internal() { return rv; } - rv = nghttp3_conn_submit_request(conn_, stream_id, nullptr, + rv = nghttp3_conn_submit_request(conn_, stream_id, reinterpret_cast(nva.data()), nva.size(), nullptr, nullptr); if (rv != 0) { @@ -105,18 +105,18 @@ size_t Http3Session::max_concurrent_streams() { } namespace { -int stream_close(nghttp3_conn *conn, int64_t stream_id, uint16_t error_code, +int stream_close(nghttp3_conn *conn, int64_t stream_id, uint64_t app_error_code, void *user_data, void *stream_user_data) { auto s = static_cast(user_data); - if (s->stream_close(stream_id, error_code) != 0) { + if (s->stream_close(stream_id, app_error_code) != 0) { return NGHTTP3_ERR_CALLBACK_FAILURE; } return 0; } } // namespace -int Http3Session::stream_close(int64_t stream_id, uint16_t error_code) { - client_->on_stream_close(stream_id, error_code == NGHTTP3_HTTP_NO_ERROR); +int Http3Session::stream_close(int64_t stream_id, uint64_t app_error_code) { + client_->on_stream_close(stream_id, app_error_code == NGHTTP3_HTTP_NO_ERROR); return 0; } @@ -186,19 +186,21 @@ void Http3Session::recv_header(int64_t stream_id, const nghttp3_vec *name, } namespace { -int send_stop_sending(nghttp3_conn *conn, int64_t stream_id, void *user_data, +int send_stop_sending(nghttp3_conn *conn, int64_t stream_id, + uint64_t app_error_code, void *user_data, void *stream_user_data) { auto s = static_cast(user_data); - if (s->send_stop_sending(stream_id) != 0) { + if (s->send_stop_sending(stream_id, app_error_code) != 0) { return NGHTTP3_ERR_CALLBACK_FAILURE; } return 0; } } // namespace -int Http3Session::send_stop_sending(int64_t stream_id) { +int Http3Session::send_stop_sending(int64_t stream_id, + uint64_t app_error_code) { auto rv = ngtcp2_conn_shutdown_stream_read(client_->quic.conn, stream_id, - NGHTTP3_HTTP_PUSH_REFUSED); + app_error_code); if (rv != 0) { std::cerr << "ngtcp2_conn_shutdown_stream_read: " << ngtcp2_strerror(rv) << std::endl; @@ -207,8 +209,8 @@ int Http3Session::send_stop_sending(int64_t stream_id) { return 0; } -int Http3Session::close_stream(int64_t stream_id, uint16_t error_code) { - auto rv = nghttp3_conn_close_stream(conn_, stream_id, error_code); +int Http3Session::close_stream(int64_t stream_id, uint64_t app_error_code) { + auto rv = nghttp3_conn_close_stream(conn_, stream_id, app_error_code); if (rv != 0) { return -1; } diff --git a/src/h2load_http3_session.h b/src/h2load_http3_session.h index 4293c77d..f62b219d 100644 --- a/src/h2load_http3_session.h +++ b/src/h2load_http3_session.h @@ -45,15 +45,15 @@ public: virtual size_t max_concurrent_streams(); int init_conn(); - int stream_close(int64_t stream_id, uint16_t error_code); + int stream_close(int64_t stream_id, uint64_t app_error_code); void recv_data(int64_t stream_id, const uint8_t *data, size_t datalen); void consume(int64_t stream_id, size_t nconsumed); void begin_headers(int64_t stream_id); void recv_header(int64_t stream_id, const nghttp3_vec *name, const nghttp3_vec *value); - int send_stop_sending(int64_t stream_id); + int send_stop_sending(int64_t stream_id, uint64_t app_error_code); - int close_stream(int64_t stream_id, uint16_t error_code); + int close_stream(int64_t stream_id, uint64_t app_error_code); int reset_stream(int64_t stream_id); int extend_max_local_streams(); int64_t submit_request_internal(); diff --git a/src/h2load_quic.cc b/src/h2load_quic.cc index 0467d2d6..a51b1d55 100644 --- a/src/h2load_quic.cc +++ b/src/h2load_quic.cc @@ -305,7 +305,7 @@ int Client::quic_recv_stream_data(int64_t stream_id, int fin, } namespace { -int stream_close(ngtcp2_conn *conn, int64_t stream_id, uint16_t app_error_code, +int stream_close(ngtcp2_conn *conn, int64_t stream_id, uint64_t app_error_code, void *user_data, void *stream_user_data) { auto c = static_cast(user_data); if (c->quic_stream_close(stream_id, app_error_code) != 0) { @@ -315,7 +315,7 @@ int stream_close(ngtcp2_conn *conn, int64_t stream_id, uint16_t app_error_code, } } // namespace -int Client::quic_stream_close(int64_t stream_id, uint16_t app_error_code) { +int Client::quic_stream_close(int64_t stream_id, uint64_t app_error_code) { auto s = static_cast(session.get()); if (s->close_stream(stream_id, app_error_code) != 0) { return -1; @@ -325,7 +325,7 @@ int Client::quic_stream_close(int64_t stream_id, uint16_t app_error_code) { namespace { int stream_reset(ngtcp2_conn *conn, int64_t stream_id, uint64_t final_size, - uint16_t app_error_code, void *user_data, + uint64_t app_error_code, void *user_data, void *stream_user_data) { auto c = static_cast(user_data); if (c->quic_stream_reset(stream_id, app_error_code) != 0) { @@ -335,7 +335,7 @@ int stream_reset(ngtcp2_conn *conn, int64_t stream_id, uint64_t final_size, } } // namespace -int Client::quic_stream_reset(int64_t stream_id, uint16_t app_error_code) { +int Client::quic_stream_reset(int64_t stream_id, uint64_t app_error_code) { auto s = static_cast(session.get()); if (s->reset_stream(stream_id) != 0) { return -1; diff --git a/src/quic.h b/src/quic.h index 4b4bb1d6..b70076e8 100644 --- a/src/quic.h +++ b/src/quic.h @@ -88,11 +88,11 @@ enum class ErrorType { }; struct Error { - Error(ErrorType type, uint16_t code) : type(type), code(code) {} + Error(ErrorType type, uint64_t code) : type(type), code(code) {} Error() : type(ErrorType::Transport), code(0) {} ErrorType type; - uint16_t code; + uint64_t code; }; Error err_transport(int liberr);