123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157 |
- //
- // openssl_init.hpp
- // ~~~~~~~~~~~~~~~~
- //
- // Copyright (c) 2005 Voipster / Indrek dot Juhani at voipster dot com
- // Copyright (c) 2005-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
- //
- // Distributed under the Boost Software License, Version 1.0. (See accompanying
- // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
- //
- #ifndef BOOST_ASIO_SSL_DETAIL_OPENSSL_INIT_HPP
- #define BOOST_ASIO_SSL_DETAIL_OPENSSL_INIT_HPP
- #if defined(_MSC_VER) && (_MSC_VER >= 1200)
- # pragma once
- #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
- #include <boost/asio/detail/push_options.hpp>
- #include <boost/asio/detail/push_options.hpp>
- #include <cstring>
- #include <vector>
- #include <boost/assert.hpp>
- #include <boost/config.hpp>
- #include <boost/shared_ptr.hpp>
- #include <boost/asio/detail/pop_options.hpp>
- #include <boost/asio/detail/mutex.hpp>
- #include <boost/asio/detail/tss_ptr.hpp>
- #include <boost/asio/ssl/detail/openssl_types.hpp>
- namespace boost {
- namespace asio {
- namespace ssl {
- namespace detail {
- template <bool Do_Init = true>
- class openssl_init
- : private boost::noncopyable
- {
- private:
- // Structure to perform the actual initialisation.
- class do_init
- {
- public:
- do_init()
- {
- if (Do_Init)
- {
- ::SSL_library_init();
- ::SSL_load_error_strings();
- ::OpenSSL_add_ssl_algorithms();
- mutexes_.resize(::CRYPTO_num_locks());
- for (size_t i = 0; i < mutexes_.size(); ++i)
- mutexes_[i].reset(new boost::asio::detail::mutex);
- ::CRYPTO_set_locking_callback(&do_init::openssl_locking_func);
- ::CRYPTO_set_id_callback(&do_init::openssl_id_func);
- }
- }
- ~do_init()
- {
- if (Do_Init)
- {
- ::CRYPTO_set_id_callback(0);
- ::CRYPTO_set_locking_callback(0);
- ::ERR_free_strings();
- ::ERR_remove_state(0);
- ::EVP_cleanup();
- ::CRYPTO_cleanup_all_ex_data();
- ::CONF_modules_unload(1);
- ::ENGINE_cleanup();
- }
- }
- // Helper function to manage a do_init singleton. The static instance of the
- // openssl_init object ensures that this function is always called before
- // main, and therefore before any other threads can get started. The do_init
- // instance must be static in this function to ensure that it gets
- // initialised before any other global objects try to use it.
- static boost::shared_ptr<do_init> instance()
- {
- static boost::shared_ptr<do_init> init(new do_init);
- return init;
- }
- private:
- static unsigned long openssl_id_func()
- {
- #if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
- return ::GetCurrentThreadId();
- #else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
- void* id = instance()->thread_id_;
- if (id == 0)
- instance()->thread_id_ = id = &id; // Ugh.
- BOOST_ASSERT(sizeof(unsigned long) >= sizeof(void*));
- return reinterpret_cast<unsigned long>(id);
- #endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
- }
- static void openssl_locking_func(int mode, int n,
- const char* /*file*/, int /*line*/)
- {
- if (mode & CRYPTO_LOCK)
- instance()->mutexes_[n]->lock();
- else
- instance()->mutexes_[n]->unlock();
- }
- // Mutexes to be used in locking callbacks.
- std::vector<boost::shared_ptr<boost::asio::detail::mutex> > mutexes_;
- #if !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
- // The thread identifiers to be used by openssl.
- boost::asio::detail::tss_ptr<void> thread_id_;
- #endif // !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
- };
- public:
- // Constructor.
- openssl_init()
- : ref_(do_init::instance())
- {
- using namespace std; // For memmove.
- // Ensure openssl_init::instance_ is linked in.
- openssl_init* tmp = &instance_;
- memmove(&tmp, &tmp, sizeof(openssl_init*));
- }
- // Destructor.
- ~openssl_init()
- {
- }
- private:
- // Instance to force initialisation of openssl at global scope.
- static openssl_init instance_;
- // Reference to singleton do_init object to ensure that openssl does not get
- // cleaned up until the last user has finished with it.
- boost::shared_ptr<do_init> ref_;
- };
- template <bool Do_Init>
- openssl_init<Do_Init> openssl_init<Do_Init>::instance_;
- } // namespace detail
- } // namespace ssl
- } // namespace asio
- } // namespace boost
- #include <boost/asio/detail/pop_options.hpp>
- #endif // BOOST_ASIO_SSL_DETAIL_OPENSSL_INIT_HPP
|