connect.hpp 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961
  1. //
  2. // impl/connect.hpp
  3. // ~~~~~~~~~~~~~~~~
  4. //
  5. // Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)
  6. //
  7. // Distributed under the Boost Software License, Version 1.0. (See accompanying
  8. // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  9. //
  10. #ifndef BOOST_ASIO_IMPL_CONNECT_HPP
  11. #define BOOST_ASIO_IMPL_CONNECT_HPP
  12. #if defined(_MSC_VER) && (_MSC_VER >= 1200)
  13. # pragma once
  14. #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
  15. #include <algorithm>
  16. #include <boost/asio/associator.hpp>
  17. #include <boost/asio/detail/base_from_cancellation_state.hpp>
  18. #include <boost/asio/detail/bind_handler.hpp>
  19. #include <boost/asio/detail/handler_alloc_helpers.hpp>
  20. #include <boost/asio/detail/handler_cont_helpers.hpp>
  21. #include <boost/asio/detail/handler_invoke_helpers.hpp>
  22. #include <boost/asio/detail/handler_tracking.hpp>
  23. #include <boost/asio/detail/handler_type_requirements.hpp>
  24. #include <boost/asio/detail/non_const_lvalue.hpp>
  25. #include <boost/asio/detail/throw_error.hpp>
  26. #include <boost/asio/detail/type_traits.hpp>
  27. #include <boost/asio/error.hpp>
  28. #include <boost/asio/post.hpp>
  29. #include <boost/asio/detail/push_options.hpp>
  30. namespace boost {
  31. namespace asio {
  32. namespace detail
  33. {
  34. struct default_connect_condition
  35. {
  36. template <typename Endpoint>
  37. bool operator()(const boost::system::error_code&, const Endpoint&)
  38. {
  39. return true;
  40. }
  41. };
  42. template <typename Protocol, typename Iterator>
  43. inline typename Protocol::endpoint deref_connect_result(
  44. Iterator iter, boost::system::error_code& ec)
  45. {
  46. return ec ? typename Protocol::endpoint() : *iter;
  47. }
  48. template <typename T, typename Iterator>
  49. struct legacy_connect_condition_helper : T
  50. {
  51. typedef char (*fallback_func_type)(...);
  52. operator fallback_func_type() const;
  53. };
  54. template <typename R, typename Arg1, typename Arg2, typename Iterator>
  55. struct legacy_connect_condition_helper<R (*)(Arg1, Arg2), Iterator>
  56. {
  57. R operator()(Arg1, Arg2) const;
  58. char operator()(...) const;
  59. };
  60. template <typename T, typename Iterator>
  61. struct is_legacy_connect_condition
  62. {
  63. static char asio_connect_condition_check(char);
  64. static char (&asio_connect_condition_check(Iterator))[2];
  65. static const bool value =
  66. sizeof(asio_connect_condition_check(
  67. (declval<legacy_connect_condition_helper<T, Iterator> >())(
  68. declval<const boost::system::error_code>(),
  69. declval<const Iterator>()))) != 1;
  70. };
  71. template <typename ConnectCondition, typename Iterator>
  72. inline Iterator call_connect_condition(ConnectCondition& connect_condition,
  73. const boost::system::error_code& ec, Iterator next, Iterator end,
  74. typename enable_if<is_legacy_connect_condition<
  75. ConnectCondition, Iterator>::value>::type* = 0)
  76. {
  77. if (next != end)
  78. return connect_condition(ec, next);
  79. return end;
  80. }
  81. template <typename ConnectCondition, typename Iterator>
  82. inline Iterator call_connect_condition(ConnectCondition& connect_condition,
  83. const boost::system::error_code& ec, Iterator next, Iterator end,
  84. typename enable_if<!is_legacy_connect_condition<
  85. ConnectCondition, Iterator>::value>::type* = 0)
  86. {
  87. for (;next != end; ++next)
  88. if (connect_condition(ec, *next))
  89. return next;
  90. return end;
  91. }
  92. }
  93. template <typename Protocol, typename Executor, typename EndpointSequence>
  94. typename Protocol::endpoint connect(basic_socket<Protocol, Executor>& s,
  95. const EndpointSequence& endpoints,
  96. typename constraint<is_endpoint_sequence<
  97. EndpointSequence>::value>::type)
  98. {
  99. boost::system::error_code ec;
  100. typename Protocol::endpoint result = connect(s, endpoints, ec);
  101. boost::asio::detail::throw_error(ec, "connect");
  102. return result;
  103. }
  104. template <typename Protocol, typename Executor, typename EndpointSequence>
  105. typename Protocol::endpoint connect(basic_socket<Protocol, Executor>& s,
  106. const EndpointSequence& endpoints, boost::system::error_code& ec,
  107. typename constraint<is_endpoint_sequence<
  108. EndpointSequence>::value>::type)
  109. {
  110. return detail::deref_connect_result<Protocol>(
  111. connect(s, endpoints.begin(), endpoints.end(),
  112. detail::default_connect_condition(), ec), ec);
  113. }
  114. #if !defined(BOOST_ASIO_NO_DEPRECATED)
  115. template <typename Protocol, typename Executor, typename Iterator>
  116. Iterator connect(basic_socket<Protocol, Executor>& s, Iterator begin,
  117. typename constraint<!is_endpoint_sequence<Iterator>::value>::type)
  118. {
  119. boost::system::error_code ec;
  120. Iterator result = connect(s, begin, ec);
  121. boost::asio::detail::throw_error(ec, "connect");
  122. return result;
  123. }
  124. template <typename Protocol, typename Executor, typename Iterator>
  125. inline Iterator connect(basic_socket<Protocol, Executor>& s,
  126. Iterator begin, boost::system::error_code& ec,
  127. typename constraint<!is_endpoint_sequence<Iterator>::value>::type)
  128. {
  129. return connect(s, begin, Iterator(), detail::default_connect_condition(), ec);
  130. }
  131. #endif // !defined(BOOST_ASIO_NO_DEPRECATED)
  132. template <typename Protocol, typename Executor, typename Iterator>
  133. Iterator connect(basic_socket<Protocol, Executor>& s,
  134. Iterator begin, Iterator end)
  135. {
  136. boost::system::error_code ec;
  137. Iterator result = connect(s, begin, end, ec);
  138. boost::asio::detail::throw_error(ec, "connect");
  139. return result;
  140. }
  141. template <typename Protocol, typename Executor, typename Iterator>
  142. inline Iterator connect(basic_socket<Protocol, Executor>& s,
  143. Iterator begin, Iterator end, boost::system::error_code& ec)
  144. {
  145. return connect(s, begin, end, detail::default_connect_condition(), ec);
  146. }
  147. template <typename Protocol, typename Executor,
  148. typename EndpointSequence, typename ConnectCondition>
  149. typename Protocol::endpoint connect(basic_socket<Protocol, Executor>& s,
  150. const EndpointSequence& endpoints, ConnectCondition connect_condition,
  151. typename constraint<is_endpoint_sequence<
  152. EndpointSequence>::value>::type)
  153. {
  154. boost::system::error_code ec;
  155. typename Protocol::endpoint result = connect(
  156. s, endpoints, connect_condition, ec);
  157. boost::asio::detail::throw_error(ec, "connect");
  158. return result;
  159. }
  160. template <typename Protocol, typename Executor,
  161. typename EndpointSequence, typename ConnectCondition>
  162. typename Protocol::endpoint connect(basic_socket<Protocol, Executor>& s,
  163. const EndpointSequence& endpoints, ConnectCondition connect_condition,
  164. boost::system::error_code& ec,
  165. typename constraint<is_endpoint_sequence<
  166. EndpointSequence>::value>::type)
  167. {
  168. return detail::deref_connect_result<Protocol>(
  169. connect(s, endpoints.begin(), endpoints.end(),
  170. connect_condition, ec), ec);
  171. }
  172. #if !defined(BOOST_ASIO_NO_DEPRECATED)
  173. template <typename Protocol, typename Executor,
  174. typename Iterator, typename ConnectCondition>
  175. Iterator connect(basic_socket<Protocol, Executor>& s,
  176. Iterator begin, ConnectCondition connect_condition,
  177. typename constraint<!is_endpoint_sequence<Iterator>::value>::type)
  178. {
  179. boost::system::error_code ec;
  180. Iterator result = connect(s, begin, connect_condition, ec);
  181. boost::asio::detail::throw_error(ec, "connect");
  182. return result;
  183. }
  184. template <typename Protocol, typename Executor,
  185. typename Iterator, typename ConnectCondition>
  186. inline Iterator connect(basic_socket<Protocol, Executor>& s,
  187. Iterator begin, ConnectCondition connect_condition,
  188. boost::system::error_code& ec,
  189. typename constraint<!is_endpoint_sequence<Iterator>::value>::type)
  190. {
  191. return connect(s, begin, Iterator(), connect_condition, ec);
  192. }
  193. #endif // !defined(BOOST_ASIO_NO_DEPRECATED)
  194. template <typename Protocol, typename Executor,
  195. typename Iterator, typename ConnectCondition>
  196. Iterator connect(basic_socket<Protocol, Executor>& s, Iterator begin,
  197. Iterator end, ConnectCondition connect_condition)
  198. {
  199. boost::system::error_code ec;
  200. Iterator result = connect(s, begin, end, connect_condition, ec);
  201. boost::asio::detail::throw_error(ec, "connect");
  202. return result;
  203. }
  204. template <typename Protocol, typename Executor,
  205. typename Iterator, typename ConnectCondition>
  206. Iterator connect(basic_socket<Protocol, Executor>& s, Iterator begin,
  207. Iterator end, ConnectCondition connect_condition,
  208. boost::system::error_code& ec)
  209. {
  210. ec = boost::system::error_code();
  211. for (Iterator iter = begin; iter != end; ++iter)
  212. {
  213. iter = (detail::call_connect_condition(connect_condition, ec, iter, end));
  214. if (iter != end)
  215. {
  216. s.close(ec);
  217. s.connect(*iter, ec);
  218. if (!ec)
  219. return iter;
  220. }
  221. else
  222. break;
  223. }
  224. if (!ec)
  225. ec = boost::asio::error::not_found;
  226. return end;
  227. }
  228. namespace detail
  229. {
  230. // Enable the empty base class optimisation for the connect condition.
  231. template <typename ConnectCondition>
  232. class base_from_connect_condition
  233. {
  234. protected:
  235. explicit base_from_connect_condition(
  236. const ConnectCondition& connect_condition)
  237. : connect_condition_(connect_condition)
  238. {
  239. }
  240. template <typename Iterator>
  241. void check_condition(const boost::system::error_code& ec,
  242. Iterator& iter, Iterator& end)
  243. {
  244. iter = detail::call_connect_condition(connect_condition_, ec, iter, end);
  245. }
  246. private:
  247. ConnectCondition connect_condition_;
  248. };
  249. // The default_connect_condition implementation is essentially a no-op. This
  250. // template specialisation lets us eliminate all costs associated with it.
  251. template <>
  252. class base_from_connect_condition<default_connect_condition>
  253. {
  254. protected:
  255. explicit base_from_connect_condition(const default_connect_condition&)
  256. {
  257. }
  258. template <typename Iterator>
  259. void check_condition(const boost::system::error_code&, Iterator&, Iterator&)
  260. {
  261. }
  262. };
  263. template <typename Protocol, typename Executor, typename EndpointSequence,
  264. typename ConnectCondition, typename RangeConnectHandler>
  265. class range_connect_op
  266. : public base_from_cancellation_state<RangeConnectHandler>,
  267. base_from_connect_condition<ConnectCondition>
  268. {
  269. public:
  270. range_connect_op(basic_socket<Protocol, Executor>& sock,
  271. const EndpointSequence& endpoints,
  272. const ConnectCondition& connect_condition,
  273. RangeConnectHandler& handler)
  274. : base_from_cancellation_state<RangeConnectHandler>(
  275. handler, enable_partial_cancellation()),
  276. base_from_connect_condition<ConnectCondition>(connect_condition),
  277. socket_(sock),
  278. endpoints_(endpoints),
  279. index_(0),
  280. start_(0),
  281. handler_(BOOST_ASIO_MOVE_CAST(RangeConnectHandler)(handler))
  282. {
  283. }
  284. #if defined(BOOST_ASIO_HAS_MOVE)
  285. range_connect_op(const range_connect_op& other)
  286. : base_from_cancellation_state<RangeConnectHandler>(other),
  287. base_from_connect_condition<ConnectCondition>(other),
  288. socket_(other.socket_),
  289. endpoints_(other.endpoints_),
  290. index_(other.index_),
  291. start_(other.start_),
  292. handler_(other.handler_)
  293. {
  294. }
  295. range_connect_op(range_connect_op&& other)
  296. : base_from_cancellation_state<RangeConnectHandler>(
  297. BOOST_ASIO_MOVE_CAST(base_from_cancellation_state<
  298. RangeConnectHandler>)(other)),
  299. base_from_connect_condition<ConnectCondition>(other),
  300. socket_(other.socket_),
  301. endpoints_(other.endpoints_),
  302. index_(other.index_),
  303. start_(other.start_),
  304. handler_(BOOST_ASIO_MOVE_CAST(RangeConnectHandler)(other.handler_))
  305. {
  306. }
  307. #endif // defined(BOOST_ASIO_HAS_MOVE)
  308. void operator()(boost::system::error_code ec, int start = 0)
  309. {
  310. this->process(ec, start,
  311. const_cast<const EndpointSequence&>(endpoints_).begin(),
  312. const_cast<const EndpointSequence&>(endpoints_).end());
  313. }
  314. //private:
  315. template <typename Iterator>
  316. void process(boost::system::error_code ec,
  317. int start, Iterator begin, Iterator end)
  318. {
  319. Iterator iter = begin;
  320. std::advance(iter, index_);
  321. switch (start_ = start)
  322. {
  323. case 1:
  324. for (;;)
  325. {
  326. this->check_condition(ec, iter, end);
  327. index_ = std::distance(begin, iter);
  328. if (iter != end)
  329. {
  330. socket_.close(ec);
  331. BOOST_ASIO_HANDLER_LOCATION((__FILE__, __LINE__, "async_connect"));
  332. socket_.async_connect(*iter,
  333. BOOST_ASIO_MOVE_CAST(range_connect_op)(*this));
  334. return;
  335. }
  336. if (start)
  337. {
  338. ec = boost::asio::error::not_found;
  339. BOOST_ASIO_HANDLER_LOCATION((__FILE__, __LINE__, "async_connect"));
  340. boost::asio::post(socket_.get_executor(),
  341. detail::bind_handler(
  342. BOOST_ASIO_MOVE_CAST(range_connect_op)(*this), ec));
  343. return;
  344. }
  345. /* fall-through */ default:
  346. if (iter == end)
  347. break;
  348. if (!socket_.is_open())
  349. {
  350. ec = boost::asio::error::operation_aborted;
  351. break;
  352. }
  353. if (!ec)
  354. break;
  355. if (this->cancelled() != cancellation_type::none)
  356. {
  357. ec = boost::asio::error::operation_aborted;
  358. break;
  359. }
  360. ++iter;
  361. ++index_;
  362. }
  363. BOOST_ASIO_MOVE_OR_LVALUE(RangeConnectHandler)(handler_)(
  364. static_cast<const boost::system::error_code&>(ec),
  365. static_cast<const typename Protocol::endpoint&>(
  366. ec || iter == end ? typename Protocol::endpoint() : *iter));
  367. }
  368. }
  369. basic_socket<Protocol, Executor>& socket_;
  370. EndpointSequence endpoints_;
  371. std::size_t index_;
  372. int start_;
  373. RangeConnectHandler handler_;
  374. };
  375. template <typename Protocol, typename Executor, typename EndpointSequence,
  376. typename ConnectCondition, typename RangeConnectHandler>
  377. inline asio_handler_allocate_is_deprecated
  378. asio_handler_allocate(std::size_t size,
  379. range_connect_op<Protocol, Executor, EndpointSequence,
  380. ConnectCondition, RangeConnectHandler>* this_handler)
  381. {
  382. #if defined(BOOST_ASIO_NO_DEPRECATED)
  383. boost_asio_handler_alloc_helpers::allocate(size, this_handler->handler_);
  384. return asio_handler_allocate_is_no_longer_used();
  385. #else // defined(BOOST_ASIO_NO_DEPRECATED)
  386. return boost_asio_handler_alloc_helpers::allocate(
  387. size, this_handler->handler_);
  388. #endif // defined(BOOST_ASIO_NO_DEPRECATED)
  389. }
  390. template <typename Protocol, typename Executor, typename EndpointSequence,
  391. typename ConnectCondition, typename RangeConnectHandler>
  392. inline asio_handler_deallocate_is_deprecated
  393. asio_handler_deallocate(void* pointer, std::size_t size,
  394. range_connect_op<Protocol, Executor, EndpointSequence,
  395. ConnectCondition, RangeConnectHandler>* this_handler)
  396. {
  397. boost_asio_handler_alloc_helpers::deallocate(
  398. pointer, size, this_handler->handler_);
  399. #if defined(BOOST_ASIO_NO_DEPRECATED)
  400. return asio_handler_deallocate_is_no_longer_used();
  401. #endif // defined(BOOST_ASIO_NO_DEPRECATED)
  402. }
  403. template <typename Protocol, typename Executor, typename EndpointSequence,
  404. typename ConnectCondition, typename RangeConnectHandler>
  405. inline bool asio_handler_is_continuation(
  406. range_connect_op<Protocol, Executor, EndpointSequence,
  407. ConnectCondition, RangeConnectHandler>* this_handler)
  408. {
  409. return boost_asio_handler_cont_helpers::is_continuation(
  410. this_handler->handler_);
  411. }
  412. template <typename Function, typename Executor, typename Protocol,
  413. typename EndpointSequence, typename ConnectCondition,
  414. typename RangeConnectHandler>
  415. inline asio_handler_invoke_is_deprecated
  416. asio_handler_invoke(Function& function,
  417. range_connect_op<Protocol, Executor, EndpointSequence,
  418. ConnectCondition, RangeConnectHandler>* this_handler)
  419. {
  420. boost_asio_handler_invoke_helpers::invoke(
  421. function, this_handler->handler_);
  422. #if defined(BOOST_ASIO_NO_DEPRECATED)
  423. return asio_handler_invoke_is_no_longer_used();
  424. #endif // defined(BOOST_ASIO_NO_DEPRECATED)
  425. }
  426. template <typename Function, typename Executor, typename Protocol,
  427. typename EndpointSequence, typename ConnectCondition,
  428. typename RangeConnectHandler>
  429. inline asio_handler_invoke_is_deprecated
  430. asio_handler_invoke(const Function& function,
  431. range_connect_op<Protocol, Executor, EndpointSequence,
  432. ConnectCondition, RangeConnectHandler>* this_handler)
  433. {
  434. boost_asio_handler_invoke_helpers::invoke(
  435. function, this_handler->handler_);
  436. #if defined(BOOST_ASIO_NO_DEPRECATED)
  437. return asio_handler_invoke_is_no_longer_used();
  438. #endif // defined(BOOST_ASIO_NO_DEPRECATED)
  439. }
  440. template <typename Protocol, typename Executor>
  441. class initiate_async_range_connect
  442. {
  443. public:
  444. typedef Executor executor_type;
  445. explicit initiate_async_range_connect(basic_socket<Protocol, Executor>& s)
  446. : socket_(s)
  447. {
  448. }
  449. executor_type get_executor() const BOOST_ASIO_NOEXCEPT
  450. {
  451. return socket_.get_executor();
  452. }
  453. template <typename RangeConnectHandler,
  454. typename EndpointSequence, typename ConnectCondition>
  455. void operator()(BOOST_ASIO_MOVE_ARG(RangeConnectHandler) handler,
  456. const EndpointSequence& endpoints,
  457. const ConnectCondition& connect_condition) const
  458. {
  459. // If you get an error on the following line it means that your
  460. // handler does not meet the documented type requirements for an
  461. // RangeConnectHandler.
  462. BOOST_ASIO_RANGE_CONNECT_HANDLER_CHECK(RangeConnectHandler,
  463. handler, typename Protocol::endpoint) type_check;
  464. non_const_lvalue<RangeConnectHandler> handler2(handler);
  465. range_connect_op<Protocol, Executor, EndpointSequence, ConnectCondition,
  466. typename decay<RangeConnectHandler>::type>(socket_, endpoints,
  467. connect_condition, handler2.value)(boost::system::error_code(), 1);
  468. }
  469. private:
  470. basic_socket<Protocol, Executor>& socket_;
  471. };
  472. template <typename Protocol, typename Executor, typename Iterator,
  473. typename ConnectCondition, typename IteratorConnectHandler>
  474. class iterator_connect_op
  475. : public base_from_cancellation_state<IteratorConnectHandler>,
  476. base_from_connect_condition<ConnectCondition>
  477. {
  478. public:
  479. iterator_connect_op(basic_socket<Protocol, Executor>& sock,
  480. const Iterator& begin, const Iterator& end,
  481. const ConnectCondition& connect_condition,
  482. IteratorConnectHandler& handler)
  483. : base_from_cancellation_state<IteratorConnectHandler>(
  484. handler, enable_partial_cancellation()),
  485. base_from_connect_condition<ConnectCondition>(connect_condition),
  486. socket_(sock),
  487. iter_(begin),
  488. end_(end),
  489. start_(0),
  490. handler_(BOOST_ASIO_MOVE_CAST(IteratorConnectHandler)(handler))
  491. {
  492. }
  493. #if defined(BOOST_ASIO_HAS_MOVE)
  494. iterator_connect_op(const iterator_connect_op& other)
  495. : base_from_cancellation_state<IteratorConnectHandler>(other),
  496. base_from_connect_condition<ConnectCondition>(other),
  497. socket_(other.socket_),
  498. iter_(other.iter_),
  499. end_(other.end_),
  500. start_(other.start_),
  501. handler_(other.handler_)
  502. {
  503. }
  504. iterator_connect_op(iterator_connect_op&& other)
  505. : base_from_cancellation_state<IteratorConnectHandler>(
  506. BOOST_ASIO_MOVE_CAST(base_from_cancellation_state<
  507. IteratorConnectHandler>)(other)),
  508. base_from_connect_condition<ConnectCondition>(other),
  509. socket_(other.socket_),
  510. iter_(other.iter_),
  511. end_(other.end_),
  512. start_(other.start_),
  513. handler_(BOOST_ASIO_MOVE_CAST(IteratorConnectHandler)(other.handler_))
  514. {
  515. }
  516. #endif // defined(BOOST_ASIO_HAS_MOVE)
  517. void operator()(boost::system::error_code ec, int start = 0)
  518. {
  519. switch (start_ = start)
  520. {
  521. case 1:
  522. for (;;)
  523. {
  524. this->check_condition(ec, iter_, end_);
  525. if (iter_ != end_)
  526. {
  527. socket_.close(ec);
  528. BOOST_ASIO_HANDLER_LOCATION((__FILE__, __LINE__, "async_connect"));
  529. socket_.async_connect(*iter_,
  530. BOOST_ASIO_MOVE_CAST(iterator_connect_op)(*this));
  531. return;
  532. }
  533. if (start)
  534. {
  535. ec = boost::asio::error::not_found;
  536. BOOST_ASIO_HANDLER_LOCATION((__FILE__, __LINE__, "async_connect"));
  537. boost::asio::post(socket_.get_executor(),
  538. detail::bind_handler(
  539. BOOST_ASIO_MOVE_CAST(iterator_connect_op)(*this), ec));
  540. return;
  541. }
  542. /* fall-through */ default:
  543. if (iter_ == end_)
  544. break;
  545. if (!socket_.is_open())
  546. {
  547. ec = boost::asio::error::operation_aborted;
  548. break;
  549. }
  550. if (!ec)
  551. break;
  552. if (this->cancelled() != cancellation_type::none)
  553. {
  554. ec = boost::asio::error::operation_aborted;
  555. break;
  556. }
  557. ++iter_;
  558. }
  559. BOOST_ASIO_MOVE_OR_LVALUE(IteratorConnectHandler)(handler_)(
  560. static_cast<const boost::system::error_code&>(ec),
  561. static_cast<const Iterator&>(iter_));
  562. }
  563. }
  564. //private:
  565. basic_socket<Protocol, Executor>& socket_;
  566. Iterator iter_;
  567. Iterator end_;
  568. int start_;
  569. IteratorConnectHandler handler_;
  570. };
  571. template <typename Protocol, typename Executor, typename Iterator,
  572. typename ConnectCondition, typename IteratorConnectHandler>
  573. inline asio_handler_allocate_is_deprecated
  574. asio_handler_allocate(std::size_t size,
  575. iterator_connect_op<Protocol, Executor, Iterator,
  576. ConnectCondition, IteratorConnectHandler>* this_handler)
  577. {
  578. #if defined(BOOST_ASIO_NO_DEPRECATED)
  579. boost_asio_handler_alloc_helpers::allocate(size, this_handler->handler_);
  580. return asio_handler_allocate_is_no_longer_used();
  581. #else // defined(BOOST_ASIO_NO_DEPRECATED)
  582. return boost_asio_handler_alloc_helpers::allocate(
  583. size, this_handler->handler_);
  584. #endif // defined(BOOST_ASIO_NO_DEPRECATED)
  585. }
  586. template <typename Protocol, typename Executor, typename Iterator,
  587. typename ConnectCondition, typename IteratorConnectHandler>
  588. inline asio_handler_deallocate_is_deprecated
  589. asio_handler_deallocate(void* pointer, std::size_t size,
  590. iterator_connect_op<Protocol, Executor, Iterator,
  591. ConnectCondition, IteratorConnectHandler>* this_handler)
  592. {
  593. boost_asio_handler_alloc_helpers::deallocate(
  594. pointer, size, this_handler->handler_);
  595. #if defined(BOOST_ASIO_NO_DEPRECATED)
  596. return asio_handler_deallocate_is_no_longer_used();
  597. #endif // defined(BOOST_ASIO_NO_DEPRECATED)
  598. }
  599. template <typename Protocol, typename Executor, typename Iterator,
  600. typename ConnectCondition, typename IteratorConnectHandler>
  601. inline bool asio_handler_is_continuation(
  602. iterator_connect_op<Protocol, Executor, Iterator,
  603. ConnectCondition, IteratorConnectHandler>* this_handler)
  604. {
  605. return boost_asio_handler_cont_helpers::is_continuation(
  606. this_handler->handler_);
  607. }
  608. template <typename Function, typename Executor, typename Protocol,
  609. typename Iterator, typename ConnectCondition,
  610. typename IteratorConnectHandler>
  611. inline asio_handler_invoke_is_deprecated
  612. asio_handler_invoke(Function& function,
  613. iterator_connect_op<Protocol, Executor, Iterator,
  614. ConnectCondition, IteratorConnectHandler>* this_handler)
  615. {
  616. boost_asio_handler_invoke_helpers::invoke(
  617. function, this_handler->handler_);
  618. #if defined(BOOST_ASIO_NO_DEPRECATED)
  619. return asio_handler_invoke_is_no_longer_used();
  620. #endif // defined(BOOST_ASIO_NO_DEPRECATED)
  621. }
  622. template <typename Function, typename Executor, typename Protocol,
  623. typename Iterator, typename ConnectCondition,
  624. typename IteratorConnectHandler>
  625. inline asio_handler_invoke_is_deprecated
  626. asio_handler_invoke(const Function& function,
  627. iterator_connect_op<Protocol, Executor, Iterator,
  628. ConnectCondition, IteratorConnectHandler>* this_handler)
  629. {
  630. boost_asio_handler_invoke_helpers::invoke(
  631. function, this_handler->handler_);
  632. #if defined(BOOST_ASIO_NO_DEPRECATED)
  633. return asio_handler_invoke_is_no_longer_used();
  634. #endif // defined(BOOST_ASIO_NO_DEPRECATED)
  635. }
  636. template <typename Protocol, typename Executor>
  637. class initiate_async_iterator_connect
  638. {
  639. public:
  640. typedef Executor executor_type;
  641. explicit initiate_async_iterator_connect(
  642. basic_socket<Protocol, Executor>& s)
  643. : socket_(s)
  644. {
  645. }
  646. executor_type get_executor() const BOOST_ASIO_NOEXCEPT
  647. {
  648. return socket_.get_executor();
  649. }
  650. template <typename IteratorConnectHandler,
  651. typename Iterator, typename ConnectCondition>
  652. void operator()(BOOST_ASIO_MOVE_ARG(IteratorConnectHandler) handler,
  653. Iterator begin, Iterator end,
  654. const ConnectCondition& connect_condition) const
  655. {
  656. // If you get an error on the following line it means that your
  657. // handler does not meet the documented type requirements for an
  658. // IteratorConnectHandler.
  659. BOOST_ASIO_ITERATOR_CONNECT_HANDLER_CHECK(
  660. IteratorConnectHandler, handler, Iterator) type_check;
  661. non_const_lvalue<IteratorConnectHandler> handler2(handler);
  662. iterator_connect_op<Protocol, Executor, Iterator, ConnectCondition,
  663. typename decay<IteratorConnectHandler>::type>(socket_, begin, end,
  664. connect_condition, handler2.value)(boost::system::error_code(), 1);
  665. }
  666. private:
  667. basic_socket<Protocol, Executor>& socket_;
  668. };
  669. } // namespace detail
  670. #if !defined(GENERATING_DOCUMENTATION)
  671. template <template <typename, typename> class Associator,
  672. typename Protocol, typename Executor, typename EndpointSequence,
  673. typename ConnectCondition, typename RangeConnectHandler,
  674. typename DefaultCandidate>
  675. struct associator<Associator,
  676. detail::range_connect_op<Protocol, Executor,
  677. EndpointSequence, ConnectCondition, RangeConnectHandler>,
  678. DefaultCandidate>
  679. : Associator<RangeConnectHandler, DefaultCandidate>
  680. {
  681. static typename Associator<RangeConnectHandler, DefaultCandidate>::type
  682. get(const detail::range_connect_op<Protocol, Executor, EndpointSequence,
  683. ConnectCondition, RangeConnectHandler>& h) BOOST_ASIO_NOEXCEPT
  684. {
  685. return Associator<RangeConnectHandler, DefaultCandidate>::get(h.handler_);
  686. }
  687. static BOOST_ASIO_AUTO_RETURN_TYPE_PREFIX2(
  688. typename Associator<RangeConnectHandler, DefaultCandidate>::type)
  689. get(const detail::range_connect_op<Protocol, Executor,
  690. EndpointSequence, ConnectCondition, RangeConnectHandler>& h,
  691. const DefaultCandidate& c) BOOST_ASIO_NOEXCEPT
  692. BOOST_ASIO_AUTO_RETURN_TYPE_SUFFIX((
  693. Associator<RangeConnectHandler, DefaultCandidate>::get(
  694. h.handler_, c)))
  695. {
  696. return Associator<RangeConnectHandler, DefaultCandidate>::get(
  697. h.handler_, c);
  698. }
  699. };
  700. template <template <typename, typename> class Associator,
  701. typename Protocol, typename Executor, typename Iterator,
  702. typename ConnectCondition, typename IteratorConnectHandler,
  703. typename DefaultCandidate>
  704. struct associator<Associator,
  705. detail::iterator_connect_op<Protocol, Executor,
  706. Iterator, ConnectCondition, IteratorConnectHandler>,
  707. DefaultCandidate>
  708. : Associator<IteratorConnectHandler, DefaultCandidate>
  709. {
  710. static typename Associator<IteratorConnectHandler, DefaultCandidate>::type
  711. get(const detail::iterator_connect_op<Protocol, Executor, Iterator,
  712. ConnectCondition, IteratorConnectHandler>& h) BOOST_ASIO_NOEXCEPT
  713. {
  714. return Associator<IteratorConnectHandler, DefaultCandidate>::get(
  715. h.handler_);
  716. }
  717. static BOOST_ASIO_AUTO_RETURN_TYPE_PREFIX2(
  718. typename Associator<IteratorConnectHandler, DefaultCandidate>::type)
  719. get(const detail::iterator_connect_op<Protocol, Executor,
  720. Iterator, ConnectCondition, IteratorConnectHandler>& h,
  721. const DefaultCandidate& c) BOOST_ASIO_NOEXCEPT
  722. BOOST_ASIO_AUTO_RETURN_TYPE_SUFFIX((
  723. Associator<IteratorConnectHandler, DefaultCandidate>::get(
  724. h.handler_, c)))
  725. {
  726. return Associator<IteratorConnectHandler, DefaultCandidate>::get(
  727. h.handler_, c);
  728. }
  729. };
  730. #endif // !defined(GENERATING_DOCUMENTATION)
  731. template <typename Protocol, typename Executor, typename EndpointSequence,
  732. BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
  733. typename Protocol::endpoint)) RangeConnectToken>
  734. inline BOOST_ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(RangeConnectToken,
  735. void (boost::system::error_code, typename Protocol::endpoint))
  736. async_connect(basic_socket<Protocol, Executor>& s,
  737. const EndpointSequence& endpoints,
  738. BOOST_ASIO_MOVE_ARG(RangeConnectToken) token,
  739. typename constraint<is_endpoint_sequence<
  740. EndpointSequence>::value>::type)
  741. BOOST_ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((
  742. async_initiate<RangeConnectToken,
  743. void (boost::system::error_code, typename Protocol::endpoint)>(
  744. declval<detail::initiate_async_range_connect<Protocol, Executor> >(),
  745. token, endpoints, declval<detail::default_connect_condition>())))
  746. {
  747. return async_initiate<RangeConnectToken,
  748. void (boost::system::error_code, typename Protocol::endpoint)>(
  749. detail::initiate_async_range_connect<Protocol, Executor>(s),
  750. token, endpoints, detail::default_connect_condition());
  751. }
  752. #if !defined(BOOST_ASIO_NO_DEPRECATED)
  753. template <typename Protocol, typename Executor, typename Iterator,
  754. BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
  755. Iterator)) IteratorConnectToken>
  756. inline BOOST_ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(IteratorConnectToken,
  757. void (boost::system::error_code, Iterator))
  758. async_connect(basic_socket<Protocol, Executor>& s, Iterator begin,
  759. BOOST_ASIO_MOVE_ARG(IteratorConnectToken) token,
  760. typename constraint<!is_endpoint_sequence<Iterator>::value>::type)
  761. BOOST_ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((
  762. async_initiate<IteratorConnectToken,
  763. void (boost::system::error_code, Iterator)>(
  764. declval<detail::initiate_async_iterator_connect<Protocol, Executor> >(),
  765. token, begin, Iterator(),
  766. declval<detail::default_connect_condition>())))
  767. {
  768. return async_initiate<IteratorConnectToken,
  769. void (boost::system::error_code, Iterator)>(
  770. detail::initiate_async_iterator_connect<Protocol, Executor>(s),
  771. token, begin, Iterator(),
  772. detail::default_connect_condition());
  773. }
  774. #endif // !defined(BOOST_ASIO_NO_DEPRECATED)
  775. template <typename Protocol, typename Executor, typename Iterator,
  776. BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
  777. Iterator)) IteratorConnectToken>
  778. inline BOOST_ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(IteratorConnectToken,
  779. void (boost::system::error_code, Iterator))
  780. async_connect(basic_socket<Protocol, Executor>& s, Iterator begin, Iterator end,
  781. BOOST_ASIO_MOVE_ARG(IteratorConnectToken) token)
  782. BOOST_ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((
  783. async_initiate<IteratorConnectToken,
  784. void (boost::system::error_code, Iterator)>(
  785. declval<detail::initiate_async_iterator_connect<Protocol, Executor> >(),
  786. token, begin, end, declval<detail::default_connect_condition>())))
  787. {
  788. return async_initiate<IteratorConnectToken,
  789. void (boost::system::error_code, Iterator)>(
  790. detail::initiate_async_iterator_connect<Protocol, Executor>(s),
  791. token, begin, end, detail::default_connect_condition());
  792. }
  793. template <typename Protocol, typename Executor,
  794. typename EndpointSequence, typename ConnectCondition,
  795. BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
  796. typename Protocol::endpoint)) RangeConnectToken>
  797. inline BOOST_ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(RangeConnectToken,
  798. void (boost::system::error_code, typename Protocol::endpoint))
  799. async_connect(basic_socket<Protocol, Executor>& s,
  800. const EndpointSequence& endpoints, ConnectCondition connect_condition,
  801. BOOST_ASIO_MOVE_ARG(RangeConnectToken) token,
  802. typename constraint<is_endpoint_sequence<
  803. EndpointSequence>::value>::type)
  804. BOOST_ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((
  805. async_initiate<RangeConnectToken,
  806. void (boost::system::error_code, typename Protocol::endpoint)>(
  807. declval<detail::initiate_async_range_connect<Protocol, Executor> >(),
  808. token, endpoints, connect_condition)))
  809. {
  810. return async_initiate<RangeConnectToken,
  811. void (boost::system::error_code, typename Protocol::endpoint)>(
  812. detail::initiate_async_range_connect<Protocol, Executor>(s),
  813. token, endpoints, connect_condition);
  814. }
  815. #if !defined(BOOST_ASIO_NO_DEPRECATED)
  816. template <typename Protocol, typename Executor,
  817. typename Iterator, typename ConnectCondition,
  818. BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
  819. Iterator)) IteratorConnectToken>
  820. inline BOOST_ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(IteratorConnectToken,
  821. void (boost::system::error_code, Iterator))
  822. async_connect(basic_socket<Protocol, Executor>& s, Iterator begin,
  823. ConnectCondition connect_condition,
  824. BOOST_ASIO_MOVE_ARG(IteratorConnectToken) token,
  825. typename constraint<!is_endpoint_sequence<Iterator>::value>::type)
  826. BOOST_ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((
  827. async_initiate<IteratorConnectToken,
  828. void (boost::system::error_code, Iterator)>(
  829. declval<detail::initiate_async_iterator_connect<Protocol, Executor> >(),
  830. token, begin, Iterator(), connect_condition)))
  831. {
  832. return async_initiate<IteratorConnectToken,
  833. void (boost::system::error_code, Iterator)>(
  834. detail::initiate_async_iterator_connect<Protocol, Executor>(s),
  835. token, begin, Iterator(), connect_condition);
  836. }
  837. #endif // !defined(BOOST_ASIO_NO_DEPRECATED)
  838. template <typename Protocol, typename Executor,
  839. typename Iterator, typename ConnectCondition,
  840. BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
  841. Iterator)) IteratorConnectToken>
  842. inline BOOST_ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(IteratorConnectToken,
  843. void (boost::system::error_code, Iterator))
  844. async_connect(basic_socket<Protocol, Executor>& s, Iterator begin,
  845. Iterator end, ConnectCondition connect_condition,
  846. BOOST_ASIO_MOVE_ARG(IteratorConnectToken) token)
  847. BOOST_ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((
  848. async_initiate<IteratorConnectToken,
  849. void (boost::system::error_code, Iterator)>(
  850. declval<detail::initiate_async_iterator_connect<Protocol, Executor> >(),
  851. token, begin, end, connect_condition)))
  852. {
  853. return async_initiate<IteratorConnectToken,
  854. void (boost::system::error_code, Iterator)>(
  855. detail::initiate_async_iterator_connect<Protocol, Executor>(s),
  856. token, begin, end, connect_condition);
  857. }
  858. } // namespace asio
  859. } // namespace boost
  860. #include <boost/asio/detail/pop_options.hpp>
  861. #endif // BOOST_ASIO_IMPL_CONNECT_HPP