diff options
Diffstat (limited to 'boost/asio/ssl/detail')
-rw-r--r-- | boost/asio/ssl/detail/engine.hpp | 162 | ||||
-rw-r--r-- | boost/asio/ssl/detail/handshake_op.hpp | 70 | ||||
-rw-r--r-- | boost/asio/ssl/detail/impl/engine.ipp | 306 | ||||
-rw-r--r-- | boost/asio/ssl/detail/impl/openssl_init.ipp | 109 | ||||
-rw-r--r-- | boost/asio/ssl/detail/io.hpp | 336 | ||||
-rw-r--r-- | boost/asio/ssl/detail/openssl_init.hpp | 88 | ||||
-rw-r--r-- | boost/asio/ssl/detail/openssl_types.hpp | 26 | ||||
-rw-r--r-- | boost/asio/ssl/detail/password_callback.hpp | 74 | ||||
-rw-r--r-- | boost/asio/ssl/detail/read_op.hpp | 75 | ||||
-rw-r--r-- | boost/asio/ssl/detail/shutdown_op.hpp | 62 | ||||
-rw-r--r-- | boost/asio/ssl/detail/stream_core.hpp | 92 | ||||
-rw-r--r-- | boost/asio/ssl/detail/verify_callback.hpp | 70 | ||||
-rw-r--r-- | boost/asio/ssl/detail/write_op.hpp | 75 |
13 files changed, 1545 insertions, 0 deletions
diff --git a/boost/asio/ssl/detail/engine.hpp b/boost/asio/ssl/detail/engine.hpp new file mode 100644 index 0000000000..41c4ee7426 --- /dev/null +++ b/boost/asio/ssl/detail/engine.hpp @@ -0,0 +1,162 @@ +// +// ssl/detail/engine.hpp +// ~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2012 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_ENGINE_HPP +#define BOOST_ASIO_SSL_DETAIL_ENGINE_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include <boost/asio/detail/config.hpp> + +#if !defined(BOOST_ASIO_ENABLE_OLD_SSL) +# include <boost/asio/buffer.hpp> +# include <boost/asio/detail/static_mutex.hpp> +# include <boost/asio/ssl/detail/openssl_types.hpp> +# include <boost/asio/ssl/detail/verify_callback.hpp> +# include <boost/asio/ssl/stream_base.hpp> +# include <boost/asio/ssl/verify_mode.hpp> +#endif // !defined(BOOST_ASIO_ENABLE_OLD_SSL) + +#include <boost/asio/detail/push_options.hpp> + +namespace boost { +namespace asio { +namespace ssl { +namespace detail { + +#if !defined(BOOST_ASIO_ENABLE_OLD_SSL) + +class engine +{ +public: + enum want + { + // Returned by functions to indicate that the engine wants input. The input + // buffer should be updated to point to the data. The engine then needs to + // be called again to retry the operation. + want_input_and_retry = -2, + + // Returned by functions to indicate that the engine wants to write output. + // The output buffer points to the data to be written. The engine then + // needs to be called again to retry the operation. + want_output_and_retry = -1, + + // Returned by functions to indicate that the engine doesn't need input or + // output. + want_nothing = 0, + + // Returned by functions to indicate that the engine wants to write output. + // The output buffer points to the data to be written. After that the + // operation is complete, and the engine does not need to be called again. + want_output = 1 + }; + + // Construct a new engine for the specified context. + BOOST_ASIO_DECL explicit engine(SSL_CTX* context); + + // Destructor. + BOOST_ASIO_DECL ~engine(); + + // Get the underlying implementation in the native type. + BOOST_ASIO_DECL SSL* native_handle(); + + // Set the peer verification mode. + BOOST_ASIO_DECL boost::system::error_code set_verify_mode( + verify_mode v, boost::system::error_code& ec); + + // Set a peer certificate verification callback. + BOOST_ASIO_DECL boost::system::error_code set_verify_callback( + verify_callback_base* callback, boost::system::error_code& ec); + + // Perform an SSL handshake using either SSL_connect (client-side) or + // SSL_accept (server-side). + BOOST_ASIO_DECL want handshake( + stream_base::handshake_type type, boost::system::error_code& ec); + + // Perform a graceful shutdown of the SSL session. + BOOST_ASIO_DECL want shutdown(boost::system::error_code& ec); + + // Write bytes to the SSL session. + BOOST_ASIO_DECL want write(const boost::asio::const_buffer& data, + boost::system::error_code& ec, std::size_t& bytes_transferred); + + // Read bytes from the SSL session. + BOOST_ASIO_DECL want read(const boost::asio::mutable_buffer& data, + boost::system::error_code& ec, std::size_t& bytes_transferred); + + // Get output data to be written to the transport. + BOOST_ASIO_DECL boost::asio::mutable_buffers_1 get_output( + const boost::asio::mutable_buffer& data); + + // Put input data that was read from the transport. + BOOST_ASIO_DECL boost::asio::const_buffer put_input( + const boost::asio::const_buffer& data); + + // Map an error::eof code returned by the underlying transport according to + // the type and state of the SSL session. Returns a const reference to the + // error code object, suitable for passing to a completion handler. + BOOST_ASIO_DECL const boost::system::error_code& map_error_code( + boost::system::error_code& ec) const; + +private: + // Disallow copying and assignment. + engine(const engine&); + engine& operator=(const engine&); + + // Callback used when the SSL implementation wants to verify a certificate. + BOOST_ASIO_DECL static int verify_callback_function( + int preverified, X509_STORE_CTX* ctx); + + // The SSL_accept function may not be thread safe. This mutex is used to + // protect all calls to the SSL_accept function. + BOOST_ASIO_DECL static boost::asio::detail::static_mutex& accept_mutex(); + + // Perform one operation. Returns >= 0 on success or error, want_read if the + // operation needs more input, or want_write if it needs to write some output + // before the operation can complete. + BOOST_ASIO_DECL want perform(int (engine::* op)(void*, std::size_t), + void* data, std::size_t length, boost::system::error_code& ec, + std::size_t* bytes_transferred); + + // Adapt the SSL_accept function to the signature needed for perform(). + BOOST_ASIO_DECL int do_accept(void*, std::size_t); + + // Adapt the SSL_connect function to the signature needed for perform(). + BOOST_ASIO_DECL int do_connect(void*, std::size_t); + + // Adapt the SSL_shutdown function to the signature needed for perform(). + BOOST_ASIO_DECL int do_shutdown(void*, std::size_t); + + // Adapt the SSL_read function to the signature needed for perform(). + BOOST_ASIO_DECL int do_read(void* data, std::size_t length); + + // Adapt the SSL_write function to the signature needed for perform(). + BOOST_ASIO_DECL int do_write(void* data, std::size_t length); + + SSL* ssl_; + BIO* ext_bio_; +}; + +#endif // !defined(BOOST_ASIO_ENABLE_OLD_SSL) + +} // namespace detail +} // namespace ssl +} // namespace asio +} // namespace boost + +#include <boost/asio/detail/pop_options.hpp> + +#if defined(BOOST_ASIO_HEADER_ONLY) +# include <boost/asio/ssl/detail/impl/engine.ipp> +#endif // defined(BOOST_ASIO_HEADER_ONLY) + +#endif // BOOST_ASIO_SSL_DETAIL_ENGINE_HPP diff --git a/boost/asio/ssl/detail/handshake_op.hpp b/boost/asio/ssl/detail/handshake_op.hpp new file mode 100644 index 0000000000..3c57a4de96 --- /dev/null +++ b/boost/asio/ssl/detail/handshake_op.hpp @@ -0,0 +1,70 @@ +// +// ssl/detail/handshake_op.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2012 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_HANDSHAKE_OP_HPP +#define BOOST_ASIO_SSL_DETAIL_HANDSHAKE_OP_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include <boost/asio/detail/config.hpp> + +#if !defined(BOOST_ASIO_ENABLE_OLD_SSL) +# include <boost/asio/ssl/detail/engine.hpp> +#endif // !defined(BOOST_ASIO_ENABLE_OLD_SSL) + +#include <boost/asio/detail/push_options.hpp> + +namespace boost { +namespace asio { +namespace ssl { +namespace detail { + +#if !defined(BOOST_ASIO_ENABLE_OLD_SSL) + +class handshake_op +{ +public: + handshake_op(stream_base::handshake_type type) + : type_(type) + { + } + + engine::want operator()(engine& eng, + boost::system::error_code& ec, + std::size_t& bytes_transferred) const + { + bytes_transferred = 0; + return eng.handshake(type_, ec); + } + + template <typename Handler> + void call_handler(Handler& handler, + const boost::system::error_code& ec, + const std::size_t&) const + { + handler(ec); + } + +private: + stream_base::handshake_type type_; +}; + +#endif // !defined(BOOST_ASIO_ENABLE_OLD_SSL) + +} // namespace detail +} // namespace ssl +} // namespace asio +} // namespace boost + +#include <boost/asio/detail/pop_options.hpp> + +#endif // BOOST_ASIO_SSL_DETAIL_HANDSHAKE_OP_HPP diff --git a/boost/asio/ssl/detail/impl/engine.ipp b/boost/asio/ssl/detail/impl/engine.ipp new file mode 100644 index 0000000000..72f1c35689 --- /dev/null +++ b/boost/asio/ssl/detail/impl/engine.ipp @@ -0,0 +1,306 @@ +// +// ssl/detail/impl/engine.ipp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2012 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_IMPL_ENGINE_IPP +#define BOOST_ASIO_SSL_DETAIL_IMPL_ENGINE_IPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include <boost/asio/detail/config.hpp> + +#if !defined(BOOST_ASIO_ENABLE_OLD_SSL) +# include <boost/asio/ssl/detail/engine.hpp> +# include <boost/asio/ssl/verify_context.hpp> +#endif // !defined(BOOST_ASIO_ENABLE_OLD_SSL) + +#include <boost/asio/detail/push_options.hpp> + +namespace boost { +namespace asio { +namespace ssl { +namespace detail { + +#if !defined(BOOST_ASIO_ENABLE_OLD_SSL) + +engine::engine(SSL_CTX* context) + : ssl_(::SSL_new(context)) +{ + accept_mutex().init(); + + ::SSL_set_mode(ssl_, SSL_MODE_ENABLE_PARTIAL_WRITE); + ::SSL_set_mode(ssl_, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER); +#if defined(SSL_MODE_RELEASE_BUFFERS) + ::SSL_set_mode(ssl_, SSL_MODE_RELEASE_BUFFERS); +#endif // defined(SSL_MODE_RELEASE_BUFFERS) + + ::BIO* int_bio = 0; + ::BIO_new_bio_pair(&int_bio, 0, &ext_bio_, 0); + ::SSL_set_bio(ssl_, int_bio, int_bio); +} + +engine::~engine() +{ + if (SSL_get_app_data(ssl_)) + { + delete static_cast<verify_callback_base*>(SSL_get_app_data(ssl_)); + SSL_set_app_data(ssl_, 0); + } + + ::BIO_free(ext_bio_); + ::SSL_free(ssl_); +} + +SSL* engine::native_handle() +{ + return ssl_; +} + +boost::system::error_code engine::set_verify_mode( + verify_mode v, boost::system::error_code& ec) +{ + ::SSL_set_verify(ssl_, v, ::SSL_get_verify_callback(ssl_)); + + ec = boost::system::error_code(); + return ec; +} + +boost::system::error_code engine::set_verify_callback( + verify_callback_base* callback, boost::system::error_code& ec) +{ + if (SSL_get_app_data(ssl_)) + delete static_cast<verify_callback_base*>(SSL_get_app_data(ssl_)); + + SSL_set_app_data(ssl_, callback); + + ::SSL_set_verify(ssl_, ::SSL_get_verify_mode(ssl_), + &engine::verify_callback_function); + + ec = boost::system::error_code(); + return ec; +} + +int engine::verify_callback_function(int preverified, X509_STORE_CTX* ctx) +{ + if (ctx) + { + if (SSL* ssl = static_cast<SSL*>( + ::X509_STORE_CTX_get_ex_data( + ctx, ::SSL_get_ex_data_X509_STORE_CTX_idx()))) + { + if (SSL_get_app_data(ssl)) + { + verify_callback_base* callback = + static_cast<verify_callback_base*>( + SSL_get_app_data(ssl)); + + verify_context verify_ctx(ctx); + return callback->call(preverified != 0, verify_ctx) ? 1 : 0; + } + } + } + + return 0; +} + +engine::want engine::handshake( + stream_base::handshake_type type, boost::system::error_code& ec) +{ + return perform((type == boost::asio::ssl::stream_base::client) + ? &engine::do_connect : &engine::do_accept, 0, 0, ec, 0); +} + +engine::want engine::shutdown(boost::system::error_code& ec) +{ + return perform(&engine::do_shutdown, 0, 0, ec, 0); +} + +engine::want engine::write(const boost::asio::const_buffer& data, + boost::system::error_code& ec, std::size_t& bytes_transferred) +{ + if (boost::asio::buffer_size(data) == 0) + { + ec = boost::system::error_code(); + return engine::want_nothing; + } + + return perform(&engine::do_write, + const_cast<void*>(boost::asio::buffer_cast<const void*>(data)), + boost::asio::buffer_size(data), ec, &bytes_transferred); +} + +engine::want engine::read(const boost::asio::mutable_buffer& data, + boost::system::error_code& ec, std::size_t& bytes_transferred) +{ + if (boost::asio::buffer_size(data) == 0) + { + ec = boost::system::error_code(); + return engine::want_nothing; + } + + return perform(&engine::do_read, + boost::asio::buffer_cast<void*>(data), + boost::asio::buffer_size(data), ec, &bytes_transferred); +} + +boost::asio::mutable_buffers_1 engine::get_output( + const boost::asio::mutable_buffer& data) +{ + int length = ::BIO_read(ext_bio_, + boost::asio::buffer_cast<void*>(data), + boost::asio::buffer_size(data)); + + return boost::asio::buffer(data, + length > 0 ? static_cast<std::size_t>(length) : 0); +} + +boost::asio::const_buffer engine::put_input( + const boost::asio::const_buffer& data) +{ + int length = ::BIO_write(ext_bio_, + boost::asio::buffer_cast<const void*>(data), + boost::asio::buffer_size(data)); + + return boost::asio::buffer(data + + (length > 0 ? static_cast<std::size_t>(length) : 0)); +} + +const boost::system::error_code& engine::map_error_code( + boost::system::error_code& ec) const +{ + // We only want to map the error::eof code. + if (ec != boost::asio::error::eof) + return ec; + + // If there's data yet to be read, it's an error. + if (BIO_wpending(ext_bio_)) + { + ec = boost::system::error_code( + ERR_PACK(ERR_LIB_SSL, 0, SSL_R_SHORT_READ), + boost::asio::error::get_ssl_category()); + return ec; + } + + // SSL v2 doesn't provide a protocol-level shutdown, so an eof on the + // underlying transport is passed through. + if (ssl_ && ssl_->version == SSL2_VERSION) + return ec; + + // Otherwise, the peer should have negotiated a proper shutdown. + if ((::SSL_get_shutdown(ssl_) & SSL_RECEIVED_SHUTDOWN) == 0) + { + ec = boost::system::error_code( + ERR_PACK(ERR_LIB_SSL, 0, SSL_R_SHORT_READ), + boost::asio::error::get_ssl_category()); + } + + return ec; +} + +boost::asio::detail::static_mutex& engine::accept_mutex() +{ + static boost::asio::detail::static_mutex mutex = BOOST_ASIO_STATIC_MUTEX_INIT; + return mutex; +} + +engine::want engine::perform(int (engine::* op)(void*, std::size_t), + void* data, std::size_t length, boost::system::error_code& ec, + std::size_t* bytes_transferred) +{ + std::size_t pending_output_before = ::BIO_ctrl_pending(ext_bio_); + int result = (this->*op)(data, length); + int ssl_error = ::SSL_get_error(ssl_, result); + int sys_error = ::ERR_get_error(); + std::size_t pending_output_after = ::BIO_ctrl_pending(ext_bio_); + + if (ssl_error == SSL_ERROR_SSL) + { + ec = boost::system::error_code(sys_error, + boost::asio::error::get_ssl_category()); + return want_nothing; + } + + if (ssl_error == SSL_ERROR_SYSCALL) + { + ec = boost::system::error_code(sys_error, + boost::asio::error::get_system_category()); + return want_nothing; + } + + if (result > 0 && bytes_transferred) + *bytes_transferred = static_cast<std::size_t>(result); + + if (ssl_error == SSL_ERROR_WANT_WRITE) + { + ec = boost::system::error_code(); + return want_output_and_retry; + } + else if (pending_output_after > pending_output_before) + { + ec = boost::system::error_code(); + return result > 0 ? want_output : want_output_and_retry; + } + else if (ssl_error == SSL_ERROR_WANT_READ) + { + ec = boost::system::error_code(); + return want_input_and_retry; + } + else if (::SSL_get_shutdown(ssl_) & SSL_RECEIVED_SHUTDOWN) + { + ec = boost::asio::error::eof; + return want_nothing; + } + else + { + ec = boost::system::error_code(); + return want_nothing; + } +} + +int engine::do_accept(void*, std::size_t) +{ + boost::asio::detail::static_mutex::scoped_lock lock(accept_mutex()); + return ::SSL_accept(ssl_); +} + +int engine::do_connect(void*, std::size_t) +{ + return ::SSL_connect(ssl_); +} + +int engine::do_shutdown(void*, std::size_t) +{ + int result = ::SSL_shutdown(ssl_); + if (result == 0) + result = ::SSL_shutdown(ssl_); + return result; +} + +int engine::do_read(void* data, std::size_t length) +{ + return ::SSL_read(ssl_, data, length < INT_MAX ? length : INT_MAX); +} + +int engine::do_write(void* data, std::size_t length) +{ + return ::SSL_write(ssl_, data, length < INT_MAX ? length : INT_MAX); +} + +#endif // !defined(BOOST_ASIO_ENABLE_OLD_SSL) + +} // namespace detail +} // namespace ssl +} // namespace asio +} // namespace boost + +#include <boost/asio/detail/pop_options.hpp> + +#endif // BOOST_ASIO_SSL_DETAIL_IMPL_ENGINE_IPP diff --git a/boost/asio/ssl/detail/impl/openssl_init.ipp b/boost/asio/ssl/detail/impl/openssl_init.ipp new file mode 100644 index 0000000000..af33f6e039 --- /dev/null +++ b/boost/asio/ssl/detail/impl/openssl_init.ipp @@ -0,0 +1,109 @@ +// +// ssl/detail/impl/openssl_init.ipp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2005 Voipster / Indrek dot Juhani at voipster dot com +// Copyright (c) 2005-2012 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_IMPL_OPENSSL_INIT_IPP +#define BOOST_ASIO_SSL_DETAIL_IMPL_OPENSSL_INIT_IPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include <boost/asio/detail/config.hpp> +#include <vector> +#include <boost/assert.hpp> +#include <boost/asio/detail/mutex.hpp> +#include <boost/asio/detail/tss_ptr.hpp> +#include <boost/asio/ssl/detail/openssl_init.hpp> +#include <boost/asio/ssl/detail/openssl_types.hpp> + +#include <boost/asio/detail/push_options.hpp> + +namespace boost { +namespace asio { +namespace ssl { +namespace detail { + +class openssl_init_base::do_init +{ +public: + do_init() + { + ::SSL_library_init(); + ::SSL_load_error_strings(); + ::OpenSSL_add_all_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() + { + ::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(); + } + +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::asio::detail::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__) +}; + +boost::asio::detail::shared_ptr<openssl_init_base::do_init> +openssl_init_base::instance() +{ + static boost::asio::detail::shared_ptr<do_init> init(new do_init); + return init; +} + +} // namespace detail +} // namespace ssl +} // namespace asio +} // namespace boost + +#include <boost/asio/detail/pop_options.hpp> + +#endif // BOOST_ASIO_SSL_DETAIL_IMPL_OPENSSL_INIT_IPP diff --git a/boost/asio/ssl/detail/io.hpp b/boost/asio/ssl/detail/io.hpp new file mode 100644 index 0000000000..e83934e313 --- /dev/null +++ b/boost/asio/ssl/detail/io.hpp @@ -0,0 +1,336 @@ +// +// ssl/detail/io.hpp +// ~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2012 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_IO_HPP +#define BOOST_ASIO_SSL_DETAIL_IO_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include <boost/asio/detail/config.hpp> + +#if !defined(BOOST_ASIO_ENABLE_OLD_SSL) +# include <boost/asio/ssl/detail/engine.hpp> +# include <boost/asio/ssl/detail/stream_core.hpp> +# include <boost/asio/write.hpp> +#endif // !defined(BOOST_ASIO_ENABLE_OLD_SSL) + +#include <boost/asio/detail/push_options.hpp> + +namespace boost { +namespace asio { +namespace ssl { +namespace detail { + +#if !defined(BOOST_ASIO_ENABLE_OLD_SSL) + +template <typename Stream, typename Operation> +std::size_t io(Stream& next_layer, stream_core& core, + const Operation& op, boost::system::error_code& ec) +{ + std::size_t bytes_transferred = 0; + do switch (op(core.engine_, ec, bytes_transferred)) + { + case engine::want_input_and_retry: + + // If the input buffer is empty then we need to read some more data from + // the underlying transport. + if (boost::asio::buffer_size(core.input_) == 0) + core.input_ = boost::asio::buffer(core.input_buffer_, + next_layer.read_some(core.input_buffer_, ec)); + + // Pass the new input data to the engine. + core.input_ = core.engine_.put_input(core.input_); + + // Try the operation again. + continue; + + case engine::want_output_and_retry: + + // Get output data from the engine and write it to the underlying + // transport. + boost::asio::write(next_layer, + core.engine_.get_output(core.output_buffer_), ec); + + // Try the operation again. + continue; + + case engine::want_output: + + // Get output data from the engine and write it to the underlying + // transport. + boost::asio::write(next_layer, + core.engine_.get_output(core.output_buffer_), ec); + + // Operation is complete. Return result to caller. + core.engine_.map_error_code(ec); + return bytes_transferred; + + default: + + // Operation is complete. Return result to caller. + core.engine_.map_error_code(ec); + return bytes_transferred; + + } while (!ec); + + // Operation failed. Return result to caller. + core.engine_.map_error_code(ec); + return 0; +} + +template <typename Stream, typename Operation, typename Handler> +class io_op +{ +public: + io_op(Stream& next_layer, stream_core& core, + const Operation& op, Handler& handler) + : next_layer_(next_layer), + core_(core), + op_(op), + bytes_transferred_(0), + handler_(BOOST_ASIO_MOVE_CAST(Handler)(handler)) + { + } + +#if defined(BOOST_ASIO_HAS_MOVE) + io_op(const io_op& other) + : next_layer_(other.next_layer_), + core_(other.core_), + op_(other.op_), + want_(other.want_), + ec_(other.ec_), + bytes_transferred_(other.bytes_transferred_), + handler_(other.handler_) + { + } + + io_op(io_op&& other) + : next_layer_(other.next_layer_), + core_(other.core_), + op_(other.op_), + want_(other.want_), + ec_(other.ec_), + bytes_transferred_(other.bytes_transferred_), + handler_(BOOST_ASIO_MOVE_CAST(Handler)(other.handler_)) + { + } +#endif // defined(BOOST_ASIO_HAS_MOVE) + + void operator()(boost::system::error_code ec, + std::size_t bytes_transferred = ~std::size_t(0), int start = 0) + { + switch (start) + { + case 1: // Called after at least one async operation. + do + { + switch (want_ = op_(core_.engine_, ec_, bytes_transferred_)) + { + case engine::want_input_and_retry: + + // If the input buffer already has data in it we can pass it to the + // engine and then retry the operation immediately. + if (boost::asio::buffer_size(core_.input_) != 0) + { + core_.input_ = core_.engine_.put_input(core_.input_); + continue; + } + + // The engine wants more data to be read from input. However, we + // cannot allow more than one read operation at a time on the + // underlying transport. The pending_read_ timer's expiry is set to + // pos_infin if a read is in progress, and neg_infin otherwise. + if (core_.pending_read_.expires_at() == boost::posix_time::neg_infin) + { + // Prevent other read operations from being started. + core_.pending_read_.expires_at(boost::posix_time::pos_infin); + + // Start reading some data from the underlying transport. + next_layer_.async_read_some( + boost::asio::buffer(core_.input_buffer_), + BOOST_ASIO_MOVE_CAST(io_op)(*this)); + } + else + { + // Wait until the current read operation completes. + core_.pending_read_.async_wait(BOOST_ASIO_MOVE_CAST(io_op)(*this)); + } + + // Yield control until asynchronous operation completes. Control + // resumes at the "default:" label below. + return; + + case engine::want_output_and_retry: + case engine::want_output: + + // The engine wants some data to be written to the output. However, we + // cannot allow more than one write operation at a time on the + // underlying transport. The pending_write_ timer's expiry is set to + // pos_infin if a write is in progress, and neg_infin otherwise. + if (core_.pending_write_.expires_at() == boost::posix_time::neg_infin) + { + // Prevent other write operations from being started. + core_.pending_write_.expires_at(boost::posix_time::pos_infin); + + // Start writing all the data to the underlying transport. + boost::asio::async_write(next_layer_, + core_.engine_.get_output(core_.output_buffer_), + BOOST_ASIO_MOVE_CAST(io_op)(*this)); + } + else + { + // Wait until the current write operation completes. + core_.pending_write_.async_wait(BOOST_ASIO_MOVE_CAST(io_op)(*this)); + } + + // Yield control until asynchronous operation completes. Control + // resumes at the "default:" label below. + return; + + default: + + // The SSL operation is done and we can invoke the handler, but we + // have to keep in mind that this function might be being called from + // the async operation's initiating function. In this case we're not + // allowed to call the handler directly. Instead, issue a zero-sized + // read so the handler runs "as-if" posted using io_service::post(). + if (start) + { + next_layer_.async_read_some( + boost::asio::buffer(core_.input_buffer_, 0), + BOOST_ASIO_MOVE_CAST(io_op)(*this)); + + // Yield control until asynchronous operation completes. Control + // resumes at the "default:" label below. + return; + } + else + { + // Continue on to run handler directly. + break; + } + } + + default: + if (bytes_transferred != ~std::size_t(0) && !ec_) + ec_ = ec; + + switch (want_) + { + case engine::want_input_and_retry: + + // Add received data to the engine's input. + core_.input_ = boost::asio::buffer( + core_.input_buffer_, bytes_transferred); + core_.input_ = core_.engine_.put_input(core_.input_); + + // Release any waiting read operations. + core_.pending_read_.expires_at(boost::posix_time::neg_infin); + + // Try the operation again. + continue; + + case engine::want_output_and_retry: + + // Release any waiting write operations. + core_.pending_write_.expires_at(boost::posix_time::neg_infin); + + // Try the operation again. + continue; + + case engine::want_output: + + // Release any waiting write operations. + core_.pending_write_.expires_at(boost::posix_time::neg_infin); + + // Fall through to call handler. + + default: + + // Pass the result to the handler. + op_.call_handler(handler_, + core_.engine_.map_error_code(ec_), + ec_ ? 0 : bytes_transferred_); + + // Our work here is done. + return; + } + } while (!ec_); + + // Operation failed. Pass the result to the handler. + op_.call_handler(handler_, core_.engine_.map_error_code(ec_), 0); + } + } + +//private: + Stream& next_layer_; + stream_core& core_; + Operation op_; + engine::want want_; + boost::system::error_code ec_; + std::size_t bytes_transferred_; + Handler handler_; +}; + +template <typename Stream, typename Operation, typename Handler> +inline void* asio_handler_allocate(std::size_t size, + io_op<Stream, Operation, Handler>* this_handler) +{ + return boost_asio_handler_alloc_helpers::allocate( + size, this_handler->handler_); +} + +template <typename Stream, typename Operation, typename Handler> +inline void asio_handler_deallocate(void* pointer, std::size_t size, + io_op<Stream, Operation, Handler>* this_handler) +{ + boost_asio_handler_alloc_helpers::deallocate( + pointer, size, this_handler->handler_); +} + +template <typename Function, typename Stream, + typename Operation, typename Handler> +inline void asio_handler_invoke(Function& function, + io_op<Stream, Operation, Handler>* this_handler) +{ + boost_asio_handler_invoke_helpers::invoke( + function, this_handler->handler_); +} + +template <typename Function, typename Stream, + typename Operation, typename Handler> +inline void asio_handler_invoke(const Function& function, + io_op<Stream, Operation, Handler>* this_handler) +{ + boost_asio_handler_invoke_helpers::invoke( + function, this_handler->handler_); +} + +template <typename Stream, typename Operation, typename Handler> +inline void async_io(Stream& next_layer, stream_core& core, + const Operation& op, Handler handler) +{ + io_op<Stream, Operation, Handler>( + next_layer, core, op, handler)( + boost::system::error_code(), 0, 1); +} + +#endif // !defined(BOOST_ASIO_ENABLE_OLD_SSL) + +} // namespace detail +} // namespace ssl +} // namespace asio +} // namespace boost + +#include <boost/asio/detail/pop_options.hpp> + +#endif // BOOST_ASIO_SSL_DETAIL_IO_HPP diff --git a/boost/asio/ssl/detail/openssl_init.hpp b/boost/asio/ssl/detail/openssl_init.hpp new file mode 100644 index 0000000000..c68909d16b --- /dev/null +++ b/boost/asio/ssl/detail/openssl_init.hpp @@ -0,0 +1,88 @@ +// +// ssl/detail/openssl_init.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2012 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/config.hpp> +#include <cstring> +#include <boost/asio/detail/noncopyable.hpp> +#include <boost/asio/detail/shared_ptr.hpp> + +#include <boost/asio/detail/push_options.hpp> + +namespace boost { +namespace asio { +namespace ssl { +namespace detail { + +class openssl_init_base + : private noncopyable +{ +protected: + // Class that performs the actual initialisation. + class do_init; + + // 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. + BOOST_ASIO_DECL static boost::asio::detail::shared_ptr<do_init> instance(); +}; + +template <bool Do_Init = true> +class openssl_init : private openssl_init_base +{ +public: + // Constructor. + openssl_init() + : ref_(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::asio::detail::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> + +#if defined(BOOST_ASIO_HEADER_ONLY) +# include <boost/asio/ssl/detail/impl/openssl_init.ipp> +#endif // defined(BOOST_ASIO_HEADER_ONLY) + +#endif // BOOST_ASIO_SSL_DETAIL_OPENSSL_INIT_HPP diff --git a/boost/asio/ssl/detail/openssl_types.hpp b/boost/asio/ssl/detail/openssl_types.hpp new file mode 100644 index 0000000000..752fe587de --- /dev/null +++ b/boost/asio/ssl/detail/openssl_types.hpp @@ -0,0 +1,26 @@ +// +// ssl/detail/openssl_types.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2012 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_TYPES_HPP +#define BOOST_ASIO_SSL_DETAIL_OPENSSL_TYPES_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include <boost/asio/detail/config.hpp> +#include <openssl/conf.h> +#include <openssl/ssl.h> +#include <openssl/engine.h> +#include <openssl/err.h> +#include <openssl/x509v3.h> +#include <boost/asio/detail/socket_types.hpp> + +#endif // BOOST_ASIO_SSL_DETAIL_OPENSSL_TYPES_HPP diff --git a/boost/asio/ssl/detail/password_callback.hpp b/boost/asio/ssl/detail/password_callback.hpp new file mode 100644 index 0000000000..438320a00b --- /dev/null +++ b/boost/asio/ssl/detail/password_callback.hpp @@ -0,0 +1,74 @@ +// +// ssl/detail/password_callback.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2012 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_PASSWORD_CALLBACK_HPP +#define BOOST_ASIO_SSL_DETAIL_PASSWORD_CALLBACK_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include <boost/asio/detail/config.hpp> + +#if !defined(BOOST_ASIO_ENABLE_OLD_SSL) +# include <cstddef> +# include <string> +# include <boost/asio/ssl/context_base.hpp> +#endif // !defined(BOOST_ASIO_ENABLE_OLD_SSL) + +#include <boost/asio/detail/push_options.hpp> + +namespace boost { +namespace asio { +namespace ssl { +namespace detail { + +#if !defined(BOOST_ASIO_ENABLE_OLD_SSL) + +class password_callback_base +{ +public: + virtual ~password_callback_base() + { + } + + virtual std::string call(std::size_t size, + context_base::password_purpose purpose) = 0; +}; + +template <typename PasswordCallback> +class password_callback : public password_callback_base +{ +public: + explicit password_callback(PasswordCallback callback) + : callback_(callback) + { + } + + virtual std::string call(std::size_t size, + context_base::password_purpose purpose) + { + return callback_(size, purpose); + } + +private: + PasswordCallback callback_; +}; + +#endif // !defined(BOOST_ASIO_ENABLE_OLD_SSL) + +} // namespace detail +} // namespace ssl +} // namespace asio +} // namespace boost + +#include <boost/asio/detail/pop_options.hpp> + +#endif // BOOST_ASIO_SSL_DETAIL_PASSWORD_CALLBACK_HPP diff --git a/boost/asio/ssl/detail/read_op.hpp b/boost/asio/ssl/detail/read_op.hpp new file mode 100644 index 0000000000..abf329c7b7 --- /dev/null +++ b/boost/asio/ssl/detail/read_op.hpp @@ -0,0 +1,75 @@ +// +// ssl/detail/read_op.hpp +// ~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2012 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_READ_OP_HPP +#define BOOST_ASIO_SSL_DETAIL_READ_OP_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include <boost/asio/detail/config.hpp> + +#if !defined(BOOST_ASIO_ENABLE_OLD_SSL) +# include <boost/asio/detail/buffer_sequence_adapter.hpp> +# include <boost/asio/ssl/detail/engine.hpp> +#endif // !defined(BOOST_ASIO_ENABLE_OLD_SSL) + +#include <boost/asio/detail/push_options.hpp> + +namespace boost { +namespace asio { +namespace ssl { +namespace detail { + +#if !defined(BOOST_ASIO_ENABLE_OLD_SSL) + +template <typename MutableBufferSequence> +class read_op +{ +public: + read_op(const MutableBufferSequence& buffers) + : buffers_(buffers) + { + } + + engine::want operator()(engine& eng, + boost::system::error_code& ec, + std::size_t& bytes_transferred) const + { + boost::asio::mutable_buffer buffer = + boost::asio::detail::buffer_sequence_adapter<boost::asio::mutable_buffer, + MutableBufferSequence>::first(buffers_); + + return eng.read(buffer, ec, bytes_transferred); + } + + template <typename Handler> + void call_handler(Handler& handler, + const boost::system::error_code& ec, + const std::size_t& bytes_transferred) const + { + handler(ec, bytes_transferred); + } + +private: + MutableBufferSequence buffers_; +}; + +#endif // !defined(BOOST_ASIO_ENABLE_OLD_SSL) + +} // namespace detail +} // namespace ssl +} // namespace asio +} // namespace boost + +#include <boost/asio/detail/pop_options.hpp> + +#endif // BOOST_ASIO_SSL_DETAIL_READ_OP_HPP diff --git a/boost/asio/ssl/detail/shutdown_op.hpp b/boost/asio/ssl/detail/shutdown_op.hpp new file mode 100644 index 0000000000..cfeb8e572e --- /dev/null +++ b/boost/asio/ssl/detail/shutdown_op.hpp @@ -0,0 +1,62 @@ +// +// ssl/detail/shutdown_op.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2012 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_SHUTDOWN_OP_HPP +#define BOOST_ASIO_SSL_DETAIL_SHUTDOWN_OP_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include <boost/asio/detail/config.hpp> + +#if !defined(BOOST_ASIO_ENABLE_OLD_SSL) +# include <boost/asio/ssl/detail/engine.hpp> +#endif // !defined(BOOST_ASIO_ENABLE_OLD_SSL) + +#include <boost/asio/detail/push_options.hpp> + +namespace boost { +namespace asio { +namespace ssl { +namespace detail { + +#if !defined(BOOST_ASIO_ENABLE_OLD_SSL) + +class shutdown_op +{ +public: + engine::want operator()(engine& eng, + boost::system::error_code& ec, + std::size_t& bytes_transferred) const + { + bytes_transferred = 0; + return eng.shutdown(ec); + } + + template <typename Handler> + void call_handler(Handler& handler, + const boost::system::error_code& ec, + const std::size_t&) const + { + handler(ec); + } +}; + +#endif // !defined(BOOST_ASIO_ENABLE_OLD_SSL) + +} // namespace detail +} // namespace ssl +} // namespace asio +} // namespace boost + +#include <boost/asio/detail/pop_options.hpp> + +#endif // BOOST_ASIO_SSL_DETAIL_SHUTDOWN_OP_HPP diff --git a/boost/asio/ssl/detail/stream_core.hpp b/boost/asio/ssl/detail/stream_core.hpp new file mode 100644 index 0000000000..b8f0afa4a1 --- /dev/null +++ b/boost/asio/ssl/detail/stream_core.hpp @@ -0,0 +1,92 @@ +// +// ssl/detail/stream_core.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2012 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_STREAM_CORE_HPP +#define BOOST_ASIO_SSL_DETAIL_STREAM_CORE_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include <boost/asio/detail/config.hpp> + +#if !defined(BOOST_ASIO_ENABLE_OLD_SSL) +# include <boost/asio/deadline_timer.hpp> +# include <boost/asio/ssl/detail/engine.hpp> +# include <boost/asio/buffer.hpp> +#endif // !defined(BOOST_ASIO_ENABLE_OLD_SSL) + +#include <boost/asio/detail/push_options.hpp> + +namespace boost { +namespace asio { +namespace ssl { +namespace detail { + +#if !defined(BOOST_ASIO_ENABLE_OLD_SSL) + +struct stream_core +{ + // According to the OpenSSL documentation, this is the buffer size that is is + // sufficient to hold the largest possible TLS record. + enum { max_tls_record_size = 17 * 1024 }; + + stream_core(SSL_CTX* context, boost::asio::io_service& io_service) + : engine_(context), + pending_read_(io_service), + pending_write_(io_service), + output_buffer_space_(max_tls_record_size), + output_buffer_(boost::asio::buffer(output_buffer_space_)), + input_buffer_space_(max_tls_record_size), + input_buffer_(boost::asio::buffer(input_buffer_space_)) + { + pending_read_.expires_at(boost::posix_time::neg_infin); + pending_write_.expires_at(boost::posix_time::neg_infin); + } + + ~stream_core() + { + } + + // The SSL engine. + engine engine_; + + // Timer used for storing queued read operations. + boost::asio::deadline_timer pending_read_; + + // Timer used for storing queued write operations. + boost::asio::deadline_timer pending_write_; + + // Buffer space used to prepare output intended for the transport. + std::vector<unsigned char> output_buffer_space_; + + // A buffer that may be used to prepare output intended for the transport. + const boost::asio::mutable_buffers_1 output_buffer_; + + // Buffer space used to read input intended for the engine. + std::vector<unsigned char> input_buffer_space_; + + // A buffer that may be used to read input intended for the engine. + const boost::asio::mutable_buffers_1 input_buffer_; + + // The buffer pointing to the engine's unconsumed input. + boost::asio::const_buffer input_; +}; + +#endif // !defined(BOOST_ASIO_ENABLE_OLD_SSL) + +} // namespace detail +} // namespace ssl +} // namespace asio +} // namespace boost + +#include <boost/asio/detail/pop_options.hpp> + +#endif // BOOST_ASIO_SSL_DETAIL_STREAM_CORE_HPP diff --git a/boost/asio/ssl/detail/verify_callback.hpp b/boost/asio/ssl/detail/verify_callback.hpp new file mode 100644 index 0000000000..2d497d1ce1 --- /dev/null +++ b/boost/asio/ssl/detail/verify_callback.hpp @@ -0,0 +1,70 @@ +// +// ssl/detail/verify_callback.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2012 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_VERIFY_CALLBACK_HPP +#define BOOST_ASIO_SSL_DETAIL_VERIFY_CALLBACK_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include <boost/asio/detail/config.hpp> + +#if !defined(BOOST_ASIO_ENABLE_OLD_SSL) +# include <boost/asio/ssl/verify_context.hpp> +#endif // !defined(BOOST_ASIO_ENABLE_OLD_SSL) + +#include <boost/asio/detail/push_options.hpp> + +namespace boost { +namespace asio { +namespace ssl { +namespace detail { + +#if !defined(BOOST_ASIO_ENABLE_OLD_SSL) + +class verify_callback_base +{ +public: + virtual ~verify_callback_base() + { + } + + virtual bool call(bool preverified, verify_context& ctx) = 0; +}; + +template <typename VerifyCallback> +class verify_callback : public verify_callback_base +{ +public: + explicit verify_callback(VerifyCallback callback) + : callback_(callback) + { + } + + virtual bool call(bool preverified, verify_context& ctx) + { + return callback_(preverified, ctx); + } + +private: + VerifyCallback callback_; +}; + +#endif // !defined(BOOST_ASIO_ENABLE_OLD_SSL) + +} // namespace detail +} // namespace ssl +} // namespace asio +} // namespace boost + +#include <boost/asio/detail/pop_options.hpp> + +#endif // BOOST_ASIO_SSL_DETAIL_VERIFY_CALLBACK_HPP diff --git a/boost/asio/ssl/detail/write_op.hpp b/boost/asio/ssl/detail/write_op.hpp new file mode 100644 index 0000000000..82ecbb9212 --- /dev/null +++ b/boost/asio/ssl/detail/write_op.hpp @@ -0,0 +1,75 @@ +// +// ssl/detail/write_op.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2012 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_WRITE_OP_HPP +#define BOOST_ASIO_SSL_DETAIL_WRITE_OP_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include <boost/asio/detail/config.hpp> + +#if !defined(BOOST_ASIO_ENABLE_OLD_SSL) +# include <boost/asio/detail/buffer_sequence_adapter.hpp> +# include <boost/asio/ssl/detail/engine.hpp> +#endif // !defined(BOOST_ASIO_ENABLE_OLD_SSL) + +#include <boost/asio/detail/push_options.hpp> + +namespace boost { +namespace asio { +namespace ssl { +namespace detail { + +#if !defined(BOOST_ASIO_ENABLE_OLD_SSL) + +template <typename ConstBufferSequence> +class write_op +{ +public: + write_op(const ConstBufferSequence& buffers) + : buffers_(buffers) + { + } + + engine::want operator()(engine& eng, + boost::system::error_code& ec, + std::size_t& bytes_transferred) const + { + boost::asio::const_buffer buffer = + boost::asio::detail::buffer_sequence_adapter<boost::asio::const_buffer, + ConstBufferSequence>::first(buffers_); + + return eng.write(buffer, ec, bytes_transferred); + } + + template <typename Handler> + void call_handler(Handler& handler, + const boost::system::error_code& ec, + const std::size_t& bytes_transferred) const + { + handler(ec, bytes_transferred); + } + +private: + ConstBufferSequence buffers_; +}; + +#endif // !defined(BOOST_ASIO_ENABLE_OLD_SSL) + +} // namespace detail +} // namespace ssl +} // namespace asio +} // namespace boost + +#include <boost/asio/detail/pop_options.hpp> + +#endif // BOOST_ASIO_SSL_DETAIL_WRITE_OP_HPP |