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