Chris@16: // Chris@16: // impl/connect.hpp Chris@16: // ~~~~~~~~~~~~~~~~ Chris@16: // Chris@101: // Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) Chris@16: // Chris@16: // Distributed under the Boost Software License, Version 1.0. (See accompanying Chris@16: // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) Chris@16: // Chris@16: Chris@16: #ifndef BOOST_ASIO_IMPL_CONNECT_HPP Chris@16: #define BOOST_ASIO_IMPL_CONNECT_HPP Chris@16: Chris@16: #if defined(_MSC_VER) && (_MSC_VER >= 1200) Chris@16: # pragma once Chris@16: #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) Chris@16: Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: Chris@16: #include Chris@16: Chris@16: namespace boost { Chris@16: namespace asio { Chris@16: Chris@16: namespace detail Chris@16: { Chris@16: struct default_connect_condition Chris@16: { Chris@16: template Chris@16: Iterator operator()(const boost::system::error_code&, Iterator next) Chris@16: { Chris@16: return next; Chris@16: } Chris@16: }; Chris@16: } Chris@16: Chris@16: template Chris@16: Iterator connect(basic_socket& s, Iterator begin) Chris@16: { Chris@16: boost::system::error_code ec; Chris@16: Iterator result = connect(s, begin, ec); Chris@16: boost::asio::detail::throw_error(ec, "connect"); Chris@16: return result; Chris@16: } Chris@16: Chris@16: template Chris@16: inline Iterator connect(basic_socket& s, Chris@16: Iterator begin, boost::system::error_code& ec) Chris@16: { Chris@16: return connect(s, begin, Iterator(), detail::default_connect_condition(), ec); Chris@16: } Chris@16: Chris@16: template Chris@16: Iterator connect(basic_socket& s, Chris@16: Iterator begin, Iterator end) Chris@16: { Chris@16: boost::system::error_code ec; Chris@16: Iterator result = connect(s, begin, end, ec); Chris@16: boost::asio::detail::throw_error(ec, "connect"); Chris@16: return result; Chris@16: } Chris@16: Chris@16: template Chris@16: inline Iterator connect(basic_socket& s, Chris@16: Iterator begin, Iterator end, boost::system::error_code& ec) Chris@16: { Chris@16: return connect(s, begin, end, detail::default_connect_condition(), ec); Chris@16: } Chris@16: Chris@16: template Chris@16: Iterator connect(basic_socket& s, Chris@16: Iterator begin, ConnectCondition connect_condition) Chris@16: { Chris@16: boost::system::error_code ec; Chris@16: Iterator result = connect(s, begin, connect_condition, ec); Chris@16: boost::asio::detail::throw_error(ec, "connect"); Chris@16: return result; Chris@16: } Chris@16: Chris@16: template Chris@16: inline Iterator connect(basic_socket& s, Chris@16: Iterator begin, ConnectCondition connect_condition, Chris@16: boost::system::error_code& ec) Chris@16: { Chris@16: return connect(s, begin, Iterator(), connect_condition, ec); Chris@16: } Chris@16: Chris@16: template Chris@16: Iterator connect(basic_socket& s, Chris@16: Iterator begin, Iterator end, ConnectCondition connect_condition) Chris@16: { Chris@16: boost::system::error_code ec; Chris@16: Iterator result = connect(s, begin, end, connect_condition, ec); Chris@16: boost::asio::detail::throw_error(ec, "connect"); Chris@16: return result; Chris@16: } Chris@16: Chris@16: template Chris@16: Iterator connect(basic_socket& s, Chris@16: Iterator begin, Iterator end, ConnectCondition connect_condition, Chris@16: boost::system::error_code& ec) Chris@16: { Chris@16: ec = boost::system::error_code(); Chris@16: Chris@16: for (Iterator iter = begin; iter != end; ++iter) Chris@16: { Chris@16: iter = connect_condition(ec, iter); Chris@16: if (iter != end) Chris@16: { Chris@16: s.close(ec); Chris@16: s.connect(*iter, ec); Chris@16: if (!ec) Chris@16: return iter; Chris@16: } Chris@16: } Chris@16: Chris@16: if (!ec) Chris@16: ec = boost::asio::error::not_found; Chris@16: Chris@16: return end; Chris@16: } Chris@16: Chris@16: namespace detail Chris@16: { Chris@16: // Enable the empty base class optimisation for the connect condition. Chris@16: template Chris@16: class base_from_connect_condition Chris@16: { Chris@16: protected: Chris@16: explicit base_from_connect_condition( Chris@16: const ConnectCondition& connect_condition) Chris@16: : connect_condition_(connect_condition) Chris@16: { Chris@16: } Chris@16: Chris@16: template Chris@16: void check_condition(const boost::system::error_code& ec, Chris@16: Iterator& iter, Iterator& end) Chris@16: { Chris@16: if (iter != end) Chris@16: iter = connect_condition_(ec, static_cast(iter)); Chris@16: } Chris@16: Chris@16: private: Chris@16: ConnectCondition connect_condition_; Chris@16: }; Chris@16: Chris@16: // The default_connect_condition implementation is essentially a no-op. This Chris@16: // template specialisation lets us eliminate all costs associated with it. Chris@16: template <> Chris@16: class base_from_connect_condition Chris@16: { Chris@16: protected: Chris@16: explicit base_from_connect_condition(const default_connect_condition&) Chris@16: { Chris@16: } Chris@16: Chris@16: template Chris@16: void check_condition(const boost::system::error_code&, Iterator&, Iterator&) Chris@16: { Chris@16: } Chris@16: }; Chris@16: Chris@16: template Chris@16: class connect_op : base_from_connect_condition Chris@16: { Chris@16: public: Chris@16: connect_op(basic_socket& sock, Chris@16: const Iterator& begin, const Iterator& end, Chris@16: const ConnectCondition& connect_condition, Chris@16: ComposedConnectHandler& handler) Chris@16: : base_from_connect_condition(connect_condition), Chris@16: socket_(sock), Chris@16: iter_(begin), Chris@16: end_(end), Chris@16: start_(0), Chris@16: handler_(BOOST_ASIO_MOVE_CAST(ComposedConnectHandler)(handler)) Chris@16: { Chris@16: } Chris@16: Chris@16: #if defined(BOOST_ASIO_HAS_MOVE) Chris@16: connect_op(const connect_op& other) Chris@16: : base_from_connect_condition(other), Chris@16: socket_(other.socket_), Chris@16: iter_(other.iter_), Chris@16: end_(other.end_), Chris@16: start_(other.start_), Chris@16: handler_(other.handler_) Chris@16: { Chris@16: } Chris@16: Chris@16: connect_op(connect_op&& other) Chris@16: : base_from_connect_condition(other), Chris@16: socket_(other.socket_), Chris@16: iter_(other.iter_), Chris@16: end_(other.end_), Chris@16: start_(other.start_), Chris@16: handler_(BOOST_ASIO_MOVE_CAST(ComposedConnectHandler)(other.handler_)) Chris@16: { Chris@16: } Chris@16: #endif // defined(BOOST_ASIO_HAS_MOVE) Chris@16: Chris@16: void operator()(boost::system::error_code ec, int start = 0) Chris@16: { Chris@16: switch (start_ = start) Chris@16: { Chris@16: case 1: Chris@16: for (;;) Chris@16: { Chris@16: this->check_condition(ec, iter_, end_); Chris@16: Chris@16: if (iter_ != end_) Chris@16: { Chris@16: socket_.close(ec); Chris@16: socket_.async_connect(*iter_, Chris@16: BOOST_ASIO_MOVE_CAST(connect_op)(*this)); Chris@16: return; Chris@16: } Chris@16: Chris@16: if (start) Chris@16: { Chris@16: ec = boost::asio::error::not_found; Chris@16: socket_.get_io_service().post(detail::bind_handler(*this, ec)); Chris@16: return; Chris@16: } Chris@16: Chris@16: default: Chris@16: Chris@16: if (iter_ == end_) Chris@16: break; Chris@16: Chris@16: if (!socket_.is_open()) Chris@16: { Chris@16: ec = boost::asio::error::operation_aborted; Chris@16: break; Chris@16: } Chris@16: Chris@16: if (!ec) Chris@16: break; Chris@16: Chris@16: ++iter_; Chris@16: } Chris@16: Chris@16: handler_(static_cast(ec), Chris@16: static_cast(iter_)); Chris@16: } Chris@16: } Chris@16: Chris@16: //private: Chris@16: basic_socket& socket_; Chris@16: Iterator iter_; Chris@16: Iterator end_; Chris@16: int start_; Chris@16: ComposedConnectHandler handler_; Chris@16: }; Chris@16: Chris@16: template Chris@16: inline void* asio_handler_allocate(std::size_t size, Chris@16: connect_op* this_handler) Chris@16: { Chris@16: return boost_asio_handler_alloc_helpers::allocate( Chris@16: size, this_handler->handler_); Chris@16: } Chris@16: Chris@16: template Chris@16: inline void asio_handler_deallocate(void* pointer, std::size_t size, Chris@16: connect_op* this_handler) Chris@16: { Chris@16: boost_asio_handler_alloc_helpers::deallocate( Chris@16: pointer, size, this_handler->handler_); Chris@16: } Chris@16: Chris@16: template Chris@16: inline bool asio_handler_is_continuation( Chris@16: connect_op* this_handler) Chris@16: { Chris@16: return boost_asio_handler_cont_helpers::is_continuation( Chris@16: this_handler->handler_); Chris@16: } Chris@16: Chris@16: template Chris@16: inline void asio_handler_invoke(Function& function, Chris@16: connect_op* this_handler) Chris@16: { Chris@16: boost_asio_handler_invoke_helpers::invoke( Chris@16: function, this_handler->handler_); Chris@16: } Chris@16: Chris@16: template Chris@16: inline void asio_handler_invoke(const Function& function, Chris@16: connect_op* this_handler) Chris@16: { Chris@16: boost_asio_handler_invoke_helpers::invoke( Chris@16: function, this_handler->handler_); Chris@16: } Chris@16: } // namespace detail Chris@16: Chris@16: template Chris@16: inline BOOST_ASIO_INITFN_RESULT_TYPE(ComposedConnectHandler, Chris@16: void (boost::system::error_code, Iterator)) Chris@16: async_connect(basic_socket& s, Chris@16: Iterator begin, BOOST_ASIO_MOVE_ARG(ComposedConnectHandler) handler) Chris@16: { Chris@16: // If you get an error on the following line it means that your handler does Chris@16: // not meet the documented type requirements for a ComposedConnectHandler. Chris@16: BOOST_ASIO_COMPOSED_CONNECT_HANDLER_CHECK( Chris@16: ComposedConnectHandler, handler, Iterator) type_check; Chris@16: Chris@16: detail::async_result_init init( Chris@16: BOOST_ASIO_MOVE_CAST(ComposedConnectHandler)(handler)); Chris@16: Chris@16: detail::connect_op(s, Chris@16: begin, Iterator(), detail::default_connect_condition(), init.handler)( Chris@16: boost::system::error_code(), 1); Chris@16: Chris@16: return init.result.get(); Chris@16: } Chris@16: Chris@16: template Chris@16: inline BOOST_ASIO_INITFN_RESULT_TYPE(ComposedConnectHandler, Chris@16: void (boost::system::error_code, Iterator)) Chris@16: async_connect(basic_socket& s, Chris@16: Iterator begin, Iterator end, Chris@16: BOOST_ASIO_MOVE_ARG(ComposedConnectHandler) handler) Chris@16: { Chris@16: // If you get an error on the following line it means that your handler does Chris@16: // not meet the documented type requirements for a ComposedConnectHandler. Chris@16: BOOST_ASIO_COMPOSED_CONNECT_HANDLER_CHECK( Chris@16: ComposedConnectHandler, handler, Iterator) type_check; Chris@16: Chris@16: detail::async_result_init init( Chris@16: BOOST_ASIO_MOVE_CAST(ComposedConnectHandler)(handler)); Chris@16: Chris@16: detail::connect_op(s, Chris@16: begin, end, detail::default_connect_condition(), init.handler)( Chris@16: boost::system::error_code(), 1); Chris@16: Chris@16: return init.result.get(); Chris@16: } Chris@16: Chris@16: template Chris@16: inline BOOST_ASIO_INITFN_RESULT_TYPE(ComposedConnectHandler, Chris@16: void (boost::system::error_code, Iterator)) Chris@16: async_connect(basic_socket& s, Chris@16: Iterator begin, ConnectCondition connect_condition, Chris@16: BOOST_ASIO_MOVE_ARG(ComposedConnectHandler) handler) Chris@16: { Chris@16: // If you get an error on the following line it means that your handler does Chris@16: // not meet the documented type requirements for a ComposedConnectHandler. Chris@16: BOOST_ASIO_COMPOSED_CONNECT_HANDLER_CHECK( Chris@16: ComposedConnectHandler, handler, Iterator) type_check; Chris@16: Chris@16: detail::async_result_init init( Chris@16: BOOST_ASIO_MOVE_CAST(ComposedConnectHandler)(handler)); Chris@16: Chris@16: detail::connect_op(s, Chris@16: begin, Iterator(), connect_condition, init.handler)( Chris@16: boost::system::error_code(), 1); Chris@16: Chris@16: return init.result.get(); Chris@16: } Chris@16: Chris@16: template Chris@16: inline BOOST_ASIO_INITFN_RESULT_TYPE(ComposedConnectHandler, Chris@16: void (boost::system::error_code, Iterator)) Chris@16: async_connect(basic_socket& s, Chris@16: Iterator begin, Iterator end, ConnectCondition connect_condition, Chris@16: BOOST_ASIO_MOVE_ARG(ComposedConnectHandler) handler) Chris@16: { Chris@16: // If you get an error on the following line it means that your handler does Chris@16: // not meet the documented type requirements for a ComposedConnectHandler. Chris@16: BOOST_ASIO_COMPOSED_CONNECT_HANDLER_CHECK( Chris@16: ComposedConnectHandler, handler, Iterator) type_check; Chris@16: Chris@16: detail::async_result_init init( Chris@16: BOOST_ASIO_MOVE_CAST(ComposedConnectHandler)(handler)); Chris@16: Chris@16: detail::connect_op(s, Chris@16: begin, end, connect_condition, init.handler)( Chris@16: boost::system::error_code(), 1); Chris@16: Chris@16: return init.result.get(); Chris@16: } Chris@16: Chris@16: } // namespace asio Chris@16: } // namespace boost Chris@16: Chris@16: #include Chris@16: Chris@16: #endif // BOOST_ASIO_IMPL_CONNECT_HPP