Use range-based interface for returning resolver results.
diff --git a/asio/include/asio/connect.hpp b/asio/include/asio/connect.hpp index 14f29b1..6956c36 100644 --- a/asio/include/asio/connect.hpp +++ b/asio/include/asio/connect.hpp
@@ -18,12 +18,43 @@ #include "asio/detail/config.hpp" #include "asio/async_result.hpp" #include "asio/basic_socket.hpp" +#include "asio/detail/type_traits.hpp" #include "asio/error.hpp" #include "asio/detail/push_options.hpp" namespace asio { +namespace detail +{ + char (&has_iterator_helper(...))[2]; + + template <typename T> + char has_iterator_helper(T*, typename T::iterator* = 0); + + template <typename T> + struct has_iterator_typedef + { + enum { value = (sizeof((has_iterator_helper)((T*)(0))) == 1) }; + }; +} // namespace detail + +/// Type trait used to determine whether a type is an endpoint sequence that can +/// be used with with @c connect and @c async_connect. +template <typename T> +struct is_endpoint_sequence +{ +#if defined(GENERATING_DOCUMENTATION) + /// The value member is true if the type may be used as an endpoint sequence. + static const bool value; +#else + enum + { + value = detail::has_iterator_typedef<T>::value + }; +#endif +}; + /** * @defgroup connect asio::connect * @@ -41,6 +72,73 @@ * @param s The socket to be connected. If the socket is already open, it will * be closed. * + * @param endpoints A sequence of endpoints. + * + * @returns The successfully connected endpoint. + * + * @throws asio::system_error Thrown on failure. If the sequence is + * empty, the associated @c error_code is asio::error::not_found. + * Otherwise, contains the error from the last connection attempt. + * + * @par Example + * @code tcp::resolver r(io_service); + * tcp::resolver::query q("host", "service"); + * tcp::socket s(io_service); + * asio::connect(s, r.resolve(q)); @endcode + */ +template <typename Protocol, typename SocketService, typename EndpointSequence> +typename Protocol::endpoint connect(basic_socket<Protocol, SocketService>& s, + const EndpointSequence& endpoints, + typename enable_if<is_endpoint_sequence< + EndpointSequence>::value>::type* = 0); + +/// Establishes a socket connection by trying each endpoint in a sequence. +/** + * This function attempts to connect a socket to one of a sequence of + * endpoints. It does this by repeated calls to the socket's @c connect member + * function, once for each endpoint in the sequence, until a connection is + * successfully established. + * + * @param s The socket to be connected. If the socket is already open, it will + * be closed. + * + * @param endpoints A sequence of endpoints. + * + * @param ec Set to indicate what error occurred, if any. If the sequence is + * empty, set to asio::error::not_found. Otherwise, contains the error + * from the last connection attempt. + * + * @returns On success, the successfully connected endpoint. Otherwise, a + * default-constructed endpoint. + * + * @par Example + * @code tcp::resolver r(io_service); + * tcp::resolver::query q("host", "service"); + * tcp::socket s(io_service); + * asio::error_code ec; + * asio::connect(s, r.resolve(q), ec); + * if (ec) + * { + * // An error occurred. + * } @endcode + */ +template <typename Protocol, typename SocketService, typename EndpointSequence> +typename Protocol::endpoint connect(basic_socket<Protocol, SocketService>& s, + const EndpointSequence& endpoints, asio::error_code& ec, + typename enable_if<is_endpoint_sequence< + EndpointSequence>::value>::type* = 0); + +/// (Deprecated.) Establishes a socket connection by trying each endpoint in a +/// sequence. +/** + * This function attempts to connect a socket to one of a sequence of + * endpoints. It does this by repeated calls to the socket's @c connect member + * function, once for each endpoint in the sequence, until a connection is + * successfully established. + * + * @param s The socket to be connected. If the socket is already open, it will + * be closed. + * * @param begin An iterator pointing to the start of a sequence of endpoints. * * @returns On success, an iterator denoting the successfully connected @@ -53,17 +151,13 @@ * @note This overload assumes that a default constructed object of type @c * Iterator represents the end of the sequence. This is a valid assumption for * iterator types such as @c asio::ip::tcp::resolver::iterator. - * - * @par Example - * @code tcp::resolver r(io_service); - * tcp::resolver::query q("host", "service"); - * tcp::socket s(io_service); - * asio::connect(s, r.resolve(q)); @endcode */ template <typename Protocol, typename SocketService, typename Iterator> -Iterator connect(basic_socket<Protocol, SocketService>& s, Iterator begin); +Iterator connect(basic_socket<Protocol, SocketService>& s, Iterator begin, + typename enable_if<!is_endpoint_sequence<Iterator>::value>::type* = 0); -/// Establishes a socket connection by trying each endpoint in a sequence. +/// (Deprecated.) Establishes a socket connection by trying each endpoint in a +/// sequence. /** * This function attempts to connect a socket to one of a sequence of * endpoints. It does this by repeated calls to the socket's @c connect member @@ -85,21 +179,11 @@ * @note This overload assumes that a default constructed object of type @c * Iterator represents the end of the sequence. This is a valid assumption for * iterator types such as @c asio::ip::tcp::resolver::iterator. - * - * @par Example - * @code tcp::resolver r(io_service); - * tcp::resolver::query q("host", "service"); - * tcp::socket s(io_service); - * asio::error_code ec; - * asio::connect(s, r.resolve(q), ec); - * if (ec) - * { - * // An error occurred. - * } @endcode */ template <typename Protocol, typename SocketService, typename Iterator> Iterator connect(basic_socket<Protocol, SocketService>& s, - Iterator begin, asio::error_code& ec); + Iterator begin, asio::error_code& ec, + typename enable_if<!is_endpoint_sequence<Iterator>::value>::type* = 0); /// Establishes a socket connection by trying each endpoint in a sequence. /** @@ -115,8 +199,7 @@ * * @param end An iterator pointing to the end of a sequence of endpoints. * - * @returns On success, an iterator denoting the successfully connected - * endpoint. Otherwise, the end iterator. + * @returns An iterator denoting the successfully connected endpoint. * * @throws asio::system_error Thrown on failure. If the sequence is * empty, the associated @c error_code is asio::error::not_found. @@ -125,9 +208,9 @@ * @par Example * @code tcp::resolver r(io_service); * tcp::resolver::query q("host", "service"); - * tcp::resolver::iterator i = r.resolve(q), end; + * tcp::resolver::results_type e = r.resolve(q); * tcp::socket s(io_service); - * asio::connect(s, i, end); @endcode + * asio::connect(s, e.begin(), e.end()); @endcode */ template <typename Protocol, typename SocketService, typename Iterator> Iterator connect(basic_socket<Protocol, SocketService>& s, @@ -157,10 +240,10 @@ * @par Example * @code tcp::resolver r(io_service); * tcp::resolver::query q("host", "service"); - * tcp::resolver::iterator i = r.resolve(q), end; + * tcp::resolver::results_type e = r.resolve(q); * tcp::socket s(io_service); * asio::error_code ec; - * asio::connect(s, i, end, ec); + * asio::connect(s, e.begin(), e.end(), ec); * if (ec) * { * // An error occurred. @@ -180,59 +263,53 @@ * @param s The socket to be connected. If the socket is already open, it will * be closed. * - * @param begin An iterator pointing to the start of a sequence of endpoints. + * @param endpoints A sequence of endpoints. * * @param connect_condition A function object that is called prior to each * connection attempt. The signature of the function object must be: - * @code Iterator connect_condition( + * @code bool connect_condition( * const asio::error_code& ec, - * Iterator next); @endcode + * const typename Protocol::endpoint& next); @endcode * The @c ec parameter contains the result from the most recent connect * operation. Before the first connection attempt, @c ec is always set to - * indicate success. The @c next parameter is an iterator pointing to the next - * endpoint to be tried. The function object should return the next iterator, - * but is permitted to return a different iterator so that endpoints may be - * skipped. The implementation guarantees that the function object will never - * be called with the end iterator. + * indicate success. The @c next parameter is the next endpoint to be tried. + * The function object should return true if the next endpoint should be tried, + * and false if it should be skipped. * - * @returns On success, an iterator denoting the successfully connected - * endpoint. Otherwise, the end iterator. + * @returns The successfully connected endpoint. * * @throws asio::system_error Thrown on failure. If the sequence is * empty, the associated @c error_code is asio::error::not_found. * Otherwise, contains the error from the last connection attempt. * - * @note This overload assumes that a default constructed object of type @c - * Iterator represents the end of the sequence. This is a valid assumption for - * iterator types such as @c asio::ip::tcp::resolver::iterator. - * * @par Example * The following connect condition function object can be used to output * information about the individual connection attempts: * @code struct my_connect_condition * { - * template <typename Iterator> - * Iterator operator()( + * bool operator()( * const asio::error_code& ec, - * Iterator next) + * const::tcp::endpoint& next) * { * if (ec) std::cout << "Error: " << ec.message() << std::endl; - * std::cout << "Trying: " << next->endpoint() << std::endl; - * return next; + * std::cout << "Trying: " << next << std::endl; + * return true; * } * }; @endcode * It would be used with the asio::connect function as follows: * @code tcp::resolver r(io_service); * tcp::resolver::query q("host", "service"); * tcp::socket s(io_service); - * tcp::resolver::iterator i = asio::connect( - * s, r.resolve(q), my_connect_condition()); - * std::cout << "Connected to: " << i->endpoint() << std::endl; @endcode + * tcp::endpoint e = asio::connect(s, + * r.resolve(q), my_connect_condition()); + * std::cout << "Connected to: " << e << std::endl; @endcode */ template <typename Protocol, typename SocketService, - typename Iterator, typename ConnectCondition> -Iterator connect(basic_socket<Protocol, SocketService>& s, - Iterator begin, ConnectCondition connect_condition); + typename EndpointSequence, typename ConnectCondition> +typename Protocol::endpoint connect(basic_socket<Protocol, SocketService>& s, + const EndpointSequence& endpoints, ConnectCondition connect_condition, + typename enable_if<is_endpoint_sequence< + EndpointSequence>::value>::type* = 0); /// Establishes a socket connection by trying each endpoint in a sequence. /** @@ -244,20 +321,128 @@ * @param s The socket to be connected. If the socket is already open, it will * be closed. * + * @param endpoints A sequence of endpoints. + * + * @param connect_condition A function object that is called prior to each + * connection attempt. The signature of the function object must be: + * @code bool connect_condition( + * const asio::error_code& ec, + * const typename Protocol::endpoint& next); @endcode + * The @c ec parameter contains the result from the most recent connect + * operation. Before the first connection attempt, @c ec is always set to + * indicate success. The @c next parameter is the next endpoint to be tried. + * The function object should return true if the next endpoint should be tried, + * and false if it should be skipped. + * + * @param ec Set to indicate what error occurred, if any. If the sequence is + * empty, set to asio::error::not_found. Otherwise, contains the error + * from the last connection attempt. + * + * @returns On success, the successfully connected endpoint. Otherwise, a + * default-constructed endpoint. + * + * @par Example + * The following connect condition function object can be used to output + * information about the individual connection attempts: + * @code struct my_connect_condition + * { + * bool operator()( + * const asio::error_code& ec, + * const::tcp::endpoint& next) + * { + * if (ec) std::cout << "Error: " << ec.message() << std::endl; + * std::cout << "Trying: " << next << std::endl; + * return true; + * } + * }; @endcode + * It would be used with the asio::connect function as follows: + * @code tcp::resolver r(io_service); + * tcp::resolver::query q("host", "service"); + * tcp::socket s(io_service); + * asio::error_code ec; + * tcp::endpoint e = asio::connect(s, + * r.resolve(q), my_connect_condition(), ec); + * if (ec) + * { + * // An error occurred. + * } + * else + * { + * std::cout << "Connected to: " << e << std::endl; + * } @endcode + */ +template <typename Protocol, typename SocketService, + typename EndpointSequence, typename ConnectCondition> +typename Protocol::endpoint connect(basic_socket<Protocol, SocketService>& s, + const EndpointSequence& endpoints, ConnectCondition connect_condition, + asio::error_code& ec, + typename enable_if<is_endpoint_sequence< + EndpointSequence>::value>::type* = 0); + +/// (Deprecated.) Establishes a socket connection by trying each endpoint in a +/// sequence. +/** + * This function attempts to connect a socket to one of a sequence of + * endpoints. It does this by repeated calls to the socket's @c connect member + * function, once for each endpoint in the sequence, until a connection is + * successfully established. + * + * @param s The socket to be connected. If the socket is already open, it will + * be closed. + * * @param begin An iterator pointing to the start of a sequence of endpoints. * * @param connect_condition A function object that is called prior to each * connection attempt. The signature of the function object must be: - * @code Iterator connect_condition( + * @code bool connect_condition( * const asio::error_code& ec, - * Iterator next); @endcode + * const typename Protocol::endpoint& next); @endcode * The @c ec parameter contains the result from the most recent connect * operation. Before the first connection attempt, @c ec is always set to - * indicate success. The @c next parameter is an iterator pointing to the next - * endpoint to be tried. The function object should return the next iterator, - * but is permitted to return a different iterator so that endpoints may be - * skipped. The implementation guarantees that the function object will never - * be called with the end iterator. + * indicate success. The @c next parameter is the next endpoint to be tried. + * The function object should return true if the next endpoint should be tried, + * and false if it should be skipped. + * + * @returns On success, an iterator denoting the successfully connected + * endpoint. Otherwise, the end iterator. + * + * @throws asio::system_error Thrown on failure. If the sequence is + * empty, the associated @c error_code is asio::error::not_found. + * Otherwise, contains the error from the last connection attempt. + * + * @note This overload assumes that a default constructed object of type @c + * Iterator represents the end of the sequence. This is a valid assumption for + * iterator types such as @c asio::ip::tcp::resolver::iterator. + */ +template <typename Protocol, typename SocketService, + typename Iterator, typename ConnectCondition> +Iterator connect(basic_socket<Protocol, SocketService>& s, + Iterator begin, ConnectCondition connect_condition, + typename enable_if<!is_endpoint_sequence<Iterator>::value>::type* = 0); + +/// (Deprecated.) Establishes a socket connection by trying each endpoint in a +/// sequence. +/** + * This function attempts to connect a socket to one of a sequence of + * endpoints. It does this by repeated calls to the socket's @c connect member + * function, once for each endpoint in the sequence, until a connection is + * successfully established. + * + * @param s The socket to be connected. If the socket is already open, it will + * be closed. + * + * @param begin An iterator pointing to the start of a sequence of endpoints. + * + * @param connect_condition A function object that is called prior to each + * connection attempt. The signature of the function object must be: + * @code bool connect_condition( + * const asio::error_code& ec, + * const typename Protocol::endpoint& next); @endcode + * The @c ec parameter contains the result from the most recent connect + * operation. Before the first connection attempt, @c ec is always set to + * indicate success. The @c next parameter is the next endpoint to be tried. + * The function object should return true if the next endpoint should be tried, + * and false if it should be skipped. * * @param ec Set to indicate what error occurred, if any. If the sequence is * empty, set to asio::error::not_found. Otherwise, contains the error @@ -269,42 +454,12 @@ * @note This overload assumes that a default constructed object of type @c * Iterator represents the end of the sequence. This is a valid assumption for * iterator types such as @c asio::ip::tcp::resolver::iterator. - * - * @par Example - * The following connect condition function object can be used to output - * information about the individual connection attempts: - * @code struct my_connect_condition - * { - * template <typename Iterator> - * Iterator operator()( - * const asio::error_code& ec, - * Iterator next) - * { - * if (ec) std::cout << "Error: " << ec.message() << std::endl; - * std::cout << "Trying: " << next->endpoint() << std::endl; - * return next; - * } - * }; @endcode - * It would be used with the asio::connect function as follows: - * @code tcp::resolver r(io_service); - * tcp::resolver::query q("host", "service"); - * tcp::socket s(io_service); - * asio::error_code ec; - * tcp::resolver::iterator i = asio::connect( - * s, r.resolve(q), my_connect_condition(), ec); - * if (ec) - * { - * // An error occurred. - * } - * else - * { - * std::cout << "Connected to: " << i->endpoint() << std::endl; - * } @endcode */ template <typename Protocol, typename SocketService, typename Iterator, typename ConnectCondition> Iterator connect(basic_socket<Protocol, SocketService>& s, Iterator begin, - ConnectCondition connect_condition, asio::error_code& ec); + ConnectCondition connect_condition, asio::error_code& ec, + typename enable_if<!is_endpoint_sequence<Iterator>::value>::type* = 0); /// Establishes a socket connection by trying each endpoint in a sequence. /** @@ -322,19 +477,16 @@ * * @param connect_condition A function object that is called prior to each * connection attempt. The signature of the function object must be: - * @code Iterator connect_condition( + * @code bool connect_condition( * const asio::error_code& ec, - * Iterator next); @endcode + * const typename Protocol::endpoint& next); @endcode * The @c ec parameter contains the result from the most recent connect * operation. Before the first connection attempt, @c ec is always set to - * indicate success. The @c next parameter is an iterator pointing to the next - * endpoint to be tried. The function object should return the next iterator, - * but is permitted to return a different iterator so that endpoints may be - * skipped. The implementation guarantees that the function object will never - * be called with the end iterator. + * indicate success. The @c next parameter is the next endpoint to be tried. + * The function object should return true if the next endpoint should be tried, + * and false if it should be skipped. * - * @returns On success, an iterator denoting the successfully connected - * endpoint. Otherwise, the end iterator. + * @returns An iterator denoting the successfully connected endpoint. * * @throws asio::system_error Thrown on failure. If the sequence is * empty, the associated @c error_code is asio::error::not_found. @@ -345,22 +497,22 @@ * information about the individual connection attempts: * @code struct my_connect_condition * { - * template <typename Iterator> - * Iterator operator()( + * bool operator()( * const asio::error_code& ec, - * Iterator next) + * const::tcp::endpoint& next) * { * if (ec) std::cout << "Error: " << ec.message() << std::endl; - * std::cout << "Trying: " << next->endpoint() << std::endl; - * return next; + * std::cout << "Trying: " << next << std::endl; + * return true; * } * }; @endcode * It would be used with the asio::connect function as follows: * @code tcp::resolver r(io_service); * tcp::resolver::query q("host", "service"); - * tcp::resolver::iterator i = r.resolve(q), end; + * tcp::resolver::results_type e = r.resolve(q); * tcp::socket s(io_service); - * i = asio::connect(s, i, end, my_connect_condition()); + * tcp::resolver::results_type::iterator i = asio::connect( + * s, e.begin(), e.end(), my_connect_condition()); * std::cout << "Connected to: " << i->endpoint() << std::endl; @endcode */ template <typename Protocol, typename SocketService, @@ -384,16 +536,14 @@ * * @param connect_condition A function object that is called prior to each * connection attempt. The signature of the function object must be: - * @code Iterator connect_condition( + * @code bool connect_condition( * const asio::error_code& ec, - * Iterator next); @endcode + * const typename Protocol::endpoint& next); @endcode * The @c ec parameter contains the result from the most recent connect * operation. Before the first connection attempt, @c ec is always set to - * indicate success. The @c next parameter is an iterator pointing to the next - * endpoint to be tried. The function object should return the next iterator, - * but is permitted to return a different iterator so that endpoints may be - * skipped. The implementation guarantees that the function object will never - * be called with the end iterator. + * indicate success. The @c next parameter is the next endpoint to be tried. + * The function object should return true if the next endpoint should be tried, + * and false if it should be skipped. * * @param ec Set to indicate what error occurred, if any. If the sequence is * empty, set to asio::error::not_found. Otherwise, contains the error @@ -407,23 +557,23 @@ * information about the individual connection attempts: * @code struct my_connect_condition * { - * template <typename Iterator> - * Iterator operator()( + * bool operator()( * const asio::error_code& ec, - * Iterator next) + * const::tcp::endpoint& next) * { * if (ec) std::cout << "Error: " << ec.message() << std::endl; - * std::cout << "Trying: " << next->endpoint() << std::endl; - * return next; + * std::cout << "Trying: " << next << std::endl; + * return true; * } * }; @endcode * It would be used with the asio::connect function as follows: * @code tcp::resolver r(io_service); * tcp::resolver::query q("host", "service"); - * tcp::resolver::iterator i = r.resolve(q), end; + * tcp::resolver::results_type e = r.resolve(q); * tcp::socket s(io_service); * asio::error_code ec; - * i = asio::connect(s, i, end, my_connect_condition(), ec); + * tcp::resolver::results_type::iterator i = asio::connect( + * s, e.begin(), e.end(), my_connect_condition()); * if (ec) * { * // An error occurred. @@ -460,6 +610,77 @@ * @param s The socket to be connected. If the socket is already open, it will * be closed. * + * @param endpoints A sequence of endpoints. + * + * @param handler The handler to be called when the connect operation + * completes. Copies will be made of the handler as required. The function + * signature of the handler must be: + * @code void handler( + * // Result of operation. if the sequence is empty, set to + * // asio::error::not_found. Otherwise, contains the + * // error from the last connection attempt. + * const asio::error_code& error, + * + * // On success, the successfully connected endpoint. + * // Otherwise, a default-constructed endpoint. + * const typename Protocol::endpoint& endpoint + * ); @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 + * asio::io_service::post(). + * + * @par Example + * @code tcp::resolver r(io_service); + * tcp::resolver::query q("host", "service"); + * tcp::socket s(io_service); + * + * // ... + * + * r.async_resolve(q, resolve_handler); + * + * // ... + * + * void resolve_handler( + * const asio::error_code& ec, + * tcp::resolver::results_type results) + * { + * if (!ec) + * { + * asio::async_connect(s, results, connect_handler); + * } + * } + * + * // ... + * + * void connect_handler( + * const asio::error_code& ec, + * const tcp::endpoint& endpoint) + * { + * // ... + * } @endcode + */ +template <typename Protocol, typename SocketService, + typename EndpointSequence, typename RangeConnectHandler> +ASIO_INITFN_RESULT_TYPE(RangeConnectHandler, + void (asio::error_code, typename Protocol::endpoint)) +async_connect(basic_socket<Protocol, SocketService>& s, + const EndpointSequence& endpoints, + ASIO_MOVE_ARG(RangeConnectHandler) handler, + typename enable_if<is_endpoint_sequence< + EndpointSequence>::value>::type* = 0); + +/// (Deprecated.) Asynchronously establishes a socket connection by trying each +/// endpoint in a sequence. +/** + * This function attempts to connect a socket to one of a sequence of + * endpoints. It does this by repeated calls to the socket's @c async_connect + * member function, once for each endpoint in the sequence, until a connection + * is successfully established. + * + * @param s The socket to be connected. If the socket is already open, it will + * be closed. + * * @param begin An iterator pointing to the start of a sequence of endpoints. * * @param handler The handler to be called when the connect operation @@ -483,43 +704,14 @@ * @note This overload assumes that a default constructed object of type @c * Iterator represents the end of the sequence. This is a valid assumption for * iterator types such as @c asio::ip::tcp::resolver::iterator. - * - * @par Example - * @code tcp::resolver r(io_service); - * tcp::resolver::query q("host", "service"); - * tcp::socket s(io_service); - * - * // ... - * - * r.async_resolve(q, resolve_handler); - * - * // ... - * - * void resolve_handler( - * const asio::error_code& ec, - * tcp::resolver::iterator i) - * { - * if (!ec) - * { - * asio::async_connect(s, i, connect_handler); - * } - * } - * - * // ... - * - * void connect_handler( - * const asio::error_code& ec, - * tcp::resolver::iterator i) - * { - * // ... - * } @endcode */ template <typename Protocol, typename SocketService, - typename Iterator, typename ComposedConnectHandler> -ASIO_INITFN_RESULT_TYPE(ComposedConnectHandler, + typename Iterator, typename IteratorConnectHandler> +ASIO_INITFN_RESULT_TYPE(IteratorConnectHandler, void (asio::error_code, Iterator)) async_connect(basic_socket<Protocol, SocketService>& s, - Iterator begin, ASIO_MOVE_ARG(ComposedConnectHandler) handler); + Iterator begin, ASIO_MOVE_ARG(IteratorConnectHandler) handler, + typename enable_if<!is_endpoint_sequence<Iterator>::value>::type* = 0); /// Asynchronously establishes a socket connection by trying each endpoint in a /// sequence. @@ -555,43 +747,28 @@ * asio::io_service::post(). * * @par Example - * @code tcp::resolver r(io_service); - * tcp::resolver::query q("host", "service"); + * @code std::vector<tcp::endpoint> endpoints = ...; * tcp::socket s(io_service); - * - * // ... - * - * r.async_resolve(q, resolve_handler); - * - * // ... - * - * void resolve_handler( - * const asio::error_code& ec, - * tcp::resolver::iterator i) - * { - * if (!ec) - * { - * tcp::resolver::iterator end; - * asio::async_connect(s, i, end, connect_handler); - * } - * } + * asio::async_connect(s, + * endpoints.begin(), endpoints.end(), + * connect_handler); * * // ... * * void connect_handler( * const asio::error_code& ec, - * tcp::resolver::iterator i) + * std::vector<tcp::endpoint>::iterator i) * { * // ... * } @endcode */ template <typename Protocol, typename SocketService, - typename Iterator, typename ComposedConnectHandler> -ASIO_INITFN_RESULT_TYPE(ComposedConnectHandler, + typename Iterator, typename IteratorConnectHandler> +ASIO_INITFN_RESULT_TYPE(IteratorConnectHandler, void (asio::error_code, Iterator)) async_connect(basic_socket<Protocol, SocketService>& s, Iterator begin, Iterator end, - ASIO_MOVE_ARG(ComposedConnectHandler) handler); + ASIO_MOVE_ARG(IteratorConnectHandler) handler); /// Asynchronously establishes a socket connection by trying each endpoint in a /// sequence. @@ -604,20 +781,18 @@ * @param s The socket to be connected. If the socket is already open, it will * be closed. * - * @param begin An iterator pointing to the start of a sequence of endpoints. + * @param endpoints A sequence of endpoints. * * @param connect_condition A function object that is called prior to each * connection attempt. The signature of the function object must be: - * @code Iterator connect_condition( + * @code bool connect_condition( * const asio::error_code& ec, - * Iterator next); @endcode + * const typename Protocol::endpoint& next); @endcode * The @c ec parameter contains the result from the most recent connect * operation. Before the first connection attempt, @c ec is always set to - * indicate success. The @c next parameter is an iterator pointing to the next - * endpoint to be tried. The function object should return the next iterator, - * but is permitted to return a different iterator so that endpoints may be - * skipped. The implementation guarantees that the function object will never - * be called with the end iterator. + * indicate success. The @c next parameter is the next endpoint to be tried. + * The function object should return true if the next endpoint should be tried, + * and false if it should be skipped. * * @param handler The handler to be called when the connect operation * completes. Copies will be made of the handler as required. The function @@ -637,23 +812,18 @@ * of the handler will be performed in a manner equivalent to using * asio::io_service::post(). * - * @note This overload assumes that a default constructed object of type @c - * Iterator represents the end of the sequence. This is a valid assumption for - * iterator types such as @c asio::ip::tcp::resolver::iterator. - * * @par Example * The following connect condition function object can be used to output * information about the individual connection attempts: * @code struct my_connect_condition * { - * template <typename Iterator> - * Iterator operator()( + * bool operator()( * const asio::error_code& ec, - * Iterator next) + * const::tcp::endpoint& next) * { * if (ec) std::cout << "Error: " << ec.message() << std::endl; - * std::cout << "Trying: " << next->endpoint() << std::endl; - * return next; + * std::cout << "Trying: " << next << std::endl; + * return true; * } * }; @endcode * It would be used with the asio::connect function as follows: @@ -669,11 +839,11 @@ * * void resolve_handler( * const asio::error_code& ec, - * tcp::resolver::iterator i) + * tcp::resolver::results_type results) * { * if (!ec) * { - * asio::async_connect(s, i, + * asio::async_connect(s, results, * my_connect_condition(), * connect_handler); * } @@ -683,7 +853,7 @@ * * void connect_handler( * const asio::error_code& ec, - * tcp::resolver::iterator i) + * const tcp::endpoint& endpoint) * { * if (ec) * { @@ -691,17 +861,74 @@ * } * else * { - * std::cout << "Connected to: " << i->endpoint() << std::endl; + * std::cout << "Connected to: " << endpoint << std::endl; * } * } @endcode */ +template <typename Protocol, typename SocketService, typename EndpointSequence, + typename ConnectCondition, typename RangeConnectHandler> +ASIO_INITFN_RESULT_TYPE(RangeConnectHandler, + void (asio::error_code, typename Protocol::endpoint)) +async_connect(basic_socket<Protocol, SocketService>& s, + const EndpointSequence& endpoints, ConnectCondition connect_condition, + ASIO_MOVE_ARG(RangeConnectHandler) handler, + typename enable_if<is_endpoint_sequence< + EndpointSequence>::value>::type* = 0); + +/// (Deprecated.) Asynchronously establishes a socket connection by trying each +/// endpoint in a sequence. +/** + * This function attempts to connect a socket to one of a sequence of + * endpoints. It does this by repeated calls to the socket's @c async_connect + * member function, once for each endpoint in the sequence, until a connection + * is successfully established. + * + * @param s The socket to be connected. If the socket is already open, it will + * be closed. + * + * @param begin An iterator pointing to the start of a sequence of endpoints. + * + * @param connect_condition A function object that is called prior to each + * connection attempt. The signature of the function object must be: + * @code bool connect_condition( + * const asio::error_code& ec, + * const typename Protocol::endpoint& next); @endcode + * The @c ec parameter contains the result from the most recent connect + * operation. Before the first connection attempt, @c ec is always set to + * indicate success. The @c next parameter is the next endpoint to be tried. + * The function object should return true if the next endpoint should be tried, + * and false if it should be skipped. + * + * @param handler The handler to be called when the connect operation + * completes. Copies will be made of the handler as required. The function + * signature of the handler must be: + * @code void handler( + * // Result of operation. if the sequence is empty, set to + * // asio::error::not_found. Otherwise, contains the + * // error from the last connection attempt. + * const asio::error_code& error, + * + * // On success, an iterator denoting the successfully + * // connected endpoint. Otherwise, the end iterator. + * Iterator iterator + * ); @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 + * asio::io_service::post(). + * + * @note This overload assumes that a default constructed object of type @c + * Iterator represents the end of the sequence. This is a valid assumption for + * iterator types such as @c asio::ip::tcp::resolver::iterator. + */ template <typename Protocol, typename SocketService, typename Iterator, - typename ConnectCondition, typename ComposedConnectHandler> -ASIO_INITFN_RESULT_TYPE(ComposedConnectHandler, + typename ConnectCondition, typename IteratorConnectHandler> +ASIO_INITFN_RESULT_TYPE(IteratorConnectHandler, void (asio::error_code, Iterator)) async_connect(basic_socket<Protocol, SocketService>& s, Iterator begin, ConnectCondition connect_condition, - ASIO_MOVE_ARG(ComposedConnectHandler) handler); + ASIO_MOVE_ARG(IteratorConnectHandler) handler, + typename enable_if<!is_endpoint_sequence<Iterator>::value>::type* = 0); /// Asynchronously establishes a socket connection by trying each endpoint in a /// sequence. @@ -720,16 +947,14 @@ * * @param connect_condition A function object that is called prior to each * connection attempt. The signature of the function object must be: - * @code Iterator connect_condition( + * @code bool connect_condition( * const asio::error_code& ec, - * Iterator next); @endcode + * const typename Protocol::endpoint& next); @endcode * The @c ec parameter contains the result from the most recent connect * operation. Before the first connection attempt, @c ec is always set to - * indicate success. The @c next parameter is an iterator pointing to the next - * endpoint to be tried. The function object should return the next iterator, - * but is permitted to return a different iterator so that endpoints may be - * skipped. The implementation guarantees that the function object will never - * be called with the end iterator. + * indicate success. The @c next parameter is the next endpoint to be tried. + * The function object should return true if the next endpoint should be tried, + * and false if it should be skipped. * * @param handler The handler to be called when the connect operation * completes. Copies will be made of the handler as required. The function @@ -754,14 +979,13 @@ * information about the individual connection attempts: * @code struct my_connect_condition * { - * template <typename Iterator> - * Iterator operator()( + * bool operator()( * const asio::error_code& ec, - * Iterator next) + * const::tcp::endpoint& next) * { * if (ec) std::cout << "Error: " << ec.message() << std::endl; - * std::cout << "Trying: " << next->endpoint() << std::endl; - * return next; + * std::cout << "Trying: " << next << std::endl; + * return true; * } * }; @endcode * It would be used with the asio::connect function as follows: @@ -805,12 +1029,12 @@ * } @endcode */ template <typename Protocol, typename SocketService, typename Iterator, - typename ConnectCondition, typename ComposedConnectHandler> -ASIO_INITFN_RESULT_TYPE(ComposedConnectHandler, + typename ConnectCondition, typename IteratorConnectHandler> +ASIO_INITFN_RESULT_TYPE(IteratorConnectHandler, void (asio::error_code, Iterator)) async_connect(basic_socket<Protocol, SocketService>& s, Iterator begin, Iterator end, ConnectCondition connect_condition, - ASIO_MOVE_ARG(ComposedConnectHandler) handler); + ASIO_MOVE_ARG(IteratorConnectHandler) handler); /*@}*/
diff --git a/asio/include/asio/detail/handler_type_requirements.hpp b/asio/include/asio/detail/handler_type_requirements.hpp index e62596f..64b80a1 100644 --- a/asio/include/asio/detail/handler_type_requirements.hpp +++ b/asio/include/asio/detail/handler_type_requirements.hpp
@@ -290,7 +290,34 @@ asio::detail::lvref<const asio::error_code>()), \ char(0))> ASIO_UNUSED_TYPEDEF -#define ASIO_COMPOSED_CONNECT_HANDLER_CHECK( \ +#define ASIO_RANGE_CONNECT_HANDLER_CHECK( \ + handler_type, handler, endpoint_type) \ + \ + typedef ASIO_HANDLER_TYPE(handler_type, \ + void(asio::error_code, endpoint_type)) \ + asio_true_handler_type; \ + \ + ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \ + sizeof(asio::detail::two_arg_handler_test( \ + asio::detail::rvref< \ + asio_true_handler_type>(), \ + static_cast<const asio::error_code*>(0), \ + static_cast<const endpoint_type*>(0))) == 1, \ + "RangeConnectHandler type requirements not met") \ + \ + typedef asio::detail::handler_type_requirements< \ + sizeof( \ + asio::detail::argbyv( \ + asio::detail::rvref< \ + asio_true_handler_type>())) + \ + sizeof( \ + asio::detail::lvref< \ + asio_true_handler_type>()( \ + asio::detail::lvref<const asio::error_code>(), \ + asio::detail::lvref<const endpoint_type>()), \ + char(0))> ASIO_UNUSED_TYPEDEF + +#define ASIO_ITERATOR_CONNECT_HANDLER_CHECK( \ handler_type, handler, iter_type) \ \ typedef ASIO_HANDLER_TYPE(handler_type, \ @@ -303,7 +330,7 @@ asio_true_handler_type>(), \ static_cast<const asio::error_code*>(0), \ static_cast<const iter_type*>(0))) == 1, \ - "ComposedConnectHandler type requirements not met") \ + "IteratorConnectHandler type requirements not met") \ \ typedef asio::detail::handler_type_requirements< \ sizeof( \ @@ -318,10 +345,10 @@ char(0))> ASIO_UNUSED_TYPEDEF #define ASIO_RESOLVE_HANDLER_CHECK( \ - handler_type, handler, iter_type) \ + handler_type, handler, range_type) \ \ typedef ASIO_HANDLER_TYPE(handler_type, \ - void(asio::error_code, iter_type)) \ + void(asio::error_code, range_type)) \ asio_true_handler_type; \ \ ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \ @@ -329,7 +356,7 @@ asio::detail::rvref< \ asio_true_handler_type>(), \ static_cast<const asio::error_code*>(0), \ - static_cast<const iter_type*>(0))) == 1, \ + static_cast<const range_type*>(0))) == 1, \ "ResolveHandler type requirements not met") \ \ typedef asio::detail::handler_type_requirements< \ @@ -341,7 +368,7 @@ asio::detail::lvref< \ asio_true_handler_type>()( \ asio::detail::lvref<const asio::error_code>(), \ - asio::detail::lvref<const iter_type>()), \ + asio::detail::lvref<const range_type>()), \ char(0))> ASIO_UNUSED_TYPEDEF #define ASIO_WAIT_HANDLER_CHECK( \ @@ -495,7 +522,11 @@ handler_type, handler) \ typedef int ASIO_UNUSED_TYPEDEF -#define ASIO_COMPOSED_CONNECT_HANDLER_CHECK( \ +#define ASIO_RANGE_CONNECT_HANDLER_CHECK( \ + handler_type, handler, iter_type) \ + typedef int ASIO_UNUSED_TYPEDEF + +#define ASIO_ITERATOR_CONNECT_HANDLER_CHECK( \ handler_type, handler, iter_type) \ typedef int ASIO_UNUSED_TYPEDEF
diff --git a/asio/include/asio/detail/resolve_endpoint_op.hpp b/asio/include/asio/detail/resolve_endpoint_op.hpp index bb8324a..b09c65a 100644 --- a/asio/include/asio/detail/resolve_endpoint_op.hpp +++ b/asio/include/asio/detail/resolve_endpoint_op.hpp
@@ -18,7 +18,7 @@ #include "asio/detail/config.hpp" #include "asio/error.hpp" #include "asio/io_service.hpp" -#include "asio/ip/basic_resolver_iterator.hpp" +#include "asio/ip/basic_resolver_results.hpp" #include "asio/detail/bind_handler.hpp" #include "asio/detail/fenced_block.hpp" #include "asio/detail/handler_alloc_helpers.hpp" @@ -39,7 +39,7 @@ ASIO_DEFINE_HANDLER_PTR(resolve_endpoint_op); typedef typename Protocol::endpoint endpoint_type; - typedef asio::ip::basic_resolver_iterator<Protocol> iterator_type; + typedef asio::ip::basic_resolver_results<Protocol> results_type; resolve_endpoint_op(socket_ops::weak_cancel_token_type cancel_token, const endpoint_type& endpoint, io_service_impl& ios, Handler& handler) @@ -72,7 +72,7 @@ socket_ops::background_getnameinfo(o->cancel_token_, o->endpoint_.data(), o->endpoint_.size(), host_name, NI_MAXHOST, service_name, NI_MAXSERV, o->endpoint_.protocol().type(), o->ec_); - o->iter_ = iterator_type::create(o->endpoint_, host_name, service_name); + o->results_ = results_type::create(o->endpoint_, host_name, service_name); // Pass operation back to main io_service for completion. o->io_service_impl_.post_deferred_completion(o); @@ -91,8 +91,8 @@ // associated with the handler. Consequently, a local copy of the handler // is required to ensure that any owning sub-object remains valid until // after we have deallocated the memory here. - detail::binder2<Handler, asio::error_code, iterator_type> - handler(o->handler_, o->ec_, o->iter_); + detail::binder2<Handler, asio::error_code, results_type> + handler(o->handler_, o->ec_, o->results_); p.h = asio::detail::addressof(handler.handler_); p.reset(); @@ -112,7 +112,7 @@ io_service_impl& io_service_impl_; Handler handler_; asio::error_code ec_; - iterator_type iter_; + results_type results_; }; } // namespace detail
diff --git a/asio/include/asio/detail/resolve_op.hpp b/asio/include/asio/detail/resolve_op.hpp index a505521..3776499 100644 --- a/asio/include/asio/detail/resolve_op.hpp +++ b/asio/include/asio/detail/resolve_op.hpp
@@ -18,8 +18,8 @@ #include "asio/detail/config.hpp" #include "asio/error.hpp" #include "asio/io_service.hpp" -#include "asio/ip/basic_resolver_iterator.hpp" #include "asio/ip/basic_resolver_query.hpp" +#include "asio/ip/basic_resolver_results.hpp" #include "asio/detail/bind_handler.hpp" #include "asio/detail/fenced_block.hpp" #include "asio/detail/handler_alloc_helpers.hpp" @@ -40,7 +40,7 @@ ASIO_DEFINE_HANDLER_PTR(resolve_op); typedef asio::ip::basic_resolver_query<Protocol> query_type; - typedef asio::ip::basic_resolver_iterator<Protocol> iterator_type; + typedef asio::ip::basic_resolver_results<Protocol> results_type; resolve_op(socket_ops::weak_cancel_token_type cancel_token, const query_type& query, io_service_impl& ios, Handler& handler) @@ -96,12 +96,12 @@ // associated with the handler. Consequently, a local copy of the handler // is required to ensure that any owning sub-object remains valid until // after we have deallocated the memory here. - detail::binder2<Handler, asio::error_code, iterator_type> - handler(o->handler_, o->ec_, iterator_type()); + detail::binder2<Handler, asio::error_code, results_type> + handler(o->handler_, o->ec_, results_type()); p.h = asio::detail::addressof(handler.handler_); if (o->addrinfo_) { - handler.arg2_ = iterator_type::create(o->addrinfo_, + handler.arg2_ = results_type::create(o->addrinfo_, o->query_.host_name(), o->query_.service_name()); } p.reset();
diff --git a/asio/include/asio/detail/resolver_service.hpp b/asio/include/asio/detail/resolver_service.hpp index 4505b04..d27c1c0 100644 --- a/asio/include/asio/detail/resolver_service.hpp +++ b/asio/include/asio/detail/resolver_service.hpp
@@ -19,8 +19,8 @@ #if !defined(ASIO_WINDOWS_RUNTIME) -#include "asio/ip/basic_resolver_iterator.hpp" #include "asio/ip/basic_resolver_query.hpp" +#include "asio/ip/basic_resolver_results.hpp" #include "asio/detail/memory.hpp" #include "asio/detail/resolve_endpoint_op.hpp" #include "asio/detail/resolve_op.hpp" @@ -45,8 +45,8 @@ // The query type. typedef asio::ip::basic_resolver_query<Protocol> query_type; - // The iterator type. - typedef asio::ip::basic_resolver_iterator<Protocol> iterator_type; + // The results type. + typedef asio::ip::basic_resolver_results<Protocol> results_type; // Constructor. resolver_service(asio::io_service& io_service) @@ -55,7 +55,7 @@ } // Resolve a query to a list of entries. - iterator_type resolve(implementation_type&, const query_type& query, + results_type resolve(implementation_type&, const query_type& query, asio::error_code& ec) { asio::detail::addrinfo_type* address_info = 0; @@ -64,7 +64,7 @@ query.service_name().c_str(), query.hints(), &address_info, ec); auto_addrinfo auto_address_info(address_info); - return ec ? iterator_type() : iterator_type::create( + return ec ? results_type() : results_type::create( address_info, query.host_name(), query.service_name()); } @@ -87,7 +87,7 @@ } // Resolve an endpoint to a list of entries. - iterator_type resolve(implementation_type&, + results_type resolve(implementation_type&, const endpoint_type& endpoint, asio::error_code& ec) { char host_name[NI_MAXHOST]; @@ -96,7 +96,7 @@ host_name, NI_MAXHOST, service_name, NI_MAXSERV, endpoint.protocol().type(), ec); - return ec ? iterator_type() : iterator_type::create( + return ec ? results_type() : results_type::create( endpoint, host_name, service_name); }
diff --git a/asio/include/asio/detail/winrt_resolve_op.hpp b/asio/include/asio/detail/winrt_resolve_op.hpp index 1c21501..45a5350 100644 --- a/asio/include/asio/detail/winrt_resolve_op.hpp +++ b/asio/include/asio/detail/winrt_resolve_op.hpp
@@ -25,7 +25,7 @@ #include "asio/detail/handler_invoke_helpers.hpp" #include "asio/detail/memory.hpp" #include "asio/detail/winrt_async_op.hpp" -#include "asio/ip/basic_resolver_iterator.hpp" +#include "asio/ip/basic_resolver_results.hpp" #include "asio/error.hpp" #include "asio/detail/push_options.hpp" @@ -44,7 +44,7 @@ typedef typename Protocol::endpoint endpoint_type; typedef asio::ip::basic_resolver_query<Protocol> query_type; - typedef asio::ip::basic_resolver_iterator<Protocol> iterator_type; + typedef asio::ip::basic_resolver_results<Protocol> results_type; winrt_resolve_op(const query_type& query, Handler& handler) : winrt_async_op< @@ -67,13 +67,12 @@ ASIO_HANDLER_COMPLETION((*o)); - iterator_type iterator = iterator_type(); + results_type results = results_type(); if (!o->ec_) { try { - iterator = iterator_type::create( - o->result_, o->query_.hints(), + results = results_type::create(o->result_, o->query_.hints(), o->query_.host_name(), o->query_.service_name()); } catch (Platform::Exception^ e) @@ -89,8 +88,8 @@ // with the handler. Consequently, a local copy of the handler is required // to ensure that any owning sub-object remains valid until after we have // deallocated the memory here. - detail::binder2<Handler, asio::error_code, iterator_type> - handler(o->handler_, o->ec_, iterator); + detail::binder2<Handler, asio::error_code, results_type> + handler(o->handler_, o->ec_, results); p.h = asio::detail::addressof(handler.handler_); p.reset();
diff --git a/asio/include/asio/detail/winrt_resolver_service.hpp b/asio/include/asio/detail/winrt_resolver_service.hpp index 68ce1ff..b8a2308 100644 --- a/asio/include/asio/detail/winrt_resolver_service.hpp +++ b/asio/include/asio/detail/winrt_resolver_service.hpp
@@ -19,8 +19,8 @@ #if defined(ASIO_WINDOWS_RUNTIME) -#include "asio/ip/basic_resolver_iterator.hpp" #include "asio/ip/basic_resolver_query.hpp" +#include "asio/ip/basic_resolver_results.hpp" #include "asio/detail/bind_handler.hpp" #include "asio/detail/memory.hpp" #include "asio/detail/socket_ops.hpp" @@ -48,8 +48,8 @@ // The query type. typedef asio::ip::basic_resolver_query<Protocol> query_type; - // The iterator type. - typedef asio::ip::basic_resolver_iterator<Protocol> iterator_type; + // The results type. + typedef asio::ip::basic_resolver_results<Protocol> results_type; // Constructor. winrt_resolver_service(asio::io_service& io_service) @@ -89,7 +89,7 @@ } // Resolve a query to a list of entries. - iterator_type resolve(implementation_type&, + results_type resolve(implementation_type&, const query_type& query, asio::error_code& ec) { try @@ -101,9 +101,9 @@ winrt_utils::string(query.service_name())), ec); if (ec) - return iterator_type(); + return results_type(); - return iterator_type::create( + return results_type::create( endpoint_pairs, query.hints(), query.host_name(), query.service_name()); } @@ -111,7 +111,7 @@ { ec = asio::error_code(e->HResult, asio::system_category()); - return iterator_type(); + return results_type(); } } @@ -151,11 +151,11 @@ } // Resolve an endpoint to a list of entries. - iterator_type resolve(implementation_type&, + results_type resolve(implementation_type&, const endpoint_type&, asio::error_code& ec) { ec = asio::error::operation_not_supported; - return iterator_type(); + return results_type(); } // Asynchronously resolve an endpoint to a list of entries. @@ -164,9 +164,9 @@ const endpoint_type&, Handler& handler) { asio::error_code ec = asio::error::operation_not_supported; - const iterator_type iterator; + const results_type results; io_service_.get_io_service().post( - detail::bind_handler(handler, ec, iterator)); + detail::bind_handler(handler, ec, results)); } private:
diff --git a/asio/include/asio/impl/connect.hpp b/asio/include/asio/impl/connect.hpp index 57f57a8..9ca8be5 100644 --- a/asio/include/asio/impl/connect.hpp +++ b/asio/include/asio/impl/connect.hpp
@@ -15,6 +15,7 @@ # pragma once #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) +#include <algorithm> #include "asio/associated_allocator.hpp" #include "asio/associated_executor.hpp" #include "asio/detail/bind_handler.hpp" @@ -35,16 +36,41 @@ { struct default_connect_condition { - template <typename Iterator> - Iterator operator()(const asio::error_code&, Iterator next) + template <typename Endpoint> + bool operator()(const asio::error_code&, const Endpoint&) { - return next; + return true; } }; } +template <typename Protocol, typename SocketService, typename EndpointSequence> +typename Protocol::endpoint connect(basic_socket<Protocol, SocketService>& s, + const EndpointSequence& endpoints, + typename enable_if<is_endpoint_sequence< + EndpointSequence>::value>::type*) +{ + asio::error_code ec; + typename Protocol::endpoint result = connect(s, endpoints, ec); + asio::detail::throw_error(ec, "connect"); + return result; +} + +template <typename Protocol, typename SocketService, typename EndpointSequence> +typename Protocol::endpoint connect(basic_socket<Protocol, SocketService>& s, + const EndpointSequence& endpoints, asio::error_code& ec, + typename enable_if<is_endpoint_sequence< + EndpointSequence>::value>::type*) +{ + typename EndpointSequence::iterator iter = connect( + s, endpoints.begin(), endpoints.end(), + detail::default_connect_condition(), ec); + return ec ? typename Protocol::endpoint() : *iter; +} + template <typename Protocol, typename SocketService, typename Iterator> -Iterator connect(basic_socket<Protocol, SocketService>& s, Iterator begin) +Iterator connect(basic_socket<Protocol, SocketService>& s, Iterator begin, + typename enable_if<!is_endpoint_sequence<Iterator>::value>::type*) { asio::error_code ec; Iterator result = connect(s, begin, ec); @@ -54,7 +80,8 @@ template <typename Protocol, typename SocketService, typename Iterator> inline Iterator connect(basic_socket<Protocol, SocketService>& s, - Iterator begin, asio::error_code& ec) + Iterator begin, asio::error_code& ec, + typename enable_if<!is_endpoint_sequence<Iterator>::value>::type*) { return connect(s, begin, Iterator(), detail::default_connect_condition(), ec); } @@ -77,9 +104,37 @@ } template <typename Protocol, typename SocketService, + typename EndpointSequence, typename ConnectCondition> +typename Protocol::endpoint connect(basic_socket<Protocol, SocketService>& s, + const EndpointSequence& endpoints, ConnectCondition connect_condition, + typename enable_if<is_endpoint_sequence< + EndpointSequence>::value>::type*) +{ + asio::error_code ec; + typename Protocol::endpoint result = connect( + s, endpoints, connect_condition, ec); + asio::detail::throw_error(ec, "connect"); + return result; +} + +template <typename Protocol, typename SocketService, + typename EndpointSequence, typename ConnectCondition> +typename Protocol::endpoint connect(basic_socket<Protocol, SocketService>& s, + const EndpointSequence& endpoints, ConnectCondition connect_condition, + asio::error_code& ec, + typename enable_if<is_endpoint_sequence< + EndpointSequence>::value>::type*) +{ + typename EndpointSequence::iterator iter = connect( + s, endpoints.begin(), endpoints.end(), connect_condition, ec); + return ec ? typename Protocol::endpoint() : *iter; +} + +template <typename Protocol, typename SocketService, typename Iterator, typename ConnectCondition> Iterator connect(basic_socket<Protocol, SocketService>& s, - Iterator begin, ConnectCondition connect_condition) + Iterator begin, ConnectCondition connect_condition, + typename enable_if<!is_endpoint_sequence<Iterator>::value>::type*) { asio::error_code ec; Iterator result = connect(s, begin, connect_condition, ec); @@ -91,7 +146,8 @@ typename Iterator, typename ConnectCondition> inline Iterator connect(basic_socket<Protocol, SocketService>& s, Iterator begin, ConnectCondition connect_condition, - asio::error_code& ec) + asio::error_code& ec, + typename enable_if<!is_endpoint_sequence<Iterator>::value>::type*) { return connect(s, begin, Iterator(), connect_condition, ec); } @@ -117,8 +173,7 @@ for (Iterator iter = begin; iter != end; ++iter) { - iter = connect_condition(ec, iter); - if (iter != end) + if (connect_condition(ec, iter)) { s.close(ec); s.connect(*iter, ec); @@ -146,12 +201,11 @@ { } - template <typename Iterator> - void check_condition(const asio::error_code& ec, - Iterator& iter, Iterator& end) + template <typename Endpoint> + bool check_condition(const asio::error_code& ec, + const Endpoint& endpoint) { - if (iter != end) - iter = connect_condition_(ec, static_cast<const Iterator&>(iter)); + return connect_condition_(ec, endpoint); } private: @@ -168,32 +222,191 @@ { } - template <typename Iterator> - void check_condition(const asio::error_code&, Iterator&, Iterator&) + template <typename Endpoint> + bool check_condition(const asio::error_code&, const Endpoint&) { + return true; } }; - template <typename Protocol, typename SocketService, typename Iterator, - typename ConnectCondition, typename ComposedConnectHandler> - class connect_op : base_from_connect_condition<ConnectCondition> + template <typename Protocol, typename SocketService, + typename EndpointSequence, typename ConnectCondition, + typename RangeConnectHandler> + class range_connect_op : base_from_connect_condition<ConnectCondition> { public: - connect_op(basic_socket<Protocol, SocketService>& sock, + range_connect_op(basic_socket<Protocol, SocketService>& sock, + const EndpointSequence& endpoints, + const ConnectCondition& connect_condition, + RangeConnectHandler& handler) + : base_from_connect_condition<ConnectCondition>(connect_condition), + socket_(sock), + endpoints_(endpoints), + index_(0), + start_(0), + handler_(ASIO_MOVE_CAST(RangeConnectHandler)(handler)) + { + } + +#if defined(ASIO_HAS_MOVE) + range_connect_op(const range_connect_op& other) + : base_from_connect_condition<ConnectCondition>(other), + socket_(other.socket_), + endpoints_(other.endpoints_), + index_(other.index_), + start_(other.start_), + handler_(other.handler_) + { + } + + range_connect_op(range_connect_op&& other) + : base_from_connect_condition<ConnectCondition>(other), + socket_(other.socket_), + endpoints_(other.endpoints_), + index_(other.index_), + start_(other.start_), + handler_(ASIO_MOVE_CAST(RangeConnectHandler)(other.handler_)) + { + } +#endif // defined(ASIO_HAS_MOVE) + + void operator()(asio::error_code ec, int start = 0) + { + typename EndpointSequence::iterator iter = endpoints_.begin(); + std::advance(iter, index_); + typename EndpointSequence::iterator end = endpoints_.end(); + + switch (start_ = start) + { + case 1: + for (;;) + { + for (; iter != end; ++iter, ++index_) + if (this->check_condition(ec, *iter)) + break; + + if (iter != end) + { + socket_.close(ec); + socket_.async_connect(*iter, + ASIO_MOVE_CAST(range_connect_op)(*this)); + return; + } + + if (start) + { + ec = asio::error::not_found; + asio::post(socket_.get_executor(), + detail::bind_handler(*this, ec)); + return; + } + + default: + + if (iter == end) + break; + + if (!socket_.is_open()) + { + ec = asio::error::operation_aborted; + break; + } + + if (!ec) + break; + + ++iter; + ++index_; + } + + handler_(static_cast<const asio::error_code&>(ec), + static_cast<const typename Protocol::endpoint&>(*iter)); + } + } + + //private: + basic_socket<Protocol, SocketService>& socket_; + EndpointSequence endpoints_; + std::size_t index_; + int start_; + RangeConnectHandler handler_; + }; + + template <typename Protocol, typename SocketService, + typename EndpointSequence, typename ConnectCondition, + typename RangeConnectHandler> + inline void* asio_handler_allocate(std::size_t size, + range_connect_op<Protocol, SocketService, EndpointSequence, + ConnectCondition, RangeConnectHandler>* this_handler) + { + return asio_handler_alloc_helpers::allocate( + size, this_handler->handler_); + } + + template <typename Protocol, typename SocketService, + typename EndpointSequence, typename ConnectCondition, + typename RangeConnectHandler> + inline void asio_handler_deallocate(void* pointer, std::size_t size, + range_connect_op<Protocol, SocketService, EndpointSequence, + ConnectCondition, RangeConnectHandler>* this_handler) + { + asio_handler_alloc_helpers::deallocate( + pointer, size, this_handler->handler_); + } + + template <typename Protocol, typename SocketService, + typename EndpointSequence, typename ConnectCondition, + typename RangeConnectHandler> + inline bool asio_handler_is_continuation( + range_connect_op<Protocol, SocketService, EndpointSequence, + ConnectCondition, RangeConnectHandler>* this_handler) + { + return asio_handler_cont_helpers::is_continuation( + this_handler->handler_); + } + + template <typename Function, typename Protocol, + typename SocketService, typename EndpointSequence, + typename ConnectCondition, typename RangeConnectHandler> + inline void asio_handler_invoke(Function& function, + range_connect_op<Protocol, SocketService, EndpointSequence, + ConnectCondition, RangeConnectHandler>* this_handler) + { + asio_handler_invoke_helpers::invoke( + function, this_handler->handler_); + } + + template <typename Function, typename Protocol, + typename SocketService, typename EndpointSequence, + typename ConnectCondition, typename RangeConnectHandler> + inline void asio_handler_invoke(const Function& function, + range_connect_op<Protocol, SocketService, EndpointSequence, + ConnectCondition, RangeConnectHandler>* this_handler) + { + asio_handler_invoke_helpers::invoke( + function, this_handler->handler_); + } + + template <typename Protocol, typename SocketService, typename Iterator, + typename ConnectCondition, typename IteratorConnectHandler> + class iterator_connect_op : base_from_connect_condition<ConnectCondition> + { + public: + iterator_connect_op(basic_socket<Protocol, SocketService>& sock, const Iterator& begin, const Iterator& end, const ConnectCondition& connect_condition, - ComposedConnectHandler& handler) + IteratorConnectHandler& handler) : base_from_connect_condition<ConnectCondition>(connect_condition), socket_(sock), iter_(begin), end_(end), start_(0), - handler_(ASIO_MOVE_CAST(ComposedConnectHandler)(handler)) + handler_(ASIO_MOVE_CAST(IteratorConnectHandler)(handler)) { } #if defined(ASIO_HAS_MOVE) - connect_op(const connect_op& other) + iterator_connect_op(const iterator_connect_op& other) : base_from_connect_condition<ConnectCondition>(other), socket_(other.socket_), iter_(other.iter_), @@ -203,13 +416,13 @@ { } - connect_op(connect_op&& other) + iterator_connect_op(iterator_connect_op&& other) : base_from_connect_condition<ConnectCondition>(other), socket_(other.socket_), iter_(other.iter_), end_(other.end_), start_(other.start_), - handler_(ASIO_MOVE_CAST(ComposedConnectHandler)(other.handler_)) + handler_(ASIO_MOVE_CAST(IteratorConnectHandler)(other.handler_)) { } #endif // defined(ASIO_HAS_MOVE) @@ -221,13 +434,15 @@ case 1: for (;;) { - this->check_condition(ec, iter_, end_); + for (; iter_ != end_; ++iter_) + if (this->check_condition(ec, *iter_)) + break; if (iter_ != end_) { socket_.close(ec); socket_.async_connect(*iter_, - ASIO_MOVE_CAST(connect_op)(*this)); + ASIO_MOVE_CAST(iterator_connect_op)(*this)); return; } @@ -266,34 +481,34 @@ Iterator iter_; Iterator end_; int start_; - ComposedConnectHandler handler_; + IteratorConnectHandler handler_; }; template <typename Protocol, typename SocketService, typename Iterator, - typename ConnectCondition, typename ComposedConnectHandler> + typename ConnectCondition, typename IteratorConnectHandler> inline void* asio_handler_allocate(std::size_t size, - connect_op<Protocol, SocketService, Iterator, - ConnectCondition, ComposedConnectHandler>* this_handler) + iterator_connect_op<Protocol, SocketService, Iterator, + ConnectCondition, IteratorConnectHandler>* this_handler) { return asio_handler_alloc_helpers::allocate( size, this_handler->handler_); } template <typename Protocol, typename SocketService, typename Iterator, - typename ConnectCondition, typename ComposedConnectHandler> + typename ConnectCondition, typename IteratorConnectHandler> inline void asio_handler_deallocate(void* pointer, std::size_t size, - connect_op<Protocol, SocketService, Iterator, - ConnectCondition, ComposedConnectHandler>* this_handler) + iterator_connect_op<Protocol, SocketService, Iterator, + ConnectCondition, IteratorConnectHandler>* this_handler) { asio_handler_alloc_helpers::deallocate( pointer, size, this_handler->handler_); } template <typename Protocol, typename SocketService, typename Iterator, - typename ConnectCondition, typename ComposedConnectHandler> + typename ConnectCondition, typename IteratorConnectHandler> inline bool asio_handler_is_continuation( - connect_op<Protocol, SocketService, Iterator, - ConnectCondition, ComposedConnectHandler>* this_handler) + iterator_connect_op<Protocol, SocketService, Iterator, + ConnectCondition, IteratorConnectHandler>* this_handler) { return asio_handler_cont_helpers::is_continuation( this_handler->handler_); @@ -301,10 +516,10 @@ template <typename Function, typename Protocol, typename SocketService, typename Iterator, - typename ConnectCondition, typename ComposedConnectHandler> + typename ConnectCondition, typename IteratorConnectHandler> inline void asio_handler_invoke(Function& function, - connect_op<Protocol, SocketService, Iterator, - ConnectCondition, ComposedConnectHandler>* this_handler) + iterator_connect_op<Protocol, SocketService, Iterator, + ConnectCondition, IteratorConnectHandler>* this_handler) { asio_handler_invoke_helpers::invoke( function, this_handler->handler_); @@ -312,10 +527,10 @@ template <typename Function, typename Protocol, typename SocketService, typename Iterator, - typename ConnectCondition, typename ComposedConnectHandler> + typename ConnectCondition, typename IteratorConnectHandler> inline void asio_handler_invoke(const Function& function, - connect_op<Protocol, SocketService, Iterator, - ConnectCondition, ComposedConnectHandler>* this_handler) + iterator_connect_op<Protocol, SocketService, Iterator, + ConnectCondition, IteratorConnectHandler>* this_handler) { asio_handler_invoke_helpers::invoke( function, this_handler->handler_); @@ -325,43 +540,85 @@ #if !defined(GENERATING_DOCUMENTATION) template <typename Protocol, typename SocketService, - typename Iterator, typename ConnectCondition, - typename ComposedConnectHandler, typename Allocator> + typename EndpointSequence, typename ConnectCondition, + typename RangeConnectHandler, typename Allocator> struct associated_allocator< - detail::connect_op<Protocol, SocketService, Iterator, - ConnectCondition, ComposedConnectHandler>, + detail::range_connect_op<Protocol, SocketService, + EndpointSequence, ConnectCondition, RangeConnectHandler>, Allocator> { typedef typename associated_allocator< - ComposedConnectHandler, Allocator>::type type; + RangeConnectHandler, Allocator>::type type; static type get( - const detail::connect_op<Protocol, SocketService, - Iterator, ConnectCondition, ComposedConnectHandler>& h, + const detail::range_connect_op<Protocol, SocketService, + EndpointSequence, ConnectCondition, RangeConnectHandler>& h, const Allocator& a = Allocator()) ASIO_NOEXCEPT { - return associated_allocator<ComposedConnectHandler, + return associated_allocator<RangeConnectHandler, + Allocator>::get(h.handler_, a); + } +}; + +template <typename Protocol, typename SocketService, + typename EndpointSequence, typename ConnectCondition, + typename RangeConnectHandler, typename Executor> +struct associated_executor< + detail::range_connect_op<Protocol, SocketService, + EndpointSequence, ConnectCondition, RangeConnectHandler>, + Executor> +{ + typedef typename associated_executor< + RangeConnectHandler, Executor>::type type; + + static type get( + const detail::range_connect_op<Protocol, SocketService, + EndpointSequence, ConnectCondition, RangeConnectHandler>& h, + const Executor& ex = Executor()) ASIO_NOEXCEPT + { + return associated_executor<RangeConnectHandler, + Executor>::get(h.handler_, ex); + } +}; + +template <typename Protocol, typename SocketService, + typename Iterator, typename ConnectCondition, + typename IteratorConnectHandler, typename Allocator> +struct associated_allocator< + detail::iterator_connect_op<Protocol, SocketService, Iterator, + ConnectCondition, IteratorConnectHandler>, + Allocator> +{ + typedef typename associated_allocator< + IteratorConnectHandler, Allocator>::type type; + + static type get( + const detail::iterator_connect_op<Protocol, SocketService, + Iterator, ConnectCondition, IteratorConnectHandler>& h, + const Allocator& a = Allocator()) ASIO_NOEXCEPT + { + return associated_allocator<IteratorConnectHandler, Allocator>::get(h.handler_, a); } }; template <typename Protocol, typename SocketService, typename Iterator, typename ConnectCondition, - typename ComposedConnectHandler, typename Executor> + typename IteratorConnectHandler, typename Executor> struct associated_executor< - detail::connect_op<Protocol, SocketService, Iterator, - ConnectCondition, ComposedConnectHandler>, + detail::iterator_connect_op<Protocol, SocketService, Iterator, + ConnectCondition, IteratorConnectHandler>, Executor> { typedef typename associated_executor< - ComposedConnectHandler, Executor>::type type; + IteratorConnectHandler, Executor>::type type; static type get( - const detail::connect_op<Protocol, SocketService, - Iterator, ConnectCondition, ComposedConnectHandler>& h, + const detail::iterator_connect_op<Protocol, SocketService, + Iterator, ConnectCondition, IteratorConnectHandler>& h, const Executor& ex = Executor()) ASIO_NOEXCEPT { - return associated_executor<ComposedConnectHandler, + return associated_executor<IteratorConnectHandler, Executor>::get(h.handler_, ex); } }; @@ -369,23 +626,53 @@ #endif // !defined(GENERATING_DOCUMENTATION) template <typename Protocol, typename SocketService, - typename Iterator, typename ComposedConnectHandler> -inline ASIO_INITFN_RESULT_TYPE(ComposedConnectHandler, - void (asio::error_code, Iterator)) + typename EndpointSequence, typename RangeConnectHandler> +inline ASIO_INITFN_RESULT_TYPE(RangeConnectHandler, + void (asio::error_code, typename Protocol::endpoint)) async_connect(basic_socket<Protocol, SocketService>& s, - Iterator begin, ASIO_MOVE_ARG(ComposedConnectHandler) handler) + const EndpointSequence& endpoints, + ASIO_MOVE_ARG(RangeConnectHandler) handler, + typename enable_if<is_endpoint_sequence< + EndpointSequence>::value>::type*) { // If you get an error on the following line it means that your handler does - // not meet the documented type requirements for a ComposedConnectHandler. - ASIO_COMPOSED_CONNECT_HANDLER_CHECK( - ComposedConnectHandler, handler, Iterator) type_check; + // not meet the documented type requirements for a RangeConnectHandler. + ASIO_RANGE_CONNECT_HANDLER_CHECK( + RangeConnectHandler, handler, typename Protocol::endpoint) type_check; - async_completion<ComposedConnectHandler, + async_completion<RangeConnectHandler, + void (asio::error_code, typename Protocol::endpoint)> + init(handler); + + detail::range_connect_op<Protocol, SocketService, EndpointSequence, + detail::default_connect_condition, + ASIO_HANDLER_TYPE(RangeConnectHandler, + void (asio::error_code, typename Protocol::endpoint))>(s, + endpoints, detail::default_connect_condition(), init.handler)( + asio::error_code(), 1); + + return init.result.get(); +} + +template <typename Protocol, typename SocketService, + typename Iterator, typename IteratorConnectHandler> +inline ASIO_INITFN_RESULT_TYPE(IteratorConnectHandler, + void (asio::error_code, Iterator)) +async_connect(basic_socket<Protocol, SocketService>& s, + Iterator begin, ASIO_MOVE_ARG(IteratorConnectHandler) handler, + typename enable_if<!is_endpoint_sequence<Iterator>::value>::type*) +{ + // If you get an error on the following line it means that your handler does + // not meet the documented type requirements for a IteratorConnectHandler. + ASIO_ITERATOR_CONNECT_HANDLER_CHECK( + IteratorConnectHandler, handler, Iterator) type_check; + + async_completion<IteratorConnectHandler, void (asio::error_code, Iterator)> init(handler); - detail::connect_op<Protocol, SocketService, Iterator, + detail::iterator_connect_op<Protocol, SocketService, Iterator, detail::default_connect_condition, ASIO_HANDLER_TYPE( - ComposedConnectHandler, void (asio::error_code, Iterator))>(s, + IteratorConnectHandler, void (asio::error_code, Iterator))>(s, begin, Iterator(), detail::default_connect_condition(), init.handler)( asio::error_code(), 1); @@ -393,49 +680,78 @@ } template <typename Protocol, typename SocketService, - typename Iterator, typename ComposedConnectHandler> -inline ASIO_INITFN_RESULT_TYPE(ComposedConnectHandler, + typename Iterator, typename IteratorConnectHandler> +inline ASIO_INITFN_RESULT_TYPE(IteratorConnectHandler, void (asio::error_code, Iterator)) async_connect(basic_socket<Protocol, SocketService>& s, Iterator begin, Iterator end, - ASIO_MOVE_ARG(ComposedConnectHandler) handler) + ASIO_MOVE_ARG(IteratorConnectHandler) handler) { // If you get an error on the following line it means that your handler does - // not meet the documented type requirements for a ComposedConnectHandler. - ASIO_COMPOSED_CONNECT_HANDLER_CHECK( - ComposedConnectHandler, handler, Iterator) type_check; + // not meet the documented type requirements for a IteratorConnectHandler. + ASIO_ITERATOR_CONNECT_HANDLER_CHECK( + IteratorConnectHandler, handler, Iterator) type_check; - async_completion<ComposedConnectHandler, + async_completion<IteratorConnectHandler, void (asio::error_code, Iterator)> init(handler); - detail::connect_op<Protocol, SocketService, Iterator, + detail::iterator_connect_op<Protocol, SocketService, Iterator, detail::default_connect_condition, ASIO_HANDLER_TYPE( - ComposedConnectHandler, void (asio::error_code, Iterator))>(s, + IteratorConnectHandler, void (asio::error_code, Iterator))>(s, begin, end, detail::default_connect_condition(), init.handler)( asio::error_code(), 1); return init.result.get(); } +template <typename Protocol, typename SocketService, typename EndpointSequence, + typename ConnectCondition, typename RangeConnectHandler> +inline ASIO_INITFN_RESULT_TYPE(RangeConnectHandler, + void (asio::error_code, typename Protocol::endpoint)) +async_connect(basic_socket<Protocol, SocketService>& s, + const EndpointSequence& endpoints, ConnectCondition connect_condition, + ASIO_MOVE_ARG(RangeConnectHandler) handler, + typename enable_if<is_endpoint_sequence< + EndpointSequence>::value>::type*) +{ + // If you get an error on the following line it means that your handler does + // not meet the documented type requirements for a RangeConnectHandler. + ASIO_RANGE_CONNECT_HANDLER_CHECK( + RangeConnectHandler, handler, typename Protocol::endpoint) type_check; + + async_completion<RangeConnectHandler, + void (asio::error_code, typename Protocol::endpoint)> + init(handler); + + detail::range_connect_op<Protocol, SocketService, EndpointSequence, + ConnectCondition, ASIO_HANDLER_TYPE(RangeConnectHandler, + void (asio::error_code, typename Protocol::endpoint))>(s, + endpoints, connect_condition, init.handler)( + asio::error_code(), 1); + + return init.result.get(); +} + template <typename Protocol, typename SocketService, typename Iterator, - typename ConnectCondition, typename ComposedConnectHandler> -inline ASIO_INITFN_RESULT_TYPE(ComposedConnectHandler, + typename ConnectCondition, typename IteratorConnectHandler> +inline ASIO_INITFN_RESULT_TYPE(IteratorConnectHandler, void (asio::error_code, Iterator)) async_connect(basic_socket<Protocol, SocketService>& s, Iterator begin, ConnectCondition connect_condition, - ASIO_MOVE_ARG(ComposedConnectHandler) handler) + ASIO_MOVE_ARG(IteratorConnectHandler) handler, + typename enable_if<!is_endpoint_sequence<Iterator>::value>::type*) { // If you get an error on the following line it means that your handler does - // not meet the documented type requirements for a ComposedConnectHandler. - ASIO_COMPOSED_CONNECT_HANDLER_CHECK( - ComposedConnectHandler, handler, Iterator) type_check; + // not meet the documented type requirements for a IteratorConnectHandler. + ASIO_ITERATOR_CONNECT_HANDLER_CHECK( + IteratorConnectHandler, handler, Iterator) type_check; - async_completion<ComposedConnectHandler, + async_completion<IteratorConnectHandler, void (asio::error_code, Iterator)> init(handler); - detail::connect_op<Protocol, SocketService, Iterator, + detail::iterator_connect_op<Protocol, SocketService, Iterator, ConnectCondition, ASIO_HANDLER_TYPE( - ComposedConnectHandler, void (asio::error_code, Iterator))>(s, + IteratorConnectHandler, void (asio::error_code, Iterator))>(s, begin, Iterator(), connect_condition, init.handler)( asio::error_code(), 1); @@ -443,24 +759,24 @@ } template <typename Protocol, typename SocketService, typename Iterator, - typename ConnectCondition, typename ComposedConnectHandler> -inline ASIO_INITFN_RESULT_TYPE(ComposedConnectHandler, + typename ConnectCondition, typename IteratorConnectHandler> +inline ASIO_INITFN_RESULT_TYPE(IteratorConnectHandler, void (asio::error_code, Iterator)) async_connect(basic_socket<Protocol, SocketService>& s, Iterator begin, Iterator end, ConnectCondition connect_condition, - ASIO_MOVE_ARG(ComposedConnectHandler) handler) + ASIO_MOVE_ARG(IteratorConnectHandler) handler) { // If you get an error on the following line it means that your handler does - // not meet the documented type requirements for a ComposedConnectHandler. - ASIO_COMPOSED_CONNECT_HANDLER_CHECK( - ComposedConnectHandler, handler, Iterator) type_check; + // not meet the documented type requirements for a IteratorConnectHandler. + ASIO_ITERATOR_CONNECT_HANDLER_CHECK( + IteratorConnectHandler, handler, Iterator) type_check; - async_completion<ComposedConnectHandler, + async_completion<IteratorConnectHandler, void (asio::error_code, Iterator)> init(handler); - detail::connect_op<Protocol, SocketService, Iterator, + detail::iterator_connect_op<Protocol, SocketService, Iterator, ConnectCondition, ASIO_HANDLER_TYPE( - ComposedConnectHandler, void (asio::error_code, Iterator))>(s, + IteratorConnectHandler, void (asio::error_code, Iterator))>(s, begin, end, connect_condition, init.handler)( asio::error_code(), 1);
diff --git a/asio/include/asio/ip/basic_endpoint.hpp b/asio/include/asio/ip/basic_endpoint.hpp index a1bae97..61926c0 100644 --- a/asio/include/asio/ip/basic_endpoint.hpp +++ b/asio/include/asio/ip/basic_endpoint.hpp
@@ -97,13 +97,13 @@ { } -#if defined(ASIO_HAS_MOVE) +#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) /// Move constructor. basic_endpoint(basic_endpoint&& other) : impl_(other.impl_) { } -#endif // defined(ASIO_HAS_MOVE) +#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) /// Assign from another endpoint. basic_endpoint& operator=(const basic_endpoint& other) @@ -112,14 +112,14 @@ return *this; } -#if defined(ASIO_HAS_MOVE) +#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) /// Move-assign from another endpoint. basic_endpoint& operator=(basic_endpoint&& other) { impl_ = other.impl_; return *this; } -#endif // defined(ASIO_HAS_MOVE) +#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) /// The protocol associated with the endpoint. protocol_type protocol() const
diff --git a/asio/include/asio/ip/basic_resolver.hpp b/asio/include/asio/ip/basic_resolver.hpp index 3fd1a39..66016c1 100644 --- a/asio/include/asio/ip/basic_resolver.hpp +++ b/asio/include/asio/ip/basic_resolver.hpp
@@ -22,6 +22,7 @@ #include "asio/error.hpp" #include "asio/ip/basic_resolver_iterator.hpp" #include "asio/ip/basic_resolver_query.hpp" +#include "asio/ip/basic_resolver_results.hpp" #include "asio/ip/resolver_service.hpp" #include "asio/detail/push_options.hpp" @@ -53,9 +54,12 @@ /// The query type. typedef basic_resolver_query<InternetProtocol> query; - /// The iterator type. + /// (Deprecated.) The iterator type. typedef basic_resolver_iterator<InternetProtocol> iterator; + /// The results type. + typedef basic_resolver_results<InternetProtocol> results_type; + /// Constructor. /** * This constructor creates a basic_resolver. @@ -85,22 +89,19 @@ * * @param q A query object that determines what endpoints will be returned. * - * @returns A forward-only iterator that can be used to traverse the list - * of endpoint entries. + * @returns A range object representing the list of endpoint entries. A + * successful call to this function is guaranteed to return a non-empty + * range. * * @throws asio::system_error Thrown on failure. - * - * @note A default constructed iterator represents the end of the list. - * - * A successful call to this function is guaranteed to return at least one - * entry. */ - iterator resolve(const query& q) + results_type resolve(const query& q) { asio::error_code ec; - iterator i = this->get_service().resolve(this->get_implementation(), q, ec); + results_type r = this->get_service().resolve( + this->get_implementation(), q, ec); asio::detail::throw_error(ec, "resolve"); - return i; + return r; } /// Perform forward resolution of a query to a list of entries. @@ -111,16 +112,11 @@ * * @param ec Set to indicate what error occurred, if any. * - * @returns A forward-only iterator that can be used to traverse the list - * of endpoint entries. Returns a default constructed iterator if an error - * occurs. - * - * @note A default constructed iterator represents the end of the list. - * - * A successful call to this function is guaranteed to return at least one - * entry. + * @returns A range object representing the list of endpoint entries. An + * empty range is returned if an error occurs. A successful call to this + * function is guaranteed to return a non-empty range. */ - iterator resolve(const query& q, asio::error_code& ec) + results_type resolve(const query& q, asio::error_code& ec) { return this->get_service().resolve(this->get_implementation(), q, ec); } @@ -137,30 +133,26 @@ * signature of the handler must be: * @code void handler( * const asio::error_code& error, // Result of operation. - * resolver::iterator iterator // Forward-only iterator that can - * // be used to traverse the list - * // of endpoint entries. + * resolver::results_type results // Resolved endpoints as a range. * ); @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 * asio::io_service::post(). * - * @note A default constructed iterator represents the end of the list. - * - * A successful resolve operation is guaranteed to pass at least one entry to + * A successful resolve operation is guaranteed to pass a non-empty range to * the handler. */ template <typename ResolveHandler> ASIO_INITFN_RESULT_TYPE(ResolveHandler, - void (asio::error_code, iterator)) + void (asio::error_code, results_type)) async_resolve(const query& q, ASIO_MOVE_ARG(ResolveHandler) handler) { // If you get an error on the following line it means that your handler does // not meet the documented type requirements for a ResolveHandler. ASIO_RESOLVE_HANDLER_CHECK( - ResolveHandler, handler, iterator) type_check; + ResolveHandler, handler, results_type) type_check; return this->get_service().async_resolve(this->get_implementation(), q, ASIO_MOVE_CAST(ResolveHandler)(handler)); @@ -174,20 +166,17 @@ * @param e An endpoint object that determines what endpoints will be * returned. * - * @returns A forward-only iterator that can be used to traverse the list - * of endpoint entries. + * @returns A range object representing the list of endpoint entries. A + * successful call to this function is guaranteed to return a non-empty + * range. * * @throws asio::system_error Thrown on failure. - * - * @note A default constructed iterator represents the end of the list. - * - * A successful call to this function is guaranteed to return at least one - * entry. */ - iterator resolve(const endpoint_type& e) + results_type resolve(const endpoint_type& e) { asio::error_code ec; - iterator i = this->get_service().resolve(this->get_implementation(), e, ec); + results_type i = this->get_service().resolve( + this->get_implementation(), e, ec); asio::detail::throw_error(ec, "resolve"); return i; } @@ -202,16 +191,11 @@ * * @param ec Set to indicate what error occurred, if any. * - * @returns A forward-only iterator that can be used to traverse the list - * of endpoint entries. Returns a default constructed iterator if an error - * occurs. - * - * @note A default constructed iterator represents the end of the list. - * - * A successful call to this function is guaranteed to return at least one - * entry. + * @returns A range object representing the list of endpoint entries. An + * empty range is returned if an error occurs. A successful call to this + * function is guaranteed to return a non-empty range. */ - iterator resolve(const endpoint_type& e, asio::error_code& ec) + results_type resolve(const endpoint_type& e, asio::error_code& ec) { return this->get_service().resolve(this->get_implementation(), e, ec); } @@ -230,30 +214,26 @@ * signature of the handler must be: * @code void handler( * const asio::error_code& error, // Result of operation. - * resolver::iterator iterator // Forward-only iterator that can - * // be used to traverse the list - * // of endpoint entries. + * resolver::results_type results // Resolved endpoints as a range. * ); @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 * asio::io_service::post(). * - * @note A default constructed iterator represents the end of the list. - * - * A successful resolve operation is guaranteed to pass at least one entry to + * A successful resolve operation is guaranteed to pass a non-empty range to * the handler. */ template <typename ResolveHandler> ASIO_INITFN_RESULT_TYPE(ResolveHandler, - void (asio::error_code, iterator)) + void (asio::error_code, results_type)) async_resolve(const endpoint_type& e, ASIO_MOVE_ARG(ResolveHandler) handler) { // If you get an error on the following line it means that your handler does // not meet the documented type requirements for a ResolveHandler. ASIO_RESOLVE_HANDLER_CHECK( - ResolveHandler, handler, iterator) type_check; + ResolveHandler, handler, results_type) type_check; return this->get_service().async_resolve(this->get_implementation(), e, ASIO_MOVE_CAST(ResolveHandler)(handler));
diff --git a/asio/include/asio/ip/basic_resolver_iterator.hpp b/asio/include/asio/ip/basic_resolver_iterator.hpp index 3ce63c0..a0b40c7 100644 --- a/asio/include/asio/ip/basic_resolver_iterator.hpp +++ b/asio/include/asio/ip/basic_resolver_iterator.hpp
@@ -72,114 +72,45 @@ { } - /// Create an iterator from an addrinfo list returned by getaddrinfo. - static basic_resolver_iterator create( - asio::detail::addrinfo_type* address_info, - const std::string& host_name, const std::string& service_name) + /// Copy constructor. + basic_resolver_iterator(const basic_resolver_iterator& other) + : values_(other.values_), + index_(other.index_) { - basic_resolver_iterator iter; - if (!address_info) - return iter; + } - std::string actual_host_name = host_name; - if (address_info->ai_canonname) - actual_host_name = address_info->ai_canonname; +#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) + /// Move constructor. + basic_resolver_iterator(basic_resolver_iterator&& other) + : values_(ASIO_MOVE_CAST(values_ptr_type)(other.values_)), + index_(other.index_) + { + other.index_ = 0; + } +#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) - iter.values_.reset(new values_type); + /// Assignment operator. + basic_resolver_iterator& operator=(const basic_resolver_iterator& other) + { + values_ = other.values_; + index_ = other.index_; + return *this; + } - while (address_info) +#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) + /// Move-assignment operator. + basic_resolver_iterator& operator=(basic_resolver_iterator&& other) + { + if (this != &other) { - if (address_info->ai_family == ASIO_OS_DEF(AF_INET) - || address_info->ai_family == ASIO_OS_DEF(AF_INET6)) - { - using namespace std; // For memcpy. - typename InternetProtocol::endpoint endpoint; - endpoint.resize(static_cast<std::size_t>(address_info->ai_addrlen)); - memcpy(endpoint.data(), address_info->ai_addr, - address_info->ai_addrlen); - iter.values_->push_back( - basic_resolver_entry<InternetProtocol>(endpoint, - actual_host_name, service_name)); - } - address_info = address_info->ai_next; + values_ = ASIO_MOVE_CAST(values_ptr_type)(other.values_); + index_ = other.index_; + other.index_ = 0; } - return iter; + return *this; } - - /// Create an iterator from an endpoint, host name and service name. - static basic_resolver_iterator create( - const typename InternetProtocol::endpoint& endpoint, - const std::string& host_name, const std::string& service_name) - { - basic_resolver_iterator iter; - iter.values_.reset(new values_type); - iter.values_->push_back( - basic_resolver_entry<InternetProtocol>( - endpoint, host_name, service_name)); - return iter; - } - - /// Create an iterator from a sequence of endpoints, host and service name. - template <typename EndpointIterator> - static basic_resolver_iterator create( - EndpointIterator begin, EndpointIterator end, - const std::string& host_name, const std::string& service_name) - { - basic_resolver_iterator iter; - if (begin != end) - { - iter.values_.reset(new values_type); - for (EndpointIterator ep_iter = begin; ep_iter != end; ++ep_iter) - { - iter.values_->push_back( - basic_resolver_entry<InternetProtocol>( - *ep_iter, host_name, service_name)); - } - } - return iter; - } - -#if defined(ASIO_WINDOWS_RUNTIME) - /// Create an iterator from a Windows Runtime list of EndpointPair objects. - static basic_resolver_iterator create( - Windows::Foundation::Collections::IVectorView< - Windows::Networking::EndpointPair^>^ endpoints, - const asio::detail::addrinfo_type& hints, - const std::string& host_name, const std::string& service_name) - { - basic_resolver_iterator iter; - if (endpoints->Size) - { - iter.values_.reset(new values_type); - for (unsigned int i = 0; i < endpoints->Size; ++i) - { - auto pair = endpoints->GetAt(i); - - if (hints.ai_family == ASIO_OS_DEF(AF_INET) - && pair->RemoteHostName->Type - != Windows::Networking::HostNameType::Ipv4) - continue; - - if (hints.ai_family == ASIO_OS_DEF(AF_INET6) - && pair->RemoteHostName->Type - != Windows::Networking::HostNameType::Ipv6) - continue; - - iter.values_->push_back( - basic_resolver_entry<InternetProtocol>( - typename InternetProtocol::endpoint( - ip::address::from_string( - asio::detail::winrt_utils::string( - pair->RemoteHostName->CanonicalName)), - asio::detail::winrt_utils::integer( - pair->RemoteServiceName)), - host_name, service_name)); - } - } - return iter; - } -#endif // defined(ASIO_WINDOWS_RUNTIME) +#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) /// Dereference an iterator. const basic_resolver_entry<InternetProtocol>& operator*() const @@ -222,7 +153,7 @@ return !a.equal(b); } -private: +protected: void increment() { if (++index_ == values_->size()) @@ -248,7 +179,8 @@ } typedef std::vector<basic_resolver_entry<InternetProtocol> > values_type; - asio::detail::shared_ptr<values_type> values_; + typedef asio::detail::shared_ptr<values_type> values_ptr_type; + values_ptr_type values_; std::size_t index_; };
diff --git a/asio/include/asio/ip/basic_resolver_results.hpp b/asio/include/asio/ip/basic_resolver_results.hpp new file mode 100644 index 0000000..2697b3a --- /dev/null +++ b/asio/include/asio/ip/basic_resolver_results.hpp
@@ -0,0 +1,309 @@ +// +// ip/basic_resolver_results.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 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 ASIO_IP_BASIC_RESOLVER_RESULTS_HPP +#define ASIO_IP_BASIC_RESOLVER_RESULTS_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "asio/detail/config.hpp" +#include <cstddef> +#include <cstring> +#include "asio/detail/socket_ops.hpp" +#include "asio/detail/socket_types.hpp" +#include "asio/ip/basic_resolver_iterator.hpp" + +#if defined(ASIO_WINDOWS_RUNTIME) +# include "asio/detail/winrt_utils.hpp" +#endif // defined(ASIO_WINDOWS_RUNTIME) + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace ip { + +/// A range of entries produced by a resolver. +/** + * The asio::ip::basic_resolver_results class template is used to define + * a range over the results returned by a resolver. + * + * The iterator's value_type, obtained when a results iterator is dereferenced, + * is: @code const basic_resolver_entry<InternetProtocol> @endcode + * + * @note For backward compatibility, basic_resolver_results is derived from + * basic_resolver_iterator. This derivation is deprecated. + * + * @par Thread Safety + * @e Distinct @e objects: Safe.@n + * @e Shared @e objects: Unsafe. + */ +template <typename InternetProtocol> +class basic_resolver_results + : public basic_resolver_iterator<InternetProtocol> +{ +public: + /// The protocol type associated with the results. + typedef InternetProtocol protocol_type; + + /// The endpoint type associated with the results. + typedef typename protocol_type::endpoint endpoint_type; + + /// The type of a value in the results range. + typedef basic_resolver_entry<endpoint_type> value_type; + + /// The type of a const reference to a value in the range. + typedef const value_type& const_reference; + + /// The type of a non-const reference to a value in the range. + typedef value_type& reference; + + /// The type of an iterator into the range. + typedef basic_resolver_iterator<protocol_type> const_iterator; + + /// The type of an iterator into the range. + typedef const_iterator iterator; + + /// Type used to represent the distance between two iterators in the range. + typedef std::ptrdiff_t difference_type; + + /// Type used to represent a count of the elements in the range. + typedef std::size_t size_type; + + /// Default constructor creates an empty range. + basic_resolver_results() + { + } + + /// Copy constructor. + basic_resolver_results(const basic_resolver_results& other) + : basic_resolver_iterator<InternetProtocol>(other) + { + } + +#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) + /// Move constructor. + basic_resolver_results(basic_resolver_results&& other) + : basic_resolver_iterator<InternetProtocol>( + ASIO_MOVE_CAST(basic_resolver_results)(other)) + { + } +#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) + + /// Assignment operator. + basic_resolver_results& operator=(const basic_resolver_results& other) + { + basic_resolver_iterator<InternetProtocol>::operator=(other); + return *this; + } + +#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) + /// Move-assignment operator. + basic_resolver_results& operator=(basic_resolver_results&& other) + { + basic_resolver_iterator<InternetProtocol>::operator=( + ASIO_MOVE_CAST(basic_resolver_results)(other)); + return *this; + } +#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) + +#if !defined(GENERATING_DOCUMENTATION) + // Create results from an addrinfo list returned by getaddrinfo. + static basic_resolver_results create( + asio::detail::addrinfo_type* address_info, + const std::string& host_name, const std::string& service_name) + { + basic_resolver_results results; + if (!address_info) + return results; + + std::string actual_host_name = host_name; + if (address_info->ai_canonname) + actual_host_name = address_info->ai_canonname; + + results.values_.reset(new values_type); + + while (address_info) + { + if (address_info->ai_family == ASIO_OS_DEF(AF_INET) + || address_info->ai_family == ASIO_OS_DEF(AF_INET6)) + { + using namespace std; // For memcpy. + typename InternetProtocol::endpoint endpoint; + endpoint.resize(static_cast<std::size_t>(address_info->ai_addrlen)); + memcpy(endpoint.data(), address_info->ai_addr, + address_info->ai_addrlen); + results.values_->push_back( + basic_resolver_entry<InternetProtocol>(endpoint, + actual_host_name, service_name)); + } + address_info = address_info->ai_next; + } + + return results; + } + + // Create results from an endpoint, host name and service name. + static basic_resolver_results create(const endpoint_type& endpoint, + const std::string& host_name, const std::string& service_name) + { + basic_resolver_results results; + results.values_.reset(new values_type); + results.values_->push_back( + basic_resolver_entry<InternetProtocol>( + endpoint, host_name, service_name)); + return results; + } + + // Create results from a sequence of endpoints, host and service name. + template <typename EndpointIterator> + static basic_resolver_results create( + EndpointIterator begin, EndpointIterator end, + const std::string& host_name, const std::string& service_name) + { + basic_resolver_results results; + if (begin != end) + { + results.values_.reset(new values_type); + for (EndpointIterator ep_iter = begin; ep_iter != end; ++ep_iter) + { + results.values_->push_back( + basic_resolver_entry<InternetProtocol>( + *ep_iter, host_name, service_name)); + } + } + return results; + } + +# if defined(ASIO_WINDOWS_RUNTIME) + // Create results from a Windows Runtime list of EndpointPair objects. + static basic_resolver_results create( + Windows::Foundation::Collections::IVectorView< + Windows::Networking::EndpointPair^>^ endpoints, + const asio::detail::addrinfo_type& hints, + const std::string& host_name, const std::string& service_name) + { + basic_resolver_results results; + if (endpoints->Size) + { + results.values_.reset(new values_type); + for (unsigned int i = 0; i < endpoints->Size; ++i) + { + auto pair = endpoints->GetAt(i); + + if (hints.ai_family == ASIO_OS_DEF(AF_INET) + && pair->RemoteHostName->Type + != Windows::Networking::HostNameType::Ipv4) + continue; + + if (hints.ai_family == ASIO_OS_DEF(AF_INET6) + && pair->RemoteHostName->Type + != Windows::Networking::HostNameType::Ipv6) + continue; + + results.values_->push_back( + basic_resolver_entry<InternetProtocol>( + typename InternetProtocol::endpoint( + ip::make_address( + asio::detail::winrt_utils::string( + pair->RemoteHostName->CanonicalName)), + asio::detail::winrt_utils::integer( + pair->RemoteServiceName)), + host_name, service_name)); + } + } + return results; + } +# endif // defined(ASIO_WINDOWS_RUNTIME) +#endif // !defined(GENERATING_DOCUMENTATION) + + /// Get the number of entries in the results range. + size_type size() const ASIO_NOEXCEPT + { + return this->values_->size(); + } + + /// Get the maximum number of entries permitted in a results range. + size_type max_size() const ASIO_NOEXCEPT + { + return this->values_->max_size(); + } + + /// Determine whether the results range is empty. + bool empty() const ASIO_NOEXCEPT + { + return this->values_->empty(); + } + + /// Obtain a begin iterator for the results range. + const_iterator begin() const + { + basic_resolver_results tmp(*this); + tmp.index_ = 0; + return tmp; + } + + /// Obtain an end iterator for the results range. + const_iterator end() const + { + basic_resolver_results tmp(*this); + tmp.index_ = size(); + return tmp; + } + + /// Obtain a begin iterator for the results range. + const_iterator cbegin() const + { + return begin(); + } + + /// Obtain an end iterator for the results range. + const_iterator cend() const + { + return end(); + } + + /// Swap the results range with another. + void swap(basic_resolver_results& that) ASIO_NOEXCEPT + { + if (this != &that) + { + this->values_.swap(that.values_); + std::size_t index = this->index_; + this->index_ = that.index_; + that.index_ = index; + } + } + + /// Test two iterators for equality. + friend bool operator==(const basic_resolver_results& a, + const basic_resolver_results& b) + { + return a.equal(b); + } + + /// Test two iterators for inequality. + friend bool operator!=(const basic_resolver_results& a, + const basic_resolver_results& b) + { + return !a.equal(b); + } + +private: + typedef std::vector<basic_resolver_entry<InternetProtocol> > values_type; +}; + +} // namespace ip +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_IP_BASIC_RESOLVER_RESULTS_HPP
diff --git a/asio/include/asio/ip/resolver_service.hpp b/asio/include/asio/ip/resolver_service.hpp index 3255497..3b78f10 100644 --- a/asio/include/asio/ip/resolver_service.hpp +++ b/asio/include/asio/ip/resolver_service.hpp
@@ -21,6 +21,7 @@ #include "asio/io_service.hpp" #include "asio/ip/basic_resolver_iterator.hpp" #include "asio/ip/basic_resolver_query.hpp" +#include "asio/ip/basic_resolver_results.hpp" #if defined(ASIO_WINDOWS_RUNTIME) # include "asio/detail/winrt_resolver_service.hpp" @@ -61,6 +62,9 @@ /// The iterator type. typedef basic_resolver_iterator<InternetProtocol> iterator_type; + /// The results type. + typedef basic_resolver_results<InternetProtocol> results_type; + private: // The type of the platform-specific implementation. #if defined(ASIO_WINDOWS_RUNTIME) @@ -106,7 +110,7 @@ } /// Resolve a query to a list of entries. - iterator_type resolve(implementation_type& impl, const query_type& query, + results_type resolve(implementation_type& impl, const query_type& query, asio::error_code& ec) { return service_impl_.resolve(impl, query, ec); @@ -115,12 +119,12 @@ /// Asynchronously resolve a query to a list of entries. template <typename ResolveHandler> ASIO_INITFN_RESULT_TYPE(ResolveHandler, - void (asio::error_code, iterator_type)) + void (asio::error_code, results_type)) async_resolve(implementation_type& impl, const query_type& query, ASIO_MOVE_ARG(ResolveHandler) handler) { asio::async_completion<ResolveHandler, - void (asio::error_code, iterator_type)> init(handler); + void (asio::error_code, results_type)> init(handler); service_impl_.async_resolve(impl, query, init.handler); @@ -128,7 +132,7 @@ } /// Resolve an endpoint to a list of entries. - iterator_type resolve(implementation_type& impl, + results_type resolve(implementation_type& impl, const endpoint_type& endpoint, asio::error_code& ec) { return service_impl_.resolve(impl, endpoint, ec); @@ -137,12 +141,12 @@ /// Asynchronously resolve an endpoint to a list of entries. template <typename ResolveHandler> ASIO_INITFN_RESULT_TYPE(ResolveHandler, - void (asio::error_code, iterator_type)) + void (asio::error_code, results_type)) async_resolve(implementation_type& impl, const endpoint_type& endpoint, ASIO_MOVE_ARG(ResolveHandler) handler) { asio::async_completion<ResolveHandler, - void (asio::error_code, iterator_type)> init(handler); + void (asio::error_code, results_type)> init(handler); service_impl_.async_resolve(impl, endpoint, init.handler);
diff --git a/asio/include/asio/placeholders.hpp b/asio/include/asio/placeholders.hpp index 011cf26..8c7a4e5 100644 --- a/asio/include/asio/placeholders.hpp +++ b/asio/include/asio/placeholders.hpp
@@ -40,10 +40,20 @@ /// An argument placeholder, for use with boost::bind(), that corresponds to /// the iterator argument of a handler for asynchronous functions such as -/// asio::basic_resolver::async_resolve. +/// asio::async_connect. unspecified iterator; /// An argument placeholder, for use with boost::bind(), that corresponds to +/// the results argument of a handler for asynchronous functions such as +/// asio::basic_resolver::async_resolve. +unspecified results; + +/// An argument placeholder, for use with boost::bind(), that corresponds to +/// the results argument of a handler for asynchronous functions such as +/// asio::async_connect. +unspecified endpoint; + +/// An argument placeholder, for use with boost::bind(), that corresponds to /// the signal_number argument of a handler for asynchronous functions such as /// asio::signal_set::async_wait. unspecified signal_number; @@ -66,6 +76,16 @@ return boost::arg<2>(); } +inline boost::arg<2> results() +{ + return boost::arg<2>(); +} + +inline boost::arg<2> endpoint() +{ + return boost::arg<2>(); +} + inline boost::arg<2> signal_number() { return boost::arg<2>(); @@ -94,6 +114,10 @@ = asio::placeholders::detail::placeholder<2>::get(); static boost::arg<2>& iterator = asio::placeholders::detail::placeholder<2>::get(); +static boost::arg<2>& results + = asio::placeholders::detail::placeholder<2>::get(); +static boost::arg<2>& endpoint + = asio::placeholders::detail::placeholder<2>::get(); static boost::arg<2>& signal_number = asio::placeholders::detail::placeholder<2>::get(); @@ -107,6 +131,10 @@ = asio::placeholders::detail::placeholder<2>::get(); boost::arg<2>& iterator = asio::placeholders::detail::placeholder<2>::get(); + boost::arg<2>& results + = asio::placeholders::detail::placeholder<2>::get(); + boost::arg<2>& endpoint + = asio::placeholders::detail::placeholder<2>::get(); boost::arg<2>& signal_number = asio::placeholders::detail::placeholder<2>::get(); } // namespace
diff --git a/asio/src/doc/quickref.xml b/asio/src/doc/quickref.xml index d193583..5d9d0c7 100644 --- a/asio/src/doc/quickref.xml +++ b/asio/src/doc/quickref.xml
@@ -90,8 +90,10 @@ <bridgehead renderas="sect3">Boost.Bind Placeholders</bridgehead> <simplelist type="vert" columns="1"> <member><link linkend="asio.reference.placeholders__bytes_transferred">placeholders::bytes_transferred</link></member> + <member><link linkend="asio.reference.placeholders__endpoint">placeholders::endpoint</link></member> <member><link linkend="asio.reference.placeholders__error">placeholders::error</link></member> <member><link linkend="asio.reference.placeholders__iterator">placeholders::iterator</link></member> + <member><link linkend="asio.reference.placeholders__results">placeholders::results</link></member> <member><link linkend="asio.reference.placeholders__signal_number">placeholders::signal_number</link></member> </simplelist> </entry>
diff --git a/asio/src/doc/reference.xsl b/asio/src/doc/reference.xsl index eb8dc5e..effb691 100644 --- a/asio/src/doc/reference.xsl +++ b/asio/src/doc/reference.xsl
@@ -45,7 +45,6 @@ [include requirements/AsyncWriteStream.qbk] [include requirements/BufferedHandshakeHandler.qbk] [include requirements/CompletionHandler.qbk] -[include requirements/ComposedConnectHandler.qbk] [include requirements/ConnectHandler.qbk] [include requirements/ConstBufferSequence.qbk] [include requirements/ConvertibleToConstBuffer.qbk] @@ -63,10 +62,12 @@ [include requirements/InternetProtocol.qbk] [include requirements/IoControlCommand.qbk] [include requirements/IoObjectService.qbk] +[include requirements/IteratorConnectHandler.qbk] [include requirements/MutableBufferSequence.qbk] [include requirements/ObjectHandleService.qbk] [include requirements/Protocol.qbk] [include requirements/RandomAccessHandleService.qbk] +[include requirements/RangeConnectHandler.qbk] [include requirements/RawSocketService.qbk] [include requirements/ReadHandler.qbk] [include requirements/ResolveHandler.qbk]
diff --git a/asio/src/doc/requirements/ComposedConnectHandler.qbk b/asio/src/doc/requirements/IteratorConnectHandler.qbk similarity index 74% rename from asio/src/doc/requirements/ComposedConnectHandler.qbk rename to asio/src/doc/requirements/IteratorConnectHandler.qbk index 053d5a5..4cfe12c 100644 --- a/asio/src/doc/requirements/ComposedConnectHandler.qbk +++ b/asio/src/doc/requirements/IteratorConnectHandler.qbk
@@ -5,17 +5,17 @@ / file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) /] -[section:ComposedConnectHandler Composed connect handler requirements] +[section:IteratorConnectHandler Iterator connect handler requirements] -A composed connect handler must meet the requirements for a [link -asio.reference.Handler handler]. A value `h` of a composed connect handler +An iterator connect handler must meet the requirements for a [link +asio.reference.Handler handler]. A value `h` of an iterator connect handler class should work correctly in the expression `h(ec, i)`, where `ec` is an lvalue of type `const error_code` and `i` is an lvalue of the type `Iterator` used in the corresponding `connect()` or async_connect()` function. [heading Examples] -A free function as a composed connect handler: +A free function as an iterator connect handler: void connect_handler( const asio::error_code& ec, @@ -24,7 +24,7 @@ ... } -A composed connect handler function object: +An iterator connect handler function object: struct connect_handler { @@ -39,7 +39,8 @@ ... }; -A non-static class member function adapted to a composed connect handler using `bind()`: +A non-static class member function adapted to an iterator connect handler using +`bind()`: void my_class::connect_handler( const asio::error_code& ec,
diff --git a/asio/src/doc/requirements/RangeConnectHandler.qbk b/asio/src/doc/requirements/RangeConnectHandler.qbk new file mode 100644 index 0000000..fcdc98b --- /dev/null +++ b/asio/src/doc/requirements/RangeConnectHandler.qbk
@@ -0,0 +1,58 @@ +[/ + / Copyright (c) 2003-2015 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) + /] + +[section:RangeConnectHandler Range connect handler requirements] + +A range connect handler must meet the requirements for a [link +asio.reference.Handler handler]. A value `h` of a range connect handler class +should work correctly in the expression `h(ec, ep)`, where `ec` is an lvalue of +type `const error_code` and `ep` is an lvalue of the type `Protocol::endpoint` +for the `Protocol` type in the corresponding `connect()` or async_connect()` +function. + +[heading Examples] + +A free function as a range connect handler: + + void connect_handler( + const asio::error_code& ec, + const asio::ip::tcp::endpoint& endpoint) + { + ... + } + +A range connect handler function object: + + struct connect_handler + { + ... + template <typename Range> + void operator()( + const asio::error_code& ec, + const asio::ip::tcp::endpoint& endpoint) + { + ... + } + ... + }; + +A non-static class member function adapted to a range connect handler using +`bind()`: + + void my_class::connect_handler( + const asio::error_code& ec, + const asio::ip::tcp::endpoint& endpoint) + { + ... + } + ... + asio::async_connect(..., + boost::bind(&my_class::connect_handler, + this, asio::placeholders::error, + asio::placeholders::endpoint)); + +[endsect]
diff --git a/asio/src/doc/requirements/ResolveHandler.qbk b/asio/src/doc/requirements/ResolveHandler.qbk index d4ae25c..709c8a1 100644 --- a/asio/src/doc/requirements/ResolveHandler.qbk +++ b/asio/src/doc/requirements/ResolveHandler.qbk
@@ -7,13 +7,13 @@ [section:ResolveHandler Resolve handler requirements] -A resolve handler must meet the requirements for a [link -asio.reference.Handler handler]. A value `h` of a resolve handler -class should work correctly in the expression `h(ec, i)`, where `ec` is an -lvalue of type `const error_code` and `i` is an lvalue of type `const -ip::basic_resolver_iterator<InternetProtocol>`. `InternetProtocol` is the -template parameter of the [link asio.reference.ip__resolver_service -`resolver_service`] which is used to initiate the asynchronous operation. +A resolve handler must meet the requirements for a [link asio.reference.Handler +handler]. A value `h` of a resolve handler class should work correctly in the +expression `h(ec, r)`, where `ec` is an lvalue of type `const error_code` and +`r` is an lvalue of type `const ip::basic_resolver_results<InternetProtocol>`. +`InternetProtocol` is the template parameter of the [link +asio.reference.ip__resolver_service `resolver_service`] which is used to +initiate the asynchronous operation. [heading Examples] @@ -21,7 +21,7 @@ void resolve_handler( const asio::error_code& ec, - asio::ip::tcp::resolver::iterator iterator) + asio::ip::tcp::resolver::results_type results) { ... } @@ -33,7 +33,7 @@ ... void operator()( const asio::error_code& ec, - asio::ip::tcp::resolver::iterator iterator) + asio::ip::tcp::resolver::results_type results) { ... } @@ -44,7 +44,7 @@ void my_class::resolve_handler( const asio::error_code& ec, - asio::ip::tcp::resolver::iterator iterator) + asio::ip::tcp::resolver::results_type results) { ... } @@ -52,6 +52,6 @@ resolver.async_resolve(..., boost::bind(&my_class::resolve_handler, this, asio::placeholders::error, - asio::placeholders::iterator)); + asio::placeholders::results)); [endsect]
diff --git a/asio/src/examples/cpp03/chat/chat_client.cpp b/asio/src/examples/cpp03/chat/chat_client.cpp index 16849c5..206dea2 100644 --- a/asio/src/examples/cpp03/chat/chat_client.cpp +++ b/asio/src/examples/cpp03/chat/chat_client.cpp
@@ -23,11 +23,11 @@ { public: chat_client(asio::io_service& io_service, - tcp::resolver::iterator endpoint_iterator) + const tcp::resolver::results_type& endpoints) : io_service_(io_service), socket_(io_service) { - asio::async_connect(socket_, endpoint_iterator, + asio::async_connect(socket_, endpoints, boost::bind(&chat_client::handle_connect, this, asio::placeholders::error)); } @@ -149,9 +149,9 @@ tcp::resolver resolver(io_service); tcp::resolver::query query(argv[1], argv[2]); - tcp::resolver::iterator iterator = resolver.resolve(query); + tcp::resolver::results_type endpoints = resolver.resolve(query); - chat_client c(io_service, iterator); + chat_client c(io_service, endpoints); asio::thread t(boost::bind(&asio::io_service::run, &io_service));
diff --git a/asio/src/examples/cpp03/chat/posix_chat_client.cpp b/asio/src/examples/cpp03/chat/posix_chat_client.cpp index 2ddf079..3185d5d 100644 --- a/asio/src/examples/cpp03/chat/posix_chat_client.cpp +++ b/asio/src/examples/cpp03/chat/posix_chat_client.cpp
@@ -25,13 +25,13 @@ { public: posix_chat_client(asio::io_service& io_service, - tcp::resolver::iterator endpoint_iterator) + const tcp::resolver::results_type& endpoints) : socket_(io_service), input_(io_service, ::dup(STDIN_FILENO)), output_(io_service, ::dup(STDOUT_FILENO)), input_buffer_(chat_message::max_body_length) { - asio::async_connect(socket_, endpoint_iterator, + asio::async_connect(socket_, endpoints, boost::bind(&posix_chat_client::handle_connect, this, asio::placeholders::error)); } @@ -186,9 +186,9 @@ tcp::resolver resolver(io_service); tcp::resolver::query query(argv[1], argv[2]); - tcp::resolver::iterator iterator = resolver.resolve(query); + tcp::resolver::results_type endpoints = resolver.resolve(query); - posix_chat_client c(io_service, iterator); + posix_chat_client c(io_service, endpoints); io_service.run(); }
diff --git a/asio/src/examples/cpp03/echo/blocking_tcp_echo_client.cpp b/asio/src/examples/cpp03/echo/blocking_tcp_echo_client.cpp index 24d4c97..fda4baa 100644 --- a/asio/src/examples/cpp03/echo/blocking_tcp_echo_client.cpp +++ b/asio/src/examples/cpp03/echo/blocking_tcp_echo_client.cpp
@@ -31,10 +31,10 @@ tcp::resolver resolver(io_service); tcp::resolver::query query(tcp::v4(), argv[1], argv[2]); - tcp::resolver::iterator iterator = resolver.resolve(query); + tcp::resolver::results_type endpoints = resolver.resolve(query); tcp::socket s(io_service); - asio::connect(s, iterator); + asio::connect(s, endpoints); using namespace std; // For strlen. std::cout << "Enter message: ";
diff --git a/asio/src/examples/cpp03/http/client/async_client.cpp b/asio/src/examples/cpp03/http/client/async_client.cpp index f660ccd..a1c6009 100644 --- a/asio/src/examples/cpp03/http/client/async_client.cpp +++ b/asio/src/examples/cpp03/http/client/async_client.cpp
@@ -40,18 +40,18 @@ resolver_.async_resolve(query, boost::bind(&client::handle_resolve, this, asio::placeholders::error, - asio::placeholders::iterator)); + asio::placeholders::results)); } private: void handle_resolve(const asio::error_code& err, - tcp::resolver::iterator endpoint_iterator) + const tcp::resolver::results_type& endpoints) { if (!err) { // Attempt a connection to each endpoint in the list until we // successfully establish a connection. - asio::async_connect(socket_, endpoint_iterator, + asio::async_connect(socket_, endpoints, boost::bind(&client::handle_connect, this, asio::placeholders::error)); }
diff --git a/asio/src/examples/cpp03/http/client/sync_client.cpp b/asio/src/examples/cpp03/http/client/sync_client.cpp index 8e1bcfa..37d7300 100644 --- a/asio/src/examples/cpp03/http/client/sync_client.cpp +++ b/asio/src/examples/cpp03/http/client/sync_client.cpp
@@ -33,11 +33,11 @@ // Get a list of endpoints corresponding to the server name. tcp::resolver resolver(io_service); tcp::resolver::query query(argv[1], "http"); - tcp::resolver::iterator endpoint_iterator = resolver.resolve(query); + tcp::resolver::results_type endpoints = resolver.resolve(query); // Try each endpoint until we successfully establish a connection. tcp::socket socket(io_service); - asio::connect(socket, endpoint_iterator); + asio::connect(socket, endpoints); // Form the request. We specify the "Connection: close" header so that the // server will close the socket after transmitting the response. This will
diff --git a/asio/src/examples/cpp03/services/daytime_client.cpp b/asio/src/examples/cpp03/services/daytime_client.cpp index 6a70ccb..f915465 100644 --- a/asio/src/examples/cpp03/services/daytime_client.cpp +++ b/asio/src/examples/cpp03/services/daytime_client.cpp
@@ -65,11 +65,11 @@ // Resolve the address corresponding to the given host. asio::ip::tcp::resolver resolver(io_service); asio::ip::tcp::resolver::query query(argv[1], "daytime"); - asio::ip::tcp::resolver::iterator iterator = resolver.resolve(query); + asio::ip::tcp::resolver::results_type endpoints = resolver.resolve(query); // Start an asynchronous connect. debug_stream_socket socket(io_service); - asio::async_connect(socket, iterator, + asio::async_connect(socket, endpoints, boost::bind(connect_handler, asio::placeholders::error, &socket));
diff --git a/asio/src/examples/cpp03/socks4/sync_client.cpp b/asio/src/examples/cpp03/socks4/sync_client.cpp index 73e86a7..feea82a 100644 --- a/asio/src/examples/cpp03/socks4/sync_client.cpp +++ b/asio/src/examples/cpp03/socks4/sync_client.cpp
@@ -36,12 +36,12 @@ // Get a list of endpoints corresponding to the SOCKS 4 server name. tcp::resolver resolver(io_service); tcp::resolver::query socks_query(argv[1], argv[2]); - tcp::resolver::iterator endpoint_iterator = resolver.resolve(socks_query); + tcp::resolver::results_type endpoints = resolver.resolve(socks_query); // Try each endpoint until we successfully establish a connection to the // SOCKS 4 server. tcp::socket socket(io_service); - asio::connect(socket, endpoint_iterator); + asio::connect(socket, endpoints); // Get an endpoint for the Boost website. This will be passed to the SOCKS // 4 server. Explicitly specify IPv4 since SOCKS 4 does not support IPv6.
diff --git a/asio/src/examples/cpp03/ssl/client.cpp b/asio/src/examples/cpp03/ssl/client.cpp index e31e19c..5c2fa7a 100644 --- a/asio/src/examples/cpp03/ssl/client.cpp +++ b/asio/src/examples/cpp03/ssl/client.cpp
@@ -21,14 +21,14 @@ public: client(asio::io_service& io_service, asio::ssl::context& context, - asio::ip::tcp::resolver::iterator endpoint_iterator) + asio::ip::tcp::resolver::results_type endpoints) : socket_(io_service, context) { socket_.set_verify_mode(asio::ssl::verify_peer); socket_.set_verify_callback( boost::bind(&client::verify_certificate, this, _1, _2)); - asio::async_connect(socket_.lowest_layer(), endpoint_iterator, + asio::async_connect(socket_.lowest_layer(), endpoints, boost::bind(&client::handle_connect, this, asio::placeholders::error)); } @@ -138,12 +138,13 @@ asio::ip::tcp::resolver resolver(io_service); asio::ip::tcp::resolver::query query(argv[1], argv[2]); - asio::ip::tcp::resolver::iterator iterator = resolver.resolve(query); + asio::ip::tcp::resolver::results_type endpoints = + resolver.resolve(query); asio::ssl::context ctx(asio::ssl::context::sslv23); ctx.load_verify_file("ca.pem"); - client c(io_service, ctx, iterator); + client c(io_service, ctx, endpoints); io_service.run(); }
diff --git a/asio/src/examples/cpp03/timeouts/blocking_tcp_client.cpp b/asio/src/examples/cpp03/timeouts/blocking_tcp_client.cpp index ee242d5..3ad630d 100644 --- a/asio/src/examples/cpp03/timeouts/blocking_tcp_client.cpp +++ b/asio/src/examples/cpp03/timeouts/blocking_tcp_client.cpp
@@ -72,7 +72,8 @@ { // Resolve the host name and service to a list of endpoints. tcp::resolver::query query(host, service); - tcp::resolver::iterator iter = tcp::resolver(io_service_).resolve(query); + tcp::resolver::results_type endpoints = + tcp::resolver(io_service_).resolve(query); // Set a deadline for the asynchronous operation. As a host name may // resolve to multiple endpoints, this function uses the composed operation @@ -91,7 +92,7 @@ // object is used as a callback and will update the ec variable when the // operation completes. The blocking_udp_client.cpp example shows how you // can use boost::bind rather than boost::lambda. - asio::async_connect(socket_, iter, var(ec) = _1); + asio::async_connect(socket_, endpoints, var(ec) = _1); // Block until the asynchronous operation has completed. do io_service_.run_one(); while (ec == asio::error::would_block);
diff --git a/asio/src/examples/cpp03/tutorial/daytime1/client.cpp b/asio/src/examples/cpp03/tutorial/daytime1/client.cpp index 263b2c5..2d3c64f 100644 --- a/asio/src/examples/cpp03/tutorial/daytime1/client.cpp +++ b/asio/src/examples/cpp03/tutorial/daytime1/client.cpp
@@ -28,10 +28,10 @@ tcp::resolver resolver(io_service); tcp::resolver::query query(argv[1], "daytime"); - tcp::resolver::iterator endpoint_iterator = resolver.resolve(query); + tcp::resolver::results_type endpoints = resolver.resolve(query); tcp::socket socket(io_service); - asio::connect(socket, endpoint_iterator); + asio::connect(socket, endpoints); for (;;) {
diff --git a/asio/src/examples/cpp11/chat/chat_client.cpp b/asio/src/examples/cpp11/chat/chat_client.cpp index 900cbf0..8163038 100644 --- a/asio/src/examples/cpp11/chat/chat_client.cpp +++ b/asio/src/examples/cpp11/chat/chat_client.cpp
@@ -23,11 +23,11 @@ { public: chat_client(asio::io_service& io_service, - tcp::resolver::iterator endpoint_iterator) + const tcp::resolver::results_type& endpoints) : io_service_(io_service), socket_(io_service) { - do_connect(endpoint_iterator); + do_connect(endpoints); } void write(const chat_message& msg) @@ -50,10 +50,10 @@ } private: - void do_connect(tcp::resolver::iterator endpoint_iterator) + void do_connect(const tcp::resolver::results_type& endpoints) { - asio::async_connect(socket_, endpoint_iterator, - [this](std::error_code ec, tcp::resolver::iterator) + asio::async_connect(socket_, endpoints, + [this](std::error_code ec, tcp::endpoint) { if (!ec) {
diff --git a/asio/src/examples/cpp11/futures/daytime_client.cpp b/asio/src/examples/cpp11/futures/daytime_client.cpp index 8dda1c8..0d40052 100644 --- a/asio/src/examples/cpp11/futures/daytime_client.cpp +++ b/asio/src/examples/cpp11/futures/daytime_client.cpp
@@ -24,7 +24,7 @@ { udp::resolver resolver(io_service); - std::future<udp::resolver::iterator> iter = + std::future<udp::resolver::results_type> iter = resolver.async_resolve( {udp::v4(), hostname, "daytime"}, asio::use_future);
diff --git a/asio/src/tests/performance/client.cpp b/asio/src/tests/performance/client.cpp index a9ec9c4..25231ef 100644 --- a/asio/src/tests/performance/client.cpp +++ b/asio/src/tests/performance/client.cpp
@@ -74,9 +74,9 @@ delete[] write_data_; } - void start(asio::ip::tcp::resolver::iterator endpoint_iterator) + void start(asio::ip::tcp::resolver::results_type endpoints) { - asio::async_connect(socket_, endpoint_iterator, + asio::async_connect(socket_, endpoints, asio::wrap(strand_,boost::bind(&session::handle_connect, this, asio::placeholders::error))); } @@ -190,7 +190,7 @@ { public: client(asio::io_service& ios, - const asio::ip::tcp::resolver::iterator endpoint_iterator, + const asio::ip::tcp::resolver::results_type endpoints, size_t block_size, size_t session_count, int timeout) : io_service_(ios), stop_timer_(ios), @@ -203,7 +203,7 @@ for (size_t i = 0; i < session_count; ++i) { session* new_session = new session(io_service_, block_size, stats_); - new_session->start(endpoint_iterator); + new_session->start(endpoints); sessions_.push_back(new_session); } } @@ -254,10 +254,10 @@ asio::io_service ios; asio::ip::tcp::resolver r(ios); - asio::ip::tcp::resolver::iterator iter = + asio::ip::tcp::resolver::results_type endpoints = r.resolve(asio::ip::tcp::resolver::query(host, port)); - client c(ios, iter, block_size, session_count, timeout); + client c(ios, endpoints, block_size, session_count, timeout); std::list<asio::thread*> threads; while (--thread_count > 0)
diff --git a/asio/src/tests/unit/ip/tcp.cpp b/asio/src/tests/unit/ip/tcp.cpp index c7b7c0d..f20a385 100644 --- a/asio/src/tests/unit/ip/tcp.cpp +++ b/asio/src/tests/unit/ip/tcp.cpp
@@ -960,7 +960,7 @@ { resolve_handler() {} void operator()(const asio::error_code&, - asio::ip::tcp::resolver::iterator) {} + asio::ip::tcp::resolver::results_type) {} #if defined(ASIO_HAS_MOVE) resolve_handler(resolve_handler&&) {} private: @@ -994,16 +994,16 @@ resolver.cancel(); - ip::tcp::resolver::iterator iter1 = resolver.resolve(q); + ip::tcp::resolver::results_type iter1 = resolver.resolve(q); (void)iter1; - ip::tcp::resolver::iterator iter2 = resolver.resolve(q, ec); + ip::tcp::resolver::results_type iter2 = resolver.resolve(q, ec); (void)iter2; - ip::tcp::resolver::iterator iter3 = resolver.resolve(e); + ip::tcp::resolver::results_type iter3 = resolver.resolve(e); (void)iter3; - ip::tcp::resolver::iterator iter4 = resolver.resolve(e, ec); + ip::tcp::resolver::results_type iter4 = resolver.resolve(e, ec); (void)iter4; resolver.async_resolve(q, resolve_handler());
diff --git a/asio/src/tests/unit/ip/udp.cpp b/asio/src/tests/unit/ip/udp.cpp index 4c72ede..7e28ffa 100644 --- a/asio/src/tests/unit/ip/udp.cpp +++ b/asio/src/tests/unit/ip/udp.cpp
@@ -516,7 +516,7 @@ { resolve_handler() {} void operator()(const asio::error_code&, - asio::ip::udp::resolver::iterator) {} + asio::ip::udp::resolver::results_type) {} #if defined(ASIO_HAS_MOVE) resolve_handler(resolve_handler&&) {} private: @@ -550,16 +550,16 @@ resolver.cancel(); - ip::udp::resolver::iterator iter1 = resolver.resolve(q); + ip::udp::resolver::results_type iter1 = resolver.resolve(q); (void)iter1; - ip::udp::resolver::iterator iter2 = resolver.resolve(q, ec); + ip::udp::resolver::results_type iter2 = resolver.resolve(q, ec); (void)iter2; - ip::udp::resolver::iterator iter3 = resolver.resolve(e); + ip::udp::resolver::results_type iter3 = resolver.resolve(e); (void)iter3; - ip::udp::resolver::iterator iter4 = resolver.resolve(e, ec); + ip::udp::resolver::results_type iter4 = resolver.resolve(e, ec); (void)iter4; resolver.async_resolve(q, resolve_handler());