| // Copyright (c) 2022 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. | 
 |  | 
 | #ifndef QUICHE_QUIC_LOAD_BALANCER_LOAD_BALANCER_SERVER_ID_H_ | 
 | #define QUICHE_QUIC_LOAD_BALANCER_LOAD_BALANCER_SERVER_ID_H_ | 
 |  | 
 | #include <array> | 
 | #include <cstdint> | 
 | #include <string> | 
 |  | 
 | #include "absl/strings/string_view.h" | 
 | #include "absl/types/span.h" | 
 | #include "quiche/quic/platform/api/quic_export.h" | 
 |  | 
 | namespace quic { | 
 |  | 
 | // The maximum number of bytes in a LoadBalancerServerId. | 
 | inline constexpr uint8_t kLoadBalancerMaxServerIdLen = 15; | 
 | // Regardless of key length, the AES block size is always 16 Bytes. | 
 | inline constexpr uint8_t kLoadBalancerBlockSize = 16; | 
 | static_assert(kLoadBalancerMaxServerIdLen <= kLoadBalancerBlockSize, | 
 |               "LoadBalancerServerId array not large enough to hold Server ID"); | 
 |  | 
 | // LoadBalancerServerId is the globally understood identifier for a given pool | 
 | // member. It is unique to any given QUIC-LB configuration. See | 
 | // draft-ietf-quic-load-balancers. | 
 | // Note: this has nothing to do with QuicServerID. It's an unfortunate collision | 
 | // between an internal term for the destination identifiers for a particular | 
 | // deployment (QuicServerID) and the object of a load balancing decision | 
 | // (LoadBalancerServerId). | 
 | class QUIC_EXPORT_PRIVATE LoadBalancerServerId { | 
 |  public: | 
 |   // Creates an empty/invalid server id. | 
 |   LoadBalancerServerId() : length_(0) {} | 
 |  | 
 |   // Copies all the bytes from |data| into a new LoadBalancerServerId. | 
 |   explicit LoadBalancerServerId(absl::Span<const uint8_t> data); | 
 |   explicit LoadBalancerServerId(absl::string_view data); | 
 |  | 
 |   // Server IDs are opaque bytes, but defining these operators allows us to sort | 
 |   // them into a tree and define ranges. | 
 |   bool operator<(const LoadBalancerServerId& other) const { | 
 |     return data() < other.data(); | 
 |   } | 
 |   bool operator==(const LoadBalancerServerId& other) const { | 
 |     return data() == other.data(); | 
 |   } | 
 |  | 
 |   // Hash function to allow use as a key in unordered maps. | 
 |   template <typename H> | 
 |   friend H AbslHashValue(H h, const LoadBalancerServerId& server_id) { | 
 |     return H::combine_contiguous(std::move(h), server_id.data().data(), | 
 |                                  server_id.length()); | 
 |   } | 
 |  | 
 |   absl::Span<const uint8_t> data() const { | 
 |     return absl::MakeConstSpan(data_.data(), length_); | 
 |   } | 
 |   uint8_t* mutable_data() { return data_.data(); } | 
 |  | 
 |   uint8_t length() const { return length_; } | 
 |   void set_length(uint8_t length); | 
 |  | 
 |   // Returns the server ID in hex format. | 
 |   std::string ToString() const; | 
 |  | 
 |   // Returns true if this is a valid server id. | 
 |   bool IsValid() { return length_ != 0; } | 
 |  | 
 |  private: | 
 |   // Make the array large enough to hold an entire decrypt result, to save a | 
 |   // copy from the decrypt result into LoadBalancerServerId. | 
 |   std::array<uint8_t, kLoadBalancerBlockSize> data_; | 
 |   uint8_t length_; | 
 | }; | 
 |  | 
 | }  // namespace quic | 
 |  | 
 | #endif  // QUICHE_QUIC_LOAD_BALANCER_LOAD_BALANCER_SERVER_ID_H_ |