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