Save large connection IDs on the heap
The IETF will soon increase the maximum size of connection IDs, this change allows us to scale that by placing large ones on the heap.
gfe-relnote: change representation of connection IDs, protected by quic_use_allocated_connection_ids
PiperOrigin-RevId: 252524833
Change-Id: Ia98aee46adebbe6f5f3df2a4c0062a54a22e2d0d
diff --git a/quic/core/quic_connection_id.cc b/quic/core/quic_connection_id.cc
index 4022283..e1487e3 100644
--- a/quic/core/quic_connection_id.cc
+++ b/quic/core/quic_connection_id.cc
@@ -19,27 +19,70 @@
namespace quic {
-QuicConnectionId::QuicConnectionId() : length_(0) {}
+QuicConnectionId::QuicConnectionId() : QuicConnectionId(nullptr, 0) {}
QuicConnectionId::QuicConnectionId(const char* data, uint8_t length) {
+ static_assert(
+ kQuicMaxConnectionIdLength <= std::numeric_limits<uint8_t>::max(),
+ "kQuicMaxConnectionIdLength too high");
if (length > kQuicMaxConnectionIdLength) {
QUIC_BUG << "Attempted to create connection ID of length " << length;
length = kQuicMaxConnectionIdLength;
}
length_ = length;
- if (length_ > 0) {
+ if (length_ == 0) {
+ return;
+ }
+ if (!GetQuicRestartFlag(quic_use_allocated_connection_ids)) {
memcpy(data_, data, length_);
+ return;
+ }
+ if (length_ <= sizeof(data_short_)) {
+ memcpy(data_short_, data, length_);
+ return;
+ }
+ data_long_ = reinterpret_cast<char*>(malloc(length_));
+ CHECK_NE(nullptr, data_long_);
+ memcpy(data_long_, data, length_);
+}
+
+QuicConnectionId::~QuicConnectionId() {
+ if (!GetQuicRestartFlag(quic_use_allocated_connection_ids)) {
+ return;
+ }
+ if (length_ > sizeof(data_short_)) {
+ free(data_long_);
+ data_long_ = nullptr;
}
}
-QuicConnectionId::~QuicConnectionId() {}
+QuicConnectionId::QuicConnectionId(const QuicConnectionId& other)
+ : QuicConnectionId(other.data(), other.length()) {}
+
+QuicConnectionId& QuicConnectionId::operator=(const QuicConnectionId& other) {
+ set_length(other.length());
+ memcpy(mutable_data(), other.data(), length_);
+ return *this;
+}
const char* QuicConnectionId::data() const {
- return data_;
+ if (!GetQuicRestartFlag(quic_use_allocated_connection_ids)) {
+ return data_;
+ }
+ if (length_ <= sizeof(data_short_)) {
+ return data_short_;
+ }
+ return data_long_;
}
char* QuicConnectionId::mutable_data() {
- return data_;
+ if (!GetQuicRestartFlag(quic_use_allocated_connection_ids)) {
+ return data_;
+ }
+ if (length_ <= sizeof(data_short_)) {
+ return data_short_;
+ }
+ return data_long_;
}
uint8_t QuicConnectionId::length() const {
@@ -47,6 +90,30 @@
}
void QuicConnectionId::set_length(uint8_t length) {
+ if (GetQuicRestartFlag(quic_use_allocated_connection_ids)) {
+ char temporary_data[sizeof(data_short_)];
+ if (length > sizeof(data_short_)) {
+ if (length_ <= sizeof(data_short_)) {
+ // Copy data from data_short_ to data_long_.
+ memcpy(temporary_data, data_short_, length_);
+ data_long_ = reinterpret_cast<char*>(malloc(length));
+ CHECK_NE(nullptr, data_long_);
+ memcpy(data_long_, temporary_data, length_);
+ } else {
+ // Resize data_long_.
+ char* realloc_result =
+ reinterpret_cast<char*>(realloc(data_long_, length));
+ CHECK_NE(nullptr, realloc_result);
+ data_long_ = realloc_result;
+ }
+ } else if (length_ > sizeof(data_short_)) {
+ // Copy data from data_long_ to data_short_.
+ memcpy(temporary_data, data_long_, length);
+ free(data_long_);
+ data_long_ = nullptr;
+ memcpy(data_short_, temporary_data, length);
+ }
+ }
length_ = length;
}
@@ -56,8 +123,9 @@
size_t QuicConnectionId::Hash() const {
uint64_t data_bytes[3] = {0, 0, 0};
- static_assert(sizeof(data_bytes) >= sizeof(data_), "sizeof(data_) changed");
- memcpy(data_bytes, data_, length_);
+ static_assert(sizeof(data_bytes) >= kQuicMaxConnectionIdLength,
+ "kQuicMaxConnectionIdLength changed");
+ memcpy(data_bytes, data(), length_);
// This Hash function is designed to return the same value as the host byte
// order representation when the connection ID length is 64 bits.
return QuicEndian::NetToHost64(kQuicDefaultConnectionIdLength ^ length_ ^
@@ -68,7 +136,7 @@
if (IsEmpty()) {
return std::string("0");
}
- return QuicTextUtils::HexEncode(data_, length_);
+ return QuicTextUtils::HexEncode(data(), length_);
}
std::ostream& operator<<(std::ostream& os, const QuicConnectionId& v) {
@@ -77,7 +145,7 @@
}
bool QuicConnectionId::operator==(const QuicConnectionId& v) const {
- return length_ == v.length_ && memcmp(data_, v.data_, length_) == 0;
+ return length_ == v.length_ && memcmp(data(), v.data(), length_) == 0;
}
bool QuicConnectionId::operator!=(const QuicConnectionId& v) const {
@@ -91,7 +159,7 @@
if (length_ > v.length_) {
return false;
}
- return memcmp(data_, v.data_, length_) < 0;
+ return memcmp(data(), v.data(), length_) < 0;
}
QuicConnectionId EmptyQuicConnectionId() {