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