TestPeer boost::asio Socket and UnitTest framework

This commit is contained in:
Vinnie Falco
2013-08-09 19:39:16 -07:00
parent 98352429c2
commit 88ffd3cdfb
31 changed files with 2487 additions and 271 deletions

View File

@@ -75,8 +75,21 @@
<ClInclude Include="..\..\modules\beast_asio\sockets\beast_SocketBase.h" />
<ClInclude Include="..\..\modules\beast_asio\sockets\beast_SocketInterface.h" />
<ClInclude Include="..\..\modules\beast_asio\sockets\beast_SocketWrapper.h" />
<ClInclude Include="..\..\modules\beast_asio\sockets\beast_SocketWrapperBasics.h" />
<ClInclude Include="..\..\modules\beast_asio\sockets\beast_SslContext.h" />
<ClInclude Include="..\..\modules\beast_asio\system\beast_BoostIncludes.h" />
<ClInclude Include="..\..\modules\beast_asio\tests\beast_TestPeer.h" />
<ClInclude Include="..\..\modules\beast_asio\tests\beast_TestPeerBasics.h" />
<ClInclude Include="..\..\modules\beast_asio\tests\beast_TestPeerDetails.h" />
<ClInclude Include="..\..\modules\beast_asio\tests\beast_TestPeerLogic.h" />
<ClInclude Include="..\..\modules\beast_asio\tests\beast_TestPeerTest.h" />
<ClInclude Include="..\..\modules\beast_asio\tests\detail\beast_TestPeerDetailsTcp.h" />
<ClInclude Include="..\..\modules\beast_asio\tests\detail\beast_TestPeerLogicAsyncClient.h" />
<ClInclude Include="..\..\modules\beast_asio\tests\detail\beast_TestPeerLogicAsyncServer.h" />
<ClInclude Include="..\..\modules\beast_asio\tests\detail\beast_TestPeerLogicSyncClient.h" />
<ClInclude Include="..\..\modules\beast_asio\tests\detail\beast_TestPeerLogicSyncServer.h" />
<ClInclude Include="..\..\modules\beast_asio\tests\detail\beast_TestPeerTestType.h" />
<ClInclude Include="..\..\modules\beast_asio\tests\detail\beast_TestPeerType.h" />
<ClInclude Include="..\..\modules\beast_basics\beast_basics.h" />
<ClInclude Include="..\..\modules\beast_basics\events\beast_DeadlineTimer.h" />
<ClInclude Include="..\..\modules\beast_basics\events\beast_OncePerSecond.h" />
@@ -279,12 +292,60 @@
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\..\modules\beast_asio\beast_asio.cpp" />
<ClCompile Include="..\..\modules\beast_asio\sockets\beast_Socket.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\modules\beast_asio\sockets\beast_SocketBase.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\modules\beast_asio\sockets\beast_SslContext.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\modules\beast_asio\tests\beast_TestPeerTests.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\modules\beast_asio\tests\beast_TestPeerBasics.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\modules\beast_asio\tests\detail\beast_TestPeerLogicAsyncClient.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\modules\beast_asio\tests\detail\beast_TestPeerLogicAsyncServer.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\modules\beast_asio\tests\detail\beast_TestPeerLogicSyncClient.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\modules\beast_asio\tests\detail\beast_TestPeerLogicSyncServer.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\modules\beast_basics\beast_basics.cpp" />
<ClCompile Include="..\..\modules\beast_basics\events\beast_DeadlineTimer.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>

View File

@@ -149,6 +149,12 @@
<Filter Include="beast_asio\system">
<UniqueIdentifier>{c7a576bb-27b2-486e-aa14-3c51aa86c50f}</UniqueIdentifier>
</Filter>
<Filter Include="beast_asio\tests">
<UniqueIdentifier>{422da6a1-e57e-4a96-9fce-e5958c16026e}</UniqueIdentifier>
</Filter>
<Filter Include="beast_asio\tests\detail">
<UniqueIdentifier>{5d8ed68a-e3b5-49f3-938b-fbe7365f6293}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\modules\beast_core\beast_core.h">
@@ -770,6 +776,45 @@
<ClInclude Include="..\..\modules\beast_asio\sockets\beast_SslContext.h">
<Filter>beast_asio\sockets</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_asio\tests\beast_TestPeer.h">
<Filter>beast_asio\tests</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_asio\tests\beast_TestPeerBasics.h">
<Filter>beast_asio\tests</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_asio\sockets\beast_SocketWrapperBasics.h">
<Filter>beast_asio\sockets</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_asio\tests\detail\beast_TestPeerType.h">
<Filter>beast_asio\tests\detail</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_asio\tests\beast_TestPeerLogic.h">
<Filter>beast_asio\tests</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_asio\tests\detail\beast_TestPeerDetailsTcp.h">
<Filter>beast_asio\tests\detail</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_asio\tests\beast_TestPeerDetails.h">
<Filter>beast_asio\tests</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_asio\tests\beast_TestPeerTest.h">
<Filter>beast_asio\tests</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_asio\tests\detail\beast_TestPeerTestType.h">
<Filter>beast_asio\tests\detail</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_asio\tests\detail\beast_TestPeerLogicAsyncClient.h">
<Filter>beast_asio\tests\detail</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_asio\tests\detail\beast_TestPeerLogicAsyncServer.h">
<Filter>beast_asio\tests\detail</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_asio\tests\detail\beast_TestPeerLogicSyncClient.h">
<Filter>beast_asio\tests\detail</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_asio\tests\detail\beast_TestPeerLogicSyncServer.h">
<Filter>beast_asio\tests\detail</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\..\modules\beast_core\beast_core.cpp">
@@ -1192,6 +1237,30 @@
<ClCompile Include="..\..\modules\beast_asio\sockets\beast_SslContext.cpp">
<Filter>beast_asio\sockets</Filter>
</ClCompile>
<ClCompile Include="..\..\modules\beast_asio\tests\beast_TestPeerBasics.cpp">
<Filter>beast_asio\tests</Filter>
</ClCompile>
<ClCompile Include="..\..\modules\beast_asio\tests\beast_TestPeerTests.cpp">
<Filter>beast_asio\tests</Filter>
</ClCompile>
<ClCompile Include="..\..\modules\beast_asio\sockets\beast_Socket.cpp">
<Filter>beast_asio\sockets</Filter>
</ClCompile>
<ClCompile Include="..\..\modules\beast_asio\sockets\beast_SocketBase.cpp">
<Filter>beast_asio\sockets</Filter>
</ClCompile>
<ClCompile Include="..\..\modules\beast_asio\tests\detail\beast_TestPeerLogicAsyncClient.cpp">
<Filter>beast_asio\tests\detail</Filter>
</ClCompile>
<ClCompile Include="..\..\modules\beast_asio\tests\detail\beast_TestPeerLogicAsyncServer.cpp">
<Filter>beast_asio\tests\detail</Filter>
</ClCompile>
<ClCompile Include="..\..\modules\beast_asio\tests\detail\beast_TestPeerLogicSyncClient.cpp">
<Filter>beast_asio\tests\detail</Filter>
</ClCompile>
<ClCompile Include="..\..\modules\beast_asio\tests\detail\beast_TestPeerLogicSyncServer.cpp">
<Filter>beast_asio\tests\detail</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<Text Include="..\..\TODO.txt" />

View File

@@ -24,6 +24,16 @@
namespace beast
{
#include "sockets/beast_SocketBase.cpp"
#include "sockets/beast_Socket.cpp"
#include "sockets/beast_SslContext.cpp"
#include "tests/beast_TestPeerBasics.cpp"
#include "tests/beast_TestPeerTests.cpp"
#include "tests/detail/beast_TestPeerLogicSyncServer.cpp"
#include "tests/detail/beast_TestPeerLogicSyncClient.cpp"
#include "tests/detail/beast_TestPeerLogicAsyncServer.cpp"
#include "tests/detail/beast_TestPeerLogicAsyncClient.cpp"
}

View File

@@ -51,10 +51,25 @@ namespace beast
#include "sockets/beast_SocketBase.h"
#include "sockets/beast_Socket.h"
#include "sockets/beast_SocketInterface.h"
#include "sockets/beast_SocketWrapperBasics.h"
#include "sockets/beast_SocketWrapper.h"
#include "sockets/beast_SharedSocket.h"
#include "sockets/beast_SslContext.h"
#include "tests/beast_TestPeerBasics.h"
#include "tests/beast_TestPeer.h"
#include "tests/beast_TestPeerDetails.h"
#include "tests/beast_TestPeerLogic.h"
#include "tests/beast_TestPeerTest.h"
#include "tests/detail/beast_TestPeerType.h"
#include "tests/detail/beast_TestPeerTestType.h"
#include "tests/detail/beast_TestPeerDetailsTcp.h"
#include "tests/detail/beast_TestPeerLogicSyncServer.h"
#include "tests/detail/beast_TestPeerLogicSyncClient.h"
#include "tests/detail/beast_TestPeerLogicAsyncServer.h"
#include "tests/detail/beast_TestPeerLogicAsyncClient.h"
}
#endif

View File

