From 86fbd3a46397fb3b958af8a4b4c3fa3f85ac8655 Mon Sep 17 00:00:00 2001 From: Alexander Larsson Date: Wed, 23 Feb 2022 10:19:20 +0100 Subject: [PATCH] Support boost 1.76 This adds support for boost 1.76. For this to work we needed a new version of the boost helpers, because boost 1.76beta1 added this change: https://github.com/boostorg/asio/commit/1c16c45a3d447f685dfa7a9b704d26f10b0f3e29 The introduction of these dummy arguments to the constructor of boost::asio::detail::io_object_impl need to be mirrored in the basic socket helpers. --- CMakeLists.txt | 6 +- .../boost/asio/basic_datagram_socket_ext.hpp | 1118 ++++++++ .../boost/asio/basic_socket_acceptor_ext.hpp | 2381 +++++++++++++++++ .../1.76/boost/asio/basic_socket_ext.hpp | 1859 +++++++++++++ .../boost/asio/basic_socket_ext_local.hpp | 1859 +++++++++++++ .../boost/asio/basic_stream_socket_ext.hpp | 996 +++++++ .../detail/handler_type_requirements_ext.hpp | 586 ++++ .../handler_type_requirements_ext_local.hpp | 588 ++++ .../impl/reactive_socket_service_base_ext.ipp | 302 +++ ...reactive_socket_service_base_ext_local.ipp | 302 +++ .../boost/asio/detail/impl/socket_ops_ext.ipp | 234 ++ .../asio/detail/impl/socket_ops_ext_local.ipp | 307 +++ .../detail/reactive_socket_recv_op_ext.hpp | 162 ++ .../reactive_socket_recv_op_ext_local.hpp | 162 ++ .../reactive_socket_recvfrom_op_ext.hpp | 153 ++ .../reactive_socket_recvfrom_op_ext_local.hpp | 148 + .../detail/reactive_socket_recvmsg_op_ext.hpp | 144 + .../reactive_socket_recvmsg_op_ext_local.hpp | 145 + .../reactive_socket_service_base_ext.hpp | 524 ++++ ...reactive_socket_service_base_ext_local.hpp | 524 ++++ .../detail/reactive_socket_service_ext.hpp | 508 ++++ .../reactive_socket_service_ext_local.hpp | 508 ++++ .../1.76/boost/asio/detail/reactor_op_ext.hpp | 43 + .../asio/detail/reactor_op_ext_local.hpp | 44 + .../1.76/boost/asio/detail/socket_ops_ext.hpp | 62 + .../asio/detail/socket_ops_ext_local.hpp | 95 + .../helper/1.76/boost/asio/ip/udp_ext.hpp | 115 + .../boost/asio/local/stream_protocol_ext.hpp | 93 + 28 files changed, 13966 insertions(+), 2 deletions(-) create mode 100644 implementation/helper/1.76/boost/asio/basic_datagram_socket_ext.hpp create mode 100644 implementation/helper/1.76/boost/asio/basic_socket_acceptor_ext.hpp create mode 100644 implementation/helper/1.76/boost/asio/basic_socket_ext.hpp create mode 100644 implementation/helper/1.76/boost/asio/basic_socket_ext_local.hpp create mode 100644 implementation/helper/1.76/boost/asio/basic_stream_socket_ext.hpp create mode 100644 implementation/helper/1.76/boost/asio/detail/handler_type_requirements_ext.hpp create mode 100644 implementation/helper/1.76/boost/asio/detail/handler_type_requirements_ext_local.hpp create mode 100644 implementation/helper/1.76/boost/asio/detail/impl/reactive_socket_service_base_ext.ipp create mode 100644 implementation/helper/1.76/boost/asio/detail/impl/reactive_socket_service_base_ext_local.ipp create mode 100644 implementation/helper/1.76/boost/asio/detail/impl/socket_ops_ext.ipp create mode 100644 implementation/helper/1.76/boost/asio/detail/impl/socket_ops_ext_local.ipp create mode 100644 implementation/helper/1.76/boost/asio/detail/reactive_socket_recv_op_ext.hpp create mode 100644 implementation/helper/1.76/boost/asio/detail/reactive_socket_recv_op_ext_local.hpp create mode 100644 implementation/helper/1.76/boost/asio/detail/reactive_socket_recvfrom_op_ext.hpp create mode 100644 implementation/helper/1.76/boost/asio/detail/reactive_socket_recvfrom_op_ext_local.hpp create mode 100644 implementation/helper/1.76/boost/asio/detail/reactive_socket_recvmsg_op_ext.hpp create mode 100644 implementation/helper/1.76/boost/asio/detail/reactive_socket_recvmsg_op_ext_local.hpp create mode 100644 implementation/helper/1.76/boost/asio/detail/reactive_socket_service_base_ext.hpp create mode 100644 implementation/helper/1.76/boost/asio/detail/reactive_socket_service_base_ext_local.hpp create mode 100644 implementation/helper/1.76/boost/asio/detail/reactive_socket_service_ext.hpp create mode 100644 implementation/helper/1.76/boost/asio/detail/reactive_socket_service_ext_local.hpp create mode 100644 implementation/helper/1.76/boost/asio/detail/reactor_op_ext.hpp create mode 100644 implementation/helper/1.76/boost/asio/detail/reactor_op_ext_local.hpp create mode 100644 implementation/helper/1.76/boost/asio/detail/socket_ops_ext.hpp create mode 100644 implementation/helper/1.76/boost/asio/detail/socket_ops_ext_local.hpp create mode 100644 implementation/helper/1.76/boost/asio/ip/udp_ext.hpp create mode 100644 implementation/helper/1.76/boost/asio/local/stream_protocol_ext.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 65148a5..4c7da8c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -164,8 +164,10 @@ else() endif() message( STATUS "Using boost version: ${VSOMEIP_BOOST_VERSION}" ) -if (${VSOMEIP_BOOST_VERSION} GREATER 107400) -message( ERROR "boost version ${VSOMEIP_BOOST_VERSION} is not (yet) supported. Latest supported version is 1.74.0" ) +if (${VSOMEIP_BOOST_VERSION} GREATER 107600) +message( ERROR "boost version ${VSOMEIP_BOOST_VERSION} is not (yet) supported. Latest supported version is 1.76.0" ) +elseif(${VSOMEIP_BOOST_VERSION} GREATER 107300) +set(VSOMEIP_BOOST_HELPER implementation/helper/1.76) elseif(${VSOMEIP_BOOST_VERSION} GREATER 107300) set(VSOMEIP_BOOST_HELPER implementation/helper/1.74) elseif(${VSOMEIP_BOOST_VERSION} GREATER 106999) diff --git a/implementation/helper/1.76/boost/asio/basic_datagram_socket_ext.hpp b/implementation/helper/1.76/boost/asio/basic_datagram_socket_ext.hpp new file mode 100644 index 0000000..49a4950 --- /dev/null +++ b/implementation/helper/1.76/boost/asio/basic_datagram_socket_ext.hpp @@ -0,0 +1,1118 @@ +// +// basic_datagram_socket_ext.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (C) 2016-2019 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_BASIC_DATAGRAM_SOCKET_EXT_HPP +#define BOOST_ASIO_BASIC_DATAGRAM_SOCKET_EXT_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace boost { +namespace asio { + +#if !defined(BOOST_ASIO_BASIC_DATAGRAM_SOCKET_EXT_FWD_DECL) +#define BOOST_ASIO_BASIC_DATAGRAM_SOCKET_EXT_FWD_DECL + +// Forward declaration with defaulted arguments. +template +class basic_datagram_socket_ext; + +#endif // !defined(BOOST_ASIO_BASIC_DATAGRAM_SOCKET_EXT_FWD_DECL) + +/// Provides datagram-oriented socket functionality. +/** + * The basic_datagram_socket class template provides asynchronous and blocking + * datagram-oriented socket functionality. + * + * @par Thread Safety + * @e Distinct @e objects: Safe.@n + * @e Shared @e objects: Unsafe. + */ +template +class basic_datagram_socket_ext + : public basic_socket_ext +{ +public: + /// The type of the executor associated with the object. + typedef Executor executor_type; + + /// Rebinds the socket type to another executor. + template + struct rebind_executor + { + /// The socket type when rebound to the specified executor. + typedef basic_datagram_socket_ext other; + }; + + /// The native representation of a socket. +#if defined(GENERATING_DOCUMENTATION) + typedef implementation_defined native_handle_type; +#else + typedef typename basic_socket_ext::native_handle_type native_handle_type; +#endif + + /// The protocol type. + typedef Protocol protocol_type; + + /// The endpoint type. + typedef typename Protocol::endpoint endpoint_type; + + /// Construct a basic_datagram_socket without opening it. + /** + * This constructor creates a datagram socket without opening it. The open() + * function must be called before data can be sent or received on the socket. + * + * @param ex The I/O executor that the socket will use, by default, to + * dispatch handlers for any asynchronous operations performed on the socket. + */ + explicit basic_datagram_socket_ext(const executor_type& ex) + : basic_socket_ext(ex) + { + } + + /// Construct a basic_datagram_socket without opening it. + /** + * This constructor creates a datagram socket without opening it. The open() + * function must be called before data can be sent or received on the socket. + * + * @param context An execution context which provides the I/O executor that + * the socket will use, by default, to dispatch handlers for any asynchronous + * operations performed on the socket. + */ + template + explicit basic_datagram_socket_ext(ExecutionContext& context, + typename enable_if< + is_convertible::value + >::type* = 0) + : basic_socket_ext(context) + { + } + + /// Construct and open a basic_datagram_socket. + /** + * This constructor creates and opens a datagram socket. + * + * @param ex The I/O executor that the socket will use, by default, to + * dispatch handlers for any asynchronous operations performed on the socket. + * + * @param protocol An object specifying protocol parameters to be used. + * + * @throws boost::system::system_error Thrown on failure. + */ + basic_datagram_socket_ext(const executor_type& ex, const protocol_type& protocol) + : basic_socket_ext(ex, protocol) + { + } + + /// Construct and open a basic_datagram_socket. + /** + * This constructor creates and opens a datagram socket. + * + * @param context An execution context which provides the I/O executor that + * the socket will use, by default, to dispatch handlers for any asynchronous + * operations performed on the socket. + * + * @param protocol An object specifying protocol parameters to be used. + * + * @throws boost::system::system_error Thrown on failure. + */ + template + basic_datagram_socket_ext(ExecutionContext& context, + const protocol_type& protocol, + typename enable_if< + is_convertible::value + >::type* = 0) + : basic_socket_ext(context, protocol) + { + } + + /// Construct a basic_datagram_socket, opening it and binding it to the given + /// local endpoint. + /** + * This constructor creates a datagram socket and automatically opens it bound + * to the specified endpoint on the local machine. The protocol used is the + * protocol associated with the given endpoint. + * + * @param ex The I/O executor that the socket will use, by default, to + * dispatch handlers for any asynchronous operations performed on the socket. + * + * @param endpoint An endpoint on the local machine to which the datagram + * socket will be bound. + * + * @throws boost::system::system_error Thrown on failure. + */ + basic_datagram_socket_ext(const executor_type& ex, const endpoint_type& endpoint) + : basic_socket_ext(ex, endpoint) + { + } + + /// Construct a basic_datagram_socket, opening it and binding it to the given + /// local endpoint. + /** + * This constructor creates a datagram socket and automatically opens it bound + * to the specified endpoint on the local machine. The protocol used is the + * protocol associated with the given endpoint. + * + * @param context An execution context which provides the I/O executor that + * the socket will use, by default, to dispatch handlers for any asynchronous + * operations performed on the socket. + * + * @param endpoint An endpoint on the local machine to which the datagram + * socket will be bound. + * + * @throws boost::system::system_error Thrown on failure. + */ + template + basic_datagram_socket_ext(ExecutionContext& context, + const endpoint_type& endpoint, + typename enable_if< + is_convertible::value + >::type* = 0) + : basic_socket_ext(context, endpoint) + { + } + + /// Construct a basic_datagram_socket on an existing native socket. + /** + * This constructor creates a datagram socket object to hold an existing + * native socket. + * + * @param ex The I/O executor that the socket will use, by default, to + * dispatch handlers for any asynchronous operations performed on the socket. + * + * @param protocol An object specifying protocol parameters to be used. + * + * @param native_socket The new underlying socket implementation. + * + * @throws boost::system::system_error Thrown on failure. + */ + basic_datagram_socket_ext(const executor_type& ex, + const protocol_type& protocol, const native_handle_type& native_socket) + : basic_socket_ext(ex, protocol, native_socket) + { + } + + /// Construct a basic_datagram_socket on an existing native socket. + /** + * This constructor creates a datagram socket object to hold an existing + * native socket. + * + * @param context An execution context which provides the I/O executor that + * the socket will use, by default, to dispatch handlers for any asynchronous + * operations performed on the socket. + * + * @param protocol An object specifying protocol parameters to be used. + * + * @param native_socket The new underlying socket implementation. + * + * @throws boost::system::system_error Thrown on failure. + */ + template + basic_datagram_socket_ext(ExecutionContext& context, + const protocol_type& protocol, const native_handle_type& native_socket, + typename enable_if< + is_convertible::value + >::type* = 0) + : basic_socket_ext(context, protocol, native_socket) + { + } + +#if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) + /// Move-construct a basic_datagram_socket from another. + /** + * This constructor moves a datagram socket from one object to another. + * + * @param other The other basic_datagram_socket object from which the move + * will occur. + * + * @note Following the move, the moved-from object is in the same state as if + * constructed using the @c basic_datagram_socket(const executor_type&) + * constructor. + */ + basic_datagram_socket_ext(basic_datagram_socket_ext&& other) + : basic_socket_ext(std::move(other)) + { + } + + /// Move-assign a basic_datagram_socket from another. + /** + * This assignment operator moves a datagram socket from one object to + * another. + * + * @param other The other basic_datagram_socket object from which the move + * will occur. + * + * @note Following the move, the moved-from object is in the same state as if + * constructed using the @c basic_datagram_socket(const executor_type&) + * constructor. + */ + basic_datagram_socket_ext& operator=(basic_datagram_socket_ext&& other) + { + basic_socket_ext::operator=(std::move(other)); + return *this; + } + + /// Move-construct a basic_datagram_socket from a socket of another protocol + /// type. + /** + * This constructor moves a datagram socket from one object to another. + * + * @param other The other basic_datagram_socket object from which the move + * will occur. + * + * @note Following the move, the moved-from object is in the same state as if + * constructed using the @c basic_datagram_socket(const executor_type&) + * constructor. + */ + template + basic_datagram_socket_ext(basic_datagram_socket_ext&& other, + typename enable_if< + is_convertible::value + && is_convertible::value + >::type* = 0) + : basic_socket_ext(std::move(other)) + { + } + + /// Move-assign a basic_datagram_socket from a socket of another protocol + /// type. + /** + * This assignment operator moves a datagram socket from one object to + * another. + * + * @param other The other basic_datagram_socket object from which the move + * will occur. + * + * @note Following the move, the moved-from object is in the same state as if + * constructed using the @c basic_datagram_socket(const executor_type&) + * constructor. + */ + template + typename enable_if< + is_convertible::value + && is_convertible::value, + basic_datagram_socket_ext& + >::type operator=(basic_datagram_socket_ext&& other) + { + basic_socket_ext::operator=(std::move(other)); + return *this; + } +#endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) + + /// Destroys the socket. + /** + * This function destroys the socket, cancelling any outstanding asynchronous + * operations associated with the socket as if by calling @c cancel. + */ + ~basic_datagram_socket_ext() + { + } + + /// Send some data on a connected socket. + /** + * This function is used to send data on the datagram socket. The function + * call will block until the data has been sent successfully or an error + * occurs. + * + * @param buffers One ore more data buffers to be sent on the socket. + * + * @returns The number of bytes sent. + * + * @throws boost::system::system_error Thrown on failure. + * + * @note The send operation can only be used with a connected socket. Use + * the send_to function to send data on an unconnected datagram socket. + * + * @par Example + * To send a single data buffer use the @ref buffer function as follows: + * @code socket.send(boost::asio::buffer(data, size)); @endcode + * See the @ref buffer documentation for information on sending multiple + * buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ + template + std::size_t send(const ConstBufferSequence& buffers) + { + boost::system::error_code ec; + std::size_t s = this->impl_.get_service().send( + this->impl_.get_implementation(), buffers, 0, ec); + boost::asio::detail::throw_error(ec, "send"); + return s; + } + + /// Send some data on a connected socket. + /** + * This function is used to send data on the datagram socket. The function + * call will block until the data has been sent successfully or an error + * occurs. + * + * @param buffers One ore more data buffers to be sent on the socket. + * + * @param flags Flags specifying how the send call is to be made. + * + * @returns The number of bytes sent. + * + * @throws boost::system::system_error Thrown on failure. + * + * @note The send operation can only be used with a connected socket. Use + * the send_to function to send data on an unconnected datagram socket. + */ + template + std::size_t send(const ConstBufferSequence& buffers, + socket_base::message_flags flags) + { + boost::system::error_code ec; + std::size_t s = this->impl_.get_service().send( + this->impl_.get_implementation(), buffers, flags, ec); + boost::asio::detail::throw_error(ec, "send"); + return s; + } + + /// Send some data on a connected socket. + /** + * This function is used to send data on the datagram socket. The function + * call will block until the data has been sent successfully or an error + * occurs. + * + * @param buffers One or more data buffers to be sent on the socket. + * + * @param flags Flags specifying how the send call is to be made. + * + * @param ec Set to indicate what error occurred, if any. + * + * @returns The number of bytes sent. + * + * @note The send operation can only be used with a connected socket. Use + * the send_to function to send data on an unconnected datagram socket. + */ + template + std::size_t send(const ConstBufferSequence& buffers, + socket_base::message_flags flags, boost::system::error_code& ec) + { + return this->impl_.get_service().send( + this->impl_.get_implementation(), buffers, flags, ec); + } + + /// Start an asynchronous send on a connected socket. + /** + * This function is used to asynchronously send data on the datagram socket. + * The function call always returns immediately. + * + * @param buffers One or more data buffers to be sent on the socket. Although + * the buffers object may be copied as necessary, ownership of the underlying + * memory blocks is retained by the caller, which must guarantee that they + * remain valid until the handler is called. + * + * @param handler The handler to be called when the send operation completes. + * Copies will be made of the handler as required. The function signature of + * the handler must be: + * @code void handler( + * const boost::system::error_code& error, // Result of operation. + * std::size_t bytes_transferred // Number of bytes sent. + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. On + * immediate completion, invocation of the handler will be performed in a + * manner equivalent to using boost::asio::post(). + * + * @note The async_send operation can only be used with a connected socket. + * Use the async_send_to function to send data on an unconnected datagram + * socket. + * + * @par Example + * To send a single data buffer use the @ref buffer function as follows: + * @code + * socket.async_send(boost::asio::buffer(data, size), handler); + * @endcode + * See the @ref buffer documentation for information on sending multiple + * buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ + template + BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler, + void (boost::system::error_code, std::size_t)) + async_send(const ConstBufferSequence& buffers, + BOOST_ASIO_MOVE_ARG(WriteHandler) handler) + { + return async_initiate( + initiate_async_send(), handler, this, + buffers, socket_base::message_flags(0)); + } + + /// Start an asynchronous send on a connected socket. + /** + * This function is used to asynchronously send data on the datagram socket. + * The function call always returns immediately. + * + * @param buffers One or more data buffers to be sent on the socket. Although + * the buffers object may be copied as necessary, ownership of the underlying + * memory blocks is retained by the caller, which must guarantee that they + * remain valid until the handler is called. + * + * @param flags Flags specifying how the send call is to be made. + * + * @param handler The handler to be called when the send operation completes. + * Copies will be made of the handler as required. The function signature of + * the handler must be: + * @code void handler( + * const boost::system::error_code& error, // Result of operation. + * std::size_t bytes_transferred // Number of bytes sent. + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. On + * immediate completion, invocation of the handler will be performed in a + * manner equivalent to using boost::asio::post(). + * + * @note The async_send operation can only be used with a connected socket. + * Use the async_send_to function to send data on an unconnected datagram + * socket. + */ + template + BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler, + void (boost::system::error_code, std::size_t)) + async_send(const ConstBufferSequence& buffers, + socket_base::message_flags flags, + BOOST_ASIO_MOVE_ARG(WriteHandler) handler) + { + return async_initiate( + initiate_async_send(), handler, this, buffers, flags); + } + + /// Send a datagram to the specified endpoint. + /** + * This function is used to send a datagram to the specified remote endpoint. + * The function call will block until the data has been sent successfully or + * an error occurs. + * + * @param buffers One or more data buffers to be sent to the remote endpoint. + * + * @param destination The remote endpoint to which the data will be sent. + * + * @returns The number of bytes sent. + * + * @throws boost::system::system_error Thrown on failure. + * + * @par Example + * To send a single data buffer use the @ref buffer function as follows: + * @code + * boost::asio::ip::udp::endpoint destination( + * boost::asio::ip::address::from_string("1.2.3.4"), 12345); + * socket.send_to(boost::asio::buffer(data, size), destination); + * @endcode + * See the @ref buffer documentation for information on sending multiple + * buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ + template + std::size_t send_to(const ConstBufferSequence& buffers, + const endpoint_type& destination) + { + boost::system::error_code ec; + std::size_t s = this->impl_.get_service().send_to( + this->impl_.get_implementation(), buffers, destination, 0, ec); + boost::asio::detail::throw_error(ec, "send_to"); + return s; + } + + /// Send a datagram to the specified endpoint. + /** + * This function is used to send a datagram to the specified remote endpoint. + * The function call will block until the data has been sent successfully or + * an error occurs. + * + * @param buffers One or more data buffers to be sent to the remote endpoint. + * + * @param destination The remote endpoint to which the data will be sent. + * + * @param flags Flags specifying how the send call is to be made. + * + * @returns The number of bytes sent. + * + * @throws boost::system::system_error Thrown on failure. + */ + template + std::size_t send_to(const ConstBufferSequence& buffers, + const endpoint_type& destination, socket_base::message_flags flags) + { + boost::system::error_code ec; + std::size_t s = this->impl_.get_service().send_to( + this->impl_.get_implementation(), buffers, destination, flags, ec); + boost::asio::detail::throw_error(ec, "send_to"); + return s; + } + + /// Send a datagram to the specified endpoint. + /** + * This function is used to send a datagram to the specified remote endpoint. + * The function call will block until the data has been sent successfully or + * an error occurs. + * + * @param buffers One or more data buffers to be sent to the remote endpoint. + * + * @param destination The remote endpoint to which the data will be sent. + * + * @param flags Flags specifying how the send call is to be made. + * + * @param ec Set to indicate what error occurred, if any. + * + * @returns The number of bytes sent. + */ + template + std::size_t send_to(const ConstBufferSequence& buffers, + const endpoint_type& destination, socket_base::message_flags flags, + boost::system::error_code& ec) + { + return this->impl_.get_service().send_to(this->impl_.get_implementation(), + buffers, destination, flags, ec); + } + + /// Start an asynchronous send. + /** + * This function is used to asynchronously send a datagram to the specified + * remote endpoint. The function call always returns immediately. + * + * @param buffers One or more data buffers to be sent to the remote endpoint. + * Although the buffers object may be copied as necessary, ownership of the + * underlying memory blocks is retained by the caller, which must guarantee + * that they remain valid until the handler is called. + * + * @param destination The remote endpoint to which the data will be sent. + * Copies will be made of the endpoint as required. + * + * @param handler The handler to be called when the send operation completes. + * Copies will be made of the handler as required. The function signature of + * the handler must be: + * @code void handler( + * const boost::system::error_code& error, // Result of operation. + * std::size_t bytes_transferred // Number of bytes sent. + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. On + * immediate completion, invocation of the handler will be performed in a + * manner equivalent to using boost::asio::post(). + * + * @par Example + * To send a single data buffer use the @ref buffer function as follows: + * @code + * boost::asio::ip::udp::endpoint destination( + * boost::asio::ip::address::from_string("1.2.3.4"), 12345); + * socket.async_send_to( + * boost::asio::buffer(data, size), destination, handler); + * @endcode + * See the @ref buffer documentation for information on sending multiple + * buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ + template + BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler, + void (boost::system::error_code, std::size_t)) + async_send_to(const ConstBufferSequence& buffers, + const endpoint_type& destination, + BOOST_ASIO_MOVE_ARG(WriteHandler) handler) + { + return async_initiate( + initiate_async_send_to(), handler, this, buffers, + destination, socket_base::message_flags(0)); + } + + /// Start an asynchronous send. + /** + * This function is used to asynchronously send a datagram to the specified + * remote endpoint. The function call always returns immediately. + * + * @param buffers One or more data buffers to be sent to the remote endpoint. + * Although the buffers object may be copied as necessary, ownership of the + * underlying memory blocks is retained by the caller, which must guarantee + * that they remain valid until the handler is called. + * + * @param flags Flags specifying how the send call is to be made. + * + * @param destination The remote endpoint to which the data will be sent. + * Copies will be made of the endpoint as required. + * + * @param handler The handler to be called when the send operation completes. + * Copies will be made of the handler as required. The function signature of + * the handler must be: + * @code void handler( + * const boost::system::error_code& error, // Result of operation. + * std::size_t bytes_transferred // Number of bytes sent. + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. On + * immediate completion, invocation of the handler will be performed in a + * manner equivalent to using boost::asio::post(). + */ + template + BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler, + void (boost::system::error_code, std::size_t)) + async_send_to(const ConstBufferSequence& buffers, + const endpoint_type& destination, socket_base::message_flags flags, + BOOST_ASIO_MOVE_ARG(WriteHandler) handler) + { + return async_initiate( + initiate_async_send_to(), handler, this, buffers, destination, flags); + } + + /// Receive some data on a connected socket. + /** + * This function is used to receive data on the datagram socket. The function + * call will block until data has been received successfully or an error + * occurs. + * + * @param buffers One or more buffers into which the data will be received. + * + * @returns The number of bytes received. + * + * @throws boost::system::system_error Thrown on failure. + * + * @note The receive operation can only be used with a connected socket. Use + * the receive_from function to receive data on an unconnected datagram + * socket. + * + * @par Example + * To receive into a single data buffer use the @ref buffer function as + * follows: + * @code socket.receive(boost::asio::buffer(data, size)); @endcode + * See the @ref buffer documentation for information on receiving into + * multiple buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ + template + std::size_t receive(const MutableBufferSequence& buffers) + { + boost::system::error_code ec; + std::size_t s = this->impl_.get_service().receive( + this->impl_.get_implementation(), buffers, 0, ec); + boost::asio::detail::throw_error(ec, "receive"); + return s; + } + + /// Receive some data on a connected socket. + /** + * This function is used to receive data on the datagram socket. The function + * call will block until data has been received successfully or an error + * occurs. + * + * @param buffers One or more buffers into which the data will be received. + * + * @param flags Flags specifying how the receive call is to be made. + * + * @returns The number of bytes received. + * + * @throws boost::system::system_error Thrown on failure. + * + * @note The receive operation can only be used with a connected socket. Use + * the receive_from function to receive data on an unconnected datagram + * socket. + */ + template + std::size_t receive(const MutableBufferSequence& buffers, + socket_base::message_flags flags) + { + boost::system::error_code ec; + std::size_t s = this->impl_.get_service().receive( + this->impl_.get_implementation(), buffers, flags, ec); + boost::asio::detail::throw_error(ec, "receive"); + return s; + } + + /// Receive some data on a connected socket. + /** + * This function is used to receive data on the datagram socket. The function + * call will block until data has been received successfully or an error + * occurs. + * + * @param buffers One or more buffers into which the data will be received. + * + * @param flags Flags specifying how the receive call is to be made. + * + * @param ec Set to indicate what error occurred, if any. + * + * @returns The number of bytes received. + * + * @note The receive operation can only be used with a connected socket. Use + * the receive_from function to receive data on an unconnected datagram + * socket. + */ + template + std::size_t receive(const MutableBufferSequence& buffers, + socket_base::message_flags flags, boost::system::error_code& ec) + { + return this->impl_.get_service().receive( + this->impl_.get_implementation(), buffers, flags, ec); + } + + /// Start an asynchronous receive on a connected socket. + /** + * This function is used to asynchronously receive data from the datagram + * socket. The function call always returns immediately. + * + * @param buffers One or more buffers into which the data will be received. + * Although the buffers object may be copied as necessary, ownership of the + * underlying memory blocks is retained by the caller, which must guarantee + * that they remain valid until the handler is called. + * + * @param handler The handler to be called when the receive operation + * completes. Copies will be made of the handler as required. The function + * signature of the handler must be: + * @code void handler( + * const boost::system::error_code& error, // Result of operation. + * std::size_t bytes_transferred // Number of bytes received. + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. On + * immediate completion, invocation of the handler will be performed in a + * manner equivalent to using boost::asio::post(). + * + * @note The async_receive operation can only be used with a connected socket. + * Use the async_receive_from function to receive data on an unconnected + * datagram socket. + * + * @par Example + * To receive into a single data buffer use the @ref buffer function as + * follows: + * @code + * socket.async_receive(boost::asio::buffer(data, size), handler); + * @endcode + * See the @ref buffer documentation for information on receiving into + * multiple buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ + template + BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler, + void (boost::system::error_code, std::size_t, boost::asio::ip::address)) + async_receive(const MutableBufferSequence& buffers, + BOOST_ASIO_MOVE_ARG(ReadHandler) handler) + { + return async_initiate( + initiate_async_receive(), handler, this, + buffers, socket_base::message_flags(0)); + } + + /// Start an asynchronous receive on a connected socket. + /** + * This function is used to asynchronously receive data from the datagram + * socket. The function call always returns immediately. + * + * @param buffers One or more buffers into which the data will be received. + * Although the buffers object may be copied as necessary, ownership of the + * underlying memory blocks is retained by the caller, which must guarantee + * that they remain valid until the handler is called. + * + * @param flags Flags specifying how the receive call is to be made. + * + * @param handler The handler to be called when the receive operation + * completes. Copies will be made of the handler as required. The function + * signature of the handler must be: + * @code void handler( + * const boost::system::error_code& error, // Result of operation. + * std::size_t bytes_transferred // Number of bytes received. + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. On + * immediate completion, invocation of the handler will be performed in a + * manner equivalent to using boost::asio::post(). + * + * @note The async_receive operation can only be used with a connected socket. + * Use the async_receive_from function to receive data on an unconnected + * datagram socket. + */ + template + BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler, + void (boost::system::error_code, std::size_t, boost::asio::ip::address)) + async_receive(const MutableBufferSequence& buffers, + socket_base::message_flags flags, + BOOST_ASIO_MOVE_ARG(ReadHandler) handler) + { + return async_initiate( + initiate_async_receive(), handler, this, buffers, flags); + } + + /// Receive a datagram with the endpoint of the sender. + /** + * This function is used to receive a datagram. The function call will block + * until data has been received successfully or an error occurs. + * + * @param buffers One or more buffers into which the data will be received. + * + * @param sender_endpoint An endpoint object that receives the endpoint of + * the remote sender of the datagram. + * + * @returns The number of bytes received. + * + * @throws boost::system::system_error Thrown on failure. + * + * @par Example + * To receive into a single data buffer use the @ref buffer function as + * follows: + * @code + * boost::asio::ip::udp::endpoint sender_endpoint; + * socket.receive_from( + * boost::asio::buffer(data, size), sender_endpoint); + * @endcode + * See the @ref buffer documentation for information on receiving into + * multiple buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ + template + std::size_t receive_from(const MutableBufferSequence& buffers, + endpoint_type& sender_endpoint) + { + boost::system::error_code ec; + std::size_t s = this->impl_.get_service().receive_from( + this->impl_.get_implementation(), buffers, sender_endpoint, 0, ec); + boost::asio::detail::throw_error(ec, "receive_from"); + return s; + } + + /// Receive a datagram with the endpoint of the sender. + /** + * This function is used to receive a datagram. The function call will block + * until data has been received successfully or an error occurs. + * + * @param buffers One or more buffers into which the data will be received. + * + * @param sender_endpoint An endpoint object that receives the endpoint of + * the remote sender of the datagram. + * + * @param flags Flags specifying how the receive call is to be made. + * + * @returns The number of bytes received. + * + * @throws boost::system::system_error Thrown on failure. + */ + template + std::size_t receive_from(const MutableBufferSequence& buffers, + endpoint_type& sender_endpoint, socket_base::message_flags flags) + { + boost::system::error_code ec; + std::size_t s = this->impl_.get_service().receive_from( + this->impl_.get_implementation(), buffers, sender_endpoint, flags, ec); + boost::asio::detail::throw_error(ec, "receive_from"); + return s; + } + + /// Receive a datagram with the endpoint of the sender. + /** + * This function is used to receive a datagram. The function call will block + * until data has been received successfully or an error occurs. + * + * @param buffers One or more buffers into which the data will be received. + * + * @param sender_endpoint An endpoint object that receives the endpoint of + * the remote sender of the datagram. + * + * @param flags Flags specifying how the receive call is to be made. + * + * @param ec Set to indicate what error occurred, if any. + * + * @returns The number of bytes received. + */ + template + std::size_t receive_from(const MutableBufferSequence& buffers, + endpoint_type& sender_endpoint, socket_base::message_flags flags, + boost::system::error_code& ec) + { + return this->impl_.get_service().receive_from( + this->impl_.get_implementation(), buffers, sender_endpoint, flags, ec); + } + + /// Start an asynchronous receive. + /** + * This function is used to asynchronously receive a datagram. The function + * call always returns immediately. + * + * @param buffers One or more buffers into which the data will be received. + * Although the buffers object may be copied as necessary, ownership of the + * underlying memory blocks is retained by the caller, which must guarantee + * that they remain valid until the handler is called. + * + * @param sender_endpoint An endpoint object that receives the endpoint of + * the remote sender of the datagram. Ownership of the sender_endpoint object + * is retained by the caller, which must guarantee that it is valid until the + * handler is called. + * + * @param handler The handler to be called when the receive operation + * completes. Copies will be made of the handler as required. The function + * signature of the handler must be: + * @code void handler( + * const boost::system::error_code& error, // Result of operation. + * std::size_t bytes_transferred // Number of bytes received. + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. On + * immediate completion, invocation of the handler will be performed in a + * manner equivalent to using boost::asio::post(). + * + * @par Example + * To receive into a single data buffer use the @ref buffer function as + * follows: + * @code socket.async_receive_from( + * boost::asio::buffer(data, size), sender_endpoint, handler); @endcode + * See the @ref buffer documentation for information on receiving into + * multiple buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ + template + BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler, + void (boost::system::error_code, std::size_t, boost::asio::ip::address)) + async_receive_from(const MutableBufferSequence& buffers, + endpoint_type& sender_endpoint, + BOOST_ASIO_MOVE_ARG(ReadHandler) handler) + { + return async_initiate( + initiate_async_receive_from(), handler, this, buffers, + &sender_endpoint, socket_base::message_flags(0)); + } + + /// Start an asynchronous receive. + /** + * This function is used to asynchronously receive a datagram. The function + * call always returns immediately. + * + * @param buffers One or more buffers into which the data will be received. + * Although the buffers object may be copied as necessary, ownership of the + * underlying memory blocks is retained by the caller, which must guarantee + * that they remain valid until the handler is called. + * + * @param sender_endpoint An endpoint object that receives the endpoint of + * the remote sender of the datagram. Ownership of the sender_endpoint object + * is retained by the caller, which must guarantee that it is valid until the + * handler is called. + * + * @param flags Flags specifying how the receive call is to be made. + * + * @param handler The handler to be called when the receive operation + * completes. Copies will be made of the handler as required. The function + * signature of the handler must be: + * @code void handler( + * const boost::system::error_code& error, // Result of operation. + * std::size_t bytes_transferred // Number of bytes received. + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. On + * immediate completion, invocation of the handler will be performed in a + * manner equivalent to using boost::asio::post(). + */ + template + BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler, + void (boost::system::error_code, std::size_t, boost::asio::ip::address)) + async_receive_from(const MutableBufferSequence& buffers, + endpoint_type& sender_endpoint, socket_base::message_flags flags, + BOOST_ASIO_MOVE_ARG(ReadHandler) handler) + { + return async_initiate( + initiate_async_receive_from(), handler, + this, buffers, &sender_endpoint, flags); + } + +private: + struct initiate_async_send + { + template + void operator()(BOOST_ASIO_MOVE_ARG(WriteHandler) handler, + basic_datagram_socket_ext* self, const ConstBufferSequence& buffers, + socket_base::message_flags flags) const + { + // If you get an error on the following line it means that your handler + // does not meet the documented type requirements for a WriteHandler. + BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check; + + detail::non_const_lvalue handler2(handler); + self->impl_.get_service().async_send( + self->impl_.get_implementation(), buffers, flags, + handler2.value, self->impl_.get_executor()); + } + }; + + struct initiate_async_send_to + { + template + void operator()(BOOST_ASIO_MOVE_ARG(WriteHandler) handler, + basic_datagram_socket_ext* self, const ConstBufferSequence& buffers, + const endpoint_type& destination, + socket_base::message_flags flags) const + { + // If you get an error on the following line it means that your handler + // does not meet the documented type requirements for a WriteHandler. + BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check; + + detail::non_const_lvalue handler2(handler); + self->impl_.get_service().async_send_to( + self->impl_.get_implementation(), buffers, destination, flags, + handler2.value, self->impl_.get_executor()); + } + }; + + struct initiate_async_receive + { + template + void operator()(BOOST_ASIO_MOVE_ARG(ReadHandler) handler, + basic_datagram_socket_ext* self, const MutableBufferSequence& buffers, + socket_base::message_flags flags) const + { + // If you get an error on the following line it means that your handler + // does not meet the documented type requirements for a ReadHandler. + BOOST_ASIO_READ_HANDLER_CHECK_EXT(ReadHandler, handler) type_check; + + detail::non_const_lvalue handler2(handler); + self->impl_.get_service().async_receive( + self->impl_.get_implementation(), buffers, flags, + handler2.value, self->impl_.get_executor()); + } + }; + + struct initiate_async_receive_from + { + template + void operator()(BOOST_ASIO_MOVE_ARG(ReadHandler) handler, + basic_datagram_socket_ext* self, const MutableBufferSequence& buffers, + endpoint_type* sender_endpoint, socket_base::message_flags flags) const + { + // If you get an error on the following line it means that your handler + // does not meet the documented type requirements for a ReadHandler. + BOOST_ASIO_READ_HANDLER_CHECK_EXT(ReadHandler, handler) type_check; + + detail::non_const_lvalue handler2(handler); + self->impl_.get_service().async_receive_from( + self->impl_.get_implementation(), buffers, *sender_endpoint, flags, + handler2.value, self->impl_.get_executor()); + } + }; +}; + +} // namespace asio +} // namespace boost + +#include + +#endif // BOOST_ASIO_BASIC_DATAGRAM_SOCKET_EXT_HPP diff --git a/implementation/helper/1.76/boost/asio/basic_socket_acceptor_ext.hpp b/implementation/helper/1.76/boost/asio/basic_socket_acceptor_ext.hpp new file mode 100644 index 0000000..0a86539 --- /dev/null +++ b/implementation/helper/1.76/boost/asio/basic_socket_acceptor_ext.hpp @@ -0,0 +1,2381 @@ +// +// basic_socket_acceptor_ext.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2019 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_boost or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_BASIC_SOCKET_ACCEPTOR_EXT_HPP +#define BOOST_ASIO_BASIC_SOCKET_ACCEPTOR_EXT_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined(BOOST_ASIO_WINDOWS_RUNTIME) +# include +#elif defined(BOOST_ASIO_HAS_IOCP) +# include +#else +# include +#endif + +#if defined(BOOST_ASIO_HAS_MOVE) +# include +#endif // defined(BOOST_ASIO_HAS_MOVE) + +#include + +namespace boost { +namespace asio { + +#if !defined(BOOST_ASIO_BASIC_SOCKET_ACCEPTOR_EXT_FWD_DECL) +#define BOOST_ASIO_BASIC_SOCKET_ACCEPTOR_EXT_FWD_DECL + +// Forward declaration with defaulted arguments. +template +class basic_socket_acceptor_ext; + +#endif // !defined(BOOST_ASIO_BASIC_SOCKET_ACCEPTOR_EXT_FWD_DECL) + +/// Provides the ability to accept new connections. +/** + * The basic_socket_acceptor_ext class template is used for accepting new socket + * connections. + * + * @par Thread Safety + * @e Distinct @e objects: Safe.@n + * @e Shared @e objects: Unsafe. + * + * @par Example + * Opening a socket acceptor with the SO_REUSEADDR option enabled: + * @code + * boost::asio::ip::tcp::acceptor acceptor(my_context); + * boost::asio::ip::tcp::endpoint endpoint(boost::asio::ip::tcp::v4(), port); + * acceptor.open(endpoint.protocol()); + * acceptor.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true)); + * acceptor.bind(endpoint); + * acceptor.listen(); + * @endcode + */ +template +class basic_socket_acceptor_ext + : public socket_base +{ +public: + /// The type of the executor associated with the object. + typedef Executor executor_type; + + /// The native representation of an acceptor. +#if defined(GENERATING_DOCUMENTATION) + typedef implementation_defined native_handle_type; +#elif defined(BOOST_ASIO_WINDOWS_RUNTIME) + typedef typename detail::null_socket_service< + Protocol>::native_handle_type native_handle_type; +#elif defined(BOOST_ASIO_HAS_IOCP) + typedef typename detail::win_iocp_socket_service< + Protocol>::native_handle_type native_handle_type; +#else + typedef typename detail::reactive_socket_service_ext_local< + Protocol>::native_handle_type native_handle_type; +#endif + + /// The protocol type. + typedef Protocol protocol_type; + + /// The endpoint type. + typedef typename Protocol::endpoint endpoint_type; + + /// Construct an acceptor without opening it. + /** + * This constructor creates an acceptor without opening it to listen for new + * connections. The open() function must be called before the acceptor can + * accept new socket connections. + * + * @param ex The I/O executor that the acceptor will use, by default, to + * dispatch handlers for any asynchronous operations performed on the + * acceptor. + */ + explicit basic_socket_acceptor_ext(const executor_type& ex) + : impl_(0, ex) + { + } + + /// Construct an acceptor without opening it. + /** + * This constructor creates an acceptor without opening it to listen for new + * connections. The open() function must be called before the acceptor can + * accept new socket connections. + * + * @param context An execution context which provides the I/O executor that + * the acceptor will use, by default, to dispatch handlers for any + * asynchronous operations performed on the acceptor. + */ + template + explicit basic_socket_acceptor_ext(ExecutionContext& context, + typename enable_if< + is_convertible::value + >::type* = 0) + : impl_(0, 0, context) + { + } + + /// Construct an open acceptor. + /** + * This constructor creates an acceptor and automatically opens it. + * + * @param ex The I/O executor that the acceptor will use, by default, to + * dispatch handlers for any asynchronous operations performed on the + * acceptor. + * + * @param protocol An object specifying protocol parameters to be used. + * + * @throws boost::system::system_error Thrown on failure. + */ + basic_socket_acceptor_ext(const executor_type& ex, const protocol_type& protocol) + : impl_(0, ex) + { + boost::system::error_code ec; + impl_.get_service().open(impl_.get_implementation(), protocol, ec); + boost::asio::detail::throw_error(ec, "open"); + } + + /// Construct an open acceptor. + /** + * This constructor creates an acceptor and automatically opens it. + * + * @param context An execution context which provides the I/O executor that + * the acceptor will use, by default, to dispatch handlers for any + * asynchronous operations performed on the acceptor. + * + * @param protocol An object specifying protocol parameters to be used. + * + * @throws boost::system::system_error Thrown on failure. + */ + template + basic_socket_acceptor_ext(ExecutionContext& context, + const protocol_type& protocol, + typename enable_if< + is_convertible::value + >::type* = 0) + : impl_(0, 0, context) + { + boost::system::error_code ec; + impl_.get_service().open(impl_.get_implementation(), protocol, ec); + boost::asio::detail::throw_error(ec, "open"); + } + + /// Construct an acceptor opened on the given endpoint. + /** + * This constructor creates an acceptor and automatically opens it to listen + * for new connections on the specified endpoint. + * + * @param ex The I/O executor that the acceptor will use, by default, to + * dispatch handlers for any asynchronous operations performed on the + * acceptor. + * + * @param endpoint An endpoint on the local machine on which the acceptor + * will listen for new connections. + * + * @param reuse_addr Whether the constructor should set the socket option + * socket_base::reuse_address. + * + * @throws boost::system::system_error Thrown on failure. + * + * @note This constructor is equivalent to the following code: + * @code + * basic_socket_acceptor acceptor(my_context); + * acceptor.open(endpoint.protocol()); + * if (reuse_addr) + * acceptor.set_option(socket_base::reuse_address(true)); + * acceptor.bind(endpoint); + * acceptor.listen(); + * @endcode + */ + basic_socket_acceptor_ext(const executor_type& ex, + const endpoint_type& endpoint, bool reuse_addr = true) + : impl_(0, ex) + { + boost::system::error_code ec; + const protocol_type protocol = endpoint.protocol(); + impl_.get_service().open(impl_.get_implementation(), protocol, ec); + boost::asio::detail::throw_error(ec, "open"); + if (reuse_addr) + { + impl_.get_service().set_option(impl_.get_implementation(), + socket_base::reuse_address(true), ec); + boost::asio::detail::throw_error(ec, "set_option"); + } + impl_.get_service().bind(impl_.get_implementation(), endpoint, ec); + boost::asio::detail::throw_error(ec, "bind"); + impl_.get_service().listen(impl_.get_implementation(), + socket_base::max_listen_connections, ec); + boost::asio::detail::throw_error(ec, "listen"); + } + + /// Construct an acceptor opened on the given endpoint. + /** + * This constructor creates an acceptor and automatically opens it to listen + * for new connections on the specified endpoint. + * + * @param context An execution context which provides the I/O executor that + * the acceptor will use, by default, to dispatch handlers for any + * asynchronous operations performed on the acceptor. + * + * @param endpoint An endpoint on the local machine on which the acceptor + * will listen for new connections. + * + * @param reuse_addr Whether the constructor should set the socket option + * socket_base::reuse_address. + * + * @throws boost::system::system_error Thrown on failure. + * + * @note This constructor is equivalent to the following code: + * @code + * basic_socket_acceptor acceptor(my_context); + * acceptor.open(endpoint.protocol()); + * if (reuse_addr) + * acceptor.set_option(socket_base::reuse_address(true)); + * acceptor.bind(endpoint); + * acceptor.listen(); + * @endcode + */ + template + basic_socket_acceptor_ext(ExecutionContext& context, + const endpoint_type& endpoint, bool reuse_addr = true, + typename enable_if< + is_convertible::value + >::type* = 0) + : impl_(0, 0, context) + { + boost::system::error_code ec; + const protocol_type protocol = endpoint.protocol(); + impl_.get_service().open(impl_.get_implementation(), protocol, ec); + boost::asio::detail::throw_error(ec, "open"); + if (reuse_addr) + { + impl_.get_service().set_option(impl_.get_implementation(), + socket_base::reuse_address(true), ec); + boost::asio::detail::throw_error(ec, "set_option"); + } + impl_.get_service().bind(impl_.get_implementation(), endpoint, ec); + boost::asio::detail::throw_error(ec, "bind"); + impl_.get_service().listen(impl_.get_implementation(), + socket_base::max_listen_connections, ec); + boost::asio::detail::throw_error(ec, "listen"); + } + + /// Construct a basic_socket_acceptor on an existing native acceptor. + /** + * This constructor creates an acceptor object to hold an existing native + * acceptor. + * + * @param ex The I/O executor that the acceptor will use, by default, to + * dispatch handlers for any asynchronous operations performed on the + * acceptor. + * + * @param protocol An object specifying protocol parameters to be used. + * + * @param native_acceptor A native acceptor. + * + * @throws boost::system::system_error Thrown on failure. + */ + basic_socket_acceptor_ext(const executor_type& ex, + const protocol_type& protocol, const native_handle_type& native_acceptor) + : impl_(0, ex) + { + boost::system::error_code ec; + impl_.get_service().assign(impl_.get_implementation(), + protocol, native_acceptor, ec); + boost::asio::detail::throw_error(ec, "assign"); + } + + /// Construct a basic_socket_acceptor on an existing native acceptor. + /** + * This constructor creates an acceptor object to hold an existing native + * acceptor. + * + * @param context An execution context which provides the I/O executor that + * the acceptor will use, by default, to dispatch handlers for any + * asynchronous operations performed on the acceptor. + * + * @param protocol An object specifying protocol parameters to be used. + * + * @param native_acceptor A native acceptor. + * + * @throws boost::system::system_error Thrown on failure. + */ + template + basic_socket_acceptor_ext(ExecutionContext& context, + const protocol_type& protocol, const native_handle_type& native_acceptor, + typename enable_if< + is_convertible::value + >::type* = 0) + : impl_(0, 0, context) + { + boost::system::error_code ec; + impl_.get_service().assign(impl_.get_implementation(), + protocol, native_acceptor, ec); + boost::asio::detail::throw_error(ec, "assign"); + } + +#if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) + /// Move-construct a basic_socket_acceptor from another. + /** + * This constructor moves an acceptor from one object to another. + * + * @param other The other basic_socket_acceptor object from which the move + * will occur. + * + * @note Following the move, the moved-from object is in the same state as if + * constructed using the @c basic_socket_acceptor(const executor_type&) + * constructor. + */ + basic_socket_acceptor_ext(basic_socket_acceptor_ext&& other) + : impl_(std::move(other.impl_)) + { + } + + /// Move-assign a basic_socket_acceptor from another. + /** + * This assignment operator moves an acceptor from one object to another. + * + * @param other The other basic_socket_acceptor object from which the move + * will occur. + * + * @note Following the move, the moved-from object is in the same state as if + * constructed using the @c basic_socket_acceptor(const executor_type&) + * constructor. + */ + basic_socket_acceptor_ext& operator=(basic_socket_acceptor_ext&& other) + { + impl_ = std::move(other.impl_); + return *this; + } + + // All socket acceptors have access to each other's implementations. + template + friend class basic_socket_acceptor_ext; + + /// Move-construct a basic_socket_acceptor from an acceptor of another + /// protocol type. + /** + * This constructor moves an acceptor from one object to another. + * + * @param other The other basic_socket_acceptor object from which the move + * will occur. + * + * @note Following the move, the moved-from object is in the same state as if + * constructed using the @c basic_socket_acceptor(const executor_type&) + * constructor. + */ + template + basic_socket_acceptor_ext(basic_socket_acceptor_ext&& other, + typename enable_if< + is_convertible::value + && is_convertible::value + >::type* = 0) + : impl_(std::move(other.impl_)) + { + } + + /// Move-assign a basic_socket_acceptor from an acceptor of another protocol + /// type. + /** + * This assignment operator moves an acceptor from one object to another. + * + * @param other The other basic_socket_acceptor object from which the move + * will occur. + * + * @note Following the move, the moved-from object is in the same state as if + * constructed using the @c basic_socket_acceptor(const executor_type&) + * constructor. + */ + template + typename enable_if< + is_convertible::value + && is_convertible::value, + basic_socket_acceptor_ext& + >::type operator=(basic_socket_acceptor_ext&& other) + { + basic_socket_acceptor_ext tmp(std::move(other)); + impl_ = std::move(tmp.impl_); + return *this; + } +#endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) + + /// Destroys the acceptor. + /** + * This function destroys the acceptor, cancelling any outstanding + * asynchronous operations associated with the acceptor as if by calling + * @c cancel. + */ + ~basic_socket_acceptor_ext() + { + } + + /// Get the executor associated with the object. + executor_type get_executor() BOOST_ASIO_NOEXCEPT + { + return impl_.get_executor(); + } + + /// Open the acceptor using the specified protocol. + /** + * This function opens the socket acceptor so that it will use the specified + * protocol. + * + * @param protocol An object specifying which protocol is to be used. + * + * @throws boost::system::system_error Thrown on failure. + * + * @par Example + * @code + * boost::asio::ip::tcp::acceptor acceptor(my_context); + * acceptor.open(boost::asio::ip::tcp::v4()); + * @endcode + */ + void open(const protocol_type& protocol = protocol_type()) + { + boost::system::error_code ec; + impl_.get_service().open(impl_.get_implementation(), protocol, ec); + boost::asio::detail::throw_error(ec, "open"); + } + + /// Open the acceptor using the specified protocol. + /** + * This function opens the socket acceptor so that it will use the specified + * protocol. + * + * @param protocol An object specifying which protocol is to be used. + * + * @param ec Set to indicate what error occurred, if any. + * + * @par Example + * @code + * boost::asio::ip::tcp::acceptor acceptor(my_context); + * boost::system::error_code ec; + * acceptor.open(boost::asio::ip::tcp::v4(), ec); + * if (ec) + * { + * // An error occurred. + * } + * @endcode + */ + BOOST_ASIO_SYNC_OP_VOID open(const protocol_type& protocol, + boost::system::error_code& ec) + { + impl_.get_service().open(impl_.get_implementation(), protocol, ec); + BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); + } + + /// Assigns an existing native acceptor to the acceptor. + /* + * This function opens the acceptor to hold an existing native acceptor. + * + * @param protocol An object specifying which protocol is to be used. + * + * @param native_acceptor A native acceptor. + * + * @throws boost::system::system_error Thrown on failure. + */ + void assign(const protocol_type& protocol, + const native_handle_type& native_acceptor) + { + boost::system::error_code ec; + impl_.get_service().assign(impl_.get_implementation(), + protocol, native_acceptor, ec); + boost::asio::detail::throw_error(ec, "assign"); + } + + /// Assigns an existing native acceptor to the acceptor. + /* + * This function opens the acceptor to hold an existing native acceptor. + * + * @param protocol An object specifying which protocol is to be used. + * + * @param native_acceptor A native acceptor. + * + * @param ec Set to indicate what error occurred, if any. + */ + BOOST_ASIO_SYNC_OP_VOID assign(const protocol_type& protocol, + const native_handle_type& native_acceptor, boost::system::error_code& ec) + { + impl_.get_service().assign(impl_.get_implementation(), + protocol, native_acceptor, ec); + BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); + } + + /// Determine whether the acceptor is open. + bool is_open() const + { + return impl_.get_service().is_open(impl_.get_implementation()); + } + + /// Bind the acceptor to the given local endpoint. + /** + * This function binds the socket acceptor to the specified endpoint on the + * local machine. + * + * @param endpoint An endpoint on the local machine to which the socket + * acceptor will be bound. + * + * @throws boost::system::system_error Thrown on failure. + * + * @par Example + * @code + * boost::asio::ip::tcp::acceptor acceptor(my_context); + * boost::asio::ip::tcp::endpoint endpoint(boost::asio::ip::tcp::v4(), 12345); + * acceptor.open(endpoint.protocol()); + * acceptor.bind(endpoint); + * @endcode + */ + void bind(const endpoint_type& endpoint) + { + boost::system::error_code ec; + impl_.get_service().bind(impl_.get_implementation(), endpoint, ec); + boost::asio::detail::throw_error(ec, "bind"); + } + + /// Bind the acceptor to the given local endpoint. + /** + * This function binds the socket acceptor to the specified endpoint on the + * local machine. + * + * @param endpoint An endpoint on the local machine to which the socket + * acceptor will be bound. + * + * @param ec Set to indicate what error occurred, if any. + * + * @par Example + * @code + * boost::asio::ip::tcp::acceptor acceptor(my_context); + * boost::asio::ip::tcp::endpoint endpoint(boost::asio::ip::tcp::v4(), 12345); + * acceptor.open(endpoint.protocol()); + * boost::system::error_code ec; + * acceptor.bind(endpoint, ec); + * if (ec) + * { + * // An error occurred. + * } + * @endcode + */ + BOOST_ASIO_SYNC_OP_VOID bind(const endpoint_type& endpoint, + boost::system::error_code& ec) + { + impl_.get_service().bind(impl_.get_implementation(), endpoint, ec); + BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); + } + + /// Place the acceptor into the state where it will listen for new + /// connections. + /** + * This function puts the socket acceptor into the state where it may accept + * new connections. + * + * @param backlog The maximum length of the queue of pending connections. + * + * @throws boost::system::system_error Thrown on failure. + */ + void listen(int backlog = socket_base::max_listen_connections) + { + boost::system::error_code ec; + impl_.get_service().listen(impl_.get_implementation(), backlog, ec); + boost::asio::detail::throw_error(ec, "listen"); + } + + /// Place the acceptor into the state where it will listen for new + /// connections. + /** + * This function puts the socket acceptor into the state where it may accept + * new connections. + * + * @param backlog The maximum length of the queue of pending connections. + * + * @param ec Set to indicate what error occurred, if any. + * + * @par Example + * @code + * boost::asio::ip::tcp::acceptor acceptor(my_context); + * ... + * boost::system::error_code ec; + * acceptor.listen(boost::asio::socket_base::max_listen_connections, ec); + * if (ec) + * { + * // An error occurred. + * } + * @endcode + */ + BOOST_ASIO_SYNC_OP_VOID listen(int backlog, boost::system::error_code& ec) + { + impl_.get_service().listen(impl_.get_implementation(), backlog, ec); + BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); + } + + /// Close the acceptor. + /** + * This function is used to close the acceptor. Any asynchronous accept + * operations will be cancelled immediately. + * + * A subsequent call to open() is required before the acceptor can again be + * used to again perform socket accept operations. + * + * @throws boost::system::system_error Thrown on failure. + */ + void close() + { + boost::system::error_code ec; + impl_.get_service().close(impl_.get_implementation(), ec); + boost::asio::detail::throw_error(ec, "close"); + } + + /// Close the acceptor. + /** + * This function is used to close the acceptor. Any asynchronous accept + * operations will be cancelled immediately. + * + * A subsequent call to open() is required before the acceptor can again be + * used to again perform socket accept operations. + * + * @param ec Set to indicate what error occurred, if any. + * + * @par Example + * @code + * boost::asio::ip::tcp::acceptor acceptor(my_context); + * ... + * boost::system::error_code ec; + * acceptor.close(ec); + * if (ec) + * { + * // An error occurred. + * } + * @endcode + */ + BOOST_ASIO_SYNC_OP_VOID close(boost::system::error_code& ec) + { + impl_.get_service().close(impl_.get_implementation(), ec); + BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); + } + + /// Release ownership of the underlying native acceptor. + /** + * This function causes all outstanding asynchronous accept operations to + * finish immediately, and the handlers for cancelled operations will be + * passed the boost::asio::error::operation_aborted error. Ownership of the + * native acceptor is then transferred to the caller. + * + * @throws boost::system::system_error Thrown on failure. + * + * @note This function is unsupported on Windows versions prior to Windows + * 8.1, and will fail with boost::asio::error::operation_not_supported on + * these platforms. + */ +#if defined(BOOST_ASIO_MSVC) && (BOOST_ASIO_MSVC >= 1400) \ + && (!defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0603) + __declspec(deprecated("This function always fails with " + "operation_not_supported when used on Windows versions " + "prior to Windows 8.1.")) +#endif + native_handle_type release() + { + boost::system::error_code ec; + native_handle_type s = impl_.get_service().release( + impl_.get_implementation(), ec); + boost::asio::detail::throw_error(ec, "release"); + return s; + } + + /// Release ownership of the underlying native acceptor. + /** + * This function causes all outstanding asynchronous accept operations to + * finish immediately, and the handlers for cancelled operations will be + * passed the boost::asio::error::operation_aborted error. Ownership of the + * native acceptor is then transferred to the caller. + * + * @param ec Set to indicate what error occurred, if any. + * + * @note This function is unsupported on Windows versions prior to Windows + * 8.1, and will fail with boost::asio::error::operation_not_supported on + * these platforms. + */ +#if defined(BOOST_ASIO_MSVC) && (BOOST_ASIO_MSVC >= 1400) \ + && (!defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0603) + __declspec(deprecated("This function always fails with " + "operation_not_supported when used on Windows versions " + "prior to Windows 8.1.")) +#endif + native_handle_type release(boost::system::error_code& ec) + { + return impl_.get_service().release(impl_.get_implementation(), ec); + } + + /// Get the native acceptor representation. + /** + * This function may be used to obtain the underlying representation of the + * acceptor. This is intended to allow access to native acceptor functionality + * that is not otherwise provided. + */ + native_handle_type native_handle() + { + return impl_.get_service().native_handle(impl_.get_implementation()); + } + + /// Cancel all asynchronous operations associated with the acceptor. + /** + * This function causes all outstanding asynchronous connect, send and receive + * operations to finish immediately, and the handlers for cancelled operations + * will be passed the boost::asio::error::operation_aborted error. + * + * @throws boost::system::system_error Thrown on failure. + */ + void cancel() + { + boost::system::error_code ec; + impl_.get_service().cancel(impl_.get_implementation(), ec); + boost::asio::detail::throw_error(ec, "cancel"); + } + + /// Cancel all asynchronous operations associated with the acceptor. + /** + * This function causes all outstanding asynchronous connect, send and receive + * operations to finish immediately, and the handlers for cancelled operations + * will be passed the boost::asio::error::operation_aborted error. + * + * @param ec Set to indicate what error occurred, if any. + */ + BOOST_ASIO_SYNC_OP_VOID cancel(boost::system::error_code& ec) + { + impl_.get_service().cancel(impl_.get_implementation(), ec); + BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); + } + + /// Set an option on the acceptor. + /** + * This function is used to set an option on the acceptor. + * + * @param option The new option value to be set on the acceptor. + * + * @throws boost::system::system_error Thrown on failure. + * + * @sa SettableSocketOption @n + * boost::asio::socket_base::reuse_address + * boost::asio::socket_base::enable_connection_aborted + * + * @par Example + * Setting the SOL_SOCKET/SO_REUSEADDR option: + * @code + * boost::asio::ip::tcp::acceptor acceptor(my_context); + * ... + * boost::asio::ip::tcp::acceptor::reuse_address option(true); + * acceptor.set_option(option); + * @endcode + */ + template + void set_option(const SettableSocketOption& option) + { + boost::system::error_code ec; + impl_.get_service().set_option(impl_.get_implementation(), option, ec); + boost::asio::detail::throw_error(ec, "set_option"); + } + + /// Set an option on the acceptor. + /** + * This function is used to set an option on the acceptor. + * + * @param option The new option value to be set on the acceptor. + * + * @param ec Set to indicate what error occurred, if any. + * + * @sa SettableSocketOption @n + * boost::asio::socket_base::reuse_address + * boost::asio::socket_base::enable_connection_aborted + * + * @par Example + * Setting the SOL_SOCKET/SO_REUSEADDR option: + * @code + * boost::asio::ip::tcp::acceptor acceptor(my_context); + * ... + * boost::asio::ip::tcp::acceptor::reuse_address option(true); + * boost::system::error_code ec; + * acceptor.set_option(option, ec); + * if (ec) + * { + * // An error occurred. + * } + * @endcode + */ + template + BOOST_ASIO_SYNC_OP_VOID set_option(const SettableSocketOption& option, + boost::system::error_code& ec) + { + impl_.get_service().set_option(impl_.get_implementation(), option, ec); + BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); + } + + /// Get an option from the acceptor. + /** + * This function is used to get the current value of an option on the + * acceptor. + * + * @param option The option value to be obtained from the acceptor. + * + * @throws boost::system::system_error Thrown on failure. + * + * @sa GettableSocketOption @n + * boost::asio::socket_base::reuse_address + * + * @par Example + * Getting the value of the SOL_SOCKET/SO_REUSEADDR option: + * @code + * boost::asio::ip::tcp::acceptor acceptor(my_context); + * ... + * boost::asio::ip::tcp::acceptor::reuse_address option; + * acceptor.get_option(option); + * bool is_set = option.get(); + * @endcode + */ + template + void get_option(GettableSocketOption& option) const + { + boost::system::error_code ec; + impl_.get_service().get_option(impl_.get_implementation(), option, ec); + boost::asio::detail::throw_error(ec, "get_option"); + } + + /// Get an option from the acceptor. + /** + * This function is used to get the current value of an option on the + * acceptor. + * + * @param option The option value to be obtained from the acceptor. + * + * @param ec Set to indicate what error occurred, if any. + * + * @sa GettableSocketOption @n + * boost::asio::socket_base::reuse_address + * + * @par Example + * Getting the value of the SOL_SOCKET/SO_REUSEADDR option: + * @code + * boost::asio::ip::tcp::acceptor acceptor(my_context); + * ... + * boost::asio::ip::tcp::acceptor::reuse_address option; + * boost::system::error_code ec; + * acceptor.get_option(option, ec); + * if (ec) + * { + * // An error occurred. + * } + * bool is_set = option.get(); + * @endcode + */ + template + BOOST_ASIO_SYNC_OP_VOID get_option(GettableSocketOption& option, + boost::system::error_code& ec) const + { + impl_.get_service().get_option(impl_.get_implementation(), option, ec); + BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); + } + + /// Perform an IO control command on the acceptor. + /** + * This function is used to execute an IO control command on the acceptor. + * + * @param command The IO control command to be performed on the acceptor. + * + * @throws boost::system::system_error Thrown on failure. + * + * @sa IoControlCommand @n + * boost::asio::socket_base::non_blocking_io + * + * @par Example + * Getting the number of bytes ready to read: + * @code + * boost::asio::ip::tcp::acceptor acceptor(my_context); + * ... + * boost::asio::ip::tcp::acceptor::non_blocking_io command(true); + * socket.io_control(command); + * @endcode + */ + template + void io_control(IoControlCommand& command) + { + boost::system::error_code ec; + impl_.get_service().io_control(impl_.get_implementation(), command, ec); + boost::asio::detail::throw_error(ec, "io_control"); + } + + /// Perform an IO control command on the acceptor. + /** + * This function is used to execute an IO control command on the acceptor. + * + * @param command The IO control command to be performed on the acceptor. + * + * @param ec Set to indicate what error occurred, if any. + * + * @sa IoControlCommand @n + * boost::asio::socket_base::non_blocking_io + * + * @par Example + * Getting the number of bytes ready to read: + * @code + * boost::asio::ip::tcp::acceptor acceptor(my_context); + * ... + * boost::asio::ip::tcp::acceptor::non_blocking_io command(true); + * boost::system::error_code ec; + * socket.io_control(command, ec); + * if (ec) + * { + * // An error occurred. + * } + * @endcode + */ + template + BOOST_ASIO_SYNC_OP_VOID io_control(IoControlCommand& command, + boost::system::error_code& ec) + { + impl_.get_service().io_control(impl_.get_implementation(), command, ec); + BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); + } + + /// Gets the non-blocking mode of the acceptor. + /** + * @returns @c true if the acceptor's synchronous operations will fail with + * boost::asio::error::would_block if they are unable to perform the requested + * operation immediately. If @c false, synchronous operations will block + * until complete. + * + * @note The non-blocking mode has no effect on the behaviour of asynchronous + * operations. Asynchronous operations will never fail with the error + * boost::asio::error::would_block. + */ + bool non_blocking() const + { + return impl_.get_service().non_blocking(impl_.get_implementation()); + } + + /// Sets the non-blocking mode of the acceptor. + /** + * @param mode If @c true, the acceptor's synchronous operations will fail + * with boost::asio::error::would_block if they are unable to perform the + * requested operation immediately. If @c false, synchronous operations will + * block until complete. + * + * @throws boost::system::system_error Thrown on failure. + * + * @note The non-blocking mode has no effect on the behaviour of asynchronous + * operations. Asynchronous operations will never fail with the error + * boost::asio::error::would_block. + */ + void non_blocking(bool mode) + { + boost::system::error_code ec; + impl_.get_service().non_blocking(impl_.get_implementation(), mode, ec); + boost::asio::detail::throw_error(ec, "non_blocking"); + } + + /// Sets the non-blocking mode of the acceptor. + /** + * @param mode If @c true, the acceptor's synchronous operations will fail + * with boost::asio::error::would_block if they are unable to perform the + * requested operation immediately. If @c false, synchronous operations will + * block until complete. + * + * @param ec Set to indicate what error occurred, if any. + * + * @note The non-blocking mode has no effect on the behaviour of asynchronous + * operations. Asynchronous operations will never fail with the error + * boost::asio::error::would_block. + */ + BOOST_ASIO_SYNC_OP_VOID non_blocking( + bool mode, boost::system::error_code& ec) + { + impl_.get_service().non_blocking(impl_.get_implementation(), mode, ec); + BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); + } + + /// Gets the non-blocking mode of the native acceptor implementation. + /** + * This function is used to retrieve the non-blocking mode of the underlying + * native acceptor. This mode has no effect on the behaviour of the acceptor + * object's synchronous operations. + * + * @returns @c true if the underlying acceptor is in non-blocking mode and + * direct system calls may fail with boost::asio::error::would_block (or the + * equivalent system error). + * + * @note The current non-blocking mode is cached by the acceptor object. + * Consequently, the return value may be incorrect if the non-blocking mode + * was set directly on the native acceptor. + */ + bool native_non_blocking() const + { + return impl_.get_service().native_non_blocking(impl_.get_implementation()); + } + + /// Sets the non-blocking mode of the native acceptor implementation. + /** + * This function is used to modify the non-blocking mode of the underlying + * native acceptor. It has no effect on the behaviour of the acceptor object's + * synchronous operations. + * + * @param mode If @c true, the underlying acceptor is put into non-blocking + * mode and direct system calls may fail with boost::asio::error::would_block + * (or the equivalent system error). + * + * @throws boost::system::system_error Thrown on failure. If the @c mode is + * @c false, but the current value of @c non_blocking() is @c true, this + * function fails with boost::asio::error::invalid_argument, as the + * combination does not make sense. + */ + void native_non_blocking(bool mode) + { + boost::system::error_code ec; + impl_.get_service().native_non_blocking( + impl_.get_implementation(), mode, ec); + boost::asio::detail::throw_error(ec, "native_non_blocking"); + } + + /// Sets the non-blocking mode of the native acceptor implementation. + /** + * This function is used to modify the non-blocking mode of the underlying + * native acceptor. It has no effect on the behaviour of the acceptor object's + * synchronous operations. + * + * @param mode If @c true, the underlying acceptor is put into non-blocking + * mode and direct system calls may fail with boost::asio::error::would_block + * (or the equivalent system error). + * + * @param ec Set to indicate what error occurred, if any. If the @c mode is + * @c false, but the current value of @c non_blocking() is @c true, this + * function fails with boost::asio::error::invalid_argument, as the + * combination does not make sense. + */ + BOOST_ASIO_SYNC_OP_VOID native_non_blocking( + bool mode, boost::system::error_code& ec) + { + impl_.get_service().native_non_blocking( + impl_.get_implementation(), mode, ec); + BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); + } + + /// Get the local endpoint of the acceptor. + /** + * This function is used to obtain the locally bound endpoint of the acceptor. + * + * @returns An object that represents the local endpoint of the acceptor. + * + * @throws boost::system::system_error Thrown on failure. + * + * @par Example + * @code + * boost::asio::ip::tcp::acceptor acceptor(my_context); + * ... + * boost::asio::ip::tcp::endpoint endpoint = acceptor.local_endpoint(); + * @endcode + */ + endpoint_type local_endpoint() const + { + boost::system::error_code ec; + endpoint_type ep = impl_.get_service().local_endpoint( + impl_.get_implementation(), ec); + boost::asio::detail::throw_error(ec, "local_endpoint"); + return ep; + } + + /// Get the local endpoint of the acceptor. + /** + * This function is used to obtain the locally bound endpoint of the acceptor. + * + * @param ec Set to indicate what error occurred, if any. + * + * @returns An object that represents the local endpoint of the acceptor. + * Returns a default-constructed endpoint object if an error occurred and the + * error handler did not throw an exception. + * + * @par Example + * @code + * boost::asio::ip::tcp::acceptor acceptor(my_context); + * ... + * boost::system::error_code ec; + * boost::asio::ip::tcp::endpoint endpoint = acceptor.local_endpoint(ec); + * if (ec) + * { + * // An error occurred. + * } + * @endcode + */ + endpoint_type local_endpoint(boost::system::error_code& ec) const + { + return impl_.get_service().local_endpoint(impl_.get_implementation(), ec); + } + + /// Wait for the acceptor to become ready to read, ready to write, or to have + /// pending error conditions. + /** + * This function is used to perform a blocking wait for an acceptor to enter + * a ready to read, write or error condition state. + * + * @param w Specifies the desired acceptor state. + * + * @par Example + * Waiting for an acceptor to become readable. + * @code + * boost::asio::ip::tcp::acceptor acceptor(my_context); + * ... + * acceptor.wait(boost::asio::ip::tcp::acceptor::wait_read); + * @endcode + */ + void wait(wait_type w) + { + boost::system::error_code ec; + impl_.get_service().wait(impl_.get_implementation(), w, ec); + boost::asio::detail::throw_error(ec, "wait"); + } + + /// Wait for the acceptor to become ready to read, ready to write, or to have + /// pending error conditions. + /** + * This function is used to perform a blocking wait for an acceptor to enter + * a ready to read, write or error condition state. + * + * @param w Specifies the desired acceptor state. + * + * @param ec Set to indicate what error occurred, if any. + * + * @par Example + * Waiting for an acceptor to become readable. + * @code + * boost::asio::ip::tcp::acceptor acceptor(my_context); + * ... + * boost::system::error_code ec; + * acceptor.wait(boost::asio::ip::tcp::acceptor::wait_read, ec); + * @endcode + */ + BOOST_ASIO_SYNC_OP_VOID wait(wait_type w, boost::system::error_code& ec) + { + impl_.get_service().wait(impl_.get_implementation(), w, ec); + BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); + } + + /// Asynchronously wait for the acceptor to become ready to read, ready to + /// write, or to have pending error conditions. + /** + * This function is used to perform an asynchronous wait for an acceptor to + * enter a ready to read, write or error condition state. + * + * @param w Specifies the desired acceptor state. + * + * @param handler The handler to be called when the wait operation completes. + * Copies will be made of the handler as required. The function signature of + * the handler must be: + * @code void handler( + * const boost::system::error_code& error // Result of operation + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. On + * immediate completion, invocation of the handler will be performed in a + * manner equivalent to using boost::asio::post(). + * + * @par Example + * @code + * void wait_handler(const boost::system::error_code& error) + * { + * if (!error) + * { + * // Wait succeeded. + * } + * } + * + * ... + * + * boost::asio::ip::tcp::acceptor acceptor(my_context); + * ... + * acceptor.async_wait( + * boost::asio::ip::tcp::acceptor::wait_read, + * wait_handler); + * @endcode + */ + template + BOOST_ASIO_INITFN_RESULT_TYPE(WaitHandler, + void (boost::system::error_code)) + async_wait(wait_type w, BOOST_ASIO_MOVE_ARG(WaitHandler) handler) + { + return async_initiate( + initiate_async_wait(), handler, this, w); + } + +#if !defined(BOOST_ASIO_NO_EXTENSIONS) + /// Accept a new connection. + /** + * This function is used to accept a new connection from a peer into the + * given socket. The function call will block until a new connection has been + * accepted successfully or an error occurs. + * + * @param peer The socket into which the new connection will be accepted. + * + * @throws boost::system::system_error Thrown on failure. + * + * @par Example + * @code + * boost::asio::ip::tcp::acceptor acceptor(my_context); + * ... + * boost::asio::ip::tcp::socket socket(my_context); + * acceptor.accept(socket); + * @endcode + */ + template + void accept(basic_socket_ext_local& peer, + typename enable_if< + is_convertible::value + >::type* = 0) + { + boost::system::error_code ec; + impl_.get_service().accept(impl_.get_implementation(), + peer, static_cast(0), ec); + boost::asio::detail::throw_error(ec, "accept"); + } + + /// Accept a new connection. + /** + * This function is used to accept a new connection from a peer into the + * given socket. The function call will block until a new connection has been + * accepted successfully or an error occurs. + * + * @param peer The socket into which the new connection will be accepted. + * + * @param ec Set to indicate what error occurred, if any. + * + * @par Example + * @code + * boost::asio::ip::tcp::acceptor acceptor(my_context); + * ... + * boost::asio::ip::tcp::socket socket(my_context); + * boost::system::error_code ec; + * acceptor.accept(socket, ec); + * if (ec) + * { + * // An error occurred. + * } + * @endcode + */ + template + BOOST_ASIO_SYNC_OP_VOID accept( + basic_socket_ext_local& peer, boost::system::error_code& ec, + typename enable_if< + is_convertible::value + >::type* = 0) + { + impl_.get_service().accept(impl_.get_implementation(), + peer, static_cast(0), ec); + BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); + } + + /// Start an asynchronous accept. + /** + * This function is used to asynchronously accept a new connection into a + * socket. The function call always returns immediately. + * + * @param peer The socket into which the new connection will be accepted. + * Ownership of the peer object is retained by the caller, which must + * guarantee that it is valid until the handler is called. + * + * @param handler The handler to be called when the accept operation + * completes. Copies will be made of the handler as required. The function + * signature of the handler must be: + * @code void handler( + * const boost::system::error_code& error // Result of operation. + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. On + * immediate completion, invocation of the handler will be performed in a + * manner equivalent to using boost::asio::post(). + * + * @par Example + * @code + * void accept_handler(const boost::system::error_code& error) + * { + * if (!error) + * { + * // Accept succeeded. + * } + * } + * + * ... + * + * boost::asio::ip::tcp::acceptor acceptor(my_context); + * ... + * boost::asio::ip::tcp::socket socket(my_context); + * acceptor.async_accept(socket, accept_handler); + * @endcode + */ + template + BOOST_ASIO_INITFN_RESULT_TYPE(AcceptHandler, + void (boost::system::error_code)) + async_accept(basic_socket_ext_local& peer, + BOOST_ASIO_MOVE_ARG(AcceptHandler) handler, + typename enable_if< + is_convertible::value + >::type* = 0) + { + return async_initiate( + initiate_async_accept(), handler, this, + &peer, static_cast(0)); + } + + /// Accept a new connection and obtain the endpoint of the peer + /** + * This function is used to accept a new connection from a peer into the + * given socket, and additionally provide the endpoint of the remote peer. + * The function call will block until a new connection has been accepted + * successfully or an error occurs. + * + * @param peer The socket into which the new connection will be accepted. + * + * @param peer_endpoint An endpoint object which will receive the endpoint of + * the remote peer. + * + * @throws boost::system::system_error Thrown on failure. + * + * @par Example + * @code + * boost::asio::ip::tcp::acceptor acceptor(my_context); + * ... + * boost::asio::ip::tcp::socket socket(my_context); + * boost::asio::ip::tcp::endpoint endpoint; + * acceptor.accept(socket, endpoint); + * @endcode + */ + template + void accept(basic_socket_ext_local& peer, + endpoint_type& peer_endpoint) + { + boost::system::error_code ec; + impl_.get_service().accept(impl_.get_implementation(), + peer, &peer_endpoint, ec); + boost::asio::detail::throw_error(ec, "accept"); + } + + /// Accept a new connection and obtain the endpoint of the peer + /** + * This function is used to accept a new connection from a peer into the + * given socket, and additionally provide the endpoint of the remote peer. + * The function call will block until a new connection has been accepted + * successfully or an error occurs. + * + * @param peer The socket into which the new connection will be accepted. + * + * @param peer_endpoint An endpoint object which will receive the endpoint of + * the remote peer. + * + * @param ec Set to indicate what error occurred, if any. + * + * @par Example + * @code + * boost::asio::ip::tcp::acceptor acceptor(my_context); + * ... + * boost::asio::ip::tcp::socket socket(my_context); + * boost::asio::ip::tcp::endpoint endpoint; + * boost::system::error_code ec; + * acceptor.accept(socket, endpoint, ec); + * if (ec) + * { + * // An error occurred. + * } + * @endcode + */ + template + BOOST_ASIO_SYNC_OP_VOID accept(basic_socket_ext_local& peer, + endpoint_type& peer_endpoint, boost::system::error_code& ec) + { + impl_.get_service().accept( + impl_.get_implementation(), peer, &peer_endpoint, ec); + BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); + } + + /// Start an asynchronous accept. + /** + * This function is used to asynchronously accept a new connection into a + * socket, and additionally obtain the endpoint of the remote peer. The + * function call always returns immediately. + * + * @param peer The socket into which the new connection will be accepted. + * Ownership of the peer object is retained by the caller, which must + * guarantee that it is valid until the handler is called. + * + * @param peer_endpoint An endpoint object into which the endpoint of the + * remote peer will be written. Ownership of the peer_endpoint object is + * retained by the caller, which must guarantee that it is valid until the + * handler is called. + * + * @param handler The handler to be called when the accept operation + * completes. Copies will be made of the handler as required. The function + * signature of the handler must be: + * @code void handler( + * const boost::system::error_code& error // Result of operation. + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. On + * immediate completion, invocation of the handler will be performed in a + * manner equivalent to using boost::asio::post(). + */ + template + BOOST_ASIO_INITFN_RESULT_TYPE(AcceptHandler, + void (boost::system::error_code)) + async_accept(basic_socket_ext_local& peer, + endpoint_type& peer_endpoint, BOOST_ASIO_MOVE_ARG(AcceptHandler) handler) + { + return async_initiate( + initiate_async_accept(), handler, this, &peer, &peer_endpoint); + } +#endif // !defined(BOOST_ASIO_NO_EXTENSIONS) + +#if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) + /// Accept a new connection. + /** + * This function is used to accept a new connection from a peer. The function + * call will block until a new connection has been accepted successfully or + * an error occurs. + * + * This overload requires that the Protocol template parameter satisfy the + * AcceptableProtocol type requirements. + * + * @returns A socket object representing the newly accepted connection. + * + * @throws boost::system::system_error Thrown on failure. + * + * @par Example + * @code + * boost::asio::ip::tcp::acceptor acceptor(my_context); + * ... + * boost::asio::ip::tcp::socket socket(acceptor.accept()); + * @endcode + */ + typename Protocol::socket accept() + { + boost::system::error_code ec; + typename Protocol::socket peer(impl_.get_executor()); + impl_.get_service().accept(impl_.get_implementation(), peer, 0, ec); + boost::asio::detail::throw_error(ec, "accept"); + return peer; + } + + /// Accept a new connection. + /** + * This function is used to accept a new connection from a peer. The function + * call will block until a new connection has been accepted successfully or + * an error occurs. + * + * This overload requires that the Protocol template parameter satisfy the + * AcceptableProtocol type requirements. + * + * @param ec Set to indicate what error occurred, if any. + * + * @returns On success, a socket object representing the newly accepted + * connection. On error, a socket object where is_open() is false. + * + * @par Example + * @code + * boost::asio::ip::tcp::acceptor acceptor(my_context); + * ... + * boost::asio::ip::tcp::socket socket(acceptor.accept(ec)); + * if (ec) + * { + * // An error occurred. + * } + * @endcode + */ + typename Protocol::socket accept(boost::system::error_code& ec) + { + typename Protocol::socket peer(impl_.get_executor()); + impl_.get_service().accept(impl_.get_implementation(), peer, 0, ec); + return peer; + } + + /// Start an asynchronous accept. + /** + * This function is used to asynchronously accept a new connection. The + * function call always returns immediately. + * + * This overload requires that the Protocol template parameter satisfy the + * AcceptableProtocol type requirements. + * + * @param handler The handler to be called when the accept operation + * completes. Copies will be made of the handler as required. The function + * signature of the handler must be: + * @code void handler( + * const boost::system::error_code& error, // Result of operation. + * typename Protocol::socket peer // On success, the newly accepted socket. + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. On + * immediate completion, invocation of the handler will be performed in a + * manner equivalent to using boost::asio::post(). + * + * @par Example + * @code + * void accept_handler(const boost::system::error_code& error, + * boost::asio::ip::tcp::socket peer) + * { + * if (!error) + * { + * // Accept succeeded. + * } + * } + * + * ... + * + * boost::asio::ip::tcp::acceptor acceptor(my_context); + * ... + * acceptor.async_accept(accept_handler); + * @endcode + */ + template + BOOST_ASIO_INITFN_RESULT_TYPE(MoveAcceptHandler, + void (boost::system::error_code, typename Protocol::socket)) + async_accept(BOOST_ASIO_MOVE_ARG(MoveAcceptHandler) handler) + { + return async_initiate( + initiate_async_move_accept(), handler, this, + impl_.get_executor(), static_cast(0), + static_cast(0)); + } + + /// Accept a new connection. + /** + * This function is used to accept a new connection from a peer. The function + * call will block until a new connection has been accepted successfully or + * an error occurs. + * + * This overload requires that the Protocol template parameter satisfy the + * AcceptableProtocol type requirements. + * + * @param ex The I/O executor object to be used for the newly + * accepted socket. + * + * @returns A socket object representing the newly accepted connection. + * + * @throws boost::system::system_error Thrown on failure. + * + * @par Example + * @code + * boost::asio::ip::tcp::acceptor acceptor(my_context); + * ... + * boost::asio::ip::tcp::socket socket(acceptor.accept()); + * @endcode + */ + template + typename Protocol::socket::template rebind_executor::other + accept(const Executor1& ex, + typename enable_if< + is_executor::value + >::type* = 0) + { + boost::system::error_code ec; + typename Protocol::socket::template + rebind_executor::other peer(ex); + impl_.get_service().accept(impl_.get_implementation(), peer, 0, ec); + boost::asio::detail::throw_error(ec, "accept"); + return peer; + } + + /// Accept a new connection. + /** + * This function is used to accept a new connection from a peer. The function + * call will block until a new connection has been accepted successfully or + * an error occurs. + * + * This overload requires that the Protocol template parameter satisfy the + * AcceptableProtocol type requirements. + * + * @param context The I/O execution context object to be used for the newly + * accepted socket. + * + * @returns A socket object representing the newly accepted connection. + * + * @throws boost::system::system_error Thrown on failure. + * + * @par Example + * @code + * boost::asio::ip::tcp::acceptor acceptor(my_context); + * ... + * boost::asio::ip::tcp::socket socket(acceptor.accept()); + * @endcode + */ + template + typename Protocol::socket::template rebind_executor< + typename ExecutionContext::executor_type>::other + accept(ExecutionContext& context, + typename enable_if< + is_convertible::value + >::type* = 0) + { + boost::system::error_code ec; + typename Protocol::socket::template rebind_executor< + typename ExecutionContext::executor_type>::other peer(context); + impl_.get_service().accept(impl_.get_implementation(), peer, 0, ec); + boost::asio::detail::throw_error(ec, "accept"); + return peer; + } + + /// Accept a new connection. + /** + * This function is used to accept a new connection from a peer. The function + * call will block until a new connection has been accepted successfully or + * an error occurs. + * + * This overload requires that the Protocol template parameter satisfy the + * AcceptableProtocol type requirements. + * + * @param ex The I/O executor object to be used for the newly accepted + * socket. + * + * @param ec Set to indicate what error occurred, if any. + * + * @returns On success, a socket object representing the newly accepted + * connection. On error, a socket object where is_open() is false. + * + * @par Example + * @code + * boost::asio::ip::tcp::acceptor acceptor(my_context); + * ... + * boost::asio::ip::tcp::socket socket(acceptor.accept(my_context2, ec)); + * if (ec) + * { + * // An error occurred. + * } + * @endcode + */ + template + typename Protocol::socket::template rebind_executor::other + accept(const Executor1& ex, boost::system::error_code& ec, + typename enable_if< + is_executor::value + >::type* = 0) + { + typename Protocol::socket::template + rebind_executor::other peer(ex); + impl_.get_service().accept(impl_.get_implementation(), peer, 0, ec); + return peer; + } + + /// Accept a new connection. + /** + * This function is used to accept a new connection from a peer. The function + * call will block until a new connection has been accepted successfully or + * an error occurs. + * + * This overload requires that the Protocol template parameter satisfy the + * AcceptableProtocol type requirements. + * + * @param context The I/O execution context object to be used for the newly + * accepted socket. + * + * @param ec Set to indicate what error occurred, if any. + * + * @returns On success, a socket object representing the newly accepted + * connection. On error, a socket object where is_open() is false. + * + * @par Example + * @code + * boost::asio::ip::tcp::acceptor acceptor(my_context); + * ... + * boost::asio::ip::tcp::socket socket(acceptor.accept(my_context2, ec)); + * if (ec) + * { + * // An error occurred. + * } + * @endcode + */ + template + typename Protocol::socket::template rebind_executor< + typename ExecutionContext::executor_type>::other + accept(ExecutionContext& context, boost::system::error_code& ec, + typename enable_if< + is_convertible::value + >::type* = 0) + { + typename Protocol::socket::template rebind_executor< + typename ExecutionContext::executor_type>::other peer(context); + impl_.get_service().accept(impl_.get_implementation(), peer, 0, ec); + return peer; + } + + /// Start an asynchronous accept. + /** + * This function is used to asynchronously accept a new connection. The + * function call always returns immediately. + * + * This overload requires that the Protocol template parameter satisfy the + * AcceptableProtocol type requirements. + * + * @param ex The I/O executor object to be used for the newly accepted + * socket. + * + * @param handler The handler to be called when the accept operation + * completes. Copies will be made of the handler as required. The function + * signature of the handler must be: + * @code void handler( + * const boost::system::error_code& error, // Result of operation. + * typename Protocol::socket::template rebind_executor< + * Executor1>::other peer // On success, the newly accepted socket. + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. On + * immediate completion, invocation of the handler will be performed in a + * manner equivalent to using boost::asio::post(). + * + * @par Example + * @code + * void accept_handler(const boost::system::error_code& error, + * boost::asio::ip::tcp::socket peer) + * { + * if (!error) + * { + * // Accept succeeded. + * } + * } + * + * ... + * + * boost::asio::ip::tcp::acceptor acceptor(my_context); + * ... + * acceptor.async_accept(my_context2, accept_handler); + * @endcode + */ + template + BOOST_ASIO_INITFN_RESULT_TYPE(MoveAcceptHandler, + void (boost::system::error_code, + typename Protocol::socket::template rebind_executor< + Executor1>::other)) + async_accept(const Executor1& ex, + BOOST_ASIO_MOVE_ARG(MoveAcceptHandler) handler, + typename enable_if< + is_executor::value + >::type* = 0) + { + typedef typename Protocol::socket::template rebind_executor< + Executor1>::other other_socket_type; + + return async_initiate( + initiate_async_move_accept(), handler, this, + ex, static_cast(0), + static_cast(0)); + } + + /// Start an asynchronous accept. + /** + * This function is used to asynchronously accept a new connection. The + * function call always returns immediately. + * + * This overload requires that the Protocol template parameter satisfy the + * AcceptableProtocol type requirements. + * + * @param context The I/O execution context object to be used for the newly + * accepted socket. + * + * @param handler The handler to be called when the accept operation + * completes. Copies will be made of the handler as required. The function + * signature of the handler must be: + * @code void handler( + * const boost::system::error_code& error, // Result of operation. + * typename Protocol::socket::template rebind_executor< + * typename ExecutionContext::executor_type>::other peer + * // On success, the newly accepted socket. + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. On + * immediate completion, invocation of the handler will be performed in a + * manner equivalent to using boost::asio::post(). + * + * @par Example + * @code + * void accept_handler(const boost::system::error_code& error, + * boost::asio::ip::tcp::socket peer) + * { + * if (!error) + * { + * // Accept succeeded. + * } + * } + * + * ... + * + * boost::asio::ip::tcp::acceptor acceptor(my_context); + * ... + * acceptor.async_accept(my_context2, accept_handler); + * @endcode + */ + template + BOOST_ASIO_INITFN_RESULT_TYPE(MoveAcceptHandler, + void (boost::system::error_code, + typename Protocol::socket::template rebind_executor< + typename ExecutionContext::executor_type>::other)) + async_accept(ExecutionContext& context, + BOOST_ASIO_MOVE_ARG(MoveAcceptHandler) handler, + typename enable_if< + is_convertible::value + >::type* = 0) + { + typedef typename Protocol::socket::template rebind_executor< + typename ExecutionContext::executor_type>::other other_socket_type; + + return async_initiate( + initiate_async_move_accept(), handler, this, + context.get_executor(), static_cast(0), + static_cast(0)); + } + + /// Accept a new connection. + /** + * This function is used to accept a new connection from a peer. The function + * call will block until a new connection has been accepted successfully or + * an error occurs. + * + * This overload requires that the Protocol template parameter satisfy the + * AcceptableProtocol type requirements. + * + * @param peer_endpoint An endpoint object into which the endpoint of the + * remote peer will be written. + * + * @returns A socket object representing the newly accepted connection. + * + * @throws boost::system::system_error Thrown on failure. + * + * @par Example + * @code + * boost::asio::ip::tcp::acceptor acceptor(my_context); + * ... + * boost::asio::ip::tcp::endpoint endpoint; + * boost::asio::ip::tcp::socket socket(acceptor.accept(endpoint)); + * @endcode + */ + typename Protocol::socket accept(endpoint_type& peer_endpoint) + { + boost::system::error_code ec; + typename Protocol::socket peer(impl_.get_executor()); + impl_.get_service().accept(impl_.get_implementation(), + peer, &peer_endpoint, ec); + boost::asio::detail::throw_error(ec, "accept"); + return peer; + } + + /// Accept a new connection. + /** + * This function is used to accept a new connection from a peer. The function + * call will block until a new connection has been accepted successfully or + * an error occurs. + * + * This overload requires that the Protocol template parameter satisfy the + * AcceptableProtocol type requirements. + * + * @param peer_endpoint An endpoint object into which the endpoint of the + * remote peer will be written. + * + * @param ec Set to indicate what error occurred, if any. + * + * @returns On success, a socket object representing the newly accepted + * connection. On error, a socket object where is_open() is false. + * + * @par Example + * @code + * boost::asio::ip::tcp::acceptor acceptor(my_context); + * ... + * boost::asio::ip::tcp::endpoint endpoint; + * boost::asio::ip::tcp::socket socket(acceptor.accept(endpoint, ec)); + * if (ec) + * { + * // An error occurred. + * } + * @endcode + */ + typename Protocol::socket accept( + endpoint_type& peer_endpoint, boost::system::error_code& ec) + { + typename Protocol::socket peer(impl_.get_executor()); + impl_.get_service().accept(impl_.get_implementation(), + peer, &peer_endpoint, ec); + return peer; + } + + /// Start an asynchronous accept. + /** + * This function is used to asynchronously accept a new connection. The + * function call always returns immediately. + * + * This overload requires that the Protocol template parameter satisfy the + * AcceptableProtocol type requirements. + * + * @param peer_endpoint An endpoint object into which the endpoint of the + * remote peer will be written. Ownership of the peer_endpoint object is + * retained by the caller, which must guarantee that it is valid until the + * handler is called. + * + * @param handler The handler to be called when the accept operation + * completes. Copies will be made of the handler as required. The function + * signature of the handler must be: + * @code void handler( + * const boost::system::error_code& error, // Result of operation. + * typename Protocol::socket peer // On success, the newly accepted socket. + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. On + * immediate completion, invocation of the handler will be performed in a + * manner equivalent to using boost::asio::post(). + * + * @par Example + * @code + * void accept_handler(const boost::system::error_code& error, + * boost::asio::ip::tcp::socket peer) + * { + * if (!error) + * { + * // Accept succeeded. + * } + * } + * + * ... + * + * boost::asio::ip::tcp::acceptor acceptor(my_context); + * ... + * boost::asio::ip::tcp::endpoint endpoint; + * acceptor.async_accept(endpoint, accept_handler); + * @endcode + */ + template + BOOST_ASIO_INITFN_RESULT_TYPE(MoveAcceptHandler, + void (boost::system::error_code, typename Protocol::socket)) + async_accept(endpoint_type& peer_endpoint, + BOOST_ASIO_MOVE_ARG(MoveAcceptHandler) handler) + { + return async_initiate( + initiate_async_move_accept(), handler, this, + impl_.get_executor(), &peer_endpoint, + static_cast(0)); + } + + /// Accept a new connection. + /** + * This function is used to accept a new connection from a peer. The function + * call will block until a new connection has been accepted successfully or + * an error occurs. + * + * This overload requires that the Protocol template parameter satisfy the + * AcceptableProtocol type requirements. + * + * @param ex The I/O executor object to be used for the newly accepted + * socket. + * + * @param peer_endpoint An endpoint object into which the endpoint of the + * remote peer will be written. + * + * @returns A socket object representing the newly accepted connection. + * + * @throws boost::system::system_error Thrown on failure. + * + * @par Example + * @code + * boost::asio::ip::tcp::acceptor acceptor(my_context); + * ... + * boost::asio::ip::tcp::endpoint endpoint; + * boost::asio::ip::tcp::socket socket( + * acceptor.accept(my_context2, endpoint)); + * @endcode + */ + template + typename Protocol::socket::template rebind_executor::other + accept(const Executor1& ex, endpoint_type& peer_endpoint, + typename enable_if< + is_executor::value + >::type* = 0) + { + boost::system::error_code ec; + typename Protocol::socket::template + rebind_executor::other peer(ex); + impl_.get_service().accept(impl_.get_implementation(), + peer, &peer_endpoint, ec); + boost::asio::detail::throw_error(ec, "accept"); + return peer; + } + + /// Accept a new connection. + /** + * This function is used to accept a new connection from a peer. The function + * call will block until a new connection has been accepted successfully or + * an error occurs. + * + * This overload requires that the Protocol template parameter satisfy the + * AcceptableProtocol type requirements. + * + * @param context The I/O execution context object to be used for the newly + * accepted socket. + * + * @param peer_endpoint An endpoint object into which the endpoint of the + * remote peer will be written. + * + * @returns A socket object representing the newly accepted connection. + * + * @throws boost::system::system_error Thrown on failure. + * + * @par Example + * @code + * boost::asio::ip::tcp::acceptor acceptor(my_context); + * ... + * boost::asio::ip::tcp::endpoint endpoint; + * boost::asio::ip::tcp::socket socket( + * acceptor.accept(my_context2, endpoint)); + * @endcode + */ + template + typename Protocol::socket::template rebind_executor< + typename ExecutionContext::executor_type>::other + accept(ExecutionContext& context, endpoint_type& peer_endpoint, + typename enable_if< + is_convertible::value + >::type* = 0) + { + boost::system::error_code ec; + typename Protocol::socket::template rebind_executor< + typename ExecutionContext::executor_type>::other peer(context); + impl_.get_service().accept(impl_.get_implementation(), + peer, &peer_endpoint, ec); + boost::asio::detail::throw_error(ec, "accept"); + return peer; + } + + /// Accept a new connection. + /** + * This function is used to accept a new connection from a peer. The function + * call will block until a new connection has been accepted successfully or + * an error occurs. + * + * This overload requires that the Protocol template parameter satisfy the + * AcceptableProtocol type requirements. + * + * @param ex The I/O executor object to be used for the newly accepted + * socket. + * + * @param peer_endpoint An endpoint object into which the endpoint of the + * remote peer will be written. + * + * @param ec Set to indicate what error occurred, if any. + * + * @returns On success, a socket object representing the newly accepted + * connection. On error, a socket object where is_open() is false. + * + * @par Example + * @code + * boost::asio::ip::tcp::acceptor acceptor(my_context); + * ... + * boost::asio::ip::tcp::endpoint endpoint; + * boost::asio::ip::tcp::socket socket( + * acceptor.accept(my_context2, endpoint, ec)); + * if (ec) + * { + * // An error occurred. + * } + * @endcode + */ + template + typename Protocol::socket::template rebind_executor::other + accept(const executor_type& ex, + endpoint_type& peer_endpoint, boost::system::error_code& ec, + typename enable_if< + is_executor::value + >::type* = 0) + { + typename Protocol::socket::template + rebind_executor::other peer(ex); + impl_.get_service().accept(impl_.get_implementation(), + peer, &peer_endpoint, ec); + return peer; + } + + /// Accept a new connection. + /** + * This function is used to accept a new connection from a peer. The function + * call will block until a new connection has been accepted successfully or + * an error occurs. + * + * This overload requires that the Protocol template parameter satisfy the + * AcceptableProtocol type requirements. + * + * @param context The I/O execution context object to be used for the newly + * accepted socket. + * + * @param peer_endpoint An endpoint object into which the endpoint of the + * remote peer will be written. + * + * @param ec Set to indicate what error occurred, if any. + * + * @returns On success, a socket object representing the newly accepted + * connection. On error, a socket object where is_open() is false. + * + * @par Example + * @code + * boost::asio::ip::tcp::acceptor acceptor(my_context); + * ... + * boost::asio::ip::tcp::endpoint endpoint; + * boost::asio::ip::tcp::socket socket( + * acceptor.accept(my_context2, endpoint, ec)); + * if (ec) + * { + * // An error occurred. + * } + * @endcode + */ + template + typename Protocol::socket::template rebind_executor< + typename ExecutionContext::executor_type>::other + accept(ExecutionContext& context, + endpoint_type& peer_endpoint, boost::system::error_code& ec, + typename enable_if< + is_convertible::value + >::type* = 0) + { + typename Protocol::socket::template rebind_executor< + typename ExecutionContext::executor_type>::other peer(context); + impl_.get_service().accept(impl_.get_implementation(), + peer, &peer_endpoint, ec); + return peer; + } + + /// Start an asynchronous accept. + /** + * This function is used to asynchronously accept a new connection. The + * function call always returns immediately. + * + * This overload requires that the Protocol template parameter satisfy the + * AcceptableProtocol type requirements. + * + * @param ex The I/O executor object to be used for the newly accepted + * socket. + * + * @param peer_endpoint An endpoint object into which the endpoint of the + * remote peer will be written. Ownership of the peer_endpoint object is + * retained by the caller, which must guarantee that it is valid until the + * handler is called. + * + * @param handler The handler to be called when the accept operation + * completes. Copies will be made of the handler as required. The function + * signature of the handler must be: + * @code void handler( + * const boost::system::error_code& error, // Result of operation. + * typename Protocol::socket::template rebind_executor< + * Executor1>::other peer // On success, the newly accepted socket. + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. On + * immediate completion, invocation of the handler will be performed in a + * manner equivalent to using boost::asio::post(). + * + * @par Example + * @code + * void accept_handler(const boost::system::error_code& error, + * boost::asio::ip::tcp::socket peer) + * { + * if (!error) + * { + * // Accept succeeded. + * } + * } + * + * ... + * + * boost::asio::ip::tcp::acceptor acceptor(my_context); + * ... + * boost::asio::ip::tcp::endpoint endpoint; + * acceptor.async_accept(my_context2, endpoint, accept_handler); + * @endcode + */ + template + BOOST_ASIO_INITFN_RESULT_TYPE(MoveAcceptHandler, + void (boost::system::error_code, + typename Protocol::socket::template rebind_executor< + Executor1>::other)) + async_accept(const Executor1& ex, endpoint_type& peer_endpoint, + BOOST_ASIO_MOVE_ARG(MoveAcceptHandler) handler, + typename enable_if< + is_executor::value + >::type* = 0) + { + typedef typename Protocol::socket::template rebind_executor< + Executor1>::other other_socket_type; + + return async_initiate( + initiate_async_move_accept(), handler, this, + ex, &peer_endpoint, + static_cast(0)); + } + + /// Start an asynchronous accept. + /** + * This function is used to asynchronously accept a new connection. The + * function call always returns immediately. + * + * This overload requires that the Protocol template parameter satisfy the + * AcceptableProtocol type requirements. + * + * @param context The I/O execution context object to be used for the newly + * accepted socket. + * + * @param peer_endpoint An endpoint object into which the endpoint of the + * remote peer will be written. Ownership of the peer_endpoint object is + * retained by the caller, which must guarantee that it is valid until the + * handler is called. + * + * @param handler The handler to be called when the accept operation + * completes. Copies will be made of the handler as required. The function + * signature of the handler must be: + * @code void handler( + * const boost::system::error_code& error, // Result of operation. + * typename Protocol::socket::template rebind_executor< + * typename ExecutionContext::executor_type>::other peer + * // On success, the newly accepted socket. + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. On + * immediate completion, invocation of the handler will be performed in a + * manner equivalent to using boost::asio::post(). + * + * @par Example + * @code + * void accept_handler(const boost::system::error_code& error, + * boost::asio::ip::tcp::socket peer) + * { + * if (!error) + * { + * // Accept succeeded. + * } + * } + * + * ... + * + * boost::asio::ip::tcp::acceptor acceptor(my_context); + * ... + * boost::asio::ip::tcp::endpoint endpoint; + * acceptor.async_accept(my_context2, endpoint, accept_handler); + * @endcode + */ + template + BOOST_ASIO_INITFN_RESULT_TYPE(MoveAcceptHandler, + void (boost::system::error_code, + typename Protocol::socket::template rebind_executor< + typename ExecutionContext::executor_type>::other)) + async_accept(ExecutionContext& context, + endpoint_type& peer_endpoint, + BOOST_ASIO_MOVE_ARG(MoveAcceptHandler) handler, + typename enable_if< + is_convertible::value + >::type* = 0) + { + typedef typename Protocol::socket::template rebind_executor< + typename ExecutionContext::executor_type>::other other_socket_type; + + return async_initiate( + initiate_async_move_accept(), handler, this, + context.get_executor(), &peer_endpoint, + static_cast(0)); + } +#endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) + +private: + // Disallow copying and assignment. + basic_socket_acceptor_ext(const basic_socket_acceptor_ext&) BOOST_ASIO_DELETED; + basic_socket_acceptor_ext& operator=( + const basic_socket_acceptor_ext&) BOOST_ASIO_DELETED; + + struct initiate_async_wait + { + template + void operator()(BOOST_ASIO_MOVE_ARG(WaitHandler) handler, + basic_socket_acceptor_ext* self, wait_type w) const + { + // If you get an error on the following line it means that your handler + // does not meet the documented type requirements for a WaitHandler. + BOOST_ASIO_WAIT_HANDLER_CHECK(WaitHandler, handler) type_check; + + detail::non_const_lvalue handler2(handler); + self->impl_.get_service().async_wait( + self->impl_.get_implementation(), w, handler2.value, + self->impl_.get_implementation_executor()); + } + }; + + struct initiate_async_accept + { + template + void operator()(BOOST_ASIO_MOVE_ARG(AcceptHandler) handler, + basic_socket_acceptor_ext* self, basic_socket_ext_local* peer, + endpoint_type* peer_endpoint) const + { + // If you get an error on the following line it means that your handler + // does not meet the documented type requirements for a AcceptHandler. + BOOST_ASIO_ACCEPT_HANDLER_CHECK(AcceptHandler, handler) type_check; + + detail::non_const_lvalue handler2(handler); + self->impl_.get_service().async_accept( + self->impl_.get_implementation(), *peer, peer_endpoint, + handler2.value, self->impl_.get_executor()); + } + }; + + struct initiate_async_move_accept + { + template + void operator()(BOOST_ASIO_MOVE_ARG(MoveAcceptHandler) handler, + basic_socket_acceptor_ext* self, const Executor1& peer_ex, + endpoint_type* peer_endpoint, Socket*) const + { + // If you get an error on the following line it means that your handler + // does not meet the documented type requirements for a MoveAcceptHandler. + BOOST_ASIO_MOVE_ACCEPT_HANDLER_CHECK( + MoveAcceptHandler, handler, Socket) type_check; + + detail::non_const_lvalue handler2(handler); + self->impl_.get_service().async_move_accept( + self->impl_.get_implementation(), peer_ex, peer_endpoint, + handler2.value, self->impl_.get_implementation_executor()); + } + }; + +#if defined(BOOST_ASIO_WINDOWS_RUNTIME) + detail::io_object_impl< + detail::null_socket_service, Executor> impl_; +#elif defined(BOOST_ASIO_HAS_IOCP) + detail::io_object_impl< + detail::win_iocp_socket_service, Executor> impl_; +#else + detail::io_object_impl< + detail::reactive_socket_service_ext_local, Executor> impl_; +#endif +}; + +} // namespace asio +} // namespace boost + +#include + +#endif // BOOST_ASIO_BASIC_SOCKET_ACCEPTOR_EXT_HPP diff --git a/implementation/helper/1.76/boost/asio/basic_socket_ext.hpp b/implementation/helper/1.76/boost/asio/basic_socket_ext.hpp new file mode 100644 index 0000000..777a0bf --- /dev/null +++ b/implementation/helper/1.76/boost/asio/basic_socket_ext.hpp @@ -0,0 +1,1859 @@ +// +// basic_socket_ext.hpp +// ~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2018,2019 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_BASIC_SOCKET_EXT_HPP +#define BOOST_ASIO_BASIC_SOCKET_EXT_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined(BOOST_ASIO_WINDOWS_RUNTIME) +# include +#elif defined(BOOST_ASIO_HAS_IOCP) +# include +#else +# include +#endif + +#if defined(BOOST_ASIO_HAS_MOVE) +# include +#endif // defined(BOOST_ASIO_HAS_MOVE) + +#include + +namespace boost { +namespace asio { + +#if !defined(BOOST_ASIO_BASIC_SOCKET_EXT_FWD_DECL) +#define BOOST_ASIO_BASIC_SOCKET_EXT_FWD_DECL + +// Forward declaration with defaulted arguments. +template +class basic_socket_ext; + +#endif // !defined(BOOST_ASIO_BASIC_SOCKET_EXT_FWD_DECL) + +/// Provides socket functionality. +/** + * The basic_socket class template provides functionality that is common to both + * stream-oriented and datagram-oriented sockets. + * + * @par Thread Safety + * @e Distinct @e objects: Safe.@n + * @e Shared @e objects: Unsafe. + */ +template +class basic_socket_ext + : public socket_base +{ +public: + /// The type of the executor associated with the object. + typedef Executor executor_type; + + /// Rebinds the socket type to another executor. + template + struct rebind_executor + { + /// The socket type when rebound to the specified executor. + typedef basic_socket_ext other; + }; + + /// The native representation of a socket. +#if defined(GENERATING_DOCUMENTATION) + typedef implementation_defined native_handle_type; +#elif defined(BOOST_ASIO_WINDOWS_RUNTIME) + typedef typename detail::null_socket_service< + Protocol>::native_handle_type native_handle_type; +#elif defined(BOOST_ASIO_HAS_IOCP) + typedef typename detail::win_iocp_socket_service< + Protocol>::native_handle_type native_handle_type; +#else + typedef typename detail::reactive_socket_service_ext< + Protocol>::native_handle_type native_handle_type; +#endif + + /// The protocol type. + typedef Protocol protocol_type; + + /// The endpoint type. + typedef typename Protocol::endpoint endpoint_type; + +#if !defined(BOOST_ASIO_NO_EXTENSIONS) + /// A basic_socket is always the lowest layer. + typedef basic_socket_ext lowest_layer_type; +#endif // !defined(BOOST_ASIO_NO_EXTENSIONS) + + /// Construct a basic_socket without opening it. + /** + * This constructor creates a socket without opening it. + * + * @param ex The I/O executor that the socket will use, by default, to + * dispatch handlers for any asynchronous operations performed on the socket. + */ + explicit basic_socket_ext(const executor_type& ex) + : impl_(0, ex) + { + } + + /// Construct a basic_socket without opening it. + /** + * This constructor creates a socket without opening it. + * + * @param context An execution context which provides the I/O executor that + * the socket will use, by default, to dispatch handlers for any asynchronous + * operations performed on the socket. + */ + template + explicit basic_socket_ext(ExecutionContext& context, + typename enable_if< + is_convertible::value + >::type* = 0) + : impl_(0, 0, context) + { + } + + /// Construct and open a basic_socket. + /** + * This constructor creates and opens a socket. + * + * @param ex The I/O executor that the socket will use, by default, to + * dispatch handlers for any asynchronous operations performed on the socket. + * + * @param protocol An object specifying protocol parameters to be used. + * + * @throws boost::system::system_error Thrown on failure. + */ + basic_socket_ext(const executor_type& ex, const protocol_type& protocol) + : impl_(0, ex) + { + boost::system::error_code ec; + impl_.get_service().open(impl_.get_implementation(), protocol, ec); + boost::asio::detail::throw_error(ec, "open"); + } + + /// Construct and open a basic_socket. + /** + * This constructor creates and opens a socket. + * + * @param context An execution context which provides the I/O executor that + * the socket will use, by default, to dispatch handlers for any asynchronous + * operations performed on the socket. + * + * @param protocol An object specifying protocol parameters to be used. + * + * @throws boost::system::system_error Thrown on failure. + */ + template + basic_socket_ext(ExecutionContext& context, const protocol_type& protocol, + typename enable_if< + is_convertible::value + >::type* = 0) + : impl_(0, 0, context) + { + boost::system::error_code ec; + impl_.get_service().open(impl_.get_implementation(), protocol, ec); + boost::asio::detail::throw_error(ec, "open"); + } + + /// Construct a basic_socket, opening it and binding it to the given local + /// endpoint. + /** + * This constructor creates a socket and automatically opens it bound to the + * specified endpoint on the local machine. The protocol used is the protocol + * associated with the given endpoint. + * + * @param ex The I/O executor that the socket will use, by default, to + * dispatch handlers for any asynchronous operations performed on the socket. + * + * @param endpoint An endpoint on the local machine to which the socket will + * be bound. + * + * @throws boost::system::system_error Thrown on failure. + */ + basic_socket_ext(const executor_type& ex, const endpoint_type& endpoint) + : impl_(0, ex) + { + boost::system::error_code ec; + const protocol_type protocol = endpoint.protocol(); + impl_.get_service().open(impl_.get_implementation(), protocol, ec); + boost::asio::detail::throw_error(ec, "open"); + impl_.get_service().bind(impl_.get_implementation(), endpoint, ec); + boost::asio::detail::throw_error(ec, "bind"); + } + + /// Construct a basic_socket, opening it and binding it to the given local + /// endpoint. + /** + * This constructor creates a socket and automatically opens it bound to the + * specified endpoint on the local machine. The protocol used is the protocol + * associated with the given endpoint. + * + * @param context An execution context which provides the I/O executor that + * the socket will use, by default, to dispatch handlers for any asynchronous + * operations performed on the socket. + * + * @param endpoint An endpoint on the local machine to which the socket will + * be bound. + * + * @throws boost::system::system_error Thrown on failure. + */ + template + basic_socket_ext(ExecutionContext& context, const endpoint_type& endpoint, + typename enable_if< + is_convertible::value + >::type* = 0) + : impl_(0, 0, context) + { + boost::system::error_code ec; + const protocol_type protocol = endpoint.protocol(); + impl_.get_service().open(impl_.get_implementation(), protocol, ec); + boost::asio::detail::throw_error(ec, "open"); + impl_.get_service().bind(impl_.get_implementation(), endpoint, ec); + boost::asio::detail::throw_error(ec, "bind"); + } + + /// Construct a basic_socket on an existing native socket. + /** + * This constructor creates a socket object to hold an existing native socket. + * + * @param ex The I/O executor that the socket will use, by default, to + * dispatch handlers for any asynchronous operations performed on the socket. + * + * @param protocol An object specifying protocol parameters to be used. + * + * @param native_socket A native socket. + * + * @throws boost::system::system_error Thrown on failure. + */ + basic_socket_ext(const executor_type& ex, const protocol_type& protocol, + const native_handle_type& native_socket) + : impl_(0, ex) + { + boost::system::error_code ec; + impl_.get_service().assign(impl_.get_implementation(), + protocol, native_socket, ec); + boost::asio::detail::throw_error(ec, "assign"); + } + + /// Construct a basic_socket on an existing native socket. + /** + * This constructor creates a socket object to hold an existing native socket. + * + * @param context An execution context which provides the I/O executor that + * the socket will use, by default, to dispatch handlers for any asynchronous + * operations performed on the socket. + * + * @param protocol An object specifying protocol parameters to be used. + * + * @param native_socket A native socket. + * + * @throws boost::system::system_error Thrown on failure. + */ + template + basic_socket_ext(ExecutionContext& context, const protocol_type& protocol, + const native_handle_type& native_socket, + typename enable_if< + is_convertible::value + >::type* = 0) + : impl_(0, 0, context) + { + boost::system::error_code ec; + impl_.get_service().assign(impl_.get_implementation(), + protocol, native_socket, ec); + boost::asio::detail::throw_error(ec, "assign"); + } + +#if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) + /// Move-construct a basic_socket from another. + /** + * This constructor moves a socket from one object to another. + * + * @param other The other basic_socket object from which the move will + * occur. + * + * @note Following the move, the moved-from object is in the same state as if + * constructed using the @c basic_socket(const executor_type&) constructor. + */ + basic_socket_ext(basic_socket_ext&& other) + : impl_(std::move(other.impl_)) + { + } + + /// Move-assign a basic_socket from another. + /** + * This assignment operator moves a socket from one object to another. + * + * @param other The other basic_socket object from which the move will + * occur. + * + * @note Following the move, the moved-from object is in the same state as if + * constructed using the @c basic_socket(const executor_type&) constructor. + */ + basic_socket_ext& operator=(basic_socket_ext&& other) + { + impl_ = std::move(other.impl_); + return *this; + } + + // All sockets have access to each other's implementations. + template + friend class basic_socket_ext; + + /// Move-construct a basic_socket from a socket of another protocol type. + /** + * This constructor moves a socket from one object to another. + * + * @param other The other basic_socket object from which the move will + * occur. + * + * @note Following the move, the moved-from object is in the same state as if + * constructed using the @c basic_socket(const executor_type&) constructor. + */ + template + basic_socket_ext(basic_socket_ext&& other, + typename enable_if< + is_convertible::value + && is_convertible::value + >::type* = 0) + : impl_(std::move(other.impl_)) + { + } + + /// Move-assign a basic_socket from a socket of another protocol type. + /** + * This assignment operator moves a socket from one object to another. + * + * @param other The other basic_socket object from which the move will + * occur. + * + * @note Following the move, the moved-from object is in the same state as if + * constructed using the @c basic_socket(const executor_type&) constructor. + */ + template + typename enable_if< + is_convertible::value + && is_convertible::value, + basic_socket_ext& + >::type operator=(basic_socket_ext && other) + { + basic_socket_ext tmp(std::move(other)); + impl_ = std::move(tmp.impl_); + return *this; + } +#endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) + + /// Get the executor associated with the object. + executor_type get_executor() BOOST_ASIO_NOEXCEPT + { + return impl_.get_executor(); + } + +#if !defined(BOOST_ASIO_NO_EXTENSIONS) + /// Get a reference to the lowest layer. + /** + * This function returns a reference to the lowest layer in a stack of + * layers. Since a basic_socket cannot contain any further layers, it simply + * returns a reference to itself. + * + * @return A reference to the lowest layer in the stack of layers. Ownership + * is not transferred to the caller. + */ + lowest_layer_type& lowest_layer() + { + return *this; + } + + /// Get a const reference to the lowest layer. + /** + * This function returns a const reference to the lowest layer in a stack of + * layers. Since a basic_socket cannot contain any further layers, it simply + * returns a reference to itself. + * + * @return A const reference to the lowest layer in the stack of layers. + * Ownership is not transferred to the caller. + */ + const lowest_layer_type& lowest_layer() const + { + return *this; + } +#endif // !defined(BOOST_ASIO_NO_EXTENSIONS) + + /// Open the socket using the specified protocol. + /** + * This function opens the socket so that it will use the specified protocol. + * + * @param protocol An object specifying protocol parameters to be used. + * + * @throws boost::system::system_error Thrown on failure. + * + * @par Example + * @code + * boost::asio::ip::tcp::socket socket(my_context); + * socket.open(boost::asio::ip::tcp::v4()); + * @endcode + */ + void open(const protocol_type& protocol = protocol_type()) + { + boost::system::error_code ec; + impl_.get_service().open(impl_.get_implementation(), protocol, ec); + boost::asio::detail::throw_error(ec, "open"); + } + + /// Open the socket using the specified protocol. + /** + * This function opens the socket so that it will use the specified protocol. + * + * @param protocol An object specifying which protocol is to be used. + * + * @param ec Set to indicate what error occurred, if any. + * + * @par Example + * @code + * boost::asio::ip::tcp::socket socket(my_context); + * boost::system::error_code ec; + * socket.open(boost::asio::ip::tcp::v4(), ec); + * if (ec) + * { + * // An error occurred. + * } + * @endcode + */ + BOOST_ASIO_SYNC_OP_VOID open(const protocol_type& protocol, + boost::system::error_code& ec) + { + impl_.get_service().open(impl_.get_implementation(), protocol, ec); + BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); + } + + /// Assign an existing native socket to the socket. + /* + * This function opens the socket to hold an existing native socket. + * + * @param protocol An object specifying which protocol is to be used. + * + * @param native_socket A native socket. + * + * @throws boost::system::system_error Thrown on failure. + */ + void assign(const protocol_type& protocol, + const native_handle_type& native_socket) + { + boost::system::error_code ec; + impl_.get_service().assign(impl_.get_implementation(), + protocol, native_socket, ec); + boost::asio::detail::throw_error(ec, "assign"); + } + + /// Assign an existing native socket to the socket. + /* + * This function opens the socket to hold an existing native socket. + * + * @param protocol An object specifying which protocol is to be used. + * + * @param native_socket A native socket. + * + * @param ec Set to indicate what error occurred, if any. + */ + BOOST_ASIO_SYNC_OP_VOID assign(const protocol_type& protocol, + const native_handle_type& native_socket, boost::system::error_code& ec) + { + impl_.get_service().assign(impl_.get_implementation(), + protocol, native_socket, ec); + BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); + } + + /// Determine whether the socket is open. + bool is_open() const + { + return impl_.get_service().is_open(impl_.get_implementation()); + } + + /// Close the socket. + /** + * This function is used to close the socket. Any asynchronous send, receive + * or connect operations will be cancelled immediately, and will complete + * with the boost::asio::error::operation_aborted error. + * + * @throws boost::system::system_error Thrown on failure. Note that, even if + * the function indicates an error, the underlying descriptor is closed. + * + * @note For portable behaviour with respect to graceful closure of a + * connected socket, call shutdown() before closing the socket. + */ + void close() + { + boost::system::error_code ec; + impl_.get_service().close(impl_.get_implementation(), ec); + boost::asio::detail::throw_error(ec, "close"); + } + + /// Close the socket. + /** + * This function is used to close the socket. Any asynchronous send, receive + * or connect operations will be cancelled immediately, and will complete + * with the boost::asio::error::operation_aborted error. + * + * @param ec Set to indicate what error occurred, if any. Note that, even if + * the function indicates an error, the underlying descriptor is closed. + * + * @par Example + * @code + * boost::asio::ip::tcp::socket socket(my_context); + * ... + * boost::system::error_code ec; + * socket.close(ec); + * if (ec) + * { + * // An error occurred. + * } + * @endcode + * + * @note For portable behaviour with respect to graceful closure of a + * connected socket, call shutdown() before closing the socket. + */ + BOOST_ASIO_SYNC_OP_VOID close(boost::system::error_code& ec) + { + impl_.get_service().close(impl_.get_implementation(), ec); + BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); + } + + /// Release ownership of the underlying native socket. + /** + * This function causes all outstanding asynchronous connect, send and receive + * operations to finish immediately, and the handlers for cancelled operations + * will be passed the boost::asio::error::operation_aborted error. Ownership + * of the native socket is then transferred to the caller. + * + * @throws boost::system::system_error Thrown on failure. + * + * @note This function is unsupported on Windows versions prior to Windows + * 8.1, and will fail with boost::asio::error::operation_not_supported on + * these platforms. + */ +#if defined(BOOST_ASIO_MSVC) && (BOOST_ASIO_MSVC >= 1400) \ + && (!defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0603) + __declspec(deprecated("This function always fails with " + "operation_not_supported when used on Windows versions " + "prior to Windows 8.1.")) +#endif + native_handle_type release() + { + boost::system::error_code ec; + native_handle_type s = impl_.get_service().release( + impl_.get_implementation(), ec); + boost::asio::detail::throw_error(ec, "release"); + return s; + } + + /// Release ownership of the underlying native socket. + /** + * This function causes all outstanding asynchronous connect, send and receive + * operations to finish immediately, and the handlers for cancelled operations + * will be passed the boost::asio::error::operation_aborted error. Ownership + * of the native socket is then transferred to the caller. + * + * @param ec Set to indicate what error occurred, if any. + * + * @note This function is unsupported on Windows versions prior to Windows + * 8.1, and will fail with boost::asio::error::operation_not_supported on + * these platforms. + */ +#if defined(BOOST_ASIO_MSVC) && (BOOST_ASIO_MSVC >= 1400) \ + && (!defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0603) + __declspec(deprecated("This function always fails with " + "operation_not_supported when used on Windows versions " + "prior to Windows 8.1.")) +#endif + native_handle_type release(boost::system::error_code& ec) + { + return impl_.get_service().release(impl_.get_implementation(), ec); + } + + /// Get the native socket representation. + /** + * This function may be used to obtain the underlying representation of the + * socket. This is intended to allow access to native socket functionality + * that is not otherwise provided. + */ + native_handle_type native_handle() + { + return impl_.get_service().native_handle(impl_.get_implementation()); + } + + /// Cancel all asynchronous operations associated with the socket. + /** + * This function causes all outstanding asynchronous connect, send and receive + * operations to finish immediately, and the handlers for cancelled operations + * will be passed the boost::asio::error::operation_aborted error. + * + * @throws boost::system::system_error Thrown on failure. + * + * @note Calls to cancel() will always fail with + * boost::asio::error::operation_not_supported when run on Windows XP, Windows + * Server 2003, and earlier versions of Windows, unless + * BOOST_ASIO_ENABLE_CANCELIO is defined. However, the CancelIo function has + * two issues that should be considered before enabling its use: + * + * @li It will only cancel asynchronous operations that were initiated in the + * current thread. + * + * @li It can appear to complete without error, but the request to cancel the + * unfinished operations may be silently ignored by the operating system. + * Whether it works or not seems to depend on the drivers that are installed. + * + * For portable cancellation, consider using one of the following + * alternatives: + * + * @li Disable asio's I/O completion port backend by defining + * BOOST_ASIO_DISABLE_IOCP. + * + * @li Use the close() function to simultaneously cancel the outstanding + * operations and close the socket. + * + * When running on Windows Vista, Windows Server 2008, and later, the + * CancelIoEx function is always used. This function does not have the + * problems described above. + */ +#if defined(BOOST_ASIO_MSVC) && (BOOST_ASIO_MSVC >= 1400) \ + && (!defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0600) \ + && !defined(BOOST_ASIO_ENABLE_CANCELIO) + __declspec(deprecated("By default, this function always fails with " + "operation_not_supported when used on Windows XP, Windows Server 2003, " + "or earlier. Consult documentation for details.")) +#endif + void cancel() + { + boost::system::error_code ec; + impl_.get_service().cancel(impl_.get_implementation(), ec); + boost::asio::detail::throw_error(ec, "cancel"); + } + + /// Cancel all asynchronous operations associated with the socket. + /** + * This function causes all outstanding asynchronous connect, send and receive + * operations to finish immediately, and the handlers for cancelled operations + * will be passed the boost::asio::error::operation_aborted error. + * + * @param ec Set to indicate what error occurred, if any. + * + * @note Calls to cancel() will always fail with + * boost::asio::error::operation_not_supported when run on Windows XP, Windows + * Server 2003, and earlier versions of Windows, unless + * BOOST_ASIO_ENABLE_CANCELIO is defined. However, the CancelIo function has + * two issues that should be considered before enabling its use: + * + * @li It will only cancel asynchronous operations that were initiated in the + * current thread. + * + * @li It can appear to complete without error, but the request to cancel the + * unfinished operations may be silently ignored by the operating system. + * Whether it works or not seems to depend on the drivers that are installed. + * + * For portable cancellation, consider using one of the following + * alternatives: + * + * @li Disable asio's I/O completion port backend by defining + * BOOST_ASIO_DISABLE_IOCP. + * + * @li Use the close() function to simultaneously cancel the outstanding + * operations and close the socket. + * + * When running on Windows Vista, Windows Server 2008, and later, the + * CancelIoEx function is always used. This function does not have the + * problems described above. + */ +#if defined(BOOST_ASIO_MSVC) && (BOOST_ASIO_MSVC >= 1400) \ + && (!defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0600) \ + && !defined(BOOST_ASIO_ENABLE_CANCELIO) + __declspec(deprecated("By default, this function always fails with " + "operation_not_supported when used on Windows XP, Windows Server 2003, " + "or earlier. Consult documentation for details.")) +#endif + BOOST_ASIO_SYNC_OP_VOID cancel(boost::system::error_code& ec) + { + impl_.get_service().cancel(impl_.get_implementation(), ec); + BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); + } + + /// Determine whether the socket is at the out-of-band data mark. + /** + * This function is used to check whether the socket input is currently + * positioned at the out-of-band data mark. + * + * @return A bool indicating whether the socket is at the out-of-band data + * mark. + * + * @throws boost::system::system_error Thrown on failure. + */ + bool at_mark() const + { + boost::system::error_code ec; + bool b = impl_.get_service().at_mark(impl_.get_implementation(), ec); + boost::asio::detail::throw_error(ec, "at_mark"); + return b; + } + + /// Determine whether the socket is at the out-of-band data mark. + /** + * This function is used to check whether the socket input is currently + * positioned at the out-of-band data mark. + * + * @param ec Set to indicate what error occurred, if any. + * + * @return A bool indicating whether the socket is at the out-of-band data + * mark. + */ + bool at_mark(boost::system::error_code& ec) const + { + return impl_.get_service().at_mark(impl_.get_implementation(), ec); + } + + /// Determine the number of bytes available for reading. + /** + * This function is used to determine the number of bytes that may be read + * without blocking. + * + * @return The number of bytes that may be read without blocking, or 0 if an + * error occurs. + * + * @throws boost::system::system_error Thrown on failure. + */ + std::size_t available() const + { + boost::system::error_code ec; + std::size_t s = impl_.get_service().available( + impl_.get_implementation(), ec); + boost::asio::detail::throw_error(ec, "available"); + return s; + } + + /// Determine the number of bytes available for reading. + /** + * This function is used to determine the number of bytes that may be read + * without blocking. + * + * @param ec Set to indicate what error occurred, if any. + * + * @return The number of bytes that may be read without blocking, or 0 if an + * error occurs. + */ + std::size_t available(boost::system::error_code& ec) const + { + return impl_.get_service().available(impl_.get_implementation(), ec); + } + + /// Bind the socket to the given local endpoint. + /** + * This function binds the socket to the specified endpoint on the local + * machine. + * + * @param endpoint An endpoint on the local machine to which the socket will + * be bound. + * + * @throws boost::system::system_error Thrown on failure. + * + * @par Example + * @code + * boost::asio::ip::tcp::socket socket(my_context); + * socket.open(boost::asio::ip::tcp::v4()); + * socket.bind(boost::asio::ip::tcp::endpoint( + * boost::asio::ip::tcp::v4(), 12345)); + * @endcode + */ + void bind(const endpoint_type& endpoint) + { + boost::system::error_code ec; + impl_.get_service().bind(impl_.get_implementation(), endpoint, ec); + boost::asio::detail::throw_error(ec, "bind"); + } + + /// Bind the socket to the given local endpoint. + /** + * This function binds the socket to the specified endpoint on the local + * machine. + * + * @param endpoint An endpoint on the local machine to which the socket will + * be bound. + * + * @param ec Set to indicate what error occurred, if any. + * + * @par Example + * @code + * boost::asio::ip::tcp::socket socket(my_context); + * socket.open(boost::asio::ip::tcp::v4()); + * boost::system::error_code ec; + * socket.bind(boost::asio::ip::tcp::endpoint( + * boost::asio::ip::tcp::v4(), 12345), ec); + * if (ec) + * { + * // An error occurred. + * } + * @endcode + */ + BOOST_ASIO_SYNC_OP_VOID bind(const endpoint_type& endpoint, + boost::system::error_code& ec) + { + impl_.get_service().bind(impl_.get_implementation(), endpoint, ec); + BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); + } + + /// Connect the socket to the specified endpoint. + /** + * This function is used to connect a socket to the specified remote endpoint. + * The function call will block until the connection is successfully made or + * an error occurs. + * + * The socket is automatically opened if it is not already open. If the + * connect fails, and the socket was automatically opened, the socket is + * not returned to the closed state. + * + * @param peer_endpoint The remote endpoint to which the socket will be + * connected. + * + * @throws boost::system::system_error Thrown on failure. + * + * @par Example + * @code + * boost::asio::ip::tcp::socket socket(my_context); + * boost::asio::ip::tcp::endpoint endpoint( + * boost::asio::ip::address::from_string("1.2.3.4"), 12345); + * socket.connect(endpoint); + * @endcode + */ + void connect(const endpoint_type& peer_endpoint) + { + boost::system::error_code ec; + if (!is_open()) + { + impl_.get_service().open(impl_.get_implementation(), + peer_endpoint.protocol(), ec); + boost::asio::detail::throw_error(ec, "connect"); + } + impl_.get_service().connect(impl_.get_implementation(), peer_endpoint, ec); + boost::asio::detail::throw_error(ec, "connect"); + } + + /// Connect the socket to the specified endpoint. + /** + * This function is used to connect a socket to the specified remote endpoint. + * The function call will block until the connection is successfully made or + * an error occurs. + * + * The socket is automatically opened if it is not already open. If the + * connect fails, and the socket was automatically opened, the socket is + * not returned to the closed state. + * + * @param peer_endpoint The remote endpoint to which the socket will be + * connected. + * + * @param ec Set to indicate what error occurred, if any. + * + * @par Example + * @code + * boost::asio::ip::tcp::socket socket(my_context); + * boost::asio::ip::tcp::endpoint endpoint( + * boost::asio::ip::address::from_string("1.2.3.4"), 12345); + * boost::system::error_code ec; + * socket.connect(endpoint, ec); + * if (ec) + * { + * // An error occurred. + * } + * @endcode + */ + BOOST_ASIO_SYNC_OP_VOID connect(const endpoint_type& peer_endpoint, + boost::system::error_code& ec) + { + if (!is_open()) + { + impl_.get_service().open(impl_.get_implementation(), + peer_endpoint.protocol(), ec); + if (ec) + { + BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); + } + } + + impl_.get_service().connect(impl_.get_implementation(), peer_endpoint, ec); + BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); + } + + /// Start an asynchronous connect. + /** + * This function is used to asynchronously connect a socket to the specified + * remote endpoint. The function call always returns immediately. + * + * The socket is automatically opened if it is not already open. If the + * connect fails, and the socket was automatically opened, the socket is + * not returned to the closed state. + * + * @param peer_endpoint The remote endpoint to which the socket will be + * connected. Copies will be made of the endpoint object as required. + * + * @param handler The handler to be called when the connection operation + * completes. Copies will be made of the handler as required. The function + * signature of the handler must be: + * @code void handler( + * const boost::system::error_code& error // Result of operation + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. On + * immediate completion, invocation of the handler will be performed in a + * manner equivalent to using boost::asio::post(). + * + * @par Example + * @code + * void connect_handler(const boost::system::error_code& error) + * { + * if (!error) + * { + * // Connect succeeded. + * } + * } + * + * ... + * + * boost::asio::ip::tcp::socket socket(my_context); + * boost::asio::ip::tcp::endpoint endpoint( + * boost::asio::ip::address::from_string("1.2.3.4"), 12345); + * socket.async_connect(endpoint, connect_handler); + * @endcode + */ + template + BOOST_ASIO_INITFN_RESULT_TYPE(ConnectHandler, + void (boost::system::error_code)) + async_connect(const endpoint_type& peer_endpoint, + BOOST_ASIO_MOVE_ARG(ConnectHandler) handler) + { + boost::system::error_code open_ec; + if (!is_open()) + { + const protocol_type protocol = peer_endpoint.protocol(); + impl_.get_service().open(impl_.get_implementation(), protocol, open_ec); + } + + return async_initiate( + initiate_async_connect(), handler, this, peer_endpoint, open_ec); + } + + /// Set an option on the socket. + /** + * This function is used to set an option on the socket. + * + * @param option The new option value to be set on the socket. + * + * @throws boost::system::system_error Thrown on failure. + * + * @sa SettableSocketOption @n + * boost::asio::socket_base::broadcast @n + * boost::asio::socket_base::do_not_route @n + * boost::asio::socket_base::keep_alive @n + * boost::asio::socket_base::linger @n + * boost::asio::socket_base::receive_buffer_size @n + * boost::asio::socket_base::receive_low_watermark @n + * boost::asio::socket_base::reuse_address @n + * boost::asio::socket_base::send_buffer_size @n + * boost::asio::socket_base::send_low_watermark @n + * boost::asio::ip::multicast::join_group @n + * boost::asio::ip::multicast::leave_group @n + * boost::asio::ip::multicast::enable_loopback @n + * boost::asio::ip::multicast::outbound_interface @n + * boost::asio::ip::multicast::hops @n + * boost::asio::ip::tcp::no_delay + * + * @par Example + * Setting the IPPROTO_TCP/TCP_NODELAY option: + * @code + * boost::asio::ip::tcp::socket socket(my_context); + * ... + * boost::asio::ip::tcp::no_delay option(true); + * socket.set_option(option); + * @endcode + */ + template + void set_option(const SettableSocketOption& option) + { + boost::system::error_code ec; + impl_.get_service().set_option(impl_.get_implementation(), option, ec); + boost::asio::detail::throw_error(ec, "set_option"); + } + + /// Set an option on the socket. + /** + * This function is used to set an option on the socket. + * + * @param option The new option value to be set on the socket. + * + * @param ec Set to indicate what error occurred, if any. + * + * @sa SettableSocketOption @n + * boost::asio::socket_base::broadcast @n + * boost::asio::socket_base::do_not_route @n + * boost::asio::socket_base::keep_alive @n + * boost::asio::socket_base::linger @n + * boost::asio::socket_base::receive_buffer_size @n + * boost::asio::socket_base::receive_low_watermark @n + * boost::asio::socket_base::reuse_address @n + * boost::asio::socket_base::send_buffer_size @n + * boost::asio::socket_base::send_low_watermark @n + * boost::asio::ip::multicast::join_group @n + * boost::asio::ip::multicast::leave_group @n + * boost::asio::ip::multicast::enable_loopback @n + * boost::asio::ip::multicast::outbound_interface @n + * boost::asio::ip::multicast::hops @n + * boost::asio::ip::tcp::no_delay + * + * @par Example + * Setting the IPPROTO_TCP/TCP_NODELAY option: + * @code + * boost::asio::ip::tcp::socket socket(my_context); + * ... + * boost::asio::ip::tcp::no_delay option(true); + * boost::system::error_code ec; + * socket.set_option(option, ec); + * if (ec) + * { + * // An error occurred. + * } + * @endcode + */ + template + BOOST_ASIO_SYNC_OP_VOID set_option(const SettableSocketOption& option, + boost::system::error_code& ec) + { + impl_.get_service().set_option(impl_.get_implementation(), option, ec); + BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); + } + + /// Get an option from the socket. + /** + * This function is used to get the current value of an option on the socket. + * + * @param option The option value to be obtained from the socket. + * + * @throws boost::system::system_error Thrown on failure. + * + * @sa GettableSocketOption @n + * boost::asio::socket_base::broadcast @n + * boost::asio::socket_base::do_not_route @n + * boost::asio::socket_base::keep_alive @n + * boost::asio::socket_base::linger @n + * boost::asio::socket_base::receive_buffer_size @n + * boost::asio::socket_base::receive_low_watermark @n + * boost::asio::socket_base::reuse_address @n + * boost::asio::socket_base::send_buffer_size @n + * boost::asio::socket_base::send_low_watermark @n + * boost::asio::ip::multicast::join_group @n + * boost::asio::ip::multicast::leave_group @n + * boost::asio::ip::multicast::enable_loopback @n + * boost::asio::ip::multicast::outbound_interface @n + * boost::asio::ip::multicast::hops @n + * boost::asio::ip::tcp::no_delay + * + * @par Example + * Getting the value of the SOL_SOCKET/SO_KEEPALIVE option: + * @code + * boost::asio::ip::tcp::socket socket(my_context); + * ... + * boost::asio::ip::tcp::socket::keep_alive option; + * socket.get_option(option); + * bool is_set = option.value(); + * @endcode + */ + template + void get_option(GettableSocketOption& option) const + { + boost::system::error_code ec; + impl_.get_service().get_option(impl_.get_implementation(), option, ec); + boost::asio::detail::throw_error(ec, "get_option"); + } + + /// Get an option from the socket. + /** + * This function is used to get the current value of an option on the socket. + * + * @param option The option value to be obtained from the socket. + * + * @param ec Set to indicate what error occurred, if any. + * + * @sa GettableSocketOption @n + * boost::asio::socket_base::broadcast @n + * boost::asio::socket_base::do_not_route @n + * boost::asio::socket_base::keep_alive @n + * boost::asio::socket_base::linger @n + * boost::asio::socket_base::receive_buffer_size @n + * boost::asio::socket_base::receive_low_watermark @n + * boost::asio::socket_base::reuse_address @n + * boost::asio::socket_base::send_buffer_size @n + * boost::asio::socket_base::send_low_watermark @n + * boost::asio::ip::multicast::join_group @n + * boost::asio::ip::multicast::leave_group @n + * boost::asio::ip::multicast::enable_loopback @n + * boost::asio::ip::multicast::outbound_interface @n + * boost::asio::ip::multicast::hops @n + * boost::asio::ip::tcp::no_delay + * + * @par Example + * Getting the value of the SOL_SOCKET/SO_KEEPALIVE option: + * @code + * boost::asio::ip::tcp::socket socket(my_context); + * ... + * boost::asio::ip::tcp::socket::keep_alive option; + * boost::system::error_code ec; + * socket.get_option(option, ec); + * if (ec) + * { + * // An error occurred. + * } + * bool is_set = option.value(); + * @endcode + */ + template + BOOST_ASIO_SYNC_OP_VOID get_option(GettableSocketOption& option, + boost::system::error_code& ec) const + { + impl_.get_service().get_option(impl_.get_implementation(), option, ec); + BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); + } + + /// Perform an IO control command on the socket. + /** + * This function is used to execute an IO control command on the socket. + * + * @param command The IO control command to be performed on the socket. + * + * @throws boost::system::system_error Thrown on failure. + * + * @sa IoControlCommand @n + * boost::asio::socket_base::bytes_readable @n + * boost::asio::socket_base::non_blocking_io + * + * @par Example + * Getting the number of bytes ready to read: + * @code + * boost::asio::ip::tcp::socket socket(my_context); + * ... + * boost::asio::ip::tcp::socket::bytes_readable command; + * socket.io_control(command); + * std::size_t bytes_readable = command.get(); + * @endcode + */ + template + void io_control(IoControlCommand& command) + { + boost::system::error_code ec; + impl_.get_service().io_control(impl_.get_implementation(), command, ec); + boost::asio::detail::throw_error(ec, "io_control"); + } + + /// Perform an IO control command on the socket. + /** + * This function is used to execute an IO control command on the socket. + * + * @param command The IO control command to be performed on the socket. + * + * @param ec Set to indicate what error occurred, if any. + * + * @sa IoControlCommand @n + * boost::asio::socket_base::bytes_readable @n + * boost::asio::socket_base::non_blocking_io + * + * @par Example + * Getting the number of bytes ready to read: + * @code + * boost::asio::ip::tcp::socket socket(my_context); + * ... + * boost::asio::ip::tcp::socket::bytes_readable command; + * boost::system::error_code ec; + * socket.io_control(command, ec); + * if (ec) + * { + * // An error occurred. + * } + * std::size_t bytes_readable = command.get(); + * @endcode + */ + template + BOOST_ASIO_SYNC_OP_VOID io_control(IoControlCommand& command, + boost::system::error_code& ec) + { + impl_.get_service().io_control(impl_.get_implementation(), command, ec); + BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); + } + + /// Gets the non-blocking mode of the socket. + /** + * @returns @c true if the socket's synchronous operations will fail with + * boost::asio::error::would_block if they are unable to perform the requested + * operation immediately. If @c false, synchronous operations will block + * until complete. + * + * @note The non-blocking mode has no effect on the behaviour of asynchronous + * operations. Asynchronous operations will never fail with the error + * boost::asio::error::would_block. + */ + bool non_blocking() const + { + return impl_.get_service().non_blocking(impl_.get_implementation()); + } + + /// Sets the non-blocking mode of the socket. + /** + * @param mode If @c true, the socket's synchronous operations will fail with + * boost::asio::error::would_block if they are unable to perform the requested + * operation immediately. If @c false, synchronous operations will block + * until complete. + * + * @throws boost::system::system_error Thrown on failure. + * + * @note The non-blocking mode has no effect on the behaviour of asynchronous + * operations. Asynchronous operations will never fail with the error + * boost::asio::error::would_block. + */ + void non_blocking(bool mode) + { + boost::system::error_code ec; + impl_.get_service().non_blocking(impl_.get_implementation(), mode, ec); + boost::asio::detail::throw_error(ec, "non_blocking"); + } + + /// Sets the non-blocking mode of the socket. + /** + * @param mode If @c true, the socket's synchronous operations will fail with + * boost::asio::error::would_block if they are unable to perform the requested + * operation immediately. If @c false, synchronous operations will block + * until complete. + * + * @param ec Set to indicate what error occurred, if any. + * + * @note The non-blocking mode has no effect on the behaviour of asynchronous + * operations. Asynchronous operations will never fail with the error + * boost::asio::error::would_block. + */ + BOOST_ASIO_SYNC_OP_VOID non_blocking( + bool mode, boost::system::error_code& ec) + { + impl_.get_service().non_blocking(impl_.get_implementation(), mode, ec); + BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); + } + + /// Gets the non-blocking mode of the native socket implementation. + /** + * This function is used to retrieve the non-blocking mode of the underlying + * native socket. This mode has no effect on the behaviour of the socket + * object's synchronous operations. + * + * @returns @c true if the underlying socket is in non-blocking mode and + * direct system calls may fail with boost::asio::error::would_block (or the + * equivalent system error). + * + * @note The current non-blocking mode is cached by the socket object. + * Consequently, the return value may be incorrect if the non-blocking mode + * was set directly on the native socket. + * + * @par Example + * This function is intended to allow the encapsulation of arbitrary + * non-blocking system calls as asynchronous operations, in a way that is + * transparent to the user of the socket object. The following example + * illustrates how Linux's @c sendfile system call might be encapsulated: + * @code template + * struct sendfile_op + * { + * tcp::socket& sock_; + * int fd_; + * Handler handler_; + * off_t offset_; + * std::size_t total_bytes_transferred_; + * + * // Function call operator meeting WriteHandler requirements. + * // Used as the handler for the async_write_some operation. + * void operator()(boost::system::error_code ec, std::size_t) + * { + * // Put the underlying socket into non-blocking mode. + * if (!ec) + * if (!sock_.native_non_blocking()) + * sock_.native_non_blocking(true, ec); + * + * if (!ec) + * { + * for (;;) + * { + * // Try the system call. + * errno = 0; + * int n = ::sendfile(sock_.native_handle(), fd_, &offset_, 65536); + * ec = boost::system::error_code(n < 0 ? errno : 0, + * boost::asio::error::get_system_category()); + * total_bytes_transferred_ += ec ? 0 : n; + * + * // Retry operation immediately if interrupted by signal. + * if (ec == boost::asio::error::interrupted) + * continue; + * + * // Check if we need to run the operation again. + * if (ec == boost::asio::error::would_block + * || ec == boost::asio::error::try_again) + * { + * // We have to wait for the socket to become ready again. + * sock_.async_wait(tcp::socket::wait_write, *this); + * return; + * } + * + * if (ec || n == 0) + * { + * // An error occurred, or we have reached the end of the file. + * // Either way we must exit the loop so we can call the handler. + * break; + * } + * + * // Loop around to try calling sendfile again. + * } + * } + * + * // Pass result back to user's handler. + * handler_(ec, total_bytes_transferred_); + * } + * }; + * + * template + * void async_sendfile(tcp::socket& sock, int fd, Handler h) + * { + * sendfile_op op = { sock, fd, h, 0, 0 }; + * sock.async_wait(tcp::socket::wait_write, op); + * } @endcode + */ + bool native_non_blocking() const + { + return impl_.get_service().native_non_blocking(impl_.get_implementation()); + } + + /// Sets the non-blocking mode of the native socket implementation. + /** + * This function is used to modify the non-blocking mode of the underlying + * native socket. It has no effect on the behaviour of the socket object's + * synchronous operations. + * + * @param mode If @c true, the underlying socket is put into non-blocking + * mode and direct system calls may fail with boost::asio::error::would_block + * (or the equivalent system error). + * + * @throws boost::system::system_error Thrown on failure. If the @c mode is + * @c false, but the current value of @c non_blocking() is @c true, this + * function fails with boost::asio::error::invalid_argument, as the + * combination does not make sense. + * + * @par Example + * This function is intended to allow the encapsulation of arbitrary + * non-blocking system calls as asynchronous operations, in a way that is + * transparent to the user of the socket object. The following example + * illustrates how Linux's @c sendfile system call might be encapsulated: + * @code template + * struct sendfile_op + * { + * tcp::socket& sock_; + * int fd_; + * Handler handler_; + * off_t offset_; + * std::size_t total_bytes_transferred_; + * + * // Function call operator meeting WriteHandler requirements. + * // Used as the handler for the async_write_some operation. + * void operator()(boost::system::error_code ec, std::size_t) + * { + * // Put the underlying socket into non-blocking mode. + * if (!ec) + * if (!sock_.native_non_blocking()) + * sock_.native_non_blocking(true, ec); + * + * if (!ec) + * { + * for (;;) + * { + * // Try the system call. + * errno = 0; + * int n = ::sendfile(sock_.native_handle(), fd_, &offset_, 65536); + * ec = boost::system::error_code(n < 0 ? errno : 0, + * boost::asio::error::get_system_category()); + * total_bytes_transferred_ += ec ? 0 : n; + * + * // Retry operation immediately if interrupted by signal. + * if (ec == boost::asio::error::interrupted) + * continue; + * + * // Check if we need to run the operation again. + * if (ec == boost::asio::error::would_block + * || ec == boost::asio::error::try_again) + * { + * // We have to wait for the socket to become ready again. + * sock_.async_wait(tcp::socket::wait_write, *this); + * return; + * } + * + * if (ec || n == 0) + * { + * // An error occurred, or we have reached the end of the file. + * // Either way we must exit the loop so we can call the handler. + * break; + * } + * + * // Loop around to try calling sendfile again. + * } + * } + * + * // Pass result back to user's handler. + * handler_(ec, total_bytes_transferred_); + * } + * }; + * + * template + * void async_sendfile(tcp::socket& sock, int fd, Handler h) + * { + * sendfile_op op = { sock, fd, h, 0, 0 }; + * sock.async_wait(tcp::socket::wait_write, op); + * } @endcode + */ + void native_non_blocking(bool mode) + { + boost::system::error_code ec; + impl_.get_service().native_non_blocking( + impl_.get_implementation(), mode, ec); + boost::asio::detail::throw_error(ec, "native_non_blocking"); + } + + /// Sets the non-blocking mode of the native socket implementation. + /** + * This function is used to modify the non-blocking mode of the underlying + * native socket. It has no effect on the behaviour of the socket object's + * synchronous operations. + * + * @param mode If @c true, the underlying socket is put into non-blocking + * mode and direct system calls may fail with boost::asio::error::would_block + * (or the equivalent system error). + * + * @param ec Set to indicate what error occurred, if any. If the @c mode is + * @c false, but the current value of @c non_blocking() is @c true, this + * function fails with boost::asio::error::invalid_argument, as the + * combination does not make sense. + * + * @par Example + * This function is intended to allow the encapsulation of arbitrary + * non-blocking system calls as asynchronous operations, in a way that is + * transparent to the user of the socket object. The following example + * illustrates how Linux's @c sendfile system call might be encapsulated: + * @code template + * struct sendfile_op + * { + * tcp::socket& sock_; + * int fd_; + * Handler handler_; + * off_t offset_; + * std::size_t total_bytes_transferred_; + * + * // Function call operator meeting WriteHandler requirements. + * // Used as the handler for the async_write_some operation. + * void operator()(boost::system::error_code ec, std::size_t) + * { + * // Put the underlying socket into non-blocking mode. + * if (!ec) + * if (!sock_.native_non_blocking()) + * sock_.native_non_blocking(true, ec); + * + * if (!ec) + * { + * for (;;) + * { + * // Try the system call. + * errno = 0; + * int n = ::sendfile(sock_.native_handle(), fd_, &offset_, 65536); + * ec = boost::system::error_code(n < 0 ? errno : 0, + * boost::asio::error::get_system_category()); + * total_bytes_transferred_ += ec ? 0 : n; + * + * // Retry operation immediately if interrupted by signal. + * if (ec == boost::asio::error::interrupted) + * continue; + * + * // Check if we need to run the operation again. + * if (ec == boost::asio::error::would_block + * || ec == boost::asio::error::try_again) + * { + * // We have to wait for the socket to become ready again. + * sock_.async_wait(tcp::socket::wait_write, *this); + * return; + * } + * + * if (ec || n == 0) + * { + * // An error occurred, or we have reached the end of the file. + * // Either way we must exit the loop so we can call the handler. + * break; + * } + * + * // Loop around to try calling sendfile again. + * } + * } + * + * // Pass result back to user's handler. + * handler_(ec, total_bytes_transferred_); + * } + * }; + * + * template + * void async_sendfile(tcp::socket& sock, int fd, Handler h) + * { + * sendfile_op op = { sock, fd, h, 0, 0 }; + * sock.async_wait(tcp::socket::wait_write, op); + * } @endcode + */ + BOOST_ASIO_SYNC_OP_VOID native_non_blocking( + bool mode, boost::system::error_code& ec) + { + impl_.get_service().native_non_blocking( + impl_.get_implementation(), mode, ec); + BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); + } + + /// Get the local endpoint of the socket. + /** + * This function is used to obtain the locally bound endpoint of the socket. + * + * @returns An object that represents the local endpoint of the socket. + * + * @throws boost::system::system_error Thrown on failure. + * + * @par Example + * @code + * boost::asio::ip::tcp::socket socket(my_context); + * ... + * boost::asio::ip::tcp::endpoint endpoint = socket.local_endpoint(); + * @endcode + */ + endpoint_type local_endpoint() const + { + boost::system::error_code ec; + endpoint_type ep = impl_.get_service().local_endpoint( + impl_.get_implementation(), ec); + boost::asio::detail::throw_error(ec, "local_endpoint"); + return ep; + } + + /// Get the local endpoint of the socket. + /** + * This function is used to obtain the locally bound endpoint of the socket. + * + * @param ec Set to indicate what error occurred, if any. + * + * @returns An object that represents the local endpoint of the socket. + * Returns a default-constructed endpoint object if an error occurred. + * + * @par Example + * @code + * boost::asio::ip::tcp::socket socket(my_context); + * ... + * boost::system::error_code ec; + * boost::asio::ip::tcp::endpoint endpoint = socket.local_endpoint(ec); + * if (ec) + * { + * // An error occurred. + * } + * @endcode + */ + endpoint_type local_endpoint(boost::system::error_code& ec) const + { + return impl_.get_service().local_endpoint(impl_.get_implementation(), ec); + } + + /// Get the remote endpoint of the socket. + /** + * This function is used to obtain the remote endpoint of the socket. + * + * @returns An object that represents the remote endpoint of the socket. + * + * @throws boost::system::system_error Thrown on failure. + * + * @par Example + * @code + * boost::asio::ip::tcp::socket socket(my_context); + * ... + * boost::asio::ip::tcp::endpoint endpoint = socket.remote_endpoint(); + * @endcode + */ + endpoint_type remote_endpoint() const + { + boost::system::error_code ec; + endpoint_type ep = impl_.get_service().remote_endpoint( + impl_.get_implementation(), ec); + boost::asio::detail::throw_error(ec, "remote_endpoint"); + return ep; + } + + /// Get the remote endpoint of the socket. + /** + * This function is used to obtain the remote endpoint of the socket. + * + * @param ec Set to indicate what error occurred, if any. + * + * @returns An object that represents the remote endpoint of the socket. + * Returns a default-constructed endpoint object if an error occurred. + * + * @par Example + * @code + * boost::asio::ip::tcp::socket socket(my_context); + * ... + * boost::system::error_code ec; + * boost::asio::ip::tcp::endpoint endpoint = socket.remote_endpoint(ec); + * if (ec) + * { + * // An error occurred. + * } + * @endcode + */ + endpoint_type remote_endpoint(boost::system::error_code& ec) const + { + return impl_.get_service().remote_endpoint(impl_.get_implementation(), ec); + } + + /// Disable sends or receives on the socket. + /** + * This function is used to disable send operations, receive operations, or + * both. + * + * @param what Determines what types of operation will no longer be allowed. + * + * @throws boost::system::system_error Thrown on failure. + * + * @par Example + * Shutting down the send side of the socket: + * @code + * boost::asio::ip::tcp::socket socket(my_context); + * ... + * socket.shutdown(boost::asio::ip::tcp::socket::shutdown_send); + * @endcode + */ + void shutdown(shutdown_type what) + { + boost::system::error_code ec; + impl_.get_service().shutdown(impl_.get_implementation(), what, ec); + boost::asio::detail::throw_error(ec, "shutdown"); + } + + /// Disable sends or receives on the socket. + /** + * This function is used to disable send operations, receive operations, or + * both. + * + * @param what Determines what types of operation will no longer be allowed. + * + * @param ec Set to indicate what error occurred, if any. + * + * @par Example + * Shutting down the send side of the socket: + * @code + * boost::asio::ip::tcp::socket socket(my_context); + * ... + * boost::system::error_code ec; + * socket.shutdown(boost::asio::ip::tcp::socket::shutdown_send, ec); + * if (ec) + * { + * // An error occurred. + * } + * @endcode + */ + BOOST_ASIO_SYNC_OP_VOID shutdown(shutdown_type what, + boost::system::error_code& ec) + { + impl_.get_service().shutdown(impl_.get_implementation(), what, ec); + BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); + } + + /// Wait for the socket to become ready to read, ready to write, or to have + /// pending error conditions. + /** + * This function is used to perform a blocking wait for a socket to enter + * a ready to read, write or error condition state. + * + * @param w Specifies the desired socket state. + * + * @par Example + * Waiting for a socket to become readable. + * @code + * boost::asio::ip::tcp::socket socket(my_context); + * ... + * socket.wait(boost::asio::ip::tcp::socket::wait_read); + * @endcode + */ + void wait(wait_type w) + { + boost::system::error_code ec; + impl_.get_service().wait(impl_.get_implementation(), w, ec); + boost::asio::detail::throw_error(ec, "wait"); + } + + /// Wait for the socket to become ready to read, ready to write, or to have + /// pending error conditions. + /** + * This function is used to perform a blocking wait for a socket to enter + * a ready to read, write or error condition state. + * + * @param w Specifies the desired socket state. + * + * @param ec Set to indicate what error occurred, if any. + * + * @par Example + * Waiting for a socket to become readable. + * @code + * boost::asio::ip::tcp::socket socket(my_context); + * ... + * boost::system::error_code ec; + * socket.wait(boost::asio::ip::tcp::socket::wait_read, ec); + * @endcode + */ + BOOST_ASIO_SYNC_OP_VOID wait(wait_type w, boost::system::error_code& ec) + { + impl_.get_service().wait(impl_.get_implementation(), w, ec); + BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); + } + + /// Asynchronously wait for the socket to become ready to read, ready to + /// write, or to have pending error conditions. + /** + * This function is used to perform an asynchronous wait for a socket to enter + * a ready to read, write or error condition state. + * + * @param w Specifies the desired socket state. + * + * @param handler The handler to be called when the wait operation completes. + * Copies will be made of the handler as required. The function signature of + * the handler must be: + * @code void handler( + * const boost::system::error_code& error // Result of operation + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. On + * immediate completion, invocation of the handler will be performed in a + * manner equivalent to using boost::asio::post(). + * + * @par Example + * @code + * void wait_handler(const boost::system::error_code& error) + * { + * if (!error) + * { + * // Wait succeeded. + * } + * } + * + * ... + * + * boost::asio::ip::tcp::socket socket(my_context); + * ... + * socket.async_wait(boost::asio::ip::tcp::socket::wait_read, wait_handler); + * @endcode + */ + template + BOOST_ASIO_INITFN_RESULT_TYPE(WaitHandler, + void (boost::system::error_code)) + async_wait(wait_type w, BOOST_ASIO_MOVE_ARG(WaitHandler) handler) + { + return async_initiate( + initiate_async_wait(), handler, this, w); + } + +protected: + /// Protected destructor to prevent deletion through this type. + /** + * This function destroys the socket, cancelling any outstanding asynchronous + * operations associated with the socket as if by calling @c cancel. + */ + ~basic_socket_ext() + { + } + +#if defined(BOOST_ASIO_WINDOWS_RUNTIME) + detail::io_object_impl< + detail::null_socket_service, Executor> impl_; +#elif defined(BOOST_ASIO_HAS_IOCP) + detail::io_object_impl< + detail::win_iocp_socket_service, Executor> impl_; +#else + detail::io_object_impl< + detail::reactive_socket_service_ext, Executor> impl_; +#endif + +private: + // Disallow copying and assignment. + basic_socket_ext(const basic_socket_ext&) BOOST_ASIO_DELETED; + basic_socket_ext& operator=(const basic_socket_ext&) BOOST_ASIO_DELETED; + + struct initiate_async_connect + { + template + void operator()(BOOST_ASIO_MOVE_ARG(ConnectHandler) handler, + basic_socket_ext* self, const endpoint_type& peer_endpoint, + const boost::system::error_code& open_ec) const + { + // If you get an error on the following line it means that your handler + // does not meet the documented type requirements for a ConnectHandler. + BOOST_ASIO_CONNECT_HANDLER_CHECK(ConnectHandler, handler) type_check; + + if (open_ec) + { + boost::asio::post(self->impl_.get_executor(), + boost::asio::detail::bind_handler( + BOOST_ASIO_MOVE_CAST(ConnectHandler)(handler), open_ec)); + } + else + { + detail::non_const_lvalue handler2(handler); + self->impl_.get_service().async_connect( + self->impl_.get_implementation(), peer_endpoint, + handler2.value, self->impl_.get_implementation_executor()); + } + } + }; + + struct initiate_async_wait + { + template + void operator()(BOOST_ASIO_MOVE_ARG(WaitHandler) handler, + basic_socket_ext* self, wait_type w) const + { + // If you get an error on the following line it means that your handler + // does not meet the documented type requirements for a WaitHandler. + BOOST_ASIO_WAIT_HANDLER_CHECK(WaitHandler, handler) type_check; + + detail::non_const_lvalue handler2(handler); + self->impl_.get_service().async_wait( + self->impl_.get_implementation(), w, handler2.value, + self->impl_.get_implementation_executor()); + } + }; +}; + +} // namespace asio +} // namespace boost + +#include + +#endif // BOOST_ASIO_BASIC_SOCKET_EXT_HPP diff --git a/implementation/helper/1.76/boost/asio/basic_socket_ext_local.hpp b/implementation/helper/1.76/boost/asio/basic_socket_ext_local.hpp new file mode 100644 index 0000000..2c898fc --- /dev/null +++ b/implementation/helper/1.76/boost/asio/basic_socket_ext_local.hpp @@ -0,0 +1,1859 @@ +// +// basic_socket_ext_local.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2018,2019 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_BASIC_SOCKET_EXT_LOCAL_HPP +#define BOOST_ASIO_BASIC_SOCKET_EXT_LOCAL_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined(BOOST_ASIO_WINDOWS_RUNTIME) +# include +#elif defined(BOOST_ASIO_HAS_IOCP) +# include +#else +# include +#endif + +#if defined(BOOST_ASIO_HAS_MOVE) +# include +#endif // defined(BOOST_ASIO_HAS_MOVE) + +#include + +namespace boost { +namespace asio { + +#if !defined(BOOST_ASIO_BASIC_SOCKET_EXT_LOCAL_FWD_DECL) +#define BOOST_ASIO_BASIC_SOCKET_EXT_LOCAL_FWD_DECL + +// Forward declaration with defaulted arguments. +template +class basic_socket_ext_local; + +#endif // !defined(BOOST_ASIO_BASIC_SOCKET_EXT_LOCAL_FWD_DECL) + +/// Provides socket functionality. +/** + * The basic_socket class template provides functionality that is common to both + * stream-oriented and datagram-oriented sockets. + * + * @par Thread Safety + * @e Distinct @e objects: Safe.@n + * @e Shared @e objects: Unsafe. + */ +template +class basic_socket_ext_local + : public socket_base +{ +public: + /// The type of the executor associated with the object. + typedef Executor executor_type; + + /// Rebinds the socket type to another executor. + template + struct rebind_executor + { + /// The socket type when rebound to the specified executor. + typedef basic_socket_ext_local other; + }; + + /// The native representation of a socket. +#if defined(GENERATING_DOCUMENTATION) + typedef implementation_defined native_handle_type; +#elif defined(BOOST_ASIO_WINDOWS_RUNTIME) + typedef typename detail::null_socket_service< + Protocol>::native_handle_type native_handle_type; +#elif defined(BOOST_ASIO_HAS_IOCP) + typedef typename detail::win_iocp_socket_service< + Protocol>::native_handle_type native_handle_type; +#else + typedef typename detail::reactive_socket_service_ext_local< + Protocol>::native_handle_type native_handle_type; +#endif + + /// The protocol type. + typedef Protocol protocol_type; + + /// The endpoint type. + typedef typename Protocol::endpoint endpoint_type; + +#if !defined(BOOST_ASIO_NO_EXTENSIONS) + /// A basic_socket is always the lowest layer. + typedef basic_socket_ext_local lowest_layer_type; +#endif // !defined(BOOST_ASIO_NO_EXTENSIONS) + + /// Construct a basic_socket without opening it. + /** + * This constructor creates a socket without opening it. + * + * @param ex The I/O executor that the socket will use, by default, to + * dispatch handlers for any asynchronous operations performed on the socket. + */ + explicit basic_socket_ext_local(const executor_type& ex) + : impl_(0, ex) + { + } + + /// Construct a basic_socket without opening it. + /** + * This constructor creates a socket without opening it. + * + * @param context An execution context which provides the I/O executor that + * the socket will use, by default, to dispatch handlers for any asynchronous + * operations performed on the socket. + */ + template + explicit basic_socket_ext_local(ExecutionContext& context, + typename enable_if< + is_convertible::value + >::type* = 0) + : impl_(0, 0, context) + { + } + + /// Construct and open a basic_socket. + /** + * This constructor creates and opens a socket. + * + * @param ex The I/O executor that the socket will use, by default, to + * dispatch handlers for any asynchronous operations performed on the socket. + * + * @param protocol An object specifying protocol parameters to be used. + * + * @throws boost::system::system_error Thrown on failure. + */ + basic_socket_ext_local(const executor_type& ex, const protocol_type& protocol) + : impl_(0, ex) + { + boost::system::error_code ec; + impl_.get_service().open(impl_.get_implementation(), protocol, ec); + boost::asio::detail::throw_error(ec, "open"); + } + + /// Construct and open a basic_socket. + /** + * This constructor creates and opens a socket. + * + * @param context An execution context which provides the I/O executor that + * the socket will use, by default, to dispatch handlers for any asynchronous + * operations performed on the socket. + * + * @param protocol An object specifying protocol parameters to be used. + * + * @throws boost::system::system_error Thrown on failure. + */ + template + basic_socket_ext_local(ExecutionContext& context, const protocol_type& protocol, + typename enable_if< + is_convertible::value + >::type* = 0) + : impl_(0, 0, context) + { + boost::system::error_code ec; + impl_.get_service().open(impl_.get_implementation(), protocol, ec); + boost::asio::detail::throw_error(ec, "open"); + } + + /// Construct a basic_socket, opening it and binding it to the given local + /// endpoint. + /** + * This constructor creates a socket and automatically opens it bound to the + * specified endpoint on the local machine. The protocol used is the protocol + * associated with the given endpoint. + * + * @param ex The I/O executor that the socket will use, by default, to + * dispatch handlers for any asynchronous operations performed on the socket. + * + * @param endpoint An endpoint on the local machine to which the socket will + * be bound. + * + * @throws boost::system::system_error Thrown on failure. + */ + basic_socket_ext_local(const executor_type& ex, const endpoint_type& endpoint) + : impl_(0, ex) + { + boost::system::error_code ec; + const protocol_type protocol = endpoint.protocol(); + impl_.get_service().open(impl_.get_implementation(), protocol, ec); + boost::asio::detail::throw_error(ec, "open"); + impl_.get_service().bind(impl_.get_implementation(), endpoint, ec); + boost::asio::detail::throw_error(ec, "bind"); + } + + /// Construct a basic_socket, opening it and binding it to the given local + /// endpoint. + /** + * This constructor creates a socket and automatically opens it bound to the + * specified endpoint on the local machine. The protocol used is the protocol + * associated with the given endpoint. + * + * @param context An execution context which provides the I/O executor that + * the socket will use, by default, to dispatch handlers for any asynchronous + * operations performed on the socket. + * + * @param endpoint An endpoint on the local machine to which the socket will + * be bound. + * + * @throws boost::system::system_error Thrown on failure. + */ + template + basic_socket_ext_local(ExecutionContext& context, const endpoint_type& endpoint, + typename enable_if< + is_convertible::value + >::type* = 0) + : impl_(0, 0, context) + { + boost::system::error_code ec; + const protocol_type protocol = endpoint.protocol(); + impl_.get_service().open(impl_.get_implementation(), protocol, ec); + boost::asio::detail::throw_error(ec, "open"); + impl_.get_service().bind(impl_.get_implementation(), endpoint, ec); + boost::asio::detail::throw_error(ec, "bind"); + } + + /// Construct a basic_socket on an existing native socket. + /** + * This constructor creates a socket object to hold an existing native socket. + * + * @param ex The I/O executor that the socket will use, by default, to + * dispatch handlers for any asynchronous operations performed on the socket. + * + * @param protocol An object specifying protocol parameters to be used. + * + * @param native_socket A native socket. + * + * @throws boost::system::system_error Thrown on failure. + */ + basic_socket_ext_local(const executor_type& ex, const protocol_type& protocol, + const native_handle_type& native_socket) + : impl_(0, ex) + { + boost::system::error_code ec; + impl_.get_service().assign(impl_.get_implementation(), + protocol, native_socket, ec); + boost::asio::detail::throw_error(ec, "assign"); + } + + /// Construct a basic_socket on an existing native socket. + /** + * This constructor creates a socket object to hold an existing native socket. + * + * @param context An execution context which provides the I/O executor that + * the socket will use, by default, to dispatch handlers for any asynchronous + * operations performed on the socket. + * + * @param protocol An object specifying protocol parameters to be used. + * + * @param native_socket A native socket. + * + * @throws boost::system::system_error Thrown on failure. + */ + template + basic_socket_ext_local(ExecutionContext& context, const protocol_type& protocol, + const native_handle_type& native_socket, + typename enable_if< + is_convertible::value + >::type* = 0) + : impl_(0, 0, context) + { + boost::system::error_code ec; + impl_.get_service().assign(impl_.get_implementation(), + protocol, native_socket, ec); + boost::asio::detail::throw_error(ec, "assign"); + } + +#if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) + /// Move-construct a basic_socket from another. + /** + * This constructor moves a socket from one object to another. + * + * @param other The other basic_socket object from which the move will + * occur. + * + * @note Following the move, the moved-from object is in the same state as if + * constructed using the @c basic_socket(const executor_type&) constructor. + */ + basic_socket_ext_local(basic_socket_ext_local&& other) + : impl_(std::move(other.impl_)) + { + } + + /// Move-assign a basic_socket from another. + /** + * This assignment operator moves a socket from one object to another. + * + * @param other The other basic_socket object from which the move will + * occur. + * + * @note Following the move, the moved-from object is in the same state as if + * constructed using the @c basic_socket(const executor_type&) constructor. + */ + basic_socket_ext_local& operator=(basic_socket_ext_local&& other) + { + impl_ = std::move(other.impl_); + return *this; + } + + // All sockets have access to each other's implementations. + template + friend class basic_socket_ext_local; + + /// Move-construct a basic_socket from a socket of another protocol type. + /** + * This constructor moves a socket from one object to another. + * + * @param other The other basic_socket object from which the move will + * occur. + * + * @note Following the move, the moved-from object is in the same state as if + * constructed using the @c basic_socket(const executor_type&) constructor. + */ + template + basic_socket_ext_local(basic_socket_ext_local&& other, + typename enable_if< + is_convertible::value + && is_convertible::value + >::type* = 0) + : impl_(std::move(other.impl_)) + { + } + + /// Move-assign a basic_socket from a socket of another protocol type. + /** + * This assignment operator moves a socket from one object to another. + * + * @param other The other basic_socket object from which the move will + * occur. + * + * @note Following the move, the moved-from object is in the same state as if + * constructed using the @c basic_socket(const executor_type&) constructor. + */ + template + typename enable_if< + is_convertible::value + && is_convertible::value, + basic_socket_ext_local& + >::type operator=(basic_socket_ext_local && other) + { + basic_socket_ext_local tmp(std::move(other)); + impl_ = std::move(tmp.impl_); + return *this; + } +#endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) + + /// Get the executor associated with the object. + executor_type get_executor() BOOST_ASIO_NOEXCEPT + { + return impl_.get_executor(); + } + +#if !defined(BOOST_ASIO_NO_EXTENSIONS) + /// Get a reference to the lowest layer. + /** + * This function returns a reference to the lowest layer in a stack of + * layers. Since a basic_socket cannot contain any further layers, it simply + * returns a reference to itself. + * + * @return A reference to the lowest layer in the stack of layers. Ownership + * is not transferred to the caller. + */ + lowest_layer_type& lowest_layer() + { + return *this; + } + + /// Get a const reference to the lowest layer. + /** + * This function returns a const reference to the lowest layer in a stack of + * layers. Since a basic_socket cannot contain any further layers, it simply + * returns a reference to itself. + * + * @return A const reference to the lowest layer in the stack of layers. + * Ownership is not transferred to the caller. + */ + const lowest_layer_type& lowest_layer() const + { + return *this; + } +#endif // !defined(BOOST_ASIO_NO_EXTENSIONS) + + /// Open the socket using the specified protocol. + /** + * This function opens the socket so that it will use the specified protocol. + * + * @param protocol An object specifying protocol parameters to be used. + * + * @throws boost::system::system_error Thrown on failure. + * + * @par Example + * @code + * boost::asio::ip::tcp::socket socket(my_context); + * socket.open(boost::asio::ip::tcp::v4()); + * @endcode + */ + void open(const protocol_type& protocol = protocol_type()) + { + boost::system::error_code ec; + impl_.get_service().open(impl_.get_implementation(), protocol, ec); + boost::asio::detail::throw_error(ec, "open"); + } + + /// Open the socket using the specified protocol. + /** + * This function opens the socket so that it will use the specified protocol. + * + * @param protocol An object specifying which protocol is to be used. + * + * @param ec Set to indicate what error occurred, if any. + * + * @par Example + * @code + * boost::asio::ip::tcp::socket socket(my_context); + * boost::system::error_code ec; + * socket.open(boost::asio::ip::tcp::v4(), ec); + * if (ec) + * { + * // An error occurred. + * } + * @endcode + */ + BOOST_ASIO_SYNC_OP_VOID open(const protocol_type& protocol, + boost::system::error_code& ec) + { + impl_.get_service().open(impl_.get_implementation(), protocol, ec); + BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); + } + + /// Assign an existing native socket to the socket. + /* + * This function opens the socket to hold an existing native socket. + * + * @param protocol An object specifying which protocol is to be used. + * + * @param native_socket A native socket. + * + * @throws boost::system::system_error Thrown on failure. + */ + void assign(const protocol_type& protocol, + const native_handle_type& native_socket) + { + boost::system::error_code ec; + impl_.get_service().assign(impl_.get_implementation(), + protocol, native_socket, ec); + boost::asio::detail::throw_error(ec, "assign"); + } + + /// Assign an existing native socket to the socket. + /* + * This function opens the socket to hold an existing native socket. + * + * @param protocol An object specifying which protocol is to be used. + * + * @param native_socket A native socket. + * + * @param ec Set to indicate what error occurred, if any. + */ + BOOST_ASIO_SYNC_OP_VOID assign(const protocol_type& protocol, + const native_handle_type& native_socket, boost::system::error_code& ec) + { + impl_.get_service().assign(impl_.get_implementation(), + protocol, native_socket, ec); + BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); + } + + /// Determine whether the socket is open. + bool is_open() const + { + return impl_.get_service().is_open(impl_.get_implementation()); + } + + /// Close the socket. + /** + * This function is used to close the socket. Any asynchronous send, receive + * or connect operations will be cancelled immediately, and will complete + * with the boost::asio::error::operation_aborted error. + * + * @throws boost::system::system_error Thrown on failure. Note that, even if + * the function indicates an error, the underlying descriptor is closed. + * + * @note For portable behaviour with respect to graceful closure of a + * connected socket, call shutdown() before closing the socket. + */ + void close() + { + boost::system::error_code ec; + impl_.get_service().close(impl_.get_implementation(), ec); + boost::asio::detail::throw_error(ec, "close"); + } + + /// Close the socket. + /** + * This function is used to close the socket. Any asynchronous send, receive + * or connect operations will be cancelled immediately, and will complete + * with the boost::asio::error::operation_aborted error. + * + * @param ec Set to indicate what error occurred, if any. Note that, even if + * the function indicates an error, the underlying descriptor is closed. + * + * @par Example + * @code + * boost::asio::ip::tcp::socket socket(my_context); + * ... + * boost::system::error_code ec; + * socket.close(ec); + * if (ec) + * { + * // An error occurred. + * } + * @endcode + * + * @note For portable behaviour with respect to graceful closure of a + * connected socket, call shutdown() before closing the socket. + */ + BOOST_ASIO_SYNC_OP_VOID close(boost::system::error_code& ec) + { + impl_.get_service().close(impl_.get_implementation(), ec); + BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); + } + + /// Release ownership of the underlying native socket. + /** + * This function causes all outstanding asynchronous connect, send and receive + * operations to finish immediately, and the handlers for cancelled operations + * will be passed the boost::asio::error::operation_aborted error. Ownership + * of the native socket is then transferred to the caller. + * + * @throws boost::system::system_error Thrown on failure. + * + * @note This function is unsupported on Windows versions prior to Windows + * 8.1, and will fail with boost::asio::error::operation_not_supported on + * these platforms. + */ +#if defined(BOOST_ASIO_MSVC) && (BOOST_ASIO_MSVC >= 1400) \ + && (!defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0603) + __declspec(deprecated("This function always fails with " + "operation_not_supported when used on Windows versions " + "prior to Windows 8.1.")) +#endif + native_handle_type release() + { + boost::system::error_code ec; + native_handle_type s = impl_.get_service().release( + impl_.get_implementation(), ec); + boost::asio::detail::throw_error(ec, "release"); + return s; + } + + /// Release ownership of the underlying native socket. + /** + * This function causes all outstanding asynchronous connect, send and receive + * operations to finish immediately, and the handlers for cancelled operations + * will be passed the boost::asio::error::operation_aborted error. Ownership + * of the native socket is then transferred to the caller. + * + * @param ec Set to indicate what error occurred, if any. + * + * @note This function is unsupported on Windows versions prior to Windows + * 8.1, and will fail with boost::asio::error::operation_not_supported on + * these platforms. + */ +#if defined(BOOST_ASIO_MSVC) && (BOOST_ASIO_MSVC >= 1400) \ + && (!defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0603) + __declspec(deprecated("This function always fails with " + "operation_not_supported when used on Windows versions " + "prior to Windows 8.1.")) +#endif + native_handle_type release(boost::system::error_code& ec) + { + return impl_.get_service().release(impl_.get_implementation(), ec); + } + + /// Get the native socket representation. + /** + * This function may be used to obtain the underlying representation of the + * socket. This is intended to allow access to native socket functionality + * that is not otherwise provided. + */ + native_handle_type native_handle() + { + return impl_.get_service().native_handle(impl_.get_implementation()); + } + + /// Cancel all asynchronous operations associated with the socket. + /** + * This function causes all outstanding asynchronous connect, send and receive + * operations to finish immediately, and the handlers for cancelled operations + * will be passed the boost::asio::error::operation_aborted error. + * + * @throws boost::system::system_error Thrown on failure. + * + * @note Calls to cancel() will always fail with + * boost::asio::error::operation_not_supported when run on Windows XP, Windows + * Server 2003, and earlier versions of Windows, unless + * BOOST_ASIO_ENABLE_CANCELIO is defined. However, the CancelIo function has + * two issues that should be considered before enabling its use: + * + * @li It will only cancel asynchronous operations that were initiated in the + * current thread. + * + * @li It can appear to complete without error, but the request to cancel the + * unfinished operations may be silently ignored by the operating system. + * Whether it works or not seems to depend on the drivers that are installed. + * + * For portable cancellation, consider using one of the following + * alternatives: + * + * @li Disable asio's I/O completion port backend by defining + * BOOST_ASIO_DISABLE_IOCP. + * + * @li Use the close() function to simultaneously cancel the outstanding + * operations and close the socket. + * + * When running on Windows Vista, Windows Server 2008, and later, the + * CancelIoEx function is always used. This function does not have the + * problems described above. + */ +#if defined(BOOST_ASIO_MSVC) && (BOOST_ASIO_MSVC >= 1400) \ + && (!defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0600) \ + && !defined(BOOST_ASIO_ENABLE_CANCELIO) + __declspec(deprecated("By default, this function always fails with " + "operation_not_supported when used on Windows XP, Windows Server 2003, " + "or earlier. Consult documentation for details.")) +#endif + void cancel() + { + boost::system::error_code ec; + impl_.get_service().cancel(impl_.get_implementation(), ec); + boost::asio::detail::throw_error(ec, "cancel"); + } + + /// Cancel all asynchronous operations associated with the socket. + /** + * This function causes all outstanding asynchronous connect, send and receive + * operations to finish immediately, and the handlers for cancelled operations + * will be passed the boost::asio::error::operation_aborted error. + * + * @param ec Set to indicate what error occurred, if any. + * + * @note Calls to cancel() will always fail with + * boost::asio::error::operation_not_supported when run on Windows XP, Windows + * Server 2003, and earlier versions of Windows, unless + * BOOST_ASIO_ENABLE_CANCELIO is defined. However, the CancelIo function has + * two issues that should be considered before enabling its use: + * + * @li It will only cancel asynchronous operations that were initiated in the + * current thread. + * + * @li It can appear to complete without error, but the request to cancel the + * unfinished operations may be silently ignored by the operating system. + * Whether it works or not seems to depend on the drivers that are installed. + * + * For portable cancellation, consider using one of the following + * alternatives: + * + * @li Disable asio's I/O completion port backend by defining + * BOOST_ASIO_DISABLE_IOCP. + * + * @li Use the close() function to simultaneously cancel the outstanding + * operations and close the socket. + * + * When running on Windows Vista, Windows Server 2008, and later, the + * CancelIoEx function is always used. This function does not have the + * problems described above. + */ +#if defined(BOOST_ASIO_MSVC) && (BOOST_ASIO_MSVC >= 1400) \ + && (!defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0600) \ + && !defined(BOOST_ASIO_ENABLE_CANCELIO) + __declspec(deprecated("By default, this function always fails with " + "operation_not_supported when used on Windows XP, Windows Server 2003, " + "or earlier. Consult documentation for details.")) +#endif + BOOST_ASIO_SYNC_OP_VOID cancel(boost::system::error_code& ec) + { + impl_.get_service().cancel(impl_.get_implementation(), ec); + BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); + } + + /// Determine whether the socket is at the out-of-band data mark. + /** + * This function is used to check whether the socket input is currently + * positioned at the out-of-band data mark. + * + * @return A bool indicating whether the socket is at the out-of-band data + * mark. + * + * @throws boost::system::system_error Thrown on failure. + */ + bool at_mark() const + { + boost::system::error_code ec; + bool b = impl_.get_service().at_mark(impl_.get_implementation(), ec); + boost::asio::detail::throw_error(ec, "at_mark"); + return b; + } + + /// Determine whether the socket is at the out-of-band data mark. + /** + * This function is used to check whether the socket input is currently + * positioned at the out-of-band data mark. + * + * @param ec Set to indicate what error occurred, if any. + * + * @return A bool indicating whether the socket is at the out-of-band data + * mark. + */ + bool at_mark(boost::system::error_code& ec) const + { + return impl_.get_service().at_mark(impl_.get_implementation(), ec); + } + + /// Determine the number of bytes available for reading. + /** + * This function is used to determine the number of bytes that may be read + * without blocking. + * + * @return The number of bytes that may be read without blocking, or 0 if an + * error occurs. + * + * @throws boost::system::system_error Thrown on failure. + */ + std::size_t available() const + { + boost::system::error_code ec; + std::size_t s = impl_.get_service().available( + impl_.get_implementation(), ec); + boost::asio::detail::throw_error(ec, "available"); + return s; + } + + /// Determine the number of bytes available for reading. + /** + * This function is used to determine the number of bytes that may be read + * without blocking. + * + * @param ec Set to indicate what error occurred, if any. + * + * @return The number of bytes that may be read without blocking, or 0 if an + * error occurs. + */ + std::size_t available(boost::system::error_code& ec) const + { + return impl_.get_service().available(impl_.get_implementation(), ec); + } + + /// Bind the socket to the given local endpoint. + /** + * This function binds the socket to the specified endpoint on the local + * machine. + * + * @param endpoint An endpoint on the local machine to which the socket will + * be bound. + * + * @throws boost::system::system_error Thrown on failure. + * + * @par Example + * @code + * boost::asio::ip::tcp::socket socket(my_context); + * socket.open(boost::asio::ip::tcp::v4()); + * socket.bind(boost::asio::ip::tcp::endpoint( + * boost::asio::ip::tcp::v4(), 12345)); + * @endcode + */ + void bind(const endpoint_type& endpoint) + { + boost::system::error_code ec; + impl_.get_service().bind(impl_.get_implementation(), endpoint, ec); + boost::asio::detail::throw_error(ec, "bind"); + } + + /// Bind the socket to the given local endpoint. + /** + * This function binds the socket to the specified endpoint on the local + * machine. + * + * @param endpoint An endpoint on the local machine to which the socket will + * be bound. + * + * @param ec Set to indicate what error occurred, if any. + * + * @par Example + * @code + * boost::asio::ip::tcp::socket socket(my_context); + * socket.open(boost::asio::ip::tcp::v4()); + * boost::system::error_code ec; + * socket.bind(boost::asio::ip::tcp::endpoint( + * boost::asio::ip::tcp::v4(), 12345), ec); + * if (ec) + * { + * // An error occurred. + * } + * @endcode + */ + BOOST_ASIO_SYNC_OP_VOID bind(const endpoint_type& endpoint, + boost::system::error_code& ec) + { + impl_.get_service().bind(impl_.get_implementation(), endpoint, ec); + BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); + } + + /// Connect the socket to the specified endpoint. + /** + * This function is used to connect a socket to the specified remote endpoint. + * The function call will block until the connection is successfully made or + * an error occurs. + * + * The socket is automatically opened if it is not already open. If the + * connect fails, and the socket was automatically opened, the socket is + * not returned to the closed state. + * + * @param peer_endpoint The remote endpoint to which the socket will be + * connected. + * + * @throws boost::system::system_error Thrown on failure. + * + * @par Example + * @code + * boost::asio::ip::tcp::socket socket(my_context); + * boost::asio::ip::tcp::endpoint endpoint( + * boost::asio::ip::address::from_string("1.2.3.4"), 12345); + * socket.connect(endpoint); + * @endcode + */ + void connect(const endpoint_type& peer_endpoint) + { + boost::system::error_code ec; + if (!is_open()) + { + impl_.get_service().open(impl_.get_implementation(), + peer_endpoint.protocol(), ec); + boost::asio::detail::throw_error(ec, "connect"); + } + impl_.get_service().connect(impl_.get_implementation(), peer_endpoint, ec); + boost::asio::detail::throw_error(ec, "connect"); + } + + /// Connect the socket to the specified endpoint. + /** + * This function is used to connect a socket to the specified remote endpoint. + * The function call will block until the connection is successfully made or + * an error occurs. + * + * The socket is automatically opened if it is not already open. If the + * connect fails, and the socket was automatically opened, the socket is + * not returned to the closed state. + * + * @param peer_endpoint The remote endpoint to which the socket will be + * connected. + * + * @param ec Set to indicate what error occurred, if any. + * + * @par Example + * @code + * boost::asio::ip::tcp::socket socket(my_context); + * boost::asio::ip::tcp::endpoint endpoint( + * boost::asio::ip::address::from_string("1.2.3.4"), 12345); + * boost::system::error_code ec; + * socket.connect(endpoint, ec); + * if (ec) + * { + * // An error occurred. + * } + * @endcode + */ + BOOST_ASIO_SYNC_OP_VOID connect(const endpoint_type& peer_endpoint, + boost::system::error_code& ec) + { + if (!is_open()) + { + impl_.get_service().open(impl_.get_implementation(), + peer_endpoint.protocol(), ec); + if (ec) + { + BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); + } + } + + impl_.get_service().connect(impl_.get_implementation(), peer_endpoint, ec); + BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); + } + + /// Start an asynchronous connect. + /** + * This function is used to asynchronously connect a socket to the specified + * remote endpoint. The function call always returns immediately. + * + * The socket is automatically opened if it is not already open. If the + * connect fails, and the socket was automatically opened, the socket is + * not returned to the closed state. + * + * @param peer_endpoint The remote endpoint to which the socket will be + * connected. Copies will be made of the endpoint object as required. + * + * @param handler The handler to be called when the connection operation + * completes. Copies will be made of the handler as required. The function + * signature of the handler must be: + * @code void handler( + * const boost::system::error_code& error // Result of operation + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. On + * immediate completion, invocation of the handler will be performed in a + * manner equivalent to using boost::asio::post(). + * + * @par Example + * @code + * void connect_handler(const boost::system::error_code& error) + * { + * if (!error) + * { + * // Connect succeeded. + * } + * } + * + * ... + * + * boost::asio::ip::tcp::socket socket(my_context); + * boost::asio::ip::tcp::endpoint endpoint( + * boost::asio::ip::address::from_string("1.2.3.4"), 12345); + * socket.async_connect(endpoint, connect_handler); + * @endcode + */ + template + BOOST_ASIO_INITFN_RESULT_TYPE(ConnectHandler, + void (boost::system::error_code)) + async_connect(const endpoint_type& peer_endpoint, + BOOST_ASIO_MOVE_ARG(ConnectHandler) handler) + { + boost::system::error_code open_ec; + if (!is_open()) + { + const protocol_type protocol = peer_endpoint.protocol(); + impl_.get_service().open(impl_.get_implementation(), protocol, open_ec); + } + + return async_initiate( + initiate_async_connect(), handler, this, peer_endpoint, open_ec); + } + + /// Set an option on the socket. + /** + * This function is used to set an option on the socket. + * + * @param option The new option value to be set on the socket. + * + * @throws boost::system::system_error Thrown on failure. + * + * @sa SettableSocketOption @n + * boost::asio::socket_base::broadcast @n + * boost::asio::socket_base::do_not_route @n + * boost::asio::socket_base::keep_alive @n + * boost::asio::socket_base::linger @n + * boost::asio::socket_base::receive_buffer_size @n + * boost::asio::socket_base::receive_low_watermark @n + * boost::asio::socket_base::reuse_address @n + * boost::asio::socket_base::send_buffer_size @n + * boost::asio::socket_base::send_low_watermark @n + * boost::asio::ip::multicast::join_group @n + * boost::asio::ip::multicast::leave_group @n + * boost::asio::ip::multicast::enable_loopback @n + * boost::asio::ip::multicast::outbound_interface @n + * boost::asio::ip::multicast::hops @n + * boost::asio::ip::tcp::no_delay + * + * @par Example + * Setting the IPPROTO_TCP/TCP_NODELAY option: + * @code + * boost::asio::ip::tcp::socket socket(my_context); + * ... + * boost::asio::ip::tcp::no_delay option(true); + * socket.set_option(option); + * @endcode + */ + template + void set_option(const SettableSocketOption& option) + { + boost::system::error_code ec; + impl_.get_service().set_option(impl_.get_implementation(), option, ec); + boost::asio::detail::throw_error(ec, "set_option"); + } + + /// Set an option on the socket. + /** + * This function is used to set an option on the socket. + * + * @param option The new option value to be set on the socket. + * + * @param ec Set to indicate what error occurred, if any. + * + * @sa SettableSocketOption @n + * boost::asio::socket_base::broadcast @n + * boost::asio::socket_base::do_not_route @n + * boost::asio::socket_base::keep_alive @n + * boost::asio::socket_base::linger @n + * boost::asio::socket_base::receive_buffer_size @n + * boost::asio::socket_base::receive_low_watermark @n + * boost::asio::socket_base::reuse_address @n + * boost::asio::socket_base::send_buffer_size @n + * boost::asio::socket_base::send_low_watermark @n + * boost::asio::ip::multicast::join_group @n + * boost::asio::ip::multicast::leave_group @n + * boost::asio::ip::multicast::enable_loopback @n + * boost::asio::ip::multicast::outbound_interface @n + * boost::asio::ip::multicast::hops @n + * boost::asio::ip::tcp::no_delay + * + * @par Example + * Setting the IPPROTO_TCP/TCP_NODELAY option: + * @code + * boost::asio::ip::tcp::socket socket(my_context); + * ... + * boost::asio::ip::tcp::no_delay option(true); + * boost::system::error_code ec; + * socket.set_option(option, ec); + * if (ec) + * { + * // An error occurred. + * } + * @endcode + */ + template + BOOST_ASIO_SYNC_OP_VOID set_option(const SettableSocketOption& option, + boost::system::error_code& ec) + { + impl_.get_service().set_option(impl_.get_implementation(), option, ec); + BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); + } + + /// Get an option from the socket. + /** + * This function is used to get the current value of an option on the socket. + * + * @param option The option value to be obtained from the socket. + * + * @throws boost::system::system_error Thrown on failure. + * + * @sa GettableSocketOption @n + * boost::asio::socket_base::broadcast @n + * boost::asio::socket_base::do_not_route @n + * boost::asio::socket_base::keep_alive @n + * boost::asio::socket_base::linger @n + * boost::asio::socket_base::receive_buffer_size @n + * boost::asio::socket_base::receive_low_watermark @n + * boost::asio::socket_base::reuse_address @n + * boost::asio::socket_base::send_buffer_size @n + * boost::asio::socket_base::send_low_watermark @n + * boost::asio::ip::multicast::join_group @n + * boost::asio::ip::multicast::leave_group @n + * boost::asio::ip::multicast::enable_loopback @n + * boost::asio::ip::multicast::outbound_interface @n + * boost::asio::ip::multicast::hops @n + * boost::asio::ip::tcp::no_delay + * + * @par Example + * Getting the value of the SOL_SOCKET/SO_KEEPALIVE option: + * @code + * boost::asio::ip::tcp::socket socket(my_context); + * ... + * boost::asio::ip::tcp::socket::keep_alive option; + * socket.get_option(option); + * bool is_set = option.value(); + * @endcode + */ + template + void get_option(GettableSocketOption& option) const + { + boost::system::error_code ec; + impl_.get_service().get_option(impl_.get_implementation(), option, ec); + boost::asio::detail::throw_error(ec, "get_option"); + } + + /// Get an option from the socket. + /** + * This function is used to get the current value of an option on the socket. + * + * @param option The option value to be obtained from the socket. + * + * @param ec Set to indicate what error occurred, if any. + * + * @sa GettableSocketOption @n + * boost::asio::socket_base::broadcast @n + * boost::asio::socket_base::do_not_route @n + * boost::asio::socket_base::keep_alive @n + * boost::asio::socket_base::linger @n + * boost::asio::socket_base::receive_buffer_size @n + * boost::asio::socket_base::receive_low_watermark @n + * boost::asio::socket_base::reuse_address @n + * boost::asio::socket_base::send_buffer_size @n + * boost::asio::socket_base::send_low_watermark @n + * boost::asio::ip::multicast::join_group @n + * boost::asio::ip::multicast::leave_group @n + * boost::asio::ip::multicast::enable_loopback @n + * boost::asio::ip::multicast::outbound_interface @n + * boost::asio::ip::multicast::hops @n + * boost::asio::ip::tcp::no_delay + * + * @par Example + * Getting the value of the SOL_SOCKET/SO_KEEPALIVE option: + * @code + * boost::asio::ip::tcp::socket socket(my_context); + * ... + * boost::asio::ip::tcp::socket::keep_alive option; + * boost::system::error_code ec; + * socket.get_option(option, ec); + * if (ec) + * { + * // An error occurred. + * } + * bool is_set = option.value(); + * @endcode + */ + template + BOOST_ASIO_SYNC_OP_VOID get_option(GettableSocketOption& option, + boost::system::error_code& ec) const + { + impl_.get_service().get_option(impl_.get_implementation(), option, ec); + BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); + } + + /// Perform an IO control command on the socket. + /** + * This function is used to execute an IO control command on the socket. + * + * @param command The IO control command to be performed on the socket. + * + * @throws boost::system::system_error Thrown on failure. + * + * @sa IoControlCommand @n + * boost::asio::socket_base::bytes_readable @n + * boost::asio::socket_base::non_blocking_io + * + * @par Example + * Getting the number of bytes ready to read: + * @code + * boost::asio::ip::tcp::socket socket(my_context); + * ... + * boost::asio::ip::tcp::socket::bytes_readable command; + * socket.io_control(command); + * std::size_t bytes_readable = command.get(); + * @endcode + */ + template + void io_control(IoControlCommand& command) + { + boost::system::error_code ec; + impl_.get_service().io_control(impl_.get_implementation(), command, ec); + boost::asio::detail::throw_error(ec, "io_control"); + } + + /// Perform an IO control command on the socket. + /** + * This function is used to execute an IO control command on the socket. + * + * @param command The IO control command to be performed on the socket. + * + * @param ec Set to indicate what error occurred, if any. + * + * @sa IoControlCommand @n + * boost::asio::socket_base::bytes_readable @n + * boost::asio::socket_base::non_blocking_io + * + * @par Example + * Getting the number of bytes ready to read: + * @code + * boost::asio::ip::tcp::socket socket(my_context); + * ... + * boost::asio::ip::tcp::socket::bytes_readable command; + * boost::system::error_code ec; + * socket.io_control(command, ec); + * if (ec) + * { + * // An error occurred. + * } + * std::size_t bytes_readable = command.get(); + * @endcode + */ + template + BOOST_ASIO_SYNC_OP_VOID io_control(IoControlCommand& command, + boost::system::error_code& ec) + { + impl_.get_service().io_control(impl_.get_implementation(), command, ec); + BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); + } + + /// Gets the non-blocking mode of the socket. + /** + * @returns @c true if the socket's synchronous operations will fail with + * boost::asio::error::would_block if they are unable to perform the requested + * operation immediately. If @c false, synchronous operations will block + * until complete. + * + * @note The non-blocking mode has no effect on the behaviour of asynchronous + * operations. Asynchronous operations will never fail with the error + * boost::asio::error::would_block. + */ + bool non_blocking() const + { + return impl_.get_service().non_blocking(impl_.get_implementation()); + } + + /// Sets the non-blocking mode of the socket. + /** + * @param mode If @c true, the socket's synchronous operations will fail with + * boost::asio::error::would_block if they are unable to perform the requested + * operation immediately. If @c false, synchronous operations will block + * until complete. + * + * @throws boost::system::system_error Thrown on failure. + * + * @note The non-blocking mode has no effect on the behaviour of asynchronous + * operations. Asynchronous operations will never fail with the error + * boost::asio::error::would_block. + */ + void non_blocking(bool mode) + { + boost::system::error_code ec; + impl_.get_service().non_blocking(impl_.get_implementation(), mode, ec); + boost::asio::detail::throw_error(ec, "non_blocking"); + } + + /// Sets the non-blocking mode of the socket. + /** + * @param mode If @c true, the socket's synchronous operations will fail with + * boost::asio::error::would_block if they are unable to perform the requested + * operation immediately. If @c false, synchronous operations will block + * until complete. + * + * @param ec Set to indicate what error occurred, if any. + * + * @note The non-blocking mode has no effect on the behaviour of asynchronous + * operations. Asynchronous operations will never fail with the error + * boost::asio::error::would_block. + */ + BOOST_ASIO_SYNC_OP_VOID non_blocking( + bool mode, boost::system::error_code& ec) + { + impl_.get_service().non_blocking(impl_.get_implementation(), mode, ec); + BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); + } + + /// Gets the non-blocking mode of the native socket implementation. + /** + * This function is used to retrieve the non-blocking mode of the underlying + * native socket. This mode has no effect on the behaviour of the socket + * object's synchronous operations. + * + * @returns @c true if the underlying socket is in non-blocking mode and + * direct system calls may fail with boost::asio::error::would_block (or the + * equivalent system error). + * + * @note The current non-blocking mode is cached by the socket object. + * Consequently, the return value may be incorrect if the non-blocking mode + * was set directly on the native socket. + * + * @par Example + * This function is intended to allow the encapsulation of arbitrary + * non-blocking system calls as asynchronous operations, in a way that is + * transparent to the user of the socket object. The following example + * illustrates how Linux's @c sendfile system call might be encapsulated: + * @code template + * struct sendfile_op + * { + * tcp::socket& sock_; + * int fd_; + * Handler handler_; + * off_t offset_; + * std::size_t total_bytes_transferred_; + * + * // Function call operator meeting WriteHandler requirements. + * // Used as the handler for the async_write_some operation. + * void operator()(boost::system::error_code ec, std::size_t) + * { + * // Put the underlying socket into non-blocking mode. + * if (!ec) + * if (!sock_.native_non_blocking()) + * sock_.native_non_blocking(true, ec); + * + * if (!ec) + * { + * for (;;) + * { + * // Try the system call. + * errno = 0; + * int n = ::sendfile(sock_.native_handle(), fd_, &offset_, 65536); + * ec = boost::system::error_code(n < 0 ? errno : 0, + * boost::asio::error::get_system_category()); + * total_bytes_transferred_ += ec ? 0 : n; + * + * // Retry operation immediately if interrupted by signal. + * if (ec == boost::asio::error::interrupted) + * continue; + * + * // Check if we need to run the operation again. + * if (ec == boost::asio::error::would_block + * || ec == boost::asio::error::try_again) + * { + * // We have to wait for the socket to become ready again. + * sock_.async_wait(tcp::socket::wait_write, *this); + * return; + * } + * + * if (ec || n == 0) + * { + * // An error occurred, or we have reached the end of the file. + * // Either way we must exit the loop so we can call the handler. + * break; + * } + * + * // Loop around to try calling sendfile again. + * } + * } + * + * // Pass result back to user's handler. + * handler_(ec, total_bytes_transferred_); + * } + * }; + * + * template + * void async_sendfile(tcp::socket& sock, int fd, Handler h) + * { + * sendfile_op op = { sock, fd, h, 0, 0 }; + * sock.async_wait(tcp::socket::wait_write, op); + * } @endcode + */ + bool native_non_blocking() const + { + return impl_.get_service().native_non_blocking(impl_.get_implementation()); + } + + /// Sets the non-blocking mode of the native socket implementation. + /** + * This function is used to modify the non-blocking mode of the underlying + * native socket. It has no effect on the behaviour of the socket object's + * synchronous operations. + * + * @param mode If @c true, the underlying socket is put into non-blocking + * mode and direct system calls may fail with boost::asio::error::would_block + * (or the equivalent system error). + * + * @throws boost::system::system_error Thrown on failure. If the @c mode is + * @c false, but the current value of @c non_blocking() is @c true, this + * function fails with boost::asio::error::invalid_argument, as the + * combination does not make sense. + * + * @par Example + * This function is intended to allow the encapsulation of arbitrary + * non-blocking system calls as asynchronous operations, in a way that is + * transparent to the user of the socket object. The following example + * illustrates how Linux's @c sendfile system call might be encapsulated: + * @code template + * struct sendfile_op + * { + * tcp::socket& sock_; + * int fd_; + * Handler handler_; + * off_t offset_; + * std::size_t total_bytes_transferred_; + * + * // Function call operator meeting WriteHandler requirements. + * // Used as the handler for the async_write_some operation. + * void operator()(boost::system::error_code ec, std::size_t) + * { + * // Put the underlying socket into non-blocking mode. + * if (!ec) + * if (!sock_.native_non_blocking()) + * sock_.native_non_blocking(true, ec); + * + * if (!ec) + * { + * for (;;) + * { + * // Try the system call. + * errno = 0; + * int n = ::sendfile(sock_.native_handle(), fd_, &offset_, 65536); + * ec = boost::system::error_code(n < 0 ? errno : 0, + * boost::asio::error::get_system_category()); + * total_bytes_transferred_ += ec ? 0 : n; + * + * // Retry operation immediately if interrupted by signal. + * if (ec == boost::asio::error::interrupted) + * continue; + * + * // Check if we need to run the operation again. + * if (ec == boost::asio::error::would_block + * || ec == boost::asio::error::try_again) + * { + * // We have to wait for the socket to become ready again. + * sock_.async_wait(tcp::socket::wait_write, *this); + * return; + * } + * + * if (ec || n == 0) + * { + * // An error occurred, or we have reached the end of the file. + * // Either way we must exit the loop so we can call the handler. + * break; + * } + * + * // Loop around to try calling sendfile again. + * } + * } + * + * // Pass result back to user's handler. + * handler_(ec, total_bytes_transferred_); + * } + * }; + * + * template + * void async_sendfile(tcp::socket& sock, int fd, Handler h) + * { + * sendfile_op op = { sock, fd, h, 0, 0 }; + * sock.async_wait(tcp::socket::wait_write, op); + * } @endcode + */ + void native_non_blocking(bool mode) + { + boost::system::error_code ec; + impl_.get_service().native_non_blocking( + impl_.get_implementation(), mode, ec); + boost::asio::detail::throw_error(ec, "native_non_blocking"); + } + + /// Sets the non-blocking mode of the native socket implementation. + /** + * This function is used to modify the non-blocking mode of the underlying + * native socket. It has no effect on the behaviour of the socket object's + * synchronous operations. + * + * @param mode If @c true, the underlying socket is put into non-blocking + * mode and direct system calls may fail with boost::asio::error::would_block + * (or the equivalent system error). + * + * @param ec Set to indicate what error occurred, if any. If the @c mode is + * @c false, but the current value of @c non_blocking() is @c true, this + * function fails with boost::asio::error::invalid_argument, as the + * combination does not make sense. + * + * @par Example + * This function is intended to allow the encapsulation of arbitrary + * non-blocking system calls as asynchronous operations, in a way that is + * transparent to the user of the socket object. The following example + * illustrates how Linux's @c sendfile system call might be encapsulated: + * @code template + * struct sendfile_op + * { + * tcp::socket& sock_; + * int fd_; + * Handler handler_; + * off_t offset_; + * std::size_t total_bytes_transferred_; + * + * // Function call operator meeting WriteHandler requirements. + * // Used as the handler for the async_write_some operation. + * void operator()(boost::system::error_code ec, std::size_t) + * { + * // Put the underlying socket into non-blocking mode. + * if (!ec) + * if (!sock_.native_non_blocking()) + * sock_.native_non_blocking(true, ec); + * + * if (!ec) + * { + * for (;;) + * { + * // Try the system call. + * errno = 0; + * int n = ::sendfile(sock_.native_handle(), fd_, &offset_, 65536); + * ec = boost::system::error_code(n < 0 ? errno : 0, + * boost::asio::error::get_system_category()); + * total_bytes_transferred_ += ec ? 0 : n; + * + * // Retry operation immediately if interrupted by signal. + * if (ec == boost::asio::error::interrupted) + * continue; + * + * // Check if we need to run the operation again. + * if (ec == boost::asio::error::would_block + * || ec == boost::asio::error::try_again) + * { + * // We have to wait for the socket to become ready again. + * sock_.async_wait(tcp::socket::wait_write, *this); + * return; + * } + * + * if (ec || n == 0) + * { + * // An error occurred, or we have reached the end of the file. + * // Either way we must exit the loop so we can call the handler. + * break; + * } + * + * // Loop around to try calling sendfile again. + * } + * } + * + * // Pass result back to user's handler. + * handler_(ec, total_bytes_transferred_); + * } + * }; + * + * template + * void async_sendfile(tcp::socket& sock, int fd, Handler h) + * { + * sendfile_op op = { sock, fd, h, 0, 0 }; + * sock.async_wait(tcp::socket::wait_write, op); + * } @endcode + */ + BOOST_ASIO_SYNC_OP_VOID native_non_blocking( + bool mode, boost::system::error_code& ec) + { + impl_.get_service().native_non_blocking( + impl_.get_implementation(), mode, ec); + BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); + } + + /// Get the local endpoint of the socket. + /** + * This function is used to obtain the locally bound endpoint of the socket. + * + * @returns An object that represents the local endpoint of the socket. + * + * @throws boost::system::system_error Thrown on failure. + * + * @par Example + * @code + * boost::asio::ip::tcp::socket socket(my_context); + * ... + * boost::asio::ip::tcp::endpoint endpoint = socket.local_endpoint(); + * @endcode + */ + endpoint_type local_endpoint() const + { + boost::system::error_code ec; + endpoint_type ep = impl_.get_service().local_endpoint( + impl_.get_implementation(), ec); + boost::asio::detail::throw_error(ec, "local_endpoint"); + return ep; + } + + /// Get the local endpoint of the socket. + /** + * This function is used to obtain the locally bound endpoint of the socket. + * + * @param ec Set to indicate what error occurred, if any. + * + * @returns An object that represents the local endpoint of the socket. + * Returns a default-constructed endpoint object if an error occurred. + * + * @par Example + * @code + * boost::asio::ip::tcp::socket socket(my_context); + * ... + * boost::system::error_code ec; + * boost::asio::ip::tcp::endpoint endpoint = socket.local_endpoint(ec); + * if (ec) + * { + * // An error occurred. + * } + * @endcode + */ + endpoint_type local_endpoint(boost::system::error_code& ec) const + { + return impl_.get_service().local_endpoint(impl_.get_implementation(), ec); + } + + /// Get the remote endpoint of the socket. + /** + * This function is used to obtain the remote endpoint of the socket. + * + * @returns An object that represents the remote endpoint of the socket. + * + * @throws boost::system::system_error Thrown on failure. + * + * @par Example + * @code + * boost::asio::ip::tcp::socket socket(my_context); + * ... + * boost::asio::ip::tcp::endpoint endpoint = socket.remote_endpoint(); + * @endcode + */ + endpoint_type remote_endpoint() const + { + boost::system::error_code ec; + endpoint_type ep = impl_.get_service().remote_endpoint( + impl_.get_implementation(), ec); + boost::asio::detail::throw_error(ec, "remote_endpoint"); + return ep; + } + + /// Get the remote endpoint of the socket. + /** + * This function is used to obtain the remote endpoint of the socket. + * + * @param ec Set to indicate what error occurred, if any. + * + * @returns An object that represents the remote endpoint of the socket. + * Returns a default-constructed endpoint object if an error occurred. + * + * @par Example + * @code + * boost::asio::ip::tcp::socket socket(my_context); + * ... + * boost::system::error_code ec; + * boost::asio::ip::tcp::endpoint endpoint = socket.remote_endpoint(ec); + * if (ec) + * { + * // An error occurred. + * } + * @endcode + */ + endpoint_type remote_endpoint(boost::system::error_code& ec) const + { + return impl_.get_service().remote_endpoint(impl_.get_implementation(), ec); + } + + /// Disable sends or receives on the socket. + /** + * This function is used to disable send operations, receive operations, or + * both. + * + * @param what Determines what types of operation will no longer be allowed. + * + * @throws boost::system::system_error Thrown on failure. + * + * @par Example + * Shutting down the send side of the socket: + * @code + * boost::asio::ip::tcp::socket socket(my_context); + * ... + * socket.shutdown(boost::asio::ip::tcp::socket::shutdown_send); + * @endcode + */ + void shutdown(shutdown_type what) + { + boost::system::error_code ec; + impl_.get_service().shutdown(impl_.get_implementation(), what, ec); + boost::asio::detail::throw_error(ec, "shutdown"); + } + + /// Disable sends or receives on the socket. + /** + * This function is used to disable send operations, receive operations, or + * both. + * + * @param what Determines what types of operation will no longer be allowed. + * + * @param ec Set to indicate what error occurred, if any. + * + * @par Example + * Shutting down the send side of the socket: + * @code + * boost::asio::ip::tcp::socket socket(my_context); + * ... + * boost::system::error_code ec; + * socket.shutdown(boost::asio::ip::tcp::socket::shutdown_send, ec); + * if (ec) + * { + * // An error occurred. + * } + * @endcode + */ + BOOST_ASIO_SYNC_OP_VOID shutdown(shutdown_type what, + boost::system::error_code& ec) + { + impl_.get_service().shutdown(impl_.get_implementation(), what, ec); + BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); + } + + /// Wait for the socket to become ready to read, ready to write, or to have + /// pending error conditions. + /** + * This function is used to perform a blocking wait for a socket to enter + * a ready to read, write or error condition state. + * + * @param w Specifies the desired socket state. + * + * @par Example + * Waiting for a socket to become readable. + * @code + * boost::asio::ip::tcp::socket socket(my_context); + * ... + * socket.wait(boost::asio::ip::tcp::socket::wait_read); + * @endcode + */ + void wait(wait_type w) + { + boost::system::error_code ec; + impl_.get_service().wait(impl_.get_implementation(), w, ec); + boost::asio::detail::throw_error(ec, "wait"); + } + + /// Wait for the socket to become ready to read, ready to write, or to have + /// pending error conditions. + /** + * This function is used to perform a blocking wait for a socket to enter + * a ready to read, write or error condition state. + * + * @param w Specifies the desired socket state. + * + * @param ec Set to indicate what error occurred, if any. + * + * @par Example + * Waiting for a socket to become readable. + * @code + * boost::asio::ip::tcp::socket socket(my_context); + * ... + * boost::system::error_code ec; + * socket.wait(boost::asio::ip::tcp::socket::wait_read, ec); + * @endcode + */ + BOOST_ASIO_SYNC_OP_VOID wait(wait_type w, boost::system::error_code& ec) + { + impl_.get_service().wait(impl_.get_implementation(), w, ec); + BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); + } + + /// Asynchronously wait for the socket to become ready to read, ready to + /// write, or to have pending error conditions. + /** + * This function is used to perform an asynchronous wait for a socket to enter + * a ready to read, write or error condition state. + * + * @param w Specifies the desired socket state. + * + * @param handler The handler to be called when the wait operation completes. + * Copies will be made of the handler as required. The function signature of + * the handler must be: + * @code void handler( + * const boost::system::error_code& error // Result of operation + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. On + * immediate completion, invocation of the handler will be performed in a + * manner equivalent to using boost::asio::post(). + * + * @par Example + * @code + * void wait_handler(const boost::system::error_code& error) + * { + * if (!error) + * { + * // Wait succeeded. + * } + * } + * + * ... + * + * boost::asio::ip::tcp::socket socket(my_context); + * ... + * socket.async_wait(boost::asio::ip::tcp::socket::wait_read, wait_handler); + * @endcode + */ + template + BOOST_ASIO_INITFN_RESULT_TYPE(WaitHandler, + void (boost::system::error_code)) + async_wait(wait_type w, BOOST_ASIO_MOVE_ARG(WaitHandler) handler) + { + return async_initiate( + initiate_async_wait(), handler, this, w); + } + +protected: + /// Protected destructor to prevent deletion through this type. + /** + * This function destroys the socket, cancelling any outstanding asynchronous + * operations associated with the socket as if by calling @c cancel. + */ + ~basic_socket_ext_local() + { + } + +#if defined(BOOST_ASIO_WINDOWS_RUNTIME) + detail::io_object_impl< + detail::null_socket_service, Executor> impl_; +#elif defined(BOOST_ASIO_HAS_IOCP) + detail::io_object_impl< + detail::win_iocp_socket_service, Executor> impl_; +#else + detail::io_object_impl< + detail::reactive_socket_service_ext_local, Executor> impl_; +#endif + +private: + // Disallow copying and assignment. + basic_socket_ext_local(const basic_socket_ext_local&) BOOST_ASIO_DELETED; + basic_socket_ext_local& operator=(const basic_socket_ext_local&) BOOST_ASIO_DELETED; + + struct initiate_async_connect + { + template + void operator()(BOOST_ASIO_MOVE_ARG(ConnectHandler) handler, + basic_socket_ext_local* self, const endpoint_type& peer_endpoint, + const boost::system::error_code& open_ec) const + { + // If you get an error on the following line it means that your handler + // does not meet the documented type requirements for a ConnectHandler. + BOOST_ASIO_CONNECT_HANDLER_CHECK(ConnectHandler, handler) type_check; + + if (open_ec) + { + boost::asio::post(self->impl_.get_executor(), + boost::asio::detail::bind_handler( + BOOST_ASIO_MOVE_CAST(ConnectHandler)(handler), open_ec)); + } + else + { + detail::non_const_lvalue handler2(handler); + self->impl_.get_service().async_connect( + self->impl_.get_implementation(), peer_endpoint, + handler2.value, self->impl_.get_implementation_executor()); + } + } + }; + + struct initiate_async_wait + { + template + void operator()(BOOST_ASIO_MOVE_ARG(WaitHandler) handler, + basic_socket_ext_local* self, wait_type w) const + { + // If you get an error on the following line it means that your handler + // does not meet the documented type requirements for a WaitHandler. + BOOST_ASIO_WAIT_HANDLER_CHECK(WaitHandler, handler) type_check; + + detail::non_const_lvalue handler2(handler); + self->impl_.get_service().async_wait( + self->impl_.get_implementation(), w, handler2.value, + self->impl_.get_implementation_executor()); + } + }; +}; + +} // namespace asio +} // namespace boost + +#include + +#endif // BOOST_ASIO_BASIC_SOCKET_EXT_LOCAL_HPP diff --git a/implementation/helper/1.76/boost/asio/basic_stream_socket_ext.hpp b/implementation/helper/1.76/boost/asio/basic_stream_socket_ext.hpp new file mode 100644 index 0000000..e77f5eb --- /dev/null +++ b/implementation/helper/1.76/boost/asio/basic_stream_socket_ext.hpp @@ -0,0 +1,996 @@ +// +// basic_stream_socket_ext.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2016-2019 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_BASIC_STREAM_SOCKET_EXT_HPP +#define BOOST_ASIO_BASIC_STREAM_SOCKET_EXT_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace boost { +namespace asio { + +#if !defined(BOOST_ASIO_BASIC_STREAM_SOCKET_EXT_FWD_DECL) +#define BOOST_ASIO_BASIC_STREAM_SOCKET_EXT_FWD_DECL + +// Forward declaration with defaulted arguments. +template +class basic_stream_socket_ext; + +#endif // !defined(BOOST_ASIO_BASIC_STREAM_SOCKET_EXT_FWD_DECL) + +/// Provides stream-oriented socket functionality. +/** + * The basic_stream_socket_ext class template provides asynchronous and blocking + * stream-oriented socket functionality. + * + * @par Thread Safety + * @e Distinct @e objects: Safe.@n + * @e Shared @e objects: Unsafe. + * + * @par Concepts: + * AsyncReadStream, AsyncWriteStream, Stream, SyncReadStream, SyncWriteStream. + */ +template +class basic_stream_socket_ext + : public basic_socket_ext_local +{ +public: + /// The type of the executor associated with the object. + typedef Executor executor_type; + + /// Rebinds the socket type to another executor. + template + struct rebind_executor + { + /// The socket type when rebound to the specified executor. + typedef basic_stream_socket_ext other; + }; + + /// The native representation of a socket. +#if defined(GENERATING_DOCUMENTATION) + typedef implementation_defined native_handle_type; +#else + typedef typename basic_socket::native_handle_type native_handle_type; +#endif + + /// The protocol type. + typedef Protocol protocol_type; + + /// The endpoint type. + typedef typename Protocol::endpoint endpoint_type; + + /// Construct a basic_stream_socket without opening it. + /** + * This constructor creates a stream socket without opening it. The socket + * needs to be opened and then connected or accepted before data can be sent + * or received on it. + * + * @param ex The I/O executor that the socket will use, by default, to + * dispatch handlers for any asynchronous operations performed on the socket. + */ + explicit basic_stream_socket_ext(const executor_type& ex) + : basic_socket_ext_local(ex) + { + } + + /// Construct a basic_stream_socket without opening it. + /** + * This constructor creates a stream socket without opening it. The socket + * needs to be opened and then connected or accepted before data can be sent + * or received on it. + * + * @param context An execution context which provides the I/O executor that + * the socket will use, by default, to dispatch handlers for any asynchronous + * operations performed on the socket. + */ + template + explicit basic_stream_socket_ext(ExecutionContext& context, + typename enable_if< + is_convertible::value + >::type* = 0) + : basic_socket_ext_local(context) + { + } + + /// Construct and open a basic_stream_socket. + /** + * This constructor creates and opens a stream socket. The socket needs to be + * connected or accepted before data can be sent or received on it. + * + * @param ex The I/O executor that the socket will use, by default, to + * dispatch handlers for any asynchronous operations performed on the socket. + * + * @param protocol An object specifying protocol parameters to be used. + * + * @throws boost::system::system_error Thrown on failure. + */ + basic_stream_socket_ext(const executor_type& ex, const protocol_type& protocol) + : basic_socket_ext_local(ex, protocol) + { + } + + /// Construct and open a basic_stream_socket. + /** + * This constructor creates and opens a stream socket. The socket needs to be + * connected or accepted before data can be sent or received on it. + * + * @param context An execution context which provides the I/O executor that + * the socket will use, by default, to dispatch handlers for any asynchronous + * operations performed on the socket. + * + * @param protocol An object specifying protocol parameters to be used. + * + * @throws boost::system::system_error Thrown on failure. + */ + template + basic_stream_socket_ext(ExecutionContext& context, const protocol_type& protocol, + typename enable_if< + is_convertible::value + >::type* = 0) + : basic_socket_ext_local(context, protocol) + { + } + + /// Construct a basic_stream_socket, opening it and binding it to the given + /// local endpoint. + /** + * This constructor creates a stream socket and automatically opens it bound + * to the specified endpoint on the local machine. The protocol used is the + * protocol associated with the given endpoint. + * + * @param ex The I/O executor that the socket will use, by default, to + * dispatch handlers for any asynchronous operations performed on the socket. + * + * @param endpoint An endpoint on the local machine to which the stream + * socket will be bound. + * + * @throws boost::system::system_error Thrown on failure. + */ + basic_stream_socket_ext(const executor_type& ex, const endpoint_type& endpoint) + : basic_socket_ext_local(ex, endpoint) + { + } + + /// Construct a basic_stream_socket, opening it and binding it to the given + /// local endpoint. + /** + * This constructor creates a stream socket and automatically opens it bound + * to the specified endpoint on the local machine. The protocol used is the + * protocol associated with the given endpoint. + * + * @param context An execution context which provides the I/O executor that + * the socket will use, by default, to dispatch handlers for any asynchronous + * operations performed on the socket. + * + * @param endpoint An endpoint on the local machine to which the stream + * socket will be bound. + * + * @throws boost::system::system_error Thrown on failure. + */ + template + basic_stream_socket_ext(ExecutionContext& context, const endpoint_type& endpoint, + typename enable_if< + is_convertible::value + >::type* = 0) + : basic_socket_ext_local(context, endpoint) + { + } + + /// Construct a basic_stream_socket on an existing native socket. + /** + * This constructor creates a stream socket object to hold an existing native + * socket. + * + * @param ex The I/O executor that the socket will use, by default, to + * dispatch handlers for any asynchronous operations performed on the socket. + * + * @param protocol An object specifying protocol parameters to be used. + * + * @param native_socket The new underlying socket implementation. + * + * @throws boost::system::system_error Thrown on failure. + */ + basic_stream_socket_ext(const executor_type& ex, + const protocol_type& protocol, const native_handle_type& native_socket) + : basic_socket_ext_local(ex, protocol, native_socket) + { + } + + /// Construct a basic_stream_socket on an existing native socket. + /** + * This constructor creates a stream socket object to hold an existing native + * socket. + * + * @param context An execution context which provides the I/O executor that + * the socket will use, by default, to dispatch handlers for any asynchronous + * operations performed on the socket. + * + * @param protocol An object specifying protocol parameters to be used. + * + * @param native_socket The new underlying socket implementation. + * + * @throws boost::system::system_error Thrown on failure. + */ + template + basic_stream_socket_ext(ExecutionContext& context, + const protocol_type& protocol, const native_handle_type& native_socket, + typename enable_if< + is_convertible::value + >::type* = 0) + : basic_socket_ext_local(context, protocol, native_socket) + { + } + +#if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) + /// Move-construct a basic_stream_socket from another. + /** + * This constructor moves a stream socket from one object to another. + * + * @param other The other basic_stream_socket object from which the move + * will occur. + * + * @note Following the move, the moved-from object is in the same state as if + * constructed using the @c basic_stream_socket(const executor_type&) + * constructor. + */ + basic_stream_socket_ext(basic_stream_socket_ext&& other) + : basic_socket_ext_local(std::move(other)) + { + } + + /// Move-assign a basic_stream_socket from another. + /** + * This assignment operator moves a stream socket from one object to another. + * + * @param other The other basic_stream_socket object from which the move + * will occur. + * + * @note Following the move, the moved-from object is in the same state as if + * constructed using the @c basic_stream_socket(const executor_type&) + * constructor. + */ + basic_stream_socket_ext& operator=(basic_stream_socket_ext&& other) + { + basic_socket_ext_local::operator=(std::move(other)); + return *this; + } + + /// Move-construct a basic_stream_socket from a socket of another protocol + /// type. + /** + * This constructor moves a stream socket from one object to another. + * + * @param other The other basic_stream_socket object from which the move + * will occur. + * + * @note Following the move, the moved-from object is in the same state as if + * constructed using the @c basic_stream_socket(const executor_type&) + * constructor. + */ + template + basic_stream_socket_ext(basic_stream_socket_ext&& other, + typename enable_if< + is_convertible::value + && is_convertible::value + >::type* = 0) + : basic_socket_ext_local(std::move(other)) + { + } + + /// Move-assign a basic_stream_socket from a socket of another protocol type. + /** + * This assignment operator moves a stream socket from one object to another. + * + * @param other The other basic_stream_socket object from which the move + * will occur. + * + * @note Following the move, the moved-from object is in the same state as if + * constructed using the @c basic_stream_socket(const executor_type&) + * constructor. + */ + template + typename enable_if< + is_convertible::value + && is_convertible::value, + basic_stream_socket_ext& + >::type operator=(basic_stream_socket_ext&& other) + { + basic_socket_ext_local::operator=(std::move(other)); + return *this; + } +#endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) + + /// Destroys the socket. + /** + * This function destroys the socket, cancelling any outstanding asynchronous + * operations associated with the socket as if by calling @c cancel. + */ + ~basic_stream_socket_ext() + { + } + + /// Send some data on the socket. + /** + * This function is used to send data on the stream socket. The function + * call will block until one or more bytes of the data has been sent + * successfully, or an until error occurs. + * + * @param buffers One or more data buffers to be sent on the socket. + * + * @returns The number of bytes sent. + * + * @throws boost::system::system_error Thrown on failure. + * + * @note The send operation may not transmit all of the data to the peer. + * Consider using the @ref write function if you need to ensure that all data + * is written before the blocking operation completes. + * + * @par Example + * To send a single data buffer use the @ref buffer function as follows: + * @code + * socket.send(boost::asio::buffer(data, size)); + * @endcode + * See the @ref buffer documentation for information on sending multiple + * buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ + template + std::size_t send(const ConstBufferSequence& buffers) + { + boost::system::error_code ec; + std::size_t s = this->impl_.get_service().send( + this->impl_.get_implementation(), buffers, 0, ec); + boost::asio::detail::throw_error(ec, "send"); + return s; + } + + /// Send some data on the socket. + /** + * This function is used to send data on the stream socket. The function + * call will block until one or more bytes of the data has been sent + * successfully, or an until error occurs. + * + * @param buffers One or more data buffers to be sent on the socket. + * + * @param flags Flags specifying how the send call is to be made. + * + * @returns The number of bytes sent. + * + * @throws boost::system::system_error Thrown on failure. + * + * @note The send operation may not transmit all of the data to the peer. + * Consider using the @ref write function if you need to ensure that all data + * is written before the blocking operation completes. + * + * @par Example + * To send a single data buffer use the @ref buffer function as follows: + * @code + * socket.send(boost::asio::buffer(data, size), 0); + * @endcode + * See the @ref buffer documentation for information on sending multiple + * buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ + template + std::size_t send(const ConstBufferSequence& buffers, + socket_base::message_flags flags) + { + boost::system::error_code ec; + std::size_t s = this->impl_.get_service().send( + this->impl_.get_implementation(), buffers, flags, ec); + boost::asio::detail::throw_error(ec, "send"); + return s; + } + + /// Send some data on the socket. + /** + * This function is used to send data on the stream socket. The function + * call will block until one or more bytes of the data has been sent + * successfully, or an until error occurs. + * + * @param buffers One or more data buffers to be sent on the socket. + * + * @param flags Flags specifying how the send call is to be made. + * + * @param ec Set to indicate what error occurred, if any. + * + * @returns The number of bytes sent. Returns 0 if an error occurred. + * + * @note The send operation may not transmit all of the data to the peer. + * Consider using the @ref write function if you need to ensure that all data + * is written before the blocking operation completes. + */ + template + std::size_t send(const ConstBufferSequence& buffers, + socket_base::message_flags flags, boost::system::error_code& ec) + { + return this->impl_.get_service().send( + this->impl_.get_implementation(), buffers, flags, ec); + } + + /// Start an asynchronous send. + /** + * This function is used to asynchronously send data on the stream socket. + * The function call always returns immediately. + * + * @param buffers One or more data buffers to be sent on the socket. Although + * the buffers object may be copied as necessary, ownership of the underlying + * memory blocks is retained by the caller, which must guarantee that they + * remain valid until the handler is called. + * + * @param handler The handler to be called when the send operation completes. + * Copies will be made of the handler as required. The function signature of + * the handler must be: + * @code void handler( + * const boost::system::error_code& error, // Result of operation. + * std::size_t bytes_transferred // Number of bytes sent. + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. On + * immediate completion, invocation of the handler will be performed in a + * manner equivalent to using boost::asio::post(). + * + * @note The send operation may not transmit all of the data to the peer. + * Consider using the @ref async_write function if you need to ensure that all + * data is written before the asynchronous operation completes. + * + * @par Example + * To send a single data buffer use the @ref buffer function as follows: + * @code + * socket.async_send(boost::asio::buffer(data, size), handler); + * @endcode + * See the @ref buffer documentation for information on sending multiple + * buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ + template + BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler, + void (boost::system::error_code, std::size_t)) + async_send(const ConstBufferSequence& buffers, + BOOST_ASIO_MOVE_ARG(WriteHandler) handler) + { + return async_initiate( + initiate_async_send(), handler, this, + buffers, socket_base::message_flags(0)); + } + + /// Start an asynchronous send. + /** + * This function is used to asynchronously send data on the stream socket. + * The function call always returns immediately. + * + * @param buffers One or more data buffers to be sent on the socket. Although + * the buffers object may be copied as necessary, ownership of the underlying + * memory blocks is retained by the caller, which must guarantee that they + * remain valid until the handler is called. + * + * @param flags Flags specifying how the send call is to be made. + * + * @param handler The handler to be called when the send operation completes. + * Copies will be made of the handler as required. The function signature of + * the handler must be: + * @code void handler( + * const boost::system::error_code& error, // Result of operation. + * std::size_t bytes_transferred // Number of bytes sent. + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. On + * immediate completion, invocation of the handler will be performed in a + * manner equivalent to using boost::asio::post(). + * + * @note The send operation may not transmit all of the data to the peer. + * Consider using the @ref async_write function if you need to ensure that all + * data is written before the asynchronous operation completes. + * + * @par Example + * To send a single data buffer use the @ref buffer function as follows: + * @code + * socket.async_send(boost::asio::buffer(data, size), 0, handler); + * @endcode + * See the @ref buffer documentation for information on sending multiple + * buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ + template + BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler, + void (boost::system::error_code, std::size_t)) + async_send(const ConstBufferSequence& buffers, + socket_base::message_flags flags, + BOOST_ASIO_MOVE_ARG(WriteHandler) handler) + { + return async_initiate( + initiate_async_send(), handler, this, buffers, flags); + } + + /// Receive some data on the socket. + /** + * This function is used to receive data on the stream socket. The function + * call will block until one or more bytes of data has been received + * successfully, or until an error occurs. + * + * @param buffers One or more buffers into which the data will be received. + * + * @returns The number of bytes received. + * + * @throws boost::system::system_error Thrown on failure. An error code of + * boost::asio::error::eof indicates that the connection was closed by the + * peer. + * + * @note The receive operation may not receive all of the requested number of + * bytes. Consider using the @ref read function if you need to ensure that the + * requested amount of data is read before the blocking operation completes. + * + * @par Example + * To receive into a single data buffer use the @ref buffer function as + * follows: + * @code + * socket.receive(boost::asio::buffer(data, size)); + * @endcode + * See the @ref buffer documentation for information on receiving into + * multiple buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ + template + std::size_t receive(const MutableBufferSequence& buffers) + { + boost::system::error_code ec; + std::size_t s = this->impl_.get_service().receive( + this->impl_.get_implementation(), buffers, 0, ec); + boost::asio::detail::throw_error(ec, "receive"); + return s; + } + + /// Receive some data on the socket. + /** + * This function is used to receive data on the stream socket. The function + * call will block until one or more bytes of data has been received + * successfully, or until an error occurs. + * + * @param buffers One or more buffers into which the data will be received. + * + * @param flags Flags specifying how the receive call is to be made. + * + * @returns The number of bytes received. + * + * @throws boost::system::system_error Thrown on failure. An error code of + * boost::asio::error::eof indicates that the connection was closed by the + * peer. + * + * @note The receive operation may not receive all of the requested number of + * bytes. Consider using the @ref read function if you need to ensure that the + * requested amount of data is read before the blocking operation completes. + * + * @par Example + * To receive into a single data buffer use the @ref buffer function as + * follows: + * @code + * socket.receive(boost::asio::buffer(data, size), 0); + * @endcode + * See the @ref buffer documentation for information on receiving into + * multiple buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ + template + std::size_t receive(const MutableBufferSequence& buffers, + socket_base::message_flags flags) + { + boost::system::error_code ec; + std::size_t s = this->impl_.get_service().receive( + this->impl_.get_implementation(), buffers, flags, ec); + boost::asio::detail::throw_error(ec, "receive"); + return s; + } + + /// Receive some data on a connected socket. + /** + * This function is used to receive data on the stream socket. The function + * call will block until one or more bytes of data has been received + * successfully, or until an error occurs. + * + * @param buffers One or more buffers into which the data will be received. + * + * @param flags Flags specifying how the receive call is to be made. + * + * @param ec Set to indicate what error occurred, if any. + * + * @returns The number of bytes received. Returns 0 if an error occurred. + * + * @note The receive operation may not receive all of the requested number of + * bytes. Consider using the @ref read function if you need to ensure that the + * requested amount of data is read before the blocking operation completes. + */ + template + std::size_t receive(const MutableBufferSequence& buffers, + socket_base::message_flags flags, boost::system::error_code& ec) + { + return this->impl_.get_service().receive( + this->impl_.get_implementation(), buffers, flags, ec); + } + + /// Start an asynchronous receive. + /** + * This function is used to asynchronously receive data from the stream + * socket. The function call always returns immediately. + * + * @param buffers One or more buffers into which the data will be received. + * Although the buffers object may be copied as necessary, ownership of the + * underlying memory blocks is retained by the caller, which must guarantee + * that they remain valid until the handler is called. + * + * @param handler The handler to be called when the receive operation + * completes. Copies will be made of the handler as required. The function + * signature of the handler must be: + * @code void handler( + * const boost::system::error_code& error, // Result of operation. + * std::size_t bytes_transferred // Number of bytes received. + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. On + * immediate completion, invocation of the handler will be performed in a + * manner equivalent to using boost::asio::post(). + * + * @note The receive operation may not receive all of the requested number of + * bytes. Consider using the @ref async_read function if you need to ensure + * that the requested amount of data is received before the asynchronous + * operation completes. + * + * @par Example + * To receive into a single data buffer use the @ref buffer function as + * follows: + * @code + * socket.async_receive(boost::asio::buffer(data, size), handler); + * @endcode + * See the @ref buffer documentation for information on receiving into + * multiple buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ + template + BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler, + void (boost::system::error_code, std::size_t, std::uint32_t, std::uint32_t)) + async_receive(const MutableBufferSequence& buffers, + BOOST_ASIO_MOVE_ARG(ReadHandler) handler) + { + return async_initiate( + initiate_async_receive(), handler, this, + buffers, socket_base::message_flags(0)); + } + + /// Start an asynchronous receive. + /** + * This function is used to asynchronously receive data from the stream + * socket. The function call always returns immediately. + * + * @param buffers One or more buffers into which the data will be received. + * Although the buffers object may be copied as necessary, ownership of the + * underlying memory blocks is retained by the caller, which must guarantee + * that they remain valid until the handler is called. + * + * @param flags Flags specifying how the receive call is to be made. + * + * @param handler The handler to be called when the receive operation + * completes. Copies will be made of the handler as required. The function + * signature of the handler must be: + * @code void handler( + * const boost::system::error_code& error, // Result of operation. + * std::size_t bytes_transferred // Number of bytes received. + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. On + * immediate completion, invocation of the handler will be performed in a + * manner equivalent to using boost::asio::post(). + * + * @note The receive operation may not receive all of the requested number of + * bytes. Consider using the @ref async_read function if you need to ensure + * that the requested amount of data is received before the asynchronous + * operation completes. + * + * @par Example + * To receive into a single data buffer use the @ref buffer function as + * follows: + * @code + * socket.async_receive(boost::asio::buffer(data, size), 0, handler); + * @endcode + * See the @ref buffer documentation for information on receiving into + * multiple buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ + template + BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler, + void (boost::system::error_code, std::size_t, std::uint32_t, std::uint32_t)) + async_receive(const MutableBufferSequence& buffers, + socket_base::message_flags flags, + BOOST_ASIO_MOVE_ARG(ReadHandler) handler) + { + return async_initiate( + initiate_async_receive(), handler, this, buffers, flags); + } + + /// Write some data to the socket. + /** + * This function is used to write data to the stream socket. The function call + * will block until one or more bytes of the data has been written + * successfully, or until an error occurs. + * + * @param buffers One or more data buffers to be written to the socket. + * + * @returns The number of bytes written. + * + * @throws boost::system::system_error Thrown on failure. An error code of + * boost::asio::error::eof indicates that the connection was closed by the + * peer. + * + * @note The write_some operation may not transmit all of the data to the + * peer. Consider using the @ref write function if you need to ensure that + * all data is written before the blocking operation completes. + * + * @par Example + * To write a single data buffer use the @ref buffer function as follows: + * @code + * socket.write_some(boost::asio::buffer(data, size)); + * @endcode + * See the @ref buffer documentation for information on writing multiple + * buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ + template + std::size_t write_some(const ConstBufferSequence& buffers) + { + boost::system::error_code ec; + std::size_t s = this->impl_.get_service().send( + this->impl_.get_implementation(), buffers, 0, ec); + boost::asio::detail::throw_error(ec, "write_some"); + return s; + } + + /// Write some data to the socket. + /** + * This function is used to write data to the stream socket. The function call + * will block until one or more bytes of the data has been written + * successfully, or until an error occurs. + * + * @param buffers One or more data buffers to be written to the socket. + * + * @param ec Set to indicate what error occurred, if any. + * + * @returns The number of bytes written. Returns 0 if an error occurred. + * + * @note The write_some operation may not transmit all of the data to the + * peer. Consider using the @ref write function if you need to ensure that + * all data is written before the blocking operation completes. + */ + template + std::size_t write_some(const ConstBufferSequence& buffers, + boost::system::error_code& ec) + { + return this->impl_.get_service().send( + this->impl_.get_implementation(), buffers, 0, ec); + } + + /// Start an asynchronous write. + /** + * This function is used to asynchronously write data to the stream socket. + * The function call always returns immediately. + * + * @param buffers One or more data buffers to be written to the socket. + * Although the buffers object may be copied as necessary, ownership of the + * underlying memory blocks is retained by the caller, which must guarantee + * that they remain valid until the handler is called. + * + * @param handler The handler to be called when the write operation completes. + * Copies will be made of the handler as required. The function signature of + * the handler must be: + * @code void handler( + * const boost::system::error_code& error, // Result of operation. + * std::size_t bytes_transferred // Number of bytes written. + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. On + * immediate completion, invocation of the handler will be performed in a + * manner equivalent to using boost::asio::post(). + * + * @note The write operation may not transmit all of the data to the peer. + * Consider using the @ref async_write function if you need to ensure that all + * data is written before the asynchronous operation completes. + * + * @par Example + * To write a single data buffer use the @ref buffer function as follows: + * @code + * socket.async_write_some(boost::asio::buffer(data, size), handler); + * @endcode + * See the @ref buffer documentation for information on writing multiple + * buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ + template + BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler, + void (boost::system::error_code, std::size_t, std::uint32_t, std::uint32_t)) + async_write_some(const ConstBufferSequence& buffers, + BOOST_ASIO_MOVE_ARG(WriteHandler) handler) + { + return async_initiate( + initiate_async_send(), handler, this, + buffers, socket_base::message_flags(0)); + } + + /// Read some data from the socket. + /** + * This function is used to read data from the stream socket. The function + * call will block until one or more bytes of data has been read successfully, + * or until an error occurs. + * + * @param buffers One or more buffers into which the data will be read. + * + * @returns The number of bytes read. + * + * @throws boost::system::system_error Thrown on failure. An error code of + * boost::asio::error::eof indicates that the connection was closed by the + * peer. + * + * @note The read_some operation may not read all of the requested number of + * bytes. Consider using the @ref read function if you need to ensure that + * the requested amount of data is read before the blocking operation + * completes. + * + * @par Example + * To read into a single data buffer use the @ref buffer function as follows: + * @code + * socket.read_some(boost::asio::buffer(data, size)); + * @endcode + * See the @ref buffer documentation for information on reading into multiple + * buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ + template + std::size_t read_some(const MutableBufferSequence& buffers) + { + boost::system::error_code ec; + std::size_t s = this->impl_.get_service().receive( + this->impl_.get_implementation(), buffers, 0, ec); + boost::asio::detail::throw_error(ec, "read_some"); + return s; + } + + /// Read some data from the socket. + /** + * This function is used to read data from the stream socket. The function + * call will block until one or more bytes of data has been read successfully, + * or until an error occurs. + * + * @param buffers One or more buffers into which the data will be read. + * + * @param ec Set to indicate what error occurred, if any. + * + * @returns The number of bytes read. Returns 0 if an error occurred. + * + * @note The read_some operation may not read all of the requested number of + * bytes. Consider using the @ref read function if you need to ensure that + * the requested amount of data is read before the blocking operation + * completes. + */ + template + std::size_t read_some(const MutableBufferSequence& buffers, + boost::system::error_code& ec) + { + return this->impl_.get_service().receive( + this->impl_.get_implementation(), buffers, 0, ec); + } + + /// Start an asynchronous read. + /** + * This function is used to asynchronously read data from the stream socket. + * The function call always returns immediately. + * + * @param buffers One or more buffers into which the data will be read. + * Although the buffers object may be copied as necessary, ownership of the + * underlying memory blocks is retained by the caller, which must guarantee + * that they remain valid until the handler is called. + * + * @param handler The handler to be called when the read operation completes. + * Copies will be made of the handler as required. The function signature of + * the handler must be: + * @code void handler( + * const boost::system::error_code& error, // Result of operation. + * std::size_t bytes_transferred // Number of bytes read. + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. On + * immediate completion, invocation of the handler will be performed in a + * manner equivalent to using boost::asio::post(). + * + * @note The read operation may not read all of the requested number of bytes. + * Consider using the @ref async_read function if you need to ensure that the + * requested amount of data is read before the asynchronous operation + * completes. + * + * @par Example + * To read into a single data buffer use the @ref buffer function as follows: + * @code + * socket.async_read_some(boost::asio::buffer(data, size), handler); + * @endcode + * See the @ref buffer documentation for information on reading into multiple + * buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ + template + BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler, + void (boost::system::error_code, std::size_t, std::uint32_t, std::uint32_t)) + async_read_some(const MutableBufferSequence& buffers, + BOOST_ASIO_MOVE_ARG(ReadHandler) handler) + { + return async_initiate( + initiate_async_receive(), handler, this, + buffers, socket_base::message_flags(0)); + } + +private: + struct initiate_async_send + { + template + void operator()(BOOST_ASIO_MOVE_ARG(WriteHandler) handler, + basic_stream_socket_ext* self, const ConstBufferSequence& buffers, + socket_base::message_flags flags) const + { + // If you get an error on the following line it means that your handler + // does not meet the documented type requirements for a WriteHandler. + BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check; + + detail::non_const_lvalue handler2(handler); + self->impl_.get_service().async_send( + self->impl_.get_implementation(), buffers, flags, + handler2.value, self->impl_.get_executor()); + } + }; + + struct initiate_async_receive + { + template + void operator()(BOOST_ASIO_MOVE_ARG(ReadHandler) handler, + basic_stream_socket_ext* self, const MutableBufferSequence& buffers, + socket_base::message_flags flags) const + { + // If you get an error on the following line it means that your handler + // does not meet the documented type requirements for a ReadHandler. + BOOST_ASIO_READ_HANDLER_CHECK_EXT_LOCAL(ReadHandler, handler) type_check; + + detail::non_const_lvalue handler2(handler); + self->impl_.get_service().async_receive( + self->impl_.get_implementation(), buffers, flags, + handler2.value, self->impl_.get_executor()); + } + }; +}; + +} // namespace asio +} // namespace boost + +#include + +#endif // BOOST_ASIO_BASIC_STREAM_SOCKET_EXT_HPP diff --git a/implementation/helper/1.76/boost/asio/detail/handler_type_requirements_ext.hpp b/implementation/helper/1.76/boost/asio/detail/handler_type_requirements_ext.hpp new file mode 100644 index 0000000..67fe6bd --- /dev/null +++ b/implementation/helper/1.76/boost/asio/detail/handler_type_requirements_ext.hpp @@ -0,0 +1,586 @@ +// +// detail/handler_type_requirements_ext.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2016-2019 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_boost or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_HANDLER_TYPE_REQUIREMENTS_EXT_HPP +#define BOOST_ASIO_DETAIL_HANDLER_TYPE_REQUIREMENTS_EXT_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +// Older versions of gcc have difficulty compiling the sizeof expressions where +// we test the handler type requirements. We'll disable checking of handler type +// requirements for those compilers, but otherwise enable it by default. +#if !defined(BOOST_ASIO_DISABLE_HANDLER_TYPE_REQUIREMENTS) +# if !defined(__GNUC__) || (__GNUC__ >= 4) +# define BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS 1 +# endif // !defined(__GNUC__) || (__GNUC__ >= 4) +#endif // !defined(BOOST_ASIO_DISABLE_HANDLER_TYPE_REQUIREMENTS) + +// With C++0x we can use a combination of enhanced SFINAE and static_assert to +// generate better template error messages. As this technique is not yet widely +// portable, we'll only enable it for tested compilers. +#if !defined(BOOST_ASIO_DISABLE_HANDLER_TYPE_REQUIREMENTS_ASSERT) +# if defined(__GNUC__) +# if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 5)) || (__GNUC__ > 4) +# if defined(__GXX_EXPERIMENTAL_CXX0X__) +# define BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS_ASSERT 1 +# endif // defined(__GXX_EXPERIMENTAL_CXX0X__) +# endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 5)) || (__GNUC__ > 4) +# endif // defined(__GNUC__) +# if defined(BOOST_ASIO_MSVC) +# if (_MSC_VER >= 1600) +# define BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS_ASSERT 1 +# endif // (_MSC_VER >= 1600) +# endif // defined(BOOST_ASIO_MSVC) +# if defined(__clang__) +# if __has_feature(__cxx_static_assert__) +# define BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS_ASSERT 1 +# endif // __has_feature(cxx_static_assert) +# endif // defined(__clang__) +#endif // !defined(BOOST_ASIO_DISABLE_HANDLER_TYPE_REQUIREMENTS) + +#if defined(BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS) +# include +#endif // defined(BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS) + +namespace boost { +namespace asio { +namespace detail { + +#if defined(BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS) + +# if defined(BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS_ASSERT) + +template +auto zero_arg_copyable_handler_test(Handler h, void*) + -> decltype( + sizeof(Handler(static_cast(h))), + ((h)()), + char(0)); + +template +char (&zero_arg_copyable_handler_test(Handler, ...))[2]; + +template +auto one_arg_handler_test(Handler h, Arg1* a1) + -> decltype( + sizeof(Handler(BOOST_ASIO_MOVE_CAST(Handler)(h))), + ((h)(*a1)), + char(0)); + +template +char (&one_arg_handler_test(Handler h, ...))[2]; + +template +auto two_arg_handler_test(Handler h, Arg1* a1, Arg2* a2) + -> decltype( + sizeof(Handler(BOOST_ASIO_MOVE_CAST(Handler)(h))), + ((h)(*a1, *a2)), + char(0)); + +template +char (&two_arg_handler_test(Handler, ...))[2]; + +template +auto two_arg_move_handler_test(Handler h, Arg1* a1, Arg2* a2) + -> decltype( + sizeof(Handler(BOOST_ASIO_MOVE_CAST(Handler)(h))), + ((h)(*a1, BOOST_ASIO_MOVE_CAST(Arg2)(*a2))), + char(0)); + +template +char (&two_arg_move_handler_test(Handler, ...))[2]; + +template +auto three_arg_handler_test(Handler h, Arg1* a1, Arg2* a2, Arg3* a3) + -> decltype( + sizeof(Handler(BOOST_ASIO_MOVE_CAST(Handler)(h))), + ((h)(*a1, *a2, *a3)), + char(0)); + +template +char (&three_arg_handler_test(Handler, ...))[2]; + +template +auto three_arg_move_handler_test(Handler h, Arg1* a1, Arg2* a2, Arg3 *a3) + -> decltype( + sizeof(Handler(BOOST_ASIO_MOVE_CAST(Handler)(h))), + ((h)(*a1, BOOST_ASIO_MOVE_CAST(Arg2)(*a2), BOOST_ASIO_MOVE_CAST(Arg3)(*a3))), + char(0)); + +template +char (&three_arg_move_handler_test(Handler, ...))[2]; + +# define BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT(expr, msg) \ + static_assert(expr, msg); + +# else // defined(BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS_ASSERT) + +# define BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT(expr, msg) + +# endif // defined(BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS_ASSERT) + +template T& lvref(); +template T& lvref(T); +template const T& clvref(); +template const T& clvref(T); +#if defined(BOOST_ASIO_HAS_MOVE) +template T rvref(); +template T rvref(T); +#else // defined(BOOST_ASIO_HAS_MOVE) +template const T& rvref(); +template const T& rvref(T); +#endif // defined(BOOST_ASIO_HAS_MOVE) +template char argbyv(T); + +#if 0 +template +struct handler_type_requirements +{ +}; +#endif + +#define BOOST_ASIO_LEGACY_COMPLETION_HANDLER_CHECK( \ + handler_type, handler) \ + \ + typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \ + void()) asio_true_handler_type; \ + \ + BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \ + sizeof(boost::asio::detail::zero_arg_copyable_handler_test( \ + boost::asio::detail::clvref< \ + asio_true_handler_type>(), 0)) == 1, \ + "CompletionHandler type requirements not met") \ + \ + typedef boost::asio::detail::handler_type_requirements< \ + sizeof( \ + boost::asio::detail::argbyv( \ + boost::asio::detail::clvref< \ + asio_true_handler_type>())) + \ + sizeof( \ + boost::asio::detail::lvref< \ + asio_true_handler_type>()(), \ + char(0))> BOOST_ASIO_UNUSED_TYPEDEF + +#define BOOST_ASIO_READ_HANDLER_CHECK_EXT( \ + handler_type, handler) \ + \ + typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \ + void(boost::system::error_code, std::size_t, \ + boost::asio::ip::address)) \ + asio_true_handler_type; \ + \ + BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \ + sizeof(boost::asio::detail::three_arg_handler_test( \ + boost::asio::detail::rvref< \ + asio_true_handler_type>(), \ + static_cast(0), \ + static_cast(0), \ + static_cast(0))) == 1, \ + "ReadHandler type requirements not met") \ + \ + typedef boost::asio::detail::handler_type_requirements< \ + sizeof( \ + boost::asio::detail::argbyv( \ + boost::asio::detail::rvref< \ + asio_true_handler_type>())) + \ + sizeof( \ + boost::asio::detail::lvref< \ + asio_true_handler_type>()( \ + boost::asio::detail::lvref(), \ + boost::asio::detail::lvref(), \ + boost::asio::detail::lvref()), \ + char(0))> BOOST_ASIO_UNUSED_TYPEDEF + +#define BOOST_ASIO_WRITE_HANDLER_CHECK( \ + handler_type, handler) \ + \ + typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \ + void(boost::system::error_code, std::size_t)) \ + asio_true_handler_type; \ + \ + BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \ + sizeof(boost::asio::detail::two_arg_handler_test( \ + boost::asio::detail::rvref< \ + asio_true_handler_type>(), \ + static_cast(0), \ + static_cast(0))) == 1, \ + "WriteHandler type requirements not met") \ + \ + typedef boost::asio::detail::handler_type_requirements< \ + sizeof( \ + boost::asio::detail::argbyv( \ + boost::asio::detail::rvref< \ + asio_true_handler_type>())) + \ + sizeof( \ + boost::asio::detail::lvref< \ + asio_true_handler_type>()( \ + boost::asio::detail::lvref(), \ + boost::asio::detail::lvref()), \ + char(0))> BOOST_ASIO_UNUSED_TYPEDEF + +#if 0 +#define BOOST_ASIO_ACCEPT_HANDLER_CHECK( \ + handler_type, handler) \ + \ + typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \ + void(boost::system::error_code)) \ + asio_true_handler_type; \ + \ + BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \ + sizeof(boost::asio::detail::one_arg_handler_test( \ + boost::asio::detail::rvref< \ + asio_true_handler_type>(), \ + static_cast(0))) == 1, \ + "AcceptHandler type requirements not met") \ + \ + typedef boost::asio::detail::handler_type_requirements< \ + sizeof( \ + boost::asio::detail::argbyv( \ + boost::asio::detail::rvref< \ + asio_true_handler_type>())) + \ + sizeof( \ + boost::asio::detail::lvref< \ + asio_true_handler_type>()( \ + boost::asio::detail::lvref()), \ + char(0))> BOOST_ASIO_UNUSED_TYPEDEF + +#define BOOST_ASIO_MOVE_ACCEPT_HANDLER_CHECK( \ + handler_type, handler, socket_type) \ + \ + typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \ + void(boost::system::error_code, socket_type)) \ + asio_true_handler_type; \ + \ + BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \ + sizeof(boost::asio::detail::two_arg_move_handler_test( \ + boost::asio::detail::rvref< \ + asio_true_handler_type>(), \ + static_cast(0), \ + static_cast(0))) == 1, \ + "MoveAcceptHandler type requirements not met") \ + \ + typedef boost::asio::detail::handler_type_requirements< \ + sizeof( \ + boost::asio::detail::argbyv( \ + boost::asio::detail::rvref< \ + asio_true_handler_type>())) + \ + sizeof( \ + boost::asio::detail::lvref< \ + asio_true_handler_type>()( \ + boost::asio::detail::lvref(), \ + boost::asio::detail::rvref()), \ + char(0))> BOOST_ASIO_UNUSED_TYPEDEF +#endif + +#define BOOST_ASIO_CONNECT_HANDLER_CHECK( \ + handler_type, handler) \ + \ + typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \ + void(boost::system::error_code)) \ + asio_true_handler_type; \ + \ + BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \ + sizeof(boost::asio::detail::one_arg_handler_test( \ + boost::asio::detail::rvref< \ + asio_true_handler_type>(), \ + static_cast(0))) == 1, \ + "ConnectHandler type requirements not met") \ + \ + typedef boost::asio::detail::handler_type_requirements< \ + sizeof( \ + boost::asio::detail::argbyv( \ + boost::asio::detail::rvref< \ + asio_true_handler_type>())) + \ + sizeof( \ + boost::asio::detail::lvref< \ + asio_true_handler_type>()( \ + boost::asio::detail::lvref()), \ + char(0))> BOOST_ASIO_UNUSED_TYPEDEF + +#define BOOST_ASIO_RANGE_CONNECT_HANDLER_CHECK( \ + handler_type, handler, endpoint_type) \ + \ + typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \ + void(boost::system::error_code, endpoint_type)) \ + asio_true_handler_type; \ + \ + BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \ + sizeof(boost::asio::detail::two_arg_handler_test( \ + boost::asio::detail::rvref< \ + asio_true_handler_type>(), \ + static_cast(0), \ + static_cast(0))) == 1, \ + "RangeConnectHandler type requirements not met") \ + \ + typedef boost::asio::detail::handler_type_requirements< \ + sizeof( \ + boost::asio::detail::argbyv( \ + boost::asio::detail::rvref< \ + asio_true_handler_type>())) + \ + sizeof( \ + boost::asio::detail::lvref< \ + asio_true_handler_type>()( \ + boost::asio::detail::lvref(), \ + boost::asio::detail::lvref()), \ + char(0))> BOOST_ASIO_UNUSED_TYPEDEF + +#define BOOST_ASIO_ITERATOR_CONNECT_HANDLER_CHECK( \ + handler_type, handler, iter_type) \ + \ + typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \ + void(boost::system::error_code, iter_type)) \ + asio_true_handler_type; \ + \ + BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \ + sizeof(boost::asio::detail::two_arg_handler_test( \ + boost::asio::detail::rvref< \ + asio_true_handler_type>(), \ + static_cast(0), \ + static_cast(0))) == 1, \ + "IteratorConnectHandler type requirements not met") \ + \ + typedef boost::asio::detail::handler_type_requirements< \ + sizeof( \ + boost::asio::detail::argbyv( \ + boost::asio::detail::rvref< \ + asio_true_handler_type>())) + \ + sizeof( \ + boost::asio::detail::lvref< \ + asio_true_handler_type>()( \ + boost::asio::detail::lvref(), \ + boost::asio::detail::lvref()), \ + char(0))> BOOST_ASIO_UNUSED_TYPEDEF + +#define BOOST_ASIO_RESOLVE_HANDLER_CHECK( \ + handler_type, handler, range_type) \ + \ + typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \ + void(boost::system::error_code, range_type)) \ + asio_true_handler_type; \ + \ + BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \ + sizeof(boost::asio::detail::two_arg_handler_test( \ + boost::asio::detail::rvref< \ + asio_true_handler_type>(), \ + static_cast(0), \ + static_cast(0))) == 1, \ + "ResolveHandler type requirements not met") \ + \ + typedef boost::asio::detail::handler_type_requirements< \ + sizeof( \ + boost::asio::detail::argbyv( \ + boost::asio::detail::rvref< \ + asio_true_handler_type>())) + \ + sizeof( \ + boost::asio::detail::lvref< \ + asio_true_handler_type>()( \ + boost::asio::detail::lvref(), \ + boost::asio::detail::lvref()), \ + char(0))> BOOST_ASIO_UNUSED_TYPEDEF + +#define BOOST_ASIO_WAIT_HANDLER_CHECK( \ + handler_type, handler) \ + \ + typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \ + void(boost::system::error_code)) \ + asio_true_handler_type; \ + \ + BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \ + sizeof(boost::asio::detail::one_arg_handler_test( \ + boost::asio::detail::rvref< \ + asio_true_handler_type>(), \ + static_cast(0))) == 1, \ + "WaitHandler type requirements not met") \ + \ + typedef boost::asio::detail::handler_type_requirements< \ + sizeof( \ + boost::asio::detail::argbyv( \ + boost::asio::detail::rvref< \ + asio_true_handler_type>())) + \ + sizeof( \ + boost::asio::detail::lvref< \ + asio_true_handler_type>()( \ + boost::asio::detail::lvref()), \ + char(0))> BOOST_ASIO_UNUSED_TYPEDEF + +#define BOOST_ASIO_SIGNAL_HANDLER_CHECK( \ + handler_type, handler) \ + \ + typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \ + void(boost::system::error_code, int)) \ + asio_true_handler_type; \ + \ + BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \ + sizeof(boost::asio::detail::two_arg_handler_test( \ + boost::asio::detail::rvref< \ + asio_true_handler_type>(), \ + static_cast(0), \ + static_cast(0))) == 1, \ + "SignalHandler type requirements not met") \ + \ + typedef boost::asio::detail::handler_type_requirements< \ + sizeof( \ + boost::asio::detail::argbyv( \ + boost::asio::detail::rvref< \ + asio_true_handler_type>())) + \ + sizeof( \ + boost::asio::detail::lvref< \ + asio_true_handler_type>()( \ + boost::asio::detail::lvref(), \ + boost::asio::detail::lvref()), \ + char(0))> BOOST_ASIO_UNUSED_TYPEDEF + +#define BOOST_ASIO_HANDSHAKE_HANDLER_CHECK( \ + handler_type, handler) \ + \ + typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \ + void(boost::system::error_code)) \ + asio_true_handler_type; \ + \ + BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \ + sizeof(boost::asio::detail::one_arg_handler_test( \ + boost::asio::detail::rvref< \ + asio_true_handler_type>(), \ + static_cast(0))) == 1, \ + "HandshakeHandler type requirements not met") \ + \ + typedef boost::asio::detail::handler_type_requirements< \ + sizeof( \ + boost::asio::detail::argbyv( \ + boost::asio::detail::rvref< \ + asio_true_handler_type>())) + \ + sizeof( \ + boost::asio::detail::lvref< \ + asio_true_handler_type>()( \ + boost::asio::detail::lvref()), \ + char(0))> BOOST_ASIO_UNUSED_TYPEDEF + +#define BOOST_ASIO_BUFFERED_HANDSHAKE_HANDLER_CHECK( \ + handler_type, handler) \ + \ + typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \ + void(boost::system::error_code, std::size_t)) \ + asio_true_handler_type; \ + \ + BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \ + sizeof(boost::asio::detail::two_arg_handler_test( \ + boost::asio::detail::rvref< \ + asio_true_handler_type>(), \ + static_cast(0), \ + static_cast(0))) == 1, \ + "BufferedHandshakeHandler type requirements not met") \ + \ + typedef boost::asio::detail::handler_type_requirements< \ + sizeof( \ + boost::asio::detail::argbyv( \ + boost::asio::detail::rvref< \ + asio_true_handler_type>())) + \ + sizeof( \ + boost::asio::detail::lvref< \ + asio_true_handler_type>()( \ + boost::asio::detail::lvref(), \ + boost::asio::detail::lvref()), \ + char(0))> BOOST_ASIO_UNUSED_TYPEDEF + +#define BOOST_ASIO_SHUTDOWN_HANDLER_CHECK( \ + handler_type, handler) \ + \ + typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \ + void(boost::system::error_code)) \ + asio_true_handler_type; \ + \ + BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \ + sizeof(boost::asio::detail::one_arg_handler_test( \ + boost::asio::detail::rvref< \ + asio_true_handler_type>(), \ + static_cast(0))) == 1, \ + "ShutdownHandler type requirements not met") \ + \ + typedef boost::asio::detail::handler_type_requirements< \ + sizeof( \ + boost::asio::detail::argbyv( \ + boost::asio::detail::rvref< \ + asio_true_handler_type>())) + \ + sizeof( \ + boost::asio::detail::lvref< \ + asio_true_handler_type>()( \ + boost::asio::detail::lvref()), \ + char(0))> BOOST_ASIO_UNUSED_TYPEDEF + +#else // !defined(BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS) + +#define BOOST_ASIO_LEGACY_COMPLETION_HANDLER_CHECK( \ + handler_type, handler) \ + typedef int BOOST_ASIO_UNUSED_TYPEDEF + +#define BOOST_ASIO_READ_HANDLER_CHECK( \ + handler_type, handler) \ + typedef int BOOST_ASIO_UNUSED_TYPEDEF + +#define BOOST_ASIO_WRITE_HANDLER_CHECK( \ + handler_type, handler) \ + typedef int BOOST_ASIO_UNUSED_TYPEDEF + +#define BOOST_ASIO_ACCEPT_HANDLER_CHECK( \ + handler_type, handler) \ + typedef int BOOST_ASIO_UNUSED_TYPEDEF + +#define BOOST_ASIO_MOVE_ACCEPT_HANDLER_CHECK( \ + handler_type, handler, socket_type) \ + typedef int BOOST_ASIO_UNUSED_TYPEDEF + +#define BOOST_ASIO_CONNECT_HANDLER_CHECK( \ + handler_type, handler) \ + typedef int BOOST_ASIO_UNUSED_TYPEDEF + +#define BOOST_ASIO_RANGE_CONNECT_HANDLER_CHECK( \ + handler_type, handler, iter_type) \ + typedef int BOOST_ASIO_UNUSED_TYPEDEF + +#define BOOST_ASIO_ITERATOR_CONNECT_HANDLER_CHECK( \ + handler_type, handler, iter_type) \ + typedef int BOOST_ASIO_UNUSED_TYPEDEF + +#define BOOST_ASIO_RESOLVE_HANDLER_CHECK( \ + handler_type, handler, iter_type) \ + typedef int BOOST_ASIO_UNUSED_TYPEDEF + +#define BOOST_ASIO_WAIT_HANDLER_CHECK( \ + handler_type, handler) \ + typedef int BOOST_ASIO_UNUSED_TYPEDEF + +#define BOOST_ASIO_SIGNAL_HANDLER_CHECK( \ + handler_type, handler) \ + typedef int BOOST_ASIO_UNUSED_TYPEDEF + +#define BOOST_ASIO_HANDSHAKE_HANDLER_CHECK( \ + handler_type, handler) \ + typedef int BOOST_ASIO_UNUSED_TYPEDEF + +#define BOOST_ASIO_BUFFERED_HANDSHAKE_HANDLER_CHECK( \ + handler_type, handler) \ + typedef int BOOST_ASIO_UNUSED_TYPEDEF + +#define BOOST_ASIO_SHUTDOWN_HANDLER_CHECK( \ + handler_type, handler) \ + typedef int BOOST_ASIO_UNUSED_TYPEDEF + +#endif // !defined(BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS) + +} // namespace detail +} // namespace asio +} // namespace boost + +#endif // BOOST_ASIO_DETAIL_HANDLER_TYPE_REQUIREMENTS_EXT_HPP diff --git a/implementation/helper/1.76/boost/asio/detail/handler_type_requirements_ext_local.hpp b/implementation/helper/1.76/boost/asio/detail/handler_type_requirements_ext_local.hpp new file mode 100644 index 0000000..65640ad --- /dev/null +++ b/implementation/helper/1.76/boost/asio/detail/handler_type_requirements_ext_local.hpp @@ -0,0 +1,588 @@ +// +// detail/handler_type_requirements_ext_local.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2016-2019 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_boost or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_HANDLER_TYPE_REQUIREMENTS_EXT_LOCAL_HPP +#define BOOST_ASIO_DETAIL_HANDLER_TYPE_REQUIREMENTS_EXT_LOCAL_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +// Older versions of gcc have difficulty compiling the sizeof expressions where +// we test the handler type requirements. We'll disable checking of handler type +// requirements for those compilers, but otherwise enable it by default. +#if !defined(BOOST_ASIO_DISABLE_HANDLER_TYPE_REQUIREMENTS) +# if !defined(__GNUC__) || (__GNUC__ >= 4) +# define BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS 1 +# endif // !defined(__GNUC__) || (__GNUC__ >= 4) +#endif // !defined(BOOST_ASIO_DISABLE_HANDLER_TYPE_REQUIREMENTS) + +// With C++0x we can use a combination of enhanced SFINAE and static_assert to +// generate better template error messages. As this technique is not yet widely +// portable, we'll only enable it for tested compilers. +#if !defined(BOOST_ASIO_DISABLE_HANDLER_TYPE_REQUIREMENTS_ASSERT) +# if defined(__GNUC__) +# if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 5)) || (__GNUC__ > 4) +# if defined(__GXX_EXPERIMENTAL_CXX0X__) +# define BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS_ASSERT 1 +# endif // defined(__GXX_EXPERIMENTAL_CXX0X__) +# endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 5)) || (__GNUC__ > 4) +# endif // defined(__GNUC__) +# if defined(BOOST_ASIO_MSVC) +# if (_MSC_VER >= 1600) +# define BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS_ASSERT 1 +# endif // (_MSC_VER >= 1600) +# endif // defined(BOOST_ASIO_MSVC) +# if defined(__clang__) +# if __has_feature(__cxx_static_assert__) +# define BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS_ASSERT 1 +# endif // __has_feature(cxx_static_assert) +# endif // defined(__clang__) +#endif // !defined(BOOST_ASIO_DISABLE_HANDLER_TYPE_REQUIREMENTS) + +#if defined(BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS) +# include +#endif // defined(BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS) + +namespace boost { +namespace asio { +namespace detail { + +#if defined(BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS) + +# if defined(BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS_ASSERT) + +template +auto zero_arg_copyable_handler_test(Handler h, void*) + -> decltype( + sizeof(Handler(static_cast(h))), + ((h)()), + char(0)); + +template +char (&zero_arg_copyable_handler_test(Handler, ...))[2]; + +template +auto one_arg_handler_test(Handler h, Arg1* a1) + -> decltype( + sizeof(Handler(BOOST_ASIO_MOVE_CAST(Handler)(h))), + ((h)(*a1)), + char(0)); + +template +char (&one_arg_handler_test(Handler h, ...))[2]; + +template +auto two_arg_handler_test(Handler h, Arg1* a1, Arg2* a2) + -> decltype( + sizeof(Handler(BOOST_ASIO_MOVE_CAST(Handler)(h))), + ((h)(*a1, *a2)), + char(0)); + +template +char (&two_arg_handler_test(Handler, ...))[2]; + +template +auto two_arg_move_handler_test(Handler h, Arg1* a1, Arg2* a2) + -> decltype( + sizeof(Handler(BOOST_ASIO_MOVE_CAST(Handler)(h))), + ((h)(*a1, BOOST_ASIO_MOVE_CAST(Arg2)(*a2))), + char(0)); + +template +char (&two_arg_move_handler_test(Handler, ...))[2]; + +template +auto four_arg_handler_test(Handler h, Arg1* a1, Arg2* a2, Arg3* a3, Arg4* a4) + -> decltype( + sizeof(Handler(BOOST_ASIO_MOVE_CAST(Handler)(h))), + ((h)(*a1, *a2, *a3, *a4)), + char(0)); + +template +char (&four_arg_handler_test(Handler, ...))[2]; + +template +auto four_arg_move_handler_test(Handler h, Arg1* a1, Arg2* a2, Arg3* a3, Arg4* a4) + -> decltype( + sizeof(Handler(BOOST_ASIO_MOVE_CAST(Handler)(h))), + ((h)(*a1, BOOST_ASIO_MOVE_CAST(Arg2)(*a2), BOOST_ASIO_MOVE_CAST(Arg3)(*a3), BOOST_ASIO_MOVE_CAST(Arg4)(*a4))), + char(0)); + +template +char (&four_arg_move_handler_test(Handler, ...))[2]; + +# define BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT(expr, msg) \ + static_assert(expr, msg); + +# else // defined(BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS_ASSERT) + +# define BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT(expr, msg) + +# endif // defined(BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS_ASSERT) + +template T& lvref(); +template T& lvref(T); +template const T& clvref(); +template const T& clvref(T); +#if defined(BOOST_ASIO_HAS_MOVE) +template T rvref(); +template T rvref(T); +#else // defined(BOOST_ASIO_HAS_MOVE) +template const T& rvref(); +template const T& rvref(T); +#endif // defined(BOOST_ASIO_HAS_MOVE) +template char argbyv(T); + +#if 0 +template +struct handler_type_requirements +{ +}; +#endif + +#define BOOST_ASIO_LEGACY_COMPLETION_HANDLER_CHECK( \ + handler_type, handler) \ + \ + typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \ + void()) asio_true_handler_type; \ + \ + BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \ + sizeof(boost::asio::detail::zero_arg_copyable_handler_test( \ + boost::asio::detail::clvref< \ + asio_true_handler_type>(), 0)) == 1, \ + "CompletionHandler type requirements not met") \ + \ + typedef boost::asio::detail::handler_type_requirements< \ + sizeof( \ + boost::asio::detail::argbyv( \ + boost::asio::detail::clvref< \ + asio_true_handler_type>())) + \ + sizeof( \ + boost::asio::detail::lvref< \ + asio_true_handler_type>()(), \ + char(0))> BOOST_ASIO_UNUSED_TYPEDEF + +#define BOOST_ASIO_READ_HANDLER_CHECK_EXT_LOCAL( \ + handler_type, handler) \ + \ + typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \ + void(boost::system::error_code, std::size_t, \ + std::uint32_t, std::uint32_t)) \ + asio_true_handler_type; \ + \ + BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \ + sizeof(boost::asio::detail::four_arg_handler_test( \ + boost::asio::detail::clvref< \ + asio_true_handler_type>(), \ + static_cast(0), \ + static_cast(0), \ + static_cast(0), \ + static_cast(0))) == 1, \ + "ReadHandler type requirements not met") \ + \ + typedef boost::asio::detail::handler_type_requirements< \ + sizeof( \ + boost::asio::detail::argbyv( \ + boost::asio::detail::clvref< \ + asio_true_handler_type>())) + \ + sizeof( \ + boost::asio::detail::lvref< \ + asio_true_handler_type>()( \ + boost::asio::detail::lvref(), \ + boost::asio::detail::lvref(), \ + boost::asio::detail::lvref(), \ + boost::asio::detail::lvref()), \ + char(0))> BOOST_ASIO_UNUSED_TYPEDEF + +#define BOOST_ASIO_WRITE_HANDLER_CHECK( \ + handler_type, handler) \ + \ + typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \ + void(boost::system::error_code, std::size_t)) \ + asio_true_handler_type; \ + \ + BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \ + sizeof(boost::asio::detail::two_arg_handler_test( \ + boost::asio::detail::rvref< \ + asio_true_handler_type>(), \ + static_cast(0), \ + static_cast(0))) == 1, \ + "WriteHandler type requirements not met") \ + \ + typedef boost::asio::detail::handler_type_requirements< \ + sizeof( \ + boost::asio::detail::argbyv( \ + boost::asio::detail::rvref< \ + asio_true_handler_type>())) + \ + sizeof( \ + boost::asio::detail::lvref< \ + asio_true_handler_type>()( \ + boost::asio::detail::lvref(), \ + boost::asio::detail::lvref()), \ + char(0))> BOOST_ASIO_UNUSED_TYPEDEF + +#if 0 +#define BOOST_ASIO_ACCEPT_HANDLER_CHECK( \ + handler_type, handler) \ + \ + typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \ + void(boost::system::error_code)) \ + asio_true_handler_type; \ + \ + BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \ + sizeof(boost::asio::detail::one_arg_handler_test( \ + boost::asio::detail::rvref< \ + asio_true_handler_type>(), \ + static_cast(0))) == 1, \ + "AcceptHandler type requirements not met") \ + \ + typedef boost::asio::detail::handler_type_requirements< \ + sizeof( \ + boost::asio::detail::argbyv( \ + boost::asio::detail::rvref< \ + asio_true_handler_type>())) + \ + sizeof( \ + boost::asio::detail::lvref< \ + asio_true_handler_type>()( \ + boost::asio::detail::lvref()), \ + char(0))> BOOST_ASIO_UNUSED_TYPEDEF + +#define BOOST_ASIO_MOVE_ACCEPT_HANDLER_CHECK( \ + handler_type, handler, socket_type) \ + \ + typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \ + void(boost::system::error_code, socket_type)) \ + asio_true_handler_type; \ + \ + BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \ + sizeof(boost::asio::detail::two_arg_move_handler_test( \ + boost::asio::detail::rvref< \ + asio_true_handler_type>(), \ + static_cast(0), \ + static_cast(0))) == 1, \ + "MoveAcceptHandler type requirements not met") \ + \ + typedef boost::asio::detail::handler_type_requirements< \ + sizeof( \ + boost::asio::detail::argbyv( \ + boost::asio::detail::rvref< \ + asio_true_handler_type>())) + \ + sizeof( \ + boost::asio::detail::lvref< \ + asio_true_handler_type>()( \ + boost::asio::detail::lvref(), \ + boost::asio::detail::rvref()), \ + char(0))> BOOST_ASIO_UNUSED_TYPEDEF +#endif + +#define BOOST_ASIO_CONNECT_HANDLER_CHECK( \ + handler_type, handler) \ + \ + typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \ + void(boost::system::error_code)) \ + asio_true_handler_type; \ + \ + BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \ + sizeof(boost::asio::detail::one_arg_handler_test( \ + boost::asio::detail::rvref< \ + asio_true_handler_type>(), \ + static_cast(0))) == 1, \ + "ConnectHandler type requirements not met") \ + \ + typedef boost::asio::detail::handler_type_requirements< \ + sizeof( \ + boost::asio::detail::argbyv( \ + boost::asio::detail::rvref< \ + asio_true_handler_type>())) + \ + sizeof( \ + boost::asio::detail::lvref< \ + asio_true_handler_type>()( \ + boost::asio::detail::lvref()), \ + char(0))> BOOST_ASIO_UNUSED_TYPEDEF + +#define BOOST_ASIO_RANGE_CONNECT_HANDLER_CHECK( \ + handler_type, handler, endpoint_type) \ + \ + typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \ + void(boost::system::error_code, endpoint_type)) \ + asio_true_handler_type; \ + \ + BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \ + sizeof(boost::asio::detail::two_arg_handler_test( \ + boost::asio::detail::rvref< \ + asio_true_handler_type>(), \ + static_cast(0), \ + static_cast(0))) == 1, \ + "RangeConnectHandler type requirements not met") \ + \ + typedef boost::asio::detail::handler_type_requirements< \ + sizeof( \ + boost::asio::detail::argbyv( \ + boost::asio::detail::rvref< \ + asio_true_handler_type>())) + \ + sizeof( \ + boost::asio::detail::lvref< \ + asio_true_handler_type>()( \ + boost::asio::detail::lvref(), \ + boost::asio::detail::lvref()), \ + char(0))> BOOST_ASIO_UNUSED_TYPEDEF + +#define BOOST_ASIO_ITERATOR_CONNECT_HANDLER_CHECK( \ + handler_type, handler, iter_type) \ + \ + typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \ + void(boost::system::error_code, iter_type)) \ + asio_true_handler_type; \ + \ + BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \ + sizeof(boost::asio::detail::two_arg_handler_test( \ + boost::asio::detail::rvref< \ + asio_true_handler_type>(), \ + static_cast(0), \ + static_cast(0))) == 1, \ + "IteratorConnectHandler type requirements not met") \ + \ + typedef boost::asio::detail::handler_type_requirements< \ + sizeof( \ + boost::asio::detail::argbyv( \ + boost::asio::detail::rvref< \ + asio_true_handler_type>())) + \ + sizeof( \ + boost::asio::detail::lvref< \ + asio_true_handler_type>()( \ + boost::asio::detail::lvref(), \ + boost::asio::detail::lvref()), \ + char(0))> BOOST_ASIO_UNUSED_TYPEDEF + +#define BOOST_ASIO_RESOLVE_HANDLER_CHECK( \ + handler_type, handler, range_type) \ + \ + typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \ + void(boost::system::error_code, range_type)) \ + asio_true_handler_type; \ + \ + BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \ + sizeof(boost::asio::detail::two_arg_handler_test( \ + boost::asio::detail::rvref< \ + asio_true_handler_type>(), \ + static_cast(0), \ + static_cast(0))) == 1, \ + "ResolveHandler type requirements not met") \ + \ + typedef boost::asio::detail::handler_type_requirements< \ + sizeof( \ + boost::asio::detail::argbyv( \ + boost::asio::detail::rvref< \ + asio_true_handler_type>())) + \ + sizeof( \ + boost::asio::detail::lvref< \ + asio_true_handler_type>()( \ + boost::asio::detail::lvref(), \ + boost::asio::detail::lvref()), \ + char(0))> BOOST_ASIO_UNUSED_TYPEDEF + +#define BOOST_ASIO_WAIT_HANDLER_CHECK( \ + handler_type, handler) \ + \ + typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \ + void(boost::system::error_code)) \ + asio_true_handler_type; \ + \ + BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \ + sizeof(boost::asio::detail::one_arg_handler_test( \ + boost::asio::detail::rvref< \ + asio_true_handler_type>(), \ + static_cast(0))) == 1, \ + "WaitHandler type requirements not met") \ + \ + typedef boost::asio::detail::handler_type_requirements< \ + sizeof( \ + boost::asio::detail::argbyv( \ + boost::asio::detail::rvref< \ + asio_true_handler_type>())) + \ + sizeof( \ + boost::asio::detail::lvref< \ + asio_true_handler_type>()( \ + boost::asio::detail::lvref()), \ + char(0))> BOOST_ASIO_UNUSED_TYPEDEF + +#define BOOST_ASIO_SIGNAL_HANDLER_CHECK( \ + handler_type, handler) \ + \ + typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \ + void(boost::system::error_code, int)) \ + asio_true_handler_type; \ + \ + BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \ + sizeof(boost::asio::detail::two_arg_handler_test( \ + boost::asio::detail::rvref< \ + asio_true_handler_type>(), \ + static_cast(0), \ + static_cast(0))) == 1, \ + "SignalHandler type requirements not met") \ + \ + typedef boost::asio::detail::handler_type_requirements< \ + sizeof( \ + boost::asio::detail::argbyv( \ + boost::asio::detail::rvref< \ + asio_true_handler_type>())) + \ + sizeof( \ + boost::asio::detail::lvref< \ + asio_true_handler_type>()( \ + boost::asio::detail::lvref(), \ + boost::asio::detail::lvref()), \ + char(0))> BOOST_ASIO_UNUSED_TYPEDEF + +#define BOOST_ASIO_HANDSHAKE_HANDLER_CHECK( \ + handler_type, handler) \ + \ + typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \ + void(boost::system::error_code)) \ + asio_true_handler_type; \ + \ + BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \ + sizeof(boost::asio::detail::one_arg_handler_test( \ + boost::asio::detail::rvref< \ + asio_true_handler_type>(), \ + static_cast(0))) == 1, \ + "HandshakeHandler type requirements not met") \ + \ + typedef boost::asio::detail::handler_type_requirements< \ + sizeof( \ + boost::asio::detail::argbyv( \ + boost::asio::detail::rvref< \ + asio_true_handler_type>())) + \ + sizeof( \ + boost::asio::detail::lvref< \ + asio_true_handler_type>()( \ + boost::asio::detail::lvref()), \ + char(0))> BOOST_ASIO_UNUSED_TYPEDEF + +#define BOOST_ASIO_BUFFERED_HANDSHAKE_HANDLER_CHECK( \ + handler_type, handler) \ + \ + typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \ + void(boost::system::error_code, std::size_t)) \ + asio_true_handler_type; \ + \ + BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \ + sizeof(boost::asio::detail::two_arg_handler_test( \ + boost::asio::detail::rvref< \ + asio_true_handler_type>(), \ + static_cast(0), \ + static_cast(0))) == 1, \ + "BufferedHandshakeHandler type requirements not met") \ + \ + typedef boost::asio::detail::handler_type_requirements< \ + sizeof( \ + boost::asio::detail::argbyv( \ + boost::asio::detail::rvref< \ + asio_true_handler_type>())) + \ + sizeof( \ + boost::asio::detail::lvref< \ + asio_true_handler_type>()( \ + boost::asio::detail::lvref(), \ + boost::asio::detail::lvref()), \ + char(0))> BOOST_ASIO_UNUSED_TYPEDEF + +#define BOOST_ASIO_SHUTDOWN_HANDLER_CHECK( \ + handler_type, handler) \ + \ + typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \ + void(boost::system::error_code)) \ + asio_true_handler_type; \ + \ + BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \ + sizeof(boost::asio::detail::one_arg_handler_test( \ + boost::asio::detail::rvref< \ + asio_true_handler_type>(), \ + static_cast(0))) == 1, \ + "ShutdownHandler type requirements not met") \ + \ + typedef boost::asio::detail::handler_type_requirements< \ + sizeof( \ + boost::asio::detail::argbyv( \ + boost::asio::detail::rvref< \ + asio_true_handler_type>())) + \ + sizeof( \ + boost::asio::detail::lvref< \ + asio_true_handler_type>()( \ + boost::asio::detail::lvref()), \ + char(0))> BOOST_ASIO_UNUSED_TYPEDEF + +#else // !defined(BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS) + +#define BOOST_ASIO_LEGACY_COMPLETION_HANDLER_CHECK( \ + handler_type, handler) \ + typedef int BOOST_ASIO_UNUSED_TYPEDEF + +#define BOOST_ASIO_READ_HANDLER_CHECK( \ + handler_type, handler) \ + typedef int BOOST_ASIO_UNUSED_TYPEDEF + +#define BOOST_ASIO_WRITE_HANDLER_CHECK( \ + handler_type, handler) \ + typedef int BOOST_ASIO_UNUSED_TYPEDEF + +#define BOOST_ASIO_ACCEPT_HANDLER_CHECK( \ + handler_type, handler) \ + typedef int BOOST_ASIO_UNUSED_TYPEDEF + +#define BOOST_ASIO_MOVE_ACCEPT_HANDLER_CHECK( \ + handler_type, handler, socket_type) \ + typedef int BOOST_ASIO_UNUSED_TYPEDEF + +#define BOOST_ASIO_CONNECT_HANDLER_CHECK( \ + handler_type, handler) \ + typedef int BOOST_ASIO_UNUSED_TYPEDEF + +#define BOOST_ASIO_RANGE_CONNECT_HANDLER_CHECK( \ + handler_type, handler, iter_type) \ + typedef int BOOST_ASIO_UNUSED_TYPEDEF + +#define BOOST_ASIO_ITERATOR_CONNECT_HANDLER_CHECK( \ + handler_type, handler, iter_type) \ + typedef int BOOST_ASIO_UNUSED_TYPEDEF + +#define BOOST_ASIO_RESOLVE_HANDLER_CHECK( \ + handler_type, handler, iter_type) \ + typedef int BOOST_ASIO_UNUSED_TYPEDEF + +#define BOOST_ASIO_WAIT_HANDLER_CHECK( \ + handler_type, handler) \ + typedef int BOOST_ASIO_UNUSED_TYPEDEF + +#define BOOST_ASIO_SIGNAL_HANDLER_CHECK( \ + handler_type, handler) \ + typedef int BOOST_ASIO_UNUSED_TYPEDEF + +#define BOOST_ASIO_HANDSHAKE_HANDLER_CHECK( \ + handler_type, handler) \ + typedef int BOOST_ASIO_UNUSED_TYPEDEF + +#define BOOST_ASIO_BUFFERED_HANDSHAKE_HANDLER_CHECK( \ + handler_type, handler) \ + typedef int BOOST_ASIO_UNUSED_TYPEDEF + +#define BOOST_ASIO_SHUTDOWN_HANDLER_CHECK( \ + handler_type, handler) \ + typedef int BOOST_ASIO_UNUSED_TYPEDEF + +#endif // !defined(BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS) + +} // namespace detail +} // namespace asio +} // namespace boost + +#endif // BOOST_ASIO_DETAIL_HANDLER_TYPE_REQUIREMENTS_EXT_LOCAL_HPP diff --git a/implementation/helper/1.76/boost/asio/detail/impl/reactive_socket_service_base_ext.ipp b/implementation/helper/1.76/boost/asio/detail/impl/reactive_socket_service_base_ext.ipp new file mode 100644 index 0000000..04036ad --- /dev/null +++ b/implementation/helper/1.76/boost/asio/detail/impl/reactive_socket_service_base_ext.ipp @@ -0,0 +1,302 @@ +// +// detail/reactive_socket_service_base_ext.ipp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (C) 2016-2019 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_boost or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_IMPL_REACTIVE_SOCKET_SERVICE_BASE_EXT_IPP +#define BOOST_ASIO_DETAIL_IMPL_REACTIVE_SOCKET_SERVICE_BASE_EXT_IPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#if !defined(BOOST_ASIO_HAS_IOCP) \ + && !defined(BOOST_ASIO_WINDOWS_RUNTIME) + +#include + +#include + +namespace boost { +namespace asio { +namespace detail { + +reactive_socket_service_base_ext::reactive_socket_service_base_ext( + execution_context& context) + : reactor_(use_service(context)) +{ + reactor_.init_task(); +} + +void reactive_socket_service_base_ext::base_shutdown() +{ +} + +void reactive_socket_service_base_ext::construct( + reactive_socket_service_base_ext::base_implementation_type& impl) +{ + impl.socket_ = invalid_socket; + impl.state_ = 0; +} + +void reactive_socket_service_base_ext::base_move_construct( + reactive_socket_service_base_ext::base_implementation_type& impl, + reactive_socket_service_base_ext::base_implementation_type& other_impl) +{ + impl.socket_ = other_impl.socket_; + other_impl.socket_ = invalid_socket; + + impl.state_ = other_impl.state_; + other_impl.state_ = 0; + + reactor_.move_descriptor(impl.socket_, + impl.reactor_data_, other_impl.reactor_data_); +} + +void reactive_socket_service_base_ext::base_move_assign( + reactive_socket_service_base_ext::base_implementation_type& impl, + reactive_socket_service_base_ext& other_service, + reactive_socket_service_base_ext::base_implementation_type& other_impl) +{ + destroy(impl); + + impl.socket_ = other_impl.socket_; + other_impl.socket_ = invalid_socket; + + impl.state_ = other_impl.state_; + other_impl.state_ = 0; + + other_service.reactor_.move_descriptor(impl.socket_, + impl.reactor_data_, other_impl.reactor_data_); +} + +void reactive_socket_service_base_ext::destroy( + reactive_socket_service_base_ext::base_implementation_type& impl) +{ + if (impl.socket_ != invalid_socket) + { + BOOST_ASIO_HANDLER_OPERATION((reactor_.context(), + "socket", &impl, impl.socket_, "close")); + + reactor_.deregister_descriptor(impl.socket_, impl.reactor_data_, + (impl.state_ & socket_ops::possible_dup) == 0); + + boost::system::error_code ignored_ec; + socket_ops::close(impl.socket_, impl.state_, true, ignored_ec); + + reactor_.cleanup_descriptor_data(impl.reactor_data_); + } +} + +boost::system::error_code reactive_socket_service_base_ext::close( + reactive_socket_service_base_ext::base_implementation_type& impl, + boost::system::error_code& ec) +{ + if (is_open(impl)) + { + BOOST_ASIO_HANDLER_OPERATION((reactor_.context(), + "socket", &impl, impl.socket_, "close")); + + reactor_.deregister_descriptor(impl.socket_, impl.reactor_data_, + (impl.state_ & socket_ops::possible_dup) == 0); + + socket_ops::close(impl.socket_, impl.state_, false, ec); + + reactor_.cleanup_descriptor_data(impl.reactor_data_); + } + else + { + ec = boost::system::error_code(); + } + + // The descriptor is closed by the OS even if close() returns an error. + // + // (Actually, POSIX says the state of the descriptor is unspecified. On + // Linux the descriptor is apparently closed anyway; e.g. see + // http://lkml.org/lkml/2005/9/10/129 + // We'll just have to assume that other OSes follow the same behaviour. The + // known exception is when Windows's closesocket() function fails with + // WSAEWOULDBLOCK, but this case is handled inside socket_ops::close(). + construct(impl); + + return ec; +} +/* +socket_type reactive_socket_service_base::release( + reactive_socket_service_base::base_implementation_type& impl, + boost::system::error_code& ec) +{ + if (!is_open(impl)) + { + ec = boost::asio::error::bad_descriptor; + return invalid_socket; + } + + BOOST_ASIO_HANDLER_OPERATION((reactor_.context(), + "socket", &impl, impl.socket_, "release")); + + reactor_.deregister_descriptor(impl.socket_, impl.reactor_data_, false); + reactor_.cleanup_descriptor_data(impl.reactor_data_); + socket_type sock = impl.socket_; + construct(impl); + ec = boost::system::error_code(); + return sock; +} +*/ +boost::system::error_code reactive_socket_service_base_ext::cancel( + reactive_socket_service_base_ext::base_implementation_type& impl, + boost::system::error_code& ec) +{ + if (!is_open(impl)) + { + ec = boost::asio::error::bad_descriptor; + return ec; + } + + BOOST_ASIO_HANDLER_OPERATION((reactor_.context(), + "socket", &impl, impl.socket_, "cancel")); + + reactor_.cancel_ops(impl.socket_, impl.reactor_data_); + ec = boost::system::error_code(); + return ec; +} + +boost::system::error_code reactive_socket_service_base_ext::do_open( + reactive_socket_service_base_ext::base_implementation_type& impl, + int af, int type, int protocol, boost::system::error_code& ec) +{ + if (is_open(impl)) + { + ec = boost::asio::error::already_open; + return ec; + } + + socket_holder sock(socket_ops::socket(af, type, protocol, ec)); + if (sock.get() == invalid_socket) + return ec; + + if (int err = reactor_.register_descriptor(sock.get(), impl.reactor_data_)) + { + ec = boost::system::error_code(err, + boost::asio::error::get_system_category()); + return ec; + } + + impl.socket_ = sock.release(); + switch (type) + { + case SOCK_STREAM: impl.state_ = socket_ops::stream_oriented; break; + case SOCK_DGRAM: impl.state_ = socket_ops::datagram_oriented; break; + default: impl.state_ = 0; break; + } + ec = boost::system::error_code(); + return ec; +} + +boost::system::error_code reactive_socket_service_base_ext::do_assign( + reactive_socket_service_base_ext::base_implementation_type& impl, int type, + const reactive_socket_service_base_ext::native_handle_type& native_socket, + boost::system::error_code& ec) +{ + if (is_open(impl)) + { + ec = boost::asio::error::already_open; + return ec; + } + + if (int err = reactor_.register_descriptor( + native_socket, impl.reactor_data_)) + { + ec = boost::system::error_code(err, + boost::asio::error::get_system_category()); + return ec; + } + + impl.socket_ = native_socket; + switch (type) + { + case SOCK_STREAM: impl.state_ = socket_ops::stream_oriented; break; + case SOCK_DGRAM: impl.state_ = socket_ops::datagram_oriented; break; + default: impl.state_ = 0; break; + } + impl.state_ |= socket_ops::possible_dup; + ec = boost::system::error_code(); + return ec; +} + +void reactive_socket_service_base_ext::start_op( + reactive_socket_service_base_ext::base_implementation_type& impl, + int op_type, reactor_op* op, bool is_continuation, + bool is_non_blocking, bool noop) +{ + if (!noop) + { + if ((impl.state_ & socket_ops::non_blocking) + || socket_ops::set_internal_non_blocking( + impl.socket_, impl.state_, true, op->ec_)) + { + reactor_.start_op(op_type, impl.socket_, + impl.reactor_data_, op, is_continuation, is_non_blocking); + return; + } + } + + reactor_.post_immediate_completion(op, is_continuation); +} + +void reactive_socket_service_base_ext::start_accept_op( + reactive_socket_service_base_ext::base_implementation_type& impl, + reactor_op* op, bool is_continuation, bool peer_is_open) +{ + if (!peer_is_open) + start_op(impl, reactor::read_op, op, is_continuation, true, false); + else + { + op->ec_ = boost::asio::error::already_open; + reactor_.post_immediate_completion(op, is_continuation); + } +} + +void reactive_socket_service_base_ext::start_connect_op( + reactive_socket_service_base_ext::base_implementation_type& impl, + reactor_op* op, bool is_continuation, + const socket_addr_type* addr, size_t addrlen) +{ + if ((impl.state_ & socket_ops::non_blocking) + || socket_ops::set_internal_non_blocking( + impl.socket_, impl.state_, true, op->ec_)) + { + if (socket_ops::connect(impl.socket_, addr, addrlen, op->ec_) != 0) + { + if (op->ec_ == boost::asio::error::in_progress + || op->ec_ == boost::asio::error::would_block) + { + op->ec_ = boost::system::error_code(); + reactor_.start_op(reactor::connect_op, impl.socket_, + impl.reactor_data_, op, is_continuation, false); + return; + } + } + } + + reactor_.post_immediate_completion(op, is_continuation); +} + +} // namespace detail +} // namespace asio +} // namespace boost + +#include + +#endif // !defined(BOOST_ASIO_HAS_IOCP) + // && !defined(BOOST_ASIO_WINDOWS_RUNTIME) + +#endif // BOOST_ASIO_DETAIL_IMPL_REACTIVE_SOCKET_SERVICE_BASE_EXT_IPP diff --git a/implementation/helper/1.76/boost/asio/detail/impl/reactive_socket_service_base_ext_local.ipp b/implementation/helper/1.76/boost/asio/detail/impl/reactive_socket_service_base_ext_local.ipp new file mode 100644 index 0000000..288cf19 --- /dev/null +++ b/implementation/helper/1.76/boost/asio/detail/impl/reactive_socket_service_base_ext_local.ipp @@ -0,0 +1,302 @@ +// +// detail/reactive_socket_service_base_ext_local.ipp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (C) 2016-2019 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_boost or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_IMPL_REACTIVE_SOCKET_SERVICE_BASE_EXT_LOCAL_IPP +#define BOOST_ASIO_DETAIL_IMPL_REACTIVE_SOCKET_SERVICE_BASE_EXT_LOCAL_IPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#if !defined(BOOST_ASIO_HAS_IOCP) \ + && !defined(BOOST_ASIO_WINDOWS_RUNTIME) + +#include + +#include + +namespace boost { +namespace asio { +namespace detail { + +reactive_socket_service_base_ext_local::reactive_socket_service_base_ext_local( + execution_context& context) + : reactor_(use_service(context)) +{ + reactor_.init_task(); +} + +void reactive_socket_service_base_ext_local::base_shutdown() +{ +} + +void reactive_socket_service_base_ext_local::construct( + reactive_socket_service_base_ext_local::base_implementation_type& impl) +{ + impl.socket_ = invalid_socket; + impl.state_ = 0; +} + +void reactive_socket_service_base_ext_local::base_move_construct( + reactive_socket_service_base_ext_local::base_implementation_type& impl, + reactive_socket_service_base_ext_local::base_implementation_type& other_impl) +{ + impl.socket_ = other_impl.socket_; + other_impl.socket_ = invalid_socket; + + impl.state_ = other_impl.state_; + other_impl.state_ = 0; + + reactor_.move_descriptor(impl.socket_, + impl.reactor_data_, other_impl.reactor_data_); +} + +void reactive_socket_service_base_ext_local::base_move_assign( + reactive_socket_service_base_ext_local::base_implementation_type& impl, + reactive_socket_service_base_ext_local& other_service, + reactive_socket_service_base_ext_local::base_implementation_type& other_impl) +{ + destroy(impl); + + impl.socket_ = other_impl.socket_; + other_impl.socket_ = invalid_socket; + + impl.state_ = other_impl.state_; + other_impl.state_ = 0; + + other_service.reactor_.move_descriptor(impl.socket_, + impl.reactor_data_, other_impl.reactor_data_); +} + +void reactive_socket_service_base_ext_local::destroy( + reactive_socket_service_base_ext_local::base_implementation_type& impl) +{ + if (impl.socket_ != invalid_socket) + { + BOOST_ASIO_HANDLER_OPERATION((reactor_.context(), + "socket", &impl, impl.socket_, "close")); + + reactor_.deregister_descriptor(impl.socket_, impl.reactor_data_, + (impl.state_ & socket_ops::possible_dup) == 0); + + boost::system::error_code ignored_ec; + socket_ops::close(impl.socket_, impl.state_, true, ignored_ec); + + reactor_.cleanup_descriptor_data(impl.reactor_data_); + } +} + +boost::system::error_code reactive_socket_service_base_ext_local::close( + reactive_socket_service_base_ext_local::base_implementation_type& impl, + boost::system::error_code& ec) +{ + if (is_open(impl)) + { + BOOST_ASIO_HANDLER_OPERATION((reactor_.context(), + "socket", &impl, impl.socket_, "close")); + + reactor_.deregister_descriptor(impl.socket_, impl.reactor_data_, + (impl.state_ & socket_ops::possible_dup) == 0); + + socket_ops::close(impl.socket_, impl.state_, false, ec); + + reactor_.cleanup_descriptor_data(impl.reactor_data_); + } + else + { + ec = boost::system::error_code(); + } + + // The descriptor is closed by the OS even if close() returns an error. + // + // (Actually, POSIX says the state of the descriptor is unspecified. On + // Linux the descriptor is apparently closed anyway; e.g. see + // http://lkml.org/lkml/2005/9/10/129 + // We'll just have to assume that other OSes follow the same behaviour. The + // known exception is when Windows's closesocket() function fails with + // WSAEWOULDBLOCK, but this case is handled inside socket_ops::close(). + construct(impl); + + return ec; +} +/* +socket_type reactive_socket_service_base::release( + reactive_socket_service_base::base_implementation_type& impl, + boost::system::error_code& ec) +{ + if (!is_open(impl)) + { + ec = boost::asio::error::bad_descriptor; + return invalid_socket; + } + + BOOST_ASIO_HANDLER_OPERATION((reactor_.context(), + "socket", &impl, impl.socket_, "release")); + + reactor_.deregister_descriptor(impl.socket_, impl.reactor_data_, false); + reactor_.cleanup_descriptor_data(impl.reactor_data_); + socket_type sock = impl.socket_; + construct(impl); + ec = boost::system::error_code(); + return sock; +} +*/ +boost::system::error_code reactive_socket_service_base_ext_local::cancel( + reactive_socket_service_base_ext_local::base_implementation_type& impl, + boost::system::error_code& ec) +{ + if (!is_open(impl)) + { + ec = boost::asio::error::bad_descriptor; + return ec; + } + + BOOST_ASIO_HANDLER_OPERATION((reactor_.context(), + "socket", &impl, impl.socket_, "cancel")); + + reactor_.cancel_ops(impl.socket_, impl.reactor_data_); + ec = boost::system::error_code(); + return ec; +} + +boost::system::error_code reactive_socket_service_base_ext_local::do_open( + reactive_socket_service_base_ext_local::base_implementation_type& impl, + int af, int type, int protocol, boost::system::error_code& ec) +{ + if (is_open(impl)) + { + ec = boost::asio::error::already_open; + return ec; + } + + socket_holder sock(socket_ops::socket(af, type, protocol, ec)); + if (sock.get() == invalid_socket) + return ec; + + if (int err = reactor_.register_descriptor(sock.get(), impl.reactor_data_)) + { + ec = boost::system::error_code(err, + boost::asio::error::get_system_category()); + return ec; + } + + impl.socket_ = sock.release(); + switch (type) + { + case SOCK_STREAM: impl.state_ = socket_ops::stream_oriented; break; + case SOCK_DGRAM: impl.state_ = socket_ops::datagram_oriented; break; + default: impl.state_ = 0; break; + } + ec = boost::system::error_code(); + return ec; +} + +boost::system::error_code reactive_socket_service_base_ext_local::do_assign( + reactive_socket_service_base_ext_local::base_implementation_type& impl, int type, + const reactive_socket_service_base_ext_local::native_handle_type& native_socket, + boost::system::error_code& ec) +{ + if (is_open(impl)) + { + ec = boost::asio::error::already_open; + return ec; + } + + if (int err = reactor_.register_descriptor( + native_socket, impl.reactor_data_)) + { + ec = boost::system::error_code(err, + boost::asio::error::get_system_category()); + return ec; + } + + impl.socket_ = native_socket; + switch (type) + { + case SOCK_STREAM: impl.state_ = socket_ops::stream_oriented; break; + case SOCK_DGRAM: impl.state_ = socket_ops::datagram_oriented; break; + default: impl.state_ = 0; break; + } + impl.state_ |= socket_ops::possible_dup; + ec = boost::system::error_code(); + return ec; +} + +void reactive_socket_service_base_ext_local::start_op( + reactive_socket_service_base_ext_local::base_implementation_type& impl, + int op_type, reactor_op* op, bool is_continuation, + bool is_non_blocking, bool noop) +{ + if (!noop) + { + if ((impl.state_ & socket_ops::non_blocking) + || socket_ops::set_internal_non_blocking( + impl.socket_, impl.state_, true, op->ec_)) + { + reactor_.start_op(op_type, impl.socket_, + impl.reactor_data_, op, is_continuation, is_non_blocking); + return; + } + } + + reactor_.post_immediate_completion(op, is_continuation); +} + +void reactive_socket_service_base_ext_local::start_accept_op( + reactive_socket_service_base_ext_local::base_implementation_type& impl, + reactor_op* op, bool is_continuation, bool peer_is_open) +{ + if (!peer_is_open) + start_op(impl, reactor::read_op, op, is_continuation, true, false); + else + { + op->ec_ = boost::asio::error::already_open; + reactor_.post_immediate_completion(op, is_continuation); + } +} + +void reactive_socket_service_base_ext_local::start_connect_op( + reactive_socket_service_base_ext_local::base_implementation_type& impl, + reactor_op* op, bool is_continuation, + const socket_addr_type* addr, size_t addrlen) +{ + if ((impl.state_ & socket_ops::non_blocking) + || socket_ops::set_internal_non_blocking( + impl.socket_, impl.state_, true, op->ec_)) + { + if (socket_ops::connect(impl.socket_, addr, addrlen, op->ec_) != 0) + { + if (op->ec_ == boost::asio::error::in_progress + || op->ec_ == boost::asio::error::would_block) + { + op->ec_ = boost::system::error_code(); + reactor_.start_op(reactor::connect_op, impl.socket_, + impl.reactor_data_, op, is_continuation, false); + return; + } + } + } + + reactor_.post_immediate_completion(op, is_continuation); +} + +} // namespace detail +} // namespace asio +} // namespace boost + +#include + +#endif // !defined(BOOST_ASIO_HAS_IOCP) + // && !defined(BOOST_ASIO_WINDOWS_RUNTIME) + +#endif // BOOST_ASIO_DETAIL_IMPL_REACTIVE_SOCKET_SERVICE_BASE_EXT_LOCAL_IPP diff --git a/implementation/helper/1.76/boost/asio/detail/impl/socket_ops_ext.ipp b/implementation/helper/1.76/boost/asio/detail/impl/socket_ops_ext.ipp new file mode 100644 index 0000000..39e2ed8 --- /dev/null +++ b/implementation/helper/1.76/boost/asio/detail/impl/socket_ops_ext.ipp @@ -0,0 +1,234 @@ +// +// detail/impl/socket_ops_ext.ipp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (C) 2016-2019 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_boost or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_SOCKET_OPS_EXT_IPP +#define BOOST_ASIO_DETAIL_SOCKET_OPS_EXT_IPP + +#include + +#include + +namespace boost { +namespace asio { +namespace detail { +namespace socket_ops { + +signed_size_type recvfrom(socket_type s, buf* bufs, size_t count, + int flags, socket_addr_type* addr, std::size_t* addrlen, + boost::system::error_code& ec, boost::asio::ip::address& da) +{ + +#if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) + GUID WSARecvMsg_GUID = WSAID_WSARECVMSG; + LPFN_WSARECVMSG WSARecvMsg; + DWORD NumberOfBytes; + signed_size_type result; + + result = WSAIoctl(s, SIO_GET_EXTENSION_FUNCTION_POINTER, + &WSARecvMsg_GUID, sizeof WSARecvMsg_GUID, + &WSARecvMsg, sizeof WSARecvMsg, + &NumberOfBytes, NULL, NULL); + get_last_error(ec, true); + if (ec.value() == SOCKET_ERROR) { + WSARecvMsg = NULL; + return 0; + } + + WSABUF wsaBuf; + WSAMSG msg; + char controlBuffer[1024]; + msg.name = addr; + msg.namelen = *addrlen; + wsaBuf.buf = bufs->buf; + wsaBuf.len = bufs->len; + msg.lpBuffers = &wsaBuf; + msg.dwBufferCount = count; + msg.Control.len = sizeof controlBuffer; + msg.Control.buf = controlBuffer; + msg.dwFlags = flags; + + DWORD dwNumberOfBytesRecvd; + result = WSARecvMsg(s, &msg, &dwNumberOfBytesRecvd, NULL, NULL); + get_last_error(ec, true); + + if (result >= 0) { + ec = boost::system::error_code(); + + // Find destination address + for (LPWSACMSGHDR cmsg = WSA_CMSG_FIRSTHDR(&msg); + cmsg != NULL; + cmsg = WSA_CMSG_NXTHDR(&msg, cmsg)) + { + if (cmsg->cmsg_level == IPPROTO_IP && cmsg->cmsg_type == IP_PKTINFO) + { + struct in_pktinfo *pi = (struct in_pktinfo *) WSA_CMSG_DATA(cmsg); + if (pi) + { + da = boost::asio::ip::address_v4(ntohl(pi->ipi_addr.s_addr)); + } + } else + if (cmsg->cmsg_level == IPPROTO_IPV6 && cmsg->cmsg_type == IPV6_PKTINFO) + { + struct in6_pktinfo *pi = (struct in6_pktinfo *) WSA_CMSG_DATA(cmsg); + if (pi) + { + boost::asio::ip::address_v6::bytes_type b; + memcpy(b.data(), pi->ipi6_addr.s6_addr, sizeof(pi->ipi6_addr.s6_addr)); + da = boost::asio::ip::address_v6(b); + } + } + } + } else { + dwNumberOfBytesRecvd = -1; + } + return dwNumberOfBytesRecvd; +#else // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) + char cmbuf[0x100]; + msghdr msg = msghdr(); + init_msghdr_msg_name(msg.msg_name, addr); + msg.msg_namelen = static_cast(*addrlen); + msg.msg_iov = bufs; + msg.msg_iovlen = static_cast(count); + msg.msg_control = cmbuf; + msg.msg_controllen = sizeof(cmbuf); + signed_size_type result = ::recvmsg(s, &msg, flags); + get_last_error(ec, true); + *addrlen = msg.msg_namelen; + if (result >= 0) { + ec.assign(0, ec.category()); + + // Find destination address + for (struct cmsghdr *cmsg = CMSG_FIRSTHDR(&msg); + cmsg != NULL; + cmsg = CMSG_NXTHDR(&msg, cmsg)) + { + if (cmsg->cmsg_level == IPPROTO_IP && cmsg->cmsg_type == IP_PKTINFO) + { + struct in_pktinfo *pi = (struct in_pktinfo *) CMSG_DATA(cmsg); + if (pi) + { + da = boost::asio::ip::address_v4(ntohl(pi->ipi_addr.s_addr)); + } + } else + if (cmsg->cmsg_level == IPPROTO_IPV6 && cmsg->cmsg_type == IPV6_PKTINFO) + { + struct in6_pktinfo *pi = (struct in6_pktinfo *) CMSG_DATA(cmsg); + if (pi) + { + boost::asio::ip::address_v6::bytes_type b; + memcpy(b.data(), pi->ipi6_addr.s6_addr, sizeof(pi->ipi6_addr.s6_addr)); + da = boost::asio::ip::address_v6(b); + } + } + } + } + return result; +#endif // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) +} + +size_t sync_recvfrom(socket_type s, state_type state, buf* bufs, + size_t count, int flags, socket_addr_type* addr, + std::size_t* addrlen, boost::system::error_code& ec, boost::asio::ip::address& da) +{ + if (s == invalid_socket) + { + ec = boost::asio::error::bad_descriptor; + return 0; + } + + // Read some data. + for (;;) + { + // Try to complete the operation without blocking. + signed_size_type bytes = socket_ops::recvfrom( + s, bufs, count, flags, addr, addrlen, ec, da); + + // Check if operation succeeded. + if (bytes >= 0) + return bytes; + + // Operation failed. + if ((state & user_set_non_blocking) + || (ec != boost::asio::error::would_block + && ec != boost::asio::error::try_again)) + return 0; + + // Wait for socket to become ready. + if (socket_ops::poll_read(s, 0, -1, ec) < 0) + return 0; + } +} + +#if defined(BOOST_ASIO_HAS_IOCP) + +void complete_iocp_recvfrom( + const weak_cancel_token_type& cancel_token, + boost::system::error_code& ec, boost::asio::ip::address& da) +{ + // Map non-portable errors to their portable counterparts. + if (ec.value() == ERROR_NETNAME_DELETED) + { + if (cancel_token.expired()) + ec = boost::asio::error::operation_aborted; + else + ec = boost::asio::error::connection_reset; + } + else if (ec.value() == ERROR_PORT_UNREACHABLE) + { + ec = boost::asio::error::connection_refused; + } +} + +#else // defined(BOOST_ASIO_HAS_IOCP) + +bool non_blocking_recvfrom(socket_type s, + buf* bufs, size_t count, int flags, + socket_addr_type* addr, std::size_t* addrlen, + boost::system::error_code& ec, size_t& bytes_transferred, boost::asio::ip::address& da) +{ + for (;;) + { + // Read some data. + signed_size_type bytes = socket_ops::recvfrom( + s, bufs, count, flags, addr, addrlen, ec, da); + + // Retry operation if interrupted by signal. + if (ec == boost::asio::error::interrupted) + continue; + + // Check if we need to run the operation again. + if (ec == boost::asio::error::would_block + || ec == boost::asio::error::try_again) + return false; + + // Operation is complete. + if (bytes >= 0) + { + ec = boost::system::error_code(); + bytes_transferred = bytes; + } + else + bytes_transferred = 0; + + return true; + } +} + +#endif // defined(BOOST_ASIO_HAS_IOCP) + +} // namespace socket_ops +} // namespace detail +} // namespace asio +} // namespace boost + +#include + +#endif // BOOST_ASIO_DETAIL_SOCKET_OPS_EXT_IPP diff --git a/implementation/helper/1.76/boost/asio/detail/impl/socket_ops_ext_local.ipp b/implementation/helper/1.76/boost/asio/detail/impl/socket_ops_ext_local.ipp new file mode 100644 index 0000000..83a673b --- /dev/null +++ b/implementation/helper/1.76/boost/asio/detail/impl/socket_ops_ext_local.ipp @@ -0,0 +1,307 @@ +// +// detail/impl/socket_ops_ext_local.ipp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (C) 2016-2019 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_boost or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_SOCKET_OPS_EXT_LOCAL_IPP +#define BOOST_ASIO_DETAIL_SOCKET_OPS_EXT_LOCAL_IPP + +#include + +#include + +namespace boost { +namespace asio { +namespace detail { +namespace socket_ops { + +signed_size_type recv(socket_type s, buf* bufs, size_t count, + int flags, boost::system::error_code& ec, + std::uint32_t& uid, std::uint32_t& gid) +{ + uid = 0xFFFFFFFF; + gid = 0xFFFFFFFF; + struct ucred *ucredp; + +#if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) + // Receive some data. + DWORD recv_buf_count = static_cast(count); + DWORD bytes_transferred = 0; + DWORD recv_flags = flags; + int result = ::WSARecv(s, bufs, + recv_buf_count, &bytes_transferred, &recv_flags, 0, 0); + get_last_error(ec, true); + if (ec.value() == ERROR_NETNAME_DELETED) + ec = boost::asio::error::connection_reset; + else if (ec.value() == ERROR_PORT_UNREACHABLE) + ec = boost::asio::error::connection_refused; + if (result != 0) + return socket_error_retval; + ec.assign(0, ec.category()); + return bytes_transferred; +#else // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) + msghdr msg = msghdr(); + msg.msg_iov = bufs; + msg.msg_iovlen = static_cast(count); + + union { + struct cmsghdr cmh; + char control[CMSG_SPACE(sizeof(struct ucred))]; + } control_un; + + // Set 'control_un' to describe ancillary data that we want to receive + control_un.cmh.cmsg_len = CMSG_LEN(sizeof(struct ucred)); + control_un.cmh.cmsg_level = SOL_SOCKET; + control_un.cmh.cmsg_type = SCM_CREDENTIALS; + + // Set 'msg' fields to describe 'control_un' + msg.msg_control = control_un.control; + msg.msg_controllen = sizeof(control_un.control); + + signed_size_type result = ::recvmsg(s, &msg, flags); + get_last_error(ec, true); + if (result >= 0) { + ec.assign(0, ec.category()); + + // Find UID / GID + for (struct cmsghdr *cmsg = CMSG_FIRSTHDR(&msg); + cmsg != NULL; + cmsg = CMSG_NXTHDR(&msg, cmsg)) + { + if (cmsg->cmsg_level != SOL_SOCKET || cmsg->cmsg_type != SCM_CREDENTIALS + || cmsg->cmsg_len != CMSG_LEN(sizeof(struct ucred))) + continue; + + ucredp = (struct ucred *) CMSG_DATA(cmsg); + if (ucredp) { + uid = ucredp->uid; + gid = ucredp->gid; + } + } + } + return result; +#endif // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) +} + +signed_size_type recvfrom(socket_type s, buf* bufs, size_t count, + int flags, socket_addr_type* addr, std::size_t* addrlen, + boost::system::error_code& ec, + std::uint32_t& uid, std::uint32_t& gid) +{ + uid = 0xFFFFFFFF; + gid = 0xFFFFFFFF; + struct ucred *ucredp; + clear_last_error(); +#if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) + // Receive some data. + DWORD recv_buf_count = static_cast(count); + DWORD bytes_transferred = 0; + DWORD recv_flags = flags; + int tmp_addrlen = (int)*addrlen; + int result = ::WSARecvFrom(s, bufs, recv_buf_count, + &bytes_transferred, &recv_flags, addr, &tmp_addrlen, 0, 0); + get_last_error(ec, true); + *addrlen = (std::size_t)tmp_addrlen; + if (ec.value() == ERROR_NETNAME_DELETED) + ec = boost::asio::error::connection_reset; + else if (ec.value() == ERROR_PORT_UNREACHABLE) + ec = boost::asio::error::connection_refused; + if (result != 0) + return socket_error_retval; + ec.assign(0, ec.category()); + return bytes_transferred; +#else // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) + msghdr msg = msghdr(); + init_msghdr_msg_name(msg.msg_name, addr); + msg.msg_namelen = static_cast(*addrlen); + msg.msg_iov = bufs; + msg.msg_iovlen = static_cast(count); + + union { + struct cmsghdr cmh; + char control[CMSG_SPACE(sizeof(struct ucred))]; + } control_un; + + // Set 'control_un' to describe ancillary data that we want to receive + control_un.cmh.cmsg_len = CMSG_LEN(sizeof(struct ucred)); + control_un.cmh.cmsg_level = SOL_SOCKET; + control_un.cmh.cmsg_type = SCM_CREDENTIALS; + + // Set 'msg' fields to describe 'control_un' + msg.msg_control = control_un.control; + msg.msg_controllen = sizeof(control_un.control); + + signed_size_type result = ::recvmsg(s, &msg, flags); + get_last_error(ec, true); + *addrlen = msg.msg_namelen; + if (result >= 0) { + ec.assign(0, ec.category()); + + // Find UID / GID + for (struct cmsghdr *cmsg = CMSG_FIRSTHDR(&msg); + cmsg != NULL; + cmsg = CMSG_NXTHDR(&msg, cmsg)) + { + if (cmsg->cmsg_level != SOL_SOCKET || cmsg->cmsg_type != SCM_CREDENTIALS + || cmsg->cmsg_len != CMSG_LEN(sizeof(struct ucred))) + continue; + + ucredp = (struct ucred *) CMSG_DATA(cmsg); + if (ucredp) { + uid = ucredp->uid; + gid = ucredp->gid; + } + } + } + return result; +#endif // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) +} + +size_t sync_recvfrom(socket_type s, state_type state, buf* bufs, + size_t count, int flags, socket_addr_type* addr, + std::size_t* addrlen, boost::system::error_code& ec, + std::uint32_t& uid, std::uint32_t& gid) +{ + if (s == invalid_socket) + { + ec = boost::asio::error::bad_descriptor; + return 0; + } + + // Read some data. + for (;;) + { + // Try to complete the operation without blocking. + signed_size_type bytes = socket_ops::recvfrom( + s, bufs, count, flags, addr, addrlen, ec, uid, gid); + + // Check if operation succeeded. + if (bytes >= 0) + return bytes; + + // Operation failed. + if ((state & user_set_non_blocking) + || (ec != boost::asio::error::would_block + && ec != boost::asio::error::try_again)) + return 0; + + // Wait for socket to become ready. + if (socket_ops::poll_read(s, 0, -1, ec) < 0) + return 0; + } +} + +#if defined(BOOST_ASIO_HAS_IOCP) + +void complete_iocp_recvfrom( + const weak_cancel_token_type& cancel_token, + boost::system::error_code& ec, + std::uint32_t& uid, std::uint32_t& gid) +{ + uid = 0xFFFFFFFF; + gid = 0xFFFFFFFF; + // Map non-portable errors to their portable counterparts. + if (ec.value() == ERROR_NETNAME_DELETED) + { + if (cancel_token.expired()) + ec = boost::asio::error::operation_aborted; + else + ec = boost::asio::error::connection_reset; + } + else if (ec.value() == ERROR_PORT_UNREACHABLE) + { + ec = boost::asio::error::connection_refused; + } +} + +#else // defined(BOOST_ASIO_HAS_IOCP) + +bool non_blocking_recv(socket_type s, + buf* bufs, size_t count, int flags, bool is_stream, + boost::system::error_code& ec, size_t& bytes_transferred, + std::uint32_t& uid, std::uint32_t& gid) +{ + for (;;) + { + // Read some data. + signed_size_type bytes = socket_ops::recv(s, bufs, count, flags, ec, uid, gid); + + // Check for end of stream. + if (is_stream && bytes == 0) + { + ec = boost::asio::error::eof; + return true; + } + + // Retry operation if interrupted by signal. + if (ec == boost::asio::error::interrupted) + continue; + + // Check if we need to run the operation again. + if (ec == boost::asio::error::would_block + || ec == boost::asio::error::try_again) + return false; + + // Operation is complete. + if (bytes >= 0) + { + ec = boost::system::error_code(); + bytes_transferred = bytes; + } + else + bytes_transferred = 0; + + return true; + } +} + +bool non_blocking_recvfrom(socket_type s, + buf* bufs, size_t count, int flags, + socket_addr_type* addr, std::size_t* addrlen, + boost::system::error_code& ec, size_t& bytes_transferred, + std::uint32_t& uid, std::uint32_t& gid) +{ + for (;;) + { + // Read some data. + signed_size_type bytes = socket_ops::recvfrom( + s, bufs, count, flags, addr, addrlen, ec, uid, gid); + + // Retry operation if interrupted by signal. + if (ec == boost::asio::error::interrupted) + continue; + + // Check if we need to run the operation again. + if (ec == boost::asio::error::would_block + || ec == boost::asio::error::try_again) + return false; + + // Operation is complete. + if (bytes >= 0) + { + ec = boost::system::error_code(); + bytes_transferred = bytes; + } + else + bytes_transferred = 0; + + return true; + } +} + +#endif // defined(BOOST_ASIO_HAS_IOCP) + +} // namespace socket_ops +} // namespace detail +} // namespace asio +} // namespace boost + +#include + +#endif // BOOST_ASIO_DETAIL_SOCKET_OPS_EXT_LOCAL_IPP diff --git a/implementation/helper/1.76/boost/asio/detail/reactive_socket_recv_op_ext.hpp b/implementation/helper/1.76/boost/asio/detail/reactive_socket_recv_op_ext.hpp new file mode 100644 index 0000000..1167d57 --- /dev/null +++ b/implementation/helper/1.76/boost/asio/detail/reactive_socket_recv_op_ext.hpp @@ -0,0 +1,162 @@ +// +// detail/reactive_socket_recv_op_ext.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2016-2019 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_boost or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_REACTIVE_SOCKET_RECV_OP_EXT_HPP +#define BOOST_ASIO_DETAIL_REACTIVE_SOCKET_RECV_OP_EXT_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace boost { +namespace asio { +namespace detail { + +template +class reactive_socket_recv_op_base_ext : public reactor_op_ext +{ +public: + reactive_socket_recv_op_base_ext(const boost::system::error_code& success_ec, + socket_type socket, socket_ops::state_type state, + const MutableBufferSequence& buffers, + socket_base::message_flags flags, func_type complete_func) + : reactor_op_ext(success_ec, &reactive_socket_recv_op_base_ext::do_perform, complete_func), + socket_(socket), + state_(state), + buffers_(buffers), + flags_(flags) + { + } + + static status do_perform(reactor_op* base) + { + reactive_socket_recv_op_base_ext* o( + static_cast(base)); + + typedef buffer_sequence_adapter bufs_type; + + status result; + if (bufs_type::is_single_buffer) + { + result = socket_ops::non_blocking_recv1(o->socket_, + bufs_type::first(o->buffers_).data(), + bufs_type::first(o->buffers_).size(), o->flags_, + (o->state_ & socket_ops::stream_oriented) != 0, + o->ec_, o->bytes_transferred_) ? done : not_done; + } + else + { + bufs_type bufs(o->buffers_); + result = socket_ops::non_blocking_recv(o->socket_, + bufs.buffers(), bufs.count(), o->flags_, + (o->state_ & socket_ops::stream_oriented) != 0, + o->ec_, o->bytes_transferred_) ? done : not_done; + } + + if (result == done) + if ((o->state_ & socket_ops::stream_oriented) != 0) + if (o->bytes_transferred_ == 0) + result = done_and_exhausted; + + BOOST_ASIO_HANDLER_REACTOR_OPERATION((*o, "non_blocking_recv", + o->ec_, o->bytes_transferred_)); + + return result; + } + +private: + socket_type socket_; + socket_ops::state_type state_; + MutableBufferSequence buffers_; + socket_base::message_flags flags_; +}; + +template +class reactive_socket_recv_op_ext : + public reactive_socket_recv_op_base_ext +{ +public: + BOOST_ASIO_DEFINE_HANDLER_PTR(reactive_socket_recv_op_ext); + + reactive_socket_recv_op_ext(const boost::system::error_code& success_ec, + socket_type socket, socket_ops::state_type state, + const MutableBufferSequence& buffers, socket_base::message_flags flags, + Handler& handler, const IoExecutor& io_ex) + : reactive_socket_recv_op_base_ext(success_ec, + socket, state, buffers, flags, + &reactive_socket_recv_op_ext::do_complete), + handler_(BOOST_ASIO_MOVE_CAST(Handler)(handler)), + work_(handler_, io_ex) + { + } + + static void do_complete(void* owner, operation* base, + const boost::system::error_code& /*ec*/, + std::size_t /*bytes_transferred*/) + { + // Take ownership of the handler object. + reactive_socket_recv_op_ext* o(static_cast(base)); + ptr p = { boost::asio::detail::addressof(o->handler_), o, o }; + + BOOST_ASIO_HANDLER_COMPLETION((*o)); + + // Take ownership of the operation's outstanding work. + handler_work w( + BOOST_ASIO_MOVE_CAST2(handler_work)( + o->work_)); + + // Make a copy of the handler so that the memory can be deallocated before + // the upcall is made. Even if we're not about to make an upcall, a + // sub-object of the handler may be the true owner of the memory associated + // with the handler. Consequently, a local copy of the handler is required + // to ensure that any owning sub-object remains valid until after we have + // deallocated the memory here. + detail::binder3 + handler(o->handler_, o->ec_, o->bytes_transferred_, o->da_); + p.h = boost::asio::detail::addressof(handler.handler_); + p.reset(); + + // Make the upcall if required. + if (owner) + { + fenced_block b(fenced_block::half); + BOOST_ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, handler.arg2_, handler.arg3_)); + w.complete(handler, handler.handler_); + BOOST_ASIO_HANDLER_INVOCATION_END; + } + } + +private: + Handler handler_; + handler_work work_; +}; + +} // namespace detail +} // namespace asio +} // namespace boost + +#include + +#endif // BOOST_ASIO_DETAIL_REACTIVE_SOCKET_RECV_OP_EXT_HPP diff --git a/implementation/helper/1.76/boost/asio/detail/reactive_socket_recv_op_ext_local.hpp b/implementation/helper/1.76/boost/asio/detail/reactive_socket_recv_op_ext_local.hpp new file mode 100644 index 0000000..bedbd29 --- /dev/null +++ b/implementation/helper/1.76/boost/asio/detail/reactive_socket_recv_op_ext_local.hpp @@ -0,0 +1,162 @@ +// +// detail/reactive_socket_recv_op_ext_local.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2019 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_REACTIVE_SOCKET_RECV_OP_EXT_LOCAL_HPP +#define BOOST_ASIO_DETAIL_REACTIVE_SOCKET_RECV_OP_EXT_LOCAL_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace boost { +namespace asio { +namespace detail { + +template +class reactive_socket_recv_op_base_ext_local : public reactor_op_ext_local +{ +public: + reactive_socket_recv_op_base_ext_local(const boost::system::error_code& success_ec, + socket_type socket, socket_ops::state_type state, + const MutableBufferSequence& buffers, + socket_base::message_flags flags, func_type complete_func) + : reactor_op_ext_local(success_ec, &reactive_socket_recv_op_base_ext_local::do_perform, complete_func), + socket_(socket), + state_(state), + buffers_(buffers), + flags_(flags) + { + } + + static status do_perform(reactor_op* base) + { + reactive_socket_recv_op_base_ext_local* o( + static_cast(base)); + + typedef buffer_sequence_adapter bufs_type; + + status result; + if (bufs_type::is_single_buffer) + { + result = socket_ops::non_blocking_recv1(o->socket_, + bufs_type::first(o->buffers_).data(), + bufs_type::first(o->buffers_).size(), o->flags_, + (o->state_ & socket_ops::stream_oriented) != 0, + o->ec_, o->bytes_transferred_) ? done : not_done; + } + else + { + bufs_type bufs(o->buffers_); + result = socket_ops::non_blocking_recv(o->socket_, + bufs.buffers(), bufs.count(), o->flags_, + (o->state_ & socket_ops::stream_oriented) != 0, + o->ec_, o->bytes_transferred_) ? done : not_done; + } + + if (result == done) + if ((o->state_ & socket_ops::stream_oriented) != 0) + if (o->bytes_transferred_ == 0) + result = done_and_exhausted; + + BOOST_ASIO_HANDLER_REACTOR_OPERATION((*o, "non_blocking_recv", + o->ec_, o->bytes_transferred_)); + + return result; + } + +private: + socket_type socket_; + socket_ops::state_type state_; + MutableBufferSequence buffers_; + socket_base::message_flags flags_; +}; + +template +class reactive_socket_recv_op_ext_local : + public reactive_socket_recv_op_base_ext_local +{ +public: + BOOST_ASIO_DEFINE_HANDLER_PTR(reactive_socket_recv_op_ext_local); + + reactive_socket_recv_op_ext_local(const boost::system::error_code& success_ec, + socket_type socket, socket_ops::state_type state, + const MutableBufferSequence& buffers, socket_base::message_flags flags, + Handler& handler, const IoExecutor& io_ex) + : reactive_socket_recv_op_base_ext_local(success_ec, + socket, state, buffers, flags, + &reactive_socket_recv_op_ext_local::do_complete), + handler_(BOOST_ASIO_MOVE_CAST(Handler)(handler)), + work_(handler_, io_ex) + { + } + + static void do_complete(void* owner, operation* base, + const boost::system::error_code& /*ec*/, + std::size_t /*bytes_transferred*/) + { + // Take ownership of the handler object. + reactive_socket_recv_op_ext_local* o(static_cast(base)); + ptr p = { boost::asio::detail::addressof(o->handler_), o, o }; + + BOOST_ASIO_HANDLER_COMPLETION((*o)); + + // Take ownership of the operation's outstanding work. + handler_work w( + BOOST_ASIO_MOVE_CAST2(handler_work)( + o->work_)); + + // Make a copy of the handler so that the memory can be deallocated before + // the upcall is made. Even if we're not about to make an upcall, a + // sub-object of the handler may be the true owner of the memory associated + // with the handler. Consequently, a local copy of the handler is required + // to ensure that any owning sub-object remains valid until after we have + // deallocated the memory here. + detail::binder4 + handler(o->handler_, o->ec_, o->bytes_transferred_, o->uid_, o->gid_); + p.h = boost::asio::detail::addressof(handler.handler_); + p.reset(); + + // Make the upcall if required. + if (owner) + { + fenced_block b(fenced_block::half); + BOOST_ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, handler.arg2_, handler.arg3, handler.arg4)); + w.complete(handler, handler.handler_); + BOOST_ASIO_HANDLER_INVOCATION_END; + } + } + +private: + Handler handler_; + handler_work work_; +}; + +} // namespace detail +} // namespace asio +} // namespace boost + +#include + +#endif // BOOST_ASIO_DETAIL_REACTIVE_SOCKET_RECV_OP_EXT_LOCAL_HPP diff --git a/implementation/helper/1.76/boost/asio/detail/reactive_socket_recvfrom_op_ext.hpp b/implementation/helper/1.76/boost/asio/detail/reactive_socket_recvfrom_op_ext.hpp new file mode 100644 index 0000000..875fe14 --- /dev/null +++ b/implementation/helper/1.76/boost/asio/detail/reactive_socket_recvfrom_op_ext.hpp @@ -0,0 +1,153 @@ +// +// detail/reactive_socket_recvfrom_op_ext.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2016-2019 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_boost or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_REACTIVE_SOCKET_RECVFROM_OP_EXT_HPP +#define BOOST_ASIO_DETAIL_REACTIVE_SOCKET_RECVFROM_OP_EXT_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace boost { +namespace asio { +namespace detail { + +template +class reactive_socket_recvfrom_op_base_ext : public reactor_op_ext +{ +public: + reactive_socket_recvfrom_op_base_ext(const boost::system::error_code& success_ec, + socket_type socket, int protocol_type, + const MutableBufferSequence& buffers, Endpoint& endpoint, + socket_base::message_flags flags, func_type complete_func) + : reactor_op_ext(success_ec, &reactive_socket_recvfrom_op_base_ext::do_perform, complete_func), + socket_(socket), + protocol_type_(protocol_type), + buffers_(buffers), + sender_endpoint_(endpoint), + flags_(flags) + { + } + + static status do_perform(reactor_op* base) + { + reactive_socket_recvfrom_op_base_ext* o( + static_cast(base)); + + buffer_sequence_adapter bufs(o->buffers_); + + std::size_t addr_len = o->sender_endpoint_.capacity(); + status result = socket_ops::non_blocking_recvfrom(o->socket_, + bufs.buffers(), bufs.count(), o->flags_, + o->sender_endpoint_.data(), &addr_len, + o->ec_, o->bytes_transferred_, o->da_) ? done : not_done; + + if (result && !o->ec_) + o->sender_endpoint_.resize(addr_len); + + BOOST_ASIO_HANDLER_REACTOR_OPERATION((*o, "non_blocking_recvfrom", + o->ec_, o->bytes_transferred_)); + + return result; + } + +private: + socket_type socket_; + int protocol_type_; + MutableBufferSequence buffers_; + Endpoint& sender_endpoint_; + socket_base::message_flags flags_; +}; + +template +class reactive_socket_recvfrom_op_ext : + public reactive_socket_recvfrom_op_base_ext +{ +public: + BOOST_ASIO_DEFINE_HANDLER_PTR(reactive_socket_recvfrom_op_ext); + + reactive_socket_recvfrom_op_ext(const boost::system::error_code& success_ec, + socket_type socket, int protocol_type, + const MutableBufferSequence& buffers, Endpoint& endpoint, + socket_base::message_flags flags, Handler& handler, + const IoExecutor& io_ex) + : reactive_socket_recvfrom_op_base_ext( + success_ec, socket, protocol_type, buffers, endpoint, flags, + &reactive_socket_recvfrom_op_ext::do_complete), + handler_(BOOST_ASIO_MOVE_CAST(Handler)(handler)), + work_(handler_, io_ex) + { + } + + static void do_complete(void* owner, operation* base, + const boost::system::error_code& /*ec*/, + std::size_t /*bytes_transferred*/) + { + // Take ownership of the handler object. + reactive_socket_recvfrom_op_ext* o( + static_cast(base)); + ptr p = { boost::asio::detail::addressof(o->handler_), o, o }; + + BOOST_ASIO_HANDLER_COMPLETION((*o)); + + // Take ownership of the operation's outstanding work. + handler_work w( + BOOST_ASIO_MOVE_CAST2(handler_work)( + o->work_)); + + // Make a copy of the handler so that the memory can be deallocated before + // the upcall is made. Even if we're not about to make an upcall, a + // sub-object of the handler may be the true owner of the memory associated + // with the handler. Consequently, a local copy of the handler is required + // to ensure that any owning sub-object remains valid until after we have + // deallocated the memory here. + detail::binder3 + handler(o->handler_, o->ec_, o->bytes_transferred_, o->da_); + p.h = boost::asio::detail::addressof(handler.handler_); + p.reset(); + + // Make the upcall if required. + if (owner) + { + fenced_block b(fenced_block::half); + BOOST_ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, handler.arg2_, handler.arg3_)); + w.complete(handler, handler.handler_); + BOOST_ASIO_HANDLER_INVOCATION_END; + } + } + +private: + Handler handler_; + handler_work work_; +}; + +} // namespace detail +} // namespace asio +} // namespace boost + +#include + +#endif // BOOST_ASIO_DETAIL_REACTIVE_SOCKET_RECVFROM_OP_EXT_HPP diff --git a/implementation/helper/1.76/boost/asio/detail/reactive_socket_recvfrom_op_ext_local.hpp b/implementation/helper/1.76/boost/asio/detail/reactive_socket_recvfrom_op_ext_local.hpp new file mode 100644 index 0000000..f9fef2b --- /dev/null +++ b/implementation/helper/1.76/boost/asio/detail/reactive_socket_recvfrom_op_ext_local.hpp @@ -0,0 +1,148 @@ +// +// detail/reactive_socket_recvfrom_op_ext_local.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2019 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_REACTIVE_SOCKET_RECVFROM_OP_EXT_LOCAL_HPP +#define BOOST_ASIO_DETAIL_REACTIVE_SOCKET_RECVFROM_OP_EXT_LOCAL_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace boost { +namespace asio { +namespace detail { + +template +class reactive_socket_recvfrom_op_base_ext_local : public reactor_op_ext_local +{ +public: + reactive_socket_recvfrom_op_base_ext_local(socket_type socket, int protocol_type, + const MutableBufferSequence& buffers, Endpoint& endpoint, + socket_base::message_flags flags, func_type complete_func) + : reactor_op_ext_local(&reactive_socket_recvfrom_op_base_ext_local::do_perform, complete_func), + socket_(socket), + protocol_type_(protocol_type), + buffers_(buffers), + sender_endpoint_(endpoint), + flags_(flags) + { + } + + static status do_perform(reactor_op* base) + { + reactive_socket_recvfrom_op_base_ext_local* o( + static_cast(base)); + + buffer_sequence_adapter bufs(o->buffers_); + + std::size_t addr_len = o->sender_endpoint_.capacity(); + status result = socket_ops::non_blocking_recvfrom(o->socket_, + bufs.buffers(), bufs.count(), o->flags_, + o->sender_endpoint_.data(), &addr_len, + o->ec_, o->bytes_transferred_, o->uid_, o->gid_) ? done : not_done; + + if (result && !o->ec_) + o->sender_endpoint_.resize(addr_len); + + BOOST_ASIO_HANDLER_REACTOR_OPERATION((*o, "non_blocking_recvfrom", + o->ec_, o->bytes_transferred_)); + + return result; + } + +private: + socket_type socket_; + int protocol_type_; + MutableBufferSequence buffers_; + Endpoint& sender_endpoint_; + socket_base::message_flags flags_; +}; + +template +class reactive_socket_recvfrom_op_ext_local : + public reactive_socket_recvfrom_op_base_ext_local +{ +public: + BOOST_ASIO_DEFINE_HANDLER_PTR(reactive_socket_recvfrom_op_ext_local); + + reactive_socket_recvfrom_op_ext_local(socket_type socket, int protocol_type, + const MutableBufferSequence& buffers, Endpoint& endpoint, + socket_base::message_flags flags, Handler& handler, + const IoExecutor& io_ex) + : reactive_socket_recvfrom_op_base_ext_local( + socket, protocol_type, buffers, endpoint, flags, + &reactive_socket_recvfrom_op_ext_local::do_complete), + handler_(BOOST_ASIO_MOVE_CAST(Handler)(handler)), + work_(handler_, io_ex) + { + } + + static void do_complete(void* owner, operation* base, + const boost::system::error_code& /*ec*/, + std::size_t /*bytes_transferred*/) + { + // Take ownership of the handler object. + reactive_socket_recvfrom_op_ext_local* o( + static_cast(base)); + ptr p = { boost::asio::detail::addressof(o->handler_), o, o }; + + BOOST_ASIO_HANDLER_COMPLETION((*o)); + + // Take ownership of the operation's outstanding work. + handler_work w( + BOOST_ASIO_MOVE_CAST2(handler_work)( + o->work_)); + + // Make a copy of the handler so that the memory can be deallocated before + // the upcall is made. Even if we're not about to make an upcall, a + // sub-object of the handler may be the true owner of the memory associated + // with the handler. Consequently, a local copy of the handler is required + // to ensure that any owning sub-object remains valid until after we have + // deallocated the memory here. + detail::binder4 + handler(o->handler_, o->ec_, o->bytes_transferred_, o->uid_, o->gid_); + p.h = boost::asio::detail::addressof(handler.handler_); + p.reset(); + + // Make the upcall if required. + if (owner) + { + fenced_block b(fenced_block::half); + BOOST_ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, handler.arg2_, handler.arg3_, handler.arg4_)); + w.complete(handler, handler.handler_); + BOOST_ASIO_HANDLER_INVOCATION_END; + } + } + +private: + Handler handler_; + handler_work work_; +}; + +} // namespace detail +} // namespace asio +} // namespace boost + +#include + +#endif // BOOST_ASIO_DETAIL_REACTIVE_SOCKET_RECVFROM_OP_EXT_LOCAL_HPP diff --git a/implementation/helper/1.76/boost/asio/detail/reactive_socket_recvmsg_op_ext.hpp b/implementation/helper/1.76/boost/asio/detail/reactive_socket_recvmsg_op_ext.hpp new file mode 100644 index 0000000..bd315dc --- /dev/null +++ b/implementation/helper/1.76/boost/asio/detail/reactive_socket_recvmsg_op_ext.hpp @@ -0,0 +1,144 @@ +// +// detail/reactive_socket_recvmsg_op_ext.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2016-2019 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_REACTIVE_SOCKET_RECVMSG_OP_EXT_HPP +#define BOOST_ASIO_DETAIL_REACTIVE_SOCKET_RECVMSG_OP_EXT_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace boost { +namespace asio { +namespace detail { + +template +class reactive_socket_recvmsg_op_base_ext : public reactor_op_ext +{ +public: + reactive_socket_recvmsg_op_base_ext(const boost::system::error_code& success_ec, + socket_type socket, const MutableBufferSequence& buffers, socket_base::message_flags in_flags, + socket_base::message_flags& out_flags, func_type complete_func) + : reactor_op_ext(&reactive_socket_recvmsg_op_base_ext::do_perform, complete_func), + socket_(socket), + buffers_(buffers), + in_flags_(in_flags), + out_flags_(out_flags) + { + } + + static status do_perform(reactor_op* base) + { + reactive_socket_recvmsg_op_base_ext* o( + static_cast(base)); + + buffer_sequence_adapter bufs(o->buffers_); + + status result = socket_ops::non_blocking_recvmsg(o->socket_, + bufs.buffers(), bufs.count(), + o->in_flags_, o->out_flags_, + o->ec_, o->bytes_transferred_) ? done : not_done; + + BOOST_ASIO_HANDLER_REACTOR_OPERATION((*o, "non_blocking_recvmsg", + o->ec_, o->bytes_transferred_)); + + return result; + } + +private: + socket_type socket_; + MutableBufferSequence buffers_; + socket_base::message_flags in_flags_; + socket_base::message_flags& out_flags_; +}; + +template +class reactive_socket_recvmsg_op_ext : + public reactive_socket_recvmsg_op_base_ext +{ +public: + BOOST_ASIO_DEFINE_HANDLER_PTR(reactive_socket_recvmsg_op_ext); + + reactive_socket_recvmsg_op_ext(const boost::system::error_code& success_ec, + socket_type socket, const MutableBufferSequence& buffers, socket_base::message_flags in_flags, + socket_base::message_flags& out_flags, Handler& handler, + const IoExecutor& io_ex) + : reactive_socket_recvmsg_op_base_ext(socket, buffers, + in_flags, out_flags, &reactive_socket_recvmsg_op_ext::do_complete), + handler_(BOOST_ASIO_MOVE_CAST(Handler)(handler)), + work_(handler_, io_ex) + { + } + + static void do_complete(void* owner, operation* base, + const boost::system::error_code& /*ec*/, + std::size_t /*bytes_transferred*/) + { + // Take ownership of the handler object. + reactive_socket_recvmsg_op_ext* o( + static_cast(base)); + ptr p = { boost::asio::detail::addressof(o->handler_), o, o }; + + BOOST_ASIO_HANDLER_COMPLETION((*o)); + + // Take ownership of the operation's outstanding work. + handler_work w( + BOOST_ASIO_MOVE_CAST2(handler_work)( + o->work_)); + + // Make a copy of the handler so that the memory can be deallocated before + // the upcall is made. Even if we're not about to make an upcall, a + // sub-object of the handler may be the true owner of the memory associated + // with the handler. Consequently, a local copy of the handler is required + // to ensure that any owning sub-object remains valid until after we have + // deallocated the memory here. + detail::binder3 + handler(o->handler_, o->ec_, o->bytes_transferred_, o->da_); + p.h = boost::asio::detail::addressof(handler.handler_); + p.reset(); + + // Make the upcall if required. + if (owner) + { + fenced_block b(fenced_block::half); + BOOST_ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, handler.arg2_, handler.arg3_)); + w.complete(handler, handler.handler_); + BOOST_ASIO_HANDLER_INVOCATION_END; + } + } + +private: + Handler handler_; + handler_work work_; +}; + +} // namespace detail +} // namespace asio +} // namespace boost + +#include + +#endif // BOOST_ASIO_DETAIL_REACTIVE_SOCKET_RECVMSG_OP_EXT_HPP diff --git a/implementation/helper/1.76/boost/asio/detail/reactive_socket_recvmsg_op_ext_local.hpp b/implementation/helper/1.76/boost/asio/detail/reactive_socket_recvmsg_op_ext_local.hpp new file mode 100644 index 0000000..8148690 --- /dev/null +++ b/implementation/helper/1.76/boost/asio/detail/reactive_socket_recvmsg_op_ext_local.hpp @@ -0,0 +1,145 @@ +// +// detail/reactive_socket_recvmsg_op_ext_local.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2019 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_REACTIVE_SOCKET_RECVMSG_OP_EXT_LOCAL_HPP +#define BOOST_ASIO_DETAIL_REACTIVE_SOCKET_RECVMSG_OP_EXT_LOCAL_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace boost { +namespace asio { +namespace detail { + +template +class reactive_socket_recvmsg_op_base_ext_local : public reactor_op_ext_local +{ +public: + reactive_socket_recvmsg_op_base_ext_local(const boost::system::error_code& success_ec, + socket_type socket, const MutableBufferSequence& buffers, socket_base::message_flags in_flags, + socket_base::message_flags& out_flags, func_type complete_func) + : reactor_op_ext_local(success_ec, &reactive_socket_recvmsg_op_base_ext_local::do_perform, complete_func), + socket_(socket), + buffers_(buffers), + in_flags_(in_flags), + out_flags_(out_flags) + { + } + + static status do_perform(reactor_op* base) + { + reactive_socket_recvmsg_op_base_ext_local* o( + static_cast(base)); + + buffer_sequence_adapter bufs(o->buffers_); + + status result = socket_ops::non_blocking_recvmsg(o->socket_, + bufs.buffers(), bufs.count(), + o->in_flags_, o->out_flags_, + o->ec_, o->bytes_transferred_) ? done : not_done; + + BOOST_ASIO_HANDLER_REACTOR_OPERATION((*o, "non_blocking_recvmsg", + o->ec_, o->bytes_transferred_)); + + return result; + } + +private: + socket_type socket_; + MutableBufferSequence buffers_; + socket_base::message_flags in_flags_; + socket_base::message_flags& out_flags_; +}; + +template +class reactive_socket_recvmsg_op_ext_local : + public reactive_socket_recvmsg_op_base_ext_local +{ +public: + BOOST_ASIO_DEFINE_HANDLER_PTR(reactive_socket_recvmsg_op_ext_local); + + reactive_socket_recvmsg_op_ext_local(const boost::system::error_code& success_ec, + socket_type socket, const MutableBufferSequence& buffers, socket_base::message_flags in_flags, + socket_base::message_flags& out_flags, Handler& handler, + const IoExecutor& io_ex) + : reactive_socket_recvmsg_op_base_ext_local(success_ec, + socket, buffers, in_flags, out_flags, + &reactive_socket_recvmsg_op_ext_local::do_complete), + handler_(BOOST_ASIO_MOVE_CAST(Handler)(handler)), + work_(handler_, io_ex) + { + } + + static void do_complete(void* owner, operation* base, + const boost::system::error_code& /*ec*/, + std::size_t /*bytes_transferred*/) + { + // Take ownership of the handler object. + reactive_socket_recvmsg_op_ext_local* o( + static_cast(base)); + ptr p = { boost::asio::detail::addressof(o->handler_), o, o }; + + BOOST_ASIO_HANDLER_COMPLETION((*o)); + + // Take ownership of the operation's outstanding work. + handler_work w( + BOOST_ASIO_MOVE_CAST2(handler_work)( + o->work_)); + + // Make a copy of the handler so that the memory can be deallocated before + // the upcall is made. Even if we're not about to make an upcall, a + // sub-object of the handler may be the true owner of the memory associated + // with the handler. Consequently, a local copy of the handler is required + // to ensure that any owning sub-object remains valid until after we have + // deallocated the memory here. + detail::binder4 + handler(o->handler_, o->ec_, o->bytes_transferred_, o->uid_, o->gid_); + p.h = boost::asio::detail::addressof(handler.handler_); + p.reset(); + + // Make the upcall if required. + if (owner) + { + fenced_block b(fenced_block::half); + BOOST_ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, handler.arg2_, handler.arg3_, handler.arg4_)); + w.complete(handler, handler.handler_); + BOOST_ASIO_HANDLER_INVOCATION_END; + } + } + +private: + Handler handler_; + handler_work work_; +}; + +} // namespace detail +} // namespace asio +} // namespace boost + +#include + +#endif // BOOST_ASIO_DETAIL_REACTIVE_SOCKET_RECVMSG_OP_EXT_LOCAL_HPP diff --git a/implementation/helper/1.76/boost/asio/detail/reactive_socket_service_base_ext.hpp b/implementation/helper/1.76/boost/asio/detail/reactive_socket_service_base_ext.hpp new file mode 100644 index 0000000..2e68a87 --- /dev/null +++ b/implementation/helper/1.76/boost/asio/detail/reactive_socket_service_base_ext.hpp @@ -0,0 +1,524 @@ +// +// detail/reactive_socket_service_base.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2016-2019 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_boost or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_REACTIVE_SOCKET_SERVICE_BASE_EXT_HPP +#define BOOST_ASIO_DETAIL_REACTIVE_SOCKET_SERVICE_BASE_EXT_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#if !defined(BOOST_ASIO_HAS_IOCP) \ + && !defined(BOOST_ASIO_WINDOWS_RUNTIME) + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace boost { +namespace asio { +namespace detail { + +class reactive_socket_service_base_ext +{ +public: + // The native type of a socket. + typedef socket_type native_handle_type; + + // The implementation type of the socket. + struct base_implementation_type + { + // The native socket representation. + socket_type socket_; + + // The current state of the socket. + socket_ops::state_type state_; + + // Per-descriptor data used by the reactor. + reactor::per_descriptor_data reactor_data_; + }; + + // Constructor. + BOOST_ASIO_DECL reactive_socket_service_base_ext(execution_context& context); + + // Destroy all user-defined handler objects owned by the service. + BOOST_ASIO_DECL void base_shutdown(); + + // Construct a new socket implementation. + BOOST_ASIO_DECL void construct(base_implementation_type& impl); + + // Move-construct a new socket implementation. + BOOST_ASIO_DECL void base_move_construct(base_implementation_type& impl, + base_implementation_type& other_impl); + + // Move-assign from another socket implementation. + BOOST_ASIO_DECL void base_move_assign(base_implementation_type& impl, + reactive_socket_service_base_ext& other_service, + base_implementation_type& other_impl); + + // Destroy a socket implementation. + BOOST_ASIO_DECL void destroy(base_implementation_type& impl); + + // Determine whether the socket is open. + bool is_open(const base_implementation_type& impl) const + { + return impl.socket_ != invalid_socket; + } + + // Destroy a socket implementation. + BOOST_ASIO_DECL boost::system::error_code close( + base_implementation_type& impl, boost::system::error_code& ec); + + // Release ownership of the socket. + BOOST_ASIO_DECL socket_type release( + base_implementation_type& impl, boost::system::error_code& ec); + + // Get the native socket representation. + native_handle_type native_handle(base_implementation_type& impl) + { + return impl.socket_; + } + + // Cancel all operations associated with the socket. + BOOST_ASIO_DECL boost::system::error_code cancel( + base_implementation_type& impl, boost::system::error_code& ec); + + // Determine whether the socket is at the out-of-band data mark. + bool at_mark(const base_implementation_type& impl, + boost::system::error_code& ec) const + { + return socket_ops::sockatmark(impl.socket_, ec); + } + + // Determine the number of bytes available for reading. + std::size_t available(const base_implementation_type& impl, + boost::system::error_code& ec) const + { + return socket_ops::available(impl.socket_, ec); + } + + // Place the socket into the state where it will listen for new connections. + boost::system::error_code listen(base_implementation_type& impl, + int backlog, boost::system::error_code& ec) + { + socket_ops::listen(impl.socket_, backlog, ec); + return ec; + } + + // Perform an IO control command on the socket. + template + boost::system::error_code io_control(base_implementation_type& impl, + IO_Control_Command& command, boost::system::error_code& ec) + { + socket_ops::ioctl(impl.socket_, impl.state_, command.name(), + static_cast(command.data()), ec); + return ec; + } + + // Gets the non-blocking mode of the socket. + bool non_blocking(const base_implementation_type& impl) const + { + return (impl.state_ & socket_ops::user_set_non_blocking) != 0; + } + + // Sets the non-blocking mode of the socket. + boost::system::error_code non_blocking(base_implementation_type& impl, + bool mode, boost::system::error_code& ec) + { + socket_ops::set_user_non_blocking(impl.socket_, impl.state_, mode, ec); + return ec; + } + + // Gets the non-blocking mode of the native socket implementation. + bool native_non_blocking(const base_implementation_type& impl) const + { + return (impl.state_ & socket_ops::internal_non_blocking) != 0; + } + + // Sets the non-blocking mode of the native socket implementation. + boost::system::error_code native_non_blocking(base_implementation_type& impl, + bool mode, boost::system::error_code& ec) + { + socket_ops::set_internal_non_blocking(impl.socket_, impl.state_, mode, ec); + return ec; + } + + // Wait for the socket to become ready to read, ready to write, or to have + // pending error conditions. + boost::system::error_code wait(base_implementation_type& impl, + socket_base::wait_type w, boost::system::error_code& ec) + { + switch (w) + { + case socket_base::wait_read: + socket_ops::poll_read(impl.socket_, impl.state_, -1, ec); + break; + case socket_base::wait_write: + socket_ops::poll_write(impl.socket_, impl.state_, -1, ec); + break; + case socket_base::wait_error: + socket_ops::poll_error(impl.socket_, impl.state_, -1, ec); + break; + default: + ec = boost::asio::error::invalid_argument; + break; + } + + return ec; + } + + // Asynchronously wait for the socket to become ready to read, ready to + // write, or to have pending error conditions. + template + void async_wait(base_implementation_type& impl, + socket_base::wait_type w, Handler& handler, const IoExecutor& io_ex) + { + bool is_continuation = + boost_asio_handler_cont_helpers::is_continuation(handler); + + // Allocate and construct an operation to wrap the handler. + typedef reactive_wait_op op; + typename op::ptr p = { boost::asio::detail::addressof(handler), + op::ptr::allocate(handler), 0 }; + p.p = new (p.v) op(success_ec_, handler, io_ex); + + BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket", + &impl, impl.socket_, "async_wait")); + + int op_type; + switch (w) + { + case socket_base::wait_read: + op_type = reactor::read_op; + break; + case socket_base::wait_write: + op_type = reactor::write_op; + break; + case socket_base::wait_error: + op_type = reactor::except_op; + break; + default: + p.p->ec_ = boost::asio::error::invalid_argument; + reactor_.post_immediate_completion(p.p, is_continuation); + p.v = p.p = 0; + return; + } + + start_op(impl, op_type, p.p, is_continuation, false, false); + p.v = p.p = 0; + } + + // Send the given data to the peer. + template + size_t send(base_implementation_type& impl, + const ConstBufferSequence& buffers, + socket_base::message_flags flags, boost::system::error_code& ec) + { + buffer_sequence_adapter bufs(buffers); + + return socket_ops::sync_send(impl.socket_, impl.state_, + bufs.buffers(), bufs.count(), flags, bufs.all_empty(), ec); + } + + // Wait until data can be sent without blocking. + size_t send(base_implementation_type& impl, const null_buffers&, + socket_base::message_flags, boost::system::error_code& ec) + { + // Wait for socket to become ready. + socket_ops::poll_write(impl.socket_, impl.state_, -1, ec); + + return 0; + } + + // Start an asynchronous send. The data being sent must be valid for the + // lifetime of the asynchronous operation. + template + void async_send(base_implementation_type& impl, + const ConstBufferSequence& buffers, socket_base::message_flags flags, + Handler& handler, const IoExecutor& io_ex) + { + bool is_continuation = + boost_asio_handler_cont_helpers::is_continuation(handler); + + // Allocate and construct an operation to wrap the handler. + typedef reactive_socket_send_op< + ConstBufferSequence, Handler, IoExecutor> op; + typename op::ptr p = { boost::asio::detail::addressof(handler), + op::ptr::allocate(handler), 0 }; + p.p = new (p.v) op(success_ec_, impl.socket_, impl.state_, + buffers, flags, handler, io_ex); + + BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket", + &impl, impl.socket_, "async_send")); + + start_op(impl, reactor::write_op, p.p, is_continuation, true, + ((impl.state_ & socket_ops::stream_oriented) + && buffer_sequence_adapter::all_empty(buffers))); + p.v = p.p = 0; + } + + // Start an asynchronous wait until data can be sent without blocking. + template + void async_send(base_implementation_type& impl, const null_buffers&, + socket_base::message_flags, Handler& handler, const IoExecutor& io_ex) + { + bool is_continuation = + boost_asio_handler_cont_helpers::is_continuation(handler); + + // Allocate and construct an operation to wrap the handler. + typedef reactive_null_buffers_op op; + typename op::ptr p = { boost::asio::detail::addressof(handler), + op::ptr::allocate(handler), 0 }; + p.p = new (p.v) op(success_ec_, handler, io_ex); + + BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket", + &impl, impl.socket_, "async_send(null_buffers)")); + + start_op(impl, reactor::write_op, p.p, is_continuation, false, false); + p.v = p.p = 0; + } + + // Receive some data from the peer. Returns the number of bytes received. + template + size_t receive(base_implementation_type& impl, + const MutableBufferSequence& buffers, + socket_base::message_flags flags, boost::system::error_code& ec) + { + buffer_sequence_adapter bufs(buffers); + + return socket_ops::sync_recv(impl.socket_, impl.state_, + bufs.buffers(), bufs.count(), flags, bufs.all_empty(), ec); + } + + // Wait until data can be received without blocking. + size_t receive(base_implementation_type& impl, const null_buffers&, + socket_base::message_flags, boost::system::error_code& ec) + { + // Wait for socket to become ready. + socket_ops::poll_read(impl.socket_, impl.state_, -1, ec); + + return 0; + } + + // Start an asynchronous receive. The buffer for the data being received + // must be valid for the lifetime of the asynchronous operation. + template + void async_receive(base_implementation_type& impl, + const MutableBufferSequence& buffers, socket_base::message_flags flags, + Handler& handler, const IoExecutor& io_ex) + { + bool is_continuation = + boost_asio_handler_cont_helpers::is_continuation(handler); + + // Allocate and construct an operation to wrap the handler. + typedef reactive_socket_recv_op_ext< + MutableBufferSequence, Handler, IoExecutor> op; + typename op::ptr p = { boost::asio::detail::addressof(handler), + op::ptr::allocate(handler), 0 }; + p.p = new (p.v) op(success_ec_, impl.socket_, impl.state_, + buffers, flags, handler, io_ex); + + BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket", + &impl, impl.socket_, "async_receive")); + + start_op(impl, + (flags & socket_base::message_out_of_band) + ? reactor::except_op : reactor::read_op, + p.p, is_continuation, + (flags & socket_base::message_out_of_band) == 0, + ((impl.state_ & socket_ops::stream_oriented) + && buffer_sequence_adapter::all_empty(buffers))); + p.v = p.p = 0; + } + + // Wait until data can be received without blocking. + template + void async_receive(base_implementation_type& impl, + const null_buffers&, socket_base::message_flags flags, + Handler& handler, const IoExecutor& io_ex) + { + bool is_continuation = + boost_asio_handler_cont_helpers::is_continuation(handler); + + // Allocate and construct an operation to wrap the handler. + typedef reactive_null_buffers_op op; + typename op::ptr p = { boost::asio::detail::addressof(handler), + op::ptr::allocate(handler), 0 }; + p.p = new (p.v) op(success_ec_, handler, io_ex); + + BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket", + &impl, impl.socket_, "async_receive(null_buffers)")); + + start_op(impl, + (flags & socket_base::message_out_of_band) + ? reactor::except_op : reactor::read_op, + p.p, is_continuation, false, false); + p.v = p.p = 0; + } + + // Receive some data with associated flags. Returns the number of bytes + // received. + template + size_t receive_with_flags(base_implementation_type& impl, + const MutableBufferSequence& buffers, + socket_base::message_flags in_flags, + socket_base::message_flags& out_flags, boost::system::error_code& ec) + { + buffer_sequence_adapter bufs(buffers); + + return socket_ops::sync_recvmsg(impl.socket_, impl.state_, + bufs.buffers(), bufs.count(), in_flags, out_flags, ec); + } + + // Wait until data can be received without blocking. + size_t receive_with_flags(base_implementation_type& impl, + const null_buffers&, socket_base::message_flags, + socket_base::message_flags& out_flags, boost::system::error_code& ec) + { + // Wait for socket to become ready. + socket_ops::poll_read(impl.socket_, impl.state_, -1, ec); + + // Clear out_flags, since we cannot give it any other sensible value when + // performing a null_buffers operation. + out_flags = 0; + + return 0; + } + + // Start an asynchronous receive. The buffer for the data being received + // must be valid for the lifetime of the asynchronous operation. + template + void async_receive_with_flags(base_implementation_type& impl, + const MutableBufferSequence& buffers, socket_base::message_flags in_flags, + socket_base::message_flags& out_flags, Handler& handler, + const IoExecutor& io_ex) + { + bool is_continuation = + boost_asio_handler_cont_helpers::is_continuation(handler); + + // Allocate and construct an operation to wrap the handler. + typedef reactive_socket_recvmsg_op_ext< + MutableBufferSequence, Handler, IoExecutor> op; + typename op::ptr p = { boost::asio::detail::addressof(handler), + op::ptr::allocate(handler), 0 }; + p.p = new (p.v) op(success_ec_, impl.socket_, buffers, + in_flags, out_flags, handler, io_ex); + + BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket", + &impl, impl.socket_, "async_receive_with_flags")); + + start_op(impl, + (in_flags & socket_base::message_out_of_band) + ? reactor::except_op : reactor::read_op, + p.p, is_continuation, + (in_flags & socket_base::message_out_of_band) == 0, false); + p.v = p.p = 0; + } + + // Wait until data can be received without blocking. + template + void async_receive_with_flags(base_implementation_type& impl, + const null_buffers&, socket_base::message_flags in_flags, + socket_base::message_flags& out_flags, Handler& handler, + const IoExecutor& io_ex) + { + bool is_continuation = + boost_asio_handler_cont_helpers::is_continuation(handler); + + // Allocate and construct an operation to wrap the handler. + typedef reactive_null_buffers_op op; + typename op::ptr p = { boost::asio::detail::addressof(handler), + op::ptr::allocate(handler), 0 }; + p.p = new (p.v) op(success_ec_, handler, io_ex); + + BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket", + &impl, impl.socket_, "async_receive_with_flags(null_buffers)")); + + // Clear out_flags, since we cannot give it any other sensible value when + // performing a null_buffers operation. + out_flags = 0; + + start_op(impl, + (in_flags & socket_base::message_out_of_band) + ? reactor::except_op : reactor::read_op, + p.p, is_continuation, false, false); + p.v = p.p = 0; + } + +protected: + // Open a new socket implementation. + BOOST_ASIO_DECL boost::system::error_code do_open( + base_implementation_type& impl, int af, + int type, int protocol, boost::system::error_code& ec); + + // Assign a native socket to a socket implementation. + BOOST_ASIO_DECL boost::system::error_code do_assign( + base_implementation_type& impl, int type, + const native_handle_type& native_socket, boost::system::error_code& ec); + + // Start the asynchronous read or write operation. + BOOST_ASIO_DECL void start_op(base_implementation_type& impl, int op_type, + reactor_op* op, bool is_continuation, bool is_non_blocking, bool noop); + + // Start the asynchronous accept operation. + BOOST_ASIO_DECL void start_accept_op(base_implementation_type& impl, + reactor_op* op, bool is_continuation, bool peer_is_open); + + // Start the asynchronous connect operation. + BOOST_ASIO_DECL void start_connect_op(base_implementation_type& impl, + reactor_op* op, bool is_continuation, + const socket_addr_type* addr, size_t addrlen); + + // The selector that performs event demultiplexing for the service. + reactor& reactor_; + + // Cached success value to avoid accessing category singleton. + const boost::system::error_code success_ec_; +}; + +} // namespace detail +} // namespace asio +} // namespace boost + +#include + +#if defined(BOOST_ASIO_HEADER_ONLY) +# include +#endif // defined(BOOST_ASIO_HEADER_ONLY) + +#endif // !defined(BOOST_ASIO_HAS_IOCP) + // && !defined(BOOST_ASIO_WINDOWS_RUNTIME) + +#endif // BOOST_ASIO_DETAIL_REACTIVE_SOCKET_SERVICE_BASE_EXT_HPP diff --git a/implementation/helper/1.76/boost/asio/detail/reactive_socket_service_base_ext_local.hpp b/implementation/helper/1.76/boost/asio/detail/reactive_socket_service_base_ext_local.hpp new file mode 100644 index 0000000..a71fce5 --- /dev/null +++ b/implementation/helper/1.76/boost/asio/detail/reactive_socket_service_base_ext_local.hpp @@ -0,0 +1,524 @@ +// +// detail/reactive_socket_service_base_ext_local.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2016-2019 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_REACTIVE_SOCKET_SERVICE_BASE_EXT_LOCAL_HPP +#define BOOST_ASIO_DETAIL_REACTIVE_SOCKET_SERVICE_BASE_EXT_LOCAL_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#if !defined(BOOST_ASIO_HAS_IOCP) \ + && !defined(BOOST_ASIO_WINDOWS_RUNTIME) + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace boost { +namespace asio { +namespace detail { + +class reactive_socket_service_base_ext_local +{ +public: + // The native type of a socket. + typedef socket_type native_handle_type; + + // The implementation type of the socket. + struct base_implementation_type + { + // The native socket representation. + socket_type socket_; + + // The current state of the socket. + socket_ops::state_type state_; + + // Per-descriptor data used by the reactor. + reactor::per_descriptor_data reactor_data_; + }; + + // Constructor. + BOOST_ASIO_DECL reactive_socket_service_base_ext_local(execution_context& context); + + // Destroy all user-defined handler objects owned by the service. + BOOST_ASIO_DECL void base_shutdown(); + + // Construct a new socket implementation. + BOOST_ASIO_DECL void construct(base_implementation_type& impl); + + // Move-construct a new socket implementation. + BOOST_ASIO_DECL void base_move_construct(base_implementation_type& impl, + base_implementation_type& other_impl); + + // Move-assign from another socket implementation. + BOOST_ASIO_DECL void base_move_assign(base_implementation_type& impl, + reactive_socket_service_base_ext_local& other_service, + base_implementation_type& other_impl); + + // Destroy a socket implementation. + BOOST_ASIO_DECL void destroy(base_implementation_type& impl); + + // Determine whether the socket is open. + bool is_open(const base_implementation_type& impl) const + { + return impl.socket_ != invalid_socket; + } + + // Destroy a socket implementation. + BOOST_ASIO_DECL boost::system::error_code close( + base_implementation_type& impl, boost::system::error_code& ec); + + // Release ownership of the socket. + BOOST_ASIO_DECL socket_type release( + base_implementation_type& impl, boost::system::error_code& ec); + + // Get the native socket representation. + native_handle_type native_handle(base_implementation_type& impl) + { + return impl.socket_; + } + + // Cancel all operations associated with the socket. + BOOST_ASIO_DECL boost::system::error_code cancel( + base_implementation_type& impl, boost::system::error_code& ec); + + // Determine whether the socket is at the out-of-band data mark. + bool at_mark(const base_implementation_type& impl, + boost::system::error_code& ec) const + { + return socket_ops::sockatmark(impl.socket_, ec); + } + + // Determine the number of bytes available for reading. + std::size_t available(const base_implementation_type& impl, + boost::system::error_code& ec) const + { + return socket_ops::available(impl.socket_, ec); + } + + // Place the socket into the state where it will listen for new connections. + boost::system::error_code listen(base_implementation_type& impl, + int backlog, boost::system::error_code& ec) + { + socket_ops::listen(impl.socket_, backlog, ec); + return ec; + } + + // Perform an IO control command on the socket. + template + boost::system::error_code io_control(base_implementation_type& impl, + IO_Control_Command& command, boost::system::error_code& ec) + { + socket_ops::ioctl(impl.socket_, impl.state_, command.name(), + static_cast(command.data()), ec); + return ec; + } + + // Gets the non-blocking mode of the socket. + bool non_blocking(const base_implementation_type& impl) const + { + return (impl.state_ & socket_ops::user_set_non_blocking) != 0; + } + + // Sets the non-blocking mode of the socket. + boost::system::error_code non_blocking(base_implementation_type& impl, + bool mode, boost::system::error_code& ec) + { + socket_ops::set_user_non_blocking(impl.socket_, impl.state_, mode, ec); + return ec; + } + + // Gets the non-blocking mode of the native socket implementation. + bool native_non_blocking(const base_implementation_type& impl) const + { + return (impl.state_ & socket_ops::internal_non_blocking) != 0; + } + + // Sets the non-blocking mode of the native socket implementation. + boost::system::error_code native_non_blocking(base_implementation_type& impl, + bool mode, boost::system::error_code& ec) + { + socket_ops::set_internal_non_blocking(impl.socket_, impl.state_, mode, ec); + return ec; + } + + // Wait for the socket to become ready to read, ready to write, or to have + // pending error conditions. + boost::system::error_code wait(base_implementation_type& impl, + socket_base::wait_type w, boost::system::error_code& ec) + { + switch (w) + { + case socket_base::wait_read: + socket_ops::poll_read(impl.socket_, impl.state_, -1, ec); + break; + case socket_base::wait_write: + socket_ops::poll_write(impl.socket_, impl.state_, -1, ec); + break; + case socket_base::wait_error: + socket_ops::poll_error(impl.socket_, impl.state_, -1, ec); + break; + default: + ec = boost::asio::error::invalid_argument; + break; + } + + return ec; + } + + // Asynchronously wait for the socket to become ready to read, ready to + // write, or to have pending error conditions. + template + void async_wait(base_implementation_type& impl, + socket_base::wait_type w, Handler& handler, const IoExecutor& io_ex) + { + bool is_continuation = + boost_asio_handler_cont_helpers::is_continuation(handler); + + // Allocate and construct an operation to wrap the handler. + typedef reactive_wait_op op; + typename op::ptr p = { boost::asio::detail::addressof(handler), + op::ptr::allocate(handler), 0 }; + p.p = new (p.v) op(success_ec_, handler, io_ex); + + BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket", + &impl, impl.socket_, "async_wait")); + + int op_type; + switch (w) + { + case socket_base::wait_read: + op_type = reactor::read_op; + break; + case socket_base::wait_write: + op_type = reactor::write_op; + break; + case socket_base::wait_error: + op_type = reactor::except_op; + break; + default: + p.p->ec_ = boost::asio::error::invalid_argument; + reactor_.post_immediate_completion(p.p, is_continuation); + p.v = p.p = 0; + return; + } + + start_op(impl, op_type, p.p, is_continuation, false, false); + p.v = p.p = 0; + } + + // Send the given data to the peer. + template + size_t send(base_implementation_type& impl, + const ConstBufferSequence& buffers, + socket_base::message_flags flags, boost::system::error_code& ec) + { + buffer_sequence_adapter bufs(buffers); + + return socket_ops::sync_send(impl.socket_, impl.state_, + bufs.buffers(), bufs.count(), flags, bufs.all_empty(), ec); + } + + // Wait until data can be sent without blocking. + size_t send(base_implementation_type& impl, const null_buffers&, + socket_base::message_flags, boost::system::error_code& ec) + { + // Wait for socket to become ready. + socket_ops::poll_write(impl.socket_, impl.state_, -1, ec); + + return 0; + } + + // Start an asynchronous send. The data being sent must be valid for the + // lifetime of the asynchronous operation. + template + void async_send(base_implementation_type& impl, + const ConstBufferSequence& buffers, socket_base::message_flags flags, + Handler& handler, const IoExecutor& io_ex) + { + bool is_continuation = + boost_asio_handler_cont_helpers::is_continuation(handler); + + // Allocate and construct an operation to wrap the handler. + typedef reactive_socket_send_op< + ConstBufferSequence, Handler, IoExecutor> op; + typename op::ptr p = { boost::asio::detail::addressof(handler), + op::ptr::allocate(handler), 0 }; + p.p = new (p.v) op(success_ec_, impl.socket_, impl.state_, + buffers, flags, handler, io_ex); + + BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket", + &impl, impl.socket_, "async_send")); + + start_op(impl, reactor::write_op, p.p, is_continuation, true, + ((impl.state_ & socket_ops::stream_oriented) + && buffer_sequence_adapter::all_empty(buffers))); + p.v = p.p = 0; + } + + // Start an asynchronous wait until data can be sent without blocking. + template + void async_send(base_implementation_type& impl, const null_buffers&, + socket_base::message_flags, Handler& handler, const IoExecutor& io_ex) + { + bool is_continuation = + boost_asio_handler_cont_helpers::is_continuation(handler); + + // Allocate and construct an operation to wrap the handler. + typedef reactive_null_buffers_op op; + typename op::ptr p = { boost::asio::detail::addressof(handler), + op::ptr::allocate(handler), 0 }; + p.p = new (p.v) op(success_ec_, handler, io_ex); + + BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket", + &impl, impl.socket_, "async_send(null_buffers)")); + + start_op(impl, reactor::write_op, p.p, is_continuation, false, false); + p.v = p.p = 0; + } + + // Receive some data from the peer. Returns the number of bytes received. + template + size_t receive(base_implementation_type& impl, + const MutableBufferSequence& buffers, + socket_base::message_flags flags, boost::system::error_code& ec) + { + buffer_sequence_adapter bufs(buffers); + + return socket_ops::sync_recv(impl.socket_, impl.state_, + bufs.buffers(), bufs.count(), flags, bufs.all_empty(), ec); + } + + // Wait until data can be received without blocking. + size_t receive(base_implementation_type& impl, const null_buffers&, + socket_base::message_flags, boost::system::error_code& ec) + { + // Wait for socket to become ready. + socket_ops::poll_read(impl.socket_, impl.state_, -1, ec); + + return 0; + } + + // Start an asynchronous receive. The buffer for the data being received + // must be valid for the lifetime of the asynchronous operation. + template + void async_receive(base_implementation_type& impl, + const MutableBufferSequence& buffers, socket_base::message_flags flags, + Handler& handler, const IoExecutor& io_ex) + { + bool is_continuation = + boost_asio_handler_cont_helpers::is_continuation(handler); + + // Allocate and construct an operation to wrap the handler. + typedef reactive_socket_recv_op_ext_local< + MutableBufferSequence, Handler, IoExecutor> op; + typename op::ptr p = { boost::asio::detail::addressof(handler), + op::ptr::allocate(handler), 0 }; + p.p = new (p.v) op(success_ec_, impl.socket_, impl.state_, + buffers, flags, handler, io_ex); + + BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket", + &impl, impl.socket_, "async_receive")); + + start_op(impl, + (flags & socket_base::message_out_of_band) + ? reactor::except_op : reactor::read_op, + p.p, is_continuation, + (flags & socket_base::message_out_of_band) == 0, + ((impl.state_ & socket_ops::stream_oriented) + && buffer_sequence_adapter::all_empty(buffers))); + p.v = p.p = 0; + } + + // Wait until data can be received without blocking. + template + void async_receive(base_implementation_type& impl, + const null_buffers&, socket_base::message_flags flags, + Handler& handler, const IoExecutor& io_ex) + { + bool is_continuation = + boost_asio_handler_cont_helpers::is_continuation(handler); + + // Allocate and construct an operation to wrap the handler. + typedef reactive_null_buffers_op op; + typename op::ptr p = { boost::asio::detail::addressof(handler), + op::ptr::allocate(handler), 0 }; + p.p = new (p.v) op(success_ec_, handler, io_ex); + + BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket", + &impl, impl.socket_, "async_receive(null_buffers)")); + + start_op(impl, + (flags & socket_base::message_out_of_band) + ? reactor::except_op : reactor::read_op, + p.p, is_continuation, false, false); + p.v = p.p = 0; + } + + // Receive some data with associated flags. Returns the number of bytes + // received. + template + size_t receive_with_flags(base_implementation_type& impl, + const MutableBufferSequence& buffers, + socket_base::message_flags in_flags, + socket_base::message_flags& out_flags, boost::system::error_code& ec) + { + buffer_sequence_adapter bufs(buffers); + + return socket_ops::sync_recvmsg(impl.socket_, impl.state_, + bufs.buffers(), bufs.count(), in_flags, out_flags, ec); + } + + // Wait until data can be received without blocking. + size_t receive_with_flags(base_implementation_type& impl, + const null_buffers&, socket_base::message_flags, + socket_base::message_flags& out_flags, boost::system::error_code& ec) + { + // Wait for socket to become ready. + socket_ops::poll_read(impl.socket_, impl.state_, -1, ec); + + // Clear out_flags, since we cannot give it any other sensible value when + // performing a null_buffers operation. + out_flags = 0; + + return 0; + } + + // Start an asynchronous receive. The buffer for the data being received + // must be valid for the lifetime of the asynchronous operation. + template + void async_receive_with_flags(base_implementation_type& impl, + const MutableBufferSequence& buffers, socket_base::message_flags in_flags, + socket_base::message_flags& out_flags, Handler& handler, + const IoExecutor& io_ex) + { + bool is_continuation = + boost_asio_handler_cont_helpers::is_continuation(handler); + + // Allocate and construct an operation to wrap the handler. + typedef reactive_socket_recvmsg_op_ext_local< + MutableBufferSequence, Handler, IoExecutor> op; + typename op::ptr p = { boost::asio::detail::addressof(handler), + op::ptr::allocate(handler), 0 }; + p.p = new (p.v) op(success_ec_, impl.socket_, buffers, + in_flags, out_flags, handler, io_ex); + + BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket", + &impl, impl.socket_, "async_receive_with_flags")); + + start_op(impl, + (in_flags & socket_base::message_out_of_band) + ? reactor::except_op : reactor::read_op, + p.p, is_continuation, + (in_flags & socket_base::message_out_of_band) == 0, false); + p.v = p.p = 0; + } + + // Wait until data can be received without blocking. + template + void async_receive_with_flags(base_implementation_type& impl, + const null_buffers&, socket_base::message_flags in_flags, + socket_base::message_flags& out_flags, Handler& handler, + const IoExecutor& io_ex) + { + bool is_continuation = + boost_asio_handler_cont_helpers::is_continuation(handler); + + // Allocate and construct an operation to wrap the handler. + typedef reactive_null_buffers_op op; + typename op::ptr p = { boost::asio::detail::addressof(handler), + op::ptr::allocate(handler), 0 }; + p.p = new (p.v) op(success_ec_, handler, io_ex); + + BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket", + &impl, impl.socket_, "async_receive_with_flags(null_buffers)")); + + // Clear out_flags, since we cannot give it any other sensible value when + // performing a null_buffers operation. + out_flags = 0; + + start_op(impl, + (in_flags & socket_base::message_out_of_band) + ? reactor::except_op : reactor::read_op, + p.p, is_continuation, false, false); + p.v = p.p = 0; + } + +protected: + // Open a new socket implementation. + BOOST_ASIO_DECL boost::system::error_code do_open( + base_implementation_type& impl, int af, + int type, int protocol, boost::system::error_code& ec); + + // Assign a native socket to a socket implementation. + BOOST_ASIO_DECL boost::system::error_code do_assign( + base_implementation_type& impl, int type, + const native_handle_type& native_socket, boost::system::error_code& ec); + + // Start the asynchronous read or write operation. + BOOST_ASIO_DECL void start_op(base_implementation_type& impl, int op_type, + reactor_op* op, bool is_continuation, bool is_non_blocking, bool noop); + + // Start the asynchronous accept operation. + BOOST_ASIO_DECL void start_accept_op(base_implementation_type& impl, + reactor_op* op, bool is_continuation, bool peer_is_open); + + // Start the asynchronous connect operation. + BOOST_ASIO_DECL void start_connect_op(base_implementation_type& impl, + reactor_op* op, bool is_continuation, + const socket_addr_type* addr, size_t addrlen); + + // The selector that performs event demultiplexing for the service. + reactor& reactor_; + + // Cached success value to avoid accessing category singleton. + const boost::system::error_code success_ec_; +}; + +} // namespace detail +} // namespace asio +} // namespace boost + +#include + +#if defined(BOOST_ASIO_HEADER_ONLY) +# include +#endif // defined(BOOST_ASIO_HEADER_ONLY) + +#endif // !defined(BOOST_ASIO_HAS_IOCP) + // && !defined(BOOST_ASIO_WINDOWS_RUNTIME) + +#endif // BOOST_ASIO_DETAIL_REACTIVE_SOCKET_SERVICE_BASE_EXT_LOCAL_HPP diff --git a/implementation/helper/1.76/boost/asio/detail/reactive_socket_service_ext.hpp b/implementation/helper/1.76/boost/asio/detail/reactive_socket_service_ext.hpp new file mode 100644 index 0000000..7254ccd --- /dev/null +++ b/implementation/helper/1.76/boost/asio/detail/reactive_socket_service_ext.hpp @@ -0,0 +1,508 @@ +// +// detail/reactive_socket_service_ext.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2019 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_boost or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_REACTIVE_SOCKET_SERVICE_EXT_HPP +#define BOOST_ASIO_DETAIL_REACTIVE_SOCKET_SERVICE_EXT_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#if !defined(BOOST_ASIO_HAS_IOCP) + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace boost { +namespace asio { +namespace detail { + +template +class reactive_socket_service_ext : + public execution_context_service_base >, + public reactive_socket_service_base_ext +{ +public: + // The protocol type. + typedef Protocol protocol_type; + + // The endpoint type. + typedef typename Protocol::endpoint endpoint_type; + + // The native type of a socket. + typedef socket_type native_handle_type; + + // The implementation type of the socket. + struct implementation_type : + reactive_socket_service_base_ext::base_implementation_type + { + // Default constructor. + implementation_type() + : protocol_(endpoint_type().protocol()) + { + } + + // The protocol associated with the socket. + protocol_type protocol_; + }; + + // Constructor. + reactive_socket_service_ext(execution_context& context) + : execution_context_service_base< + reactive_socket_service_ext >(context), + reactive_socket_service_base_ext(context) + { + } + + // Destroy all user-defined handler objects owned by the service. + void shutdown() + { + this->base_shutdown(); + } + + // Move-construct a new socket implementation. + void move_construct(implementation_type& impl, + implementation_type& other_impl) + { + this->base_move_construct(impl, other_impl); + + impl.protocol_ = other_impl.protocol_; + other_impl.protocol_ = endpoint_type().protocol(); + } + + // Move-assign from another socket implementation. + void move_assign(implementation_type& impl, + reactive_socket_service_base_ext& other_service, + implementation_type& other_impl) + { + this->base_move_assign(impl, other_service, other_impl); + + impl.protocol_ = other_impl.protocol_; + other_impl.protocol_ = endpoint_type().protocol(); + } + + // Move-construct a new socket implementation from another protocol type. + template + void converting_move_construct(implementation_type& impl, + reactive_socket_service_ext&, + typename reactive_socket_service_ext< + Protocol1>::implementation_type& other_impl) + { + this->base_move_construct(impl, other_impl); + + impl.protocol_ = protocol_type(other_impl.protocol_); + other_impl.protocol_ = typename Protocol1::endpoint().protocol(); + } + + // Open a new socket implementation. + boost::system::error_code open(implementation_type& impl, + const protocol_type& protocol, boost::system::error_code& ec) + { + if (!do_open(impl, protocol.family(), + protocol.type(), protocol.protocol(), ec)) + impl.protocol_ = protocol; + return ec; + } + + // Assign a native socket to a socket implementation. + boost::system::error_code assign(implementation_type& impl, + const protocol_type& protocol, const native_handle_type& native_socket, + boost::system::error_code& ec) + { + if (!do_assign(impl, protocol.type(), native_socket, ec)) + impl.protocol_ = protocol; + return ec; + } + + // Get the native socket representation. + native_handle_type native_handle(implementation_type& impl) + { + return impl.socket_; + } + + // Bind the socket to the specified local endpoint. + boost::system::error_code bind(implementation_type& impl, + const endpoint_type& endpoint, boost::system::error_code& ec) + { + socket_ops::bind(impl.socket_, endpoint.data(), endpoint.size(), ec); + return ec; + } + + // Set a socket option. + template + boost::system::error_code set_option(implementation_type& impl, + const Option& option, boost::system::error_code& ec) + { + socket_ops::setsockopt(impl.socket_, impl.state_, + option.level(impl.protocol_), option.name(impl.protocol_), + option.data(impl.protocol_), option.size(impl.protocol_), ec); + return ec; + } + + // Set a socket option. + template + boost::system::error_code get_option(const implementation_type& impl, + Option& option, boost::system::error_code& ec) const + { + std::size_t size = option.size(impl.protocol_); + socket_ops::getsockopt(impl.socket_, impl.state_, + option.level(impl.protocol_), option.name(impl.protocol_), + option.data(impl.protocol_), &size, ec); + if (!ec) + option.resize(impl.protocol_, size); + return ec; + } + + // Get the local endpoint. + endpoint_type local_endpoint(const implementation_type& impl, + boost::system::error_code& ec) const + { + endpoint_type endpoint; + std::size_t addr_len = endpoint.capacity(); + if (socket_ops::getsockname(impl.socket_, endpoint.data(), &addr_len, ec)) + return endpoint_type(); + endpoint.resize(addr_len); + return endpoint; + } + + // Get the remote endpoint. + endpoint_type remote_endpoint(const implementation_type& impl, + boost::system::error_code& ec) const + { + endpoint_type endpoint; + std::size_t addr_len = endpoint.capacity(); + if (socket_ops::getpeername(impl.socket_, + endpoint.data(), &addr_len, false, ec)) + return endpoint_type(); + endpoint.resize(addr_len); + return endpoint; + } + + // Disable sends or receives on the socket. + boost::system::error_code shutdown(base_implementation_type& impl, + socket_base::shutdown_type what, boost::system::error_code& ec) + { + socket_ops::shutdown(impl.socket_, what, ec); + return ec; + } + + // Send a datagram to the specified endpoint. Returns the number of bytes + // sent. + template + size_t send_to(implementation_type& impl, const ConstBufferSequence& buffers, + const endpoint_type& destination, socket_base::message_flags flags, + boost::system::error_code& ec) + { + buffer_sequence_adapter bufs(buffers); + + return socket_ops::sync_sendto(impl.socket_, impl.state_, + bufs.buffers(), bufs.count(), flags, + destination.data(), destination.size(), ec); + } + + // Wait until data can be sent without blocking. + size_t send_to(implementation_type& impl, const null_buffers&, + const endpoint_type&, socket_base::message_flags, + boost::system::error_code& ec) + { + // Wait for socket to become ready. + socket_ops::poll_write(impl.socket_, impl.state_, -1, ec); + + return 0; + } + + // Start an asynchronous send. The data being sent must be valid for the + // lifetime of the asynchronous operation. + template + void async_send_to(implementation_type& impl, + const ConstBufferSequence& buffers, + const endpoint_type& destination, socket_base::message_flags flags, + Handler& handler, const IoExecutor& io_ex) + { + bool is_continuation = + boost_asio_handler_cont_helpers::is_continuation(handler); + + // Allocate and construct an operation to wrap the handler. + typedef reactive_socket_sendto_op op; + typename op::ptr p = { boost::asio::detail::addressof(handler), + op::ptr::allocate(handler), 0 }; + p.p = new (p.v) op(success_ec_, impl.socket_, buffers, + destination, flags, handler, io_ex); + + BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket", + &impl, impl.socket_, "async_send_to")); + + start_op(impl, reactor::write_op, p.p, is_continuation, true, false); + p.v = p.p = 0; + } + + // Start an asynchronous wait until data can be sent without blocking. + template + void async_send_to(implementation_type& impl, const null_buffers&, + const endpoint_type&, socket_base::message_flags, + Handler& handler, const IoExecutor& io_ex) + { + bool is_continuation = + boost_asio_handler_cont_helpers::is_continuation(handler); + + // Allocate and construct an operation to wrap the handler. + typedef reactive_null_buffers_op op; + typename op::ptr p = { boost::asio::detail::addressof(handler), + op::ptr::allocate(handler), 0 }; + p.p = new (p.v) op(success_ec_, handler, io_ex); + + BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket", + &impl, impl.socket_, "async_send_to(null_buffers)")); + + start_op(impl, reactor::write_op, p.p, is_continuation, false, false); + p.v = p.p = 0; + } + + // Receive a datagram with the endpoint of the sender. Returns the number of + // bytes received. + template + size_t receive_from(implementation_type& impl, + const MutableBufferSequence& buffers, + endpoint_type& sender_endpoint, socket_base::message_flags flags, + boost::system::error_code& ec) + { + buffer_sequence_adapter bufs(buffers); + + std::size_t addr_len = sender_endpoint.capacity(); + std::size_t bytes_recvd = socket_ops::sync_recvfrom( + impl.socket_, impl.state_, bufs.buffers(), bufs.count(), + flags, sender_endpoint.data(), &addr_len, ec); + + if (!ec) + sender_endpoint.resize(addr_len); + + return bytes_recvd; + } + + // Wait until data can be received without blocking. + size_t receive_from(implementation_type& impl, const null_buffers&, + endpoint_type& sender_endpoint, socket_base::message_flags, + boost::system::error_code& ec) + { + // Wait for socket to become ready. + socket_ops::poll_read(impl.socket_, impl.state_, -1, ec); + + // Reset endpoint since it can be given no sensible value at this time. + sender_endpoint = endpoint_type(); + + return 0; + } + + // Start an asynchronous receive. The buffer for the data being received and + // the sender_endpoint object must both be valid for the lifetime of the + // asynchronous operation. + template + void async_receive_from(implementation_type& impl, + const MutableBufferSequence& buffers, endpoint_type& sender_endpoint, + socket_base::message_flags flags, Handler& handler, + const IoExecutor& io_ex) + { + bool is_continuation = + boost_asio_handler_cont_helpers::is_continuation(handler); + + // Allocate and construct an operation to wrap the handler. + typedef reactive_socket_recvfrom_op_ext op; + typename op::ptr p = { boost::asio::detail::addressof(handler), + op::ptr::allocate(handler), 0 }; + int protocol = impl.protocol_.type(); + p.p = new (p.v) op(success_ec_, impl.socket_, protocol, buffers, + sender_endpoint, flags, handler, io_ex); + + BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket", + &impl, impl.socket_, "async_receive_from")); + + start_op(impl, + (flags & socket_base::message_out_of_band) + ? reactor::except_op : reactor::read_op, + p.p, is_continuation, true, false); + p.v = p.p = 0; + } + + // Wait until data can be received without blocking. + template + void async_receive_from(implementation_type& impl, const null_buffers&, + endpoint_type& sender_endpoint, socket_base::message_flags flags, + Handler& handler, const IoExecutor& io_ex) + { + bool is_continuation = + boost_asio_handler_cont_helpers::is_continuation(handler); + + // Allocate and construct an operation to wrap the handler. + typedef reactive_null_buffers_op op; + typename op::ptr p = { boost::asio::detail::addressof(handler), + op::ptr::allocate(handler), 0 }; + p.p = new (p.v) op(success_ec_, handler, io_ex); + + BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket", + &impl, impl.socket_, "async_receive_from(null_buffers)")); + + // Reset endpoint since it can be given no sensible value at this time. + sender_endpoint = endpoint_type(); + + start_op(impl, + (flags & socket_base::message_out_of_band) + ? reactor::except_op : reactor::read_op, + p.p, is_continuation, false, false); + p.v = p.p = 0; + } + + // Accept a new connection. + template + boost::system::error_code accept(implementation_type& impl, + Socket& peer, endpoint_type* peer_endpoint, boost::system::error_code& ec) + { + // We cannot accept a socket that is already open. + if (peer.is_open()) + { + ec = boost::asio::error::already_open; + return ec; + } + + std::size_t addr_len = peer_endpoint ? peer_endpoint->capacity() : 0; + socket_holder new_socket(socket_ops::sync_accept(impl.socket_, + impl.state_, peer_endpoint ? peer_endpoint->data() : 0, + peer_endpoint ? &addr_len : 0, ec)); + + // On success, assign new connection to peer socket object. + if (new_socket.get() != invalid_socket) + { + if (peer_endpoint) + peer_endpoint->resize(addr_len); + peer.assign(impl.protocol_, new_socket.get(), ec); + if (!ec) + new_socket.release(); + } + + return ec; + } + + // Start an asynchronous accept. The peer and peer_endpoint objects must be + // valid until the accept's handler is invoked. + template + void async_accept(implementation_type& impl, Socket& peer, + endpoint_type* peer_endpoint, Handler& handler, const IoExecutor& io_ex) + { + bool is_continuation = + boost_asio_handler_cont_helpers::is_continuation(handler); + + // Allocate and construct an operation to wrap the handler. + typedef reactive_socket_accept_op op; + typename op::ptr p = { boost::asio::detail::addressof(handler), + op::ptr::allocate(handler), 0 }; + p.p = new (p.v) op(success_ec_, impl.socket_, impl.state_, peer, + impl.protocol_, peer_endpoint, handler, io_ex); + + BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket", + &impl, impl.socket_, "async_accept")); + + start_accept_op(impl, p.p, is_continuation, peer.is_open()); + p.v = p.p = 0; + } + +#if defined(BOOST_ASIO_HAS_MOVE) + // Start an asynchronous accept. The peer_endpoint object must be valid until + // the accept's handler is invoked. + template + void async_move_accept(implementation_type& impl, + const PeerIoExecutor& peer_io_ex, endpoint_type* peer_endpoint, + Handler& handler, const IoExecutor& io_ex) + { + bool is_continuation = + boost_asio_handler_cont_helpers::is_continuation(handler); + + // Allocate and construct an operation to wrap the handler. + typedef reactive_socket_move_accept_op op; + typename op::ptr p = { boost::asio::detail::addressof(handler), + op::ptr::allocate(handler), 0 }; + p.p = new (p.v) op(success_ec_, peer_io_ex, impl.socket_, impl.state_, + impl.protocol_, peer_endpoint, handler, io_ex); + + BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket", + &impl, impl.socket_, "async_accept")); + + start_accept_op(impl, p.p, is_continuation, false); + p.v = p.p = 0; + } +#endif // defined(BOOST_ASIO_HAS_MOVE) + + // Connect the socket to the specified endpoint. + boost::system::error_code connect(implementation_type& impl, + const endpoint_type& peer_endpoint, boost::system::error_code& ec) + { + socket_ops::sync_connect(impl.socket_, + peer_endpoint.data(), peer_endpoint.size(), ec); + return ec; + } + + // Start an asynchronous connect. + template + void async_connect(implementation_type& impl, + const endpoint_type& peer_endpoint, + Handler& handler, const IoExecutor& io_ex) + { + bool is_continuation = + boost_asio_handler_cont_helpers::is_continuation(handler); + + // Allocate and construct an operation to wrap the handler. + typedef reactive_socket_connect_op op; + typename op::ptr p = { boost::asio::detail::addressof(handler), + op::ptr::allocate(handler), 0 }; + p.p = new (p.v) op(success_ec_, impl.socket_, handler, io_ex); + + BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket", + &impl, impl.socket_, "async_connect")); + + start_connect_op(impl, p.p, is_continuation, + peer_endpoint.data(), peer_endpoint.size()); + p.v = p.p = 0; + } +}; + +} // namespace detail +} // namespace asio +} // namespace boost + +#include + +#endif // !defined(BOOST_ASIO_HAS_IOCP) + +#endif // BOOST_ASIO_DETAIL_REACTIVE_SOCKET_SERVICE_EXT_HPP diff --git a/implementation/helper/1.76/boost/asio/detail/reactive_socket_service_ext_local.hpp b/implementation/helper/1.76/boost/asio/detail/reactive_socket_service_ext_local.hpp new file mode 100644 index 0000000..8ac3265 --- /dev/null +++ b/implementation/helper/1.76/boost/asio/detail/reactive_socket_service_ext_local.hpp @@ -0,0 +1,508 @@ +// +// detail/reactive_socket_service_ext_local.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2019 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_REACTIVE_SOCKET_SERVICE_EXT_LOCAL_HPP +#define BOOST_ASIO_DETAIL_REACTIVE_SOCKET_SERVICE_EXT_LOCAL_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#if !defined(BOOST_ASIO_HAS_IOCP) + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace boost { +namespace asio { +namespace detail { + +template +class reactive_socket_service_ext_local : + public execution_context_service_base >, + public reactive_socket_service_base_ext_local +{ +public: + // The protocol type. + typedef Protocol protocol_type; + + // The endpoint type. + typedef typename Protocol::endpoint endpoint_type; + + // The native type of a socket. + typedef socket_type native_handle_type; + + // The implementation type of the socket. + struct implementation_type : + reactive_socket_service_base_ext_local::base_implementation_type + { + // Default constructor. + implementation_type() + : protocol_(endpoint_type().protocol()) + { + } + + // The protocol associated with the socket. + protocol_type protocol_; + }; + + // Constructor. + reactive_socket_service_ext_local(execution_context& context) + : execution_context_service_base< + reactive_socket_service_ext_local >(context), + reactive_socket_service_base_ext_local(context) + { + } + + // Destroy all user-defined handler objects owned by the service. + void shutdown() + { + this->base_shutdown(); + } + + // Move-construct a new socket implementation. + void move_construct(implementation_type& impl, + implementation_type& other_impl) + { + this->base_move_construct(impl, other_impl); + + impl.protocol_ = other_impl.protocol_; + other_impl.protocol_ = endpoint_type().protocol(); + } + + // Move-assign from another socket implementation. + void move_assign(implementation_type& impl, + reactive_socket_service_base_ext_local& other_service, + implementation_type& other_impl) + { + this->base_move_assign(impl, other_service, other_impl); + + impl.protocol_ = other_impl.protocol_; + other_impl.protocol_ = endpoint_type().protocol(); + } + + // Move-construct a new socket implementation from another protocol type. + template + void converting_move_construct(implementation_type& impl, + reactive_socket_service_ext_local&, + typename reactive_socket_service_ext_local< + Protocol1>::implementation_type& other_impl) + { + this->base_move_construct(impl, other_impl); + + impl.protocol_ = protocol_type(other_impl.protocol_); + other_impl.protocol_ = typename Protocol1::endpoint().protocol(); + } + + // Open a new socket implementation. + boost::system::error_code open(implementation_type& impl, + const protocol_type& protocol, boost::system::error_code& ec) + { + if (!do_open(impl, protocol.family(), + protocol.type(), protocol.protocol(), ec)) + impl.protocol_ = protocol; + return ec; + } + + // Assign a native socket to a socket implementation. + boost::system::error_code assign(implementation_type& impl, + const protocol_type& protocol, const native_handle_type& native_socket, + boost::system::error_code& ec) + { + if (!do_assign(impl, protocol.type(), native_socket, ec)) + impl.protocol_ = protocol; + return ec; + } + + // Get the native socket representation. + native_handle_type native_handle(implementation_type& impl) + { + return impl.socket_; + } + + // Bind the socket to the specified local endpoint. + boost::system::error_code bind(implementation_type& impl, + const endpoint_type& endpoint, boost::system::error_code& ec) + { + socket_ops::bind(impl.socket_, endpoint.data(), endpoint.size(), ec); + return ec; + } + + // Set a socket option. + template + boost::system::error_code set_option(implementation_type& impl, + const Option& option, boost::system::error_code& ec) + { + socket_ops::setsockopt(impl.socket_, impl.state_, + option.level(impl.protocol_), option.name(impl.protocol_), + option.data(impl.protocol_), option.size(impl.protocol_), ec); + return ec; + } + + // Set a socket option. + template + boost::system::error_code get_option(const implementation_type& impl, + Option& option, boost::system::error_code& ec) const + { + std::size_t size = option.size(impl.protocol_); + socket_ops::getsockopt(impl.socket_, impl.state_, + option.level(impl.protocol_), option.name(impl.protocol_), + option.data(impl.protocol_), &size, ec); + if (!ec) + option.resize(impl.protocol_, size); + return ec; + } + + // Get the local endpoint. + endpoint_type local_endpoint(const implementation_type& impl, + boost::system::error_code& ec) const + { + endpoint_type endpoint; + std::size_t addr_len = endpoint.capacity(); + if (socket_ops::getsockname(impl.socket_, endpoint.data(), &addr_len, ec)) + return endpoint_type(); + endpoint.resize(addr_len); + return endpoint; + } + + // Get the remote endpoint. + endpoint_type remote_endpoint(const implementation_type& impl, + boost::system::error_code& ec) const + { + endpoint_type endpoint; + std::size_t addr_len = endpoint.capacity(); + if (socket_ops::getpeername(impl.socket_, + endpoint.data(), &addr_len, false, ec)) + return endpoint_type(); + endpoint.resize(addr_len); + return endpoint; + } + + // Disable sends or receives on the socket. + boost::system::error_code shutdown(base_implementation_type& impl, + socket_base::shutdown_type what, boost::system::error_code& ec) + { + socket_ops::shutdown(impl.socket_, what, ec); + return ec; + } + + // Send a datagram to the specified endpoint. Returns the number of bytes + // sent. + template + size_t send_to(implementation_type& impl, const ConstBufferSequence& buffers, + const endpoint_type& destination, socket_base::message_flags flags, + boost::system::error_code& ec) + { + buffer_sequence_adapter bufs(buffers); + + return socket_ops::sync_sendto(impl.socket_, impl.state_, + bufs.buffers(), bufs.count(), flags, + destination.data(), destination.size(), ec); + } + + // Wait until data can be sent without blocking. + size_t send_to(implementation_type& impl, const null_buffers&, + const endpoint_type&, socket_base::message_flags, + boost::system::error_code& ec) + { + // Wait for socket to become ready. + socket_ops::poll_write(impl.socket_, impl.state_, -1, ec); + + return 0; + } + + // Start an asynchronous send. The data being sent must be valid for the + // lifetime of the asynchronous operation. + template + void async_send_to(implementation_type& impl, + const ConstBufferSequence& buffers, + const endpoint_type& destination, socket_base::message_flags flags, + Handler& handler, const IoExecutor& io_ex) + { + bool is_continuation = + boost_asio_handler_cont_helpers::is_continuation(handler); + + // Allocate and construct an operation to wrap the handler. + typedef reactive_socket_sendto_op op; + typename op::ptr p = { boost::asio::detail::addressof(handler), + op::ptr::allocate(handler), 0 }; + p.p = new (p.v) op(success_ec_, impl.socket_, buffers, + destination, flags, handler, io_ex); + + BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket", + &impl, impl.socket_, "async_send_to")); + + start_op(impl, reactor::write_op, p.p, is_continuation, true, false); + p.v = p.p = 0; + } + + // Start an asynchronous wait until data can be sent without blocking. + template + void async_send_to(implementation_type& impl, const null_buffers&, + const endpoint_type&, socket_base::message_flags, + Handler& handler, const IoExecutor& io_ex) + { + bool is_continuation = + boost_asio_handler_cont_helpers::is_continuation(handler); + + // Allocate and construct an operation to wrap the handler. + typedef reactive_null_buffers_op op; + typename op::ptr p = { boost::asio::detail::addressof(handler), + op::ptr::allocate(handler), 0 }; + p.p = new (p.v) op(success_ec_, handler, io_ex); + + BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket", + &impl, impl.socket_, "async_send_to(null_buffers)")); + + start_op(impl, reactor::write_op, p.p, is_continuation, false, false); + p.v = p.p = 0; + } + + // Receive a datagram with the endpoint of the sender. Returns the number of + // bytes received. + template + size_t receive_from(implementation_type& impl, + const MutableBufferSequence& buffers, + endpoint_type& sender_endpoint, socket_base::message_flags flags, + boost::system::error_code& ec) + { + buffer_sequence_adapter bufs(buffers); + + std::size_t addr_len = sender_endpoint.capacity(); + std::size_t bytes_recvd = socket_ops::sync_recvfrom( + impl.socket_, impl.state_, bufs.buffers(), bufs.count(), + flags, sender_endpoint.data(), &addr_len, ec); + + if (!ec) + sender_endpoint.resize(addr_len); + + return bytes_recvd; + } + + // Wait until data can be received without blocking. + size_t receive_from(implementation_type& impl, const null_buffers&, + endpoint_type& sender_endpoint, socket_base::message_flags, + boost::system::error_code& ec) + { + // Wait for socket to become ready. + socket_ops::poll_read(impl.socket_, impl.state_, -1, ec); + + // Reset endpoint since it can be given no sensible value at this time. + sender_endpoint = endpoint_type(); + + return 0; + } + + // Start an asynchronous receive. The buffer for the data being received and + // the sender_endpoint object must both be valid for the lifetime of the + // asynchronous operation. + template + void async_receive_from(implementation_type& impl, + const MutableBufferSequence& buffers, endpoint_type& sender_endpoint, + socket_base::message_flags flags, Handler& handler, + const IoExecutor& io_ex) + { + bool is_continuation = + boost_asio_handler_cont_helpers::is_continuation(handler); + + // Allocate and construct an operation to wrap the handler. + typedef reactive_socket_recvfrom_op_ext_local op; + typename op::ptr p = { boost::asio::detail::addressof(handler), + op::ptr::allocate(handler), 0 }; + int protocol = impl.protocol_.type(); + p.p = new (p.v) op(success_ec_, impl.socket_, protocol, buffers, + sender_endpoint, flags, handler, io_ex); + + BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket", + &impl, impl.socket_, "async_receive_from")); + + start_op(impl, + (flags & socket_base::message_out_of_band) + ? reactor::except_op : reactor::read_op, + p.p, is_continuation, true, false); + p.v = p.p = 0; + } + + // Wait until data can be received without blocking. + template + void async_receive_from(implementation_type& impl, const null_buffers&, + endpoint_type& sender_endpoint, socket_base::message_flags flags, + Handler& handler, const IoExecutor& io_ex) + { + bool is_continuation = + boost_asio_handler_cont_helpers::is_continuation(handler); + + // Allocate and construct an operation to wrap the handler. + typedef reactive_null_buffers_op op; + typename op::ptr p = { boost::asio::detail::addressof(handler), + op::ptr::allocate(handler), 0 }; + p.p = new (p.v) op(success_ec_, handler, io_ex); + + BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket", + &impl, impl.socket_, "async_receive_from(null_buffers)")); + + // Reset endpoint since it can be given no sensible value at this time. + sender_endpoint = endpoint_type(); + + start_op(impl, + (flags & socket_base::message_out_of_band) + ? reactor::except_op : reactor::read_op, + p.p, is_continuation, false, false); + p.v = p.p = 0; + } + + // Accept a new connection. + template + boost::system::error_code accept(implementation_type& impl, + Socket& peer, endpoint_type* peer_endpoint, boost::system::error_code& ec) + { + // We cannot accept a socket that is already open. + if (peer.is_open()) + { + ec = boost::asio::error::already_open; + return ec; + } + + std::size_t addr_len = peer_endpoint ? peer_endpoint->capacity() : 0; + socket_holder new_socket(socket_ops::sync_accept(impl.socket_, + impl.state_, peer_endpoint ? peer_endpoint->data() : 0, + peer_endpoint ? &addr_len : 0, ec)); + + // On success, assign new connection to peer socket object. + if (new_socket.get() != invalid_socket) + { + if (peer_endpoint) + peer_endpoint->resize(addr_len); + peer.assign(impl.protocol_, new_socket.get(), ec); + if (!ec) + new_socket.release(); + } + + return ec; + } + + // Start an asynchronous accept. The peer and peer_endpoint objects must be + // valid until the accept's handler is invoked. + template + void async_accept(implementation_type& impl, Socket& peer, + endpoint_type* peer_endpoint, Handler& handler, const IoExecutor& io_ex) + { + bool is_continuation = + boost_asio_handler_cont_helpers::is_continuation(handler); + + // Allocate and construct an operation to wrap the handler. + typedef reactive_socket_accept_op op; + typename op::ptr p = { boost::asio::detail::addressof(handler), + op::ptr::allocate(handler), 0 }; + p.p = new (p.v) op(success_ec_, impl.socket_, impl.state_, peer, + impl.protocol_, peer_endpoint, handler, io_ex); + + BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket", + &impl, impl.socket_, "async_accept")); + + start_accept_op(impl, p.p, is_continuation, peer.is_open()); + p.v = p.p = 0; + } + +#if defined(BOOST_ASIO_HAS_MOVE) + // Start an asynchronous accept. The peer_endpoint object must be valid until + // the accept's handler is invoked. + template + void async_move_accept(implementation_type& impl, + const PeerIoExecutor& peer_io_ex, endpoint_type* peer_endpoint, + Handler& handler, const IoExecutor& io_ex) + { + bool is_continuation = + boost_asio_handler_cont_helpers::is_continuation(handler); + + // Allocate and construct an operation to wrap the handler. + typedef reactive_socket_move_accept_op op; + typename op::ptr p = { boost::asio::detail::addressof(handler), + op::ptr::allocate(handler), 0 }; + p.p = new (p.v) op(success_ec_, peer_io_ex, impl.socket_, impl.state_, + impl.protocol_, peer_endpoint, handler, io_ex); + + BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket", + &impl, impl.socket_, "async_accept")); + + start_accept_op(impl, p.p, is_continuation, false); + p.v = p.p = 0; + } +#endif // defined(BOOST_ASIO_HAS_MOVE) + + // Connect the socket to the specified endpoint. + boost::system::error_code connect(implementation_type& impl, + const endpoint_type& peer_endpoint, boost::system::error_code& ec) + { + socket_ops::sync_connect(impl.socket_, + peer_endpoint.data(), peer_endpoint.size(), ec); + return ec; + } + + // Start an asynchronous connect. + template + void async_connect(implementation_type& impl, + const endpoint_type& peer_endpoint, + Handler& handler, const IoExecutor& io_ex) + { + bool is_continuation = + boost_asio_handler_cont_helpers::is_continuation(handler); + + // Allocate and construct an operation to wrap the handler. + typedef reactive_socket_connect_op op; + typename op::ptr p = { boost::asio::detail::addressof(handler), + op::ptr::allocate(handler), 0 }; + p.p = new (p.v) op(success_ec_, impl.socket_, handler, io_ex); + + BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket", + &impl, impl.socket_, "async_connect")); + + start_connect_op(impl, p.p, is_continuation, + peer_endpoint.data(), peer_endpoint.size()); + p.v = p.p = 0; + } +}; + +} // namespace detail +} // namespace asio +} // namespace boost + +#include + +#endif // !defined(BOOST_ASIO_HAS_IOCP) + +#endif // BOOST_ASIO_DETAIL_REACTIVE_SOCKET_SERVICE_EXT_LOCAL_HPP diff --git a/implementation/helper/1.76/boost/asio/detail/reactor_op_ext.hpp b/implementation/helper/1.76/boost/asio/detail/reactor_op_ext.hpp new file mode 100644 index 0000000..697cd9f --- /dev/null +++ b/implementation/helper/1.76/boost/asio/detail/reactor_op_ext.hpp @@ -0,0 +1,43 @@ +// +// detail/reactor_op_ext.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2016-2019 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_boost or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_REACTOR_OP_EXT_HPP +#define BOOST_ASIO_DETAIL_REACTOR_OP_EXT_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +namespace boost { +namespace asio { +namespace detail { + +class reactor_op_ext + : public reactor_op +{ +public: + // The destination address + boost::asio::ip::address da_; + + reactor_op_ext(const boost::system::error_code& success_ec, + perform_func_type perform_func, func_type complete_func) + : reactor_op(success_ec, perform_func, complete_func) + { + } +}; + +} // namespace detail +} // namespace asio +} // namespace boost + +#endif // BOOST_ASIO_DETAIL_REACTOR_OP_EXT_HPP diff --git a/implementation/helper/1.76/boost/asio/detail/reactor_op_ext_local.hpp b/implementation/helper/1.76/boost/asio/detail/reactor_op_ext_local.hpp new file mode 100644 index 0000000..3d9ae5f --- /dev/null +++ b/implementation/helper/1.76/boost/asio/detail/reactor_op_ext_local.hpp @@ -0,0 +1,44 @@ +// +// detail/reactor_op_ext_local.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2016-2019 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_boost or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_REACTOR_OP_EXT_LOCAL_HPP +#define BOOST_ASIO_DETAIL_REACTOR_OP_EXT_LOCAL_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +namespace boost { +namespace asio { +namespace detail { + +class reactor_op_ext_local + : public reactor_op +{ +public: + // Credentials + std::uint32_t uid_; + std::uint32_t gid_; + + reactor_op_ext_local(const boost::system::error_code& success_ec, + perform_func_type perform_func, func_type complete_func) + : reactor_op(success_ec, perform_func, complete_func) + { + } +}; + +} // namespace detail +} // namespace asio +} // namespace boost + +#endif // BOOST_ASIO_DETAIL_REACTOR_OP_EXT_LOCAL_HPP diff --git a/implementation/helper/1.76/boost/asio/detail/socket_ops_ext.hpp b/implementation/helper/1.76/boost/asio/detail/socket_ops_ext.hpp new file mode 100644 index 0000000..9285fed --- /dev/null +++ b/implementation/helper/1.76/boost/asio/detail/socket_ops_ext.hpp @@ -0,0 +1,62 @@ +// +// detail/socket_ops_ext.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (C) 2016-2019 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_boost or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_SOCKET_OPS_EXT_HPP +#define BOOST_ASIO_DETAIL_SOCKET_OPS_EXT_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +namespace boost { +namespace asio { +namespace detail { +namespace socket_ops { + +BOOST_ASIO_DECL signed_size_type recvfrom(socket_type s, buf* bufs, + size_t count, int flags, socket_addr_type* addr, + std::size_t* addrlen, boost::system::error_code& ec, + boost::asio::ip::address& da); + +BOOST_ASIO_DECL size_t sync_recvfrom(socket_type s, state_type state, + buf* bufs, size_t count, int flags, socket_addr_type* addr, + std::size_t* addrlen, boost::system::error_code& ec, boost::asio::ip::address& da); + +#if defined(BOOST_ASIO_HAS_IOCP) + +BOOST_ASIO_DECL void complete_iocp_recvfrom( + const weak_cancel_token_type& cancel_token, + boost::system::error_code& ec, + boost::asio::ip::address& da); + +#else // defined(BOOST_ASIO_HAS_IOCP) + +BOOST_ASIO_DECL bool non_blocking_recvfrom(socket_type s, + buf* bufs, size_t count, int flags, + socket_addr_type* addr, std::size_t* addrlen, + boost::system::error_code& ec, size_t& bytes_transferred, + boost::asio::ip::address& da); + +#endif // defined(BOOST_ASIO_HAS_IOCP) + +} // namespace socket_ops +} // namespace detail +} // namespace asio +} // namespace boost + + +#if defined(BOOST_ASIO_HEADER_ONLY) +# include +#endif // defined(BOOST_ASIO_HEADER_ONLY) + +#endif // BOOST_EXT_ASIO_DETAIL_SOCKET_OPS_HPP diff --git a/implementation/helper/1.76/boost/asio/detail/socket_ops_ext_local.hpp b/implementation/helper/1.76/boost/asio/detail/socket_ops_ext_local.hpp new file mode 100644 index 0000000..a937bb6 --- /dev/null +++ b/implementation/helper/1.76/boost/asio/detail/socket_ops_ext_local.hpp @@ -0,0 +1,95 @@ +// +// detail/socket_ops_ext_local.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (C) 2016-2019 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_boost or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_SOCKET_OPS_EXT_LOCAL_HPP +#define BOOST_ASIO_DETAIL_SOCKET_OPS_EXT_LOCAL_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include + +#include + +namespace boost { +namespace asio { +namespace detail { +namespace socket_ops { + +BOOST_ASIO_DECL signed_size_type recv(socket_type s, buf* bufs, + size_t count, int flags, boost::system::error_code& ec, + std::uint32_t& uid, std::uint32_t& gid); + +BOOST_ASIO_DECL size_t sync_recv(socket_type s, state_type state, buf* bufs, + size_t count, int flags, bool all_empty, boost::system::error_code& ec, + std::uint32_t& uid, std::uint32_t& gid); + +#if defined(BOOST_ASIO_HAS_IOCP) + +BOOST_ASIO_DECL void complete_iocp_recv(state_type state, + const weak_cancel_token_type& cancel_token, bool all_empty, + boost::system::error_code& ec, size_t bytes_transferred, + std::uint32_t& uid, std::uint32_t& gid); + +#else // defined(BOOST_ASIO_HAS_IOCP) + +BOOST_ASIO_DECL bool non_blocking_recv(socket_type s, + buf* bufs, size_t count, int flags, bool is_stream, + boost::system::error_code& ec, size_t& bytes_transferred, + std::uint32_t& uid, std::uint32_t& gid); + +#endif // defined(BOOST_ASIO_HAS_IOCP) + +BOOST_ASIO_DECL signed_size_type recvfrom(socket_type s, buf* bufs, + size_t count, int flags, socket_addr_type* addr, + std::size_t* addrlen, boost::system::error_code& ec, + std::uint32_t& uid, std::uint32_t& gid); + +BOOST_ASIO_DECL size_t sync_recvfrom(socket_type s, state_type state, + buf* bufs, size_t count, int flags, socket_addr_type* addr, + std::size_t* addrlen, boost::system::error_code& ec, + std::uint32_t& uid, std::uint32_t& gid); + +#if defined(BOOST_ASIO_HAS_IOCP) + +BOOST_ASIO_DECL void complete_iocp_recvfrom( + const weak_cancel_token_type& cancel_token, + boost::system::error_code& ec, + std::uint32_t& uid, std::uint32_t& gid); + +#else // defined(BOOST_ASIO_HAS_IOCP) + +BOOST_ASIO_DECL bool non_blocking_recvfrom(socket_type s, + buf* bufs, size_t count, int flags, + socket_addr_type* addr, std::size_t* addrlen, + boost::system::error_code& ec, size_t& bytes_transferred, + std::uint32_t& uid, std::uint32_t& gid); + +#endif // defined(BOOST_ASIO_HAS_IOCP) + + +} // namespace socket_ops +} // namespace detail +} // namespace asio +} // namespace boost + +#include + +#if defined(BOOST_ASIO_HEADER_ONLY) +# include +#endif // defined(BOOST_ASIO_HEADER_ONLY) + +#endif // BOOST_ASIO_DETAIL_SOCKET_OPS_EXT_LOCAL_HPP diff --git a/implementation/helper/1.76/boost/asio/ip/udp_ext.hpp b/implementation/helper/1.76/boost/asio/ip/udp_ext.hpp new file mode 100644 index 0000000..6ce2ac4 --- /dev/null +++ b/implementation/helper/1.76/boost/asio/ip/udp_ext.hpp @@ -0,0 +1,115 @@ +// +// ip/udp_ext.hpp +// ~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (C) 2016-2018 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_boost or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_IP_UDP_EXT_HPP +#define BOOST_ASIO_IP_UDP_EXT_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace boost { +namespace asio { +namespace ip { + +/// Encapsulates the flags needed for UDP. +/** + * The boost::asio::ip::udp_ext class contains flags necessary for UDP sockets. + * + * @par Thread Safety + * @e Distinct @e objects: Safe.@n + * @e Shared @e objects: Safe. + * + * @par Concepts: + * Protocol, InternetProtocol. + */ +class udp_ext +{ +public: + /// The type of a UDP endpoint. + typedef basic_endpoint endpoint; + + /// Construct to represent the IPv4 UDP protocol. + static udp_ext v4() + { + return udp_ext(BOOST_ASIO_OS_DEF(AF_INET)); + } + + /// Construct to represent the IPv6 UDP protocol. + static udp_ext v6() + { + return udp_ext(BOOST_ASIO_OS_DEF(AF_INET6)); + } + + /// Obtain an identifier for the type of the protocol. + int type() const + { + return BOOST_ASIO_OS_DEF(SOCK_DGRAM); + } + + /// Obtain an identifier for the protocol. + int protocol() const + { + return BOOST_ASIO_OS_DEF(IPPROTO_UDP); + } + + /// Obtain an identifier for the protocol family. + int family() const + { + return family_; + } + + /// The UDP socket type. + typedef basic_datagram_socket_ext socket; + + /// The UDP resolver type. + typedef basic_resolver resolver; + + /// Compare two protocols for equality. + friend bool operator==(const udp_ext& p1, const udp_ext& p2) + { + return p1.family_ == p2.family_; + } + + /// Compare two protocols for inequality. + friend bool operator!=(const udp_ext& p1, const udp_ext& p2) + { + return p1.family_ != p2.family_; + } + +private: + // Construct with a specific family. + explicit udp_ext(int protocol_family) + : family_(protocol_family) + { + } + + int family_; +}; + +} // namespace ip +} // namespace asio +} // namespace boost + +#include + +#endif // BOOST_ASIO_IP_UDP_EXT_HPP diff --git a/implementation/helper/1.76/boost/asio/local/stream_protocol_ext.hpp b/implementation/helper/1.76/boost/asio/local/stream_protocol_ext.hpp new file mode 100644 index 0000000..7c57c62 --- /dev/null +++ b/implementation/helper/1.76/boost/asio/local/stream_protocol_ext.hpp @@ -0,0 +1,93 @@ +// +// local/stream_protocol_ext.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2019 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_LOCAL_STREAM_PROTOCOL_EXT_HPP +#define BOOST_ASIO_LOCAL_STREAM_PROTOCOL_EXT_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#if defined(BOOST_ASIO_HAS_LOCAL_SOCKETS) \ + || defined(GENERATING_DOCUMENTATION) + +#include +#include +#include +#include +#include + +#include + +namespace boost { +namespace asio { +namespace local { + +/// Encapsulates the flags needed for stream-oriented UNIX sockets. +/** + * The boost::asio::local::stream_protocol class contains flags necessary for + * stream-oriented UNIX domain sockets. + * + * @par Thread Safety + * @e Distinct @e objects: Safe.@n + * @e Shared @e objects: Safe. + * + * @par Concepts: + * Protocol. + */ +class stream_protocol_ext +{ +public: + /// Obtain an identifier for the type of the protocol. + int type() const + { + return SOCK_STREAM; + } + + /// Obtain an identifier for the protocol. + int protocol() const + { + return 0; + } + + /// Obtain an identifier for the protocol family. + int family() const + { + return AF_UNIX; + } + + /// The type of a UNIX domain endpoint. + typedef basic_endpoint endpoint; + + /// The UNIX domain socket type. + typedef basic_stream_socket_ext socket; + + /// The UNIX domain acceptor type. + typedef basic_socket_acceptor_ext acceptor; + +#if !defined(BOOST_ASIO_NO_IOSTREAM) + /// The UNIX domain iostream type. + typedef basic_socket_iostream iostream; +#endif // !defined(BOOST_ASIO_NO_IOSTREAM) +}; + +} // namespace local +} // namespace asio +} // namespace boost + +#include + +#endif // defined(BOOST_ASIO_HAS_LOCAL_SOCKETS) + // || defined(GENERATING_DOCUMENTATION) + +#endif // BOOST_ASIO_LOCAL_STREAM_PROTOCOL_EXT_HPP -- 2.35.1