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) 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) 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) 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) 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 #endif
} }
//--------------------------------------------------------------------------
#if BEAST_ASIO_HAS_BUFFEREDHANDSHAKE #if BEAST_ASIO_HAS_BUFFEREDHANDSHAKE
boost::system::error_code Socket::handshake (handshake_type, 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: /* members, and the most common base class in which they appear:
basic_io_object basic_io_object
@@ -296,8 +250,10 @@ basic_io_object
basic_socket <Protocol> : basic_io_object basic_socket <Protocol> : basic_io_object
typedef protocol_type typedef protocol_type
typedef lowest_layer_type typedef lowest_layer_type
lowest_layer_type& lowest_layer () 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 () cancel ()
shutdon (shutdown_type) shutdon (shutdown_type)
close () close ()
@@ -314,4 +270,8 @@ basic_socket_acceptor <Protocol> : basic_io_object
basic_stream_socket <Protocol> : basic_socket <Protocol> 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 When member functions are called and the underlying implementation does
not support the operation, a fatal error is generated. 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 class Socket
: public SocketBase : 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; /** Retrieve the lowest layer object.
Note that you must know the type name for this to work, or
/** Determines if the underlying stream requires a handshake. else a fatal error will occur.
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 (); /** @{ */
/** 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> template <class Object>
Object& lowest_layer () Object& lowest_layer ()
{ {
Object* object (lowest_layer_ptr <Object> ()); Object* object (this->lowest_layer_ptr <Object> ());
if (object == nullptr) if (object == nullptr)
Throw (std::bad_cast (), __FILE__, __LINE__); Throw (std::bad_cast (), __FILE__, __LINE__);
return *object; return *object;
@@ -178,7 +66,7 @@ public:
template <class Object> template <class Object>
Object const& lowest_layer () const Object const& lowest_layer () const
{ {
Object const* object (lowest_layer_ptr <Object> ()); Object const* object (this->lowest_layer_ptr <Object> ());
if (object == nullptr) if (object == nullptr)
Throw (std::bad_cast (), __FILE__, __LINE__); Throw (std::bad_cast (), __FILE__, __LINE__);
return *object; return *object;
@@ -188,24 +76,58 @@ public:
Object* lowest_layer_ptr () Object* lowest_layer_ptr ()
{ {
return static_cast <Object*> ( return static_cast <Object*> (
lowest_layer_raw (typeid (Object).name ())); this->lowest_layer (typeid (Object).name ()));
} }
template <class Object> template <class Object>
Object const* lowest_layer_ptr () const Object const* lowest_layer_ptr () const
{ {
return static_cast <Object 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 template <class Object>
virtual void* lowest_layer_raw (char const* type_name) const; Object const& native_handle () const
{
Object const* object (this->native_handle_ptr <Object> ());
if (object == nullptr)
Throw (std::bad_cast (), __FILE__, __LINE__);
return *object;
}
//-------------------------------------------------------------------------- template <class Object>
// Object* native_handle_ptr ()
// SocketInterface::Socket {
// 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 () void cancel ()
{ {
@@ -224,16 +146,40 @@ public:
virtual boost::system::error_code shutdown (shutdown_type what, virtual boost::system::error_code shutdown (shutdown_type what,
boost::system::error_code& ec); 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 // SyncReadStream
//
// http://www.boost.org/doc/libs/1_54_0/doc/html/boost_asio/reference/SyncReadStream.html // http://www.boost.org/doc/libs/1_54_0/doc/html/boost_asio/reference/SyncReadStream.html
//
template <class MutableBufferSequence> template <class MutableBufferSequence>
std::size_t read_some (MutableBufferSequence const& buffers, std::size_t read_some (MutableBufferSequence const& buffers,
boost::system::error_code& ec) boost::system::error_code& ec)
@@ -244,9 +190,7 @@ public:
virtual std::size_t read_some (MutableBuffers const& buffers, boost::system::error_code& ec); virtual std::size_t read_some (MutableBuffers const& buffers, boost::system::error_code& ec);
// SyncWriteStream // SyncWriteStream
//
// http://www.boost.org/doc/libs/1_54_0/doc/html/boost_asio/reference/SyncWriteStream.html // http://www.boost.org/doc/libs/1_54_0/doc/html/boost_asio/reference/SyncWriteStream.html
//
template <class ConstBufferSequence> template <class ConstBufferSequence>
std::size_t write_some (ConstBufferSequence const& buffers, boost::system::error_code &ec) 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); virtual std::size_t write_some (ConstBuffers const& buffers, boost::system::error_code& ec);
// AsyncReadStream // AsyncReadStream
//
// http://www.boost.org/doc/libs/1_54_0/doc/html/boost_asio/reference/AsyncReadStream.html // http://www.boost.org/doc/libs/1_54_0/doc/html/boost_asio/reference/AsyncReadStream.html
//
template <class MutableBufferSequence, class ReadHandler> template <class MutableBufferSequence, class ReadHandler>
BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler, void (boost::system::error_code, std::size_t)) 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) 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); async_read_some (MutableBuffers const& buffers, BOOST_ASIO_MOVE_ARG(TransferCall) handler);
// AsyncWriteStream // AsyncWriteStream
//
// http://www.boost.org/doc/libs/1_54_0/doc/html/boost_asio/reference/AsyncWriteStream.html // http://www.boost.org/doc/libs/1_54_0/doc/html/boost_asio/reference/AsyncWriteStream.html
//
template <class ConstBufferSequence, class WriteHandler> template <class ConstBufferSequence, class WriteHandler>
BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler, void (boost::system::error_code, std::size_t)) 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) 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) // 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 // 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. /** Implementation details for Socket.
Normally you wont need to use this. Normally you wont need to use this.
*/ */
class SocketBase struct SocketBase
{ {
protected:
static void pure_virtual (); static void pure_virtual ();
static boost::system::error_code pure_virtual (boost::system::error_code& ec); static boost::system::error_code pure_virtual (boost::system::error_code& ec);
protected:
/** Called when the underlying object does not support the interface. */ /** Called when the underlying object does not support the interface. */
void throw_error (boost::system::error_code const& ec) 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 Note that only a reference to the underlying is stored. Management
of the lifetime of the object is controlled by the caller. 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 namespace SocketWrapperMemberChecks
{ {
public: template <bool Enable>
typedef typename boost::remove_pointer < struct EnableIf : boost::false_type { };
typename boost::remove_reference <
typename boost::remove_cv <Object>::type >::type >::type
ObjectType;
SocketWrapper (Object& object) noexcept template <>
: m_impl (&object) struct EnableIf <true> : boost::true_type { };
{
}
SocketWrapper (SocketWrapper const& other) noexcept BEAST_DEFINE_IS_CALL_POSSIBLE(has_get_io_service, get_io_service);
: m_impl (other.m_impl)
{
}
SocketWrapper& operator= (SocketWrapper const& other) noexcept BEAST_DEFINE_IS_CALL_POSSIBLE(has_lowest_layer, lowest_layer);
{ BEAST_DEFINE_IS_CALL_POSSIBLE(has_cancel, cancel);
m_impl = other.m_impl; BEAST_DEFINE_IS_CALL_POSSIBLE(has_shutdown, shutdown);
} BEAST_DEFINE_IS_CALL_POSSIBLE(has_close, close);
// Retrieve the underlying object BEAST_DEFINE_IS_CALL_POSSIBLE(has_accept, accept);
Object& get_object () const noexcept BEAST_DEFINE_IS_CALL_POSSIBLE(has_async_accept, async_accept);
{
fatal_assert (m_impl != nullptr);
return *m_impl;
}
// Retrieves a reference to the underlying socket. BEAST_DEFINE_IS_CALL_POSSIBLE(has_read_some, read_some);
// usually asio::basic_socket or asio::basic_stream_socket BEAST_DEFINE_IS_CALL_POSSIBLE(has_write_some, write_some);
// It must be compatible with our Protocol and SocketService BEAST_DEFINE_IS_CALL_POSSIBLE(has_async_read_some, async_read_some);
// or else a std::bad cast will be thrown. BEAST_DEFINE_IS_CALL_POSSIBLE(has_async_write_some, async_write_some);
//
// The reason its a template class and not a function is BEAST_DEFINE_IS_CALL_POSSIBLE(has_handshake, handshake);
// because it would otherwise generate a compile error BEAST_DEFINE_IS_CALL_POSSIBLE(has_async_handshake, async_handshake);
// if Object did not have a declaration for BEAST_DEFINE_IS_CALL_POSSIBLE(has_async_shutdown, async_shutdown);
// protocol_type::socket
// // Extracts the underlying socket type from the protocol of another asio object
template <typename AsioObject, class Enable = void> template <typename T, typename Enable = void>
struct native_socket struct native_socket
{ {
typedef void* native_socket_type; typedef void* socket_type;
native_socket (Socket&) { pure_virtual (); } inline native_socket (Socket&) : m_socket (nullptr) { SocketBase::pure_virtual (); }
native_socket_type& get () { pure_virtual (); return m_socket; } inline socket_type& get () { SocketBase::pure_virtual (); return m_socket; }
native_socket_type& operator-> () noexcept { return get(); } inline socket_type& operator-> () { return get (); }
private: private:
native_socket_type m_socket; socket_type m_socket;
}; };
template <typename AsioObject> // Enabled if T::protocol_type::socket exists as a type
struct native_socket <AsioObject, typename boost::enable_if <boost::is_class < template <typename T>
typename AsioObject::protocol_type::socket> >::type> 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; typedef typename T::protocol_type::socket socket_type;
native_socket (Socket& peer) inline native_socket (Socket& peer) : m_socket_ptr (&peer.native_handle <socket_type> ()) { }
: m_socket (&peer.this_layer <native_socket_type> ()) { } inline socket_type& get () noexcept { return *m_socket_ptr; }
native_socket_type& get () noexcept { return *m_socket; } inline socket_type& operator-> () noexcept { return get (); }
native_socket_type& operator-> () noexcept { return *m_socket; }
private: private:
native_socket_type* m_socket; socket_type* m_socket_ptr;
}; };
};
//-------------------------------------------------------------------------- template <typename WrappedObject>
class SocketWrapper
: public virtual Socket
, public SocketWrapperBasics
, public Uncopyable
{
private:
typedef typename boost::remove_reference <WrappedObject>::type wrapped_type;
#if 0 public:
typedef typename boost::remove_reference <Object>::type next_layer_type; typedef typename boost::remove_reference <WrappedObject>::type WrappedObjectType;
typedef typename next_layer_type::lowest_layer_type lowest_layer_type;
next_layer_type& next_layer () noexcept 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 () 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 ()); pure_virtual ();
if (strcmp (type_name, this_type_name) == 0) return *static_cast <boost::asio::io_service*>(nullptr);
return const_cast <void*> (static_cast <void const*>(m_impl)); }
//--------------------------------------------------------------------------
//
// 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; 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) boost::system::error_code close (boost::system::error_code& ec)
{ {
using namespace boost;
using namespace SocketWrapperMemberChecks;
return close (ec, 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::system::error_code close (boost::system::error_code& ec,
boost::true_type) boost::true_type)
{ {
return get_object ().close (ec); return m_object.close (ec);
} }
boost::system::error_code close (boost::system::error_code& 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) 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, 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::system::error_code accept (Socket& peer, boost::system::error_code& ec,
boost::true_type) boost::true_type)
{ {
#if 1 using namespace SocketWrapperMemberChecks;
return get_object ().accept ( return m_object.accept (
native_socket <Object> (peer).get (), ec); native_socket <wrapped_type> (peer).get (), ec);
#else
typedef ObjectType::protocol_type::socket socket_type;
socket_type& socket (peer.this_layer <socket_type> ());
return get_object ().accept (socket, ec);
#endif
} }
boost::system::error_code accept (Socket&, boost::system::error_code& ec, boost::system::error_code accept (Socket&, boost::system::error_code& ec,
@@ -205,11 +338,18 @@ public:
return pure_virtual (ec); return pure_virtual (ec);
} }
//--------------------------------------------------------------------------
BEAST_ASIO_INITFN_RESULT_TYPE_MEMBER(ErrorCall, void (boost::system::error_code)) BEAST_ASIO_INITFN_RESULT_TYPE_MEMBER(ErrorCall, void (boost::system::error_code))
async_accept (Socket& peer, BOOST_ASIO_MOVE_ARG(ErrorCall) handler) 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), 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> template <typename AcceptHandler>
@@ -217,14 +357,10 @@ public:
async_accept (Socket& peer, BOOST_ASIO_MOVE_ARG(AcceptHandler) handler, async_accept (Socket& peer, BOOST_ASIO_MOVE_ARG(AcceptHandler) handler,
boost::true_type) boost::true_type)
{ {
#if 1 using namespace SocketWrapperMemberChecks;
return get_object ().async_accept ( return m_object.async_accept (
native_socket <Object> (peer).get (), handler); native_socket <wrapped_type> (peer).get (),
#else BOOST_ASIO_MOVE_CAST(AcceptHandler)(handler));
typedef ObjectType::protocol_type::socket socket_type;
socket_type& socket (peer.this_layer <socket_type> ());
return get_object ().async_accept (socket, handler);
#endif
} }
template <typename AcceptHandler> 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) std::size_t read_some (MutableBuffers const& buffers, boost::system::error_code& ec)
{ {
using namespace boost;
using namespace SocketWrapperMemberChecks;
return read_some (buffers, ec, 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> template <typename MutableBufferSequence>
std::size_t read_some (MutableBufferSequence const& buffers, boost::system::error_code& ec, std::size_t read_some (MutableBufferSequence const& buffers, boost::system::error_code& ec,
boost::true_type) boost::true_type)
{ {
return get_object ().read_some (buffers, ec); return m_object.read_some (buffers, ec);
} }
template <typename MutableBufferSequence> template <typename MutableBufferSequence>
@@ -347,17 +414,22 @@ public:
return 0; return 0;
} }
//--------------------------------------------------------------------------
std::size_t write_some (ConstBuffers const& buffers, boost::system::error_code& ec) std::size_t write_some (ConstBuffers const& buffers, boost::system::error_code& ec)
{ {
using namespace boost;
using namespace SocketWrapperMemberChecks;
return write_some (buffers, ec, 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> template <typename ConstBufferSequence>
std::size_t write_some (ConstBufferSequence const& buffers, boost::system::error_code& ec, std::size_t write_some (ConstBufferSequence const& buffers, boost::system::error_code& ec,
boost::true_type) boost::true_type)
{ {
return get_object ().write_some (buffers, ec); return m_object.write_some (buffers, ec);
} }
template <typename ConstBufferSequence> template <typename ConstBufferSequence>
@@ -368,11 +440,17 @@ public:
return 0; return 0;
} }
//--------------------------------------------------------------------------
BEAST_ASIO_INITFN_RESULT_TYPE_MEMBER(TransferCall, void (boost::system::error_code, std::size_t)) BEAST_ASIO_INITFN_RESULT_TYPE_MEMBER(TransferCall, void (boost::system::error_code, std::size_t))
async_read_some (MutableBuffers const& buffers, BOOST_ASIO_MOVE_ARG(TransferCall) handler) 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), 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> template <typename MutableBufferSequence, typename ReadHandler>
@@ -380,7 +458,7 @@ public:
async_read_some (MutableBufferSequence const& buffers, BOOST_ASIO_MOVE_ARG(ReadHandler) handler, async_read_some (MutableBufferSequence const& buffers, BOOST_ASIO_MOVE_ARG(ReadHandler) handler,
boost::true_type) boost::true_type)
{ {
return get_object ().async_read_some (buffers, return m_object.async_read_some (buffers,
BOOST_ASIO_MOVE_CAST(ReadHandler)(handler)); BOOST_ASIO_MOVE_CAST(ReadHandler)(handler));
} }
@@ -404,11 +482,17 @@ public:
#endif #endif
} }
//--------------------------------------------------------------------------
BEAST_ASIO_INITFN_RESULT_TYPE_MEMBER(TransferCall, void (boost::system::error_code, std::size_t)) BEAST_ASIO_INITFN_RESULT_TYPE_MEMBER(TransferCall, void (boost::system::error_code, std::size_t))
async_write_some (ConstBuffers const& buffers, BOOST_ASIO_MOVE_ARG(TransferCall) handler) 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), 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> template <typename ConstBufferSequence, typename WriteHandler>
@@ -416,7 +500,7 @@ public:
async_write_some (ConstBufferSequence const& buffers, BOOST_ASIO_MOVE_ARG(WriteHandler) handler, async_write_some (ConstBufferSequence const& buffers, BOOST_ASIO_MOVE_ARG(WriteHandler) handler,
boost::true_type) boost::true_type)
{ {
return get_object ().async_write_some (buffers, return m_object.async_write_some (buffers,
BOOST_ASIO_MOVE_CAST(WriteHandler)(handler)); 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) boost::system::error_code handshake (handshake_type type, boost::system::error_code& ec)
{ {
using namespace boost;
using namespace SocketWrapperMemberChecks;
return handshake (type, ec, 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::system::error_code handshake (handshake_type type, boost::system::error_code& ec,
boost::true_type) 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, boost::system::error_code handshake (handshake_type, boost::system::error_code& ec,
@@ -466,50 +566,60 @@ public:
return pure_virtual (ec); return pure_virtual (ec);
} }
//--------------------------------------------------------------------------
BEAST_ASIO_INITFN_RESULT_TYPE_MEMBER(ErrorCall, void (boost::system::error_code)) BEAST_ASIO_INITFN_RESULT_TYPE_MEMBER(ErrorCall, void (boost::system::error_code))
async_handshake (handshake_type type, BOOST_ASIO_MOVE_ARG(ErrorCall) handler) 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), 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> BEAST_ASIO_INITFN_RESULT_TYPE_MEMBER(ErrorCall, void (boost::system::error_code))
BOOST_ASIO_INITFN_RESULT_TYPE(HandshakeHandler, void (boost::system::error_code)) async_handshake (handshake_type type, BOOST_ASIO_MOVE_ARG(ErrorCall) handler,
async_handshake (handshake_type type, BOOST_ASIO_MOVE_ARG(HandshakeHandler) handler,
boost::true_type) boost::true_type)
{ {
return get_object ().async_handshake (type, return m_object.async_handshake (type,
BOOST_ASIO_MOVE_CAST(HandshakeHandler)(handler)); BOOST_ASIO_MOVE_CAST(ErrorCall)(handler));
} }
template <typename HandshakeHandler> BEAST_ASIO_INITFN_RESULT_TYPE_MEMBER(ErrorCall, void (boost::system::error_code))
BOOST_ASIO_INITFN_RESULT_TYPE(HandshakeHandler, void (boost::system::error_code)) async_handshake (handshake_type, BOOST_ASIO_MOVE_ARG(ErrorCall) handler,
async_handshake (handshake_type, BOOST_ASIO_MOVE_ARG(HandshakeHandler) handler,
boost::false_type) boost::false_type)
{ {
#if BEAST_ASIO_HAS_FUTURE_RETURNS #if BEAST_ASIO_HAS_FUTURE_RETURNS
boost::asio::detail::async_result_init< boost::asio::detail::async_result_init<
HandshakeHandler, void (boost::system::error_code)> init( ErrorCall, void (boost::system::error_code)> init(
BOOST_ASIO_MOVE_CAST(HandshakeHandler)(handler)); BOOST_ASIO_MOVE_CAST(ErrorCall)(handler));
boost::system::error_code ec; boost::system::error_code ec;
ec = pure_virtual (ec); ec = pure_virtual (ec);
get_io_service ().post (boost::bind ( get_io_service ().post (boost::bind (
BOOST_ASIO_MOVE_CAST(HandshakeHandler)(handler), ec)); BOOST_ASIO_MOVE_CAST(ErrorCall)(handler), ec));
return init.result.get(); return init.result.get();
#else #else
boost::system::error_code ec; boost::system::error_code ec;
ec = pure_virtual (ec); ec = pure_virtual (ec);
get_io_service ().post (boost::bind ( get_io_service ().post (boost::bind (
BOOST_ASIO_MOVE_CAST(HandshakeHandler)(handler), ec)); BOOST_ASIO_MOVE_CAST(ErrorCall)(handler), ec));
#endif #endif
} }
//--------------------------------------------------------------------------
#if BEAST_ASIO_HAS_BUFFEREDHANDSHAKE #if BEAST_ASIO_HAS_BUFFEREDHANDSHAKE
boost::system::error_code handshake (handshake_type type, boost::system::error_code handshake (handshake_type type,
ConstBuffers const& buffers, boost::system::error_code& ec) ConstBuffers const& buffers, boost::system::error_code& ec)
{ {
using namespace boost;
using namespace SocketWrapperMemberChecks;
return handshake (type, buffers, ec, 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> template <typename ConstBufferSequence>
@@ -517,7 +627,7 @@ public:
ConstBufferSequence const& buffers, boost::system::error_code& ec, ConstBufferSequence const& buffers, boost::system::error_code& ec,
boost::true_type) boost::true_type)
{ {
return get_object ().handshake (type, buffers, ec); return m_object.handshake (type, buffers, ec);
} }
template <typename ConstBufferSequence> template <typename ConstBufferSequence>
@@ -528,59 +638,65 @@ public:
return pure_virtual (ec); return pure_virtual (ec);
} }
//--------------------------------------------------------------------------
BEAST_ASIO_INITFN_RESULT_TYPE_MEMBER(TransferCall, void (boost::system::error_code, std::size_t)) BEAST_ASIO_INITFN_RESULT_TYPE_MEMBER(TransferCall, void (boost::system::error_code, std::size_t))
async_handshake (handshake_type type, ConstBuffers const& buffers, async_handshake (handshake_type type, ConstBuffers const& buffers,
BOOST_ASIO_MOVE_ARG(TransferCall) handler) BOOST_ASIO_MOVE_ARG(TransferCall) handler)
{ {
return async_handshake (type, buffers, using namespace boost;
BOOST_ASIO_MOVE_CAST(TransferCall)(handler), using namespace SocketWrapperMemberChecks;
Has <SocketInterface::BufferedAsyncHandshake> ()); 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> BEAST_ASIO_INITFN_RESULT_TYPE_MEMBER(TransferCall, void (boost::system::error_code, std::size_t))
BOOST_ASIO_INITFN_RESULT_TYPE(BufferedHandshakeHandler, void (boost::system::error_code, std::size_t)) async_handshake (handshake_type type, ConstBuffers const& buffers, BOOST_ASIO_MOVE_ARG(TransferCall) handler,
async_handshake (handshake_type type, const ConstBufferSequence& buffers,
BOOST_ASIO_MOVE_ARG(BufferedHandshakeHandler) handler,
boost::true_type) boost::true_type)
{ {
return get_object ().async_handshake (type, buffers, return m_object.async_handshake (type, buffers,
BOOST_ASIO_MOVE_CAST(BufferedHandshakeHandler)(handler)); BOOST_ASIO_MOVE_CAST(TransferCall)(handler));
} }
template <typename ConstBufferSequence, typename BufferedHandshakeHandler> BEAST_ASIO_INITFN_RESULT_TYPE_MEMBER(TransferCall, void (boost::system::error_code, std::size_t))
BOOST_ASIO_INITFN_RESULT_TYPE(BufferedHandshakeHandler, void (boost::system::error_code, std::size_t)) async_handshake (handshake_type, ConstBuffers const&, BOOST_ASIO_MOVE_ARG(TransferCall) handler,
async_handshake (handshake_type, const ConstBufferSequence&,
BOOST_ASIO_MOVE_ARG(BufferedHandshakeHandler) handler,
boost::false_type) boost::false_type)
{ {
#if BEAST_ASIO_HAS_FUTURE_RETURNS #if BEAST_ASIO_HAS_FUTURE_RETURNS
boost::asio::detail::async_result_init< boost::asio::detail::async_result_init<
BufferedHandshakeHandler, void (boost::system::error_code, std::size_t)> init( TransferCall, void (boost::system::error_code, std::size_t)> init(
BOOST_ASIO_MOVE_CAST(BufferedHandshakeHandler)(handler)); BOOST_ASIO_MOVE_CAST(TransferCall)(handler));
boost::system::error_code ec; boost::system::error_code ec;
ec = pure_virtual (ec); ec = pure_virtual (ec);
get_io_service ().post (boost::bind ( 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(); return init.result.get();
#else #else
boost::system::error_code ec; boost::system::error_code ec;
ec = pure_virtual (ec); ec = pure_virtual (ec);
get_io_service ().post (boost::bind ( get_io_service ().post (boost::bind (
BOOST_ASIO_MOVE_CAST(BufferedHandshakeHandler)(handler), ec, 0)); BOOST_ASIO_MOVE_CAST(TransferCall)(handler), ec, 0));
#endif #endif
} }
#endif #endif
//--------------------------------------------------------------------------
boost::system::error_code shutdown (boost::system::error_code& ec) boost::system::error_code shutdown (boost::system::error_code& ec)
{ {
using namespace boost;
using namespace SocketWrapperMemberChecks;
return shutdown (ec, 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::system::error_code shutdown (boost::system::error_code& ec,
boost::true_type) boost::true_type)
{ {
return get_object ().shutdown (ec); return m_object.shutdown (ec);
} }
boost::system::error_code shutdown (boost::system::error_code& ec, boost::system::error_code shutdown (boost::system::error_code& ec,
@@ -589,70 +705,49 @@ public:
return pure_virtual (ec); return pure_virtual (ec);
} }
//--------------------------------------------------------------------------
void async_shutdown (BOOST_ASIO_MOVE_ARG(ErrorCall) handler) void async_shutdown (BOOST_ASIO_MOVE_ARG(ErrorCall) handler)
{ {
async_shutdown (BOOST_ASIO_MOVE_CAST(ErrorCall)(handler), using namespace boost;
Has <SocketInterface::AsyncHandshake> ()); 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> BEAST_ASIO_INITFN_RESULT_TYPE_MEMBER(ErrorCall, void (boost::system::error_code))
BOOST_ASIO_INITFN_RESULT_TYPE(ShutdownHandler, void (boost::system::error_code)) async_shutdown (BOOST_ASIO_MOVE_ARG(ErrorCall) handler,
async_shutdown (BOOST_ASIO_MOVE_ARG(ShutdownHandler) handler,
boost::true_type) boost::true_type)
{ {
return get_object ().async_shutdown ( return m_object.async_shutdown (
BOOST_ASIO_MOVE_CAST(ShutdownHandler)(handler)); BOOST_ASIO_MOVE_CAST(ErrorCall)(handler));
} }
template <typename ShutdownHandler> BEAST_ASIO_INITFN_RESULT_TYPE_MEMBER(ErrorCall, void (boost::system::error_code))
BOOST_ASIO_INITFN_RESULT_TYPE(ShutdownHandler, void (boost::system::error_code)) async_shutdown (BOOST_ASIO_MOVE_ARG(ErrorCall) handler,
async_shutdown (BOOST_ASIO_MOVE_ARG(ShutdownHandler) handler,
boost::false_type) boost::false_type)
{ {
#if BEAST_ASIO_HAS_FUTURE_RETURNS #if BEAST_ASIO_HAS_FUTURE_RETURNS
boost::asio::detail::async_result_init< boost::asio::detail::async_result_init<
ShutdownHandler, void (boost::system::error_code, std::size_t)> init( ErrorCall, void (boost::system::error_code, std::size_t)> init(
BOOST_ASIO_MOVE_CAST(ShutdownHandler)(handler)); BOOST_ASIO_MOVE_CAST(ErrorCall)(handler));
boost::system::error_code ec; boost::system::error_code ec;
ec = pure_virtual (ec); ec = pure_virtual (ec);
get_io_service ().post (boost::bind ( get_io_service ().post (boost::bind (
BOOST_ASIO_MOVE_CAST(ShutdownHandler)(handler), ec)); BOOST_ASIO_MOVE_CAST(ErrorCall)(handler), ec));
return init.result.get(); return init.result.get();
#else #else
boost::system::error_code ec; boost::system::error_code ec;
ec = pure_virtual (ec); ec = pure_virtual (ec);
get_io_service ().post (boost::bind ( get_io_service ().post (boost::bind (
BOOST_ASIO_MOVE_CAST(ShutdownHandler)(handler), ec)); BOOST_ASIO_MOVE_CAST(ErrorCall)(handler), ec));
#endif #endif
} }
protected: private:
explicit SocketWrapper (Object* object = nullptr) noexcept WrappedObject m_object;
: m_impl (object)
{
}
void set (Object* ptr) noexcept
{
m_impl = ptr;
}
template <typename Interface>
struct Has : HasInterface <ObjectType, Interface> { };
public:
Object* m_impl;
}; };
//------------------------------------------------------------------------------
/** 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 #endif

View File

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

View File

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