connect.hpp 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918
  1. //
  2. // impl/connect.hpp
  3. // ~~~~~~~~~~~~~~~~
  4. //
  5. // Copyright (c) 2003-2021 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/associated_allocator.hpp>
  17. #include <boost/asio/associated_executor.hpp>
  18. #include <boost/asio/detail/bind_handler.hpp>
  19. #include <boost/asio/detail/handler_alloc_helpers.hpp>
  20. #include <boost/asio/detail/handler_cont_helpers.hpp>
  21. #include <boost/asio/detail/handler_invoke_helpers.hpp>
  22. #include <boost/asio/detail/handler_tracking.hpp>
  23. #include <boost/asio/detail/handler_type_requirements.hpp>
  24. #include <boost/asio/detail/non_const_lvalue.hpp>
  25. #include <boost/asio/detail/throw_error.hpp>
  26. #include <boost/asio/error.hpp>
  27. #include <boost/asio/post.hpp>
  28. #include <boost/asio/detail/push_options.hpp>
  29. namespace boost {
  30. namespace asio {
  31. namespace detail
  32. {
  33. struct default_connect_condition
  34. {
  35. template <typename Endpoint>
  36. bool operator()(const boost::system::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, boost::system::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. (*static_cast<legacy_connect_condition_helper<T, Iterator>*>(0))(
  67. *static_cast<const boost::system::error_code*>(0),
  68. *static_cast<const Iterator*>(0)))) != 1;
  69. };
  70. template <typename ConnectCondition, typename Iterator>
  71. inline Iterator call_connect_condition(ConnectCondition& connect_condition,
  72. const boost::system::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 boost::system::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. boost::system::error_code ec;
  99. typename Protocol::endpoint result = connect(s, endpoints, ec);
  100. boost::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, boost::system::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(BOOST_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. boost::system::error_code ec;
  119. Iterator result = connect(s, begin, ec);
  120. boost::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, boost::system::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(BOOST_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. boost::system::error_code ec;
  136. Iterator result = connect(s, begin, end, ec);
  137. boost::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, boost::system::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. boost::system::error_code ec;
  154. typename Protocol::endpoint result = connect(
  155. s, endpoints, connect_condition, ec);
  156. boost::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. boost::system::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(BOOST_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. boost::system::error_code ec;
  179. Iterator result = connect(s, begin, connect_condition, ec);
  180. boost::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. boost::system::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(BOOST_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. boost::system::error_code ec;
  199. Iterator result = connect(s, begin, end, connect_condition, ec);
  200. boost::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. boost::system::error_code& ec)
  208. {
  209. ec = boost::system::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 = boost::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 boost::system::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 boost::system::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 : base_from_connect_condition<ConnectCondition>
  265. {
  266. public:
  267. range_connect_op(basic_socket<Protocol, Executor>& sock,
  268. const EndpointSequence& endpoints,
  269. const ConnectCondition& connect_condition,
  270. RangeConnectHandler& handler)
  271. : base_from_connect_condition<ConnectCondition>(connect_condition),
  272. socket_(sock),
  273. endpoints_(endpoints),
  274. index_(0),
  275. start_(0),
  276. handler_(BOOST_ASIO_MOVE_CAST(RangeConnectHandler)(handler))
  277. {
  278. }
  279. #if defined(BOOST_ASIO_HAS_MOVE)
  280. range_connect_op(const range_connect_op& other)
  281. : base_from_connect_condition<ConnectCondition>(other),
  282. socket_(other.socket_),
  283. endpoints_(other.endpoints_),
  284. index_(other.index_),
  285. start_(other.start_),
  286. handler_(other.handler_)
  287. {
  288. }
  289. range_connect_op(range_connect_op&& other)
  290. : base_from_connect_condition<ConnectCondition>(other),
  291. socket_(other.socket_),
  292. endpoints_(other.endpoints_),
  293. index_(other.index_),
  294. start_(other.start_),
  295. handler_(BOOST_ASIO_MOVE_CAST(RangeConnectHandler)(other.handler_))
  296. {
  297. }
  298. #endif // defined(BOOST_ASIO_HAS_MOVE)
  299. void operator()(boost::system::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(boost::system::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. BOOST_ASIO_HANDLER_LOCATION((__FILE__, __LINE__, "async_connect"));
  323. socket_.async_connect(*iter,
  324. BOOST_ASIO_MOVE_CAST(range_connect_op)(*this));
  325. return;
  326. }
  327. if (start)
  328. {
  329. ec = boost::asio::error::not_found;
  330. BOOST_ASIO_HANDLER_LOCATION((__FILE__, __LINE__, "async_connect"));
  331. boost::asio::post(socket_.get_executor(),
  332. detail::bind_handler(
  333. BOOST_ASIO_MOVE_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 = boost::asio::error::operation_aborted;
  342. break;
  343. }
  344. if (!ec)
  345. break;
  346. ++iter;
  347. ++index_;
  348. }
  349. handler_(static_cast<const boost::system::error_code&>(ec),
  350. static_cast<const typename Protocol::endpoint&>(
  351. ec || iter == end ? typename Protocol::endpoint() : *iter));
  352. }
  353. }
  354. basic_socket<Protocol, Executor>& socket_;
  355. EndpointSequence endpoints_;
  356. std::size_t index_;
  357. int start_;
  358. RangeConnectHandler handler_;
  359. };
  360. template <typename Protocol, typename Executor, typename EndpointSequence,
  361. typename ConnectCondition, typename RangeConnectHandler>
  362. inline asio_handler_allocate_is_deprecated
  363. asio_handler_allocate(std::size_t size,
  364. range_connect_op<Protocol, Executor, EndpointSequence,
  365. ConnectCondition, RangeConnectHandler>* this_handler)
  366. {
  367. #if defined(BOOST_ASIO_NO_DEPRECATED)
  368. boost_asio_handler_alloc_helpers::allocate(size, this_handler->handler_);
  369. return asio_handler_allocate_is_no_longer_used();
  370. #else // defined(BOOST_ASIO_NO_DEPRECATED)
  371. return boost_asio_handler_alloc_helpers::allocate(
  372. size, this_handler->handler_);
  373. #endif // defined(BOOST_ASIO_NO_DEPRECATED)
  374. }
  375. template <typename Protocol, typename Executor, typename EndpointSequence,
  376. typename ConnectCondition, typename RangeConnectHandler>
  377. inline asio_handler_deallocate_is_deprecated
  378. asio_handler_deallocate(void* pointer, std::size_t size,
  379. range_connect_op<Protocol, Executor, EndpointSequence,
  380. ConnectCondition, RangeConnectHandler>* this_handler)
  381. {
  382. boost_asio_handler_alloc_helpers::deallocate(
  383. pointer, size, this_handler->handler_);
  384. #if defined(BOOST_ASIO_NO_DEPRECATED)
  385. return asio_handler_deallocate_is_no_longer_used();
  386. #endif // defined(BOOST_ASIO_NO_DEPRECATED)
  387. }
  388. template <typename Protocol, typename Executor, typename EndpointSequence,
  389. typename ConnectCondition, typename RangeConnectHandler>
  390. inline bool asio_handler_is_continuation(
  391. range_connect_op<Protocol, Executor, EndpointSequence,
  392. ConnectCondition, RangeConnectHandler>* this_handler)
  393. {
  394. return boost_asio_handler_cont_helpers::is_continuation(
  395. this_handler->handler_);
  396. }
  397. template <typename Function, typename Executor, typename Protocol,
  398. typename EndpointSequence, typename ConnectCondition,
  399. typename RangeConnectHandler>
  400. inline asio_handler_invoke_is_deprecated
  401. asio_handler_invoke(Function& function,
  402. range_connect_op<Protocol, Executor, EndpointSequence,
  403. ConnectCondition, RangeConnectHandler>* this_handler)
  404. {
  405. boost_asio_handler_invoke_helpers::invoke(
  406. function, this_handler->handler_);
  407. #if defined(BOOST_ASIO_NO_DEPRECATED)
  408. return asio_handler_invoke_is_no_longer_used();
  409. #endif // defined(BOOST_ASIO_NO_DEPRECATED)
  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(const Function& function,
  416. range_connect_op<Protocol, Executor, EndpointSequence,
  417. ConnectCondition, RangeConnectHandler>* this_handler)
  418. {
  419. boost_asio_handler_invoke_helpers::invoke(
  420. function, this_handler->handler_);
  421. #if defined(BOOST_ASIO_NO_DEPRECATED)
  422. return asio_handler_invoke_is_no_longer_used();
  423. #endif // defined(BOOST_ASIO_NO_DEPRECATED)
  424. }
  425. template <typename Protocol, typename Executor>
  426. class initiate_async_range_connect
  427. {
  428. public:
  429. typedef Executor executor_type;
  430. explicit initiate_async_range_connect(basic_socket<Protocol, Executor>& s)
  431. : socket_(s)
  432. {
  433. }
  434. executor_type get_executor() const BOOST_ASIO_NOEXCEPT
  435. {
  436. return socket_.get_executor();
  437. }
  438. template <typename RangeConnectHandler,
  439. typename EndpointSequence, typename ConnectCondition>
  440. void operator()(BOOST_ASIO_MOVE_ARG(RangeConnectHandler) handler,
  441. const EndpointSequence& endpoints,
  442. const ConnectCondition& connect_condition) const
  443. {
  444. // If you get an error on the following line it means that your
  445. // handler does not meet the documented type requirements for an
  446. // RangeConnectHandler.
  447. BOOST_ASIO_RANGE_CONNECT_HANDLER_CHECK(RangeConnectHandler,
  448. handler, typename Protocol::endpoint) type_check;
  449. non_const_lvalue<RangeConnectHandler> handler2(handler);
  450. range_connect_op<Protocol, Executor, EndpointSequence, ConnectCondition,
  451. typename decay<RangeConnectHandler>::type>(socket_, endpoints,
  452. connect_condition, handler2.value)(boost::system::error_code(), 1);
  453. }
  454. private:
  455. basic_socket<Protocol, Executor>& socket_;
  456. };
  457. template <typename Protocol, typename Executor, typename Iterator,
  458. typename ConnectCondition, typename IteratorConnectHandler>
  459. class iterator_connect_op : base_from_connect_condition<ConnectCondition>
  460. {
  461. public:
  462. iterator_connect_op(basic_socket<Protocol, Executor>& sock,
  463. const Iterator& begin, const Iterator& end,
  464. const ConnectCondition& connect_condition,
  465. IteratorConnectHandler& handler)
  466. : base_from_connect_condition<ConnectCondition>(connect_condition),
  467. socket_(sock),
  468. iter_(begin),
  469. end_(end),
  470. start_(0),
  471. handler_(BOOST_ASIO_MOVE_CAST(IteratorConnectHandler)(handler))
  472. {
  473. }
  474. #if defined(BOOST_ASIO_HAS_MOVE)
  475. iterator_connect_op(const iterator_connect_op& other)
  476. : base_from_connect_condition<ConnectCondition>(other),
  477. socket_(other.socket_),
  478. iter_(other.iter_),
  479. end_(other.end_),
  480. start_(other.start_),
  481. handler_(other.handler_)
  482. {
  483. }
  484. iterator_connect_op(iterator_connect_op&& other)
  485. : base_from_connect_condition<ConnectCondition>(other),
  486. socket_(other.socket_),
  487. iter_(other.iter_),
  488. end_(other.end_),
  489. start_(other.start_),
  490. handler_(BOOST_ASIO_MOVE_CAST(IteratorConnectHandler)(other.handler_))
  491. {
  492. }
  493. #endif // defined(BOOST_ASIO_HAS_MOVE)
  494. void operator()(boost::system::error_code ec, int start = 0)
  495. {
  496. switch (start_ = start)
  497. {
  498. case 1:
  499. for (;;)
  500. {
  501. this->check_condition(ec, iter_, end_);
  502. if (iter_ != end_)
  503. {
  504. socket_.close(ec);
  505. BOOST_ASIO_HANDLER_LOCATION((__FILE__, __LINE__, "async_connect"));
  506. socket_.async_connect(*iter_,
  507. BOOST_ASIO_MOVE_CAST(iterator_connect_op)(*this));
  508. return;
  509. }
  510. if (start)
  511. {
  512. ec = boost::asio::error::not_found;
  513. BOOST_ASIO_HANDLER_LOCATION((__FILE__, __LINE__, "async_connect"));
  514. boost::asio::post(socket_.get_executor(),
  515. detail::bind_handler(
  516. BOOST_ASIO_MOVE_CAST(iterator_connect_op)(*this), ec));
  517. return;
  518. }
  519. /* fall-through */ default:
  520. if (iter_ == end_)
  521. break;
  522. if (!socket_.is_open())
  523. {
  524. ec = boost::asio::error::operation_aborted;
  525. break;
  526. }
  527. if (!ec)
  528. break;
  529. ++iter_;
  530. }
  531. handler_(static_cast<const boost::system::error_code&>(ec),
  532. static_cast<const Iterator&>(iter_));
  533. }
  534. }
  535. //private:
  536. basic_socket<Protocol, Executor>& socket_;
  537. Iterator iter_;
  538. Iterator end_;
  539. int start_;
  540. IteratorConnectHandler handler_;
  541. };
  542. template <typename Protocol, typename Executor, typename Iterator,
  543. typename ConnectCondition, typename IteratorConnectHandler>
  544. inline asio_handler_allocate_is_deprecated
  545. asio_handler_allocate(std::size_t size,
  546. iterator_connect_op<Protocol, Executor, Iterator,
  547. ConnectCondition, IteratorConnectHandler>* this_handler)
  548. {
  549. #if defined(BOOST_ASIO_NO_DEPRECATED)
  550. boost_asio_handler_alloc_helpers::allocate(size, this_handler->handler_);
  551. return asio_handler_allocate_is_no_longer_used();
  552. #else // defined(BOOST_ASIO_NO_DEPRECATED)
  553. return boost_asio_handler_alloc_helpers::allocate(
  554. size, this_handler->handler_);
  555. #endif // defined(BOOST_ASIO_NO_DEPRECATED)
  556. }
  557. template <typename Protocol, typename Executor, typename Iterator,
  558. typename ConnectCondition, typename IteratorConnectHandler>
  559. inline asio_handler_deallocate_is_deprecated
  560. asio_handler_deallocate(void* pointer, std::size_t size,
  561. iterator_connect_op<Protocol, Executor, Iterator,
  562. ConnectCondition, IteratorConnectHandler>* this_handler)
  563. {
  564. boost_asio_handler_alloc_helpers::deallocate(
  565. pointer, size, this_handler->handler_);
  566. #if defined(BOOST_ASIO_NO_DEPRECATED)
  567. return asio_handler_deallocate_is_no_longer_used();
  568. #endif // defined(BOOST_ASIO_NO_DEPRECATED)
  569. }
  570. template <typename Protocol, typename Executor, typename Iterator,
  571. typename ConnectCondition, typename IteratorConnectHandler>
  572. inline bool asio_handler_is_continuation(
  573. iterator_connect_op<Protocol, Executor, Iterator,
  574. ConnectCondition, IteratorConnectHandler>* this_handler)
  575. {
  576. return boost_asio_handler_cont_helpers::is_continuation(
  577. this_handler->handler_);
  578. }
  579. template <typename Function, typename Executor, typename Protocol,
  580. typename Iterator, typename ConnectCondition,
  581. typename IteratorConnectHandler>
  582. inline asio_handler_invoke_is_deprecated
  583. asio_handler_invoke(Function& function,
  584. iterator_connect_op<Protocol, Executor, Iterator,
  585. ConnectCondition, IteratorConnectHandler>* this_handler)
  586. {
  587. boost_asio_handler_invoke_helpers::invoke(
  588. function, this_handler->handler_);
  589. #if defined(BOOST_ASIO_NO_DEPRECATED)
  590. return asio_handler_invoke_is_no_longer_used();
  591. #endif // defined(BOOST_ASIO_NO_DEPRECATED)
  592. }
  593. template <typename Function, typename Executor, typename Protocol,
  594. typename Iterator, typename ConnectCondition,
  595. typename IteratorConnectHandler>
  596. inline asio_handler_invoke_is_deprecated
  597. asio_handler_invoke(const Function& function,
  598. iterator_connect_op<Protocol, Executor, Iterator,
  599. ConnectCondition, IteratorConnectHandler>* this_handler)
  600. {
  601. boost_asio_handler_invoke_helpers::invoke(
  602. function, this_handler->handler_);
  603. #if defined(BOOST_ASIO_NO_DEPRECATED)
  604. return asio_handler_invoke_is_no_longer_used();
  605. #endif // defined(BOOST_ASIO_NO_DEPRECATED)
  606. }
  607. template <typename Protocol, typename Executor>
  608. class initiate_async_iterator_connect
  609. {
  610. public:
  611. typedef Executor executor_type;
  612. explicit initiate_async_iterator_connect(
  613. basic_socket<Protocol, Executor>& s)
  614. : socket_(s)
  615. {
  616. }
  617. executor_type get_executor() const BOOST_ASIO_NOEXCEPT
  618. {
  619. return socket_.get_executor();
  620. }
  621. template <typename IteratorConnectHandler,
  622. typename Iterator, typename ConnectCondition>
  623. void operator()(BOOST_ASIO_MOVE_ARG(IteratorConnectHandler) handler,
  624. Iterator begin, Iterator end,
  625. const ConnectCondition& connect_condition) const
  626. {
  627. // If you get an error on the following line it means that your
  628. // handler does not meet the documented type requirements for an
  629. // IteratorConnectHandler.
  630. BOOST_ASIO_ITERATOR_CONNECT_HANDLER_CHECK(
  631. IteratorConnectHandler, handler, Iterator) type_check;
  632. non_const_lvalue<IteratorConnectHandler> handler2(handler);
  633. iterator_connect_op<Protocol, Executor, Iterator, ConnectCondition,
  634. typename decay<IteratorConnectHandler>::type>(socket_, begin, end,
  635. connect_condition, handler2.value)(boost::system::error_code(), 1);
  636. }
  637. private:
  638. basic_socket<Protocol, Executor>& socket_;
  639. };
  640. } // namespace detail
  641. #if !defined(GENERATING_DOCUMENTATION)
  642. template <typename Protocol, typename Executor, typename EndpointSequence,
  643. typename ConnectCondition, typename RangeConnectHandler, typename Allocator>
  644. struct associated_allocator<
  645. detail::range_connect_op<Protocol, Executor, EndpointSequence,
  646. ConnectCondition, RangeConnectHandler>, Allocator>
  647. {
  648. typedef typename associated_allocator<
  649. RangeConnectHandler, Allocator>::type type;
  650. static type get(
  651. const detail::range_connect_op<Protocol, Executor, EndpointSequence,
  652. ConnectCondition, RangeConnectHandler>& h,
  653. const Allocator& a = Allocator()) BOOST_ASIO_NOEXCEPT
  654. {
  655. return associated_allocator<RangeConnectHandler,
  656. Allocator>::get(h.handler_, a);
  657. }
  658. };
  659. template <typename Protocol, typename Executor, typename EndpointSequence,
  660. typename ConnectCondition, typename RangeConnectHandler, typename Executor1>
  661. struct associated_executor<
  662. detail::range_connect_op<Protocol, Executor, EndpointSequence,
  663. ConnectCondition, RangeConnectHandler>, Executor1>
  664. : detail::associated_executor_forwarding_base<RangeConnectHandler, Executor1>
  665. {
  666. typedef typename associated_executor<
  667. RangeConnectHandler, Executor1>::type type;
  668. static type get(
  669. const detail::range_connect_op<Protocol, Executor, EndpointSequence,
  670. ConnectCondition, RangeConnectHandler>& h,
  671. const Executor1& ex = Executor1()) BOOST_ASIO_NOEXCEPT
  672. {
  673. return associated_executor<RangeConnectHandler,
  674. Executor1>::get(h.handler_, ex);
  675. }
  676. };
  677. template <typename Protocol, typename Executor, typename Iterator,
  678. typename ConnectCondition, typename IteratorConnectHandler,
  679. typename Allocator>
  680. struct associated_allocator<
  681. detail::iterator_connect_op<Protocol, Executor,
  682. Iterator, ConnectCondition, IteratorConnectHandler>,
  683. Allocator>
  684. {
  685. typedef typename associated_allocator<
  686. IteratorConnectHandler, Allocator>::type type;
  687. static type get(
  688. const detail::iterator_connect_op<Protocol, Executor,
  689. Iterator, ConnectCondition, IteratorConnectHandler>& h,
  690. const Allocator& a = Allocator()) BOOST_ASIO_NOEXCEPT
  691. {
  692. return associated_allocator<IteratorConnectHandler,
  693. Allocator>::get(h.handler_, a);
  694. }
  695. };
  696. template <typename Protocol, typename Executor, typename Iterator,
  697. typename ConnectCondition, typename IteratorConnectHandler,
  698. typename Executor1>
  699. struct associated_executor<
  700. detail::iterator_connect_op<Protocol, Executor,
  701. Iterator, ConnectCondition, IteratorConnectHandler>,
  702. Executor1>
  703. : detail::associated_executor_forwarding_base<
  704. IteratorConnectHandler, Executor1>
  705. {
  706. typedef typename associated_executor<
  707. IteratorConnectHandler, Executor1>::type type;
  708. static type get(
  709. const detail::iterator_connect_op<Protocol, Executor,
  710. Iterator, ConnectCondition, IteratorConnectHandler>& h,
  711. const Executor1& ex = Executor1()) BOOST_ASIO_NOEXCEPT
  712. {
  713. return associated_executor<IteratorConnectHandler,
  714. Executor1>::get(h.handler_, ex);
  715. }
  716. };
  717. #endif // !defined(GENERATING_DOCUMENTATION)
  718. template <typename Protocol, typename Executor, typename EndpointSequence,
  719. BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
  720. typename Protocol::endpoint)) RangeConnectHandler>
  721. inline BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(RangeConnectHandler,
  722. void (boost::system::error_code, typename Protocol::endpoint))
  723. async_connect(basic_socket<Protocol, Executor>& s,
  724. const EndpointSequence& endpoints,
  725. BOOST_ASIO_MOVE_ARG(RangeConnectHandler) handler,
  726. typename constraint<is_endpoint_sequence<
  727. EndpointSequence>::value>::type)
  728. {
  729. return async_initiate<RangeConnectHandler,
  730. void (boost::system::error_code, typename Protocol::endpoint)>(
  731. detail::initiate_async_range_connect<Protocol, Executor>(s),
  732. handler, endpoints, detail::default_connect_condition());
  733. }
  734. #if !defined(BOOST_ASIO_NO_DEPRECATED)
  735. template <typename Protocol, typename Executor, typename Iterator,
  736. BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
  737. Iterator)) IteratorConnectHandler>
  738. inline BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(IteratorConnectHandler,
  739. void (boost::system::error_code, Iterator))
  740. async_connect(basic_socket<Protocol, Executor>& s, Iterator begin,
  741. BOOST_ASIO_MOVE_ARG(IteratorConnectHandler) handler,
  742. typename constraint<!is_endpoint_sequence<Iterator>::value>::type)
  743. {
  744. return async_initiate<IteratorConnectHandler,
  745. void (boost::system::error_code, Iterator)>(
  746. detail::initiate_async_iterator_connect<Protocol, Executor>(s),
  747. handler, begin, Iterator(), detail::default_connect_condition());
  748. }
  749. #endif // !defined(BOOST_ASIO_NO_DEPRECATED)
  750. template <typename Protocol, typename Executor, typename Iterator,
  751. BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
  752. Iterator)) IteratorConnectHandler>
  753. inline BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(IteratorConnectHandler,
  754. void (boost::system::error_code, Iterator))
  755. async_connect(basic_socket<Protocol, Executor>& s, Iterator begin, Iterator end,
  756. BOOST_ASIO_MOVE_ARG(IteratorConnectHandler) handler)
  757. {
  758. return async_initiate<IteratorConnectHandler,
  759. void (boost::system::error_code, Iterator)>(
  760. detail::initiate_async_iterator_connect<Protocol, Executor>(s),
  761. handler, begin, end, detail::default_connect_condition());
  762. }
  763. template <typename Protocol, typename Executor,
  764. typename EndpointSequence, typename ConnectCondition,
  765. BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
  766. typename Protocol::endpoint)) RangeConnectHandler>
  767. inline BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(RangeConnectHandler,
  768. void (boost::system::error_code, typename Protocol::endpoint))
  769. async_connect(basic_socket<Protocol, Executor>& s,
  770. const EndpointSequence& endpoints, ConnectCondition connect_condition,
  771. BOOST_ASIO_MOVE_ARG(RangeConnectHandler) handler,
  772. typename constraint<is_endpoint_sequence<
  773. EndpointSequence>::value>::type)
  774. {
  775. return async_initiate<RangeConnectHandler,
  776. void (boost::system::error_code, typename Protocol::endpoint)>(
  777. detail::initiate_async_range_connect<Protocol, Executor>(s),
  778. handler, endpoints, connect_condition);
  779. }
  780. #if !defined(BOOST_ASIO_NO_DEPRECATED)
  781. template <typename Protocol, typename Executor,
  782. typename Iterator, typename ConnectCondition,
  783. BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
  784. Iterator)) IteratorConnectHandler>
  785. inline BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(IteratorConnectHandler,
  786. void (boost::system::error_code, Iterator))
  787. async_connect(basic_socket<Protocol, Executor>& s, Iterator begin,
  788. ConnectCondition connect_condition,
  789. BOOST_ASIO_MOVE_ARG(IteratorConnectHandler) handler,
  790. typename constraint<!is_endpoint_sequence<Iterator>::value>::type)
  791. {
  792. return async_initiate<IteratorConnectHandler,
  793. void (boost::system::error_code, Iterator)>(
  794. detail::initiate_async_iterator_connect<Protocol, Executor>(s),
  795. handler, begin, Iterator(), connect_condition);
  796. }
  797. #endif // !defined(BOOST_ASIO_NO_DEPRECATED)
  798. template <typename Protocol, typename Executor,
  799. typename Iterator, typename ConnectCondition,
  800. BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
  801. Iterator)) IteratorConnectHandler>
  802. inline BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(IteratorConnectHandler,
  803. void (boost::system::error_code, Iterator))
  804. async_connect(basic_socket<Protocol, Executor>& s, Iterator begin,
  805. Iterator end, ConnectCondition connect_condition,
  806. BOOST_ASIO_MOVE_ARG(IteratorConnectHandler) handler)
  807. {
  808. return async_initiate<IteratorConnectHandler,
  809. void (boost::system::error_code, Iterator)>(
  810. detail::initiate_async_iterator_connect<Protocol, Executor>(s),
  811. handler, begin, end, connect_condition);
  812. }
  813. } // namespace asio
  814. } // namespace boost
  815. #include <boost/asio/detail/pop_options.hpp>
  816. #endif // BOOST_ASIO_IMPL_CONNECT_HPP