Send the path and query parameters of QuicTransport URL in the client indication. gfe-relnote: n/a (not used in production) PiperOrigin-RevId: 283837693 Change-Id: I14d5de3a8da4af3af2ee7c00e07ac3feaa4e39f9
diff --git a/quic/quic_transport/quic_transport_client_session.cc b/quic/quic_transport/quic_transport_client_session.cc index f0110b7..e9487ec 100644 --- a/quic/quic_transport/quic_transport_client_session.cc +++ b/quic/quic_transport/quic_transport_client_session.cc
@@ -43,7 +43,7 @@ Visitor* owner, const QuicConfig& config, const ParsedQuicVersionVector& supported_versions, - const QuicServerId& server_id, + const GURL& url, QuicCryptoClientConfig* crypto_config, url::Origin origin, ClientVisitor* visitor) @@ -52,6 +52,7 @@ config, supported_versions, /*num_expected_unidirectional_static_streams*/ 0), + url_(url), origin_(origin), visitor_(visitor) { for (const ParsedQuicVersion& version : supported_versions) { @@ -61,8 +62,9 @@ // ProofHandler API is not used by TLS 1.3. static DummyProofHandler* proof_handler = new DummyProofHandler(); crypto_stream_ = std::make_unique<QuicCryptoClientStream>( - server_id, this, crypto_config->proof_verifier()->CreateDefaultContext(), - crypto_config, proof_handler); + QuicServerId(url.host(), url.EffectiveIntPort()), this, + crypto_config->proof_verifier()->CreateDefaultContext(), crypto_config, + proof_handler); } QuicStream* QuicTransportClientSession::CreateIncomingStream(QuicStreamId id) { @@ -153,16 +155,40 @@ QUIC_DLOG(INFO) << "Sending client indication with origin " << serialized_origin; - std::string buffer; - buffer.resize(/* key */ sizeof(QuicTransportClientIndicationKeys) + - /* length */ sizeof(uint16_t) + serialized_origin.size()); - QuicDataWriter writer(buffer.size(), &buffer[0]); - writer.WriteUInt16( - static_cast<uint16_t>(QuicTransportClientIndicationKeys::kOrigin)); - writer.WriteUInt16(serialized_origin.size()); - writer.WriteStringPiece(serialized_origin); + std::string path = url_.PathForRequest(); + if (path.size() > std::numeric_limits<uint16_t>::max()) { + connection()->CloseConnection( + QUIC_TRANSPORT_INVALID_CLIENT_INDICATION, "Requested URL path too long", + ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET); + return ""; + } - buffer.resize(writer.length()); + constexpr size_t kPrefixSize = + sizeof(QuicTransportClientIndicationKeys) + sizeof(uint16_t); + const size_t buffer_size = + 2 * kPrefixSize + serialized_origin.size() + path.size(); + if (buffer_size > std::numeric_limits<uint16_t>::max()) { + connection()->CloseConnection( + QUIC_TRANSPORT_INVALID_CLIENT_INDICATION, + "Client indication size limit exceeded", + ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET); + return ""; + } + + std::string buffer; + buffer.resize(buffer_size); + QuicDataWriter writer(buffer.size(), &buffer[0]); + bool success = + writer.WriteUInt16( + static_cast<uint16_t>(QuicTransportClientIndicationKeys::kOrigin)) && + writer.WriteUInt16(serialized_origin.size()) && + writer.WriteStringPiece(serialized_origin) && + writer.WriteUInt16( + static_cast<uint16_t>(QuicTransportClientIndicationKeys::kPath)) && + writer.WriteUInt16(path.size()) && writer.WriteStringPiece(path); + QUIC_BUG_IF(!success) << "Failed to serialize client indication"; + QUIC_BUG_IF(writer.length() != buffer.length()) + << "Serialized client indication has length different from expected"; return buffer; }
diff --git a/quic/quic_transport/quic_transport_client_session.h b/quic/quic_transport/quic_transport_client_session.h index 5872bf1..b3d8f17 100644 --- a/quic/quic_transport/quic_transport_client_session.h +++ b/quic/quic_transport/quic_transport_client_session.h
@@ -8,6 +8,7 @@ #include <cstdint> #include <memory> +#include "url/gurl.h" #include "url/origin.h" #include "net/third_party/quiche/src/quic/core/crypto/quic_crypto_client_config.h" #include "net/third_party/quiche/src/quic/core/quic_config.h" @@ -47,7 +48,7 @@ Visitor* owner, const QuicConfig& config, const ParsedQuicVersionVector& supported_versions, - const QuicServerId& server_id, + const GURL& url, QuicCryptoClientConfig* crypto_config, url::Origin origin, ClientVisitor* visitor); @@ -116,6 +117,7 @@ void SendClientIndication(); std::unique_ptr<QuicCryptoClientStream> crypto_stream_; + GURL url_; url::Origin origin_; ClientVisitor* visitor_; // not owned bool client_indication_sent_ = false;
diff --git a/quic/quic_transport/quic_transport_client_session_test.cc b/quic/quic_transport/quic_transport_client_session_test.cc index 53213a4..17a4757 100644 --- a/quic/quic_transport/quic_transport_client_session_test.cc +++ b/quic/quic_transport/quic_transport_client_session_test.cc
@@ -30,8 +30,6 @@ using testing::ElementsAre; const char* kTestOrigin = "https://test-origin.test"; -constexpr char kTestOriginClientIndication[] = - "\0\0\0\x18https://test-origin.test"; url::Origin GetTestOrigin() { GURL origin_url(kTestOrigin); return url::Origin::Create(origin_url); @@ -58,15 +56,15 @@ &alarm_factory_, Perspective::IS_CLIENT, GetVersions()), - server_id_("test.example.com", 443), crypto_config_(crypto_test_utils::ProofVerifierForTesting()) { SetQuicReloadableFlag(quic_supports_tls_handshake, true); - CreateSession(GetTestOrigin()); + CreateSession(GetTestOrigin(), ""); } - void CreateSession(url::Origin origin) { + void CreateSession(url::Origin origin, std::string url_suffix) { session_ = std::make_unique<QuicTransportClientSession>( - &connection_, nullptr, DefaultQuicConfig(), GetVersions(), server_id_, + &connection_, nullptr, DefaultQuicConfig(), GetVersions(), + GURL("quic-transport://test.example.com:50000" + url_suffix), &crypto_config_, origin, &visitor_); session_->Initialize(); crypto_stream_ = static_cast<QuicCryptoClientStream*>( @@ -87,7 +85,6 @@ MockQuicConnectionHelper helper_; PacketSavingConnection connection_; - QuicServerId server_id_; QuicCryptoClientConfig crypto_config_; MockClientVisitor visitor_; std::unique_ptr<QuicTransportClientSession> session_; @@ -99,6 +96,39 @@ } TEST_F(QuicTransportClientSessionTest, SuccessfulConnection) { + constexpr char kTestOriginClientIndication[] = + "\0\0" // key (0x0000, origin) + "\0\x18" // length + "https://test-origin.test" // value + "\0\x01" // key (0x0001, path) + "\0\x01" // length + "/"; // value + + Connect(); + EXPECT_TRUE(session_->IsSessionReady()); + + QuicStream* client_indication_stream = + QuicSessionPeer::zombie_streams(session_.get())[ClientIndicationStream()] + .get(); + ASSERT_TRUE(client_indication_stream != nullptr); + const std::string client_indication = DataInStream(client_indication_stream); + const std::string expected_client_indication{ + kTestOriginClientIndication, + QUIC_ARRAYSIZE(kTestOriginClientIndication) - 1}; + EXPECT_EQ(client_indication, expected_client_indication); +} + +TEST_F(QuicTransportClientSessionTest, SuccessfulConnectionWithPath) { + constexpr char kSuffix[] = "/foo/bar?hello=world#not-sent"; + constexpr char kTestOriginClientIndication[] = + "\0\0" // key (0x0000, origin) + "\0\x18" // length + "https://test-origin.test" // value + "\0\x01" // key (0x0001, path) + "\0\x14" // length + "/foo/bar?hello=world"; // value + + CreateSession(GetTestOrigin(), kSuffix); Connect(); EXPECT_TRUE(session_->IsSessionReady()); @@ -117,7 +147,7 @@ std::string long_string(68000, 'a'); GURL bad_origin_url{"https://" + long_string + ".example/"}; EXPECT_TRUE(bad_origin_url.is_valid()); - CreateSession(url::Origin::Create(bad_origin_url)); + CreateSession(url::Origin::Create(bad_origin_url), ""); EXPECT_QUIC_BUG(Connect(), "Client origin too long"); }
diff --git a/quic/quic_transport/quic_transport_integration_test.cc b/quic/quic_transport/quic_transport_integration_test.cc index 715bd9f..57f5380 100644 --- a/quic/quic_transport/quic_transport_integration_test.cc +++ b/quic/quic_transport/quic_transport_integration_test.cc
@@ -80,7 +80,7 @@ nullptr, DefaultQuicConfig(), GetVersions(), - QuicServerId("test.example.com", 443), + GURL("quic-transport://test.example.com:50000"), &crypto_config_, origin, &visitor_) {
diff --git a/quic/quic_transport/quic_transport_protocol.h b/quic/quic_transport/quic_transport_protocol.h index 47ed877..f97b8e7 100644 --- a/quic/quic_transport/quic_transport_protocol.h +++ b/quic/quic_transport/quic_transport_protocol.h
@@ -29,6 +29,7 @@ // The keys of the fields in the client indication. enum class QuicTransportClientIndicationKeys : uint16_t { kOrigin = 0x0000, + kPath = 0x0001, }; } // namespace quic