| Index: net/cert/x509_util_openssl.cc
|
| diff --git a/net/cert/x509_util_openssl.cc b/net/cert/x509_util_openssl.cc
|
| index 2327deddcf29cde90ab173a4e2a4da0a3d74d5d0..ded70c0ffda92883d1ea4ba83da12bf2ba924227 100644
|
| --- a/net/cert/x509_util_openssl.cc
|
| +++ b/net/cert/x509_util_openssl.cc
|
| @@ -11,6 +11,7 @@
|
|
|
| #include <algorithm>
|
| #include <memory>
|
| +#include <map>
|
|
|
| #include "base/lazy_instance.h"
|
| #include "base/logging.h"
|
| @@ -28,6 +29,14 @@
|
| #include "net/cert/x509_util.h"
|
| #include "net/ssl/scoped_openssl_types.h"
|
|
|
| +#if defined(OS_ANDROID)
|
| +#include <android/log.h>
|
| +#define PRINTF(format, arguments...) \
|
| + __android_log_print(ANDROID_LOG_WARN, "PRINTF", format, ##arguments)
|
| +#else
|
| +#define PRINTF printf
|
| +#endif
|
| +
|
| namespace net {
|
|
|
| namespace {
|
| @@ -172,8 +181,76 @@ bool SignAndDerEncodeCert(X509* cert,
|
| return DerEncodeCert(cert, der_encoded);
|
| }
|
|
|
| +struct {
|
| + pthread_mutex_t lock;
|
| + size_t hits;
|
| + size_t misses;
|
| + size_t count;
|
| + size_t total_size;
|
| + size_t total_unique_size;
|
| + std::map<std::string, size_t>* uniques;
|
| +} g_der_cache_stats = {PTHREAD_MUTEX_INITIALIZER};
|
| +
|
| +enum DERCacheAction {
|
| + DER_HIT,
|
| + DER_MISS,
|
| + DER_REMOVE
|
| +};
|
| +
|
| +void UpdateDERCacheStats(DERCacheAction action, const std::string* data) {
|
| + auto& stats = g_der_cache_stats;
|
| + pthread_mutex_lock(&stats.lock);
|
| + switch (action) {
|
| + case DER_HIT: {
|
| + stats.hits++;
|
| + break;
|
| + }
|
| + case DER_MISS: {
|
| + stats.misses++;
|
| + stats.count++;
|
| + stats.total_size += data->capacity();
|
| + if (!stats.uniques) {
|
| + stats.uniques = new std::map<std::string, size_t>();
|
| + }
|
| + auto insert_result = stats.uniques->emplace(*data, 0);
|
| + auto unique_iter = insert_result.first;
|
| + bool inserted = insert_result.second;
|
| + if (inserted) {
|
| + stats.total_unique_size += unique_iter->first.capacity();
|
| + }
|
| + unique_iter->second++;
|
| + break;
|
| + }
|
| + case DER_REMOVE: {
|
| + stats.count -= 1;
|
| + stats.total_size -= data->capacity();
|
| + auto unique_iter = stats.uniques->find(*data);
|
| + CHECK(unique_iter != stats.uniques->end());
|
| + unique_iter->second--;
|
| + if (unique_iter->second == 0) {
|
| + stats.total_unique_size -= unique_iter->first.capacity();
|
| + stats.uniques->erase(unique_iter);
|
| + }
|
| + break;
|
| + }
|
| + }
|
| + if (action != DER_HIT) {
|
| + PRINTF("DERCache: %zu KiB @ %zu instances (%zu KiB @ %zu unique), "
|
| + "hit rate: %.1f%% (%zu/%zu)\n",
|
| + stats.total_size / 1024, stats.count,
|
| + stats.total_unique_size / 1024, stats.uniques->size(),
|
| + stats.hits * 100.0 / (stats.hits + stats.misses),
|
| + stats.hits, stats.misses);
|
| + }
|
| + pthread_mutex_unlock(&stats.lock);
|
| +}
|
| +
|
| struct DERCache {
|
| std::string data;
|
| +
|
| + ~DERCache() {
|
| + UpdateDERCacheStats(DER_REMOVE, &data);
|
| + }
|
| };
|
|
|
| void DERCache_free(void* parent, void* ptr, CRYPTO_EX_DATA* ad, int idx,
|
| @@ -301,8 +378,11 @@ bool GetDER(X509* x509, base::StringPiece* der_cache) {
|
| std::unique_ptr<DERCache> new_cache(new DERCache);
|
| if (!DerEncodeCert(x509, &new_cache->data))
|
| return false;
|
| + UpdateDERCacheStats(DER_MISS, &new_cache->data);
|
| internal_cache = new_cache.get();
|
| X509_set_ex_data(x509, x509_der_cache_index, new_cache.release());
|
| + } else {
|
| + UpdateDERCacheStats(DER_HIT, nullptr);
|
| }
|
| *der_cache = base::StringPiece(internal_cache->data);
|
| return true;
|
|
|