winrt_ssocket_service_base.hpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361
  1. //
  2. // detail/winrt_ssocket_service_base.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_DETAIL_WINRT_SSOCKET_SERVICE_BASE_HPP
  11. #define BOOST_ASIO_DETAIL_WINRT_SSOCKET_SERVICE_BASE_HPP
  12. #if defined(_MSC_VER) && (_MSC_VER >= 1200)
  13. # pragma once
  14. #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
  15. #include <boost/asio/detail/config.hpp>
  16. #if defined(BOOST_ASIO_WINDOWS_RUNTIME)
  17. #include <boost/asio/buffer.hpp>
  18. #include <boost/asio/error.hpp>
  19. #include <boost/asio/io_context.hpp>
  20. #include <boost/asio/socket_base.hpp>
  21. #include <boost/asio/detail/buffer_sequence_adapter.hpp>
  22. #include <boost/asio/detail/memory.hpp>
  23. #include <boost/asio/detail/socket_types.hpp>
  24. #include <boost/asio/detail/winrt_async_manager.hpp>
  25. #include <boost/asio/detail/winrt_socket_recv_op.hpp>
  26. #include <boost/asio/detail/winrt_socket_send_op.hpp>
  27. #include <boost/asio/detail/push_options.hpp>
  28. namespace boost {
  29. namespace asio {
  30. namespace detail {
  31. class winrt_ssocket_service_base
  32. {
  33. public:
  34. // The native type of a socket.
  35. typedef Windows::Networking::Sockets::StreamSocket^ native_handle_type;
  36. // The implementation type of the socket.
  37. struct base_implementation_type
  38. {
  39. // Default constructor.
  40. base_implementation_type()
  41. : socket_(nullptr),
  42. next_(0),
  43. prev_(0)
  44. {
  45. }
  46. // The underlying native socket.
  47. native_handle_type socket_;
  48. // Pointers to adjacent socket implementations in linked list.
  49. base_implementation_type* next_;
  50. base_implementation_type* prev_;
  51. };
  52. // Constructor.
  53. BOOST_ASIO_DECL winrt_ssocket_service_base(
  54. boost::asio::io_context& io_context);
  55. // Destroy all user-defined handler objects owned by the service.
  56. BOOST_ASIO_DECL void base_shutdown();
  57. // Construct a new socket implementation.
  58. BOOST_ASIO_DECL void construct(base_implementation_type&);
  59. // Move-construct a new socket implementation.
  60. BOOST_ASIO_DECL void base_move_construct(base_implementation_type& impl,
  61. base_implementation_type& other_impl);
  62. // Move-assign from another socket implementation.
  63. BOOST_ASIO_DECL void base_move_assign(base_implementation_type& impl,
  64. winrt_ssocket_service_base& other_service,
  65. base_implementation_type& other_impl);
  66. // Destroy a socket implementation.
  67. BOOST_ASIO_DECL void destroy(base_implementation_type& impl);
  68. // Determine whether the socket is open.
  69. bool is_open(const base_implementation_type& impl) const
  70. {
  71. return impl.socket_ != nullptr;
  72. }
  73. // Destroy a socket implementation.
  74. BOOST_ASIO_DECL boost::system::error_code close(
  75. base_implementation_type& impl, boost::system::error_code& ec);
  76. // Release ownership of the socket.
  77. BOOST_ASIO_DECL native_handle_type release(
  78. base_implementation_type& impl, boost::system::error_code& ec);
  79. // Get the native socket representation.
  80. native_handle_type native_handle(base_implementation_type& impl)
  81. {
  82. return impl.socket_;
  83. }
  84. // Cancel all operations associated with the socket.
  85. boost::system::error_code cancel(base_implementation_type&,
  86. boost::system::error_code& ec)
  87. {
  88. ec = boost::asio::error::operation_not_supported;
  89. return ec;
  90. }
  91. // Determine whether the socket is at the out-of-band data mark.
  92. bool at_mark(const base_implementation_type&,
  93. boost::system::error_code& ec) const
  94. {
  95. ec = boost::asio::error::operation_not_supported;
  96. return false;
  97. }
  98. // Determine the number of bytes available for reading.
  99. std::size_t available(const base_implementation_type&,
  100. boost::system::error_code& ec) const
  101. {
  102. ec = boost::asio::error::operation_not_supported;
  103. return 0;
  104. }
  105. // Perform an IO control command on the socket.
  106. template <typename IO_Control_Command>
  107. boost::system::error_code io_control(base_implementation_type&,
  108. IO_Control_Command&, boost::system::error_code& ec)
  109. {
  110. ec = boost::asio::error::operation_not_supported;
  111. return ec;
  112. }
  113. // Gets the non-blocking mode of the socket.
  114. bool non_blocking(const base_implementation_type&) const
  115. {
  116. return false;
  117. }
  118. // Sets the non-blocking mode of the socket.
  119. boost::system::error_code non_blocking(base_implementation_type&,
  120. bool, boost::system::error_code& ec)
  121. {
  122. ec = boost::asio::error::operation_not_supported;
  123. return ec;
  124. }
  125. // Gets the non-blocking mode of the native socket implementation.
  126. bool native_non_blocking(const base_implementation_type&) const
  127. {
  128. return false;
  129. }
  130. // Sets the non-blocking mode of the native socket implementation.
  131. boost::system::error_code native_non_blocking(base_implementation_type&,
  132. bool, boost::system::error_code& ec)
  133. {
  134. ec = boost::asio::error::operation_not_supported;
  135. return ec;
  136. }
  137. // Disable sends or receives on the socket.
  138. boost::system::error_code shutdown(base_implementation_type&,
  139. socket_base::shutdown_type, boost::system::error_code& ec)
  140. {
  141. ec = boost::asio::error::operation_not_supported;
  142. return ec;
  143. }
  144. // Send the given data to the peer.
  145. template <typename ConstBufferSequence>
  146. std::size_t send(base_implementation_type& impl,
  147. const ConstBufferSequence& buffers,
  148. socket_base::message_flags flags, boost::system::error_code& ec)
  149. {
  150. return do_send(impl,
  151. buffer_sequence_adapter<boost::asio::const_buffer,
  152. ConstBufferSequence>::first(buffers), flags, ec);
  153. }
  154. // Wait until data can be sent without blocking.
  155. std::size_t send(base_implementation_type&, const null_buffers&,
  156. socket_base::message_flags, boost::system::error_code& ec)
  157. {
  158. ec = boost::asio::error::operation_not_supported;
  159. return 0;
  160. }
  161. // Start an asynchronous send. The data being sent must be valid for the
  162. // lifetime of the asynchronous operation.
  163. template <typename ConstBufferSequence, typename Handler>
  164. void async_send(base_implementation_type& impl,
  165. const ConstBufferSequence& buffers,
  166. socket_base::message_flags flags, Handler& handler)
  167. {
  168. bool is_continuation =
  169. boost_asio_handler_cont_helpers::is_continuation(handler);
  170. // Allocate and construct an operation to wrap the handler.
  171. typedef winrt_socket_send_op<ConstBufferSequence, Handler> op;
  172. typename op::ptr p = { boost::asio::detail::addressof(handler),
  173. op::ptr::allocate(handler), 0 };
  174. p.p = new (p.v) op(buffers, handler);
  175. BOOST_ASIO_HANDLER_CREATION((io_context_.context(),
  176. *p.p, "socket", &impl, 0, "async_send"));
  177. start_send_op(impl,
  178. buffer_sequence_adapter<boost::asio::const_buffer,
  179. ConstBufferSequence>::first(buffers),
  180. flags, p.p, is_continuation);
  181. p.v = p.p = 0;
  182. }
  183. // Start an asynchronous wait until data can be sent without blocking.
  184. template <typename Handler>
  185. void async_send(base_implementation_type&, const null_buffers&,
  186. socket_base::message_flags, Handler& handler)
  187. {
  188. boost::system::error_code ec = boost::asio::error::operation_not_supported;
  189. const std::size_t bytes_transferred = 0;
  190. io_context_.get_io_context().post(
  191. detail::bind_handler(handler, ec, bytes_transferred));
  192. }
  193. // Receive some data from the peer. Returns the number of bytes received.
  194. template <typename MutableBufferSequence>
  195. std::size_t receive(base_implementation_type& impl,
  196. const MutableBufferSequence& buffers,
  197. socket_base::message_flags flags, boost::system::error_code& ec)
  198. {
  199. return do_receive(impl,
  200. buffer_sequence_adapter<boost::asio::mutable_buffer,
  201. MutableBufferSequence>::first(buffers), flags, ec);
  202. }
  203. // Wait until data can be received without blocking.
  204. std::size_t receive(base_implementation_type&, const null_buffers&,
  205. socket_base::message_flags, boost::system::error_code& ec)
  206. {
  207. ec = boost::asio::error::operation_not_supported;
  208. return 0;
  209. }
  210. // Start an asynchronous receive. The buffer for the data being received
  211. // must be valid for the lifetime of the asynchronous operation.
  212. template <typename MutableBufferSequence, typename Handler>
  213. void async_receive(base_implementation_type& impl,
  214. const MutableBufferSequence& buffers,
  215. socket_base::message_flags flags, Handler& handler)
  216. {
  217. bool is_continuation =
  218. boost_asio_handler_cont_helpers::is_continuation(handler);
  219. // Allocate and construct an operation to wrap the handler.
  220. typedef winrt_socket_recv_op<MutableBufferSequence, Handler> op;
  221. typename op::ptr p = { boost::asio::detail::addressof(handler),
  222. op::ptr::allocate(handler), 0 };
  223. p.p = new (p.v) op(buffers, handler);
  224. BOOST_ASIO_HANDLER_CREATION((io_context_.context(),
  225. *p.p, "socket", &impl, 0, "async_receive"));
  226. start_receive_op(impl,
  227. buffer_sequence_adapter<boost::asio::mutable_buffer,
  228. MutableBufferSequence>::first(buffers),
  229. flags, p.p, is_continuation);
  230. p.v = p.p = 0;
  231. }
  232. // Wait until data can be received without blocking.
  233. template <typename Handler>
  234. void async_receive(base_implementation_type&, const null_buffers&,
  235. socket_base::message_flags, Handler& handler)
  236. {
  237. boost::system::error_code ec = boost::asio::error::operation_not_supported;
  238. const std::size_t bytes_transferred = 0;
  239. io_context_.get_io_context().post(
  240. detail::bind_handler(handler, ec, bytes_transferred));
  241. }
  242. protected:
  243. // Helper function to obtain endpoints associated with the connection.
  244. BOOST_ASIO_DECL std::size_t do_get_endpoint(
  245. const base_implementation_type& impl, bool local,
  246. void* addr, std::size_t addr_len, boost::system::error_code& ec) const;
  247. // Helper function to set a socket option.
  248. BOOST_ASIO_DECL boost::system::error_code do_set_option(
  249. base_implementation_type& impl,
  250. int level, int optname, const void* optval,
  251. std::size_t optlen, boost::system::error_code& ec);
  252. // Helper function to get a socket option.
  253. BOOST_ASIO_DECL void do_get_option(
  254. const base_implementation_type& impl,
  255. int level, int optname, void* optval,
  256. std::size_t* optlen, boost::system::error_code& ec) const;
  257. // Helper function to perform a synchronous connect.
  258. BOOST_ASIO_DECL boost::system::error_code do_connect(
  259. base_implementation_type& impl,
  260. const void* addr, boost::system::error_code& ec);
  261. // Helper function to start an asynchronous connect.
  262. BOOST_ASIO_DECL void start_connect_op(
  263. base_implementation_type& impl, const void* addr,
  264. winrt_async_op<void>* op, bool is_continuation);
  265. // Helper function to perform a synchronous send.
  266. BOOST_ASIO_DECL std::size_t do_send(
  267. base_implementation_type& impl, const boost::asio::const_buffer& data,
  268. socket_base::message_flags flags, boost::system::error_code& ec);
  269. // Helper function to start an asynchronous send.
  270. BOOST_ASIO_DECL void start_send_op(base_implementation_type& impl,
  271. const boost::asio::const_buffer& data, socket_base::message_flags flags,
  272. winrt_async_op<unsigned int>* op, bool is_continuation);
  273. // Helper function to perform a synchronous receive.
  274. BOOST_ASIO_DECL std::size_t do_receive(
  275. base_implementation_type& impl, const boost::asio::mutable_buffer& data,
  276. socket_base::message_flags flags, boost::system::error_code& ec);
  277. // Helper function to start an asynchronous receive.
  278. BOOST_ASIO_DECL void start_receive_op(base_implementation_type& impl,
  279. const boost::asio::mutable_buffer& data, socket_base::message_flags flags,
  280. winrt_async_op<Windows::Storage::Streams::IBuffer^>* op,
  281. bool is_continuation);
  282. // The io_context implementation used for delivering completions.
  283. io_context_impl& io_context_;
  284. // The manager that keeps track of outstanding operations.
  285. winrt_async_manager& async_manager_;
  286. // Mutex to protect access to the linked list of implementations.
  287. boost::asio::detail::mutex mutex_;
  288. // The head of a linked list of all implementations.
  289. base_implementation_type* impl_list_;
  290. };
  291. } // namespace detail
  292. } // namespace asio
  293. } // namespace boost
  294. #include <boost/asio/detail/pop_options.hpp>
  295. #if defined(BOOST_ASIO_HEADER_ONLY)
  296. # include <boost/asio/detail/impl/winrt_ssocket_service_base.ipp>
  297. #endif // defined(BOOST_ASIO_HEADER_ONLY)
  298. #endif // defined(BOOST_ASIO_WINDOWS_RUNTIME)
  299. #endif // BOOST_ASIO_DETAIL_WINRT_SSOCKET_SERVICE_BASE_HPP