From 7d9fba1c9e2410c7873d71a2c8b66e9e7e0ea72b Mon Sep 17 00:00:00 2001 From: Paul Gregoire Date: Tue, 6 Oct 2026 07:20:42 -0700 Subject: [PATCH 1/2] fix: advertise reliable resets on mvfst listeners --- src/MoqxRelayServer.cpp | 3 ++ test/CMakeLists.txt | 5 ++ test/MoqxRelayServerTest.cpp | 89 ++++++++++++++++++++++++++++++++++++ 3 files changed, 97 insertions(+) create mode 100644 test/MoqxRelayServerTest.cpp diff --git a/src/MoqxRelayServer.cpp b/src/MoqxRelayServer.cpp index b798ba7b3..7b364747e 100644 --- a/src/MoqxRelayServer.cpp +++ b/src/MoqxRelayServer.cpp @@ -133,6 +133,9 @@ quic::TransportSettings buildTransportSettings(const config::QuicConfig& quic, const config::MvfstConfig& mvfst) { // Start with MoQServer's optimized defaults, then apply config overrides. quic::TransportSettings ts; + // WebTransport over HTTP/3 draft-16 section 3.1 requires reset_stream_at. + // Advertising support is safe for native MoQT peers that do not enable it. + ts.advertisedReliableResetStreamSupport = true; ts.defaultCongestionController = quic::CongestionControlType::Copa; ts.pacingEnabled = mvfst.pacingEnabled; ts.maxCwndInMss = mvfst.maxCwndInMss; diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 9981201a3..c8b8649a5 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -232,6 +232,11 @@ moqx_add_gtest(moqx_relay_context_test moxygen::moxygen_events_moq_folly_executor_impl ) +moqx_add_gtest(moqx_relay_server_test + SRCS MoqxRelayServerTest.cpp + LIBS moqx_core moqx_test_main moxygen::moxygen_util_quic_connector +) + # Registers an integration test once per QUIC stack. The mvfst run keeps the # plain name; the picoquic run gets a _picoquic suffix and selects the stack # through MOQ_HARNESS_QUIC_STACK, which the Python harness and the shell tests diff --git a/test/MoqxRelayServerTest.cpp b/test/MoqxRelayServerTest.cpp new file mode 100644 index 000000000..344b892af --- /dev/null +++ b/test/MoqxRelayServerTest.cpp @@ -0,0 +1,89 @@ +/* + * Copyright (c) OpenMOQ contributors. + * This source code is licensed under the Apache 2.0 license found in the + * LICENSE file in the root directory of this source tree. + */ + +#include "MoqxRelayServer.h" + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +namespace openmoq::moqx::test { +namespace { + +class MoqxRelayServerTest : public ::testing::Test { +protected: + void SetUp() override { + config::ListenerConfig listener; + listener.address = folly::SocketAddress("::1", 0); + listener.tlsMode = config::Insecure{}; + listener.endpoint = "/moq"; + listener.moqtVersions = "18"; + auto context = std::make_shared( + folly::F14FastMap{}, + "test-relay" + ); + server_ = std::make_unique(listener, std::move(context), &ioExecutor_); + server_->start(); + } + + void TearDown() override { + if (client_) { + client_->closeNow({}); + client_.reset(); + } + if (server_) { + server_->stop(); + server_.reset(); + } + clientEvb_.loop(); + } + + void connect(const std::string& alpn, bool reliableResetSupport) { + quic::TransportSettings settings; + settings.advertisedReliableResetStreamSupport = reliableResetSupport; + client_ = folly::coro::blockingWait( + moxygen::QuicConnector::connectQuic( + &clientEvb_, + server_->getAddress(), + std::chrono::seconds(5), + std::make_shared(), + {alpn}, + settings + ), + &clientEvb_ + ); + } + + folly::EventBase clientEvb_; + folly::IOThreadPoolExecutor ioExecutor_{1}; + std::unique_ptr server_; + std::shared_ptr client_; +}; + +TEST_F(MoqxRelayServerTest, AdvertisesReliableResetSupportForWebTransport) { + connect("h3", true); + + ASSERT_NE(client_, nullptr); + ASSERT_NE(client_->getState(), nullptr); + EXPECT_TRUE(client_->getState()->peerAdvertisedReliableStreamResetSupport); +} + +TEST_F(MoqxRelayServerTest, AcceptsHttp3PeerWithoutReliableResetSupport) { + connect("h3", false); + + ASSERT_NE(client_, nullptr); + EXPECT_TRUE(client_->good()); +} + +} // namespace +} // namespace openmoq::moqx::test From 87b80dbf699cc1324141647592c78f5bf13f2935 Mon Sep 17 00:00:00 2001 From: Alan Frindell <8259689+afrind@users.noreply.github.com> Date: Fri, 9 Oct 2026 16:59:34 -0700 Subject: [PATCH 2/2] test: reliable reset keeps the connection open Check that a reliable RESET_STREAM_AT on an ignored H3 stream does not close the connection now that the listener advertises support. Co-Authored-By: Claude Opus 5.5 --- test/MoqxRelayServerTest.cpp | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/test/MoqxRelayServerTest.cpp b/test/MoqxRelayServerTest.cpp index 344b892af..c25bf0e6f 100644 --- a/test/MoqxRelayServerTest.cpp +++ b/test/MoqxRelayServerTest.cpp @@ -7,6 +7,8 @@ #include "MoqxRelayServer.h" #include +#include +#include #include #include #include @@ -85,5 +87,25 @@ TEST_F(MoqxRelayServerTest, AcceptsHttp3PeerWithoutReliableResetSupport) { EXPECT_TRUE(client_->good()); } +TEST_F(MoqxRelayServerTest, ReliableResetKeepsConnectionOpen) { + connect("h3", true); + ASSERT_NE(client_, nullptr); + ASSERT_TRUE(client_->getState()->peerAdvertisedReliableStreamResetSupport); + + auto stream = client_->createUnidirectionalStream(); + ASSERT_TRUE(stream.has_value()); + // Reserved HTTP/3 stream type 0x21, which the server must ignore. + ASSERT_TRUE(client_->writeChain(*stream, folly::IOBuf::copyBuffer("\x21reliable"), false)); + ASSERT_TRUE(client_->updateReliableDeliveryCheckpoint(*stream)); + ASSERT_TRUE(client_->writeChain(*stream, folly::IOBuf::copyBuffer("unreliable"), false)); + ASSERT_TRUE(client_->resetStreamReliably(*stream, quic::ApplicationErrorCode(0x10c))); + + folly::coro::blockingWait(folly::coro::sleep(std::chrono::seconds(1)), &clientEvb_); + + EXPECT_TRUE(client_->good()); + EXPECT_FALSE(client_->getState()->localConnectionError.has_value()); + EXPECT_FALSE(client_->getState()->peerConnectionError.has_value()); +} + } // namespace } // namespace openmoq::moqx::test