diff --git a/Builds/VisualStudio2012/RippleD.vcxproj b/Builds/VisualStudio2012/RippleD.vcxproj index 2ea606580..8165e34b5 100644 --- a/Builds/VisualStudio2012/RippleD.vcxproj +++ b/Builds/VisualStudio2012/RippleD.vcxproj @@ -696,12 +696,6 @@ true true - - true - true - true - true - true true diff --git a/Builds/VisualStudio2012/RippleD.vcxproj.filters b/Builds/VisualStudio2012/RippleD.vcxproj.filters index e7e719824..106315f1a 100644 --- a/Builds/VisualStudio2012/RippleD.vcxproj.filters +++ b/Builds/VisualStudio2012/RippleD.vcxproj.filters @@ -160,9 +160,6 @@ {f4e4fbf0-3dd2-4413-8318-9d6bc15ada57} - - {2fdf2a12-4f97-45f6-a63d-7e99e97835dd} - {625992a9-7333-4782-8ee3-6ed072d02fe5} @@ -888,9 +885,6 @@ [1] Ripple\ripple_asio - - [1] Ripple\ripple_asio\tests - [1] Ripple\ripple_asio\boost diff --git a/modules/ripple_asio/ripple_asio.cpp b/modules/ripple_asio/ripple_asio.cpp index 64b823001..1a4ec5c73 100644 --- a/modules/ripple_asio/ripple_asio.cpp +++ b/modules/ripple_asio/ripple_asio.cpp @@ -29,16 +29,4 @@ namespace ripple #include "sockets/ripple_RippleTlsContext.cpp" #include "sockets/ripple_MultiSocket.cpp" -#ifdef _MSC_VER -#pragma warning (push) -#pragma warning (disable: 4100) -#pragma warning (disable: 4127) // conditional expression is constant -#endif - -#include "tests/ripple_AsioTests.cpp" - -#ifdef _MSC_VER -#pragma warning (pop) -#endif - } diff --git a/modules/ripple_asio/tests/ripple_AsioTests.cpp b/modules/ripple_asio/tests/ripple_AsioTests.cpp deleted file mode 100644 index 521009e98..000000000 --- a/modules/ripple_asio/tests/ripple_AsioTests.cpp +++ /dev/null @@ -1,2101 +0,0 @@ -//------------------------------------------------------------------------------ -/* - Copyright (c) 2011-2013, OpenCoin, Inc. -*/ -//============================================================================== - -#ifndef BOOST_ASIO_INITFN_RESULT_TYPE -#define BOOST_ASIO_INITFN_RESULT_TYPE(expr,val) void -#endif - -namespace AsioUnitTestsNamespace -{ - -using namespace boost; - -//------------------------------------------------------------------------------ - -// A handshaking stream that can distinguish multiple protocols -// -// SSL note: -// -// http://stackoverflow.com/questions/8467277/boostasio-and-async-ssl-stream-how-to-detect-end-of-data-connection-close/18024071#18024071 -// -class RippleHandshakeStream - : public asio::socket_base - , public asio::ssl::stream_base -{ -public: - struct SocketInterfaces - : SocketInterface::Socket - , SocketInterface::Stream - , SocketInterface::Handshake - {}; - - enum Status - { - needMore, - proxy, - plain, - ssl - }; - - struct Options - { - Options () - : useClientSsl (false) - , enableServerSsl (false) - , requireServerSsl (false) - , requireServerProxy (false) - { - } - - // Always perform SSL handshake as client role - bool useClientSsl; - - // Enable optional SSL capability as server role - bool enableServerSsl; - - // Require SSL as server role. - // Does not require that enableServerSsl is set - bool requireServerSsl; - - // Require PROXY protocol handshake as server role - bool requireServerProxy; - }; -}; - -template -class RippleHandshakeStreamType : public RippleHandshakeStream -{ -public: - typedef typename remove_reference ::type next_layer_type; - typedef typename next_layer_type::lowest_layer_type lowest_layer_type; - - typedef typename add_reference ::type next_layer_type_ref; - typedef typename asio::ssl::stream SslStreamType; - - typedef RippleHandshakeStreamType ThisType; - - template - explicit RippleHandshakeStreamType (Arg& arg, Options options = Options ()) - : m_options (options) - , m_context (RippleTlsContext::New ()) - , m_next_layer (arg) - , m_io_service (m_next_layer.get_io_service ()) - , m_strand (m_io_service) - , m_status (needMore) - , m_role (Socket::client) - - { - } - - //-------------------------------------------------------------------------- - - asio::io_service& get_io_service () noexcept - { - return m_io_service; - } - - next_layer_type& next_layer () noexcept - { - return m_next_layer; - } - - next_layer_type const& next_layer () const noexcept - { - return m_next_layer; - } - - lowest_layer_type& lowest_layer () noexcept - { - return m_next_layer.lowest_layer (); - } - - lowest_layer_type const& lowest_layer () const noexcept - { - return m_next_layer.lowest_layer (); - } - - //-------------------------------------------------------------------------- - - Socket& stream () const noexcept - { - fatal_assert (m_stream != nullptr); - return *m_stream; - } - - //-------------------------------------------------------------------------- - // - // SocketInterface - // - //-------------------------------------------------------------------------- - - system::error_code cancel (boost::system::error_code& ec) - { - return lowest_layer ().cancel (ec); - } - - system::error_code close (boost::system::error_code& ec) - { - return lowest_layer ().close (ec); - } - - system::error_code shutdown (Socket::shutdown_type what, boost::system::error_code& ec) - { - return lowest_layer ().shutdown (what, ec); - } - - //-------------------------------------------------------------------------- - // - // StreamInterface - // - //-------------------------------------------------------------------------- - - template - std::size_t read_some (MutableBufferSequence const& buffers, system::error_code& ec) - { - if (m_buffer.size () > 0) - { - ec = system::error_code (); - std::size_t const amount = asio::buffer_copy (buffers, m_buffer.data ()); - m_buffer.consume (amount); - return amount; - } - return stream ().read_some (buffers, ec); - } - - template - std::size_t write_some (ConstBufferSequence const& buffers, system::error_code& ec) - { - return stream ().write_some (buffers, ec); - } - - template - BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler, void (boost::system::error_code, std::size_t)) - async_read_some (MutableBufferSequence const& buffers, BOOST_ASIO_MOVE_ARG(ReadHandler) handler) - { - if (m_buffer.size () > 0) - { - // Return the leftover bytes from the handshake - std::size_t const amount = asio::buffer_copy (buffers, m_buffer.data ()); - m_buffer.consume (amount); - return m_io_service.post (m_strand.wrap (boost::bind ( - BOOST_ASIO_MOVE_CAST(ReadHandler)(handler), system::error_code (), amount))); - } - return stream ().async_read_some (buffers, m_strand.wrap (boost::bind ( - BOOST_ASIO_MOVE_CAST(ReadHandler)(handler), boost::asio::placeholders::error, - boost::asio::placeholders::bytes_transferred))); - } - - template - BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler, void (boost::system::error_code, std::size_t)) - async_write_some (ConstBufferSequence const& buffers, BOOST_ASIO_MOVE_ARG(WriteHandler) handler) - { - return stream ().async_write_some (buffers, - BOOST_ASIO_MOVE_CAST(WriteHandler)(handler)); - } - - //-------------------------------------------------------------------------- - - system::error_code handshake (Socket::handshake_type role, system::error_code& ec) - { - Action action = calcAction (role); - - switch (action) - { - default: - case actionPlain: - handshakePlain (ec); - break; - - case actionSsl: - handshakeSsl (ec); - break; - - case actionDetect: - detectHandshake (ec); - if (! ec) - { - action = calcDetectAction (ec); - switch (action) - { - default: - case actionPlain: - handshakePlain (ec); - break; - case actionSsl: - handshakeSsl (ec); - break; - }; - } - break; - } - - return ec; - } - -#if BEAST_ASIO_HAS_BUFFEREDHANDSHAKE - template - boost::system::error_code handshake (handshake_type type, - ConstBufferSequence const& buffers, boost::system::error_code& ec) - { - Action action = calcAction (type); - ec = system::error_code (); - switch (action) - { - default: - case actionPlain: - handshakePlain (buffers, ec); - break; - case actionSsl: - handshakeSsl (buffers, ec); - break; - case actionDetect: - detectHandshake (buffers, ec); - if (! ec) - { - action = calcDetectAction (ec); - switch (action) - { - default: - case actionPlain: - handshakePlain (buffers, ec); - break; - case actionSsl: - handshakeSsl (buffers, ec); - break; - }; - } - break; - } - return ec; - } -#endif - - template - BOOST_ASIO_INITFN_RESULT_TYPE(HandshakeHandler, void (boost::system::error_code)) - async_handshake (handshake_type type, BOOST_ASIO_MOVE_ARG(HandshakeHandler) handler) - { - Action const action = calcAction (type); - switch (action) - { - default: - case actionPlain: - return handshakePlainAsync (BOOST_ASIO_MOVE_CAST(HandshakeHandler)(handler)); - break; - - case actionSsl: - return handshakeSslAsync (BOOST_ASIO_MOVE_CAST(HandshakeHandler)(handler)); - break; - - case actionDetect: - return detectHandshakeAsync (BOOST_ASIO_MOVE_CAST(HandshakeHandler)(handler)); - break; - } - } - -#if BEAST_ASIO_HAS_BUFFEREDHANDSHAKE - template - BOOST_ASIO_INITFN_RESULT_TYPE(BufferedHandshakeHandler, void (boost::system::error_code, std::size_t)) - async_handshake (handshake_type type, const ConstBufferSequence& buffers, - BOOST_ASIO_MOVE_ARG(BufferedHandshakeHandler) handler) - { - Action const action = calcAction (type); - switch (action) - { - default: - case actionPlain: - return handshakePlainAsync (buffers, - BOOST_ASIO_MOVE_CAST(BufferedHandshakeHandler)(handler)); - break; - - case actionSsl: - return handshakeSslAsync (buffers, - BOOST_ASIO_MOVE_CAST(BufferedHandshakeHandler)(handler)); - break; - - case actionDetect: - return detectHandshakeAsync (buffers, - BOOST_ASIO_MOVE_CAST(BufferedHandshakeHandler)(handler)); - break; - } - } -#endif - - system::error_code shutdown (system::error_code& ec) - { - if (m_status == ssl) - { - return m_ssl_stream->shutdown (ec); - } - else - { - // we need to close the lwest layer - return m_next_layer.shutdown (next_layer_type::shutdown_both, ec); - } - } - - template - BOOST_ASIO_INITFN_RESULT_TYPE(ShutdownHandler, void (boost::system::error_code)) - async_shutdown (BOOST_ASIO_MOVE_ARG(ShutdownHandler) handler) - { - if (m_status == ssl) - { - m_ssl_stream->async_shutdown (m_strand.wrap (boost::bind ( - BOOST_ASIO_MOVE_CAST(ShutdownHandler)(handler), - boost::asio::placeholders::error))); - } - else - { - system::error_code ec; - m_next_layer.shutdown (next_layer_type::shutdown_both, ec); - m_io_service.post (m_strand.wrap (boost::bind ( - BOOST_ASIO_MOVE_CAST(ShutdownHandler)(handler), ec))); - } - } - - //-------------------------------------------------------------------------- - - enum Action - { - actionDetect, - actionPlain, - actionSsl, - actionFail - }; - - // Determines what action to take based on - // the stream options and the desired role. - // - Action calcAction (Socket::handshake_type role) - { - m_role = role; - - if (role == Socket::server) - { - if (! m_options.enableServerSsl && - ! m_options.requireServerSsl && - ! m_options.requireServerProxy) - { - return actionPlain; - } - else if (m_options.requireServerSsl && ! m_options.requireServerProxy) - { - return actionSsl; - } - else - { - return actionDetect; - } - } - else if (m_role == Socket::client) - { - if (m_options.useClientSsl) - { - return actionSsl; - } - else - { - return actionPlain; - } - } - - return actionPlain; - } - - // Determines what action to take based on the auto-detected - // handshake, the stream options, and desired role. - // - Action calcDetectAction (system::error_code& ec) - { - ec = system::error_code (); - - if (m_status == plain) - { - if (! m_options.requireServerProxy && ! m_options.requireServerSsl) - { - return actionPlain; - } - else - { - failedHandshake (ec); - return actionFail; - } - } - else if (m_status == ssl) - { - if (! m_options.requireServerProxy) - { - if (m_options.enableServerSsl || m_options.requireServerSsl) - { - return actionSsl; - } - else - { - failedHandshake (ec); - return actionFail; - } - } - else - { - failedHandshake (ec); - return actionFail; - } - } - else if (m_status == proxy) - { - if (m_options.requireServerProxy) - { - // read the rest of the proxy string - // then transition to SSL handshake mode - failedHandshake (ec); - return actionFail; - } - else - { - // Can we make PROXY optional? - failedHandshake (ec); - return actionFail; - } - } - - failedHandshake (ec); - return actionFail; - } - - //-------------------------------------------------------------------------- - - // called when options disallow handshake - void failedHandshake (system::error_code& ec) - { - // VFALCO TODO maybe use a ripple error category? - // set this to something custom that we can recognize later? - ec = asio::error::invalid_argument; - } - - void createPlainStream () - { - m_status = plain; - m_stream = new SocketWrapper (m_next_layer); - } - - void handshakePlain (system::error_code& ec) - { - ec = system::error_code (); - createPlainStream (); - } - - template - void handshakePlain (ConstBufferSequence const& buffers, system::error_code& ec) - { - fatal_assert (asio::buffer_size (buffers) == 0 ); - ec = system::error_code (); - createPlainStream (); - } - - template - BOOST_ASIO_INITFN_RESULT_TYPE(HandshakeHandler, void (boost::system::error_code)) - handshakePlainAsync (BOOST_ASIO_MOVE_ARG(HandshakeHandler) handler) - { - createPlainStream (); - return m_io_service.post (m_strand.wrap (boost::bind ( - BOOST_ASIO_MOVE_CAST(HandshakeHandler)(handler), system::error_code()))); - } - -#if BEAST_ASIO_HAS_BUFFEREDHANDSHAKE - template - BOOST_ASIO_INITFN_RESULT_TYPE(BufferedHandshakeHandler, void (boost::system::error_code, std::size_t)) - handshakePlainAsync (ConstBufferSequence const& buffers, - BOOST_ASIO_MOVE_ARG(BufferedHandshakeHandler) handler) - { - fatal_assert (asio::buffer_size (buffers) == 0); - createPlainStream (); - return m_io_service.post (m_strand.wrap (boost::bind ( - BOOST_ASIO_MOVE_CAST(BufferedHandshakeHandler)(handler), - system::error_code(), 0))); - } -#endif - - void createSslStream () - { - m_status = ssl; - m_ssl_stream = new SslStreamType (m_next_layer, m_context->getBoostContext ()); - m_stream = new SocketWrapper (*m_ssl_stream); - } - - void handshakeSsl (system::error_code& ec) - { - createSslStream (); - m_ssl_stream->handshake (m_role, ec); - } - -#if BEAST_ASIO_HAS_BUFFEREDHANDSHAKE - template - void handshakeSsl (ConstBufferSequence const& buffers, system::error_code& ec) - { - createSslStream (); - m_ssl_stream->handshake (m_role, buffers, ec); - } -#endif - - template - BOOST_ASIO_INITFN_RESULT_TYPE(HandshakeHandler, void (boost::system::error_code)) - handshakeSslAsync (BOOST_ASIO_MOVE_ARG(HandshakeHandler) handler) - { - createSslStream (); - return m_ssl_stream->async_handshake (m_role, - BOOST_ASIO_MOVE_CAST(HandshakeHandler)(handler)); - } - -#if BEAST_ASIO_HAS_BUFFEREDHANDSHAKE - template - BOOST_ASIO_INITFN_RESULT_TYPE (BufferedHandshakeHandler, void (boost::system::error_code, std::size_t)) - handshakeSslAsync (ConstBufferSequence const& buffers, - BOOST_ASIO_MOVE_ARG(BufferedHandshakeHandler) handler) - { - createSslStream (); - return m_ssl_stream->async_handshake (m_role, buffers, - BOOST_ASIO_MOVE_CAST(BufferedHandshakeHandler)(handler)); - } -#endif - - //-------------------------------------------------------------------------- - - enum - { - autoDetectBytes = 5 - }; - - void detectHandshake (system::error_code& ec) - { - // Top up our buffer - bassert (m_buffer.size () == 0); - std::size_t const needed = autoDetectBytes; - std::size_t const amount = m_next_layer.receive ( - m_buffer.prepare (needed), asio::socket_base::message_peek, ec); - m_buffer.commit (amount); - if (! ec) - { - analyzeHandshake (m_buffer.data ()); - m_buffer.consume (amount); - if (m_status == needMore) - ec = asio::error::invalid_argument; // should never happen - } - } - -#if BEAST_ASIO_HAS_BUFFEREDHANDSHAKE - template - void detectHandshake (ConstBufferSequence const& buffers, system::error_code& ec) - { - m_buffer.commit (asio::buffer_copy ( - m_buffer.prepare (asio::buffer_size (buffers)), buffers)); - detectHandshake (ec); - } -#endif - - //-------------------------------------------------------------------------- - - template - void onDetectRead (BOOST_ASIO_MOVE_ARG(HandshakeHandler) handler, - system::error_code const& ec, std::size_t bytes_transferred) - { - m_buffer.commit (bytes_transferred); - - if (! ec) - { - analyzeHandshake (m_buffer.data ()); - - system::error_code ec; - - if (m_status != needMore) - { - m_buffer.consume (bytes_transferred); - - Action action = calcDetectAction (ec); - if (! ec) - { - switch (action) - { - default: - case actionPlain: - handshakePlainAsync ( - BOOST_ASIO_MOVE_CAST(HandshakeHandler)(handler)); - break; - case actionSsl: - handshakeSslAsync ( - BOOST_ASIO_MOVE_CAST(HandshakeHandler)(handler)); - break; - }; - } - } - else - { - ec = asio::error::invalid_argument; - } - - if (ec) - { - m_io_service.post (m_strand.wrap (boost::bind ( - BOOST_ASIO_MOVE_CAST(HandshakeHandler)(handler), ec))); - } - } - } - - template - BOOST_ASIO_INITFN_RESULT_TYPE(HandshakeHandler, void (boost::system::error_code)) - detectHandshakeAsync (BOOST_ASIO_MOVE_ARG(HandshakeHandler) handler) - { - bassert (m_buffer.size () == 0); - return m_next_layer.async_receive ( - m_buffer.prepare (autoDetectBytes), asio::socket_base::message_peek, - m_strand.wrap (boost::bind (&ThisType::onDetectRead , this, - BOOST_ASIO_MOVE_CAST(HandshakeHandler)(handler), - asio::placeholders::error, asio::placeholders::bytes_transferred))); - } - -#if BEAST_ASIO_HAS_BUFFEREDHANDSHAKE - template - BOOST_ASIO_INITFN_RESULT_TYPE(BufferedHandshakeHandler, void (boost::system::error_code, std::size_t)) - detectHandshakeAsync (ConstBufferSequence const& buffers, - BOOST_ASIO_MOVE_ARG(BufferedHandshakeHandler) handler) - { - fatal_error ("unimplemented"); - } -#endif - - //-------------------------------------------------------------------------- - - static inline bool isPrintable (unsigned char c) - { - return (c < 127) && (c > 31); - } - - template - void analyzeHandshake (ConstBufferSequence const& buffers) - { - m_status = needMore; - - unsigned char data [5]; - - std::size_t const bytes = asio::buffer_copy (asio::buffer (data), buffers); - - if (bytes > 0) - { - if ( isPrintable (data [0]) && - ((bytes < 2) || isPrintable (data [1])) && - ((bytes < 3) || isPrintable (data [2])) && - ((bytes < 4) || isPrintable (data [3])) && - ((bytes < 5) || isPrintable (data [4]))) - { - if (bytes < 5 || memcmp (data, "PROXY", 5) != 0) - { - m_status = plain; - } - else - { - m_status = proxy; - } - } - else - { - m_status = ssl; - } - } - } - -private: - Options m_options; - //RippleSslContext m_context; - ScopedPointer m_context; - Stream m_next_layer; - asio::io_service& m_io_service; - asio::io_service::strand m_strand; - Status m_status; - Socket::handshake_type m_role; - ScopedPointer m_stream; - ScopedPointer m_ssl_stream; - asio::streambuf m_buffer; -}; - -//------------------------------------------------------------------------------ -// -// -// -//------------------------------------------------------------------------------ - -class AsioUnitTests : public UnitTest -{ -public: - AsioUnitTests () : UnitTest ("Asio", "ripple", runManual) - { - } - - //-------------------------------------------------------------------------- - - // These are passed as template arguments and package up - // the parameters needed to establish the connection. - - // ip::tcp with v4 addresses - // - struct TcpV6 - { - typedef asio::ip::tcp Protocol; - - static asio::ip::tcp::endpoint server_endpoint () - { - return asio::ip::tcp::endpoint (asio::ip::tcp::v6 (), 1052); - } - - static asio::ip::tcp::endpoint client_endpoint () - { - return asio::ip::tcp::endpoint (asio::ip::address_v6 ().from_string ("::1"), 1052); - } - }; - - // ip::tcp with v6 addresses - // - struct TcpV4 - { - typedef asio::ip::tcp Protocol; - - static asio::ip::tcp::endpoint server_endpoint () - { - return asio::ip::tcp::endpoint (asio::ip::address_v4::any (), 1053); - } - - static asio::ip::tcp::endpoint client_endpoint () - { - return asio::ip::tcp::endpoint (asio::ip::address_v4::loopback (), 1053); - } - }; - - //-------------------------------------------------------------------------- - - // We create our own error category to distinguish unexpected - // errors like connection failures, versus intended errors like - // a planned mismatch in handshakes. - - enum - { - timeout = 1, - unexpected // a unexpected test result was encountered - }; - - struct unit_test_category_t : system::error_category - { - char const* name () const noexcept - { - return "unit_test"; - } - - std::string message (int ev) const - { - switch (ev) - { - case timeout: return "The timeout expired before the test could complete"; - case unexpected: return "An unexpected test result was encountered"; - default: - break; - }; - - return "unknown"; - } - - system::error_condition default_error_condition (int ev) const noexcept - { - return system::error_condition (ev, *this); - } - - bool equivalent (int code, system::error_condition const& condition) const noexcept - { - return default_error_condition (code) == condition; - } - - bool equivalent (system::error_code const& code, int condition) const noexcept - { - return *this == code.category() && code.value() == condition; - } - }; - - static unit_test_category_t& unit_test_category () - { - static unit_test_category_t category; - return category; - } - - //-------------------------------------------------------------------------- - - // These flags get combined to determine the handshaking attributes - // - enum - { - none = 0, - client_ssl = 1, - server_ssl = 2, - server_ssl_required = 4, - server_proxy = 8 - }; - - // The scenario object provides inputs to construct children with - // the test information. It also holds the outputs of the client and - // server threads. - // - class Scenario - { - public: - // Implicit construction from flags - Scenario (int options = 0) - { - handshakeOptions.useClientSsl = (options & client_ssl) != 0; - handshakeOptions.enableServerSsl = (options & (server_ssl | server_ssl_required)) != 0; - handshakeOptions.requireServerSsl = (options & server_ssl_required) != 0; - handshakeOptions.requireServerProxy = (options & server_proxy) !=0; - } - - // inputs - RippleHandshakeStream::Options handshakeOptions; - - // outputs - system::error_code client_error; - system::error_code server_error; - }; - - //-------------------------------------------------------------------------- - - // Common code for client and server tests - // - class BasicTest : public Thread - { - public: - enum - { - // how long to wait until we give up - //milliSecondsToWait = 1000 - //milliSecondsToWait = 20000 - milliSecondsToWait = -1 - }; - - BasicTest (UnitTest& test, - Scenario& scenario, - Socket::handshake_type role) - : Thread ((role == Socket::client) ? "client" : "server") - , m_test (test) - , m_scenario (scenario) - , m_role (role) - { - } - - ~BasicTest () - { - } - - // Called from the unit test thread, reports the - // error to the unit test if it indicates a failure. - // - bool check_success (system::error_code const& ec, bool eofIsOkay = false) - { - if (eofIsOkay && ec == asio::error::eof) - return true; - return m_test.expect ( - (! ec) || (eofIsOkay && ec == asio::error::eof), ec.message ()); - } - - // Called from the thread to check the error code. - // This sets the error code in the scenario appropriately. - // - bool thread_success (system::error_code const& ec, bool eofIsOkay = false) - { - if (! check_success (ec, eofIsOkay)) - { - if (m_role == Socket::server) - m_scenario.server_error = ec; - else - m_scenario.client_error = ec; - return false; - } - return true; - } - - // Called from the thread to check a condition - // This just calls thread_success with a special code if the condition is false - // - bool thread_expect (bool condition) - { - if (! condition) - return thread_success (system::error_code (unexpected, unit_test_category ())); - return true; - } - - virtual system::error_code start (system::error_code& ec) = 0; - - virtual void finish () = 0; - - protected: - UnitTest& m_test; - Scenario& m_scenario; - Socket::handshake_type const m_role; - }; - - //-------------------------------------------------------------------------- - - // Common code for synchronous operations - // - class BasicSync : public BasicTest - { - public: - BasicSync (UnitTest& test, - Scenario& scenario, - Socket::handshake_type role) - : BasicTest (test, scenario, role) - { - } - - void finish () - { - // This is dangerous - if (! stopThread (milliSecondsToWait)) - { - check_success (system::error_code (timeout, unit_test_category ())); - } - } - }; - - //-------------------------------------------------------------------------- - - // Common code for synchronous servers - // - class BasicSyncServer : public BasicSync - { - public: - BasicSyncServer (UnitTest& test, Scenario& scenario) - : BasicSync (test, scenario, Socket::server) - { - } - - void process (Socket& socket, system::error_code& ec) - { - { - asio::streambuf buf (5); - std::size_t const amount = asio::read_until (socket, buf, "hello", ec); - - if (! thread_success (ec)) - return; - - if (! thread_expect (amount == 5)) - return; - - if (! thread_expect (buf.size () == 5)) - return; - } - - { - std::size_t const amount = asio::write (socket, asio::buffer ("goodbye", 7), ec); - - if (! thread_success (ec)) - return; - - if (! thread_expect (amount == 7)) - return; - } - } - }; - - //-------------------------------------------------------------------------- - - // Common code for synchronous clients - // - class BasicSyncClient : public BasicSync - { - public: - BasicSyncClient (UnitTest& test, Scenario& scenario) - : BasicSync (test, scenario, Socket::client) - { - } - - void process (Socket& socket, system::error_code& ec) - { - { - std::size_t const amount = asio::write (socket, asio::buffer ("hello", 5), ec); - - if (! thread_success (ec)) - return; - - if (! thread_expect (amount == 5)) - return; - } - - { - char data [7]; - - size_t const amount = asio::read (socket, asio::buffer (data, 7), ec); - - if (! thread_success (ec, true)) - return; - - if (! thread_expect (amount == 7)) - return; - - thread_expect (memcmp (&data, "goodbye", 7) == 0); - } - - // Wait for 1 byte which should never come. Instead, - // the server should close its end and we will get eof - { - char data [1]; - asio::read (socket, asio::buffer (data, 1), ec); - if (ec == asio::error::eof) - { - ec = system::error_code (); - } - else if (thread_success (ec)) - { - thread_expect (false); - } - } - } - }; - - //-------------------------------------------------------------------------- - - // A synchronous server - // - template - class SyncServer : public BasicSyncServer - { - public: - typedef typename Transport::Protocol Protocol; - typedef typename Protocol::socket SocketType; - typedef typename Protocol::acceptor Acceptor; - typedef typename Protocol::endpoint Endpoint; - - SyncServer (UnitTest& test, Scenario& scenario) - : BasicSyncServer (test, scenario) - , m_acceptor (m_io_service) - , m_socket (m_io_service) - { - } - - system::error_code start (system::error_code& ec) - { - ec = system::error_code (); - - if (! check_success (m_acceptor.open (Transport::server_endpoint ().protocol (), ec))) - return ec; - - if (! check_success (m_acceptor.set_option (typename SocketType::reuse_address (true), ec))) - return ec; - - if (! check_success (m_acceptor.bind (Transport::server_endpoint (), ec))) - return ec; - - if (! check_success (m_acceptor.listen (asio::socket_base::max_connections, ec))) - return ec; - - startThread (); - - return ec; - } - - private: - void run () - { - system::error_code ec; - - if (! thread_success (m_acceptor.accept (m_socket, ec))) - return; - - if (! thread_success (m_acceptor.close (ec))) - return; - - SocketWrapper socket (m_socket); - - process (socket, ec); - - if (! ec) - { - if (! thread_success (m_socket.shutdown (SocketType::shutdown_both, ec))) - return; - - if (! thread_success (m_socket.close (ec))) - return; - } - } - - protected: - asio::io_service m_io_service; - Acceptor m_acceptor; - SocketType m_socket; - }; - - //-------------------------------------------------------------------------- - - // A synchronous client - // - template - class SyncClient : public BasicSyncClient - { - public: - typedef typename Transport::Protocol Protocol; - typedef typename Protocol::socket SocketType; - typedef typename Protocol::acceptor Acceptor; - typedef typename Protocol::endpoint Endpoint; - - SyncClient (UnitTest& test, Scenario& scenario) - : BasicSyncClient (test, scenario) - , m_socket (m_io_service) - { - } - - system::error_code start (system::error_code& ec) - { - ec = system::error_code (); - - startThread (); - - return ec; - } - - private: - void run () - { - system::error_code ec; - - if (! thread_success (m_socket.connect (Transport::client_endpoint (), ec))) - return; - - SocketWrapper socket (m_socket); - - process (socket, ec); - - if (! ec) - { - if (! thread_success (m_socket.shutdown (SocketType::shutdown_both, ec))) - return; - - if (! thread_success (m_socket.close (ec))) - return; - } - } - - private: - asio::io_service m_io_service; - SocketType m_socket; - }; - - //-------------------------------------------------------------------------- - - // A synchronous server that supports a handshake - // - template class HandshakeType> - class HandshakeSyncServer : public BasicSyncServer - { - public: - typedef typename Transport::Protocol Protocol; - typedef typename Protocol::socket SocketType; - typedef typename Protocol::acceptor Acceptor; - typedef typename Protocol::endpoint Endpoint; - - HandshakeSyncServer (UnitTest& test, Scenario& scenario) - : BasicSyncServer (test, scenario) - , m_socket (m_io_service) - , m_acceptor (m_io_service) - , m_handshake (m_socket, m_scenario.handshakeOptions) - { - } - - system::error_code start (system::error_code& ec) - { - ec = system::error_code (); - - if (! check_success (m_acceptor.open (Transport::server_endpoint ().protocol (), ec))) - return ec; - - if (! check_success (m_acceptor.set_option (typename SocketType::reuse_address (true), ec))) - return ec; - - if (! check_success (m_acceptor.bind (Transport::server_endpoint (), ec))) - return ec; - - if (! check_success (m_acceptor.listen (asio::socket_base::max_connections, ec))) - return ec; - - startThread (); - - return ec; - } - - private: - void run () - { - system::error_code ec; - - if (! thread_success (m_acceptor.accept (m_socket, ec))) - return; - - if (! thread_success (m_acceptor.close (ec))) - return; - - SocketWrapper > socket (m_handshake); - - if (! thread_success (socket.handshake (m_role, ec))) - return; - - process (socket, ec); - - if (! ec) - { - // closing the stream also shuts down the socket - if (! thread_success (socket.shutdown (ec), true)) - return; - - if (! thread_success (m_socket.close (ec))) - return; - } - } - - protected: - asio::io_service m_io_service; - SocketType m_socket; - Acceptor m_acceptor; - HandshakeType m_handshake; - }; - - //-------------------------------------------------------------------------- - - // A synchronous client that supports a handshake - // - template class HandshakeType> - class HandshakeSyncClient : public BasicSyncClient - { - public: - typedef typename Transport::Protocol Protocol; - typedef typename Protocol::socket SocketType; - typedef typename Protocol::acceptor Acceptor; - typedef typename Protocol::endpoint Endpoint; - - HandshakeSyncClient (UnitTest& test, Scenario& scenario) - : BasicSyncClient (test, scenario) - , m_socket (m_io_service) - , m_handshake (m_socket, m_scenario.handshakeOptions) - { - } - - system::error_code start (system::error_code& ec) - { - ec = system::error_code (); - - startThread (); - - return ec; - } - - private: - void run () - { - system::error_code ec; - - if (! thread_success (m_socket.connect (Transport::client_endpoint (), ec))) - return; - - SocketWrapper > socket (m_handshake); - - if (! thread_success (socket.handshake (m_role, ec))) - return; - - process (socket, ec); - - if (! ec) - { - // Without doing a shutdown on the handshake stream in the - // client, the call to close the socket will return "short read". - if (! thread_success (socket.shutdown (ec), true)) - return; - - if (! thread_success (m_socket.close (ec))) - return; - } - } - - private: - asio::io_service m_io_service; - SocketType m_socket; - HandshakeType m_handshake; - }; - - //-------------------------------------------------------------------------- - - // Common code for asynchronous operations - // - class BasicAsync : public BasicTest - { - public: - BasicAsync (UnitTest& test, - Scenario& scenario, - Socket::handshake_type role) - : BasicTest (test, scenario, role) - { - } - - system::error_code start (system::error_code& ec) - { - ec = system::error_code (); - - // put the deadline timer here - - on_start (ec); - - if (! ec) - startThread (); - - return ec; - } - - void finish () - { - // wait for io_service::run to return - m_done.wait (); - } - - protected: - virtual asio::io_service& get_io_service () = 0; - virtual Socket& socket () = 0; - - void run () - { - get_io_service ().run (); - m_done.signal (); - } - - virtual void on_start (system::error_code& ec) = 0; - - virtual void on_shutdown (system::error_code const& ec) = 0; - - virtual void closed () = 0; - - protected: - asio::streambuf m_buf; - - private: - WaitableEvent m_done; - }; - - //-------------------------------------------------------------------------- - - // Common code for asynchronous servers - // - class BasicAsyncServer : public BasicAsync - { - public: - BasicAsyncServer (UnitTest& test, Scenario& scenario) - : BasicAsync (test, scenario, Socket::server) - { - } - - void on_accept (system::error_code const& ec) - { - asio::async_read_until (socket (), m_buf, std::string ("hello"), - boost::bind (&BasicAsyncServer::on_read, this, - asio::placeholders::error, asio::placeholders::bytes_transferred)); - } - - void on_read (system::error_code const& ec, std::size_t bytes_transferred) - { - if (thread_success (ec)) - { - if (! thread_expect (bytes_transferred == 5)) - return; - - asio::async_write (socket (), asio::buffer ("goodbye", 7), - boost::bind (&BasicAsyncServer::on_write, this, - asio::placeholders::error, asio::placeholders::bytes_transferred)); - } - } - - void on_write (system::error_code const& ec, std::size_t bytes_transferred) - { - if (thread_success (ec)) - { - if (! thread_expect (bytes_transferred == 7)) - return; - - { - system::error_code ec; - if (! thread_success (socket ().shutdown (Socket::shutdown_both, ec))) - return; - } - - on_shutdown (ec); - } - } - - void on_shutdown (system::error_code const& ec) - { - if (thread_success (ec)) - { - system::error_code ec; - - if (! thread_success (socket ().shutdown (Socket::shutdown_both, ec))) - return; - - if (! thread_success (socket ().close (ec))) - return; - - closed (); - } - } - }; - - //-------------------------------------------------------------------------- - - // Common code for asynchronous clients - // - class BasicAsyncClient : public BasicAsync - { - public: - BasicAsyncClient (UnitTest& test, Scenario& scenario) - : BasicAsync (test, scenario, Socket::client) - { - } - - void on_connect (system::error_code const& ec) - { - if (thread_success (ec)) - { - asio::async_write (socket (), asio::buffer ("hello", 5), - boost::bind (&BasicAsyncClient::on_write, this, - asio::placeholders::error, asio::placeholders::bytes_transferred)); - } - } - - void on_write (system::error_code const& ec, std::size_t bytes_transferred) - { - if (thread_success (ec)) - { - if (! thread_expect (bytes_transferred == 5)) - return; - - asio::async_read_until (socket (), m_buf, std::string ("goodbye"), - boost::bind (&BasicAsyncClient::on_read, this, - asio::placeholders::error, asio::placeholders::bytes_transferred)); - } - } - - void on_read (system::error_code const& ec, std::size_t bytes_transferred) - { - if (thread_success (ec)) - { - if (! thread_expect (bytes_transferred == 7)) - return; - - // should check the data here? - m_buf.consume (bytes_transferred); - - asio::async_read (socket (), m_buf.prepare (1), - boost::bind (&BasicAsyncClient::on_read_final, this, - asio::placeholders::error, asio::placeholders::bytes_transferred)); - } - } - - void on_read_final (system::error_code const& ec, std::size_t bytes_transferred) - { - if (ec == asio::error::eof) - { - system::error_code ec; // to hide the eof - - if (! thread_success (socket ().shutdown (Socket::shutdown_both, ec))) - return; - - on_shutdown (ec); - } - else if (thread_success (ec)) - { - thread_expect (false); - } - } - - void on_shutdown (system::error_code const& ec) - { - if (thread_success (ec)) - { - system::error_code ec; - - if (! thread_success (socket ().shutdown (Socket::shutdown_both, ec))) - return; - - if (! thread_success (socket ().close (ec))) - return; - - closed (); - } - } - }; - - //-------------------------------------------------------------------------- - - template - class AsyncServer : public BasicAsyncServer - { - public: - typedef typename Transport::Protocol Protocol; - typedef typename Protocol::socket SocketType; - typedef typename Protocol::acceptor Acceptor; - typedef typename Protocol::endpoint Endpoint; - - AsyncServer (UnitTest& test, Scenario& scenario) - : BasicAsyncServer (test, scenario) - , m_acceptor (m_io_service) - , m_socket (m_io_service) - , m_socketWrapper (m_socket) - { - } - - asio::io_service& get_io_service () - { - return m_io_service; - } - - Socket& socket () - { - return m_socketWrapper; - } - - void on_start (system::error_code& ec) - { - if (! check_success (m_acceptor.open (Transport::server_endpoint ().protocol (), ec))) - return; - - if (! check_success (m_acceptor.set_option (typename SocketType::reuse_address (true), ec))) - return; - - if (! check_success (m_acceptor.bind (Transport::server_endpoint (), ec))) - return; - - if (! check_success (m_acceptor.listen (asio::socket_base::max_connections, ec))) - return; - - m_acceptor.async_accept (m_socket, boost::bind ( - &BasicAsyncServer::on_accept, this, asio::placeholders::error)); - } - - void closed () - { - system::error_code ec; - if (! thread_success (m_acceptor.close (ec))) - return; - } - - private: - asio::io_service m_io_service; - Acceptor m_acceptor; - SocketType m_socket; - asio::streambuf m_buf; - SocketWrapper m_socketWrapper; - }; - - //-------------------------------------------------------------------------- - - // An asynchronous client - // - template - class AsyncClient : public BasicAsyncClient - { - public: - typedef typename Transport::Protocol Protocol; - typedef typename Protocol::socket SocketType; - typedef typename Protocol::acceptor Acceptor; - typedef typename Protocol::endpoint Endpoint; - - AsyncClient (UnitTest& test, Scenario& scenario) - : BasicAsyncClient (test, scenario) - , m_socket (m_io_service) - , m_socketWrapper (m_socket) - { - } - - asio::io_service& get_io_service () - { - return m_io_service; - } - - Socket& socket () - { - return m_socketWrapper; - } - - void on_start (system::error_code& ec) - { - m_socket.async_connect (Transport::client_endpoint (), - boost::bind (&BasicAsyncClient::on_connect, this, asio::placeholders::error)); - } - - void closed () - { - } - - private: - asio::io_service m_io_service; - SocketType m_socket; - asio::streambuf m_buf; - SocketWrapper m_socketWrapper; - }; - - //-------------------------------------------------------------------------- - - // An asynchronous handshaking server - // - template class HandshakeType> - class HandshakeAsyncServer : public BasicAsyncServer - { - public: - typedef typename Transport::Protocol Protocol; - typedef typename Protocol::socket SocketType; - typedef typename Protocol::acceptor Acceptor; - typedef typename Protocol::endpoint Endpoint; - typedef HandshakeType StreamType; - typedef HandshakeAsyncServer ThisType; - - HandshakeAsyncServer (UnitTest& test, Scenario& scenario) - : BasicAsyncServer (test, scenario) - , m_acceptor (m_io_service) - , m_socket (m_acceptor.get_io_service ()) - , m_stream (m_socket, m_scenario.handshakeOptions) - , m_socketWrapper (m_stream) - { - } - - asio::io_service& get_io_service () - { - return m_io_service; - } - - Socket& socket () - { - return m_socketWrapper; - } - - void on_start (system::error_code& ec) - { - if (! check_success (m_acceptor.open (Transport::server_endpoint ().protocol (), ec))) - return; - - if (! check_success (m_acceptor.set_option (typename SocketType::reuse_address (true), ec))) - return; - - if (! check_success (m_acceptor.bind (Transport::server_endpoint (), ec))) - return; - - if (! check_success (m_acceptor.listen (asio::socket_base::max_connections, ec))) - return; - - m_acceptor.async_accept (m_socket, boost::bind ( - &ThisType::on_accept, this, asio::placeholders::error)); - } - - void on_accept (system::error_code const& ec) - { - { - system::error_code ec; - if (! thread_success (m_acceptor.close (ec))) - return; - } - - if (thread_success (ec)) - { - socket ().async_handshake (Socket::server, - boost::bind (&ThisType::on_handshake, this, asio::placeholders::error)); - } - } - - void on_handshake (system::error_code const& ec) - { - if (thread_success (ec)) - { - asio::async_read_until (socket (), m_buf, std::string ("hello"), - boost::bind (&ThisType::on_read, this, - asio::placeholders::error, asio::placeholders::bytes_transferred)); - } - } - - void on_read (system::error_code const& ec, std::size_t bytes_transferred) - { - if (thread_success (ec)) - { - if (! thread_expect (bytes_transferred == 5)) - return; - - asio::async_write (socket (), asio::buffer ("goodbye", 7), - boost::bind (&ThisType::on_write, this, - asio::placeholders::error, asio::placeholders::bytes_transferred)); - } - } - - void on_write (system::error_code const& ec, std::size_t bytes_transferred) - { - if (thread_success (ec)) - { - if (! thread_expect (bytes_transferred == 7)) - return; - - socket ().async_shutdown (boost::bind (&ThisType::on_shutdown, this, - asio::placeholders::error)); - } - } - - void on_shutdown (system::error_code const& ec) - { - if (thread_success (ec, true)) - { - system::error_code ec; - - if (! thread_success (socket ().close (ec))) - return; - - closed (); - } - } - - void closed () - { - } - - private: - asio::io_service m_io_service; - Acceptor m_acceptor; - SocketType m_socket; - asio::streambuf m_buf; - StreamType m_stream; - SocketWrapper m_socketWrapper; - }; - - //-------------------------------------------------------------------------- - - // An asynchronous handshaking client - // - template class HandshakeType> - class HandshakeAsyncClient : public BasicAsyncClient - { - public: - typedef typename Transport::Protocol Protocol; - typedef typename Protocol::socket SocketType; - typedef typename Protocol::acceptor Acceptor; - typedef typename Protocol::endpoint Endpoint; - typedef HandshakeType StreamType; - typedef HandshakeAsyncClient ThisType; - - HandshakeAsyncClient (UnitTest& test, Scenario& scenario) - : BasicAsyncClient (test, scenario) - , m_socket (m_io_service) - , m_stream (m_socket, m_scenario.handshakeOptions) - , m_socketWrapper (m_stream) - { - } - - asio::io_service& get_io_service () - { - return m_io_service; - } - - Socket& socket () - { - return m_socketWrapper; - } - - void on_start (system::error_code& ec) - { - m_socket.async_connect (Transport::client_endpoint (), boost::bind ( - &ThisType::on_connect, this, asio::placeholders::error)); - } - - void on_connect (system::error_code const& ec) - { - if (thread_success (ec)) - { - socket ().async_handshake (Socket::client, - boost::bind (&ThisType::on_handshake, this, asio::placeholders::error)); - } - } - - void on_handshake (system::error_code const& ec) - { - if (thread_success (ec)) - { - asio::async_write (socket (), asio::buffer ("hello", 5), - boost::bind (&ThisType::on_write, this, - asio::placeholders::error, asio::placeholders::bytes_transferred)); - } - } - - void on_write (system::error_code const& ec, std::size_t bytes_transferred) - { - if (thread_success (ec)) - { - if (! thread_expect (bytes_transferred == 5)) - return; - - asio::async_read_until (socket (), m_buf, std::string ("goodbye"), - boost::bind (&ThisType::on_read, this, - asio::placeholders::error, asio::placeholders::bytes_transferred)); - } - } - - void on_read (system::error_code const& ec, std::size_t bytes_transferred) - { - if (thread_success (ec)) - { - if (! thread_expect (bytes_transferred == 7)) - return; - - m_buf.consume (bytes_transferred); - - asio::async_read (socket (), m_buf.prepare (1), boost::bind (&ThisType::on_read_final, - this, asio::placeholders::error, asio::placeholders::bytes_transferred)); - } - } - - void on_read_final (system::error_code const& ec, std::size_t bytes_transferred) - { - if (ec == asio::error::eof) - { - socket ().async_shutdown (boost::bind (&ThisType::on_shutdown, this, - asio::placeholders::error)); - } - else if (thread_success (ec)) - { - thread_expect (false); - } - } - - void on_shutdown (system::error_code const& ec) - { - if (thread_success (ec, true)) - { - system::error_code ec; - - if (! thread_success (socket ().close (ec))) - return; - - closed (); - } - } - - void closed () - { - } - - private: - asio::io_service m_io_service; - SocketType m_socket; - asio::streambuf m_buf; - StreamType m_stream; - SocketWrapper m_socketWrapper; - }; - - //-------------------------------------------------------------------------- - - // Analyzes the client and server settings to - // determine if the correct test case outcome was achieved. - // - // This relies on distinguishing abnormal errors (like a socket connect - // failing, which should never happen) from errors that arise naturally - // because of the test parameters. - // - // For example, a non-ssl client attempting a - // connection to a server that has ssl required. - // - void checkScenario (Scenario const& s) - { - if (s.handshakeOptions.useClientSsl) - { - if (s.handshakeOptions.enableServerSsl) - { - } - else - { - // client ssl on, but server ssl disabled - expect (s.client_error.value () != 0); - } - } - } - - //-------------------------------------------------------------------------- - - // Test any generic synchronous client/server pair - // - template - void testScenario (Scenario scenario = Scenario ()) - { - String s; - s << "scenario <" - << typeid (ServerType).name () << ", " - << typeid (ClientType).name () << ">"; - beginTestCase (s); - - system::error_code ec; - - try - { - ServerType server (*this, scenario); - - try - { - ClientType client (*this, scenario); - - server.start (ec); - - if (expect (! ec, ec.message ())) - { - client.start (ec); - - if (expect (! ec, ec.message ())) - { - // at this point the threads for the client and - // server should be doing their thing. so we will - // just try to stop them within some reasonable - // amount of time. by then they should have finished - // what they were doing and set the error codes in - // the scenario, or they will have gotten hung and - // will need to be killed. If they hang, we will - // record a timeout in the corresponding scenario - // error code and deal with it. - } - - client.finish (); - } - - server.finish (); - - // only check scenario results if we - // didn't get an unexpected error - if (! ec) - { - checkScenario (scenario); - } - } - catch (...) - { - failException (); - } - } - catch (...) - { - failException (); - } - } - - //-------------------------------------------------------------------------- - - // Test wrapper and facade assignment and lifetime management - // - void testFacade () - { - typedef asio::ip::tcp Protocol; - typedef Protocol::socket SocketType; - -#if 0 - beginTestCase ("facade"); - - asio::io_service ios; - - { - SharedWrapper f1 (new SocketType (ios)); - SharedWrapper f2 (f1); - - expect (f1 == f2); - } - - { - SharedWrapper f1 (new SocketType (ios)); - SharedWrapper f2 (new SocketType (ios)); - - expect (f1 != f2); - f2 = f1; - expect (f1 == f2); - } -#endif - // test typedef inheritance - { - typedef SocketWrapper SocketWrapper; - //typedef SocketWrapper::lowest_layer_type lowest_layer_type; - } - } - - //-------------------------------------------------------------------------- - - template - void testHandshakes () - { - testScenario (client_ssl | server_ssl); - testScenario (client_ssl | server_ssl_required); -#if 0 - testScenario (client_ssl); - testScenario (server_ssl); - testScenario (server_ssl_required); -#endif - } - - - template - void testTransport () - { -#if 1 - // Synchronous - testScenario , SyncClient > (); - testScenario , - SyncClient > (); - testScenario , - HandshakeSyncClient > (); - testScenario , - HandshakeSyncClient > (); -#endif - - // Asynchronous - testScenario , SyncClient > (); -#if 1 - testScenario , AsyncClient > (); - testScenario , AsyncClient > (); - - // Asynchronous - testScenario , - HandshakeAsyncClient > (); - testScenario , - HandshakeSyncClient > (); - testScenario , - HandshakeAsyncClient > (); - - // Handshaking - testHandshakes , - HandshakeSyncClient > (); - testHandshakes , - HandshakeAsyncClient > (); - testHandshakes , - HandshakeSyncClient > (); - testHandshakes , - HandshakeAsyncClient > (); -#endif - } - -//------------------------------------------------------------------------------ - - void runTest () - { - testFacade (); - testTransport (); - testTransport (); - } -}; - -static AsioUnitTests asioUnitTests; - -} - - -/* - -What we want is a MultiSocket - Derived from beast::Socket so it can be used generically - -BUT, conforms to - - -*/