Index: base/openssl_util.cc |
diff --git a/base/openssl_util.cc b/base/openssl_util.cc |
index 82da86836c2ac08e21071fea26b7f9702553a6a7..894c710ad830496a53c19cbf5c5f077a74d30154 100644 |
--- a/base/openssl_util.cc |
+++ b/base/openssl_util.cc |
@@ -5,11 +5,68 @@ |
#include "base/openssl_util.h" |
#include <openssl/err.h> |
+#include <openssl/ssl.h> |
+#include "base/lock.h" |
#include "base/logging.h" |
+#include "base/scoped_vector.h" |
+#include "base/singleton.h" |
namespace base { |
+namespace { |
+ |
+unsigned long CurrentThreadId() { |
+ return static_cast<unsigned long>(PlatformThread::CurrentId()); |
+} |
+ |
+// Singleton for initializing and cleaning up the OpenSSL library. |
+class OpenSSLInitSingleton { |
+ private: |
+ friend struct DefaultSingletonTraits<OpenSSLInitSingleton>; |
+ OpenSSLInitSingleton() { |
+ SSL_load_error_strings(); |
+ SSL_library_init(); |
+ OpenSSL_add_all_algorithms(); |
+ int num_locks = CRYPTO_num_locks(); |
+ locks_.reserve(num_locks); |
+ for (int i = 0; i < num_locks; ++i) |
+ locks_.push_back(new Lock()); |
+ CRYPTO_set_locking_callback(LockingCallback); |
+ CRYPTO_set_id_callback(CurrentThreadId); |
+ } |
+ |
+ ~OpenSSLInitSingleton() { |
+ CRYPTO_set_locking_callback(NULL); |
+ EVP_cleanup(); |
+ ERR_free_strings(); |
+ } |
+ |
+ static void LockingCallback(int mode, int n, const char* file, int line) { |
+ Singleton<OpenSSLInitSingleton>::get()->OnLockingCallback(mode, n, file, |
+ line); |
+ } |
+ |
+ void OnLockingCallback(int mode, int n, const char* file, int line) { |
+ CHECK_LT(static_cast<size_t>(n), locks_.size()); |
+ if (mode & CRYPTO_LOCK) |
+ locks_[n]->Acquire(); |
+ else |
+ locks_[n]->Release(); |
+ } |
+ |
+ // These locks are used and managed by OpenSSL via LockingCallback(). |
+ ScopedVector<Lock> locks_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(OpenSSLInitSingleton); |
+}; |
+ |
+} // namespace |
+ |
+void EnsureOpenSSLInit() { |
+ (void)Singleton<OpenSSLInitSingleton>::get(); |
+} |
+ |
void ClearOpenSSLERRStack() { |
if (logging::DEBUG_MODE && VLOG_IS_ON(1)) { |
int error_num = ERR_get_error(); |