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