mirror of
https://github.com/XRPLF/rippled.git
synced 2025-12-02 08:55:53 +00:00
Refactor beast::asio:
* New tools for completion handlers: - wrap_handler provides composed io_service execution guarantees. - bind_handler rebinds arguments to handlers. - shared_handler type-erases any completion handler. - buffer_sequence type-erases templated BufferSequences - abstract_socket replaces Socket - socket_wrapper replaces SocketWrapper - beast::asio placeholders to work with std::bind * Removed obsolete classes and functions - AbstractHandler - ComposedAsyncOperation - SharedFunction - SharedHandler - SharedHandlerAllocator - SharedHandlerPtr - SharedHandlerType - SocketBase - SocketWrapperStrand - wrapHandler * Refactored classes to use new tools - abstract_socket - socket_wrapper - HandshakeDetector - HttpClientType * Miscellanous tidying - socket classes moved to beast::asio namespace - beast asio files provide their own namespace declaration. - Fix IsCallPossible conflicting template parameter name - Use <boost/get_pointer.hpp> for C++11 compatibility. - Remove extraneous include path from build environment.
This commit is contained in:
@@ -20,6 +20,4 @@
|
||||
#ifndef BEAST_ASIO_H_INCLUDED
|
||||
#define BEAST_ASIO_H_INCLUDED
|
||||
|
||||
#include "asio/IPAddressConversion.h"
|
||||
|
||||
#endif
|
||||
|
||||
@@ -20,3 +20,9 @@
|
||||
#include "BeastConfig.h"
|
||||
|
||||
#include "impl/IPAddressConversion.cpp"
|
||||
|
||||
#include "tests/wrap_handler_tests.cpp"
|
||||
#include "tests/bind_handler_tests.cpp"
|
||||
#include "tests/shared_handler_tests.cpp"
|
||||
|
||||
#include "abstract_socket.cpp" // TEMPORARY!
|
||||
|
||||
217
beast/asio/abstract_socket.cpp
Normal file
217
beast/asio/abstract_socket.cpp
Normal file
@@ -0,0 +1,217 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#include "abstract_socket.h"
|
||||
#include "bind_handler.h"
|
||||
|
||||
namespace beast {
|
||||
namespace asio {
|
||||
|
||||
#if ! BEAST_COMPILER_CHECKS_SOCKET_OVERRIDES
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//
|
||||
// Socket
|
||||
//
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void* abstract_socket::this_layer_ptr (char const*) const
|
||||
{
|
||||
pure_virtual_called ();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//
|
||||
// native_handle
|
||||
//
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
bool abstract_socket::native_handle (char const*, void*)
|
||||
{
|
||||
pure_virtual_called ();
|
||||
return false;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//
|
||||
// basic_io_object
|
||||
//
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
boost::asio::io_service& abstract_socket::get_io_service ()
|
||||
{
|
||||
pure_virtual_called ();
|
||||
return *static_cast <boost::asio::io_service*>(nullptr);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//
|
||||
// basic_socket
|
||||
//
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void*
|
||||
abstract_socket::lowest_layer_ptr (char const*) const
|
||||
{
|
||||
pure_virtual_called ();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto
|
||||
abstract_socket::cancel (boost::system::error_code& ec) -> error_code
|
||||
{
|
||||
return pure_virtual_error (ec);
|
||||
}
|
||||
|
||||
auto
|
||||
abstract_socket::shutdown (shutdown_type, boost::system::error_code& ec) -> error_code
|
||||
{
|
||||
return pure_virtual_error (ec);
|
||||
}
|
||||
|
||||
auto
|
||||
abstract_socket::close (boost::system::error_code& ec) -> error_code
|
||||
{
|
||||
return pure_virtual_error (ec);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//
|
||||
// basic_socket_acceptor
|
||||
//
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
auto
|
||||
abstract_socket::accept (abstract_socket&, error_code& ec) -> error_code
|
||||
{
|
||||
return pure_virtual_error (ec);
|
||||
}
|
||||
|
||||
void
|
||||
abstract_socket::async_accept (abstract_socket&, error_handler handler)
|
||||
{
|
||||
get_io_service ().post (bind_handler (
|
||||
handler, pure_virtual_error()));
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//
|
||||
// basic_stream_socket
|
||||
//
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
std::size_t
|
||||
abstract_socket::read_some (mutable_buffers, error_code& ec)
|
||||
{
|
||||
ec = pure_virtual_error ();
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::size_t
|
||||
abstract_socket::write_some (const_buffers, error_code& ec)
|
||||
{
|
||||
ec = pure_virtual_error ();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
abstract_socket::async_read_some (mutable_buffers, transfer_handler handler)
|
||||
{
|
||||
get_io_service ().post (bind_handler (
|
||||
handler, pure_virtual_error(), 0));
|
||||
}
|
||||
|
||||
void
|
||||
abstract_socket::async_write_some (const_buffers, transfer_handler handler)
|
||||
{
|
||||
get_io_service ().post (bind_handler (
|
||||
handler, pure_virtual_error(), 0));
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//
|
||||
// ssl::stream
|
||||
//
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void*
|
||||
abstract_socket::next_layer_ptr (char const*) const
|
||||
{
|
||||
pure_virtual_called ();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool
|
||||
abstract_socket::needs_handshake ()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
abstract_socket::set_verify_mode (int)
|
||||
{
|
||||
pure_virtual_called ();
|
||||
}
|
||||
|
||||
auto
|
||||
abstract_socket::handshake (handshake_type, error_code& ec) -> error_code
|
||||
{
|
||||
return pure_virtual_error (ec);
|
||||
}
|
||||
|
||||
void
|
||||
abstract_socket::async_handshake (handshake_type, error_handler handler)
|
||||
{
|
||||
get_io_service ().post (bind_handler (
|
||||
handler, pure_virtual_error()));
|
||||
}
|
||||
|
||||
auto
|
||||
abstract_socket::handshake (handshake_type, const_buffers, error_code& ec) ->
|
||||
error_code
|
||||
{
|
||||
return pure_virtual_error (ec);
|
||||
}
|
||||
|
||||
void
|
||||
abstract_socket::async_handshake (handshake_type, const_buffers,
|
||||
transfer_handler handler)
|
||||
{
|
||||
get_io_service ().post (bind_handler (
|
||||
handler, pure_virtual_error(), 0));
|
||||
}
|
||||
|
||||
auto
|
||||
abstract_socket::shutdown (error_code& ec) -> error_code
|
||||
{
|
||||
return pure_virtual_error (ec);
|
||||
}
|
||||
|
||||
void
|
||||
abstract_socket::async_shutdown (error_handler handler)
|
||||
{
|
||||
get_io_service ().post (bind_handler (
|
||||
handler, pure_virtual_error()));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
}
|
||||
}
|
||||
404
beast/asio/abstract_socket.h
Normal file
404
beast/asio/abstract_socket.h
Normal file
@@ -0,0 +1,404 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
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_ASIO_ABSTRACT_SOCKET_H_INCLUDED
|
||||
#define BEAST_ASIO_ABSTRACT_SOCKET_H_INCLUDED
|
||||
|
||||
#include "buffer_sequence.h"
|
||||
#include "shared_handler.h"
|
||||
|
||||
#include <boost/asio/socket_base.hpp>
|
||||
#include <boost/asio/ssl/stream_base.hpp>
|
||||
|
||||
// Checking overrides replaces unimplemented stubs with pure virtuals
|
||||
#ifndef BEAST_COMPILER_CHECKS_SOCKET_OVERRIDES
|
||||
# define BEAST_COMPILER_CHECKS_SOCKET_OVERRIDES 1
|
||||
#endif
|
||||
|
||||
#if BEAST_COMPILER_CHECKS_SOCKET_OVERRIDES
|
||||
# define BEAST_SOCKET_VIRTUAL = 0
|
||||
#else
|
||||
# define BEAST_SOCKET_VIRTUAL
|
||||
#endif
|
||||
|
||||
namespace beast {
|
||||
namespace asio {
|
||||
|
||||
/** A high level socket abstraction.
|
||||
|
||||
This combines the capabilities of multiple socket interfaces such
|
||||
as listening, connecting, streaming, and handshaking. It brings
|
||||
everything together into a single abstract interface.
|
||||
|
||||
When member functions are called and the underlying implementation does
|
||||
not support the operation, a fatal error is generated.
|
||||
*/
|
||||
class abstract_socket
|
||||
: public boost::asio::ssl::stream_base
|
||||
, public boost::asio::socket_base
|
||||
{
|
||||
protected:
|
||||
typedef boost::system::error_code error_code;
|
||||
|
||||
typedef asio::shared_handler <void (void)> post_handler;
|
||||
|
||||
typedef asio::shared_handler <void (error_code)> error_handler;
|
||||
|
||||
typedef asio::shared_handler <
|
||||
void (error_code, std::size_t)> transfer_handler;
|
||||
|
||||
static
|
||||
void
|
||||
pure_virtual_called()
|
||||
{
|
||||
throw std::runtime_error ("pure virtual called");
|
||||
}
|
||||
|
||||
static
|
||||
error_code
|
||||
pure_virtual_error ()
|
||||
{
|
||||
pure_virtual_called();
|
||||
return boost::system::errc::make_error_code (
|
||||
boost::system::errc::function_not_supported);
|
||||
}
|
||||
|
||||
static
|
||||
error_code
|
||||
pure_virtual_error (error_code& ec)
|
||||
{
|
||||
return ec = pure_virtual_error();
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
throw_if (error_code const& ec)
|
||||
{
|
||||
if (ec)
|
||||
throw boost::system::system_error (ec);
|
||||
}
|
||||
|
||||
public:
|
||||
virtual ~abstract_socket ()
|
||||
{
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
// abstract_socket
|
||||
//
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
/** Retrieve the underlying object.
|
||||
|
||||
@note If the type doesn't match, nullptr is returned or an
|
||||
exception is thrown if trying to acquire a reference.
|
||||
*/
|
||||
/** @{ */
|
||||
template <class Object>
|
||||
Object& this_layer ()
|
||||
{
|
||||
Object* object (this->this_layer_ptr <Object> ());
|
||||
if (object == nullptr)
|
||||
throw std::bad_cast ();
|
||||
return *object;
|
||||
}
|
||||
|
||||
template <class Object>
|
||||
Object const& this_layer () const
|
||||
{
|
||||
Object const* object (this->this_layer_ptr <Object> ());
|
||||
if (object == nullptr)
|
||||
throw std::bad_cast ();
|
||||
return *object;
|
||||
}
|
||||
|
||||
template <class Object>
|
||||
Object* this_layer_ptr ()
|
||||
{
|
||||
return static_cast <Object*> (
|
||||
this->this_layer_ptr (typeid (Object).name ()));
|
||||
}
|
||||
|
||||
template <class Object>
|
||||
Object const* this_layer_ptr () const
|
||||
{
|
||||
return static_cast <Object const*> (
|
||||
this->this_layer_ptr (typeid (Object).name ()));
|
||||
}
|
||||
/** @} */
|
||||
|
||||
virtual void* this_layer_ptr (char const* type_name) const
|
||||
BEAST_SOCKET_VIRTUAL;
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
// native_handle
|
||||
//
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
/** Retrieve the native representation of the object.
|
||||
|
||||
Since we dont know the return type, and because almost every
|
||||
asio implementation passes the result by value, you need to provide
|
||||
a pointer to a default-constructed object of the matching type.
|
||||
|
||||
@note If the type doesn't match, an exception is thrown.
|
||||
*/
|
||||
template <typename Handle>
|
||||
void native_handle (Handle* dest)
|
||||
{
|
||||
if (! native_handle (typeid (Handle).name (), dest))
|
||||
throw std::bad_cast ();
|
||||
}
|
||||
|
||||
virtual bool native_handle (char const* type_name, void* dest)
|
||||
BEAST_SOCKET_VIRTUAL;
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
// basic_io_object
|
||||
//
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
virtual boost::asio::io_service& get_io_service ()
|
||||
BEAST_SOCKET_VIRTUAL;
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
// basic_socket
|
||||
//
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
/** Retrieve the lowest layer object.
|
||||
|
||||
@note If the type doesn't match, nullptr is returned or an
|
||||
exception is thrown if trying to acquire a reference.
|
||||
*/
|
||||
/** @{ */
|
||||
template <class Object>
|
||||
Object& lowest_layer ()
|
||||
{
|
||||
Object* object (this->lowest_layer_ptr <Object> ());
|
||||
if (object == nullptr)
|
||||
throw std::bad_cast ();
|
||||
return *object;
|
||||
}
|
||||
|
||||
template <class Object>
|
||||
Object const& lowest_layer () const
|
||||
{
|
||||
Object const* object (this->lowest_layer_ptr <Object> ());
|
||||
if (object == nullptr)
|
||||
throw std::bad_cast ();
|
||||
return *object;
|
||||
}
|
||||
|
||||
template <class Object>
|
||||
Object* lowest_layer_ptr ()
|
||||
{
|
||||
return static_cast <Object*> (
|
||||
this->lowest_layer_ptr (typeid (Object).name ()));
|
||||
}
|
||||
|
||||
template <class Object>
|
||||
Object const* lowest_layer_ptr () const
|
||||
{
|
||||
return static_cast <Object const*> (
|
||||
this->lowest_layer_ptr (typeid (Object).name ()));
|
||||
}
|
||||
/** @} */
|
||||
|
||||
virtual void* lowest_layer_ptr (char const* type_name) const
|
||||
BEAST_SOCKET_VIRTUAL;
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
void cancel ()
|
||||
{
|
||||
error_code ec;
|
||||
cancel (ec);
|
||||
throw_if (ec);
|
||||
}
|
||||
|
||||
virtual error_code cancel (error_code& ec)
|
||||
BEAST_SOCKET_VIRTUAL;
|
||||
|
||||
void shutdown (shutdown_type what)
|
||||
{
|
||||
error_code ec;
|
||||
shutdown (what, ec);
|
||||
throw_if (ec);
|
||||
}
|
||||
|
||||
virtual error_code shutdown (shutdown_type what,
|
||||
error_code& ec)
|
||||
BEAST_SOCKET_VIRTUAL;
|
||||
|
||||
void close ()
|
||||
{
|
||||
error_code ec;
|
||||
close (ec);
|
||||
throw_if (ec);
|
||||
}
|
||||
|
||||
virtual error_code close (error_code& ec)
|
||||
BEAST_SOCKET_VIRTUAL;
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
// basic_socket_acceptor
|
||||
//
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
virtual error_code accept (abstract_socket& peer, error_code& ec)
|
||||
BEAST_SOCKET_VIRTUAL;
|
||||
|
||||
virtual void async_accept (abstract_socket& peer, error_handler handler)
|
||||
BEAST_SOCKET_VIRTUAL;
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
// basic_stream_socket
|
||||
//
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
virtual std::size_t read_some (mutable_buffers buffers, error_code& ec)
|
||||
BEAST_SOCKET_VIRTUAL;
|
||||
|
||||
virtual std::size_t write_some (const_buffers buffers, error_code& ec)
|
||||
BEAST_SOCKET_VIRTUAL;
|
||||
|
||||
virtual void async_read_some (mutable_buffers buffers,
|
||||
transfer_handler handler)
|
||||
BEAST_SOCKET_VIRTUAL;
|
||||
|
||||
virtual void async_write_some (const_buffers buffers,
|
||||
transfer_handler handler)
|
||||
BEAST_SOCKET_VIRTUAL;
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
// ssl::stream
|
||||
//
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
/** Retrieve the next layer object.
|
||||
|
||||
@note If the type doesn't match, nullptr is returned or an
|
||||
exception is thrown if trying to acquire a reference.
|
||||
*/
|
||||
/** @{ */
|
||||
template <class Object>
|
||||
Object& next_layer ()
|
||||
{
|
||||
Object* object (this->next_layer_ptr <Object> ());
|
||||
if (object == nullptr)
|
||||
throw std::bad_cast ();
|
||||
return *object;
|
||||
}
|
||||
|
||||
template <class Object>
|
||||
Object const& next_layer () const
|
||||
{
|
||||
Object const* object (this->next_layer_ptr <Object> ());
|
||||
if (object == nullptr)
|
||||
throw std::bad_cast ();
|
||||
return *object;
|
||||
}
|
||||
|
||||
template <class Object>
|
||||
Object* next_layer_ptr ()
|
||||
{
|
||||
return static_cast <Object*> (
|
||||
this->next_layer_ptr (typeid (Object).name ()));
|
||||
}
|
||||
|
||||
template <class Object>
|
||||
Object const* next_layer_ptr () const
|
||||
{
|
||||
return static_cast <Object const*> (
|
||||
this->next_layer_ptr (typeid (Object).name ()));
|
||||
}
|
||||
/** @} */
|
||||
|
||||
virtual void* next_layer_ptr (char const* type_name) const
|
||||
BEAST_SOCKET_VIRTUAL;
|
||||
|
||||
/** Determines if the underlying stream requires a handshake.
|
||||
|
||||
If needs_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 needs_handshake ()
|
||||
BEAST_SOCKET_VIRTUAL;
|
||||
|
||||
virtual void set_verify_mode (int verify_mode)
|
||||
BEAST_SOCKET_VIRTUAL;
|
||||
|
||||
void handshake (handshake_type type)
|
||||
{
|
||||
error_code ec;
|
||||
handshake (type, ec);
|
||||
throw_if (ec);
|
||||
}
|
||||
|
||||
virtual error_code handshake (handshake_type type, error_code& ec)
|
||||
BEAST_SOCKET_VIRTUAL;
|
||||
|
||||
virtual void async_handshake (handshake_type type, error_handler handler)
|
||||
BEAST_SOCKET_VIRTUAL;
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
virtual error_code handshake (handshake_type type,
|
||||
const_buffers buffers, error_code& ec)
|
||||
BEAST_SOCKET_VIRTUAL;
|
||||
|
||||
virtual void async_handshake (handshake_type type,
|
||||
const_buffers buffers, transfer_handler handler)
|
||||
BEAST_SOCKET_VIRTUAL;
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
void shutdown ()
|
||||
{
|
||||
error_code ec;
|
||||
shutdown (ec);
|
||||
throw_if (ec);
|
||||
}
|
||||
|
||||
virtual error_code shutdown (error_code& ec)
|
||||
BEAST_SOCKET_VIRTUAL;
|
||||
|
||||
virtual void async_shutdown (error_handler handler)
|
||||
BEAST_SOCKET_VIRTUAL;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
163
beast/asio/bind_handler.h
Normal file
163
beast/asio/bind_handler.h
Normal file
@@ -0,0 +1,163 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
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_ASIO_BIND_HANDLER_H_INCLUDED
|
||||
#define BEAST_ASIO_BIND_HANDLER_H_INCLUDED
|
||||
|
||||
#include <boost/asio/detail/handler_alloc_helpers.hpp>
|
||||
#include <boost/asio/detail/handler_cont_helpers.hpp>
|
||||
#include <boost/asio/detail/handler_invoke_helpers.hpp>
|
||||
|
||||
#include <functional>
|
||||
#include "../cxx14/type_traits.h" // <type_traits>
|
||||
#include "../cxx14/utility.h" // <utility>
|
||||
|
||||
namespace beast {
|
||||
namespace asio {
|
||||
|
||||
namespace detail {
|
||||
|
||||
/** Nullary handler that calls Handler with bound arguments.
|
||||
The rebound handler provides the same io_service execution
|
||||
guarantees as the original handler.
|
||||
*/
|
||||
template <class DeducedHandler, class... Args>
|
||||
class bound_handler
|
||||
{
|
||||
private:
|
||||
typedef std::tuple <std::decay_t <Args>...> args_type;
|
||||
|
||||
std::decay_t <DeducedHandler> m_handler;
|
||||
args_type m_args;
|
||||
|
||||
template <class Handler, class Tuple, std::size_t... S>
|
||||
static void invoke (Handler& h, Tuple& args,
|
||||
std::index_sequence <S...>)
|
||||
{
|
||||
h (std::get <S> (args)...);
|
||||
}
|
||||
|
||||
public:
|
||||
typedef void result_type;
|
||||
|
||||
bound_handler (DeducedHandler&& handler, Args&&... args)
|
||||
: m_handler (std::forward <DeducedHandler> (handler))
|
||||
, m_args (std::forward <Args> (args)...)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
operator() ()
|
||||
{
|
||||
invoke (m_handler, m_args,
|
||||
std::index_sequence_for <Args...> ());
|
||||
}
|
||||
|
||||
void
|
||||
operator() () const
|
||||
{
|
||||
invoke (m_handler, m_args,
|
||||
std::index_sequence_for <Args...> ());
|
||||
}
|
||||
|
||||
template <class Function>
|
||||
friend
|
||||
void
|
||||
asio_handler_invoke (Function& f, bound_handler* h)
|
||||
{
|
||||
boost_asio_handler_invoke_helpers::
|
||||
invoke (f, h->m_handler);
|
||||
}
|
||||
|
||||
template <class Function>
|
||||
friend
|
||||
void
|
||||
asio_handler_invoke (Function const& f, bound_handler* h)
|
||||
{
|
||||
boost_asio_handler_invoke_helpers::
|
||||
invoke (f, h->m_handler);
|
||||
}
|
||||
|
||||
friend
|
||||
void*
|
||||
asio_handler_allocate (std::size_t size, bound_handler* h)
|
||||
{
|
||||
return boost_asio_handler_alloc_helpers::
|
||||
allocate (size, h->m_handler);
|
||||
}
|
||||
|
||||
friend
|
||||
void
|
||||
asio_handler_deallocate (void* p, std::size_t size, bound_handler* h)
|
||||
{
|
||||
boost_asio_handler_alloc_helpers::
|
||||
deallocate (p, size, h->m_handler);
|
||||
}
|
||||
|
||||
friend
|
||||
bool
|
||||
asio_handler_is_continuation (bound_handler* h)
|
||||
{
|
||||
return boost_asio_handler_cont_helpers::
|
||||
is_continuation (h->m_handler);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** Binds parameters to a handler to produce a nullary functor.
|
||||
The returned handler provides the same io_service execution guarantees
|
||||
as the original handler. This is designed to use as a replacement for
|
||||
io_service::wrap, to ensure that the handler will not be invoked
|
||||
immediately by the calling function.
|
||||
*/
|
||||
template <class DeducedHandler, class... Args>
|
||||
detail::bound_handler <DeducedHandler, Args...>
|
||||
bind_handler (DeducedHandler&& handler, Args&&... args)
|
||||
{
|
||||
return detail::bound_handler <DeducedHandler, Args...> (
|
||||
std::forward <DeducedHandler> (handler),
|
||||
std::forward <Args> (args)...);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace std {
|
||||
|
||||
template <class Handler, class... Args>
|
||||
void bind (beast::asio::detail::bound_handler <
|
||||
Handler, Args...>, ...) = delete;
|
||||
|
||||
#if 0
|
||||
template <class Handler, class... Args>
|
||||
struct is_bind_expression <
|
||||
beast::asio::detail::bound_handler <Handler, Args...>
|
||||
> : std::true_type
|
||||
{
|
||||
};
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
110
beast/asio/buffer_sequence.h
Normal file
110
beast/asio/buffer_sequence.h
Normal 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_ASIO_BUFFER_SEQUENCE_H_INCLUDED
|
||||
#define BEAST_ASIO_BUFFER_SEQUENCE_H_INCLUDED
|
||||
|
||||
#include <boost/asio/buffer.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
#include "../cxx14/type_traits.h" // <type_traits>
|
||||
#include <vector>
|
||||
|
||||
namespace beast {
|
||||
namespace asio {
|
||||
|
||||
template <class Buffer>
|
||||
class buffer_sequence
|
||||
{
|
||||
private:
|
||||
typedef std::vector <Buffer> sequence_type;
|
||||
|
||||
public:
|
||||
typedef Buffer value_type;
|
||||
typedef typename sequence_type::const_iterator const_iterator;
|
||||
|
||||
private:
|
||||
sequence_type m_buffers;
|
||||
|
||||
template <class FwdIter>
|
||||
void assign (FwdIter first, FwdIter last)
|
||||
{
|
||||
m_buffers.clear();
|
||||
m_buffers.reserve (std::distance (first, last));
|
||||
for (;first != last; ++first)
|
||||
m_buffers.push_back (*first);
|
||||
}
|
||||
|
||||
public:
|
||||
buffer_sequence ()
|
||||
{
|
||||
}
|
||||
|
||||
template <
|
||||
class BufferSequence,
|
||||
class = std::enable_if_t <std::is_constructible <
|
||||
Buffer, typename BufferSequence::value_type>::value>
|
||||
>
|
||||
buffer_sequence (BufferSequence const& s)
|
||||
{
|
||||
assign (std::begin (s), std::end (s));
|
||||
}
|
||||
|
||||
template <
|
||||
class FwdIter,
|
||||
class = std::enable_if_t <std::is_constructible <
|
||||
Buffer, typename std::iterator_traits <
|
||||
FwdIter>::value_type>::value>
|
||||
>
|
||||
buffer_sequence (FwdIter first, FwdIter last)
|
||||
{
|
||||
assign (first, last);
|
||||
}
|
||||
|
||||
template <class BufferSequence>
|
||||
std::enable_if_t <std::is_constructible <
|
||||
Buffer, typename BufferSequence::value_type>::value,
|
||||
buffer_sequence&
|
||||
>
|
||||
operator= (BufferSequence const& s)
|
||||
{
|
||||
return assign (s);
|
||||
}
|
||||
|
||||
const_iterator
|
||||
begin () const noexcept
|
||||
{
|
||||
return m_buffers.begin ();
|
||||
}
|
||||
|
||||
const_iterator
|
||||
end () const noexcept
|
||||
{
|
||||
return m_buffers.end ();
|
||||
}
|
||||
};
|
||||
|
||||
typedef buffer_sequence <boost::asio::const_buffer> const_buffers;
|
||||
typedef buffer_sequence <boost::asio::mutable_buffer> mutable_buffers;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
41
beast/asio/placeholders.h
Normal file
41
beast/asio/placeholders.h
Normal file
@@ -0,0 +1,41 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
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_ASIO_PLACEHOLDERS_H_INCLUDED
|
||||
#define BEAST_ASIO_PLACEHOLDERS_H_INCLUDED
|
||||
|
||||
#include <functional>
|
||||
|
||||
namespace beast {
|
||||
namespace asio {
|
||||
|
||||
namespace placeholders {
|
||||
// asio placeholders that work with std::bind
|
||||
namespace {
|
||||
static auto const error (std::placeholders::_1);
|
||||
static auto const bytes_transferred (std::placeholders::_2);
|
||||
static auto const iterator (std::placeholders::_2);
|
||||
static auto const signal_number (std::placeholders::_2);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
472
beast/asio/shared_handler.h
Normal file
472
beast/asio/shared_handler.h
Normal file
@@ -0,0 +1,472 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
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_ASIO_SHARED_HANDLER_H_INCLUDED
|
||||
#define BEAST_ASIO_SHARED_HANDLER_H_INCLUDED
|
||||
|
||||
#include "../mpl/IsCallPossible.h"
|
||||
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include "../cxx14/type_traits.h" // <type_traits>
|
||||
|
||||
#include <boost/utility/base_from_member.hpp>
|
||||
|
||||
#include <boost/asio/detail/handler_alloc_helpers.hpp>
|
||||
#include <boost/asio/detail/handler_cont_helpers.hpp>
|
||||
#include <boost/asio/detail/handler_invoke_helpers.hpp>
|
||||
|
||||
#ifndef BEAST_ASIO_NO_ALLOCATE_SHARED
|
||||
#define BEAST_ASIO_NO_ALLOCATE_SHARED 0
|
||||
#endif
|
||||
|
||||
#ifndef BEAST_ASIO_NO_HANDLER_RESULT_OF
|
||||
#define BEAST_ASIO_NO_HANDLER_RESULT_OF 1
|
||||
#endif
|
||||
|
||||
namespace beast {
|
||||
namespace asio {
|
||||
|
||||
class shared_handler_wrapper_base
|
||||
{
|
||||
public:
|
||||
virtual ~shared_handler_wrapper_base()
|
||||
{
|
||||
}
|
||||
|
||||
virtual void invoke (std::function <void (void)> f) = 0;
|
||||
virtual void* allocate (std::size_t size) = 0;
|
||||
virtual void deallocate (void* p, std::size_t size) = 0;
|
||||
virtual bool is_continuation () = 0;
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template <class Signature>
|
||||
class shared_handler_wrapper_func
|
||||
: public shared_handler_wrapper_base
|
||||
{
|
||||
private:
|
||||
std::function <Signature> m_func;
|
||||
|
||||
public:
|
||||
template <class Handler>
|
||||
explicit shared_handler_wrapper_func (Handler&& handler)
|
||||
: m_func (std::ref (std::forward <Handler> (handler)))
|
||||
{
|
||||
}
|
||||
|
||||
template <class... Args>
|
||||
#if BEAST_ASIO_NO_HANDLER_RESULT_OF
|
||||
void
|
||||
#else
|
||||
std::result_of_t <std::function <Signature> (Args...)>
|
||||
#endif
|
||||
operator() (Args&&... args) const
|
||||
{
|
||||
return m_func (std::forward <Args> (args)...);
|
||||
}
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace detail {
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning (push)
|
||||
#pragma warning (disable: 4512) // assignment operator could not be generated
|
||||
#endif
|
||||
|
||||
template <class Signature, class Handler>
|
||||
class shared_handler_wrapper
|
||||
: private boost::base_from_member <Handler>
|
||||
, public shared_handler_wrapper_func <Signature>
|
||||
{
|
||||
private:
|
||||
typedef boost::base_from_member <Handler> Base;
|
||||
|
||||
BEAST_DEFINE_IS_CALL_POSSIBLE(has_is_continuation, is_continuation);
|
||||
|
||||
public:
|
||||
shared_handler_wrapper (Handler&& handler)
|
||||
: boost::base_from_member <Handler> (std::move (handler))
|
||||
, shared_handler_wrapper_func <Signature> (Base::member)
|
||||
{
|
||||
}
|
||||
|
||||
shared_handler_wrapper (Handler const& handler)
|
||||
: boost::base_from_member <Handler> (handler)
|
||||
, shared_handler_wrapper_func <Signature> (Base::member)
|
||||
{
|
||||
}
|
||||
|
||||
private:
|
||||
void
|
||||
invoke (std::function <void (void)> f) override
|
||||
{
|
||||
return boost_asio_handler_invoke_helpers::
|
||||
invoke (f, Base::member);
|
||||
}
|
||||
|
||||
void*
|
||||
allocate (std::size_t size) override
|
||||
{
|
||||
return boost_asio_handler_alloc_helpers::
|
||||
allocate (size, Base::member);
|
||||
}
|
||||
|
||||
void
|
||||
deallocate (void* p, std::size_t size) override
|
||||
{
|
||||
boost_asio_handler_alloc_helpers::
|
||||
deallocate (p, size, Base::member);
|
||||
}
|
||||
|
||||
bool
|
||||
is_continuation () override
|
||||
{
|
||||
return is_continuation (std::integral_constant <bool,
|
||||
has_is_continuation <Handler, bool(void)>::value>());
|
||||
}
|
||||
|
||||
bool
|
||||
is_continuation (std::true_type)
|
||||
{
|
||||
return Base::member.is_continuation();
|
||||
}
|
||||
|
||||
bool
|
||||
is_continuation (std::false_type)
|
||||
{
|
||||
return boost_asio_handler_cont_helpers::
|
||||
is_continuation (Base::member);
|
||||
}
|
||||
};
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning (pop)
|
||||
#endif
|
||||
|
||||
template <class T>
|
||||
struct is_shared_handler : public std::false_type
|
||||
{
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template <class T, class Handler>
|
||||
class handler_allocator
|
||||
{
|
||||
private:
|
||||
// We want a partial template specialization as a friend
|
||||
// but that isn't allowed so we friend all versions. This
|
||||
// should produce a compile error if Handler is not constructible
|
||||
// from H.
|
||||
//
|
||||
template <class U, class H>
|
||||
friend class handler_allocator;
|
||||
|
||||
Handler m_handler;
|
||||
|
||||
public:
|
||||
typedef T value_type;
|
||||
typedef T* pointer;
|
||||
|
||||
template <class U>
|
||||
struct rebind
|
||||
{
|
||||
public:
|
||||
typedef handler_allocator <U, Handler> other;
|
||||
};
|
||||
|
||||
handler_allocator() = delete;
|
||||
|
||||
handler_allocator (Handler const& handler)
|
||||
: m_handler (handler)
|
||||
{
|
||||
}
|
||||
|
||||
template <class U>
|
||||
handler_allocator (
|
||||
handler_allocator <U, Handler> const& other)
|
||||
: m_handler (other.m_handler)
|
||||
{
|
||||
}
|
||||
|
||||
handler_allocator&
|
||||
operator= (handler_allocator const&) = delete;
|
||||
|
||||
pointer
|
||||
allocate (std::ptrdiff_t n)
|
||||
{
|
||||
auto const size (n * sizeof (T));
|
||||
return static_cast <pointer> (
|
||||
boost_asio_handler_alloc_helpers::allocate (
|
||||
size, m_handler));
|
||||
}
|
||||
|
||||
void
|
||||
deallocate (pointer p, std::ptrdiff_t n)
|
||||
{
|
||||
auto const size (n * sizeof (T));
|
||||
boost_asio_handler_alloc_helpers::deallocate (
|
||||
p, size, m_handler);
|
||||
}
|
||||
|
||||
// Work-around for MSVC not using allocator_traits
|
||||
// in the implementation of shared_ptr
|
||||
//
|
||||
#ifdef _MSC_VER
|
||||
void
|
||||
destroy (T* t)
|
||||
{
|
||||
t->~T();
|
||||
}
|
||||
#endif
|
||||
|
||||
friend
|
||||
bool
|
||||
operator== (handler_allocator const& lhs, handler_allocator const& rhs)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
friend
|
||||
bool
|
||||
operator!= (handler_allocator const& lhs, handler_allocator const& rhs)
|
||||
{
|
||||
return ! (lhs == rhs);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** Handler shared reference that provides io_service execution guarantees. */
|
||||
template <
|
||||
class Signature
|
||||
>
|
||||
class shared_handler
|
||||
{
|
||||
private:
|
||||
template <class T>
|
||||
friend class shared_handler_allocator;
|
||||
|
||||
typedef shared_handler_wrapper_func <
|
||||
Signature> wrapper_type;
|
||||
|
||||
typedef std::shared_ptr <wrapper_type> ptr_type;
|
||||
|
||||
ptr_type m_ptr;
|
||||
|
||||
public:
|
||||
shared_handler()
|
||||
{
|
||||
}
|
||||
|
||||
template <
|
||||
class DeducedHandler,
|
||||
class = std::enable_if_t <
|
||||
! detail::is_shared_handler <
|
||||
std::decay_t <DeducedHandler>>::value &&
|
||||
std::is_constructible <std::function <Signature>,
|
||||
std::decay_t <DeducedHandler>>::value
|
||||
>
|
||||
>
|
||||
shared_handler (DeducedHandler&& handler)
|
||||
{
|
||||
typedef std::remove_reference_t <DeducedHandler> Handler;
|
||||
|
||||
#if BEAST_ASIO_NO_ALLOCATE_SHARED
|
||||
m_ptr = std::make_shared <detail::shared_handler_wrapper <
|
||||
Signature, Handler>> (std::forward <DeducedHandler> (handler));
|
||||
#else
|
||||
m_ptr = std::allocate_shared <detail::shared_handler_wrapper <
|
||||
Signature, Handler>> (detail::handler_allocator <char, Handler> (
|
||||
handler), std::forward <DeducedHandler> (handler));
|
||||
#endif
|
||||
}
|
||||
|
||||
shared_handler (shared_handler&& other)
|
||||
: m_ptr (std::move (other.m_ptr))
|
||||
{
|
||||
}
|
||||
|
||||
shared_handler (shared_handler const& other)
|
||||
: m_ptr (other.m_ptr)
|
||||
{
|
||||
}
|
||||
|
||||
shared_handler&
|
||||
operator= (std::nullptr_t)
|
||||
{
|
||||
m_ptr = nullptr;
|
||||
}
|
||||
|
||||
shared_handler&
|
||||
operator= (shared_handler const& rhs)
|
||||
{
|
||||
m_ptr = rhs.m_ptr;
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool
|
||||
empty() const
|
||||
{
|
||||
return ! m_ptr.operator bool();
|
||||
}
|
||||
|
||||
operator bool() const
|
||||
{
|
||||
return !empty();
|
||||
}
|
||||
|
||||
void
|
||||
reset()
|
||||
{
|
||||
m_ptr.reset();
|
||||
}
|
||||
|
||||
template <class... Args>
|
||||
#if BEAST_ASIO_NO_HANDLER_RESULT_OF
|
||||
void
|
||||
#else
|
||||
std::result_of_t <std::function <Signature> (Args...)>
|
||||
#endif
|
||||
operator() (Args&&... args) const
|
||||
{
|
||||
return (*m_ptr)(std::forward <Args> (args)...);
|
||||
}
|
||||
|
||||
template <class Function>
|
||||
friend
|
||||
void
|
||||
asio_handler_invoke (Function&& f, shared_handler* h)
|
||||
{
|
||||
return h->m_ptr->invoke (f);
|
||||
}
|
||||
|
||||
friend
|
||||
void*
|
||||
asio_handler_allocate (
|
||||
std::size_t size, shared_handler* h)
|
||||
{
|
||||
return h->m_ptr->allocate (size);
|
||||
}
|
||||
|
||||
friend
|
||||
void
|
||||
asio_handler_deallocate (
|
||||
void* p, std::size_t size, shared_handler* h)
|
||||
{
|
||||
return h->m_ptr->deallocate (p, size);
|
||||
}
|
||||
|
||||
friend
|
||||
bool
|
||||
asio_handler_is_continuation (
|
||||
shared_handler* h)
|
||||
{
|
||||
return h->m_ptr->is_continuation ();
|
||||
}
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace detail {
|
||||
|
||||
template <
|
||||
class Signature
|
||||
>
|
||||
struct is_shared_handler <
|
||||
shared_handler <Signature>
|
||||
> : public std::true_type
|
||||
{
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template <class T>
|
||||
class shared_handler_allocator
|
||||
{
|
||||
private:
|
||||
template <class U>
|
||||
friend class shared_handler_allocator;
|
||||
|
||||
std::shared_ptr <shared_handler_wrapper_base> m_ptr;
|
||||
|
||||
public:
|
||||
typedef T value_type;
|
||||
typedef T* pointer;
|
||||
|
||||
shared_handler_allocator() = delete;
|
||||
|
||||
template <class Signature>
|
||||
shared_handler_allocator (
|
||||
shared_handler <Signature> const& handler)
|
||||
: m_ptr (handler.m_ptr)
|
||||
{
|
||||
}
|
||||
|
||||
template <class U>
|
||||
shared_handler_allocator (
|
||||
shared_handler_allocator <U> const& other)
|
||||
: m_ptr (other.m_ptr)
|
||||
{
|
||||
}
|
||||
|
||||
pointer
|
||||
allocate (std::ptrdiff_t n)
|
||||
{
|
||||
auto const size (n * sizeof (T));
|
||||
return static_cast <pointer> (
|
||||
m_ptr->allocate (size));
|
||||
}
|
||||
|
||||
void
|
||||
deallocate (pointer p, std::ptrdiff_t n)
|
||||
{
|
||||
auto const size (n * sizeof (T));
|
||||
m_ptr->deallocate (p, size);
|
||||
}
|
||||
|
||||
friend
|
||||
bool
|
||||
operator== (shared_handler_allocator const& lhs,
|
||||
shared_handler_allocator const& rhs)
|
||||
{
|
||||
return lhs.m_ptr == rhs.m_ptr;
|
||||
}
|
||||
|
||||
friend
|
||||
bool
|
||||
operator!= (shared_handler_allocator const& lhs,
|
||||
shared_handler_allocator const& rhs)
|
||||
{
|
||||
return ! (lhs == rhs);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
829
beast/asio/socket_wrapper.h
Normal file
829
beast/asio/socket_wrapper.h
Normal file
@@ -0,0 +1,829 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
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_ASIO_SOCKET_WRAPPER_H_INCLUDED
|
||||
#define BEAST_ASIO_SOCKET_WRAPPER_H_INCLUDED
|
||||
|
||||
#include "abstract_socket.h"
|
||||
#include "bind_handler.h"
|
||||
|
||||
namespace beast {
|
||||
namespace asio {
|
||||
|
||||
/** Wraps a reference to any object and exports all availble interfaces.
|
||||
|
||||
If the object does not support an interface, calling those
|
||||
member functions will behave as if a pure virtual was called.
|
||||
|
||||
Note that only a reference to the underlying is stored. Management
|
||||
of the lifetime of the object is controlled by the caller.
|
||||
|
||||
Examples of the type of Object:
|
||||
|
||||
asio::ip::tcp::socket
|
||||
asio::ip::tcp::socket&
|
||||
asio::ssl::stream <asio::ip::tcp::socket>
|
||||
asio::ssl::stream <asio::ip::tcp::socket&>
|
||||
explain arg must be an io_context
|
||||
explain socket_wrapper will create and take ownership of the tcp::socket
|
||||
explain this_layer_type will be tcp::socket
|
||||
explain next_layer () returns a asio::ip::tcp::socket&
|
||||
explain lowest_layer () returns a asio::ip::tcp::socket&
|
||||
|
||||
asio::ssl::stream <asio::buffered_stream <asio::ip::tcp::socket> > >
|
||||
This makes my head explode
|
||||
*/
|
||||
template <typename Object>
|
||||
class socket_wrapper : public abstract_socket
|
||||
{
|
||||
private:
|
||||
Object m_object;
|
||||
|
||||
public:
|
||||
template <class... Args>
|
||||
explicit socket_wrapper (Args&&... args)
|
||||
: m_object (std::forward <Args> (args)...)
|
||||
{
|
||||
}
|
||||
|
||||
socket_wrapper (socket_wrapper const&) = delete;
|
||||
socket_wrapper& operator= (socket_wrapper const&) = delete;
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
// socket_wrapper
|
||||
//
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
/** The type of the object being wrapped. */
|
||||
typedef typename boost::remove_reference <Object>::type this_layer_type;
|
||||
|
||||
/** Get a reference to this layer. */
|
||||
this_layer_type& this_layer () noexcept
|
||||
{
|
||||
return m_object;
|
||||
}
|
||||
|
||||
/** Get a const reference to this layer. */
|
||||
this_layer_type const& this_layer () const noexcept
|
||||
{
|
||||
return m_object;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
// abstract_socket
|
||||
//
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
void* this_layer_ptr (char const* type_name) const override
|
||||
{
|
||||
char const* const name (typeid (this_layer_type).name ());
|
||||
if (strcmp (name, type_name) == 0)
|
||||
return const_cast <void*> (static_cast <void const*> (&m_object));
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
private:
|
||||
BEAST_DEFINE_IS_CALL_POSSIBLE(has_get_io_service, get_io_service);
|
||||
|
||||
BEAST_DEFINE_IS_CALL_POSSIBLE(has_lowest_layer, lowest_layer);
|
||||
BEAST_DEFINE_IS_CALL_POSSIBLE(has_cancel, cancel);
|
||||
BEAST_DEFINE_IS_CALL_POSSIBLE(has_shutdown, shutdown);
|
||||
BEAST_DEFINE_IS_CALL_POSSIBLE(has_close, close);
|
||||
|
||||
BEAST_DEFINE_IS_CALL_POSSIBLE(has_accept, accept);
|
||||
BEAST_DEFINE_IS_CALL_POSSIBLE(has_async_accept, async_accept);
|
||||
|
||||
BEAST_DEFINE_IS_CALL_POSSIBLE(has_read_some, read_some);
|
||||
BEAST_DEFINE_IS_CALL_POSSIBLE(has_write_some, write_some);
|
||||
BEAST_DEFINE_IS_CALL_POSSIBLE(has_async_read_some, async_read_some);
|
||||
BEAST_DEFINE_IS_CALL_POSSIBLE(has_async_write_some, async_write_some);
|
||||
|
||||
BEAST_DEFINE_IS_CALL_POSSIBLE(has_set_verify_mode, set_verify_mode);
|
||||
BEAST_DEFINE_IS_CALL_POSSIBLE(has_handshake, handshake);
|
||||
BEAST_DEFINE_IS_CALL_POSSIBLE(has_async_handshake, async_handshake);
|
||||
BEAST_DEFINE_IS_CALL_POSSIBLE(has_async_shutdown, async_shutdown);
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
// Implementation
|
||||
//
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
template <class Cond>
|
||||
struct Enabled : public std::integral_constant <bool, Cond::value>
|
||||
{
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
// native_handle
|
||||
//
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
#if 0
|
||||
// This is a potential work-around for the problem with
|
||||
// the has_type_native_handle_type template, but requires
|
||||
// Boost 1.54 or later.
|
||||
//
|
||||
// This include will be needed:
|
||||
//
|
||||
// boost/tti/has_type.hpp
|
||||
//
|
||||
//
|
||||
BOOST_TTI_HAS_TYPE(native_handle_type)
|
||||
|
||||
#else
|
||||
template <class T>
|
||||
struct has_type_native_handle_type
|
||||
{
|
||||
typedef char yes;
|
||||
typedef struct {char dummy[2];} no;
|
||||
template <class C> static yes f(typename C::native_handle_type*);
|
||||
template <class C> static no f(...);
|
||||
#ifdef _MSC_VER
|
||||
static bool const value = sizeof(f<T>(0)) == 1;
|
||||
#else
|
||||
// This line fails to compile under Visual Studio 2012
|
||||
static bool const value = sizeof(
|
||||
has_type_native_handle_type<T>::f<T>(0)) == 1;
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
template <typename T,
|
||||
bool Exists = has_type_native_handle_type <T>::value
|
||||
>
|
||||
struct extract_native_handle_type
|
||||
{
|
||||
typedef typename T::native_handle_type type;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct extract_native_handle_type <T, false>
|
||||
{
|
||||
typedef void type;
|
||||
};
|
||||
|
||||
// This will be void if native_handle_type doesn't exist in Object
|
||||
typedef typename extract_native_handle_type <
|
||||
this_layer_type>::type native_handle_type;
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
bool native_handle (char const* type_name, void* dest) override
|
||||
{
|
||||
return native_handle (type_name, dest,
|
||||
Enabled <has_type_native_handle_type <this_layer_type> > ());
|
||||
}
|
||||
|
||||
bool native_handle (char const* type_name, void* dest,
|
||||
std::true_type)
|
||||
{
|
||||
char const* const name (typeid (
|
||||
typename this_layer_type::native_handle_type).name ());
|
||||
if (strcmp (name, type_name) == 0)
|
||||
{
|
||||
native_handle_type* const p (reinterpret_cast <
|
||||
native_handle_type*> (dest));
|
||||
*p = m_object.native_handle ();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool native_handle (char const*, void*,
|
||||
std::false_type)
|
||||
{
|
||||
pure_virtual_called();
|
||||
return false;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
// basic_io_object
|
||||
//
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
boost::asio::io_service& get_io_service () override
|
||||
{
|
||||
#if 0
|
||||
// Apparently has_get_io_service always results in false
|
||||
return get_io_service (
|
||||
Enabled <has_get_io_service <this_layer_type,
|
||||
boost::asio::io_service&()> > ());
|
||||
#else
|
||||
return get_io_service (std::true_type ());
|
||||
#endif
|
||||
}
|
||||
|
||||
boost::asio::io_service& get_io_service (
|
||||
std::true_type)
|
||||
{
|
||||
return m_object.get_io_service ();
|
||||
}
|
||||
|
||||
boost::asio::io_service& get_io_service (
|
||||
std::false_type)
|
||||
{
|
||||
pure_virtual_called();
|
||||
return *static_cast <boost::asio::io_service*>(nullptr);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
// basic_socket
|
||||
//
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
To forward the lowest_layer_type type, we need to make sure it
|
||||
exists in Object. This is a little more tricky than just figuring
|
||||
out if Object has a particular member function.
|
||||
|
||||
The problem is boost::asio::basic_socket_acceptor, which doesn't
|
||||
have lowest_layer () or lowest_layer_type ().
|
||||
*/
|
||||
|
||||
template <class T>
|
||||
struct has_type_lowest_layer_type
|
||||
{
|
||||
typedef char yes;
|
||||
typedef struct {char dummy[2];} no;
|
||||
template <class C> static yes f(typename C::lowest_layer_type*);
|
||||
template <class C> static no f(...);
|
||||
#ifdef _MSC_VER
|
||||
static bool const value = sizeof(f<T>(0)) == 1;
|
||||
#else
|
||||
// This line fails to compile under Visual Studio 2012
|
||||
static bool const value = sizeof(has_type_lowest_layer_type<T>::f<T>(0)) == 1;
|
||||
#endif
|
||||
};
|
||||
|
||||
template <typename T, bool Exists = has_type_lowest_layer_type <T>::value >
|
||||
struct extract_lowest_layer_type
|
||||
{
|
||||
typedef typename T::lowest_layer_type type;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct extract_lowest_layer_type <T, false>
|
||||
{
|
||||
typedef void type;
|
||||
};
|
||||
|
||||
// This will be void if lowest_layer_type doesn't exist in Object
|
||||
typedef typename extract_lowest_layer_type <this_layer_type>::type lowest_layer_type;
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
void* lowest_layer_ptr (char const* type_name) const override
|
||||
{
|
||||
return lowest_layer_ptr (type_name,
|
||||
Enabled <has_type_lowest_layer_type <this_layer_type> > ());
|
||||
}
|
||||
|
||||
void* lowest_layer_ptr (char const* type_name,
|
||||
std::true_type) const
|
||||
{
|
||||
char const* const name (typeid (typename this_layer_type::lowest_layer_type).name ());
|
||||
if (strcmp (name, type_name) == 0)
|
||||
return const_cast <void*> (static_cast <void const*> (&m_object.lowest_layer ()));
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void* lowest_layer_ptr (char const*,
|
||||
std::false_type) const
|
||||
{
|
||||
pure_virtual_called();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
error_code cancel (error_code& ec) override
|
||||
{
|
||||
return cancel (ec,
|
||||
Enabled <has_cancel <this_layer_type,
|
||||
error_code (error_code&)> > ());
|
||||
}
|
||||
|
||||
error_code cancel (error_code& ec,
|
||||
std::true_type)
|
||||
{
|
||||
return m_object.cancel (ec);
|
||||
}
|
||||
|
||||
error_code cancel (error_code& ec,
|
||||
std::false_type)
|
||||
{
|
||||
return pure_virtual_error (ec);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
error_code shutdown (shutdown_type what, error_code& ec) override
|
||||
{
|
||||
return shutdown (what, ec,
|
||||
Enabled <has_shutdown <this_layer_type,
|
||||
error_code (shutdown_type, error_code&)> > ());
|
||||
}
|
||||
|
||||
|
||||
error_code shutdown (shutdown_type what, error_code& ec,
|
||||
std::true_type)
|
||||
{
|
||||
return m_object.shutdown (what, ec);
|
||||
}
|
||||
|
||||
error_code shutdown (shutdown_type, error_code& ec,
|
||||
std::false_type)
|
||||
{
|
||||
return pure_virtual_error (ec);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
error_code close (error_code& ec) override
|
||||
{
|
||||
return close (ec,
|
||||
Enabled <has_close <this_layer_type,
|
||||
error_code (error_code&)> > ());
|
||||
}
|
||||
|
||||
error_code close (error_code& ec,
|
||||
std::true_type)
|
||||
{
|
||||
return m_object.close (ec);
|
||||
}
|
||||
|
||||
error_code close (error_code& ec,
|
||||
std::false_type)
|
||||
{
|
||||
return pure_virtual_error (ec);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
// basic_socket_acceptor
|
||||
//
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
// Extracts the underlying socket type from the protocol of another asio object
|
||||
template <typename T, typename Enable = void>
|
||||
struct native_socket
|
||||
{
|
||||
typedef void* socket_type;
|
||||
inline native_socket (abstract_socket&)
|
||||
: m_socket (nullptr)
|
||||
{
|
||||
abstract_socket::pure_virtual_called();
|
||||
}
|
||||
inline socket_type& get ()
|
||||
{
|
||||
abstract_socket::pure_virtual_called();
|
||||
return m_socket;
|
||||
}
|
||||
inline socket_type& operator-> ()
|
||||
{
|
||||
return get ();
|
||||
}
|
||||
private:
|
||||
socket_type m_socket;
|
||||
};
|
||||
|
||||
// Enabled if T::protocol_type::socket exists as a type
|
||||
template <typename T>
|
||||
struct native_socket <T, typename boost::enable_if <boost::is_class <
|
||||
typename T::protocol_type::socket> >::type>
|
||||
{
|
||||
typedef typename T::protocol_type::socket socket_type;
|
||||
inline native_socket (abstract_socket& peer)
|
||||
: m_socket_ptr (&peer.this_layer <socket_type> ())
|
||||
{
|
||||
}
|
||||
inline socket_type& get () noexcept
|
||||
{
|
||||
return *m_socket_ptr;
|
||||
}
|
||||
inline socket_type& operator-> () noexcept
|
||||
{
|
||||
return get ();
|
||||
}
|
||||
private:
|
||||
socket_type* m_socket_ptr;
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
error_code accept (abstract_socket& peer, error_code& ec) override
|
||||
{
|
||||
typedef typename native_socket <this_layer_type>::socket_type socket_type;
|
||||
return accept (peer, ec,
|
||||
Enabled <has_accept <this_layer_type,
|
||||
error_code (socket_type&, error_code&)> > ());
|
||||
}
|
||||
|
||||
error_code accept (abstract_socket& peer, error_code& ec,
|
||||
std::true_type)
|
||||
{
|
||||
return m_object.accept (
|
||||
native_socket <this_layer_type> (peer).get (), ec);
|
||||
}
|
||||
|
||||
error_code accept (abstract_socket&, error_code& ec,
|
||||
std::false_type)
|
||||
{
|
||||
return pure_virtual_error (ec);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
void async_accept (abstract_socket& peer, error_handler handler) override
|
||||
{
|
||||
typedef typename native_socket <this_layer_type>::socket_type socket_type;
|
||||
async_accept (peer, handler,
|
||||
Enabled <has_async_accept <this_layer_type,
|
||||
void (socket_type&, error_handler)> > ());
|
||||
}
|
||||
|
||||
void async_accept (abstract_socket& peer, error_handler const& handler,
|
||||
std::true_type)
|
||||
{
|
||||
m_object.async_accept (
|
||||
native_socket <this_layer_type> (peer).get (), handler);
|
||||
}
|
||||
|
||||
void async_accept (abstract_socket&, error_handler const& handler,
|
||||
std::false_type)
|
||||
{
|
||||
get_io_service ().post (bind_handler (
|
||||
handler, pure_virtual_error()));
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
// basic_stream_socket
|
||||
//
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
std::size_t
|
||||
read_some (mutable_buffers buffers, error_code& ec) override
|
||||
{
|
||||
return read_some (buffers, ec,
|
||||
Enabled <has_read_some <this_layer_type,
|
||||
std::size_t (mutable_buffers const&, error_code&)> > ());
|
||||
}
|
||||
|
||||
std::size_t
|
||||
read_some (mutable_buffers const& buffers, error_code& ec,
|
||||
std::true_type)
|
||||
{
|
||||
return m_object.read_some (buffers, ec);
|
||||
}
|
||||
|
||||
std::size_t read_some (mutable_buffers const&, error_code& ec,
|
||||
std::false_type)
|
||||
{
|
||||
ec = pure_virtual_error ();
|
||||
return 0;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
std::size_t
|
||||
write_some (const_buffers buffers, error_code& ec) override
|
||||
{
|
||||
return write_some (buffers, ec,
|
||||
Enabled <has_write_some <this_layer_type,
|
||||
std::size_t (const_buffers const&, error_code&)> > ());
|
||||
}
|
||||
|
||||
std::size_t
|
||||
write_some (const_buffers const& buffers, error_code& ec,
|
||||
std::true_type)
|
||||
{
|
||||
return m_object.write_some (buffers, ec);
|
||||
}
|
||||
|
||||
std::size_t
|
||||
write_some (const_buffers const&, error_code& ec,
|
||||
std::false_type)
|
||||
{
|
||||
ec = pure_virtual_error ();
|
||||
return 0;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
void async_read_some (mutable_buffers buffers,
|
||||
transfer_handler handler) override
|
||||
{
|
||||
async_read_some (buffers, handler,
|
||||
Enabled <has_async_read_some <this_layer_type,
|
||||
void (mutable_buffers const&, transfer_handler const&)> > ());
|
||||
}
|
||||
|
||||
void
|
||||
async_read_some (mutable_buffers const& buffers,
|
||||
transfer_handler const& handler,
|
||||
std::true_type)
|
||||
{
|
||||
m_object.async_read_some (buffers, handler);
|
||||
}
|
||||
|
||||
void
|
||||
async_read_some (mutable_buffers const&,
|
||||
transfer_handler const& handler,
|
||||
std::false_type)
|
||||
{
|
||||
get_io_service ().post (bind_handler (
|
||||
handler, pure_virtual_error(), 0));
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
void
|
||||
async_write_some (const_buffers buffers,
|
||||
transfer_handler handler) override
|
||||
{
|
||||
async_write_some (buffers, handler,
|
||||
Enabled <has_async_write_some <this_layer_type,
|
||||
void (const_buffers const&, transfer_handler const&)> > ());
|
||||
}
|
||||
|
||||
void
|
||||
async_write_some (const_buffers const& buffers,
|
||||
transfer_handler const& handler,
|
||||
std::true_type)
|
||||
{
|
||||
m_object.async_write_some (buffers, handler);
|
||||
}
|
||||
|
||||
void
|
||||
async_write_some (const_buffers const&,
|
||||
transfer_handler const& handler,
|
||||
std::false_type)
|
||||
{
|
||||
get_io_service ().post (bind_handler (
|
||||
handler, pure_virtual_error(), 0));
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
// ssl::stream
|
||||
//
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
template <class T>
|
||||
struct has_type_next_layer_type
|
||||
{
|
||||
typedef char yes;
|
||||
typedef struct {char dummy[2];} no;
|
||||
template <class C> static yes f(typename C::next_layer_type*);
|
||||
template <class C> static no f(...);
|
||||
#ifdef _MSC_VER
|
||||
static bool const value = sizeof(f<T>(0)) == 1;
|
||||
#else
|
||||
// This line fails to compile under Visual Studio 2012
|
||||
static bool const value = sizeof(has_type_next_layer_type<T>::f<T>(0)) == 1;
|
||||
#endif
|
||||
};
|
||||
|
||||
template <typename T, bool Exists = has_type_next_layer_type <T>::value >
|
||||
struct extract_next_layer_type
|
||||
{
|
||||
typedef typename T::next_layer_type type;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct extract_next_layer_type <T, false>
|
||||
{
|
||||
typedef void type;
|
||||
};
|
||||
|
||||
// This will be void if next_layer_type doesn't exist in Object
|
||||
typedef typename extract_next_layer_type <this_layer_type>::type next_layer_type;
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
void* next_layer_ptr (char const* type_name) const override
|
||||
{
|
||||
return next_layer_ptr (type_name,
|
||||
Enabled <has_type_next_layer_type <this_layer_type> > ());
|
||||
}
|
||||
|
||||
void* next_layer_ptr (char const* type_name,
|
||||
std::true_type) const
|
||||
{
|
||||
char const* const name (typeid (typename this_layer_type::next_layer_type).name ());
|
||||
if (strcmp (name, type_name) == 0)
|
||||
return const_cast <void*> (static_cast <void const*> (&m_object.next_layer ()));
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void* next_layer_ptr (char const*,
|
||||
std::false_type) const
|
||||
{
|
||||
pure_virtual_called();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
bool needs_handshake () override
|
||||
{
|
||||
return
|
||||
has_handshake <this_layer_type,
|
||||
error_code (handshake_type, error_code&)>::value ||
|
||||
has_async_handshake <this_layer_type,
|
||||
void (handshake_type, error_handler)>::value;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
void set_verify_mode (int verify_mode) override
|
||||
{
|
||||
set_verify_mode (verify_mode,
|
||||
Enabled <has_set_verify_mode <this_layer_type,
|
||||
void (int)> > ());
|
||||
|
||||
}
|
||||
|
||||
void set_verify_mode (int verify_mode,
|
||||
std::true_type)
|
||||
{
|
||||
m_object.set_verify_mode (verify_mode);
|
||||
}
|
||||
|
||||
void set_verify_mode (int,
|
||||
std::false_type)
|
||||
{
|
||||
pure_virtual_called();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
error_code
|
||||
handshake (handshake_type type, error_code& ec) override
|
||||
{
|
||||
return handshake (type, ec,
|
||||
Enabled <has_handshake <this_layer_type,
|
||||
error_code (handshake_type, error_code&)> > ());
|
||||
}
|
||||
|
||||
error_code
|
||||
handshake (handshake_type type, error_code& ec,
|
||||
std::true_type)
|
||||
{
|
||||
return m_object.handshake (type, ec);
|
||||
}
|
||||
|
||||
error_code
|
||||
handshake (handshake_type, error_code& ec,
|
||||
std::false_type)
|
||||
{
|
||||
return pure_virtual_error (ec);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
void async_handshake (handshake_type type, error_handler handler) override
|
||||
{
|
||||
async_handshake (type, handler,
|
||||
Enabled <has_async_handshake <this_layer_type,
|
||||
void (handshake_type, error_handler)> > ());
|
||||
}
|
||||
|
||||
void async_handshake (handshake_type type, error_handler const& handler,
|
||||
std::true_type)
|
||||
{
|
||||
m_object.async_handshake (type, handler);
|
||||
}
|
||||
|
||||
void async_handshake (handshake_type, error_handler const& handler,
|
||||
std::false_type)
|
||||
{
|
||||
get_io_service ().post (bind_handler (
|
||||
handler, pure_virtual_error()));
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
error_code
|
||||
handshake (handshake_type type, const_buffers buffers,
|
||||
error_code& ec) override
|
||||
{
|
||||
return handshake (type, buffers, ec,
|
||||
Enabled <has_handshake <this_layer_type,
|
||||
error_code (handshake_type, const_buffers const&, error_code&)> > ());
|
||||
}
|
||||
|
||||
error_code
|
||||
handshake (handshake_type type, const_buffers const& buffers,
|
||||
error_code& ec,
|
||||
std::true_type)
|
||||
{
|
||||
return m_object.handshake (type, buffers, ec);
|
||||
}
|
||||
|
||||
error_code
|
||||
handshake (handshake_type, const_buffers const&,
|
||||
error_code& ec,
|
||||
std::false_type)
|
||||
{
|
||||
return pure_virtual_error (ec);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
void async_handshake (handshake_type type,
|
||||
const_buffers buffers, transfer_handler handler) override
|
||||
{
|
||||
async_handshake (type, buffers, handler,
|
||||
Enabled <has_async_handshake <this_layer_type,
|
||||
void (handshake_type, const_buffers const&,
|
||||
transfer_handler)> > ());
|
||||
}
|
||||
|
||||
void async_handshake (handshake_type type, const_buffers const& buffers,
|
||||
transfer_handler const& handler,
|
||||
std::true_type)
|
||||
{
|
||||
m_object.async_handshake (type, buffers, handler);
|
||||
}
|
||||
|
||||
void async_handshake (handshake_type, const_buffers const&,
|
||||
transfer_handler const& handler,
|
||||
std::false_type)
|
||||
{
|
||||
get_io_service ().post (bind_handler (
|
||||
handler, pure_virtual_error(), 0));
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
error_code shutdown (error_code& ec) override
|
||||
{
|
||||
return shutdown (ec,
|
||||
Enabled <has_shutdown <this_layer_type,
|
||||
error_code (error_code&)> > ());
|
||||
}
|
||||
|
||||
error_code shutdown (error_code& ec,
|
||||
std::true_type)
|
||||
{
|
||||
return m_object.shutdown (ec);
|
||||
}
|
||||
|
||||
error_code shutdown (error_code& ec,
|
||||
std::false_type)
|
||||
{
|
||||
return pure_virtual_error (ec);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
void async_shutdown (error_handler handler) override
|
||||
{
|
||||
async_shutdown (handler,
|
||||
Enabled <has_async_shutdown <this_layer_type,
|
||||
void (error_handler)> > ());
|
||||
}
|
||||
|
||||
void async_shutdown (error_handler const& handler,
|
||||
std::true_type)
|
||||
{
|
||||
m_object.async_shutdown (handler);
|
||||
}
|
||||
|
||||
void async_shutdown (error_handler const& handler,
|
||||
std::false_type)
|
||||
{
|
||||
get_io_service ().post (bind_handler (
|
||||
handler, pure_virtual_error()));
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
58
beast/asio/tests/bind_handler_tests.cpp
Normal file
58
beast/asio/tests/bind_handler_tests.cpp
Normal file
@@ -0,0 +1,58 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#include "BeastConfig.h"
|
||||
|
||||
#include "../../../modules/beast_core/beast_core.h" // for UnitTest
|
||||
|
||||
#include "../bind_handler.h"
|
||||
|
||||
#include <functional>
|
||||
|
||||
namespace beast {
|
||||
namespace asio {
|
||||
|
||||
class bind_handler_Tests : public UnitTest
|
||||
{
|
||||
public:
|
||||
static void foo (int)
|
||||
{
|
||||
}
|
||||
|
||||
void runTest()
|
||||
{
|
||||
beginTestCase ("call");
|
||||
|
||||
auto f (bind_handler (std::bind (&foo, std::placeholders::_1),
|
||||
42));
|
||||
|
||||
f();
|
||||
|
||||
pass();
|
||||
}
|
||||
|
||||
bind_handler_Tests() : UnitTest ("bind_handler", "beast", runManual)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
static bind_handler_Tests bind_handler_tests;
|
||||
|
||||
}
|
||||
}
|
||||
239
beast/asio/tests/shared_handler_tests.cpp
Normal file
239
beast/asio/tests/shared_handler_tests.cpp
Normal file
@@ -0,0 +1,239 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#include "BeastConfig.h"
|
||||
|
||||
#include "../../../modules/beast_core/beast_core.h" // for UnitTest
|
||||
|
||||
#include "../shared_handler.h"
|
||||
|
||||
// Disables is_constructible tests for std::function
|
||||
// Visual Studio std::function fails the is_constructible tests
|
||||
#ifndef BEAST_NO_STD_FUNCTION_CONSTRUCTIBLE
|
||||
# ifdef _MSC_VER
|
||||
# define BEAST_NO_STD_FUNCTION_CONSTRUCTIBLE 1
|
||||
# else
|
||||
# define BEAST_NO_STD_FUNCTION_CONSTRUCTIBLE 0
|
||||
# endif
|
||||
#endif
|
||||
|
||||
namespace beast {
|
||||
|
||||
class shared_handler_Tests : public UnitTest
|
||||
{
|
||||
public:
|
||||
struct test_results
|
||||
{
|
||||
bool call;
|
||||
bool invoke;
|
||||
bool alloc;
|
||||
bool dealloc;
|
||||
bool cont;
|
||||
|
||||
test_results ()
|
||||
: call (false)
|
||||
, invoke (false)
|
||||
, alloc (false)
|
||||
, dealloc (false)
|
||||
, cont (false)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
struct test_handler
|
||||
{
|
||||
std::reference_wrapper <test_results> results;
|
||||
|
||||
explicit test_handler (test_results& results_)
|
||||
: results (results_)
|
||||
{
|
||||
}
|
||||
|
||||
void operator() ()
|
||||
{
|
||||
results.get().call = true;
|
||||
}
|
||||
|
||||
template <class Function>
|
||||
friend void asio_handler_invoke (
|
||||
Function& f, test_handler* h)
|
||||
{
|
||||
h->results.get().invoke = true;
|
||||
f();
|
||||
}
|
||||
|
||||
template <class Function>
|
||||
friend void asio_handler_invoke (
|
||||
Function const& f, test_handler* h)
|
||||
{
|
||||
h->results.get().invoke = true;
|
||||
f();
|
||||
}
|
||||
|
||||
friend void* asio_handler_allocate (
|
||||
std::size_t size, test_handler* h)
|
||||
{
|
||||
h->results.get().alloc = true;
|
||||
return boost::asio::asio_handler_allocate (size);
|
||||
}
|
||||
|
||||
friend void asio_handler_deallocate (
|
||||
void* p, std::size_t size, test_handler* h)
|
||||
{
|
||||
h->results.get().dealloc = true;
|
||||
boost::asio::asio_handler_deallocate (p, size);
|
||||
}
|
||||
|
||||
friend bool asio_handler_is_continuation (
|
||||
test_handler* h)
|
||||
{
|
||||
h->results.get().cont = true;
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
struct test_invokable
|
||||
{
|
||||
bool call;
|
||||
|
||||
test_invokable ()
|
||||
: call (false)
|
||||
{
|
||||
}
|
||||
|
||||
void operator() ()
|
||||
{
|
||||
call = true;
|
||||
}
|
||||
};
|
||||
|
||||
template <class Handler>
|
||||
bool async_op (Handler&& handler)
|
||||
{
|
||||
void* const p (boost_asio_handler_alloc_helpers::allocate (32, handler));
|
||||
handler();
|
||||
boost_asio_handler_alloc_helpers::deallocate (p, 32, handler);
|
||||
return boost_asio_handler_cont_helpers::is_continuation (handler);
|
||||
}
|
||||
|
||||
void virtual_async_op (asio::shared_handler <void(void)> handler)
|
||||
{
|
||||
async_op (handler);
|
||||
}
|
||||
|
||||
void runTest()
|
||||
{
|
||||
beginTestCase ("hooks");
|
||||
|
||||
#if ! BEAST_NO_STD_FUNCTION_CONSTRUCTIBLE
|
||||
static_assert (! std::is_constructible <
|
||||
std::function <void(void)>, int&&>::value,
|
||||
"Cannot construct std::function from int&&");
|
||||
|
||||
static_assert (! std::is_constructible <
|
||||
std::function <void(void)>, int>::value,
|
||||
"Cannot construct std::function from int");
|
||||
|
||||
static_assert (! std::is_constructible <
|
||||
asio::shared_handler <void(void)>, int>::value,
|
||||
"Cannot construct shared_handler from int");
|
||||
#endif
|
||||
|
||||
static_assert (std::is_constructible <
|
||||
asio::shared_handler <void(int)>,
|
||||
asio::shared_handler <void(int)>>::value,
|
||||
"Should construct <void(int)> from <void(int)>");
|
||||
|
||||
static_assert (! std::is_constructible <
|
||||
asio::shared_handler <void(int)>,
|
||||
asio::shared_handler <void(void)>>::value,
|
||||
"Can't construct <void(int)> from <void(void)>");
|
||||
|
||||
// Hooks called when using the raw handler
|
||||
{
|
||||
test_results r;
|
||||
test_handler h (r);
|
||||
|
||||
async_op (h);
|
||||
expect (r.call);
|
||||
expect (r.alloc);
|
||||
expect (r.dealloc);
|
||||
expect (r.cont);
|
||||
|
||||
test_invokable f;
|
||||
boost_asio_handler_invoke_helpers::invoke (std::ref (f), h);
|
||||
expect (r.invoke);
|
||||
expect (f.call);
|
||||
}
|
||||
|
||||
// Use of std::function shows the hooks not getting called
|
||||
{
|
||||
test_results r;
|
||||
std::function <void(void)> fh ((test_handler) (r));
|
||||
|
||||
async_op (fh);
|
||||
expect (r.call);
|
||||
unexpected (r.alloc);
|
||||
unexpected (r.dealloc);
|
||||
unexpected (r.cont);
|
||||
|
||||
test_invokable f;
|
||||
boost_asio_handler_invoke_helpers::invoke (std::ref (f), fh);
|
||||
unexpected (r.invoke);
|
||||
expect (f.call);
|
||||
}
|
||||
|
||||
// Make sure shared_handler calls the hooks
|
||||
{
|
||||
test_results r;
|
||||
asio::shared_handler <void(void)> sh ((test_handler)(r));
|
||||
|
||||
async_op (sh);
|
||||
expect (r.call);
|
||||
expect (r.alloc);
|
||||
expect (r.dealloc);
|
||||
expect (r.cont);
|
||||
|
||||
test_invokable f;
|
||||
boost_asio_handler_invoke_helpers::invoke (std::ref (f), sh);
|
||||
expect (r.invoke);
|
||||
expect (f.call);
|
||||
}
|
||||
|
||||
// Make sure shared_handler via implicit conversion calls hooks
|
||||
{
|
||||
test_results r;
|
||||
test_handler h (r);
|
||||
|
||||
virtual_async_op ((test_handler) (r));
|
||||
expect (r.call);
|
||||
expect (r.alloc);
|
||||
expect (r.dealloc);
|
||||
expect (r.cont);
|
||||
}
|
||||
}
|
||||
|
||||
shared_handler_Tests() : UnitTest ("shared_handler", "beast")
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
static shared_handler_Tests shared_handler_tests;
|
||||
|
||||
}
|
||||
287
beast/asio/tests/wrap_handler_tests.cpp
Normal file
287
beast/asio/tests/wrap_handler_tests.cpp
Normal file
@@ -0,0 +1,287 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#include "BeastConfig.h"
|
||||
|
||||
#include "../../../modules/beast_core/beast_core.h" // for UnitTest
|
||||
|
||||
#include "../wrap_handler.h"
|
||||
|
||||
#include <boost/version.hpp>
|
||||
|
||||
#include <boost/bind.hpp>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
|
||||
namespace beast {
|
||||
namespace asio {
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
// Displays the order of destruction of parameters in the bind wrapper
|
||||
//
|
||||
class boost_bind_Tests : public UnitTest
|
||||
{
|
||||
public:
|
||||
struct Result
|
||||
{
|
||||
std::string text;
|
||||
|
||||
void push_back (std::string const& s)
|
||||
{
|
||||
if (! text.empty())
|
||||
text += ", ";
|
||||
text += s;
|
||||
}
|
||||
};
|
||||
|
||||
struct Payload
|
||||
{
|
||||
std::reference_wrapper <Result> m_result;
|
||||
std::string m_name;
|
||||
|
||||
explicit Payload (Result& result, std::string const& name)
|
||||
: m_result (result)
|
||||
, m_name (name)
|
||||
{
|
||||
}
|
||||
|
||||
~Payload ()
|
||||
{
|
||||
m_result.get().push_back (m_name);
|
||||
}
|
||||
};
|
||||
|
||||
struct Arg
|
||||
{
|
||||
std::shared_ptr <Payload> m_payload;
|
||||
|
||||
Arg (Result& result, std::string const& name)
|
||||
: m_payload (std::make_shared <Payload> (result, name))
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
static void foo (Arg const&, Arg const&, Arg const&)
|
||||
{
|
||||
}
|
||||
|
||||
void runTest()
|
||||
{
|
||||
beginTestCase ("order");
|
||||
|
||||
{
|
||||
Result r;
|
||||
{
|
||||
boost::bind (&foo,
|
||||
Arg (r, "one"),
|
||||
Arg (r, "two"),
|
||||
Arg (r, "three"));
|
||||
}
|
||||
logMessage (std::string ("boost::bind (") + r.text + ")");
|
||||
}
|
||||
|
||||
{
|
||||
Result r;
|
||||
{
|
||||
std::bind (&foo,
|
||||
Arg (r, "one"),
|
||||
Arg (r, "two"),
|
||||
Arg (r, "three"));
|
||||
}
|
||||
logMessage (std::string ("std::bind (") + r.text + ")");
|
||||
}
|
||||
|
||||
pass();
|
||||
}
|
||||
|
||||
boost_bind_Tests() : UnitTest ("bind", "beast", runManual)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
static boost_bind_Tests boost_bind_tests;
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
class wrap_handler_handler_Tests : public UnitTest
|
||||
{
|
||||
public:
|
||||
struct test_results
|
||||
{
|
||||
bool call;
|
||||
bool invoke;
|
||||
bool alloc;
|
||||
bool dealloc;
|
||||
bool cont;
|
||||
|
||||
test_results ()
|
||||
: call (false)
|
||||
, invoke (false)
|
||||
, alloc (false)
|
||||
, dealloc (false)
|
||||
, cont (false)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
struct test_handler
|
||||
{
|
||||
std::reference_wrapper <test_results> results;
|
||||
|
||||
explicit test_handler (test_results& results_)
|
||||
: results (results_)
|
||||
{
|
||||
}
|
||||
|
||||
void operator() ()
|
||||
{
|
||||
results.get().call = true;
|
||||
}
|
||||
|
||||
template <class Function>
|
||||
friend void asio_handler_invoke (
|
||||
Function& f, test_handler* h)
|
||||
{
|
||||
h->results.get().invoke = true;
|
||||
f();
|
||||
}
|
||||
|
||||
template <class Function>
|
||||
friend void asio_handler_invoke (
|
||||
Function const& f, test_handler* h)
|
||||
{
|
||||
h->results.get().invoke = true;
|
||||
f();
|
||||
}
|
||||
|
||||
friend void* asio_handler_allocate (
|
||||
std::size_t, test_handler* h)
|
||||
{
|
||||
h->results.get().alloc = true;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
friend void asio_handler_deallocate (
|
||||
void*, std::size_t, test_handler* h)
|
||||
{
|
||||
h->results.get().dealloc = true;
|
||||
}
|
||||
|
||||
friend bool asio_handler_is_continuation (
|
||||
test_handler* h)
|
||||
{
|
||||
h->results.get().cont = true;
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
struct test_invokable
|
||||
{
|
||||
bool call;
|
||||
|
||||
test_invokable ()
|
||||
: call (false)
|
||||
{
|
||||
}
|
||||
|
||||
void operator() ()
|
||||
{
|
||||
call = true;
|
||||
}
|
||||
};
|
||||
|
||||
template <class Handler>
|
||||
bool async_op (Handler&& handler)
|
||||
{
|
||||
void* const p (boost_asio_handler_alloc_helpers::allocate (32, handler));
|
||||
(handler)();
|
||||
boost_asio_handler_alloc_helpers::deallocate (p, 32, handler);
|
||||
return boost_asio_handler_cont_helpers::is_continuation (handler);
|
||||
}
|
||||
|
||||
void runTest()
|
||||
{
|
||||
beginTestCase ("hooks");
|
||||
|
||||
// Hooks called when using the raw handler
|
||||
{
|
||||
test_results r;
|
||||
test_handler h (r);
|
||||
|
||||
async_op (h);
|
||||
expect (r.call);
|
||||
expect (r.alloc);
|
||||
expect (r.dealloc);
|
||||
expect (r.cont);
|
||||
|
||||
test_invokable f;
|
||||
boost_asio_handler_invoke_helpers::invoke (std::ref (f), h);
|
||||
expect (r.invoke);
|
||||
expect (f.call);
|
||||
}
|
||||
|
||||
// Use of boost::bind shows the hooks not getting called
|
||||
{
|
||||
test_results r;
|
||||
test_handler h (r);
|
||||
auto b (std::bind (&test_handler::operator(), &h));
|
||||
|
||||
async_op (b);
|
||||
expect (r.call);
|
||||
unexpected (r.alloc);
|
||||
unexpected (r.dealloc);
|
||||
unexpected (r.cont);
|
||||
|
||||
test_invokable f;
|
||||
boost_asio_handler_invoke_helpers::invoke (std::ref (f), b);
|
||||
unexpected (r.invoke);
|
||||
expect (f.call);
|
||||
}
|
||||
|
||||
// Make sure the wrapped handler calls the hooks
|
||||
{
|
||||
test_results r;
|
||||
test_handler h (r);
|
||||
auto w (wrap_handler (
|
||||
std::bind (&test_handler::operator(), test_handler(r)), h));
|
||||
|
||||
async_op (w);
|
||||
expect (r.call);
|
||||
expect (r.alloc);
|
||||
expect (r.dealloc);
|
||||
expect (r.cont);
|
||||
|
||||
test_invokable f;
|
||||
boost_asio_handler_invoke_helpers::invoke (std::ref (f), w);
|
||||
expect (r.invoke);
|
||||
expect (f.call);
|
||||
}
|
||||
}
|
||||
|
||||
wrap_handler_handler_Tests() : UnitTest ("wrap_handler", "beast")
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
static wrap_handler_handler_Tests wrap_handler_handler_tests;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
176
beast/asio/wrap_handler.h
Normal file
176
beast/asio/wrap_handler.h
Normal 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_ASIO_WRAP_HANDLER_H_INCLUDED
|
||||
#define BEAST_ASIO_WRAP_HANDLER_H_INCLUDED
|
||||
|
||||
#include <boost/asio/detail/handler_alloc_helpers.hpp>
|
||||
#include <boost/asio/detail/handler_cont_helpers.hpp>
|
||||
#include <boost/asio/detail/handler_invoke_helpers.hpp>
|
||||
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
namespace beast {
|
||||
namespace asio {
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning (push)
|
||||
#pragma warning (disable: 4512) // assignment operator could not be generated
|
||||
#endif
|
||||
|
||||
namespace detail {
|
||||
|
||||
/** A handler which wraps another handler using a specfic context.
|
||||
The handler is invoked with the same io_service execution guarantees
|
||||
as the provided context.
|
||||
@note A copy of Context is made.
|
||||
*/
|
||||
template <class Handler, class Context>
|
||||
class wrapped_handler
|
||||
{
|
||||
private:
|
||||
Handler m_handler;
|
||||
Context m_context;
|
||||
bool m_continuation;
|
||||
|
||||
// If this goes off, consider carefully what the intent is.
|
||||
static_assert (! std::is_reference <Handler>::value,
|
||||
"Handler should not be a reference type");
|
||||
|
||||
public:
|
||||
wrapped_handler (bool continuation, Handler&& handler, Context context)
|
||||
: m_handler (std::move (handler))
|
||||
, m_context (context)
|
||||
, m_continuation (continuation ? true :
|
||||
boost_asio_handler_cont_helpers::is_continuation (context))
|
||||
{
|
||||
}
|
||||
|
||||
wrapped_handler (bool continuation, Handler const& handler, Context context)
|
||||
: m_handler (handler)
|
||||
, m_context (context)
|
||||
, m_continuation (continuation ? true :
|
||||
boost_asio_handler_cont_helpers::is_continuation (context))
|
||||
{
|
||||
}
|
||||
|
||||
template <class... Args>
|
||||
void
|
||||
operator() (Args&&... args)
|
||||
{
|
||||
m_handler (std::forward <Args> (args)...);
|
||||
}
|
||||
|
||||
template <class... Args>
|
||||
void
|
||||
operator() (Args&&... args) const
|
||||
{
|
||||
m_handler (std::forward <Args> (args)...);
|
||||
}
|
||||
|
||||
template <class Function>
|
||||
friend
|
||||
void
|
||||
asio_handler_invoke (Function& f, wrapped_handler* h)
|
||||
{
|
||||
boost_asio_handler_invoke_helpers::
|
||||
invoke (f, h->m_context);
|
||||
}
|
||||
|
||||
template <class Function>
|
||||
friend
|
||||
void
|
||||
asio_handler_invoke (Function const& f, wrapped_handler* h)
|
||||
{
|
||||
boost_asio_handler_invoke_helpers::
|
||||
invoke (f, h->m_context);
|
||||
}
|
||||
|
||||
friend
|
||||
void*
|
||||
asio_handler_allocate (std::size_t size, wrapped_handler* h)
|
||||
{
|
||||
return boost_asio_handler_alloc_helpers::
|
||||
allocate (size, h->m_context);
|
||||
}
|
||||
|
||||
friend
|
||||
void
|
||||
asio_handler_deallocate (void* p, std::size_t size, wrapped_handler* h)
|
||||
{
|
||||
boost_asio_handler_alloc_helpers::
|
||||
deallocate (p, size, h->m_context);
|
||||
}
|
||||
|
||||
friend
|
||||
bool
|
||||
asio_handler_is_continuation (wrapped_handler* h)
|
||||
{
|
||||
return h->m_continuation;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
// Tag for dispatching wrap_handler with is_continuation == true
|
||||
enum continuation_t
|
||||
{
|
||||
continuation
|
||||
};
|
||||
|
||||
/** Returns a wrapped handler so it executes within another context.
|
||||
The handler is invoked with the same io_service execution guarantees
|
||||
as the provided context. The handler will be copied if necessary.
|
||||
@note A copy of Context is made.
|
||||
*/
|
||||
/** @{ */
|
||||
template <class DeducedHandler, class Context>
|
||||
detail::wrapped_handler <
|
||||
std::remove_reference_t <DeducedHandler>,
|
||||
Context
|
||||
>
|
||||
wrap_handler (DeducedHandler&& handler, Context const& context,
|
||||
bool continuation = false)
|
||||
{
|
||||
typedef std::remove_reference_t <DeducedHandler> Handler;
|
||||
return detail::wrapped_handler <Handler, Context> (continuation,
|
||||
std::forward <DeducedHandler> (handler), context);
|
||||
}
|
||||
|
||||
template <class DeducedHandler, class Context>
|
||||
detail::wrapped_handler <
|
||||
std::remove_reference_t <DeducedHandler>,
|
||||
Context
|
||||
>
|
||||
wrap_handler (continuation_t, DeducedHandler&& handler,
|
||||
Context const& context)
|
||||
{
|
||||
typedef std::remove_reference_t <DeducedHandler> Handler;
|
||||
return detail::wrapped_handler <Handler, Context> (true,
|
||||
std::forward <DeducedHandler> (handler), context);
|
||||
}
|
||||
/** @} */
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
46
beast/boost/get_pointer.h
Normal file
46
beast/boost/get_pointer.h
Normal 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.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_BOOST_GET_POINTER_H_INCLUDED
|
||||
#define BEAST_BOOST_GET_POINTER_H_INCLUDED
|
||||
|
||||
#include <boost/get_pointer.hpp>
|
||||
|
||||
// Boost 1.55 incorrectly defines BOOST_NO_CXX11_SMART_PTR
|
||||
// when building with clang 3.4 and earlier. This workaround
|
||||
// gives beast its own overloads.
|
||||
|
||||
#ifdef BOOST_NO_CXX11_SMART_PTR
|
||||
#include <memory>
|
||||
namespace beast {
|
||||
template <class T>
|
||||
T* get_pointer (std::unique_ptr<T> const& p)
|
||||
{
|
||||
return p.get();
|
||||
}
|
||||
|
||||
template <class T>
|
||||
T* get_pointer (std::shared_ptr<T> const& p)
|
||||
{
|
||||
return p.get();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -27,13 +27,11 @@
|
||||
namespace std {
|
||||
|
||||
#if ! BEAST_NO_CXX14_MAKE_UNIQUE
|
||||
|
||||
template <class T, class... Args>
|
||||
std::unique_ptr <T> make_unique (Args&&... args)
|
||||
{
|
||||
return std::unique_ptr <T> (new T (std::forward <Args> (args)...));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
@@ -19,10 +19,10 @@
|
||||
|
||||
#include "../ParsedURL.h"
|
||||
|
||||
#include "http-parser/http_parser.h"
|
||||
|
||||
#include "../../../modules/beast_core/beast_core.h" // for UnitTest
|
||||
|
||||
#include "http_parser.h"
|
||||
|
||||
namespace beast {
|
||||
|
||||
ParsedURL::ParsedURL ()
|
||||
|
||||
@@ -24,13 +24,13 @@
|
||||
namespace beast {
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning (push)
|
||||
#pragma warning (disable: 4127) // conditional expression is constant
|
||||
#pragma warning (disable: 4244) // integer conversion, possible loss of data
|
||||
# pragma warning (push)
|
||||
# pragma warning (disable: 4127) // conditional expression is constant
|
||||
# pragma warning (disable: 4244) // integer conversion, possible loss of data
|
||||
#endif
|
||||
#include "http-parser/http_parser.c"
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning (pop)
|
||||
# pragma warning (pop)
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
33
beast/http/impl/http_parser.h
Normal file
33
beast/http/impl/http_parser.h
Normal file
@@ -0,0 +1,33 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
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_HTTP_HTTP_PARSER_H_INCLUDED
|
||||
#define BEAST_HTTP_HTTP_PARSER_H_INCLUDED
|
||||
|
||||
#include "BeastConfig.h"
|
||||
|
||||
// Wraps the C-language joyent http parser header in our namespace
|
||||
|
||||
namespace beast {
|
||||
|
||||
#include "http-parser/http_parser.h"
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -62,7 +62,7 @@ namespace is_call_possible_detail
|
||||
}
|
||||
|
||||
#define BEAST_DEFINE_HAS_MEMBER_FUNCTION(trait_name, member_function_name) \
|
||||
template<typename T, typename Signature> class trait_name; \
|
||||
template<typename T, typename IsCallPossibleSignature> class trait_name; \
|
||||
\
|
||||
template<typename T, typename Result> \
|
||||
class trait_name<T, Result(void)> \
|
||||
@@ -160,7 +160,7 @@ struct trait_name##_detail
|
||||
BEAST_DEFINE_HAS_MEMBER_FUNCTION(has_member, member_function_name); \
|
||||
}; \
|
||||
\
|
||||
template <typename T, typename Signature> \
|
||||
template <typename T, typename IsCallPossibleSignature> \
|
||||
struct trait_name \
|
||||
{ \
|
||||
private: \
|
||||
@@ -261,7 +261,8 @@ struct trait_name
|
||||
}; \
|
||||
\
|
||||
public: \
|
||||
static const bool value = impl<trait_name##_detail::has_member<T,Signature>::value, Signature>::value; \
|
||||
static const bool value = impl<trait_name##_detail::template has_member<T,IsCallPossibleSignature>::value, \
|
||||
IsCallPossibleSignature>::value; \
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user