Add new free functions connect() and async_connect(). These try
each endpoint in a list until the socket is successfully connected.
This commit is contained in:
parent
f8d583bbb5
commit
066e739628
@ -21,6 +21,7 @@ nobase_include_HEADERS = \
|
||||
asio/buffer.hpp \
|
||||
asio/buffers_iterator.hpp \
|
||||
asio/completion_condition.hpp \
|
||||
asio/connect.hpp \
|
||||
asio/datagram_socket_service.hpp \
|
||||
asio/deadline_timer.hpp \
|
||||
asio/deadline_timer_service.hpp \
|
||||
@ -200,6 +201,7 @@ nobase_include_HEADERS = \
|
||||
asio/handler_alloc_hook.hpp \
|
||||
asio/handler_invoke_hook.hpp \
|
||||
asio.hpp \
|
||||
asio/impl/connect.hpp \
|
||||
asio/impl/error_code.ipp \
|
||||
asio/impl/error.ipp \
|
||||
asio/impl/io_service.hpp \
|
||||
|
@ -34,6 +34,7 @@
|
||||
#include "asio/buffered_write_stream.hpp"
|
||||
#include "asio/buffers_iterator.hpp"
|
||||
#include "asio/completion_condition.hpp"
|
||||
#include "asio/connect.hpp"
|
||||
#include "asio/datagram_socket_service.hpp"
|
||||
#include "asio/deadline_timer_service.hpp"
|
||||
#include "asio/deadline_timer.hpp"
|
||||
|
799
asio/include/asio/connect.hpp
Normal file
799
asio/include/asio/connect.hpp
Normal file
@ -0,0 +1,799 @@
|
||||
//
|
||||
// connect.hpp
|
||||
// ~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2011 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_CONNECT_HPP
|
||||
#define ASIO_CONNECT_HPP
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
|
||||
#include "asio/detail/config.hpp"
|
||||
#include "asio/error.hpp"
|
||||
|
||||
#include "asio/detail/push_options.hpp"
|
||||
|
||||
namespace asio {
|
||||
|
||||
/**
|
||||
* @defgroup connect asio::connect
|
||||
*
|
||||
* @brief Establishes a socket connection by trying each endpoint in a sequence.
|
||||
*/
|
||||
/*@{*/
|
||||
|
||||
/// 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
|
||||
* 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.
|
||||
*
|
||||
* @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 Socket, typename Iterator>
|
||||
Iterator connect(Socket& s, Iterator begin);
|
||||
|
||||
/// 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 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, an iterator denoting the successfully connected
|
||||
* endpoint. Otherwise, the end iterator.
|
||||
*
|
||||
* @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 Socket, typename Iterator>
|
||||
Iterator connect(Socket& s, Iterator begin, asio::error_code& ec);
|
||||
|
||||
/// 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 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.
|
||||
*
|
||||
* @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::resolver::iterator i = r.resolve(q), end;
|
||||
* tcp::socket s(io_service);
|
||||
* asio::connect(s, i, end); @endcode
|
||||
*/
|
||||
template <typename Socket, typename Iterator>
|
||||
Iterator connect(Socket& s, Iterator begin, Iterator end);
|
||||
|
||||
/// 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 end An iterator pointing to the end of 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, an iterator denoting the successfully connected
|
||||
* endpoint. Otherwise, the end iterator.
|
||||
*
|
||||
* @par Example
|
||||
* @code tcp::resolver r(io_service);
|
||||
* tcp::resolver::query q("host", "service");
|
||||
* tcp::resolver::iterator i = r.resolve(q), end;
|
||||
* tcp::socket s(io_service);
|
||||
* asio::error_code ec;
|
||||
* asio::connect(s, i, end, ec);
|
||||
* if (ec)
|
||||
* {
|
||||
* // An error occurred.
|
||||
* } @endcode
|
||||
*/
|
||||
template <typename Socket, typename Iterator>
|
||||
Iterator connect(Socket& s, Iterator begin, Iterator end,
|
||||
asio::error_code& ec);
|
||||
|
||||
/// 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(
|
||||
* const asio::error_code& ec,
|
||||
* Iterator 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.
|
||||
*
|
||||
* @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.
|
||||
*
|
||||
* @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);
|
||||
* tcp::resolver::iterator i = asio::connect(
|
||||
* s, r.resolve(q), my_connect_condition());
|
||||
* std::cout << "Connected to: " << i->endpoint() << std::endl; @endcode
|
||||
*/
|
||||
template <typename Socket, typename Iterator, typename ConnectCondition>
|
||||
Iterator connect(Socket& s, Iterator begin, ConnectCondition connect_condition);
|
||||
|
||||
/// 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(
|
||||
* const asio::error_code& ec,
|
||||
* Iterator 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.
|
||||
*
|
||||
* @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, an iterator denoting the successfully connected
|
||||
* endpoint. Otherwise, the end iterator.
|
||||
*
|
||||
* @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 Socket, typename Iterator, typename ConnectCondition>
|
||||
Iterator connect(Socket& s, Iterator begin,
|
||||
ConnectCondition connect_condition, asio::error_code& ec);
|
||||
|
||||
/// 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 end An iterator pointing to the end 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(
|
||||
* const asio::error_code& ec,
|
||||
* Iterator 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.
|
||||
*
|
||||
* @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.
|
||||
*
|
||||
* @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::resolver::iterator i = r.resolve(q), end;
|
||||
* tcp::socket s(io_service);
|
||||
* i = asio::connect(s, i, end, my_connect_condition());
|
||||
* std::cout << "Connected to: " << i->endpoint() << std::endl; @endcode
|
||||
*/
|
||||
template <typename Socket, typename Iterator, typename ConnectCondition>
|
||||
Iterator connect(Socket& s, Iterator begin, Iterator end,
|
||||
ConnectCondition connect_condition);
|
||||
|
||||
/// 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 end An iterator pointing to the end 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(
|
||||
* const asio::error_code& ec,
|
||||
* Iterator 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.
|
||||
*
|
||||
* @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, an iterator denoting the successfully connected
|
||||
* endpoint. Otherwise, the end 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::resolver::iterator i = r.resolve(q), end;
|
||||
* tcp::socket s(io_service);
|
||||
* asio::error_code ec;
|
||||
* i = asio::connect(s, i, end, my_connect_condition(), ec);
|
||||
* if (ec)
|
||||
* {
|
||||
* // An error occurred.
|
||||
* }
|
||||
* else
|
||||
* {
|
||||
* std::cout << "Connected to: " << i->endpoint() << std::endl;
|
||||
* } @endcode
|
||||
*/
|
||||
template <typename Socket, typename Iterator, typename ConnectCondition>
|
||||
Iterator connect(Socket& s, Iterator begin, Iterator end,
|
||||
ConnectCondition connect_condition, asio::error_code& ec);
|
||||
|
||||
/*@}*/
|
||||
|
||||
/**
|
||||
* @defgroup async_connect asio::async_connect
|
||||
*
|
||||
* @brief Asynchronously establishes a socket connection by trying each
|
||||
* endpoint in a sequence.
|
||||
*/
|
||||
/*@{*/
|
||||
|
||||
/// 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
|
||||
* 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.
|
||||
*
|
||||
* @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 Socket, typename Iterator, typename ComposedConnectHandler>
|
||||
void async_connect(Socket& s, Iterator begin, ComposedConnectHandler handler);
|
||||
|
||||
/// 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 end An iterator pointing to the end of 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, 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().
|
||||
*
|
||||
* @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)
|
||||
* {
|
||||
* tcp::resolver::iterator end;
|
||||
* asio::async_connect(s, i, end, connect_handler);
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* // ...
|
||||
*
|
||||
* void connect_handler(
|
||||
* const asio::error_code& ec,
|
||||
* tcp::resolver::iterator i)
|
||||
* {
|
||||
* // ...
|
||||
* } @endcode
|
||||
*/
|
||||
template <typename Socket, typename Iterator, typename ComposedConnectHandler>
|
||||
void async_connect(Socket& s, Iterator begin, Iterator end,
|
||||
ComposedConnectHandler handler);
|
||||
|
||||
/// 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 Iterator connect_condition(
|
||||
* const asio::error_code& ec,
|
||||
* Iterator 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.
|
||||
*
|
||||
* @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.
|
||||
*
|
||||
* @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);
|
||||
*
|
||||
* // ...
|
||||
*
|
||||
* 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,
|
||||
* my_connect_condition(),
|
||||
* connect_handler);
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* // ...
|
||||
*
|
||||
* void connect_handler(
|
||||
* const asio::error_code& ec,
|
||||
* tcp::resolver::iterator i)
|
||||
* {
|
||||
* if (ec)
|
||||
* {
|
||||
* // An error occurred.
|
||||
* }
|
||||
* else
|
||||
* {
|
||||
* std::cout << "Connected to: " << i->endpoint() << std::endl;
|
||||
* }
|
||||
* } @endcode
|
||||
*/
|
||||
template <typename Socket, typename Iterator,
|
||||
typename ConnectCondition, typename ComposedConnectHandler>
|
||||
void async_connect(Socket& s, Iterator begin,
|
||||
ConnectCondition connect_condition, ComposedConnectHandler handler);
|
||||
|
||||
/// 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 end An iterator pointing to the end 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(
|
||||
* const asio::error_code& ec,
|
||||
* Iterator 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.
|
||||
*
|
||||
* @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().
|
||||
*
|
||||
* @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);
|
||||
*
|
||||
* // ...
|
||||
*
|
||||
* 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,
|
||||
* my_connect_condition(),
|
||||
* connect_handler);
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* // ...
|
||||
*
|
||||
* void connect_handler(
|
||||
* const asio::error_code& ec,
|
||||
* tcp::resolver::iterator i)
|
||||
* {
|
||||
* if (ec)
|
||||
* {
|
||||
* // An error occurred.
|
||||
* }
|
||||
* else
|
||||
* {
|
||||
* std::cout << "Connected to: " << i->endpoint() << std::endl;
|
||||
* }
|
||||
* } @endcode
|
||||
*/
|
||||
template <typename Socket, typename Iterator,
|
||||
typename ConnectCondition, typename ComposedConnectHandler>
|
||||
void async_connect(Socket& s, Iterator begin, Iterator end,
|
||||
ConnectCondition connect_condition, ComposedConnectHandler handler);
|
||||
|
||||
/*@}*/
|
||||
|
||||
} // namespace asio
|
||||
|
||||
#include "asio/detail/pop_options.hpp"
|
||||
|
||||
#include "asio/impl/connect.hpp"
|
||||
|
||||
#endif
|
311
asio/include/asio/impl/connect.hpp
Normal file
311
asio/include/asio/impl/connect.hpp
Normal file
@ -0,0 +1,311 @@
|
||||
//
|
||||
// impl/connect.hpp
|
||||
// ~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2011 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_IMPL_CONNECT_HPP
|
||||
#define ASIO_IMPL_CONNECT_HPP
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
|
||||
#include "asio/detail/bind_handler.hpp"
|
||||
#include "asio/detail/consuming_buffers.hpp"
|
||||
#include "asio/detail/handler_alloc_helpers.hpp"
|
||||
#include "asio/detail/handler_invoke_helpers.hpp"
|
||||
#include "asio/detail/throw_error.hpp"
|
||||
#include "asio/error.hpp"
|
||||
|
||||
#include "asio/detail/push_options.hpp"
|
||||
|
||||
namespace asio {
|
||||
|
||||
namespace detail
|
||||
{
|
||||
struct default_connect_condition
|
||||
{
|
||||
template <typename Iterator>
|
||||
Iterator operator()(const asio::error_code&, Iterator next)
|
||||
{
|
||||
return next;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
template <typename Socket, typename Iterator>
|
||||
Iterator connect(Socket& s, Iterator begin)
|
||||
{
|
||||
asio::error_code ec;
|
||||
Iterator result = connect(s, begin, ec);
|
||||
asio::detail::throw_error(ec);
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename Socket, typename Iterator>
|
||||
inline Iterator connect(Socket& s, Iterator begin,
|
||||
asio::error_code& ec)
|
||||
{
|
||||
return connect(s, begin, Iterator(), detail::default_connect_condition(), ec);
|
||||
}
|
||||
|
||||
template <typename Socket, typename Iterator>
|
||||
Iterator connect(Socket& s, Iterator begin, Iterator end)
|
||||
{
|
||||
asio::error_code ec;
|
||||
Iterator result = connect(s, begin, end, ec);
|
||||
asio::detail::throw_error(ec);
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename Socket, typename Iterator>
|
||||
inline Iterator connect(Socket& s, Iterator begin, Iterator end,
|
||||
asio::error_code& ec)
|
||||
{
|
||||
return connect(s, begin, end, detail::default_connect_condition(), ec);
|
||||
}
|
||||
|
||||
template <typename Socket, typename Iterator, typename ConnectCondition>
|
||||
Iterator connect(Socket& s, Iterator begin,
|
||||
ConnectCondition connect_condition)
|
||||
{
|
||||
asio::error_code ec;
|
||||
Iterator result = connect(s, begin, connect_condition, ec);
|
||||
asio::detail::throw_error(ec);
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename Socket, typename Iterator, typename ConnectCondition>
|
||||
inline Iterator connect(Socket& s, Iterator begin,
|
||||
ConnectCondition connect_condition, asio::error_code& ec)
|
||||
{
|
||||
return connect(s, begin, Iterator(), connect_condition, ec);
|
||||
}
|
||||
|
||||
template <typename Socket, typename Iterator, typename ConnectCondition>
|
||||
Iterator connect(Socket& s, Iterator begin, Iterator end,
|
||||
ConnectCondition connect_condition)
|
||||
{
|
||||
asio::error_code ec;
|
||||
Iterator result = connect(s, begin, end, connect_condition, ec);
|
||||
asio::detail::throw_error(ec);
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename Socket, typename Iterator, typename ConnectCondition>
|
||||
Iterator connect(Socket& s, Iterator begin, Iterator end,
|
||||
ConnectCondition connect_condition, asio::error_code& ec)
|
||||
{
|
||||
ec = asio::error_code();
|
||||
|
||||
for (Iterator iter = begin; iter != end; ++iter)
|
||||
{
|
||||
iter = connect_condition(ec, iter);
|
||||
if (iter != end)
|
||||
{
|
||||
s.close(ec);
|
||||
s.connect(*iter, ec);
|
||||
if (!ec)
|
||||
return iter;
|
||||
}
|
||||
}
|
||||
|
||||
if (!ec)
|
||||
ec = asio::error::not_found;
|
||||
|
||||
return end;
|
||||
}
|
||||
|
||||
namespace detail
|
||||
{
|
||||
// Enable the empty base class optimisation for the connect condition.
|
||||
template <typename ConnectCondition>
|
||||
class base_from_connect_condition
|
||||
{
|
||||
protected:
|
||||
explicit base_from_connect_condition(
|
||||
const ConnectCondition& connect_condition)
|
||||
: connect_condition_(connect_condition)
|
||||
{
|
||||
}
|
||||
|
||||
template <typename Iterator>
|
||||
void check_condition(const asio::error_code& ec,
|
||||
Iterator& iter, Iterator& end)
|
||||
{
|
||||
if (iter != end)
|
||||
iter = connect_condition_(ec, static_cast<const Iterator&>(iter));
|
||||
}
|
||||
|
||||
private:
|
||||
ConnectCondition connect_condition_;
|
||||
};
|
||||
|
||||
// The default_connect_condition implementation is essentially a no-op. This
|
||||
// template specialisation lets us eliminate all costs associated with it.
|
||||
template <>
|
||||
class base_from_connect_condition<default_connect_condition>
|
||||
{
|
||||
protected:
|
||||
explicit base_from_connect_condition(const default_connect_condition&)
|
||||
{
|
||||
}
|
||||
|
||||
template <typename Iterator>
|
||||
void check_condition(const asio::error_code&, Iterator&, Iterator&)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Socket, typename Iterator,
|
||||
typename ConnectCondition, typename ComposedConnectHandler>
|
||||
class connect_op : base_from_connect_condition<ConnectCondition>
|
||||
{
|
||||
public:
|
||||
connect_op(Socket& sock,
|
||||
const Iterator& begin, const Iterator& end,
|
||||
const ConnectCondition& connect_condition,
|
||||
ComposedConnectHandler& handler)
|
||||
: base_from_connect_condition<ConnectCondition>(connect_condition),
|
||||
socket_(sock),
|
||||
iter_(begin),
|
||||
end_(end),
|
||||
handler_(ASIO_MOVE_CAST(ComposedConnectHandler)(handler))
|
||||
{
|
||||
}
|
||||
|
||||
void operator()(asio::error_code ec, int start = 0)
|
||||
{
|
||||
switch (start)
|
||||
{
|
||||
case 1:
|
||||
for (;;)
|
||||
{
|
||||
this->check_condition(ec, iter_, end_);
|
||||
|
||||
if (iter_ != end_)
|
||||
{
|
||||
socket_.close(ec);
|
||||
socket_.async_connect(*iter_, *this);
|
||||
return;
|
||||
}
|
||||
|
||||
if (start)
|
||||
{
|
||||
ec = asio::error::not_found;
|
||||
socket_.get_io_service().post(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_;
|
||||
}
|
||||
|
||||
handler_(static_cast<const asio::error_code&>(ec),
|
||||
static_cast<const Iterator&>(iter_));
|
||||
}
|
||||
}
|
||||
|
||||
//private:
|
||||
Socket& socket_;
|
||||
Iterator iter_;
|
||||
Iterator end_;
|
||||
ComposedConnectHandler handler_;
|
||||
};
|
||||
|
||||
template <typename Socket, typename Iterator,
|
||||
typename ConnectCondition, typename ComposedConnectHandler>
|
||||
inline void* asio_handler_allocate(std::size_t size,
|
||||
connect_op<Socket, Iterator, ConnectCondition,
|
||||
ComposedConnectHandler>* this_handler)
|
||||
{
|
||||
return asio_handler_alloc_helpers::allocate(
|
||||
size, this_handler->handler_);
|
||||
}
|
||||
|
||||
template <typename Socket, typename Iterator,
|
||||
typename ConnectCondition, typename ComposedConnectHandler>
|
||||
inline void asio_handler_deallocate(void* pointer, std::size_t size,
|
||||
connect_op<Socket, Iterator, ConnectCondition,
|
||||
ComposedConnectHandler>* this_handler)
|
||||
{
|
||||
asio_handler_alloc_helpers::deallocate(
|
||||
pointer, size, this_handler->handler_);
|
||||
}
|
||||
|
||||
template <typename Function, typename Socket, typename Iterator,
|
||||
typename ConnectCondition, typename ComposedConnectHandler>
|
||||
inline void asio_handler_invoke(const Function& function,
|
||||
connect_op<Socket, Iterator, ConnectCondition,
|
||||
ComposedConnectHandler>* this_handler)
|
||||
{
|
||||
asio_handler_invoke_helpers::invoke(
|
||||
function, this_handler->handler_);
|
||||
}
|
||||
} // namespace detail
|
||||
|
||||
template <typename Socket, typename Iterator, typename ComposedConnectHandler>
|
||||
inline void async_connect(Socket& s, Iterator begin,
|
||||
ComposedConnectHandler handler)
|
||||
{
|
||||
detail::connect_op<Socket, Iterator,
|
||||
detail::default_connect_condition, ComposedConnectHandler>(
|
||||
s, begin, Iterator(), detail::default_connect_condition(), handler)(
|
||||
asio::error_code(), 1);
|
||||
}
|
||||
|
||||
template <typename Socket, typename Iterator, typename ComposedConnectHandler>
|
||||
inline void async_connect(Socket& s, Iterator begin, Iterator end,
|
||||
ComposedConnectHandler handler)
|
||||
{
|
||||
detail::connect_op<Socket, Iterator,
|
||||
detail::default_connect_condition, ComposedConnectHandler>(
|
||||
s, begin, end, detail::default_connect_condition(), handler)(
|
||||
asio::error_code(), 1);
|
||||
}
|
||||
|
||||
template <typename Socket, typename Iterator,
|
||||
typename ConnectCondition, typename ComposedConnectHandler>
|
||||
inline void async_connect(Socket& s, Iterator begin,
|
||||
ConnectCondition connect_condition, ComposedConnectHandler handler)
|
||||
{
|
||||
detail::connect_op<Socket, Iterator,
|
||||
ConnectCondition, ComposedConnectHandler>(
|
||||
s, begin, Iterator(), connect_condition, handler)(
|
||||
asio::error_code(), 1);
|
||||
}
|
||||
|
||||
template <typename Socket, typename Iterator,
|
||||
typename ConnectCondition, typename ComposedConnectHandler>
|
||||
void async_connect(Socket& s, Iterator begin, Iterator end,
|
||||
ConnectCondition connect_condition, ComposedConnectHandler handler)
|
||||
{
|
||||
detail::connect_op<Socket, Iterator,
|
||||
ConnectCondition, ComposedConnectHandler>(
|
||||
s, begin, end, connect_condition, handler)(
|
||||
asio::error_code(), 1);
|
||||
}
|
||||
|
||||
} // namespace asio
|
||||
|
||||
#include "asio/detail/pop_options.hpp"
|
||||
|
||||
#endif // ASIO_IMPL_CONNECT_HPP
|
@ -22,6 +22,7 @@ check_PROGRAMS = \
|
||||
tests/unit/buffer \
|
||||
tests/unit/buffers_iterator \
|
||||
tests/unit/completion_condition \
|
||||
tests/unit/connect \
|
||||
tests/unit/datagram_socket_service \
|
||||
tests/unit/deadline_timer_service \
|
||||
tests/unit/deadline_timer \
|
||||
@ -174,6 +175,7 @@ TESTS = \
|
||||
tests/unit/buffer \
|
||||
tests/unit/buffers_iterator \
|
||||
tests/unit/completion_condition \
|
||||
tests/unit/connect \
|
||||
tests/unit/datagram_socket_service \
|
||||
tests/unit/deadline_timer_service \
|
||||
tests/unit/deadline_timer \
|
||||
@ -274,6 +276,7 @@ tests_unit_buffered_read_stream_SOURCES = tests/unit/buffered_read_stream.cpp te
|
||||
tests_unit_buffered_stream_SOURCES = tests/unit/buffered_stream.cpp tests/unit/unit_test.cpp
|
||||
tests_unit_buffered_write_stream_SOURCES = tests/unit/buffered_write_stream.cpp tests/unit/unit_test.cpp
|
||||
tests_unit_completion_condition_SOURCES = tests/unit/completion_condition.cpp tests/unit/unit_test.cpp
|
||||
tests_unit_connect_SOURCES = tests/unit/connect.cpp tests/unit/unit_test.cpp
|
||||
tests_unit_datagram_socket_service_SOURCES = tests/unit/datagram_socket_service.cpp tests/unit/unit_test.cpp
|
||||
tests_unit_deadline_timer_service_SOURCES = tests/unit/deadline_timer_service.cpp tests/unit/unit_test.cpp
|
||||
tests_unit_deadline_timer_SOURCES = tests/unit/deadline_timer.cpp tests/unit/unit_test.cpp
|
||||
|
@ -25,6 +25,7 @@ UNIT_TEST_EXES = \
|
||||
tests/unit/buffer.exe \
|
||||
tests/unit/buffers_iterator.exe \
|
||||
tests/unit/completion_condition.exe \
|
||||
tests/unit/connect.exe \
|
||||
tests/unit/datagram_socket_service.exe \
|
||||
tests/unit/deadline_timer_service.exe \
|
||||
tests/unit/deadline_timer.exe \
|
||||
|
@ -90,6 +90,7 @@ UNIT_TEST_EXES = \
|
||||
tests\unit\buffer.exe \
|
||||
tests\unit\buffers_iterator.exe \
|
||||
tests\unit\completion_condition.exe \
|
||||
tests\unit\connect.exe \
|
||||
tests\unit\datagram_socket_service.exe \
|
||||
tests\unit\deadline_timer_service.exe \
|
||||
tests\unit\deadline_timer.exe \
|
||||
|
@ -27,10 +27,9 @@ public:
|
||||
: io_service_(io_service),
|
||||
socket_(io_service)
|
||||
{
|
||||
tcp::endpoint endpoint = *endpoint_iterator;
|
||||
socket_.async_connect(endpoint,
|
||||
asio::async_connect(socket_, endpoint_iterator,
|
||||
boost::bind(&chat_client::handle_connect, this,
|
||||
asio::placeholders::error, ++endpoint_iterator));
|
||||
asio::placeholders::error));
|
||||
}
|
||||
|
||||
void write(const chat_message& msg)
|
||||
@ -45,8 +44,7 @@ public:
|
||||
|
||||
private:
|
||||
|
||||
void handle_connect(const asio::error_code& error,
|
||||
tcp::resolver::iterator endpoint_iterator)
|
||||
void handle_connect(const asio::error_code& error)
|
||||
{
|
||||
if (!error)
|
||||
{
|
||||
@ -55,14 +53,6 @@ private:
|
||||
boost::bind(&chat_client::handle_read_header, this,
|
||||
asio::placeholders::error));
|
||||
}
|
||||
else if (endpoint_iterator != tcp::resolver::iterator())
|
||||
{
|
||||
socket_.close();
|
||||
tcp::endpoint endpoint = *endpoint_iterator;
|
||||
socket_.async_connect(endpoint,
|
||||
boost::bind(&chat_client::handle_connect, this,
|
||||
asio::placeholders::error, ++endpoint_iterator));
|
||||
}
|
||||
}
|
||||
|
||||
void handle_read_header(const asio::error_code& error)
|
||||
|
@ -31,17 +31,14 @@ public:
|
||||
output_(io_service, ::dup(STDOUT_FILENO)),
|
||||
input_buffer_(chat_message::max_body_length)
|
||||
{
|
||||
// Try connecting to the first endpoint.
|
||||
tcp::endpoint endpoint = *endpoint_iterator;
|
||||
socket_.async_connect(endpoint,
|
||||
asio::async_connect(socket_, endpoint_iterator,
|
||||
boost::bind(&posix_chat_client::handle_connect, this,
|
||||
asio::placeholders::error, ++endpoint_iterator));
|
||||
asio::placeholders::error));
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
void handle_connect(const asio::error_code& error,
|
||||
tcp::resolver::iterator endpoint_iterator)
|
||||
void handle_connect(const asio::error_code& error)
|
||||
{
|
||||
if (!error)
|
||||
{
|
||||
@ -57,15 +54,6 @@ private:
|
||||
asio::placeholders::error,
|
||||
asio::placeholders::bytes_transferred));
|
||||
}
|
||||
else if (endpoint_iterator != tcp::resolver::iterator())
|
||||
{
|
||||
// That endpoint didn't work, try the next one.
|
||||
socket_.close();
|
||||
tcp::endpoint endpoint = *endpoint_iterator;
|
||||
socket_.async_connect(endpoint,
|
||||
boost::bind(&posix_chat_client::handle_connect, this,
|
||||
asio::placeholders::error, ++endpoint_iterator));
|
||||
}
|
||||
}
|
||||
|
||||
void handle_read_header(const asio::error_code& error)
|
||||
|
@ -34,7 +34,7 @@ int main(int argc, char* argv[])
|
||||
tcp::resolver::iterator iterator = resolver.resolve(query);
|
||||
|
||||
tcp::socket s(io_service);
|
||||
s.connect(*iterator);
|
||||
asio::connect(s, iterator);
|
||||
|
||||
using namespace std; // For strlen.
|
||||
std::cout << "Enter message: ";
|
||||
|
@ -49,12 +49,11 @@ private:
|
||||
{
|
||||
if (!err)
|
||||
{
|
||||
// Attempt a connection to the first endpoint in the list. Each endpoint
|
||||
// will be tried until we successfully establish a connection.
|
||||
tcp::endpoint endpoint = *endpoint_iterator;
|
||||
socket_.async_connect(endpoint,
|
||||
// Attempt a connection to each endpoint in the list until we
|
||||
// successfully establish a connection.
|
||||
asio::async_connect(socket_, endpoint_iterator,
|
||||
boost::bind(&client::handle_connect, this,
|
||||
asio::placeholders::error, ++endpoint_iterator));
|
||||
asio::placeholders::error));
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -62,8 +61,7 @@ private:
|
||||
}
|
||||
}
|
||||
|
||||
void handle_connect(const asio::error_code& err,
|
||||
tcp::resolver::iterator endpoint_iterator)
|
||||
void handle_connect(const asio::error_code& err)
|
||||
{
|
||||
if (!err)
|
||||
{
|
||||
@ -72,15 +70,6 @@ private:
|
||||
boost::bind(&client::handle_write_request, this,
|
||||
asio::placeholders::error));
|
||||
}
|
||||
else if (endpoint_iterator != tcp::resolver::iterator())
|
||||
{
|
||||
// The connection failed. Try the next endpoint in the list.
|
||||
socket_.close();
|
||||
tcp::endpoint endpoint = *endpoint_iterator;
|
||||
socket_.async_connect(endpoint,
|
||||
boost::bind(&client::handle_connect, this,
|
||||
asio::placeholders::error, ++endpoint_iterator));
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << "Error: " << err.message() << "\n";
|
||||
|
@ -34,18 +34,10 @@ int main(int argc, char* argv[])
|
||||
tcp::resolver resolver(io_service);
|
||||
tcp::resolver::query query(argv[1], "http");
|
||||
tcp::resolver::iterator endpoint_iterator = resolver.resolve(query);
|
||||
tcp::resolver::iterator end;
|
||||
|
||||
// Try each endpoint until we successfully establish a connection.
|
||||
tcp::socket socket(io_service);
|
||||
asio::error_code error = asio::error::host_not_found;
|
||||
while (error && endpoint_iterator != end)
|
||||
{
|
||||
socket.close();
|
||||
socket.connect(*endpoint_iterator++, error);
|
||||
}
|
||||
if (error)
|
||||
throw asio::system_error(error);
|
||||
asio::connect(socket, endpoint_iterator);
|
||||
|
||||
// Form the request. We specify the "Connection: close" header so that the
|
||||
// server will close the socket after transmitting the response. This will
|
||||
@ -99,6 +91,7 @@ int main(int argc, char* argv[])
|
||||
std::cout << &response;
|
||||
|
||||
// Read until EOF, writing data to output as we go.
|
||||
asio::error_code error;
|
||||
while (asio::read(socket, response,
|
||||
asio::transfer_at_least(1), error))
|
||||
std::cout << &response;
|
||||
|
@ -32,17 +32,15 @@ public:
|
||||
asio::ip::tcp::resolver::query query(host, service);
|
||||
asio::ip::tcp::resolver::iterator endpoint_iterator =
|
||||
resolver.resolve(query);
|
||||
asio::ip::tcp::endpoint endpoint = *endpoint_iterator;
|
||||
|
||||
// Start an asynchronous connect operation.
|
||||
connection_.socket().async_connect(endpoint,
|
||||
asio::async_connect(connection_.socket(), endpoint_iterator,
|
||||
boost::bind(&client::handle_connect, this,
|
||||
asio::placeholders::error, ++endpoint_iterator));
|
||||
asio::placeholders::error));
|
||||
}
|
||||
|
||||
/// Handle completion of a connect operation.
|
||||
void handle_connect(const asio::error_code& e,
|
||||
asio::ip::tcp::resolver::iterator endpoint_iterator)
|
||||
void handle_connect(const asio::error_code& e)
|
||||
{
|
||||
if (!e)
|
||||
{
|
||||
@ -53,15 +51,6 @@ public:
|
||||
boost::bind(&client::handle_read, this,
|
||||
asio::placeholders::error));
|
||||
}
|
||||
else if (endpoint_iterator != asio::ip::tcp::resolver::iterator())
|
||||
{
|
||||
// Try the next endpoint.
|
||||
connection_.socket().close();
|
||||
asio::ip::tcp::endpoint endpoint = *endpoint_iterator;
|
||||
connection_.socket().async_connect(endpoint,
|
||||
boost::bind(&client::handle_connect, this,
|
||||
asio::placeholders::error, ++endpoint_iterator));
|
||||
}
|
||||
else
|
||||
{
|
||||
// An error occurred. Log it and return. Since we are not starting a new
|
||||
|
@ -32,8 +32,7 @@ void read_handler(const asio::error_code& e,
|
||||
}
|
||||
}
|
||||
|
||||
void connect_handler(const asio::error_code& e, debug_stream_socket* s,
|
||||
asio::ip::tcp::resolver::iterator endpoint_iterator)
|
||||
void connect_handler(const asio::error_code& e, debug_stream_socket* s)
|
||||
{
|
||||
if (!e)
|
||||
{
|
||||
@ -41,14 +40,6 @@ void connect_handler(const asio::error_code& e, debug_stream_socket* s,
|
||||
boost::bind(read_handler, asio::placeholders::error,
|
||||
asio::placeholders::bytes_transferred, s));
|
||||
}
|
||||
else if (endpoint_iterator != asio::ip::tcp::resolver::iterator())
|
||||
{
|
||||
s->close();
|
||||
asio::ip::tcp::endpoint endpoint = *endpoint_iterator;
|
||||
s->async_connect(endpoint,
|
||||
boost::bind(connect_handler,
|
||||
asio::placeholders::error, s, ++endpoint_iterator));
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cerr << e.message() << std::endl;
|
||||
@ -75,13 +66,12 @@ int main(int argc, char* argv[])
|
||||
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::endpoint endpoint = *iterator;
|
||||
|
||||
// Start an asynchronous connect.
|
||||
debug_stream_socket socket(io_service);
|
||||
socket.async_connect(endpoint,
|
||||
asio::async_connect(socket, iterator,
|
||||
boost::bind(connect_handler,
|
||||
asio::placeholders::error, &socket, ++iterator));
|
||||
asio::placeholders::error, &socket));
|
||||
|
||||
// Run the io_service until all operations have finished.
|
||||
io_service.run();
|
||||
|
@ -37,19 +37,11 @@ int main(int argc, char* argv[])
|
||||
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::iterator end;
|
||||
|
||||
// Try each endpoint until we successfully establish a connection to the
|
||||
// SOCKS 4 server.
|
||||
tcp::socket socket(io_service);
|
||||
asio::error_code error = asio::error::host_not_found;
|
||||
while (error && endpoint_iterator != end)
|
||||
{
|
||||
socket.close();
|
||||
socket.connect(*endpoint_iterator++, error);
|
||||
}
|
||||
if (error)
|
||||
throw asio::system_error(error);
|
||||
asio::connect(socket, endpoint_iterator);
|
||||
|
||||
// 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.
|
||||
@ -87,6 +79,7 @@ int main(int argc, char* argv[])
|
||||
|
||||
// Read until EOF, writing data to output as we go.
|
||||
boost::array<char, 512> response;
|
||||
asio::error_code error;
|
||||
while (std::size_t s = socket.read_some(
|
||||
asio::buffer(response), error))
|
||||
std::cout.write(response.data(), s);
|
||||
|
@ -23,14 +23,12 @@ public:
|
||||
asio::ip::tcp::resolver::iterator endpoint_iterator)
|
||||
: socket_(io_service, context)
|
||||
{
|
||||
asio::ip::tcp::endpoint endpoint = *endpoint_iterator;
|
||||
socket_.lowest_layer().async_connect(endpoint,
|
||||
asio::async_connect(socket_.lowest_layer(), endpoint_iterator,
|
||||
boost::bind(&client::handle_connect, this,
|
||||
asio::placeholders::error, ++endpoint_iterator));
|
||||
asio::placeholders::error));
|
||||
}
|
||||
|
||||
void handle_connect(const asio::error_code& error,
|
||||
asio::ip::tcp::resolver::iterator endpoint_iterator)
|
||||
void handle_connect(const asio::error_code& error)
|
||||
{
|
||||
if (!error)
|
||||
{
|
||||
@ -38,14 +36,6 @@ public:
|
||||
boost::bind(&client::handle_handshake, this,
|
||||
asio::placeholders::error));
|
||||
}
|
||||
else if (endpoint_iterator != asio::ip::tcp::resolver::iterator())
|
||||
{
|
||||
socket_.lowest_layer().close();
|
||||
asio::ip::tcp::endpoint endpoint = *endpoint_iterator;
|
||||
socket_.lowest_layer().async_connect(endpoint,
|
||||
boost::bind(&client::handle_connect, this,
|
||||
asio::placeholders::error, ++endpoint_iterator));
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << "Connect failed: " << error << "\n";
|
||||
|
@ -8,6 +8,7 @@
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#include "asio/connect.hpp"
|
||||
#include "asio/deadline_timer.hpp"
|
||||
#include "asio/io_service.hpp"
|
||||
#include "asio/ip/tcp.hpp"
|
||||
@ -73,47 +74,36 @@ public:
|
||||
tcp::resolver::query query(host, service);
|
||||
tcp::resolver::iterator iter = tcp::resolver(io_service_).resolve(query);
|
||||
|
||||
// Set a deadline for the asynchronous operation. The host name may resolve
|
||||
// to multiple endpoints, and this function tries to connect to each one in
|
||||
// turn. Setting the deadline here means it applies to the entire sequence.
|
||||
// Set a deadline for the asynchronous operation. As a host name may
|
||||
// resolve to multiple endpoints, this function uses the composed operation
|
||||
// async_connect. The deadline applies to the entire operation, rather than
|
||||
// individual connection attempts.
|
||||
deadline_.expires_from_now(timeout);
|
||||
|
||||
asio::error_code ec;
|
||||
// Set up the variable that receives the result of the asynchronous
|
||||
// operation. The error code is set to would_block to signal that the
|
||||
// operation is incomplete. Asio guarantees that its asynchronous
|
||||
// operations will never fail with would_block, so any other value in
|
||||
// ec indicates completion.
|
||||
asio::error_code ec = asio::error::would_block;
|
||||
|
||||
for (; iter != tcp::resolver::iterator(); ++iter)
|
||||
{
|
||||
// We may have an open socket from a previous connection attempt. This
|
||||
// socket cannot be reused, so we must close it before trying to connect
|
||||
// again.
|
||||
socket_.close();
|
||||
// Start the asynchronous operation itself. The boost::lambda function
|
||||
// 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);
|
||||
|
||||
// Set up the variable that receives the result of the asynchronous
|
||||
// operation. The error code is set to would_block to signal that the
|
||||
// operation is incomplete. Asio guarantees that its asynchronous
|
||||
// operations will never fail with would_block, so any other value in
|
||||
// ec indicates completion.
|
||||
ec = asio::error::would_block;
|
||||
// Block until the asynchronous operation has completed.
|
||||
do io_service_.run_one(); while (ec == asio::error::would_block);
|
||||
|
||||
// Start the asynchronous operation itself. The boost::lambda function
|
||||
// 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.
|
||||
socket_.async_connect(iter->endpoint(), var(ec) = _1);
|
||||
|
||||
// Block until the asynchronous operation has completed.
|
||||
do io_service_.run_one(); while (ec == asio::error::would_block);
|
||||
|
||||
// Determine whether a connection was successfully established. The
|
||||
// deadline actor may have had a chance to run and close our socket, even
|
||||
// though the connect operation notionally succeeded. Therefore we must
|
||||
// check whether the socket is still open before deciding that the we
|
||||
// were successful.
|
||||
if (!ec && socket_.is_open())
|
||||
return;
|
||||
}
|
||||
|
||||
throw asio::system_error(
|
||||
ec ? ec : asio::error::host_not_found);
|
||||
// Determine whether a connection was successfully established. The
|
||||
// deadline actor may have had a chance to run and close our socket, even
|
||||
// though the connect operation notionally succeeded. Therefore we must
|
||||
// check whether the socket is still open before deciding if we succeeded
|
||||
// or failed.
|
||||
if (ec || !socket_.is_open())
|
||||
throw asio::system_error(
|
||||
ec ? ec : asio::error::operation_aborted);
|
||||
}
|
||||
|
||||
std::string read_line(boost::posix_time::time_duration timeout)
|
||||
|
@ -29,17 +29,9 @@ int main(int argc, char* argv[])
|
||||
tcp::resolver resolver(io_service);
|
||||
tcp::resolver::query query(argv[1], "daytime");
|
||||
tcp::resolver::iterator endpoint_iterator = resolver.resolve(query);
|
||||
tcp::resolver::iterator end;
|
||||
|
||||
tcp::socket socket(io_service);
|
||||
asio::error_code error = asio::error::host_not_found;
|
||||
while (error && endpoint_iterator != end)
|
||||
{
|
||||
socket.close();
|
||||
socket.connect(*endpoint_iterator++, error);
|
||||
}
|
||||
if (error)
|
||||
throw asio::system_error(error);
|
||||
asio::connect(socket, endpoint_iterator);
|
||||
|
||||
for (;;)
|
||||
{
|
||||
|
@ -41,17 +41,17 @@ and the name of the service, in this case <tt>"daytime"</tt>.
|
||||
\until tcp::resolver::query
|
||||
|
||||
The list of endpoints is returned using an iterator of type
|
||||
asio::ip::tcp::resolver::iterator. A default constructed
|
||||
asio::ip::tcp::resolver::iterator object is used as the end iterator.
|
||||
asio::ip::tcp::resolver::iterator. (Note that a default constructed
|
||||
asio::ip::tcp::resolver::iterator object can be used as an end iterator.)
|
||||
|
||||
\until tcp::resolver::iterator end;
|
||||
\until tcp::resolver::iterator
|
||||
|
||||
Now we create and connect the socket. The list of endpoints obtained above may
|
||||
contain both IPv4 and IPv6 endpoints, so we need to try each of them until we
|
||||
find one that works. This keeps the client program independent of a specific IP
|
||||
version.
|
||||
version. The asio::connect() function does this for us automatically.
|
||||
|
||||
\until throw
|
||||
\until asio::connect
|
||||
|
||||
The connection is open. All we need to do now is read the response from the
|
||||
daytime service.
|
||||
|
@ -76,10 +76,9 @@ public:
|
||||
|
||||
void start(asio::ip::tcp::resolver::iterator endpoint_iterator)
|
||||
{
|
||||
asio::ip::tcp::endpoint endpoint = *endpoint_iterator;
|
||||
socket_.async_connect(endpoint,
|
||||
asio::async_connect(socket_, endpoint_iterator,
|
||||
strand_.wrap(boost::bind(&session::handle_connect, this,
|
||||
asio::placeholders::error, ++endpoint_iterator)));
|
||||
asio::placeholders::error)));
|
||||
}
|
||||
|
||||
void stop()
|
||||
@ -88,8 +87,7 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
void handle_connect(const asio::error_code& err,
|
||||
asio::ip::tcp::resolver::iterator endpoint_iterator)
|
||||
void handle_connect(const asio::error_code& err)
|
||||
{
|
||||
if (!err)
|
||||
{
|
||||
@ -113,14 +111,6 @@ private:
|
||||
asio::placeholders::bytes_transferred))));
|
||||
}
|
||||
}
|
||||
else if (endpoint_iterator != asio::ip::tcp::resolver::iterator())
|
||||
{
|
||||
socket_.close();
|
||||
asio::ip::tcp::endpoint endpoint = *endpoint_iterator;
|
||||
socket_.async_connect(endpoint,
|
||||
strand_.wrap(boost::bind(&session::handle_connect, this,
|
||||
asio::placeholders::error, ++endpoint_iterator)));
|
||||
}
|
||||
}
|
||||
|
||||
void handle_read(const asio::error_code& err, size_t length)
|
||||
|
1
asio/src/tests/unit/.gitignore
vendored
1
asio/src/tests/unit/.gitignore
vendored
@ -18,6 +18,7 @@ buffered_stream
|
||||
buffered_write_stream
|
||||
buffers_iterator
|
||||
completion_condition
|
||||
connect
|
||||
datagram_socket_service
|
||||
deadline_timer
|
||||
deadline_timer_service
|
||||
|
26
asio/src/tests/unit/connect.cpp
Normal file
26
asio/src/tests/unit/connect.cpp
Normal file
@ -0,0 +1,26 @@
|
||||
//
|
||||
// connect.cpp
|
||||
// ~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2011 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)
|
||||
//
|
||||
|
||||
// Disable autolinking for unit tests.
|
||||
#if !defined(BOOST_ALL_NO_LIB)
|
||||
#define BOOST_ALL_NO_LIB 1
|
||||
#endif // !defined(BOOST_ALL_NO_LIB)
|
||||
|
||||
// Test that header file is self-contained.
|
||||
#include "asio/connect.hpp"
|
||||
|
||||
#include "unit_test.hpp"
|
||||
|
||||
test_suite* init_unit_test_suite(int, char*[])
|
||||
{
|
||||
test_suite* test = BOOST_TEST_SUITE("connect");
|
||||
test->add(BOOST_TEST_CASE(&null_test));
|
||||
return test;
|
||||
}
|
Loading…
Reference in New Issue
Block a user