diff --git a/include/urdl/detail/connect.hpp b/include/urdl/detail/connect.hpp index 241212f..a876578 100644 --- a/include/urdl/detail/connect.hpp +++ b/include/urdl/detail/connect.hpp @@ -11,7 +11,9 @@ #ifndef URDL_DETAIL_CONNECT_HPP #define URDL_DETAIL_CONNECT_HPP +#include #include +#include #include #include "urdl/detail/coroutine.hpp" @@ -28,25 +30,22 @@ inline boost::system::error_code connect( // Create a query that corresponds to the url. std::ostringstream port_string; port_string << u.port(); - boost::asio::ip::tcp::resolver::query query(u.host(), port_string.str()); // Get a list of endpoints corresponding to the query. - boost::asio::ip::tcp::resolver::iterator iter = resolver.resolve(query, ec); + boost::asio::ip::tcp::resolver::results_type endpoints = resolver.resolve(u.host(), port_string.str(), ec); if (ec) return ec; // Try each endpoint until we successfully establish a connection. ec = boost::asio::error::host_not_found; - while (ec && iter != boost::asio::ip::tcp::resolver::iterator()) - { - socket.close(ec); - socket.connect(*iter++, ec); - } + boost::asio::connect(socket, endpoints, ec); if (ec) return ec; // Disable the Nagle algorithm on all sockets. - return socket.set_option(boost::asio::ip::tcp::no_delay(true), ec); + ec = boost::system::error_code(); + socket.set_option(boost::asio::ip::tcp::no_delay(true), ec); + return ec; } template @@ -63,14 +62,15 @@ class connect_coro : coroutine } void operator()(boost::system::error_code ec, - boost::asio::ip::tcp::resolver::iterator iter) + boost::asio::ip::tcp::resolver::results_type iter) { - iter_ = iter; + results_ = iter; (*this)(ec); } void operator()(boost::system::error_code ec, - const boost::asio::ip::tcp::resolver::query* query = 0) + boost::asio::string_view host = {}, + boost::asio::string_view port = {}) { URDL_CORO_BEGIN; @@ -79,14 +79,14 @@ class connect_coro : coroutine socket_.open(boost::asio::ip::tcp::v4(), ec); if (ec) { - URDL_CORO_YIELD(socket_.get_io_service().post( + URDL_CORO_YIELD(boost::asio::post( boost::asio::detail::bind_handler(*this, ec))); handler_(ec); return; } // Get a list of endpoints corresponding to the host name. - URDL_CORO_YIELD(resolver_.async_resolve(*query, *this)); + URDL_CORO_YIELD(resolver_.async_resolve(host, port, *this)); if (ec) { handler_(ec); @@ -95,21 +95,7 @@ class connect_coro : coroutine // Try each endpoint until we successfully establish a connection. ec = boost::asio::error::host_not_found; - while (ec && iter_ != boost::asio::ip::tcp::resolver::iterator()) - { - // Check whether the operation has been cancelled. - if (!socket_.is_open()) - { - ec = boost::asio::error::operation_aborted; - handler_(ec); - return; - } - - // Try next endpoint. - socket_.close(ec); - endpoint_ = *iter_++; - URDL_CORO_YIELD(socket_.async_connect(endpoint_, *this)); - } + URDL_CORO_YIELD(boost::asio::connect(socket_, results_, ec)); if (ec) { handler_(ec); @@ -166,8 +152,7 @@ class connect_coro : coroutine Handler handler_; boost::asio::ip::tcp::socket::lowest_layer_type& socket_; boost::asio::ip::tcp::resolver& resolver_; - boost::asio::ip::tcp::resolver::iterator iter_; - boost::asio::ip::tcp::endpoint endpoint_; + boost::asio::ip::tcp::resolver::results_type results_; }; template @@ -176,9 +161,8 @@ void async_connect(boost::asio::ip::tcp::socket::lowest_layer_type& socket, { std::ostringstream port_string; port_string << u.port(); - boost::asio::ip::tcp::resolver::query query(u.host(), port_string.str()); connect_coro(handler, socket, resolver)( - boost::system::error_code(), &query); + boost::system::error_code(), u.host(), port_string.str()); } } // namespace detail diff --git a/include/urdl/detail/file_read_stream.hpp b/include/urdl/detail/file_read_stream.hpp index 99372c8..4479d61 100644 --- a/include/urdl/detail/file_read_stream.hpp +++ b/include/urdl/detail/file_read_stream.hpp @@ -12,7 +12,7 @@ #define URDL_DETAIL_FILE_READ_STREAM_HPP #include -#include +#include #include #include #include @@ -28,9 +28,9 @@ namespace detail { class file_read_stream { public: - explicit file_read_stream(boost::asio::io_service& io_service, + explicit file_read_stream(boost::asio::io_context& io_context, option_set& options) - : io_service_(io_service), + : io_context_(io_context), options_(options) { } @@ -59,7 +59,7 @@ class file_read_stream { boost::system::error_code ec; open(u, ec); - io_service_.post(boost::asio::detail::bind_handler(handler, ec)); + boost::asio::post(boost::asio::detail::bind_handler(handler, ec)); } boost::system::error_code close(boost::system::error_code& ec) @@ -77,7 +77,7 @@ class file_read_stream } template - std::size_t read_some(const MutableBufferSequence& buffers, + std::size_t read_some(const MutableBufferSequence& buffer, boost::system::error_code& ec) { if (!file_) @@ -86,20 +86,14 @@ class file_read_stream return 0; } - typename MutableBufferSequence::const_iterator iter = buffers.begin(); - typename MutableBufferSequence::const_iterator end = buffers.end(); - for (; iter != end; ++iter) + size_t length = boost::asio::buffer_size(buffer); + if (length > 0) { - boost::asio::mutable_buffer buffer(*iter); - size_t length = boost::asio::buffer_size(buffer); - if (length > 0) - { - file_.read(boost::asio::buffer_cast(buffer), length); - length = file_.gcount(); - if (length == 0 && !file_) - ec = boost::asio::error::eof; - return length; - } + file_.read(static_cast(buffer.data()), length); + length = file_.gcount(); + if (length == 0 && !file_) + ec = boost::asio::error::eof; + return length; } ec = boost::system::error_code(); @@ -111,12 +105,12 @@ class file_read_stream { boost::system::error_code ec; std::size_t bytes_transferred = read_some(buffers, ec); - io_service_.post(boost::asio::detail::bind_handler( + boost::asio::post(boost::asio::detail::bind_handler( handler, ec, bytes_transferred)); } private: - boost::asio::io_service& io_service_; + boost::asio::io_context& io_context_; option_set& options_; std::ifstream file_; }; diff --git a/include/urdl/detail/handshake.hpp b/include/urdl/detail/handshake.hpp index 470f188..6927ccd 100644 --- a/include/urdl/detail/handshake.hpp +++ b/include/urdl/detail/handshake.hpp @@ -41,7 +41,7 @@ void async_handshake(boost::asio::ip::tcp::socket& socket, const std::string& /*host*/, Handler handler) { boost::system::error_code ec; - socket.get_io_service().post(boost::asio::detail::bind_handler(handler, ec)); + boost::asio::post(socket.get_executor(), boost::asio::detail::bind_handler(handler, ec)); } #if !defined(URDL_DISABLE_SSL) @@ -81,7 +81,7 @@ inline bool certificate_matches_host(X509* cert, const std::string& host) // to look for an IP address in the certificate rather than a host name. boost::system::error_code ec; boost::asio::ip::address address - = boost::asio::ip::address::from_string(host, ec); + = boost::asio::ip::make_address(host, ec); bool is_address = !ec; // Go through the alternate names in the certificate looking for matching DNS @@ -167,9 +167,9 @@ inline boost::system::error_code handshake( return ec; // Verify the certificate returned by the host. - if (X509* cert = SSL_get_peer_certificate(socket.impl()->ssl)) + if (X509* cert = SSL_get_peer_certificate(socket.native_handle())) { - if (SSL_get_verify_result(socket.impl()->ssl) == X509_V_OK) + if (SSL_get_verify_result(socket.native_handle()) == X509_V_OK) { if (certificate_matches_host(cert, host)) ec = boost::system::error_code(); @@ -213,9 +213,9 @@ class handshake_coro : coroutine } // Verify the certificate returned by the host. - if (X509* cert = SSL_get_peer_certificate(socket_.impl()->ssl)) + if (X509* cert = SSL_get_peer_certificate(socket_.native_handle())) { - if (SSL_get_verify_result(socket_.impl()->ssl) == X509_V_OK) + if (SSL_get_verify_result(socket_.native_handle()) == X509_V_OK) { if (certificate_matches_host(cert, host_)) ec = boost::system::error_code(); diff --git a/include/urdl/detail/http_read_stream.hpp b/include/urdl/detail/http_read_stream.hpp index 720bec7..81df25d 100644 --- a/include/urdl/detail/http_read_stream.hpp +++ b/include/urdl/detail/http_read_stream.hpp @@ -12,7 +12,7 @@ #define URDL_DETAIL_HTTP_READ_STREAM_HPP #include -#include +#include #include #include #include @@ -39,20 +39,20 @@ template class http_read_stream { public: - explicit http_read_stream(boost::asio::io_service& io_service, + explicit http_read_stream(boost::asio::io_context& io_context, option_set& options) - : resolver_(io_service), - socket_(io_service), + : resolver_(io_context), + socket_(io_context), options_(options), content_length_(0) { } template - http_read_stream(boost::asio::io_service& io_service, + http_read_stream(boost::asio::io_context& io_context, option_set& options, Arg& arg) - : resolver_(io_service), - socket_(io_service, arg), + : resolver_(io_context), + socket_(io_context, arg), options_(options), content_length_(0) { @@ -203,7 +203,7 @@ class http_read_stream if (socket_.lowest_layer().is_open()) { ec = boost::asio::error::already_open; - URDL_CORO_YIELD(socket_.get_io_service().post( + URDL_CORO_YIELD(boost::asio::post( boost::asio::detail::bind_handler(*this, ec))); handler_(ec); return; @@ -394,7 +394,8 @@ class http_read_stream boost::system::error_code close(boost::system::error_code& ec) { resolver_.cancel(); - if (!socket_.lowest_layer().close(ec)) + socket_.lowest_layer().close(ec); + if (!ec) { request_buffer_.consume(request_buffer_.size()); reply_buffer_.consume(reply_buffer_.size()); @@ -432,31 +433,26 @@ class http_read_stream } template - std::size_t read_some(const MutableBufferSequence& buffers, + std::size_t read_some(const MutableBufferSequence& buffer, boost::system::error_code& ec) { // If we have any data in the reply_buffer_, return that first. if (reply_buffer_.size() > 0) { std::size_t bytes_transferred = 0; - typename MutableBufferSequence::const_iterator iter = buffers.begin(); - typename MutableBufferSequence::const_iterator end = buffers.end(); - for (; iter != end && reply_buffer_.size() > 0; ++iter) + size_t length = boost::asio::buffer_size(buffer); + if (length > 0) { - boost::asio::mutable_buffer buffer(*iter); - size_t length = boost::asio::buffer_size(buffer); - if (length > 0) - { - bytes_transferred += reply_buffer_.sgetn( - boost::asio::buffer_cast(buffer), length); - } + bytes_transferred += reply_buffer_.sgetn( + static_cast(buffer.data()), length); } + ec = boost::system::error_code(); return bytes_transferred; } // Otherwise we forward the call to the underlying socket. - std::size_t bytes_transferred = socket_.read_some(buffers, ec); + std::size_t bytes_transferred = socket_.read_some(buffer, ec); if (ec == boost::asio::error::shut_down) ec = boost::asio::error::eof; return bytes_transferred; @@ -520,7 +516,7 @@ class http_read_stream { boost::system::error_code ec; std::size_t bytes_transferred = read_some(buffers, ec); - socket_.get_io_service().post(boost::asio::detail::bind_handler( + boost::asio::post(boost::asio::detail::bind_handler( handler, ec, bytes_transferred)); return; } diff --git a/include/urdl/impl/istreambuf.ipp b/include/urdl/impl/istreambuf.ipp index 33a0aa1..4c5b32b 100644 --- a/include/urdl/impl/istreambuf.ipp +++ b/include/urdl/impl/istreambuf.ipp @@ -12,7 +12,7 @@ #define URDL_IMPL_ISTREAMBUF_IPP #include -#include +#include #include #include #include @@ -28,15 +28,15 @@ struct istreambuf::body enum { buffer_size = 512 }; body() - : read_stream_(io_service_), - timer_(io_service_), + : read_stream_(io_context_), + timer_(io_context_), open_timeout_(300 * 1000), read_timeout_(300 * 1000) { } boost::array get_buffer_; - boost::asio::io_service io_service_; + boost::asio::io_context io_context_; boost::system::error_code error_; read_stream read_stream_; boost::asio::deadline_timer timer_; @@ -125,8 +125,8 @@ istreambuf* istreambuf::open(const url& u) boost::posix_time::milliseconds(body_->open_timeout_)); body_->timer_.async_wait(th); - body_->io_service_.reset(); - body_->io_service_.run(); + body_->io_context_.restart(); + body_->io_context_.run(); if (!body_->read_stream_.is_open()) body_->error_ = make_error_code(boost::system::errc::timed_out); @@ -205,8 +205,8 @@ std::streambuf::int_type istreambuf::underflow() boost::posix_time::milliseconds(body_->read_timeout_)); body_->timer_.async_wait(th); - body_->io_service_.reset(); - body_->io_service_.run(); + body_->io_context_.restart(); + body_->io_context_.run(); if (!body_->read_stream_.is_open()) body_->error_ = make_error_code(boost::system::errc::timed_out); diff --git a/include/urdl/read_stream.hpp b/include/urdl/read_stream.hpp index 1bc5907..bdb49d9 100644 --- a/include/urdl/read_stream.hpp +++ b/include/urdl/read_stream.hpp @@ -11,7 +11,7 @@ #ifndef URDL_READ_STREAM_HPP #define URDL_READ_STREAM_HPP -#include +#include #include #include #include @@ -48,8 +48,8 @@ namespace urdl { * @code * try * { - * boost::asio::io_service io_service; - * urdl::read_stream read_stream(io_service); + * boost::asio::io_context io_context; + * urdl::read_stream read_stream(io_context); * read_stream.open("http://www.boost.org/LICENSE_1_0.txt"); * for (;;) * { @@ -72,8 +72,8 @@ namespace urdl { * To asynchronously open the URL, read the content and write it to standard * output: * @code - * boost::asio::io_service io_service; - * urdl::read_stream read_stream(io_service) + * boost::asio::io_context io_context; + * urdl::read_stream read_stream(io_context) * char data[1024]; * ... * read_stream.async_open("http://www.boost.org/LICENSE_1_0.txt", open_handler); @@ -105,33 +105,33 @@ class read_stream public: /// Constructs an object of class @c read_stream. /** - * @param io_service The @c io_service object that the stream will use to + * @param io_context The @c io_context object that the stream will use to * dispatch handlers for any asynchronous operations performed on the stream. */ - explicit read_stream(boost::asio::io_service& io_service) - : io_service_(io_service), - file_(io_service, options_), - http_(io_service, options_), + explicit read_stream(boost::asio::io_context& io_context) + : io_context_(io_context), + file_(io_context, options_), + http_(io_context, options_), #if !defined(URDL_DISABLE_SSL) - ssl_context_(io_service, boost::asio::ssl::context::sslv23), - https_(io_service, options_, ssl_context_), + ssl_context_(boost::asio::ssl::context::sslv23), + https_(io_context, options_, ssl_context_), #endif // !defined(URDL_DISABLE_SSL) protocol_(unknown) { #if !defined(URDL_DISABLE_SSL) ssl_context_.set_verify_mode(boost::asio::ssl::context::verify_peer); - SSL_CTX_set_default_verify_paths(ssl_context_.impl()); + SSL_CTX_set_default_verify_paths(ssl_context_.native_handle()); #endif // !defined(URDL_DISABLE_SSL) } - /// Gets the @c io_service associated with the stream. + /// Gets the @c io_context associated with the stream. /** - * @returns A reference to the @c io_service object that the stream will use + * @returns A reference to the @c io_context object that the stream will use * to dispatch handlers. Ownership is not transferred to the caller. */ - boost::asio::io_service& get_io_service() + boost::asio::io_context& get_io_context() { - return io_service_; + return io_context_; } /// Sets an option to control the behaviour of the stream. @@ -143,7 +143,7 @@ class read_stream * * @par Example * @code - * urdl::read_stream stream(io_service); + * urdl::read_stream stream(io_context); * stream.set_option(urdl::http::max_redirects(1)); * @endcode */ @@ -160,7 +160,7 @@ class read_stream * * @par Example * @code - * urdl::read_stream stream(io_service); + * urdl::read_stream stream(io_context); * urdl::option_set options; * options.set_option(urdl::http::max_redirects(1)); * options.set_option(urdl::ssl::verify_peer(false)); @@ -182,7 +182,7 @@ class read_stream * * @par Example * @code - * urdl::read_stream stream(io_service); + * urdl::read_stream stream(io_context); * urdl::http::max_redirects option * = stream.get_option(); * std::size_t value = option.value(); @@ -200,7 +200,7 @@ class read_stream * * @par Example * @code - * urdl::read_stream stream(io_service); + * urdl::read_stream stream(io_context); * ... * urdl::option_set options(stream.get_options()); * urdl::http::max_redirects option @@ -242,7 +242,7 @@ class read_stream * * @par Example * @code - * urdl::read_stream read_stream(io_service); + * urdl::read_stream read_stream(io_context); * * try * { @@ -274,7 +274,7 @@ class read_stream * * @par Example * @code - * urdl::read_stream read_stream(io_service); + * urdl::read_stream read_stream(io_context); * * boost::system::error_code ec; * read_stream.open("http://www.boost.org", ec); @@ -356,7 +356,7 @@ class read_stream * 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 - * @c boost::asio::io_service::post(). + * @c boost::asio::io_context::post(). * * @par Example * @code @@ -368,7 +368,7 @@ class read_stream * } * } * ... - * urdl::read_stream read_stream(io_service); + * urdl::read_stream read_stream(io_context); * read_stream.async_open("http://www.boost.org/", open_handler); * @endcode */ @@ -377,7 +377,12 @@ class read_stream void (boost::system::error_code)) async_open(const url& u, Handler handler) { -#if (BOOST_VERSION >= 105400) +#if (BOOST_VERSION >= 106600) + boost::asio::async_result result(handler); + typedef Handler real_handler_type; + Handler real_handler(handler); +#elif (BOOST_VERSION >= 105400) typedef typename boost::asio::handler_type::type real_handler_type; real_handler_type real_handler(handler); @@ -632,7 +637,7 @@ class read_stream * 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 - * @c boost::asio::io_service::post(). + * @c boost::asio::io_context::post(). * * @par Remarks * The asynchronous operation will continue until one or more bytes of data @@ -658,7 +663,11 @@ class read_stream void (boost::system::error_code, std::size_t)) async_read_some(const MutableBufferSequence& buffers, Handler handler) { -#if (BOOST_VERSION >= 105400) +#if (BOOST_VERSION >= 106600) + boost::asio::async_result result(handler); + Handler real_handler(handler); +#elif (BOOST_VERSION >= 105400) typedef typename boost::asio::handler_type::type real_handler_type; real_handler_type real_handler(handler); @@ -683,7 +692,7 @@ class read_stream default: boost::system::error_code ec = boost::asio::error::operation_not_supported; - io_service_.post(boost::asio::detail::bind_handler(real_handler, ec, 0)); + boost::asio::post(boost::asio::detail::bind_handler(real_handler, ec, 0)); break; } @@ -748,8 +757,7 @@ class read_stream else { ec = boost::asio::error::operation_not_supported; - this_->io_service_.post( - boost::asio::detail::bind_handler(handler_, ec)); + boost::asio::post(boost::asio::detail::bind_handler(handler_, ec)); return; } } @@ -795,7 +803,7 @@ class read_stream template friend class open_coro; - boost::asio::io_service& io_service_; + boost::asio::io_context& io_context_; option_set options_; detail::file_read_stream file_; detail::http_read_stream http_;