reactive_socket_service_base.ipp 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310
  1. //
  2. // detail/reactive_socket_service_base.ipp
  3. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  4. //
  5. // Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)
  6. //
  7. // Distributed under the Boost Software License, Version 1.0. (See accompanying
  8. // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  9. //
  10. #ifndef ASIO_DETAIL_IMPL_REACTIVE_SOCKET_SERVICE_BASE_IPP
  11. #define ASIO_DETAIL_IMPL_REACTIVE_SOCKET_SERVICE_BASE_IPP
  12. #if defined(_MSC_VER) && (_MSC_VER >= 1200)
  13. # pragma once
  14. #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
  15. #include "asio/detail/config.hpp"
  16. #if !defined(ASIO_HAS_IOCP) \
  17. && !defined(ASIO_WINDOWS_RUNTIME) \
  18. && !defined(ASIO_HAS_IO_URING_AS_DEFAULT)
  19. #include "asio/detail/reactive_socket_service_base.hpp"
  20. #include "asio/detail/push_options.hpp"
  21. namespace asio {
  22. namespace detail {
  23. reactive_socket_service_base::reactive_socket_service_base(
  24. execution_context& context)
  25. : reactor_(use_service<reactor>(context))
  26. {
  27. reactor_.init_task();
  28. }
  29. void reactive_socket_service_base::base_shutdown()
  30. {
  31. }
  32. void reactive_socket_service_base::construct(
  33. reactive_socket_service_base::base_implementation_type& impl)
  34. {
  35. impl.socket_ = invalid_socket;
  36. impl.state_ = 0;
  37. impl.reactor_data_ = reactor::per_descriptor_data();
  38. }
  39. void reactive_socket_service_base::base_move_construct(
  40. reactive_socket_service_base::base_implementation_type& impl,
  41. reactive_socket_service_base::base_implementation_type& other_impl)
  42. noexcept
  43. {
  44. impl.socket_ = other_impl.socket_;
  45. other_impl.socket_ = invalid_socket;
  46. impl.state_ = other_impl.state_;
  47. other_impl.state_ = 0;
  48. reactor_.move_descriptor(impl.socket_,
  49. impl.reactor_data_, other_impl.reactor_data_);
  50. }
  51. void reactive_socket_service_base::base_move_assign(
  52. reactive_socket_service_base::base_implementation_type& impl,
  53. reactive_socket_service_base& other_service,
  54. reactive_socket_service_base::base_implementation_type& other_impl)
  55. {
  56. destroy(impl);
  57. impl.socket_ = other_impl.socket_;
  58. other_impl.socket_ = invalid_socket;
  59. impl.state_ = other_impl.state_;
  60. other_impl.state_ = 0;
  61. other_service.reactor_.move_descriptor(impl.socket_,
  62. impl.reactor_data_, other_impl.reactor_data_);
  63. }
  64. void reactive_socket_service_base::destroy(
  65. reactive_socket_service_base::base_implementation_type& impl)
  66. {
  67. if (impl.socket_ != invalid_socket)
  68. {
  69. ASIO_HANDLER_OPERATION((reactor_.context(),
  70. "socket", &impl, impl.socket_, "close"));
  71. reactor_.deregister_descriptor(impl.socket_, impl.reactor_data_,
  72. (impl.state_ & socket_ops::possible_dup) == 0);
  73. asio::error_code ignored_ec;
  74. socket_ops::close(impl.socket_, impl.state_, true, ignored_ec);
  75. reactor_.cleanup_descriptor_data(impl.reactor_data_);
  76. }
  77. }
  78. asio::error_code reactive_socket_service_base::close(
  79. reactive_socket_service_base::base_implementation_type& impl,
  80. asio::error_code& ec)
  81. {
  82. if (is_open(impl))
  83. {
  84. ASIO_HANDLER_OPERATION((reactor_.context(),
  85. "socket", &impl, impl.socket_, "close"));
  86. reactor_.deregister_descriptor(impl.socket_, impl.reactor_data_,
  87. (impl.state_ & socket_ops::possible_dup) == 0);
  88. socket_ops::close(impl.socket_, impl.state_, false, ec);
  89. reactor_.cleanup_descriptor_data(impl.reactor_data_);
  90. }
  91. else
  92. {
  93. ec = asio::error_code();
  94. }
  95. // The descriptor is closed by the OS even if close() returns an error.
  96. //
  97. // (Actually, POSIX says the state of the descriptor is unspecified. On
  98. // Linux the descriptor is apparently closed anyway; e.g. see
  99. // http://lkml.org/lkml/2005/9/10/129
  100. // We'll just have to assume that other OSes follow the same behaviour. The
  101. // known exception is when Windows's closesocket() function fails with
  102. // WSAEWOULDBLOCK, but this case is handled inside socket_ops::close().
  103. construct(impl);
  104. return ec;
  105. }
  106. socket_type reactive_socket_service_base::release(
  107. reactive_socket_service_base::base_implementation_type& impl,
  108. asio::error_code& ec)
  109. {
  110. if (!is_open(impl))
  111. {
  112. ec = asio::error::bad_descriptor;
  113. return invalid_socket;
  114. }
  115. ASIO_HANDLER_OPERATION((reactor_.context(),
  116. "socket", &impl, impl.socket_, "release"));
  117. reactor_.deregister_descriptor(impl.socket_, impl.reactor_data_, false);
  118. reactor_.cleanup_descriptor_data(impl.reactor_data_);
  119. socket_type sock = impl.socket_;
  120. construct(impl);
  121. ec = asio::error_code();
  122. return sock;
  123. }
  124. asio::error_code reactive_socket_service_base::cancel(
  125. reactive_socket_service_base::base_implementation_type& impl,
  126. asio::error_code& ec)
  127. {
  128. if (!is_open(impl))
  129. {
  130. ec = asio::error::bad_descriptor;
  131. return ec;
  132. }
  133. ASIO_HANDLER_OPERATION((reactor_.context(),
  134. "socket", &impl, impl.socket_, "cancel"));
  135. reactor_.cancel_ops(impl.socket_, impl.reactor_data_);
  136. ec = asio::error_code();
  137. return ec;
  138. }
  139. asio::error_code reactive_socket_service_base::do_open(
  140. reactive_socket_service_base::base_implementation_type& impl,
  141. int af, int type, int protocol, asio::error_code& ec)
  142. {
  143. if (is_open(impl))
  144. {
  145. ec = asio::error::already_open;
  146. return ec;
  147. }
  148. socket_holder sock(socket_ops::socket(af, type, protocol, ec));
  149. if (sock.get() == invalid_socket)
  150. return ec;
  151. if (int err = reactor_.register_descriptor(sock.get(), impl.reactor_data_))
  152. {
  153. ec = asio::error_code(err,
  154. asio::error::get_system_category());
  155. return ec;
  156. }
  157. impl.socket_ = sock.release();
  158. switch (type)
  159. {
  160. case SOCK_STREAM: impl.state_ = socket_ops::stream_oriented; break;
  161. case SOCK_DGRAM: impl.state_ = socket_ops::datagram_oriented; break;
  162. default: impl.state_ = 0; break;
  163. }
  164. ec = asio::error_code();
  165. return ec;
  166. }
  167. asio::error_code reactive_socket_service_base::do_assign(
  168. reactive_socket_service_base::base_implementation_type& impl, int type,
  169. const reactive_socket_service_base::native_handle_type& native_socket,
  170. asio::error_code& ec)
  171. {
  172. if (is_open(impl))
  173. {
  174. ec = asio::error::already_open;
  175. return ec;
  176. }
  177. if (int err = reactor_.register_descriptor(
  178. native_socket, impl.reactor_data_))
  179. {
  180. ec = asio::error_code(err,
  181. asio::error::get_system_category());
  182. return ec;
  183. }
  184. impl.socket_ = native_socket;
  185. switch (type)
  186. {
  187. case SOCK_STREAM: impl.state_ = socket_ops::stream_oriented; break;
  188. case SOCK_DGRAM: impl.state_ = socket_ops::datagram_oriented; break;
  189. default: impl.state_ = 0; break;
  190. }
  191. impl.state_ |= socket_ops::possible_dup;
  192. ec = asio::error_code();
  193. return ec;
  194. }
  195. void reactive_socket_service_base::do_start_op(
  196. reactive_socket_service_base::base_implementation_type& impl, int op_type,
  197. reactor_op* op, bool is_continuation, bool is_non_blocking, bool noop,
  198. void (*on_immediate)(operation* op, bool, const void*),
  199. const void* immediate_arg)
  200. {
  201. if (!noop)
  202. {
  203. if ((impl.state_ & socket_ops::non_blocking)
  204. || socket_ops::set_internal_non_blocking(
  205. impl.socket_, impl.state_, true, op->ec_))
  206. {
  207. reactor_.start_op(op_type, impl.socket_, impl.reactor_data_, op,
  208. is_continuation, is_non_blocking, on_immediate, immediate_arg);
  209. return;
  210. }
  211. }
  212. on_immediate(op, is_continuation, immediate_arg);
  213. }
  214. void reactive_socket_service_base::do_start_accept_op(
  215. reactive_socket_service_base::base_implementation_type& impl,
  216. reactor_op* op, bool is_continuation, bool peer_is_open,
  217. void (*on_immediate)(operation* op, bool, const void*),
  218. const void* immediate_arg)
  219. {
  220. if (!peer_is_open)
  221. {
  222. do_start_op(impl, reactor::read_op, op, is_continuation,
  223. true, false, on_immediate, immediate_arg);
  224. }
  225. else
  226. {
  227. op->ec_ = asio::error::already_open;
  228. on_immediate(op, is_continuation, immediate_arg);
  229. }
  230. }
  231. void reactive_socket_service_base::do_start_connect_op(
  232. reactive_socket_service_base::base_implementation_type& impl,
  233. reactor_op* op, bool is_continuation, const void* addr, size_t addrlen,
  234. void (*on_immediate)(operation* op, bool, const void*),
  235. const void* immediate_arg)
  236. {
  237. if ((impl.state_ & socket_ops::non_blocking)
  238. || socket_ops::set_internal_non_blocking(
  239. impl.socket_, impl.state_, true, op->ec_))
  240. {
  241. if (socket_ops::connect(impl.socket_, addr, addrlen, op->ec_) != 0)
  242. {
  243. if (op->ec_ == asio::error::in_progress
  244. || op->ec_ == asio::error::would_block)
  245. {
  246. op->ec_ = asio::error_code();
  247. reactor_.start_op(reactor::connect_op, impl.socket_, impl.reactor_data_,
  248. op, is_continuation, false, on_immediate, immediate_arg);
  249. return;
  250. }
  251. }
  252. }
  253. on_immediate(op, is_continuation, immediate_arg);
  254. }
  255. } // namespace detail
  256. } // namespace asio
  257. #include "asio/detail/pop_options.hpp"
  258. #endif // !defined(ASIO_HAS_IOCP)
  259. // && !defined(ASIO_WINDOWS_RUNTIME)
  260. // && !defined(ASIO_HAS_IO_URING_AS_DEFAULT)
  261. #endif // ASIO_DETAIL_IMPL_REACTIVE_SOCKET_SERVICE_BASE_IPP