@@ -0,0 +1,249 @@
//------------------------------------------------------------------------------
/*
This file is part of Beast: https://github.com/vinniefalco/Beast
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
Socket::~Socket ()
{
}
//------------------------------------------------------------------------------
//
// General
//
//------------------------------------------------------------------------------
bool Socket::requires_handshake ()
{
return false;
}
//------------------------------------------------------------------------------
//
// SocketInterface::Close
//
//------------------------------------------------------------------------------
boost::system::error_code Socket::close (boost::system::error_code& ec)
{
return pure_virtual (ec);
}
//------------------------------------------------------------------------------
//
// SocketInterface::Acceptor
//
//------------------------------------------------------------------------------
boost::system::error_code Socket::accept (Socket&, boost::system::error_code& ec)
{
return pure_virtual (ec);
}
BEAST_ASIO_INITFN_RESULT_TYPE_MEMBER(Socket::ErrorCall, void (boost::system::error_code))
Socket::async_accept (Socket&, BOOST_ASIO_MOVE_ARG(ErrorCall) handler)
{
#if BEAST_ASIO_HAS_FUTURE_RETURNS
boost::asio::detail::async_result_init<
ErrorCall, void (boost::system::error_code)> init(
BOOST_ASIO_MOVE_CAST(ErrorCall)(handler));
boost::system::error_code ec;
ec = pure_virtual (ec);
get_io_service ().post (boost::bind (
BOOST_ASIO_MOVE_CAST(ErrorCall)(handler), ec));
return init.result.get();
#else
boost::system::error_code ec;
ec = pure_virtual (ec);
get_io_service ().post (boost::bind (
BOOST_ASIO_MOVE_CAST(ErrorCall)(handler), ec));
#endif
}
//------------------------------------------------------------------------------
//
// SocketInterface::LowestLayer
//
//------------------------------------------------------------------------------
void* Socket::lowest_layer_raw (char const*) const
{
pure_virtual ();
return nullptr;
}
//--------------------------------------------------------------------------
//
// SocketInterface::Socket
//
//--------------------------------------------------------------------------
boost::system::error_code Socket::cancel (boost::system::error_code& ec)
{
return pure_virtual (ec);
}
boost::system::error_code Socket::shutdown (shutdown_type, boost::system::error_code& ec)
{
return pure_virtual (ec);
}
//--------------------------------------------------------------------------
//
// SocketInterface::Stream
//
//--------------------------------------------------------------------------
std::size_t Socket::read_some (MutableBuffers const&, boost::system::error_code& ec)
{
pure_virtual (ec);
return 0;
}
std::size_t Socket::write_some (ConstBuffers const&, boost::system::error_code& ec)
{
pure_virtual (ec);
return 0;
}
BEAST_ASIO_INITFN_RESULT_TYPE_MEMBER(Socket::TransferCall, void (boost::system::error_code, std::size_t))
Socket::async_read_some (MutableBuffers const&, BOOST_ASIO_MOVE_ARG(TransferCall) handler)
{
#if BEAST_ASIO_HAS_FUTURE_RETURNS
boost::asio::detail::async_result_init<
TransferCall, void (boost::system::error_code, std::size_t)> init(
BOOST_ASIO_MOVE_CAST(TransferCall)(handler));
boost::system::error_code ec;
ec = pure_virtual (ec);
get_io_service ().post (boost::bind (BOOST_ASIO_MOVE_CAST(TransferCall)(handler), ec, 0));
return init.result.get();
#else
boost::system::error_code ec;
ec = pure_virtual (ec);
get_io_service ().post (boost::bind (BOOST_ASIO_MOVE_CAST(TransferCall)(handler), ec, 0));
#endif
}
BEAST_ASIO_INITFN_RESULT_TYPE_MEMBER(Socket::TransferCall, void (boost::system::error_code, std::size_t))
Socket::async_write_some (ConstBuffers const&, BOOST_ASIO_MOVE_ARG(TransferCall) handler)
{
#if BEAST_ASIO_HAS_FUTURE_RETURNS
boost::asio::detail::async_result_init<
TransferCall, void (boost::system::error_code, std::size_t)> init(
BOOST_ASIO_MOVE_CAST(TransferCall)(handler));
boost::system::error_code ec;
ec = pure_virtual (ec);
get_io_service ().post (boost::bind (
BOOST_ASIO_MOVE_CAST(TransferCall)(handler), ec, 0));
return init.result.get();
#else
boost::system::error_code ec;
ec = pure_virtual (ec);
get_io_service ().post (boost::bind (
BOOST_ASIO_MOVE_CAST(TransferCall)(handler), ec, 0));
#endif
}
//--------------------------------------------------------------------------
//
// SocketInterface::Handshake
//
//--------------------------------------------------------------------------
boost::system::error_code Socket::handshake (handshake_type, boost::system::error_code& ec)
{
return pure_virtual (ec);
}
BEAST_ASIO_INITFN_RESULT_TYPE_MEMBER(Socket::ErrorCall, void (boost::system::error_code))
Socket::async_handshake (handshake_type, BOOST_ASIO_MOVE_ARG(ErrorCall) handler)
{
#if BEAST_ASIO_HAS_FUTURE_RETURNS
boost::asio::detail::async_result_init<
ErrorCall, void (boost::system::error_code)> init(
BOOST_ASIO_MOVE_CAST(ErrorCall)(handler));
boost::system::error_code ec;
ec = pure_virtual (ec);
get_io_service ().post (boost::bind (
BOOST_ASIO_MOVE_CAST(ErrorCall)(handler), ec));
return init.result.get();
#else
boost::system::error_code ec;
ec = pure_virtual (ec);
get_io_service ().post (boost::bind (
BOOST_ASIO_MOVE_CAST(ErrorCall)(handler), ec));
#endif
}
//--------------------------------------------------------------------------
#if BEAST_ASIO_HAS_BUFFEREDHANDSHAKE
boost::system::error_code Socket::handshake (handshake_type,
ConstBuffers const&, boost::system::error_code& ec)
{
return pure_virtual (ec);
}
BEAST_ASIO_INITFN_RESULT_TYPE_MEMBER(Socket::TransferCall, void (boost::system::error_code, std::size_t))
Socket::async_handshake (handshake_type, ConstBuffers const&,
BOOST_ASIO_MOVE_ARG(TransferCall) handler)
{
#if BEAST_ASIO_HAS_FUTURE_RETURNS
boost::asio::detail::async_result_init<
TransferCall, void (boost::system::error_code, std::size_t)> init(
BOOST_ASIO_MOVE_CAST(TransferCall)(handler));
boost::system::error_code ec;
ec = pure_virtual (ec);
get_io_service ().post (boost::bind (
BOOST_ASIO_MOVE_CAST(TransferCall)(handler), ec, 0));
return init.result.get();
#else
boost::system::error_code ec;
ec = pure_virtual (ec);
get_io_service ().post (boost::bind (
BOOST_ASIO_MOVE_CAST(TransferCall)(handler), ec, 0));
#endif
}
#endif
boost::system::error_code Socket::shutdown (boost::system::error_code& ec)
{
return pure_virtual (ec);
}
BEAST_ASIO_INITFN_RESULT_TYPE_MEMBER(Socket::ErrorCall, void (boost::system::error_code))
Socket::async_shutdown (BOOST_ASIO_MOVE_ARG(ErrorCall) handler)
{
#if BEAST_ASIO_HAS_FUTURE_RETURNS
boost::asio::detail::async_result_init<
ErrorCall, void (boost::system::error_code, std::size_t)> init(
BOOST_ASIO_MOVE_CAST(ErrorCall)(handler));
boost::system::error_code ec;
ec = pure_virtual (ec);
get_io_service ().post (boost::bind (
BOOST_ASIO_MOVE_CAST(ErrorCall)(handler), ec));
return init.result.get();
#else
boost::system::error_code ec;
ec = pure_virtual (ec);
get_io_service ().post (boost::bind (
BOOST_ASIO_MOVE_CAST(ErrorCall)(handler), ec));
#endif
}

View File

@@ -46,38 +46,29 @@ class Socket
, public boost::asio::socket_base
{
public:
virtual ~Socket () { }
virtual ~Socket ();
//--------------------------------------------------------------------------
//
// General attributes
// General
//
//--------------------------------------------------------------------------
#if 0
typedef Socket next_layer_type;
typedef Socket lowest_layer_type;
virtual next_layer_type& next_layer () = 0;
virtual next_layer_type const& next_layer () const = 0;
virtual lowest_layer_type& lowest_layer () = 0;
virtual lowest_layer_type const& lowest_layer () const = 0;
#endif
virtual boost::asio::io_service& get_io_service () = 0;
/** Determines if the underlying stream requires a handshake.
If is_handshaked is true, it will be necessary to call handshake or
If requires_handshake is true, it will be necessary to call handshake or
async_handshake after the connection is established. Furthermore it
will be necessary to call the shutdown member from the
HandshakeInterface to close the connection. Do not close the underlying
socket or else the closure will not be graceful. Only one side should
initiate the handshaking shutdon. The other side should observe it.
Which side does what is up to the user.
The default version returns false
*/
virtual bool is_handshaked () = 0;
virtual bool requires_handshake ();
/** Retrieve the underlying object.
Returns nullptr if the implementation doesn't match. Usually
@@ -88,27 +79,127 @@ public:
void set_options (Socket& socket)
{
bost::boost::asio::ip::tcp::socket* sock =
socket.native_object <bost::boost::asio::ip::tcp::socket> ();
typedef bost::boost::asio::ip::tcp Protocol;
typedef Protocol::socket;
Protocol::socket* const sock =
socket.this_layer <Protocol::socket> ();
if (sock != nullptr)
sock->set_option (
boost::boost::asio::ip::tcp::no_delay (true));
Protocol::no_delay (true));
}
@endcode
*/
template <class Object>
Object& native_object ()
Object& this_layer ()
{
void* const object = native_object_raw ();
Object* object (this_layer_ptr <Object> ());
if (object == nullptr)
Throw (std::bad_cast (), __FILE__, __LINE__);
return *static_cast <Object*> (object);
return *object;
}
virtual void* native_object_raw () = 0;
template <class Object>
Object const& this_layer () const
{
Object const* object (this_layer_ptr <Object> ());
if (object == nullptr)
Throw (std::bad_cast (), __FILE__, __LINE__);
return *object;
}
template <class Object>
Object* this_layer_ptr ()
{
return static_cast <Object*> (
this_layer_raw (typeid (Object).name ()));
}
template <class Object>
Object const* this_layer_ptr () const
{
return static_cast <Object const*> (
this_layer_raw (typeid (Object).name ()));
}
// Shouldn't call this directly, use this_layer<> instead
virtual void* this_layer_raw (char const* type_name) const = 0;
//--------------------------------------------------------------------------
//
// SocketInterface::Close
//
//--------------------------------------------------------------------------
void close ()
{
boost::system::error_code ec;
throw_error (close (ec));
}
virtual boost::system::error_code close (boost::system::error_code& ec);
//--------------------------------------------------------------------------
//
// SocketInterface::Acceptor
//
//--------------------------------------------------------------------------
virtual boost::system::error_code accept (Socket& peer, boost::system::error_code& ec);
template <class AcceptHandler>
BOOST_ASIO_INITFN_RESULT_TYPE(AcceptHandler, void (boost::system::error_code))
async_accept (Socket& peer, BOOST_ASIO_MOVE_ARG(AcceptHandler) handler)
{
return async_accept (peer, ErrorCall (
BOOST_ASIO_MOVE_CAST(AcceptHandler)(handler)));
}
virtual
BEAST_ASIO_INITFN_RESULT_TYPE_MEMBER(ErrorCall, void (boost::system::error_code))
async_accept (Socket& peer, BOOST_ASIO_MOVE_ARG(ErrorCall) handler);
//--------------------------------------------------------------------------
//
// SocketInterface::LowestLayer
//
//--------------------------------------------------------------------------
template <class Object>
Object& lowest_layer ()
{
Object* object (lowest_layer_ptr <Object> ());
if (object == nullptr)
Throw (std::bad_cast (), __FILE__, __LINE__);
return *object;
}
template <class Object>
Object const& lowest_layer () const
{
Object const* object (lowest_layer_ptr <Object> ());
if (object == nullptr)
Throw (std::bad_cast (), __FILE__, __LINE__);
return *object;
}
template <class Object>
Object* lowest_layer_ptr ()
{
return static_cast <Object*> (
lowest_layer_raw (typeid (Object).name ()));
}
template <class Object>
Object const* lowest_layer_ptr () const
{
return static_cast <Object const*> (
lowest_layer_raw (typeid (Object).name ()));
}
// Shouldn't call this directly, use lowest_layer<> instead
virtual void* lowest_layer_raw (char const* type_name) const;
//--------------------------------------------------------------------------
//
@@ -122,7 +213,7 @@ public:
throw_error (cancel (ec));
}
virtual boost::system::error_code cancel (boost::system::error_code& ec) = 0;
virtual boost::system::error_code cancel (boost::system::error_code& ec);
void shutdown (shutdown_type what)
{
@@ -131,15 +222,7 @@ public:
}
virtual boost::system::error_code shutdown (shutdown_type what,
boost::system::error_code& ec) = 0;
void close ()
{
boost::system::error_code ec;
throw_error (close (ec));
}
virtual boost::system::error_code close (boost::system::error_code& ec) = 0;
boost::system::error_code& ec);
//--------------------------------------------------------------------------
//
@@ -158,7 +241,7 @@ public:
return read_some (MutableBuffers (buffers), ec);
}
virtual std::size_t read_some (MutableBuffers const& buffers, boost::system::error_code& ec) = 0;
virtual std::size_t read_some (MutableBuffers const& buffers, boost::system::error_code& ec);
// SyncWriteStream
//
@@ -170,7 +253,7 @@ public:
return write_some (BOOST_ASIO_MOVE_CAST(ConstBuffers)(ConstBuffers (buffers)), ec);
}
virtual std::size_t write_some (ConstBuffers const& buffers, boost::system::error_code& ec) = 0;
virtual std::size_t write_some (ConstBuffers const& buffers, boost::system::error_code& ec);
// AsyncReadStream
//
@@ -185,8 +268,8 @@ public:
}
virtual
BOOST_ASIO_INITFN_RESULT_TYPE_MEMBER(TransferCall, void (boost::system::error_code, std::size_t))
async_read_some (MutableBuffers const& buffers, BOOST_ASIO_MOVE_ARG(TransferCall) handler) = 0;
BEAST_ASIO_INITFN_RESULT_TYPE_MEMBER(TransferCall, void (boost::system::error_code, std::size_t))
async_read_some (MutableBuffers const& buffers, BOOST_ASIO_MOVE_ARG(TransferCall) handler);
// AsyncWriteStream
//
@@ -201,8 +284,8 @@ public:
}
virtual
BOOST_ASIO_INITFN_RESULT_TYPE_MEMBER(TransferCall, void (boost::system::error_code, std::size_t))
async_write_some (ConstBuffers const& buffers, BOOST_ASIO_MOVE_ARG(TransferCall) handler) = 0;
BEAST_ASIO_INITFN_RESULT_TYPE_MEMBER(TransferCall, void (boost::system::error_code, std::size_t))
async_write_some (ConstBuffers const& buffers, BOOST_ASIO_MOVE_ARG(TransferCall) handler);
//--------------------------------------------------------------------------
//
@@ -223,7 +306,7 @@ public:
// http://www.boost.org/doc/libs/1_54_0/doc/html/boost_asio/reference/ssl__stream/handshake/overload2.html
//
virtual boost::system::error_code handshake (handshake_type type,
boost::system::error_code& ec) = 0;
boost::system::error_code& ec);
// ssl::stream::async_handshake (1 of 2)
// http://www.boost.org/doc/libs/1_54_0/doc/html/boost_asio/reference/ssl__stream/async_handshake/overload1.html
@@ -237,12 +320,12 @@ public:
}
virtual
BOOST_ASIO_INITFN_RESULT_TYPE_MEMBER(ErrorCall, void (boost::system::error_code))
async_handshake (handshake_type type, BOOST_ASIO_MOVE_ARG(ErrorCall) handler) = 0;
BEAST_ASIO_INITFN_RESULT_TYPE_MEMBER(ErrorCall, void (boost::system::error_code))
async_handshake (handshake_type type, BOOST_ASIO_MOVE_ARG(ErrorCall) handler);
//--------------------------------------------------------------------------
#if BOOST_ASIO_HAS_BUFFEREDHANDSHAKE
#if BEAST_ASIO_HAS_BUFFEREDHANDSHAKE
// ssl::stream::handshake (3 of 4)
// http://www.boost.org/doc/libs/1_54_0/doc/html/boost_asio/reference/ssl__stream/handshake/overload3.html
//
@@ -264,7 +347,7 @@ public:
}
virtual boost::system::error_code handshake (handshake_type type,
ConstBuffers const& buffers, boost::system::error_code& ec) = 0;
ConstBuffers const& buffers, boost::system::error_code& ec);
// ssl::stream::async_handshake (2 of 2)
// http://www.boost.org/doc/libs/1_54_0/doc/html/boost_asio/reference/ssl__stream/async_handshake/overload2.html
@@ -279,9 +362,9 @@ public:
}
virtual
BOOST_ASIO_INITFN_RESULT_TYPE_MEMBER(TransferCall, void (boost::system::error_code, std::size_t))
BEAST_ASIO_INITFN_RESULT_TYPE_MEMBER(TransferCall, void (boost::system::error_code, std::size_t))
async_handshake (handshake_type type, ConstBuffers const& buffers,
BOOST_ASIO_MOVE_ARG(TransferCall) handler) = 0;
BOOST_ASIO_MOVE_ARG(TransferCall) handler);
#endif
//--------------------------------------------------------------------------
@@ -295,7 +378,7 @@ public:
throw_error (shutdown (ec));
}
virtual boost::system::error_code shutdown (boost::system::error_code& ec) = 0;
virtual boost::system::error_code shutdown (boost::system::error_code& ec);
// ssl::stream::async_shutdown
// http://www.boost.org/doc/libs/1_54_0/doc/html/boost_asio/reference/ssl__stream/async_shutdown.html
@@ -307,8 +390,8 @@ public:
}
virtual
BOOST_ASIO_INITFN_RESULT_TYPE_MEMBER(ErrorCall, void (boost::system::error_code))
async_shutdown (BOOST_ASIO_MOVE_ARG(ErrorCall) handler) = 0;
BEAST_ASIO_INITFN_RESULT_TYPE_MEMBER(ErrorCall, void (boost::system::error_code))
async_shutdown (BOOST_ASIO_MOVE_ARG(ErrorCall) handler);
};
#endif

