Implement an end-to-end test for WebTransport negotiation.
PiperOrigin-RevId: 362632936
Change-Id: Ifd4a18fdb86f24bdcb7a043e3d318b4317b5dbae
diff --git a/quic/core/http/end_to_end_test.cc b/quic/core/http/end_to_end_test.cc
index 1b300e9..de43714 100644
--- a/quic/core/http/end_to_end_test.cc
+++ b/quic/core/http/end_to_end_test.cc
@@ -24,6 +24,7 @@
#include "quic/core/quic_packet_writer_wrapper.h"
#include "quic/core/quic_packets.h"
#include "quic/core/quic_session.h"
+#include "quic/core/quic_types.h"
#include "quic/core/quic_utils.h"
#include "quic/platform/api/quic_epoll.h"
#include "quic/platform/api/quic_error_code_wrappers.h"
@@ -55,6 +56,7 @@
#include "quic/test_tools/quic_stream_id_manager_peer.h"
#include "quic/test_tools/quic_stream_peer.h"
#include "quic/test_tools/quic_stream_sequencer_peer.h"
+#include "quic/test_tools/quic_test_backend.h"
#include "quic/test_tools/quic_test_client.h"
#include "quic/test_tools/quic_test_server.h"
#include "quic/test_tools/quic_test_utils.h"
@@ -220,6 +222,7 @@
client->UseConnectionIdLength(override_server_connection_id_length_);
client->UseClientConnectionIdLength(override_client_connection_id_length_);
client->client()->set_connection_debug_visitor(connection_debug_visitor_);
+ client->client()->set_enable_web_transport(enable_web_transport_);
client->Connect();
return client;
}
@@ -356,6 +359,11 @@
}
bool Initialize() {
+ if (enable_web_transport_) {
+ SetQuicReloadableFlag(quic_h3_datagram, true);
+ memory_cache_backend_.set_enable_webtransport(true);
+ }
+
QuicTagVector copt;
server_config_.SetConnectionOptionsToSend(copt);
copt = client_extra_copts_;
@@ -676,7 +684,7 @@
bool connect_to_server_on_initialize_;
QuicSocketAddress server_address_;
std::string server_hostname_;
- QuicMemoryCacheBackend memory_cache_backend_;
+ QuicTestBackend memory_cache_backend_;
std::unique_ptr<ServerThread> server_thread_;
std::unique_ptr<QuicTestClient> client_;
QuicConnectionDebugVisitor* connection_debug_visitor_ = nullptr;
@@ -695,6 +703,7 @@
int override_server_connection_id_length_ = -1;
int override_client_connection_id_length_ = -1;
uint8_t expected_server_connection_id_length_;
+ bool enable_web_transport_ = false;
};
// Run all end to end tests with all supported versions.
@@ -5667,6 +5676,35 @@
ADD_FAILURE() << "Client should not have 10 resumption tickets.";
}
+TEST_P(EndToEndTest, WebTransportSession) {
+ enable_web_transport_ = true;
+ ASSERT_TRUE(Initialize());
+
+ if (!version_.UsesHttp3()) {
+ return;
+ }
+
+ spdy::SpdyHeaderBlock headers;
+ headers[":scheme"] = "https";
+ headers[":authority"] = "localhost";
+ headers[":path"] = "/echo";
+ headers[":method"] = "CONNECT";
+ headers[":protocol"] = "webtransport";
+
+ client_->SendMessage(headers, "", /*fin=*/false);
+ QuicSpdyStream* stream = client_->latest_created_stream();
+ EXPECT_TRUE(stream->web_transport() != nullptr);
+ WebTransportSessionId id = client_->latest_created_stream()->id();
+ QuicSpdySession* client_session = GetClientSession();
+ EXPECT_TRUE(client_session->GetWebTransportSession(id) != nullptr);
+ client_->WaitUntil(-1, [stream]() { return stream->headers_decompressed(); });
+
+ server_thread_->Pause();
+ QuicSpdySession* server_session = GetServerSession();
+ EXPECT_TRUE(server_session->GetWebTransportSession(id) != nullptr);
+ server_thread_->Resume();
+}
+
} // namespace
} // namespace test
} // namespace quic
diff --git a/quic/test_tools/quic_test_backend.cc b/quic/test_tools/quic_test_backend.cc
new file mode 100644
index 0000000..f33c6f1
--- /dev/null
+++ b/quic/test_tools/quic_test_backend.cc
@@ -0,0 +1,23 @@
+// Copyright (c) 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "quic/test_tools/quic_test_backend.h"
+
+namespace quic {
+namespace test {
+
+QuicSimpleServerBackend::WebTransportResponse
+QuicTestBackend::ProcessWebTransportRequest(
+ const spdy::Http2HeaderBlock& request_headers) {
+ if (!SupportsWebTransport()) {
+ return QuicSimpleServerBackend::ProcessWebTransportRequest(request_headers);
+ }
+
+ WebTransportResponse response;
+ response.response_headers[":status"] = "200";
+ return response;
+}
+
+} // namespace test
+} // namespace quic
diff --git a/quic/test_tools/quic_test_backend.h b/quic/test_tools/quic_test_backend.h
new file mode 100644
index 0000000..fe5b454
--- /dev/null
+++ b/quic/test_tools/quic_test_backend.h
@@ -0,0 +1,33 @@
+// Copyright (c) 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef QUICHE_QUIC_TEST_TOOLS_QUIC_TEST_BACKEND_H_
+#define QUICHE_QUIC_TEST_TOOLS_QUIC_TEST_BACKEND_H_
+
+#include "quic/tools/quic_memory_cache_backend.h"
+
+namespace quic {
+namespace test {
+
+// QuicTestBackend is a QuicSimpleServer backend usable in tests. It has extra
+// WebTransport endpoints on top of what QuicMemoryCacheBackend already
+// provides.
+class QuicTestBackend : public QuicMemoryCacheBackend {
+ public:
+ WebTransportResponse ProcessWebTransportRequest(
+ const spdy::Http2HeaderBlock& /*request_headers*/) override;
+ bool SupportsWebTransport() override { return enable_webtransport_; }
+
+ void set_enable_webtransport(bool enable_webtransport) {
+ enable_webtransport_ = enable_webtransport;
+ }
+
+ private:
+ bool enable_webtransport_ = false;
+};
+
+} // namespace test
+} // namespace quic
+
+#endif // QUICHE_QUIC_TEST_TOOLS_QUIC_TEST_BACKEND_H_
diff --git a/quic/tools/quic_client.cc b/quic/tools/quic_client.cc
index f8375ab..448291b 100644
--- a/quic/tools/quic_client.cc
+++ b/quic/tools/quic_client.cc
@@ -165,7 +165,7 @@
QuicConnection* connection) {
return std::make_unique<QuicSimpleClientSession>(
*config(), supported_versions, connection, server_id(), crypto_config(),
- push_promise_index(), drop_response_body());
+ push_promise_index(), drop_response_body(), enable_web_transport());
}
QuicClientEpollNetworkHelper* QuicClient::epoll_network_helper() {
diff --git a/quic/tools/quic_simple_client_session.cc b/quic/tools/quic_simple_client_session.cc
index 7f64495..d1efcba 100644
--- a/quic/tools/quic_simple_client_session.cc
+++ b/quic/tools/quic_simple_client_session.cc
@@ -16,13 +16,32 @@
QuicCryptoClientConfig* crypto_config,
QuicClientPushPromiseIndex* push_promise_index,
bool drop_response_body)
+ : QuicSimpleClientSession(config,
+ supported_versions,
+ connection,
+ server_id,
+ crypto_config,
+ push_promise_index,
+ drop_response_body,
+ /*enable_web_transport=*/false) {}
+
+QuicSimpleClientSession::QuicSimpleClientSession(
+ const QuicConfig& config,
+ const ParsedQuicVersionVector& supported_versions,
+ QuicConnection* connection,
+ const QuicServerId& server_id,
+ QuicCryptoClientConfig* crypto_config,
+ QuicClientPushPromiseIndex* push_promise_index,
+ bool drop_response_body,
+ bool enable_web_transport)
: QuicSpdyClientSession(config,
supported_versions,
connection,
server_id,
crypto_config,
push_promise_index),
- drop_response_body_(drop_response_body) {}
+ drop_response_body_(drop_response_body),
+ enable_web_transport_(enable_web_transport) {}
std::unique_ptr<QuicSpdyClientStream>
QuicSimpleClientSession::CreateClientStream() {
@@ -31,4 +50,8 @@
drop_response_body_);
}
+bool QuicSimpleClientSession::ShouldNegotiateWebTransport() {
+ return enable_web_transport_;
+}
+
} // namespace quic
diff --git a/quic/tools/quic_simple_client_session.h b/quic/tools/quic_simple_client_session.h
index 5b53141..aa86d9a 100644
--- a/quic/tools/quic_simple_client_session.h
+++ b/quic/tools/quic_simple_client_session.h
@@ -19,11 +19,21 @@
QuicCryptoClientConfig* crypto_config,
QuicClientPushPromiseIndex* push_promise_index,
bool drop_response_body);
+ QuicSimpleClientSession(const QuicConfig& config,
+ const ParsedQuicVersionVector& supported_versions,
+ QuicConnection* connection,
+ const QuicServerId& server_id,
+ QuicCryptoClientConfig* crypto_config,
+ QuicClientPushPromiseIndex* push_promise_index,
+ bool drop_response_body,
+ bool enable_web_transport);
std::unique_ptr<QuicSpdyClientStream> CreateClientStream() override;
+ bool ShouldNegotiateWebTransport() override;
private:
const bool drop_response_body_;
+ const bool enable_web_transport_;
};
} // namespace quic
diff --git a/quic/tools/quic_simple_server_backend.h b/quic/tools/quic_simple_server_backend.h
index 9e16d4e..1a1125a 100644
--- a/quic/tools/quic_simple_server_backend.h
+++ b/quic/tools/quic_simple_server_backend.h
@@ -5,7 +5,10 @@
#ifndef QUICHE_QUIC_TOOLS_QUIC_SIMPLE_SERVER_BACKEND_H_
#define QUICHE_QUIC_TOOLS_QUIC_SIMPLE_SERVER_BACKEND_H_
+#include <memory>
+
#include "quic/core/quic_types.h"
+#include "quic/core/web_transport_interface.h"
#include "quic/tools/quic_backend_response.h"
#include "spdy/core/spdy_header_block.h"
@@ -33,6 +36,11 @@
std::list<QuicBackendResponse::ServerPushInfo> resources) = 0;
};
+ struct WebTransportResponse {
+ spdy::Http2HeaderBlock response_headers;
+ std::unique_ptr<WebTransportVisitor> visitor;
+ };
+
virtual ~QuicSimpleServerBackend() = default;
// This method initializes the backend instance to fetch responses
// from a backend server, in-memory cache etc.
@@ -51,6 +59,14 @@
RequestHandler* request_handler) = 0;
// Clears the state of the backend instance
virtual void CloseBackendResponseStream(RequestHandler* request_handler) = 0;
+
+ virtual WebTransportResponse ProcessWebTransportRequest(
+ const spdy::Http2HeaderBlock& /*request_headers*/) {
+ WebTransportResponse response;
+ response.response_headers[":status"] = "400";
+ return response;
+ }
+ virtual bool SupportsWebTransport() { return false; }
};
} // namespace quic
diff --git a/quic/tools/quic_simple_server_session.h b/quic/tools/quic_simple_server_session.h
index 49aaae5..c117cdd 100644
--- a/quic/tools/quic_simple_server_session.h
+++ b/quic/tools/quic_simple_server_session.h
@@ -104,6 +104,10 @@
void MaybeInitializeHttp3UnidirectionalStreams() override;
+ bool ShouldNegotiateWebTransport() override {
+ return quic_simple_server_backend_->SupportsWebTransport();
+ }
+
private:
friend class test::QuicSimpleServerSessionPeer;
diff --git a/quic/tools/quic_spdy_client_base.h b/quic/tools/quic_spdy_client_base.h
index 54c73f7..1b4ca81 100644
--- a/quic/tools/quic_spdy_client_base.h
+++ b/quic/tools/quic_spdy_client_base.h
@@ -139,6 +139,11 @@
}
bool drop_response_body() const { return drop_response_body_; }
+ void set_enable_web_transport(bool enable_web_transport) {
+ enable_web_transport_ = enable_web_transport;
+ }
+ bool enable_web_transport() const { return enable_web_transport_; }
+
// Set the max promise id for the client session.
// TODO(b/151641466): Rename this method.
void SetMaxAllowedPushId(PushId max) { max_allowed_push_id_ = max; }
@@ -221,6 +226,7 @@
std::unique_ptr<ClientQuicDataToResend> push_promise_data_to_resend_;
bool drop_response_body_ = false;
+ bool enable_web_transport_ = false;
// The max promise id to set on the client session when created.
PushId max_allowed_push_id_;