Introduce draft-28 transport parameters
This CL adds the new transport parameters to TransportParameters.
They will be used in a subsequent CL.
Add unused code
PiperOrigin-RevId: 313678124
Change-Id: Ic04c88f8e3a7275316f67abfd8207d9d1efe15ee
diff --git a/quic/core/crypto/transport_parameters.cc b/quic/core/crypto/transport_parameters.cc
index 45b284b..12c0d0d 100644
--- a/quic/core/crypto/transport_parameters.cc
+++ b/quic/core/crypto/transport_parameters.cc
@@ -46,6 +46,8 @@
kDisableActiveMigration = 0xc,
kPreferredAddress = 0xd,
kActiveConnectionIdLimit = 0xe,
+ kInitialSourceConnectionId = 0xf,
+ kRetrySourceConnectionId = 0x10,
kMaxDatagramFrameSize = 0x20,
@@ -104,6 +106,10 @@
return "preferred_address";
case TransportParameters::kActiveConnectionIdLimit:
return "active_connection_id_limit";
+ case TransportParameters::kInitialSourceConnectionId:
+ return "initial_source_connection_id";
+ case TransportParameters::kRetrySourceConnectionId:
+ return "retry_source_connection_id";
case TransportParameters::kMaxDatagramFrameSize:
return "max_datagram_frame_size";
case TransportParameters::kInitialRoundTripTime:
@@ -138,6 +144,8 @@
case TransportParameters::kDisableActiveMigration:
case TransportParameters::kPreferredAddress:
case TransportParameters::kActiveConnectionIdLimit:
+ case TransportParameters::kInitialSourceConnectionId:
+ case TransportParameters::kRetrySourceConnectionId:
case TransportParameters::kMaxDatagramFrameSize:
case TransportParameters::kInitialRoundTripTime:
case TransportParameters::kGoogleConnectionOptions:
@@ -429,6 +437,14 @@
preferred_address->ToString();
}
rv += active_connection_id_limit.ToString(/*for_use_in_list=*/true);
+ if (initial_source_connection_id.has_value()) {
+ rv += " " + TransportParameterIdToString(kInitialSourceConnectionId) + " " +
+ initial_source_connection_id.value().ToString();
+ }
+ if (retry_source_connection_id.has_value()) {
+ rv += " " + TransportParameterIdToString(kRetrySourceConnectionId) + " " +
+ retry_source_connection_id.value().ToString();
+ }
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()) {
@@ -522,6 +538,8 @@
max_ack_delay(other.max_ack_delay),
disable_active_migration(other.disable_active_migration),
active_connection_id_limit(other.active_connection_id_limit),
+ initial_source_connection_id(other.initial_source_connection_id),
+ 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_connection_options(other.google_connection_options),
@@ -561,6 +579,8 @@
disable_active_migration == rhs.disable_active_migration &&
active_connection_id_limit.value() ==
rhs.active_connection_id_limit.value() &&
+ initial_source_connection_id == rhs.initial_source_connection_id &&
+ retry_source_connection_id == rhs.retry_source_connection_id &&
max_datagram_frame_size.value() ==
rhs.max_datagram_frame_size.value() &&
initial_round_trip_time_us.value() ==
@@ -602,7 +622,7 @@
}
if (perspective == Perspective::IS_CLIENT &&
original_destination_connection_id.has_value()) {
- *error_details = "Client cannot send original connection ID";
+ *error_details = "Client cannot send original_destination_connection_id";
return false;
}
if (!stateless_reset_token.empty() &&
@@ -629,6 +649,11 @@
*error_details = "Internal preferred address family failure";
return false;
}
+ if (perspective == Perspective::IS_CLIENT &&
+ retry_source_connection_id.has_value()) {
+ *error_details = "Client cannot send retry_source_connection_id";
+ return false;
+ }
for (const auto& kv : custom_parameters) {
if (TransportParameterIdIsKnown(kv.first)) {
*error_details = quiche::QuicheStrCat(
@@ -715,6 +740,8 @@
kTypeAndValueLength + // disable_active_migration
kPreferredAddressParameterLength + // preferred_address
kIntegerParameterLength + // active_connection_id_limit
+ kConnectionIdParameterLength + // initial_source_connection_id
+ kConnectionIdParameterLength + // retry_source_connection_id
kIntegerParameterLength + // max_datagram_frame_size
kIntegerParameterLength + // initial_round_trip_time_us
kTypeAndValueLength + // google_connection_options
@@ -868,6 +895,42 @@
}
}
+ // initial_source_connection_id
+ if (in.initial_source_connection_id.has_value()) {
+ QuicConnectionId initial_source_connection_id =
+ in.initial_source_connection_id.value();
+ if (!WriteTransportParameterId(
+ &writer, TransportParameters::kInitialSourceConnectionId,
+ version) ||
+ !WriteTransportParameterStringPiece(
+ &writer,
+ quiche::QuicheStringPiece(initial_source_connection_id.data(),
+ initial_source_connection_id.length()),
+ version)) {
+ QUIC_BUG << "Failed to write initial_source_connection_id "
+ << initial_source_connection_id << " for " << in;
+ return false;
+ }
+ }
+
+ // retry_source_connection_id
+ if (in.retry_source_connection_id.has_value()) {
+ DCHECK_EQ(Perspective::IS_SERVER, in.perspective);
+ QuicConnectionId retry_source_connection_id =
+ in.retry_source_connection_id.value();
+ if (!WriteTransportParameterId(
+ &writer, TransportParameters::kRetrySourceConnectionId, version) ||
+ !WriteTransportParameterStringPiece(
+ &writer,
+ quiche::QuicheStringPiece(retry_source_connection_id.data(),
+ retry_source_connection_id.length()),
+ version)) {
+ QUIC_BUG << "Failed to write retry_source_connection_id "
+ << retry_source_connection_id << " for " << in;
+ return false;
+ }
+ }
+
// Google-specific connection options.
if (in.google_connection_options.has_value()) {
static_assert(sizeof(in.google_connection_options.value().front()) == 4,
@@ -1193,6 +1256,48 @@
parse_success =
out->active_connection_id_limit.Read(&value_reader, error_details);
break;
+ case TransportParameters::kInitialSourceConnectionId: {
+ if (out->initial_source_connection_id.has_value()) {
+ *error_details = "Received a second initial_source_connection_id";
+ return false;
+ }
+ const size_t connection_id_length = value_reader.BytesRemaining();
+ if (!QuicUtils::IsConnectionIdLengthValidForVersion(
+ connection_id_length, version.transport_version)) {
+ *error_details = quiche::QuicheStrCat(
+ "Received initial_source_connection_id of invalid length ",
+ connection_id_length);
+ return false;
+ }
+ QuicConnectionId initial_source_connection_id;
+ if (!value_reader.ReadConnectionId(&initial_source_connection_id,
+ connection_id_length)) {
+ *error_details = "Failed to read initial_source_connection_id";
+ return false;
+ }
+ out->initial_source_connection_id = initial_source_connection_id;
+ } break;
+ case TransportParameters::kRetrySourceConnectionId: {
+ if (out->retry_source_connection_id.has_value()) {
+ *error_details = "Received a second retry_source_connection_id";
+ return false;
+ }
+ const size_t connection_id_length = value_reader.BytesRemaining();
+ if (!QuicUtils::IsConnectionIdLengthValidForVersion(
+ connection_id_length, version.transport_version)) {
+ *error_details = quiche::QuicheStrCat(
+ "Received retry_source_connection_id of invalid length ",
+ connection_id_length);
+ return false;
+ }
+ QuicConnectionId retry_source_connection_id;
+ if (!value_reader.ReadConnectionId(&retry_source_connection_id,
+ connection_id_length)) {
+ *error_details = "Failed to read retry_source_connection_id";
+ return false;
+ }
+ out->retry_source_connection_id = retry_source_connection_id;
+ } break;
case TransportParameters::kMaxDatagramFrameSize:
parse_success =
out->max_datagram_frame_size.Read(&value_reader, error_details);
diff --git a/quic/core/crypto/transport_parameters.h b/quic/core/crypto/transport_parameters.h
index 1d91db3..80c905c 100644
--- a/quic/core/crypto/transport_parameters.h
+++ b/quic/core/crypto/transport_parameters.h
@@ -180,6 +180,14 @@
// to store.
IntegerParameter active_connection_id_limit;
+ // The value that the endpoint included in the Source Connection ID field of
+ // the first Initial packet it sent.
+ quiche::QuicheOptional<QuicConnectionId> initial_source_connection_id;
+
+ // The value that the server included in the Source Connection ID field of a
+ // Retry packet it sent.
+ quiche::QuicheOptional<QuicConnectionId> retry_source_connection_id;
+
// Indicates support for the DATAGRAM frame and the maximum frame size that
// the sender accepts. See draft-ietf-quic-datagram.
IntegerParameter max_datagram_frame_size;
diff --git a/quic/core/crypto/transport_parameters_test.cc b/quic/core/crypto/transport_parameters_test.cc
index 628c19f..a3fc084 100644
--- a/quic/core/crypto/transport_parameters_test.cc
+++ b/quic/core/crypto/transport_parameters_test.cc
@@ -56,6 +56,14 @@
return TestConnectionId(0x1337);
}
+QuicConnectionId CreateFakeInitialSourceConnectionId() {
+ return TestConnectionId(0x2345);
+}
+
+QuicConnectionId CreateFakeRetrySourceConnectionId() {
+ return TestConnectionId(0x9876);
+}
+
QuicConnectionId CreateFakePreferredConnectionId() {
return TestConnectionId(0xBEEF);
}
@@ -222,6 +230,23 @@
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 = QuicheNullOpt;
+ 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) {
@@ -250,6 +275,9 @@
orig_params.preferred_address = CreateFakePreferredAddress();
orig_params.active_connection_id_limit.set_value(
kFakeActiveConnectionIdLimit);
+ 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_connection_options = CreateFakeGoogleConnectionOptions();
orig_params.user_agent_id = CreateFakeUserAgentId();
@@ -280,6 +308,8 @@
orig_params.disable_active_migration = kFakeDisableMigration;
orig_params.active_connection_id_limit.set_value(
kFakeActiveConnectionIdLimit);
+ 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.user_agent_id = CreateFakeUserAgentId();
@@ -326,6 +356,9 @@
orig_params.preferred_address = CreateFakePreferredAddress();
orig_params.active_connection_id_limit.set_value(
kFakeActiveConnectionIdLimit);
+ 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;
@@ -454,7 +487,7 @@
TEST_P(TransportParametersTest, ParseClientParams) {
// clang-format off
const uint8_t kClientParamsOld[] = {
- 0x00, 0x6a, // length of the parameters array that follows
+ 0x00, 0x76, // length of the parameters array that follows
// max_idle_timeout
0x00, 0x01, // parameter id
0x00, 0x02, // length
@@ -502,6 +535,10 @@
0x00, 0x0e, // parameter id
0x00, 0x01, // length
0x34, // value
+ // initial_source_connection_id
+ 0x00, 0x0f, // parameter id
+ 0x00, 0x08, // length
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x23, 0x45,
// initial_round_trip_time_us
0x31, 0x27, // parameter id
0x00, 0x01, // length
@@ -569,6 +606,10 @@
0x0e, // parameter id
0x01, // length
0x34, // value
+ // initial_source_connection_id
+ 0x0f, // parameter id
+ 0x08, // length
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x23, 0x45,
// initial_round_trip_time_us
0x71, 0x27, // parameter id
0x01, // length
@@ -627,6 +668,10 @@
EXPECT_EQ(kFakeDisableMigration, new_params.disable_active_migration);
EXPECT_EQ(kFakeActiveConnectionIdLimit,
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());
@@ -801,7 +846,7 @@
TEST_P(TransportParametersTest, ParseServerParams) {
// clang-format off
const uint8_t kServerParamsOld[] = {
- 0x00, 0xb7, // length of parameters array that follows
+ 0x00, 0xcf, // length of parameters array that follows
// original_destination_connection_id
0x00, 0x00, // parameter id
0x00, 0x08, // length
@@ -870,6 +915,14 @@
0x00, 0x0e, // parameter id
0x00, 0x01, // length
0x34, // value
+ // initial_source_connection_id
+ 0x00, 0x0f, // parameter id
+ 0x00, 0x08, // length
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x23, 0x45,
+ // retry_source_connection_id
+ 0x00, 0x10, // parameter id
+ 0x00, 0x08, // length
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x98, 0x76,
// google_connection_options
0x31, 0x28, // parameter id
0x00, 0x0c, // length
@@ -953,6 +1006,14 @@
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
@@ -1019,6 +1080,12 @@
new_params.preferred_address->stateless_reset_token);
EXPECT_EQ(kFakeActiveConnectionIdLimit,
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());