openssl_init.hpp
Go to the documentation of this file.
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
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines


Castor
Author(s): Carpe Noctem
autogenerated on Fri Nov 8 2013 11:05:39