View File

@@ -0,0 +1,30 @@
//------------------------------------------------------------------------------
/*
This file is part of Beast: https://github.com/vinniefalco/Beast
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
void SocketBase::pure_virtual ()
{
fatal_error ("A beast::Socket function was called on an object that doesn't support the interface");
}
boost::system::error_code SocketBase::pure_virtual (boost::system::error_code& ec)
{
pure_virtual ();
return ec = boost::system::errc::make_error_code (
boost::system::errc::function_not_supported);
}

View File

@@ -20,11 +20,15 @@
#ifndef BEAST_SOCKETBASE_H_INCLUDED
#define BEAST_SOCKETBASE_H_INCLUDED
/** Implementation details for AbstractSocket.
/** Implementation details for Socket.
Normally you wont need to use this.
*/
class SocketBase
{
protected:
static void pure_virtual ();
static boost::system::error_code pure_virtual (boost::system::error_code& ec);
protected:
//--------------------------------------------------------------------------
//

View File

@@ -23,102 +23,40 @@
/** These define the interfaces that SocketWrapper can adapt with SFINAE. */
struct SocketInterface
{
/** Tag for some compatibility with asio::basic_socket
// has close()
struct Close { };
/** Tag for some compatibility with boost::asio::basic_socket_acceptor
http://www.boost.org/doc/libs/1_54_0/doc/html/boost_asio/reference/basic_socket_acceptor.html
*/
struct Acceptor : Close { };
// Has lowest_layer() and lowest_layer_type
struct LowestLayer { };
/** Tag for parts of boost::asio::basic_socket
http://www.boost.org/doc/libs/1_54_0/doc/html/boost_asio/reference/basic_socket.html
*/
struct Socket { };
struct Socket : Close, LowestLayer { };
/** Tag for some compatibility with asio::basic_stream_socket
/** Tag for parts of boost::asio::basic_stream_socket
http://www.boost.org/doc/libs/1_54_0/doc/html/boost_asio/reference/basic_stream_socket.html
*/
struct SyncStream { };
struct AsyncStream { };
struct Stream : SyncStream, AsyncStream { };
/** Tags for compatibility with asio::ssl::stream
/** Tags for parts of boost::asio::ssl::stream
http://www.boost.org/doc/libs/1_54_0/doc/html/boost_asio/reference/ssl__stream.html
*/
struct SyncHandshake { };
struct SyncBufferedHandshake : SyncHandshake { };
struct AsyncHandshake { };
struct AsyncBufferedHandshake : AsyncHandshake{ };
struct Handshake : SyncBufferedHandshake, AsyncBufferedHandshake { };
protected:
//--------------------------------------------------------------------------
/** Template specialization to determine available interfaces. */
template <typename Object>
struct InterfacesOf
{
/** Intrusive tag support.
To use this, add a struct called SocketInterfaces to your
class and derive it from the interfaces that you support.
For example:
@code
struct MyHandshakingStream
{
struct SocketInterfaces
: SocketInterface::Stream
, SocketInterface::Handshake
{
};
}
@endcode
*/
typedef typename Object::SocketInterfaces type;
typedef type value;
};
// Specialization for boost::asio::basic_socket
template <typename Protocol, typename SocketService>
struct InterfacesOf <boost::asio::basic_socket <Protocol, SocketService> >
{
struct value : SocketInterface::Socket { };
typedef value type;
};
// Specialization for boost::asio::basic_stream_socket
template <typename Protocol, typename SocketService>
struct InterfacesOf <boost::asio::basic_stream_socket <Protocol, SocketService> >
{
struct value : SocketInterface::Socket, SocketInterface::Stream { };
typedef value type;
};
// Specialization for boost::asio::ssl::stream
template <typename Stream>
struct InterfacesOf <boost::asio::ssl::stream <Stream> >
{
struct value : SocketInterface::Stream , SocketInterface::Handshake { };
typedef value type;
};
#if 1
// Less elegant, but works.
// Determines if Object supports the specified Interface
template <typename Object, typename Interface, class Enable = void>
struct HasInterface : boost::false_type { };
template <typename Object, typename Interface>
struct HasInterface <Object, Interface,
typename boost::enable_if <boost::is_base_of <
Interface, typename InterfacesOf <Object>::type> >::type >
: boost::true_type { };
#else
// This should work, but doesn't.
// K-ballo from #boost suggested it.
//
// Determines if Object supports the specified Interface
template <typename Object, typename Interface>
struct HasInterface : boost::is_base_of <Interface, typename InterfacesOf <Object> >
{
};
#endif
struct AnyHandshake { };
struct SyncHandshake : AnyHandshake { };
struct AsyncHandshake : AnyHandshake { };
struct BufferedSyncHandshake : AnyHandshake { };
struct BufferedAsyncHandshake : AnyHandshake { };
struct Handshake : SyncHandshake, AsyncHandshake,
BufferedSyncHandshake, BufferedAsyncHandshake,
LowestLayer { };
};
#endif

View File

@@ -34,17 +34,14 @@
*/
template <class Object>
class SocketWrapper
: public SocketInterface
, public virtual Socket
: public virtual Socket
, protected SocketWrapperBasics
{
public:
typedef Object ObjectType;
typedef typename boost::remove_reference <Object>::type ObjectT;
typedef typename boost::remove_reference <Object>::type ObjectType;
SocketWrapper (Object& object) noexcept
: m_impl (&object)
//, m_next_layer (object.next_layer ())
//, m_lowest_layer (object.lowest_layer ())
{
}
@@ -65,10 +62,40 @@ public:
return *m_impl;
}
boost::asio::io_service& get_io_service () noexcept
// Retrieves a reference to the underlying socket.
// usually asio::basic_socket or asio::basic_stream_socket
// It must be compatible with our Protocol and SocketService
// or else a std::bad cast will be thrown.
//
// The reason its a template class and not a function is
// because it would otherwise generate a compile error
// if Object did not have a declaration for
// protocol_type::socket
//
template <typename Object, class Enable = void>
struct native_socket
{
return get_object ().get_io_service ();
}
typedef void* native_socket_type;
native_socket (Socket&) { pure_virtual (); }
native_socket_type& get () { pure_virtual (); return m_socket; }
native_socket_type& operator-> () noexcept { return get(); }
private:
native_socket_type m_socket;
};
template <typename Object>
struct native_socket <Object, typename boost::enable_if <boost::is_class <
typename Object::protocol_type::socket> >::type>
{
typedef typename Object::protocol_type::socket native_socket_type;
native_socket (Socket& peer)
: m_socket (&peer.this_layer <native_socket_type> ()) { }
native_socket_type& get () noexcept { return *m_socket; }
native_socket_type& operator-> () noexcept { return *m_socket; }
private:
native_socket_type* m_socket;
};
//--------------------------------------------------------------------------
@@ -95,74 +122,44 @@ public:
{
return get_object ().lowest_layer ();
}
#endif
//--------------------------------------------------------------------------
//
// General
//
//--------------------------------------------------------------------------
bool is_handshaked ()
boost::asio::io_service& get_io_service ()
{
return HasInterface <ObjectT, SocketInterface::Handshake>::value;
return get_object ().get_io_service ();
}
void* native_object_raw ()
bool requires_handshake ()
{
return m_impl;
return Has <SocketInterface::AnyHandshake>::value;
}
void* this_layer_raw (char const* type_name) const
{
char const* const this_type_name (typeid (ObjectType).name ());
if (strcmp (type_name, this_type_name) == 0)
return const_cast <void*> (static_cast <void const*>(m_impl));
return nullptr;
}
//--------------------------------------------------------------------------
//
// SocketInterface::Socket
// SocketInterface::Close
//
//--------------------------------------------------------------------------
public:
boost::system::error_code cancel (boost::system::error_code& ec)
{
return cancel (ec,
HasInterface <ObjectT, SocketInterface::Socket> ());
}
private:
boost::system::error_code cancel (boost::system::error_code& ec,
boost::true_type)
{
return get_object ().cancel (ec);
}
boost::system::error_code cancel (boost::system::error_code& ec,
boost::false_type)
{
return pure_virtual (ec);
}
public:
boost::system::error_code shutdown (shutdown_type what, boost::system::error_code& ec)
{
return shutdown (what, ec,
HasInterface <ObjectT, SocketInterface::Socket> ());
}
private:
boost::system::error_code shutdown (Socket::shutdown_type what, boost::system::error_code& ec,
boost::true_type)
{
return get_object ().shutdown (what, ec);
}
boost::system::error_code shutdown (Socket::shutdown_type, boost::system::error_code& ec,
boost::false_type)
{
return pure_virtual (ec);
}
public:
boost::system::error_code close (boost::system::error_code& ec)
{
return close (ec,
HasInterface <ObjectT, SocketInterface::Socket> ());
Has <SocketInterface::Close> ());
}
private:
boost::system::error_code close (boost::system::error_code& ec,
boost::true_type)
{
@@ -175,20 +172,164 @@ private:
return pure_virtual (ec);
}
//--------------------------------------------------------------------------
//
// SocketInterface::Acceptor
//
//--------------------------------------------------------------------------
boost::system::error_code accept (Socket& peer, boost::system::error_code& ec)
{
return accept (peer, ec,
Has <SocketInterface::Acceptor> ());
}
boost::system::error_code accept (Socket& peer, boost::system::error_code& ec,
boost::true_type)
{
#if 1
return get_object ().accept (
native_socket <Object> (peer).get (), ec);
#else
typedef ObjectType::protocol_type::socket socket_type;
socket_type& socket (peer.this_layer <socket_type> ());
return get_object ().accept (socket, ec);
#endif
}
boost::system::error_code accept (Socket&, boost::system::error_code& ec,
boost::false_type)
{
return pure_virtual (ec);
}
BEAST_ASIO_INITFN_RESULT_TYPE_MEMBER(ErrorCall, void (boost::system::error_code))
async_accept (Socket& peer, BOOST_ASIO_MOVE_ARG(ErrorCall) handler)
{
return async_accept (peer, BOOST_ASIO_MOVE_CAST(ErrorCall)(handler),
Has <SocketInterface::Acceptor> ());
}
template <typename AcceptHandler>
BOOST_ASIO_INITFN_RESULT_TYPE(ErrorCall, void (boost::system::error_code))
async_accept (Socket& peer, BOOST_ASIO_MOVE_ARG(AcceptHandler) handler,
boost::true_type)
{
#if 1
return get_object ().async_accept (
native_socket <Object> (peer).get (), handler);
#else
typedef ObjectType::protocol_type::socket socket_type;
socket_type& socket (peer.this_layer <socket_type> ());
return get_object ().async_accept (socket, handler);
#endif
}
template <typename AcceptHandler>
BOOST_ASIO_INITFN_RESULT_TYPE(AcceptHandler, void (boost::system::error_code))
async_accept (Socket&, BOOST_ASIO_MOVE_ARG(AcceptHandler) handler,
boost::false_type)
{
#if BEAST_ASIO_HAS_FUTURE_RETURNS
boost::asio::detail::async_result_init<
AcceptHandler, void (boost::system::error_code)> init(
BOOST_ASIO_MOVE_CAST(AcceptHandler)(handler));
boost::system::error_code ec;
ec = pure_virtual (ec);
get_io_service ().post (boost::bind (
BOOST_ASIO_MOVE_CAST(AcceptHandler)(handler), ec));
return init.result.get();
#else
boost::system::error_code ec;
ec = pure_virtual (ec);
get_io_service ().post (boost::bind (
BOOST_ASIO_MOVE_CAST(AcceptHandler)(handler), ec));
#endif
}
//--------------------------------------------------------------------------
//
// SocketInterface::LowestLayer
//
//--------------------------------------------------------------------------
void* lowest_layer_raw (char const* type_name) const
{
return lowest_layer_raw (type_name,
Has <SocketInterface::LowestLayer> ());
}
void* lowest_layer_raw (char const* type_name,
boost::true_type) const
{
typedef typename ObjectType::lowest_layer_type lowest_layer_type;
char const* const lowest_layer_type_name (typeid (lowest_layer_type).name ());
if (strcmp (type_name, lowest_layer_type_name) == 0)
return const_cast <void*> (static_cast <void const*>(&get_object ().lowest_layer ()));
return nullptr;
}
void* lowest_layer_raw (char const*,
boost::false_type) const
{
pure_virtual ();
return nullptr;
}
//--------------------------------------------------------------------------
//
// SocketInterface::Socket
//
//--------------------------------------------------------------------------
boost::system::error_code cancel (boost::system::error_code& ec)
{
return cancel (ec,
Has <SocketInterface::Socket> ());
}
boost::system::error_code cancel (boost::system::error_code& ec,
boost::true_type)
{
return get_object ().cancel (ec);
}
boost::system::error_code cancel (boost::system::error_code& ec,
boost::false_type)
{
return pure_virtual (ec);
}
boost::system::error_code shutdown (shutdown_type what, boost::system::error_code& ec)
{
return shutdown (what, ec,
Has <SocketInterface::Socket> ());
}
boost::system::error_code shutdown (Socket::shutdown_type what, boost::system::error_code& ec,
boost::true_type)
{
return get_object ().shutdown (what, ec);
}
boost::system::error_code shutdown (Socket::shutdown_type, boost::system::error_code& ec,
boost::false_type)
{
return pure_virtual (ec);
}
//--------------------------------------------------------------------------
//
// SocketInterface::Stream
//
//--------------------------------------------------------------------------
public:
std::size_t read_some (MutableBuffers const& buffers, boost::system::error_code& ec)
{
return read_some (buffers, ec,
HasInterface <ObjectT, SocketInterface::SyncStream> ());
Has <SocketInterface::SyncStream> ());
}
private:
template <typename MutableBufferSequence>
std::size_t read_some (MutableBufferSequence const& buffers, boost::system::error_code& ec,
boost::true_type)
@@ -204,14 +345,12 @@ private:
return 0;
}
public:
std::size_t write_some (ConstBuffers const& buffers, boost::system::error_code& ec)
{
return write_some (buffers, ec,
HasInterface <ObjectT, SocketInterface::SyncStream> ());
Has <SocketInterface::SyncStream> ());
}
private:
template <typename ConstBufferSequence>
std::size_t write_some (ConstBufferSequence const& buffers, boost::system::error_code& ec,
boost::true_type)
@@ -227,15 +366,13 @@ private:
return 0;
}
public:
BOOST_ASIO_INITFN_RESULT_TYPE_MEMBER(TransferCall, void (boost::system::error_code, std::size_t))
BEAST_ASIO_INITFN_RESULT_TYPE_MEMBER(TransferCall, void (boost::system::error_code, std::size_t))
async_read_some (MutableBuffers const& buffers, BOOST_ASIO_MOVE_ARG(TransferCall) handler)
{
return async_read_some (buffers, BOOST_ASIO_MOVE_CAST(TransferCall)(handler),
HasInterface <ObjectT, SocketInterface::AsyncStream> ());
Has <SocketInterface::AsyncStream> ());
}
private:
template <typename MutableBufferSequence, typename ReadHandler>
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,
@@ -250,11 +387,11 @@ private:
async_read_some (MutableBufferSequence const&, BOOST_ASIO_MOVE_ARG(ReadHandler) handler,
boost::false_type)
{
#if BOOST_ASIO_HAS_FUTURE_RETURNS
#if BEAST_ASIO_HAS_FUTURE_RETURNS
boost::asio::detail::async_result_init<
ReadHandler, void (boost::system::error_code, std::size_t)> init(
BOOST_ASIO_MOVE_CAST(ReadHandler)(handler));
system::error_code ec;
boost::system::error_code ec;
ec = pure_virtual (ec);
get_io_service ().post (boost::bind (BOOST_ASIO_MOVE_CAST(ReadHandler)(handler), ec, 0));
return init.result.get();
@@ -265,15 +402,13 @@ private:
#endif
}
public:
BOOST_ASIO_INITFN_RESULT_TYPE_MEMBER(TransferCall, void (boost::system::error_code, std::size_t))
BEAST_ASIO_INITFN_RESULT_TYPE_MEMBER(TransferCall, void (boost::system::error_code, std::size_t))
async_write_some (ConstBuffers const& buffers, BOOST_ASIO_MOVE_ARG(TransferCall) handler)
{
return async_write_some (buffers, BOOST_ASIO_MOVE_CAST(TransferCall)(handler),
HasInterface <ObjectT, SocketInterface::AsyncStream> ());
Has <SocketInterface::AsyncStream> ());
}
private:
template <typename ConstBufferSequence, typename WriteHandler>
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,
@@ -288,11 +423,11 @@ private:
async_write_some (ConstBufferSequence const&, BOOST_ASIO_MOVE_ARG(WriteHandler) handler,
boost::false_type)
{
#if BOOST_ASIO_HAS_FUTURE_RETURNS
#if BEAST_ASIO_HAS_FUTURE_RETURNS
boost::asio::detail::async_result_init<
WriteHandler, void (boost::system::error_code, std::size_t)> init(
BOOST_ASIO_MOVE_CAST(WriteHandler)(handler));
system::error_code ec;
boost::system::error_code ec;
ec = pure_virtual (ec);
get_io_service ().post (boost::bind (
BOOST_ASIO_MOVE_CAST(WriteHandler)(handler), ec, 0));
@@ -307,18 +442,16 @@ private:
//--------------------------------------------------------------------------
//
// Handshake
// SocketInterface::Handshake
//
//--------------------------------------------------------------------------
public:
boost::system::error_code handshake (handshake_type type, boost::system::error_code& ec)
{
return handshake (type, ec,
HasInterface <ObjectT, SocketInterface::SyncHandshake> ());
Has <SocketInterface::SyncHandshake> ());
}
private:
boost::system::error_code handshake (handshake_type type, boost::system::error_code& ec,
boost::true_type)
{
@@ -331,15 +464,13 @@ private:
return pure_virtual (ec);
}
public:
BOOST_ASIO_INITFN_RESULT_TYPE_MEMBER(ErrorCall, void (boost::system::error_code))
BEAST_ASIO_INITFN_RESULT_TYPE_MEMBER(ErrorCall, void (boost::system::error_code))
async_handshake (handshake_type type, BOOST_ASIO_MOVE_ARG(ErrorCall) handler)
{
return async_handshake (type, BOOST_ASIO_MOVE_CAST(ErrorCall)(handler),
HasInterface <ObjectT, SocketInterface::AsyncHandshake> ());
Has <SocketInterface::AsyncHandshake> ());
}
private:
template <typename HandshakeHandler>
BOOST_ASIO_INITFN_RESULT_TYPE(HandshakeHandler, void (boost::system::error_code))
async_handshake (handshake_type type, BOOST_ASIO_MOVE_ARG(HandshakeHandler) handler,
@@ -354,11 +485,11 @@ private:
async_handshake (handshake_type, BOOST_ASIO_MOVE_ARG(HandshakeHandler) handler,
boost::false_type)
{
#if BOOST_ASIO_HAS_FUTURE_RETURNS
#if BEAST_ASIO_HAS_FUTURE_RETURNS
boost::asio::detail::async_result_init<
HandshakeHandler, void (boost::system::error_code)> init(
BOOST_ASIO_MOVE_CAST(HandshakeHandler)(handler));
system::error_code ec;
boost::system::error_code ec;
ec = pure_virtual (ec);
get_io_service ().post (boost::bind (
BOOST_ASIO_MOVE_CAST(HandshakeHandler)(handler), ec));
@@ -371,16 +502,14 @@ private:
#endif
}
public:
#if BOOST_ASIO_HAS_BUFFEREDHANDSHAKE
#if BEAST_ASIO_HAS_BUFFEREDHANDSHAKE
boost::system::error_code handshake (handshake_type type,
ConstBuffers const& buffers, boost::system::error_code& ec)
{
return handshake (type, buffers, ec,
HasInterface <ObjectT, SocketInterface::SyncBufferedHandshake> ());
Has <SocketInterface::BufferedSyncHandshake> ());
}
private:
template <typename ConstBufferSequence>
boost::system::error_code handshake (handshake_type type,
ConstBufferSequence const& buffers, boost::system::error_code& ec,
@@ -397,17 +526,15 @@ private:
return pure_virtual (ec);
}
public:
BOOST_ASIO_INITFN_RESULT_TYPE_MEMBER(TransferCall, void (boost::system::error_code, std::size_t))
BEAST_ASIO_INITFN_RESULT_TYPE_MEMBER(TransferCall, void (boost::system::error_code, std::size_t))
async_handshake (handshake_type type, ConstBuffers const& buffers,
BOOST_ASIO_MOVE_ARG(TransferCall) handler)
{
return async_handshake (type, buffers,
BOOST_ASIO_MOVE_CAST(TransferCall)(handler),
HasInterface <ObjectT, SocketInterface::AsyncBufferedHandshake> ());
Has <SocketInterface::BufferedAsyncHandshake> ());
}
private:
template <typename ConstBufferSequence, typename BufferedHandshakeHandler>
BOOST_ASIO_INITFN_RESULT_TYPE(BufferedHandshakeHandler, void (boost::system::error_code, std::size_t))
async_handshake (handshake_type type, const ConstBufferSequence& buffers,
@@ -424,7 +551,7 @@ private:
BOOST_ASIO_MOVE_ARG(BufferedHandshakeHandler) handler,
boost::false_type)
{
#if BOOST_ASIO_HAS_FUTURE_RETURNS
#if BEAST_ASIO_HAS_FUTURE_RETURNS
boost::asio::detail::async_result_init<
BufferedHandshakeHandler, void (boost::system::error_code, std::size_t)> init(
BOOST_ASIO_MOVE_CAST(BufferedHandshakeHandler)(handler));
@@ -442,14 +569,12 @@ private:
}
#endif
public:
boost::system::error_code shutdown (boost::system::error_code& ec)
{
return shutdown (ec,
HasInterface <ObjectT, SocketInterface::SyncHandshake> ());
Has <SocketInterface::SyncHandshake> ());
}
private:
boost::system::error_code shutdown (boost::system::error_code& ec,
boost::true_type)
{
@@ -462,14 +587,12 @@ private:
return pure_virtual (ec);
}
public:
void async_shutdown (BOOST_ASIO_MOVE_ARG(ErrorCall) handler)
{
async_shutdown (BOOST_ASIO_MOVE_CAST(ErrorCall)(handler),
HasInterface <ObjectT, SocketInterface::AsyncHandshake> ());
Has <SocketInterface::AsyncHandshake> ());
}
private:
template <typename ShutdownHandler>
BOOST_ASIO_INITFN_RESULT_TYPE(ShutdownHandler, void (boost::system::error_code))
async_shutdown (BOOST_ASIO_MOVE_ARG(ShutdownHandler) handler,
@@ -484,11 +607,11 @@ private:
async_shutdown (BOOST_ASIO_MOVE_ARG(ShutdownHandler) handler,
boost::false_type)
{
#if BOOST_ASIO_HAS_FUTURE_RETURNS
#if BEAST_ASIO_HAS_FUTURE_RETURNS
boost::asio::detail::async_result_init<
ShutdownHandler, void (boost::system::error_code, std::size_t)> init(
BOOST_ASIO_MOVE_CAST(ShutdownHandler)(handler));
system::error_code ec;
boost::system::error_code ec;
ec = pure_virtual (ec);
get_io_service ().post (boost::bind (
BOOST_ASIO_MOVE_CAST(ShutdownHandler)(handler), ec));
@@ -512,20 +635,10 @@ protected:
m_impl = ptr;
}
private:
static void pure_virtual ()
{
fatal_error ("A beast::Socket function was called on an object that doesn't support the interface");
}
template <typename Interface>
struct Has : HasInterface <ObjectType, Interface> { };
static boost::system::error_code pure_virtual (boost::system::error_code& ec)
{
pure_virtual ();
return ec = boost::system::errc::make_error_code (
boost::system::errc::function_not_supported);
}
private:
public:
Object* m_impl;
};

