1 | // |
2 | // seq_packet_socket_service.hpp |
3 | // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
4 | // |
5 | // Copyright (c) 2003-2015 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 | |
11 | #ifndef BOOST_ASIO_SEQ_PACKET_SOCKET_SERVICE_HPP |
12 | #define BOOST_ASIO_SEQ_PACKET_SOCKET_SERVICE_HPP |
13 | |
14 | #if defined(_MSC_VER) && (_MSC_VER >= 1200) |
15 | # pragma once |
16 | #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) |
17 | |
18 | #include <boost/asio/detail/config.hpp> |
19 | #include <cstddef> |
20 | #include <boost/asio/async_result.hpp> |
21 | #include <boost/asio/detail/type_traits.hpp> |
22 | #include <boost/asio/error.hpp> |
23 | #include <boost/asio/io_service.hpp> |
24 | |
25 | #if defined(BOOST_ASIO_WINDOWS_RUNTIME) |
26 | # include <boost/asio/detail/null_socket_service.hpp> |
27 | #elif defined(BOOST_ASIO_HAS_IOCP) |
28 | # include <boost/asio/detail/win_iocp_socket_service.hpp> |
29 | #else |
30 | # include <boost/asio/detail/reactive_socket_service.hpp> |
31 | #endif |
32 | |
33 | #include <boost/asio/detail/push_options.hpp> |
34 | |
35 | namespace boost { |
36 | namespace asio { |
37 | |
38 | /// Default service implementation for a sequenced packet socket. |
39 | template <typename Protocol> |
40 | class seq_packet_socket_service |
41 | #if defined(GENERATING_DOCUMENTATION) |
42 | : public boost::asio::io_service::service |
43 | #else |
44 | : public boost::asio::detail::service_base< |
45 | seq_packet_socket_service<Protocol> > |
46 | #endif |
47 | { |
48 | public: |
49 | #if defined(GENERATING_DOCUMENTATION) |
50 | /// The unique service identifier. |
51 | static boost::asio::io_service::id id; |
52 | #endif |
53 | |
54 | /// The protocol type. |
55 | typedef Protocol protocol_type; |
56 | |
57 | /// The endpoint type. |
58 | typedef typename Protocol::endpoint endpoint_type; |
59 | |
60 | private: |
61 | // The type of the platform-specific implementation. |
62 | #if defined(BOOST_ASIO_WINDOWS_RUNTIME) |
63 | typedef detail::null_socket_service<Protocol> service_impl_type; |
64 | #elif defined(BOOST_ASIO_HAS_IOCP) |
65 | typedef detail::win_iocp_socket_service<Protocol> service_impl_type; |
66 | #else |
67 | typedef detail::reactive_socket_service<Protocol> service_impl_type; |
68 | #endif |
69 | |
70 | public: |
71 | /// The type of a sequenced packet socket implementation. |
72 | #if defined(GENERATING_DOCUMENTATION) |
73 | typedef implementation_defined implementation_type; |
74 | #else |
75 | typedef typename service_impl_type::implementation_type implementation_type; |
76 | #endif |
77 | |
78 | /// (Deprecated: Use native_handle_type.) The native socket type. |
79 | #if defined(GENERATING_DOCUMENTATION) |
80 | typedef implementation_defined native_type; |
81 | #else |
82 | typedef typename service_impl_type::native_handle_type native_type; |
83 | #endif |
84 | |
85 | /// The native socket type. |
86 | #if defined(GENERATING_DOCUMENTATION) |
87 | typedef implementation_defined native_handle_type; |
88 | #else |
89 | typedef typename service_impl_type::native_handle_type native_handle_type; |
90 | #endif |
91 | |
92 | /// Construct a new sequenced packet socket service for the specified |
93 | /// io_service. |
94 | explicit seq_packet_socket_service(boost::asio::io_service& io_service) |
95 | : boost::asio::detail::service_base< |
96 | seq_packet_socket_service<Protocol> >(io_service), |
97 | service_impl_(io_service) |
98 | { |
99 | } |
100 | |
101 | /// Construct a new sequenced packet socket implementation. |
102 | void construct(implementation_type& impl) |
103 | { |
104 | service_impl_.construct(impl); |
105 | } |
106 | |
107 | #if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) |
108 | /// Move-construct a new sequenced packet socket implementation. |
109 | void move_construct(implementation_type& impl, |
110 | implementation_type& other_impl) |
111 | { |
112 | service_impl_.move_construct(impl, other_impl); |
113 | } |
114 | |
115 | /// Move-assign from another sequenced packet socket implementation. |
116 | void move_assign(implementation_type& impl, |
117 | seq_packet_socket_service& other_service, |
118 | implementation_type& other_impl) |
119 | { |
120 | service_impl_.move_assign(impl, other_service.service_impl_, other_impl); |
121 | } |
122 | |
123 | /// Move-construct a new sequenced packet socket implementation from another |
124 | /// protocol type. |
125 | template <typename Protocol1> |
126 | void converting_move_construct(implementation_type& impl, |
127 | typename seq_packet_socket_service< |
128 | Protocol1>::implementation_type& other_impl, |
129 | typename enable_if<is_convertible< |
130 | Protocol1, Protocol>::value>::type* = 0) |
131 | { |
132 | service_impl_.template converting_move_construct<Protocol1>( |
133 | impl, other_impl); |
134 | } |
135 | #endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) |
136 | |
137 | /// Destroy a sequenced packet socket implementation. |
138 | void destroy(implementation_type& impl) |
139 | { |
140 | service_impl_.destroy(impl); |
141 | } |
142 | |
143 | /// Open a sequenced packet socket. |
144 | boost::system::error_code open(implementation_type& impl, |
145 | const protocol_type& protocol, boost::system::error_code& ec) |
146 | { |
147 | if (protocol.type() == BOOST_ASIO_OS_DEF(SOCK_SEQPACKET)) |
148 | service_impl_.open(impl, protocol, ec); |
149 | else |
150 | ec = boost::asio::error::invalid_argument; |
151 | return ec; |
152 | } |
153 | |
154 | /// Assign an existing native socket to a sequenced packet socket. |
155 | boost::system::error_code assign(implementation_type& impl, |
156 | const protocol_type& protocol, const native_handle_type& native_socket, |
157 | boost::system::error_code& ec) |
158 | { |
159 | return service_impl_.assign(impl, protocol, native_socket, ec); |
160 | } |
161 | |
162 | /// Determine whether the socket is open. |
163 | bool is_open(const implementation_type& impl) const |
164 | { |
165 | return service_impl_.is_open(impl); |
166 | } |
167 | |
168 | /// Close a sequenced packet socket implementation. |
169 | boost::system::error_code close(implementation_type& impl, |
170 | boost::system::error_code& ec) |
171 | { |
172 | return service_impl_.close(impl, ec); |
173 | } |
174 | |
175 | /// (Deprecated: Use native_handle().) Get the native socket implementation. |
176 | native_type native(implementation_type& impl) |
177 | { |
178 | return service_impl_.native_handle(impl); |
179 | } |
180 | |
181 | /// Get the native socket implementation. |
182 | native_handle_type native_handle(implementation_type& impl) |
183 | { |
184 | return service_impl_.native_handle(impl); |
185 | } |
186 | |
187 | /// Cancel all asynchronous operations associated with the socket. |
188 | boost::system::error_code cancel(implementation_type& impl, |
189 | boost::system::error_code& ec) |
190 | { |
191 | return service_impl_.cancel(impl, ec); |
192 | } |
193 | |
194 | /// Determine whether the socket is at the out-of-band data mark. |
195 | bool at_mark(const implementation_type& impl, |
196 | boost::system::error_code& ec) const |
197 | { |
198 | return service_impl_.at_mark(impl, ec); |
199 | } |
200 | |
201 | /// Determine the number of bytes available for reading. |
202 | std::size_t available(const implementation_type& impl, |
203 | boost::system::error_code& ec) const |
204 | { |
205 | return service_impl_.available(impl, ec); |
206 | } |
207 | |
208 | /// Bind the sequenced packet socket to the specified local endpoint. |
209 | boost::system::error_code bind(implementation_type& impl, |
210 | const endpoint_type& endpoint, boost::system::error_code& ec) |
211 | { |
212 | return service_impl_.bind(impl, endpoint, ec); |
213 | } |
214 | |
215 | /// Connect the sequenced packet socket to the specified endpoint. |
216 | boost::system::error_code connect(implementation_type& impl, |
217 | const endpoint_type& peer_endpoint, boost::system::error_code& ec) |
218 | { |
219 | return service_impl_.connect(impl, peer_endpoint, ec); |
220 | } |
221 | |
222 | /// Start an asynchronous connect. |
223 | template <typename ConnectHandler> |
224 | BOOST_ASIO_INITFN_RESULT_TYPE(ConnectHandler, |
225 | void (boost::system::error_code)) |
226 | async_connect(implementation_type& impl, |
227 | const endpoint_type& peer_endpoint, |
228 | BOOST_ASIO_MOVE_ARG(ConnectHandler) handler) |
229 | { |
230 | detail::async_result_init< |
231 | ConnectHandler, void (boost::system::error_code)> init( |
232 | BOOST_ASIO_MOVE_CAST(ConnectHandler)(handler)); |
233 | |
234 | service_impl_.async_connect(impl, peer_endpoint, init.handler); |
235 | |
236 | return init.result.get(); |
237 | } |
238 | |
239 | /// Set a socket option. |
240 | template <typename SettableSocketOption> |
241 | boost::system::error_code set_option(implementation_type& impl, |
242 | const SettableSocketOption& option, boost::system::error_code& ec) |
243 | { |
244 | return service_impl_.set_option(impl, option, ec); |
245 | } |
246 | |
247 | /// Get a socket option. |
248 | template <typename GettableSocketOption> |
249 | boost::system::error_code get_option(const implementation_type& impl, |
250 | GettableSocketOption& option, boost::system::error_code& ec) const |
251 | { |
252 | return service_impl_.get_option(impl, option, ec); |
253 | } |
254 | |
255 | /// Perform an IO control command on the socket. |
256 | template <typename IoControlCommand> |
257 | boost::system::error_code io_control(implementation_type& impl, |
258 | IoControlCommand& command, boost::system::error_code& ec) |
259 | { |
260 | return service_impl_.io_control(impl, command, ec); |
261 | } |
262 | |
263 | /// Gets the non-blocking mode of the socket. |
264 | bool non_blocking(const implementation_type& impl) const |
265 | { |
266 | return service_impl_.non_blocking(impl); |
267 | } |
268 | |
269 | /// Sets the non-blocking mode of the socket. |
270 | boost::system::error_code non_blocking(implementation_type& impl, |
271 | bool mode, boost::system::error_code& ec) |
272 | { |
273 | return service_impl_.non_blocking(impl, mode, ec); |
274 | } |
275 | |
276 | /// Gets the non-blocking mode of the native socket implementation. |
277 | bool native_non_blocking(const implementation_type& impl) const |
278 | { |
279 | return service_impl_.native_non_blocking(impl); |
280 | } |
281 | |
282 | /// Sets the non-blocking mode of the native socket implementation. |
283 | boost::system::error_code native_non_blocking(implementation_type& impl, |
284 | bool mode, boost::system::error_code& ec) |
285 | { |
286 | return service_impl_.native_non_blocking(impl, mode, ec); |
287 | } |
288 | |
289 | /// Get the local endpoint. |
290 | endpoint_type local_endpoint(const implementation_type& impl, |
291 | boost::system::error_code& ec) const |
292 | { |
293 | return service_impl_.local_endpoint(impl, ec); |
294 | } |
295 | |
296 | /// Get the remote endpoint. |
297 | endpoint_type remote_endpoint(const implementation_type& impl, |
298 | boost::system::error_code& ec) const |
299 | { |
300 | return service_impl_.remote_endpoint(impl, ec); |
301 | } |
302 | |
303 | /// Disable sends or receives on the socket. |
304 | boost::system::error_code shutdown(implementation_type& impl, |
305 | socket_base::shutdown_type what, boost::system::error_code& ec) |
306 | { |
307 | return service_impl_.shutdown(impl, what, ec); |
308 | } |
309 | |
310 | /// Send the given data to the peer. |
311 | template <typename ConstBufferSequence> |
312 | std::size_t send(implementation_type& impl, |
313 | const ConstBufferSequence& buffers, |
314 | socket_base::message_flags flags, boost::system::error_code& ec) |
315 | { |
316 | return service_impl_.send(impl, buffers, flags, ec); |
317 | } |
318 | |
319 | /// Start an asynchronous send. |
320 | template <typename ConstBufferSequence, typename WriteHandler> |
321 | BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler, |
322 | void (boost::system::error_code, std::size_t)) |
323 | async_send(implementation_type& impl, |
324 | const ConstBufferSequence& buffers, |
325 | socket_base::message_flags flags, |
326 | BOOST_ASIO_MOVE_ARG(WriteHandler) handler) |
327 | { |
328 | detail::async_result_init< |
329 | WriteHandler, void (boost::system::error_code, std::size_t)> init( |
330 | BOOST_ASIO_MOVE_CAST(WriteHandler)(handler)); |
331 | |
332 | service_impl_.async_send(impl, buffers, flags, init.handler); |
333 | |
334 | return init.result.get(); |
335 | } |
336 | |
337 | /// Receive some data from the peer. |
338 | template <typename MutableBufferSequence> |
339 | std::size_t receive(implementation_type& impl, |
340 | const MutableBufferSequence& buffers, socket_base::message_flags in_flags, |
341 | socket_base::message_flags& out_flags, boost::system::error_code& ec) |
342 | { |
343 | return service_impl_.receive_with_flags(impl, |
344 | buffers, in_flags, out_flags, ec); |
345 | } |
346 | |
347 | /// Start an asynchronous receive. |
348 | template <typename MutableBufferSequence, typename ReadHandler> |
349 | BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler, |
350 | void (boost::system::error_code, std::size_t)) |
351 | async_receive(implementation_type& impl, |
352 | const MutableBufferSequence& buffers, socket_base::message_flags in_flags, |
353 | socket_base::message_flags& out_flags, |
354 | BOOST_ASIO_MOVE_ARG(ReadHandler) handler) |
355 | { |
356 | detail::async_result_init< |
357 | ReadHandler, void (boost::system::error_code, std::size_t)> init( |
358 | BOOST_ASIO_MOVE_CAST(ReadHandler)(handler)); |
359 | |
360 | service_impl_.async_receive_with_flags(impl, |
361 | buffers, in_flags, out_flags, init.handler); |
362 | |
363 | return init.result.get(); |
364 | } |
365 | |
366 | private: |
367 | // Destroy all user-defined handler objects owned by the service. |
368 | void shutdown_service() |
369 | { |
370 | service_impl_.shutdown_service(); |
371 | } |
372 | |
373 | // The platform-specific implementation. |
374 | service_impl_type service_impl_; |
375 | }; |
376 | |
377 | } // namespace asio |
378 | } // namespace boost |
379 | |
380 | #include <boost/asio/detail/pop_options.hpp> |
381 | |
382 | #endif // BOOST_ASIO_SEQ_PACKET_SOCKET_SERVICE_HPP |
383 | |