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) {