connect.hpp 28 KB

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