Fully support draft-28 transport parameters
This CL adopts the new transport parameters from
QuicConnection and QuicSession.
Add draft-28 transport parameters, protected by draft-28 flag
PiperOrigin-RevId: 313860932
Change-Id: I1384f3457c254802fec33b24fb62cf555a772051
diff --git a/quic/core/http/quic_spdy_session_test.cc b/quic/core/http/quic_spdy_session_test.cc
index 1e36258..ba22c81 100644
--- a/quic/core/http/quic_spdy_session_test.cc
+++ b/quic/core/http/quic_spdy_session_test.cc
@@ -91,6 +91,17 @@
kInitialStreamFlowControlWindowForTest);
session()->config()->SetInitialSessionFlowControlWindowToSend(
kInitialSessionFlowControlWindowForTest);
+ if (session()->version().AuthenticatesHandshakeConnectionIds()) {
+ if (session()->perspective() == Perspective::IS_CLIENT) {
+ session()->config()->SetOriginalConnectionIdToSend(
+ session()->connection()->connection_id());
+ session()->config()->SetInitialSourceConnectionIdToSend(
+ session()->connection()->connection_id());
+ } else {
+ session()->config()->SetInitialSourceConnectionIdToSend(
+ session()->connection()->client_connection_id());
+ }
+ }
if (session()->connection()->version().handshake_protocol ==
PROTOCOL_TLS1_3) {
TransportParameters transport_parameters;
diff --git a/quic/core/http/quic_spdy_stream_test.cc b/quic/core/http/quic_spdy_stream_test.cc
index 41c204f..7ab9aa0 100644
--- a/quic/core/http/quic_spdy_stream_test.cc
+++ b/quic/core/http/quic_spdy_stream_test.cc
@@ -78,6 +78,17 @@
kInitialStreamFlowControlWindowForTest);
session()->config()->SetInitialSessionFlowControlWindowToSend(
kInitialSessionFlowControlWindowForTest);
+ if (session()->version().AuthenticatesHandshakeConnectionIds()) {
+ if (session()->perspective() == Perspective::IS_CLIENT) {
+ session()->config()->SetOriginalConnectionIdToSend(
+ session()->connection()->connection_id());
+ session()->config()->SetInitialSourceConnectionIdToSend(
+ session()->connection()->connection_id());
+ } else {
+ session()->config()->SetInitialSourceConnectionIdToSend(
+ session()->connection()->client_connection_id());
+ }
+ }
if (session()->connection()->version().handshake_protocol ==
PROTOCOL_TLS1_3) {
TransportParameters transport_parameters;
diff --git a/quic/core/quic_connection.cc b/quic/core/quic_connection.cc
index 1ed056d..17b3fee 100644
--- a/quic/core/quic_connection.cc
+++ b/quic/core/quic_connection.cc
@@ -402,6 +402,141 @@
buffered_packets_.clear();
}
+bool QuicConnection::ValidateConfigConnectionIdsOld(const QuicConfig& config) {
+ // This function validates connection IDs as defined in IETF draft-27 and
+ // earlier.
+ DCHECK(config.negotiated());
+ DCHECK(!version().AuthenticatesHandshakeConnectionIds());
+ if (original_destination_connection_id_.has_value() &&
+ retry_source_connection_id_.has_value()) {
+ DCHECK_EQ(perspective_, Perspective::IS_CLIENT);
+ // We received a RETRY packet, validate that the original destination
+ // connection ID from the config matches the one from the RETRY.
+ if (!config.HasReceivedOriginalConnectionId() ||
+ config.ReceivedOriginalConnectionId() !=
+ original_destination_connection_id_.value()) {
+ std::string received_value;
+ if (config.HasReceivedOriginalConnectionId()) {
+ received_value = config.ReceivedOriginalConnectionId().ToString();
+ } else {
+ received_value = "none";
+ }
+ std::string error_details = quiche::QuicheStrCat(
+ "Bad original_connection_id: expected ",
+ original_destination_connection_id_.value().ToString(), ", received ",
+ received_value, ", RETRY used ", server_connection_id_.ToString());
+ CloseConnection(IETF_QUIC_PROTOCOL_VIOLATION, error_details,
+ ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
+ return false;
+ }
+ } else {
+ // We did not receive a RETRY packet, make sure we did not receive the
+ // original_destination_connection_id transport parameter.
+ if (config.HasReceivedOriginalConnectionId()) {
+ std::string error_details = quiche::QuicheStrCat(
+ "Bad original_connection_id: did not receive RETRY but received ",
+ config.ReceivedOriginalConnectionId().ToString());
+ CloseConnection(IETF_QUIC_PROTOCOL_VIOLATION, error_details,
+ ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
+ return false;
+ }
+ }
+ return true;
+}
+
+bool QuicConnection::ValidateConfigConnectionIds(const QuicConfig& config) {
+ DCHECK(config.negotiated());
+ if (!version().UsesTls()) {
+ // QUIC+TLS is required to transmit connection ID transport parameters.
+ return true;
+ }
+ if (!version().AuthenticatesHandshakeConnectionIds()) {
+ return ValidateConfigConnectionIdsOld(config);
+ }
+ // This function validates connection IDs as defined in IETF draft-28 and
+ // later.
+
+ // Validate initial_source_connection_id.
+ QuicConnectionId expected_initial_source_connection_id;
+ if (perspective_ == Perspective::IS_CLIENT) {
+ expected_initial_source_connection_id = server_connection_id_;
+ } else {
+ expected_initial_source_connection_id = client_connection_id_;
+ }
+ if (!config.HasReceivedInitialSourceConnectionId() ||
+ config.ReceivedInitialSourceConnectionId() !=
+ expected_initial_source_connection_id) {
+ std::string received_value;
+ if (config.HasReceivedInitialSourceConnectionId()) {
+ received_value = config.ReceivedInitialSourceConnectionId().ToString();
+ } else {
+ received_value = "none";
+ }
+ std::string error_details =
+ quiche::QuicheStrCat("Bad initial_source_connection_id: expected ",
+ expected_initial_source_connection_id.ToString(),
+ ", received ", received_value);
+ CloseConnection(IETF_QUIC_PROTOCOL_VIOLATION, error_details,
+ ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
+ return false;
+ }
+ if (perspective_ == Perspective::IS_CLIENT) {
+ // Validate original_destination_connection_id.
+ if (!config.HasReceivedOriginalConnectionId() ||
+ config.ReceivedOriginalConnectionId() !=
+ GetOriginalDestinationConnectionId()) {
+ std::string received_value;
+ if (config.HasReceivedOriginalConnectionId()) {
+ received_value = config.ReceivedOriginalConnectionId().ToString();
+ } else {
+ received_value = "none";
+ }
+ std::string error_details = quiche::QuicheStrCat(
+ "Bad original_destination_connection_id: expected ",
+ GetOriginalDestinationConnectionId().ToString(), ", received ",
+ received_value);
+ CloseConnection(IETF_QUIC_PROTOCOL_VIOLATION, error_details,
+ ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
+ return false;
+ }
+ // Validate retry_source_connection_id.
+ if (retry_source_connection_id_.has_value()) {
+ // We received a RETRY packet, validate that the retry source
+ // connection ID from the config matches the one from the RETRY.
+ if (!config.HasReceivedRetrySourceConnectionId() ||
+ config.ReceivedRetrySourceConnectionId() !=
+ retry_source_connection_id_.value()) {
+ std::string received_value;
+ if (config.HasReceivedRetrySourceConnectionId()) {
+ received_value = config.ReceivedRetrySourceConnectionId().ToString();
+ } else {
+ received_value = "none";
+ }
+ std::string error_details =
+ quiche::QuicheStrCat("Bad retry_source_connection_id: expected ",
+ retry_source_connection_id_.value().ToString(),
+ ", received ", received_value);
+ CloseConnection(IETF_QUIC_PROTOCOL_VIOLATION, error_details,
+ ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
+ return false;
+ }
+ } else {
+ // We did not receive a RETRY packet, make sure we did not receive the
+ // retry_source_connection_id transport parameter.
+ if (config.HasReceivedRetrySourceConnectionId()) {
+ std::string error_details = quiche::QuicheStrCat(
+ "Bad retry_source_connection_id: did not receive RETRY but "
+ "received ",
+ config.ReceivedRetrySourceConnectionId().ToString());
+ CloseConnection(IETF_QUIC_PROTOCOL_VIOLATION, error_details,
+ ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
+ return false;
+ }
+ }
+ }
+ return true;
+}
+
void QuicConnection::SetFromConfig(const QuicConfig& config) {
if (config.negotiated()) {
// Handshake complete, set handshake timeout to Infinite.
@@ -409,38 +544,8 @@
config.IdleNetworkTimeout());
idle_timeout_connection_close_behavior_ =
ConnectionCloseBehavior::SILENT_CLOSE;
- if (original_connection_id_.has_value()) {
- DCHECK_EQ(perspective_, Perspective::IS_CLIENT);
- // We received a RETRY packet, validate that the |original_connection_id|
- // from the config matches the one from the RETRY.
- if (!config.HasReceivedOriginalConnectionId() ||
- config.ReceivedOriginalConnectionId() !=
- original_connection_id_.value()) {
- std::string received_value;
- if (config.HasReceivedOriginalConnectionId()) {
- received_value = config.ReceivedOriginalConnectionId().ToString();
- } else {
- received_value = "none";
- }
- std::string error_details = quiche::QuicheStrCat(
- "Bad original_connection_id: expected ",
- original_connection_id_.value().ToString(), ", received ",
- received_value, ", RETRY used ", server_connection_id_.ToString());
- CloseConnection(IETF_QUIC_PROTOCOL_VIOLATION, error_details,
- ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
- return;
- }
- } else {
- // We did not receive a RETRY packet, make sure we did not receive the
- // original_connection_id transport parameter.
- if (config.HasReceivedOriginalConnectionId()) {
- std::string error_details = quiche::QuicheStrCat(
- "Bad original_connection_id: did not receive RETRY but received ",
- config.ReceivedOriginalConnectionId().ToString());
- CloseConnection(IETF_QUIC_PROTOCOL_VIOLATION, error_details,
- ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
- return;
- }
+ if (!ValidateConfigConnectionIds(config)) {
+ return;
}
} else {
SetNetworkTimeouts(config.max_time_before_crypto_handshake(),
@@ -719,8 +824,12 @@
<< server_connection_id_ << " with " << new_connection_id
<< ", received token "
<< quiche::QuicheTextUtils::HexEncode(retry_token);
- DCHECK(!original_connection_id_.has_value());
- original_connection_id_ = server_connection_id_;
+ if (!original_destination_connection_id_.has_value()) {
+ original_destination_connection_id_ = server_connection_id_;
+ }
+ DCHECK(!retry_source_connection_id_.has_value())
+ << retry_source_connection_id_.value();
+ retry_source_connection_id_ = new_connection_id;
server_connection_id_ = new_connection_id;
packet_creator_.SetServerConnectionId(server_connection_id_);
packet_creator_.SetRetryToken(retry_token);
@@ -741,11 +850,25 @@
void QuicConnection::SetOriginalDestinationConnectionId(
const QuicConnectionId& original_destination_connection_id) {
+ QUIC_DLOG(INFO) << "Setting original_destination_connection_id to "
+ << original_destination_connection_id
+ << " on connection with server_connection_id "
+ << server_connection_id_;
DCHECK_NE(original_destination_connection_id, server_connection_id_);
if (!HasIncomingConnectionId(original_destination_connection_id)) {
incoming_connection_ids_.push_back(original_destination_connection_id);
}
InstallInitialCrypters(original_destination_connection_id);
+ DCHECK(!original_destination_connection_id_.has_value())
+ << original_destination_connection_id_.value();
+ original_destination_connection_id_ = original_destination_connection_id;
+}
+
+QuicConnectionId QuicConnection::GetOriginalDestinationConnectionId() {
+ if (original_destination_connection_id_.has_value()) {
+ return original_destination_connection_id_.value();
+ }
+ return server_connection_id_;
}
bool QuicConnection::OnUnauthenticatedPublicHeader(
@@ -2068,6 +2191,9 @@
QUIC_DLOG(INFO) << ENDPOINT << "Replacing connection ID "
<< server_connection_id_ << " with "
<< header.source_connection_id;
+ if (!original_destination_connection_id_.has_value()) {
+ original_destination_connection_id_ = server_connection_id_;
+ }
server_connection_id_ = header.source_connection_id;
packet_creator_.SetServerConnectionId(server_connection_id_);
}
diff --git a/quic/core/quic_connection.h b/quic/core/quic_connection.h
index 589568a..6782e06 100644
--- a/quic/core/quic_connection.h
+++ b/quic/core/quic_connection.h
@@ -952,6 +952,9 @@
void SetOriginalDestinationConnectionId(
const QuicConnectionId& original_destination_connection_id);
+ // Returns the original destination connection ID used for this connection.
+ QuicConnectionId GetOriginalDestinationConnectionId();
+
// Called when ACK alarm goes off. Sends ACKs of those packet number spaces
// which have expired ACK timeout. Only used when this connection supports
// multiple packet number spaces.
@@ -1303,6 +1306,11 @@
QuicTime::Delta GetHandshakeTimeout() const;
QuicTime GetTimeOfLastReceivedPacket() const;
+ // Validate connection IDs used during the handshake. Closes the connection
+ // on validation failure.
+ bool ValidateConfigConnectionIds(const QuicConfig& config);
+ bool ValidateConfigConnectionIdsOld(const QuicConfig& config);
+
QuicFramer framer_;
// Contents received in the current packet, especially used to identify
@@ -1619,10 +1627,15 @@
// vector to improve performance since it is expected to be very small.
std::vector<QuicConnectionId> incoming_connection_ids_;
- // When we receive a RETRY packet, we replace |server_connection_id_| with the
- // value from the RETRY packet and save off the original value of
- // |server_connection_id_| into |original_connection_id_| for validation.
- quiche::QuicheOptional<QuicConnectionId> original_connection_id_;
+ // When we receive a RETRY packet or some INITIAL packets, we replace
+ // |server_connection_id_| with the value from that packet and save off the
+ // original value of |server_connection_id_| into
+ // |original_destination_connection_id_| for validation.
+ quiche::QuicheOptional<QuicConnectionId> original_destination_connection_id_;
+
+ // After we receive a RETRY packet, |retry_source_connection_id_| contains
+ // the source connection ID from that packet.
+ quiche::QuicheOptional<QuicConnectionId> retry_source_connection_id_;
// Indicates whether received RETRY packets should be dropped.
bool drop_incoming_retry_packets_;
diff --git a/quic/core/quic_connection_test.cc b/quic/core/quic_connection_test.cc
index ff29c26..582bb54 100644
--- a/quic/core/quic_connection_test.cc
+++ b/quic/core/quic_connection_test.cc
@@ -1774,8 +1774,10 @@
}
void TestClientRetryHandling(bool invalid_retry_tag,
- bool missing_id_in_config,
- bool wrong_id_in_config);
+ bool missing_original_id_in_config,
+ bool wrong_original_id_in_config,
+ bool missing_retry_id_in_config,
+ bool wrong_retry_id_in_config);
QuicConnectionId connection_id_;
QuicFramer framer_;
@@ -4309,6 +4311,12 @@
options.push_back(kTLPR);
config.SetConnectionOptionsToSend(options);
QuicConfigPeer::SetNegotiated(&config, true);
+ if (connection_.version().AuthenticatesHandshakeConnectionIds()) {
+ QuicConfigPeer::SetReceivedOriginalConnectionId(
+ &config, connection_.connection_id());
+ QuicConfigPeer::SetReceivedInitialSourceConnectionId(
+ &config, connection_.connection_id());
+ }
connection_.SetFromConfig(config);
connection_.SetMaxTailLossProbes(1);
@@ -5791,6 +5799,12 @@
config.ProcessPeerHello(msg, CLIENT, &error_details);
EXPECT_THAT(error, IsQuicNoError());
+ if (connection_.version().AuthenticatesHandshakeConnectionIds()) {
+ QuicConfigPeer::SetReceivedOriginalConnectionId(
+ &config, connection_.connection_id());
+ QuicConfigPeer::SetReceivedInitialSourceConnectionId(
+ &config, connection_.connection_id());
+ }
connection_.SetFromConfig(config);
const QuicTime::Delta default_idle_timeout =
@@ -5937,6 +5951,12 @@
config.ProcessPeerHello(msg, CLIENT, &error_details);
EXPECT_THAT(error, IsQuicNoError());
+ if (connection_.version().AuthenticatesHandshakeConnectionIds()) {
+ QuicConfigPeer::SetReceivedOriginalConnectionId(
+ &config, connection_.connection_id());
+ QuicConfigPeer::SetReceivedInitialSourceConnectionId(
+ &config, connection_.connection_id());
+ }
connection_.SetFromConfig(config);
const QuicTime::Delta default_idle_timeout =
@@ -6101,6 +6121,12 @@
connection_options.push_back(k5RTO);
config.SetConnectionOptionsToSend(connection_options);
QuicConfigPeer::SetNegotiated(&config, true);
+ if (connection_.version().AuthenticatesHandshakeConnectionIds()) {
+ QuicConfigPeer::SetReceivedOriginalConnectionId(
+ &config, connection_.connection_id());
+ QuicConfigPeer::SetReceivedInitialSourceConnectionId(
+ &config, connection_.connection_id());
+ }
connection_.SetFromConfig(config);
// Send stream data.
@@ -9901,6 +9927,12 @@
connection_options.push_back(k6PTO);
config.SetConnectionOptionsToSend(connection_options);
QuicConfigPeer::SetNegotiated(&config, true);
+ if (connection_.version().AuthenticatesHandshakeConnectionIds()) {
+ QuicConfigPeer::SetReceivedOriginalConnectionId(
+ &config, connection_.connection_id());
+ QuicConfigPeer::SetReceivedInitialSourceConnectionId(
+ &config, connection_.connection_id());
+ }
EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _));
connection_.SetFromConfig(config);
EXPECT_FALSE(connection_.GetRetransmissionAlarm()->IsSet());
@@ -9942,6 +9974,12 @@
connection_options.push_back(k7PTO);
config.SetConnectionOptionsToSend(connection_options);
QuicConfigPeer::SetNegotiated(&config, true);
+ if (connection_.version().AuthenticatesHandshakeConnectionIds()) {
+ QuicConfigPeer::SetReceivedOriginalConnectionId(
+ &config, connection_.connection_id());
+ QuicConfigPeer::SetReceivedInitialSourceConnectionId(
+ &config, connection_.connection_id());
+ }
EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _));
connection_.SetFromConfig(config);
EXPECT_FALSE(connection_.GetRetransmissionAlarm()->IsSet());
@@ -9981,6 +10019,12 @@
connection_options.push_back(k2PTO);
connection_options.push_back(k8PTO);
QuicConfigPeer::SetNegotiated(&config, true);
+ if (connection_.version().AuthenticatesHandshakeConnectionIds()) {
+ QuicConfigPeer::SetReceivedOriginalConnectionId(
+ &config, connection_.connection_id());
+ QuicConfigPeer::SetReceivedInitialSourceConnectionId(
+ &config, connection_.connection_id());
+ }
config.SetConnectionOptionsToSend(connection_options);
EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _));
connection_.SetFromConfig(config);
@@ -10385,14 +10429,20 @@
EXPECT_EQ(0x01010101u, writer_->final_bytes_of_last_packet());
}
-void QuicConnectionTest::TestClientRetryHandling(bool invalid_retry_tag,
- bool missing_id_in_config,
- bool wrong_id_in_config) {
+void QuicConnectionTest::TestClientRetryHandling(
+ bool invalid_retry_tag,
+ bool missing_original_id_in_config,
+ bool wrong_original_id_in_config,
+ bool missing_retry_id_in_config,
+ bool wrong_retry_id_in_config) {
if (invalid_retry_tag) {
- ASSERT_FALSE(missing_id_in_config);
- ASSERT_FALSE(wrong_id_in_config);
+ ASSERT_FALSE(missing_original_id_in_config);
+ ASSERT_FALSE(wrong_original_id_in_config);
+ ASSERT_FALSE(missing_retry_id_in_config);
+ ASSERT_FALSE(wrong_retry_id_in_config);
} else {
- ASSERT_FALSE(missing_id_in_config && wrong_id_in_config);
+ ASSERT_FALSE(missing_original_id_in_config && wrong_original_id_in_config);
+ ASSERT_FALSE(missing_retry_id_in_config && wrong_retry_id_in_config);
}
if (!version().HasRetryIntegrityTag()) {
return;
@@ -10454,11 +10504,17 @@
}
QuicConnectionId config_original_connection_id = original_connection_id;
- if (wrong_id_in_config) {
+ if (wrong_original_id_in_config) {
// Flip the first bit of the connection ID.
ASSERT_FALSE(config_original_connection_id.IsEmpty());
config_original_connection_id.mutable_data()[0] ^= 0x80;
}
+ QuicConnectionId config_retry_source_connection_id = new_connection_id;
+ if (wrong_retry_id_in_config) {
+ // Flip the first bit of the connection ID.
+ ASSERT_FALSE(config_retry_source_connection_id.IsEmpty());
+ config_retry_source_connection_id.mutable_data()[0] ^= 0x80;
+ }
// Make sure the connection uses the connection ID from the test vectors,
QuicConnectionPeer::SetServerConnectionId(&connection_,
@@ -10491,11 +10547,21 @@
// Test validating the original_connection_id from the config.
QuicConfig received_config;
QuicConfigPeer::SetNegotiated(&received_config, true);
- if (!missing_id_in_config) {
+ if (connection_.version().AuthenticatesHandshakeConnectionIds()) {
+ QuicConfigPeer::SetReceivedInitialSourceConnectionId(
+ &received_config, connection_.connection_id());
+ if (!missing_retry_id_in_config) {
+ QuicConfigPeer::SetReceivedRetrySourceConnectionId(
+ &received_config, config_retry_source_connection_id);
+ }
+ }
+ if (!missing_original_id_in_config) {
QuicConfigPeer::SetReceivedOriginalConnectionId(
&received_config, config_original_connection_id);
}
- if (missing_id_in_config || wrong_id_in_config) {
+
+ if (missing_original_id_in_config || wrong_original_id_in_config ||
+ missing_retry_id_in_config || wrong_retry_id_in_config) {
EXPECT_CALL(visitor_,
OnConnectionClosed(_, ConnectionCloseSource::FROM_SELF))
.Times(1);
@@ -10506,8 +10572,9 @@
}
EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _)).Times(AnyNumber());
connection_.SetFromConfig(received_config);
- if (missing_id_in_config || wrong_id_in_config) {
- EXPECT_FALSE(connection_.connected());
+ if (missing_original_id_in_config || wrong_original_id_in_config ||
+ missing_retry_id_in_config || wrong_retry_id_in_config) {
+ ASSERT_FALSE(connection_.connected());
TestConnectionCloseQuicErrorCode(IETF_QUIC_PROTOCOL_VIOLATION);
} else {
EXPECT_TRUE(connection_.connected());
@@ -10516,31 +10583,74 @@
TEST_P(QuicConnectionTest, ClientParsesRetry) {
TestClientRetryHandling(/*invalid_retry_tag=*/false,
- /*missing_id_in_config=*/false,
- /*wrong_id_in_config=*/false);
+ /*missing_original_id_in_config=*/false,
+ /*wrong_original_id_in_config=*/false,
+ /*missing_retry_id_in_config=*/false,
+ /*wrong_retry_id_in_config=*/false);
}
-TEST_P(QuicConnectionTest, ClientParsesInvalidRetry) {
+TEST_P(QuicConnectionTest, ClientParsesRetryInvalidTag) {
TestClientRetryHandling(/*invalid_retry_tag=*/true,
- /*missing_id_in_config=*/false,
- /*wrong_id_in_config=*/false);
+ /*missing_original_id_in_config=*/false,
+ /*wrong_original_id_in_config=*/false,
+ /*missing_retry_id_in_config=*/false,
+ /*wrong_retry_id_in_config=*/false);
}
-TEST_P(QuicConnectionTest, ClientParsesRetryMissingId) {
+TEST_P(QuicConnectionTest, ClientParsesRetryMissingOriginalId) {
TestClientRetryHandling(/*invalid_retry_tag=*/false,
- /*missing_id_in_config=*/true,
- /*wrong_id_in_config=*/false);
+ /*missing_original_id_in_config=*/true,
+ /*wrong_original_id_in_config=*/false,
+ /*missing_retry_id_in_config=*/false,
+ /*wrong_retry_id_in_config=*/false);
}
-TEST_P(QuicConnectionTest, ClientParsesRetryWrongId) {
+TEST_P(QuicConnectionTest, ClientParsesRetryWrongOriginalId) {
TestClientRetryHandling(/*invalid_retry_tag=*/false,
- /*missing_id_in_config=*/false,
- /*wrong_id_in_config=*/true);
+ /*missing_original_id_in_config=*/false,
+ /*wrong_original_id_in_config=*/true,
+ /*missing_retry_id_in_config=*/false,
+ /*wrong_retry_id_in_config=*/false);
+}
+
+TEST_P(QuicConnectionTest, ClientParsesRetryMissingRetryId) {
+ if (!connection_.version().AuthenticatesHandshakeConnectionIds()) {
+ // Versions that do not authenticate connection IDs never send the
+ // retry_source_connection_id transport parameter.
+ return;
+ }
+ TestClientRetryHandling(/*invalid_retry_tag=*/false,
+ /*missing_original_id_in_config=*/false,
+ /*wrong_original_id_in_config=*/false,
+ /*missing_retry_id_in_config=*/true,
+ /*wrong_retry_id_in_config=*/false);
+}
+
+TEST_P(QuicConnectionTest, ClientParsesRetryWrongRetryId) {
+ if (!connection_.version().AuthenticatesHandshakeConnectionIds()) {
+ // Versions that do not authenticate connection IDs never send the
+ // retry_source_connection_id transport parameter.
+ return;
+ }
+ TestClientRetryHandling(/*invalid_retry_tag=*/false,
+ /*missing_original_id_in_config=*/false,
+ /*wrong_original_id_in_config=*/false,
+ /*missing_retry_id_in_config=*/false,
+ /*wrong_retry_id_in_config=*/true);
}
TEST_P(QuicConnectionTest, ClientReceivesOriginalConnectionIdWithoutRetry) {
- // Make sure that receiving the original_connection_id transport parameter
- // fails the handshake when no RETRY packet was received before it.
+ if (!connection_.version().UsesTls()) {
+ // QUIC+TLS is required to transmit connection ID transport parameters.
+ return;
+ }
+ if (connection_.version().AuthenticatesHandshakeConnectionIds()) {
+ // Versions that authenticate connection IDs always send the
+ // original_destination_connection_id transport parameter.
+ return;
+ }
+ // Make sure that receiving the original_destination_connection_id transport
+ // parameter fails the handshake when no RETRY packet was received before it.
QuicConfig received_config;
QuicConfigPeer::SetNegotiated(&received_config, true);
QuicConfigPeer::SetReceivedOriginalConnectionId(&received_config,
@@ -10553,6 +10663,26 @@
TestConnectionCloseQuicErrorCode(IETF_QUIC_PROTOCOL_VIOLATION);
}
+TEST_P(QuicConnectionTest, ClientReceivesRetrySourceConnectionIdWithoutRetry) {
+ if (!connection_.version().AuthenticatesHandshakeConnectionIds()) {
+ // Versions that do not authenticate connection IDs never send the
+ // retry_source_connection_id transport parameter.
+ return;
+ }
+ // Make sure that receiving the retry_source_connection_id transport parameter
+ // fails the handshake when no RETRY packet was received before it.
+ QuicConfig received_config;
+ QuicConfigPeer::SetNegotiated(&received_config, true);
+ QuicConfigPeer::SetReceivedRetrySourceConnectionId(&received_config,
+ TestConnectionId(0x12345));
+ EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _)).Times(AnyNumber());
+ EXPECT_CALL(visitor_, OnConnectionClosed(_, ConnectionCloseSource::FROM_SELF))
+ .Times(1);
+ connection_.SetFromConfig(received_config);
+ EXPECT_FALSE(connection_.connected());
+ TestConnectionCloseQuicErrorCode(IETF_QUIC_PROTOCOL_VIOLATION);
+}
+
// Regression test for http://crbug/1047977
TEST_P(QuicConnectionTest, MaxStreamsFrameCausesConnectionClose) {
if (!VersionHasIetfQuicFrames(connection_.transport_version())) {
diff --git a/quic/core/quic_session.cc b/quic/core/quic_session.cc
index 76869a3..a1f20c6 100644
--- a/quic/core/quic_session.cc
+++ b/quic/core/quic_session.cc
@@ -1623,6 +1623,16 @@
}
bool QuicSession::FillTransportParameters(TransportParameters* params) {
+ if (version().AuthenticatesHandshakeConnectionIds()) {
+ if (perspective() == Perspective::IS_SERVER) {
+ config_.SetOriginalConnectionIdToSend(
+ connection_->GetOriginalDestinationConnectionId());
+ config_.SetInitialSourceConnectionIdToSend(connection_->connection_id());
+ } else {
+ config_.SetInitialSourceConnectionIdToSend(
+ connection_->client_connection_id());
+ }
+ }
return config_.FillTransportParameters(params);
}
diff --git a/quic/core/quic_session_test.cc b/quic/core/quic_session_test.cc
index ddebac2..d57180b 100644
--- a/quic/core/quic_session_test.cc
+++ b/quic/core/quic_session_test.cc
@@ -77,6 +77,17 @@
kInitialStreamFlowControlWindowForTest);
session()->config()->SetInitialSessionFlowControlWindowToSend(
kInitialSessionFlowControlWindowForTest);
+ if (session()->version().AuthenticatesHandshakeConnectionIds()) {
+ if (session()->perspective() == Perspective::IS_CLIENT) {
+ session()->config()->SetOriginalConnectionIdToSend(
+ session()->connection()->connection_id());
+ session()->config()->SetInitialSourceConnectionIdToSend(
+ session()->connection()->connection_id());
+ } else {
+ session()->config()->SetInitialSourceConnectionIdToSend(
+ session()->connection()->client_connection_id());
+ }
+ }
if (session()->connection()->version().handshake_protocol ==
PROTOCOL_TLS1_3) {
TransportParameters transport_parameters;
diff --git a/quic/test_tools/simulator/queue.cc b/quic/test_tools/simulator/queue.cc
index 3816fd4..52f7fe6 100644
--- a/quic/test_tools/simulator/queue.cc
+++ b/quic/test_tools/simulator/queue.cc
@@ -20,6 +20,7 @@
aggregation_timeout_(QuicTime::Delta::Infinite()),
current_bundle_(0),
current_bundle_bytes_(0),
+ tx_port_(nullptr),
listener_(nullptr) {
aggregation_timeout_alarm_.reset(simulator_->GetAlarmFactory()->CreateAlarm(
new AggregationAlarmDelegate(this)));
@@ -116,7 +117,12 @@
return;
}
- Schedule(clock_->Now() + tx_port_->TimeUntilAvailable());
+ QuicTime::Delta time_until_available = QuicTime::Delta::Zero();
+ if (tx_port_) {
+ time_until_available = tx_port_->TimeUntilAvailable();
+ }
+
+ Schedule(clock_->Now() + time_until_available);
}
} // namespace simulator
diff --git a/quic/test_tools/simulator/quic_endpoint.cc b/quic/test_tools/simulator/quic_endpoint.cc
index 7061898..aba7b46 100644
--- a/quic/test_tools/simulator/quic_endpoint.cc
+++ b/quic/test_tools/simulator/quic_endpoint.cc
@@ -11,6 +11,7 @@
#include "net/third_party/quiche/src/quic/core/crypto/crypto_protocol.h"
#include "net/third_party/quiche/src/quic/core/quic_data_writer.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_test_output.h"
+#include "net/third_party/quiche/src/quic/test_tools/quic_config_peer.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_connection_peer.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h"
#include "net/third_party/quiche/src/quic/test_tools/simulator/simulator.h"
@@ -75,6 +76,17 @@
peer_hello, perspective == Perspective::IS_CLIENT ? SERVER : CLIENT,
&error);
DCHECK_EQ(error_code, QUIC_NO_ERROR) << "Configuration failed: " << error;
+ if (connection_->version().AuthenticatesHandshakeConnectionIds()) {
+ if (connection_->perspective() == Perspective::IS_CLIENT) {
+ test::QuicConfigPeer::SetReceivedOriginalConnectionId(
+ &config, connection_->connection_id());
+ test::QuicConfigPeer::SetReceivedInitialSourceConnectionId(
+ &config, connection_->connection_id());
+ } else {
+ test::QuicConfigPeer::SetReceivedInitialSourceConnectionId(
+ &config, connection_->client_connection_id());
+ }
+ }
connection_->SetFromConfig(config);
}