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:
Vinnie Falco
2014-03-07 20:06:12 -08:00
parent 5478c540cb
commit 6546c30e17
88 changed files with 2709 additions and 3378 deletions

View File

@@ -20,6 +20,4 @@
#ifndef BEAST_ASIO_H_INCLUDED
#define BEAST_ASIO_H_INCLUDED
#include "asio/IPAddressConversion.h"
#endif

View File

@@ -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!

View 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
}
}

View 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
View 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

View File

@@ -0,0 +1,110 @@
//------------------------------------------------------------------------------
/*
This file is part of Beast: https://github.com/vinniefalco/Beast
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
#ifndef BEAST_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
View 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
View 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
View 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

View 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;
}
}

View 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;
}

View 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
View File

@@ -0,0 +1,176 @@
//------------------------------------------------------------------------------
/*
This file is part of Beast: https://github.com/vinniefalco/Beast
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
#ifndef BEAST_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
View File

@@ -0,0 +1,46 @@
//------------------------------------------------------------------------------
/*
This file is part of Beast: https://github.com/vinniefalco/Beast
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
#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

View File

@@ -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
}

View File

@@ -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 ()

View File

@@ -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
}

View 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

View File

@@ -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; \
}
}