Add a new mode to MockCryptoClientStream to send CHLO packet on wire on cold start.
This mode can be used in QuicStreamFactoryTest to simulate cases where connection
migraiton is triggered while crypto handshake is not completed.
Bug: 790547
Change-Id: I3c32f156d503318b9a9b203c772d3ec4ed41d9f8
Reviewed-on: https://chromium-review.googlesource.com/1157439
Commit-Queue: Zhongyi Shi <[email protected]>
Reviewed-by: Ryan Hamilton <[email protected]>
Cr-Commit-Position: refs/heads/master@{#580243}
diff --git a/net/quic/mock_crypto_client_stream.cc b/net/quic/mock_crypto_client_stream.cc
index 57ae56a..6631b986 100644
--- a/net/quic/mock_crypto_client_stream.cc
+++ b/net/quic/mock_crypto_client_stream.cc
@@ -43,6 +43,7 @@
using quic::QuicSession;
using quic::QuicSpdyClientSessionBase;
using quic::QuicString;
+using quic::QuicStringPiece;
using quic::QuicTagVector;
using quic::QuicTime;
@@ -163,8 +164,19 @@
break;
}
- case USE_DEFAULT_CRYPTO_STREAM: {
- NOTREACHED();
+ case COLD_START_WITH_CHLO_SENT: {
+ handshake_confirmed_ = false;
+ encryption_established_ = false;
+
+ CryptoHandshakeMessage message = GetDummyCHLOMessage();
+ QUIC_DVLOG(1) << "Sending "
+ << message.DebugString(session()->perspective());
+ session()->NeuterUnencryptedData();
+ session()->OnCryptoHandshakeMessageSent(message);
+ const quic::QuicData& data =
+ message.GetSerialized(session()->perspective());
+ WriteOrBufferData(QuicStringPiece(data.data(), data.length()), false,
+ nullptr);
break;
}
}
@@ -216,6 +228,13 @@
session()->OnCryptoHandshakeEvent(event);
}
+// static
+CryptoHandshakeMessage MockCryptoClientStream::GetDummyCHLOMessage() {
+ CryptoHandshakeMessage message;
+ message.set_tag(quic::kCHLO);
+ return message;
+}
+
void MockCryptoClientStream::SetConfigNegotiated() {
ASSERT_FALSE(session()->config()->negotiated());
QuicTagVector cgst;
diff --git a/net/quic/mock_crypto_client_stream.h b/net/quic/mock_crypto_client_stream.h
index 382a797..4a35f72 100644
--- a/net/quic/mock_crypto_client_stream.h
+++ b/net/quic/mock_crypto_client_stream.h
@@ -21,8 +21,6 @@
class MockCryptoClientStream : public quic::QuicCryptoClientStream,
public quic::QuicCryptoHandshaker {
public:
- // TODO(zhongyi): might consider move HandshakeMode up to
- // MockCryptoClientStreamFactory.
// HandshakeMode enumerates the handshake mode MockCryptoClientStream should
// mock in CryptoConnect.
enum HandshakeMode {
@@ -36,13 +34,14 @@
ZERO_RTT,
// COLD_START indicates that CryptoConnect will neither establish encryption
- // nor confirm the handshake
+ // nor confirm the handshake.
COLD_START,
- // USE_DEFAULT_CRYPTO_STREAM indicates that MockCryptoClientStreamFactory
- // will create a QuicCryptoClientStream instead of a
- // MockCryptoClientStream.
- USE_DEFAULT_CRYPTO_STREAM,
+ // COLD_START_WITH_CHLO_SENT indicates that CryptoConnection will attempt to
+ // establish encryption by sending the initial CHLO packet on wire, which
+ // contains an empty CryptoHandshakeMessage. It will not confirm the
+ // hanshake though.
+ COLD_START_WITH_CHLO_SENT,
};
MockCryptoClientStream(
@@ -72,13 +71,15 @@
void SendOnCryptoHandshakeEvent(
quic::QuicSession::CryptoHandshakeEvent event);
- HandshakeMode handshake_mode_;
+ static quic::CryptoHandshakeMessage GetDummyCHLOMessage();
protected:
using quic::QuicCryptoClientStream::session;
private:
void SetConfigNegotiated();
+
+ HandshakeMode handshake_mode_;
bool encryption_established_;
bool handshake_confirmed_;
quic::QuicReferenceCountedPointer<quic::QuicCryptoNegotiatedParameters>
diff --git a/net/quic/mock_crypto_client_stream_factory.cc b/net/quic/mock_crypto_client_stream_factory.cc
index c8a415a..8fb80c9 100644
--- a/net/quic/mock_crypto_client_stream_factory.cc
+++ b/net/quic/mock_crypto_client_stream_factory.cc
@@ -30,11 +30,6 @@
QuicChromiumClientSession* session,
std::unique_ptr<quic::ProofVerifyContext> /*proof_verify_context*/,
quic::QuicCryptoClientConfig* crypto_config) {
- if (handshake_mode_ == MockCryptoClientStream::USE_DEFAULT_CRYPTO_STREAM) {
- return new quic::QuicCryptoClientStream(server_id, session, nullptr,
- crypto_config, session);
- }
-
const ProofVerifyDetailsChromium* proof_verify_details = nullptr;
if (!proof_verify_details_queue_.empty()) {
proof_verify_details = proof_verify_details_queue_.front();
diff --git a/net/quic/quic_stream_factory_test.cc b/net/quic/quic_stream_factory_test.cc
index a2fd432..16a17518 100644
--- a/net/quic/quic_stream_factory_test.cc
+++ b/net/quic/quic_stream_factory_test.cc
@@ -1802,7 +1802,7 @@
Initialize();
// Use unmocked crypto stream to do crypto connect.
crypto_client_stream_factory_.set_handshake_mode(
- MockCryptoClientStream::USE_DEFAULT_CRYPTO_STREAM);
+ MockCryptoClientStream::COLD_START_WITH_CHLO_SENT);
MockQuicData socket_data;
socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
@@ -1863,7 +1863,7 @@
Initialize();
// Use unmocked crypto stream to do crypto connect.
crypto_client_stream_factory_.set_handshake_mode(
- MockCryptoClientStream::USE_DEFAULT_CRYPTO_STREAM);
+ MockCryptoClientStream::COLD_START_WITH_CHLO_SENT);
host_resolver_.set_synchronous_mode(true);
host_resolver_.rules()->AddIPLiteralRule(host_port_pair_.host(),
"192.168.0.1", "");
@@ -2188,12 +2188,12 @@
// The response to the earlier request is read on the new socket.
MockQuicData quic_data2;
// Connectivity probe to be sent on the new path.
- quic_data2.AddWrite(
- SYNCHRONOUS, client_maker_.MakeConnectivityProbingPacket(3, true, 1338));
+ quic_data2.AddWrite(SYNCHRONOUS,
+ client_maker_.MakeConnectivityProbingPacket(3, true));
quic_data2.AddRead(ASYNC, ERR_IO_PENDING); // Pause
// Connectivity probe to receive from the server.
- quic_data2.AddRead(
- ASYNC, server_maker_.MakeConnectivityProbingPacket(1, false, 1338));
+ quic_data2.AddRead(ASYNC,
+ server_maker_.MakeConnectivityProbingPacket(1, false));
// Ping packet to send after migration is completed.
quic_data2.AddWrite(ASYNC,
client_maker_.MakeAckAndPingPacket(4, false, 1, 1, 1));
@@ -2360,16 +2360,16 @@
// The response to the earlier request is read on the new socket.
MockQuicData quic_data2;
// First connectivity probe to be sent on the new path.
- quic_data2.AddWrite(
- SYNCHRONOUS, client_maker_.MakeConnectivityProbingPacket(3, true, 1338));
+ quic_data2.AddWrite(SYNCHRONOUS,
+ client_maker_.MakeConnectivityProbingPacket(3, true));
quic_data2.AddRead(ASYNC,
ERR_IO_PENDING); // Pause so that we can control time.
// Connectivity probe to receive from the server.
- quic_data2.AddRead(
- ASYNC, server_maker_.MakeConnectivityProbingPacket(1, false, 1338));
+ quic_data2.AddRead(ASYNC,
+ server_maker_.MakeConnectivityProbingPacket(1, false));
// Second connectivity probe which will complete asynchronously.
- quic_data2.AddWrite(
- ASYNC, client_maker_.MakeConnectivityProbingPacket(4, true, 1338));
+ quic_data2.AddWrite(ASYNC,
+ client_maker_.MakeConnectivityProbingPacket(4, true));
quic_data2.AddRead(
ASYNC, ConstructOkResponsePacket(2, GetNthClientInitiatedStreamId(0),
false, false));
@@ -2596,12 +2596,12 @@
// Set up the second socket data provider that is used for probing.
MockQuicData quic_data1;
// Connectivity probe to be sent on the new path.
- quic_data1.AddWrite(
- SYNCHRONOUS, client_maker_.MakeConnectivityProbingPacket(2, true, 1338));
+ quic_data1.AddWrite(SYNCHRONOUS,
+ client_maker_.MakeConnectivityProbingPacket(2, true));
quic_data1.AddRead(ASYNC, ERR_IO_PENDING); // Pause
// Connectivity probe to receive from the server.
- quic_data1.AddRead(
- ASYNC, server_maker_.MakeConnectivityProbingPacket(1, false, 1338));
+ quic_data1.AddRead(ASYNC,
+ server_maker_.MakeConnectivityProbingPacket(1, false));
quic_data1.AddSocketDataToFactory(socket_factory_.get());
// Create request and QuicHttpStream.
@@ -3199,11 +3199,11 @@
MockQuicData quic_data2;
// Connectivity probe to be sent on the new path.
quic_data2.AddWrite(SYNCHRONOUS, client_maker_.MakeConnectivityProbingPacket(
- packet_number++, true, 1338));
+ packet_number++, true));
quic_data2.AddRead(ASYNC, ERR_IO_PENDING); // Pause
// Connectivity probe to receive from the server.
- quic_data2.AddRead(
- ASYNC, server_maker_.MakeConnectivityProbingPacket(1, false, 1338));
+ quic_data2.AddRead(ASYNC,
+ server_maker_.MakeConnectivityProbingPacket(1, false));
// Ping packet to send after migration is completed.
quic_data2.AddWrite(ASYNC, client_maker_.MakeAckAndPingPacket(
packet_number++, false, 1, 1, 1));
@@ -3476,11 +3476,11 @@
MockQuicData quic_data2;
// Connectivity probe to be sent on the new path.
quic_data2.AddWrite(SYNCHRONOUS, client_maker_.MakeConnectivityProbingPacket(
- packet_number++, false, 1338));
+ packet_number++, false));
quic_data2.AddRead(ASYNC, ERR_IO_PENDING); // Pause
// Connectivity probe to receive from the server.
- quic_data2.AddRead(
- ASYNC, server_maker_.MakeConnectivityProbingPacket(3, false, 1338));
+ quic_data2.AddRead(ASYNC,
+ server_maker_.MakeConnectivityProbingPacket(3, false));
// Ping packet to send after migration is completed.
quic_data2.AddWrite(
write_mode_for_queued_packet,
@@ -3632,12 +3632,12 @@
// The response to the earlier request is read on the new socket.
MockQuicData quic_data2;
// Connectivity probe to be sent on the new path.
- quic_data2.AddWrite(
- SYNCHRONOUS, client_maker_.MakeConnectivityProbingPacket(3, true, 1338));
+ quic_data2.AddWrite(SYNCHRONOUS,
+ client_maker_.MakeConnectivityProbingPacket(3, true));
quic_data2.AddRead(ASYNC, ERR_IO_PENDING); // Pause
// Connectivity probe to receive from the server.
- quic_data2.AddRead(
- ASYNC, server_maker_.MakeConnectivityProbingPacket(1, false, 1338));
+ quic_data2.AddRead(ASYNC,
+ server_maker_.MakeConnectivityProbingPacket(1, false));
// Ping packet to send after migration is completed.
quic_data2.AddWrite(ASYNC,
client_maker_.MakeAckAndPingPacket(4, false, 1, 1, 1));
@@ -3982,12 +3982,12 @@
// Set up the second socket data provider that is used for probing.
MockQuicData quic_data1;
// Connectivity probe to be sent on the new path.
- quic_data1.AddWrite(
- SYNCHRONOUS, client_maker_.MakeConnectivityProbingPacket(2, true, 1338));
+ quic_data1.AddWrite(SYNCHRONOUS,
+ client_maker_.MakeConnectivityProbingPacket(2, true));
quic_data1.AddRead(ASYNC, ERR_IO_PENDING); // Pause
// Connectivity probe to receive from the server.
- quic_data1.AddRead(
- ASYNC, server_maker_.MakeConnectivityProbingPacket(1, false, 1338));
+ quic_data1.AddRead(ASYNC,
+ server_maker_.MakeConnectivityProbingPacket(1, false));
quic_data1.AddSocketDataToFactory(socket_factory_.get());
// Create request and QuicHttpStream.
@@ -4344,11 +4344,11 @@
// Set up the third socket data provider for migrate back to default network.
MockQuicData quic_data3;
// Connectivity probe to be sent on the new path.
- quic_data3.AddWrite(
- SYNCHRONOUS, client_maker_.MakeConnectivityProbingPacket(3, false, 1338));
+ quic_data3.AddWrite(SYNCHRONOUS,
+ client_maker_.MakeConnectivityProbingPacket(3, false));
// Connectivity probe to receive from the server.
- quic_data3.AddRead(
- ASYNC, server_maker_.MakeConnectivityProbingPacket(2, false, 1338));
+ quic_data3.AddRead(ASYNC,
+ server_maker_.MakeConnectivityProbingPacket(2, false));
quic_data3.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
quic_data3.AddWrite(ASYNC, client_maker_.MakeAckPacket(4, 1, 2, 1, 1, true));
quic_data3.AddWrite(
@@ -4391,7 +4391,7 @@
// Use unmocked crypto stream to do crypto connect.
crypto_client_stream_factory_.set_handshake_mode(
- MockCryptoClientStream::USE_DEFAULT_CRYPTO_STREAM);
+ MockCryptoClientStream::COLD_START_WITH_CHLO_SENT);
MockQuicData socket_data;
socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
@@ -5327,15 +5327,13 @@
InitializeConnectionMigrationV2Test(
{kDefaultNetworkForTests, kNewNetworkForTests});
- // Use unmocked crypto stream to do crypto connect.
+ // Use cold start mode to do crypto connect, and send CHLO packet on wire.
crypto_client_stream_factory_.set_handshake_mode(
- MockCryptoClientStream::USE_DEFAULT_CRYPTO_STREAM);
+ MockCryptoClientStream::COLD_START_WITH_CHLO_SENT);
- // Add hanging socket data so that handshake is not confirmed when
- // OnNetworkDisconnected is delivered.
MockQuicData socket_data;
- socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING); // Hanging read.
- socket_data.AddWrite(SYNCHRONOUS, ERR_IO_PENDING); // Hanging write.
+ socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
+ socket_data.AddWrite(ASYNC, client_maker_.MakeInitialDummyCHLOPacket());
socket_data.AddSocketDataToFactory(socket_factory_.get());
// Create request and QuicHttpStream.
diff --git a/net/quic/quic_test_packet_maker.cc b/net/quic/quic_test_packet_maker.cc
index 0b7e6ade..ae74228 100644
--- a/net/quic/quic_test_packet_maker.cc
+++ b/net/quic/quic_test_packet_maker.cc
@@ -7,6 +7,7 @@
#include <list>
#include <utility>
+#include "net/quic/mock_crypto_client_stream.h"
#include "net/quic/quic_http_utils.h"
#include "net/third_party/quic/core/quic_framer.h"
#include "net/third_party/quic/core/quic_utils.h"
@@ -54,10 +55,8 @@
}
std::unique_ptr<quic::QuicReceivedPacket>
-QuicTestPacketMaker::MakeConnectivityProbingPacket(
- quic::QuicPacketNumber num,
- bool include_version,
- quic::QuicByteCount packet_length) {
+QuicTestPacketMaker::MakeConnectivityProbingPacket(quic::QuicPacketNumber num,
+ bool include_version) {
quic::QuicPacketHeader header;
header.destination_connection_id = connection_id_;
header.destination_connection_id_length = GetDestinationConnectionIdLength();
@@ -72,15 +71,16 @@
quic::QuicFramer framer(quic::test::SupportedVersions(quic::ParsedQuicVersion(
quic::PROTOCOL_QUIC_CRYPTO, version_)),
clock_->Now(), perspective_);
-
- char buffer[quic::kMaxPacketSize];
+ size_t max_plaintext_size =
+ framer.GetMaxPlaintextSize(quic::kDefaultMaxPacketSize);
+ char buffer[quic::kDefaultMaxPacketSize];
size_t length =
- framer.BuildConnectivityProbingPacket(header, buffer, packet_length);
+ framer.BuildConnectivityProbingPacket(header, buffer, max_plaintext_size);
size_t encrypted_size = framer.EncryptInPlace(
quic::ENCRYPTION_NONE, header.packet_number,
GetStartOfEncryptedData(framer.transport_version(), header), length,
- quic::kMaxPacketSize, buffer);
- EXPECT_NE(0u, encrypted_size);
+ quic::kDefaultMaxPacketSize, buffer);
+ EXPECT_EQ(quic::kDefaultMaxPacketSize, encrypted_size);
quic::QuicReceivedPacket encrypted(buffer, encrypted_size, clock_->Now(),
false);
return encrypted.Clone();
@@ -105,6 +105,45 @@
}
std::unique_ptr<quic::QuicReceivedPacket>
+QuicTestPacketMaker::MakeInitialDummyCHLOPacket() {
+ encryption_level_ = quic::ENCRYPTION_NONE;
+ SetLongHeaderType(quic::INITIAL);
+ InitializeHeader(/*packet_number=*/1, /*include_version=*/true);
+
+ quic::CryptoHandshakeMessage message =
+ MockCryptoClientStream::GetDummyCHLOMessage();
+ const quic::QuicData& data =
+ message.GetSerialized(quic::Perspective::IS_CLIENT);
+
+ quic::QuicFrames frames;
+ quic::QuicStreamFrame frame(
+ quic::kCryptoStreamId, /*fin=*/false, /*offset=*/0,
+ quic::QuicStringPiece(data.data(), data.length()));
+ frames.push_back(quic::QuicFrame(&frame));
+ DVLOG(1) << "Adding frame: " << frames.back();
+ quic::QuicPaddingFrame padding;
+ frames.push_back(quic::QuicFrame(padding));
+ DVLOG(1) << "Adding frame: " << frames.back();
+
+ quic::QuicFramer framer(quic::test::SupportedVersions(quic::ParsedQuicVersion(
+ quic::PROTOCOL_QUIC_CRYPTO, version_)),
+ clock_->Now(), perspective_);
+ size_t max_plaintext_size =
+ framer.GetMaxPlaintextSize(quic::kDefaultMaxPacketSize);
+ std::unique_ptr<quic::QuicPacket> packet(quic::test::BuildUnsizedDataPacket(
+ &framer, header_, frames, max_plaintext_size));
+
+ char buffer[quic::kDefaultMaxPacketSize];
+ size_t encrypted_size =
+ framer.EncryptPayload(quic::ENCRYPTION_NONE, header_.packet_number,
+ *packet, buffer, quic::kDefaultMaxPacketSize);
+ EXPECT_EQ(quic::kDefaultMaxPacketSize, encrypted_size);
+ quic::QuicReceivedPacket encrypted(buffer, encrypted_size,
+ quic::QuicTime::Zero(), false);
+ return encrypted.Clone();
+}
+
+std::unique_ptr<quic::QuicReceivedPacket>
QuicTestPacketMaker::MakeAckAndPingPacket(
quic::QuicPacketNumber num,
bool include_version,
diff --git a/net/quic/quic_test_packet_maker.h b/net/quic/quic_test_packet_maker.h
index 6553eb1..4906ee9e 100644
--- a/net/quic/quic_test_packet_maker.h
+++ b/net/quic/quic_test_packet_maker.h
@@ -50,11 +50,11 @@
void set_hostname(const std::string& host);
std::unique_ptr<quic::QuicReceivedPacket> MakeConnectivityProbingPacket(
quic::QuicPacketNumber num,
- bool include_version,
- quic::QuicByteCount packet_length);
+ bool include_version);
std::unique_ptr<quic::QuicReceivedPacket> MakePingPacket(
quic::QuicPacketNumber num,
bool include_version);
+ std::unique_ptr<quic::QuicReceivedPacket> MakeInitialDummyCHLOPacket();
std::unique_ptr<quic::QuicReceivedPacket> MakeAckAndPingPacket(
quic::QuicPacketNumber num,
bool include_version,