Refactor SocketWrapper

This commit is contained in:
Vinnie Falco
2013-08-15 12:36:02 -07:00
parent d2a61ee7f0
commit e2b0df5f1d
6 changed files with 509 additions and 501 deletions

View File

@@ -21,22 +21,43 @@ Socket::~Socket ()
{
}
//------------------------------------------------------------------------------
//-----------------------------------------------------------------------------
//
// General
// basic_io_object
//
//------------------------------------------------------------------------------
bool Socket::requires_handshake ()
boost::asio::io_service& Socket::get_io_service ()
{
return false;
pure_virtual ();
return *static_cast <boost::asio::io_service*>(nullptr);
}
//------------------------------------------------------------------------------
//-----------------------------------------------------------------------------
//
// SocketInterface::Close
// basic_socket
//
//------------------------------------------------------------------------------
void* Socket::lowest_layer (char const*) const
{
pure_virtual ();
return nullptr;
}
void* Socket::native_handle (char const*) const
{
pure_virtual ();
return nullptr;
}
boost::system::error_code Socket::cancel (boost::system::error_code& ec)
{
return pure_virtual (ec);
}
boost::system::error_code Socket::shutdown (shutdown_type, boost::system::error_code& ec)
{
return pure_virtual (ec);
}
boost::system::error_code Socket::close (boost::system::error_code& ec)
{
@@ -45,9 +66,8 @@ boost::system::error_code Socket::close (boost::system::error_code& ec)
//------------------------------------------------------------------------------
//
// SocketInterface::Acceptor
// basic_socket_acceptor
//
//------------------------------------------------------------------------------
boost::system::error_code Socket::accept (Socket&, boost::system::error_code& ec)
{
@@ -76,37 +96,8 @@ Socket::async_accept (Socket&, BOOST_ASIO_MOVE_ARG(ErrorCall) handler)
//------------------------------------------------------------------------------
//
// SocketInterface::LowestLayer
// basic_stream_socket
//
//------------------------------------------------------------------------------
void* Socket::lowest_layer_raw (char const*) const
{
pure_virtual ();
return nullptr;
}
//--------------------------------------------------------------------------
//
// SocketInterface::Socket
//
//--------------------------------------------------------------------------
boost::system::error_code Socket::cancel (boost::system::error_code& ec)
{
return pure_virtual (ec);
}
boost::system::error_code Socket::shutdown (shutdown_type, boost::system::error_code& ec)
{
return pure_virtual (ec);
}
//--------------------------------------------------------------------------
//
// SocketInterface::Stream
//
//--------------------------------------------------------------------------
std::size_t Socket::read_some (MutableBuffers const&, boost::system::error_code& ec)
{
@@ -160,9 +151,13 @@ Socket::async_write_some (ConstBuffers const&, BOOST_ASIO_MOVE_ARG(TransferCall)
//--------------------------------------------------------------------------
//
// SocketInterface::Handshake
// ssl::stream
//
//--------------------------------------------------------------------------
bool Socket::requires_handshake ()
{
return false;
}
boost::system::error_code Socket::handshake (handshake_type, boost::system::error_code& ec)
{
@@ -189,8 +184,6 @@ Socket::async_handshake (handshake_type, BOOST_ASIO_MOVE_ARG(ErrorCall) handler)
#endif
}
//--------------------------------------------------------------------------
#if BEAST_ASIO_HAS_BUFFEREDHANDSHAKE
boost::system::error_code Socket::handshake (handshake_type,
@@ -249,45 +242,6 @@ Socket::async_shutdown (BOOST_ASIO_MOVE_ARG(ErrorCall) handler)
//------------------------------------------------------------------------------
#if 0
/* Stream, SyncReadStream, AsyncReadStream, WriteStream, AsyncWriteStream */
// Note, missing std::future<> returns
class Stream
{
public:
// Stream
typedef typename remove_reference<Stream>::type next_layer_type;
typedef typename next_layer_type::lowest_layer_type lowest_layer_type;
next_layer_type& next_layer()
next_layer_type const& next_layer() const
lowest_layer_type& lowest_layer()
const lowest_layer_type& lowest_layer() const
boost::asio::io_service& get_io_service()
void close()
boost::system::error_code close(boost::system::error_code& ec)
// SyncWriteStream
template <typename ConstBufferSequence>
std::size_t write_some (const ConstBufferSequence& buffers)
template <typename ConstBufferSequence>
std::size_t write_some (const ConstBufferSequence& buffers, boost::system::error_code& ec)
// AsyncWriteStream
template <typename ConstBufferSequence, typename WriteHandler>
void async_write_some (const ConstBufferSequence& buffers, WriteHandler handler)
// ReadStream
template <typename MutableBufferSequence>
std::size_t read_some (const MutableBufferSequence& buffers)
template <typename MutableBufferSequence>
std::size_t read_some (const MutableBufferSequence& buffers, boost::system::error_code& ec)
// AsyncReadStream
template <typename MutableBufferSequence, typename ReadHandler>
void async_read_some (const MutableBufferSequence& buffers, ReadHandler handler)
};
#endif
/* members, and the most common base class in which they appear:
basic_io_object
@@ -296,8 +250,10 @@ basic_io_object
basic_socket <Protocol> : basic_io_object
typedef protocol_type
typedef lowest_layer_type
lowest_layer_type& lowest_layer ()
native_handle () // Socket::native_handle() would return void* and we'd use the templates to do the static_cast
lowest_layer_type const& lowest_layer () const
native_handle ()
cancel ()
shutdon (shutdown_type)
close ()
@@ -314,4 +270,8 @@ basic_socket_acceptor <Protocol> : basic_io_object
basic_stream_socket <Protocol> : basic_socket <Protocol>
ssl::stream
handshake ()
async_handshake ()
shutdown ()
*/

View File

@@ -28,17 +28,6 @@
When member functions are called and the underlying implementation does
not support the operation, a fatal error is generated.
Must satisfy these requirements:
DefaultConstructible, MoveConstructible, CopyConstructible,
MoveAssignable, CopyAssignable, Destructible
Meets the requirements of these boost concepts:
SyncReadStream, SyncWriteStream, AsyncReadStream, AsyncWriteStream,
@see SharedObjectPtr
*/
class Socket
: public SocketBase
@@ -50,126 +39,25 @@ public:
//--------------------------------------------------------------------------
//
// General
// basic_io_object
//
virtual boost::asio::io_service& get_io_service ();
//--------------------------------------------------------------------------
//
// basic_socket
//
virtual boost::asio::io_service& get_io_service () = 0;
/** Determines if the underlying stream requires a handshake.
If requires_handshake is true, it will be necessary to call handshake or
async_handshake after the connection is established. Furthermore it
will be necessary to call the shutdown member from the
HandshakeInterface to close the connection. Do not close the underlying
socket or else the closure will not be graceful. Only one side should
initiate the handshaking shutdon. The other side should observe it.
Which side does what is up to the user.
The default version returns false
/** Retrieve the lowest layer object.
Note that you must know the type name for this to work, or
else a fatal error will occur.
*/
virtual bool requires_handshake ();
/** Retrieve the underlying object.
Returns nullptr if the implementation doesn't match. Usually
you will use this if you need to get at the underlying boost::asio
object. For example:
@code
void set_options (Socket& socket)
{
typedef bost::boost::asio::ip::tcp Protocol;
typedef Protocol::socket;
Protocol::socket* const sock =
socket.this_layer <Protocol::socket> ();
if (sock != nullptr)
sock->set_option (
Protocol::no_delay (true));
}
@endcode
*/
template <class Object>
Object& this_layer ()
{
Object* object (this_layer_ptr <Object> ());
if (object == nullptr)
Throw (std::bad_cast (), __FILE__, __LINE__);
return *object;
}
template <class Object>
Object const& this_layer () const
{
Object const* object (this_layer_ptr <Object> ());
if (object == nullptr)
Throw (std::bad_cast (), __FILE__, __LINE__);
return *object;
}
template <class Object>
Object* this_layer_ptr ()
{
return static_cast <Object*> (
this_layer_raw (typeid (Object).name ()));
}
template <class Object>
Object const* this_layer_ptr () const
{
return static_cast <Object const*> (
this_layer_raw (typeid (Object).name ()));
}
// Shouldn't call this directly, use this_layer<> instead
virtual void* this_layer_raw (char const* type_name) const = 0;
//--------------------------------------------------------------------------
//
// SocketInterface::Close
//
//--------------------------------------------------------------------------
void close ()
{
boost::system::error_code ec;
throw_error (close (ec));
}
virtual boost::system::error_code close (boost::system::error_code& ec);
//--------------------------------------------------------------------------
//
// SocketInterface::Acceptor
//
//--------------------------------------------------------------------------
virtual boost::system::error_code accept (Socket& peer, boost::system::error_code& ec);
template <class AcceptHandler>
BOOST_ASIO_INITFN_RESULT_TYPE(AcceptHandler, void (boost::system::error_code))
async_accept (Socket& peer, BOOST_ASIO_MOVE_ARG(AcceptHandler) handler)
{
return async_accept (peer, ErrorCall (
BOOST_ASIO_MOVE_CAST(AcceptHandler)(handler)));
}
virtual
BEAST_ASIO_INITFN_RESULT_TYPE_MEMBER(ErrorCall, void (boost::system::error_code))
async_accept (Socket& peer, BOOST_ASIO_MOVE_ARG(ErrorCall) handler);
//--------------------------------------------------------------------------
//
// SocketInterface::LowestLayer
//
//--------------------------------------------------------------------------
/** @{ */
template <class Object>
Object& lowest_layer ()
{
Object* object (lowest_layer_ptr <Object> ());
Object* object (this->lowest_layer_ptr <Object> ());
if (object == nullptr)
Throw (std::bad_cast (), __FILE__, __LINE__);
return *object;
@@ -178,7 +66,7 @@ public:
template <class Object>
Object const& lowest_layer () const
{
Object const* object (lowest_layer_ptr <Object> ());
Object const* object (this->lowest_layer_ptr <Object> ());
if (object == nullptr)
Throw (std::bad_cast (), __FILE__, __LINE__);
return *object;
@@ -188,24 +76,58 @@ public:
Object* lowest_layer_ptr ()
{
return static_cast <Object*> (
lowest_layer_raw (typeid (Object).name ()));
this->lowest_layer (typeid (Object).name ()));
}
template <class Object>
Object const* lowest_layer_ptr () const
{
return static_cast <Object const*> (
lowest_layer_raw (typeid (Object).name ()));
this->lowest_layer (typeid (Object).name ()));
}
/** @} */
virtual void* lowest_layer (char const* type_name) const;
/** Retrieve the underlying object.
Note that you must know the type name for this to work, or
else a fatal error will occur.
*/
/** @{ */
template <class Object>
Object& native_handle ()
{
Object* object (this->native_handle_ptr <Object> ());
if (object == nullptr)
Throw (std::bad_cast (), __FILE__, __LINE__);
return *object;
}
// Shouldn't call this directly, use lowest_layer<> instead
virtual void* lowest_layer_raw (char const* type_name) const;
template <class Object>
Object const& native_handle () const
{
Object const* object (this->native_handle_ptr <Object> ());
if (object == nullptr)
Throw (std::bad_cast (), __FILE__, __LINE__);
return *object;
}
//--------------------------------------------------------------------------
//
// SocketInterface::Socket
//
//--------------------------------------------------------------------------
template <class Object>
Object* native_handle_ptr ()
{
return static_cast <Object*> (
this->native_handle (typeid (Object).name ()));
}
template <class Object>
Object const* native_handle_ptr () const
{
return static_cast <Object const*> (
this->native_handle (typeid (Object).name ()));
}
/** @} */
virtual void* native_handle (char const* type_name) const;
void cancel ()
{
@@ -224,16 +146,40 @@ public:
virtual boost::system::error_code shutdown (shutdown_type what,
boost::system::error_code& ec);
void close ()
{
boost::system::error_code ec;
throw_error (close (ec));
}
virtual boost::system::error_code close (boost::system::error_code& ec);
//--------------------------------------------------------------------------
//
// SocketInterface::Stream
// basic_socket_acceptor
//
virtual boost::system::error_code accept (Socket& peer, boost::system::error_code& ec);
template <class AcceptHandler>
BOOST_ASIO_INITFN_RESULT_TYPE(AcceptHandler, void (boost::system::error_code))
async_accept (Socket& peer, BOOST_ASIO_MOVE_ARG(AcceptHandler) handler)
{
return async_accept (peer, ErrorCall (
BOOST_ASIO_MOVE_CAST(AcceptHandler)(handler)));
}
virtual
BEAST_ASIO_INITFN_RESULT_TYPE_MEMBER(ErrorCall, void (boost::system::error_code))
async_accept (Socket& peer, BOOST_ASIO_MOVE_ARG(ErrorCall) handler);
//--------------------------------------------------------------------------
//
// basic_stream_socket
//
// SyncReadStream
//
// http://www.boost.org/doc/libs/1_54_0/doc/html/boost_asio/reference/SyncReadStream.html
//
template <class MutableBufferSequence>
std::size_t read_some (MutableBufferSequence const& buffers,
boost::system::error_code& ec)
@@ -244,9 +190,7 @@ public:
virtual std::size_t read_some (MutableBuffers const& buffers, boost::system::error_code& ec);
// SyncWriteStream
//
// http://www.boost.org/doc/libs/1_54_0/doc/html/boost_asio/reference/SyncWriteStream.html
//
template <class ConstBufferSequence>
std::size_t write_some (ConstBufferSequence const& buffers, boost::system::error_code &ec)
{
@@ -256,9 +200,7 @@ public:
virtual std::size_t write_some (ConstBuffers const& buffers, boost::system::error_code& ec);
// AsyncReadStream
//
// http://www.boost.org/doc/libs/1_54_0/doc/html/boost_asio/reference/AsyncReadStream.html
//
template <class MutableBufferSequence, class ReadHandler>
BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler, void (boost::system::error_code, std::size_t))
async_read_some (MutableBufferSequence const& buffers, BOOST_ASIO_MOVE_ARG(ReadHandler) handler)
@@ -272,9 +214,7 @@ public:
async_read_some (MutableBuffers const& buffers, BOOST_ASIO_MOVE_ARG(TransferCall) handler);
// AsyncWriteStream
//
// http://www.boost.org/doc/libs/1_54_0/doc/html/boost_asio/reference/AsyncWriteStream.html
//
template <class ConstBufferSequence, class WriteHandler>
BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler, void (boost::system::error_code, std::size_t))
async_write_some (ConstBufferSequence const& buffers, BOOST_ASIO_MOVE_ARG(WriteHandler) handler)
@@ -289,9 +229,22 @@ public:
//--------------------------------------------------------------------------
//
// SocketInterface::Handshake
// ssl::stream
//
//--------------------------------------------------------------------------
/** Determines if the underlying stream requires a handshake.
If requires_handshake is true, it will be necessary to call handshake or
async_handshake after the connection is established. Furthermore it
will be necessary to call the shutdown member from the
HandshakeInterface to close the connection. Do not close the underlying
socket or else the closure will not be graceful. Only one side should
initiate the handshaking shutdon. The other side should observe it.
Which side does what is up to the user.
The default version returns false.
*/
virtual bool requires_handshake ();
// ssl::stream::handshake (1 of 4)
// http://www.boost.org/doc/libs/1_54_0/doc/html/boost_asio/reference/ssl__stream/handshake/overload1.html

View File

@@ -23,13 +23,11 @@
/** Implementation details for Socket.
Normally you wont need to use this.
*/
class SocketBase
struct SocketBase
{
protected:
static void pure_virtual ();
static boost::system::error_code pure_virtual (boost::system::error_code& ec);
protected:
/** Called when the underlying object does not support the interface. */
void throw_error (boost::system::error_code const& ec)
{

View File

@@ -28,144 +28,279 @@
Note that only a reference to the underlying is stored. Management
of the lifetime of the object is controlled by the caller.
Supports these concepts:
Examples of the type of WrappedObject:
CopyConstructible, CopyAssignable, Destructible
asio::ip::tcp::socket
arg must be an io_context
SocketWrapper will create and take ownership of the tcp::socket
WrappedObjectType will be tcp::socket
next_layer () returns a asio::ip::tcp::socket&
lowest_layer () returns a asio::ip::tcp::socket&
asio::ip::tcp::socket&
arg must be an existing socket&
The caller owns the underlying socket object
WrappedObjectType will be tcp::socket
next_layer () returns a asio::ip::tcp::socket&
lowest_layer () returns a asio::ip::tcp::socket&
asio::ssl::stream <asio::ip::tcp::socket>
arg must be an io_context
SocketWrapper creates and takes ownership of the ssl::stream
WrappedObjecType will be asio::ssl::stream <asio::ip::tcp::socket>
next_layer () returns a asio::ip::tcp::socket&
lowest_layer () returns a asio::ip::tcp::socket&
asio::ssl::stream <asio::ip::tcp::socket&>
arg must be an existing socket&
The caller owns the socket, but SocketWrapper owns the ssl::stream
WrappedObjectType will be asio::ssl::stream <asio::ip::tcp::socket&>
next_layer () returns a asio::ip::tcp::socket&
lowest_layer () returns a asio::ip::tcp::socket&
asio::ssl::stream <asio::buffered_stream <asio::ip::tcp::socket> > >
This makes my head explode
*/
template <class Object>
class SocketWrapper
: public virtual Socket
, protected SocketWrapperBasics
{
public:
typedef typename boost::remove_pointer <
typename boost::remove_reference <
typename boost::remove_cv <Object>::type >::type >::type
ObjectType;
SocketWrapper (Object& object) noexcept
: m_impl (&object)
{
}
//------------------------------------------------------------------------------
SocketWrapper (SocketWrapper const& other) noexcept
: m_impl (other.m_impl)
namespace SocketWrapperMemberChecks
{
}
template <bool Enable>
struct EnableIf : boost::false_type { };
SocketWrapper& operator= (SocketWrapper const& other) noexcept
{
m_impl = other.m_impl;
}
template <>
struct EnableIf <true> : boost::true_type { };
// Retrieve the underlying object
Object& get_object () const noexcept
{
fatal_assert (m_impl != nullptr);
return *m_impl;
}
BEAST_DEFINE_IS_CALL_POSSIBLE(has_get_io_service, get_io_service);
// Retrieves a reference to the underlying socket.
// usually asio::basic_socket or asio::basic_stream_socket
// It must be compatible with our Protocol and SocketService
// or else a std::bad cast will be thrown.
//
// The reason its a template class and not a function is
// because it would otherwise generate a compile error
// if Object did not have a declaration for
// protocol_type::socket
//
template <typename AsioObject, class Enable = void>
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_handshake, handshake);
BEAST_DEFINE_IS_CALL_POSSIBLE(has_async_handshake, async_handshake);
BEAST_DEFINE_IS_CALL_POSSIBLE(has_async_shutdown, async_shutdown);
// Extracts the underlying socket type from the protocol of another asio object
template <typename T, typename Enable = void>
struct native_socket
{
typedef void* native_socket_type;
native_socket (Socket&) { pure_virtual (); }
native_socket_type& get () { pure_virtual (); return m_socket; }
native_socket_type& operator-> () noexcept { return get(); }
typedef void* socket_type;
inline native_socket (Socket&) : m_socket (nullptr) { SocketBase::pure_virtual (); }
inline socket_type& get () { SocketBase::pure_virtual (); return m_socket; }
inline socket_type& operator-> () { return get (); }
private:
native_socket_type m_socket;
socket_type m_socket;
};
template <typename AsioObject>
struct native_socket <AsioObject, typename boost::enable_if <boost::is_class <
typename AsioObject::protocol_type::socket> >::type>
// 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 AsioObject::protocol_type::socket native_socket_type;
native_socket (Socket& peer)
: m_socket (&peer.this_layer <native_socket_type> ()) { }
native_socket_type& get () noexcept { return *m_socket; }
native_socket_type& operator-> () noexcept { return *m_socket; }
typedef typename T::protocol_type::socket socket_type;
inline native_socket (Socket& peer) : m_socket_ptr (&peer.native_handle <socket_type> ()) { }
inline socket_type& get () noexcept { return *m_socket_ptr; }
inline socket_type& operator-> () noexcept { return get (); }
private:
native_socket_type* m_socket;
socket_type* m_socket_ptr;
};
};
//--------------------------------------------------------------------------
#if 0
typedef typename boost::remove_reference <Object>::type next_layer_type;
typedef typename next_layer_type::lowest_layer_type lowest_layer_type;
next_layer_type& next_layer () noexcept
template <typename WrappedObject>
class SocketWrapper
: public virtual Socket
, public SocketWrapperBasics
, public Uncopyable
{
private:
typedef typename boost::remove_reference <WrappedObject>::type wrapped_type;
public:
typedef typename boost::remove_reference <WrappedObject>::type WrappedObjectType;
template <typename Arg>
explicit SocketWrapper (Arg& arg)
: m_object (arg)
{
return get_object ().next_layer ();
}
next_layer_type const& next_layer () const noexcept
template <typename Arg1, typename Arg2>
SocketWrapper (Arg1& arg1, Arg2& arg2)
: m_object (arg1, arg2)
{
return get_object ().next_layer ();
}
lowest_layer_type& lowest_layer () noexcept
{
return get_object ().lowest_layer ();
}
lowest_layer_type const& lowest_layer () const noexcept
{
return get_object ().lowest_layer ();
}
#endif
//--------------------------------------------------------------------------
//
// General
// basic_io_object
//
//--------------------------------------------------------------------------
boost::asio::io_service& get_io_service ()
{
return get_object ().get_io_service ();
using namespace boost::asio;
using namespace SocketWrapperMemberChecks;
#if 0
// This is the one that doesn't work, (void) arg lists
return get_io_service (
EnableIf <has_get_io_service <wrapped_type,
io_service ()>::value> ());
#else
return get_io_service (boost::true_type ());
#endif
}
bool requires_handshake ()
boost::asio::io_service& get_io_service (
boost::true_type)
{
return Has <SocketInterface::AnyHandshake>::value;
return m_object.get_io_service ();
}
void* this_layer_raw (char const* type_name) const
boost::asio::io_service& get_io_service (
boost::false_type)
{
char const* const this_type_name (typeid (ObjectType).name ());
if (strcmp (type_name, this_type_name) == 0)
return const_cast <void*> (static_cast <void const*>(m_impl));
pure_virtual ();
return *static_cast <boost::asio::io_service*>(nullptr);
}
//--------------------------------------------------------------------------
//
// basic_socket
//
#if 0
// This is a potential work-around for the problem with
// the has_type_lowest_layer_type template, but requires
// Boost 1.54 or later.
//
// This include will be needed:
//
// #include <boost/tti/has_type.hpp>
//
//
BOOST_TTI_HAS_TYPE(lowest_layer_type)
#endif
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
};
void* lowest_layer (char const* type_name) const
{
using namespace SocketWrapperMemberChecks;
return lowest_layer (type_name,
EnableIf <has_type_lowest_layer_type <wrapped_type>::value> ());
}
void* lowest_layer (char const* type_name,
boost::true_type) const
{
char const* const name (typeid (typename wrapped_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 (char const*,
boost::false_type) const
{
pure_virtual ();
return nullptr;
}
//--------------------------------------------------------------------------
//
// SocketInterface::Close
//
void* native_handle (char const* type_name) const
{
char const* const name (typeid (wrapped_type).name ());
if (strcmp (name, type_name) == 0)
return const_cast <void*> (static_cast <void const*> (&m_object));
return nullptr;
}
//--------------------------------------------------------------------------
boost::system::error_code cancel (boost::system::error_code& ec)
{
using namespace boost;
using namespace SocketWrapperMemberChecks;
return cancel (ec,
EnableIf <has_cancel <wrapped_type,
system::error_code (system::error_code&)>::value> ());
}
boost::system::error_code cancel (boost::system::error_code& ec,
boost::true_type)
{
return m_object.cancel (ec);
}
boost::system::error_code cancel (boost::system::error_code& ec,
boost::false_type)
{
return pure_virtual (ec);
}
//--------------------------------------------------------------------------
boost::system::error_code shutdown (shutdown_type what, boost::system::error_code& ec)
{
using namespace boost;
using namespace SocketWrapperMemberChecks;
return shutdown (what, ec,
EnableIf <has_shutdown <wrapped_type,
system::error_code (shutdown_type, system::error_code&)>::value> ());
}
boost::system::error_code shutdown (shutdown_type what, boost::system::error_code& ec,
boost::true_type)
{
return m_object.shutdown (what, ec);
}
boost::system::error_code shutdown (shutdown_type, boost::system::error_code& ec,
boost::false_type)
{
return pure_virtual (ec);
}
//--------------------------------------------------------------------------
boost::system::error_code close (boost::system::error_code& ec)
{
using namespace boost;
using namespace SocketWrapperMemberChecks;
return close (ec,
Has <SocketInterface::Close> ());
EnableIf <has_close <wrapped_type,
system::error_code (system::error_code&)>::value> ());
}
boost::system::error_code close (boost::system::error_code& ec,
boost::true_type)
{
return get_object ().close (ec);
return m_object.close (ec);
}
boost::system::error_code close (boost::system::error_code& ec,
@@ -176,27 +311,25 @@ public:
//--------------------------------------------------------------------------
//
// SocketInterface::Acceptor
// basic_socket_acceptor
//
//--------------------------------------------------------------------------
boost::system::error_code accept (Socket& peer, boost::system::error_code& ec)
{
using namespace boost;
using namespace SocketWrapperMemberChecks;
typedef typename native_socket <wrapped_type>::socket_type socket_type;
return accept (peer, ec,
Has <SocketInterface::Acceptor> ());
EnableIf <has_accept <wrapped_type,
system::error_code (socket_type&, system::error_code&)>::value> ());
}
boost::system::error_code accept (Socket& peer, boost::system::error_code& ec,
boost::true_type)
{
#if 1
return get_object ().accept (
native_socket <Object> (peer).get (), ec);
#else
typedef ObjectType::protocol_type::socket socket_type;
socket_type& socket (peer.this_layer <socket_type> ());
return get_object ().accept (socket, ec);
#endif
using namespace SocketWrapperMemberChecks;
return m_object.accept (
native_socket <wrapped_type> (peer).get (), ec);
}
boost::system::error_code accept (Socket&, boost::system::error_code& ec,
@@ -205,11 +338,18 @@ public:
return pure_virtual (ec);
}
//--------------------------------------------------------------------------
BEAST_ASIO_INITFN_RESULT_TYPE_MEMBER(ErrorCall, void (boost::system::error_code))
async_accept (Socket& peer, BOOST_ASIO_MOVE_ARG(ErrorCall) handler)
{
using namespace boost;
using namespace SocketWrapperMemberChecks;
typedef typename native_socket <wrapped_type>::socket_type socket_type;
return async_accept (peer, BOOST_ASIO_MOVE_CAST(ErrorCall)(handler),
Has <SocketInterface::Acceptor> ());
EnableIf <has_async_accept <wrapped_type,
BEAST_ASIO_INITFN_RESULT_TYPE_MEMBER(ErrorCall, void (system::error_code))
(socket_type&, BOOST_ASIO_MOVE_ARG(TransferCall))>::value> ());
}
template <typename AcceptHandler>
@@ -217,14 +357,10 @@ public:
async_accept (Socket& peer, BOOST_ASIO_MOVE_ARG(AcceptHandler) handler,
boost::true_type)
{
#if 1
return get_object ().async_accept (
native_socket <Object> (peer).get (), handler);
#else
typedef ObjectType::protocol_type::socket socket_type;
socket_type& socket (peer.this_layer <socket_type> ());
return get_object ().async_accept (socket, handler);
#endif
using namespace SocketWrapperMemberChecks;
return m_object.async_accept (
native_socket <wrapped_type> (peer).get (),
BOOST_ASIO_MOVE_CAST(AcceptHandler)(handler));
}
template <typename AcceptHandler>
@@ -251,92 +387,23 @@ public:
//--------------------------------------------------------------------------
//
// SocketInterface::LowestLayer
// basic_stream_socket
//
//--------------------------------------------------------------------------
void* lowest_layer_raw (char const* type_name) const
{
return lowest_layer_raw (type_name,
Has <SocketInterface::LowestLayer> ());
}
void* lowest_layer_raw (char const* type_name,
boost::true_type) const
{
typedef typename ObjectType::lowest_layer_type lowest_layer_type;
char const* const lowest_layer_type_name (typeid (lowest_layer_type).name ());
if (strcmp (type_name, lowest_layer_type_name) == 0)
return const_cast <void*> (static_cast <void const*>(&get_object ().lowest_layer ()));
return nullptr;
}
void* lowest_layer_raw (char const*,
boost::false_type) const
{
pure_virtual ();
return nullptr;
}
//--------------------------------------------------------------------------
//
// SocketInterface::Socket
//
//--------------------------------------------------------------------------
boost::system::error_code cancel (boost::system::error_code& ec)
{
return cancel (ec,
Has <SocketInterface::Socket> ());
}
boost::system::error_code cancel (boost::system::error_code& ec,
boost::true_type)
{
return get_object ().cancel (ec);
}
boost::system::error_code cancel (boost::system::error_code& ec,
boost::false_type)
{
return pure_virtual (ec);
}
boost::system::error_code shutdown (shutdown_type what, boost::system::error_code& ec)
{
return shutdown (what, ec,
Has <SocketInterface::Socket> ());
}
boost::system::error_code shutdown (Socket::shutdown_type what, boost::system::error_code& ec,
boost::true_type)
{
return get_object ().shutdown (what, ec);
}
boost::system::error_code shutdown (Socket::shutdown_type, boost::system::error_code& ec,
boost::false_type)
{
return pure_virtual (ec);
}
//--------------------------------------------------------------------------
//
// SocketInterface::Stream
//
//--------------------------------------------------------------------------
std::size_t read_some (MutableBuffers const& buffers, boost::system::error_code& ec)
{
using namespace boost;
using namespace SocketWrapperMemberChecks;
return read_some (buffers, ec,
Has <SocketInterface::SyncStream> ());
EnableIf <has_read_some <wrapped_type,
std::size_t (MutableBuffers const&, system::error_code&)>::value> ());
}
template <typename MutableBufferSequence>
std::size_t read_some (MutableBufferSequence const& buffers, boost::system::error_code& ec,
boost::true_type)
{
return get_object ().read_some (buffers, ec);
return m_object.read_some (buffers, ec);
}
template <typename MutableBufferSequence>
@@ -347,17 +414,22 @@ public:
return 0;
}
//--------------------------------------------------------------------------
std::size_t write_some (ConstBuffers const& buffers, boost::system::error_code& ec)
{
using namespace boost;
using namespace SocketWrapperMemberChecks;
return write_some (buffers, ec,
Has <SocketInterface::SyncStream> ());
EnableIf <has_write_some <wrapped_type,
std::size_t (ConstBuffers const&, system::error_code&)>::value> ());
}
template <typename ConstBufferSequence>
std::size_t write_some (ConstBufferSequence const& buffers, boost::system::error_code& ec,
boost::true_type)
{
return get_object ().write_some (buffers, ec);
return m_object.write_some (buffers, ec);
}
template <typename ConstBufferSequence>
@@ -368,11 +440,17 @@ public:
return 0;
}
//--------------------------------------------------------------------------
BEAST_ASIO_INITFN_RESULT_TYPE_MEMBER(TransferCall, void (boost::system::error_code, std::size_t))
async_read_some (MutableBuffers const& buffers, BOOST_ASIO_MOVE_ARG(TransferCall) handler)
{
using namespace boost;
using namespace SocketWrapperMemberChecks;
return async_read_some (buffers, BOOST_ASIO_MOVE_CAST(TransferCall)(handler),
Has <SocketInterface::AsyncStream> ());
EnableIf <has_async_read_some <wrapped_type,
BEAST_ASIO_INITFN_RESULT_TYPE_MEMBER(TransferCall, void (system::error_code, std::size_t))
(MutableBuffers const&, BOOST_ASIO_MOVE_ARG(TransferCall))>::value> ());
}
template <typename MutableBufferSequence, typename ReadHandler>
@@ -380,7 +458,7 @@ public:
async_read_some (MutableBufferSequence const& buffers, BOOST_ASIO_MOVE_ARG(ReadHandler) handler,
boost::true_type)
{
return get_object ().async_read_some (buffers,
return m_object.async_read_some (buffers,
BOOST_ASIO_MOVE_CAST(ReadHandler)(handler));
}
@@ -404,11 +482,17 @@ public:
#endif
}
//--------------------------------------------------------------------------
BEAST_ASIO_INITFN_RESULT_TYPE_MEMBER(TransferCall, void (boost::system::error_code, std::size_t))
async_write_some (ConstBuffers const& buffers, BOOST_ASIO_MOVE_ARG(TransferCall) handler)
{
using namespace boost;
using namespace SocketWrapperMemberChecks;
return async_write_some (buffers, BOOST_ASIO_MOVE_CAST(TransferCall)(handler),
Has <SocketInterface::AsyncStream> ());
EnableIf <has_async_write_some <wrapped_type,
BEAST_ASIO_INITFN_RESULT_TYPE_MEMBER(TransferCall, void (system::error_code, std::size_t))
(ConstBuffers const&, BOOST_ASIO_MOVE_ARG(TransferCall))>::value> ());
}
template <typename ConstBufferSequence, typename WriteHandler>
@@ -416,7 +500,7 @@ public:
async_write_some (ConstBufferSequence const& buffers, BOOST_ASIO_MOVE_ARG(WriteHandler) handler,
boost::true_type)
{
return get_object ().async_write_some (buffers,
return m_object.async_write_some (buffers,
BOOST_ASIO_MOVE_CAST(WriteHandler)(handler));
}
@@ -444,20 +528,36 @@ public:
//--------------------------------------------------------------------------
//
// SocketInterface::Handshake
// ssl::stream
//
bool requires_handshake ()
{
using namespace boost;
using namespace SocketWrapperMemberChecks;
return
has_handshake <wrapped_type,
system::error_code (handshake_type, system::error_code&)>::value ||
has_async_handshake <wrapped_type,
BEAST_ASIO_INITFN_RESULT_TYPE_MEMBER(ErrorCall, void (boost::system::error_code))
(handshake_type, BOOST_ASIO_MOVE_ARG(ErrorCall))>::value;
}
//--------------------------------------------------------------------------
boost::system::error_code handshake (handshake_type type, boost::system::error_code& ec)
{
using namespace boost;
using namespace SocketWrapperMemberChecks;
return handshake (type, ec,
Has <SocketInterface::SyncHandshake> ());
EnableIf <has_handshake <wrapped_type,
system::error_code (handshake_type, system::error_code&)>::value> ());
}
boost::system::error_code handshake (handshake_type type, boost::system::error_code& ec,
boost::true_type)
{
return get_object ().handshake (type, ec);
return m_object.handshake (type, ec);
}
boost::system::error_code handshake (handshake_type, boost::system::error_code& ec,
@@ -466,50 +566,60 @@ public:
return pure_virtual (ec);
}
//--------------------------------------------------------------------------
BEAST_ASIO_INITFN_RESULT_TYPE_MEMBER(ErrorCall, void (boost::system::error_code))
async_handshake (handshake_type type, BOOST_ASIO_MOVE_ARG(ErrorCall) handler)
{
using namespace boost;
using namespace SocketWrapperMemberChecks;
return async_handshake (type, BOOST_ASIO_MOVE_CAST(ErrorCall)(handler),
Has <SocketInterface::AsyncHandshake> ());
EnableIf <has_async_handshake <wrapped_type,
BEAST_ASIO_INITFN_RESULT_TYPE_MEMBER(ErrorCall, void (system::error_code))
(handshake_type, BOOST_ASIO_MOVE_ARG(ErrorCall))>::value> ());
}
template <typename HandshakeHandler>
BOOST_ASIO_INITFN_RESULT_TYPE(HandshakeHandler, void (boost::system::error_code))
async_handshake (handshake_type type, BOOST_ASIO_MOVE_ARG(HandshakeHandler) handler,
BEAST_ASIO_INITFN_RESULT_TYPE_MEMBER(ErrorCall, void (boost::system::error_code))
async_handshake (handshake_type type, BOOST_ASIO_MOVE_ARG(ErrorCall) handler,
boost::true_type)
{
return get_object ().async_handshake (type,
BOOST_ASIO_MOVE_CAST(HandshakeHandler)(handler));
return m_object.async_handshake (type,
BOOST_ASIO_MOVE_CAST(ErrorCall)(handler));
}
template <typename HandshakeHandler>
BOOST_ASIO_INITFN_RESULT_TYPE(HandshakeHandler, void (boost::system::error_code))
async_handshake (handshake_type, BOOST_ASIO_MOVE_ARG(HandshakeHandler) handler,
BEAST_ASIO_INITFN_RESULT_TYPE_MEMBER(ErrorCall, void (boost::system::error_code))
async_handshake (handshake_type, BOOST_ASIO_MOVE_ARG(ErrorCall) handler,
boost::false_type)
{
#if BEAST_ASIO_HAS_FUTURE_RETURNS
boost::asio::detail::async_result_init<
HandshakeHandler, void (boost::system::error_code)> init(
BOOST_ASIO_MOVE_CAST(HandshakeHandler)(handler));
ErrorCall, void (boost::system::error_code)> init(
BOOST_ASIO_MOVE_CAST(ErrorCall)(handler));
boost::system::error_code ec;
ec = pure_virtual (ec);
get_io_service ().post (boost::bind (
BOOST_ASIO_MOVE_CAST(HandshakeHandler)(handler), ec));
BOOST_ASIO_MOVE_CAST(ErrorCall)(handler), ec));
return init.result.get();
#else
boost::system::error_code ec;
ec = pure_virtual (ec);
get_io_service ().post (boost::bind (
BOOST_ASIO_MOVE_CAST(HandshakeHandler)(handler), ec));
BOOST_ASIO_MOVE_CAST(ErrorCall)(handler), ec));
#endif
}
//--------------------------------------------------------------------------
#if BEAST_ASIO_HAS_BUFFEREDHANDSHAKE
boost::system::error_code handshake (handshake_type type,
ConstBuffers const& buffers, boost::system::error_code& ec)
{
using namespace boost;
using namespace SocketWrapperMemberChecks;
return handshake (type, buffers, ec,
Has <SocketInterface::BufferedSyncHandshake> ());
EnableIf <has_handshake <wrapped_type,
system::error_code (handshake_type, ConstBuffers const&, system::error_code&)>::value> ());
}
template <typename ConstBufferSequence>
@@ -517,7 +627,7 @@ public:
ConstBufferSequence const& buffers, boost::system::error_code& ec,
boost::true_type)
{
return get_object ().handshake (type, buffers, ec);
return m_object.handshake (type, buffers, ec);
}
template <typename ConstBufferSequence>
@@ -528,59 +638,65 @@ public:
return pure_virtual (ec);
}
//--------------------------------------------------------------------------
BEAST_ASIO_INITFN_RESULT_TYPE_MEMBER(TransferCall, void (boost::system::error_code, std::size_t))
async_handshake (handshake_type type, ConstBuffers const& buffers,
BOOST_ASIO_MOVE_ARG(TransferCall) handler)
{
return async_handshake (type, buffers,
BOOST_ASIO_MOVE_CAST(TransferCall)(handler),
Has <SocketInterface::BufferedAsyncHandshake> ());
using namespace boost;
using namespace SocketWrapperMemberChecks;
return async_handshake (type, buffers, BOOST_ASIO_MOVE_CAST(TransferCall)(handler),
EnableIf <has_async_handshake <wrapped_type,
BEAST_ASIO_INITFN_RESULT_TYPE_MEMBER(TransferCall, void (system::error_code, std::size_t))
(handshake_type, ConstBuffers const&, system::error_code&)>::value> ());
}
template <typename ConstBufferSequence, typename BufferedHandshakeHandler>
BOOST_ASIO_INITFN_RESULT_TYPE(BufferedHandshakeHandler, void (boost::system::error_code, std::size_t))
async_handshake (handshake_type type, const ConstBufferSequence& buffers,
BOOST_ASIO_MOVE_ARG(BufferedHandshakeHandler) handler,
BEAST_ASIO_INITFN_RESULT_TYPE_MEMBER(TransferCall, void (boost::system::error_code, std::size_t))
async_handshake (handshake_type type, ConstBuffers const& buffers, BOOST_ASIO_MOVE_ARG(TransferCall) handler,
boost::true_type)
{
return get_object ().async_handshake (type, buffers,
BOOST_ASIO_MOVE_CAST(BufferedHandshakeHandler)(handler));
return m_object.async_handshake (type, buffers,
BOOST_ASIO_MOVE_CAST(TransferCall)(handler));
}
template <typename ConstBufferSequence, typename BufferedHandshakeHandler>
BOOST_ASIO_INITFN_RESULT_TYPE(BufferedHandshakeHandler, void (boost::system::error_code, std::size_t))
async_handshake (handshake_type, const ConstBufferSequence&,
BOOST_ASIO_MOVE_ARG(BufferedHandshakeHandler) handler,
BEAST_ASIO_INITFN_RESULT_TYPE_MEMBER(TransferCall, void (boost::system::error_code, std::size_t))
async_handshake (handshake_type, ConstBuffers const&, BOOST_ASIO_MOVE_ARG(TransferCall) handler,
boost::false_type)
{
#if BEAST_ASIO_HAS_FUTURE_RETURNS
boost::asio::detail::async_result_init<
BufferedHandshakeHandler, void (boost::system::error_code, std::size_t)> init(
BOOST_ASIO_MOVE_CAST(BufferedHandshakeHandler)(handler));
TransferCall, void (boost::system::error_code, std::size_t)> init(
BOOST_ASIO_MOVE_CAST(TransferCall)(handler));
boost::system::error_code ec;
ec = pure_virtual (ec);
get_io_service ().post (boost::bind (
BOOST_ASIO_MOVE_CAST(BufferedHandshakeHandler)(handler), ec, 0));
BOOST_ASIO_MOVE_CAST(TransferCall)(handler), ec, 0));
return init.result.get();
#else
boost::system::error_code ec;
ec = pure_virtual (ec);
get_io_service ().post (boost::bind (
BOOST_ASIO_MOVE_CAST(BufferedHandshakeHandler)(handler), ec, 0));
BOOST_ASIO_MOVE_CAST(TransferCall)(handler), ec, 0));
#endif
}
#endif
//--------------------------------------------------------------------------
boost::system::error_code shutdown (boost::system::error_code& ec)
{
using namespace boost;
using namespace SocketWrapperMemberChecks;
return shutdown (ec,
Has <SocketInterface::SyncHandshake> ());
EnableIf <has_shutdown <wrapped_type,
system::error_code (system::error_code&)>::value> ());
}
boost::system::error_code shutdown (boost::system::error_code& ec,
boost::true_type)
{
return get_object ().shutdown (ec);
return m_object.shutdown (ec);
}
boost::system::error_code shutdown (boost::system::error_code& ec,
@@ -589,70 +705,49 @@ public:
return pure_virtual (ec);
}
//--------------------------------------------------------------------------
void async_shutdown (BOOST_ASIO_MOVE_ARG(ErrorCall) handler)
{
async_shutdown (BOOST_ASIO_MOVE_CAST(ErrorCall)(handler),
Has <SocketInterface::AsyncHandshake> ());
using namespace boost;
using namespace SocketWrapperMemberChecks;
return async_shutdown (BOOST_ASIO_MOVE_CAST(ErrorCall)(handler),
EnableIf <has_async_shutdown <wrapped_type,
BEAST_ASIO_INITFN_RESULT_TYPE_MEMBER(ErrorCall, void (system::error_code))
(BOOST_ASIO_MOVE_ARG(ErrorCall))>::value> ());
}
template <typename ShutdownHandler>
BOOST_ASIO_INITFN_RESULT_TYPE(ShutdownHandler, void (boost::system::error_code))
async_shutdown (BOOST_ASIO_MOVE_ARG(ShutdownHandler) handler,
BEAST_ASIO_INITFN_RESULT_TYPE_MEMBER(ErrorCall, void (boost::system::error_code))
async_shutdown (BOOST_ASIO_MOVE_ARG(ErrorCall) handler,
boost::true_type)
{
return get_object ().async_shutdown (
BOOST_ASIO_MOVE_CAST(ShutdownHandler)(handler));
return m_object.async_shutdown (
BOOST_ASIO_MOVE_CAST(ErrorCall)(handler));
}
template <typename ShutdownHandler>
BOOST_ASIO_INITFN_RESULT_TYPE(ShutdownHandler, void (boost::system::error_code))
async_shutdown (BOOST_ASIO_MOVE_ARG(ShutdownHandler) handler,
BEAST_ASIO_INITFN_RESULT_TYPE_MEMBER(ErrorCall, void (boost::system::error_code))
async_shutdown (BOOST_ASIO_MOVE_ARG(ErrorCall) handler,
boost::false_type)
{
#if BEAST_ASIO_HAS_FUTURE_RETURNS
boost::asio::detail::async_result_init<
ShutdownHandler, void (boost::system::error_code, std::size_t)> init(
BOOST_ASIO_MOVE_CAST(ShutdownHandler)(handler));
ErrorCall, void (boost::system::error_code, std::size_t)> init(
BOOST_ASIO_MOVE_CAST(ErrorCall)(handler));
boost::system::error_code ec;
ec = pure_virtual (ec);
get_io_service ().post (boost::bind (
BOOST_ASIO_MOVE_CAST(ShutdownHandler)(handler), ec));
BOOST_ASIO_MOVE_CAST(ErrorCall)(handler), ec));
return init.result.get();
#else
boost::system::error_code ec;
ec = pure_virtual (ec);
get_io_service ().post (boost::bind (
BOOST_ASIO_MOVE_CAST(ShutdownHandler)(handler), ec));
BOOST_ASIO_MOVE_CAST(ErrorCall)(handler), ec));
#endif
}
protected:
explicit SocketWrapper (Object* object = nullptr) noexcept
: m_impl (object)
{
}
void set (Object* ptr) noexcept
{
m_impl = ptr;
}
template <typename Interface>
struct Has : HasInterface <ObjectType, Interface> { };
public:
Object* m_impl;
private:
WrappedObject m_object;
};
//------------------------------------------------------------------------------
/** Dynamically allocate a SocketWrapper.
This deduces the template arguments for convenience.
*/
template <typename Object>
SocketWrapper <Object>* newSocketWrapper (Object& object)
{
return new SocketWrapper <Object> (object);
}
#endif

View File

@@ -24,7 +24,8 @@
*/
class SocketWrapperBasics
{
protected:
public:
#if 0
/** Template specialization to determine available interfaces. */
template <typename Object>
struct InterfacesOf
@@ -129,6 +130,7 @@ protected:
{
};
#endif
#endif
};
#endif

View File

@@ -101,8 +101,8 @@ protected:
protocol_type m_protocol;
socket_type m_socket;
acceptor_type m_acceptor;
SocketWrapper <socket_type> m_socket_wrapper;
SocketWrapper <acceptor_type> m_acceptor_wrapper;
SocketWrapper <socket_type&> m_socket_wrapper;
SocketWrapper <acceptor_type&> m_acceptor_wrapper;
};
#endif