1 // 2 // basic_seq_packet_socket.hpp 3 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~ 4 // 5 // Copyright (c) 2003-2018 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_BASIC_SEQ_PACKET_SOCKET_HPP 12 #define ASIO_BASIC_SEQ_PACKET_SOCKET_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/basic_socket.hpp" 21 #include "asio/detail/handler_type_requirements.hpp" 22 #include "asio/detail/throw_error.hpp" 23 #include "asio/error.hpp" 24 25 #if defined(ASIO_ENABLE_OLD_SERVICES) 26 # include "asio/seq_packet_socket_service.hpp" 27 #endif // defined(ASIO_ENABLE_OLD_SERVICES) 28 29 #include "asio/detail/push_options.hpp" 30 31 namespace asio { 32 33 /// Provides sequenced packet socket functionality. 34 /** 35 * The basic_seq_packet_socket class template provides asynchronous and blocking 36 * sequenced packet socket functionality. 37 * 38 * @par Thread Safety 39 * @e Distinct @e objects: Safe.@n 40 * @e Shared @e objects: Unsafe. 41 */ 42 template <typename Protocol 43 ASIO_SVC_TPARAM_DEF1(= seq_packet_socket_service<Protocol>)> 44 class basic_seq_packet_socket 45 : public basic_socket<Protocol ASIO_SVC_TARG> 46 { 47 public: 48 /// The native representation of a socket. 49 #if defined(GENERATING_DOCUMENTATION) 50 typedef implementation_defined native_handle_type; 51 #else 52 typedef typename basic_socket< 53 Protocol ASIO_SVC_TARG>::native_handle_type native_handle_type; 54 #endif 55 56 /// The protocol type. 57 typedef Protocol protocol_type; 58 59 /// The endpoint type. 60 typedef typename Protocol::endpoint endpoint_type; 61 62 /// Construct a basic_seq_packet_socket without opening it. 63 /** 64 * This constructor creates a sequenced packet socket without opening it. The 65 * socket needs to be opened and then connected or accepted before data can 66 * be sent or received on it. 67 * 68 * @param io_context The io_context object that the sequenced packet socket 69 * will use to dispatch handlers for any asynchronous operations performed on 70 * the socket. 71 */ basic_seq_packet_socket(asio::io_context & io_context)72 explicit basic_seq_packet_socket(asio::io_context& io_context) 73 : basic_socket<Protocol ASIO_SVC_TARG>(io_context) 74 { 75 } 76 77 /// Construct and open a basic_seq_packet_socket. 78 /** 79 * This constructor creates and opens a sequenced_packet socket. The socket 80 * needs to be connected or accepted before data can be sent or received on 81 * it. 82 * 83 * @param io_context The io_context object that the sequenced packet socket 84 * will use to dispatch handlers for any asynchronous operations performed on 85 * the socket. 86 * 87 * @param protocol An object specifying protocol parameters to be used. 88 * 89 * @throws asio::system_error Thrown on failure. 90 */ basic_seq_packet_socket(asio::io_context & io_context,const protocol_type & protocol)91 basic_seq_packet_socket(asio::io_context& io_context, 92 const protocol_type& protocol) 93 : basic_socket<Protocol ASIO_SVC_TARG>(io_context, protocol) 94 { 95 } 96 97 /// Construct a basic_seq_packet_socket, opening it and binding it to the 98 /// given local endpoint. 99 /** 100 * This constructor creates a sequenced packet socket and automatically opens 101 * it bound to the specified endpoint on the local machine. The protocol used 102 * is the protocol associated with the given endpoint. 103 * 104 * @param io_context The io_context object that the sequenced packet socket 105 * will use to dispatch handlers for any asynchronous operations performed on 106 * the socket. 107 * 108 * @param endpoint An endpoint on the local machine to which the sequenced 109 * packet socket will be bound. 110 * 111 * @throws asio::system_error Thrown on failure. 112 */ basic_seq_packet_socket(asio::io_context & io_context,const endpoint_type & endpoint)113 basic_seq_packet_socket(asio::io_context& io_context, 114 const endpoint_type& endpoint) 115 : basic_socket<Protocol ASIO_SVC_TARG>(io_context, endpoint) 116 { 117 } 118 119 /// Construct a basic_seq_packet_socket on an existing native socket. 120 /** 121 * This constructor creates a sequenced packet socket object to hold an 122 * existing native socket. 123 * 124 * @param io_context The io_context object that the sequenced packet socket 125 * will use to dispatch handlers for any asynchronous operations performed on 126 * the socket. 127 * 128 * @param protocol An object specifying protocol parameters to be used. 129 * 130 * @param native_socket The new underlying socket implementation. 131 * 132 * @throws asio::system_error Thrown on failure. 133 */ basic_seq_packet_socket(asio::io_context & io_context,const protocol_type & protocol,const native_handle_type & native_socket)134 basic_seq_packet_socket(asio::io_context& io_context, 135 const protocol_type& protocol, const native_handle_type& native_socket) 136 : basic_socket<Protocol ASIO_SVC_TARG>( 137 io_context, protocol, native_socket) 138 { 139 } 140 141 #if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) 142 /// Move-construct a basic_seq_packet_socket from another. 143 /** 144 * This constructor moves a sequenced packet socket from one object to 145 * another. 146 * 147 * @param other The other basic_seq_packet_socket object from which the move 148 * will occur. 149 * 150 * @note Following the move, the moved-from object is in the same state as if 151 * constructed using the @c basic_seq_packet_socket(io_context&) constructor. 152 */ basic_seq_packet_socket(basic_seq_packet_socket && other)153 basic_seq_packet_socket(basic_seq_packet_socket&& other) 154 : basic_socket<Protocol ASIO_SVC_TARG>(std::move(other)) 155 { 156 } 157 158 /// Move-assign a basic_seq_packet_socket from another. 159 /** 160 * This assignment operator moves a sequenced packet socket from one object to 161 * another. 162 * 163 * @param other The other basic_seq_packet_socket object from which the move 164 * will occur. 165 * 166 * @note Following the move, the moved-from object is in the same state as if 167 * constructed using the @c basic_seq_packet_socket(io_context&) constructor. 168 */ operator =(basic_seq_packet_socket && other)169 basic_seq_packet_socket& operator=(basic_seq_packet_socket&& other) 170 { 171 basic_socket<Protocol ASIO_SVC_TARG>::operator=(std::move(other)); 172 return *this; 173 } 174 175 /// Move-construct a basic_seq_packet_socket from a socket of another protocol 176 /// type. 177 /** 178 * This constructor moves a sequenced packet socket from one object to 179 * another. 180 * 181 * @param other The other basic_seq_packet_socket object from which the move 182 * will occur. 183 * 184 * @note Following the move, the moved-from object is in the same state as if 185 * constructed using the @c basic_seq_packet_socket(io_context&) constructor. 186 */ 187 template <typename Protocol1 ASIO_SVC_TPARAM1> basic_seq_packet_socket(basic_seq_packet_socket<Protocol1 ASIO_SVC_TARG1> && other,typename enable_if<is_convertible<Protocol1,Protocol>::value>::type * =0)188 basic_seq_packet_socket( 189 basic_seq_packet_socket<Protocol1 ASIO_SVC_TARG1>&& other, 190 typename enable_if<is_convertible<Protocol1, Protocol>::value>::type* = 0) 191 : basic_socket<Protocol ASIO_SVC_TARG>(std::move(other)) 192 { 193 } 194 195 /// Move-assign a basic_seq_packet_socket from a socket of another protocol 196 /// type. 197 /** 198 * This assignment operator moves a sequenced packet socket from one object to 199 * another. 200 * 201 * @param other The other basic_seq_packet_socket object from which the move 202 * will occur. 203 * 204 * @note Following the move, the moved-from object is in the same state as if 205 * constructed using the @c basic_seq_packet_socket(io_context&) constructor. 206 */ 207 template <typename Protocol1 ASIO_SVC_TPARAM1> 208 typename enable_if<is_convertible<Protocol1, Protocol>::value, operator =(basic_seq_packet_socket<Protocol1 ASIO_SVC_TARG1> && other)209 basic_seq_packet_socket>::type& operator=( 210 basic_seq_packet_socket<Protocol1 ASIO_SVC_TARG1>&& other) 211 { 212 basic_socket<Protocol ASIO_SVC_TARG>::operator=(std::move(other)); 213 return *this; 214 } 215 #endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) 216 217 /// Destroys the socket. 218 /** 219 * This function destroys the socket, cancelling any outstanding asynchronous 220 * operations associated with the socket as if by calling @c cancel. 221 */ ~basic_seq_packet_socket()222 ~basic_seq_packet_socket() 223 { 224 } 225 226 /// Send some data on the socket. 227 /** 228 * This function is used to send data on the sequenced packet socket. The 229 * function call will block until the data has been sent successfully, or an 230 * until error occurs. 231 * 232 * @param buffers One or more data buffers to be sent on the socket. 233 * 234 * @param flags Flags specifying how the send call is to be made. 235 * 236 * @returns The number of bytes sent. 237 * 238 * @throws asio::system_error Thrown on failure. 239 * 240 * @par Example 241 * To send a single data buffer use the @ref buffer function as follows: 242 * @code 243 * socket.send(asio::buffer(data, size), 0); 244 * @endcode 245 * See the @ref buffer documentation for information on sending multiple 246 * buffers in one go, and how to use it with arrays, boost::array or 247 * std::vector. 248 */ 249 template <typename ConstBufferSequence> send(const ConstBufferSequence & buffers,socket_base::message_flags flags)250 std::size_t send(const ConstBufferSequence& buffers, 251 socket_base::message_flags flags) 252 { 253 asio::error_code ec; 254 std::size_t s = this->get_service().send( 255 this->get_implementation(), buffers, flags, ec); 256 asio::detail::throw_error(ec, "send"); 257 return s; 258 } 259 260 /// Send some data on the socket. 261 /** 262 * This function is used to send data on the sequenced packet socket. The 263 * function call will block the data has been sent successfully, or an until 264 * error occurs. 265 * 266 * @param buffers One or more data buffers to be sent on the socket. 267 * 268 * @param flags Flags specifying how the send call is to be made. 269 * 270 * @param ec Set to indicate what error occurred, if any. 271 * 272 * @returns The number of bytes sent. Returns 0 if an error occurred. 273 * 274 * @note The send operation may not transmit all of the data to the peer. 275 * Consider using the @ref write function if you need to ensure that all data 276 * is written before the blocking operation completes. 277 */ 278 template <typename ConstBufferSequence> send(const ConstBufferSequence & buffers,socket_base::message_flags flags,asio::error_code & ec)279 std::size_t send(const ConstBufferSequence& buffers, 280 socket_base::message_flags flags, asio::error_code& ec) 281 { 282 return this->get_service().send( 283 this->get_implementation(), buffers, flags, ec); 284 } 285 286 /// Start an asynchronous send. 287 /** 288 * This function is used to asynchronously send data on the sequenced packet 289 * socket. The function call always returns immediately. 290 * 291 * @param buffers One or more data buffers to be sent on the socket. Although 292 * the buffers object may be copied as necessary, ownership of the underlying 293 * memory blocks is retained by the caller, which must guarantee that they 294 * remain valid until the handler is called. 295 * 296 * @param flags Flags specifying how the send call is to be made. 297 * 298 * @param handler The handler to be called when the send operation completes. 299 * Copies will be made of the handler as required. The function signature of 300 * the handler must be: 301 * @code void handler( 302 * const asio::error_code& error, // Result of operation. 303 * std::size_t bytes_transferred // Number of bytes sent. 304 * ); @endcode 305 * Regardless of whether the asynchronous operation completes immediately or 306 * not, the handler will not be invoked from within this function. Invocation 307 * of the handler will be performed in a manner equivalent to using 308 * asio::io_context::post(). 309 * 310 * @par Example 311 * To send a single data buffer use the @ref buffer function as follows: 312 * @code 313 * socket.async_send(asio::buffer(data, size), 0, handler); 314 * @endcode 315 * See the @ref buffer documentation for information on sending multiple 316 * buffers in one go, and how to use it with arrays, boost::array or 317 * std::vector. 318 */ 319 template <typename ConstBufferSequence, typename WriteHandler> ASIO_INITFN_RESULT_TYPE(WriteHandler,void (asio::error_code,std::size_t))320 ASIO_INITFN_RESULT_TYPE(WriteHandler, 321 void (asio::error_code, std::size_t)) 322 async_send(const ConstBufferSequence& buffers, 323 socket_base::message_flags flags, 324 ASIO_MOVE_ARG(WriteHandler) handler) 325 { 326 // If you get an error on the following line it means that your handler does 327 // not meet the documented type requirements for a WriteHandler. 328 ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check; 329 330 #if defined(ASIO_ENABLE_OLD_SERVICES) 331 return this->get_service().async_send(this->get_implementation(), 332 buffers, flags, ASIO_MOVE_CAST(WriteHandler)(handler)); 333 #else // defined(ASIO_ENABLE_OLD_SERVICES) 334 async_completion<WriteHandler, 335 void (asio::error_code, std::size_t)> init(handler); 336 337 this->get_service().async_send(this->get_implementation(), 338 buffers, flags, init.completion_handler); 339 340 return init.result.get(); 341 #endif // defined(ASIO_ENABLE_OLD_SERVICES) 342 } 343 344 /// Receive some data on the socket. 345 /** 346 * This function is used to receive data on the sequenced packet socket. The 347 * function call will block until data has been received successfully, or 348 * until an error occurs. 349 * 350 * @param buffers One or more buffers into which the data will be received. 351 * 352 * @param out_flags After the receive call completes, contains flags 353 * associated with the received data. For example, if the 354 * socket_base::message_end_of_record bit is set then the received data marks 355 * the end of a record. 356 * 357 * @returns The number of bytes received. 358 * 359 * @throws asio::system_error Thrown on failure. An error code of 360 * asio::error::eof indicates that the connection was closed by the 361 * peer. 362 * 363 * @par Example 364 * To receive into a single data buffer use the @ref buffer function as 365 * follows: 366 * @code 367 * socket.receive(asio::buffer(data, size), out_flags); 368 * @endcode 369 * See the @ref buffer documentation for information on receiving into 370 * multiple buffers in one go, and how to use it with arrays, boost::array or 371 * std::vector. 372 */ 373 template <typename MutableBufferSequence> receive(const MutableBufferSequence & buffers,socket_base::message_flags & out_flags)374 std::size_t receive(const MutableBufferSequence& buffers, 375 socket_base::message_flags& out_flags) 376 { 377 asio::error_code ec; 378 #if defined(ASIO_ENABLE_OLD_SERVICES) 379 std::size_t s = this->get_service().receive( 380 this->get_implementation(), buffers, 0, out_flags, ec); 381 #else // defined(ASIO_ENABLE_OLD_SERVICES) 382 std::size_t s = this->get_service().receive_with_flags( 383 this->get_implementation(), buffers, 0, out_flags, ec); 384 #endif // defined(ASIO_ENABLE_OLD_SERVICES) 385 asio::detail::throw_error(ec, "receive"); 386 return s; 387 } 388 389 /// Receive some data on the socket. 390 /** 391 * This function is used to receive data on the sequenced packet socket. The 392 * function call will block until data has been received successfully, or 393 * until an error occurs. 394 * 395 * @param buffers One or more buffers into which the data will be received. 396 * 397 * @param in_flags Flags specifying how the receive call is to be made. 398 * 399 * @param out_flags After the receive call completes, contains flags 400 * associated with the received data. For example, if the 401 * socket_base::message_end_of_record bit is set then the received data marks 402 * the end of a record. 403 * 404 * @returns The number of bytes received. 405 * 406 * @throws asio::system_error Thrown on failure. An error code of 407 * asio::error::eof indicates that the connection was closed by the 408 * peer. 409 * 410 * @note The receive operation may not receive all of the requested number of 411 * bytes. Consider using the @ref read function if you need to ensure that the 412 * requested amount of data is read before the blocking operation completes. 413 * 414 * @par Example 415 * To receive into a single data buffer use the @ref buffer function as 416 * follows: 417 * @code 418 * socket.receive(asio::buffer(data, size), 0, out_flags); 419 * @endcode 420 * See the @ref buffer documentation for information on receiving into 421 * multiple buffers in one go, and how to use it with arrays, boost::array or 422 * std::vector. 423 */ 424 template <typename MutableBufferSequence> receive(const MutableBufferSequence & buffers,socket_base::message_flags in_flags,socket_base::message_flags & out_flags)425 std::size_t receive(const MutableBufferSequence& buffers, 426 socket_base::message_flags in_flags, 427 socket_base::message_flags& out_flags) 428 { 429 asio::error_code ec; 430 #if defined(ASIO_ENABLE_OLD_SERVICES) 431 std::size_t s = this->get_service().receive( 432 this->get_implementation(), buffers, in_flags, out_flags, ec); 433 #else // defined(ASIO_ENABLE_OLD_SERVICES) 434 std::size_t s = this->get_service().receive_with_flags( 435 this->get_implementation(), buffers, in_flags, out_flags, ec); 436 #endif // defined(ASIO_ENABLE_OLD_SERVICES) 437 asio::detail::throw_error(ec, "receive"); 438 return s; 439 } 440 441 /// Receive some data on a connected socket. 442 /** 443 * This function is used to receive data on the sequenced packet socket. The 444 * function call will block until data has been received successfully, or 445 * until an error occurs. 446 * 447 * @param buffers One or more buffers into which the data will be received. 448 * 449 * @param in_flags Flags specifying how the receive call is to be made. 450 * 451 * @param out_flags After the receive call completes, contains flags 452 * associated with the received data. For example, if the 453 * socket_base::message_end_of_record bit is set then the received data marks 454 * the end of a record. 455 * 456 * @param ec Set to indicate what error occurred, if any. 457 * 458 * @returns The number of bytes received. Returns 0 if an error occurred. 459 * 460 * @note The receive operation may not receive all of the requested number of 461 * bytes. Consider using the @ref read function if you need to ensure that the 462 * requested amount of data is read before the blocking operation completes. 463 */ 464 template <typename MutableBufferSequence> receive(const MutableBufferSequence & buffers,socket_base::message_flags in_flags,socket_base::message_flags & out_flags,asio::error_code & ec)465 std::size_t receive(const MutableBufferSequence& buffers, 466 socket_base::message_flags in_flags, 467 socket_base::message_flags& out_flags, asio::error_code& ec) 468 { 469 #if defined(ASIO_ENABLE_OLD_SERVICES) 470 return this->get_service().receive(this->get_implementation(), 471 buffers, in_flags, out_flags, ec); 472 #else // defined(ASIO_ENABLE_OLD_SERVICES) 473 return this->get_service().receive_with_flags(this->get_implementation(), 474 buffers, in_flags, out_flags, ec); 475 #endif // defined(ASIO_ENABLE_OLD_SERVICES) 476 } 477 478 /// Start an asynchronous receive. 479 /** 480 * This function is used to asynchronously receive data from the sequenced 481 * packet socket. The function call always returns immediately. 482 * 483 * @param buffers One or more buffers into which the data will be received. 484 * Although the buffers object may be copied as necessary, ownership of the 485 * underlying memory blocks is retained by the caller, which must guarantee 486 * that they remain valid until the handler is called. 487 * 488 * @param out_flags Once the asynchronous operation completes, contains flags 489 * associated with the received data. For example, if the 490 * socket_base::message_end_of_record bit is set then the received data marks 491 * the end of a record. The caller must guarantee that the referenced 492 * variable remains valid until the handler is called. 493 * 494 * @param handler The handler to be called when the receive operation 495 * completes. Copies will be made of the handler as required. The function 496 * signature of the handler must be: 497 * @code void handler( 498 * const asio::error_code& error, // Result of operation. 499 * std::size_t bytes_transferred // Number of bytes received. 500 * ); @endcode 501 * Regardless of whether the asynchronous operation completes immediately or 502 * not, the handler will not be invoked from within this function. Invocation 503 * of the handler will be performed in a manner equivalent to using 504 * asio::io_context::post(). 505 * 506 * @par Example 507 * To receive into a single data buffer use the @ref buffer function as 508 * follows: 509 * @code 510 * socket.async_receive(asio::buffer(data, size), out_flags, handler); 511 * @endcode 512 * See the @ref buffer documentation for information on receiving into 513 * multiple buffers in one go, and how to use it with arrays, boost::array or 514 * std::vector. 515 */ 516 template <typename MutableBufferSequence, typename ReadHandler> ASIO_INITFN_RESULT_TYPE(ReadHandler,void (asio::error_code,std::size_t))517 ASIO_INITFN_RESULT_TYPE(ReadHandler, 518 void (asio::error_code, std::size_t)) 519 async_receive(const MutableBufferSequence& buffers, 520 socket_base::message_flags& out_flags, 521 ASIO_MOVE_ARG(ReadHandler) handler) 522 { 523 // If you get an error on the following line it means that your handler does 524 // not meet the documented type requirements for a ReadHandler. 525 ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check; 526 527 #if defined(ASIO_ENABLE_OLD_SERVICES) 528 return this->get_service().async_receive( 529 this->get_implementation(), buffers, 0, out_flags, 530 ASIO_MOVE_CAST(ReadHandler)(handler)); 531 #else // defined(ASIO_ENABLE_OLD_SERVICES) 532 async_completion<ReadHandler, 533 void (asio::error_code, std::size_t)> init(handler); 534 535 this->get_service().async_receive_with_flags( 536 this->get_implementation(), buffers, 0, out_flags, 537 init.completion_handler); 538 539 return init.result.get(); 540 #endif // defined(ASIO_ENABLE_OLD_SERVICES) 541 } 542 543 /// Start an asynchronous receive. 544 /** 545 * This function is used to asynchronously receive data from the sequenced 546 * data socket. The function call always returns immediately. 547 * 548 * @param buffers One or more buffers into which the data will be received. 549 * Although the buffers object may be copied as necessary, ownership of the 550 * underlying memory blocks is retained by the caller, which must guarantee 551 * that they remain valid until the handler is called. 552 * 553 * @param in_flags Flags specifying how the receive call is to be made. 554 * 555 * @param out_flags Once the asynchronous operation completes, contains flags 556 * associated with the received data. For example, if the 557 * socket_base::message_end_of_record bit is set then the received data marks 558 * the end of a record. The caller must guarantee that the referenced 559 * variable remains valid until the handler is called. 560 * 561 * @param handler The handler to be called when the receive operation 562 * completes. Copies will be made of the handler as required. The function 563 * signature of the handler must be: 564 * @code void handler( 565 * const asio::error_code& error, // Result of operation. 566 * std::size_t bytes_transferred // Number of bytes received. 567 * ); @endcode 568 * Regardless of whether the asynchronous operation completes immediately or 569 * not, the handler will not be invoked from within this function. Invocation 570 * of the handler will be performed in a manner equivalent to using 571 * asio::io_context::post(). 572 * 573 * @par Example 574 * To receive into a single data buffer use the @ref buffer function as 575 * follows: 576 * @code 577 * socket.async_receive( 578 * asio::buffer(data, size), 579 * 0, out_flags, handler); 580 * @endcode 581 * See the @ref buffer documentation for information on receiving into 582 * multiple buffers in one go, and how to use it with arrays, boost::array or 583 * std::vector. 584 */ 585 template <typename MutableBufferSequence, typename ReadHandler> ASIO_INITFN_RESULT_TYPE(ReadHandler,void (asio::error_code,std::size_t))586 ASIO_INITFN_RESULT_TYPE(ReadHandler, 587 void (asio::error_code, std::size_t)) 588 async_receive(const MutableBufferSequence& buffers, 589 socket_base::message_flags in_flags, 590 socket_base::message_flags& out_flags, 591 ASIO_MOVE_ARG(ReadHandler) handler) 592 { 593 // If you get an error on the following line it means that your handler does 594 // not meet the documented type requirements for a ReadHandler. 595 ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check; 596 597 #if defined(ASIO_ENABLE_OLD_SERVICES) 598 return this->get_service().async_receive( 599 this->get_implementation(), buffers, in_flags, out_flags, 600 ASIO_MOVE_CAST(ReadHandler)(handler)); 601 #else // defined(ASIO_ENABLE_OLD_SERVICES) 602 async_completion<ReadHandler, 603 void (asio::error_code, std::size_t)> init(handler); 604 605 this->get_service().async_receive_with_flags( 606 this->get_implementation(), buffers, in_flags, out_flags, 607 init.completion_handler); 608 609 return init.result.get(); 610 #endif // defined(ASIO_ENABLE_OLD_SERVICES) 611 } 612 }; 613 614 } // namespace asio 615 616 #include "asio/detail/pop_options.hpp" 617 618 #endif // ASIO_BASIC_SEQ_PACKET_SOCKET_HPP 619