Move WebTransportEchoServer from test_tools to tools.
So that it can be used from QUIC test servers.
Add `enable_webtransport` flag in QuicToyServer. If true, QuicMemoryCacheBackend
is set up to handle WebTransport requests.
PiperOrigin-RevId: 370638467
Change-Id: I0f3555fa7da6cb1e4ca211134f5123eed8ae56e3
diff --git a/quic/test_tools/quic_test_backend.cc b/quic/test_tools/quic_test_backend.cc
index 9623d75..b88301a 100644
--- a/quic/test_tools/quic_test_backend.cc
+++ b/quic/test_tools/quic_test_backend.cc
@@ -18,95 +18,6 @@
namespace quic {
namespace test {
-namespace {
-
-class EchoWebTransportServer : public WebTransportVisitor {
- public:
- EchoWebTransportServer(WebTransportSession* session) : session_(session) {}
-
- void OnSessionReady() override {
- if (session_->CanOpenNextOutgoingBidirectionalStream()) {
- OnCanCreateNewOutgoingBidirectionalStream();
- }
- }
-
- void OnIncomingBidirectionalStreamAvailable() override {
- while (true) {
- WebTransportStream* stream =
- session_->AcceptIncomingBidirectionalStream();
- if (stream == nullptr) {
- return;
- }
- QUIC_DVLOG(1) << "EchoWebTransportServer received a bidirectional stream "
- << stream->GetStreamId();
- stream->SetVisitor(
- std::make_unique<WebTransportBidirectionalEchoVisitor>(stream));
- stream->visitor()->OnCanRead();
- }
- }
-
- void OnIncomingUnidirectionalStreamAvailable() override {
- while (true) {
- WebTransportStream* stream =
- session_->AcceptIncomingUnidirectionalStream();
- if (stream == nullptr) {
- return;
- }
- QUIC_DVLOG(1)
- << "EchoWebTransportServer received a unidirectional stream";
- stream->SetVisitor(
- std::make_unique<WebTransportUnidirectionalEchoReadVisitor>(
- stream, [this](const std::string& data) {
- streams_to_echo_back_.push_back(data);
- TrySendingUnidirectionalStreams();
- }));
- stream->visitor()->OnCanRead();
- }
- }
-
- void OnDatagramReceived(absl::string_view datagram) override {
- auto buffer = MakeUniqueBuffer(&allocator_, datagram.size());
- memcpy(buffer.get(), datagram.data(), datagram.size());
- QuicMemSlice slice(std::move(buffer), datagram.size());
- session_->SendOrQueueDatagram(std::move(slice));
- }
-
- void OnCanCreateNewOutgoingBidirectionalStream() override {
- if (!echo_stream_opened_) {
- WebTransportStream* stream = session_->OpenOutgoingBidirectionalStream();
- stream->SetVisitor(
- std::make_unique<WebTransportBidirectionalEchoVisitor>(stream));
- echo_stream_opened_ = true;
- }
- }
- void OnCanCreateNewOutgoingUnidirectionalStream() override {
- TrySendingUnidirectionalStreams();
- }
-
- void TrySendingUnidirectionalStreams() {
- while (!streams_to_echo_back_.empty() &&
- session_->CanOpenNextOutgoingUnidirectionalStream()) {
- QUIC_DVLOG(1)
- << "EchoWebTransportServer echoed a unidirectional stream back";
- WebTransportStream* stream = session_->OpenOutgoingUnidirectionalStream();
- stream->SetVisitor(
- std::make_unique<WebTransportUnidirectionalEchoWriteVisitor>(
- stream, streams_to_echo_back_.front()));
- streams_to_echo_back_.pop_front();
- stream->visitor()->OnCanWrite();
- }
- }
-
- private:
- WebTransportSession* session_;
- SimpleBufferAllocator allocator_;
- bool echo_stream_opened_ = false;
-
- QuicCircularDeque<std::string> streams_to_echo_back_;
-};
-
-} // namespace
-
QuicSimpleServerBackend::WebTransportResponse
QuicTestBackend::ProcessWebTransportRequest(
const spdy::Http2HeaderBlock& request_headers,
@@ -126,7 +37,8 @@
if (path == "/echo") {
WebTransportResponse response;
response.response_headers[":status"] = "200";
- response.visitor = std::make_unique<EchoWebTransportServer>(session);
+ response.visitor =
+ std::make_unique<EchoWebTransportSessionVisitor>(session);
return response;
}
diff --git a/quic/tools/quic_memory_cache_backend.cc b/quic/tools/quic_memory_cache_backend.cc
index e76a6cf..967e60f 100644
--- a/quic/tools/quic_memory_cache_backend.cc
+++ b/quic/tools/quic_memory_cache_backend.cc
@@ -15,6 +15,7 @@
#include "quic/platform/api/quic_file_utils.h"
#include "quic/platform/api/quic_logging.h"
#include "quic/platform/api/quic_map_util.h"
+#include "quic/tools/web_transport_test_visitors.h"
#include "common/platform/api/quiche_text_utils.h"
using spdy::Http2HeaderBlock;
@@ -313,6 +314,10 @@
QuicBackendResponse::GENERATE_BYTES);
}
+void QuicMemoryCacheBackend::EnableWebTransport() {
+ enable_webtransport_ = true;
+}
+
bool QuicMemoryCacheBackend::IsBackendInitialized() const {
return cache_initialized_;
}
@@ -361,6 +366,35 @@
return resources;
}
+QuicMemoryCacheBackend::WebTransportResponse
+QuicMemoryCacheBackend::ProcessWebTransportRequest(
+ const spdy::Http2HeaderBlock& request_headers,
+ WebTransportSession* session) {
+ if (!SupportsWebTransport()) {
+ return QuicSimpleServerBackend::ProcessWebTransportRequest(request_headers,
+ session);
+ }
+
+ auto path_it = request_headers.find(":path");
+ if (path_it == request_headers.end()) {
+ WebTransportResponse response;
+ response.response_headers[":status"] = "400";
+ return response;
+ }
+ absl::string_view path = path_it->second;
+ if (path == "/echo") {
+ WebTransportResponse response;
+ response.response_headers[":status"] = "200";
+ response.visitor =
+ std::make_unique<EchoWebTransportSessionVisitor>(session);
+ return response;
+ }
+
+ WebTransportResponse response;
+ response.response_headers[":status"] = "404";
+ return response;
+}
+
QuicMemoryCacheBackend::~QuicMemoryCacheBackend() {
{
QuicWriterMutexLock lock(&response_mutex_);
diff --git a/quic/tools/quic_memory_cache_backend.h b/quic/tools/quic_memory_cache_backend.h
index 8ba6d60..1caea5d 100644
--- a/quic/tools/quic_memory_cache_backend.h
+++ b/quic/tools/quic_memory_cache_backend.h
@@ -139,6 +139,8 @@
// generated response of that many bytes.
void GenerateDynamicResponses();
+ void EnableWebTransport();
+
// Find all the server push resources associated with |request_url|.
std::list<QuicBackendResponse::ServerPushInfo> GetServerPushResources(
std::string request_url);
@@ -153,6 +155,10 @@
QuicSimpleServerBackend::RequestHandler* quic_server_stream) override;
void CloseBackendResponseStream(
QuicSimpleServerBackend::RequestHandler* quic_server_stream) override;
+ WebTransportResponse ProcessWebTransportRequest(
+ const spdy::Http2HeaderBlock& request_headers,
+ WebTransportSession* session) override;
+ bool SupportsWebTransport() override { return enable_webtransport_; }
private:
void AddResponseImpl(absl::string_view host,
@@ -197,6 +203,8 @@
// server threads accessing those responses.
mutable QuicMutex response_mutex_;
bool cache_initialized_;
+
+ bool enable_webtransport_ = false;
};
} // namespace quic
diff --git a/quic/tools/quic_toy_server.cc b/quic/tools/quic_toy_server.cc
index 93f699b..e7b4e1e 100644
--- a/quic/tools/quic_toy_server.cc
+++ b/quic/tools/quic_toy_server.cc
@@ -46,6 +46,11 @@
"QUIC versions to enable, e.g. \"h3-25,h3-27\". If not set, then all "
"available versions are enabled.");
+DEFINE_QUIC_COMMAND_LINE_FLAG(bool,
+ enable_webtransport,
+ false,
+ "If true, WebTransport support is enabled.");
+
namespace quic {
std::unique_ptr<quic::QuicSimpleServerBackend>
@@ -58,6 +63,9 @@
memory_cache_backend->InitializeBackend(
GetQuicFlag(FLAGS_quic_response_cache_dir));
}
+ if (GetQuicFlag(FLAGS_enable_webtransport)) {
+ memory_cache_backend->EnableWebTransport();
+ }
return memory_cache_backend;
}
diff --git a/quic/tools/web_transport_test_visitors.h b/quic/tools/web_transport_test_visitors.h
index 9bf6e6b..c9efcb7 100644
--- a/quic/tools/web_transport_test_visitors.h
+++ b/quic/tools/web_transport_test_visitors.h
@@ -7,6 +7,8 @@
#include <string>
+#include "quic/core/quic_circular_deque.h"
+#include "quic/core/quic_simple_buffer_allocator.h"
#include "quic/core/web_transport_interface.h"
#include "quic/platform/api/quic_logging.h"
@@ -132,6 +134,95 @@
std::string data_;
};
+// A session visitor which sets unidirectional or bidirectional stream visitors
+// to echo.
+class EchoWebTransportSessionVisitor : public WebTransportVisitor {
+ public:
+ EchoWebTransportSessionVisitor(WebTransportSession* session)
+ : session_(session) {}
+
+ void OnSessionReady() override {
+ if (session_->CanOpenNextOutgoingBidirectionalStream()) {
+ OnCanCreateNewOutgoingBidirectionalStream();
+ }
+ }
+
+ void OnIncomingBidirectionalStreamAvailable() override {
+ while (true) {
+ WebTransportStream* stream =
+ session_->AcceptIncomingBidirectionalStream();
+ if (stream == nullptr) {
+ return;
+ }
+ QUIC_DVLOG(1)
+ << "EchoWebTransportSessionVisitor received a bidirectional stream "
+ << stream->GetStreamId();
+ stream->SetVisitor(
+ std::make_unique<WebTransportBidirectionalEchoVisitor>(stream));
+ stream->visitor()->OnCanRead();
+ }
+ }
+
+ void OnIncomingUnidirectionalStreamAvailable() override {
+ while (true) {
+ WebTransportStream* stream =
+ session_->AcceptIncomingUnidirectionalStream();
+ if (stream == nullptr) {
+ return;
+ }
+ QUIC_DVLOG(1)
+ << "EchoWebTransportSessionVisitor received a unidirectional stream";
+ stream->SetVisitor(
+ std::make_unique<WebTransportUnidirectionalEchoReadVisitor>(
+ stream, [this](const std::string& data) {
+ streams_to_echo_back_.push_back(data);
+ TrySendingUnidirectionalStreams();
+ }));
+ stream->visitor()->OnCanRead();
+ }
+ }
+
+ void OnDatagramReceived(absl::string_view datagram) override {
+ auto buffer = MakeUniqueBuffer(&allocator_, datagram.size());
+ memcpy(buffer.get(), datagram.data(), datagram.size());
+ QuicMemSlice slice(std::move(buffer), datagram.size());
+ session_->SendOrQueueDatagram(std::move(slice));
+ }
+
+ void OnCanCreateNewOutgoingBidirectionalStream() override {
+ if (!echo_stream_opened_) {
+ WebTransportStream* stream = session_->OpenOutgoingBidirectionalStream();
+ stream->SetVisitor(
+ std::make_unique<WebTransportBidirectionalEchoVisitor>(stream));
+ echo_stream_opened_ = true;
+ }
+ }
+ void OnCanCreateNewOutgoingUnidirectionalStream() override {
+ TrySendingUnidirectionalStreams();
+ }
+
+ void TrySendingUnidirectionalStreams() {
+ while (!streams_to_echo_back_.empty() &&
+ session_->CanOpenNextOutgoingUnidirectionalStream()) {
+ QUIC_DVLOG(1)
+ << "EchoWebTransportServer echoed a unidirectional stream back";
+ WebTransportStream* stream = session_->OpenOutgoingUnidirectionalStream();
+ stream->SetVisitor(
+ std::make_unique<WebTransportUnidirectionalEchoWriteVisitor>(
+ stream, streams_to_echo_back_.front()));
+ streams_to_echo_back_.pop_front();
+ stream->visitor()->OnCanWrite();
+ }
+ }
+
+ private:
+ WebTransportSession* session_;
+ SimpleBufferAllocator allocator_;
+ bool echo_stream_opened_ = false;
+
+ QuicCircularDeque<std::string> streams_to_echo_back_;
+};
+
} // namespace quic
#endif // QUICHE_QUIC_TOOLS_WEB_TRANSPORT_TEST_VISITORS_H_