1 // 2 // raw_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_RAW_SOCKET_SERVICE_HPP 12 #define BOOST_ASIO_RAW_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 raw socket. 39 template <typename Protocol> 40 class raw_socket_service 41 #if defined(GENERATING_DOCUMENTATION) 42 : public boost::asio::io_service::service 43 #else 44 : public boost::asio::detail::service_base<raw_socket_service<Protocol> > 45 #endif 46 { 47 public: 48 #if defined(GENERATING_DOCUMENTATION) 49 /// The unique service identifier. 50 static boost::asio::io_service::id id; 51 #endif 52 53 /// The protocol type. 54 typedef Protocol protocol_type; 55 56 /// The endpoint type. 57 typedef typename Protocol::endpoint endpoint_type; 58 59 private: 60 // The type of the platform-specific implementation. 61 #if defined(BOOST_ASIO_WINDOWS_RUNTIME) 62 typedef detail::null_socket_service<Protocol> service_impl_type; 63 #elif defined(BOOST_ASIO_HAS_IOCP) 64 typedef detail::win_iocp_socket_service<Protocol> service_impl_type; 65 #else 66 typedef detail::reactive_socket_service<Protocol> service_impl_type; 67 #endif 68 69 public: 70 /// The type of a raw socket. 71 #if defined(GENERATING_DOCUMENTATION) 72 typedef implementation_defined implementation_type; 73 #else 74 typedef typename service_impl_type::implementation_type implementation_type; 75 #endif 76 77 /// (Deprecated: Use native_handle_type.) The native socket type. 78 #if defined(GENERATING_DOCUMENTATION) 79 typedef implementation_defined native_type; 80 #else 81 typedef typename service_impl_type::native_handle_type native_type; 82 #endif 83 84 /// The native socket type. 85 #if defined(GENERATING_DOCUMENTATION) 86 typedef implementation_defined native_handle_type; 87 #else 88 typedef typename service_impl_type::native_handle_type native_handle_type; 89 #endif 90 91 /// Construct a new raw socket service for the specified io_service. raw_socket_service(boost::asio::io_service & io_service)92 explicit raw_socket_service(boost::asio::io_service& io_service) 93 : boost::asio::detail::service_base< 94 raw_socket_service<Protocol> >(io_service), 95 service_impl_(io_service) 96 { 97 } 98 99 /// Construct a new raw socket implementation. construct(implementation_type & impl)100 void construct(implementation_type& impl) 101 { 102 service_impl_.construct(impl); 103 } 104 105 #if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) 106 /// Move-construct a new raw socket implementation. move_construct(implementation_type & impl,implementation_type & other_impl)107 void move_construct(implementation_type& impl, 108 implementation_type& other_impl) 109 { 110 service_impl_.move_construct(impl, other_impl); 111 } 112 113 /// Move-assign from another raw socket implementation. move_assign(implementation_type & impl,raw_socket_service & other_service,implementation_type & other_impl)114 void move_assign(implementation_type& impl, 115 raw_socket_service& other_service, 116 implementation_type& other_impl) 117 { 118 service_impl_.move_assign(impl, other_service.service_impl_, other_impl); 119 } 120 121 /// Move-construct a new raw socket implementation from another protocol 122 /// type. 123 template <typename Protocol1> converting_move_construct(implementation_type & impl,typename raw_socket_service<Protocol1>::implementation_type & other_impl,typename enable_if<is_convertible<Protocol1,Protocol>::value>::type * =0)124 void converting_move_construct(implementation_type& impl, 125 typename raw_socket_service< 126 Protocol1>::implementation_type& other_impl, 127 typename enable_if<is_convertible< 128 Protocol1, Protocol>::value>::type* = 0) 129 { 130 service_impl_.template converting_move_construct<Protocol1>( 131 impl, other_impl); 132 } 133 #endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) 134 135 /// Destroy a raw socket implementation. destroy(implementation_type & impl)136 void destroy(implementation_type& impl) 137 { 138 service_impl_.destroy(impl); 139 } 140 141 // Open a new raw socket implementation. open(implementation_type & impl,const protocol_type & protocol,boost::system::error_code & ec)142 boost::system::error_code open(implementation_type& impl, 143 const protocol_type& protocol, boost::system::error_code& ec) 144 { 145 if (protocol.type() == BOOST_ASIO_OS_DEF(SOCK_RAW)) 146 service_impl_.open(impl, protocol, ec); 147 else 148 ec = boost::asio::error::invalid_argument; 149 return ec; 150 } 151 152 /// Assign an existing native socket to a raw socket. assign(implementation_type & impl,const protocol_type & protocol,const native_handle_type & native_socket,boost::system::error_code & ec)153 boost::system::error_code assign(implementation_type& impl, 154 const protocol_type& protocol, const native_handle_type& native_socket, 155 boost::system::error_code& ec) 156 { 157 return service_impl_.assign(impl, protocol, native_socket, ec); 158 } 159 160 /// Determine whether the socket is open. is_open(const implementation_type & impl) const161 bool is_open(const implementation_type& impl) const 162 { 163 return service_impl_.is_open(impl); 164 } 165 166 /// Close a raw socket implementation. close(implementation_type & impl,boost::system::error_code & ec)167 boost::system::error_code close(implementation_type& impl, 168 boost::system::error_code& ec) 169 { 170 return service_impl_.close(impl, ec); 171 } 172 173 /// (Deprecated: Use native_handle().) Get the native socket implementation. native(implementation_type & impl)174 native_type native(implementation_type& impl) 175 { 176 return service_impl_.native_handle(impl); 177 } 178 179 /// Get the native socket implementation. native_handle(implementation_type & impl)180 native_handle_type native_handle(implementation_type& impl) 181 { 182 return service_impl_.native_handle(impl); 183 } 184 185 /// Cancel all asynchronous operations associated with the socket. cancel(implementation_type & impl,boost::system::error_code & ec)186 boost::system::error_code cancel(implementation_type& impl, 187 boost::system::error_code& ec) 188 { 189 return service_impl_.cancel(impl, ec); 190 } 191 192 /// Determine whether the socket is at the out-of-band data mark. at_mark(const implementation_type & impl,boost::system::error_code & ec) const193 bool at_mark(const implementation_type& impl, 194 boost::system::error_code& ec) const 195 { 196 return service_impl_.at_mark(impl, ec); 197 } 198 199 /// Determine the number of bytes available for reading. available(const implementation_type & impl,boost::system::error_code & ec) const200 std::size_t available(const implementation_type& impl, 201 boost::system::error_code& ec) const 202 { 203 return service_impl_.available(impl, ec); 204 } 205 206 // Bind the raw socket to the specified local endpoint. bind(implementation_type & impl,const endpoint_type & endpoint,boost::system::error_code & ec)207 boost::system::error_code bind(implementation_type& impl, 208 const endpoint_type& endpoint, boost::system::error_code& ec) 209 { 210 return service_impl_.bind(impl, endpoint, ec); 211 } 212 213 /// Connect the raw socket to the specified endpoint. connect(implementation_type & impl,const endpoint_type & peer_endpoint,boost::system::error_code & ec)214 boost::system::error_code connect(implementation_type& impl, 215 const endpoint_type& peer_endpoint, boost::system::error_code& ec) 216 { 217 return service_impl_.connect(impl, peer_endpoint, ec); 218 } 219 220 /// Start an asynchronous connect. 221 template <typename ConnectHandler> BOOST_ASIO_INITFN_RESULT_TYPE(ConnectHandler,void (boost::system::error_code))222 BOOST_ASIO_INITFN_RESULT_TYPE(ConnectHandler, 223 void (boost::system::error_code)) 224 async_connect(implementation_type& impl, 225 const endpoint_type& peer_endpoint, 226 BOOST_ASIO_MOVE_ARG(ConnectHandler) handler) 227 { 228 detail::async_result_init< 229 ConnectHandler, void (boost::system::error_code)> init( 230 BOOST_ASIO_MOVE_CAST(ConnectHandler)(handler)); 231 232 service_impl_.async_connect(impl, peer_endpoint, init.handler); 233 234 return init.result.get(); 235 } 236 237 /// Set a socket option. 238 template <typename SettableSocketOption> set_option(implementation_type & impl,const SettableSocketOption & option,boost::system::error_code & ec)239 boost::system::error_code set_option(implementation_type& impl, 240 const SettableSocketOption& option, boost::system::error_code& ec) 241 { 242 return service_impl_.set_option(impl, option, ec); 243 } 244 245 /// Get a socket option. 246 template <typename GettableSocketOption> get_option(const implementation_type & impl,GettableSocketOption & option,boost::system::error_code & ec) const247 boost::system::error_code get_option(const implementation_type& impl, 248 GettableSocketOption& option, boost::system::error_code& ec) const 249 { 250 return service_impl_.get_option(impl, option, ec); 251 } 252 253 /// Perform an IO control command on the socket. 254 template <typename IoControlCommand> io_control(implementation_type & impl,IoControlCommand & command,boost::system::error_code & ec)255 boost::system::error_code io_control(implementation_type& impl, 256 IoControlCommand& command, boost::system::error_code& ec) 257 { 258 return service_impl_.io_control(impl, command, ec); 259 } 260 261 /// Gets the non-blocking mode of the socket. non_blocking(const implementation_type & impl) const262 bool non_blocking(const implementation_type& impl) const 263 { 264 return service_impl_.non_blocking(impl); 265 } 266 267 /// Sets the non-blocking mode of the socket. non_blocking(implementation_type & impl,bool mode,boost::system::error_code & ec)268 boost::system::error_code non_blocking(implementation_type& impl, 269 bool mode, boost::system::error_code& ec) 270 { 271 return service_impl_.non_blocking(impl, mode, ec); 272 } 273 274 /// Gets the non-blocking mode of the native socket implementation. native_non_blocking(const implementation_type & impl) const275 bool native_non_blocking(const implementation_type& impl) const 276 { 277 return service_impl_.native_non_blocking(impl); 278 } 279 280 /// Sets the non-blocking mode of the native socket implementation. native_non_blocking(implementation_type & impl,bool mode,boost::system::error_code & ec)281 boost::system::error_code native_non_blocking(implementation_type& impl, 282 bool mode, boost::system::error_code& ec) 283 { 284 return service_impl_.native_non_blocking(impl, mode, ec); 285 } 286 287 /// Get the local endpoint. local_endpoint(const implementation_type & impl,boost::system::error_code & ec) const288 endpoint_type local_endpoint(const implementation_type& impl, 289 boost::system::error_code& ec) const 290 { 291 return service_impl_.local_endpoint(impl, ec); 292 } 293 294 /// Get the remote endpoint. remote_endpoint(const implementation_type & impl,boost::system::error_code & ec) const295 endpoint_type remote_endpoint(const implementation_type& impl, 296 boost::system::error_code& ec) const 297 { 298 return service_impl_.remote_endpoint(impl, ec); 299 } 300 301 /// Disable sends or receives on the socket. shutdown(implementation_type & impl,socket_base::shutdown_type what,boost::system::error_code & ec)302 boost::system::error_code shutdown(implementation_type& impl, 303 socket_base::shutdown_type what, boost::system::error_code& ec) 304 { 305 return service_impl_.shutdown(impl, what, ec); 306 } 307 308 /// Send the given data to the peer. 309 template <typename ConstBufferSequence> send(implementation_type & impl,const ConstBufferSequence & buffers,socket_base::message_flags flags,boost::system::error_code & ec)310 std::size_t send(implementation_type& impl, 311 const ConstBufferSequence& buffers, 312 socket_base::message_flags flags, boost::system::error_code& ec) 313 { 314 return service_impl_.send(impl, buffers, flags, ec); 315 } 316 317 /// Start an asynchronous send. 318 template <typename ConstBufferSequence, typename WriteHandler> BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler,void (boost::system::error_code,std::size_t))319 BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler, 320 void (boost::system::error_code, std::size_t)) 321 async_send(implementation_type& impl, const ConstBufferSequence& buffers, 322 socket_base::message_flags flags, 323 BOOST_ASIO_MOVE_ARG(WriteHandler) handler) 324 { 325 detail::async_result_init< 326 WriteHandler, void (boost::system::error_code, std::size_t)> init( 327 BOOST_ASIO_MOVE_CAST(WriteHandler)(handler)); 328 329 service_impl_.async_send(impl, buffers, flags, init.handler); 330 331 return init.result.get(); 332 } 333 334 /// Send raw data to the specified endpoint. 335 template <typename ConstBufferSequence> send_to(implementation_type & impl,const ConstBufferSequence & buffers,const endpoint_type & destination,socket_base::message_flags flags,boost::system::error_code & ec)336 std::size_t send_to(implementation_type& impl, 337 const ConstBufferSequence& buffers, const endpoint_type& destination, 338 socket_base::message_flags flags, boost::system::error_code& ec) 339 { 340 return service_impl_.send_to(impl, buffers, destination, flags, ec); 341 } 342 343 /// Start an asynchronous send. 344 template <typename ConstBufferSequence, typename WriteHandler> BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler,void (boost::system::error_code,std::size_t))345 BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler, 346 void (boost::system::error_code, std::size_t)) 347 async_send_to(implementation_type& impl, 348 const ConstBufferSequence& buffers, const endpoint_type& destination, 349 socket_base::message_flags flags, 350 BOOST_ASIO_MOVE_ARG(WriteHandler) handler) 351 { 352 detail::async_result_init< 353 WriteHandler, void (boost::system::error_code, std::size_t)> init( 354 BOOST_ASIO_MOVE_CAST(WriteHandler)(handler)); 355 356 service_impl_.async_send_to(impl, buffers, 357 destination, flags, init.handler); 358 359 return init.result.get(); 360 } 361 362 /// Receive some data from the peer. 363 template <typename MutableBufferSequence> receive(implementation_type & impl,const MutableBufferSequence & buffers,socket_base::message_flags flags,boost::system::error_code & ec)364 std::size_t receive(implementation_type& impl, 365 const MutableBufferSequence& buffers, 366 socket_base::message_flags flags, boost::system::error_code& ec) 367 { 368 return service_impl_.receive(impl, buffers, flags, ec); 369 } 370 371 /// Start an asynchronous receive. 372 template <typename MutableBufferSequence, typename ReadHandler> BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler,void (boost::system::error_code,std::size_t))373 BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler, 374 void (boost::system::error_code, std::size_t)) 375 async_receive(implementation_type& impl, 376 const MutableBufferSequence& buffers, 377 socket_base::message_flags flags, 378 BOOST_ASIO_MOVE_ARG(ReadHandler) handler) 379 { 380 detail::async_result_init< 381 ReadHandler, void (boost::system::error_code, std::size_t)> init( 382 BOOST_ASIO_MOVE_CAST(ReadHandler)(handler)); 383 384 service_impl_.async_receive(impl, buffers, flags, init.handler); 385 386 return init.result.get(); 387 } 388 389 /// Receive raw data with the endpoint of the sender. 390 template <typename MutableBufferSequence> receive_from(implementation_type & impl,const MutableBufferSequence & buffers,endpoint_type & sender_endpoint,socket_base::message_flags flags,boost::system::error_code & ec)391 std::size_t receive_from(implementation_type& impl, 392 const MutableBufferSequence& buffers, endpoint_type& sender_endpoint, 393 socket_base::message_flags flags, boost::system::error_code& ec) 394 { 395 return service_impl_.receive_from(impl, buffers, sender_endpoint, flags, 396 ec); 397 } 398 399 /// Start an asynchronous receive that will get the endpoint of the sender. 400 template <typename MutableBufferSequence, typename ReadHandler> BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler,void (boost::system::error_code,std::size_t))401 BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler, 402 void (boost::system::error_code, std::size_t)) 403 async_receive_from(implementation_type& impl, 404 const MutableBufferSequence& buffers, endpoint_type& sender_endpoint, 405 socket_base::message_flags flags, 406 BOOST_ASIO_MOVE_ARG(ReadHandler) handler) 407 { 408 detail::async_result_init< 409 ReadHandler, void (boost::system::error_code, std::size_t)> init( 410 BOOST_ASIO_MOVE_CAST(ReadHandler)(handler)); 411 412 service_impl_.async_receive_from(impl, buffers, 413 sender_endpoint, flags, init.handler); 414 415 return init.result.get(); 416 } 417 418 private: 419 // Destroy all user-defined handler objects owned by the service. shutdown_service()420 void shutdown_service() 421 { 422 service_impl_.shutdown_service(); 423 } 424 425 // The platform-specific implementation. 426 service_impl_type service_impl_; 427 }; 428 429 } // namespace asio 430 } // namespace boost 431 432 #include <boost/asio/detail/pop_options.hpp> 433 434 #endif // BOOST_ASIO_RAW_SOCKET_SERVICE_HPP 435