OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 // |
| 5 // OpenSSL multi-threading initialization |
| 6 |
| 7 #include "chrome/browser/sync/engine/net/openssl_init.h" |
| 8 |
| 9 #include <openssl/crypto.h> |
| 10 |
| 11 #include "base/logging.h" |
| 12 #include "chrome/browser/sync/util/compat-pthread.h" |
| 13 #include "chrome/browser/sync/util/pthread_helpers.h" |
| 14 |
| 15 // OpenSSL requires multithreading callbacks to be initialized prior to using |
| 16 // the library so that it can manage thread locking as necessary. |
| 17 |
| 18 // Dynamic lock type |
| 19 // |
| 20 // This needs to be a struct and in global scope because OpenSSL relies on some |
| 21 // macro magic. |
| 22 struct CRYPTO_dynlock_value { |
| 23 PThreadMutex mutex; |
| 24 void Lock() { |
| 25 mutex.Lock(); |
| 26 } |
| 27 void Unlock() { |
| 28 mutex.Unlock(); |
| 29 } |
| 30 }; |
| 31 |
| 32 namespace { |
| 33 |
| 34 // This array stores all of the mutexes available to OpenSSL |
| 35 PThreadMutex* mutex_buf = NULL; |
| 36 |
| 37 // OpenSSL mutex handling callback functions |
| 38 |
| 39 // OpenSSL Callback - Locks/unlocks the specified mutex held by OpenSSL. |
| 40 void OpenSslMutexLockControl(int mode, int n, const char* file, int line) { |
| 41 if (mode & CRYPTO_LOCK) { |
| 42 mutex_buf[n].Lock(); |
| 43 } else { |
| 44 mutex_buf[n].Unlock(); |
| 45 } |
| 46 } |
| 47 |
| 48 // OpenSSL Callback - Returns the thread ID |
| 49 unsigned long OpenSslGetThreadID(void) { |
| 50 return GetCurrentThreadId(); |
| 51 } |
| 52 |
| 53 // Dynamic locking functions |
| 54 |
| 55 // Allocate a new lock |
| 56 struct CRYPTO_dynlock_value* dyn_create_function(const char* file, int line) { |
| 57 return new CRYPTO_dynlock_value; |
| 58 } |
| 59 |
| 60 void dyn_lock_function(int mode, struct CRYPTO_dynlock_value* lock, |
| 61 const char* file, int line) { |
| 62 if (mode & CRYPTO_LOCK) { |
| 63 lock->Lock(); |
| 64 } else { |
| 65 lock->Unlock(); |
| 66 } |
| 67 } |
| 68 |
| 69 void dyn_destroy_function(struct CRYPTO_dynlock_value* lock, |
| 70 const char* file, int line) { |
| 71 delete lock; |
| 72 } |
| 73 |
| 74 } // namespace |
| 75 |
| 76 // We want to log the version of the OpenSSL library being used, in particular |
| 77 // for the case where it's dynamically linked. We want the version from the |
| 78 // library, not from the header files. It seems the OpenSSL folks haven't |
| 79 // bothered with an accessor for this, so we just pluck it out. |
| 80 #ifdef OS_WINDOWS |
| 81 // TODO(sync): Figure out how to get the SSL version string on Windows. |
| 82 const char* SSL_version_str = "UNKNOWN"; |
| 83 #else |
| 84 extern const char* SSL_version_str; |
| 85 #endif |
| 86 |
| 87 namespace browser_sync { |
| 88 |
| 89 // Initializes the OpenSSL multithreading callbacks. This isn't thread-safe, |
| 90 // but it is called early enough that it doesn't matter. |
| 91 void InitOpenSslMultithreading() { |
| 92 LOG(INFO) << "Using OpenSSL headers version " << OPENSSL_VERSION_TEXT |
| 93 << ", lib version " << SSL_version_str; |
| 94 |
| 95 if (mutex_buf) |
| 96 return; |
| 97 |
| 98 mutex_buf = new PThreadMutex[CRYPTO_num_locks()]; |
| 99 CHECK(NULL != mutex_buf); |
| 100 |
| 101 // OpenSSL has only one single global set of callbacks, so this |
| 102 // initialization must be done only once, even though the OpenSSL lib may be |
| 103 // used by multiple modules (jingle jabber connections and P2P tunnels). |
| 104 CRYPTO_set_id_callback(OpenSslGetThreadID); |
| 105 CRYPTO_set_locking_callback(OpenSslMutexLockControl); |
| 106 |
| 107 CRYPTO_set_dynlock_create_callback(dyn_create_function); |
| 108 CRYPTO_set_dynlock_lock_callback(dyn_lock_function); |
| 109 CRYPTO_set_dynlock_destroy_callback(dyn_destroy_function); |
| 110 } |
| 111 |
| 112 // Cleans up the OpenSSL multithreading callbacks. |
| 113 void CleanupOpenSslMultithreading() { |
| 114 if (!mutex_buf) { |
| 115 return; |
| 116 } |
| 117 |
| 118 CRYPTO_set_dynlock_create_callback(NULL); |
| 119 CRYPTO_set_dynlock_lock_callback(NULL); |
| 120 CRYPTO_set_dynlock_destroy_callback(NULL); |
| 121 |
| 122 CRYPTO_set_id_callback(NULL); |
| 123 CRYPTO_set_locking_callback(NULL); |
| 124 |
| 125 delete [] mutex_buf; |
| 126 mutex_buf = NULL; |
| 127 } |
| 128 |
| 129 } // namespace browser_sync |
OLD | NEW |