View File

@@ -0,0 +1,110 @@
//------------------------------------------------------------------------------
/*
This file is part of Beast: https://github.com/vinniefalco/Beast
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
#ifndef BEAST_SOCKETWRAPPERBASICS_H_INCLUDED
#define BEAST_SOCKETWRAPPERBASICS_H_INCLUDED
/** Some utilities for SocketWrapper and others.
*/
class SocketWrapperBasics
{
protected:
/** Template specialization to determine available interfaces. */
template <typename Object>
struct InterfacesOf
{
/** Intrusive tag support.
To use this, add a struct called SocketInterfaces to your
class and derive it from the interfaces that you support.
For example:
@code
struct MyHandshakingStream
{
struct SocketInterfaces
: SocketInterface::Stream
, SocketInterface::Handshake
{
};
}
@endcode
*/
typedef typename Object::SocketInterfaces type;
typedef type value;
};
// Specialization for boost::asio::basic_socket_acceptor
template <typename Protocol, typename SocketService>
struct InterfacesOf <boost::asio::basic_socket_acceptor <Protocol, SocketService> >
{
struct value : SocketInterface::Acceptor { };
typedef value type;
};
// Specialization for boost::asio::basic_socket
template <typename Protocol, typename SocketService>
struct InterfacesOf <boost::asio::basic_socket <Protocol, SocketService> >
{
struct value : SocketInterface::Socket { };
typedef value type;
};
// Specialization for boost::asio::basic_stream_socket
template <typename Protocol, typename SocketService>
struct InterfacesOf <boost::asio::basic_stream_socket <Protocol, SocketService> >
{
struct value : SocketInterface::Socket, SocketInterface::Stream { };
typedef value type;
};
// Specialization for boost::asio::ssl::stream
template <typename Stream>
struct InterfacesOf <boost::asio::ssl::stream <Stream> >
{
struct value : SocketInterface::Stream , SocketInterface::Handshake { };
typedef value type;
};
#if 1
// Less elegant, but works.
// Determines if Object supports the specified Interface
template <typename Object, typename Interface, class Enable = void>
struct HasInterface : boost::false_type { };
template <typename Object, typename Interface>
struct HasInterface <Object, Interface,
typename boost::enable_if <boost::is_base_of <
Interface, typename InterfacesOf <Object>::type> >::type >
: boost::true_type { };
#else
// This should work, but doesn't.
// K-ballo from #boost suggested it.
//
// Determines if Object supports the specified Interface
template <typename Object, typename Interface>
struct HasInterface : boost::is_base_of <Interface, typename InterfacesOf <Object> >
{
};
#endif
};
#endif

