blob: 6b782c459cb7d2a4fbd5a39f6ee1ac1d303edb2e [file] [log] [blame]
// Copyright (c) 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "quiche/quic/core/crypto/transport_parameters.h"
#include <cstring>
#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"
#include "quiche/quic/core/quic_tag.h"
#include "quiche/quic/core/quic_types.h"
#include "quiche/quic/core/quic_versions.h"
#include "quiche/quic/platform/api/quic_expect_bug.h"
#include "quiche/quic/platform/api/quic_ip_address.h"
#include "quiche/quic/platform/api/quic_test.h"
#include "quiche/quic/test_tools/quic_test_utils.h"
namespace quic {
namespace test {
namespace {
const QuicVersionLabel kFakeVersionLabel = 0x01234567;
const QuicVersionLabel kFakeVersionLabel2 = 0x89ABCDEF;
const uint64_t kFakeIdleTimeoutMilliseconds = 12012;
const uint64_t kFakeInitialMaxData = 101;
const uint64_t kFakeInitialMaxStreamDataBidiLocal = 2001;
const uint64_t kFakeInitialMaxStreamDataBidiRemote = 2002;
const uint64_t kFakeInitialMaxStreamDataUni = 3000;
const uint64_t kFakeInitialMaxStreamsBidi = 21;
const uint64_t kFakeInitialMaxStreamsUni = 22;
const bool kFakeDisableMigration = true;
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};
const auto kCustomParameter1 =
static_cast<TransportParameters::TransportParameterId>(0xffcd);
const char* kCustomParameter1Value = "foo";
const auto kCustomParameter2 =
static_cast<TransportParameters::TransportParameterId>(0xff34);
const char* kCustomParameter2Value = "bar";
const char kFakeGoogleHandshakeMessage[] =
"01000106030392655f5230270d4964a4f99b15bbad220736d972aea97bf9ac494ead62e6";
QuicConnectionId CreateFakeOriginalDestinationConnectionId() {
return TestConnectionId(0x1337);
}
QuicConnectionId CreateFakeInitialSourceConnectionId() {
return TestConnectionId(0x2345);
}
QuicConnectionId CreateFakeRetrySourceConnectionId() {
return TestConnectionId(0x9876);
}
QuicConnectionId CreateFakePreferredConnectionId() {
return TestConnectionId(0xBEEF);
}
std::vector<uint8_t> CreateFakePreferredStatelessResetToken() {
return std::vector<uint8_t>(
kFakePreferredStatelessResetTokenData,
kFakePreferredStatelessResetTokenData +
sizeof(kFakePreferredStatelessResetTokenData));
}
QuicSocketAddress CreateFakeV4SocketAddress() {
QuicIpAddress ipv4_address;
if (!ipv4_address.FromString("65.66.67.68")) { // 0x41, 0x42, 0x43, 0x44
QUIC_LOG(FATAL) << "Failed to create IPv4 address";
return QuicSocketAddress();
}
return QuicSocketAddress(ipv4_address, 0x4884);
}
QuicSocketAddress CreateFakeV6SocketAddress() {
QuicIpAddress ipv6_address;
if (!ipv6_address.FromString("6061:6263:6465:6667:6869:6A6B:6C6D:6E6F")) {
QUIC_LOG(FATAL) << "Failed to create IPv6 address";
return QuicSocketAddress();
}
return QuicSocketAddress(ipv6_address, 0x6336);
}
std::unique_ptr<TransportParameters::PreferredAddress>
CreateFakePreferredAddress() {
TransportParameters::PreferredAddress preferred_address;
preferred_address.ipv4_socket_address = CreateFakeV4SocketAddress();
preferred_address.ipv6_socket_address = CreateFakeV6SocketAddress();
preferred_address.connection_id = CreateFakePreferredConnectionId();
preferred_address.stateless_reset_token =
CreateFakePreferredStatelessResetToken();
return std::make_unique<TransportParameters::PreferredAddress>(
preferred_address);
}
TransportParameters::LegacyVersionInformation
CreateFakeLegacyVersionInformationClient() {
TransportParameters::LegacyVersionInformation legacy_version_information;
legacy_version_information.version = kFakeVersionLabel;
return legacy_version_information;
}
TransportParameters::LegacyVersionInformation
CreateFakeLegacyVersionInformationServer() {
TransportParameters::LegacyVersionInformation legacy_version_information =
CreateFakeLegacyVersionInformationClient();
legacy_version_information.supported_versions.push_back(kFakeVersionLabel);
legacy_version_information.supported_versions.push_back(kFakeVersionLabel2);
return legacy_version_information;
}
TransportParameters::VersionInformation CreateFakeVersionInformation() {
TransportParameters::VersionInformation version_information;
version_information.chosen_version = kFakeVersionLabel;
version_information.other_versions.push_back(kFakeVersionLabel);
version_information.other_versions.push_back(kFakeVersionLabel2);
return version_information;
}
QuicTagVector CreateFakeGoogleConnectionOptions() {
return {kALPN, MakeQuicTag('E', 'F', 'G', 0x00),
MakeQuicTag('H', 'I', 'J', 0xff)};
}
void RemoveGreaseParameters(TransportParameters* params) {
std::vector<TransportParameters::TransportParameterId> grease_params;
for (const auto& kv : params->custom_parameters) {
if (kv.first % 31 == 27) {
grease_params.push_back(kv.first);
}
}
EXPECT_EQ(grease_params.size(), 1u);
for (TransportParameters::TransportParameterId param_id : grease_params) {
params->custom_parameters.erase(param_id);
}
// Remove all GREASE versions from version_information.other_versions.
if (params->version_information.has_value()) {
QuicVersionLabelVector& other_versions =
params->version_information.value().other_versions;
for (auto it = other_versions.begin(); it != other_versions.end();) {
if ((*it & 0x0f0f0f0f) == 0x0a0a0a0a) {
it = other_versions.erase(it);
} else {
++it;
}
}
}
}
} // namespace
class TransportParametersTest : public QuicTestWithParam<ParsedQuicVersion> {
protected:
TransportParametersTest() : version_(GetParam()) {}
ParsedQuicVersion version_;
};
INSTANTIATE_TEST_SUITE_P(TransportParametersTests, TransportParametersTest,
::testing::ValuesIn(AllSupportedVersionsWithTls()),
::testing::PrintToStringParamName());
TEST_P(TransportParametersTest, Comparator) {
TransportParameters orig_params;
TransportParameters new_params;
// Test comparison on primitive members.
orig_params.perspective = Perspective::IS_CLIENT;
new_params.perspective = Perspective::IS_SERVER;
EXPECT_NE(orig_params, new_params);
EXPECT_FALSE(orig_params == new_params);
EXPECT_TRUE(orig_params != new_params);
new_params.perspective = Perspective::IS_CLIENT;
orig_params.legacy_version_information =
CreateFakeLegacyVersionInformationClient();
new_params.legacy_version_information =
CreateFakeLegacyVersionInformationClient();
orig_params.version_information = CreateFakeVersionInformation();
new_params.version_information = CreateFakeVersionInformation();
orig_params.disable_active_migration = true;
new_params.disable_active_migration = true;
EXPECT_EQ(orig_params, new_params);
EXPECT_TRUE(orig_params == new_params);
EXPECT_FALSE(orig_params != new_params);
// Test comparison on vectors.
orig_params.legacy_version_information.value().supported_versions.push_back(
kFakeVersionLabel);
new_params.legacy_version_information.value().supported_versions.push_back(
kFakeVersionLabel2);
EXPECT_NE(orig_params, new_params);
EXPECT_FALSE(orig_params == new_params);
EXPECT_TRUE(orig_params != new_params);
new_params.legacy_version_information.value().supported_versions.pop_back();
new_params.legacy_version_information.value().supported_versions.push_back(
kFakeVersionLabel);
orig_params.stateless_reset_token = CreateStatelessResetTokenForTest();
new_params.stateless_reset_token = CreateStatelessResetTokenForTest();
EXPECT_EQ(orig_params, new_params);
EXPECT_TRUE(orig_params == new_params);
EXPECT_FALSE(orig_params != new_params);
// Test comparison on IntegerParameters.
orig_params.max_udp_payload_size.set_value(kMaxPacketSizeForTest);
new_params.max_udp_payload_size.set_value(kMaxPacketSizeForTest + 1);
EXPECT_NE(orig_params, new_params);
EXPECT_FALSE(orig_params == new_params);
EXPECT_TRUE(orig_params != new_params);
new_params.max_udp_payload_size.set_value(kMaxPacketSizeForTest);
EXPECT_EQ(orig_params, new_params);
EXPECT_TRUE(orig_params == new_params);
EXPECT_FALSE(orig_params != new_params);
// Test comparison on PreferredAddress
orig_params.preferred_address = CreateFakePreferredAddress();
EXPECT_NE(orig_params, new_params);
EXPECT_FALSE(orig_params == new_params);
EXPECT_TRUE(orig_params != new_params);
new_params.preferred_address = CreateFakePreferredAddress();
EXPECT_EQ(orig_params, new_params);
EXPECT_TRUE(orig_params == new_params);
EXPECT_FALSE(orig_params != new_params);
// Test comparison on CustomMap
orig_params.custom_parameters[kCustomParameter1] = kCustomParameter1Value;
orig_params.custom_parameters[kCustomParameter2] = kCustomParameter2Value;
new_params.custom_parameters[kCustomParameter2] = kCustomParameter2Value;
new_params.custom_parameters[kCustomParameter1] = kCustomParameter1Value;
EXPECT_EQ(orig_params, new_params);
EXPECT_TRUE(orig_params == new_params);
EXPECT_FALSE(orig_params != new_params);
// Test comparison on connection IDs.
orig_params.initial_source_connection_id =
CreateFakeInitialSourceConnectionId();
new_params.initial_source_connection_id = absl::nullopt;
EXPECT_NE(orig_params, new_params);
EXPECT_FALSE(orig_params == new_params);
EXPECT_TRUE(orig_params != new_params);
new_params.initial_source_connection_id = TestConnectionId(0xbadbad);
EXPECT_NE(orig_params, new_params);
EXPECT_FALSE(orig_params == new_params);
EXPECT_TRUE(orig_params != new_params);
new_params.initial_source_connection_id =
CreateFakeInitialSourceConnectionId();
EXPECT_EQ(orig_params, new_params);
EXPECT_TRUE(orig_params == new_params);
EXPECT_FALSE(orig_params != new_params);
}
TEST_P(TransportParametersTest, CopyConstructor) {
TransportParameters orig_params;
orig_params.perspective = Perspective::IS_CLIENT;
orig_params.legacy_version_information =
CreateFakeLegacyVersionInformationClient();
orig_params.version_information = CreateFakeVersionInformation();
orig_params.original_destination_connection_id =
CreateFakeOriginalDestinationConnectionId();
orig_params.max_idle_timeout_ms.set_value(kFakeIdleTimeoutMilliseconds);
orig_params.stateless_reset_token = CreateStatelessResetTokenForTest();
orig_params.max_udp_payload_size.set_value(kMaxPacketSizeForTest);
orig_params.initial_max_data.set_value(kFakeInitialMaxData);
orig_params.initial_max_stream_data_bidi_local.set_value(
kFakeInitialMaxStreamDataBidiLocal);
orig_params.initial_max_stream_data_bidi_remote.set_value(
kFakeInitialMaxStreamDataBidiRemote);
orig_params.initial_max_stream_data_uni.set_value(
kFakeInitialMaxStreamDataUni);
orig_params.initial_max_streams_bidi.set_value(kFakeInitialMaxStreamsBidi);
orig_params.initial_max_streams_uni.set_value(kFakeInitialMaxStreamsUni);
orig_params.ack_delay_exponent.set_value(kAckDelayExponentForTest);
orig_params.max_ack_delay.set_value(kMaxAckDelayForTest);
orig_params.min_ack_delay_us.set_value(kMinAckDelayUsForTest);
orig_params.disable_active_migration = kFakeDisableMigration;
orig_params.preferred_address = CreateFakePreferredAddress();
orig_params.active_connection_id_limit.set_value(
kActiveConnectionIdLimitForTest);
orig_params.initial_source_connection_id =
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;
TransportParameters new_params(orig_params);
EXPECT_EQ(new_params, orig_params);
}
TEST_P(TransportParametersTest, RoundTripClient) {
TransportParameters orig_params;
orig_params.perspective = Perspective::IS_CLIENT;
orig_params.legacy_version_information =
CreateFakeLegacyVersionInformationClient();
orig_params.version_information = CreateFakeVersionInformation();
orig_params.max_idle_timeout_ms.set_value(kFakeIdleTimeoutMilliseconds);
orig_params.max_udp_payload_size.set_value(kMaxPacketSizeForTest);
orig_params.initial_max_data.set_value(kFakeInitialMaxData);
orig_params.initial_max_stream_data_bidi_local.set_value(
kFakeInitialMaxStreamDataBidiLocal);
orig_params.initial_max_stream_data_bidi_remote.set_value(
kFakeInitialMaxStreamDataBidiRemote);
orig_params.initial_max_stream_data_uni.set_value(
kFakeInitialMaxStreamDataUni);
orig_params.initial_max_streams_bidi.set_value(kFakeInitialMaxStreamsBidi);
orig_params.initial_max_streams_uni.set_value(kFakeInitialMaxStreamsUni);
orig_params.ack_delay_exponent.set_value(kAckDelayExponentForTest);
orig_params.max_ack_delay.set_value(kMaxAckDelayForTest);
orig_params.min_ack_delay_us.set_value(kMinAckDelayUsForTest);
orig_params.disable_active_migration = kFakeDisableMigration;
orig_params.active_connection_id_limit.set_value(
kActiveConnectionIdLimitForTest);
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;
std::vector<uint8_t> serialized;
ASSERT_TRUE(SerializeTransportParameters(orig_params, &serialized));
TransportParameters new_params;
std::string error_details;
ASSERT_TRUE(ParseTransportParameters(version_, Perspective::IS_CLIENT,
serialized.data(), serialized.size(),
&new_params, &error_details))
<< error_details;
EXPECT_TRUE(error_details.empty());
RemoveGreaseParameters(&new_params);
EXPECT_EQ(new_params, orig_params);
}
TEST_P(TransportParametersTest, RoundTripServer) {
TransportParameters orig_params;
orig_params.perspective = Perspective::IS_SERVER;
orig_params.legacy_version_information =
CreateFakeLegacyVersionInformationServer();
orig_params.version_information = CreateFakeVersionInformation();
orig_params.original_destination_connection_id =
CreateFakeOriginalDestinationConnectionId();
orig_params.max_idle_timeout_ms.set_value(kFakeIdleTimeoutMilliseconds);
orig_params.stateless_reset_token = CreateStatelessResetTokenForTest();
orig_params.max_udp_payload_size.set_value(kMaxPacketSizeForTest);
orig_params.initial_max_data.set_value(kFakeInitialMaxData);
orig_params.initial_max_stream_data_bidi_local.set_value(
kFakeInitialMaxStreamDataBidiLocal);
orig_params.initial_max_stream_data_bidi_remote.set_value(
kFakeInitialMaxStreamDataBidiRemote);
orig_params.initial_max_stream_data_uni.set_value(
kFakeInitialMaxStreamDataUni);
orig_params.initial_max_streams_bidi.set_value(kFakeInitialMaxStreamsBidi);
orig_params.initial_max_streams_uni.set_value(kFakeInitialMaxStreamsUni);
orig_params.ack_delay_exponent.set_value(kAckDelayExponentForTest);
orig_params.max_ack_delay.set_value(kMaxAckDelayForTest);
orig_params.min_ack_delay_us.set_value(kMinAckDelayUsForTest);
orig_params.disable_active_migration = kFakeDisableMigration;
orig_params.preferred_address = CreateFakePreferredAddress();
orig_params.active_connection_id_limit.set_value(
kActiveConnectionIdLimitForTest);
orig_params.initial_source_connection_id =
CreateFakeInitialSourceConnectionId();
orig_params.retry_source_connection_id = CreateFakeRetrySourceConnectionId();
orig_params.google_connection_options = CreateFakeGoogleConnectionOptions();
std::vector<uint8_t> serialized;
ASSERT_TRUE(SerializeTransportParameters(orig_params, &serialized));
TransportParameters new_params;
std::string error_details;
ASSERT_TRUE(ParseTransportParameters(version_, Perspective::IS_SERVER,
serialized.data(), serialized.size(),
&new_params, &error_details))
<< error_details;
EXPECT_TRUE(error_details.empty());
RemoveGreaseParameters(&new_params);
EXPECT_EQ(new_params, orig_params);
}
TEST_P(TransportParametersTest, AreValid) {
{
TransportParameters params;
std::string error_details;
params.perspective = Perspective::IS_CLIENT;
EXPECT_TRUE(params.AreValid(&error_details));
EXPECT_TRUE(error_details.empty());
}
{
TransportParameters params;
std::string error_details;
params.perspective = Perspective::IS_CLIENT;
EXPECT_TRUE(params.AreValid(&error_details));
EXPECT_TRUE(error_details.empty());
params.max_idle_timeout_ms.set_value(kFakeIdleTimeoutMilliseconds);
EXPECT_TRUE(params.AreValid(&error_details));
EXPECT_TRUE(error_details.empty());
params.max_idle_timeout_ms.set_value(601000);
EXPECT_TRUE(params.AreValid(&error_details));
EXPECT_TRUE(error_details.empty());
}
{
TransportParameters params;
std::string error_details;
params.perspective = Perspective::IS_CLIENT;
EXPECT_TRUE(params.AreValid(&error_details));
EXPECT_TRUE(error_details.empty());
params.max_udp_payload_size.set_value(1200);
EXPECT_TRUE(params.AreValid(&error_details));
EXPECT_TRUE(error_details.empty());
params.max_udp_payload_size.set_value(65535);
EXPECT_TRUE(params.AreValid(&error_details));
EXPECT_TRUE(error_details.empty());
params.max_udp_payload_size.set_value(9999999);
EXPECT_TRUE(params.AreValid(&error_details));
EXPECT_TRUE(error_details.empty());
params.max_udp_payload_size.set_value(0);
error_details = "";
EXPECT_FALSE(params.AreValid(&error_details));
EXPECT_EQ(error_details,
"Invalid transport parameters [Client max_udp_payload_size 0 "
"(Invalid)]");
params.max_udp_payload_size.set_value(1199);
error_details = "";
EXPECT_FALSE(params.AreValid(&error_details));
EXPECT_EQ(error_details,
"Invalid transport parameters [Client max_udp_payload_size 1199 "
"(Invalid)]");
}
{
TransportParameters params;
std::string error_details;
params.perspective = Perspective::IS_CLIENT;
EXPECT_TRUE(params.AreValid(&error_details));
EXPECT_TRUE(error_details.empty());
params.ack_delay_exponent.set_value(0);
EXPECT_TRUE(params.AreValid(&error_details));
EXPECT_TRUE(error_details.empty());
params.ack_delay_exponent.set_value(20);
EXPECT_TRUE(params.AreValid(&error_details));
EXPECT_TRUE(error_details.empty());
params.ack_delay_exponent.set_value(21);
EXPECT_FALSE(params.AreValid(&error_details));
EXPECT_EQ(error_details,
"Invalid transport parameters [Client ack_delay_exponent 21 "
"(Invalid)]");
}
{
TransportParameters params;
std::string error_details;
params.perspective = Perspective::IS_CLIENT;
EXPECT_TRUE(params.AreValid(&error_details));
EXPECT_TRUE(error_details.empty());
params.active_connection_id_limit.set_value(2);
EXPECT_TRUE(params.AreValid(&error_details));
EXPECT_TRUE(error_details.empty());
params.active_connection_id_limit.set_value(999999);
EXPECT_TRUE(params.AreValid(&error_details));
EXPECT_TRUE(error_details.empty());
params.active_connection_id_limit.set_value(1);
EXPECT_FALSE(params.AreValid(&error_details));
EXPECT_EQ(error_details,
"Invalid transport parameters [Client active_connection_id_limit"
" 1 (Invalid)]");
params.active_connection_id_limit.set_value(0);
EXPECT_FALSE(params.AreValid(&error_details));
EXPECT_EQ(error_details,
"Invalid transport parameters [Client active_connection_id_limit"
" 0 (Invalid)]");
}
}
TEST_P(TransportParametersTest, NoClientParamsWithStatelessResetToken) {
TransportParameters orig_params;
orig_params.perspective = Perspective::IS_CLIENT;
orig_params.legacy_version_information =
CreateFakeLegacyVersionInformationClient();
orig_params.max_idle_timeout_ms.set_value(kFakeIdleTimeoutMilliseconds);
orig_params.stateless_reset_token = CreateStatelessResetTokenForTest();
orig_params.max_udp_payload_size.set_value(kMaxPacketSizeForTest);
std::vector<uint8_t> out;
EXPECT_QUIC_BUG(
EXPECT_FALSE(SerializeTransportParameters(orig_params, &out)),
"Not serializing invalid transport parameters: Client cannot send "
"stateless reset token");
}
TEST_P(TransportParametersTest, ParseClientParams) {
// clang-format off
const uint8_t kClientParams[] = {
// max_idle_timeout
0x01, // parameter id
0x02, // length
0x6e, 0xec, // value
// max_udp_payload_size
0x03, // parameter id
0x02, // length
0x63, 0x29, // value
// initial_max_data
0x04, // parameter id
0x02, // length
0x40, 0x65, // value
// initial_max_stream_data_bidi_local
0x05, // parameter id
0x02, // length
0x47, 0xD1, // value
// initial_max_stream_data_bidi_remote
0x06, // parameter id
0x02, // length
0x47, 0xD2, // value
// initial_max_stream_data_uni
0x07, // parameter id
0x02, // length
0x4B, 0xB8, // value
// initial_max_streams_bidi
0x08, // parameter id
0x01, // length
0x15, // value
// initial_max_streams_uni
0x09, // parameter id
0x01, // length
0x16, // value
// ack_delay_exponent
0x0a, // parameter id
0x01, // length
0x0a, // value
// max_ack_delay
0x0b, // parameter id
0x01, // length
0x33, // value
// min_ack_delay_us
0x80, 0x00, 0xde, 0x1a, // parameter id
0x02, // length
0x43, 0xe8, // value
// disable_active_migration
0x0c, // parameter id
0x00, // length
// active_connection_id_limit
0x0e, // parameter id
0x01, // length
0x34, // value
// initial_source_connection_id
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
0x35, // 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
0x04, // length
0x01, 0x23, 0x45, 0x67, // initial version
// version_information
0x80, 0xFF, 0x73, 0xDB, // parameter id
0x0C, // length
0x01, 0x23, 0x45, 0x67, // chosen version
0x01, 0x23, 0x45, 0x67, // other version 1
0x89, 0xab, 0xcd, 0xef, // other version 2
};
// clang-format on
const uint8_t* client_params =
reinterpret_cast<const uint8_t*>(kClientParams);
size_t client_params_length = ABSL_ARRAYSIZE(kClientParams);
TransportParameters new_params;
std::string error_details;
ASSERT_TRUE(ParseTransportParameters(version_, Perspective::IS_CLIENT,
client_params, client_params_length,
&new_params, &error_details))
<< error_details;
EXPECT_TRUE(error_details.empty());
EXPECT_EQ(Perspective::IS_CLIENT, new_params.perspective);
ASSERT_TRUE(new_params.legacy_version_information.has_value());
EXPECT_EQ(kFakeVersionLabel,
new_params.legacy_version_information.value().version);
EXPECT_TRUE(
new_params.legacy_version_information.value().supported_versions.empty());
ASSERT_TRUE(new_params.version_information.has_value());
EXPECT_EQ(new_params.version_information.value(),
CreateFakeVersionInformation());
EXPECT_FALSE(new_params.original_destination_connection_id.has_value());
EXPECT_EQ(kFakeIdleTimeoutMilliseconds,
new_params.max_idle_timeout_ms.value());
EXPECT_TRUE(new_params.stateless_reset_token.empty());
EXPECT_EQ(kMaxPacketSizeForTest, new_params.max_udp_payload_size.value());
EXPECT_EQ(kFakeInitialMaxData, new_params.initial_max_data.value());
EXPECT_EQ(kFakeInitialMaxStreamDataBidiLocal,
new_params.initial_max_stream_data_bidi_local.value());
EXPECT_EQ(kFakeInitialMaxStreamDataBidiRemote,
new_params.initial_max_stream_data_bidi_remote.value());
EXPECT_EQ(kFakeInitialMaxStreamDataUni,
new_params.initial_max_stream_data_uni.value());
EXPECT_EQ(kFakeInitialMaxStreamsBidi,
new_params.initial_max_streams_bidi.value());
EXPECT_EQ(kFakeInitialMaxStreamsUni,
new_params.initial_max_streams_uni.value());
EXPECT_EQ(kAckDelayExponentForTest, new_params.ack_delay_exponent.value());
EXPECT_EQ(kMaxAckDelayForTest, new_params.max_ack_delay.value());
EXPECT_EQ(kMinAckDelayUsForTest, new_params.min_ack_delay_us.value());
EXPECT_EQ(kFakeDisableMigration, new_params.disable_active_migration);
EXPECT_EQ(kActiveConnectionIdLimitForTest,
new_params.active_connection_id_limit.value());
ASSERT_TRUE(new_params.initial_source_connection_id.has_value());
EXPECT_EQ(CreateFakeInitialSourceConnectionId(),
new_params.initial_source_connection_id.value());
EXPECT_FALSE(new_params.retry_source_connection_id.has_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());
EXPECT_EQ(absl::HexStringToBytes(kFakeGoogleHandshakeMessage),
new_params.google_handshake_message);
}
TEST_P(TransportParametersTest,
ParseClientParamsFailsWithFullStatelessResetToken) {
// clang-format off
const uint8_t kClientParamsWithFullToken[] = {
// max_idle_timeout
0x01, // parameter id
0x02, // length
0x6e, 0xec, // value
// stateless_reset_token
0x02, // parameter id
0x10, // length
0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F,
// max_udp_payload_size
0x03, // parameter id
0x02, // length
0x63, 0x29, // value
// initial_max_data
0x04, // parameter id
0x02, // length
0x40, 0x65, // value
};
// clang-format on
const uint8_t* client_params =
reinterpret_cast<const uint8_t*>(kClientParamsWithFullToken);
size_t client_params_length = ABSL_ARRAYSIZE(kClientParamsWithFullToken);
TransportParameters out_params;
std::string error_details;
EXPECT_FALSE(ParseTransportParameters(version_, Perspective::IS_CLIENT,
client_params, client_params_length,
&out_params, &error_details));
EXPECT_EQ(error_details, "Client cannot send stateless reset token");
}
TEST_P(TransportParametersTest,
ParseClientParamsFailsWithEmptyStatelessResetToken) {
// clang-format off
const uint8_t kClientParamsWithEmptyToken[] = {
// max_idle_timeout
0x01, // parameter id
0x02, // length
0x6e, 0xec, // value
// stateless_reset_token
0x02, // parameter id
0x00, // length
// max_udp_payload_size
0x03, // parameter id
0x02, // length
0x63, 0x29, // value
// initial_max_data
0x04, // parameter id
0x02, // length
0x40, 0x65, // value
};
// clang-format on
const uint8_t* client_params =
reinterpret_cast<const uint8_t*>(kClientParamsWithEmptyToken);
size_t client_params_length = ABSL_ARRAYSIZE(kClientParamsWithEmptyToken);
TransportParameters out_params;
std::string error_details;
EXPECT_FALSE(ParseTransportParameters(version_, Perspective::IS_CLIENT,
client_params, client_params_length,
&out_params, &error_details));
EXPECT_EQ(error_details,
"Received stateless_reset_token of invalid length 0");
}
TEST_P(TransportParametersTest, ParseClientParametersRepeated) {
// clang-format off
const uint8_t kClientParamsRepeated[] = {
// max_idle_timeout
0x01, // parameter id
0x02, // length
0x6e, 0xec, // value
// max_udp_payload_size
0x03, // parameter id
0x02, // length
0x63, 0x29, // value
// max_idle_timeout (repeated)
0x01, // parameter id
0x02, // length
0x6e, 0xec, // value
};
// clang-format on
const uint8_t* client_params =
reinterpret_cast<const uint8_t*>(kClientParamsRepeated);
size_t client_params_length = ABSL_ARRAYSIZE(kClientParamsRepeated);
TransportParameters out_params;
std::string error_details;
EXPECT_FALSE(ParseTransportParameters(version_, Perspective::IS_CLIENT,
client_params, client_params_length,
&out_params, &error_details));
EXPECT_EQ(error_details, "Received a second max_idle_timeout");
}
TEST_P(TransportParametersTest, ParseServerParams) {
// clang-format off
const uint8_t kServerParams[] = {
// original_destination_connection_id
0x00, // parameter id
0x08, // length
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x37,
// max_idle_timeout
0x01, // parameter id
0x02, // length
0x6e, 0xec, // value
// stateless_reset_token
0x02, // parameter id
0x10, // length
0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F,
// max_udp_payload_size
0x03, // parameter id
0x02, // length
0x63, 0x29, // value
// initial_max_data
0x04, // parameter id
0x02, // length
0x40, 0x65, // value
// initial_max_stream_data_bidi_local
0x05, // parameter id
0x02, // length
0x47, 0xD1, // value
// initial_max_stream_data_bidi_remote
0x06, // parameter id
0x02, // length
0x47, 0xD2, // value
// initial_max_stream_data_uni
0x07, // parameter id
0x02, // length
0x4B, 0xB8, // value
// initial_max_streams_bidi
0x08, // parameter id
0x01, // length
0x15, // value
// initial_max_streams_uni
0x09, // parameter id
0x01, // length
0x16, // value
// ack_delay_exponent
0x0a, // parameter id
0x01, // length
0x0a, // value
// max_ack_delay
0x0b, // parameter id
0x01, // length
0x33, // value
// min_ack_delay_us
0x80, 0x00, 0xde, 0x1a, // parameter id
0x02, // length
0x43, 0xe8, // value
// disable_active_migration
0x0c, // parameter id
0x00, // length
// preferred_address
0x0d, // parameter id
0x31, // length
0x41, 0x42, 0x43, 0x44, // IPv4 address
0x48, 0x84, // IPv4 port
0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, // IPv6 address
0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
0x63, 0x36, // IPv6 port
0x08, // connection ID length
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xBE, 0xEF, // connection ID
0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, // stateless reset token
0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F,
// active_connection_id_limit
0x0e, // parameter id
0x01, // length
0x34, // value
// initial_source_connection_id
0x0f, // parameter id
0x08, // length
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x23, 0x45,
// retry_source_connection_id
0x10, // parameter id
0x08, // length
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x98, 0x76,
// 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
0x01, 0x23, 0x45, 0x67, // negotiated_version
0x08, // length of supported versions array
0x01, 0x23, 0x45, 0x67,
0x89, 0xab, 0xcd, 0xef,
// version_information
0x80, 0xFF, 0x73, 0xDB, // parameter id
0x0C, // length
0x01, 0x23, 0x45, 0x67, // chosen version
0x01, 0x23, 0x45, 0x67, // other version 1
0x89, 0xab, 0xcd, 0xef, // other version 2
};
// clang-format on
const uint8_t* server_params =
reinterpret_cast<const uint8_t*>(kServerParams);
size_t server_params_length = ABSL_ARRAYSIZE(kServerParams);
TransportParameters new_params;
std::string error_details;
ASSERT_TRUE(ParseTransportParameters(version_, Perspective::IS_SERVER,
server_params, server_params_length,
&new_params, &error_details))
<< error_details;
EXPECT_TRUE(error_details.empty());
EXPECT_EQ(Perspective::IS_SERVER, new_params.perspective);
ASSERT_TRUE(new_params.legacy_version_information.has_value());
EXPECT_EQ(kFakeVersionLabel,
new_params.legacy_version_information.value().version);
ASSERT_EQ(
2u,
new_params.legacy_version_information.value().supported_versions.size());
EXPECT_EQ(
kFakeVersionLabel,
new_params.legacy_version_information.value().supported_versions[0]);
EXPECT_EQ(
kFakeVersionLabel2,
new_params.legacy_version_information.value().supported_versions[1]);
ASSERT_TRUE(new_params.version_information.has_value());
EXPECT_EQ(new_params.version_information.value(),
CreateFakeVersionInformation());
ASSERT_TRUE(new_params.original_destination_connection_id.has_value());
EXPECT_EQ(CreateFakeOriginalDestinationConnectionId(),
new_params.original_destination_connection_id.value());
EXPECT_EQ(kFakeIdleTimeoutMilliseconds,
new_params.max_idle_timeout_ms.value());
EXPECT_EQ(CreateStatelessResetTokenForTest(),
new_params.stateless_reset_token);
EXPECT_EQ(kMaxPacketSizeForTest, new_params.max_udp_payload_size.value());
EXPECT_EQ(kFakeInitialMaxData, new_params.initial_max_data.value());
EXPECT_EQ(kFakeInitialMaxStreamDataBidiLocal,
new_params.initial_max_stream_data_bidi_local.value());
EXPECT_EQ(kFakeInitialMaxStreamDataBidiRemote,
new_params.initial_max_stream_data_bidi_remote.value());
EXPECT_EQ(kFakeInitialMaxStreamDataUni,
new_params.initial_max_stream_data_uni.value());
EXPECT_EQ(kFakeInitialMaxStreamsBidi,
new_params.initial_max_streams_bidi.value());
EXPECT_EQ(kFakeInitialMaxStreamsUni,
new_params.initial_max_streams_uni.value());
EXPECT_EQ(kAckDelayExponentForTest, new_params.ack_delay_exponent.value());
EXPECT_EQ(kMaxAckDelayForTest, new_params.max_ack_delay.value());
EXPECT_EQ(kMinAckDelayUsForTest, new_params.min_ack_delay_us.value());
EXPECT_EQ(kFakeDisableMigration, new_params.disable_active_migration);
ASSERT_NE(nullptr, new_params.preferred_address.get());
EXPECT_EQ(CreateFakeV4SocketAddress(),
new_params.preferred_address->ipv4_socket_address);
EXPECT_EQ(CreateFakeV6SocketAddress(),
new_params.preferred_address->ipv6_socket_address);
EXPECT_EQ(CreateFakePreferredConnectionId(),
new_params.preferred_address->connection_id);
EXPECT_EQ(CreateFakePreferredStatelessResetToken(),
new_params.preferred_address->stateless_reset_token);
EXPECT_EQ(kActiveConnectionIdLimitForTest,
new_params.active_connection_id_limit.value());
ASSERT_TRUE(new_params.initial_source_connection_id.has_value());
EXPECT_EQ(CreateFakeInitialSourceConnectionId(),
new_params.initial_source_connection_id.value());
ASSERT_TRUE(new_params.retry_source_connection_id.has_value());
EXPECT_EQ(CreateFakeRetrySourceConnectionId(),
new_params.retry_source_connection_id.value());
ASSERT_TRUE(new_params.google_connection_options.has_value());
EXPECT_EQ(CreateFakeGoogleConnectionOptions(),
new_params.google_connection_options.value());
}
TEST_P(TransportParametersTest, ParseServerParametersRepeated) {
// clang-format off
const uint8_t kServerParamsRepeated[] = {
// original_destination_connection_id
0x00, // parameter id
0x08, // length
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x37,
// max_idle_timeout
0x01, // parameter id
0x02, // length
0x6e, 0xec, // value
// stateless_reset_token
0x02, // parameter id
0x10, // length
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
// max_idle_timeout (repeated)
0x01, // parameter id
0x02, // length
0x6e, 0xec, // value
};
// clang-format on
const uint8_t* server_params =
reinterpret_cast<const uint8_t*>(kServerParamsRepeated);
size_t server_params_length = ABSL_ARRAYSIZE(kServerParamsRepeated);
TransportParameters out_params;
std::string error_details;
EXPECT_FALSE(ParseTransportParameters(version_, Perspective::IS_SERVER,
server_params, server_params_length,
&out_params, &error_details));
EXPECT_EQ(error_details, "Received a second max_idle_timeout");
}
TEST_P(TransportParametersTest,
ParseServerParametersEmptyOriginalConnectionId) {
// clang-format off
const uint8_t kServerParamsEmptyOriginalConnectionId[] = {
// original_destination_connection_id
0x00, // parameter id
0x00, // length
// max_idle_timeout
0x01, // parameter id
0x02, // length
0x6e, 0xec, // value
// stateless_reset_token
0x02, // parameter id
0x10, // length
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
};
// clang-format on
const uint8_t* server_params =
reinterpret_cast<const uint8_t*>(kServerParamsEmptyOriginalConnectionId);
size_t server_params_length =
ABSL_ARRAYSIZE(kServerParamsEmptyOriginalConnectionId);
TransportParameters out_params;
std::string error_details;
ASSERT_TRUE(ParseTransportParameters(version_, Perspective::IS_SERVER,
server_params, server_params_length,
&out_params, &error_details))
<< error_details;
ASSERT_TRUE(out_params.original_destination_connection_id.has_value());
EXPECT_EQ(out_params.original_destination_connection_id.value(),
EmptyQuicConnectionId());
}
TEST_P(TransportParametersTest, VeryLongCustomParameter) {
// Ensure we can handle a 70KB custom parameter on both send and receive.
std::string custom_value(70000, '?');
TransportParameters orig_params;
orig_params.perspective = Perspective::IS_CLIENT;
orig_params.legacy_version_information =
CreateFakeLegacyVersionInformationClient();
orig_params.custom_parameters[kCustomParameter1] = custom_value;
std::vector<uint8_t> serialized;
ASSERT_TRUE(SerializeTransportParameters(orig_params, &serialized));
TransportParameters new_params;
std::string error_details;
ASSERT_TRUE(ParseTransportParameters(version_, Perspective::IS_CLIENT,
serialized.data(), serialized.size(),
&new_params, &error_details))
<< error_details;
EXPECT_TRUE(error_details.empty());
RemoveGreaseParameters(&new_params);
EXPECT_EQ(new_params, orig_params);
}
TEST_P(TransportParametersTest, SerializationOrderIsRandom) {
TransportParameters orig_params;
orig_params.perspective = Perspective::IS_CLIENT;
orig_params.legacy_version_information =
CreateFakeLegacyVersionInformationClient();
orig_params.max_idle_timeout_ms.set_value(kFakeIdleTimeoutMilliseconds);
orig_params.max_udp_payload_size.set_value(kMaxPacketSizeForTest);
orig_params.initial_max_data.set_value(kFakeInitialMaxData);
orig_params.initial_max_stream_data_bidi_local.set_value(
kFakeInitialMaxStreamDataBidiLocal);
orig_params.initial_max_stream_data_bidi_remote.set_value(
kFakeInitialMaxStreamDataBidiRemote);
orig_params.initial_max_stream_data_uni.set_value(
kFakeInitialMaxStreamDataUni);
orig_params.initial_max_streams_bidi.set_value(kFakeInitialMaxStreamsBidi);
orig_params.initial_max_streams_uni.set_value(kFakeInitialMaxStreamsUni);
orig_params.ack_delay_exponent.set_value(kAckDelayExponentForTest);
orig_params.max_ack_delay.set_value(kMaxAckDelayForTest);
orig_params.min_ack_delay_us.set_value(kMinAckDelayUsForTest);
orig_params.disable_active_migration = kFakeDisableMigration;
orig_params.active_connection_id_limit.set_value(
kActiveConnectionIdLimitForTest);
orig_params.initial_source_connection_id =
CreateFakeInitialSourceConnectionId();
orig_params.initial_round_trip_time_us.set_value(kFakeInitialRoundTripTime);
orig_params.google_connection_options = CreateFakeGoogleConnectionOptions();
orig_params.custom_parameters[kCustomParameter1] = kCustomParameter1Value;
orig_params.custom_parameters[kCustomParameter2] = kCustomParameter2Value;
std::vector<uint8_t> first_serialized;
ASSERT_TRUE(SerializeTransportParameters(orig_params, &first_serialized));
// Test that a subsequent serialization is different from the first.
// Run in a loop to avoid a failure in the unlikely event that randomization
// produces the same result multiple times.
for (int i = 0; i < 1000; i++) {
std::vector<uint8_t> serialized;
ASSERT_TRUE(SerializeTransportParameters(orig_params, &serialized));
if (serialized != first_serialized) {
return;
}
}
}
TEST_P(TransportParametersTest, Degrease) {
TransportParameters orig_params;
orig_params.perspective = Perspective::IS_CLIENT;
orig_params.legacy_version_information =
CreateFakeLegacyVersionInformationClient();
orig_params.version_information = CreateFakeVersionInformation();
orig_params.max_idle_timeout_ms.set_value(kFakeIdleTimeoutMilliseconds);
orig_params.max_udp_payload_size.set_value(kMaxPacketSizeForTest);
orig_params.initial_max_data.set_value(kFakeInitialMaxData);
orig_params.initial_max_stream_data_bidi_local.set_value(
kFakeInitialMaxStreamDataBidiLocal);
orig_params.initial_max_stream_data_bidi_remote.set_value(
kFakeInitialMaxStreamDataBidiRemote);
orig_params.initial_max_stream_data_uni.set_value(
kFakeInitialMaxStreamDataUni);
orig_params.initial_max_streams_bidi.set_value(kFakeInitialMaxStreamsBidi);
orig_params.initial_max_streams_uni.set_value(kFakeInitialMaxStreamsUni);
orig_params.ack_delay_exponent.set_value(kAckDelayExponentForTest);
orig_params.max_ack_delay.set_value(kMaxAckDelayForTest);
orig_params.min_ack_delay_us.set_value(kMinAckDelayUsForTest);
orig_params.disable_active_migration = kFakeDisableMigration;
orig_params.active_connection_id_limit.set_value(
kActiveConnectionIdLimitForTest);
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;
std::vector<uint8_t> serialized;
ASSERT_TRUE(SerializeTransportParameters(orig_params, &serialized));
TransportParameters new_params;
std::string error_details;
ASSERT_TRUE(ParseTransportParameters(version_, Perspective::IS_CLIENT,
serialized.data(), serialized.size(),
&new_params, &error_details))
<< error_details;
EXPECT_TRUE(error_details.empty());
// Deserialized parameters have grease added.
EXPECT_NE(new_params, orig_params);
DegreaseTransportParameters(new_params);
EXPECT_EQ(new_params, orig_params);
}
class TransportParametersTicketSerializationTest : public QuicTest {
protected:
void SetUp() override {
original_params_.perspective = Perspective::IS_SERVER;
original_params_.legacy_version_information =
CreateFakeLegacyVersionInformationServer();
original_params_.original_destination_connection_id =
CreateFakeOriginalDestinationConnectionId();
original_params_.max_idle_timeout_ms.set_value(
kFakeIdleTimeoutMilliseconds);
original_params_.stateless_reset_token = CreateStatelessResetTokenForTest();
original_params_.max_udp_payload_size.set_value(kMaxPacketSizeForTest);
original_params_.initial_max_data.set_value(kFakeInitialMaxData);
original_params_.initial_max_stream_data_bidi_local.set_value(
kFakeInitialMaxStreamDataBidiLocal);
original_params_.initial_max_stream_data_bidi_remote.set_value(
kFakeInitialMaxStreamDataBidiRemote);
original_params_.initial_max_stream_data_uni.set_value(
kFakeInitialMaxStreamDataUni);
original_params_.initial_max_streams_bidi.set_value(
kFakeInitialMaxStreamsBidi);
original_params_.initial_max_streams_uni.set_value(
kFakeInitialMaxStreamsUni);
original_params_.ack_delay_exponent.set_value(kAckDelayExponentForTest);
original_params_.max_ack_delay.set_value(kMaxAckDelayForTest);
original_params_.min_ack_delay_us.set_value(kMinAckDelayUsForTest);
original_params_.disable_active_migration = kFakeDisableMigration;
original_params_.preferred_address = CreateFakePreferredAddress();
original_params_.active_connection_id_limit.set_value(
kActiveConnectionIdLimitForTest);
original_params_.initial_source_connection_id =
CreateFakeInitialSourceConnectionId();
original_params_.retry_source_connection_id =
CreateFakeRetrySourceConnectionId();
original_params_.google_connection_options =
CreateFakeGoogleConnectionOptions();
ASSERT_TRUE(SerializeTransportParametersForTicket(
original_params_, application_state_, &original_serialized_params_));
}
TransportParameters original_params_;
std::vector<uint8_t> application_state_ = {0, 1};
std::vector<uint8_t> original_serialized_params_;
};
TEST_F(TransportParametersTicketSerializationTest,
StatelessResetTokenDoesntChangeOutput) {
// Test that changing the stateless reset token doesn't change the ticket
// serialization.
TransportParameters new_params = original_params_;
new_params.stateless_reset_token = CreateFakePreferredStatelessResetToken();
EXPECT_NE(new_params, original_params_);
std::vector<uint8_t> serialized;
ASSERT_TRUE(SerializeTransportParametersForTicket(
new_params, application_state_, &serialized));
EXPECT_EQ(original_serialized_params_, serialized);
}
TEST_F(TransportParametersTicketSerializationTest,
ConnectionIDDoesntChangeOutput) {
// Changing original destination CID doesn't change serialization.
TransportParameters new_params = original_params_;
new_params.original_destination_connection_id = TestConnectionId(0xCAFE);
EXPECT_NE(new_params, original_params_);
std::vector<uint8_t> serialized;
ASSERT_TRUE(SerializeTransportParametersForTicket(
new_params, application_state_, &serialized));
EXPECT_EQ(original_serialized_params_, serialized);
}
TEST_F(TransportParametersTicketSerializationTest, StreamLimitChangesOutput) {
// Changing a stream limit does change the serialization.
TransportParameters new_params = original_params_;
new_params.initial_max_stream_data_bidi_local.set_value(
kFakeInitialMaxStreamDataBidiLocal + 1);
EXPECT_NE(new_params, original_params_);
std::vector<uint8_t> serialized;
ASSERT_TRUE(SerializeTransportParametersForTicket(
new_params, application_state_, &serialized));
EXPECT_NE(original_serialized_params_, serialized);
}
TEST_F(TransportParametersTicketSerializationTest,
ApplicationStateChangesOutput) {
// Changing the application state changes the serialization.
std::vector<uint8_t> new_application_state = {0};
EXPECT_NE(new_application_state, application_state_);
std::vector<uint8_t> serialized;
ASSERT_TRUE(SerializeTransportParametersForTicket(
original_params_, new_application_state, &serialized));
EXPECT_NE(original_serialized_params_, serialized);
}
} // namespace test
} // namespace quic