Add google_handshake_message transport parameter.
PiperOrigin-RevId: 483816526
diff --git a/quiche/quic/core/crypto/transport_parameters.cc b/quiche/quic/core/crypto/transport_parameters.cc
index 140c16a..7aa2e05 100644
--- a/quiche/quic/core/crypto/transport_parameters.cc
+++ b/quiche/quic/core/crypto/transport_parameters.cc
@@ -53,6 +53,8 @@
kMaxDatagramFrameSize = 0x20,
+ kGoogleHandshakeMessage = 0x26ab,
+
kInitialRoundTripTime = 0x3127,
kGoogleConnectionOptions = 0x3128,
// 0x3129 was used to convey the user agent string.
@@ -119,6 +121,8 @@
return "retry_source_connection_id";
case TransportParameters::kMaxDatagramFrameSize:
return "max_datagram_frame_size";
+ case TransportParameters::kGoogleHandshakeMessage:
+ return "google_handshake_message";
case TransportParameters::kInitialRoundTripTime:
return "initial_round_trip_time";
case TransportParameters::kGoogleConnectionOptions:
@@ -154,6 +158,7 @@
case TransportParameters::kInitialSourceConnectionId:
case TransportParameters::kRetrySourceConnectionId:
case TransportParameters::kMaxDatagramFrameSize:
+ case TransportParameters::kGoogleHandshakeMessage:
case TransportParameters::kInitialRoundTripTime:
case TransportParameters::kGoogleConnectionOptions:
case TransportParameters::kGoogleQuicVersion:
@@ -419,6 +424,11 @@
retry_source_connection_id.value().ToString();
}
rv += max_datagram_frame_size.ToString(/*for_use_in_list=*/true);
+ if (google_handshake_message.has_value()) {
+ absl::StrAppend(&rv, " ",
+ TransportParameterIdToString(kGoogleHandshakeMessage),
+ " length: ", google_handshake_message.value().length());
+ }
rv += initial_round_trip_time_us.ToString(/*for_use_in_list=*/true);
if (google_connection_options.has_value()) {
rv += " " + TransportParameterIdToString(kGoogleConnectionOptions) + " ";
@@ -505,6 +515,7 @@
retry_source_connection_id(other.retry_source_connection_id),
max_datagram_frame_size(other.max_datagram_frame_size),
initial_round_trip_time_us(other.initial_round_trip_time_us),
+ google_handshake_message(other.google_handshake_message),
google_connection_options(other.google_connection_options),
custom_parameters(other.custom_parameters) {
if (other.preferred_address) {
@@ -545,6 +556,7 @@
rhs.max_datagram_frame_size.value() &&
initial_round_trip_time_us.value() ==
rhs.initial_round_trip_time_us.value() &&
+ google_handshake_message == rhs.google_handshake_message &&
google_connection_options == rhs.google_connection_options &&
custom_parameters == rhs.custom_parameters)) {
return false;
@@ -616,6 +628,11 @@
}
}
if (perspective == Perspective::IS_SERVER &&
+ google_handshake_message.has_value()) {
+ *error_details = "Server cannot send google_handshake_message";
+ 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;
@@ -726,6 +743,7 @@
kConnectionIdParameterLength + // retry_source_connection_id
kIntegerParameterLength + // max_datagram_frame_size
kIntegerParameterLength + // initial_round_trip_time_us
+ kTypeAndValueLength + // google_handshake_message
kTypeAndValueLength + // google_connection_options
kTypeAndValueLength; // google-version
@@ -745,6 +763,7 @@
TransportParameters::kMinAckDelay,
TransportParameters::kActiveConnectionIdLimit,
TransportParameters::kMaxDatagramFrameSize,
+ TransportParameters::kGoogleHandshakeMessage,
TransportParameters::kInitialRoundTripTime,
TransportParameters::kDisableActiveMigration,
TransportParameters::kPreferredAddress,
@@ -777,6 +796,10 @@
(in.version_information.value().other_versions.size() + 1) *
sizeof(QuicVersionLabel);
}
+ // google_handshake_message.
+ if (in.google_handshake_message.has_value()) {
+ max_transport_param_length += in.google_handshake_message.value().length();
+ }
// Add a random GREASE transport parameter, as defined in the
// "Reserved Transport Parameters" section of RFC 9000.
@@ -958,6 +981,20 @@
return false;
}
} break;
+ // google_handshake_message
+ case TransportParameters::kGoogleHandshakeMessage: {
+ if (in.google_handshake_message.has_value()) {
+ if (!writer.WriteVarInt62(
+ TransportParameters::kGoogleHandshakeMessage) ||
+ !writer.WriteStringPieceVarInt62(
+ in.google_handshake_message.value())) {
+ QUIC_BUG(Failed to write google_handshake_message)
+ << "Failed to write google_handshake_message: "
+ << in.google_handshake_message.value() << " for " << in;
+ return false;
+ }
+ }
+ } break;
// initial_round_trip_time_us
case TransportParameters::kInitialRoundTripTime: {
if (!in.initial_round_trip_time_us.Write(&writer)) {
@@ -1386,6 +1423,14 @@
parse_success =
out->max_datagram_frame_size.Read(&value_reader, error_details);
break;
+ case TransportParameters::kGoogleHandshakeMessage:
+ if (out->google_handshake_message.has_value()) {
+ *error_details = "Received a second google_handshake_message";
+ return false;
+ }
+ out->google_handshake_message =
+ std::string(value_reader.ReadRemainingPayload());
+ break;
case TransportParameters::kInitialRoundTripTime:
parse_success =
out->initial_round_trip_time_us.Read(&value_reader, error_details);
diff --git a/quiche/quic/core/crypto/transport_parameters.h b/quiche/quic/core/crypto/transport_parameters.h
index 14ae6e9..e62d1ef 100644
--- a/quiche/quic/core/crypto/transport_parameters.h
+++ b/quiche/quic/core/crypto/transport_parameters.h
@@ -252,6 +252,9 @@
// initial round-trip time in microseconds.
IntegerParameter initial_round_trip_time_us;
+ // Google internal handshake message.
+ absl::optional<std::string> google_handshake_message;
+
// Google-specific connection options.
absl::optional<QuicTagVector> google_connection_options;
diff --git a/quiche/quic/core/crypto/transport_parameters_test.cc b/quiche/quic/core/crypto/transport_parameters_test.cc
index 76613f0..569a5a0 100644
--- a/quiche/quic/core/crypto/transport_parameters_test.cc
+++ b/quiche/quic/core/crypto/transport_parameters_test.cc
@@ -8,6 +8,7 @@
#include <utility>
#include "absl/base/macros.h"
+#include "absl/strings/escaping.h"
#include "absl/strings/string_view.h"
#include "quiche/quic/core/crypto/crypto_protocol.h"
#include "quiche/quic/core/quic_connection_id.h"
@@ -45,6 +46,9 @@
static_cast<TransportParameters::TransportParameterId>(0xff34);
const char* kCustomParameter2Value = "bar";
+const char kFakeGoogleHandshakeMessage[] =
+ "01000106030392655f5230270d4964a4f99b15bbad220736d972aea97bf9ac494ead62e6";
+
QuicConnectionId CreateFakeOriginalDestinationConnectionId() {
return TestConnectionId(0x1337);
}
@@ -284,6 +288,8 @@
CreateFakeInitialSourceConnectionId();
orig_params.retry_source_connection_id = CreateFakeRetrySourceConnectionId();
orig_params.initial_round_trip_time_us.set_value(kFakeInitialRoundTripTime);
+ orig_params.google_handshake_message =
+ absl::HexStringToBytes(kFakeGoogleHandshakeMessage);
orig_params.google_connection_options = CreateFakeGoogleConnectionOptions();
orig_params.custom_parameters[kCustomParameter1] = kCustomParameter1Value;
orig_params.custom_parameters[kCustomParameter2] = kCustomParameter2Value;
@@ -318,6 +324,8 @@
orig_params.initial_source_connection_id =
CreateFakeInitialSourceConnectionId();
orig_params.initial_round_trip_time_us.set_value(kFakeInitialRoundTripTime);
+ orig_params.google_handshake_message =
+ absl::HexStringToBytes(kFakeGoogleHandshakeMessage);
orig_params.google_connection_options = CreateFakeGoogleConnectionOptions();
orig_params.custom_parameters[kCustomParameter1] = kCustomParameter1Value;
orig_params.custom_parameters[kCustomParameter2] = kCustomParameter2Value;
@@ -548,6 +556,12 @@
0x0f, // parameter id
0x08, // length
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x23, 0x45,
+ // google_handshake_message
+ 0x66, 0xab, // parameter id
+ 0x24, // length
+ 0x01, 0x00, 0x01, 0x06, 0x03, 0x03, 0x92, 0x65, 0x5f, 0x52, 0x30, 0x27,
+ 0x0d, 0x49, 0x64, 0xa4, 0xf9, 0x9b, 0x15, 0xbb, 0xad, 0x22, 0x07, 0x36,
+ 0xd9, 0x72, 0xae, 0xa9, 0x7b, 0xf9, 0xac, 0x49, 0x4e, 0xad, 0x62, 0xe6,
// initial_round_trip_time_us
0x71, 0x27, // parameter id
0x01, // length
@@ -620,6 +634,8 @@
ASSERT_TRUE(new_params.google_connection_options.has_value());
EXPECT_EQ(CreateFakeGoogleConnectionOptions(),
new_params.google_connection_options.value());
+ EXPECT_EQ(absl::HexStringToBytes(kFakeGoogleHandshakeMessage),
+ new_params.google_handshake_message);
}
TEST_P(TransportParametersTest,
diff --git a/quiche/quic/core/quic_config.cc b/quiche/quic/core/quic_config.cc
index 04aa196..c059787 100644
--- a/quiche/quic/core/quic_config.cc
+++ b/quiche/quic/core/quic_config.cc
@@ -467,6 +467,15 @@
connection_options_.SetSendValues(connection_options);
}
+void QuicConfig::SetGoogleHandshakeMessageToSend(const std::string& message) {
+ google_handshake_message_to_send_ = message;
+}
+
+absl::optional<std::string> QuicConfig::GetReceivedGoogleHandshakeMessage()
+ const {
+ return received_google_handshake_message_;
+}
+
bool QuicConfig::HasReceivedConnectionOptions() const {
return connection_options_.HasReceivedValues();
}
@@ -1253,6 +1262,10 @@
params->google_connection_options = connection_options_.GetSendValues();
}
+ if (google_handshake_message_to_send_.has_value()) {
+ params->google_handshake_message = google_handshake_message_to_send_;
+ }
+
params->custom_parameters = custom_transport_parameters_to_send_;
return true;
@@ -1384,6 +1397,9 @@
connection_options_.SetReceivedValues(
params.google_connection_options.value());
}
+ if (params.google_handshake_message.has_value()) {
+ received_google_handshake_message_ = params.google_handshake_message;
+ }
received_custom_transport_parameters_ = params.custom_parameters;
diff --git a/quiche/quic/core/quic_config.h b/quiche/quic/core/quic_config.h
index 846872f..7abfb7d 100644
--- a/quiche/quic/core/quic_config.h
+++ b/quiche/quic/core/quic_config.h
@@ -247,6 +247,10 @@
bool HasReceivedConnectionOptions() const;
+ void SetGoogleHandshakeMessageToSend(const std::string& message);
+
+ absl::optional<std::string> GetReceivedGoogleHandshakeMessage() const;
+
// Sets initial received connection options. All received connection options
// will be initialized with these fields. Initial received options may only be
// set once per config, prior to the setting of any other options. If options
@@ -657,6 +661,10 @@
// handshake.
TransportParameters::ParameterMap custom_transport_parameters_to_send_;
TransportParameters::ParameterMap received_custom_transport_parameters_;
+
+ // Google internal handshake message.
+ absl::optional<std::string> google_handshake_message_to_send_;
+ absl::optional<std::string> received_google_handshake_message_;
};
} // namespace quic
diff --git a/quiche/quic/core/quic_config_test.cc b/quiche/quic/core/quic_config_test.cc
index fc8afe8..244d967 100644
--- a/quiche/quic/core/quic_config_test.cc
+++ b/quiche/quic/core/quic_config_test.cc
@@ -459,6 +459,7 @@
// TransportParameters are only used for QUIC+TLS.
return;
}
+ const std::string kFakeGoogleHandshakeMessage = "Fake handshake message";
config_.SetInitialMaxStreamDataBytesIncomingBidirectionalToSend(
2 * kMinimumFlowControlSendWindow);
config_.SetInitialMaxStreamDataBytesOutgoingBidirectionalToSend(
@@ -473,6 +474,7 @@
config_.SetInitialSourceConnectionIdToSend(TestConnectionId(0x2222));
config_.SetRetrySourceConnectionIdToSend(TestConnectionId(0x3333));
config_.SetMinAckDelayMs(kDefaultMinAckDelayTimeMs);
+ config_.SetGoogleHandshakeMessageToSend(kFakeGoogleHandshakeMessage);
QuicIpAddress host;
host.FromString("127.0.3.1");
@@ -520,6 +522,7 @@
EXPECT_EQ(*reinterpret_cast<StatelessResetToken*>(
¶ms.preferred_address->stateless_reset_token.front()),
new_stateless_reset_token);
+ EXPECT_EQ(kFakeGoogleHandshakeMessage, params.google_handshake_message);
}
TEST_P(QuicConfigTest, ProcessTransportParametersServer) {
@@ -527,6 +530,7 @@
// TransportParameters are only used for QUIC+TLS.
return;
}
+ const std::string kFakeGoogleHandshakeMessage = "Fake handshake message";
TransportParameters params;
params.initial_max_stream_data_bidi_local.set_value(
@@ -546,6 +550,7 @@
params.original_destination_connection_id = TestConnectionId(0x1111);
params.initial_source_connection_id = TestConnectionId(0x2222);
params.retry_source_connection_id = TestConnectionId(0x3333);
+ params.google_handshake_message = kFakeGoogleHandshakeMessage;
std::string error_details;
EXPECT_THAT(config_.ProcessTransportParameters(
@@ -664,6 +669,8 @@
ASSERT_TRUE(config_.HasReceivedRetrySourceConnectionId());
EXPECT_EQ(config_.ReceivedRetrySourceConnectionId(),
TestConnectionId(0x3333));
+ EXPECT_EQ(kFakeGoogleHandshakeMessage,
+ config_.GetReceivedGoogleHandshakeMessage());
}
TEST_P(QuicConfigTest, DisableMigrationTransportParameter) {