View File

@@ -49,25 +49,25 @@
// Configure some options based on the version of boost
#include <boost/version.hpp>
#if (BOOST_VERSION / 100) >= 1054
# define BOOST_ASIO_HAS_BUFFEREDHANDSHAKE 1
# define BOOST_ASIO_HAS_FUTURE_RETURNS 1
# define BEAST_ASIO_HAS_BUFFEREDHANDSHAKE 1
# define BEAST_ASIO_HAS_FUTURE_RETURNS 1
#else
# define BOOST_ASIO_HAS_BUFFEREDHANDSHAKE 0
# define BOOST_ASIO_HAS_FUTURE_RETURNS 0
# define BEAST_ASIO_HAS_BUFFEREDHANDSHAKE 0
# define BEAST_ASIO_HAS_FUTURE_RETURNS 0
#endif
#if ! BOOST_ASIO_HAS_FUTURE_RETURNS
#if ! BEAST_ASIO_HAS_FUTURE_RETURNS
# define BOOST_ASIO_INITFN_RESULT_TYPE(expr,val) void
# define BOOST_ASIO_INITFN_RESULT_TYPE_MEMBER(expr,val) void
# define BEAST_ASIO_INITFN_RESULT_TYPE_MEMBER(expr,val) void
#else
# if defined(GENERATING_DOCUMENTATION)
# define BOOST_ASIO_INITFN_RESULT_TYPE_MEMBER(h, sig) \
# define BEAST_ASIO_INITFN_RESULT_TYPE_MEMBER(h, sig) \
void_or_deduced
# elif defined(_MSC_VER) && (_MSC_VER < 1500)
# define BOOST_ASIO_INITFN_RESULT_TYPE_MEMBER(h, sig) \
# define BEAST_ASIO_INITFN_RESULT_TYPE_MEMBER(h, sig) \
boost::asio::detail::async_result_type_helper<h, sig>::type
# else
# define BOOST_ASIO_INITFN_RESULT_TYPE_MEMBER(h, sig) \
# define BEAST_ASIO_INITFN_RESULT_TYPE_MEMBER(h, sig) \
boost::asio::async_result <boost::asio::handler_type<h, sig>::type>::type
# endif
#endif

