Home | History | Annotate | Download | only in asio
      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.
     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 
    324 private:
    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