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
26namespace asio {
27
28/// Default service implementation for a stream socket.
29template <typename Protocol>
30class stream_socket_service
31  : public asio::detail::service_base<stream_socket_service<Protocol> >
32{
33public:
34
35  /// The protocol type.
36  typedef Protocol protocol_type;
37
38  /// The endpoint type.
39  typedef typename Protocol::endpoint endpoint_type;
40
41private:
42  // The type of the platform-specific implementation.
43  typedef detail::reactive_socket_service<Protocol> service_impl_type;
44
45public:
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.
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.
64  void construct(implementation_type& impl)
65  {
66    service_impl_.construct(impl);
67  }
68
69  /// Move-construct a new stream socket implementation.
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.
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>
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.
98  void destroy(implementation_type& impl)
99  {
100    service_impl_.destroy(impl);
101  }
102
103  /// Open a stream socket.
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.
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.
123  bool is_open(const implementation_type& impl) const
124  {
125    return service_impl_.is_open(impl);
126  }
127
128  /// Close a stream socket implementation.
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.
136  native_type native(implementation_type& impl)
137  {
138    return service_impl_.native_handle(impl);
139  }
140
141  /// Get the native socket implementation.
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.
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.
155  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.
162  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.
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.
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>
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>
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>
209  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>
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.
224  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.
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.
237  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.
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.
250  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.
257  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.
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>
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>
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>
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>
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
324private:
325  // Destroy all user-defined handler objects owned by the 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