View File

@@ -0,0 +1,63 @@
//------------------------------------------------------------------------------
/*
This file is part of Beast: https://github.com/vinniefalco/Beast
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
#ifndef BEAST_TESTPEER_H_INCLUDED
#define BEAST_TESTPEER_H_INCLUDED
/** An abstract peer for unit tests.
*/
class TestPeer
: public TestPeerBasics
, public Uncopyable
{
public:
virtual ~TestPeer () { }
/** Get the name of this peer. */
virtual String name () const = 0;
/** Start the peer.
If the peer is a server, the call will block until the
listening socket is ready to receive connections.
*/
virtual void start () = 0;
/** Wait for the peer to finish.
If the peer does not complete before the timout expires
then a timeout error is returned. If timeoutSeconds is less
than 0, then the wait is infinite.
@return Any error code generated during the server operation.
*/
virtual boost::system::error_code join (int timeoutSeconds = -1) = 0;
/** Runs a unit test on the specified pair of peers.
Returns true if the tests passed.
*/
#if 0
static bool runTest (UnitTest& test,
TestPeer& server,
TestPeer& client,
int timeoutSeconds,
String const& name);
#endif
};
#endif

View File

@@ -0,0 +1,101 @@
//------------------------------------------------------------------------------
/*
This file is part of Beast: https://github.com/vinniefalco/Beast
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
boost::system::error_category const& TestPeerBasics::test_category () noexcept
{
struct test_category_type : boost::system::error_category
{
char const* name () const noexcept
{
return "TestPeer";
}
std::string message (int ev) const
{
switch (ev)
{
case errc::none: return "No error";
case errc::timeout: return "The timeout expired before the test could complete";
case errc::unexpected: return "An unexpected test result was encountered";
case errc::exceptioned: return "An unexpected exception was thrown";
case errc::skipped: return "The test was skipped because of previous errors";
default:
break;
};
return "An unknown error";
}
boost::system::error_condition default_error_condition (int ev) const noexcept
{
return boost::system::error_condition (ev, *this);
}
bool equivalent (int ev, boost::system::error_condition const& condition) const noexcept
{
return default_error_condition (ev) == condition;
}
bool equivalent (boost::system::error_code const& code, int ev) const noexcept
{
return *this == code.category() && code.value() == ev;
}
};
static test_category_type category;
return category;
}
boost::system::error_code TestPeerBasics::make_error (errc::errc_t ev) noexcept
{
return boost::system::error_code (ev, test_category ());
}
boost::system::error_code TestPeerBasics::make_error (errc::errc_t ev, boost::system::error_code& ec) noexcept
{
return ec = make_error (ev);
}
bool TestPeerBasics::success (boost::system::error_code const& ec, bool eofIsOkay) noexcept
{
if (eofIsOkay && ec == boost::asio::error::eof)
return true;
return ! ec;
}
bool TestPeerBasics::failure (boost::system::error_code const& ec, bool eofIsOkay) noexcept
{
return ! success (ec, eofIsOkay);
}
bool TestPeerBasics::expected (bool condition, boost::system::error_code& ec) noexcept
{
if (condition)
ec = boost::system::error_code ();
else
make_error (errc::unexpected, ec);
return condition;
}
bool TestPeerBasics::unexpected (bool condition, boost::system::error_code& ec) noexcept
{
return ! expected (condition, ec);
}

View File

@@ -0,0 +1,143 @@
//------------------------------------------------------------------------------
/*
This file is part of Beast: https://github.com/vinniefalco/Beast
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
#ifndef BEAST_TESTPEERBASICS_H_INCLUDED
#define BEAST_TESTPEERBASICS_H_INCLUDED
/** Common declarations for TestPeer.
@see TestPeer
*/
struct TestPeerBasics
{
// Custom error codes for distinguishing test conditions
struct errc
{
enum errc_t
{
none = 0,
timeout, // The peer join timeout expired
unexpected, // An expected condition was false
exceptioned, // An exception occurred
skipped // Test skipped due to previous errors
};
};
/** Returns the category that represents TestPeer errors.
*/
static boost::system::error_category const& test_category () noexcept;
/** Creates a test error_code from the give code value.
*/
static boost::system::error_code make_error (errc::errc_t ev) noexcept;
/** Sets the passed error_code to a test error and returns it.
*/
static boost::system::error_code make_error (errc::errc_t ev,
boost::system::error_code& ec) noexcept;
/** Returns true if the error code indicates success.
*/
static bool success (boost::system::error_code const& ec, bool eofIsOkay = false) noexcept;
/** Returns false if the error code indicates failure.
*/
static bool failure (boost::system::error_code const& ec, bool eofIsOkay = false) noexcept;
/** Set the error based on a failed condition and return the success.
*/
static bool expected (bool condition, boost::system::error_code& ec) noexcept;
/** Set the error based on a passed condition and return the success.
*/
static bool unexpected (bool condition, boost::system::error_code& ec) noexcept;
//--------------------------------------------------------------------------
struct Role
{
enum role_t
{
client,
server
};
Role (role_t role)
: m_role (role)
{
}
String name () const noexcept
{
if (m_role == server)
return "server";
return "client";
}
bool operator== (role_t role) const noexcept
{
return m_role == role;
}
operator Socket::handshake_type () const noexcept
{
if (m_role == server)
return Socket::server;
return Socket::client;
}
private:
role_t m_role;
};
//--------------------------------------------------------------------------
struct Model
{
enum model_t
{
sync,
async
};
Model (model_t model)
: m_model (model)
{
}
String name () const noexcept
{
if (m_model == async)
return "async";
return "sync";
}
bool operator== (model_t model) const noexcept
{
return m_model == model;
}
private:
model_t m_model;
};
//--------------------------------------------------------------------------
};
#endif

View File

@@ -0,0 +1,45 @@
//------------------------------------------------------------------------------
/*
This file is part of Beast: https://github.com/vinniefalco/Beast
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
#ifndef BEAST_TESTPEERDETAILS_H_INCLUDED
#define BEAST_TESTPEERDETAILS_H_INCLUDED
/** Base class of all detail objects.
*/
class TestPeerDetails : public Uncopyable
{
public:
virtual ~TestPeerDetails () { }
virtual String name () = 0;
virtual Socket& get_socket () = 0;
virtual Socket& get_acceptor () = 0;
boost::asio::io_service& get_io_service ()
{
return m_io_service;
}
private:
boost::asio::io_service m_io_service;
};
#endif

View File

@@ -0,0 +1,83 @@
//------------------------------------------------------------------------------
/*
This file is part of Beast: https://github.com/vinniefalco/Beast
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
#ifndef BEAST_TESTPEERLOGIC_H_INCLUDED
#define BEAST_TESTPEERLOGIC_H_INCLUDED
/** Interface for implementing the logic part of a peer test.
*/
class TestPeerLogic
: public TestPeerBasics
, public Uncopyable
{
public:
typedef boost::system::error_code error_code;
explicit TestPeerLogic (Socket& socket)
: m_socket (socket)
{
}
error_code& error () noexcept
{
return m_ec;
}
error_code const& error () const noexcept
{
return m_ec;
}
// also assigns, used for async handlers
error_code const& error (error_code const& ec) noexcept
{
return m_ec = ec;
}
Socket& socket () noexcept
{
return m_socket;
}
virtual Role get_role () const noexcept = 0;
virtual Model get_model () const noexcept = 0;
virtual void on_connect ()
{
pure_virtual ();
}
virtual void on_connect_async (error_code const&)
{
pure_virtual ();
}
protected:
static void pure_virtual ()
{
fatal_error ("A TestPeerLogic function was called incorrectly");
}
private:
error_code m_ec;
Socket& m_socket;
};
#endif

View File

