Project import generated by Copybara.

PiperOrigin-RevId: 237361882
Change-Id: I109a68f44db867b20f8c6a7732b0ce657133e52a
diff --git a/quic/core/crypto/quic_compressed_certs_cache.cc b/quic/core/crypto/quic_compressed_certs_cache.cc
new file mode 100644
index 0000000..595ac31
--- /dev/null
+++ b/quic/core/crypto/quic_compressed_certs_cache.cc
@@ -0,0 +1,128 @@
+// Copyright 2016 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 "net/third_party/quiche/src/quic/core/crypto/quic_compressed_certs_cache.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_string.h"
+
+namespace quic {
+
+namespace {
+
+// Inline helper function for extending a 64-bit |seed| in-place with a 64-bit
+// |value|. Based on Boost's hash_combine function.
+inline void hash_combine(uint64_t* seed, const uint64_t& val) {
+  (*seed) ^= val + 0x9e3779b9 + ((*seed) << 6) + ((*seed) >> 2);
+}
+
+}  // namespace
+
+const size_t QuicCompressedCertsCache::kQuicCompressedCertsCacheSize = 225;
+
+QuicCompressedCertsCache::UncompressedCerts::UncompressedCerts()
+    : chain(nullptr),
+      client_common_set_hashes(nullptr),
+      client_cached_cert_hashes(nullptr) {}
+
+QuicCompressedCertsCache::UncompressedCerts::UncompressedCerts(
+    const QuicReferenceCountedPointer<ProofSource::Chain>& chain,
+    const QuicString* client_common_set_hashes,
+    const QuicString* client_cached_cert_hashes)
+    : chain(chain),
+      client_common_set_hashes(client_common_set_hashes),
+      client_cached_cert_hashes(client_cached_cert_hashes) {}
+
+QuicCompressedCertsCache::UncompressedCerts::~UncompressedCerts() {}
+
+QuicCompressedCertsCache::CachedCerts::CachedCerts() {}
+
+QuicCompressedCertsCache::CachedCerts::CachedCerts(
+    const UncompressedCerts& uncompressed_certs,
+    const QuicString& compressed_cert)
+    : chain_(uncompressed_certs.chain),
+      client_common_set_hashes_(*uncompressed_certs.client_common_set_hashes),
+      client_cached_cert_hashes_(*uncompressed_certs.client_cached_cert_hashes),
+      compressed_cert_(compressed_cert) {}
+
+QuicCompressedCertsCache::CachedCerts::CachedCerts(const CachedCerts& other) =
+    default;
+
+QuicCompressedCertsCache::CachedCerts::~CachedCerts() {}
+
+bool QuicCompressedCertsCache::CachedCerts::MatchesUncompressedCerts(
+    const UncompressedCerts& uncompressed_certs) const {
+  return (client_common_set_hashes_ ==
+              *uncompressed_certs.client_common_set_hashes &&
+          client_cached_cert_hashes_ ==
+              *uncompressed_certs.client_cached_cert_hashes &&
+          chain_ == uncompressed_certs.chain);
+}
+
+const QuicString* QuicCompressedCertsCache::CachedCerts::compressed_cert()
+    const {
+  return &compressed_cert_;
+}
+
+QuicCompressedCertsCache::QuicCompressedCertsCache(int64_t max_num_certs)
+    : certs_cache_(max_num_certs) {}
+
+QuicCompressedCertsCache::~QuicCompressedCertsCache() {
+  // Underlying cache must be cleared before destruction.
+  certs_cache_.Clear();
+}
+
+const QuicString* QuicCompressedCertsCache::GetCompressedCert(
+    const QuicReferenceCountedPointer<ProofSource::Chain>& chain,
+    const QuicString& client_common_set_hashes,
+    const QuicString& client_cached_cert_hashes) {
+  UncompressedCerts uncompressed_certs(chain, &client_common_set_hashes,
+                                       &client_cached_cert_hashes);
+
+  uint64_t key = ComputeUncompressedCertsHash(uncompressed_certs);
+
+  CachedCerts* cached_value = certs_cache_.Lookup(key);
+  if (cached_value != nullptr &&
+      cached_value->MatchesUncompressedCerts(uncompressed_certs)) {
+    return cached_value->compressed_cert();
+  }
+  return nullptr;
+}
+
+void QuicCompressedCertsCache::Insert(
+    const QuicReferenceCountedPointer<ProofSource::Chain>& chain,
+    const QuicString& client_common_set_hashes,
+    const QuicString& client_cached_cert_hashes,
+    const QuicString& compressed_cert) {
+  UncompressedCerts uncompressed_certs(chain, &client_common_set_hashes,
+                                       &client_cached_cert_hashes);
+
+  uint64_t key = ComputeUncompressedCertsHash(uncompressed_certs);
+
+  // Insert one unit to the cache.
+  std::unique_ptr<CachedCerts> cached_certs(
+      new CachedCerts(uncompressed_certs, compressed_cert));
+  certs_cache_.Insert(key, std::move(cached_certs));
+}
+
+size_t QuicCompressedCertsCache::MaxSize() {
+  return certs_cache_.MaxSize();
+}
+
+size_t QuicCompressedCertsCache::Size() {
+  return certs_cache_.Size();
+}
+
+uint64_t QuicCompressedCertsCache::ComputeUncompressedCertsHash(
+    const UncompressedCerts& uncompressed_certs) {
+  uint64_t hash =
+      std::hash<QuicString>()(*uncompressed_certs.client_common_set_hashes);
+  uint64_t h =
+      std::hash<QuicString>()(*uncompressed_certs.client_cached_cert_hashes);
+  hash_combine(&hash, h);
+
+  hash_combine(&hash,
+               reinterpret_cast<uint64_t>(uncompressed_certs.chain.get()));
+  return hash;
+}
+
+}  // namespace quic