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