Replace legacy Google-specific parameter with individual parameters
Now that we've removed the majority of Google-specific parameters, we can now move the remaining 3 to their own transport parameter. This'll remove the dependency from QUIC+TLS on QUIC_CRYPTO handshake message code, and simplify debugging.
Tweak quic+tls transport parameters, protected by gfe2_restart_flag_quic_google_transport_param_send_new and gfe2_restart_flag_quic_google_transport_param_omit_old
PiperOrigin-RevId: 311438446
Change-Id: I95a61b9acf6523d845600fe70c2f752d5e30f28a
diff --git a/quic/core/crypto/transport_parameters.cc b/quic/core/crypto/transport_parameters.cc
index 4e761b3..3e286ad 100644
--- a/quic/core/crypto/transport_parameters.cc
+++ b/quic/core/crypto/transport_parameters.cc
@@ -49,6 +49,9 @@
kMaxDatagramFrameSize = 0x20,
+ kInitialRoundTripTime = 0x3127,
+ kGoogleConnectionOptions = 0x3128,
+ kGoogleUserAgentId = 0x3129,
kGoogleQuicParam = 18257, // Used for non-standard Google-specific params.
kGoogleQuicVersion =
18258, // Used to transmit version and supported_versions.
@@ -103,6 +106,12 @@
return "active_connection_id_limit";
case TransportParameters::kMaxDatagramFrameSize:
return "max_datagram_frame_size";
+ case TransportParameters::kInitialRoundTripTime:
+ return "initial_round_trip_time";
+ case TransportParameters::kGoogleConnectionOptions:
+ return "google_connection_options";
+ case TransportParameters::kGoogleUserAgentId:
+ return "user_agent_id";
case TransportParameters::kGoogleQuicParam:
return "google";
case TransportParameters::kGoogleQuicVersion:
@@ -130,6 +139,9 @@
case TransportParameters::kPreferredAddress:
case TransportParameters::kActiveConnectionIdLimit:
case TransportParameters::kMaxDatagramFrameSize:
+ case TransportParameters::kInitialRoundTripTime:
+ case TransportParameters::kGoogleConnectionOptions:
+ case TransportParameters::kGoogleUserAgentId:
case TransportParameters::kGoogleQuicParam:
case TransportParameters::kGoogleQuicVersion:
return true;
@@ -418,14 +430,31 @@
}
rv += active_connection_id_limit.ToString(/*for_use_in_list=*/true);
rv += max_datagram_frame_size.ToString(/*for_use_in_list=*/true);
+ rv += initial_round_trip_time_us.ToString(/*for_use_in_list=*/true);
+ if (google_connection_options.has_value()) {
+ rv += " " + TransportParameterIdToString(kGoogleConnectionOptions) + " ";
+ bool first = true;
+ for (const QuicTag& connection_option : google_connection_options.value()) {
+ if (first) {
+ first = false;
+ } else {
+ rv += ",";
+ }
+ rv += QuicTagToString(connection_option);
+ }
+ }
+ if (user_agent_id.has_value()) {
+ rv += " " + TransportParameterIdToString(kGoogleUserAgentId) + " \"" +
+ user_agent_id.value() + "\"";
+ }
if (google_quic_params) {
rv += " " + TransportParameterIdToString(kGoogleQuicParam);
}
- rv += "]";
for (const auto& kv : custom_parameters) {
rv += " 0x" + quiche::QuicheTextUtils::Hex(static_cast<uint32_t>(kv.first));
rv += "=" + quiche::QuicheTextUtils::HexEncode(kv.second);
}
+ rv += "]";
return rv;
}
@@ -455,7 +484,8 @@
kDefaultActiveConnectionIdLimitTransportParam,
kMinActiveConnectionIdLimitTransportParam,
kVarInt62MaxValue),
- max_datagram_frame_size(kMaxDatagramFrameSize)
+ max_datagram_frame_size(kMaxDatagramFrameSize),
+ initial_round_trip_time_us(kInitialRoundTripTime)
// Important note: any new transport parameters must be added
// to TransportParameters::AreValid, SerializeTransportParameters and
// ParseTransportParameters, TransportParameters's custom copy constructor, the
@@ -483,6 +513,9 @@
disable_migration(other.disable_migration),
active_connection_id_limit(other.active_connection_id_limit),
max_datagram_frame_size(other.max_datagram_frame_size),
+ initial_round_trip_time_us(other.initial_round_trip_time_us),
+ google_connection_options(other.google_connection_options),
+ user_agent_id(other.user_agent_id),
custom_parameters(other.custom_parameters) {
if (other.preferred_address) {
preferred_address = std::make_unique<TransportParameters::PreferredAddress>(
@@ -520,6 +553,10 @@
rhs.active_connection_id_limit.value() &&
max_datagram_frame_size.value() ==
rhs.max_datagram_frame_size.value() &&
+ initial_round_trip_time_us.value() ==
+ rhs.initial_round_trip_time_us.value() &&
+ google_connection_options == rhs.google_connection_options &&
+ user_agent_id == rhs.user_agent_id &&
custom_parameters == rhs.custom_parameters)) {
return false;
}
@@ -590,6 +627,15 @@
return false;
}
}
+ if (perspective == Perspective::IS_SERVER &&
+ initial_round_trip_time_us.value() > 0) {
+ *error_details = "Server cannot send initial round trip time";
+ return false;
+ }
+ if (perspective == Perspective::IS_SERVER && user_agent_id.has_value()) {
+ *error_details = "Server cannot send user agent ID";
+ return false;
+ }
const bool ok =
idle_timeout_milliseconds.IsValid() && max_packet_size.IsValid() &&
initial_max_data.IsValid() &&
@@ -598,7 +644,8 @@
initial_max_stream_data_uni.IsValid() &&
initial_max_streams_bidi.IsValid() && initial_max_streams_uni.IsValid() &&
ack_delay_exponent.IsValid() && max_ack_delay.IsValid() &&
- active_connection_id_limit.IsValid() && max_datagram_frame_size.IsValid();
+ active_connection_id_limit.IsValid() &&
+ max_datagram_frame_size.IsValid() && initial_round_trip_time_us.IsValid();
if (!ok) {
*error_details = "Invalid transport parameters " + this->ToString();
}
@@ -691,7 +738,8 @@
!in.ack_delay_exponent.Write(&writer, version) ||
!in.max_ack_delay.Write(&writer, version) ||
!in.active_connection_id_limit.Write(&writer, version) ||
- !in.max_datagram_frame_size.Write(&writer, version)) {
+ !in.max_datagram_frame_size.Write(&writer, version) ||
+ !in.initial_round_trip_time_us.Write(&writer, version)) {
QUIC_BUG << "Failed to write integers for " << in;
return false;
}
@@ -743,6 +791,42 @@
}
}
+ // Google-specific connection options.
+ if (in.google_connection_options.has_value()) {
+ static_assert(sizeof(in.google_connection_options.value().front()) == 4,
+ "bad size");
+ uint64_t connection_options_length =
+ in.google_connection_options.value().size() * 4;
+ if (!WriteTransportParameterId(
+ &writer, TransportParameters::kGoogleConnectionOptions, version) ||
+ !WriteTransportParameterLength(&writer, connection_options_length,
+ version)) {
+ QUIC_BUG << "Failed to write google_connection_options of length "
+ << connection_options_length << " for " << in;
+ return false;
+ }
+ for (const QuicTag& connection_option :
+ in.google_connection_options.value()) {
+ if (!writer.WriteTag(connection_option)) {
+ QUIC_BUG << "Failed to write google_connection_option "
+ << QuicTagToString(connection_option) << " for " << in;
+ return false;
+ }
+ }
+ }
+
+ // Google-specific user agent identifier.
+ if (in.user_agent_id.has_value()) {
+ if (!WriteTransportParameterId(
+ &writer, TransportParameters::kGoogleUserAgentId, version) ||
+ !WriteTransportParameterStringPiece(&writer, in.user_agent_id.value(),
+ version)) {
+ QUIC_BUG << "Failed to write Google user agent ID \""
+ << in.user_agent_id.value() << "\" for " << in;
+ return false;
+ }
+ }
+
// Google-specific non-standard parameter.
if (in.google_quic_params) {
const QuicData& serialized_google_quic_params =
@@ -862,6 +946,7 @@
QUIC_DLOG(INFO) << "Serialized " << in << " as " << writer.length()
<< " bytes";
+
return true;
}
@@ -1033,6 +1118,32 @@
parse_success =
out->max_datagram_frame_size.Read(&value_reader, error_details);
break;
+ case TransportParameters::kInitialRoundTripTime:
+ parse_success =
+ out->initial_round_trip_time_us.Read(&value_reader, error_details);
+ break;
+ case TransportParameters::kGoogleConnectionOptions: {
+ if (out->google_connection_options.has_value()) {
+ *error_details = "Received a second Google connection options";
+ return false;
+ }
+ out->google_connection_options = QuicTagVector{};
+ while (!value_reader.IsDoneReading()) {
+ QuicTag connection_option;
+ if (!value_reader.ReadTag(&connection_option)) {
+ *error_details = "Failed to read a Google connection option";
+ return false;
+ }
+ out->google_connection_options.value().push_back(connection_option);
+ }
+ } break;
+ case TransportParameters::kGoogleUserAgentId:
+ if (out->user_agent_id.has_value()) {
+ *error_details = "Received a second user agent ID";
+ return false;
+ }
+ out->user_agent_id = std::string(value_reader.ReadRemainingPayload());
+ break;
case TransportParameters::kGoogleQuicParam: {
if (out->google_quic_params) {
*error_details = "Received a second Google parameter";
diff --git a/quic/core/crypto/transport_parameters.h b/quic/core/crypto/transport_parameters.h
index 9f9e616..9dec484 100644
--- a/quic/core/crypto/transport_parameters.h
+++ b/quic/core/crypto/transport_parameters.h
@@ -184,6 +184,16 @@
// the sender accepts. See draft-ietf-quic-datagram.
IntegerParameter max_datagram_frame_size;
+ // Google-specific transport parameter that carries an estimate of the
+ // initial round-trip time in microseconds.
+ IntegerParameter initial_round_trip_time_us;
+
+ // Google-specific connection options.
+ quiche::QuicheOptional<QuicTagVector> google_connection_options;
+
+ // Google-specific user agent identifier.
+ quiche::QuicheOptional<std::string> user_agent_id;
+
// Transport parameters used by Google QUIC but not IETF QUIC. This is
// serialized into a TransportParameter struct with a TransportParameterId of
// kGoogleQuicParamId.
diff --git a/quic/core/crypto/transport_parameters_test.cc b/quic/core/crypto/transport_parameters_test.cc
index c3d5d57..1fc1f5c 100644
--- a/quic/core/crypto/transport_parameters_test.cc
+++ b/quic/core/crypto/transport_parameters_test.cc
@@ -7,7 +7,9 @@
#include <cstring>
#include <utility>
+#include "net/third_party/quiche/src/quic/core/crypto/crypto_protocol.h"
#include "net/third_party/quiche/src/quic/core/quic_connection_id.h"
+#include "net/third_party/quiche/src/quic/core/quic_tag.h"
#include "net/third_party/quiche/src/quic/core/quic_types.h"
#include "net/third_party/quiche/src/quic/core/quic_versions.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_expect_bug.h"
@@ -38,6 +40,7 @@
const uint64_t kFakeMaxAckDelay = 51;
const bool kFakeDisableMigration = true;
const uint64_t kFakeActiveConnectionIdLimit = 52;
+const uint64_t kFakeInitialRoundTripTime = 53;
const uint8_t kFakePreferredStatelessResetTokenData[16] = {
0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F};
@@ -100,6 +103,15 @@
preferred_address);
}
+QuicTagVector CreateFakeGoogleConnectionOptions() {
+ return {kALPN, MakeQuicTag('E', 'F', 'G', 0x00),
+ MakeQuicTag('H', 'I', 'J', 0xff)};
+}
+
+std::string CreateFakeUserAgentId() {
+ return "FakeUAID";
+}
+
void RemoveGreaseParameters(TransportParameters* params) {
std::vector<TransportParameters::TransportParameterId> grease_params;
for (const auto& kv : params->custom_parameters) {
@@ -237,6 +249,9 @@
orig_params.preferred_address = CreateFakePreferredAddress();
orig_params.active_connection_id_limit.set_value(
kFakeActiveConnectionIdLimit);
+ orig_params.initial_round_trip_time_us.set_value(kFakeInitialRoundTripTime);
+ orig_params.google_connection_options = CreateFakeGoogleConnectionOptions();
+ orig_params.user_agent_id = CreateFakeUserAgentId();
orig_params.custom_parameters[kCustomParameter1] = kCustomParameter1Value;
orig_params.custom_parameters[kCustomParameter2] = kCustomParameter2Value;
@@ -264,6 +279,9 @@
orig_params.disable_migration = kFakeDisableMigration;
orig_params.active_connection_id_limit.set_value(
kFakeActiveConnectionIdLimit);
+ orig_params.initial_round_trip_time_us.set_value(kFakeInitialRoundTripTime);
+ orig_params.google_connection_options = CreateFakeGoogleConnectionOptions();
+ orig_params.user_agent_id = CreateFakeUserAgentId();
orig_params.custom_parameters[kCustomParameter1] = kCustomParameter1Value;
orig_params.custom_parameters[kCustomParameter2] = kCustomParameter2Value;
@@ -306,6 +324,7 @@
orig_params.preferred_address = CreateFakePreferredAddress();
orig_params.active_connection_id_limit.set_value(
kFakeActiveConnectionIdLimit);
+ orig_params.google_connection_options = CreateFakeGoogleConnectionOptions();
std::vector<uint8_t> serialized;
ASSERT_TRUE(SerializeTransportParameters(version_, orig_params, &serialized));
@@ -433,7 +452,7 @@
TEST_P(TransportParametersTest, ParseClientParams) {
// clang-format off
const uint8_t kClientParamsOld[] = {
- 0x00, 0x49, // length of the parameters array that follows
+ 0x00, 0x6a, // length of the parameters array that follows
// idle_timeout
0x00, 0x01, // parameter id
0x00, 0x02, // length
@@ -481,6 +500,20 @@
0x00, 0x0e, // parameter id
0x00, 0x01, // length
0x34, // value
+ // initial_round_trip_time_us
+ 0x31, 0x27, // parameter id
+ 0x00, 0x01, // length
+ 0x35, // value
+ // google_connection_options
+ 0x31, 0x28, // parameter id
+ 0x00, 0x0c, // length
+ 'A', 'L', 'P', 'N', // value
+ 'E', 'F', 'G', 0x00,
+ 'H', 'I', 'J', 0xff,
+ // user_agent_id
+ 0x31, 0x29, // parameter id
+ 0x00, 0x08, // length
+ 'F', 'a', 'k', 'e', 'U', 'A', 'I', 'D', // value
// Google version extension
0x47, 0x52, // parameter id
0x00, 0x04, // length
@@ -534,6 +567,20 @@
0x0e, // parameter id
0x01, // length
0x34, // value
+ // initial_round_trip_time_us
+ 0x71, 0x27, // parameter id
+ 0x01, // length
+ 0x35, // value
+ // google_connection_options
+ 0x71, 0x28, // parameter id
+ 0x0c, // length
+ 'A', 'L', 'P', 'N', // value
+ 'E', 'F', 'G', 0x00,
+ 'H', 'I', 'J', 0xff,
+ // user_agent_id
+ 0x71, 0x29, // parameter id
+ 0x08, // length
+ 'F', 'a', 'k', 'e', 'U', 'A', 'I', 'D', // value
// Google version extension
0x80, 0x00, 0x47, 0x52, // parameter id
0x04, // length
@@ -578,6 +625,13 @@
EXPECT_EQ(kFakeDisableMigration, new_params.disable_migration);
EXPECT_EQ(kFakeActiveConnectionIdLimit,
new_params.active_connection_id_limit.value());
+ EXPECT_EQ(kFakeInitialRoundTripTime,
+ new_params.initial_round_trip_time_us.value());
+ ASSERT_TRUE(new_params.google_connection_options.has_value());
+ EXPECT_EQ(CreateFakeGoogleConnectionOptions(),
+ new_params.google_connection_options.value());
+ ASSERT_TRUE(new_params.user_agent_id.has_value());
+ EXPECT_EQ(CreateFakeUserAgentId(), new_params.user_agent_id.value());
}
TEST_P(TransportParametersTest,
@@ -745,7 +799,7 @@
TEST_P(TransportParametersTest, ParseServerParams) {
// clang-format off
const uint8_t kServerParamsOld[] = {
- 0x00, 0xa7, // length of parameters array that follows
+ 0x00, 0xb7, // length of parameters array that follows
// original_connection_id
0x00, 0x00, // parameter id
0x00, 0x08, // length
@@ -814,6 +868,12 @@
0x00, 0x0e, // parameter id
0x00, 0x01, // length
0x34, // value
+ // google_connection_options
+ 0x31, 0x28, // parameter id
+ 0x00, 0x0c, // length
+ 'A', 'L', 'P', 'N', // value
+ 'E', 'F', 'G', 0x00,
+ 'H', 'I', 'J', 0xff,
// Google version extension
0x47, 0x52, // parameter id
0x00, 0x0d, // length
@@ -891,6 +951,12 @@
0x0e, // parameter id
0x01, // length
0x34, // value
+ // google_connection_options
+ 0x71, 0x28, // parameter id
+ 0x0c, // length
+ 'A', 'L', 'P', 'N', // value
+ 'E', 'F', 'G', 0x00,
+ 'H', 'I', 'J', 0xff,
// Google version extension
0x80, 0x00, 0x47, 0x52, // parameter id
0x0d, // length
@@ -951,6 +1017,10 @@
new_params.preferred_address->stateless_reset_token);
EXPECT_EQ(kFakeActiveConnectionIdLimit,
new_params.active_connection_id_limit.value());
+ ASSERT_TRUE(new_params.google_connection_options.has_value());
+ EXPECT_EQ(CreateFakeGoogleConnectionOptions(),
+ new_params.google_connection_options.value());
+ EXPECT_FALSE(new_params.user_agent_id.has_value());
}
TEST_P(TransportParametersTest, ParseServerParametersRepeated) {
diff --git a/quic/core/quic_config.cc b/quic/core/quic_config.cc
index 865aef8..7c781f4 100644
--- a/quic/core/quic_config.cc
+++ b/quic/core/quic_config.cc
@@ -686,7 +686,7 @@
return bytes_for_connection_id_.GetReceivedValue();
}
-void QuicConfig::SetInitialRoundTripTimeUsToSend(uint32_t rtt) {
+void QuicConfig::SetInitialRoundTripTimeUsToSend(uint64_t rtt) {
initial_round_trip_time_us_.SetSendValue(rtt);
}
@@ -694,7 +694,7 @@
return initial_round_trip_time_us_.HasReceivedValue();
}
-uint32_t QuicConfig::ReceivedInitialRoundTripTimeUs() const {
+uint64_t QuicConfig::ReceivedInitialRoundTripTimeUs() const {
return initial_round_trip_time_us_.GetReceivedValue();
}
@@ -702,7 +702,7 @@
return initial_round_trip_time_us_.HasSendValue();
}
-uint32_t QuicConfig::GetInitialRoundTripTimeUsToSend() const {
+uint64_t QuicConfig::GetInitialRoundTripTimeUsToSend() const {
return initial_round_trip_time_us_.GetSendValue();
}
@@ -1138,12 +1138,29 @@
active_connection_id_limit_.GetSendValue());
}
- if (!params->google_quic_params) {
- params->google_quic_params = std::make_unique<CryptoHandshakeMessage>();
+ if (GetQuicRestartFlag(quic_google_transport_param_send_new)) {
+ QUIC_RESTART_FLAG_COUNT_N(quic_google_transport_param_send_new, 1, 3);
+ if (initial_round_trip_time_us_.HasSendValue()) {
+ params->initial_round_trip_time_us.set_value(
+ initial_round_trip_time_us_.GetSendValue());
+ }
+ if (connection_options_.HasSendValues() &&
+ !connection_options_.GetSendValues().empty()) {
+ params->google_connection_options = connection_options_.GetSendValues();
+ }
}
- initial_round_trip_time_us_.ToHandshakeMessage(
- params->google_quic_params.get());
- connection_options_.ToHandshakeMessage(params->google_quic_params.get());
+
+ if (!GetQuicRestartFlag(quic_google_transport_param_omit_old)) {
+ if (!params->google_quic_params) {
+ params->google_quic_params = std::make_unique<CryptoHandshakeMessage>();
+ }
+ initial_round_trip_time_us_.ToHandshakeMessage(
+ params->google_quic_params.get());
+ connection_options_.ToHandshakeMessage(params->google_quic_params.get());
+ } else {
+ QUIC_RESTART_FLAG_COUNT_N(quic_google_transport_param_omit_old, 1, 3);
+ }
+
params->custom_parameters = custom_transport_parameters_to_send_;
return true;
@@ -1242,22 +1259,41 @@
active_connection_id_limit_.SetReceivedValue(
params.active_connection_id_limit.value());
- const CryptoHandshakeMessage* peer_params = params.google_quic_params.get();
- if (peer_params != nullptr) {
- QuicErrorCode error = initial_round_trip_time_us_.ProcessPeerHello(
- *peer_params, hello_type, error_details);
- if (error != QUIC_NO_ERROR) {
- DCHECK(!error_details->empty());
- return error;
+ bool google_params_already_parsed = false;
+ if (GetQuicRestartFlag(quic_google_transport_param_send_new)) {
+ QUIC_RESTART_FLAG_COUNT_N(quic_google_transport_param_send_new, 2, 3);
+ if (params.initial_round_trip_time_us.value() > 0) {
+ google_params_already_parsed = true;
+ initial_round_trip_time_us_.SetReceivedValue(
+ params.initial_round_trip_time_us.value());
}
- error = connection_options_.ProcessPeerHello(*peer_params, hello_type,
- error_details);
- if (error != QUIC_NO_ERROR) {
- DCHECK(!error_details->empty());
- return error;
+ if (params.google_connection_options.has_value()) {
+ google_params_already_parsed = true;
+ connection_options_.SetReceivedValues(
+ params.google_connection_options.value());
}
}
+ if (!GetQuicRestartFlag(quic_google_transport_param_omit_old)) {
+ const CryptoHandshakeMessage* peer_params = params.google_quic_params.get();
+ if (peer_params != nullptr && !google_params_already_parsed) {
+ QuicErrorCode error = initial_round_trip_time_us_.ProcessPeerHello(
+ *peer_params, hello_type, error_details);
+ if (error != QUIC_NO_ERROR) {
+ DCHECK(!error_details->empty());
+ return error;
+ }
+ error = connection_options_.ProcessPeerHello(*peer_params, hello_type,
+ error_details);
+ if (error != QUIC_NO_ERROR) {
+ DCHECK(!error_details->empty());
+ return error;
+ }
+ }
+ } else {
+ QUIC_RESTART_FLAG_COUNT_N(quic_google_transport_param_omit_old, 2, 3);
+ }
+
received_custom_transport_parameters_ = params.custom_parameters;
if (!is_resumption) {
diff --git a/quic/core/quic_config.h b/quic/core/quic_config.h
index 893e3e7..4d2bacc 100644
--- a/quic/core/quic_config.h
+++ b/quic/core/quic_config.h
@@ -331,11 +331,11 @@
uint32_t ReceivedBytesForConnectionId() const;
// Estimated initial round trip time in us.
- void SetInitialRoundTripTimeUsToSend(uint32_t rtt_us);
+ void SetInitialRoundTripTimeUsToSend(uint64_t rtt_us);
bool HasReceivedInitialRoundTripTimeUs() const;
- uint32_t ReceivedInitialRoundTripTimeUs() const;
+ uint64_t ReceivedInitialRoundTripTimeUs() const;
bool HasInitialRoundTripTimeUsToSend() const;
- uint32_t GetInitialRoundTripTimeUsToSend() const;
+ uint64_t GetInitialRoundTripTimeUsToSend() const;
// Sets an initial stream flow control window size to transmit to the peer.
void SetInitialStreamFlowControlWindowToSend(uint64_t window_bytes);
@@ -528,7 +528,7 @@
// the legacy header format used only by Q043 at this point.
QuicFixedUint32 bytes_for_connection_id_;
// Initial round trip time estimate in microseconds.
- QuicFixedUint32 initial_round_trip_time_us_;
+ QuicFixedUint62 initial_round_trip_time_us_;
// Initial IETF QUIC stream flow control receive windows in bytes.
// Incoming bidirectional streams.
diff --git a/quic/core/tls_client_handshaker.cc b/quic/core/tls_client_handshaker.cc
index 0378ed0..30a9ac4 100644
--- a/quic/core/tls_client_handshaker.cc
+++ b/quic/core/tls_client_handshaker.cc
@@ -207,7 +207,14 @@
if (!session()->config()->FillTransportParameters(¶ms)) {
return false;
}
- params.google_quic_params->SetStringPiece(kUAID, user_agent_id_);
+ if (GetQuicRestartFlag(quic_google_transport_param_send_new)) {
+ if (!user_agent_id_.empty()) {
+ params.user_agent_id = user_agent_id_;
+ }
+ }
+ if (!GetQuicRestartFlag(quic_google_transport_param_omit_old)) {
+ params.google_quic_params->SetStringPiece(kUAID, user_agent_id_);
+ }
std::vector<uint8_t> param_bytes;
return SerializeTransportParameters(session()->connection()->version(),