Implement subprotocol negotiation in WebTransport.
This implements the //net part; the //services/network will follow. Change-Id: I87ecaf1231cc7140b51e7f3d5f19fc24ec12b8f9 Bug: 416080492 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6512202 Commit-Queue: Victor Vasiliev <vasilvv@chromium.org> Reviewed-by: Kenichi Ishibashi <bashi@chromium.org> Cr-Commit-Position: refs/heads/main@{#1456804}
This commit is contained in:

committed by
Chromium LUCI CQ

parent
ce41c97e34
commit
435ec1039c
@ -967,6 +967,7 @@ _BANNED_CPP_FUNCTIONS: Sequence[BanRule] = (
|
||||
r'android_webview/browser/ip_protection/.*',
|
||||
r'chrome/browser/ip_protection/.*',
|
||||
r'components/ip_protection/.*',
|
||||
r'net/quic/dedicated_web_transport_http3_client\.cc',
|
||||
|
||||
# Needed to use MediaPipe API.
|
||||
r'components/media_effects/.*\.cc',
|
||||
|
@ -28,6 +28,7 @@
|
||||
#include "net/third_party/quiche/src/quiche/quic/core/quic_connection.h"
|
||||
#include "net/third_party/quiche/src/quiche/quic/core/quic_types.h"
|
||||
#include "net/third_party/quiche/src/quiche/quic/core/quic_utils.h"
|
||||
#include "net/third_party/quiche/src/quiche/web_transport/web_transport_headers.h"
|
||||
#include "net/url_request/url_request_context.h"
|
||||
#include "url/scheme_host_port.h"
|
||||
|
||||
@ -365,6 +366,7 @@ DedicatedWebTransportHttp3Client::DedicatedWebTransportHttp3Client(
|
||||
: url_(url),
|
||||
origin_(origin),
|
||||
anonymization_key_(anonymization_key),
|
||||
application_protocols_(parameters.application_protocols),
|
||||
context_(context),
|
||||
visitor_(visitor),
|
||||
quic_context_(context->quic_context()),
|
||||
@ -748,6 +750,14 @@ int DedicatedWebTransportHttp3Client::DoSendRequest() {
|
||||
headers[":protocol"] = "webtransport";
|
||||
headers["sec-webtransport-http3-draft02"] = "1";
|
||||
headers["origin"] = origin_.Serialize();
|
||||
if (!application_protocols_.empty()) {
|
||||
absl::StatusOr<std::string> protocols_header =
|
||||
webtransport::SerializeSubprotocolRequestHeader(application_protocols_);
|
||||
if (protocols_header.ok()) {
|
||||
headers[webtransport::kSubprotocolRequestHeader] =
|
||||
*std::move(protocols_header);
|
||||
}
|
||||
}
|
||||
stream->WriteHeaders(std::move(headers), /*fin=*/false, nullptr);
|
||||
|
||||
web_transport_session_ = stream->web_transport();
|
||||
|
@ -150,6 +150,7 @@ class NET_EXPORT DedicatedWebTransportHttp3Client
|
||||
const GURL url_;
|
||||
const url::Origin origin_;
|
||||
const NetworkAnonymizationKey anonymization_key_;
|
||||
const std::vector<std::string> application_protocols_;
|
||||
const raw_ptr<URLRequestContext> context_; // Unowned.
|
||||
const raw_ptr<WebTransportClientVisitor> visitor_; // Unowned.
|
||||
|
||||
|
@ -210,7 +210,7 @@ TEST_F(DedicatedWebTransportHttp3Test, Connect) {
|
||||
GetURL("/echo"), origin_, &visitor_, anonymization_key_, context_.get(),
|
||||
WebTransportParameters());
|
||||
|
||||
EXPECT_CALL(visitor_, OnConnected(_)).WillOnce(StopRunning());
|
||||
EXPECT_CALL(visitor_, OnConnected).WillOnce(StopRunning());
|
||||
client_->Connect();
|
||||
Run();
|
||||
ASSERT_TRUE(client_->session() != nullptr);
|
||||
@ -251,7 +251,7 @@ TEST_F(DedicatedWebTransportHttp3Test, MAYBE_CloseTimeout) {
|
||||
GetURL("/echo"), origin_, &visitor_, anonymization_key_, context_.get(),
|
||||
WebTransportParameters());
|
||||
|
||||
EXPECT_CALL(visitor_, OnConnected(_)).WillOnce(StopRunning());
|
||||
EXPECT_CALL(visitor_, OnConnected).WillOnce(StopRunning());
|
||||
client_->Connect();
|
||||
Run();
|
||||
ASSERT_TRUE(client_->session() != nullptr);
|
||||
@ -277,7 +277,7 @@ TEST_F(DedicatedWebTransportHttp3Test, CloseReason) {
|
||||
GetURL("/session-close"), origin_, &visitor_, anonymization_key_,
|
||||
context_.get(), WebTransportParameters());
|
||||
|
||||
EXPECT_CALL(visitor_, OnConnected(_)).WillOnce(StopRunning());
|
||||
EXPECT_CALL(visitor_, OnConnected).WillOnce(StopRunning());
|
||||
client_->Connect();
|
||||
Run();
|
||||
ASSERT_TRUE(client_->session() != nullptr);
|
||||
@ -296,5 +296,42 @@ TEST_F(DedicatedWebTransportHttp3Test, CloseReason) {
|
||||
EXPECT_THAT(received_close_info, Optional(close_info));
|
||||
}
|
||||
|
||||
// Test negotiation of the application protocol via
|
||||
// https://www.ietf.org/archive/id/draft-ietf-webtrans-http3-12.html#name-application-protocol-negoti
|
||||
TEST_F(DedicatedWebTransportHttp3Test, SubprotocolHeader) {
|
||||
StartServer();
|
||||
WebTransportParameters parameters;
|
||||
parameters.application_protocols = {"first", "second", "third"};
|
||||
// The selected-subprotocol endpoint selects the first of the offered
|
||||
// protocols by default, and echoes it on a unidirectional stream.
|
||||
client_ = std::make_unique<DedicatedWebTransportHttp3Client>(
|
||||
GetURL("/selected-subprotocol"), origin_, &visitor_, anonymization_key_,
|
||||
context_.get(), parameters);
|
||||
|
||||
bool stream_received = false;
|
||||
EXPECT_CALL(visitor_, OnConnected).WillOnce(StopRunning());
|
||||
EXPECT_CALL(visitor_, OnIncomingUnidirectionalStreamAvailable).WillOnce([&] {
|
||||
stream_received = true;
|
||||
StopRunning();
|
||||
});
|
||||
client_->Connect();
|
||||
Run();
|
||||
ASSERT_TRUE(client_->session() != nullptr);
|
||||
|
||||
EXPECT_EQ(client_->session()->GetNegotiatedSubprotocol(), "first");
|
||||
|
||||
if (!stream_received) {
|
||||
Run();
|
||||
}
|
||||
|
||||
quic::WebTransportStream* stream =
|
||||
client_->session()->AcceptIncomingUnidirectionalStream();
|
||||
ASSERT_TRUE(stream != nullptr);
|
||||
std::string read_buffer;
|
||||
webtransport::Stream::ReadResult read_result = stream->Read(&read_buffer);
|
||||
ASSERT_TRUE(read_result.fin);
|
||||
EXPECT_EQ(read_buffer, "first");
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace net::test
|
||||
|
@ -106,9 +106,13 @@ struct NET_EXPORT WebTransportParameters {
|
||||
bool enable_web_transport_http3 = false;
|
||||
|
||||
// A vector of fingerprints for expected server certificates, as described in
|
||||
// https://wicg.github.io/web-transport/#dom-quictransportconfiguration-server_certificate_fingerprints
|
||||
// https://w3c.github.io/webtransport/#dom-webtransportoptions-servercertificatehashes
|
||||
// When empty, Web PKI is used.
|
||||
std::vector<quic::CertificateFingerprint> server_certificate_fingerprints;
|
||||
|
||||
// A vector of strings offered by client as a list of potential subprotocols.
|
||||
// https://w3c.github.io/webtransport/#dom-webtransportoptions-protocols
|
||||
std::vector<std::string> application_protocols;
|
||||
};
|
||||
|
||||
// An abstract base for a WebTransport client. Most of the useful operations
|
||||
|
Reference in New Issue
Block a user