| Index: net/socket/ssl_session_cache_openssl.cc
|
| diff --git a/net/socket/ssl_session_cache_openssl.cc b/net/socket/ssl_session_cache_openssl.cc
|
| index d16bb8d6325ec6b105da7219d4e9ea9e5f6f4828..d4605b44cbd4a69f7bd930cceab094760dd15043 100644
|
| --- a/net/socket/ssl_session_cache_openssl.cc
|
| +++ b/net/socket/ssl_session_cache_openssl.cc
|
| @@ -10,6 +10,7 @@
|
| #include <openssl/rand.h>
|
| #include <openssl/ssl.h>
|
|
|
| +#include "base/callback.h"
|
| #include "base/containers/hash_tables.h"
|
| #include "base/lazy_instance.h"
|
| #include "base/logging.h"
|
| @@ -236,6 +237,45 @@ class SSLSessionCacheOpenSSLImpl {
|
| return SSL_set_session(ssl, session) == 1;
|
| }
|
|
|
| + bool SSLSessionIsInCache(const std::string& cache_key) const {
|
| + SSL_SESSION* session = *it->second;
|
| + DCHECK(session);
|
| + DVLOG(2) << "Lookup session: " << session << " for " << cache_key;
|
| +
|
| + void* session_is_good =
|
| + SSL_SESSION_get_ex_data(session, GetSSLSessionExIndex());
|
| +
|
| + if (!session_is_good)
|
| + return false; // Session has not yet been marked good. Treat as a miss.
|
| +
|
| + base::AutoLock locked(lock_);
|
| + KeyIndex::const_iterator it = key_index_.find(cache_key);
|
| + return it != key_index_.end();
|
| + }
|
| +
|
| + void SetSessionAddedCallback(SSL* ssl, const base::Closure& callback) {
|
| + // Add this SSL* to the SSLtoCallbackMap.
|
| + ssl_to_callback_map_[ssl] = CallbackAndCompletionCount(callback, 0);
|
| + }
|
| +
|
| + // Determines if the session for |ssl| is in the cache, and calls the
|
| + // appropriate callback if that is the case.
|
| + void CheckIfSessionAdded(SSL* ssl) {
|
| + SSLToCallbackMap::iterator it = ssl_to_callback_map_.find(ssl);
|
| + if (it == ssl_to_callback_map_.end())
|
| + return;
|
| + // Increment the session's completion count.
|
| + if (++it->second.count == 2) {
|
| + // The session has been MarkedAsGood and Added, so it can be used.
|
| + // These two events can occur in either order.
|
| + base::Closure callback = it->second.callback;
|
| + ssl_to_callback_map_.erase(it);
|
| + callback.Run();
|
| + }
|
| + }
|
| +
|
| + void RemoveSessionAddedCallback(SSL* ssl) { ssl_to_callback_map_.erase(ssl); }
|
| +
|
| void MarkSSLSessionAsGood(SSL* ssl) {
|
| SSL_SESSION* session = SSL_get_session(ssl);
|
| if (!session)
|
| @@ -244,6 +284,8 @@ class SSLSessionCacheOpenSSLImpl {
|
| // Mark the session as good, allowing it to be used for future connections.
|
| SSL_SESSION_set_ex_data(
|
| session, GetSSLSessionExIndex(), reinterpret_cast<void*>(1));
|
| +
|
| + CheckIfSessionAdded(ssl);
|
| }
|
|
|
| // Flush all entries from the cache.
|
| @@ -259,12 +301,29 @@ class SSLSessionCacheOpenSSLImpl {
|
| }
|
|
|
| private:
|
| + // CallbackAndCompletionCounts are used to group callback a callback
|
| + // that should be run when a certian sesssion is added to the session
|
| + // cache with an integer indicating the status of that session.
|
| + struct CallbackAndCompletionCount {
|
| + CallbackAndCompletionCount(base::Closure completion_callback,
|
| + int completion_count)
|
| + : callback(completion_callback), count(completion_count) {}
|
| +
|
| + const base::Closure callback;
|
| + // |count| < 2 means that the ssl session associated with this object
|
| + // has not been added to the session cache. |count| == 2 means that the
|
| + // session has been added to the cache and is ready for use.
|
| + int count;
|
| + };
|
| +
|
| // Type for list of SSL_SESSION handles, ordered in MRU order.
|
| typedef std::list<SSL_SESSION*> MRUSessionList;
|
| // Type for a dictionary from unique cache keys to session list nodes.
|
| typedef base::hash_map<std::string, MRUSessionList::iterator> KeyIndex;
|
| // Type for a dictionary from SessionId values to key index nodes.
|
| typedef base::hash_map<SessionId, KeyIndex::iterator> SessionIdIndex;
|
| + // Type for a map from SSL* to associated callbacks
|
| + typedef std::map<SSL*, CallbackAndCompletionCount> SSLToCallbackMap;
|
|
|
| // Return the key associated with a given session, or the empty string if
|
| // none exist. This shall only be used for debugging.
|
| @@ -342,7 +401,9 @@ class SSLSessionCacheOpenSSLImpl {
|
| // to indicate that it took ownership of the session, i.e. that the caller
|
| // should not decrement its reference count after completion.
|
| static int NewSessionCallbackStatic(SSL* ssl, SSL_SESSION* session) {
|
| - GetCache(ssl->ctx)->OnSessionAdded(ssl, session);
|
| + SSLSessionCacheOpenSSLImpl* cache = GetCache(ssl->ctx);
|
| + cache->OnSessionAdded(ssl, session);
|
| + cache->CheckIfSessionAdded(ssl);
|
| return 1;
|
| }
|
|
|
| @@ -466,10 +527,11 @@ class SSLSessionCacheOpenSSLImpl {
|
|
|
| SSL_CTX* ctx_;
|
| SSLSessionCacheOpenSSL::Config config_;
|
| + SSLToCallbackMap ssl_to_callback_map_;
|
|
|
| // method to get the index which can later be used with SSL_CTX_get_ex_data()
|
| // or SSL_CTX_set_ex_data().
|
| - base::Lock lock_; // Protects access to containers below.
|
| + mutable base::Lock lock_; // Protects access to containers below.
|
|
|
| MRUSessionList ordering_;
|
| KeyIndex key_index_;
|
| @@ -499,6 +561,20 @@ bool SSLSessionCacheOpenSSL::SetSSLSessionWithKey(
|
| return impl_->SetSSLSessionWithKey(ssl, cache_key);
|
| }
|
|
|
| +bool SSLSessionCacheOpenSSL::SSLSessionIsInCache(
|
| + const std::string& cache_key) const {
|
| + return impl_->SSLSessionIsInCache(cache_key);
|
| +}
|
| +
|
| +void SSLSessionCacheOpenSSL::RemoveSessionAddedCallback(SSL* ssl) {
|
| + impl_->RemoveSessionAddedCallback(ssl);
|
| +}
|
| +
|
| +void SSLSessionCacheOpenSSL::SetSessionAddedCallback(SSL* ssl,
|
| + const base::Closure& cb) {
|
| + impl_->SetSessionAddedCallback(ssl, cb);
|
| +}
|
| +
|
| void SSLSessionCacheOpenSSL::MarkSSLSessionAsGood(SSL* ssl) {
|
| return impl_->MarkSSLSessionAsGood(ssl);
|
| }
|
|
|