PageRenderTime 56ms CodeModel.GetById 31ms RepoModel.GetById 0ms app.codeStats 0ms

/asio/include/asio/impl/connect.hpp

https://github.com/BorisSchaeling/asio
C++ Header | 389 lines | 317 code | 51 blank | 21 comment | 18 complexity | 4c09c75389ef7079e2e52f78bcf78fa3 MD5 | raw file
  1. //
  2. // impl/connect.hpp
  3. // ~~~~~~~~~~~~~~~~
  4. //
  5. // Copyright (c) 2003-2011 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 "asio/detail/bind_handler.hpp"
  16. #include "asio/detail/consuming_buffers.hpp"
  17. #include "asio/detail/handler_alloc_helpers.hpp"
  18. #include "asio/detail/handler_invoke_helpers.hpp"
  19. #include "asio/detail/handler_type_requirements.hpp"
  20. #include "asio/detail/throw_error.hpp"
  21. #include "asio/error.hpp"
  22. #include "asio/detail/push_options.hpp"
  23. namespace asio {
  24. namespace detail
  25. {
  26. struct default_connect_condition
  27. {
  28. template <typename Iterator>
  29. Iterator operator()(const asio::error_code&, Iterator next)
  30. {
  31. return next;
  32. }
  33. };
  34. }
  35. template <typename Protocol, typename SocketService, typename Iterator>
  36. Iterator connect(basic_socket<Protocol, SocketService>& s, Iterator begin)
  37. {
  38. asio::error_code ec;
  39. Iterator result = connect(s, begin, ec);
  40. asio::detail::throw_error(ec, "connect");
  41. return result;
  42. }
  43. template <typename Protocol, typename SocketService, typename Iterator>
  44. inline Iterator connect(basic_socket<Protocol, SocketService>& s,
  45. Iterator begin, asio::error_code& ec)
  46. {
  47. return connect(s, begin, Iterator(), detail::default_connect_condition(), ec);
  48. }
  49. template <typename Protocol, typename SocketService, typename Iterator>
  50. Iterator connect(basic_socket<Protocol, SocketService>& s,
  51. Iterator begin, Iterator end)
  52. {
  53. asio::error_code ec;
  54. Iterator result = connect(s, begin, end, ec);
  55. asio::detail::throw_error(ec, "connect");
  56. return result;
  57. }
  58. template <typename Protocol, typename SocketService, typename Iterator>
  59. inline Iterator connect(basic_socket<Protocol, SocketService>& s,
  60. Iterator begin, Iterator end, asio::error_code& ec)
  61. {
  62. return connect(s, begin, end, detail::default_connect_condition(), ec);
  63. }
  64. template <typename Protocol, typename SocketService,
  65. typename Iterator, typename ConnectCondition>
  66. Iterator connect(basic_socket<Protocol, SocketService>& s,
  67. Iterator begin, ConnectCondition connect_condition)
  68. {
  69. asio::error_code ec;
  70. Iterator result = connect(s, begin, connect_condition, ec);
  71. asio::detail::throw_error(ec, "connect");
  72. return result;
  73. }
  74. template <typename Protocol, typename SocketService,
  75. typename Iterator, typename ConnectCondition>
  76. inline Iterator connect(basic_socket<Protocol, SocketService>& s,
  77. Iterator begin, ConnectCondition connect_condition,
  78. asio::error_code& ec)
  79. {
  80. return connect(s, begin, Iterator(), connect_condition, ec);
  81. }
  82. template <typename Protocol, typename SocketService,
  83. typename Iterator, typename ConnectCondition>
  84. Iterator connect(basic_socket<Protocol, SocketService>& s,
  85. Iterator begin, Iterator end, ConnectCondition connect_condition)
  86. {
  87. asio::error_code ec;
  88. Iterator result = connect(s, begin, end, connect_condition, ec);
  89. asio::detail::throw_error(ec, "connect");
  90. return result;
  91. }
  92. template <typename Protocol, typename SocketService,
  93. typename Iterator, typename ConnectCondition>
  94. Iterator connect(basic_socket<Protocol, SocketService>& s,
  95. Iterator begin, Iterator end, ConnectCondition connect_condition,
  96. asio::error_code& ec)
  97. {
  98. ec = asio::error_code();
  99. for (Iterator iter = begin; iter != end; ++iter)
  100. {
  101. iter = connect_condition(ec, iter);
  102. if (iter != end)
  103. {
  104. s.close(ec);
  105. s.connect(*iter, ec);
  106. if (!ec)
  107. return iter;
  108. }
  109. }
  110. if (!ec)
  111. ec = asio::error::not_found;
  112. return end;
  113. }
  114. namespace detail
  115. {
  116. // Enable the empty base class optimisation for the connect condition.
  117. template <typename ConnectCondition>
  118. class base_from_connect_condition
  119. {
  120. protected:
  121. explicit base_from_connect_condition(
  122. const ConnectCondition& connect_condition)
  123. : connect_condition_(connect_condition)
  124. {
  125. }
  126. template <typename Iterator>
  127. void check_condition(const asio::error_code& ec,
  128. Iterator& iter, Iterator& end)
  129. {
  130. if (iter != end)
  131. iter = connect_condition_(ec, static_cast<const Iterator&>(iter));
  132. }
  133. private:
  134. ConnectCondition connect_condition_;
  135. };
  136. // The default_connect_condition implementation is essentially a no-op. This
  137. // template specialisation lets us eliminate all costs associated with it.
  138. template <>
  139. class base_from_connect_condition<default_connect_condition>
  140. {
  141. protected:
  142. explicit base_from_connect_condition(const default_connect_condition&)
  143. {
  144. }
  145. template <typename Iterator>
  146. void check_condition(const asio::error_code&, Iterator&, Iterator&)
  147. {
  148. }
  149. };
  150. template <typename Protocol, typename SocketService, typename Iterator,
  151. typename ConnectCondition, typename ComposedConnectHandler>
  152. class connect_op : base_from_connect_condition<ConnectCondition>
  153. {
  154. public:
  155. connect_op(basic_socket<Protocol, SocketService>& sock,
  156. const Iterator& begin, const Iterator& end,
  157. const ConnectCondition& connect_condition,
  158. ComposedConnectHandler& handler)
  159. : base_from_connect_condition<ConnectCondition>(connect_condition),
  160. socket_(sock),
  161. iter_(begin),
  162. end_(end),
  163. handler_(ASIO_MOVE_CAST(ComposedConnectHandler)(handler))
  164. {
  165. }
  166. #if defined(ASIO_HAS_MOVE)
  167. connect_op(const connect_op& other)
  168. : base_from_connect_condition<ConnectCondition>(other),
  169. socket_(other.socket_),
  170. iter_(other.iter_),
  171. end_(other.end_),
  172. handler_(other.handler_)
  173. {
  174. }
  175. connect_op(connect_op&& other)
  176. : base_from_connect_condition<ConnectCondition>(other),
  177. socket_(other.socket_),
  178. iter_(other.iter_),
  179. end_(other.end_),
  180. handler_(ASIO_MOVE_CAST(ComposedConnectHandler)(other.handler_))
  181. {
  182. }
  183. #endif // defined(ASIO_HAS_MOVE)
  184. void operator()(asio::error_code ec, int start = 0)
  185. {
  186. switch (start)
  187. {
  188. case 1:
  189. for (;;)
  190. {
  191. this->check_condition(ec, iter_, end_);
  192. if (iter_ != end_)
  193. {
  194. socket_.close(ec);
  195. socket_.async_connect(*iter_,
  196. ASIO_MOVE_CAST(connect_op)(*this));
  197. return;
  198. }
  199. if (start)
  200. {
  201. ec = asio::error::not_found;
  202. socket_.get_io_service().post(detail::bind_handler(*this, ec));
  203. return;
  204. }
  205. default:
  206. if (iter_ == end_)
  207. break;
  208. if (!socket_.is_open())
  209. {
  210. ec = asio::error::operation_aborted;
  211. break;
  212. }
  213. if (!ec)
  214. break;
  215. ++iter_;
  216. }
  217. handler_(static_cast<const asio::error_code&>(ec),
  218. static_cast<const Iterator&>(iter_));
  219. }
  220. }
  221. //private:
  222. basic_socket<Protocol, SocketService>& socket_;
  223. Iterator iter_;
  224. Iterator end_;
  225. ComposedConnectHandler handler_;
  226. };
  227. template <typename Protocol, typename SocketService, typename Iterator,
  228. typename ConnectCondition, typename ComposedConnectHandler>
  229. inline void* asio_handler_allocate(std::size_t size,
  230. connect_op<Protocol, SocketService, Iterator,
  231. ConnectCondition, ComposedConnectHandler>* this_handler)
  232. {
  233. return asio_handler_alloc_helpers::allocate(
  234. size, this_handler->handler_);
  235. }
  236. template <typename Protocol, typename SocketService, typename Iterator,
  237. typename ConnectCondition, typename ComposedConnectHandler>
  238. inline void asio_handler_deallocate(void* pointer, std::size_t size,
  239. connect_op<Protocol, SocketService, Iterator,
  240. ConnectCondition, ComposedConnectHandler>* this_handler)
  241. {
  242. asio_handler_alloc_helpers::deallocate(
  243. pointer, size, this_handler->handler_);
  244. }
  245. template <typename Function, typename Protocol,
  246. typename SocketService, typename Iterator,
  247. typename ConnectCondition, typename ComposedConnectHandler>
  248. inline void asio_handler_invoke(Function& function,
  249. connect_op<Protocol, SocketService, Iterator,
  250. ConnectCondition, ComposedConnectHandler>* this_handler)
  251. {
  252. asio_handler_invoke_helpers::invoke(
  253. function, this_handler->handler_);
  254. }
  255. template <typename Function, typename Protocol,
  256. typename SocketService, typename Iterator,
  257. typename ConnectCondition, typename ComposedConnectHandler>
  258. inline void asio_handler_invoke(const Function& function,
  259. connect_op<Protocol, SocketService, Iterator,
  260. ConnectCondition, ComposedConnectHandler>* this_handler)
  261. {
  262. asio_handler_invoke_helpers::invoke(
  263. function, this_handler->handler_);
  264. }
  265. template <typename Protocol, typename SocketService, typename Iterator,
  266. typename ConnectCondition, typename ComposedConnectHandler>
  267. inline connect_op<Protocol, SocketService, Iterator,
  268. ConnectCondition, ComposedConnectHandler>
  269. make_connect_op(basic_socket<Protocol, SocketService>& sock,
  270. const Iterator& begin, const Iterator& end,
  271. const ConnectCondition& connect_condition,
  272. ComposedConnectHandler handler)
  273. {
  274. return connect_op<Protocol, SocketService, Iterator,
  275. ConnectCondition, ComposedConnectHandler>(
  276. sock, begin, end, connect_condition, handler);
  277. }
  278. } // namespace detail
  279. template <typename Protocol, typename SocketService,
  280. typename Iterator, typename ComposedConnectHandler>
  281. inline void async_connect(basic_socket<Protocol, SocketService>& s,
  282. Iterator begin, ASIO_MOVE_ARG(ComposedConnectHandler) handler)
  283. {
  284. // If you get an error on the following line it means that your handler does
  285. // not meet the documented type requirements for a ComposedConnectHandler.
  286. ASIO_COMPOSED_CONNECT_HANDLER_CHECK(
  287. ComposedConnectHandler, handler, Iterator) type_check;
  288. detail::make_connect_op(s, begin, Iterator(),
  289. detail::default_connect_condition(),
  290. ASIO_MOVE_CAST(ComposedConnectHandler)(handler))(
  291. asio::error_code(), 1);
  292. }
  293. template <typename Protocol, typename SocketService,
  294. typename Iterator, typename ComposedConnectHandler>
  295. inline void async_connect(basic_socket<Protocol, SocketService>& s,
  296. Iterator begin, Iterator end,
  297. ASIO_MOVE_ARG(ComposedConnectHandler) handler)
  298. {
  299. // If you get an error on the following line it means that your handler does
  300. // not meet the documented type requirements for a ComposedConnectHandler.
  301. ASIO_COMPOSED_CONNECT_HANDLER_CHECK(
  302. ComposedConnectHandler, handler, Iterator) type_check;
  303. detail::make_connect_op(s, begin, end,
  304. detail::default_connect_condition(),
  305. ASIO_MOVE_CAST(ComposedConnectHandler)(handler))(
  306. asio::error_code(), 1);
  307. }
  308. template <typename Protocol, typename SocketService, typename Iterator,
  309. typename ConnectCondition, typename ComposedConnectHandler>
  310. inline void async_connect(basic_socket<Protocol, SocketService>& s,
  311. Iterator begin, ConnectCondition connect_condition,
  312. ASIO_MOVE_ARG(ComposedConnectHandler) handler)
  313. {
  314. // If you get an error on the following line it means that your handler does
  315. // not meet the documented type requirements for a ComposedConnectHandler.
  316. ASIO_COMPOSED_CONNECT_HANDLER_CHECK(
  317. ComposedConnectHandler, handler, Iterator) type_check;
  318. detail::make_connect_op(s, begin, Iterator(), connect_condition,
  319. ASIO_MOVE_CAST(ComposedConnectHandler)(handler))(
  320. asio::error_code(), 1);
  321. }
  322. template <typename Protocol, typename SocketService, typename Iterator,
  323. typename ConnectCondition, typename ComposedConnectHandler>
  324. void async_connect(basic_socket<Protocol, SocketService>& s,
  325. Iterator begin, Iterator end, ConnectCondition connect_condition,
  326. ASIO_MOVE_ARG(ComposedConnectHandler) handler)
  327. {
  328. // If you get an error on the following line it means that your handler does
  329. // not meet the documented type requirements for a ComposedConnectHandler.
  330. ASIO_COMPOSED_CONNECT_HANDLER_CHECK(
  331. ComposedConnectHandler, handler, Iterator) type_check;
  332. detail::make_connect_op(s, begin, end, connect_condition,
  333. ASIO_MOVE_CAST(ComposedConnectHandler)(handler))(
  334. asio::error_code(), 1);
  335. }
  336. } // namespace asio
  337. #include "asio/detail/pop_options.hpp"
  338. #endif // ASIO_IMPL_CONNECT_HPP