@@ -0,0 +1,128 @@
//------------------------------------------------------------------------------
/*
This file is part of Beast: https://github.com/vinniefalco/Beast
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
#ifndef RIPPLE_TESTPEERTEST_H_INCLUDED
#define RIPPLE_TESTPEERTEST_H_INCLUDED
/** Performs a test of two peers defined by template parameters.
*/
struct TestPeerTest : protected TestPeerBasics
{
enum
{
/** How long to wait before aborting a peer and reporting a timeout.
@note Aborting synchronous logics may cause undefined behavior.
*/
defaultTimeoutSeconds = 30
};
/** Holds the results for one peer. */
class Result : protected TestPeerBasics
{
public:
/** Default constructor indicates the test was skipped.
*/
Result ()
: m_ec (make_error (errc::skipped))
, m_message (m_ec.message ())
{
}
/** Construct from an error code.
The prefix is prepended to the error message.
*/
explicit Result (boost::system::error_code const& ec, String const& prefix = "")
: m_ec (ec)
, m_message ((prefix == String::empty) ? ec.message ()
: prefix + " " + ec.message ())
{
}
/** Returns true if the peer failed.
*/
bool failed () const noexcept
{
return failure (m_ec);
}
/** Convenience for determining if the peer timed out. */
bool timedout () const noexcept
{
return m_ec == make_error (errc::timeout);
}
/** Provides a descriptive message.
This is suitable to pass to UnitTest::fail.
*/
String message () const noexcept
{
return m_message;
}
/** Report the result to a UnitTest object.
A return value of true indicates success.
*/
bool report (UnitTest& test)
{
bool const success = test.unexpected (failed (), message ());
#if 0
// Option to report passing tests
if (success)
test.logMessage (String ("passed ") + message());
#endif
return success;
}
private:
boost::system::error_code m_ec;
String m_message;
};
//--------------------------------------------------------------------------
/** Holds the results for both peers. */
struct Results
{
String name; // A descriptive name for this test case.
Result client;
Result server;
Results () : name ("unknown")
{
}
/** Report the results to a UnitTest object.
A return value of true indicates success.
*/
bool report (UnitTest& test, bool beginTestCase = true)
{
if (beginTestCase)
test.beginTestCase (name);
bool success = true;
if (! client.report (test))
success = false;
if (! server.report (test))
success = false;
return success;
}
};
};
#endif

View File

@@ -0,0 +1,46 @@
//------------------------------------------------------------------------------
/*
This file is part of Beast: https://github.com/vinniefalco/Beast
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
class TestPeerTests : public UnitTest
{
public:
enum
{
timeoutSeconds = 3
};
TestPeerTests () : UnitTest ("TestPeer", "beast")
{
}
template <typename Details, typename Arg >
void testDetails (Arg const& arg = Arg ())
{
TestPeerTestType::test <Details> (*this, arg, timeoutSeconds);
}
void runTest ()
{
typedef boost::asio::ip::tcp protocol;
testDetails <TcpDetails, TcpDetails::arg_type> (protocol::v4 ());
testDetails <TcpDetails, TcpDetails::arg_type> (protocol::v6 ());
}
};
static TestPeerTests testPeerTests;

View File

@@ -0,0 +1,110 @@
//------------------------------------------------------------------------------
/*
This file is part of Beast: https://github.com/vinniefalco/Beast
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
#ifndef BEAST_TESTPEERDETAILSTCP_H_INCLUDED
#define BEAST_TESTPEERDETAILSTCP_H_INCLUDED
/** Some predefined Detail classes for TestPeer
*/
struct TcpDetails : public TestPeerDetails
{
protected:
typedef boost::asio::ip::tcp protocol_type;
typedef protocol_type::socket socket_type;
typedef protocol_type::acceptor acceptor_type;
typedef protocol_type::endpoint endpoint_type;
typedef protocol_type::resolver resolver_type;
struct NoArg { }; // dummy
public:
typedef protocol_type arg_type;
typedef socket_type native_socket_type;
typedef acceptor_type native_acceptor_type;
explicit TcpDetails (arg_type protocol)
: m_protocol (protocol)
, m_socket (get_io_service ())
, m_acceptor (get_io_service ())
, m_socket_wrapper (m_socket)
, m_acceptor_wrapper (m_acceptor)
{
}
static String getArgName (arg_type arg)
{
if (arg == protocol_type::v4 ())
return "tcpv4";
else if (arg == protocol_type::v6 ())
return "tcpv6";
return "tcp?";
}
String name ()
{
return getArgName (m_protocol);
}
Socket& get_socket ()
{
return m_socket_wrapper;
}
Socket& get_acceptor ()
{
return m_acceptor_wrapper;
}
socket_type& get_native_socket ()
{
return m_socket;
}
acceptor_type& get_native_acceptor ()
{
return m_acceptor;
}
endpoint_type get_endpoint (TestPeer::Role role)
{
if (m_protocol == protocol_type::v4 ())
{
if (role == TestPeer::Role::server)
return endpoint_type (m_protocol, 1053);
else
return endpoint_type (boost::asio::ip::address_v4::loopback (), 1053);
}
else
{
if (role == TestPeer::Role::server)
return endpoint_type (m_protocol, 1052);
else
return endpoint_type (boost::asio::ip::address_v6 ().from_string ("::1"), 1052);
}
}
protected:
protocol_type m_protocol;
socket_type m_socket;
acceptor_type m_acceptor;
SocketWrapper <socket_type> m_socket_wrapper;
SocketWrapper <acceptor_type> m_acceptor_wrapper;
};
#endif

View File

