diff --git a/src/quic/http3.cc b/src/quic/http3.cc index b6d876af60f6..54668a89c90b 100644 --- a/src/quic/http3.cc +++ b/src/quic/http3.cc @@ -503,7 +503,12 @@ class Http3ApplicationImpl final : public Session::Application { code = error.code(); } - int rv = nghttp3_conn_close_stream(*this, stream->id(), code); + int rv = nghttp3_conn_close_stream2( + *this, + NGHTTP3_STREAM_CLOSE_FLAG_RX_APP_ERROR_CODE_SET, + stream->id(), + code, + 0); // If the call is successful, Http3Application::OnStreamClose callback will // be invoked when the stream is ready to be closed. We'll handle destroying // the actual Stream object there. @@ -797,16 +802,32 @@ class Http3ApplicationImpl final : public Session::Application { return Http3ConnectionPointer(conn); } - void OnStreamClose(Stream* stream, error_code app_error_code) { - if (app_error_code != NGHTTP3_H3_NO_ERROR) { + void OnStreamClose(Stream* stream, + uint32_t flags, + error_code rx_app_error_code, + error_code tx_app_error_code) { + if (flags & NGHTTP3_STREAM_CLOSE_FLAG_RX_APP_ERROR_CODE_SET) { Debug(&session(), "HTTP/3 application received stream close for stream %" PRIi64 - " with code %" PRIu64, + " with remote error code %" PRIu64, stream->id(), - app_error_code); + rx_app_error_code); + } + if (flags & NGHTTP3_STREAM_CLOSE_FLAG_TX_APP_ERROR_CODE_SET) { + Debug(&session(), + "HTTP/3 application send stream close for stream %" PRIi64 + " with error code %" PRIu64, + stream->id(), + tx_app_error_code); } auto direction = stream->direction(); - stream->Destroy(QuicError::ForApplication(app_error_code)); + if (flags & NGHTTP3_STREAM_CLOSE_FLAG_RX_APP_ERROR_CODE_SET) { + stream->Destroy(QuicError::ForApplication(rx_app_error_code)); + } else if (flags & NGHTTP3_STREAM_CLOSE_FLAG_TX_APP_ERROR_CODE_SET) { + stream->Destroy(QuicError::ForApplication(tx_app_error_code)); + } else { + stream->Destroy(); + } ExtendMaxStreams(EndpointLabel::REMOTE, direction, 1); } @@ -1168,13 +1189,16 @@ class Http3ApplicationImpl final : public Session::Application { } static int on_stream_close(nghttp3_conn* conn, + uint32_t flags, stream_id id, - error_code app_error_code, + error_code rx_app_error_code, + error_code tx_app_error_code, void* conn_user_data, void* stream_user_data) { NGHTTP3_CALLBACK_SCOPE(app); if (auto stream = app.session().FindStream(id)) { - app.OnStreamClose(stream.get(), app_error_code); + app.OnStreamClose( + stream.get(), flags, rx_app_error_code, tx_app_error_code); } return NGTCP2_SUCCESS; } @@ -1382,7 +1406,7 @@ class Http3ApplicationImpl final : public Session::Application { static constexpr nghttp3_callbacks kCallbacks = { on_acked_stream_data, - on_stream_close, + nullptr, // nghttp3_stream_close (deprecated) on_receive_data, on_deferred_consume, on_begin_headers, @@ -1400,10 +1424,7 @@ class Http3ApplicationImpl final : public Session::Application { on_end_origin, on_rand, on_receive_settings, -#ifdef NGHTTP3_CALLBACKS_V4 - nullptr, -#endif // NGHTTP3_CALLBACKS_V4 - }; + on_stream_close}; }; std::optional ParseHttp3TicketData(const uv_buf_t& data) {