connect.hpp 30 KB

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