|
||||
File indexing completed on 2025-01-18 09:29:05
0001 // 0002 // basic_socket.hpp 0003 // ~~~~~~~~~~~~~~~~ 0004 // 0005 // Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) 0006 // 0007 // Distributed under the Boost Software License, Version 1.0. (See accompanying 0008 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 0009 // 0010 0011 #ifndef BOOST_ASIO_BASIC_SOCKET_HPP 0012 #define BOOST_ASIO_BASIC_SOCKET_HPP 0013 0014 #if defined(_MSC_VER) && (_MSC_VER >= 1200) 0015 # pragma once 0016 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) 0017 0018 #include <utility> 0019 #include <boost/asio/any_io_executor.hpp> 0020 #include <boost/asio/detail/config.hpp> 0021 #include <boost/asio/async_result.hpp> 0022 #include <boost/asio/detail/handler_type_requirements.hpp> 0023 #include <boost/asio/detail/io_object_impl.hpp> 0024 #include <boost/asio/detail/non_const_lvalue.hpp> 0025 #include <boost/asio/detail/throw_error.hpp> 0026 #include <boost/asio/detail/type_traits.hpp> 0027 #include <boost/asio/error.hpp> 0028 #include <boost/asio/execution_context.hpp> 0029 #include <boost/asio/post.hpp> 0030 #include <boost/asio/socket_base.hpp> 0031 0032 #if defined(BOOST_ASIO_WINDOWS_RUNTIME) 0033 # include <boost/asio/detail/null_socket_service.hpp> 0034 #elif defined(BOOST_ASIO_HAS_IOCP) 0035 # include <boost/asio/detail/win_iocp_socket_service.hpp> 0036 #elif defined(BOOST_ASIO_HAS_IO_URING_AS_DEFAULT) 0037 # include <boost/asio/detail/io_uring_socket_service.hpp> 0038 #else 0039 # include <boost/asio/detail/reactive_socket_service.hpp> 0040 #endif 0041 0042 #include <boost/asio/detail/push_options.hpp> 0043 0044 namespace boost { 0045 namespace asio { 0046 0047 #if !defined(BOOST_ASIO_BASIC_SOCKET_FWD_DECL) 0048 #define BOOST_ASIO_BASIC_SOCKET_FWD_DECL 0049 0050 // Forward declaration with defaulted arguments. 0051 template <typename Protocol, typename Executor = any_io_executor> 0052 class basic_socket; 0053 0054 #endif // !defined(BOOST_ASIO_BASIC_SOCKET_FWD_DECL) 0055 0056 /// Provides socket functionality. 0057 /** 0058 * The basic_socket class template provides functionality that is common to both 0059 * stream-oriented and datagram-oriented sockets. 0060 * 0061 * @par Thread Safety 0062 * @e Distinct @e objects: Safe.@n 0063 * @e Shared @e objects: Unsafe. 0064 */ 0065 template <typename Protocol, typename Executor> 0066 class basic_socket 0067 : public socket_base 0068 { 0069 private: 0070 class initiate_async_connect; 0071 class initiate_async_wait; 0072 0073 public: 0074 /// The type of the executor associated with the object. 0075 typedef Executor executor_type; 0076 0077 /// Rebinds the socket type to another executor. 0078 template <typename Executor1> 0079 struct rebind_executor 0080 { 0081 /// The socket type when rebound to the specified executor. 0082 typedef basic_socket<Protocol, Executor1> other; 0083 }; 0084 0085 /// The native representation of a socket. 0086 #if defined(GENERATING_DOCUMENTATION) 0087 typedef implementation_defined native_handle_type; 0088 #elif defined(BOOST_ASIO_WINDOWS_RUNTIME) 0089 typedef typename detail::null_socket_service< 0090 Protocol>::native_handle_type native_handle_type; 0091 #elif defined(BOOST_ASIO_HAS_IOCP) 0092 typedef typename detail::win_iocp_socket_service< 0093 Protocol>::native_handle_type native_handle_type; 0094 #elif defined(BOOST_ASIO_HAS_IO_URING_AS_DEFAULT) 0095 typedef typename detail::io_uring_socket_service< 0096 Protocol>::native_handle_type native_handle_type; 0097 #else 0098 typedef typename detail::reactive_socket_service< 0099 Protocol>::native_handle_type native_handle_type; 0100 #endif 0101 0102 /// The protocol type. 0103 typedef Protocol protocol_type; 0104 0105 /// The endpoint type. 0106 typedef typename Protocol::endpoint endpoint_type; 0107 0108 #if !defined(BOOST_ASIO_NO_EXTENSIONS) 0109 /// A basic_socket is always the lowest layer. 0110 typedef basic_socket<Protocol, Executor> lowest_layer_type; 0111 #endif // !defined(BOOST_ASIO_NO_EXTENSIONS) 0112 0113 /// Construct a basic_socket without opening it. 0114 /** 0115 * This constructor creates a socket without opening it. 0116 * 0117 * @param ex The I/O executor that the socket will use, by default, to 0118 * dispatch handlers for any asynchronous operations performed on the socket. 0119 */ 0120 explicit basic_socket(const executor_type& ex) 0121 : impl_(0, ex) 0122 { 0123 } 0124 0125 /// Construct a basic_socket without opening it. 0126 /** 0127 * This constructor creates a socket without opening it. 0128 * 0129 * @param context An execution context which provides the I/O executor that 0130 * the socket will use, by default, to dispatch handlers for any asynchronous 0131 * operations performed on the socket. 0132 */ 0133 template <typename ExecutionContext> 0134 explicit basic_socket(ExecutionContext& context, 0135 constraint_t< 0136 is_convertible<ExecutionContext&, execution_context&>::value 0137 > = 0) 0138 : impl_(0, 0, context) 0139 { 0140 } 0141 0142 /// Construct and open a basic_socket. 0143 /** 0144 * This constructor creates and opens a socket. 0145 * 0146 * @param ex The I/O executor that the socket will use, by default, to 0147 * dispatch handlers for any asynchronous operations performed on the socket. 0148 * 0149 * @param protocol An object specifying protocol parameters to be used. 0150 * 0151 * @throws boost::system::system_error Thrown on failure. 0152 */ 0153 basic_socket(const executor_type& ex, const protocol_type& protocol) 0154 : impl_(0, ex) 0155 { 0156 boost::system::error_code ec; 0157 impl_.get_service().open(impl_.get_implementation(), protocol, ec); 0158 boost::asio::detail::throw_error(ec, "open"); 0159 } 0160 0161 /// Construct and open a basic_socket. 0162 /** 0163 * This constructor creates and opens a socket. 0164 * 0165 * @param context An execution context which provides the I/O executor that 0166 * the socket will use, by default, to dispatch handlers for any asynchronous 0167 * operations performed on the socket. 0168 * 0169 * @param protocol An object specifying protocol parameters to be used. 0170 * 0171 * @throws boost::system::system_error Thrown on failure. 0172 */ 0173 template <typename ExecutionContext> 0174 basic_socket(ExecutionContext& context, const protocol_type& protocol, 0175 constraint_t< 0176 is_convertible<ExecutionContext&, execution_context&>::value, 0177 defaulted_constraint 0178 > = defaulted_constraint()) 0179 : impl_(0, 0, context) 0180 { 0181 boost::system::error_code ec; 0182 impl_.get_service().open(impl_.get_implementation(), protocol, ec); 0183 boost::asio::detail::throw_error(ec, "open"); 0184 } 0185 0186 /// Construct a basic_socket, opening it and binding it to the given local 0187 /// endpoint. 0188 /** 0189 * This constructor creates a socket and automatically opens it bound to the 0190 * specified endpoint on the local machine. The protocol used is the protocol 0191 * associated with the given endpoint. 0192 * 0193 * @param ex The I/O executor that the socket will use, by default, to 0194 * dispatch handlers for any asynchronous operations performed on the socket. 0195 * 0196 * @param endpoint An endpoint on the local machine to which the socket will 0197 * be bound. 0198 * 0199 * @throws boost::system::system_error Thrown on failure. 0200 */ 0201 basic_socket(const executor_type& ex, const endpoint_type& endpoint) 0202 : impl_(0, ex) 0203 { 0204 boost::system::error_code ec; 0205 const protocol_type protocol = endpoint.protocol(); 0206 impl_.get_service().open(impl_.get_implementation(), protocol, ec); 0207 boost::asio::detail::throw_error(ec, "open"); 0208 impl_.get_service().bind(impl_.get_implementation(), endpoint, ec); 0209 boost::asio::detail::throw_error(ec, "bind"); 0210 } 0211 0212 /// Construct a basic_socket, opening it and binding it to the given local 0213 /// endpoint. 0214 /** 0215 * This constructor creates a socket and automatically opens it bound to the 0216 * specified endpoint on the local machine. The protocol used is the protocol 0217 * associated with the given endpoint. 0218 * 0219 * @param context An execution context which provides the I/O executor that 0220 * the socket will use, by default, to dispatch handlers for any asynchronous 0221 * operations performed on the socket. 0222 * 0223 * @param endpoint An endpoint on the local machine to which the socket will 0224 * be bound. 0225 * 0226 * @throws boost::system::system_error Thrown on failure. 0227 */ 0228 template <typename ExecutionContext> 0229 basic_socket(ExecutionContext& context, const endpoint_type& endpoint, 0230 constraint_t< 0231 is_convertible<ExecutionContext&, execution_context&>::value 0232 > = 0) 0233 : impl_(0, 0, context) 0234 { 0235 boost::system::error_code ec; 0236 const protocol_type protocol = endpoint.protocol(); 0237 impl_.get_service().open(impl_.get_implementation(), protocol, ec); 0238 boost::asio::detail::throw_error(ec, "open"); 0239 impl_.get_service().bind(impl_.get_implementation(), endpoint, ec); 0240 boost::asio::detail::throw_error(ec, "bind"); 0241 } 0242 0243 /// Construct a basic_socket on an existing native socket. 0244 /** 0245 * This constructor creates a socket object to hold an existing native socket. 0246 * 0247 * @param ex The I/O executor that the socket will use, by default, to 0248 * dispatch handlers for any asynchronous operations performed on the socket. 0249 * 0250 * @param protocol An object specifying protocol parameters to be used. 0251 * 0252 * @param native_socket A native socket. 0253 * 0254 * @throws boost::system::system_error Thrown on failure. 0255 */ 0256 basic_socket(const executor_type& ex, const protocol_type& protocol, 0257 const native_handle_type& native_socket) 0258 : impl_(0, ex) 0259 { 0260 boost::system::error_code ec; 0261 impl_.get_service().assign(impl_.get_implementation(), 0262 protocol, native_socket, ec); 0263 boost::asio::detail::throw_error(ec, "assign"); 0264 } 0265 0266 /// Construct a basic_socket on an existing native socket. 0267 /** 0268 * This constructor creates a socket object to hold an existing native socket. 0269 * 0270 * @param context An execution context which provides the I/O executor that 0271 * the socket will use, by default, to dispatch handlers for any asynchronous 0272 * operations performed on the socket. 0273 * 0274 * @param protocol An object specifying protocol parameters to be used. 0275 * 0276 * @param native_socket A native socket. 0277 * 0278 * @throws boost::system::system_error Thrown on failure. 0279 */ 0280 template <typename ExecutionContext> 0281 basic_socket(ExecutionContext& context, const protocol_type& protocol, 0282 const native_handle_type& native_socket, 0283 constraint_t< 0284 is_convertible<ExecutionContext&, execution_context&>::value 0285 > = 0) 0286 : impl_(0, 0, context) 0287 { 0288 boost::system::error_code ec; 0289 impl_.get_service().assign(impl_.get_implementation(), 0290 protocol, native_socket, ec); 0291 boost::asio::detail::throw_error(ec, "assign"); 0292 } 0293 0294 /// Move-construct a basic_socket from another. 0295 /** 0296 * This constructor moves a socket from one object to another. 0297 * 0298 * @param other The other basic_socket object from which the move will 0299 * occur. 0300 * 0301 * @note Following the move, the moved-from object is in the same state as if 0302 * constructed using the @c basic_socket(const executor_type&) constructor. 0303 */ 0304 basic_socket(basic_socket&& other) noexcept 0305 : impl_(std::move(other.impl_)) 0306 { 0307 } 0308 0309 /// Move-assign a basic_socket from another. 0310 /** 0311 * This assignment operator moves a socket from one object to another. 0312 * 0313 * @param other The other basic_socket object from which the move will 0314 * occur. 0315 * 0316 * @note Following the move, the moved-from object is in the same state as if 0317 * constructed using the @c basic_socket(const executor_type&) constructor. 0318 */ 0319 basic_socket& operator=(basic_socket&& other) 0320 { 0321 impl_ = std::move(other.impl_); 0322 return *this; 0323 } 0324 0325 // All sockets have access to each other's implementations. 0326 template <typename Protocol1, typename Executor1> 0327 friend class basic_socket; 0328 0329 /// Move-construct a basic_socket from a socket of another protocol type. 0330 /** 0331 * This constructor moves a socket from one object to another. 0332 * 0333 * @param other The other basic_socket object from which the move will 0334 * occur. 0335 * 0336 * @note Following the move, the moved-from object is in the same state as if 0337 * constructed using the @c basic_socket(const executor_type&) constructor. 0338 */ 0339 template <typename Protocol1, typename Executor1> 0340 basic_socket(basic_socket<Protocol1, Executor1>&& other, 0341 constraint_t< 0342 is_convertible<Protocol1, Protocol>::value 0343 && is_convertible<Executor1, Executor>::value 0344 > = 0) 0345 : impl_(std::move(other.impl_)) 0346 { 0347 } 0348 0349 /// Move-assign a basic_socket from a socket of another protocol type. 0350 /** 0351 * This assignment operator moves a socket from one object to another. 0352 * 0353 * @param other The other basic_socket object from which the move will 0354 * occur. 0355 * 0356 * @note Following the move, the moved-from object is in the same state as if 0357 * constructed using the @c basic_socket(const executor_type&) constructor. 0358 */ 0359 template <typename Protocol1, typename Executor1> 0360 constraint_t< 0361 is_convertible<Protocol1, Protocol>::value 0362 && is_convertible<Executor1, Executor>::value, 0363 basic_socket& 0364 > operator=(basic_socket<Protocol1, Executor1>&& other) 0365 { 0366 basic_socket tmp(std::move(other)); 0367 impl_ = std::move(tmp.impl_); 0368 return *this; 0369 } 0370 0371 /// Get the executor associated with the object. 0372 const executor_type& get_executor() noexcept 0373 { 0374 return impl_.get_executor(); 0375 } 0376 0377 #if !defined(BOOST_ASIO_NO_EXTENSIONS) 0378 /// Get a reference to the lowest layer. 0379 /** 0380 * This function returns a reference to the lowest layer in a stack of 0381 * layers. Since a basic_socket cannot contain any further layers, it simply 0382 * returns a reference to itself. 0383 * 0384 * @return A reference to the lowest layer in the stack of layers. Ownership 0385 * is not transferred to the caller. 0386 */ 0387 lowest_layer_type& lowest_layer() 0388 { 0389 return *this; 0390 } 0391 0392 /// Get a const reference to the lowest layer. 0393 /** 0394 * This function returns a const reference to the lowest layer in a stack of 0395 * layers. Since a basic_socket cannot contain any further layers, it simply 0396 * returns a reference to itself. 0397 * 0398 * @return A const reference to the lowest layer in the stack of layers. 0399 * Ownership is not transferred to the caller. 0400 */ 0401 const lowest_layer_type& lowest_layer() const 0402 { 0403 return *this; 0404 } 0405 #endif // !defined(BOOST_ASIO_NO_EXTENSIONS) 0406 0407 /// Open the socket using the specified protocol. 0408 /** 0409 * This function opens the socket so that it will use the specified protocol. 0410 * 0411 * @param protocol An object specifying protocol parameters to be used. 0412 * 0413 * @throws boost::system::system_error Thrown on failure. 0414 * 0415 * @par Example 0416 * @code 0417 * boost::asio::ip::tcp::socket socket(my_context); 0418 * socket.open(boost::asio::ip::tcp::v4()); 0419 * @endcode 0420 */ 0421 void open(const protocol_type& protocol = protocol_type()) 0422 { 0423 boost::system::error_code ec; 0424 impl_.get_service().open(impl_.get_implementation(), protocol, ec); 0425 boost::asio::detail::throw_error(ec, "open"); 0426 } 0427 0428 /// Open the socket using the specified protocol. 0429 /** 0430 * This function opens the socket so that it will use the specified protocol. 0431 * 0432 * @param protocol An object specifying which protocol is to be used. 0433 * 0434 * @param ec Set to indicate what error occurred, if any. 0435 * 0436 * @par Example 0437 * @code 0438 * boost::asio::ip::tcp::socket socket(my_context); 0439 * boost::system::error_code ec; 0440 * socket.open(boost::asio::ip::tcp::v4(), ec); 0441 * if (ec) 0442 * { 0443 * // An error occurred. 0444 * } 0445 * @endcode 0446 */ 0447 BOOST_ASIO_SYNC_OP_VOID open(const protocol_type& protocol, 0448 boost::system::error_code& ec) 0449 { 0450 impl_.get_service().open(impl_.get_implementation(), protocol, ec); 0451 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); 0452 } 0453 0454 /// Assign an existing native socket to the socket. 0455 /* 0456 * This function opens the socket to hold an existing native socket. 0457 * 0458 * @param protocol An object specifying which protocol is to be used. 0459 * 0460 * @param native_socket A native socket. 0461 * 0462 * @throws boost::system::system_error Thrown on failure. 0463 */ 0464 void assign(const protocol_type& protocol, 0465 const native_handle_type& native_socket) 0466 { 0467 boost::system::error_code ec; 0468 impl_.get_service().assign(impl_.get_implementation(), 0469 protocol, native_socket, ec); 0470 boost::asio::detail::throw_error(ec, "assign"); 0471 } 0472 0473 /// Assign an existing native socket to the socket. 0474 /* 0475 * This function opens the socket to hold an existing native socket. 0476 * 0477 * @param protocol An object specifying which protocol is to be used. 0478 * 0479 * @param native_socket A native socket. 0480 * 0481 * @param ec Set to indicate what error occurred, if any. 0482 */ 0483 BOOST_ASIO_SYNC_OP_VOID assign(const protocol_type& protocol, 0484 const native_handle_type& native_socket, boost::system::error_code& ec) 0485 { 0486 impl_.get_service().assign(impl_.get_implementation(), 0487 protocol, native_socket, ec); 0488 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); 0489 } 0490 0491 /// Determine whether the socket is open. 0492 bool is_open() const 0493 { 0494 return impl_.get_service().is_open(impl_.get_implementation()); 0495 } 0496 0497 /// Close the socket. 0498 /** 0499 * This function is used to close the socket. Any asynchronous send, receive 0500 * or connect operations will be cancelled immediately, and will complete 0501 * with the boost::asio::error::operation_aborted error. 0502 * 0503 * @throws boost::system::system_error Thrown on failure. Note that, even if 0504 * the function indicates an error, the underlying descriptor is closed. 0505 * 0506 * @note For portable behaviour with respect to graceful closure of a 0507 * connected socket, call shutdown() before closing the socket. 0508 */ 0509 void close() 0510 { 0511 boost::system::error_code ec; 0512 impl_.get_service().close(impl_.get_implementation(), ec); 0513 boost::asio::detail::throw_error(ec, "close"); 0514 } 0515 0516 /// Close the socket. 0517 /** 0518 * This function is used to close the socket. Any asynchronous send, receive 0519 * or connect operations will be cancelled immediately, and will complete 0520 * with the boost::asio::error::operation_aborted error. 0521 * 0522 * @param ec Set to indicate what error occurred, if any. Note that, even if 0523 * the function indicates an error, the underlying descriptor is closed. 0524 * 0525 * @par Example 0526 * @code 0527 * boost::asio::ip::tcp::socket socket(my_context); 0528 * ... 0529 * boost::system::error_code ec; 0530 * socket.close(ec); 0531 * if (ec) 0532 * { 0533 * // An error occurred. 0534 * } 0535 * @endcode 0536 * 0537 * @note For portable behaviour with respect to graceful closure of a 0538 * connected socket, call shutdown() before closing the socket. 0539 */ 0540 BOOST_ASIO_SYNC_OP_VOID close(boost::system::error_code& ec) 0541 { 0542 impl_.get_service().close(impl_.get_implementation(), ec); 0543 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); 0544 } 0545 0546 /// Release ownership of the underlying native socket. 0547 /** 0548 * This function causes all outstanding asynchronous connect, send and receive 0549 * operations to finish immediately, and the handlers for cancelled operations 0550 * will be passed the boost::asio::error::operation_aborted error. Ownership 0551 * of the native socket is then transferred to the caller. 0552 * 0553 * @throws boost::system::system_error Thrown on failure. 0554 * 0555 * @note This function is unsupported on Windows versions prior to Windows 0556 * 8.1, and will fail with boost::asio::error::operation_not_supported on 0557 * these platforms. 0558 */ 0559 #if defined(BOOST_ASIO_MSVC) && (BOOST_ASIO_MSVC >= 1400) \ 0560 && (!defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0603) 0561 __declspec(deprecated("This function always fails with " 0562 "operation_not_supported when used on Windows versions " 0563 "prior to Windows 8.1.")) 0564 #endif 0565 native_handle_type release() 0566 { 0567 boost::system::error_code ec; 0568 native_handle_type s = impl_.get_service().release( 0569 impl_.get_implementation(), ec); 0570 boost::asio::detail::throw_error(ec, "release"); 0571 return s; 0572 } 0573 0574 /// Release ownership of the underlying native socket. 0575 /** 0576 * This function causes all outstanding asynchronous connect, send and receive 0577 * operations to finish immediately, and the handlers for cancelled operations 0578 * will be passed the boost::asio::error::operation_aborted error. Ownership 0579 * of the native socket is then transferred to the caller. 0580 * 0581 * @param ec Set to indicate what error occurred, if any. 0582 * 0583 * @note This function is unsupported on Windows versions prior to Windows 0584 * 8.1, and will fail with boost::asio::error::operation_not_supported on 0585 * these platforms. 0586 */ 0587 #if defined(BOOST_ASIO_MSVC) && (BOOST_ASIO_MSVC >= 1400) \ 0588 && (!defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0603) 0589 __declspec(deprecated("This function always fails with " 0590 "operation_not_supported when used on Windows versions " 0591 "prior to Windows 8.1.")) 0592 #endif 0593 native_handle_type release(boost::system::error_code& ec) 0594 { 0595 return impl_.get_service().release(impl_.get_implementation(), ec); 0596 } 0597 0598 /// Get the native socket representation. 0599 /** 0600 * This function may be used to obtain the underlying representation of the 0601 * socket. This is intended to allow access to native socket functionality 0602 * that is not otherwise provided. 0603 */ 0604 native_handle_type native_handle() 0605 { 0606 return impl_.get_service().native_handle(impl_.get_implementation()); 0607 } 0608 0609 /// Cancel all asynchronous operations associated with the socket. 0610 /** 0611 * This function causes all outstanding asynchronous connect, send and receive 0612 * operations to finish immediately, and the handlers for cancelled operations 0613 * will be passed the boost::asio::error::operation_aborted error. 0614 * 0615 * @throws boost::system::system_error Thrown on failure. 0616 * 0617 * @note Calls to cancel() will always fail with 0618 * boost::asio::error::operation_not_supported when run on Windows XP, Windows 0619 * Server 2003, and earlier versions of Windows, unless 0620 * BOOST_ASIO_ENABLE_CANCELIO is defined. However, the CancelIo function has 0621 * two issues that should be considered before enabling its use: 0622 * 0623 * @li It will only cancel asynchronous operations that were initiated in the 0624 * current thread. 0625 * 0626 * @li It can appear to complete without error, but the request to cancel the 0627 * unfinished operations may be silently ignored by the operating system. 0628 * Whether it works or not seems to depend on the drivers that are installed. 0629 * 0630 * For portable cancellation, consider using one of the following 0631 * alternatives: 0632 * 0633 * @li Disable asio's I/O completion port backend by defining 0634 * BOOST_ASIO_DISABLE_IOCP. 0635 * 0636 * @li Use the close() function to simultaneously cancel the outstanding 0637 * operations and close the socket. 0638 * 0639 * When running on Windows Vista, Windows Server 2008, and later, the 0640 * CancelIoEx function is always used. This function does not have the 0641 * problems described above. 0642 */ 0643 #if defined(BOOST_ASIO_MSVC) && (BOOST_ASIO_MSVC >= 1400) \ 0644 && (!defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0600) \ 0645 && !defined(BOOST_ASIO_ENABLE_CANCELIO) 0646 __declspec(deprecated("By default, this function always fails with " 0647 "operation_not_supported when used on Windows XP, Windows Server 2003, " 0648 "or earlier. Consult documentation for details.")) 0649 #endif 0650 void cancel() 0651 { 0652 boost::system::error_code ec; 0653 impl_.get_service().cancel(impl_.get_implementation(), ec); 0654 boost::asio::detail::throw_error(ec, "cancel"); 0655 } 0656 0657 /// Cancel all asynchronous operations associated with the socket. 0658 /** 0659 * This function causes all outstanding asynchronous connect, send and receive 0660 * operations to finish immediately, and the handlers for cancelled operations 0661 * will be passed the boost::asio::error::operation_aborted error. 0662 * 0663 * @param ec Set to indicate what error occurred, if any. 0664 * 0665 * @note Calls to cancel() will always fail with 0666 * boost::asio::error::operation_not_supported when run on Windows XP, Windows 0667 * Server 2003, and earlier versions of Windows, unless 0668 * BOOST_ASIO_ENABLE_CANCELIO is defined. However, the CancelIo function has 0669 * two issues that should be considered before enabling its use: 0670 * 0671 * @li It will only cancel asynchronous operations that were initiated in the 0672 * current thread. 0673 * 0674 * @li It can appear to complete without error, but the request to cancel the 0675 * unfinished operations may be silently ignored by the operating system. 0676 * Whether it works or not seems to depend on the drivers that are installed. 0677 * 0678 * For portable cancellation, consider using one of the following 0679 * alternatives: 0680 * 0681 * @li Disable asio's I/O completion port backend by defining 0682 * BOOST_ASIO_DISABLE_IOCP. 0683 * 0684 * @li Use the close() function to simultaneously cancel the outstanding 0685 * operations and close the socket. 0686 * 0687 * When running on Windows Vista, Windows Server 2008, and later, the 0688 * CancelIoEx function is always used. This function does not have the 0689 * problems described above. 0690 */ 0691 #if defined(BOOST_ASIO_MSVC) && (BOOST_ASIO_MSVC >= 1400) \ 0692 && (!defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0600) \ 0693 && !defined(BOOST_ASIO_ENABLE_CANCELIO) 0694 __declspec(deprecated("By default, this function always fails with " 0695 "operation_not_supported when used on Windows XP, Windows Server 2003, " 0696 "or earlier. Consult documentation for details.")) 0697 #endif 0698 BOOST_ASIO_SYNC_OP_VOID cancel(boost::system::error_code& ec) 0699 { 0700 impl_.get_service().cancel(impl_.get_implementation(), ec); 0701 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); 0702 } 0703 0704 /// Determine whether the socket is at the out-of-band data mark. 0705 /** 0706 * This function is used to check whether the socket input is currently 0707 * positioned at the out-of-band data mark. 0708 * 0709 * @return A bool indicating whether the socket is at the out-of-band data 0710 * mark. 0711 * 0712 * @throws boost::system::system_error Thrown on failure. 0713 */ 0714 bool at_mark() const 0715 { 0716 boost::system::error_code ec; 0717 bool b = impl_.get_service().at_mark(impl_.get_implementation(), ec); 0718 boost::asio::detail::throw_error(ec, "at_mark"); 0719 return b; 0720 } 0721 0722 /// Determine whether the socket is at the out-of-band data mark. 0723 /** 0724 * This function is used to check whether the socket input is currently 0725 * positioned at the out-of-band data mark. 0726 * 0727 * @param ec Set to indicate what error occurred, if any. 0728 * 0729 * @return A bool indicating whether the socket is at the out-of-band data 0730 * mark. 0731 */ 0732 bool at_mark(boost::system::error_code& ec) const 0733 { 0734 return impl_.get_service().at_mark(impl_.get_implementation(), ec); 0735 } 0736 0737 /// Determine the number of bytes available for reading. 0738 /** 0739 * This function is used to determine the number of bytes that may be read 0740 * without blocking. 0741 * 0742 * @return The number of bytes that may be read without blocking, or 0 if an 0743 * error occurs. 0744 * 0745 * @throws boost::system::system_error Thrown on failure. 0746 */ 0747 std::size_t available() const 0748 { 0749 boost::system::error_code ec; 0750 std::size_t s = impl_.get_service().available( 0751 impl_.get_implementation(), ec); 0752 boost::asio::detail::throw_error(ec, "available"); 0753 return s; 0754 } 0755 0756 /// Determine the number of bytes available for reading. 0757 /** 0758 * This function is used to determine the number of bytes that may be read 0759 * without blocking. 0760 * 0761 * @param ec Set to indicate what error occurred, if any. 0762 * 0763 * @return The number of bytes that may be read without blocking, or 0 if an 0764 * error occurs. 0765 */ 0766 std::size_t available(boost::system::error_code& ec) const 0767 { 0768 return impl_.get_service().available(impl_.get_implementation(), ec); 0769 } 0770 0771 /// Bind the socket to the given local endpoint. 0772 /** 0773 * This function binds the socket to the specified endpoint on the local 0774 * machine. 0775 * 0776 * @param endpoint An endpoint on the local machine to which the socket will 0777 * be bound. 0778 * 0779 * @throws boost::system::system_error Thrown on failure. 0780 * 0781 * @par Example 0782 * @code 0783 * boost::asio::ip::tcp::socket socket(my_context); 0784 * socket.open(boost::asio::ip::tcp::v4()); 0785 * socket.bind(boost::asio::ip::tcp::endpoint( 0786 * boost::asio::ip::tcp::v4(), 12345)); 0787 * @endcode 0788 */ 0789 void bind(const endpoint_type& endpoint) 0790 { 0791 boost::system::error_code ec; 0792 impl_.get_service().bind(impl_.get_implementation(), endpoint, ec); 0793 boost::asio::detail::throw_error(ec, "bind"); 0794 } 0795 0796 /// Bind the socket to the given local endpoint. 0797 /** 0798 * This function binds the socket to the specified endpoint on the local 0799 * machine. 0800 * 0801 * @param endpoint An endpoint on the local machine to which the socket will 0802 * be bound. 0803 * 0804 * @param ec Set to indicate what error occurred, if any. 0805 * 0806 * @par Example 0807 * @code 0808 * boost::asio::ip::tcp::socket socket(my_context); 0809 * socket.open(boost::asio::ip::tcp::v4()); 0810 * boost::system::error_code ec; 0811 * socket.bind(boost::asio::ip::tcp::endpoint( 0812 * boost::asio::ip::tcp::v4(), 12345), ec); 0813 * if (ec) 0814 * { 0815 * // An error occurred. 0816 * } 0817 * @endcode 0818 */ 0819 BOOST_ASIO_SYNC_OP_VOID bind(const endpoint_type& endpoint, 0820 boost::system::error_code& ec) 0821 { 0822 impl_.get_service().bind(impl_.get_implementation(), endpoint, ec); 0823 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); 0824 } 0825 0826 /// Connect the socket to the specified endpoint. 0827 /** 0828 * This function is used to connect a socket to the specified remote endpoint. 0829 * The function call will block until the connection is successfully made or 0830 * an error occurs. 0831 * 0832 * The socket is automatically opened if it is not already open. If the 0833 * connect fails, and the socket was automatically opened, the socket is 0834 * not returned to the closed state. 0835 * 0836 * @param peer_endpoint The remote endpoint to which the socket will be 0837 * connected. 0838 * 0839 * @throws boost::system::system_error Thrown on failure. 0840 * 0841 * @par Example 0842 * @code 0843 * boost::asio::ip::tcp::socket socket(my_context); 0844 * boost::asio::ip::tcp::endpoint endpoint( 0845 * boost::asio::ip::address::from_string("1.2.3.4"), 12345); 0846 * socket.connect(endpoint); 0847 * @endcode 0848 */ 0849 void connect(const endpoint_type& peer_endpoint) 0850 { 0851 boost::system::error_code ec; 0852 if (!is_open()) 0853 { 0854 impl_.get_service().open(impl_.get_implementation(), 0855 peer_endpoint.protocol(), ec); 0856 boost::asio::detail::throw_error(ec, "connect"); 0857 } 0858 impl_.get_service().connect(impl_.get_implementation(), peer_endpoint, ec); 0859 boost::asio::detail::throw_error(ec, "connect"); 0860 } 0861 0862 /// Connect the socket to the specified endpoint. 0863 /** 0864 * This function is used to connect a socket to the specified remote endpoint. 0865 * The function call will block until the connection is successfully made or 0866 * an error occurs. 0867 * 0868 * The socket is automatically opened if it is not already open. If the 0869 * connect fails, and the socket was automatically opened, the socket is 0870 * not returned to the closed state. 0871 * 0872 * @param peer_endpoint The remote endpoint to which the socket will be 0873 * connected. 0874 * 0875 * @param ec Set to indicate what error occurred, if any. 0876 * 0877 * @par Example 0878 * @code 0879 * boost::asio::ip::tcp::socket socket(my_context); 0880 * boost::asio::ip::tcp::endpoint endpoint( 0881 * boost::asio::ip::address::from_string("1.2.3.4"), 12345); 0882 * boost::system::error_code ec; 0883 * socket.connect(endpoint, ec); 0884 * if (ec) 0885 * { 0886 * // An error occurred. 0887 * } 0888 * @endcode 0889 */ 0890 BOOST_ASIO_SYNC_OP_VOID connect(const endpoint_type& peer_endpoint, 0891 boost::system::error_code& ec) 0892 { 0893 if (!is_open()) 0894 { 0895 impl_.get_service().open(impl_.get_implementation(), 0896 peer_endpoint.protocol(), ec); 0897 if (ec) 0898 { 0899 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); 0900 } 0901 } 0902 0903 impl_.get_service().connect(impl_.get_implementation(), peer_endpoint, ec); 0904 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); 0905 } 0906 0907 /// Start an asynchronous connect. 0908 /** 0909 * This function is used to asynchronously connect a socket to the specified 0910 * remote endpoint. It is an initiating function for an @ref 0911 * asynchronous_operation, and always returns immediately. 0912 * 0913 * The socket is automatically opened if it is not already open. If the 0914 * connect fails, and the socket was automatically opened, the socket is 0915 * not returned to the closed state. 0916 * 0917 * @param peer_endpoint The remote endpoint to which the socket will be 0918 * connected. Copies will be made of the endpoint object as required. 0919 * 0920 * @param token The @ref completion_token that will be used to produce a 0921 * completion handler, which will be called when the connect completes. 0922 * Potential completion tokens include @ref use_future, @ref use_awaitable, 0923 * @ref yield_context, or a function object with the correct completion 0924 * signature. The function signature of the completion handler must be: 0925 * @code void handler( 0926 * const boost::system::error_code& error // Result of operation. 0927 * ); @endcode 0928 * Regardless of whether the asynchronous operation completes immediately or 0929 * not, the completion handler will not be invoked from within this function. 0930 * On immediate completion, invocation of the handler will be performed in a 0931 * manner equivalent to using boost::asio::post(). 0932 * 0933 * @par Completion Signature 0934 * @code void(boost::system::error_code) @endcode 0935 * 0936 * @par Example 0937 * @code 0938 * void connect_handler(const boost::system::error_code& error) 0939 * { 0940 * if (!error) 0941 * { 0942 * // Connect succeeded. 0943 * } 0944 * } 0945 * 0946 * ... 0947 * 0948 * boost::asio::ip::tcp::socket socket(my_context); 0949 * boost::asio::ip::tcp::endpoint endpoint( 0950 * boost::asio::ip::address::from_string("1.2.3.4"), 12345); 0951 * socket.async_connect(endpoint, connect_handler); 0952 * @endcode 0953 * 0954 * @par Per-Operation Cancellation 0955 * On POSIX or Windows operating systems, this asynchronous operation supports 0956 * cancellation for the following boost::asio::cancellation_type values: 0957 * 0958 * @li @c cancellation_type::terminal 0959 * 0960 * @li @c cancellation_type::partial 0961 * 0962 * @li @c cancellation_type::total 0963 */ 0964 template < 0965 BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code)) 0966 ConnectToken = default_completion_token_t<executor_type>> 0967 auto async_connect(const endpoint_type& peer_endpoint, 0968 ConnectToken&& token = default_completion_token_t<executor_type>()) 0969 -> decltype( 0970 async_initiate<ConnectToken, void (boost::system::error_code)>( 0971 declval<initiate_async_connect>(), token, 0972 peer_endpoint, declval<boost::system::error_code&>())) 0973 { 0974 boost::system::error_code open_ec; 0975 if (!is_open()) 0976 { 0977 const protocol_type protocol = peer_endpoint.protocol(); 0978 impl_.get_service().open(impl_.get_implementation(), protocol, open_ec); 0979 } 0980 0981 return async_initiate<ConnectToken, void (boost::system::error_code)>( 0982 initiate_async_connect(this), token, peer_endpoint, open_ec); 0983 } 0984 0985 /// Set an option on the socket. 0986 /** 0987 * This function is used to set an option on the socket. 0988 * 0989 * @param option The new option value to be set on the socket. 0990 * 0991 * @throws boost::system::system_error Thrown on failure. 0992 * 0993 * @sa SettableSocketOption @n 0994 * boost::asio::socket_base::broadcast @n 0995 * boost::asio::socket_base::do_not_route @n 0996 * boost::asio::socket_base::keep_alive @n 0997 * boost::asio::socket_base::linger @n 0998 * boost::asio::socket_base::receive_buffer_size @n 0999 * boost::asio::socket_base::receive_low_watermark @n 1000 * boost::asio::socket_base::reuse_address @n 1001 * boost::asio::socket_base::send_buffer_size @n 1002 * boost::asio::socket_base::send_low_watermark @n 1003 * boost::asio::ip::multicast::join_group @n 1004 * boost::asio::ip::multicast::leave_group @n 1005 * boost::asio::ip::multicast::enable_loopback @n 1006 * boost::asio::ip::multicast::outbound_interface @n 1007 * boost::asio::ip::multicast::hops @n 1008 * boost::asio::ip::tcp::no_delay 1009 * 1010 * @par Example 1011 * Setting the IPPROTO_TCP/TCP_NODELAY option: 1012 * @code 1013 * boost::asio::ip::tcp::socket socket(my_context); 1014 * ... 1015 * boost::asio::ip::tcp::no_delay option(true); 1016 * socket.set_option(option); 1017 * @endcode 1018 */ 1019 template <typename SettableSocketOption> 1020 void set_option(const SettableSocketOption& option) 1021 { 1022 boost::system::error_code ec; 1023 impl_.get_service().set_option(impl_.get_implementation(), option, ec); 1024 boost::asio::detail::throw_error(ec, "set_option"); 1025 } 1026 1027 /// Set an option on the socket. 1028 /** 1029 * This function is used to set an option on the socket. 1030 * 1031 * @param option The new option value to be set on the socket. 1032 * 1033 * @param ec Set to indicate what error occurred, if any. 1034 * 1035 * @sa SettableSocketOption @n 1036 * boost::asio::socket_base::broadcast @n 1037 * boost::asio::socket_base::do_not_route @n 1038 * boost::asio::socket_base::keep_alive @n 1039 * boost::asio::socket_base::linger @n 1040 * boost::asio::socket_base::receive_buffer_size @n 1041 * boost::asio::socket_base::receive_low_watermark @n 1042 * boost::asio::socket_base::reuse_address @n 1043 * boost::asio::socket_base::send_buffer_size @n 1044 * boost::asio::socket_base::send_low_watermark @n 1045 * boost::asio::ip::multicast::join_group @n 1046 * boost::asio::ip::multicast::leave_group @n 1047 * boost::asio::ip::multicast::enable_loopback @n 1048 * boost::asio::ip::multicast::outbound_interface @n 1049 * boost::asio::ip::multicast::hops @n 1050 * boost::asio::ip::tcp::no_delay 1051 * 1052 * @par Example 1053 * Setting the IPPROTO_TCP/TCP_NODELAY option: 1054 * @code 1055 * boost::asio::ip::tcp::socket socket(my_context); 1056 * ... 1057 * boost::asio::ip::tcp::no_delay option(true); 1058 * boost::system::error_code ec; 1059 * socket.set_option(option, ec); 1060 * if (ec) 1061 * { 1062 * // An error occurred. 1063 * } 1064 * @endcode 1065 */ 1066 template <typename SettableSocketOption> 1067 BOOST_ASIO_SYNC_OP_VOID set_option(const SettableSocketOption& option, 1068 boost::system::error_code& ec) 1069 { 1070 impl_.get_service().set_option(impl_.get_implementation(), option, ec); 1071 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); 1072 } 1073 1074 /// Get an option from the socket. 1075 /** 1076 * This function is used to get the current value of an option on the socket. 1077 * 1078 * @param option The option value to be obtained from the socket. 1079 * 1080 * @throws boost::system::system_error Thrown on failure. 1081 * 1082 * @sa GettableSocketOption @n 1083 * boost::asio::socket_base::broadcast @n 1084 * boost::asio::socket_base::do_not_route @n 1085 * boost::asio::socket_base::keep_alive @n 1086 * boost::asio::socket_base::linger @n 1087 * boost::asio::socket_base::receive_buffer_size @n 1088 * boost::asio::socket_base::receive_low_watermark @n 1089 * boost::asio::socket_base::reuse_address @n 1090 * boost::asio::socket_base::send_buffer_size @n 1091 * boost::asio::socket_base::send_low_watermark @n 1092 * boost::asio::ip::multicast::join_group @n 1093 * boost::asio::ip::multicast::leave_group @n 1094 * boost::asio::ip::multicast::enable_loopback @n 1095 * boost::asio::ip::multicast::outbound_interface @n 1096 * boost::asio::ip::multicast::hops @n 1097 * boost::asio::ip::tcp::no_delay 1098 * 1099 * @par Example 1100 * Getting the value of the SOL_SOCKET/SO_KEEPALIVE option: 1101 * @code 1102 * boost::asio::ip::tcp::socket socket(my_context); 1103 * ... 1104 * boost::asio::ip::tcp::socket::keep_alive option; 1105 * socket.get_option(option); 1106 * bool is_set = option.value(); 1107 * @endcode 1108 */ 1109 template <typename GettableSocketOption> 1110 void get_option(GettableSocketOption& option) const 1111 { 1112 boost::system::error_code ec; 1113 impl_.get_service().get_option(impl_.get_implementation(), option, ec); 1114 boost::asio::detail::throw_error(ec, "get_option"); 1115 } 1116 1117 /// Get an option from the socket. 1118 /** 1119 * This function is used to get the current value of an option on the socket. 1120 * 1121 * @param option The option value to be obtained from the socket. 1122 * 1123 * @param ec Set to indicate what error occurred, if any. 1124 * 1125 * @sa GettableSocketOption @n 1126 * boost::asio::socket_base::broadcast @n 1127 * boost::asio::socket_base::do_not_route @n 1128 * boost::asio::socket_base::keep_alive @n 1129 * boost::asio::socket_base::linger @n 1130 * boost::asio::socket_base::receive_buffer_size @n 1131 * boost::asio::socket_base::receive_low_watermark @n 1132 * boost::asio::socket_base::reuse_address @n 1133 * boost::asio::socket_base::send_buffer_size @n 1134 * boost::asio::socket_base::send_low_watermark @n 1135 * boost::asio::ip::multicast::join_group @n 1136 * boost::asio::ip::multicast::leave_group @n 1137 * boost::asio::ip::multicast::enable_loopback @n 1138 * boost::asio::ip::multicast::outbound_interface @n 1139 * boost::asio::ip::multicast::hops @n 1140 * boost::asio::ip::tcp::no_delay 1141 * 1142 * @par Example 1143 * Getting the value of the SOL_SOCKET/SO_KEEPALIVE option: 1144 * @code 1145 * boost::asio::ip::tcp::socket socket(my_context); 1146 * ... 1147 * boost::asio::ip::tcp::socket::keep_alive option; 1148 * boost::system::error_code ec; 1149 * socket.get_option(option, ec); 1150 * if (ec) 1151 * { 1152 * // An error occurred. 1153 * } 1154 * bool is_set = option.value(); 1155 * @endcode 1156 */ 1157 template <typename GettableSocketOption> 1158 BOOST_ASIO_SYNC_OP_VOID get_option(GettableSocketOption& option, 1159 boost::system::error_code& ec) const 1160 { 1161 impl_.get_service().get_option(impl_.get_implementation(), option, ec); 1162 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); 1163 } 1164 1165 /// Perform an IO control command on the socket. 1166 /** 1167 * This function is used to execute an IO control command on the socket. 1168 * 1169 * @param command The IO control command to be performed on the socket. 1170 * 1171 * @throws boost::system::system_error Thrown on failure. 1172 * 1173 * @sa IoControlCommand @n 1174 * boost::asio::socket_base::bytes_readable @n 1175 * boost::asio::socket_base::non_blocking_io 1176 * 1177 * @par Example 1178 * Getting the number of bytes ready to read: 1179 * @code 1180 * boost::asio::ip::tcp::socket socket(my_context); 1181 * ... 1182 * boost::asio::ip::tcp::socket::bytes_readable command; 1183 * socket.io_control(command); 1184 * std::size_t bytes_readable = command.get(); 1185 * @endcode 1186 */ 1187 template <typename IoControlCommand> 1188 void io_control(IoControlCommand& command) 1189 { 1190 boost::system::error_code ec; 1191 impl_.get_service().io_control(impl_.get_implementation(), command, ec); 1192 boost::asio::detail::throw_error(ec, "io_control"); 1193 } 1194 1195 /// Perform an IO control command on the socket. 1196 /** 1197 * This function is used to execute an IO control command on the socket. 1198 * 1199 * @param command The IO control command to be performed on the socket. 1200 * 1201 * @param ec Set to indicate what error occurred, if any. 1202 * 1203 * @sa IoControlCommand @n 1204 * boost::asio::socket_base::bytes_readable @n 1205 * boost::asio::socket_base::non_blocking_io 1206 * 1207 * @par Example 1208 * Getting the number of bytes ready to read: 1209 * @code 1210 * boost::asio::ip::tcp::socket socket(my_context); 1211 * ... 1212 * boost::asio::ip::tcp::socket::bytes_readable command; 1213 * boost::system::error_code ec; 1214 * socket.io_control(command, ec); 1215 * if (ec) 1216 * { 1217 * // An error occurred. 1218 * } 1219 * std::size_t bytes_readable = command.get(); 1220 * @endcode 1221 */ 1222 template <typename IoControlCommand> 1223 BOOST_ASIO_SYNC_OP_VOID io_control(IoControlCommand& command, 1224 boost::system::error_code& ec) 1225 { 1226 impl_.get_service().io_control(impl_.get_implementation(), command, ec); 1227 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); 1228 } 1229 1230 /// Gets the non-blocking mode of the socket. 1231 /** 1232 * @returns @c true if the socket's synchronous operations will fail with 1233 * boost::asio::error::would_block if they are unable to perform the requested 1234 * operation immediately. If @c false, synchronous operations will block 1235 * until complete. 1236 * 1237 * @note The non-blocking mode has no effect on the behaviour of asynchronous 1238 * operations. Asynchronous operations will never fail with the error 1239 * boost::asio::error::would_block. 1240 */ 1241 bool non_blocking() const 1242 { 1243 return impl_.get_service().non_blocking(impl_.get_implementation()); 1244 } 1245 1246 /// Sets the non-blocking mode of the socket. 1247 /** 1248 * @param mode If @c true, the socket's synchronous operations will fail with 1249 * boost::asio::error::would_block if they are unable to perform the requested 1250 * operation immediately. If @c false, synchronous operations will block 1251 * until complete. 1252 * 1253 * @throws boost::system::system_error Thrown on failure. 1254 * 1255 * @note The non-blocking mode has no effect on the behaviour of asynchronous 1256 * operations. Asynchronous operations will never fail with the error 1257 * boost::asio::error::would_block. 1258 */ 1259 void non_blocking(bool mode) 1260 { 1261 boost::system::error_code ec; 1262 impl_.get_service().non_blocking(impl_.get_implementation(), mode, ec); 1263 boost::asio::detail::throw_error(ec, "non_blocking"); 1264 } 1265 1266 /// Sets the non-blocking mode of the socket. 1267 /** 1268 * @param mode If @c true, the socket's synchronous operations will fail with 1269 * boost::asio::error::would_block if they are unable to perform the requested 1270 * operation immediately. If @c false, synchronous operations will block 1271 * until complete. 1272 * 1273 * @param ec Set to indicate what error occurred, if any. 1274 * 1275 * @note The non-blocking mode has no effect on the behaviour of asynchronous 1276 * operations. Asynchronous operations will never fail with the error 1277 * boost::asio::error::would_block. 1278 */ 1279 BOOST_ASIO_SYNC_OP_VOID non_blocking( 1280 bool mode, boost::system::error_code& ec) 1281 { 1282 impl_.get_service().non_blocking(impl_.get_implementation(), mode, ec); 1283 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); 1284 } 1285 1286 /// Gets the non-blocking mode of the native socket implementation. 1287 /** 1288 * This function is used to retrieve the non-blocking mode of the underlying 1289 * native socket. This mode has no effect on the behaviour of the socket 1290 * object's synchronous operations. 1291 * 1292 * @returns @c true if the underlying socket is in non-blocking mode and 1293 * direct system calls may fail with boost::asio::error::would_block (or the 1294 * equivalent system error). 1295 * 1296 * @note The current non-blocking mode is cached by the socket object. 1297 * Consequently, the return value may be incorrect if the non-blocking mode 1298 * was set directly on the native socket. 1299 * 1300 * @par Example 1301 * This function is intended to allow the encapsulation of arbitrary 1302 * non-blocking system calls as asynchronous operations, in a way that is 1303 * transparent to the user of the socket object. The following example 1304 * illustrates how Linux's @c sendfile system call might be encapsulated: 1305 * @code template <typename Handler> 1306 * struct sendfile_op 1307 * { 1308 * tcp::socket& sock_; 1309 * int fd_; 1310 * Handler handler_; 1311 * off_t offset_; 1312 * std::size_t total_bytes_transferred_; 1313 * 1314 * // Function call operator meeting WriteHandler requirements. 1315 * // Used as the handler for the async_write_some operation. 1316 * void operator()(boost::system::error_code ec, std::size_t) 1317 * { 1318 * // Put the underlying socket into non-blocking mode. 1319 * if (!ec) 1320 * if (!sock_.native_non_blocking()) 1321 * sock_.native_non_blocking(true, ec); 1322 * 1323 * if (!ec) 1324 * { 1325 * for (;;) 1326 * { 1327 * // Try the system call. 1328 * errno = 0; 1329 * int n = ::sendfile(sock_.native_handle(), fd_, &offset_, 65536); 1330 * ec = boost::system::error_code(n < 0 ? errno : 0, 1331 * boost::asio::error::get_system_category()); 1332 * total_bytes_transferred_ += ec ? 0 : n; 1333 * 1334 * // Retry operation immediately if interrupted by signal. 1335 * if (ec == boost::asio::error::interrupted) 1336 * continue; 1337 * 1338 * // Check if we need to run the operation again. 1339 * if (ec == boost::asio::error::would_block 1340 * || ec == boost::asio::error::try_again) 1341 * { 1342 * // We have to wait for the socket to become ready again. 1343 * sock_.async_wait(tcp::socket::wait_write, *this); 1344 * return; 1345 * } 1346 * 1347 * if (ec || n == 0) 1348 * { 1349 * // An error occurred, or we have reached the end of the file. 1350 * // Either way we must exit the loop so we can call the handler. 1351 * break; 1352 * } 1353 * 1354 * // Loop around to try calling sendfile again. 1355 * } 1356 * } 1357 * 1358 * // Pass result back to user's handler. 1359 * handler_(ec, total_bytes_transferred_); 1360 * } 1361 * }; 1362 * 1363 * template <typename Handler> 1364 * void async_sendfile(tcp::socket& sock, int fd, Handler h) 1365 * { 1366 * sendfile_op<Handler> op = { sock, fd, h, 0, 0 }; 1367 * sock.async_wait(tcp::socket::wait_write, op); 1368 * } @endcode 1369 */ 1370 bool native_non_blocking() const 1371 { 1372 return impl_.get_service().native_non_blocking(impl_.get_implementation()); 1373 } 1374 1375 /// Sets the non-blocking mode of the native socket implementation. 1376 /** 1377 * This function is used to modify the non-blocking mode of the underlying 1378 * native socket. It has no effect on the behaviour of the socket object's 1379 * synchronous operations. 1380 * 1381 * @param mode If @c true, the underlying socket is put into non-blocking 1382 * mode and direct system calls may fail with boost::asio::error::would_block 1383 * (or the equivalent system error). 1384 * 1385 * @throws boost::system::system_error Thrown on failure. If the @c mode is 1386 * @c false, but the current value of @c non_blocking() is @c true, this 1387 * function fails with boost::asio::error::invalid_argument, as the 1388 * combination does not make sense. 1389 * 1390 * @par Example 1391 * This function is intended to allow the encapsulation of arbitrary 1392 * non-blocking system calls as asynchronous operations, in a way that is 1393 * transparent to the user of the socket object. The following example 1394 * illustrates how Linux's @c sendfile system call might be encapsulated: 1395 * @code template <typename Handler> 1396 * struct sendfile_op 1397 * { 1398 * tcp::socket& sock_; 1399 * int fd_; 1400 * Handler handler_; 1401 * off_t offset_; 1402 * std::size_t total_bytes_transferred_; 1403 * 1404 * // Function call operator meeting WriteHandler requirements. 1405 * // Used as the handler for the async_write_some operation. 1406 * void operator()(boost::system::error_code ec, std::size_t) 1407 * { 1408 * // Put the underlying socket into non-blocking mode. 1409 * if (!ec) 1410 * if (!sock_.native_non_blocking()) 1411 * sock_.native_non_blocking(true, ec); 1412 * 1413 * if (!ec) 1414 * { 1415 * for (;;) 1416 * { 1417 * // Try the system call. 1418 * errno = 0; 1419 * int n = ::sendfile(sock_.native_handle(), fd_, &offset_, 65536); 1420 * ec = boost::system::error_code(n < 0 ? errno : 0, 1421 * boost::asio::error::get_system_category()); 1422 * total_bytes_transferred_ += ec ? 0 : n; 1423 * 1424 * // Retry operation immediately if interrupted by signal. 1425 * if (ec == boost::asio::error::interrupted) 1426 * continue; 1427 * 1428 * // Check if we need to run the operation again. 1429 * if (ec == boost::asio::error::would_block 1430 * || ec == boost::asio::error::try_again) 1431 * { 1432 * // We have to wait for the socket to become ready again. 1433 * sock_.async_wait(tcp::socket::wait_write, *this); 1434 * return; 1435 * } 1436 * 1437 * if (ec || n == 0) 1438 * { 1439 * // An error occurred, or we have reached the end of the file. 1440 * // Either way we must exit the loop so we can call the handler. 1441 * break; 1442 * } 1443 * 1444 * // Loop around to try calling sendfile again. 1445 * } 1446 * } 1447 * 1448 * // Pass result back to user's handler. 1449 * handler_(ec, total_bytes_transferred_); 1450 * } 1451 * }; 1452 * 1453 * template <typename Handler> 1454 * void async_sendfile(tcp::socket& sock, int fd, Handler h) 1455 * { 1456 * sendfile_op<Handler> op = { sock, fd, h, 0, 0 }; 1457 * sock.async_wait(tcp::socket::wait_write, op); 1458 * } @endcode 1459 */ 1460 void native_non_blocking(bool mode) 1461 { 1462 boost::system::error_code ec; 1463 impl_.get_service().native_non_blocking( 1464 impl_.get_implementation(), mode, ec); 1465 boost::asio::detail::throw_error(ec, "native_non_blocking"); 1466 } 1467 1468 /// Sets the non-blocking mode of the native socket implementation. 1469 /** 1470 * This function is used to modify the non-blocking mode of the underlying 1471 * native socket. It has no effect on the behaviour of the socket object's 1472 * synchronous operations. 1473 * 1474 * @param mode If @c true, the underlying socket is put into non-blocking 1475 * mode and direct system calls may fail with boost::asio::error::would_block 1476 * (or the equivalent system error). 1477 * 1478 * @param ec Set to indicate what error occurred, if any. If the @c mode is 1479 * @c false, but the current value of @c non_blocking() is @c true, this 1480 * function fails with boost::asio::error::invalid_argument, as the 1481 * combination does not make sense. 1482 * 1483 * @par Example 1484 * This function is intended to allow the encapsulation of arbitrary 1485 * non-blocking system calls as asynchronous operations, in a way that is 1486 * transparent to the user of the socket object. The following example 1487 * illustrates how Linux's @c sendfile system call might be encapsulated: 1488 * @code template <typename Handler> 1489 * struct sendfile_op 1490 * { 1491 * tcp::socket& sock_; 1492 * int fd_; 1493 * Handler handler_; 1494 * off_t offset_; 1495 * std::size_t total_bytes_transferred_; 1496 * 1497 * // Function call operator meeting WriteHandler requirements. 1498 * // Used as the handler for the async_write_some operation. 1499 * void operator()(boost::system::error_code ec, std::size_t) 1500 * { 1501 * // Put the underlying socket into non-blocking mode. 1502 * if (!ec) 1503 * if (!sock_.native_non_blocking()) 1504 * sock_.native_non_blocking(true, ec); 1505 * 1506 * if (!ec) 1507 * { 1508 * for (;;) 1509 * { 1510 * // Try the system call. 1511 * errno = 0; 1512 * int n = ::sendfile(sock_.native_handle(), fd_, &offset_, 65536); 1513 * ec = boost::system::error_code(n < 0 ? errno : 0, 1514 * boost::asio::error::get_system_category()); 1515 * total_bytes_transferred_ += ec ? 0 : n; 1516 * 1517 * // Retry operation immediately if interrupted by signal. 1518 * if (ec == boost::asio::error::interrupted) 1519 * continue; 1520 * 1521 * // Check if we need to run the operation again. 1522 * if (ec == boost::asio::error::would_block 1523 * || ec == boost::asio::error::try_again) 1524 * { 1525 * // We have to wait for the socket to become ready again. 1526 * sock_.async_wait(tcp::socket::wait_write, *this); 1527 * return; 1528 * } 1529 * 1530 * if (ec || n == 0) 1531 * { 1532 * // An error occurred, or we have reached the end of the file. 1533 * // Either way we must exit the loop so we can call the handler. 1534 * break; 1535 * } 1536 * 1537 * // Loop around to try calling sendfile again. 1538 * } 1539 * } 1540 * 1541 * // Pass result back to user's handler. 1542 * handler_(ec, total_bytes_transferred_); 1543 * } 1544 * }; 1545 * 1546 * template <typename Handler> 1547 * void async_sendfile(tcp::socket& sock, int fd, Handler h) 1548 * { 1549 * sendfile_op<Handler> op = { sock, fd, h, 0, 0 }; 1550 * sock.async_wait(tcp::socket::wait_write, op); 1551 * } @endcode 1552 */ 1553 BOOST_ASIO_SYNC_OP_VOID native_non_blocking( 1554 bool mode, boost::system::error_code& ec) 1555 { 1556 impl_.get_service().native_non_blocking( 1557 impl_.get_implementation(), mode, ec); 1558 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); 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 * @returns An object that represents the local endpoint of the socket. 1566 * 1567 * @throws boost::system::system_error Thrown on failure. 1568 * 1569 * @par Example 1570 * @code 1571 * boost::asio::ip::tcp::socket socket(my_context); 1572 * ... 1573 * boost::asio::ip::tcp::endpoint endpoint = socket.local_endpoint(); 1574 * @endcode 1575 */ 1576 endpoint_type local_endpoint() const 1577 { 1578 boost::system::error_code ec; 1579 endpoint_type ep = impl_.get_service().local_endpoint( 1580 impl_.get_implementation(), ec); 1581 boost::asio::detail::throw_error(ec, "local_endpoint"); 1582 return ep; 1583 } 1584 1585 /// Get the local endpoint of the socket. 1586 /** 1587 * This function is used to obtain the locally bound endpoint of the socket. 1588 * 1589 * @param ec Set to indicate what error occurred, if any. 1590 * 1591 * @returns An object that represents the local endpoint of the socket. 1592 * Returns a default-constructed endpoint object if an error occurred. 1593 * 1594 * @par Example 1595 * @code 1596 * boost::asio::ip::tcp::socket socket(my_context); 1597 * ... 1598 * boost::system::error_code ec; 1599 * boost::asio::ip::tcp::endpoint endpoint = socket.local_endpoint(ec); 1600 * if (ec) 1601 * { 1602 * // An error occurred. 1603 * } 1604 * @endcode 1605 */ 1606 endpoint_type local_endpoint(boost::system::error_code& ec) const 1607 { 1608 return impl_.get_service().local_endpoint(impl_.get_implementation(), ec); 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 * @returns An object that represents the remote endpoint of the socket. 1616 * 1617 * @throws boost::system::system_error Thrown on failure. 1618 * 1619 * @par Example 1620 * @code 1621 * boost::asio::ip::tcp::socket socket(my_context); 1622 * ... 1623 * boost::asio::ip::tcp::endpoint endpoint = socket.remote_endpoint(); 1624 * @endcode 1625 */ 1626 endpoint_type remote_endpoint() const 1627 { 1628 boost::system::error_code ec; 1629 endpoint_type ep = impl_.get_service().remote_endpoint( 1630 impl_.get_implementation(), ec); 1631 boost::asio::detail::throw_error(ec, "remote_endpoint"); 1632 return ep; 1633 } 1634 1635 /// Get the remote endpoint of the socket. 1636 /** 1637 * This function is used to obtain the remote endpoint of the socket. 1638 * 1639 * @param ec Set to indicate what error occurred, if any. 1640 * 1641 * @returns An object that represents the remote endpoint of the socket. 1642 * Returns a default-constructed endpoint object if an error occurred. 1643 * 1644 * @par Example 1645 * @code 1646 * boost::asio::ip::tcp::socket socket(my_context); 1647 * ... 1648 * boost::system::error_code ec; 1649 * boost::asio::ip::tcp::endpoint endpoint = socket.remote_endpoint(ec); 1650 * if (ec) 1651 * { 1652 * // An error occurred. 1653 * } 1654 * @endcode 1655 */ 1656 endpoint_type remote_endpoint(boost::system::error_code& ec) const 1657 { 1658 return impl_.get_service().remote_endpoint(impl_.get_implementation(), ec); 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 * @throws boost::system::system_error Thrown on failure. 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 * socket.shutdown(boost::asio::ip::tcp::socket::shutdown_send); 1676 * @endcode 1677 */ 1678 void shutdown(shutdown_type what) 1679 { 1680 boost::system::error_code ec; 1681 impl_.get_service().shutdown(impl_.get_implementation(), what, ec); 1682 boost::asio::detail::throw_error(ec, "shutdown"); 1683 } 1684 1685 /// Disable sends or receives on the socket. 1686 /** 1687 * This function is used to disable send operations, receive operations, or 1688 * both. 1689 * 1690 * @param what Determines what types of operation will no longer be allowed. 1691 * 1692 * @param ec Set to indicate what error occurred, if any. 1693 * 1694 * @par Example 1695 * Shutting down the send side of the socket: 1696 * @code 1697 * boost::asio::ip::tcp::socket socket(my_context); 1698 * ... 1699 * boost::system::error_code ec; 1700 * socket.shutdown(boost::asio::ip::tcp::socket::shutdown_send, ec); 1701 * if (ec) 1702 * { 1703 * // An error occurred. 1704 * } 1705 * @endcode 1706 */ 1707 BOOST_ASIO_SYNC_OP_VOID shutdown(shutdown_type what, 1708 boost::system::error_code& ec) 1709 { 1710 impl_.get_service().shutdown(impl_.get_implementation(), what, ec); 1711 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); 1712 } 1713 1714 /// Wait for the socket to become ready to read, ready to write, or to have 1715 /// pending error conditions. 1716 /** 1717 * This function is used to perform a blocking wait for a socket to enter 1718 * a ready to read, write or error condition state. 1719 * 1720 * @param w Specifies the desired socket state. 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 * socket.wait(boost::asio::ip::tcp::socket::wait_read); 1728 * @endcode 1729 */ 1730 void wait(wait_type w) 1731 { 1732 boost::system::error_code ec; 1733 impl_.get_service().wait(impl_.get_implementation(), w, ec); 1734 boost::asio::detail::throw_error(ec, "wait"); 1735 } 1736 1737 /// Wait for the socket to become ready to read, ready to write, or to have 1738 /// pending error conditions. 1739 /** 1740 * This function is used to perform a blocking 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 ec Set to indicate what error occurred, if any. 1746 * 1747 * @par Example 1748 * Waiting for a socket to become readable. 1749 * @code 1750 * boost::asio::ip::tcp::socket socket(my_context); 1751 * ... 1752 * boost::system::error_code ec; 1753 * socket.wait(boost::asio::ip::tcp::socket::wait_read, ec); 1754 * @endcode 1755 */ 1756 BOOST_ASIO_SYNC_OP_VOID wait(wait_type w, boost::system::error_code& ec) 1757 { 1758 impl_.get_service().wait(impl_.get_implementation(), w, ec); 1759 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); 1760 } 1761 1762 /// Asynchronously wait for the socket to become ready to read, ready to 1763 /// write, or to have pending error conditions. 1764 /** 1765 * This function is used to perform an asynchronous wait for a socket to enter 1766 * a ready to read, write or error condition state. It is an initiating 1767 * function for an @ref asynchronous_operation, and always returns 1768 * immediately. 1769 * 1770 * @param w Specifies the desired socket state. 1771 * 1772 * @param token The @ref completion_token that will be used to produce a 1773 * completion handler, which will be called when the wait completes. Potential 1774 * completion tokens include @ref use_future, @ref use_awaitable, @ref 1775 * yield_context, or a function object with the correct completion signature. 1776 * The function signature of the completion handler must be: 1777 * @code void handler( 1778 * const boost::system::error_code& error // Result of operation. 1779 * ); @endcode 1780 * Regardless of whether the asynchronous operation completes immediately or 1781 * not, the completion handler will not be invoked from within this function. 1782 * On immediate completion, invocation of the handler will be performed in a 1783 * manner equivalent to using boost::asio::post(). 1784 * 1785 * @par Completion Signature 1786 * @code void(boost::system::error_code) @endcode 1787 * 1788 * @par Example 1789 * @code 1790 * void wait_handler(const boost::system::error_code& error) 1791 * { 1792 * if (!error) 1793 * { 1794 * // Wait succeeded. 1795 * } 1796 * } 1797 * 1798 * ... 1799 * 1800 * boost::asio::ip::tcp::socket socket(my_context); 1801 * ... 1802 * socket.async_wait(boost::asio::ip::tcp::socket::wait_read, wait_handler); 1803 * @endcode 1804 * 1805 * @par Per-Operation Cancellation 1806 * On POSIX or Windows operating systems, this asynchronous operation supports 1807 * cancellation for the following boost::asio::cancellation_type values: 1808 * 1809 * @li @c cancellation_type::terminal 1810 * 1811 * @li @c cancellation_type::partial 1812 * 1813 * @li @c cancellation_type::total 1814 */ 1815 template < 1816 BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code)) 1817 WaitToken = default_completion_token_t<executor_type>> 1818 auto async_wait(wait_type w, 1819 WaitToken&& token = default_completion_token_t<executor_type>()) 1820 -> decltype( 1821 async_initiate<WaitToken, void (boost::system::error_code)>( 1822 declval<initiate_async_wait>(), token, w)) 1823 { 1824 return async_initiate<WaitToken, void (boost::system::error_code)>( 1825 initiate_async_wait(this), token, w); 1826 } 1827 1828 protected: 1829 /// Protected destructor to prevent deletion through this type. 1830 /** 1831 * This function destroys the socket, cancelling any outstanding asynchronous 1832 * operations associated with the socket as if by calling @c cancel. 1833 */ 1834 ~basic_socket() 1835 { 1836 } 1837 1838 #if defined(BOOST_ASIO_WINDOWS_RUNTIME) 1839 detail::io_object_impl< 1840 detail::null_socket_service<Protocol>, Executor> impl_; 1841 #elif defined(BOOST_ASIO_HAS_IOCP) 1842 detail::io_object_impl< 1843 detail::win_iocp_socket_service<Protocol>, Executor> impl_; 1844 #elif defined(BOOST_ASIO_HAS_IO_URING_AS_DEFAULT) 1845 detail::io_object_impl< 1846 detail::io_uring_socket_service<Protocol>, Executor> impl_; 1847 #else 1848 detail::io_object_impl< 1849 detail::reactive_socket_service<Protocol>, Executor> impl_; 1850 #endif 1851 1852 private: 1853 // Disallow copying and assignment. 1854 basic_socket(const basic_socket&) = delete; 1855 basic_socket& operator=(const basic_socket&) = delete; 1856 1857 class initiate_async_connect 1858 { 1859 public: 1860 typedef Executor executor_type; 1861 1862 explicit initiate_async_connect(basic_socket* self) 1863 : self_(self) 1864 { 1865 } 1866 1867 const executor_type& get_executor() const noexcept 1868 { 1869 return self_->get_executor(); 1870 } 1871 1872 template <typename ConnectHandler> 1873 void operator()(ConnectHandler&& handler, 1874 const endpoint_type& peer_endpoint, 1875 const boost::system::error_code& open_ec) const 1876 { 1877 // If you get an error on the following line it means that your handler 1878 // does not meet the documented type requirements for a ConnectHandler. 1879 BOOST_ASIO_CONNECT_HANDLER_CHECK(ConnectHandler, handler) type_check; 1880 1881 if (open_ec) 1882 { 1883 boost::asio::post(self_->impl_.get_executor(), 1884 boost::asio::detail::bind_handler( 1885 static_cast<ConnectHandler&&>(handler), open_ec)); 1886 } 1887 else 1888 { 1889 detail::non_const_lvalue<ConnectHandler> handler2(handler); 1890 self_->impl_.get_service().async_connect( 1891 self_->impl_.get_implementation(), peer_endpoint, 1892 handler2.value, self_->impl_.get_executor()); 1893 } 1894 } 1895 1896 private: 1897 basic_socket* self_; 1898 }; 1899 1900 class initiate_async_wait 1901 { 1902 public: 1903 typedef Executor executor_type; 1904 1905 explicit initiate_async_wait(basic_socket* self) 1906 : self_(self) 1907 { 1908 } 1909 1910 const executor_type& get_executor() const noexcept 1911 { 1912 return self_->get_executor(); 1913 } 1914 1915 template <typename WaitHandler> 1916 void operator()(WaitHandler&& handler, wait_type w) const 1917 { 1918 // If you get an error on the following line it means that your handler 1919 // does not meet the documented type requirements for a WaitHandler. 1920 BOOST_ASIO_WAIT_HANDLER_CHECK(WaitHandler, handler) type_check; 1921 1922 detail::non_const_lvalue<WaitHandler> handler2(handler); 1923 self_->impl_.get_service().async_wait( 1924 self_->impl_.get_implementation(), w, 1925 handler2.value, self_->impl_.get_executor()); 1926 } 1927 1928 private: 1929 basic_socket* self_; 1930 }; 1931 }; 1932 1933 } // namespace asio 1934 } // namespace boost 1935 1936 #include <boost/asio/detail/pop_options.hpp> 1937 1938 #endif // BOOST_ASIO_BASIC_SOCKET_HPP
[ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
This page was automatically generated by the 2.3.7 LXR engine. The LXR team |