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/shared_ptr.hpp>
00024 #include "asio/detail/pop_options.hpp"
00025
00026 #include "asio/detail/mutex.hpp"
00027 #include "asio/ssl/detail/openssl_types.hpp"
00028
00029 namespace asio {
00030 namespace ssl {
00031 namespace detail {
00032
00033 template <bool Do_Init = true>
00034 class openssl_init
00035 : private boost::noncopyable
00036 {
00037 private:
00038
00039 class do_init
00040 {
00041 public:
00042 do_init()
00043 {
00044 if (Do_Init)
00045 {
00046 ::SSL_library_init();
00047 ::SSL_load_error_strings();
00048 ::OpenSSL_add_ssl_algorithms();
00049
00050 mutexes_.resize(::CRYPTO_num_locks());
00051 for (size_t i = 0; i < mutexes_.size(); ++i)
00052 mutexes_[i].reset(new asio::detail::mutex);
00053 ::CRYPTO_set_locking_callback(&do_init::openssl_locking_func);
00054 }
00055 }
00056
00057 ~do_init()
00058 {
00059 if (Do_Init)
00060 {
00061 ::CRYPTO_set_locking_callback(0);
00062 ::ERR_free_strings();
00063 ::ERR_remove_state(0);
00064 ::EVP_cleanup();
00065 ::CRYPTO_cleanup_all_ex_data();
00066 ::CONF_modules_unload(1);
00067 ::ENGINE_cleanup();
00068 }
00069 }
00070
00071
00072
00073
00074
00075
00076 static boost::shared_ptr<do_init> instance()
00077 {
00078 static boost::shared_ptr<do_init> init(new do_init);
00079 return init;
00080 }
00081
00082 private:
00083 static void openssl_locking_func(int mode, int n,
00084 const char *file, int line)
00085 {
00086 if (mode & CRYPTO_LOCK)
00087 instance()->mutexes_[n]->lock();
00088 else
00089 instance()->mutexes_[n]->unlock();
00090 }
00091
00092
00093 std::vector<boost::shared_ptr<asio::detail::mutex> > mutexes_;
00094 };
00095
00096 public:
00097
00098 openssl_init()
00099 : ref_(do_init::instance())
00100 {
00101 while (&instance_ == 0);
00102 }
00103
00104
00105 ~openssl_init()
00106 {
00107 }
00108
00109 private:
00110
00111 static openssl_init instance_;
00112
00113
00114
00115 boost::shared_ptr<do_init> ref_;
00116 };
00117
00118 template <bool Do_Init>
00119 openssl_init<Do_Init> openssl_init<Do_Init>::instance_;
00120
00121 }
00122 }
00123 }
00124
00125 #include "asio/detail/pop_options.hpp"
00126
00127 #endif // ASIO_SSL_DETAIL_OPENSSL_INIT_HPP