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. seq_packet_socket_service(boost::asio::io_service & 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. construct(implementation_type & impl)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. move_construct(implementation_type & impl,implementation_type & other_impl)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. move_assign(implementation_type & impl,seq_packet_socket_service & other_service,implementation_type & other_impl)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> converting_move_construct(implementation_type & impl,typename seq_packet_socket_service<Protocol1>::implementation_type & other_impl,typename enable_if<is_convertible<Protocol1,Protocol>::value>::type * =0)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. destroy(implementation_type & impl)138 void destroy(implementation_type& impl) 139 { 140 service_impl_.destroy(impl); 141 } 142 143 /// Open a sequenced packet socket. open(implementation_type & impl,const protocol_type & protocol,boost::system::error_code & ec)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. assign(implementation_type & impl,const protocol_type & protocol,const native_handle_type & native_socket,boost::system::error_code & ec)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. is_open(const implementation_type & impl) const163 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. close(implementation_type & impl,boost::system::error_code & ec)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. native(implementation_type & impl)176 native_type native(implementation_type& impl) 177 { 178 return service_impl_.native_handle(impl); 179 } 180 181 /// Get the native socket implementation. native_handle(implementation_type & impl)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. cancel(implementation_type & impl,boost::system::error_code & ec)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. at_mark(const implementation_type & impl,boost::system::error_code & ec) const195 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. available(const implementation_type & impl,boost::system::error_code & ec) const202 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. bind(implementation_type & impl,const endpoint_type & endpoint,boost::system::error_code & ec)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. connect(implementation_type & impl,const endpoint_type & peer_endpoint,boost::system::error_code & ec)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> BOOST_ASIO_INITFN_RESULT_TYPE(ConnectHandler,void (boost::system::error_code))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> set_option(implementation_type & impl,const SettableSocketOption & option,boost::system::error_code & ec)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> get_option(const implementation_type & impl,GettableSocketOption & option,boost::system::error_code & ec) const249 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> io_control(implementation_type & impl,IoControlCommand & command,boost::system::error_code & ec)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. non_blocking(const implementation_type & impl) const264 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. non_blocking(implementation_type & impl,bool mode,boost::system::error_code & ec)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. native_non_blocking(const implementation_type & impl) const277 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. native_non_blocking(implementation_type & impl,bool mode,boost::system::error_code & ec)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. local_endpoint(const implementation_type & impl,boost::system::error_code & ec) const290 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. remote_endpoint(const implementation_type & impl,boost::system::error_code & ec) const297 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. shutdown(implementation_type & impl,socket_base::shutdown_type what,boost::system::error_code & ec)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> send(implementation_type & impl,const ConstBufferSequence & buffers,socket_base::message_flags flags,boost::system::error_code & ec)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> BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler,void (boost::system::error_code,std::size_t))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> receive(implementation_type & impl,const MutableBufferSequence & buffers,socket_base::message_flags in_flags,socket_base::message_flags & out_flags,boost::system::error_code & ec)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> BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler,void (boost::system::error_code,std::size_t))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. shutdown_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