// // read_stream.hpp // ~~~~~~~~~~~~~~~ // // Copyright (c) 2009-2013 Christopher M. Kohlhoff (chris at kohlhoff 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) // #ifndef URDL_READ_STREAM_HPP #define URDL_READ_STREAM_HPP #include #include #include #include #include "urdl/http.hpp" #include "urdl/option_set.hpp" #include "urdl/url.hpp" #include "urdl/detail/coroutine.hpp" #include "urdl/detail/file_read_stream.hpp" #include "urdl/detail/http_read_stream.hpp" #if !defined(URDL_DISABLE_SSL) # include #endif // !defined(URDL_DISABLE_SSL) #include "urdl/detail/abi_prefix.hpp" namespace urdl { /// The class @c read_stream supports reading content from a specified URL /// using synchronous or asynchronous operations. /** * @par Remarks * Currently supported URL protocols are @c http, @c https and @c file. * * The class @c read_stream meets the type requirements for @c SyncReadStream * and @c AsyncReadStream, as defined in the Boost.Asio documentation. This * allows objects of class @c read_stream to be used with the functions * @c boost::asio::read, @c boost::asio::async_read, @c boost::asio::read_until * and @c boost::asio::async_read_until. * * @par Example * To synchronously open the URL, read the content and write it to standard * output: * @code * try * { * boost::asio::io_service io_service; * urdl::read_stream read_stream(io_service); * read_stream.open("http://www.boost.org/LICENSE_1_0.txt"); * for (;;) * { * char data[1024]; * boost::system::error_code ec; * std::size_t length = stream.read_some(boost::asio::buffer(data), ec); * if (ec == boost::asio::error::eof) * break; * if (ec) * throw boost::system::system_error(ec); * os.write(data, length); * } * } * catch (std::exception& e) * { * std::cerr << "Exception: " << e.what() << std::endl; * } * @endcode * * 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) * char data[1024]; * ... * read_stream.async_open("http://www.boost.org/LICENSE_1_0.txt", open_handler); * ... * void open_handler(const boost::system::error_code& ec) * { * if (!ec) * { * read_stream.async_read_some(boost::asio::buffer(data), read_handler); * } * } * ... * void read_handler(const boost::system::error_code& ec, std::size_t length) * { * if (!ec) * { * std::cout.write(data, length); * read_stream.async_read_some(boost::asio::buffer(data), read_handler); * } * } * @endcode * * @par Requirements * @e Header: @c @n * @e Namespace: @c urdl */ 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 * 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_), #if !defined(URDL_DISABLE_SSL) ssl_context_(io_service, boost::asio::ssl::context::sslv23), https_(io_service, 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()); #endif // !defined(URDL_DISABLE_SSL) } /// Gets the @c io_service associated with the stream. /** * @returns A reference to the @c io_service object that the stream will use * to dispatch handlers. Ownership is not transferred to the caller. */ boost::asio::io_service& get_io_service() { return io_service_; } /// Sets an option to control the behaviour of the stream. /** * @param option The option to be set on the stream. * * @par Remarks * Options are uniquely identified by type. * * @par Example * @code * urdl::read_stream stream(io_service); * stream.set_option(urdl::http::max_redirects(1)); * @endcode */ template void set_option(const Option& option) { options_.set_option(option); } /// Sets options to control the behaviour of the stream. /** * @param options The options to be set on the stream. The options in the set * are added on top of any options already set on the stream. * * @par Example * @code * urdl::read_stream stream(io_service); * urdl::option_set options; * options.set_option(urdl::http::max_redirects(1)); * options.set_option(urdl::ssl::verify_peer(false)); * stream.set_options(options); * @endcode */ void set_options(const option_set& options) { options_.set_options(options); } /// Gets the current value of an option that controls the behaviour of the /// stream. /** * @returns The current value of the option. * * @par Remarks * Options are uniquely identified by type. * * @par Example * @code * urdl::read_stream stream(io_service); * urdl::http::max_redirects option * = stream.get_option(); * std::size_t value = option.value(); * @endcode */ template Option get_option() const { return options_.get_option