$search
00001 // 00002 // openssl_init.hpp 00003 // ~~~~~~~~~~~~~~~~ 00004 // 00005 // Copyright (c) 2005 Voipster / Indrek dot Juhani at voipster dot com 00006 // Copyright (c) 2005-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) 00007 // 00008 // Distributed under the Boost Software License, Version 1.0. (See accompanying 00009 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 00010 // 00011 00012 #ifndef ASIO_SSL_DETAIL_OPENSSL_INIT_HPP 00013 #define ASIO_SSL_DETAIL_OPENSSL_INIT_HPP 00014 00015 #if defined(_MSC_VER) && (_MSC_VER >= 1200) 00016 # pragma once 00017 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) 00018 00019 #include "asio/detail/push_options.hpp" 00020 00021 #include "asio/detail/push_options.hpp" 00022 #include <vector> 00023 #include <boost/assert.hpp> 00024 #include <boost/config.hpp> 00025 #include <boost/shared_ptr.hpp> 00026 #include "asio/detail/pop_options.hpp" 00027 00028 #include "asio/detail/mutex.hpp" 00029 #include "asio/detail/tss_ptr.hpp" 00030 #include "asio/ssl/detail/openssl_types.hpp" 00031 00032 namespace asio { 00033 namespace ssl { 00034 namespace detail { 00035 00036 template <bool Do_Init = true> 00037 class openssl_init 00038 : private boost::noncopyable 00039 { 00040 private: 00041 // Structure to perform the actual initialisation. 00042 class do_init 00043 { 00044 public: 00045 do_init() 00046 { 00047 if (Do_Init) 00048 { 00049 ::SSL_library_init(); 00050 ::SSL_load_error_strings(); 00051 ::OpenSSL_add_ssl_algorithms(); 00052 00053 mutexes_.resize(::CRYPTO_num_locks()); 00054 for (size_t i = 0; i < mutexes_.size(); ++i) 00055 mutexes_[i].reset(new asio::detail::mutex); 00056 ::CRYPTO_set_locking_callback(&do_init::openssl_locking_func); 00057 ::CRYPTO_set_id_callback(&do_init::openssl_id_func); 00058 } 00059 } 00060 00061 ~do_init() 00062 { 00063 if (Do_Init) 00064 { 00065 ::CRYPTO_set_id_callback(0); 00066 ::CRYPTO_set_locking_callback(0); 00067 ::ERR_free_strings(); 00068 ::ERR_remove_state(0); 00069 ::EVP_cleanup(); 00070 ::CRYPTO_cleanup_all_ex_data(); 00071 ::CONF_modules_unload(1); 00072 ::ENGINE_cleanup(); 00073 } 00074 } 00075 00076 // Helper function to manage a do_init singleton. The static instance of the 00077 // openssl_init object ensures that this function is always called before 00078 // main, and therefore before any other threads can get started. The do_init 00079 // instance must be static in this function to ensure that it gets 00080 // initialised before any other global objects try to use it. 00081 static boost::shared_ptr<do_init> instance() 00082 { 00083 static boost::shared_ptr<do_init> init(new do_init); 00084 return init; 00085 } 00086 00087 private: 00088 static unsigned long openssl_id_func() 00089 { 00090 #if defined(BOOST_WINDOWS) || defined(__CYGWIN__) 00091 return ::GetCurrentThreadId(); 00092 #else // defined(BOOST_WINDOWS) || defined(__CYGWIN__) 00093 void* id = instance()->thread_id_; 00094 if (id == 0) 00095 instance()->thread_id_ = id = &id; // Ugh. 00096 BOOST_ASSERT(sizeof(unsigned long) >= sizeof(void*)); 00097 return reinterpret_cast<unsigned long>(id); 00098 #endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__) 00099 } 00100 00101 static void openssl_locking_func(int mode, int n, 00102 const char *file, int line) 00103 { 00104 if (mode & CRYPTO_LOCK) 00105 instance()->mutexes_[n]->lock(); 00106 else 00107 instance()->mutexes_[n]->unlock(); 00108 } 00109 00110 // Mutexes to be used in locking callbacks. 00111 std::vector<boost::shared_ptr<asio::detail::mutex> > mutexes_; 00112 00113 #if !defined(BOOST_WINDOWS) && !defined(__CYGWIN__) 00114 // The thread identifiers to be used by openssl. 00115 asio::detail::tss_ptr<void> thread_id_; 00116 #endif // !defined(BOOST_WINDOWS) && !defined(__CYGWIN__) 00117 }; 00118 00119 public: 00120 // Constructor. 00121 openssl_init() 00122 : ref_(do_init::instance()) 00123 { 00124 while (&instance_ == 0); // Ensure openssl_init::instance_ is linked in. 00125 } 00126 00127 // Destructor. 00128 ~openssl_init() 00129 { 00130 } 00131 00132 private: 00133 // Instance to force initialisation of openssl at global scope. 00134 static openssl_init instance_; 00135 00136 // Reference to singleton do_init object to ensure that openssl does not get 00137 // cleaned up until the last user has finished with it. 00138 boost::shared_ptr<do_init> ref_; 00139 }; 00140 00141 template <bool Do_Init> 00142 openssl_init<Do_Init> openssl_init<Do_Init>::instance_; 00143 00144 } // namespace detail 00145 } // namespace ssl 00146 } // namespace asio 00147 00148 #include "asio/detail/pop_options.hpp" 00149 00150 #endif // ASIO_SSL_DETAIL_OPENSSL_INIT_HPP