1 // 2 // basic_socket_ext.hpp 3 // ~~~~~~~~~~~~~~~~ 4 // 5 // Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com) 6 // Copyright (C) 2018 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) 7 // 8 // Distributed under the Boost Software License, Version 1.0. (See accompanying 9 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 10 // 11 12 #ifndef BOOST_ASIO_BASIC_SOCKET_EXT_HPP 13 #define BOOST_ASIO_BASIC_SOCKET_EXT_HPP 14 15 #if defined(_MSC_VER) && (_MSC_VER >= 1200) 16 # pragma once 17 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) 18 19 #include <boost/asio/detail/config.hpp> 20 #include <boost/asio/async_result.hpp> 21 #include <boost/asio/basic_io_object.hpp> 22 #include <boost/asio/detail/handler_type_requirements.hpp> 23 #include <boost/asio/detail/throw_error.hpp> 24 #include <boost/asio/detail/type_traits.hpp> 25 #include <boost/asio/error.hpp> 26 #include <boost/asio/post.hpp> 27 #include <boost/asio/socket_base.hpp> 28 29 #if defined(BOOST_ASIO_HAS_MOVE) 30 # include <utility> 31 #endif // defined(BOOST_ASIO_HAS_MOVE) 32 33 #if !defined(BOOST_ASIO_ENABLE_OLD_SERVICES) 34 # if defined(BOOST_ASIO_WINDOWS_RUNTIME) 35 # include <boost/asio/detail/winrt_ssocket_service.hpp> 36 # define BOOST_ASIO_SVC_T detail::winrt_ssocket_service<Protocol> 37 # elif defined(BOOST_ASIO_HAS_IOCP) 38 # include <boost/asio/detail/win_iocp_socket_service.hpp> 39 # define BOOST_ASIO_SVC_T detail::win_iocp_socket_service<Protocol> 40 # else 41 # include <boost/asio/detail/reactive_socket_service_ext.hpp> 42 # define BOOST_ASIO_SVC_T detail::reactive_socket_service_ext<Protocol> 43 # endif 44 #endif // !defined(BOOST_ASIO_ENABLE_OLD_SERVICES) 45 46 #include <boost/asio/detail/push_options.hpp> 47 48 namespace boost { 49 namespace asio { 50 51 /// Provides socket functionality. 52 /** 53 * The basic_socket class template provides functionality that is common to both 54 * stream-oriented and datagram-oriented sockets. 55 * 56 * @par Thread Safety 57 * @e Distinct @e objects: Safe.@n 58 * @e Shared @e objects: Unsafe. 59 */ 60 template <typename Protocol BOOST_ASIO_SVC_TPARAM> 61 class basic_socket_ext 62 : BOOST_ASIO_SVC_ACCESS basic_io_object<BOOST_ASIO_SVC_T>, 63 public socket_base 64 { 65 public: 66 /// The type of the executor associated with the object. 67 typedef io_context::executor_type executor_type; 68 69 /// The native representation of a socket. 70 #if defined(GENERATING_DOCUMENTATION) 71 typedef implementation_defined native_handle_type; 72 #else 73 typedef typename BOOST_ASIO_SVC_T::native_handle_type native_handle_type; 74 #endif 75 76 /// The protocol type. 77 typedef Protocol protocol_type; 78 79 /// The endpoint type. 80 typedef typename Protocol::endpoint endpoint_type; 81 82 #if !defined(BOOST_ASIO_NO_EXTENSIONS) 83 /// A basic_socket is always the lowest layer. 84 typedef basic_socket_ext<Protocol BOOST_ASIO_SVC_TARG> lowest_layer_type; 85 #endif // !defined(BOOST_ASIO_NO_EXTENSIONS) 86 87 /// Construct a basic_socket without opening it. 88 /** 89 * This constructor creates a socket without opening it. 90 * 91 * @param io_context The io_context object that the socket will use to 92 * dispatch handlers for any asynchronous operations performed on the socket. 93 */ basic_socket_ext(boost::asio::io_context & io_context)94 explicit basic_socket_ext(boost::asio::io_context& io_context) 95 : basic_io_object<BOOST_ASIO_SVC_T>(io_context) 96 { 97 } 98 99 /// Construct and open a basic_socket. 100 /** 101 * This constructor creates and opens a socket. 102 * 103 * @param io_context The io_context object that the socket will use to 104 * dispatch handlers for any asynchronous operations performed on the socket. 105 * 106 * @param protocol An object specifying protocol parameters to be used. 107 * 108 * @throws boost::system::system_error Thrown on failure. 109 */ basic_socket_ext(boost::asio::io_context & io_context,const protocol_type & protocol)110 basic_socket_ext(boost::asio::io_context& io_context, 111 const protocol_type& protocol) 112 : basic_io_object<BOOST_ASIO_SVC_T>(io_context) 113 { 114 boost::system::error_code ec; 115 this->get_service().open(this->get_implementation(), protocol, ec); 116 boost::asio::detail::throw_error(ec, "open"); 117 } 118 119 /// Construct a basic_socket, opening it and binding it to the given local 120 /// endpoint. 121 /** 122 * This constructor creates a socket and automatically opens it bound to the 123 * specified endpoint on the local machine. The protocol used is the protocol 124 * associated with the given endpoint. 125 * 126 * @param io_context The io_context object that the socket will use to 127 * dispatch handlers for any asynchronous operations performed on the socket. 128 * 129 * @param endpoint An endpoint on the local machine to which the socket will 130 * be bound. 131 * 132 * @throws boost::system::system_error Thrown on failure. 133 */ basic_socket_ext(boost::asio::io_context & io_context,const endpoint_type & endpoint)134 basic_socket_ext(boost::asio::io_context& io_context, 135 const endpoint_type& endpoint) 136 : basic_io_object<BOOST_ASIO_SVC_T>(io_context) 137 { 138 boost::system::error_code ec; 139 const protocol_type protocol = endpoint.protocol(); 140 this->get_service().open(this->get_implementation(), protocol, ec); 141 boost::asio::detail::throw_error(ec, "open"); 142 this->get_service().bind(this->get_implementation(), endpoint, ec); 143 boost::asio::detail::throw_error(ec, "bind"); 144 } 145 146 /// Construct a basic_socket on an existing native socket. 147 /** 148 * This constructor creates a socket object to hold an existing native socket. 149 * 150 * @param io_context The io_context object that the socket will use to 151 * dispatch handlers for any asynchronous operations performed on the socket. 152 * 153 * @param protocol An object specifying protocol parameters to be used. 154 * 155 * @param native_socket A native socket. 156 * 157 * @throws boost::system::system_error Thrown on failure. 158 */ basic_socket_ext(boost::asio::io_context & io_context,const protocol_type & protocol,const native_handle_type & native_socket)159 basic_socket_ext(boost::asio::io_context& io_context, 160 const protocol_type& protocol, const native_handle_type& native_socket) 161 : basic_io_object<BOOST_ASIO_SVC_T>(io_context) 162 { 163 boost::system::error_code ec; 164 this->get_service().assign(this->get_implementation(), 165 protocol, native_socket, ec); 166 boost::asio::detail::throw_error(ec, "assign"); 167 } 168 169 #if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) 170 /// Move-construct a basic_socket from another. 171 /** 172 * This constructor moves a socket from one object to another. 173 * 174 * @param other The other basic_socket object from which the move will 175 * occur. 176 * 177 * @note Following the move, the moved-from object is in the same state as if 178 * constructed using the @c basic_socket(io_context&) constructor. 179 */ basic_socket_ext(basic_socket_ext && other)180 basic_socket_ext(basic_socket_ext&& other) 181 : basic_io_object<BOOST_ASIO_SVC_T>(std::move(other)) 182 { 183 } 184 185 /// Move-assign a basic_socket from another. 186 /** 187 * This assignment operator moves a socket from one object to another. 188 * 189 * @param other The other basic_socket object from which the move will 190 * occur. 191 * 192 * @note Following the move, the moved-from object is in the same state as if 193 * constructed using the @c basic_socket(io_context&) constructor. 194 */ operator =(basic_socket_ext && other)195 basic_socket_ext& operator=(basic_socket_ext&& other) 196 { 197 basic_io_object<BOOST_ASIO_SVC_T>::operator=(std::move(other)); 198 return *this; 199 } 200 201 // All sockets have access to each other's implementations. 202 template <typename Protocol1 BOOST_ASIO_SVC_TPARAM1> 203 friend class basic_socket; 204 205 /// Move-construct a basic_socket from a socket of another protocol type. 206 /** 207 * This constructor moves a socket from one object to another. 208 * 209 * @param other The other basic_socket object from which the move will 210 * occur. 211 * 212 * @note Following the move, the moved-from object is in the same state as if 213 * constructed using the @c basic_socket(io_context&) constructor. 214 */ 215 template <typename Protocol1 BOOST_ASIO_SVC_TPARAM1> basic_socket_ext(basic_socket_ext<Protocol1 BOOST_ASIO_SVC_TARG1> && other,typename enable_if<is_convertible<Protocol1,Protocol>::value>::type * =0)216 basic_socket_ext(basic_socket_ext<Protocol1 BOOST_ASIO_SVC_TARG1>&& other, 217 typename enable_if<is_convertible<Protocol1, Protocol>::value>::type* = 0) 218 : basic_io_object<BOOST_ASIO_SVC_T>( 219 other.get_service(), other.get_implementation()) 220 { 221 } 222 223 /// Move-assign a basic_socket from a socket of another protocol type. 224 /** 225 * This assignment operator moves a socket from one object to another. 226 * 227 * @param other The other basic_socket object from which the move will 228 * occur. 229 * 230 * @note Following the move, the moved-from object is in the same state as if 231 * constructed using the @c basic_socket(io_context&) constructor. 232 */ 233 template <typename Protocol1 BOOST_ASIO_SVC_TPARAM1> 234 typename enable_if<is_convertible<Protocol1, Protocol>::value, operator =(basic_socket_ext<Protocol1 BOOST_ASIO_SVC_TARG1> && other)235 basic_socket_ext>::type& operator=( 236 basic_socket_ext<Protocol1 BOOST_ASIO_SVC_TARG1>&& other) 237 { 238 basic_socket_ext tmp(std::move(other)); 239 basic_io_object<BOOST_ASIO_SVC_T>::operator=(std::move(tmp)); 240 return *this; 241 } 242 #endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) 243 244 #if defined(BOOST_ASIO_ENABLE_OLD_SERVICES) 245 // These functions are provided by basic_io_object<>. 246 #else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) 247 #if !defined(BOOST_ASIO_NO_DEPRECATED) 248 /// (Deprecated: Use get_executor().) Get the io_context associated with the 249 /// object. 250 /** 251 * This function may be used to obtain the io_context object that the I/O 252 * object uses to dispatch handlers for asynchronous operations. 253 * 254 * @return A reference to the io_context object that the I/O object will use 255 * to dispatch handlers. Ownership is not transferred to the caller. 256 */ get_io_context()257 boost::asio::io_context& get_io_context() 258 { 259 return basic_io_object<BOOST_ASIO_SVC_T>::get_io_context(); 260 } 261 262 /// (Deprecated: Use get_executor().) Get the io_context associated with the 263 /// object. 264 /** 265 * This function may be used to obtain the io_context object that the I/O 266 * object uses to dispatch handlers for asynchronous operations. 267 * 268 * @return A reference to the io_context object that the I/O object will use 269 * to dispatch handlers. Ownership is not transferred to the caller. 270 */ get_io_service()271 boost::asio::io_context& get_io_service() 272 { 273 return basic_io_object<BOOST_ASIO_SVC_T>::get_io_service(); 274 } 275 #endif // !defined(BOOST_ASIO_NO_DEPRECATED) 276 277 /// Get the executor associated with the object. get_executor()278 executor_type get_executor() BOOST_ASIO_NOEXCEPT 279 { 280 return basic_io_object<BOOST_ASIO_SVC_T>::get_executor(); 281 } 282 #endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) 283 284 #if !defined(BOOST_ASIO_NO_EXTENSIONS) 285 /// Get a reference to the lowest layer. 286 /** 287 * This function returns a reference to the lowest layer in a stack of 288 * layers. Since a basic_socket cannot contain any further layers, it simply 289 * returns a reference to itself. 290 * 291 * @return A reference to the lowest layer in the stack of layers. Ownership 292 * is not transferred to the caller. 293 */ lowest_layer()294 lowest_layer_type& lowest_layer() 295 { 296 return *this; 297 } 298 299 /// Get a const reference to the lowest layer. 300 /** 301 * This function returns a const reference to the lowest layer in a stack of 302 * layers. Since a basic_socket cannot contain any further layers, it simply 303 * returns a reference to itself. 304 * 305 * @return A const reference to the lowest layer in the stack of layers. 306 * Ownership is not transferred to the caller. 307 */ lowest_layer() const308 const lowest_layer_type& lowest_layer() const 309 { 310 return *this; 311 } 312 #endif // !defined(BOOST_ASIO_NO_EXTENSIONS) 313 314 /// Open the socket using the specified protocol. 315 /** 316 * This function opens the socket so that it will use the specified protocol. 317 * 318 * @param protocol An object specifying protocol parameters to be used. 319 * 320 * @throws boost::system::system_error Thrown on failure. 321 * 322 * @par Example 323 * @code 324 * boost::asio::ip::tcp::socket socket(io_context); 325 * socket.open(boost::asio::ip::tcp::v4()); 326 * @endcode 327 */ open(const protocol_type & protocol=protocol_type ())328 void open(const protocol_type& protocol = protocol_type()) 329 { 330 boost::system::error_code ec; 331 this->get_service().open(this->get_implementation(), protocol, ec); 332 boost::asio::detail::throw_error(ec, "open"); 333 } 334 335 /// Open the socket using the specified protocol. 336 /** 337 * This function opens the socket so that it will use the specified protocol. 338 * 339 * @param protocol An object specifying which protocol is to be used. 340 * 341 * @param ec Set to indicate what error occurred, if any. 342 * 343 * @par Example 344 * @code 345 * boost::asio::ip::tcp::socket socket(io_context); 346 * boost::system::error_code ec; 347 * socket.open(boost::asio::ip::tcp::v4(), ec); 348 * if (ec) 349 * { 350 * // An error occurred. 351 * } 352 * @endcode 353 */ open(const protocol_type & protocol,boost::system::error_code & ec)354 BOOST_ASIO_SYNC_OP_VOID open(const protocol_type& protocol, 355 boost::system::error_code& ec) 356 { 357 this->get_service().open(this->get_implementation(), protocol, ec); 358 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); 359 } 360 361 /// Assign an existing native socket to the socket. 362 /* 363 * This function opens the socket to hold an existing native socket. 364 * 365 * @param protocol An object specifying which protocol is to be used. 366 * 367 * @param native_socket A native socket. 368 * 369 * @throws boost::system::system_error Thrown on failure. 370 */ assign(const protocol_type & protocol,const native_handle_type & native_socket)371 void assign(const protocol_type& protocol, 372 const native_handle_type& native_socket) 373 { 374 boost::system::error_code ec; 375 this->get_service().assign(this->get_implementation(), 376 protocol, native_socket, ec); 377 boost::asio::detail::throw_error(ec, "assign"); 378 } 379 380 /// Assign an existing native socket to the socket. 381 /* 382 * This function opens the socket to hold an existing native socket. 383 * 384 * @param protocol An object specifying which protocol is to be used. 385 * 386 * @param native_socket A native socket. 387 * 388 * @param ec Set to indicate what error occurred, if any. 389 */ assign(const protocol_type & protocol,const native_handle_type & native_socket,boost::system::error_code & ec)390 BOOST_ASIO_SYNC_OP_VOID assign(const protocol_type& protocol, 391 const native_handle_type& native_socket, boost::system::error_code& ec) 392 { 393 this->get_service().assign(this->get_implementation(), 394 protocol, native_socket, ec); 395 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); 396 } 397 398 /// Determine whether the socket is open. is_open() const399 bool is_open() const 400 { 401 return this->get_service().is_open(this->get_implementation()); 402 } 403 404 /// Close the socket. 405 /** 406 * This function is used to close the socket. Any asynchronous send, receive 407 * or connect operations will be cancelled immediately, and will complete 408 * with the boost::asio::error::operation_aborted error. 409 * 410 * @throws boost::system::system_error Thrown on failure. Note that, even if 411 * the function indicates an error, the underlying descriptor is closed. 412 * 413 * @note For portable behaviour with respect to graceful closure of a 414 * connected socket, call shutdown() before closing the socket. 415 */ close()416 void close() 417 { 418 boost::system::error_code ec; 419 this->get_service().close(this->get_implementation(), ec); 420 boost::asio::detail::throw_error(ec, "close"); 421 } 422 423 /// Close the socket. 424 /** 425 * This function is used to close the socket. Any asynchronous send, receive 426 * or connect operations will be cancelled immediately, and will complete 427 * with the boost::asio::error::operation_aborted error. 428 * 429 * @param ec Set to indicate what error occurred, if any. Note that, even if 430 * the function indicates an error, the underlying descriptor is closed. 431 * 432 * @par Example 433 * @code 434 * boost::asio::ip::tcp::socket socket(io_context); 435 * ... 436 * boost::system::error_code ec; 437 * socket.close(ec); 438 * if (ec) 439 * { 440 * // An error occurred. 441 * } 442 * @endcode 443 * 444 * @note For portable behaviour with respect to graceful closure of a 445 * connected socket, call shutdown() before closing the socket. 446 */ close(boost::system::error_code & ec)447 BOOST_ASIO_SYNC_OP_VOID close(boost::system::error_code& ec) 448 { 449 this->get_service().close(this->get_implementation(), ec); 450 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); 451 } 452 453 /// Release ownership of the underlying native socket. 454 /** 455 * This function causes all outstanding asynchronous connect, send and receive 456 * operations to finish immediately, and the handlers for cancelled operations 457 * will be passed the boost::asio::error::operation_aborted error. Ownership 458 * of the native socket is then transferred to the caller. 459 * 460 * @throws boost::system::system_error Thrown on failure. 461 * 462 * @note This function is unsupported on Windows versions prior to Windows 463 * 8.1, and will fail with boost::asio::error::operation_not_supported on 464 * these platforms. 465 */ 466 #if defined(BOOST_ASIO_MSVC) && (BOOST_ASIO_MSVC >= 1400) \ 467 && (!defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0603) 468 __declspec(deprecated("This function always fails with " 469 "operation_not_supported when used on Windows versions " 470 "prior to Windows 8.1.")) 471 #endif release()472 native_handle_type release() 473 { 474 boost::system::error_code ec; 475 native_handle_type s = this->get_service().release( 476 this->get_implementation(), ec); 477 boost::asio::detail::throw_error(ec, "release"); 478 return s; 479 } 480 481 /// Release ownership of the underlying native socket. 482 /** 483 * This function causes all outstanding asynchronous connect, send and receive 484 * operations to finish immediately, and the handlers for cancelled operations 485 * will be passed the boost::asio::error::operation_aborted error. Ownership 486 * of the native socket is then transferred to the caller. 487 * 488 * @param ec Set to indicate what error occurred, if any. 489 * 490 * @note This function is unsupported on Windows versions prior to Windows 491 * 8.1, and will fail with boost::asio::error::operation_not_supported on 492 * these platforms. 493 */ 494 #if defined(BOOST_ASIO_MSVC) && (BOOST_ASIO_MSVC >= 1400) \ 495 && (!defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0603) 496 __declspec(deprecated("This function always fails with " 497 "operation_not_supported when used on Windows versions " 498 "prior to Windows 8.1.")) 499 #endif release(boost::system::error_code & ec)500 native_handle_type release(boost::system::error_code& ec) 501 { 502 return this->get_service().release(this->get_implementation(), ec); 503 } 504 505 /// Get the native socket representation. 506 /** 507 * This function may be used to obtain the underlying representation of the 508 * socket. This is intended to allow access to native socket functionality 509 * that is not otherwise provided. 510 */ native_handle()511 native_handle_type native_handle() 512 { 513 return this->get_service().native_handle(this->get_implementation()); 514 } 515 516 /// Cancel all asynchronous operations associated with the socket. 517 /** 518 * This function causes all outstanding asynchronous connect, send and receive 519 * operations to finish immediately, and the handlers for cancelled operations 520 * will be passed the boost::asio::error::operation_aborted error. 521 * 522 * @throws boost::system::system_error Thrown on failure. 523 * 524 * @note Calls to cancel() will always fail with 525 * boost::asio::error::operation_not_supported when run on Windows XP, Windows 526 * Server 2003, and earlier versions of Windows, unless 527 * BOOST_ASIO_ENABLE_CANCELIO is defined. However, the CancelIo function has 528 * two issues that should be considered before enabling its use: 529 * 530 * @li It will only cancel asynchronous operations that were initiated in the 531 * current thread. 532 * 533 * @li It can appear to complete without error, but the request to cancel the 534 * unfinished operations may be silently ignored by the operating system. 535 * Whether it works or not seems to depend on the drivers that are installed. 536 * 537 * For portable cancellation, consider using one of the following 538 * alternatives: 539 * 540 * @li Disable asio's I/O completion port backend by defining 541 * BOOST_ASIO_DISABLE_IOCP. 542 * 543 * @li Use the close() function to simultaneously cancel the outstanding 544 * operations and close the socket. 545 * 546 * When running on Windows Vista, Windows Server 2008, and later, the 547 * CancelIoEx function is always used. This function does not have the 548 * problems described above. 549 */ 550 #if defined(BOOST_ASIO_MSVC) && (BOOST_ASIO_MSVC >= 1400) \ 551 && (!defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0600) \ 552 && !defined(BOOST_ASIO_ENABLE_CANCELIO) 553 __declspec(deprecated("By default, this function always fails with " 554 "operation_not_supported when used on Windows XP, Windows Server 2003, " 555 "or earlier. Consult documentation for details.")) 556 #endif cancel()557 void cancel() 558 { 559 boost::system::error_code ec; 560 this->get_service().cancel(this->get_implementation(), ec); 561 boost::asio::detail::throw_error(ec, "cancel"); 562 } 563 564 /// Cancel all asynchronous operations associated with the socket. 565 /** 566 * This function causes all outstanding asynchronous connect, send and receive 567 * operations to finish immediately, and the handlers for cancelled operations 568 * will be passed the boost::asio::error::operation_aborted error. 569 * 570 * @param ec Set to indicate what error occurred, if any. 571 * 572 * @note Calls to cancel() will always fail with 573 * boost::asio::error::operation_not_supported when run on Windows XP, Windows 574 * Server 2003, and earlier versions of Windows, unless 575 * BOOST_ASIO_ENABLE_CANCELIO is defined. However, the CancelIo function has 576 * two issues that should be considered before enabling its use: 577 * 578 * @li It will only cancel asynchronous operations that were initiated in the 579 * current thread. 580 * 581 * @li It can appear to complete without error, but the request to cancel the 582 * unfinished operations may be silently ignored by the operating system. 583 * Whether it works or not seems to depend on the drivers that are installed. 584 * 585 * For portable cancellation, consider using one of the following 586 * alternatives: 587 * 588 * @li Disable asio's I/O completion port backend by defining 589 * BOOST_ASIO_DISABLE_IOCP. 590 * 591 * @li Use the close() function to simultaneously cancel the outstanding 592 * operations and close the socket. 593 * 594 * When running on Windows Vista, Windows Server 2008, and later, the 595 * CancelIoEx function is always used. This function does not have the 596 * problems described above. 597 */ 598 #if defined(BOOST_ASIO_MSVC) && (BOOST_ASIO_MSVC >= 1400) \ 599 && (!defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0600) \ 600 && !defined(BOOST_ASIO_ENABLE_CANCELIO) 601 __declspec(deprecated("By default, this function always fails with " 602 "operation_not_supported when used on Windows XP, Windows Server 2003, " 603 "or earlier. Consult documentation for details.")) 604 #endif cancel(boost::system::error_code & ec)605 BOOST_ASIO_SYNC_OP_VOID cancel(boost::system::error_code& ec) 606 { 607 this->get_service().cancel(this->get_implementation(), ec); 608 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); 609 } 610 611 /// Determine whether the socket is at the out-of-band data mark. 612 /** 613 * This function is used to check whether the socket input is currently 614 * positioned at the out-of-band data mark. 615 * 616 * @return A bool indicating whether the socket is at the out-of-band data 617 * mark. 618 * 619 * @throws boost::system::system_error Thrown on failure. 620 */ at_mark() const621 bool at_mark() const 622 { 623 boost::system::error_code ec; 624 bool b = this->get_service().at_mark(this->get_implementation(), ec); 625 boost::asio::detail::throw_error(ec, "at_mark"); 626 return b; 627 } 628 629 /// Determine whether the socket is at the out-of-band data mark. 630 /** 631 * This function is used to check whether the socket input is currently 632 * positioned at the out-of-band data mark. 633 * 634 * @param ec Set to indicate what error occurred, if any. 635 * 636 * @return A bool indicating whether the socket is at the out-of-band data 637 * mark. 638 */ at_mark(boost::system::error_code & ec) const639 bool at_mark(boost::system::error_code& ec) const 640 { 641 return this->get_service().at_mark(this->get_implementation(), ec); 642 } 643 644 /// Determine the number of bytes available for reading. 645 /** 646 * This function is used to determine the number of bytes that may be read 647 * without blocking. 648 * 649 * @return The number of bytes that may be read without blocking, or 0 if an 650 * error occurs. 651 * 652 * @throws boost::system::system_error Thrown on failure. 653 */ available() const654 std::size_t available() const 655 { 656 boost::system::error_code ec; 657 std::size_t s = this->get_service().available( 658 this->get_implementation(), ec); 659 boost::asio::detail::throw_error(ec, "available"); 660 return s; 661 } 662 663 /// Determine the number of bytes available for reading. 664 /** 665 * This function is used to determine the number of bytes that may be read 666 * without blocking. 667 * 668 * @param ec Set to indicate what error occurred, if any. 669 * 670 * @return The number of bytes that may be read without blocking, or 0 if an 671 * error occurs. 672 */ available(boost::system::error_code & ec) const673 std::size_t available(boost::system::error_code& ec) const 674 { 675 return this->get_service().available(this->get_implementation(), ec); 676 } 677 678 /// Bind the socket to the given local endpoint. 679 /** 680 * This function binds the socket to the specified endpoint on the local 681 * machine. 682 * 683 * @param endpoint An endpoint on the local machine to which the socket will 684 * be bound. 685 * 686 * @throws boost::system::system_error Thrown on failure. 687 * 688 * @par Example 689 * @code 690 * boost::asio::ip::tcp::socket socket(io_context); 691 * socket.open(boost::asio::ip::tcp::v4()); 692 * socket.bind(boost::asio::ip::tcp::endpoint( 693 * boost::asio::ip::tcp::v4(), 12345)); 694 * @endcode 695 */ bind(const endpoint_type & endpoint)696 void bind(const endpoint_type& endpoint) 697 { 698 boost::system::error_code ec; 699 this->get_service().bind(this->get_implementation(), endpoint, ec); 700 boost::asio::detail::throw_error(ec, "bind"); 701 } 702 703 /// Bind the socket to the given local endpoint. 704 /** 705 * This function binds the socket to the specified endpoint on the local 706 * machine. 707 * 708 * @param endpoint An endpoint on the local machine to which the socket will 709 * be bound. 710 * 711 * @param ec Set to indicate what error occurred, if any. 712 * 713 * @par Example 714 * @code 715 * boost::asio::ip::tcp::socket socket(io_context); 716 * socket.open(boost::asio::ip::tcp::v4()); 717 * boost::system::error_code ec; 718 * socket.bind(boost::asio::ip::tcp::endpoint( 719 * boost::asio::ip::tcp::v4(), 12345), ec); 720 * if (ec) 721 * { 722 * // An error occurred. 723 * } 724 * @endcode 725 */ bind(const endpoint_type & endpoint,boost::system::error_code & ec)726 BOOST_ASIO_SYNC_OP_VOID bind(const endpoint_type& endpoint, 727 boost::system::error_code& ec) 728 { 729 this->get_service().bind(this->get_implementation(), endpoint, ec); 730 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); 731 } 732 733 /// Connect the socket to the specified endpoint. 734 /** 735 * This function is used to connect a socket to the specified remote endpoint. 736 * The function call will block until the connection is successfully made or 737 * an error occurs. 738 * 739 * The socket is automatically opened if it is not already open. If the 740 * connect fails, and the socket was automatically opened, the socket is 741 * not returned to the closed state. 742 * 743 * @param peer_endpoint The remote endpoint to which the socket will be 744 * connected. 745 * 746 * @throws boost::system::system_error Thrown on failure. 747 * 748 * @par Example 749 * @code 750 * boost::asio::ip::tcp::socket socket(io_context); 751 * boost::asio::ip::tcp::endpoint endpoint( 752 * boost::asio::ip::address::from_string("1.2.3.4"), 12345); 753 * socket.connect(endpoint); 754 * @endcode 755 */ connect(const endpoint_type & peer_endpoint)756 void connect(const endpoint_type& peer_endpoint) 757 { 758 boost::system::error_code ec; 759 if (!is_open()) 760 { 761 this->get_service().open(this->get_implementation(), 762 peer_endpoint.protocol(), ec); 763 boost::asio::detail::throw_error(ec, "connect"); 764 } 765 this->get_service().connect(this->get_implementation(), peer_endpoint, ec); 766 boost::asio::detail::throw_error(ec, "connect"); 767 } 768 769 /// Connect the socket to the specified endpoint. 770 /** 771 * This function is used to connect a socket to the specified remote endpoint. 772 * The function call will block until the connection is successfully made or 773 * an error occurs. 774 * 775 * The socket is automatically opened if it is not already open. If the 776 * connect fails, and the socket was automatically opened, the socket is 777 * not returned to the closed state. 778 * 779 * @param peer_endpoint The remote endpoint to which the socket will be 780 * connected. 781 * 782 * @param ec Set to indicate what error occurred, if any. 783 * 784 * @par Example 785 * @code 786 * boost::asio::ip::tcp::socket socket(io_context); 787 * boost::asio::ip::tcp::endpoint endpoint( 788 * boost::asio::ip::address::from_string("1.2.3.4"), 12345); 789 * boost::system::error_code ec; 790 * socket.connect(endpoint, ec); 791 * if (ec) 792 * { 793 * // An error occurred. 794 * } 795 * @endcode 796 */ connect(const endpoint_type & peer_endpoint,boost::system::error_code & ec)797 BOOST_ASIO_SYNC_OP_VOID connect(const endpoint_type& peer_endpoint, 798 boost::system::error_code& ec) 799 { 800 if (!is_open()) 801 { 802 this->get_service().open(this->get_implementation(), 803 peer_endpoint.protocol(), ec); 804 if (ec) 805 { 806 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); 807 } 808 } 809 810 this->get_service().connect(this->get_implementation(), peer_endpoint, ec); 811 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); 812 } 813 814 /// Start an asynchronous connect. 815 /** 816 * This function is used to asynchronously connect a socket to the specified 817 * remote endpoint. The function call always returns immediately. 818 * 819 * The socket is automatically opened if it is not already open. If the 820 * connect fails, and the socket was automatically opened, the socket is 821 * not returned to the closed state. 822 * 823 * @param peer_endpoint The remote endpoint to which the socket will be 824 * connected. Copies will be made of the endpoint object as required. 825 * 826 * @param handler The handler to be called when the connection operation 827 * completes. Copies will be made of the handler as required. The function 828 * signature of the handler must be: 829 * @code void handler( 830 * const boost::system::error_code& error // Result of operation 831 * ); @endcode 832 * Regardless of whether the asynchronous operation completes immediately or 833 * not, the handler will not be invoked from within this function. Invocation 834 * of the handler will be performed in a manner equivalent to using 835 * boost::asio::io_context::post(). 836 * 837 * @par Example 838 * @code 839 * void connect_handler(const boost::system::error_code& error) 840 * { 841 * if (!error) 842 * { 843 * // Connect succeeded. 844 * } 845 * } 846 * 847 * ... 848 * 849 * boost::asio::ip::tcp::socket socket(io_context); 850 * boost::asio::ip::tcp::endpoint endpoint( 851 * boost::asio::ip::address::from_string("1.2.3.4"), 12345); 852 * socket.async_connect(endpoint, connect_handler); 853 * @endcode 854 */ 855 template <typename ConnectHandler> BOOST_ASIO_INITFN_RESULT_TYPE(ConnectHandler,void (boost::system::error_code))856 BOOST_ASIO_INITFN_RESULT_TYPE(ConnectHandler, 857 void (boost::system::error_code)) 858 async_connect(const endpoint_type& peer_endpoint, 859 BOOST_ASIO_MOVE_ARG(ConnectHandler) handler) 860 { 861 // If you get an error on the following line it means that your handler does 862 // not meet the documented type requirements for a ConnectHandler. 863 BOOST_ASIO_CONNECT_HANDLER_CHECK(ConnectHandler, handler) type_check; 864 865 if (!is_open()) 866 { 867 boost::system::error_code ec; 868 const protocol_type protocol = peer_endpoint.protocol(); 869 this->get_service().open(this->get_implementation(), protocol, ec); 870 if (ec) 871 { 872 async_completion<ConnectHandler, 873 void (boost::system::error_code)> init(handler); 874 875 boost::asio::post(this->get_executor(), 876 boost::asio::detail::bind_handler( 877 BOOST_ASIO_MOVE_CAST(BOOST_ASIO_HANDLER_TYPE( 878 ConnectHandler, void (boost::system::error_code)))( 879 init.completion_handler), ec)); 880 881 return init.result.get(); 882 } 883 } 884 885 #if defined(BOOST_ASIO_ENABLE_OLD_SERVICES) 886 return this->get_service().async_connect(this->get_implementation(), 887 peer_endpoint, BOOST_ASIO_MOVE_CAST(ConnectHandler)(handler)); 888 #else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) 889 async_completion<ConnectHandler, 890 void (boost::system::error_code)> init(handler); 891 892 this->get_service().async_connect( 893 this->get_implementation(), peer_endpoint, init.completion_handler); 894 895 return init.result.get(); 896 #endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) 897 } 898 899 /// Set an option on the socket. 900 /** 901 * This function is used to set an option on the socket. 902 * 903 * @param option The new option value to be set on the socket. 904 * 905 * @throws boost::system::system_error Thrown on failure. 906 * 907 * @sa SettableSocketOption @n 908 * boost::asio::socket_base::broadcast @n 909 * boost::asio::socket_base::do_not_route @n 910 * boost::asio::socket_base::keep_alive @n 911 * boost::asio::socket_base::linger @n 912 * boost::asio::socket_base::receive_buffer_size @n 913 * boost::asio::socket_base::receive_low_watermark @n 914 * boost::asio::socket_base::reuse_address @n 915 * boost::asio::socket_base::send_buffer_size @n 916 * boost::asio::socket_base::send_low_watermark @n 917 * boost::asio::ip::multicast::join_group @n 918 * boost::asio::ip::multicast::leave_group @n 919 * boost::asio::ip::multicast::enable_loopback @n 920 * boost::asio::ip::multicast::outbound_interface @n 921 * boost::asio::ip::multicast::hops @n 922 * boost::asio::ip::tcp::no_delay 923 * 924 * @par Example 925 * Setting the IPPROTO_TCP/TCP_NODELAY option: 926 * @code 927 * boost::asio::ip::tcp::socket socket(io_context); 928 * ... 929 * boost::asio::ip::tcp::no_delay option(true); 930 * socket.set_option(option); 931 * @endcode 932 */ 933 template <typename SettableSocketOption> set_option(const SettableSocketOption & option)934 void set_option(const SettableSocketOption& option) 935 { 936 boost::system::error_code ec; 937 this->get_service().set_option(this->get_implementation(), option, ec); 938 boost::asio::detail::throw_error(ec, "set_option"); 939 } 940 941 /// Set an option on the socket. 942 /** 943 * This function is used to set an option on the socket. 944 * 945 * @param option The new option value to be set on the socket. 946 * 947 * @param ec Set to indicate what error occurred, if any. 948 * 949 * @sa SettableSocketOption @n 950 * boost::asio::socket_base::broadcast @n 951 * boost::asio::socket_base::do_not_route @n 952 * boost::asio::socket_base::keep_alive @n 953 * boost::asio::socket_base::linger @n 954 * boost::asio::socket_base::receive_buffer_size @n 955 * boost::asio::socket_base::receive_low_watermark @n 956 * boost::asio::socket_base::reuse_address @n 957 * boost::asio::socket_base::send_buffer_size @n 958 * boost::asio::socket_base::send_low_watermark @n 959 * boost::asio::ip::multicast::join_group @n 960 * boost::asio::ip::multicast::leave_group @n 961 * boost::asio::ip::multicast::enable_loopback @n 962 * boost::asio::ip::multicast::outbound_interface @n 963 * boost::asio::ip::multicast::hops @n 964 * boost::asio::ip::tcp::no_delay 965 * 966 * @par Example 967 * Setting the IPPROTO_TCP/TCP_NODELAY option: 968 * @code 969 * boost::asio::ip::tcp::socket socket(io_context); 970 * ... 971 * boost::asio::ip::tcp::no_delay option(true); 972 * boost::system::error_code ec; 973 * socket.set_option(option, ec); 974 * if (ec) 975 * { 976 * // An error occurred. 977 * } 978 * @endcode 979 */ 980 template <typename SettableSocketOption> set_option(const SettableSocketOption & option,boost::system::error_code & ec)981 BOOST_ASIO_SYNC_OP_VOID set_option(const SettableSocketOption& option, 982 boost::system::error_code& ec) 983 { 984 this->get_service().set_option(this->get_implementation(), option, ec); 985 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); 986 } 987 988 /// Get an option from the socket. 989 /** 990 * This function is used to get the current value of an option on the socket. 991 * 992 * @param option The option value to be obtained from the socket. 993 * 994 * @throws boost::system::system_error Thrown on failure. 995 * 996 * @sa GettableSocketOption @n 997 * boost::asio::socket_base::broadcast @n 998 * boost::asio::socket_base::do_not_route @n 999 * boost::asio::socket_base::keep_alive @n 1000 * boost::asio::socket_base::linger @n 1001 * boost::asio::socket_base::receive_buffer_size @n 1002 * boost::asio::socket_base::receive_low_watermark @n 1003 * boost::asio::socket_base::reuse_address @n 1004 * boost::asio::socket_base::send_buffer_size @n 1005 * boost::asio::socket_base::send_low_watermark @n 1006 * boost::asio::ip::multicast::join_group @n 1007 * boost::asio::ip::multicast::leave_group @n 1008 * boost::asio::ip::multicast::enable_loopback @n 1009 * boost::asio::ip::multicast::outbound_interface @n 1010 * boost::asio::ip::multicast::hops @n 1011 * boost::asio::ip::tcp::no_delay 1012 * 1013 * @par Example 1014 * Getting the value of the SOL_SOCKET/SO_KEEPALIVE option: 1015 * @code 1016 * boost::asio::ip::tcp::socket socket(io_context); 1017 * ... 1018 * boost::asio::ip::tcp::socket::keep_alive option; 1019 * socket.get_option(option); 1020 * bool is_set = option.value(); 1021 * @endcode 1022 */ 1023 template <typename GettableSocketOption> get_option(GettableSocketOption & option) const1024 void get_option(GettableSocketOption& option) const 1025 { 1026 boost::system::error_code ec; 1027 this->get_service().get_option(this->get_implementation(), option, ec); 1028 boost::asio::detail::throw_error(ec, "get_option"); 1029 } 1030 1031 /// Get an option from the socket. 1032 /** 1033 * This function is used to get the current value of an option on the socket. 1034 * 1035 * @param option The option value to be obtained from the socket. 1036 * 1037 * @param ec Set to indicate what error occurred, if any. 1038 * 1039 * @sa GettableSocketOption @n 1040 * boost::asio::socket_base::broadcast @n 1041 * boost::asio::socket_base::do_not_route @n 1042 * boost::asio::socket_base::keep_alive @n 1043 * boost::asio::socket_base::linger @n 1044 * boost::asio::socket_base::receive_buffer_size @n 1045 * boost::asio::socket_base::receive_low_watermark @n 1046 * boost::asio::socket_base::reuse_address @n 1047 * boost::asio::socket_base::send_buffer_size @n 1048 * boost::asio::socket_base::send_low_watermark @n 1049 * boost::asio::ip::multicast::join_group @n 1050 * boost::asio::ip::multicast::leave_group @n 1051 * boost::asio::ip::multicast::enable_loopback @n 1052 * boost::asio::ip::multicast::outbound_interface @n 1053 * boost::asio::ip::multicast::hops @n 1054 * boost::asio::ip::tcp::no_delay 1055 * 1056 * @par Example 1057 * Getting the value of the SOL_SOCKET/SO_KEEPALIVE option: 1058 * @code 1059 * boost::asio::ip::tcp::socket socket(io_context); 1060 * ... 1061 * boost::asio::ip::tcp::socket::keep_alive option; 1062 * boost::system::error_code ec; 1063 * socket.get_option(option, ec); 1064 * if (ec) 1065 * { 1066 * // An error occurred. 1067 * } 1068 * bool is_set = option.value(); 1069 * @endcode 1070 */ 1071 template <typename GettableSocketOption> get_option(GettableSocketOption & option,boost::system::error_code & ec) const1072 BOOST_ASIO_SYNC_OP_VOID get_option(GettableSocketOption& option, 1073 boost::system::error_code& ec) const 1074 { 1075 this->get_service().get_option(this->get_implementation(), option, ec); 1076 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); 1077 } 1078 1079 /// Perform an IO control command on the socket. 1080 /** 1081 * This function is used to execute an IO control command on the socket. 1082 * 1083 * @param command The IO control command to be performed on the socket. 1084 * 1085 * @throws boost::system::system_error Thrown on failure. 1086 * 1087 * @sa IoControlCommand @n 1088 * boost::asio::socket_base::bytes_readable @n 1089 * boost::asio::socket_base::non_blocking_io 1090 * 1091 * @par Example 1092 * Getting the number of bytes ready to read: 1093 * @code 1094 * boost::asio::ip::tcp::socket socket(io_context); 1095 * ... 1096 * boost::asio::ip::tcp::socket::bytes_readable command; 1097 * socket.io_control(command); 1098 * std::size_t bytes_readable = command.get(); 1099 * @endcode 1100 */ 1101 template <typename IoControlCommand> io_control(IoControlCommand & command)1102 void io_control(IoControlCommand& command) 1103 { 1104 boost::system::error_code ec; 1105 this->get_service().io_control(this->get_implementation(), command, ec); 1106 boost::asio::detail::throw_error(ec, "io_control"); 1107 } 1108 1109 /// Perform an IO control command on the socket. 1110 /** 1111 * This function is used to execute an IO control command on the socket. 1112 * 1113 * @param command The IO control command to be performed on the socket. 1114 * 1115 * @param ec Set to indicate what error occurred, if any. 1116 * 1117 * @sa IoControlCommand @n 1118 * boost::asio::socket_base::bytes_readable @n 1119 * boost::asio::socket_base::non_blocking_io 1120 * 1121 * @par Example 1122 * Getting the number of bytes ready to read: 1123 * @code 1124 * boost::asio::ip::tcp::socket socket(io_context); 1125 * ... 1126 * boost::asio::ip::tcp::socket::bytes_readable command; 1127 * boost::system::error_code ec; 1128 * socket.io_control(command, ec); 1129 * if (ec) 1130 * { 1131 * // An error occurred. 1132 * } 1133 * std::size_t bytes_readable = command.get(); 1134 * @endcode 1135 */ 1136 template <typename IoControlCommand> io_control(IoControlCommand & command,boost::system::error_code & ec)1137 BOOST_ASIO_SYNC_OP_VOID io_control(IoControlCommand& command, 1138 boost::system::error_code& ec) 1139 { 1140 this->get_service().io_control(this->get_implementation(), command, ec); 1141 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); 1142 } 1143 1144 /// Gets the non-blocking mode of the socket. 1145 /** 1146 * @returns @c true if the socket's synchronous operations will fail with 1147 * boost::asio::error::would_block if they are unable to perform the requested 1148 * operation immediately. If @c false, synchronous operations will block 1149 * until complete. 1150 * 1151 * @note The non-blocking mode has no effect on the behaviour of asynchronous 1152 * operations. Asynchronous operations will never fail with the error 1153 * boost::asio::error::would_block. 1154 */ non_blocking() const1155 bool non_blocking() const 1156 { 1157 return this->get_service().non_blocking(this->get_implementation()); 1158 } 1159 1160 /// Sets the non-blocking mode of the socket. 1161 /** 1162 * @param mode If @c true, the socket's synchronous operations will fail with 1163 * boost::asio::error::would_block if they are unable to perform the requested 1164 * operation immediately. If @c false, synchronous operations will block 1165 * until complete. 1166 * 1167 * @throws boost::system::system_error Thrown on failure. 1168 * 1169 * @note The non-blocking mode has no effect on the behaviour of asynchronous 1170 * operations. Asynchronous operations will never fail with the error 1171 * boost::asio::error::would_block. 1172 */ non_blocking(bool mode)1173 void non_blocking(bool mode) 1174 { 1175 boost::system::error_code ec; 1176 this->get_service().non_blocking(this->get_implementation(), mode, ec); 1177 boost::asio::detail::throw_error(ec, "non_blocking"); 1178 } 1179 1180 /// Sets the non-blocking mode of the socket. 1181 /** 1182 * @param mode If @c true, the socket's synchronous operations will fail with 1183 * boost::asio::error::would_block if they are unable to perform the requested 1184 * operation immediately. If @c false, synchronous operations will block 1185 * until complete. 1186 * 1187 * @param ec Set to indicate what error occurred, if any. 1188 * 1189 * @note The non-blocking mode has no effect on the behaviour of asynchronous 1190 * operations. Asynchronous operations will never fail with the error 1191 * boost::asio::error::would_block. 1192 */ non_blocking(bool mode,boost::system::error_code & ec)1193 BOOST_ASIO_SYNC_OP_VOID non_blocking( 1194 bool mode, boost::system::error_code& ec) 1195 { 1196 this->get_service().non_blocking(this->get_implementation(), mode, ec); 1197 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); 1198 } 1199 1200 /// Gets the non-blocking mode of the native socket implementation. 1201 /** 1202 * This function is used to retrieve the non-blocking mode of the underlying 1203 * native socket. This mode has no effect on the behaviour of the socket 1204 * object's synchronous operations. 1205 * 1206 * @returns @c true if the underlying socket is in non-blocking mode and 1207 * direct system calls may fail with boost::asio::error::would_block (or the 1208 * equivalent system error). 1209 * 1210 * @note The current non-blocking mode is cached by the socket object. 1211 * Consequently, the return value may be incorrect if the non-blocking mode 1212 * was set directly on the native socket. 1213 * 1214 * @par Example 1215 * This function is intended to allow the encapsulation of arbitrary 1216 * non-blocking system calls as asynchronous operations, in a way that is 1217 * transparent to the user of the socket object. The following example 1218 * illustrates how Linux's @c sendfile system call might be encapsulated: 1219 * @code template <typename Handler> 1220 * struct sendfile_op 1221 * { 1222 * tcp::socket& sock_; 1223 * int fd_; 1224 * Handler handler_; 1225 * off_t offset_; 1226 * std::size_t total_bytes_transferred_; 1227 * 1228 * // Function call operator meeting WriteHandler requirements. 1229 * // Used as the handler for the async_write_some operation. 1230 * void operator()(boost::system::error_code ec, std::size_t) 1231 * { 1232 * // Put the underlying socket into non-blocking mode. 1233 * if (!ec) 1234 * if (!sock_.native_non_blocking()) 1235 * sock_.native_non_blocking(true, ec); 1236 * 1237 * if (!ec) 1238 * { 1239 * for (;;) 1240 * { 1241 * // Try the system call. 1242 * errno = 0; 1243 * int n = ::sendfile(sock_.native_handle(), fd_, &offset_, 65536); 1244 * ec = boost::system::error_code(n < 0 ? errno : 0, 1245 * boost::asio::error::get_system_category()); 1246 * total_bytes_transferred_ += ec ? 0 : n; 1247 * 1248 * // Retry operation immediately if interrupted by signal. 1249 * if (ec == boost::asio::error::interrupted) 1250 * continue; 1251 * 1252 * // Check if we need to run the operation again. 1253 * if (ec == boost::asio::error::would_block 1254 * || ec == boost::asio::error::try_again) 1255 * { 1256 * // We have to wait for the socket to become ready again. 1257 * sock_.async_wait(tcp::socket::wait_write, *this); 1258 * return; 1259 * } 1260 * 1261 * if (ec || n == 0) 1262 * { 1263 * // An error occurred, or we have reached the end of the file. 1264 * // Either way we must exit the loop so we can call the handler. 1265 * break; 1266 * } 1267 * 1268 * // Loop around to try calling sendfile again. 1269 * } 1270 * } 1271 * 1272 * // Pass result back to user's handler. 1273 * handler_(ec, total_bytes_transferred_); 1274 * } 1275 * }; 1276 * 1277 * template <typename Handler> 1278 * void async_sendfile(tcp::socket& sock, int fd, Handler h) 1279 * { 1280 * sendfile_op<Handler> op = { sock, fd, h, 0, 0 }; 1281 * sock.async_wait(tcp::socket::wait_write, op); 1282 * } @endcode 1283 */ native_non_blocking() const1284 bool native_non_blocking() const 1285 { 1286 return this->get_service().native_non_blocking(this->get_implementation()); 1287 } 1288 1289 /// Sets the non-blocking mode of the native socket implementation. 1290 /** 1291 * This function is used to modify the non-blocking mode of the underlying 1292 * native socket. It has no effect on the behaviour of the socket object's 1293 * synchronous operations. 1294 * 1295 * @param mode If @c true, the underlying socket is put into non-blocking 1296 * mode and direct system calls may fail with boost::asio::error::would_block 1297 * (or the equivalent system error). 1298 * 1299 * @throws boost::system::system_error Thrown on failure. If the @c mode is 1300 * @c false, but the current value of @c non_blocking() is @c true, this 1301 * function fails with boost::asio::error::invalid_argument, as the 1302 * combination does not make sense. 1303 * 1304 * @par Example 1305 * This function is intended to allow the encapsulation of arbitrary 1306 * non-blocking system calls as asynchronous operations, in a way that is 1307 * transparent to the user of the socket object. The following example 1308 * illustrates how Linux's @c sendfile system call might be encapsulated: 1309 * @code template <typename Handler> 1310 * struct sendfile_op 1311 * { 1312 * tcp::socket& sock_; 1313 * int fd_; 1314 * Handler handler_; 1315 * off_t offset_; 1316 * std::size_t total_bytes_transferred_; 1317 * 1318 * // Function call operator meeting WriteHandler requirements. 1319 * // Used as the handler for the async_write_some operation. 1320 * void operator()(boost::system::error_code ec, std::size_t) 1321 * { 1322 * // Put the underlying socket into non-blocking mode. 1323 * if (!ec) 1324 * if (!sock_.native_non_blocking()) 1325 * sock_.native_non_blocking(true, ec); 1326 * 1327 * if (!ec) 1328 * { 1329 * for (;;) 1330 * { 1331 * // Try the system call. 1332 * errno = 0; 1333 * int n = ::sendfile(sock_.native_handle(), fd_, &offset_, 65536); 1334 * ec = boost::system::error_code(n < 0 ? errno : 0, 1335 * boost::asio::error::get_system_category()); 1336 * total_bytes_transferred_ += ec ? 0 : n; 1337 * 1338 * // Retry operation immediately if interrupted by signal. 1339 * if (ec == boost::asio::error::interrupted) 1340 * continue; 1341 * 1342 * // Check if we need to run the operation again. 1343 * if (ec == boost::asio::error::would_block 1344 * || ec == boost::asio::error::try_again) 1345 * { 1346 * // We have to wait for the socket to become ready again. 1347 * sock_.async_wait(tcp::socket::wait_write, *this); 1348 * return; 1349 * } 1350 * 1351 * if (ec || n == 0) 1352 * { 1353 * // An error occurred, or we have reached the end of the file. 1354 * // Either way we must exit the loop so we can call the handler. 1355 * break; 1356 * } 1357 * 1358 * // Loop around to try calling sendfile again. 1359 * } 1360 * } 1361 * 1362 * // Pass result back to user's handler. 1363 * handler_(ec, total_bytes_transferred_); 1364 * } 1365 * }; 1366 * 1367 * template <typename Handler> 1368 * void async_sendfile(tcp::socket& sock, int fd, Handler h) 1369 * { 1370 * sendfile_op<Handler> op = { sock, fd, h, 0, 0 }; 1371 * sock.async_wait(tcp::socket::wait_write, op); 1372 * } @endcode 1373 */ native_non_blocking(bool mode)1374 void native_non_blocking(bool mode) 1375 { 1376 boost::system::error_code ec; 1377 this->get_service().native_non_blocking( 1378 this->get_implementation(), mode, ec); 1379 boost::asio::detail::throw_error(ec, "native_non_blocking"); 1380 } 1381 1382 /// Sets the non-blocking mode of the native socket implementation. 1383 /** 1384 * This function is used to modify the non-blocking mode of the underlying 1385 * native socket. It has no effect on the behaviour of the socket object's 1386 * synchronous operations. 1387 * 1388 * @param mode If @c true, the underlying socket is put into non-blocking 1389 * mode and direct system calls may fail with boost::asio::error::would_block 1390 * (or the equivalent system error). 1391 * 1392 * @param ec Set to indicate what error occurred, if any. If the @c mode is 1393 * @c false, but the current value of @c non_blocking() is @c true, this 1394 * function fails with boost::asio::error::invalid_argument, as the 1395 * combination does not make sense. 1396 * 1397 * @par Example 1398 * This function is intended to allow the encapsulation of arbitrary 1399 * non-blocking system calls as asynchronous operations, in a way that is 1400 * transparent to the user of the socket object. The following example 1401 * illustrates how Linux's @c sendfile system call might be encapsulated: 1402 * @code template <typename Handler> 1403 * struct sendfile_op 1404 * { 1405 * tcp::socket& sock_; 1406 * int fd_; 1407 * Handler handler_; 1408 * off_t offset_; 1409 * std::size_t total_bytes_transferred_; 1410 * 1411 * // Function call operator meeting WriteHandler requirements. 1412 * // Used as the handler for the async_write_some operation. 1413 * void operator()(boost::system::error_code ec, std::size_t) 1414 * { 1415 * // Put the underlying socket into non-blocking mode. 1416 * if (!ec) 1417 * if (!sock_.native_non_blocking()) 1418 * sock_.native_non_blocking(true, ec); 1419 * 1420 * if (!ec) 1421 * { 1422 * for (;;) 1423 * { 1424 * // Try the system call. 1425 * errno = 0; 1426 * int n = ::sendfile(sock_.native_handle(), fd_, &offset_, 65536); 1427 * ec = boost::system::error_code(n < 0 ? errno : 0, 1428 * boost::asio::error::get_system_category()); 1429 * total_bytes_transferred_ += ec ? 0 : n; 1430 * 1431 * // Retry operation immediately if interrupted by signal. 1432 * if (ec == boost::asio::error::interrupted) 1433 * continue; 1434 * 1435 * // Check if we need to run the operation again. 1436 * if (ec == boost::asio::error::would_block 1437 * || ec == boost::asio::error::try_again) 1438 * { 1439 * // We have to wait for the socket to become ready again. 1440 * sock_.async_wait(tcp::socket::wait_write, *this); 1441 * return; 1442 * } 1443 * 1444 * if (ec || n == 0) 1445 * { 1446 * // An error occurred, or we have reached the end of the file. 1447 * // Either way we must exit the loop so we can call the handler. 1448 * break; 1449 * } 1450 * 1451 * // Loop around to try calling sendfile again. 1452 * } 1453 * } 1454 * 1455 * // Pass result back to user's handler. 1456 * handler_(ec, total_bytes_transferred_); 1457 * } 1458 * }; 1459 * 1460 * template <typename Handler> 1461 * void async_sendfile(tcp::socket& sock, int fd, Handler h) 1462 * { 1463 * sendfile_op<Handler> op = { sock, fd, h, 0, 0 }; 1464 * sock.async_wait(tcp::socket::wait_write, op); 1465 * } @endcode 1466 */ native_non_blocking(bool mode,boost::system::error_code & ec)1467 BOOST_ASIO_SYNC_OP_VOID native_non_blocking( 1468 bool mode, boost::system::error_code& ec) 1469 { 1470 this->get_service().native_non_blocking( 1471 this->get_implementation(), mode, ec); 1472 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); 1473 } 1474 1475 /// Get the local endpoint of the socket. 1476 /** 1477 * This function is used to obtain the locally bound endpoint of the socket. 1478 * 1479 * @returns An object that represents the local endpoint of the socket. 1480 * 1481 * @throws boost::system::system_error Thrown on failure. 1482 * 1483 * @par Example 1484 * @code 1485 * boost::asio::ip::tcp::socket socket(io_context); 1486 * ... 1487 * boost::asio::ip::tcp::endpoint endpoint = socket.local_endpoint(); 1488 * @endcode 1489 */ local_endpoint() const1490 endpoint_type local_endpoint() const 1491 { 1492 boost::system::error_code ec; 1493 endpoint_type ep = this->get_service().local_endpoint( 1494 this->get_implementation(), ec); 1495 boost::asio::detail::throw_error(ec, "local_endpoint"); 1496 return ep; 1497 } 1498 1499 /// Get the local endpoint of the socket. 1500 /** 1501 * This function is used to obtain the locally bound endpoint of the socket. 1502 * 1503 * @param ec Set to indicate what error occurred, if any. 1504 * 1505 * @returns An object that represents the local endpoint of the socket. 1506 * Returns a default-constructed endpoint object if an error occurred. 1507 * 1508 * @par Example 1509 * @code 1510 * boost::asio::ip::tcp::socket socket(io_context); 1511 * ... 1512 * boost::system::error_code ec; 1513 * boost::asio::ip::tcp::endpoint endpoint = socket.local_endpoint(ec); 1514 * if (ec) 1515 * { 1516 * // An error occurred. 1517 * } 1518 * @endcode 1519 */ local_endpoint(boost::system::error_code & ec) const1520 endpoint_type local_endpoint(boost::system::error_code& ec) const 1521 { 1522 return this->get_service().local_endpoint(this->get_implementation(), ec); 1523 } 1524 1525 /// Get the remote endpoint of the socket. 1526 /** 1527 * This function is used to obtain the remote endpoint of the socket. 1528 * 1529 * @returns An object that represents the remote endpoint of the socket. 1530 * 1531 * @throws boost::system::system_error Thrown on failure. 1532 * 1533 * @par Example 1534 * @code 1535 * boost::asio::ip::tcp::socket socket(io_context); 1536 * ... 1537 * boost::asio::ip::tcp::endpoint endpoint = socket.remote_endpoint(); 1538 * @endcode 1539 */ remote_endpoint() const1540 endpoint_type remote_endpoint() const 1541 { 1542 boost::system::error_code ec; 1543 endpoint_type ep = this->get_service().remote_endpoint( 1544 this->get_implementation(), ec); 1545 boost::asio::detail::throw_error(ec, "remote_endpoint"); 1546 return ep; 1547 } 1548 1549 /// Get the remote endpoint of the socket. 1550 /** 1551 * This function is used to obtain the remote endpoint of the socket. 1552 * 1553 * @param ec Set to indicate what error occurred, if any. 1554 * 1555 * @returns An object that represents the remote endpoint of the socket. 1556 * Returns a default-constructed endpoint object if an error occurred. 1557 * 1558 * @par Example 1559 * @code 1560 * boost::asio::ip::tcp::socket socket(io_context); 1561 * ... 1562 * boost::system::error_code ec; 1563 * boost::asio::ip::tcp::endpoint endpoint = socket.remote_endpoint(ec); 1564 * if (ec) 1565 * { 1566 * // An error occurred. 1567 * } 1568 * @endcode 1569 */ remote_endpoint(boost::system::error_code & ec) const1570 endpoint_type remote_endpoint(boost::system::error_code& ec) const 1571 { 1572 return this->get_service().remote_endpoint(this->get_implementation(), ec); 1573 } 1574 1575 /// Disable sends or receives on the socket. 1576 /** 1577 * This function is used to disable send operations, receive operations, or 1578 * both. 1579 * 1580 * @param what Determines what types of operation will no longer be allowed. 1581 * 1582 * @throws boost::system::system_error Thrown on failure. 1583 * 1584 * @par Example 1585 * Shutting down the send side of the socket: 1586 * @code 1587 * boost::asio::ip::tcp::socket socket(io_context); 1588 * ... 1589 * socket.shutdown(boost::asio::ip::tcp::socket::shutdown_send); 1590 * @endcode 1591 */ shutdown(shutdown_type what)1592 void shutdown(shutdown_type what) 1593 { 1594 boost::system::error_code ec; 1595 this->get_service().shutdown(this->get_implementation(), what, ec); 1596 boost::asio::detail::throw_error(ec, "shutdown"); 1597 } 1598 1599 /// Disable sends or receives on the socket. 1600 /** 1601 * This function is used to disable send operations, receive operations, or 1602 * both. 1603 * 1604 * @param what Determines what types of operation will no longer be allowed. 1605 * 1606 * @param ec Set to indicate what error occurred, if any. 1607 * 1608 * @par Example 1609 * Shutting down the send side of the socket: 1610 * @code 1611 * boost::asio::ip::tcp::socket socket(io_context); 1612 * ... 1613 * boost::system::error_code ec; 1614 * socket.shutdown(boost::asio::ip::tcp::socket::shutdown_send, ec); 1615 * if (ec) 1616 * { 1617 * // An error occurred. 1618 * } 1619 * @endcode 1620 */ shutdown(shutdown_type what,boost::system::error_code & ec)1621 BOOST_ASIO_SYNC_OP_VOID shutdown(shutdown_type what, 1622 boost::system::error_code& ec) 1623 { 1624 this->get_service().shutdown(this->get_implementation(), what, ec); 1625 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); 1626 } 1627 1628 /// Wait for the socket to become ready to read, ready to write, or to have 1629 /// pending error conditions. 1630 /** 1631 * This function is used to perform a blocking wait for a socket to enter 1632 * a ready to read, write or error condition state. 1633 * 1634 * @param w Specifies the desired socket state. 1635 * 1636 * @par Example 1637 * Waiting for a socket to become readable. 1638 * @code 1639 * boost::asio::ip::tcp::socket socket(io_context); 1640 * ... 1641 * socket.wait(boost::asio::ip::tcp::socket::wait_read); 1642 * @endcode 1643 */ wait(wait_type w)1644 void wait(wait_type w) 1645 { 1646 boost::system::error_code ec; 1647 this->get_service().wait(this->get_implementation(), w, ec); 1648 boost::asio::detail::throw_error(ec, "wait"); 1649 } 1650 1651 /// Wait for the socket to become ready to read, ready to write, or to have 1652 /// pending error conditions. 1653 /** 1654 * This function is used to perform a blocking wait for a socket to enter 1655 * a ready to read, write or error condition state. 1656 * 1657 * @param w Specifies the desired socket state. 1658 * 1659 * @param ec Set to indicate what error occurred, if any. 1660 * 1661 * @par Example 1662 * Waiting for a socket to become readable. 1663 * @code 1664 * boost::asio::ip::tcp::socket socket(io_context); 1665 * ... 1666 * boost::system::error_code ec; 1667 * socket.wait(boost::asio::ip::tcp::socket::wait_read, ec); 1668 * @endcode 1669 */ wait(wait_type w,boost::system::error_code & ec)1670 BOOST_ASIO_SYNC_OP_VOID wait(wait_type w, boost::system::error_code& ec) 1671 { 1672 this->get_service().wait(this->get_implementation(), w, ec); 1673 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); 1674 } 1675 1676 /// Asynchronously wait for the socket to become ready to read, ready to 1677 /// write, or to have pending error conditions. 1678 /** 1679 * This function is used to perform an asynchronous wait for a socket to enter 1680 * a ready to read, write or error condition state. 1681 * 1682 * @param w Specifies the desired socket state. 1683 * 1684 * @param handler The handler to be called when the wait operation completes. 1685 * Copies will be made of the handler as required. The function signature of 1686 * the handler must be: 1687 * @code void handler( 1688 * const boost::system::error_code& error // Result of operation 1689 * ); @endcode 1690 * Regardless of whether the asynchronous operation completes immediately or 1691 * not, the handler will not be invoked from within this function. Invocation 1692 * of the handler will be performed in a manner equivalent to using 1693 * boost::asio::io_context::post(). 1694 * 1695 * @par Example 1696 * @code 1697 * void wait_handler(const boost::system::error_code& error) 1698 * { 1699 * if (!error) 1700 * { 1701 * // Wait succeeded. 1702 * } 1703 * } 1704 * 1705 * ... 1706 * 1707 * boost::asio::ip::tcp::socket socket(io_context); 1708 * ... 1709 * socket.async_wait(boost::asio::ip::tcp::socket::wait_read, wait_handler); 1710 * @endcode 1711 */ 1712 template <typename WaitHandler> BOOST_ASIO_INITFN_RESULT_TYPE(WaitHandler,void (boost::system::error_code))1713 BOOST_ASIO_INITFN_RESULT_TYPE(WaitHandler, 1714 void (boost::system::error_code)) 1715 async_wait(wait_type w, BOOST_ASIO_MOVE_ARG(WaitHandler) handler) 1716 { 1717 // If you get an error on the following line it means that your handler does 1718 // not meet the documented type requirements for a WaitHandler. 1719 BOOST_ASIO_WAIT_HANDLER_CHECK(WaitHandler, handler) type_check; 1720 1721 #if defined(BOOST_ASIO_ENABLE_OLD_SERVICES) 1722 return this->get_service().async_wait(this->get_implementation(), 1723 w, BOOST_ASIO_MOVE_CAST(WaitHandler)(handler)); 1724 #else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) 1725 async_completion<WaitHandler, 1726 void (boost::system::error_code)> init(handler); 1727 1728 this->get_service().async_wait(this->get_implementation(), 1729 w, init.completion_handler); 1730 1731 return init.result.get(); 1732 #endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) 1733 } 1734 1735 protected: 1736 /// Protected destructor to prevent deletion through this type. 1737 /** 1738 * This function destroys the socket, cancelling any outstanding asynchronous 1739 * operations associated with the socket as if by calling @c cancel. 1740 */ ~basic_socket_ext()1741 ~basic_socket_ext() 1742 { 1743 } 1744 1745 private: 1746 // Disallow copying and assignment. 1747 basic_socket_ext(const basic_socket_ext&) BOOST_ASIO_DELETED; 1748 basic_socket_ext& operator=(const basic_socket_ext&) BOOST_ASIO_DELETED; 1749 }; 1750 1751 } // namespace asio 1752 } // namespace boost 1753 1754 #include <boost/asio/detail/pop_options.hpp> 1755 1756 #if !defined(BOOST_ASIO_ENABLE_OLD_SERVICES) 1757 # undef BOOST_ASIO_SVC_T 1758 #endif // !defined(BOOST_ASIO_ENABLE_OLD_SERVICES) 1759 1760 #endif // BOOST_ASIO_BASIC_SOCKET_EXT_HPP 1761