Add methods that reads/writes connection ID in preferred_address transport parameter . PiperOrigin-RevId: 351576008 Change-Id: I6ce671ba7b90b338655713c92f811ac2338379e8
diff --git a/quic/core/quic_config.cc b/quic/core/quic_config.cc index 63c6f77..725b513 100644 --- a/quic/core/quic_config.cc +++ b/quic/core/quic_config.cc
@@ -17,6 +17,7 @@ #include "quic/core/quic_connection_id.h" #include "quic/core/quic_constants.h" #include "quic/core/quic_socket_address_coder.h" +#include "quic/core/quic_types.h" #include "quic/core/quic_utils.h" #include "quic/platform/api/quic_bug_tracker.h" #include "quic/platform/api/quic_flag_utils.h" @@ -877,6 +878,20 @@ alternate_server_address_ipv6_.SetSendValue(alternate_server_address_ipv6); } +void QuicConfig::SetIPv6AlternateServerAddressToSend( + const QuicSocketAddress& alternate_server_address_ipv6, + const QuicConnectionId& connection_id, + QuicUint128 stateless_reset_token) { + if (!alternate_server_address_ipv6.host().IsIPv6()) { + QUIC_BUG << "Cannot use SetIPv6AlternateServerAddressToSend with " + << alternate_server_address_ipv6; + return; + } + alternate_server_address_ipv6_.SetSendValue(alternate_server_address_ipv6); + preferred_address_connection_id_and_token_ = + std::make_pair(connection_id, stateless_reset_token); +} + bool QuicConfig::HasReceivedIPv6AlternateServerAddress() const { return alternate_server_address_ipv6_.HasReceivedValue(); } @@ -896,6 +911,20 @@ alternate_server_address_ipv4_.SetSendValue(alternate_server_address_ipv4); } +void QuicConfig::SetIPv4AlternateServerAddressToSend( + const QuicSocketAddress& alternate_server_address_ipv4, + const QuicConnectionId& connection_id, + QuicUint128 stateless_reset_token) { + if (!alternate_server_address_ipv4.host().IsIPv4()) { + QUIC_BUG << "Cannot use SetIPv4AlternateServerAddressToSend with " + << alternate_server_address_ipv4; + return; + } + alternate_server_address_ipv4_.SetSendValue(alternate_server_address_ipv4); + preferred_address_connection_id_and_token_ = + std::make_pair(connection_id, stateless_reset_token); +} + bool QuicConfig::HasReceivedIPv4AlternateServerAddress() const { return alternate_server_address_ipv4_.HasReceivedValue(); } @@ -905,6 +934,18 @@ return alternate_server_address_ipv4_.GetReceivedValue(); } +bool QuicConfig::HasReceivedPreferredAddressConnectionIdAndToken() const { + return (HasReceivedIPv6AlternateServerAddress() || + HasReceivedIPv4AlternateServerAddress()) && + preferred_address_connection_id_and_token_.has_value(); +} + +const std::pair<QuicConnectionId, QuicUint128>& +QuicConfig::ReceivedPreferredAddressConnectionIdAndToken() const { + DCHECK(HasReceivedPreferredAddressConnectionIdAndToken()); + return *preferred_address_connection_id_and_token_; +} + void QuicConfig::SetOriginalConnectionIdToSend( const QuicConnectionId& original_destination_connection_id) { original_destination_connection_id_to_send_ = @@ -1202,6 +1243,15 @@ preferred_address.ipv4_socket_address = alternate_server_address_ipv4_.GetSendValue(); } + if (preferred_address_connection_id_and_token_) { + preferred_address.connection_id = + preferred_address_connection_id_and_token_->first; + auto* begin = reinterpret_cast<const char*>( + &preferred_address_connection_id_and_token_->second); + auto* end = + begin + sizeof(preferred_address_connection_id_and_token_->second); + preferred_address.stateless_reset_token.assign(begin, end); + } params->preferred_address = std::make_unique<TransportParameters::PreferredAddress>( preferred_address); @@ -1320,6 +1370,15 @@ alternate_server_address_ipv4_.SetReceivedValue( params.preferred_address->ipv4_socket_address); } + // TODO(haoyuewang) Treat 0 length connection ID sent in preferred_address + // as a connection error of type TRANSPORT_PARAMETER_ERROR when server + // fully supports it. + if (!params.preferred_address->connection_id.IsEmpty()) { + preferred_address_connection_id_and_token_ = std::make_pair( + params.preferred_address->connection_id, + *reinterpret_cast<const QuicUint128*>( + ¶ms.preferred_address->stateless_reset_token.front())); + } } if (params.min_ack_delay_us.value() != 0) { if (params.min_ack_delay_us.value() >
diff --git a/quic/core/quic_config.h b/quic/core/quic_config.h index 6778e80..d0fa2c7 100644 --- a/quic/core/quic_config.h +++ b/quic/core/quic_config.h
@@ -391,15 +391,28 @@ // IPv6 alternate server address. void SetIPv6AlternateServerAddressToSend( const QuicSocketAddress& alternate_server_address_ipv6); + void SetIPv6AlternateServerAddressToSend( + const QuicSocketAddress& alternate_server_address_ipv6, + const QuicConnectionId& connection_id, + QuicUint128 stateless_reset_token); bool HasReceivedIPv6AlternateServerAddress() const; const QuicSocketAddress& ReceivedIPv6AlternateServerAddress() const; // IPv4 alternate server address. void SetIPv4AlternateServerAddressToSend( const QuicSocketAddress& alternate_server_address_ipv4); + void SetIPv4AlternateServerAddressToSend( + const QuicSocketAddress& alternate_server_address_ipv4, + const QuicConnectionId& connection_id, + QuicUint128 stateless_reset_token); bool HasReceivedIPv4AlternateServerAddress() const; const QuicSocketAddress& ReceivedIPv4AlternateServerAddress() const; + // Preferred Address Connection ID and Token. + bool HasReceivedPreferredAddressConnectionIdAndToken() const; + const std::pair<QuicConnectionId, QuicUint128>& + ReceivedPreferredAddressConnectionIdAndToken() const; + // Original destination connection ID. void SetOriginalConnectionIdToSend( const QuicConnectionId& original_destination_connection_id); @@ -589,6 +602,10 @@ // Note that when QUIC_CRYPTO is in use, only one of the addresses is sent. QuicFixedSocketAddress alternate_server_address_ipv6_; QuicFixedSocketAddress alternate_server_address_ipv4_; + // Connection Id data to send from the server or receive at the client as part + // of the preferred address transport parameter. + absl::optional<std::pair<QuicConnectionId, QuicUint128>> + preferred_address_connection_id_and_token_; // Stateless reset token used in IETF public reset packet. // Uses the stateless_reset_token transport parameter in IETF QUIC.
diff --git a/quic/core/quic_config_test.cc b/quic/core/quic_config_test.cc index e38975c..2f37835 100644 --- a/quic/core/quic_config_test.cc +++ b/quic/core/quic_config_test.cc
@@ -4,10 +4,12 @@ #include "quic/core/quic_config.h" +#include <memory> #include <string> #include "quic/core/crypto/crypto_handshake_message.h" #include "quic/core/crypto/crypto_protocol.h" +#include "quic/core/crypto/transport_parameters.h" #include "quic/core/quic_constants.h" #include "quic/core/quic_packets.h" #include "quic/core/quic_time.h" @@ -475,6 +477,15 @@ config_.SetRetrySourceConnectionIdToSend(TestConnectionId(0x3333)); config_.SetMinAckDelayMs(kDefaultMinAckDelayTimeMs); + QuicIpAddress host; + host.FromString("127.0.3.1"); + QuicSocketAddress kTestServerAddress = QuicSocketAddress(host, 1234); + QuicConnectionId new_connection_id = TestConnectionId(5); + QuicUint128 new_stateless_reset_token = + QuicUtils::GenerateStatelessResetToken(new_connection_id); + config_.SetIPv4AlternateServerAddressToSend( + kTestServerAddress, new_connection_id, new_stateless_reset_token); + TransportParameters params; config_.FillTransportParameters(¶ms); @@ -508,6 +519,12 @@ static_cast<uint64_t>(kDefaultMinAckDelayTimeMs) * kNumMicrosPerMilli, params.min_ack_delay_us.value()); EXPECT_TRUE(params.key_update_not_yet_supported); + + EXPECT_EQ(params.preferred_address->ipv4_socket_address, kTestServerAddress); + EXPECT_EQ(params.preferred_address->connection_id, new_connection_id); + EXPECT_EQ(*reinterpret_cast<QuicUint128*>( + ¶ms.preferred_address->stateless_reset_token.front()), + new_stateless_reset_token); } TEST_P(QuicConfigTest, ProcessTransportParametersServer) { @@ -745,6 +762,47 @@ EXPECT_TRUE(config_.KeyUpdateSupportedRemotely()); } +TEST_P(QuicConfigTest, SendPreferredIPv4Address) { + if (!version_.UsesTls()) { + // TransportParameters are only used for QUIC+TLS. + return; + } + + EXPECT_FALSE(config_.HasReceivedPreferredAddressConnectionIdAndToken()); + + TransportParameters params; + QuicIpAddress host; + host.FromString("::ffff:192.0.2.128"); + QuicSocketAddress kTestServerAddress = QuicSocketAddress(host, 1234); + QuicConnectionId new_connection_id = TestConnectionId(5); + QuicUint128 new_stateless_reset_token = + QuicUtils::GenerateStatelessResetToken(new_connection_id); + auto preferred_address = + std::make_unique<TransportParameters::PreferredAddress>(); + preferred_address->ipv6_socket_address = kTestServerAddress; + preferred_address->connection_id = new_connection_id; + preferred_address->stateless_reset_token.assign( + reinterpret_cast<const char*>(&new_stateless_reset_token), + reinterpret_cast<const char*>(&new_stateless_reset_token) + + sizeof(new_stateless_reset_token)); + params.preferred_address = std::move(preferred_address); + + std::string error_details; + EXPECT_THAT(config_.ProcessTransportParameters( + params, /* is_resumption = */ false, &error_details), + IsQuicNoError()); + + EXPECT_TRUE(config_.HasReceivedIPv6AlternateServerAddress()); + EXPECT_EQ(config_.ReceivedIPv6AlternateServerAddress(), kTestServerAddress); + EXPECT_TRUE(config_.HasReceivedPreferredAddressConnectionIdAndToken()); + const std::pair<QuicConnectionId, QuicUint128>& + preferred_address_connection_id_and_token = + config_.ReceivedPreferredAddressConnectionIdAndToken(); + EXPECT_EQ(preferred_address_connection_id_and_token.first, new_connection_id); + EXPECT_EQ(preferred_address_connection_id_and_token.second, + new_stateless_reset_token); +} + } // namespace } // namespace test } // namespace quic