boost/beast/experimental/core/timeout_socket.hpp
// // Copyright (c) 2018 Vinnie Falco (vinnie dot falco at gmail dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // // Official repository: https://github.com/boostorg/beast // #ifndef BOOST_BEAST_CORE_TIMEOUT_SOCKET_HPP #define BOOST_BEAST_CORE_TIMEOUT_SOCKET_HPP #include <boost/beast/core/detail/config.hpp> #include <boost/beast/core/error.hpp> #include <boost/beast/core/type_traits.hpp> #include <boost/beast/experimental/core/detail/timeout_service.hpp> #include <boost/asio/async_result.hpp> #include <boost/asio/basic_stream_socket.hpp> #include <boost/asio/executor.hpp> #include <chrono> namespace boost { namespace asio { namespace ip { class tcp; } // ip } // asio } // boost namespace boost { namespace beast { /** A socket wrapper which automatically times out on asynchronous reads. This wraps a normal stream socket and implements a simple and efficient timeout for asynchronous read operations. @note Meets the requirements of @b AsyncReadStream and @b AsyncWriteStream */ template< class Protocol, class Executor = boost::asio::executor > class basic_timeout_socket { template<class> class async_op; class timer : public detail::timeout_object { basic_timeout_socket& s_; public: explicit timer(basic_timeout_socket& s); timer& operator=(timer&& other); void on_timeout() override; }; Executor ex_; // must come first timer rd_timer_; timer wr_timer_; boost::asio::basic_stream_socket<Protocol> sock_; bool expired_ = false; public: /// The type of the next layer. using next_layer_type = boost::asio::basic_stream_socket<Protocol>; /// The type of the lowest layer. using lowest_layer_type = get_lowest_layer<next_layer_type>; /// The protocol used by the stream. using protocol_type = Protocol; /// The type of the executor associated with the object. using executor_type = Executor; // VFALCO we only support default-construction // of the contained socket for now. // This constructor needs a protocol parameter. // /** Constructor */ template<class ExecutionContext #if ! BOOST_BEAST_DOXYGEN , class = typename std::enable_if< std::is_convertible< ExecutionContext&, boost::asio::execution_context&>::value && std::is_constructible< executor_type, typename ExecutionContext::executor_type>::value >::type #endif > explicit basic_timeout_socket(ExecutionContext& ctx); //-------------------------------------------------------------------------- /** Get the executor associated with the object. This function may be used to obtain the executor object that the stream uses to dispatch handlers for asynchronous operations. @return A copy of the executor that stream will use to dispatch handlers. */ executor_type get_executor() const noexcept { return ex_; } /** Get a reference to the next layer This function returns a reference to the next layer in a stack of stream layers. @return A reference to the next layer in the stack of stream layers. */ next_layer_type& next_layer() { return sock_; } /** Get a reference to the next layer This function returns a reference to the next layer in a stack of stream layers. @return A reference to the next layer in the stack of stream layers. */ next_layer_type const& next_layer() const { return sock_; } /** Get a reference to the lowest layer This function returns a reference to the lowest layer in a stack of stream layers. @return A reference to the lowest layer in the stack of stream layers. */ lowest_layer_type& lowest_layer() { return sock_.lowest_layer(); } /** Get a reference to the lowest layer This function returns a reference to the lowest layer in a stack of stream layers. @return A reference to the lowest layer in the stack of stream layers. Ownership is not transferred to the caller. */ lowest_layer_type const& lowest_layer() const { return sock_.lowest_layer(); } //-------------------------------------------------------------------------- /** Start an asynchronous read. This function is used to asynchronously read data from the stream socket. The function call always returns immediately. @param buffers One or more buffers into which the data will be read. Although the buffers object may be copied as necessary, ownership of the underlying memory blocks is retained by the caller, which must guarantee that they remain valid until the handler is called. @param handler The handler to be called when the read operation completes. Copies will be made of the handler as required. The function signature of the handler must be: @code void handler( const boost::system::error_code& error, // Result of operation. std::size_t bytes_transferred // Number of bytes read. ); @endcode Regardless of whether the asynchronous operation completes immediately or not, the handler will not be invoked from within this function. Invocation of the handler will be performed in a manner equivalent to using boost::asio::io_context::post(). */ template<class MutableBufferSequence, class ReadHandler> BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler, void(boost::system::error_code, std::size_t)) async_read_some( MutableBufferSequence const& buffers, ReadHandler&& handler); /** Start an asynchronous write. This function is used to asynchronously write data to the stream socket. The function call always returns immediately. @param buffers One or more data buffers to be written to the socket. Although the buffers object may be copied as necessary, ownership of the underlying memory blocks is retained by the caller, which must guarantee that they remain valid until the handler is called. @param handler The handler to be called when the write operation completes. Copies will be made of the handler as required. The function signature of the handler must be: @code void handler( const boost::system::error_code& error, // Result of operation. std::size_t bytes_transferred // Number of bytes written. ); @endcode Regardless of whether the asynchronous operation completes immediately or not, the handler will not be invoked from within this function. Invocation of the handler will be performed in a manner equivalent to using boost::asio::io_context::post(). */ template<class ConstBufferSequence, class WriteHandler> BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler, void(boost::system::error_code, std::size_t)) async_write_some( ConstBufferSequence const& buffers, WriteHandler&& handler); }; /// A TCP/IP socket wrapper which has a built-in asynchronous timeout using timeout_socket = basic_timeout_socket< boost::asio::ip::tcp, boost::asio::io_context::executor_type>; } // beast } // boost #include <boost/beast/experimental/core/impl/timeout_socket.hpp> #endif