diff --git a/modules/beast_asio/sockets/beast_Socket.cpp b/modules/beast_asio/sockets/beast_Socket.cpp index e67bc1a27..2dfc4116f 100644 --- a/modules/beast_asio/sockets/beast_Socket.cpp +++ b/modules/beast_asio/sockets/beast_Socket.cpp @@ -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 (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::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 - std::size_t write_some (const ConstBufferSequence& buffers) - template - std::size_t write_some (const ConstBufferSequence& buffers, boost::system::error_code& ec) - - // AsyncWriteStream - template - void async_write_some (const ConstBufferSequence& buffers, WriteHandler handler) - - // ReadStream - template - std::size_t read_some (const MutableBufferSequence& buffers) - template - std::size_t read_some (const MutableBufferSequence& buffers, boost::system::error_code& ec) - - // AsyncReadStream - template - 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 : 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 : basic_io_object basic_stream_socket : basic_socket +ssl::stream + handshake () + async_handshake () + shutdown () */ diff --git a/modules/beast_asio/sockets/beast_Socket.h b/modules/beast_asio/sockets/beast_Socket.h index 59d92684d..cbe4b1300 100644 --- a/modules/beast_asio/sockets/beast_Socket.h +++ b/modules/beast_asio/sockets/beast_Socket.h @@ -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 (); - - if (sock != nullptr) - sock->set_option ( - Protocol::no_delay (true)); - } - - @endcode - */ - template - Object& this_layer () - { - Object* object (this_layer_ptr ()); - if (object == nullptr) - Throw (std::bad_cast (), __FILE__, __LINE__); - return *object; - } - - template - Object const& this_layer () const - { - Object const* object (this_layer_ptr ()); - if (object == nullptr) - Throw (std::bad_cast (), __FILE__, __LINE__); - return *object; - } - - template - Object* this_layer_ptr () - { - return static_cast ( - this_layer_raw (typeid (Object).name ())); - } - - template - Object const* this_layer_ptr () const - { - return static_cast ( - 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 - 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 Object& lowest_layer () { - Object* object (lowest_layer_ptr ()); + Object* object (this->lowest_layer_ptr ()); if (object == nullptr) Throw (std::bad_cast (), __FILE__, __LINE__); return *object; @@ -178,7 +66,7 @@ public: template Object const& lowest_layer () const { - Object const* object (lowest_layer_ptr ()); + Object const* object (this->lowest_layer_ptr ()); if (object == nullptr) Throw (std::bad_cast (), __FILE__, __LINE__); return *object; @@ -188,24 +76,58 @@ public: Object* lowest_layer_ptr () { return static_cast ( - lowest_layer_raw (typeid (Object).name ())); + this->lowest_layer (typeid (Object).name ())); } template Object const* lowest_layer_ptr () const { return static_cast ( - 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 + Object& native_handle () + { + Object* object (this->native_handle_ptr ()); + 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 + Object const& native_handle () const + { + Object const* object (this->native_handle_ptr ()); + if (object == nullptr) + Throw (std::bad_cast (), __FILE__, __LINE__); + return *object; + } - //-------------------------------------------------------------------------- - // - // SocketInterface::Socket - // - //-------------------------------------------------------------------------- + template + Object* native_handle_ptr () + { + return static_cast ( + this->native_handle (typeid (Object).name ())); + } + + template + Object const* native_handle_ptr () const + { + return static_cast ( + 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 + 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 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 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 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 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 diff --git a/modules/beast_asio/sockets/beast_SocketBase.h b/modules/beast_asio/sockets/beast_SocketBase.h index f14453541..f8e20f5a3 100644 --- a/modules/beast_asio/sockets/beast_SocketBase.h +++ b/modules/beast_asio/sockets/beast_SocketBase.h @@ -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) { diff --git a/modules/beast_asio/sockets/beast_SocketWrapper.h b/modules/beast_asio/sockets/beast_SocketWrapper.h index 9e0fdd5d6..699199301 100644 --- a/modules/beast_asio/sockets/beast_SocketWrapper.h +++ b/modules/beast_asio/sockets/beast_SocketWrapper.h @@ -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 + arg must be an io_context + SocketWrapper creates and takes ownership of the ssl::stream + WrappedObjecType will be asio::ssl::stream + next_layer () returns a asio::ip::tcp::socket& + lowest_layer () returns a asio::ip::tcp::socket& + + asio::ssl::stream + arg must be an existing socket& + The caller owns the socket, but SocketWrapper owns the ssl::stream + WrappedObjectType will be asio::ssl::stream + next_layer () returns a asio::ip::tcp::socket& + lowest_layer () returns a asio::ip::tcp::socket& + + asio::ssl::stream > > + This makes my head explode */ -template -class SocketWrapper - : public virtual Socket - , protected SocketWrapperBasics + +//------------------------------------------------------------------------------ + +namespace SocketWrapperMemberChecks { -public: - typedef typename boost::remove_pointer < - typename boost::remove_reference < - typename boost::remove_cv ::type >::type >::type - ObjectType; + template + struct EnableIf : boost::false_type { }; - SocketWrapper (Object& object) noexcept - : m_impl (&object) - { - } + template <> + struct EnableIf : boost::true_type { }; - SocketWrapper (SocketWrapper const& other) noexcept - : m_impl (other.m_impl) - { - } + BEAST_DEFINE_IS_CALL_POSSIBLE(has_get_io_service, get_io_service); - SocketWrapper& operator= (SocketWrapper const& other) noexcept - { - m_impl = other.m_impl; - } + 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); - // Retrieve the underlying object - Object& get_object () const noexcept - { - fatal_assert (m_impl != nullptr); - return *m_impl; - } + BEAST_DEFINE_IS_CALL_POSSIBLE(has_accept, accept); + BEAST_DEFINE_IS_CALL_POSSIBLE(has_async_accept, async_accept); - // 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 + 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 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 - struct native_socket >::type> + // Enabled if T::protocol_type::socket exists as a type + template + struct native_socket >::type> { - typedef typename AsioObject::protocol_type::socket native_socket_type; - native_socket (Socket& peer) - : m_socket (&peer.this_layer ()) { } - 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 ()) { } + 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; }; +}; - //-------------------------------------------------------------------------- +template +class SocketWrapper + : public virtual Socket + , public SocketWrapperBasics + , public Uncopyable +{ +private: + typedef typename boost::remove_reference ::type wrapped_type; -#if 0 - typedef typename boost::remove_reference ::type next_layer_type; - typedef typename next_layer_type::lowest_layer_type lowest_layer_type; +public: + typedef typename boost::remove_reference ::type WrappedObjectType; - next_layer_type& next_layer () noexcept + template + explicit SocketWrapper (Arg& arg) + : m_object (arg) { - return get_object ().next_layer (); } - next_layer_type const& next_layer () const noexcept + template + 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 ::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 ::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 (static_cast (m_impl)); + pure_virtual (); + return *static_cast (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(lowest_layer_type) +#endif + + template + struct has_type_lowest_layer_type + { + typedef char yes; + typedef struct {char dummy[2];} no; + template static yes f(typename C::lowest_layer_type*); + template static no f(...); +#ifdef _MSC_VER + static bool const value = sizeof(f(0)) == 1; +#else + // This line fails to compile under Visual Studio 2012 + static bool const value = sizeof(has_type_lowest_layer_type::f(0)) == 1; +#endif + }; + + void* lowest_layer (char const* type_name) const + { + using namespace SocketWrapperMemberChecks; + return lowest_layer (type_name, + EnableIf ::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 (static_cast (&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 (static_cast (&m_object)); + return nullptr; + } + + //-------------------------------------------------------------------------- + + boost::system::error_code cancel (boost::system::error_code& ec) + { + using namespace boost; + using namespace SocketWrapperMemberChecks; + return cancel (ec, + EnableIf ::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 ::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 ()); + EnableIf ::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 ::socket_type socket_type; return accept (peer, ec, - Has ()); + EnableIf ::value> ()); } boost::system::error_code accept (Socket& peer, boost::system::error_code& ec, boost::true_type) { -#if 1 - return get_object ().accept ( - native_socket (peer).get (), ec); -#else - typedef ObjectType::protocol_type::socket socket_type; - socket_type& socket (peer.this_layer ()); - return get_object ().accept (socket, ec); -#endif + using namespace SocketWrapperMemberChecks; + return m_object.accept ( + native_socket (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 ::socket_type socket_type; return async_accept (peer, BOOST_ASIO_MOVE_CAST(ErrorCall)(handler), - Has ()); + EnableIf ::value> ()); } template @@ -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 (peer).get (), handler); -#else - typedef ObjectType::protocol_type::socket socket_type; - socket_type& socket (peer.this_layer ()); - return get_object ().async_accept (socket, handler); -#endif + using namespace SocketWrapperMemberChecks; + return m_object.async_accept ( + native_socket (peer).get (), + BOOST_ASIO_MOVE_CAST(AcceptHandler)(handler)); } template @@ -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 ()); - } - - 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 (static_cast (&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 ()); - } - - 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 ()); - } - - 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 ()); + EnableIf ::value> ()); } template 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 @@ -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 ()); + EnableIf ::value> ()); } template 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 @@ -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 ()); + EnableIf ::value> ()); } template @@ -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 ()); + EnableIf ::value> ()); } template @@ -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 ::value || + has_async_handshake ::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 ()); + EnableIf ::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 ()); + EnableIf ::value> ()); } - template - 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 - 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 ()); + EnableIf ::value> ()); } template @@ -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 @@ -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 ()); + using namespace boost; + using namespace SocketWrapperMemberChecks; + return async_handshake (type, buffers, BOOST_ASIO_MOVE_CAST(TransferCall)(handler), + EnableIf ::value> ()); } - template - 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 - 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 ()); + EnableIf ::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 ()); + using namespace boost; + using namespace SocketWrapperMemberChecks; + return async_shutdown (BOOST_ASIO_MOVE_CAST(ErrorCall)(handler), + EnableIf ::value> ()); } - template - 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 - 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 - struct Has : HasInterface { }; - -public: - Object* m_impl; +private: + WrappedObject m_object; }; -//------------------------------------------------------------------------------ - -/** Dynamically allocate a SocketWrapper. - This deduces the template arguments for convenience. -*/ -template -SocketWrapper * newSocketWrapper (Object& object) -{ - return new SocketWrapper (object); -} - #endif diff --git a/modules/beast_asio/sockets/beast_SocketWrapperBasics.h b/modules/beast_asio/sockets/beast_SocketWrapperBasics.h index 6c7e2f948..ab06f719c 100644 --- a/modules/beast_asio/sockets/beast_SocketWrapperBasics.h +++ b/modules/beast_asio/sockets/beast_SocketWrapperBasics.h @@ -24,7 +24,8 @@ */ class SocketWrapperBasics { -protected: +public: +#if 0 /** Template specialization to determine available interfaces. */ template struct InterfacesOf @@ -129,6 +130,7 @@ protected: { }; #endif +#endif }; #endif diff --git a/modules/beast_asio/tests/beast_TestPeerDetailsTcp.h b/modules/beast_asio/tests/beast_TestPeerDetailsTcp.h index a93e8537e..eef55745e 100644 --- a/modules/beast_asio/tests/beast_TestPeerDetailsTcp.h +++ b/modules/beast_asio/tests/beast_TestPeerDetailsTcp.h @@ -101,8 +101,8 @@ protected: protocol_type m_protocol; socket_type m_socket; acceptor_type m_acceptor; - SocketWrapper m_socket_wrapper; - SocketWrapper m_acceptor_wrapper; + SocketWrapper m_socket_wrapper; + SocketWrapper m_acceptor_wrapper; }; #endif