@@ -0,0 +1,108 @@
//------------------------------------------------------------------------------
/*
This file is part of Beast: https://github.com/vinniefalco/Beast
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
TestPeerLogicAsyncClient::TestPeerLogicAsyncClient (Socket& socket)
: TestPeerLogic (socket)
{
}
TestPeerBasics::Role TestPeerLogicAsyncClient::get_role () const noexcept
{
return Role::client;
}
TestPeerBasics::Model TestPeerLogicAsyncClient::get_model () const noexcept
{
return Model::async;
}
void TestPeerLogicAsyncClient::on_connect_async (error_code const& ec)
{
if (failure (error (ec)))
return;
if (socket ().requires_handshake ())
{
socket ().async_handshake (Socket::client,
boost::bind (&TestPeerLogicAsyncClient::on_handshake, this,
boost::asio::placeholders::error));
}
else
{
on_handshake (ec);
}
}
void TestPeerLogicAsyncClient::on_handshake (error_code const& ec)
{
if (failure (error (ec)))
return;
boost::asio::async_write (socket (), boost::asio::buffer ("hello", 5),
boost::bind (&TestPeerLogicAsyncClient::on_write, this,
boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred));
}
void TestPeerLogicAsyncClient::on_write (error_code const& ec, std::size_t bytes_transferred)
{
if (failure (error (ec)))
return;
if (unexpected (bytes_transferred == 5, error ()))
return;
boost::asio::async_read_until (socket (), m_buf, std::string ("goodbye"),
boost::bind (&TestPeerLogicAsyncClient::on_read, this,
boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred));
}
void TestPeerLogicAsyncClient::on_read (error_code const& ec, std::size_t bytes_transferred)
{
if (failure (error (ec)))
return;
if (unexpected (bytes_transferred == 7, error ()))
return;
// should check the data here?
m_buf.consume (bytes_transferred);
boost::asio::async_read (socket (), m_buf.prepare (1),
boost::bind (&TestPeerLogicAsyncClient::on_read_final, this,
boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred));
}
void TestPeerLogicAsyncClient::on_read_final (error_code const& ec, std::size_t)
{
if (ec == boost::asio::error::eof)
{
if (failure (socket ().shutdown (Socket::shutdown_both, error ())))
return;
if (failure (socket ().close (error ())))
return;
}
else
{
// If we don't get eof, then there should be some other
// error in there. We don't expect the server to send more bytes!
//
unexpected (success (error (ec)), error ());
}
}

View File

@@ -0,0 +1,38 @@
//------------------------------------------------------------------------------
/*
This file is part of Beast: https://github.com/vinniefalco/Beast
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
#ifndef BEAST_TESTPEERLOGICASYNCCLIENT_H_INCLUDED
#define BEAST_TESTPEERLOGICASYNCCLIENT_H_INCLUDED
class TestPeerLogicAsyncClient : public TestPeerLogic
{
public:
explicit TestPeerLogicAsyncClient (Socket& socket);
Role get_role () const noexcept;
Model get_model () const noexcept;
void on_connect_async (error_code const& ec);
void on_handshake (error_code const& ec);
void on_write (error_code const& ec, std::size_t bytes_transferred);
void on_read (error_code const& ec, std::size_t bytes_transferred);
void on_read_final (error_code const& ec, std::size_t);
private:
boost::asio::streambuf m_buf;
};
#endif

View File

@@ -0,0 +1,104 @@
//------------------------------------------------------------------------------
/*
This file is part of Beast: https://github.com/vinniefalco/Beast
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
TestPeerLogicAsyncServer::TestPeerLogicAsyncServer (Socket& socket)
: TestPeerLogic (socket)
{
}
TestPeerBasics::Role TestPeerLogicAsyncServer::get_role () const noexcept
{
return Role::server;
}
TestPeerBasics::Model TestPeerLogicAsyncServer::get_model () const noexcept
{
return Model::async;
}
void TestPeerLogicAsyncServer::on_connect_async (error_code const& ec)
{
if (failure (error (ec)))
return;
if (socket ().requires_handshake ())
{
socket ().async_handshake (Socket::server,
boost::bind (&TestPeerLogicAsyncServer::on_handshake, this,
boost::asio::placeholders::error));
}
else
{
on_handshake (ec);
}
}
void TestPeerLogicAsyncServer::on_handshake (error_code const& ec)
{
if (failure (error (ec)))
return;
boost::asio::async_read_until (socket (), m_buf, std::string ("hello"),
boost::bind (&TestPeerLogicAsyncServer::on_read, this,
boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred));
}
void TestPeerLogicAsyncServer::on_read (error_code const& ec, std::size_t bytes_transferred)
{
if (failure (error (ec)))
return;
if (unexpected (bytes_transferred == 5, error ()))
return;
boost::asio::async_write (socket (), boost::asio::buffer ("goodbye", 7),
boost::bind (&TestPeerLogicAsyncServer::on_write, this,
boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred));
}
void TestPeerLogicAsyncServer::on_write (error_code const& ec, std::size_t bytes_transferred)
{
if (failure (error (ec)))
return;
if (unexpected (bytes_transferred == 7, error ()))
return;
if (socket ().requires_handshake ())
{
socket ().async_shutdown (boost::bind (&TestPeerLogicAsyncServer::on_shutdown, this,
boost::asio::placeholders::error));
}
else
{
// we need another instance of ec so we can call on_shutdown()
error_code ec;
on_shutdown (socket ().shutdown (Socket::shutdown_both, ec));
}
}
void TestPeerLogicAsyncServer::on_shutdown (error_code const& ec)
{
if (failure (error (ec), true))
return;
if (failure (socket ().close (error ())))
return;
}

View File

@@ -0,0 +1,38 @@
//------------------------------------------------------------------------------
/*
This file is part of Beast: https://github.com/vinniefalco/Beast
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
#ifndef BEAST_TESTPEERLOGICASYNCSERVER_H_INCLUDED
#define BEAST_TESTPEERLOGICASYNCSERVER_H_INCLUDED
class TestPeerLogicAsyncServer : public TestPeerLogic
{
public:
explicit TestPeerLogicAsyncServer (Socket& socket);
Role get_role () const noexcept;
Model get_model () const noexcept;
void on_connect_async (error_code const& ec);
void on_handshake (error_code const& ec);
void on_read (error_code const& ec, std::size_t bytes_transferred);
void on_write (error_code const& ec, std::size_t bytes_transferred);
void on_shutdown (error_code const& ec);
private:
boost::asio::streambuf m_buf;
};
#endif

View File

@@ -0,0 +1,97 @@
//------------------------------------------------------------------------------
/*
This file is part of Beast: https://github.com/vinniefalco/Beast
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
TestPeerLogicSyncClient::TestPeerLogicSyncClient (Socket& socket)
: TestPeerLogic (socket)
{
}
TestPeerBasics::Role TestPeerLogicSyncClient::get_role () const noexcept
{
return Role::client;
}
TestPeerBasics::Model TestPeerLogicSyncClient::get_model () const noexcept
{
return Model::sync;
}
void TestPeerLogicSyncClient::on_connect ()
{
if (socket ().requires_handshake ())
{
if (failure (socket ().handshake (get_role (), error ())))
return;
}
{
std::size_t const amount = boost::asio::write (
socket (), boost::asio::buffer ("hello", 5), error ());
if (failure (error ()))
return;
if (unexpected (amount == 5, error ()))
return;
}
{
char data [7];
size_t const amount = boost::asio::read (
socket (), boost::asio::buffer (data, 7), error ());
if (failure (error ()))
return;
if (unexpected (amount == 7, error ()))
return;
if (unexpected (memcmp (&data, "goodbye", 7) == 0, error ()))
return;
}
// Wait for 1 byte which should never come. Instead,
// the server should close its end and we will get eof
{
char data [1];
boost::asio::read (socket (), boost::asio::buffer (data, 1), error ());
if (error () == boost::asio::error::eof)
{
error () = error_code ();
}
else if (unexpected (failure (error ()), error ()))
{
return;
}
}
if (socket ().requires_handshake ())
{
if (failure (socket ().shutdown (error ()), true))
return;
}
if (failure (socket ().shutdown (Socket::shutdown_both, error ())))
return;
if (failure (socket ().close (error ())))
return;
}

View File

@@ -0,0 +1,32 @@
//------------------------------------------------------------------------------
/*
This file is part of Beast: https://github.com/vinniefalco/Beast
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
#ifndef BEAST_TESTPEERLOGICSYNCCLIENT_H_INCLUDED
#define BEAST_TESTPEERLOGICSYNCCLIENT_H_INCLUDED
class TestPeerLogicSyncClient : public TestPeerLogic
{
public:
explicit TestPeerLogicSyncClient (Socket& socket);
Role get_role () const noexcept;
Model get_model () const noexcept;
void on_connect ();
};
#endif

View File

@@ -0,0 +1,80 @@
//------------------------------------------------------------------------------
/*
This file is part of Beast: https://github.com/vinniefalco/Beast
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
TestPeerLogicSyncServer::TestPeerLogicSyncServer (Socket& socket)
: TestPeerLogic (socket)
{
}
TestPeerBasics::Role TestPeerLogicSyncServer::get_role () const noexcept
{
return Role::server;
}
TestPeerBasics::Model TestPeerLogicSyncServer::get_model () const noexcept
{
return Model::sync;
}
void TestPeerLogicSyncServer::on_connect ()
{
if (socket ().requires_handshake ())
{
if (failure (socket ().handshake (get_role (), error ())))
return;
}
{
boost::asio::streambuf buf (5);
std::size_t const amount = boost::asio::read_until (
socket (), buf, "hello", error ());
if (failure (error ()))
return;
if (unexpected (amount == 5, error ()))
return;
if (unexpected (buf.size () == 5, error ()))
return;
}
{
std::size_t const amount = boost::asio::write (
socket (), boost::asio::buffer ("goodbye", 7), error ());
if (failure (error ()))
return;
if (unexpected (amount == 7, error ()))
return;
}
if (socket ().requires_handshake ())
{
if (failure (socket ().shutdown (error ()), true))
return;
}
if (failure (socket ().shutdown (Socket::shutdown_both, error ())))
return;
if (failure (socket ().close (error ())))
return;
}

View File

@@ -0,0 +1,32 @@
//------------------------------------------------------------------------------
/*
This file is part of Beast: https://github.com/vinniefalco/Beast
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
#ifndef BEAST_TESTPEERLOGICSYNCSERVER_H_INCLUDED
#define BEAST_TESTPEERLOGICSYNCSERVER_H_INCLUDED
class TestPeerLogicSyncServer : public TestPeerLogic
{
public:
explicit TestPeerLogicSyncServer (Socket& socket);
Role get_role () const noexcept;
Model get_model () const noexcept;
void on_connect ();
};
#endif

View File

@@ -0,0 +1,119 @@
//------------------------------------------------------------------------------
/*
This file is part of Beast: https://github.com/vinniefalco/Beast
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
#ifndef RIPPLE_TESTPEERTESTTYPE_H_INCLUDED
#define RIPPLE_TESTPEERTESTTYPE_H_INCLUDED
/** Performs a test of two peers defined by template parameters.
*/
class TestPeerTestType : public TestPeerTest
{
public:
/** Test two peers and return the results.
*/
template <typename Details, typename ServerLogic, typename ClientLogic, class Arg>
static Results run (Arg const& arg, int timeoutSeconds = defaultTimeoutSeconds)
{
Results results;
results.name = Details::getArgName (arg);
try
{
TestPeerType <ServerLogic, Details> server (arg);
results.name << " / " << server.name ();
try
{
TestPeerType <ClientLogic, Details> client (arg);
results.name << " / " << client.name ();
try
{
server.start ();
try
{
client.start ();
boost::system::error_code const ec =
client.join (timeoutSeconds);
results.client = Result (ec, client.name ());
try
{
boost::system::error_code const ec =
server.join (timeoutSeconds);
results.server = Result (ec, server.name ());
}
catch (...)
{
results.server = Result (make_error (
errc::exceptioned), server.name ());
}
}
catch (...)
{
results.client = Result (make_error (
errc::exceptioned), client.name ());
}
}
catch (...)
{
results.server = Result (make_error (
errc::exceptioned), server.name ());
}
}
catch (...)
{
results.client = Result (make_error (
errc::exceptioned), "client");
}
}
catch (...)
{
results.server = Result (make_error (
errc::exceptioned), "server");
}
return results;
}
//--------------------------------------------------------------------------
/** Reports tests of Details against all known logic combinations to a UnitTest.
*/
template <typename Details, class Arg>
static void test (UnitTest& test, Arg const& arg,
int timeoutSeconds = defaultTimeoutSeconds,
bool beginTestCase = true)
{
run <Details, TestPeerLogicSyncServer, TestPeerLogicSyncClient> (arg, timeoutSeconds).report (test, beginTestCase);
run <Details, TestPeerLogicSyncServer, TestPeerLogicAsyncClient> (arg, timeoutSeconds).report (test, beginTestCase);
run <Details, TestPeerLogicAsyncServer, TestPeerLogicSyncClient> (arg, timeoutSeconds).report (test, beginTestCase);
run <Details, TestPeerLogicAsyncServer, TestPeerLogicAsyncClient> (arg, timeoutSeconds).report (test, beginTestCase);
}
};
#endif

View File

@@ -0,0 +1,176 @@
//------------------------------------------------------------------------------
/*
This file is part of Beast: https://github.com/vinniefalco/Beast
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
#ifndef BEAST_TESTPEERTYPE_H_INCLUDED
#define BEAST_TESTPEERTYPE_H_INCLUDED
template <typename Logic, typename DetailsType>
class TestPeerType
: public DetailsType
, public Logic
, public TestPeer
, public Thread
{
public:
typedef typename DetailsType::arg_type arg_type;
typedef TestPeerType <Logic, DetailsType> ThisType;
TestPeerType (arg_type const& arg)
: DetailsType (arg)
, Logic (get_socket ())
, Thread (name ())
{
}
~TestPeerType ()
{
}
String name () const
{
return get_model ().name () + "_" + get_role ().name ();
}
void start ()
{
startThread ();
}
boost::system::error_code join (int timeoutSeconds)
{
if (! wait (timeoutSeconds * 1000))
{
stopThread (0);
return error (make_error (errc::timeout));
}
return error ();
}
//--------------------------------------------------------------------------
void run ()
{
if (get_model () == Model::async)
{
if (get_role () == Role::server)
{
run_async_server ();
}
else if (get_role () == Role::client)
{
run_async_client ();
}
else
{
error () = make_error (errc::unexpected);
}
}
else if (get_model () == Model::sync)
{
if (get_role () == Role::server)
{
run_sync_server ();
}
else if (get_role () == Role::client)
{
run_sync_client ();
}
else
{
error () = make_error (errc::unexpected);
}
}
else
{
error () = make_error (errc::unexpected);
}
get_io_service ().run ();
notify ();
}
//--------------------------------------------------------------------------
void run_sync_server ()
{
do_listen ();
if (failure (error ()))
return;
if (failure (get_acceptor ().accept (get_socket (), error ())))
return;
this->on_connect ();
if (failure (error ()))
return ;
}
void run_async_server ()
{
do_listen ();
if (failure (error ()))
return;
get_acceptor ().async_accept (get_socket (), boost::bind (
&Logic::on_connect_async, this, boost::asio::placeholders::error));
}
//--------------------------------------------------------------------------
void run_sync_client ()
{
if (failure (get_native_socket ().connect (get_endpoint (get_role ()), error ())))
return;
this->on_connect ();
if (failure (error ()))
return;
}
void run_async_client ()
{
get_native_socket ().async_connect (get_endpoint (get_role ()),
boost::bind (&Logic::on_connect_async, this, boost::asio::placeholders::error));
}
//--------------------------------------------------------------------------
void do_listen ()
{
if (failure (get_native_acceptor ().open (get_endpoint (get_role ()).protocol (), error ())))
return;
if (failure (get_native_acceptor ().set_option (socket_type::reuse_address (true), error ())))
return;
if (failure (get_native_acceptor ().bind (get_endpoint (get_role ()), error ())))
return;
if (failure (get_native_acceptor ().listen (socket_type::max_connections, error ())))
return;
}
};
#endif

View File

@@ -129,16 +129,7 @@ bool UnitTest::expect (bool trueCondition, String const& failureMessage)
bool UnitTest::unexpected (bool falseCondition, String const& failureMessage)
{
if (! falseCondition)
{
pass ();
}
else
{
fail (failureMessage);
}
return ! falseCondition;
return expect (! falseCondition, failureMessage);
}
void UnitTest::pass ()