summaryrefslogtreecommitdiffstats
path: root/net/ssl/ssl_client_session_cache_openssl.cc
blob: 0ff7d3be564c82ffdc358d625fa03716f94bfffb (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
// Copyright 2015 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/ssl/ssl_client_session_cache_openssl.h"

#include <utility>

#include "base/time/clock.h"
#include "base/time/default_clock.h"

namespace net {

SSLClientSessionCacheOpenSSL::SSLClientSessionCacheOpenSSL(const Config& config)
    : clock_(new base::DefaultClock),
      config_(config),
      cache_(config.max_entries),
      lookups_since_flush_(0) {
}

SSLClientSessionCacheOpenSSL::~SSLClientSessionCacheOpenSSL() {
  Flush();
}

size_t SSLClientSessionCacheOpenSSL::size() const {
  return cache_.size();
}

ScopedSSL_SESSION SSLClientSessionCacheOpenSSL::Lookup(
    const std::string& cache_key) {
  base::AutoLock lock(lock_);

  // Expire stale sessions.
  lookups_since_flush_++;
  if (lookups_since_flush_ >= config_.expiration_check_count) {
    lookups_since_flush_ = 0;
    FlushExpiredSessions();
  }

  CacheEntryMap::iterator iter = cache_.Get(cache_key);
  if (iter == cache_.end())
    return nullptr;
  if (IsExpired(iter->second, clock_->Now())) {
    cache_.Erase(iter);
    return nullptr;
  }
  return ScopedSSL_SESSION(SSL_SESSION_up_ref(iter->second->session.get()));
}

void SSLClientSessionCacheOpenSSL::Insert(const std::string& cache_key,
                                          SSL_SESSION* session) {
  base::AutoLock lock(lock_);

  // Make a new entry.
  CacheEntry* entry = new CacheEntry;
  entry->session.reset(SSL_SESSION_up_ref(session));
  entry->creation_time = clock_->Now();

  // Takes ownership.
  cache_.Put(cache_key, entry);
}

void SSLClientSessionCacheOpenSSL::Flush() {
  base::AutoLock lock(lock_);

  cache_.Clear();
}

void SSLClientSessionCacheOpenSSL::SetClockForTesting(
    scoped_ptr<base::Clock> clock) {
  clock_ = clock.Pass();
}

SSLClientSessionCacheOpenSSL::CacheEntry::CacheEntry() {
}

SSLClientSessionCacheOpenSSL::CacheEntry::~CacheEntry() {
}

bool SSLClientSessionCacheOpenSSL::IsExpired(
    SSLClientSessionCacheOpenSSL::CacheEntry* entry,
    const base::Time& now) {
  return now < entry->creation_time ||
         entry->creation_time + config_.timeout < now;
}

void SSLClientSessionCacheOpenSSL::FlushExpiredSessions() {
  base::Time now = clock_->Now();
  CacheEntryMap::iterator iter = cache_.begin();
  while (iter != cache_.end()) {
    if (IsExpired(iter->second, now)) {
      iter = cache_.Erase(iter);
    } else {
      ++iter;
    }
  }
}

}  // namespace net