connect.hpp 30 KB

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