Miscellaneous changes to quic/load_balancer:
- Add LoadBalancerDecoder::GetConfig to return the LoadBalancerConfig for a config_id.
- Add LoadBalancerDecoder::GetConfigId(uint8_t connection_id_first_byte) to get the config id from the first byte of the connection ID.
- Add LoadBalancerServerId::Create(absl::string_view data) to create a LoadBalancerServerId from a string_view.
PiperOrigin-RevId: 505150431
diff --git a/quiche/quic/load_balancer/load_balancer_decoder.cc b/quiche/quic/load_balancer/load_balancer_decoder.cc
index a946b36..cdff314 100644
--- a/quiche/quic/load_balancer/load_balancer_decoder.cc
+++ b/quiche/quic/load_balancer/load_balancer_decoder.cc
@@ -75,8 +75,12 @@
if (connection_id.IsEmpty()) {
return absl::optional<uint8_t>();
}
- const uint8_t first_byte = connection_id.data()[0];
- uint8_t codepoint = (first_byte >> 6);
+ return GetConfigId(*reinterpret_cast<const uint8_t*>(connection_id.data()));
+}
+
+absl::optional<uint8_t> LoadBalancerDecoder::GetConfigId(
+ const uint8_t connection_id_first_byte) {
+ uint8_t codepoint = (connection_id_first_byte >> 6);
if (codepoint < kNumLoadBalancerConfigs) {
return codepoint;
}
diff --git a/quiche/quic/load_balancer/load_balancer_decoder.h b/quiche/quic/load_balancer/load_balancer_decoder.h
index 2c326cb..f5ba6f3 100644
--- a/quiche/quic/load_balancer/load_balancer_decoder.h
+++ b/quiche/quic/load_balancer/load_balancer_decoder.h
@@ -20,7 +20,17 @@
// Remove support for a config. Does nothing if there is no config for
// |config_id|. Does nothing and creates a bug if |config_id| is greater than
// 2.
- void DeleteConfig(const uint8_t config_id);
+ void DeleteConfig(uint8_t config_id);
+
+ // Return the config for |config_id|, or nullptr if not found.
+ const LoadBalancerConfig* GetConfig(const uint8_t config_id) const {
+ if (config_id >= kNumLoadBalancerConfigs ||
+ !config_[config_id].has_value()) {
+ return nullptr;
+ }
+
+ return &config_[config_id].value();
+ }
// Extract a server ID from |connection_id|. If there is no config for the
// codepoint, |connection_id| is too short, or there's a decrypt error,
@@ -30,10 +40,15 @@
const QuicConnectionId& connection_id) const;
// Returns the config ID stored in the first two bits of |connection_id|, or
- // empty if |connection_id| is empty.
+ // empty if |connection_id| is empty, or the first two bits of the first byte
+ // of |connection_id| are 0b11.
static absl::optional<uint8_t> GetConfigId(
const QuicConnectionId& connection_id);
+ // Returns the config ID stored in the first two bits of
+ // |connection_id_first_byte|, or empty if the first two bits are 0b11.
+ static absl::optional<uint8_t> GetConfigId(uint8_t connection_id_first_byte);
+
private:
// Decoders can support up to 3 configs at once.
absl::optional<LoadBalancerConfig> config_[kNumLoadBalancerConfigs];
diff --git a/quiche/quic/load_balancer/load_balancer_decoder_test.cc b/quiche/quic/load_balancer/load_balancer_decoder_test.cc
index 728467f..b2bdfd3 100644
--- a/quiche/quic/load_balancer/load_balancer_decoder_test.cc
+++ b/quiche/quic/load_balancer/load_balancer_decoder_test.cc
@@ -208,8 +208,10 @@
EXPECT_FALSE(
LoadBalancerDecoder::GetConfigId(QuicConnectionId()).has_value());
for (uint8_t i = 0; i < 3; i++) {
- auto config_id = LoadBalancerDecoder::GetConfigId(
- QuicConnectionId({static_cast<unsigned char>(i << 6)}));
+ const QuicConnectionId connection_id({static_cast<unsigned char>(i << 6)});
+ auto config_id = LoadBalancerDecoder::GetConfigId(connection_id);
+ EXPECT_EQ(config_id,
+ LoadBalancerDecoder::GetConfigId(connection_id.data()[0]));
EXPECT_TRUE(config_id.has_value());
EXPECT_EQ(*config_id, i);
}
@@ -217,6 +219,22 @@
LoadBalancerDecoder::GetConfigId(QuicConnectionId({0xc0})).has_value());
}
+TEST_F(LoadBalancerDecoderTest, GetConfig) {
+ LoadBalancerDecoder decoder;
+ decoder.AddConfig(*LoadBalancerConfig::CreateUnencrypted(2, 3, 4));
+
+ EXPECT_EQ(decoder.GetConfig(0), nullptr);
+ EXPECT_EQ(decoder.GetConfig(1), nullptr);
+ EXPECT_EQ(decoder.GetConfig(3), nullptr);
+ EXPECT_EQ(decoder.GetConfig(4), nullptr);
+
+ const LoadBalancerConfig* config = decoder.GetConfig(2);
+ ASSERT_NE(config, nullptr);
+ EXPECT_EQ(config->server_id_len(), 3);
+ EXPECT_EQ(config->nonce_len(), 4);
+ EXPECT_FALSE(config->IsEncrypted());
+}
+
} // namespace
} // namespace test
diff --git a/quiche/quic/load_balancer/load_balancer_server_id.h b/quiche/quic/load_balancer/load_balancer_server_id.h
index 18fc40e..cdd3c95 100644
--- a/quiche/quic/load_balancer/load_balancer_server_id.h
+++ b/quiche/quic/load_balancer/load_balancer_server_id.h
@@ -26,7 +26,13 @@
public:
// Copies all the bytes from |data| into a new LoadBalancerServerId.
static absl::optional<LoadBalancerServerId> Create(
- const absl::Span<const uint8_t> data);
+ absl::Span<const uint8_t> data);
+
+ // For callers with a string_view at hand.
+ static absl::optional<LoadBalancerServerId> Create(absl::string_view data) {
+ return Create(absl::MakeSpan(reinterpret_cast<const uint8_t*>(data.data()),
+ data.length()));
+ }
// Server IDs are opaque bytes, but defining these operators allows us to sort
// them into a tree and define ranges.