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