connect.hpp 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809
  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 ASIO_IMPL_CONNECT_HPP
  11. #define 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 "asio/associator.hpp"
  17. #include "asio/detail/base_from_cancellation_state.hpp"
  18. #include "asio/detail/bind_handler.hpp"
  19. #include "asio/detail/handler_cont_helpers.hpp"
  20. #include "asio/detail/handler_tracking.hpp"
  21. #include "asio/detail/handler_type_requirements.hpp"
  22. #include "asio/detail/non_const_lvalue.hpp"
  23. #include "asio/detail/throw_error.hpp"
  24. #include "asio/detail/type_traits.hpp"
  25. #include "asio/error.hpp"
  26. #include "asio/post.hpp"
  27. #include "asio/detail/push_options.hpp"
  28. namespace asio {
  29. namespace detail
  30. {
  31. struct default_connect_condition
  32. {
  33. template <typename Endpoint>
  34. bool operator()(const asio::error_code&, const Endpoint&)
  35. {
  36. return true;
  37. }
  38. };
  39. template <typename Protocol, typename Iterator>
  40. inline typename Protocol::endpoint deref_connect_result(
  41. Iterator iter, asio::error_code& ec)
  42. {
  43. return ec ? typename Protocol::endpoint() : *iter;
  44. }
  45. template <typename T, typename Iterator>
  46. struct legacy_connect_condition_helper : T
  47. {
  48. typedef char (*fallback_func_type)(...);
  49. operator fallback_func_type() const;
  50. };
  51. template <typename R, typename Arg1, typename Arg2, typename Iterator>
  52. struct legacy_connect_condition_helper<R (*)(Arg1, Arg2), Iterator>
  53. {
  54. R operator()(Arg1, Arg2) const;
  55. char operator()(...) const;
  56. };
  57. template <typename T, typename Iterator>
  58. struct is_legacy_connect_condition
  59. {
  60. static char asio_connect_condition_check(char);
  61. static char (&asio_connect_condition_check(Iterator))[2];
  62. static const bool value =
  63. sizeof(asio_connect_condition_check(
  64. (declval<legacy_connect_condition_helper<T, Iterator>>())(
  65. declval<const asio::error_code>(),
  66. declval<const Iterator>()))) != 1;
  67. };
  68. template <typename ConnectCondition, typename Iterator>
  69. inline Iterator call_connect_condition(ConnectCondition& connect_condition,
  70. const asio::error_code& ec, Iterator next, Iterator end,
  71. enable_if_t<is_legacy_connect_condition<
  72. ConnectCondition, Iterator>::value>* = 0)
  73. {
  74. if (next != end)
  75. return connect_condition(ec, next);
  76. return end;
  77. }
  78. template <typename ConnectCondition, typename Iterator>
  79. inline Iterator call_connect_condition(ConnectCondition& connect_condition,
  80. const asio::error_code& ec, Iterator next, Iterator end,
  81. enable_if_t<!is_legacy_connect_condition<
  82. ConnectCondition, Iterator>::value>* = 0)
  83. {
  84. for (;next != end; ++next)
  85. if (connect_condition(ec, *next))
  86. return next;
  87. return end;
  88. }
  89. }
  90. template <typename Protocol, typename Executor, typename EndpointSequence>
  91. typename Protocol::endpoint connect(basic_socket<Protocol, Executor>& s,
  92. const EndpointSequence& endpoints,
  93. constraint_t<is_endpoint_sequence<EndpointSequence>::value>)
  94. {
  95. asio::error_code ec;
  96. typename Protocol::endpoint result = connect(s, endpoints, ec);
  97. asio::detail::throw_error(ec, "connect");
  98. return result;
  99. }
  100. template <typename Protocol, typename Executor, typename EndpointSequence>
  101. typename Protocol::endpoint connect(basic_socket<Protocol, Executor>& s,
  102. const EndpointSequence& endpoints, asio::error_code& ec,
  103. constraint_t<is_endpoint_sequence<EndpointSequence>::value>)
  104. {
  105. return detail::deref_connect_result<Protocol>(
  106. connect(s, endpoints.begin(), endpoints.end(),
  107. detail::default_connect_condition(), ec), ec);
  108. }
  109. #if !defined(ASIO_NO_DEPRECATED)
  110. template <typename Protocol, typename Executor, typename Iterator>
  111. Iterator connect(basic_socket<Protocol, Executor>& s, Iterator begin,
  112. constraint_t<!is_endpoint_sequence<Iterator>::value>)
  113. {
  114. asio::error_code ec;
  115. Iterator result = connect(s, begin, ec);
  116. asio::detail::throw_error(ec, "connect");
  117. return result;
  118. }
  119. template <typename Protocol, typename Executor, typename Iterator>
  120. inline Iterator connect(basic_socket<Protocol, Executor>& s,
  121. Iterator begin, asio::error_code& ec,
  122. constraint_t<!is_endpoint_sequence<Iterator>::value>)
  123. {
  124. return connect(s, begin, Iterator(), detail::default_connect_condition(), ec);
  125. }
  126. #endif // !defined(ASIO_NO_DEPRECATED)
  127. template <typename Protocol, typename Executor, typename Iterator>
  128. Iterator connect(basic_socket<Protocol, Executor>& s,
  129. Iterator begin, Iterator end)
  130. {
  131. asio::error_code ec;
  132. Iterator result = connect(s, begin, end, ec);
  133. asio::detail::throw_error(ec, "connect");
  134. return result;
  135. }
  136. template <typename Protocol, typename Executor, typename Iterator>
  137. inline Iterator connect(basic_socket<Protocol, Executor>& s,
  138. Iterator begin, Iterator end, asio::error_code& ec)
  139. {
  140. return connect(s, begin, end, detail::default_connect_condition(), ec);
  141. }
  142. template <typename Protocol, typename Executor,
  143. typename EndpointSequence, typename ConnectCondition>
  144. typename Protocol::endpoint connect(basic_socket<Protocol, Executor>& s,
  145. const EndpointSequence& endpoints, ConnectCondition connect_condition,
  146. constraint_t<is_endpoint_sequence<EndpointSequence>::value>)
  147. {
  148. asio::error_code ec;
  149. typename Protocol::endpoint result = connect(
  150. s, endpoints, connect_condition, ec);
  151. asio::detail::throw_error(ec, "connect");
  152. return result;
  153. }
  154. template <typename Protocol, typename Executor,
  155. typename EndpointSequence, typename ConnectCondition>
  156. typename Protocol::endpoint connect(basic_socket<Protocol, Executor>& s,
  157. const EndpointSequence& endpoints, ConnectCondition connect_condition,
  158. asio::error_code& ec,
  159. constraint_t<is_endpoint_sequence<EndpointSequence>::value>)
  160. {
  161. return detail::deref_connect_result<Protocol>(
  162. connect(s, endpoints.begin(), endpoints.end(),
  163. connect_condition, ec), ec);
  164. }
  165. #if !defined(ASIO_NO_DEPRECATED)
  166. template <typename Protocol, typename Executor,
  167. typename Iterator, typename ConnectCondition>
  168. Iterator connect(basic_socket<Protocol, Executor>& s,
  169. Iterator begin, ConnectCondition connect_condition,
  170. constraint_t<!is_endpoint_sequence<Iterator>::value>)
  171. {
  172. asio::error_code ec;
  173. Iterator result = connect(s, begin, connect_condition, ec);
  174. asio::detail::throw_error(ec, "connect");
  175. return result;
  176. }
  177. template <typename Protocol, typename Executor,
  178. typename Iterator, typename ConnectCondition>
  179. inline Iterator connect(basic_socket<Protocol, Executor>& s,
  180. Iterator begin, ConnectCondition connect_condition,
  181. asio::error_code& ec,
  182. constraint_t<!is_endpoint_sequence<Iterator>::value>)
  183. {
  184. return connect(s, begin, Iterator(), connect_condition, ec);
  185. }
  186. #endif // !defined(ASIO_NO_DEPRECATED)
  187. template <typename Protocol, typename Executor,
  188. typename Iterator, typename ConnectCondition>
  189. Iterator connect(basic_socket<Protocol, Executor>& s, Iterator begin,
  190. Iterator end, ConnectCondition connect_condition)
  191. {
  192. asio::error_code ec;
  193. Iterator result = connect(s, begin, end, connect_condition, ec);
  194. asio::detail::throw_error(ec, "connect");
  195. return result;
  196. }
  197. template <typename Protocol, typename Executor,
  198. typename Iterator, typename ConnectCondition>
  199. Iterator connect(basic_socket<Protocol, Executor>& s, Iterator begin,
  200. Iterator end, ConnectCondition connect_condition,
  201. asio::error_code& ec)
  202. {
  203. ec = asio::error_code();
  204. for (Iterator iter = begin; iter != end; ++iter)
  205. {
  206. iter = (detail::call_connect_condition(connect_condition, ec, iter, end));
  207. if (iter != end)
  208. {
  209. s.close(ec);
  210. s.connect(*iter, ec);
  211. if (!ec)
  212. return iter;
  213. }
  214. else
  215. break;
  216. }
  217. if (!ec)
  218. ec = asio::error::not_found;
  219. return end;
  220. }
  221. namespace detail
  222. {
  223. // Enable the empty base class optimisation for the connect condition.
  224. template <typename ConnectCondition>
  225. class base_from_connect_condition
  226. {
  227. protected:
  228. explicit base_from_connect_condition(
  229. const ConnectCondition& connect_condition)
  230. : connect_condition_(connect_condition)
  231. {
  232. }
  233. template <typename Iterator>
  234. void check_condition(const asio::error_code& ec,
  235. Iterator& iter, Iterator& end)
  236. {
  237. iter = detail::call_connect_condition(connect_condition_, ec, iter, end);
  238. }
  239. private:
  240. ConnectCondition connect_condition_;
  241. };
  242. // The default_connect_condition implementation is essentially a no-op. This
  243. // template specialisation lets us eliminate all costs associated with it.
  244. template <>
  245. class base_from_connect_condition<default_connect_condition>
  246. {
  247. protected:
  248. explicit base_from_connect_condition(const default_connect_condition&)
  249. {
  250. }
  251. template <typename Iterator>
  252. void check_condition(const asio::error_code&, Iterator&, Iterator&)
  253. {
  254. }
  255. };
  256. template <typename Protocol, typename Executor, typename EndpointSequence,
  257. typename ConnectCondition, typename RangeConnectHandler>
  258. class range_connect_op
  259. : public base_from_cancellation_state<RangeConnectHandler>,
  260. base_from_connect_condition<ConnectCondition>
  261. {
  262. public:
  263. range_connect_op(basic_socket<Protocol, Executor>& sock,
  264. const EndpointSequence& endpoints,
  265. const ConnectCondition& connect_condition,
  266. RangeConnectHandler& handler)
  267. : base_from_cancellation_state<RangeConnectHandler>(
  268. handler, enable_partial_cancellation()),
  269. base_from_connect_condition<ConnectCondition>(connect_condition),
  270. socket_(sock),
  271. endpoints_(endpoints),
  272. index_(0),
  273. start_(0),
  274. handler_(static_cast<RangeConnectHandler&&>(handler))
  275. {
  276. }
  277. range_connect_op(const range_connect_op& other)
  278. : base_from_cancellation_state<RangeConnectHandler>(other),
  279. base_from_connect_condition<ConnectCondition>(other),
  280. socket_(other.socket_),
  281. endpoints_(other.endpoints_),
  282. index_(other.index_),
  283. start_(other.start_),
  284. handler_(other.handler_)
  285. {
  286. }
  287. range_connect_op(range_connect_op&& other)
  288. : base_from_cancellation_state<RangeConnectHandler>(
  289. static_cast<base_from_cancellation_state<RangeConnectHandler>&&>(
  290. other)),
  291. base_from_connect_condition<ConnectCondition>(other),
  292. socket_(other.socket_),
  293. endpoints_(other.endpoints_),
  294. index_(other.index_),
  295. start_(other.start_),
  296. handler_(static_cast<RangeConnectHandler&&>(other.handler_))
  297. {
  298. }
  299. void operator()(asio::error_code ec, int start = 0)
  300. {
  301. this->process(ec, start,
  302. const_cast<const EndpointSequence&>(endpoints_).begin(),
  303. const_cast<const EndpointSequence&>(endpoints_).end());
  304. }
  305. //private:
  306. template <typename Iterator>
  307. void process(asio::error_code ec,
  308. int start, Iterator begin, Iterator end)
  309. {
  310. Iterator iter = begin;
  311. std::advance(iter, index_);
  312. switch (start_ = start)
  313. {
  314. case 1:
  315. for (;;)
  316. {
  317. this->check_condition(ec, iter, end);
  318. index_ = std::distance(begin, iter);
  319. if (iter != end)
  320. {
  321. socket_.close(ec);
  322. ASIO_HANDLER_LOCATION((__FILE__, __LINE__, "async_connect"));
  323. socket_.async_connect(*iter,
  324. static_cast<range_connect_op&&>(*this));
  325. return;
  326. }
  327. if (start)
  328. {
  329. ec = asio::error::not_found;
  330. ASIO_HANDLER_LOCATION((__FILE__, __LINE__, "async_connect"));
  331. asio::post(socket_.get_executor(),
  332. detail::bind_handler(
  333. static_cast<range_connect_op&&>(*this), ec));
  334. return;
  335. }
  336. /* fall-through */ default:
  337. if (iter == end)
  338. break;
  339. if (!socket_.is_open())
  340. {
  341. ec = asio::error::operation_aborted;
  342. break;
  343. }
  344. if (!ec)
  345. break;
  346. if (this->cancelled() != cancellation_type::none)
  347. {
  348. ec = asio::error::operation_aborted;
  349. break;
  350. }
  351. ++iter;
  352. ++index_;
  353. }
  354. static_cast<RangeConnectHandler&&>(handler_)(
  355. static_cast<const asio::error_code&>(ec),
  356. static_cast<const typename Protocol::endpoint&>(
  357. ec || iter == end ? typename Protocol::endpoint() : *iter));
  358. }
  359. }
  360. basic_socket<Protocol, Executor>& socket_;
  361. EndpointSequence endpoints_;
  362. std::size_t index_;
  363. int start_;
  364. RangeConnectHandler handler_;
  365. };
  366. template <typename Protocol, typename Executor, typename EndpointSequence,
  367. typename ConnectCondition, typename RangeConnectHandler>
  368. inline bool asio_handler_is_continuation(
  369. range_connect_op<Protocol, Executor, EndpointSequence,
  370. ConnectCondition, RangeConnectHandler>* this_handler)
  371. {
  372. return asio_handler_cont_helpers::is_continuation(
  373. this_handler->handler_);
  374. }
  375. template <typename Protocol, typename Executor>
  376. class initiate_async_range_connect
  377. {
  378. public:
  379. typedef Executor executor_type;
  380. explicit initiate_async_range_connect(basic_socket<Protocol, Executor>& s)
  381. : socket_(s)
  382. {
  383. }
  384. executor_type get_executor() const noexcept
  385. {
  386. return socket_.get_executor();
  387. }
  388. template <typename RangeConnectHandler,
  389. typename EndpointSequence, typename ConnectCondition>
  390. void operator()(RangeConnectHandler&& handler,
  391. const EndpointSequence& endpoints,
  392. const ConnectCondition& connect_condition) const
  393. {
  394. // If you get an error on the following line it means that your
  395. // handler does not meet the documented type requirements for an
  396. // RangeConnectHandler.
  397. ASIO_RANGE_CONNECT_HANDLER_CHECK(RangeConnectHandler,
  398. handler, typename Protocol::endpoint) type_check;
  399. non_const_lvalue<RangeConnectHandler> handler2(handler);
  400. range_connect_op<Protocol, Executor, EndpointSequence, ConnectCondition,
  401. decay_t<RangeConnectHandler>>(socket_, endpoints,
  402. connect_condition, handler2.value)(asio::error_code(), 1);
  403. }
  404. private:
  405. basic_socket<Protocol, Executor>& socket_;
  406. };
  407. template <typename Protocol, typename Executor, typename Iterator,
  408. typename ConnectCondition, typename IteratorConnectHandler>
  409. class iterator_connect_op
  410. : public base_from_cancellation_state<IteratorConnectHandler>,
  411. base_from_connect_condition<ConnectCondition>
  412. {
  413. public:
  414. iterator_connect_op(basic_socket<Protocol, Executor>& sock,
  415. const Iterator& begin, const Iterator& end,
  416. const ConnectCondition& connect_condition,
  417. IteratorConnectHandler& handler)
  418. : base_from_cancellation_state<IteratorConnectHandler>(
  419. handler, enable_partial_cancellation()),
  420. base_from_connect_condition<ConnectCondition>(connect_condition),
  421. socket_(sock),
  422. iter_(begin),
  423. end_(end),
  424. start_(0),
  425. handler_(static_cast<IteratorConnectHandler&&>(handler))
  426. {
  427. }
  428. iterator_connect_op(const iterator_connect_op& other)
  429. : base_from_cancellation_state<IteratorConnectHandler>(other),
  430. base_from_connect_condition<ConnectCondition>(other),
  431. socket_(other.socket_),
  432. iter_(other.iter_),
  433. end_(other.end_),
  434. start_(other.start_),
  435. handler_(other.handler_)
  436. {
  437. }
  438. iterator_connect_op(iterator_connect_op&& other)
  439. : base_from_cancellation_state<IteratorConnectHandler>(
  440. static_cast<base_from_cancellation_state<IteratorConnectHandler>&&>(
  441. other)),
  442. base_from_connect_condition<ConnectCondition>(other),
  443. socket_(other.socket_),
  444. iter_(other.iter_),
  445. end_(other.end_),
  446. start_(other.start_),
  447. handler_(static_cast<IteratorConnectHandler&&>(other.handler_))
  448. {
  449. }
  450. void operator()(asio::error_code ec, int start = 0)
  451. {
  452. switch (start_ = start)
  453. {
  454. case 1:
  455. for (;;)
  456. {
  457. this->check_condition(ec, iter_, end_);
  458. if (iter_ != end_)
  459. {
  460. socket_.close(ec);
  461. ASIO_HANDLER_LOCATION((__FILE__, __LINE__, "async_connect"));
  462. socket_.async_connect(*iter_,
  463. static_cast<iterator_connect_op&&>(*this));
  464. return;
  465. }
  466. if (start)
  467. {
  468. ec = asio::error::not_found;
  469. ASIO_HANDLER_LOCATION((__FILE__, __LINE__, "async_connect"));
  470. asio::post(socket_.get_executor(),
  471. detail::bind_handler(
  472. static_cast<iterator_connect_op&&>(*this), ec));
  473. return;
  474. }
  475. /* fall-through */ default:
  476. if (iter_ == end_)
  477. break;
  478. if (!socket_.is_open())
  479. {
  480. ec = asio::error::operation_aborted;
  481. break;
  482. }
  483. if (!ec)
  484. break;
  485. if (this->cancelled() != cancellation_type::none)
  486. {
  487. ec = asio::error::operation_aborted;
  488. break;
  489. }
  490. ++iter_;
  491. }
  492. static_cast<IteratorConnectHandler&&>(handler_)(
  493. static_cast<const asio::error_code&>(ec),
  494. static_cast<const Iterator&>(iter_));
  495. }
  496. }
  497. //private:
  498. basic_socket<Protocol, Executor>& socket_;
  499. Iterator iter_;
  500. Iterator end_;
  501. int start_;
  502. IteratorConnectHandler handler_;
  503. };
  504. template <typename Protocol, typename Executor, typename Iterator,
  505. typename ConnectCondition, typename IteratorConnectHandler>
  506. inline bool asio_handler_is_continuation(
  507. iterator_connect_op<Protocol, Executor, Iterator,
  508. ConnectCondition, IteratorConnectHandler>* this_handler)
  509. {
  510. return asio_handler_cont_helpers::is_continuation(
  511. this_handler->handler_);
  512. }
  513. template <typename Protocol, typename Executor>
  514. class initiate_async_iterator_connect
  515. {
  516. public:
  517. typedef Executor executor_type;
  518. explicit initiate_async_iterator_connect(
  519. basic_socket<Protocol, Executor>& s)
  520. : socket_(s)
  521. {
  522. }
  523. executor_type get_executor() const noexcept
  524. {
  525. return socket_.get_executor();
  526. }
  527. template <typename IteratorConnectHandler,
  528. typename Iterator, typename ConnectCondition>
  529. void operator()(IteratorConnectHandler&& handler,
  530. Iterator begin, Iterator end,
  531. const ConnectCondition& connect_condition) const
  532. {
  533. // If you get an error on the following line it means that your
  534. // handler does not meet the documented type requirements for an
  535. // IteratorConnectHandler.
  536. ASIO_ITERATOR_CONNECT_HANDLER_CHECK(
  537. IteratorConnectHandler, handler, Iterator) type_check;
  538. non_const_lvalue<IteratorConnectHandler> handler2(handler);
  539. iterator_connect_op<Protocol, Executor, Iterator, ConnectCondition,
  540. decay_t<IteratorConnectHandler>>(socket_, begin, end,
  541. connect_condition, handler2.value)(asio::error_code(), 1);
  542. }
  543. private:
  544. basic_socket<Protocol, Executor>& socket_;
  545. };
  546. } // namespace detail
  547. #if !defined(GENERATING_DOCUMENTATION)
  548. template <template <typename, typename> class Associator,
  549. typename Protocol, typename Executor, typename EndpointSequence,
  550. typename ConnectCondition, typename RangeConnectHandler,
  551. typename DefaultCandidate>
  552. struct associator<Associator,
  553. detail::range_connect_op<Protocol, Executor,
  554. EndpointSequence, ConnectCondition, RangeConnectHandler>,
  555. DefaultCandidate>
  556. : Associator<RangeConnectHandler, DefaultCandidate>
  557. {
  558. static typename Associator<RangeConnectHandler, DefaultCandidate>::type get(
  559. const detail::range_connect_op<Protocol, Executor, EndpointSequence,
  560. ConnectCondition, RangeConnectHandler>& h) noexcept
  561. {
  562. return Associator<RangeConnectHandler, DefaultCandidate>::get(h.handler_);
  563. }
  564. static auto get(
  565. const detail::range_connect_op<Protocol, Executor,
  566. EndpointSequence, ConnectCondition, RangeConnectHandler>& h,
  567. const DefaultCandidate& c) noexcept
  568. -> decltype(
  569. Associator<RangeConnectHandler, DefaultCandidate>::get(
  570. h.handler_, c))
  571. {
  572. return Associator<RangeConnectHandler, DefaultCandidate>::get(
  573. h.handler_, c);
  574. }
  575. };
  576. template <template <typename, typename> class Associator,
  577. typename Protocol, typename Executor, typename Iterator,
  578. typename ConnectCondition, typename IteratorConnectHandler,
  579. typename DefaultCandidate>
  580. struct associator<Associator,
  581. detail::iterator_connect_op<Protocol, Executor,
  582. Iterator, ConnectCondition, IteratorConnectHandler>,
  583. DefaultCandidate>
  584. : Associator<IteratorConnectHandler, DefaultCandidate>
  585. {
  586. static typename Associator<IteratorConnectHandler, DefaultCandidate>::type
  587. get(const detail::iterator_connect_op<Protocol, Executor, Iterator,
  588. ConnectCondition, IteratorConnectHandler>& h) noexcept
  589. {
  590. return Associator<IteratorConnectHandler, DefaultCandidate>::get(
  591. h.handler_);
  592. }
  593. static auto get(
  594. const detail::iterator_connect_op<Protocol, Executor,
  595. Iterator, ConnectCondition, IteratorConnectHandler>& h,
  596. const DefaultCandidate& c) noexcept
  597. -> decltype(
  598. Associator<IteratorConnectHandler, DefaultCandidate>::get(
  599. h.handler_, c))
  600. {
  601. return Associator<IteratorConnectHandler, DefaultCandidate>::get(
  602. h.handler_, c);
  603. }
  604. };
  605. #endif // !defined(GENERATING_DOCUMENTATION)
  606. template <typename Protocol, typename Executor, typename EndpointSequence,
  607. ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,
  608. typename Protocol::endpoint)) RangeConnectToken>
  609. inline auto async_connect(basic_socket<Protocol, Executor>& s,
  610. const EndpointSequence& endpoints, RangeConnectToken&& token,
  611. constraint_t<is_endpoint_sequence<EndpointSequence>::value>)
  612. -> decltype(
  613. async_initiate<RangeConnectToken,
  614. void (asio::error_code, typename Protocol::endpoint)>(
  615. declval<detail::initiate_async_range_connect<Protocol, Executor>>(),
  616. token, endpoints, declval<detail::default_connect_condition>()))
  617. {
  618. return async_initiate<RangeConnectToken,
  619. void (asio::error_code, typename Protocol::endpoint)>(
  620. detail::initiate_async_range_connect<Protocol, Executor>(s),
  621. token, endpoints, detail::default_connect_condition());
  622. }
  623. #if !defined(ASIO_NO_DEPRECATED)
  624. template <typename Protocol, typename Executor, typename Iterator,
  625. ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,
  626. Iterator)) IteratorConnectToken>
  627. inline auto async_connect(basic_socket<Protocol, Executor>& s,
  628. Iterator begin, IteratorConnectToken&& token,
  629. constraint_t<!is_endpoint_sequence<Iterator>::value>)
  630. -> decltype(
  631. async_initiate<IteratorConnectToken,
  632. void (asio::error_code, Iterator)>(
  633. declval<detail::initiate_async_iterator_connect<Protocol, Executor>>(),
  634. token, begin, Iterator(), declval<detail::default_connect_condition>()))
  635. {
  636. return async_initiate<IteratorConnectToken,
  637. void (asio::error_code, Iterator)>(
  638. detail::initiate_async_iterator_connect<Protocol, Executor>(s),
  639. token, begin, Iterator(), detail::default_connect_condition());
  640. }
  641. #endif // !defined(ASIO_NO_DEPRECATED)
  642. template <typename Protocol, typename Executor, typename Iterator,
  643. ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,
  644. Iterator)) IteratorConnectToken>
  645. inline auto async_connect(basic_socket<Protocol, Executor>& s,
  646. Iterator begin, Iterator end, IteratorConnectToken&& token)
  647. -> decltype(
  648. async_initiate<IteratorConnectToken,
  649. void (asio::error_code, Iterator)>(
  650. declval<detail::initiate_async_iterator_connect<Protocol, Executor>>(),
  651. token, begin, end, declval<detail::default_connect_condition>()))
  652. {
  653. return async_initiate<IteratorConnectToken,
  654. void (asio::error_code, Iterator)>(
  655. detail::initiate_async_iterator_connect<Protocol, Executor>(s),
  656. token, begin, end, detail::default_connect_condition());
  657. }
  658. template <typename Protocol, typename Executor,
  659. typename EndpointSequence, typename ConnectCondition,
  660. ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,
  661. typename Protocol::endpoint)) RangeConnectToken>
  662. inline auto async_connect(basic_socket<Protocol, Executor>& s,
  663. const EndpointSequence& endpoints, ConnectCondition connect_condition,
  664. RangeConnectToken&& token,
  665. constraint_t<is_endpoint_sequence<EndpointSequence>::value>)
  666. -> decltype(
  667. async_initiate<RangeConnectToken,
  668. void (asio::error_code, typename Protocol::endpoint)>(
  669. declval<detail::initiate_async_range_connect<Protocol, Executor>>(),
  670. token, endpoints, connect_condition))
  671. {
  672. return async_initiate<RangeConnectToken,
  673. void (asio::error_code, typename Protocol::endpoint)>(
  674. detail::initiate_async_range_connect<Protocol, Executor>(s),
  675. token, endpoints, connect_condition);
  676. }
  677. #if !defined(ASIO_NO_DEPRECATED)
  678. template <typename Protocol, typename Executor,
  679. typename Iterator, typename ConnectCondition,
  680. ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,
  681. Iterator)) IteratorConnectToken>
  682. inline auto async_connect(basic_socket<Protocol, Executor>& s, Iterator begin,
  683. ConnectCondition connect_condition, IteratorConnectToken&& token,
  684. constraint_t<!is_endpoint_sequence<Iterator>::value>)
  685. -> decltype(
  686. async_initiate<IteratorConnectToken,
  687. void (asio::error_code, Iterator)>(
  688. declval<detail::initiate_async_iterator_connect<Protocol, Executor>>(),
  689. token, begin, Iterator(), connect_condition))
  690. {
  691. return async_initiate<IteratorConnectToken,
  692. void (asio::error_code, Iterator)>(
  693. detail::initiate_async_iterator_connect<Protocol, Executor>(s),
  694. token, begin, Iterator(), connect_condition);
  695. }
  696. #endif // !defined(ASIO_NO_DEPRECATED)
  697. template <typename Protocol, typename Executor,
  698. typename Iterator, typename ConnectCondition,
  699. ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,
  700. Iterator)) IteratorConnectToken>
  701. inline auto async_connect(basic_socket<Protocol, Executor>& s,
  702. Iterator begin, Iterator end, ConnectCondition connect_condition,
  703. IteratorConnectToken&& token)
  704. -> decltype(
  705. async_initiate<IteratorConnectToken,
  706. void (asio::error_code, Iterator)>(
  707. declval<detail::initiate_async_iterator_connect<Protocol, Executor>>(),
  708. token, begin, end, connect_condition))
  709. {
  710. return async_initiate<IteratorConnectToken,
  711. void (asio::error_code, Iterator)>(
  712. detail::initiate_async_iterator_connect<Protocol, Executor>(s),
  713. token, begin, end, connect_condition);
  714. }
  715. } // namespace asio
  716. #include "asio/detail/pop_options.hpp"
  717. #endif // ASIO_IMPL_CONNECT_HPP