Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
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
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
00077
00078
00079
00080
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;
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
00111 std::vector<boost::shared_ptr<asio::detail::mutex> > mutexes_;
00112
00113 #if !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
00114
00115 asio::detail::tss_ptr<void> thread_id_;
00116 #endif // !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
00117 };
00118
00119 public:
00120
00121 openssl_init()
00122 : ref_(do_init::instance())
00123 {
00124 while (&instance_ == 0);
00125 }
00126
00127
00128 ~openssl_init()
00129 {
00130 }
00131
00132 private:
00133
00134 static openssl_init instance_;
00135
00136
00137
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 }
00145 }
00146 }
00147
00148 #include "asio/detail/pop_options.hpp"
00149
00150 #endif // ASIO_SSL_DETAIL_OPENSSL_INIT_HPP