new file mode 100644
@@ -0,0 +1,28 @@
+From 72a0489833311525b6e91c560dad772431b31214 Mon Sep 17 00:00:00 2001
+From: Yi Zhao <yi.zhao@windriver.com>
+Date: Wed, 2 Mar 2022 14:51:13 +0800
+Subject: [PATCH] Fix pkgconfig dir for multilib
+
+Upstream-Status: Pending
+
+Signed-off-by: Yi Zhao <yi.zhao@windriver.com>
+---
+ CMakeLists.txt | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/CMakeLists.txt b/CMakeLists.txt
+index 65148a5c..3b9d0248 100644
+--- a/CMakeLists.txt
++++ b/CMakeLists.txt
+@@ -580,7 +580,7 @@ endif()
+ # create pkg-config file
+ if(NOT WIN32)
+ configure_file(vsomeip3.pc.in ${PROJECT_BINARY_DIR}/vsomeip3.pc @ONLY)
+- install(FILES ${PROJECT_BINARY_DIR}/vsomeip3.pc DESTINATION lib/pkgconfig)
++ install(FILES ${PROJECT_BINARY_DIR}/vsomeip3.pc DESTINATION ${INSTALL_LIB_DIR}/pkgconfig)
+ endif()
+
+ ##############################################################################
+--
+2.25.1
+
new file mode 100644
@@ -0,0 +1,28 @@
+From eaefba5ed36396176f09dd2084b07c6d19497863 Mon Sep 17 00:00:00 2001
+From: Yi Zhao <yi.zhao@windriver.com>
+Date: Wed, 9 Mar 2022 11:48:44 +0800
+Subject: [PATCH] Install example configuration files to /etc/vsomeip
+
+Upstream-Status: Inappropriate [configuration]
+
+Signed-off-by: Yi Zhao <yi.zhao@windriver.com>
+---
+ CMakeLists.txt | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/CMakeLists.txt b/CMakeLists.txt
+index 3b9d0248..4f8b66b8 100644
+--- a/CMakeLists.txt
++++ b/CMakeLists.txt
+@@ -479,7 +479,7 @@ install(FILES ${PROJECT_BINARY_DIR}/vsomeip.pc DESTINATION lib/pkgconfig)
+ endif ()
+
+ install (
+- FILES ${EXAMPLE_CONFIG_FILES} DESTINATION etc/vsomeip COMPONENT config
++ FILES ${EXAMPLE_CONFIG_FILES} DESTINATION ${DEFAULT_CONFIGURATION_FOLDER} COMPONENT config
+ )
+
+ # Add all targets to the build-tree export set
+--
+2.25.1
+
new file mode 100644
@@ -0,0 +1,68 @@
+From 9669b1ff360b04dc8a6fe1e283281ce77df38fae Mon Sep 17 00:00:00 2001
+From: Yi Zhao <yi.zhao@windriver.com>
+Date: Tue, 11 Jul 2023 16:53:46 +0800
+Subject: [PATCH] Do not build external gtest
+
+We don't need to build external gtest since we already depend on
+googletest.
+
+Upstream-Status: Inappropriate [embedded specific]
+
+Signed-off-by: Yi Zhao <yi.zhao@windriver.com>
+---
+ CMakeLists.txt | 30 +++---------------------------
+ 1 file changed, 3 insertions(+), 27 deletions(-)
+
+diff --git a/CMakeLists.txt b/CMakeLists.txt
+index 4f8b66b8..745cc455 100644
+--- a/CMakeLists.txt
++++ b/CMakeLists.txt
+@@ -18,14 +18,6 @@ set (VSOMEIP_VERSION ${VSOMEIP_MAJOR_VERSION}.${VSOMEIP_MINOR_VERSION}.${VSOMEIP
+ set (PACKAGE_VERSION ${VSOMEIP_VERSION}) # Used in documentation/doxygen.in
+ set (CMAKE_VERBOSE_MAKEFILE off)
+
+-if (NOT GTEST_ROOT)
+- if (DEFINED ENV{GTEST_ROOT})
+- set(GTEST_ROOT $ENV{GTEST_ROOT})
+- else()
+- set(GTEST_ROOT "n/a" CACHE STRING "Path to root folder of googletest. Must be set for building the tests.")
+- endif()
+-endif()
+-
+ ###################################################################################################
+ # see http://www.cmake.org/Wiki/CMake/Tutorials/How_to_create_a_ProjectConfig.cmake_file
+ ###################################################################################################
+@@ -608,27 +600,11 @@ endif()
+ ##############################################################################
+ # google test
+
+-# check for set environment variable
+-if(${GTEST_ROOT} STREQUAL "n/a")
+- message(STATUS "GTEST_ROOT is not defined. For building the tests the variable
+- GTEST_ROOT has to be defined. Tests can not be built.")
+- # early exit
+- return() # test can not be build -> make commands build_tests and check are not available
+-else()
+- message(STATUS "GTEST_ROOT is set. gtest root path set to ${GTEST_ROOT}")
++find_package(GTest)
++if (NOT GTest_FOUND)
++ message(WARNING "GTest is not found. Tests can not be built.")
+ endif()
+
+-# build google test as static library (always) -> therefore deactivate BUILD_SHARED_LIBS in case it is active
+-set(BUILD_SHARED_LIBS_AUTOMATIC_OFF 0)
+-if ("${BUILD_SHARED_LIBS}" STREQUAL "ON")
+- set(BUILD_SHARED_LIBS OFF)
+- set(BUILD_SHARED_LIBS_AUTOMATIC_OFF 1)
+-endif()
+-add_subdirectory(${GTEST_ROOT} ${CMAKE_CURRENT_BINARY_DIR}/gtest EXCLUDE_FROM_ALL)
+-if ("${BUILD_SHARED_LIBS_AUTOMATIC_OFF}" STREQUAL "1")
+- set(BUILD_SHARED_LIBS ON)
+- set(BUILD_SHARED_LIBS_AUTOMATIC_OFF 0)
+-endif()
+
+
+
+--
+2.25.1
+
new file mode 100644
@@ -0,0 +1,14220 @@
+From 8205a61f116d2874ebddc65a3bd7d766bb737417 Mon Sep 17 00:00:00 2001
+From: Alexander Larsson <alexl@redhat.com>
+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.
+
+Upstream-Status: Backport
+[https://github.com/COVESA/vsomeip/commit/3e90d6b40d3dead231444d652954d617c7985cc6]
+
+Signed-off-by: Yi Zhao <yi.zhao@windriver.com>
+---
+ 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 745cc455..dad03555 100644
+--- a/CMakeLists.txt
++++ b/CMakeLists.txt
+@@ -156,8 +156,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 107500)
++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 00000000..49a4950a
+--- /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 <boost/asio/detail/config.hpp>
++#include <cstddef>
++#include <boost/asio/basic_socket_ext.hpp>
++#include <boost/asio/detail/handler_type_requirements_ext.hpp>
++#include <boost/asio/detail/non_const_lvalue.hpp>
++#include <boost/asio/detail/throw_error.hpp>
++#include <boost/asio/detail/type_traits.hpp>
++#include <boost/asio/error.hpp>
++
++#include <boost/asio/detail/push_options.hpp>
++
++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 <typename Protocol, typename Executor = executor>
++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 <typename Protocol, typename Executor>
++class basic_datagram_socket_ext
++ : public basic_socket_ext<Protocol, Executor>
++{
++public:
++ /// The type of the executor associated with the object.
++ typedef Executor executor_type;
++
++ /// Rebinds the socket type to another executor.
++ template <typename Executor1>
++ struct rebind_executor
++ {
++ /// The socket type when rebound to the specified executor.
++ typedef basic_datagram_socket_ext<Protocol, Executor1> other;
++ };
++
++ /// The native representation of a socket.
++#if defined(GENERATING_DOCUMENTATION)
++ typedef implementation_defined native_handle_type;
++#else
++ typedef typename basic_socket_ext<Protocol,
++ Executor>::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<Protocol, Executor>(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 <typename ExecutionContext>
++ explicit basic_datagram_socket_ext(ExecutionContext& context,
++ typename enable_if<
++ is_convertible<ExecutionContext&, execution_context&>::value
++ >::type* = 0)
++ : basic_socket_ext<Protocol, Executor>(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<Protocol, Executor>(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 <typename ExecutionContext>
++ basic_datagram_socket_ext(ExecutionContext& context,
++ const protocol_type& protocol,
++ typename enable_if<
++ is_convertible<ExecutionContext&, execution_context&>::value
++ >::type* = 0)
++ : basic_socket_ext<Protocol, Executor>(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<Protocol, Executor>(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 <typename ExecutionContext>
++ basic_datagram_socket_ext(ExecutionContext& context,
++ const endpoint_type& endpoint,
++ typename enable_if<
++ is_convertible<ExecutionContext&, execution_context&>::value
++ >::type* = 0)
++ : basic_socket_ext<Protocol, Executor>(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<Protocol, Executor>(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 <typename ExecutionContext>
++ basic_datagram_socket_ext(ExecutionContext& context,
++ const protocol_type& protocol, const native_handle_type& native_socket,
++ typename enable_if<
++ is_convertible<ExecutionContext&, execution_context&>::value
++ >::type* = 0)
++ : basic_socket_ext<Protocol, Executor>(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<Protocol, Executor>(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<Protocol, Executor>::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 <typename Protocol1, typename Executor1>
++ basic_datagram_socket_ext(basic_datagram_socket_ext<Protocol1, Executor1>&& other,
++ typename enable_if<
++ is_convertible<Protocol1, Protocol>::value
++ && is_convertible<Executor1, Executor>::value
++ >::type* = 0)
++ : basic_socket_ext<Protocol, Executor>(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 Protocol1, typename Executor1>
++ typename enable_if<
++ is_convertible<Protocol1, Protocol>::value
++ && is_convertible<Executor1, Executor>::value,
++ basic_datagram_socket_ext&
++ >::type operator=(basic_datagram_socket_ext<Protocol1, Executor1>&& other)
++ {
++ basic_socket_ext<Protocol, Executor>::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 <typename ConstBufferSequence>
++ 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 <typename ConstBufferSequence>
++ 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 <typename ConstBufferSequence>
++ 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 <typename ConstBufferSequence, typename WriteHandler>
++ 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<WriteHandler,
++ void (boost::system::error_code, std::size_t)>(
++ 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 <typename ConstBufferSequence, typename WriteHandler>
++ 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<WriteHandler,
++ void (boost::system::error_code, std::size_t)>(
++ 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 <typename ConstBufferSequence>
++ 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 <typename ConstBufferSequence>
++ 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 <typename ConstBufferSequence>
++ 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 <typename ConstBufferSequence, typename WriteHandler>
++ 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<WriteHandler,
++ void (boost::system::error_code, std::size_t)>(
++ 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 <typename ConstBufferSequence, typename WriteHandler>
++ 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<WriteHandler,
++ void (boost::system::error_code, std::size_t)>(
++ 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 <typename MutableBufferSequence>
++ 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 <typename MutableBufferSequence>
++ 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 <typename MutableBufferSequence>
++ 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 <typename MutableBufferSequence, typename ReadHandler>
++ 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<ReadHandler,
++ void (boost::system::error_code, std::size_t, boost::asio::ip::address)>(
++ 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 <typename MutableBufferSequence, typename ReadHandler>
++ 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<ReadHandler,
++ void (boost::system::error_code, std::size_t, boost::asio::ip::address)>(
++ 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 <typename MutableBufferSequence>
++ 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 <typename MutableBufferSequence>
++ 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 <typename MutableBufferSequence>
++ 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 <typename MutableBufferSequence, typename ReadHandler>
++ 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<ReadHandler,
++ void (boost::system::error_code, std::size_t, boost::asio::ip::address)>(
++ 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 <typename MutableBufferSequence, typename ReadHandler>
++ 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<ReadHandler,
++ void (boost::system::error_code, std::size_t, boost::asio::ip::address)>(
++ initiate_async_receive_from(), handler,
++ this, buffers, &sender_endpoint, flags);
++ }
++
++private:
++ struct initiate_async_send
++ {
++ template <typename WriteHandler, typename ConstBufferSequence>
++ 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<WriteHandler> 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 <typename WriteHandler, typename ConstBufferSequence>
++ 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<WriteHandler> 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 <typename ReadHandler, typename MutableBufferSequence>
++ 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<ReadHandler> 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 <typename ReadHandler, typename MutableBufferSequence>
++ 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<ReadHandler> 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 <boost/asio/detail/pop_options.hpp>
++
++#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 00000000..0a86539a
+--- /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 <boost/asio/detail/config.hpp>
++#include <boost/asio/basic_socket_ext_local.hpp>
++#include <boost/asio/detail/handler_type_requirements_ext.hpp>
++#include <boost/asio/detail/io_object_impl.hpp>
++#include <boost/asio/detail/non_const_lvalue.hpp>
++#include <boost/asio/detail/throw_error.hpp>
++#include <boost/asio/detail/type_traits.hpp>
++#include <boost/asio/error.hpp>
++#include <boost/asio/execution_context.hpp>
++#include <boost/asio/executor.hpp>
++#include <boost/asio/socket_base.hpp>
++
++#if defined(BOOST_ASIO_WINDOWS_RUNTIME)
++# include <boost/asio/detail/null_socket_service.hpp>
++#elif defined(BOOST_ASIO_HAS_IOCP)
++# include <boost/asio/detail/win_iocp_socket_service.hpp>
++#else
++# include <boost/asio/detail/reactive_socket_service_ext_local.hpp>
++#endif
++
++#if defined(BOOST_ASIO_HAS_MOVE)
++# include <utility>
++#endif // defined(BOOST_ASIO_HAS_MOVE)
++
++#include <boost/asio/detail/push_options.hpp>
++
++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 <typename Protocol, typename Executor = executor>
++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 <typename Protocol, typename Executor>
++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 <typename ExecutionContext>
++ explicit basic_socket_acceptor_ext(ExecutionContext& context,
++ typename enable_if<
++ is_convertible<ExecutionContext&, execution_context&>::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 <typename ExecutionContext>
++ basic_socket_acceptor_ext(ExecutionContext& context,
++ const protocol_type& protocol,
++ typename enable_if<
++ is_convertible<ExecutionContext&, execution_context&>::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<Protocol> 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<Protocol> 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 <typename ExecutionContext>
++ basic_socket_acceptor_ext(ExecutionContext& context,
++ const endpoint_type& endpoint, bool reuse_addr = true,
++ typename enable_if<
++ is_convertible<ExecutionContext&, execution_context&>::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 <typename ExecutionContext>
++ basic_socket_acceptor_ext(ExecutionContext& context,
++ const protocol_type& protocol, const native_handle_type& native_acceptor,
++ typename enable_if<
++ is_convertible<ExecutionContext&, execution_context&>::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 <typename Protocol1, typename Executor1>
++ 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 <typename Protocol1, typename Executor1>
++ basic_socket_acceptor_ext(basic_socket_acceptor_ext<Protocol1, Executor1>&& other,
++ typename enable_if<
++ is_convertible<Protocol1, Protocol>::value
++ && is_convertible<Executor1, Executor>::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 Protocol1, typename Executor1>
++ typename enable_if<
++ is_convertible<Protocol1, Protocol>::value
++ && is_convertible<Executor1, Executor>::value,
++ basic_socket_acceptor_ext&
++ >::type operator=(basic_socket_acceptor_ext<Protocol1, Executor1>&& 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 <typename SettableSocketOption>
++ 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 <typename SettableSocketOption>
++ 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 <typename GettableSocketOption>
++ 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 <typename GettableSocketOption>
++ 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 <typename IoControlCommand>
++ 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 <typename IoControlCommand>
++ 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 <typename WaitHandler>
++ 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<WaitHandler, void (boost::system::error_code)>(
++ 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 <typename Protocol1, typename Executor1>
++ void accept(basic_socket_ext_local<Protocol1, Executor1>& peer,
++ typename enable_if<
++ is_convertible<Protocol, Protocol1>::value
++ >::type* = 0)
++ {
++ boost::system::error_code ec;
++ impl_.get_service().accept(impl_.get_implementation(),
++ peer, static_cast<endpoint_type*>(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 <typename Protocol1, typename Executor1>
++ BOOST_ASIO_SYNC_OP_VOID accept(
++ basic_socket_ext_local<Protocol1, Executor1>& peer, boost::system::error_code& ec,
++ typename enable_if<
++ is_convertible<Protocol, Protocol1>::value
++ >::type* = 0)
++ {
++ impl_.get_service().accept(impl_.get_implementation(),
++ peer, static_cast<endpoint_type*>(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 <typename Protocol1, typename Executor1, typename AcceptHandler>
++ BOOST_ASIO_INITFN_RESULT_TYPE(AcceptHandler,
++ void (boost::system::error_code))
++ async_accept(basic_socket_ext_local<Protocol1, Executor1>& peer,
++ BOOST_ASIO_MOVE_ARG(AcceptHandler) handler,
++ typename enable_if<
++ is_convertible<Protocol, Protocol1>::value
++ >::type* = 0)
++ {
++ return async_initiate<AcceptHandler, void (boost::system::error_code)>(
++ initiate_async_accept(), handler, this,
++ &peer, static_cast<endpoint_type*>(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 <typename Executor1>
++ void accept(basic_socket_ext_local<protocol_type, Executor1>& 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 <typename Executor1>
++ BOOST_ASIO_SYNC_OP_VOID accept(basic_socket_ext_local<protocol_type, Executor1>& 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 <typename Executor1, typename AcceptHandler>
++ BOOST_ASIO_INITFN_RESULT_TYPE(AcceptHandler,
++ void (boost::system::error_code))
++ async_accept(basic_socket_ext_local<protocol_type, Executor1>& peer,
++ endpoint_type& peer_endpoint, BOOST_ASIO_MOVE_ARG(AcceptHandler) handler)
++ {
++ return async_initiate<AcceptHandler, void (boost::system::error_code)>(
++ 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 <typename MoveAcceptHandler>
++ 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<MoveAcceptHandler,
++ void (boost::system::error_code, typename Protocol::socket)>(
++ initiate_async_move_accept(), handler, this,
++ impl_.get_executor(), static_cast<endpoint_type*>(0),
++ static_cast<typename Protocol::socket*>(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 Executor1>
++ typename Protocol::socket::template rebind_executor<Executor1>::other
++ accept(const Executor1& ex,
++ typename enable_if<
++ is_executor<Executor1>::value
++ >::type* = 0)
++ {
++ boost::system::error_code ec;
++ typename Protocol::socket::template
++ rebind_executor<Executor1>::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 ExecutionContext>
++ typename Protocol::socket::template rebind_executor<
++ typename ExecutionContext::executor_type>::other
++ accept(ExecutionContext& context,
++ typename enable_if<
++ is_convertible<ExecutionContext&, execution_context&>::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 Executor1>
++ typename Protocol::socket::template rebind_executor<Executor1>::other
++ accept(const Executor1& ex, boost::system::error_code& ec,
++ typename enable_if<
++ is_executor<Executor1>::value
++ >::type* = 0)
++ {
++ typename Protocol::socket::template
++ rebind_executor<Executor1>::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 ExecutionContext>
++ typename Protocol::socket::template rebind_executor<
++ typename ExecutionContext::executor_type>::other
++ accept(ExecutionContext& context, boost::system::error_code& ec,
++ typename enable_if<
++ is_convertible<ExecutionContext&, execution_context&>::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 <typename Executor1, typename MoveAcceptHandler>
++ 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<Executor1>::value
++ >::type* = 0)
++ {
++ typedef typename Protocol::socket::template rebind_executor<
++ Executor1>::other other_socket_type;
++
++ return async_initiate<MoveAcceptHandler,
++ void (boost::system::error_code, other_socket_type)>(
++ initiate_async_move_accept(), handler, this,
++ ex, static_cast<endpoint_type*>(0),
++ static_cast<other_socket_type*>(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 <typename ExecutionContext, typename MoveAcceptHandler>
++ 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<ExecutionContext&, execution_context&>::value
++ >::type* = 0)
++ {
++ typedef typename Protocol::socket::template rebind_executor<
++ typename ExecutionContext::executor_type>::other other_socket_type;
++
++ return async_initiate<MoveAcceptHandler,
++ void (boost::system::error_code, other_socket_type)>(
++ initiate_async_move_accept(), handler, this,
++ context.get_executor(), static_cast<endpoint_type*>(0),
++ static_cast<other_socket_type*>(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 <typename MoveAcceptHandler>
++ 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<MoveAcceptHandler,
++ void (boost::system::error_code, typename Protocol::socket)>(
++ initiate_async_move_accept(), handler, this,
++ impl_.get_executor(), &peer_endpoint,
++ static_cast<typename Protocol::socket*>(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 Executor1>
++ typename Protocol::socket::template rebind_executor<Executor1>::other
++ accept(const Executor1& ex, endpoint_type& peer_endpoint,
++ typename enable_if<
++ is_executor<Executor1>::value
++ >::type* = 0)
++ {
++ boost::system::error_code ec;
++ typename Protocol::socket::template
++ rebind_executor<Executor1>::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 ExecutionContext>
++ typename Protocol::socket::template rebind_executor<
++ typename ExecutionContext::executor_type>::other
++ accept(ExecutionContext& context, endpoint_type& peer_endpoint,
++ typename enable_if<
++ is_convertible<ExecutionContext&, execution_context&>::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 Executor1>
++ typename Protocol::socket::template rebind_executor<Executor1>::other
++ accept(const executor_type& ex,
++ endpoint_type& peer_endpoint, boost::system::error_code& ec,
++ typename enable_if<
++ is_executor<Executor1>::value
++ >::type* = 0)
++ {
++ typename Protocol::socket::template
++ rebind_executor<Executor1>::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 ExecutionContext>
++ 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<ExecutionContext&, execution_context&>::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 <typename Executor1, typename MoveAcceptHandler>
++ 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<Executor1>::value
++ >::type* = 0)
++ {
++ typedef typename Protocol::socket::template rebind_executor<
++ Executor1>::other other_socket_type;
++
++ return async_initiate<MoveAcceptHandler,
++ void (boost::system::error_code, other_socket_type)>(
++ initiate_async_move_accept(), handler, this,
++ ex, &peer_endpoint,
++ static_cast<other_socket_type*>(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 <typename ExecutionContext, typename MoveAcceptHandler>
++ 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<ExecutionContext&, execution_context&>::value
++ >::type* = 0)
++ {
++ typedef typename Protocol::socket::template rebind_executor<
++ typename ExecutionContext::executor_type>::other other_socket_type;
++
++ return async_initiate<MoveAcceptHandler,
++ void (boost::system::error_code, other_socket_type)>(
++ initiate_async_move_accept(), handler, this,
++ context.get_executor(), &peer_endpoint,
++ static_cast<other_socket_type*>(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 <typename WaitHandler>
++ 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<WaitHandler> 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 <typename AcceptHandler, typename Protocol1, typename Executor1>
++ void operator()(BOOST_ASIO_MOVE_ARG(AcceptHandler) handler,
++ basic_socket_acceptor_ext* self, basic_socket_ext_local<Protocol1, Executor1>* 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<AcceptHandler> 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 <typename MoveAcceptHandler, typename Executor1, typename Socket>
++ 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<MoveAcceptHandler> 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<Protocol>, Executor> impl_;
++#elif defined(BOOST_ASIO_HAS_IOCP)
++ detail::io_object_impl<
++ detail::win_iocp_socket_service<Protocol>, Executor> impl_;
++#else
++ detail::io_object_impl<
++ detail::reactive_socket_service_ext_local<Protocol>, Executor> impl_;
++#endif
++};
++
++} // namespace asio
++} // namespace boost
++
++#include <boost/asio/detail/pop_options.hpp>
++
++#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 00000000..777a0bf7
+--- /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 <boost/asio/detail/config.hpp>
++#include <boost/asio/async_result.hpp>
++#include <boost/asio/detail/handler_type_requirements.hpp>
++#include <boost/asio/detail/io_object_impl.hpp>
++#include <boost/asio/detail/non_const_lvalue.hpp>
++#include <boost/asio/detail/throw_error.hpp>
++#include <boost/asio/detail/type_traits.hpp>
++#include <boost/asio/error.hpp>
++#include <boost/asio/execution_context.hpp>
++#include <boost/asio/executor.hpp>
++#include <boost/asio/post.hpp>
++#include <boost/asio/socket_base.hpp>
++
++#if defined(BOOST_ASIO_WINDOWS_RUNTIME)
++# include <boost/asio/detail/null_socket_service.hpp>
++#elif defined(BOOST_ASIO_HAS_IOCP)
++# include <boost/asio/detail/win_iocp_socket_service.hpp>
++#else
++# include <boost/asio/detail/reactive_socket_service_ext.hpp>
++#endif
++
++#if defined(BOOST_ASIO_HAS_MOVE)
++# include <utility>
++#endif // defined(BOOST_ASIO_HAS_MOVE)
++
++#include <boost/asio/detail/push_options.hpp>
++
++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 <typename Protocol, typename Executor = executor>
++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 <typename Protocol, typename Executor>
++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 <typename Executor1>
++ struct rebind_executor
++ {
++ /// The socket type when rebound to the specified executor.
++ typedef basic_socket_ext<Protocol, Executor1> 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<Protocol, Executor> 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 <typename ExecutionContext>
++ explicit basic_socket_ext(ExecutionContext& context,
++ typename enable_if<
++ is_convertible<ExecutionContext&, execution_context&>::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 <typename ExecutionContext>
++ basic_socket_ext(ExecutionContext& context, const protocol_type& protocol,
++ typename enable_if<
++ is_convertible<ExecutionContext&, execution_context&>::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 <typename ExecutionContext>
++ basic_socket_ext(ExecutionContext& context, const endpoint_type& endpoint,
++ typename enable_if<
++ is_convertible<ExecutionContext&, execution_context&>::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 <typename ExecutionContext>
++ basic_socket_ext(ExecutionContext& context, const protocol_type& protocol,
++ const native_handle_type& native_socket,
++ typename enable_if<
++ is_convertible<ExecutionContext&, execution_context&>::value
++ >::type* = 0)
++ : 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 <typename Protocol1, typename Executor1>
++ 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 <typename Protocol1, typename Executor1>
++ basic_socket_ext(basic_socket_ext<Protocol1, Executor1>&& other,
++ typename enable_if<
++ is_convertible<Protocol1, Protocol>::value
++ && is_convertible<Executor1, Executor>::value
++ >::type* = 0)
++ : 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 Protocol1, typename Executor1>
++ typename enable_if<
++ is_convertible<Protocol1, Protocol>::value
++ && is_convertible<Executor1, Executor>::value,
++ basic_socket_ext&
++ >::type operator=(basic_socket_ext<Protocol1, Executor1> && 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 <typename ConnectHandler>
++ 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<ConnectHandler, void (boost::system::error_code)>(
++ 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 <typename SettableSocketOption>
++ 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 <typename SettableSocketOption>
++ 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 <typename GettableSocketOption>
++ 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 <typename GettableSocketOption>
++ 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 <typename IoControlCommand>
++ 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 <typename IoControlCommand>
++ 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 <typename Handler>
++ * 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 <typename Handler>
++ * void async_sendfile(tcp::socket& sock, int fd, Handler h)
++ * {
++ * sendfile_op<Handler> 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 <typename Handler>
++ * 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 <typename Handler>
++ * void async_sendfile(tcp::socket& sock, int fd, Handler h)
++ * {
++ * sendfile_op<Handler> 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 <typename Handler>
++ * 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 <typename Handler>
++ * void async_sendfile(tcp::socket& sock, int fd, Handler h)
++ * {
++ * sendfile_op<Handler> 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 <typename WaitHandler>
++ 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<WaitHandler, void (boost::system::error_code)>(
++ 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<Protocol>, Executor> impl_;
++#elif defined(BOOST_ASIO_HAS_IOCP)
++ detail::io_object_impl<
++ detail::win_iocp_socket_service<Protocol>, Executor> impl_;
++#else
++ detail::io_object_impl<
++ detail::reactive_socket_service_ext<Protocol>, 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 <typename ConnectHandler>
++ 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<ConnectHandler> 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 <typename WaitHandler>
++ 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<WaitHandler> 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 <boost/asio/detail/pop_options.hpp>
++
++#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 00000000..2c898fc6
+--- /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 <boost/asio/detail/config.hpp>
++#include <boost/asio/async_result.hpp>
++#include <boost/asio/detail/handler_type_requirements_ext.hpp>
++#include <boost/asio/detail/io_object_impl.hpp>
++#include <boost/asio/detail/non_const_lvalue.hpp>
++#include <boost/asio/detail/throw_error.hpp>
++#include <boost/asio/detail/type_traits.hpp>
++#include <boost/asio/error.hpp>
++#include <boost/asio/execution_context.hpp>
++#include <boost/asio/executor.hpp>
++#include <boost/asio/post.hpp>
++#include <boost/asio/socket_base.hpp>
++
++#if defined(BOOST_ASIO_WINDOWS_RUNTIME)
++# include <boost/asio/detail/null_socket_service.hpp>
++#elif defined(BOOST_ASIO_HAS_IOCP)
++# include <boost/asio/detail/win_iocp_socket_service.hpp>
++#else
++# include <boost/asio/detail/reactive_socket_service_ext_local.hpp>
++#endif
++
++#if defined(BOOST_ASIO_HAS_MOVE)
++# include <utility>
++#endif // defined(BOOST_ASIO_HAS_MOVE)
++
++#include <boost/asio/detail/push_options.hpp>
++
++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 <typename Protocol, typename Executor = executor>
++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 <typename Protocol, typename Executor>
++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 <typename Executor1>
++ struct rebind_executor
++ {
++ /// The socket type when rebound to the specified executor.
++ typedef basic_socket_ext_local<Protocol, Executor1> 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<Protocol, Executor> 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 <typename ExecutionContext>
++ explicit basic_socket_ext_local(ExecutionContext& context,
++ typename enable_if<
++ is_convertible<ExecutionContext&, execution_context&>::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 <typename ExecutionContext>
++ basic_socket_ext_local(ExecutionContext& context, const protocol_type& protocol,
++ typename enable_if<
++ is_convertible<ExecutionContext&, execution_context&>::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 <typename ExecutionContext>
++ basic_socket_ext_local(ExecutionContext& context, const endpoint_type& endpoint,
++ typename enable_if<
++ is_convertible<ExecutionContext&, execution_context&>::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 <typename ExecutionContext>
++ basic_socket_ext_local(ExecutionContext& context, const protocol_type& protocol,
++ const native_handle_type& native_socket,
++ typename enable_if<
++ is_convertible<ExecutionContext&, execution_context&>::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 <typename Protocol1, typename Executor1>
++ 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 <typename Protocol1, typename Executor1>
++ basic_socket_ext_local(basic_socket_ext_local<Protocol1, Executor1>&& other,
++ typename enable_if<
++ is_convertible<Protocol1, Protocol>::value
++ && is_convertible<Executor1, Executor>::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 Protocol1, typename Executor1>
++ typename enable_if<
++ is_convertible<Protocol1, Protocol>::value
++ && is_convertible<Executor1, Executor>::value,
++ basic_socket_ext_local&
++ >::type operator=(basic_socket_ext_local<Protocol1, Executor1> && 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 <typename ConnectHandler>
++ 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<ConnectHandler, void (boost::system::error_code)>(
++ 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 <typename SettableSocketOption>
++ 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 <typename SettableSocketOption>
++ 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 <typename GettableSocketOption>
++ 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 <typename GettableSocketOption>
++ 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 <typename IoControlCommand>
++ 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 <typename IoControlCommand>
++ 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 <typename Handler>
++ * 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 <typename Handler>
++ * void async_sendfile(tcp::socket& sock, int fd, Handler h)
++ * {
++ * sendfile_op<Handler> 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 <typename Handler>
++ * 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 <typename Handler>
++ * void async_sendfile(tcp::socket& sock, int fd, Handler h)
++ * {
++ * sendfile_op<Handler> 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 <typename Handler>
++ * 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 <typename Handler>
++ * void async_sendfile(tcp::socket& sock, int fd, Handler h)
++ * {
++ * sendfile_op<Handler> 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 <typename WaitHandler>
++ 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<WaitHandler, void (boost::system::error_code)>(
++ 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<Protocol>, Executor> impl_;
++#elif defined(BOOST_ASIO_HAS_IOCP)
++ detail::io_object_impl<
++ detail::win_iocp_socket_service<Protocol>, Executor> impl_;
++#else
++ detail::io_object_impl<
++ detail::reactive_socket_service_ext_local<Protocol>, 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 <typename ConnectHandler>
++ 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<ConnectHandler> 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 <typename WaitHandler>
++ 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<WaitHandler> 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 <boost/asio/detail/pop_options.hpp>
++
++#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 00000000..e77f5ebb
+--- /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 <boost/asio/detail/config.hpp>
++#include <cstddef>
++#include <boost/asio/async_result.hpp>
++#include <boost/asio/basic_socket_ext_local.hpp>
++#include <boost/asio/detail/handler_type_requirements_ext_local.hpp>
++#include <boost/asio/detail/non_const_lvalue.hpp>
++#include <boost/asio/detail/throw_error.hpp>
++#include <boost/asio/error.hpp>
++
++#include <boost/asio/detail/push_options.hpp>
++
++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 <typename Protocol, typename Executor = executor>
++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 <typename Protocol, typename Executor>
++class basic_stream_socket_ext
++ : public basic_socket_ext_local<Protocol, Executor>
++{
++public:
++ /// The type of the executor associated with the object.
++ typedef Executor executor_type;
++
++ /// Rebinds the socket type to another executor.
++ template <typename Executor1>
++ struct rebind_executor
++ {
++ /// The socket type when rebound to the specified executor.
++ typedef basic_stream_socket_ext<Protocol, Executor1> other;
++ };
++
++ /// The native representation of a socket.
++#if defined(GENERATING_DOCUMENTATION)
++ typedef implementation_defined native_handle_type;
++#else
++ typedef typename basic_socket<Protocol,
++ Executor>::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<Protocol, Executor>(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 <typename ExecutionContext>
++ explicit basic_stream_socket_ext(ExecutionContext& context,
++ typename enable_if<
++ is_convertible<ExecutionContext&, execution_context&>::value
++ >::type* = 0)
++ : basic_socket_ext_local<Protocol, Executor>(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<Protocol, Executor>(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 <typename ExecutionContext>
++ basic_stream_socket_ext(ExecutionContext& context, const protocol_type& protocol,
++ typename enable_if<
++ is_convertible<ExecutionContext&, execution_context&>::value
++ >::type* = 0)
++ : basic_socket_ext_local<Protocol, Executor>(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<Protocol, Executor>(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 <typename ExecutionContext>
++ basic_stream_socket_ext(ExecutionContext& context, const endpoint_type& endpoint,
++ typename enable_if<
++ is_convertible<ExecutionContext&, execution_context&>::value
++ >::type* = 0)
++ : basic_socket_ext_local<Protocol, Executor>(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<Protocol, Executor>(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 <typename ExecutionContext>
++ basic_stream_socket_ext(ExecutionContext& context,
++ const protocol_type& protocol, const native_handle_type& native_socket,
++ typename enable_if<
++ is_convertible<ExecutionContext&, execution_context&>::value
++ >::type* = 0)
++ : basic_socket_ext_local<Protocol, Executor>(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<Protocol, Executor>(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<Protocol, Executor>::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 <typename Protocol1, typename Executor1>
++ basic_stream_socket_ext(basic_stream_socket_ext<Protocol1, Executor1>&& other,
++ typename enable_if<
++ is_convertible<Protocol1, Protocol>::value
++ && is_convertible<Executor1, Executor>::value
++ >::type* = 0)
++ : basic_socket_ext_local<Protocol, Executor>(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 Protocol1, typename Executor1>
++ typename enable_if<
++ is_convertible<Protocol1, Protocol>::value
++ && is_convertible<Executor1, Executor>::value,
++ basic_stream_socket_ext&
++ >::type operator=(basic_stream_socket_ext<Protocol1, Executor1>&& other)
++ {
++ basic_socket_ext_local<Protocol, Executor>::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 <typename ConstBufferSequence>
++ 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 <typename ConstBufferSequence>
++ 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 <typename ConstBufferSequence>
++ 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 <typename ConstBufferSequence, typename WriteHandler>
++ 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<WriteHandler,
++ void (boost::system::error_code, std::size_t)>(
++ 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 <typename ConstBufferSequence, typename WriteHandler>
++ 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<WriteHandler,
++ void (boost::system::error_code, std::size_t)>(
++ 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 <typename MutableBufferSequence>
++ 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 <typename MutableBufferSequence>
++ 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 <typename MutableBufferSequence>
++ 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 <typename MutableBufferSequence, typename ReadHandler>
++ 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<ReadHandler,
++ void (boost::system::error_code, std::size_t, std::uint32_t, std::uint32_t)>(
++ 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 <typename MutableBufferSequence, typename ReadHandler>
++ 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<ReadHandler,
++ void (boost::system::error_code, std::size_t, std::uint32_t, std::uint32_t)>(
++ 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 <typename ConstBufferSequence>
++ 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 <typename ConstBufferSequence>
++ 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 <typename ConstBufferSequence, typename WriteHandler>
++ 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<WriteHandler,
++ void (boost::system::error_code, std::size_t, std::uint32_t, std::uint32_t)>(
++ 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 <typename MutableBufferSequence>
++ 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 <typename MutableBufferSequence>
++ 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 <typename MutableBufferSequence, typename ReadHandler>
++ 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<ReadHandler,
++ void (boost::system::error_code, std::size_t, std::uint32_t, std::uint32_t)>(
++ initiate_async_receive(), handler, this,
++ buffers, socket_base::message_flags(0));
++ }
++
++private:
++ struct initiate_async_send
++ {
++ template <typename WriteHandler, typename ConstBufferSequence>
++ 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<WriteHandler> 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 <typename ReadHandler, typename MutableBufferSequence>
++ 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<ReadHandler> 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 <boost/asio/detail/pop_options.hpp>
++
++#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 00000000..67fe6bd9
+--- /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 <boost/asio/detail/config.hpp>
++
++// 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 <boost/asio/async_result.hpp>
++#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 <typename Handler>
++auto zero_arg_copyable_handler_test(Handler h, void*)
++ -> decltype(
++ sizeof(Handler(static_cast<const Handler&>(h))),
++ ((h)()),
++ char(0));
++
++template <typename Handler>
++char (&zero_arg_copyable_handler_test(Handler, ...))[2];
++
++template <typename Handler, typename Arg1>
++auto one_arg_handler_test(Handler h, Arg1* a1)
++ -> decltype(
++ sizeof(Handler(BOOST_ASIO_MOVE_CAST(Handler)(h))),
++ ((h)(*a1)),
++ char(0));
++
++template <typename Handler>
++char (&one_arg_handler_test(Handler h, ...))[2];
++
++template <typename Handler, typename Arg1, typename Arg2>
++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 <typename Handler>
++char (&two_arg_handler_test(Handler, ...))[2];
++
++template <typename Handler, typename Arg1, typename Arg2>
++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 <typename Handler>
++char (&two_arg_move_handler_test(Handler, ...))[2];
++
++template <typename Handler, typename Arg1, typename Arg2, typename Arg3>
++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 <typename Handler>
++char (&three_arg_handler_test(Handler, ...))[2];
++
++template <typename Handler, typename Arg1, typename Arg2, typename Arg3>
++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 <typename Handler>
++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 <typename T> T& lvref();
++template <typename T> T& lvref(T);
++template <typename T> const T& clvref();
++template <typename T> const T& clvref(T);
++#if defined(BOOST_ASIO_HAS_MOVE)
++template <typename T> T rvref();
++template <typename T> T rvref(T);
++#else // defined(BOOST_ASIO_HAS_MOVE)
++template <typename T> const T& rvref();
++template <typename T> const T& rvref(T);
++#endif // defined(BOOST_ASIO_HAS_MOVE)
++template <typename T> char argbyv(T);
++
++#if 0
++template <int>
++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<const boost::system::error_code*>(0), \
++ static_cast<const std::size_t*>(0), \
++ static_cast<const boost::asio::ip::address*>(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<const boost::system::error_code>(), \
++ boost::asio::detail::lvref<const std::size_t>(), \
++ boost::asio::detail::lvref<const boost::asio::ip::address>()), \
++ 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<const boost::system::error_code*>(0), \
++ static_cast<const std::size_t*>(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<const boost::system::error_code>(), \
++ boost::asio::detail::lvref<const std::size_t>()), \
++ 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<const boost::system::error_code*>(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<const boost::system::error_code>()), \
++ 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<const boost::system::error_code*>(0), \
++ static_cast<socket_type*>(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<const boost::system::error_code>(), \
++ boost::asio::detail::rvref<socket_type>()), \
++ 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<const boost::system::error_code*>(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<const boost::system::error_code>()), \
++ 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<const boost::system::error_code*>(0), \
++ static_cast<const endpoint_type*>(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<const boost::system::error_code>(), \
++ boost::asio::detail::lvref<const endpoint_type>()), \
++ 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<const boost::system::error_code*>(0), \
++ static_cast<const iter_type*>(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<const boost::system::error_code>(), \
++ boost::asio::detail::lvref<const iter_type>()), \
++ 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<const boost::system::error_code*>(0), \
++ static_cast<const range_type*>(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<const boost::system::error_code>(), \
++ boost::asio::detail::lvref<const range_type>()), \
++ 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<const boost::system::error_code*>(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<const boost::system::error_code>()), \
++ 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<const boost::system::error_code*>(0), \
++ static_cast<const int*>(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<const boost::system::error_code>(), \
++ boost::asio::detail::lvref<const int>()), \
++ 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<const boost::system::error_code*>(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<const boost::system::error_code>()), \
++ 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<const boost::system::error_code*>(0), \
++ static_cast<const std::size_t*>(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<const boost::system::error_code>(), \
++ boost::asio::detail::lvref<const std::size_t>()), \
++ 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<const boost::system::error_code*>(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<const boost::system::error_code>()), \
++ 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 00000000..65640adf
+--- /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 <boost/asio/detail/config.hpp>
++
++// 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 <boost/asio/async_result.hpp>
++#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 <typename Handler>
++auto zero_arg_copyable_handler_test(Handler h, void*)
++ -> decltype(
++ sizeof(Handler(static_cast<const Handler&>(h))),
++ ((h)()),
++ char(0));
++
++template <typename Handler>
++char (&zero_arg_copyable_handler_test(Handler, ...))[2];
++
++template <typename Handler, typename Arg1>
++auto one_arg_handler_test(Handler h, Arg1* a1)
++ -> decltype(
++ sizeof(Handler(BOOST_ASIO_MOVE_CAST(Handler)(h))),
++ ((h)(*a1)),
++ char(0));
++
++template <typename Handler>
++char (&one_arg_handler_test(Handler h, ...))[2];
++
++template <typename Handler, typename Arg1, typename Arg2>
++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 <typename Handler>
++char (&two_arg_handler_test(Handler, ...))[2];
++
++template <typename Handler, typename Arg1, typename Arg2>
++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 <typename Handler>
++char (&two_arg_move_handler_test(Handler, ...))[2];
++
++template <typename Handler, typename Arg1, typename Arg2, typename Arg3, typename Arg4>
++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 <typename Handler>
++char (&four_arg_handler_test(Handler, ...))[2];
++
++template <typename Handler, typename Arg1, typename Arg2, typename Arg3, typename Arg4>
++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 <typename Handler>
++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 <typename T> T& lvref();
++template <typename T> T& lvref(T);
++template <typename T> const T& clvref();
++template <typename T> const T& clvref(T);
++#if defined(BOOST_ASIO_HAS_MOVE)
++template <typename T> T rvref();
++template <typename T> T rvref(T);
++#else // defined(BOOST_ASIO_HAS_MOVE)
++template <typename T> const T& rvref();
++template <typename T> const T& rvref(T);
++#endif // defined(BOOST_ASIO_HAS_MOVE)
++template <typename T> char argbyv(T);
++
++#if 0
++template <int>
++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<const boost::system::error_code*>(0), \
++ static_cast<const std::size_t*>(0), \
++ static_cast<const std::uint32_t*>(0), \
++ static_cast<const std::uint32_t*>(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<const boost::system::error_code>(), \
++ boost::asio::detail::lvref<const std::size_t>(), \
++ boost::asio::detail::lvref<const std::uint32_t>(), \
++ boost::asio::detail::lvref<const std::uint32_t>()), \
++ 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<const boost::system::error_code*>(0), \
++ static_cast<const std::size_t*>(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<const boost::system::error_code>(), \
++ boost::asio::detail::lvref<const std::size_t>()), \
++ 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<const boost::system::error_code*>(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<const boost::system::error_code>()), \
++ 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<const boost::system::error_code*>(0), \
++ static_cast<socket_type*>(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<const boost::system::error_code>(), \
++ boost::asio::detail::rvref<socket_type>()), \
++ 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<const boost::system::error_code*>(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<const boost::system::error_code>()), \
++ 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<const boost::system::error_code*>(0), \
++ static_cast<const endpoint_type*>(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<const boost::system::error_code>(), \
++ boost::asio::detail::lvref<const endpoint_type>()), \
++ 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<const boost::system::error_code*>(0), \
++ static_cast<const iter_type*>(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<const boost::system::error_code>(), \
++ boost::asio::detail::lvref<const iter_type>()), \
++ 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<const boost::system::error_code*>(0), \
++ static_cast<const range_type*>(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<const boost::system::error_code>(), \
++ boost::asio::detail::lvref<const range_type>()), \
++ 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<const boost::system::error_code*>(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<const boost::system::error_code>()), \
++ 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<const boost::system::error_code*>(0), \
++ static_cast<const int*>(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<const boost::system::error_code>(), \
++ boost::asio::detail::lvref<const int>()), \
++ 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<const boost::system::error_code*>(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<const boost::system::error_code>()), \
++ 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<const boost::system::error_code*>(0), \
++ static_cast<const std::size_t*>(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<const boost::system::error_code>(), \
++ boost::asio::detail::lvref<const std::size_t>()), \
++ 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<const boost::system::error_code*>(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<const boost::system::error_code>()), \
++ 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 00000000..04036adf
+--- /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 <boost/asio/detail/config.hpp>
++
++#if !defined(BOOST_ASIO_HAS_IOCP) \
++ && !defined(BOOST_ASIO_WINDOWS_RUNTIME)
++
++#include <boost/asio/detail/reactive_socket_service_base_ext.hpp>
++
++#include <boost/asio/detail/push_options.hpp>
++
++namespace boost {
++namespace asio {
++namespace detail {
++
++reactive_socket_service_base_ext::reactive_socket_service_base_ext(
++ execution_context& context)
++ : reactor_(use_service<reactor>(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 <boost/asio/detail/pop_options.hpp>
++
++#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 00000000..288cf193
+--- /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 <boost/asio/detail/config.hpp>
++
++#if !defined(BOOST_ASIO_HAS_IOCP) \
++ && !defined(BOOST_ASIO_WINDOWS_RUNTIME)
++
++#include <boost/asio/detail/reactive_socket_service_base_ext_local.hpp>
++
++#include <boost/asio/detail/push_options.hpp>
++
++namespace boost {
++namespace asio {
++namespace detail {
++
++reactive_socket_service_base_ext_local::reactive_socket_service_base_ext_local(
++ execution_context& context)
++ : reactor_(use_service<reactor>(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 <boost/asio/detail/pop_options.hpp>
++
++#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 00000000..39e2ed84
+--- /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 <boost/asio/detail/impl/socket_ops.ipp>
++
++#include <boost/asio/detail/push_options.hpp>
++
++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<int>(*addrlen);
++ msg.msg_iov = bufs;
++ msg.msg_iovlen = static_cast<int>(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 <boost/asio/detail/pop_options.hpp>
++
++#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 00000000..83a673b8
+--- /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 <boost/asio/detail/impl/socket_ops.ipp>
++
++#include <boost/asio/detail/push_options.hpp>
++
++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<DWORD>(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<int>(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<DWORD>(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<int>(*addrlen);
++ msg.msg_iov = bufs;
++ msg.msg_iovlen = static_cast<int>(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 <boost/asio/detail/pop_options.hpp>
++
++#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 00000000..1167d57f
+--- /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 <boost/asio/detail/config.hpp>
++#include <boost/asio/detail/bind_handler.hpp>
++#include <boost/asio/detail/buffer_sequence_adapter.hpp>
++#include <boost/asio/detail/fenced_block.hpp>
++#include <boost/asio/detail/handler_alloc_helpers.hpp>
++#include <boost/asio/detail/handler_invoke_helpers.hpp>
++#include <boost/asio/detail/handler_work.hpp>
++#include <boost/asio/detail/memory.hpp>
++#include <boost/asio/detail/reactor_op_ext.hpp>
++#include <boost/asio/detail/socket_ops_ext.hpp>
++
++#include <boost/asio/detail/push_options.hpp>
++
++namespace boost {
++namespace asio {
++namespace detail {
++
++template <typename MutableBufferSequence>
++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<reactive_socket_recv_op_base_ext*>(base));
++
++ typedef buffer_sequence_adapter<boost::asio::mutable_buffer,
++ MutableBufferSequence> 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 <typename MutableBufferSequence, typename Handler, typename IoExecutor>
++class reactive_socket_recv_op_ext :
++ public reactive_socket_recv_op_base_ext<MutableBufferSequence>
++{
++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<MutableBufferSequence>(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<reactive_socket_recv_op_ext*>(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<Handler, IoExecutor> w(
++ BOOST_ASIO_MOVE_CAST2(handler_work<Handler, IoExecutor>)(
++ 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, boost::system::error_code, std::size_t, boost::asio::ip::address>
++ 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<Handler, IoExecutor> work_;
++};
++
++} // namespace detail
++} // namespace asio
++} // namespace boost
++
++#include <boost/asio/detail/pop_options.hpp>
++
++#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 00000000..bedbd290
+--- /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 <boost/asio/detail/config.hpp>
++#include <boost/asio/detail/bind_handler.hpp>
++#include <boost/asio/detail/buffer_sequence_adapter.hpp>
++#include <boost/asio/detail/fenced_block.hpp>
++#include <boost/asio/detail/handler_alloc_helpers.hpp>
++#include <boost/asio/detail/handler_invoke_helpers.hpp>
++#include <boost/asio/detail/handler_work.hpp>
++#include <boost/asio/detail/memory.hpp>
++#include <boost/asio/detail/reactor_op_ext_local.hpp>
++#include <boost/asio/detail/socket_ops_ext_local.hpp>
++
++#include <boost/asio/detail/push_options.hpp>
++
++namespace boost {
++namespace asio {
++namespace detail {
++
++template <typename MutableBufferSequence>
++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<reactive_socket_recv_op_base_ext_local*>(base));
++
++ typedef buffer_sequence_adapter<boost::asio::mutable_buffer,
++ MutableBufferSequence> 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 <typename MutableBufferSequence, typename Handler, typename IoExecutor>
++class reactive_socket_recv_op_ext_local :
++ public reactive_socket_recv_op_base_ext_local<MutableBufferSequence>
++{
++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<MutableBufferSequence>(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<reactive_socket_recv_op_ext_local*>(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<Handler, IoExecutor> w(
++ BOOST_ASIO_MOVE_CAST2(handler_work<Handler, IoExecutor>)(
++ 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, boost::system::error_code, std::size_t, std::uint32_t, std::uint32_t>
++ 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<Handler, IoExecutor> work_;
++};
++
++} // namespace detail
++} // namespace asio
++} // namespace boost
++
++#include <boost/asio/detail/pop_options.hpp>
++
++#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 00000000..875fe142
+--- /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 <boost/asio/detail/config.hpp>
++#include <boost/asio/detail/bind_handler.hpp>
++#include <boost/asio/detail/buffer_sequence_adapter.hpp>
++#include <boost/asio/detail/fenced_block.hpp>
++#include <boost/asio/detail/handler_alloc_helpers.hpp>
++#include <boost/asio/detail/handler_invoke_helpers.hpp>
++#include <boost/asio/detail/handler_work.hpp>
++#include <boost/asio/detail/memory.hpp>
++#include <boost/asio/detail/reactor_op_ext.hpp>
++#include <boost/asio/detail/socket_ops_ext.hpp>
++
++#include <boost/asio/detail/push_options.hpp>
++
++namespace boost {
++namespace asio {
++namespace detail {
++
++template <typename MutableBufferSequence, typename Endpoint>
++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<reactive_socket_recvfrom_op_base_ext*>(base));
++
++ buffer_sequence_adapter<boost::asio::mutable_buffer,
++ MutableBufferSequence> 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 <typename MutableBufferSequence, typename Endpoint,
++ typename Handler, typename IoExecutor>
++class reactive_socket_recvfrom_op_ext :
++ public reactive_socket_recvfrom_op_base_ext<MutableBufferSequence, Endpoint>
++{
++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<MutableBufferSequence, Endpoint>(
++ 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<reactive_socket_recvfrom_op_ext*>(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<Handler, IoExecutor> w(
++ BOOST_ASIO_MOVE_CAST2(handler_work<Handler, IoExecutor>)(
++ 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, boost::system::error_code, std::size_t, boost::asio::ip::address>
++ 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<Handler, IoExecutor> work_;
++};
++
++} // namespace detail
++} // namespace asio
++} // namespace boost
++
++#include <boost/asio/detail/pop_options.hpp>
++
++#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 00000000..f9fef2b8
+--- /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 <boost/asio/detail/config.hpp>
++#include <boost/asio/detail/bind_handler.hpp>
++#include <boost/asio/detail/buffer_sequence_adapter.hpp>
++#include <boost/asio/detail/fenced_block.hpp>
++#include <boost/asio/detail/memory.hpp>
++#include <boost/asio/detail/reactor_op_ext_local.hpp>
++#include <boost/asio/detail/socket_ops_ext_local.hpp>
++
++#include <boost/asio/detail/push_options.hpp>
++
++namespace boost {
++namespace asio {
++namespace detail {
++
++template <typename MutableBufferSequence, typename Endpoint>
++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<reactive_socket_recvfrom_op_base_ext_local*>(base));
++
++ buffer_sequence_adapter<boost::asio::mutable_buffer,
++ MutableBufferSequence> 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 <typename MutableBufferSequence, typename Endpoint,
++ typename Handler, typename IoExecutor>
++class reactive_socket_recvfrom_op_ext_local :
++ public reactive_socket_recvfrom_op_base_ext_local<MutableBufferSequence, Endpoint>
++{
++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<MutableBufferSequence, Endpoint>(
++ 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<reactive_socket_recvfrom_op_ext_local*>(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<Handler, IoExecutor> w(
++ BOOST_ASIO_MOVE_CAST2(handler_work<Handler, IoExecutor>)(
++ 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, boost::system::error_code, std::size_t, std::uint32_t, std::uint32_t>
++ 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<Handler, IoExecutor> work_;
++};
++
++} // namespace detail
++} // namespace asio
++} // namespace boost
++
++#include <boost/asio/detail/pop_options.hpp>
++
++#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 00000000..bd315dcf
+--- /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 <boost/asio/detail/config.hpp>
++#include <boost/asio/detail/bind_handler.hpp>
++#include <boost/asio/detail/buffer_sequence_adapter.hpp>
++#include <boost/asio/detail/fenced_block.hpp>
++#include <boost/asio/detail/handler_alloc_helpers.hpp>
++#include <boost/asio/detail/handler_invoke_helpers.hpp>
++#include <boost/asio/detail/handler_work.hpp>
++#include <boost/asio/detail/memory.hpp>
++#include <boost/asio/detail/reactor_op_ext.hpp>
++#include <boost/asio/detail/socket_ops_ext.hpp>
++#include <boost/asio/socket_base.hpp>
++
++#include <boost/asio/detail/push_options.hpp>
++
++namespace boost {
++namespace asio {
++namespace detail {
++
++template <typename MutableBufferSequence>
++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<reactive_socket_recvmsg_op_base_ext*>(base));
++
++ buffer_sequence_adapter<boost::asio::mutable_buffer,
++ MutableBufferSequence> 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 <typename MutableBufferSequence, typename Handler, typename IoExecutor>
++class reactive_socket_recvmsg_op_ext :
++ public reactive_socket_recvmsg_op_base_ext<MutableBufferSequence>
++{
++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<MutableBufferSequence>(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<reactive_socket_recvmsg_op_ext*>(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<Handler, IoExecutor> w(
++ BOOST_ASIO_MOVE_CAST2(handler_work<Handler, IoExecutor>)(
++ 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, boost::system::error_code, std::size_t, boost::asio::ip::address>
++ 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<Handler, IoExecutor> work_;
++};
++
++} // namespace detail
++} // namespace asio
++} // namespace boost
++
++#include <boost/asio/detail/pop_options.hpp>
++
++#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 00000000..81486904
+--- /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 <boost/asio/detail/config.hpp>
++#include <boost/asio/detail/bind_handler.hpp>
++#include <boost/asio/detail/buffer_sequence_adapter.hpp>
++#include <boost/asio/detail/fenced_block.hpp>
++#include <boost/asio/detail/handler_alloc_helpers.hpp>
++#include <boost/asio/detail/handler_invoke_helpers.hpp>
++#include <boost/asio/detail/handler_work.hpp>
++#include <boost/asio/detail/memory.hpp>
++#include <boost/asio/detail/reactor_op_ext_local.hpp>
++#include <boost/asio/detail/socket_ops_ext_local.hpp>
++#include <boost/asio/socket_base.hpp>
++
++#include <boost/asio/detail/push_options.hpp>
++
++namespace boost {
++namespace asio {
++namespace detail {
++
++template <typename MutableBufferSequence>
++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<reactive_socket_recvmsg_op_base_ext_local*>(base));
++
++ buffer_sequence_adapter<boost::asio::mutable_buffer,
++ MutableBufferSequence> 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 <typename MutableBufferSequence, typename Handler, typename IoExecutor>
++class reactive_socket_recvmsg_op_ext_local :
++ public reactive_socket_recvmsg_op_base_ext_local<MutableBufferSequence>
++{
++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<MutableBufferSequence>(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<reactive_socket_recvmsg_op_ext_local*>(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<Handler, IoExecutor> w(
++ BOOST_ASIO_MOVE_CAST2(handler_work<Handler, IoExecutor>)(
++ 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, boost::system::error_code, std::size_t, std::uint32_t, std::uint32_t>
++ 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<Handler, IoExecutor> work_;
++};
++
++} // namespace detail
++} // namespace asio
++} // namespace boost
++
++#include <boost/asio/detail/pop_options.hpp>
++
++#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 00000000..2e68a877
+--- /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 <boost/asio/detail/config.hpp>
++
++#if !defined(BOOST_ASIO_HAS_IOCP) \
++ && !defined(BOOST_ASIO_WINDOWS_RUNTIME)
++
++#include <boost/asio/buffer.hpp>
++#include <boost/asio/error.hpp>
++#include <boost/asio/execution_context.hpp>
++#include <boost/asio/socket_base.hpp>
++#include <boost/asio/detail/buffer_sequence_adapter.hpp>
++#include <boost/asio/detail/memory.hpp>
++#include <boost/asio/detail/reactive_null_buffers_op.hpp>
++#include <boost/asio/detail/reactive_socket_recv_op_ext.hpp>
++#include <boost/asio/detail/reactive_socket_recvmsg_op_ext.hpp>
++#include <boost/asio/detail/reactive_socket_send_op.hpp>
++#include <boost/asio/detail/reactive_wait_op.hpp>
++#include <boost/asio/detail/reactor.hpp>
++#include <boost/asio/detail/reactor_op.hpp>
++#include <boost/asio/detail/socket_holder.hpp>
++#include <boost/asio/detail/socket_ops_ext.hpp>
++#include <boost/asio/detail/socket_types.hpp>
++
++#include <boost/asio/detail/push_options.hpp>
++
++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 <typename IO_Control_Command>
++ 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<ioctl_arg_type*>(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 <typename Handler, typename IoExecutor>
++ 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<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_, 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 <typename ConstBufferSequence>
++ size_t send(base_implementation_type& impl,
++ const ConstBufferSequence& buffers,
++ socket_base::message_flags flags, boost::system::error_code& ec)
++ {
++ buffer_sequence_adapter<boost::asio::const_buffer,
++ ConstBufferSequence> 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 <typename ConstBufferSequence, typename Handler, typename IoExecutor>
++ 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<boost::asio::const_buffer,
++ ConstBufferSequence>::all_empty(buffers)));
++ p.v = p.p = 0;
++ }
++
++ // Start an asynchronous wait until data can be sent without blocking.
++ template <typename Handler, typename IoExecutor>
++ 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<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_, 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 <typename MutableBufferSequence>
++ size_t receive(base_implementation_type& impl,
++ const MutableBufferSequence& buffers,
++ socket_base::message_flags flags, boost::system::error_code& ec)
++ {
++ buffer_sequence_adapter<boost::asio::mutable_buffer,
++ MutableBufferSequence> 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 <typename MutableBufferSequence,
++ typename Handler, typename IoExecutor>
++ 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<boost::asio::mutable_buffer,
++ MutableBufferSequence>::all_empty(buffers)));
++ p.v = p.p = 0;
++ }
++
++ // Wait until data can be received without blocking.
++ template <typename Handler, typename IoExecutor>
++ 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<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_, 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 <typename MutableBufferSequence>
++ 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<boost::asio::mutable_buffer,
++ MutableBufferSequence> 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 <typename MutableBufferSequence,
++ typename Handler, typename IoExecutor>
++ 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 <typename Handler, typename IoExecutor>
++ 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<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_, 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 <boost/asio/detail/pop_options.hpp>
++
++#if defined(BOOST_ASIO_HEADER_ONLY)
++# include <boost/asio/detail/impl/reactive_socket_service_base_ext.ipp>
++#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 00000000..a71fce5b
+--- /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 <boost/asio/detail/config.hpp>
++
++#if !defined(BOOST_ASIO_HAS_IOCP) \
++ && !defined(BOOST_ASIO_WINDOWS_RUNTIME)
++
++#include <boost/asio/buffer.hpp>
++#include <boost/asio/error.hpp>
++#include <boost/asio/execution_context.hpp>
++#include <boost/asio/socket_base.hpp>
++#include <boost/asio/detail/buffer_sequence_adapter.hpp>
++#include <boost/asio/detail/memory.hpp>
++#include <boost/asio/detail/reactive_null_buffers_op.hpp>
++#include <boost/asio/detail/reactive_socket_recv_op_ext_local.hpp>
++#include <boost/asio/detail/reactive_socket_recvmsg_op_ext_local.hpp>
++#include <boost/asio/detail/reactive_socket_send_op.hpp>
++#include <boost/asio/detail/reactive_wait_op.hpp>
++#include <boost/asio/detail/reactor.hpp>
++#include <boost/asio/detail/reactor_op.hpp>
++#include <boost/asio/detail/socket_holder.hpp>
++#include <boost/asio/detail/socket_ops_ext_local.hpp>
++#include <boost/asio/detail/socket_types.hpp>
++
++#include <boost/asio/detail/push_options.hpp>
++
++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 <typename IO_Control_Command>
++ 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<ioctl_arg_type*>(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 <typename Handler, typename IoExecutor>
++ 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<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_, 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 <typename ConstBufferSequence>
++ size_t send(base_implementation_type& impl,
++ const ConstBufferSequence& buffers,
++ socket_base::message_flags flags, boost::system::error_code& ec)
++ {
++ buffer_sequence_adapter<boost::asio::const_buffer,
++ ConstBufferSequence> 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 <typename ConstBufferSequence, typename Handler, typename IoExecutor>
++ 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<boost::asio::const_buffer,
++ ConstBufferSequence>::all_empty(buffers)));
++ p.v = p.p = 0;
++ }
++
++ // Start an asynchronous wait until data can be sent without blocking.
++ template <typename Handler, typename IoExecutor>
++ 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<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_, 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 <typename MutableBufferSequence>
++ size_t receive(base_implementation_type& impl,
++ const MutableBufferSequence& buffers,
++ socket_base::message_flags flags, boost::system::error_code& ec)
++ {
++ buffer_sequence_adapter<boost::asio::mutable_buffer,
++ MutableBufferSequence> 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 <typename MutableBufferSequence,
++ typename Handler, typename IoExecutor>
++ 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<boost::asio::mutable_buffer,
++ MutableBufferSequence>::all_empty(buffers)));
++ p.v = p.p = 0;
++ }
++
++ // Wait until data can be received without blocking.
++ template <typename Handler, typename IoExecutor>
++ 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<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_, 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 <typename MutableBufferSequence>
++ 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<boost::asio::mutable_buffer,
++ MutableBufferSequence> 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 <typename MutableBufferSequence,
++ typename Handler, typename IoExecutor>
++ 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 <typename Handler, typename IoExecutor>
++ 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<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_, 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 <boost/asio/detail/pop_options.hpp>
++
++#if defined(BOOST_ASIO_HEADER_ONLY)
++# include <boost/asio/detail/impl/reactive_socket_service_base_ext_local.ipp>
++#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 00000000..7254ccdd
+--- /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 <boost/asio/detail/config.hpp>
++
++#if !defined(BOOST_ASIO_HAS_IOCP)
++
++#include <boost/asio/buffer.hpp>
++#include <boost/asio/error.hpp>
++#include <boost/asio/execution_context.hpp>
++#include <boost/asio/socket_base.hpp>
++#include <boost/asio/detail/buffer_sequence_adapter.hpp>
++#include <boost/asio/detail/memory.hpp>
++#include <boost/asio/detail/noncopyable.hpp>
++#include <boost/asio/detail/reactive_null_buffers_op.hpp>
++#include <boost/asio/detail/reactive_socket_accept_op.hpp>
++#include <boost/asio/detail/reactive_socket_connect_op.hpp>
++#include <boost/asio/detail/reactive_socket_recvfrom_op_ext.hpp>
++#include <boost/asio/detail/reactive_socket_sendto_op.hpp>
++#include <boost/asio/detail/reactive_socket_service_base_ext.hpp>
++#include <boost/asio/detail/reactor.hpp>
++#include <boost/asio/detail/reactor_op.hpp>
++#include <boost/asio/detail/socket_holder.hpp>
++#include <boost/asio/detail/socket_ops.hpp>
++#include <boost/asio/detail/socket_types.hpp>
++
++#include <boost/asio/detail/push_options.hpp>
++
++namespace boost {
++namespace asio {
++namespace detail {
++
++template <typename Protocol>
++class reactive_socket_service_ext :
++ public execution_context_service_base<reactive_socket_service_ext<Protocol> >,
++ 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<Protocol> >(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 <typename Protocol1>
++ void converting_move_construct(implementation_type& impl,
++ reactive_socket_service_ext<Protocol1>&,
++ 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 <typename Option>
++ 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 <typename Option>
++ 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 <typename ConstBufferSequence>
++ 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<boost::asio::const_buffer,
++ ConstBufferSequence> 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 <typename ConstBufferSequence, typename Handler, typename IoExecutor>
++ 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<ConstBufferSequence,
++ endpoint_type, 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,
++ 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 <typename Handler, typename IoExecutor>
++ 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<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_, 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 <typename MutableBufferSequence>
++ 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<boost::asio::mutable_buffer,
++ MutableBufferSequence> 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 <typename MutableBufferSequence,
++ typename Handler, typename IoExecutor>
++ 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<MutableBufferSequence,
++ endpoint_type, Handler, IoExecutor> 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 <typename Handler, typename IoExecutor>
++ 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<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_, 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 <typename Socket>
++ 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 <typename Socket, typename Handler, typename IoExecutor>
++ 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<Socket, Protocol, 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_, 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 <typename PeerIoExecutor, typename Handler, typename IoExecutor>
++ 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<Protocol,
++ PeerIoExecutor, 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_, 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 <typename Handler, typename IoExecutor>
++ 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<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_, 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 <boost/asio/detail/pop_options.hpp>
++
++#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 00000000..8ac32654
+--- /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 <boost/asio/detail/config.hpp>
++
++#if !defined(BOOST_ASIO_HAS_IOCP)
++
++#include <boost/asio/buffer.hpp>
++#include <boost/asio/error.hpp>
++#include <boost/asio/execution_context.hpp>
++#include <boost/asio/socket_base.hpp>
++#include <boost/asio/detail/buffer_sequence_adapter.hpp>
++#include <boost/asio/detail/memory.hpp>
++#include <boost/asio/detail/noncopyable.hpp>
++#include <boost/asio/detail/reactive_null_buffers_op.hpp>
++#include <boost/asio/detail/reactive_socket_accept_op.hpp>
++#include <boost/asio/detail/reactive_socket_connect_op.hpp>
++#include <boost/asio/detail/reactive_socket_recvfrom_op_ext_local.hpp>
++#include <boost/asio/detail/reactive_socket_sendto_op.hpp>
++#include <boost/asio/detail/reactive_socket_service_base_ext_local.hpp>
++#include <boost/asio/detail/reactor.hpp>
++#include <boost/asio/detail/reactor_op.hpp>
++#include <boost/asio/detail/socket_holder.hpp>
++#include <boost/asio/detail/socket_ops.hpp>
++#include <boost/asio/detail/socket_types.hpp>
++
++#include <boost/asio/detail/push_options.hpp>
++
++namespace boost {
++namespace asio {
++namespace detail {
++
++template <typename Protocol>
++class reactive_socket_service_ext_local :
++ public execution_context_service_base<reactive_socket_service_ext_local<Protocol> >,
++ 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<Protocol> >(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 <typename Protocol1>
++ void converting_move_construct(implementation_type& impl,
++ reactive_socket_service_ext_local<Protocol1>&,
++ 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 <typename Option>
++ 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 <typename Option>
++ 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 <typename ConstBufferSequence>
++ 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<boost::asio::const_buffer,
++ ConstBufferSequence> 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 <typename ConstBufferSequence, typename Handler, typename IoExecutor>
++ 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<ConstBufferSequence,
++ endpoint_type, 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,
++ 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 <typename Handler, typename IoExecutor>
++ 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<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_, 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 <typename MutableBufferSequence>
++ 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<boost::asio::mutable_buffer,
++ MutableBufferSequence> 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 <typename MutableBufferSequence,
++ typename Handler, typename IoExecutor>
++ 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<MutableBufferSequence,
++ endpoint_type, Handler, IoExecutor> 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 <typename Handler, typename IoExecutor>
++ 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<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_, 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 <typename Socket>
++ 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 <typename Socket, typename Handler, typename IoExecutor>
++ 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<Socket, Protocol, 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_, 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 <typename PeerIoExecutor, typename Handler, typename IoExecutor>
++ 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<Protocol,
++ PeerIoExecutor, 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_, 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 <typename Handler, typename IoExecutor>
++ 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<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_, 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 <boost/asio/detail/pop_options.hpp>
++
++#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 00000000..697cd9ff
+--- /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 <boost/asio/detail/reactor_op.hpp>
++
++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 00000000..3d9ae5fa
+--- /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 <boost/asio/detail/reactor_op.hpp>
++
++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 00000000..9285fedb
+--- /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 <boost/asio/detail/socket_ops.hpp>
++
++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 <boost/asio/detail/impl/socket_ops_ext.ipp>
++#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 00000000..a937bb65
+--- /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 <boost/asio/detail/config.hpp>
++
++#include <boost/system/error_code.hpp>
++#include <boost/asio/detail/memory.hpp>
++#include <boost/asio/detail/socket_types.hpp>
++
++#include <boost/asio/detail/push_options.hpp>
++
++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 <boost/asio/detail/pop_options.hpp>
++
++#if defined(BOOST_ASIO_HEADER_ONLY)
++# include <boost/asio/detail/impl/socket_ops_ext_local.ipp>
++#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 00000000..6ce2ac44
+--- /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 <boost/asio/detail/config.hpp>
++#include <boost/asio/basic_datagram_socket_ext.hpp>
++#include <boost/asio/detail/socket_types.hpp>
++#include <boost/asio/ip/basic_endpoint.hpp>
++#include <boost/asio/ip/basic_resolver.hpp>
++#include <boost/asio/ip/basic_resolver_iterator.hpp>
++#include <boost/asio/ip/basic_resolver_query.hpp>
++#include <boost/asio/ip/udp.hpp>
++
++#include <boost/asio/detail/push_options.hpp>
++
++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<udp> 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<udp> socket;
++
++ /// The UDP resolver type.
++ typedef basic_resolver<udp> 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 <boost/asio/detail/pop_options.hpp>
++
++#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 00000000..7c57c62f
+--- /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 <boost/asio/detail/config.hpp>
++
++#if defined(BOOST_ASIO_HAS_LOCAL_SOCKETS) \
++ || defined(GENERATING_DOCUMENTATION)
++
++#include <boost/asio/basic_socket_acceptor_ext.hpp>
++#include <boost/asio/basic_socket_iostream.hpp>
++#include <boost/asio/basic_stream_socket_ext.hpp>
++#include <boost/asio/detail/socket_types.hpp>
++#include <boost/asio/local/basic_endpoint.hpp>
++
++#include <boost/asio/detail/push_options.hpp>
++
++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<stream_protocol_ext> endpoint;
++
++ /// The UNIX domain socket type.
++ typedef basic_stream_socket_ext<stream_protocol_ext> socket;
++
++ /// The UNIX domain acceptor type.
++ typedef basic_socket_acceptor_ext<stream_protocol_ext> acceptor;
++
++#if !defined(BOOST_ASIO_NO_IOSTREAM)
++ /// The UNIX domain iostream type.
++ typedef basic_socket_iostream<stream_protocol_ext> iostream;
++#endif // !defined(BOOST_ASIO_NO_IOSTREAM)
++};
++
++} // namespace local
++} // namespace asio
++} // namespace boost
++
++#include <boost/asio/detail/pop_options.hpp>
++
++#endif // defined(BOOST_ASIO_HAS_LOCAL_SOCKETS)
++ // || defined(GENERATING_DOCUMENTATION)
++
++#endif // BOOST_ASIO_LOCAL_STREAM_PROTOCOL_EXT_HPP
+--
+2.25.1
+
new file mode 100644
@@ -0,0 +1,14216 @@
+From a67459625130120a01e787b87bafd68c39db65c8 Mon Sep 17 00:00:00 2001
+From: Stephen Smoogen <ssmoogen@redhat.com>
+Date: Wed, 3 Aug 2022 18:13:36 -0400
+Subject: [PATCH] Add boost 1.78 support so that vsomeip3 will compile in
+ Fedora.
+
+Signed-off-by: Stephen Smoogen <ssmoogen@redhat.com>
+
+Upstream-Status: Backport
+[https://github.com/COVESA/vsomeip/pull/367]
+
+Signed-off-by: Yi Zhao <yi.zhao@windriver.com>
+---
+ CMakeLists.txt | 6 +-
+ .../boost/asio/basic_datagram_socket_ext.hpp | 1118 ++++++++
+ .../boost/asio/basic_socket_acceptor_ext.hpp | 2381 +++++++++++++++++
+ .../1.78/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 | 587 ++++
+ .../handler_type_requirements_ext_local.hpp | 589 ++++
+ .../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.78/boost/asio/detail/reactor_op_ext.hpp | 43 +
+ .../asio/detail/reactor_op_ext_local.hpp | 44 +
+ .../1.78/boost/asio/detail/socket_ops_ext.hpp | 62 +
+ .../asio/detail/socket_ops_ext_local.hpp | 95 +
+ .../helper/1.78/boost/asio/ip/udp_ext.hpp | 115 +
+ .../boost/asio/local/stream_protocol_ext.hpp | 93 +
+ 28 files changed, 13968 insertions(+), 2 deletions(-)
+ create mode 100644 implementation/helper/1.78/boost/asio/basic_datagram_socket_ext.hpp
+ create mode 100644 implementation/helper/1.78/boost/asio/basic_socket_acceptor_ext.hpp
+ create mode 100644 implementation/helper/1.78/boost/asio/basic_socket_ext.hpp
+ create mode 100644 implementation/helper/1.78/boost/asio/basic_socket_ext_local.hpp
+ create mode 100644 implementation/helper/1.78/boost/asio/basic_stream_socket_ext.hpp
+ create mode 100644 implementation/helper/1.78/boost/asio/detail/handler_type_requirements_ext.hpp
+ create mode 100644 implementation/helper/1.78/boost/asio/detail/handler_type_requirements_ext_local.hpp
+ create mode 100644 implementation/helper/1.78/boost/asio/detail/impl/reactive_socket_service_base_ext.ipp
+ create mode 100644 implementation/helper/1.78/boost/asio/detail/impl/reactive_socket_service_base_ext_local.ipp
+ create mode 100644 implementation/helper/1.78/boost/asio/detail/impl/socket_ops_ext.ipp
+ create mode 100644 implementation/helper/1.78/boost/asio/detail/impl/socket_ops_ext_local.ipp
+ create mode 100644 implementation/helper/1.78/boost/asio/detail/reactive_socket_recv_op_ext.hpp
+ create mode 100644 implementation/helper/1.78/boost/asio/detail/reactive_socket_recv_op_ext_local.hpp
+ create mode 100644 implementation/helper/1.78/boost/asio/detail/reactive_socket_recvfrom_op_ext.hpp
+ create mode 100644 implementation/helper/1.78/boost/asio/detail/reactive_socket_recvfrom_op_ext_local.hpp
+ create mode 100644 implementation/helper/1.78/boost/asio/detail/reactive_socket_recvmsg_op_ext.hpp
+ create mode 100644 implementation/helper/1.78/boost/asio/detail/reactive_socket_recvmsg_op_ext_local.hpp
+ create mode 100644 implementation/helper/1.78/boost/asio/detail/reactive_socket_service_base_ext.hpp
+ create mode 100644 implementation/helper/1.78/boost/asio/detail/reactive_socket_service_base_ext_local.hpp
+ create mode 100644 implementation/helper/1.78/boost/asio/detail/reactive_socket_service_ext.hpp
+ create mode 100644 implementation/helper/1.78/boost/asio/detail/reactive_socket_service_ext_local.hpp
+ create mode 100644 implementation/helper/1.78/boost/asio/detail/reactor_op_ext.hpp
+ create mode 100644 implementation/helper/1.78/boost/asio/detail/reactor_op_ext_local.hpp
+ create mode 100644 implementation/helper/1.78/boost/asio/detail/socket_ops_ext.hpp
+ create mode 100644 implementation/helper/1.78/boost/asio/detail/socket_ops_ext_local.hpp
+ create mode 100644 implementation/helper/1.78/boost/asio/ip/udp_ext.hpp
+ create mode 100644 implementation/helper/1.78/boost/asio/local/stream_protocol_ext.hpp
+
+diff --git a/CMakeLists.txt b/CMakeLists.txt
+index dad03555..02172b7a 100644
+--- a/CMakeLists.txt
++++ b/CMakeLists.txt
+@@ -156,8 +156,10 @@ else()
+ endif()
+
+ message( STATUS "Using boost version: ${VSOMEIP_BOOST_VERSION}" )
+-if (${VSOMEIP_BOOST_VERSION} GREATER 107600)
+-message( ERROR "boost version ${VSOMEIP_BOOST_VERSION} is not (yet) supported. Latest supported version is 1.76.0" )
++if (${VSOMEIP_BOOST_VERSION} GREATER 107800)
++message( ERROR "boost version ${VSOMEIP_BOOST_VERSION} is not (yet) supported. Latest supported version is 1.78.0" )
++elseif(${VSOMEIP_BOOST_VERSION} GREATER 107600)
++set(VSOMEIP_BOOST_HELPER implementation/helper/1.78)
+ elseif(${VSOMEIP_BOOST_VERSION} GREATER 107500)
+ set(VSOMEIP_BOOST_HELPER implementation/helper/1.76)
+ elseif(${VSOMEIP_BOOST_VERSION} GREATER 107300)
+diff --git a/implementation/helper/1.78/boost/asio/basic_datagram_socket_ext.hpp b/implementation/helper/1.78/boost/asio/basic_datagram_socket_ext.hpp
+new file mode 100644
+index 00000000..49a4950a
+--- /dev/null
++++ b/implementation/helper/1.78/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 <boost/asio/detail/config.hpp>
++#include <cstddef>
++#include <boost/asio/basic_socket_ext.hpp>
++#include <boost/asio/detail/handler_type_requirements_ext.hpp>
++#include <boost/asio/detail/non_const_lvalue.hpp>
++#include <boost/asio/detail/throw_error.hpp>
++#include <boost/asio/detail/type_traits.hpp>
++#include <boost/asio/error.hpp>
++
++#include <boost/asio/detail/push_options.hpp>
++
++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 <typename Protocol, typename Executor = executor>
++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 <typename Protocol, typename Executor>
++class basic_datagram_socket_ext
++ : public basic_socket_ext<Protocol, Executor>
++{
++public:
++ /// The type of the executor associated with the object.
++ typedef Executor executor_type;
++
++ /// Rebinds the socket type to another executor.
++ template <typename Executor1>
++ struct rebind_executor
++ {
++ /// The socket type when rebound to the specified executor.
++ typedef basic_datagram_socket_ext<Protocol, Executor1> other;
++ };
++
++ /// The native representation of a socket.
++#if defined(GENERATING_DOCUMENTATION)
++ typedef implementation_defined native_handle_type;
++#else
++ typedef typename basic_socket_ext<Protocol,
++ Executor>::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<Protocol, Executor>(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 <typename ExecutionContext>
++ explicit basic_datagram_socket_ext(ExecutionContext& context,
++ typename enable_if<
++ is_convertible<ExecutionContext&, execution_context&>::value
++ >::type* = 0)
++ : basic_socket_ext<Protocol, Executor>(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<Protocol, Executor>(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 <typename ExecutionContext>
++ basic_datagram_socket_ext(ExecutionContext& context,
++ const protocol_type& protocol,
++ typename enable_if<
++ is_convertible<ExecutionContext&, execution_context&>::value
++ >::type* = 0)
++ : basic_socket_ext<Protocol, Executor>(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<Protocol, Executor>(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 <typename ExecutionContext>
++ basic_datagram_socket_ext(ExecutionContext& context,
++ const endpoint_type& endpoint,
++ typename enable_if<
++ is_convertible<ExecutionContext&, execution_context&>::value
++ >::type* = 0)
++ : basic_socket_ext<Protocol, Executor>(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<Protocol, Executor>(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 <typename ExecutionContext>
++ basic_datagram_socket_ext(ExecutionContext& context,
++ const protocol_type& protocol, const native_handle_type& native_socket,
++ typename enable_if<
++ is_convertible<ExecutionContext&, execution_context&>::value
++ >::type* = 0)
++ : basic_socket_ext<Protocol, Executor>(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<Protocol, Executor>(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<Protocol, Executor>::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 <typename Protocol1, typename Executor1>
++ basic_datagram_socket_ext(basic_datagram_socket_ext<Protocol1, Executor1>&& other,
++ typename enable_if<
++ is_convertible<Protocol1, Protocol>::value
++ && is_convertible<Executor1, Executor>::value
++ >::type* = 0)
++ : basic_socket_ext<Protocol, Executor>(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 Protocol1, typename Executor1>
++ typename enable_if<
++ is_convertible<Protocol1, Protocol>::value
++ && is_convertible<Executor1, Executor>::value,
++ basic_datagram_socket_ext&
++ >::type operator=(basic_datagram_socket_ext<Protocol1, Executor1>&& other)
++ {
++ basic_socket_ext<Protocol, Executor>::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 <typename ConstBufferSequence>
++ 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 <typename ConstBufferSequence>
++ 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 <typename ConstBufferSequence>
++ 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 <typename ConstBufferSequence, typename WriteHandler>
++ 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<WriteHandler,
++ void (boost::system::error_code, std::size_t)>(
++ 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 <typename ConstBufferSequence, typename WriteHandler>
++ 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<WriteHandler,
++ void (boost::system::error_code, std::size_t)>(
++ 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 <typename ConstBufferSequence>
++ 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 <typename ConstBufferSequence>
++ 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 <typename ConstBufferSequence>
++ 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 <typename ConstBufferSequence, typename WriteHandler>
++ 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<WriteHandler,
++ void (boost::system::error_code, std::size_t)>(
++ 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 <typename ConstBufferSequence, typename WriteHandler>
++ 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<WriteHandler,
++ void (boost::system::error_code, std::size_t)>(
++ 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 <typename MutableBufferSequence>
++ 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 <typename MutableBufferSequence>
++ 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 <typename MutableBufferSequence>
++ 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 <typename MutableBufferSequence, typename ReadHandler>
++ 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<ReadHandler,
++ void (boost::system::error_code, std::size_t, boost::asio::ip::address)>(
++ 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 <typename MutableBufferSequence, typename ReadHandler>
++ 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<ReadHandler,
++ void (boost::system::error_code, std::size_t, boost::asio::ip::address)>(
++ 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 <typename MutableBufferSequence>
++ 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 <typename MutableBufferSequence>
++ 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 <typename MutableBufferSequence>
++ 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 <typename MutableBufferSequence, typename ReadHandler>
++ 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<ReadHandler,
++ void (boost::system::error_code, std::size_t, boost::asio::ip::address)>(
++ 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 <typename MutableBufferSequence, typename ReadHandler>
++ 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<ReadHandler,
++ void (boost::system::error_code, std::size_t, boost::asio::ip::address)>(
++ initiate_async_receive_from(), handler,
++ this, buffers, &sender_endpoint, flags);
++ }
++
++private:
++ struct initiate_async_send
++ {
++ template <typename WriteHandler, typename ConstBufferSequence>
++ 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<WriteHandler> 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 <typename WriteHandler, typename ConstBufferSequence>
++ 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<WriteHandler> 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 <typename ReadHandler, typename MutableBufferSequence>
++ 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<ReadHandler> 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 <typename ReadHandler, typename MutableBufferSequence>
++ 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<ReadHandler> 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 <boost/asio/detail/pop_options.hpp>
++
++#endif // BOOST_ASIO_BASIC_DATAGRAM_SOCKET_EXT_HPP
+diff --git a/implementation/helper/1.78/boost/asio/basic_socket_acceptor_ext.hpp b/implementation/helper/1.78/boost/asio/basic_socket_acceptor_ext.hpp
+new file mode 100644
+index 00000000..0a86539a
+--- /dev/null
++++ b/implementation/helper/1.78/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 <boost/asio/detail/config.hpp>
++#include <boost/asio/basic_socket_ext_local.hpp>
++#include <boost/asio/detail/handler_type_requirements_ext.hpp>
++#include <boost/asio/detail/io_object_impl.hpp>
++#include <boost/asio/detail/non_const_lvalue.hpp>
++#include <boost/asio/detail/throw_error.hpp>
++#include <boost/asio/detail/type_traits.hpp>
++#include <boost/asio/error.hpp>
++#include <boost/asio/execution_context.hpp>
++#include <boost/asio/executor.hpp>
++#include <boost/asio/socket_base.hpp>
++
++#if defined(BOOST_ASIO_WINDOWS_RUNTIME)
++# include <boost/asio/detail/null_socket_service.hpp>
++#elif defined(BOOST_ASIO_HAS_IOCP)
++# include <boost/asio/detail/win_iocp_socket_service.hpp>
++#else
++# include <boost/asio/detail/reactive_socket_service_ext_local.hpp>
++#endif
++
++#if defined(BOOST_ASIO_HAS_MOVE)
++# include <utility>
++#endif // defined(BOOST_ASIO_HAS_MOVE)
++
++#include <boost/asio/detail/push_options.hpp>
++
++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 <typename Protocol, typename Executor = executor>
++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 <typename Protocol, typename Executor>
++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 <typename ExecutionContext>
++ explicit basic_socket_acceptor_ext(ExecutionContext& context,
++ typename enable_if<
++ is_convertible<ExecutionContext&, execution_context&>::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 <typename ExecutionContext>
++ basic_socket_acceptor_ext(ExecutionContext& context,
++ const protocol_type& protocol,
++ typename enable_if<
++ is_convertible<ExecutionContext&, execution_context&>::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<Protocol> 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<Protocol> 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 <typename ExecutionContext>
++ basic_socket_acceptor_ext(ExecutionContext& context,
++ const endpoint_type& endpoint, bool reuse_addr = true,
++ typename enable_if<
++ is_convertible<ExecutionContext&, execution_context&>::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 <typename ExecutionContext>
++ basic_socket_acceptor_ext(ExecutionContext& context,
++ const protocol_type& protocol, const native_handle_type& native_acceptor,
++ typename enable_if<
++ is_convertible<ExecutionContext&, execution_context&>::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 <typename Protocol1, typename Executor1>
++ 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 <typename Protocol1, typename Executor1>
++ basic_socket_acceptor_ext(basic_socket_acceptor_ext<Protocol1, Executor1>&& other,
++ typename enable_if<
++ is_convertible<Protocol1, Protocol>::value
++ && is_convertible<Executor1, Executor>::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 Protocol1, typename Executor1>
++ typename enable_if<
++ is_convertible<Protocol1, Protocol>::value
++ && is_convertible<Executor1, Executor>::value,
++ basic_socket_acceptor_ext&
++ >::type operator=(basic_socket_acceptor_ext<Protocol1, Executor1>&& 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 <typename SettableSocketOption>
++ 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 <typename SettableSocketOption>
++ 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 <typename GettableSocketOption>
++ 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 <typename GettableSocketOption>
++ 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 <typename IoControlCommand>
++ 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 <typename IoControlCommand>
++ 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 <typename WaitHandler>
++ 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<WaitHandler, void (boost::system::error_code)>(
++ 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 <typename Protocol1, typename Executor1>
++ void accept(basic_socket_ext_local<Protocol1, Executor1>& peer,
++ typename enable_if<
++ is_convertible<Protocol, Protocol1>::value
++ >::type* = 0)
++ {
++ boost::system::error_code ec;
++ impl_.get_service().accept(impl_.get_implementation(),
++ peer, static_cast<endpoint_type*>(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 <typename Protocol1, typename Executor1>
++ BOOST_ASIO_SYNC_OP_VOID accept(
++ basic_socket_ext_local<Protocol1, Executor1>& peer, boost::system::error_code& ec,
++ typename enable_if<
++ is_convertible<Protocol, Protocol1>::value
++ >::type* = 0)
++ {
++ impl_.get_service().accept(impl_.get_implementation(),
++ peer, static_cast<endpoint_type*>(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 <typename Protocol1, typename Executor1, typename AcceptHandler>
++ BOOST_ASIO_INITFN_RESULT_TYPE(AcceptHandler,
++ void (boost::system::error_code))
++ async_accept(basic_socket_ext_local<Protocol1, Executor1>& peer,
++ BOOST_ASIO_MOVE_ARG(AcceptHandler) handler,
++ typename enable_if<
++ is_convertible<Protocol, Protocol1>::value
++ >::type* = 0)
++ {
++ return async_initiate<AcceptHandler, void (boost::system::error_code)>(
++ initiate_async_accept(), handler, this,
++ &peer, static_cast<endpoint_type*>(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 <typename Executor1>
++ void accept(basic_socket_ext_local<protocol_type, Executor1>& 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 <typename Executor1>
++ BOOST_ASIO_SYNC_OP_VOID accept(basic_socket_ext_local<protocol_type, Executor1>& 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 <typename Executor1, typename AcceptHandler>
++ BOOST_ASIO_INITFN_RESULT_TYPE(AcceptHandler,
++ void (boost::system::error_code))
++ async_accept(basic_socket_ext_local<protocol_type, Executor1>& peer,
++ endpoint_type& peer_endpoint, BOOST_ASIO_MOVE_ARG(AcceptHandler) handler)
++ {
++ return async_initiate<AcceptHandler, void (boost::system::error_code)>(
++ 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 <typename MoveAcceptHandler>
++ 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<MoveAcceptHandler,
++ void (boost::system::error_code, typename Protocol::socket)>(
++ initiate_async_move_accept(), handler, this,
++ impl_.get_executor(), static_cast<endpoint_type*>(0),
++ static_cast<typename Protocol::socket*>(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 Executor1>
++ typename Protocol::socket::template rebind_executor<Executor1>::other
++ accept(const Executor1& ex,
++ typename enable_if<
++ is_executor<Executor1>::value
++ >::type* = 0)
++ {
++ boost::system::error_code ec;
++ typename Protocol::socket::template
++ rebind_executor<Executor1>::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 ExecutionContext>
++ typename Protocol::socket::template rebind_executor<
++ typename ExecutionContext::executor_type>::other
++ accept(ExecutionContext& context,
++ typename enable_if<
++ is_convertible<ExecutionContext&, execution_context&>::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 Executor1>
++ typename Protocol::socket::template rebind_executor<Executor1>::other
++ accept(const Executor1& ex, boost::system::error_code& ec,
++ typename enable_if<
++ is_executor<Executor1>::value
++ >::type* = 0)
++ {
++ typename Protocol::socket::template
++ rebind_executor<Executor1>::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 ExecutionContext>
++ typename Protocol::socket::template rebind_executor<
++ typename ExecutionContext::executor_type>::other
++ accept(ExecutionContext& context, boost::system::error_code& ec,
++ typename enable_if<
++ is_convertible<ExecutionContext&, execution_context&>::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 <typename Executor1, typename MoveAcceptHandler>
++ 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<Executor1>::value
++ >::type* = 0)
++ {
++ typedef typename Protocol::socket::template rebind_executor<
++ Executor1>::other other_socket_type;
++
++ return async_initiate<MoveAcceptHandler,
++ void (boost::system::error_code, other_socket_type)>(
++ initiate_async_move_accept(), handler, this,
++ ex, static_cast<endpoint_type*>(0),
++ static_cast<other_socket_type*>(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 <typename ExecutionContext, typename MoveAcceptHandler>
++ 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<ExecutionContext&, execution_context&>::value
++ >::type* = 0)
++ {
++ typedef typename Protocol::socket::template rebind_executor<
++ typename ExecutionContext::executor_type>::other other_socket_type;
++
++ return async_initiate<MoveAcceptHandler,
++ void (boost::system::error_code, other_socket_type)>(
++ initiate_async_move_accept(), handler, this,
++ context.get_executor(), static_cast<endpoint_type*>(0),
++ static_cast<other_socket_type*>(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 <typename MoveAcceptHandler>
++ 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<MoveAcceptHandler,
++ void (boost::system::error_code, typename Protocol::socket)>(
++ initiate_async_move_accept(), handler, this,
++ impl_.get_executor(), &peer_endpoint,
++ static_cast<typename Protocol::socket*>(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 Executor1>
++ typename Protocol::socket::template rebind_executor<Executor1>::other
++ accept(const Executor1& ex, endpoint_type& peer_endpoint,
++ typename enable_if<
++ is_executor<Executor1>::value
++ >::type* = 0)
++ {
++ boost::system::error_code ec;
++ typename Protocol::socket::template
++ rebind_executor<Executor1>::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 ExecutionContext>
++ typename Protocol::socket::template rebind_executor<
++ typename ExecutionContext::executor_type>::other
++ accept(ExecutionContext& context, endpoint_type& peer_endpoint,
++ typename enable_if<
++ is_convertible<ExecutionContext&, execution_context&>::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 Executor1>
++ typename Protocol::socket::template rebind_executor<Executor1>::other
++ accept(const executor_type& ex,
++ endpoint_type& peer_endpoint, boost::system::error_code& ec,
++ typename enable_if<
++ is_executor<Executor1>::value
++ >::type* = 0)
++ {
++ typename Protocol::socket::template
++ rebind_executor<Executor1>::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 ExecutionContext>
++ 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<ExecutionContext&, execution_context&>::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 <typename Executor1, typename MoveAcceptHandler>
++ 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<Executor1>::value
++ >::type* = 0)
++ {
++ typedef typename Protocol::socket::template rebind_executor<
++ Executor1>::other other_socket_type;
++
++ return async_initiate<MoveAcceptHandler,
++ void (boost::system::error_code, other_socket_type)>(
++ initiate_async_move_accept(), handler, this,
++ ex, &peer_endpoint,
++ static_cast<other_socket_type*>(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 <typename ExecutionContext, typename MoveAcceptHandler>
++ 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<ExecutionContext&, execution_context&>::value
++ >::type* = 0)
++ {
++ typedef typename Protocol::socket::template rebind_executor<
++ typename ExecutionContext::executor_type>::other other_socket_type;
++
++ return async_initiate<MoveAcceptHandler,
++ void (boost::system::error_code, other_socket_type)>(
++ initiate_async_move_accept(), handler, this,
++ context.get_executor(), &peer_endpoint,
++ static_cast<other_socket_type*>(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 <typename WaitHandler>
++ 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<WaitHandler> 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 <typename AcceptHandler, typename Protocol1, typename Executor1>
++ void operator()(BOOST_ASIO_MOVE_ARG(AcceptHandler) handler,
++ basic_socket_acceptor_ext* self, basic_socket_ext_local<Protocol1, Executor1>* 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<AcceptHandler> 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 <typename MoveAcceptHandler, typename Executor1, typename Socket>
++ 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<MoveAcceptHandler> 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<Protocol>, Executor> impl_;
++#elif defined(BOOST_ASIO_HAS_IOCP)
++ detail::io_object_impl<
++ detail::win_iocp_socket_service<Protocol>, Executor> impl_;
++#else
++ detail::io_object_impl<
++ detail::reactive_socket_service_ext_local<Protocol>, Executor> impl_;
++#endif
++};
++
++} // namespace asio
++} // namespace boost
++
++#include <boost/asio/detail/pop_options.hpp>
++
++#endif // BOOST_ASIO_BASIC_SOCKET_ACCEPTOR_EXT_HPP
+diff --git a/implementation/helper/1.78/boost/asio/basic_socket_ext.hpp b/implementation/helper/1.78/boost/asio/basic_socket_ext.hpp
+new file mode 100644
+index 00000000..777a0bf7
+--- /dev/null
++++ b/implementation/helper/1.78/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 <boost/asio/detail/config.hpp>
++#include <boost/asio/async_result.hpp>
++#include <boost/asio/detail/handler_type_requirements.hpp>
++#include <boost/asio/detail/io_object_impl.hpp>
++#include <boost/asio/detail/non_const_lvalue.hpp>
++#include <boost/asio/detail/throw_error.hpp>
++#include <boost/asio/detail/type_traits.hpp>
++#include <boost/asio/error.hpp>
++#include <boost/asio/execution_context.hpp>
++#include <boost/asio/executor.hpp>
++#include <boost/asio/post.hpp>
++#include <boost/asio/socket_base.hpp>
++
++#if defined(BOOST_ASIO_WINDOWS_RUNTIME)
++# include <boost/asio/detail/null_socket_service.hpp>
++#elif defined(BOOST_ASIO_HAS_IOCP)
++# include <boost/asio/detail/win_iocp_socket_service.hpp>
++#else
++# include <boost/asio/detail/reactive_socket_service_ext.hpp>
++#endif
++
++#if defined(BOOST_ASIO_HAS_MOVE)
++# include <utility>
++#endif // defined(BOOST_ASIO_HAS_MOVE)
++
++#include <boost/asio/detail/push_options.hpp>
++
++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 <typename Protocol, typename Executor = executor>
++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 <typename Protocol, typename Executor>
++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 <typename Executor1>
++ struct rebind_executor
++ {
++ /// The socket type when rebound to the specified executor.
++ typedef basic_socket_ext<Protocol, Executor1> 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<Protocol, Executor> 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 <typename ExecutionContext>
++ explicit basic_socket_ext(ExecutionContext& context,
++ typename enable_if<
++ is_convertible<ExecutionContext&, execution_context&>::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 <typename ExecutionContext>
++ basic_socket_ext(ExecutionContext& context, const protocol_type& protocol,
++ typename enable_if<
++ is_convertible<ExecutionContext&, execution_context&>::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 <typename ExecutionContext>
++ basic_socket_ext(ExecutionContext& context, const endpoint_type& endpoint,
++ typename enable_if<
++ is_convertible<ExecutionContext&, execution_context&>::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 <typename ExecutionContext>
++ basic_socket_ext(ExecutionContext& context, const protocol_type& protocol,
++ const native_handle_type& native_socket,
++ typename enable_if<
++ is_convertible<ExecutionContext&, execution_context&>::value
++ >::type* = 0)
++ : 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 <typename Protocol1, typename Executor1>
++ 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 <typename Protocol1, typename Executor1>
++ basic_socket_ext(basic_socket_ext<Protocol1, Executor1>&& other,
++ typename enable_if<
++ is_convertible<Protocol1, Protocol>::value
++ && is_convertible<Executor1, Executor>::value
++ >::type* = 0)
++ : 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 Protocol1, typename Executor1>
++ typename enable_if<
++ is_convertible<Protocol1, Protocol>::value
++ && is_convertible<Executor1, Executor>::value,
++ basic_socket_ext&
++ >::type operator=(basic_socket_ext<Protocol1, Executor1> && 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 <typename ConnectHandler>
++ 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<ConnectHandler, void (boost::system::error_code)>(
++ 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 <typename SettableSocketOption>
++ 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 <typename SettableSocketOption>
++ 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 <typename GettableSocketOption>
++ 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 <typename GettableSocketOption>
++ 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 <typename IoControlCommand>
++ 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 <typename IoControlCommand>
++ 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 <typename Handler>
++ * 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 <typename Handler>
++ * void async_sendfile(tcp::socket& sock, int fd, Handler h)
++ * {
++ * sendfile_op<Handler> 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 <typename Handler>
++ * 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 <typename Handler>
++ * void async_sendfile(tcp::socket& sock, int fd, Handler h)
++ * {
++ * sendfile_op<Handler> 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 <typename Handler>
++ * 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 <typename Handler>
++ * void async_sendfile(tcp::socket& sock, int fd, Handler h)
++ * {
++ * sendfile_op<Handler> 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 <typename WaitHandler>
++ 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<WaitHandler, void (boost::system::error_code)>(
++ 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<Protocol>, Executor> impl_;
++#elif defined(BOOST_ASIO_HAS_IOCP)
++ detail::io_object_impl<
++ detail::win_iocp_socket_service<Protocol>, Executor> impl_;
++#else
++ detail::io_object_impl<
++ detail::reactive_socket_service_ext<Protocol>, 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 <typename ConnectHandler>
++ 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<ConnectHandler> 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 <typename WaitHandler>
++ 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<WaitHandler> 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 <boost/asio/detail/pop_options.hpp>
++
++#endif // BOOST_ASIO_BASIC_SOCKET_EXT_HPP
+diff --git a/implementation/helper/1.78/boost/asio/basic_socket_ext_local.hpp b/implementation/helper/1.78/boost/asio/basic_socket_ext_local.hpp
+new file mode 100644
+index 00000000..2c898fc6
+--- /dev/null
++++ b/implementation/helper/1.78/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 <boost/asio/detail/config.hpp>
++#include <boost/asio/async_result.hpp>
++#include <boost/asio/detail/handler_type_requirements_ext.hpp>
++#include <boost/asio/detail/io_object_impl.hpp>
++#include <boost/asio/detail/non_const_lvalue.hpp>
++#include <boost/asio/detail/throw_error.hpp>
++#include <boost/asio/detail/type_traits.hpp>
++#include <boost/asio/error.hpp>
++#include <boost/asio/execution_context.hpp>
++#include <boost/asio/executor.hpp>
++#include <boost/asio/post.hpp>
++#include <boost/asio/socket_base.hpp>
++
++#if defined(BOOST_ASIO_WINDOWS_RUNTIME)
++# include <boost/asio/detail/null_socket_service.hpp>
++#elif defined(BOOST_ASIO_HAS_IOCP)
++# include <boost/asio/detail/win_iocp_socket_service.hpp>
++#else
++# include <boost/asio/detail/reactive_socket_service_ext_local.hpp>
++#endif
++
++#if defined(BOOST_ASIO_HAS_MOVE)
++# include <utility>
++#endif // defined(BOOST_ASIO_HAS_MOVE)
++
++#include <boost/asio/detail/push_options.hpp>
++
++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 <typename Protocol, typename Executor = executor>
++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 <typename Protocol, typename Executor>
++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 <typename Executor1>
++ struct rebind_executor
++ {
++ /// The socket type when rebound to the specified executor.
++ typedef basic_socket_ext_local<Protocol, Executor1> 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<Protocol, Executor> 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 <typename ExecutionContext>
++ explicit basic_socket_ext_local(ExecutionContext& context,
++ typename enable_if<
++ is_convertible<ExecutionContext&, execution_context&>::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 <typename ExecutionContext>
++ basic_socket_ext_local(ExecutionContext& context, const protocol_type& protocol,
++ typename enable_if<
++ is_convertible<ExecutionContext&, execution_context&>::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 <typename ExecutionContext>
++ basic_socket_ext_local(ExecutionContext& context, const endpoint_type& endpoint,
++ typename enable_if<
++ is_convertible<ExecutionContext&, execution_context&>::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 <typename ExecutionContext>
++ basic_socket_ext_local(ExecutionContext& context, const protocol_type& protocol,
++ const native_handle_type& native_socket,
++ typename enable_if<
++ is_convertible<ExecutionContext&, execution_context&>::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 <typename Protocol1, typename Executor1>
++ 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 <typename Protocol1, typename Executor1>
++ basic_socket_ext_local(basic_socket_ext_local<Protocol1, Executor1>&& other,
++ typename enable_if<
++ is_convertible<Protocol1, Protocol>::value
++ && is_convertible<Executor1, Executor>::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 Protocol1, typename Executor1>
++ typename enable_if<
++ is_convertible<Protocol1, Protocol>::value
++ && is_convertible<Executor1, Executor>::value,
++ basic_socket_ext_local&
++ >::type operator=(basic_socket_ext_local<Protocol1, Executor1> && 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 <typename ConnectHandler>
++ 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<ConnectHandler, void (boost::system::error_code)>(
++ 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 <typename SettableSocketOption>
++ 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 <typename SettableSocketOption>
++ 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 <typename GettableSocketOption>
++ 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 <typename GettableSocketOption>
++ 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 <typename IoControlCommand>
++ 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 <typename IoControlCommand>
++ 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 <typename Handler>
++ * 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 <typename Handler>
++ * void async_sendfile(tcp::socket& sock, int fd, Handler h)
++ * {
++ * sendfile_op<Handler> 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 <typename Handler>
++ * 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 <typename Handler>
++ * void async_sendfile(tcp::socket& sock, int fd, Handler h)
++ * {
++ * sendfile_op<Handler> 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 <typename Handler>
++ * 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 <typename Handler>
++ * void async_sendfile(tcp::socket& sock, int fd, Handler h)
++ * {
++ * sendfile_op<Handler> 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 <typename WaitHandler>
++ 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<WaitHandler, void (boost::system::error_code)>(
++ 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<Protocol>, Executor> impl_;
++#elif defined(BOOST_ASIO_HAS_IOCP)
++ detail::io_object_impl<
++ detail::win_iocp_socket_service<Protocol>, Executor> impl_;
++#else
++ detail::io_object_impl<
++ detail::reactive_socket_service_ext_local<Protocol>, 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 <typename ConnectHandler>
++ 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<ConnectHandler> 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 <typename WaitHandler>
++ 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<WaitHandler> 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 <boost/asio/detail/pop_options.hpp>
++
++#endif // BOOST_ASIO_BASIC_SOCKET_EXT_LOCAL_HPP
+diff --git a/implementation/helper/1.78/boost/asio/basic_stream_socket_ext.hpp b/implementation/helper/1.78/boost/asio/basic_stream_socket_ext.hpp
+new file mode 100644
+index 00000000..e77f5ebb
+--- /dev/null
++++ b/implementation/helper/1.78/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 <boost/asio/detail/config.hpp>
++#include <cstddef>
++#include <boost/asio/async_result.hpp>
++#include <boost/asio/basic_socket_ext_local.hpp>
++#include <boost/asio/detail/handler_type_requirements_ext_local.hpp>
++#include <boost/asio/detail/non_const_lvalue.hpp>
++#include <boost/asio/detail/throw_error.hpp>
++#include <boost/asio/error.hpp>
++
++#include <boost/asio/detail/push_options.hpp>
++
++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 <typename Protocol, typename Executor = executor>
++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 <typename Protocol, typename Executor>
++class basic_stream_socket_ext
++ : public basic_socket_ext_local<Protocol, Executor>
++{
++public:
++ /// The type of the executor associated with the object.
++ typedef Executor executor_type;
++
++ /// Rebinds the socket type to another executor.
++ template <typename Executor1>
++ struct rebind_executor
++ {
++ /// The socket type when rebound to the specified executor.
++ typedef basic_stream_socket_ext<Protocol, Executor1> other;
++ };
++
++ /// The native representation of a socket.
++#if defined(GENERATING_DOCUMENTATION)
++ typedef implementation_defined native_handle_type;
++#else
++ typedef typename basic_socket<Protocol,
++ Executor>::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<Protocol, Executor>(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 <typename ExecutionContext>
++ explicit basic_stream_socket_ext(ExecutionContext& context,
++ typename enable_if<
++ is_convertible<ExecutionContext&, execution_context&>::value
++ >::type* = 0)
++ : basic_socket_ext_local<Protocol, Executor>(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<Protocol, Executor>(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 <typename ExecutionContext>
++ basic_stream_socket_ext(ExecutionContext& context, const protocol_type& protocol,
++ typename enable_if<
++ is_convertible<ExecutionContext&, execution_context&>::value
++ >::type* = 0)
++ : basic_socket_ext_local<Protocol, Executor>(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<Protocol, Executor>(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 <typename ExecutionContext>
++ basic_stream_socket_ext(ExecutionContext& context, const endpoint_type& endpoint,
++ typename enable_if<
++ is_convertible<ExecutionContext&, execution_context&>::value
++ >::type* = 0)
++ : basic_socket_ext_local<Protocol, Executor>(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<Protocol, Executor>(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 <typename ExecutionContext>
++ basic_stream_socket_ext(ExecutionContext& context,
++ const protocol_type& protocol, const native_handle_type& native_socket,
++ typename enable_if<
++ is_convertible<ExecutionContext&, execution_context&>::value
++ >::type* = 0)
++ : basic_socket_ext_local<Protocol, Executor>(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<Protocol, Executor>(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<Protocol, Executor>::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 <typename Protocol1, typename Executor1>
++ basic_stream_socket_ext(basic_stream_socket_ext<Protocol1, Executor1>&& other,
++ typename enable_if<
++ is_convertible<Protocol1, Protocol>::value
++ && is_convertible<Executor1, Executor>::value
++ >::type* = 0)
++ : basic_socket_ext_local<Protocol, Executor>(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 Protocol1, typename Executor1>
++ typename enable_if<
++ is_convertible<Protocol1, Protocol>::value
++ && is_convertible<Executor1, Executor>::value,
++ basic_stream_socket_ext&
++ >::type operator=(basic_stream_socket_ext<Protocol1, Executor1>&& other)
++ {
++ basic_socket_ext_local<Protocol, Executor>::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 <typename ConstBufferSequence>
++ 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 <typename ConstBufferSequence>
++ 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 <typename ConstBufferSequence>
++ 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 <typename ConstBufferSequence, typename WriteHandler>
++ 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<WriteHandler,
++ void (boost::system::error_code, std::size_t)>(
++ 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 <typename ConstBufferSequence, typename WriteHandler>
++ 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<WriteHandler,
++ void (boost::system::error_code, std::size_t)>(
++ 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 <typename MutableBufferSequence>
++ 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 <typename MutableBufferSequence>
++ 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 <typename MutableBufferSequence>
++ 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 <typename MutableBufferSequence, typename ReadHandler>
++ 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<ReadHandler,
++ void (boost::system::error_code, std::size_t, std::uint32_t, std::uint32_t)>(
++ 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 <typename MutableBufferSequence, typename ReadHandler>
++ 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<ReadHandler,
++ void (boost::system::error_code, std::size_t, std::uint32_t, std::uint32_t)>(
++ 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 <typename ConstBufferSequence>
++ 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 <typename ConstBufferSequence>
++ 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 <typename ConstBufferSequence, typename WriteHandler>
++ 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<WriteHandler,
++ void (boost::system::error_code, std::size_t, std::uint32_t, std::uint32_t)>(
++ 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 <typename MutableBufferSequence>
++ 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 <typename MutableBufferSequence>
++ 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 <typename MutableBufferSequence, typename ReadHandler>
++ 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<ReadHandler,
++ void (boost::system::error_code, std::size_t, std::uint32_t, std::uint32_t)>(
++ initiate_async_receive(), handler, this,
++ buffers, socket_base::message_flags(0));
++ }
++
++private:
++ struct initiate_async_send
++ {
++ template <typename WriteHandler, typename ConstBufferSequence>
++ 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<WriteHandler> 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 <typename ReadHandler, typename MutableBufferSequence>
++ 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<ReadHandler> 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 <boost/asio/detail/pop_options.hpp>
++
++#endif // BOOST_ASIO_BASIC_STREAM_SOCKET_EXT_HPP
+diff --git a/implementation/helper/1.78/boost/asio/detail/handler_type_requirements_ext.hpp b/implementation/helper/1.78/boost/asio/detail/handler_type_requirements_ext.hpp
+new file mode 100644
+index 00000000..ffa5f61d
+--- /dev/null
++++ b/implementation/helper/1.78/boost/asio/detail/handler_type_requirements_ext.hpp
+@@ -0,0 +1,587 @@
++//
++// 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 <boost/asio/detail/config.hpp>
++
++// 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 <boost/asio/async_result.hpp>
++#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 <typename Handler>
++auto zero_arg_copyable_handler_test(Handler h, void*)
++ -> decltype(
++ sizeof(Handler(static_cast<const Handler&>(h))),
++ (BOOST_ASIO_MOVE_OR_LVALUE(Handler)(h)()),
++ char(0));
++
++template <typename Handler>
++char (&zero_arg_copyable_handler_test(Handler, ...))[2];
++
++template <typename Handler, typename Arg1>
++auto one_arg_handler_test(Handler h, Arg1* a1)
++ -> decltype(
++ sizeof(Handler(BOOST_ASIO_MOVE_CAST(Handler)(h))),
++ (BOOST_ASIO_MOVE_OR_LVALUE(Handler)(h)(*a1)),
++ char(0));
++
++template <typename Handler>
++char (&one_arg_handler_test(Handler h, ...))[2];
++
++template <typename Handler, typename Arg1, typename Arg2>
++auto two_arg_handler_test(Handler h, Arg1* a1, Arg2* a2)
++ -> decltype(
++ sizeof(Handler(BOOST_ASIO_MOVE_CAST(Handler)(h))),
++ (BOOST_ASIO_MOVE_OR_LVALUE(Handler)(h)(*a1, *a2)),
++ char(0));
++
++template <typename Handler>
++char (&two_arg_handler_test(Handler, ...))[2];
++
++template <typename Handler, typename Arg1, typename Arg2>
++auto two_arg_move_handler_test(Handler h, Arg1* a1, Arg2* a2)
++ -> decltype(
++ sizeof(Handler(BOOST_ASIO_MOVE_CAST(Handler)(h))),
++ (BOOST_ASIO_MOVE_OR_LVALUE(Handler)(h)(
++ *a1, BOOST_ASIO_MOVE_CAST(Arg2)(*a2))),
++ char(0));
++
++template <typename Handler>
++char (&two_arg_move_handler_test(Handler, ...))[2];
++
++template <typename Handler, typename Arg1, typename Arg2, typename Arg3>
++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 <typename Handler>
++char (&three_arg_handler_test(Handler, ...))[2];
++
++template <typename Handler, typename Arg1, typename Arg2, typename Arg3>
++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 <typename Handler>
++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 <typename T> T& lvref();
++template <typename T> T& lvref(T);
++template <typename T> const T& clvref();
++template <typename T> const T& clvref(T);
++#if defined(BOOST_ASIO_HAS_MOVE)
++template <typename T> T rvref();
++template <typename T> T rvref(T);
++#else // defined(BOOST_ASIO_HAS_MOVE)
++template <typename T> const T& rvref();
++template <typename T> const T& rvref(T);
++#endif // defined(BOOST_ASIO_HAS_MOVE)
++template <typename T> char argbyv(T);
++
++#if 0
++template <int>
++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<const boost::system::error_code*>(0), \
++ static_cast<const std::size_t*>(0), \
++ static_cast<const boost::asio::ip::address*>(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<const boost::system::error_code>(), \
++ boost::asio::detail::lvref<const std::size_t>(), \
++ boost::asio::detail::lvref<const boost::asio::ip::address>()), \
++ 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<const boost::system::error_code*>(0), \
++ static_cast<const std::size_t*>(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<const boost::system::error_code>(), \
++ boost::asio::detail::lvref<const std::size_t>()), \
++ 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<const boost::system::error_code*>(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<const boost::system::error_code>()), \
++ 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<const boost::system::error_code*>(0), \
++ static_cast<socket_type*>(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<const boost::system::error_code>(), \
++ boost::asio::detail::rvref<socket_type>()), \
++ 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<const boost::system::error_code*>(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<const boost::system::error_code>()), \
++ 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<const boost::system::error_code*>(0), \
++ static_cast<const endpoint_type*>(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<const boost::system::error_code>(), \
++ boost::asio::detail::lvref<const endpoint_type>()), \
++ 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<const boost::system::error_code*>(0), \
++ static_cast<const iter_type*>(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<const boost::system::error_code>(), \
++ boost::asio::detail::lvref<const iter_type>()), \
++ 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<const boost::system::error_code*>(0), \
++ static_cast<const range_type*>(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<const boost::system::error_code>(), \
++ boost::asio::detail::lvref<const range_type>()), \
++ 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<const boost::system::error_code*>(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<const boost::system::error_code>()), \
++ 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<const boost::system::error_code*>(0), \
++ static_cast<const int*>(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<const boost::system::error_code>(), \
++ boost::asio::detail::lvref<const int>()), \
++ 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<const boost::system::error_code*>(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<const boost::system::error_code>()), \
++ 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<const boost::system::error_code*>(0), \
++ static_cast<const std::size_t*>(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<const boost::system::error_code>(), \
++ boost::asio::detail::lvref<const std::size_t>()), \
++ 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<const boost::system::error_code*>(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<const boost::system::error_code>()), \
++ 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.78/boost/asio/detail/handler_type_requirements_ext_local.hpp b/implementation/helper/1.78/boost/asio/detail/handler_type_requirements_ext_local.hpp
+new file mode 100644
+index 00000000..15f58c7c
+--- /dev/null
++++ b/implementation/helper/1.78/boost/asio/detail/handler_type_requirements_ext_local.hpp
+@@ -0,0 +1,589 @@
++//
++// 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 <boost/asio/detail/config.hpp>
++
++// 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 <boost/asio/async_result.hpp>
++#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 <typename Handler>
++auto zero_arg_copyable_handler_test(Handler h, void*)
++ -> decltype(
++ sizeof(Handler(static_cast<const Handler&>(h))),
++ (BOOST_ASIO_MOVE_OR_LVALUE(Handler)(h)()),
++ char(0));
++
++template <typename Handler>
++char (&zero_arg_copyable_handler_test(Handler, ...))[2];
++
++template <typename Handler, typename Arg1>
++auto one_arg_handler_test(Handler h, Arg1* a1)
++ -> decltype(
++ sizeof(Handler(BOOST_ASIO_MOVE_CAST(Handler)(h))),
++ (BOOST_ASIO_MOVE_OR_LVALUE(Handler)(h)(*a1)),
++ char(0));
++
++template <typename Handler>
++char (&one_arg_handler_test(Handler h, ...))[2];
++
++template <typename Handler, typename Arg1, typename Arg2>
++auto two_arg_handler_test(Handler h, Arg1* a1, Arg2* a2)
++ -> decltype(
++ sizeof(Handler(BOOST_ASIO_MOVE_CAST(Handler)(h))),
++ (BOOST_ASIO_MOVE_OR_LVALUE(Handler)(h)(*a1, *a2)),
++ char(0));
++
++template <typename Handler>
++char (&two_arg_handler_test(Handler, ...))[2];
++
++template <typename Handler, typename Arg1, typename Arg2>
++auto two_arg_move_handler_test(Handler h, Arg1* a1, Arg2* a2)
++ -> decltype(
++ sizeof(Handler(BOOST_ASIO_MOVE_CAST(Handler)(h))),
++ (BOOST_ASIO_MOVE_OR_LVALUE(Handler)(h)(
++ *a1, BOOST_ASIO_MOVE_CAST(Arg2)(*a2))),
++ char(0));
++
++template <typename Handler>
++char (&two_arg_move_handler_test(Handler, ...))[2];
++
++template <typename Handler, typename Arg1, typename Arg2, typename Arg3, typename Arg4>
++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 <typename Handler>
++char (&four_arg_handler_test(Handler, ...))[2];
++
++template <typename Handler, typename Arg1, typename Arg2, typename Arg3, typename Arg4>
++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 <typename Handler>
++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 <typename T> T& lvref();
++template <typename T> T& lvref(T);
++template <typename T> const T& clvref();
++template <typename T> const T& clvref(T);
++#if defined(BOOST_ASIO_HAS_MOVE)
++template <typename T> T rvref();
++template <typename T> T rvref(T);
++#else // defined(BOOST_ASIO_HAS_MOVE)
++template <typename T> const T& rvref();
++template <typename T> const T& rvref(T);
++#endif // defined(BOOST_ASIO_HAS_MOVE)
++template <typename T> char argbyv(T);
++
++#if 0
++template <int>
++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<const boost::system::error_code*>(0), \
++ static_cast<const std::size_t*>(0), \
++ static_cast<const std::uint32_t*>(0), \
++ static_cast<const std::uint32_t*>(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<const boost::system::error_code>(), \
++ boost::asio::detail::lvref<const std::size_t>(), \
++ boost::asio::detail::lvref<const std::uint32_t>(), \
++ boost::asio::detail::lvref<const std::uint32_t>()), \
++ 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<const boost::system::error_code*>(0), \
++ static_cast<const std::size_t*>(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<const boost::system::error_code>(), \
++ boost::asio::detail::lvref<const std::size_t>()), \
++ 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<const boost::system::error_code*>(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<const boost::system::error_code>()), \
++ 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<const boost::system::error_code*>(0), \
++ static_cast<socket_type*>(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<const boost::system::error_code>(), \
++ boost::asio::detail::rvref<socket_type>()), \
++ 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<const boost::system::error_code*>(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<const boost::system::error_code>()), \
++ 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<const boost::system::error_code*>(0), \
++ static_cast<const endpoint_type*>(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<const boost::system::error_code>(), \
++ boost::asio::detail::lvref<const endpoint_type>()), \
++ 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<const boost::system::error_code*>(0), \
++ static_cast<const iter_type*>(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<const boost::system::error_code>(), \
++ boost::asio::detail::lvref<const iter_type>()), \
++ 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<const boost::system::error_code*>(0), \
++ static_cast<const range_type*>(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<const boost::system::error_code>(), \
++ boost::asio::detail::lvref<const range_type>()), \
++ 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<const boost::system::error_code*>(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<const boost::system::error_code>()), \
++ 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<const boost::system::error_code*>(0), \
++ static_cast<const int*>(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<const boost::system::error_code>(), \
++ boost::asio::detail::lvref<const int>()), \
++ 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<const boost::system::error_code*>(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<const boost::system::error_code>()), \
++ 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<const boost::system::error_code*>(0), \
++ static_cast<const std::size_t*>(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<const boost::system::error_code>(), \
++ boost::asio::detail::lvref<const std::size_t>()), \
++ 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<const boost::system::error_code*>(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<const boost::system::error_code>()), \
++ 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.78/boost/asio/detail/impl/reactive_socket_service_base_ext.ipp b/implementation/helper/1.78/boost/asio/detail/impl/reactive_socket_service_base_ext.ipp
+new file mode 100644
+index 00000000..04036adf
+--- /dev/null
++++ b/implementation/helper/1.78/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 <boost/asio/detail/config.hpp>
++
++#if !defined(BOOST_ASIO_HAS_IOCP) \
++ && !defined(BOOST_ASIO_WINDOWS_RUNTIME)
++
++#include <boost/asio/detail/reactive_socket_service_base_ext.hpp>
++
++#include <boost/asio/detail/push_options.hpp>
++
++namespace boost {
++namespace asio {
++namespace detail {
++
++reactive_socket_service_base_ext::reactive_socket_service_base_ext(
++ execution_context& context)
++ : reactor_(use_service<reactor>(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 <boost/asio/detail/pop_options.hpp>
++
++#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.78/boost/asio/detail/impl/reactive_socket_service_base_ext_local.ipp b/implementation/helper/1.78/boost/asio/detail/impl/reactive_socket_service_base_ext_local.ipp
+new file mode 100644
+index 00000000..288cf193
+--- /dev/null
++++ b/implementation/helper/1.78/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 <boost/asio/detail/config.hpp>
++
++#if !defined(BOOST_ASIO_HAS_IOCP) \
++ && !defined(BOOST_ASIO_WINDOWS_RUNTIME)
++
++#include <boost/asio/detail/reactive_socket_service_base_ext_local.hpp>
++
++#include <boost/asio/detail/push_options.hpp>
++
++namespace boost {
++namespace asio {
++namespace detail {
++
++reactive_socket_service_base_ext_local::reactive_socket_service_base_ext_local(
++ execution_context& context)
++ : reactor_(use_service<reactor>(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 <boost/asio/detail/pop_options.hpp>
++
++#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.78/boost/asio/detail/impl/socket_ops_ext.ipp b/implementation/helper/1.78/boost/asio/detail/impl/socket_ops_ext.ipp
+new file mode 100644
+index 00000000..39e2ed84
+--- /dev/null
++++ b/implementation/helper/1.78/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 <boost/asio/detail/impl/socket_ops.ipp>
++
++#include <boost/asio/detail/push_options.hpp>
++
++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<int>(*addrlen);
++ msg.msg_iov = bufs;
++ msg.msg_iovlen = static_cast<int>(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 <boost/asio/detail/pop_options.hpp>
++
++#endif // BOOST_ASIO_DETAIL_SOCKET_OPS_EXT_IPP
+diff --git a/implementation/helper/1.78/boost/asio/detail/impl/socket_ops_ext_local.ipp b/implementation/helper/1.78/boost/asio/detail/impl/socket_ops_ext_local.ipp
+new file mode 100644
+index 00000000..83a673b8
+--- /dev/null
++++ b/implementation/helper/1.78/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 <boost/asio/detail/impl/socket_ops.ipp>
++
++#include <boost/asio/detail/push_options.hpp>
++
++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<DWORD>(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<int>(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<DWORD>(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<int>(*addrlen);
++ msg.msg_iov = bufs;
++ msg.msg_iovlen = static_cast<int>(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 <boost/asio/detail/pop_options.hpp>
++
++#endif // BOOST_ASIO_DETAIL_SOCKET_OPS_EXT_LOCAL_IPP
+diff --git a/implementation/helper/1.78/boost/asio/detail/reactive_socket_recv_op_ext.hpp b/implementation/helper/1.78/boost/asio/detail/reactive_socket_recv_op_ext.hpp
+new file mode 100644
+index 00000000..1167d57f
+--- /dev/null
++++ b/implementation/helper/1.78/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 <boost/asio/detail/config.hpp>
++#include <boost/asio/detail/bind_handler.hpp>
++#include <boost/asio/detail/buffer_sequence_adapter.hpp>
++#include <boost/asio/detail/fenced_block.hpp>
++#include <boost/asio/detail/handler_alloc_helpers.hpp>
++#include <boost/asio/detail/handler_invoke_helpers.hpp>
++#include <boost/asio/detail/handler_work.hpp>
++#include <boost/asio/detail/memory.hpp>
++#include <boost/asio/detail/reactor_op_ext.hpp>
++#include <boost/asio/detail/socket_ops_ext.hpp>
++
++#include <boost/asio/detail/push_options.hpp>
++
++namespace boost {
++namespace asio {
++namespace detail {
++
++template <typename MutableBufferSequence>
++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<reactive_socket_recv_op_base_ext*>(base));
++
++ typedef buffer_sequence_adapter<boost::asio::mutable_buffer,
++ MutableBufferSequence> 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 <typename MutableBufferSequence, typename Handler, typename IoExecutor>
++class reactive_socket_recv_op_ext :
++ public reactive_socket_recv_op_base_ext<MutableBufferSequence>
++{
++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<MutableBufferSequence>(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<reactive_socket_recv_op_ext*>(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<Handler, IoExecutor> w(
++ BOOST_ASIO_MOVE_CAST2(handler_work<Handler, IoExecutor>)(
++ 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, boost::system::error_code, std::size_t, boost::asio::ip::address>
++ 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<Handler, IoExecutor> work_;
++};
++
++} // namespace detail
++} // namespace asio
++} // namespace boost
++
++#include <boost/asio/detail/pop_options.hpp>
++
++#endif // BOOST_ASIO_DETAIL_REACTIVE_SOCKET_RECV_OP_EXT_HPP
+diff --git a/implementation/helper/1.78/boost/asio/detail/reactive_socket_recv_op_ext_local.hpp b/implementation/helper/1.78/boost/asio/detail/reactive_socket_recv_op_ext_local.hpp
+new file mode 100644
+index 00000000..bedbd290
+--- /dev/null
++++ b/implementation/helper/1.78/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 <boost/asio/detail/config.hpp>
++#include <boost/asio/detail/bind_handler.hpp>
++#include <boost/asio/detail/buffer_sequence_adapter.hpp>
++#include <boost/asio/detail/fenced_block.hpp>
++#include <boost/asio/detail/handler_alloc_helpers.hpp>
++#include <boost/asio/detail/handler_invoke_helpers.hpp>
++#include <boost/asio/detail/handler_work.hpp>
++#include <boost/asio/detail/memory.hpp>
++#include <boost/asio/detail/reactor_op_ext_local.hpp>
++#include <boost/asio/detail/socket_ops_ext_local.hpp>
++
++#include <boost/asio/detail/push_options.hpp>
++
++namespace boost {
++namespace asio {
++namespace detail {
++
++template <typename MutableBufferSequence>
++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<reactive_socket_recv_op_base_ext_local*>(base));
++
++ typedef buffer_sequence_adapter<boost::asio::mutable_buffer,
++ MutableBufferSequence> 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 <typename MutableBufferSequence, typename Handler, typename IoExecutor>
++class reactive_socket_recv_op_ext_local :
++ public reactive_socket_recv_op_base_ext_local<MutableBufferSequence>
++{
++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<MutableBufferSequence>(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<reactive_socket_recv_op_ext_local*>(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<Handler, IoExecutor> w(
++ BOOST_ASIO_MOVE_CAST2(handler_work<Handler, IoExecutor>)(
++ 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, boost::system::error_code, std::size_t, std::uint32_t, std::uint32_t>
++ 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<Handler, IoExecutor> work_;
++};
++
++} // namespace detail
++} // namespace asio
++} // namespace boost
++
++#include <boost/asio/detail/pop_options.hpp>
++
++#endif // BOOST_ASIO_DETAIL_REACTIVE_SOCKET_RECV_OP_EXT_LOCAL_HPP
+diff --git a/implementation/helper/1.78/boost/asio/detail/reactive_socket_recvfrom_op_ext.hpp b/implementation/helper/1.78/boost/asio/detail/reactive_socket_recvfrom_op_ext.hpp
+new file mode 100644
+index 00000000..875fe142
+--- /dev/null
++++ b/implementation/helper/1.78/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 <boost/asio/detail/config.hpp>
++#include <boost/asio/detail/bind_handler.hpp>
++#include <boost/asio/detail/buffer_sequence_adapter.hpp>
++#include <boost/asio/detail/fenced_block.hpp>
++#include <boost/asio/detail/handler_alloc_helpers.hpp>
++#include <boost/asio/detail/handler_invoke_helpers.hpp>
++#include <boost/asio/detail/handler_work.hpp>
++#include <boost/asio/detail/memory.hpp>
++#include <boost/asio/detail/reactor_op_ext.hpp>
++#include <boost/asio/detail/socket_ops_ext.hpp>
++
++#include <boost/asio/detail/push_options.hpp>
++
++namespace boost {
++namespace asio {
++namespace detail {
++
++template <typename MutableBufferSequence, typename Endpoint>
++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<reactive_socket_recvfrom_op_base_ext*>(base));
++
++ buffer_sequence_adapter<boost::asio::mutable_buffer,
++ MutableBufferSequence> 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 <typename MutableBufferSequence, typename Endpoint,
++ typename Handler, typename IoExecutor>
++class reactive_socket_recvfrom_op_ext :
++ public reactive_socket_recvfrom_op_base_ext<MutableBufferSequence, Endpoint>
++{
++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<MutableBufferSequence, Endpoint>(
++ 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<reactive_socket_recvfrom_op_ext*>(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<Handler, IoExecutor> w(
++ BOOST_ASIO_MOVE_CAST2(handler_work<Handler, IoExecutor>)(
++ 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, boost::system::error_code, std::size_t, boost::asio::ip::address>
++ 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<Handler, IoExecutor> work_;
++};
++
++} // namespace detail
++} // namespace asio
++} // namespace boost
++
++#include <boost/asio/detail/pop_options.hpp>
++
++#endif // BOOST_ASIO_DETAIL_REACTIVE_SOCKET_RECVFROM_OP_EXT_HPP
+diff --git a/implementation/helper/1.78/boost/asio/detail/reactive_socket_recvfrom_op_ext_local.hpp b/implementation/helper/1.78/boost/asio/detail/reactive_socket_recvfrom_op_ext_local.hpp
+new file mode 100644
+index 00000000..f9fef2b8
+--- /dev/null
++++ b/implementation/helper/1.78/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 <boost/asio/detail/config.hpp>
++#include <boost/asio/detail/bind_handler.hpp>
++#include <boost/asio/detail/buffer_sequence_adapter.hpp>
++#include <boost/asio/detail/fenced_block.hpp>
++#include <boost/asio/detail/memory.hpp>
++#include <boost/asio/detail/reactor_op_ext_local.hpp>
++#include <boost/asio/detail/socket_ops_ext_local.hpp>
++
++#include <boost/asio/detail/push_options.hpp>
++
++namespace boost {
++namespace asio {
++namespace detail {
++
++template <typename MutableBufferSequence, typename Endpoint>
++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<reactive_socket_recvfrom_op_base_ext_local*>(base));
++
++ buffer_sequence_adapter<boost::asio::mutable_buffer,
++ MutableBufferSequence> 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 <typename MutableBufferSequence, typename Endpoint,
++ typename Handler, typename IoExecutor>
++class reactive_socket_recvfrom_op_ext_local :
++ public reactive_socket_recvfrom_op_base_ext_local<MutableBufferSequence, Endpoint>
++{
++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<MutableBufferSequence, Endpoint>(
++ 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<reactive_socket_recvfrom_op_ext_local*>(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<Handler, IoExecutor> w(
++ BOOST_ASIO_MOVE_CAST2(handler_work<Handler, IoExecutor>)(
++ 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, boost::system::error_code, std::size_t, std::uint32_t, std::uint32_t>
++ 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<Handler, IoExecutor> work_;
++};
++
++} // namespace detail
++} // namespace asio
++} // namespace boost
++
++#include <boost/asio/detail/pop_options.hpp>
++
++#endif // BOOST_ASIO_DETAIL_REACTIVE_SOCKET_RECVFROM_OP_EXT_LOCAL_HPP
+diff --git a/implementation/helper/1.78/boost/asio/detail/reactive_socket_recvmsg_op_ext.hpp b/implementation/helper/1.78/boost/asio/detail/reactive_socket_recvmsg_op_ext.hpp
+new file mode 100644
+index 00000000..bd315dcf
+--- /dev/null
++++ b/implementation/helper/1.78/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 <boost/asio/detail/config.hpp>
++#include <boost/asio/detail/bind_handler.hpp>
++#include <boost/asio/detail/buffer_sequence_adapter.hpp>
++#include <boost/asio/detail/fenced_block.hpp>
++#include <boost/asio/detail/handler_alloc_helpers.hpp>
++#include <boost/asio/detail/handler_invoke_helpers.hpp>
++#include <boost/asio/detail/handler_work.hpp>
++#include <boost/asio/detail/memory.hpp>
++#include <boost/asio/detail/reactor_op_ext.hpp>
++#include <boost/asio/detail/socket_ops_ext.hpp>
++#include <boost/asio/socket_base.hpp>
++
++#include <boost/asio/detail/push_options.hpp>
++
++namespace boost {
++namespace asio {
++namespace detail {
++
++template <typename MutableBufferSequence>
++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<reactive_socket_recvmsg_op_base_ext*>(base));
++
++ buffer_sequence_adapter<boost::asio::mutable_buffer,
++ MutableBufferSequence> 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 <typename MutableBufferSequence, typename Handler, typename IoExecutor>
++class reactive_socket_recvmsg_op_ext :
++ public reactive_socket_recvmsg_op_base_ext<MutableBufferSequence>
++{
++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<MutableBufferSequence>(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<reactive_socket_recvmsg_op_ext*>(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<Handler, IoExecutor> w(
++ BOOST_ASIO_MOVE_CAST2(handler_work<Handler, IoExecutor>)(
++ 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, boost::system::error_code, std::size_t, boost::asio::ip::address>
++ 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<Handler, IoExecutor> work_;
++};
++
++} // namespace detail
++} // namespace asio
++} // namespace boost
++
++#include <boost/asio/detail/pop_options.hpp>
++
++#endif // BOOST_ASIO_DETAIL_REACTIVE_SOCKET_RECVMSG_OP_EXT_HPP
+diff --git a/implementation/helper/1.78/boost/asio/detail/reactive_socket_recvmsg_op_ext_local.hpp b/implementation/helper/1.78/boost/asio/detail/reactive_socket_recvmsg_op_ext_local.hpp
+new file mode 100644
+index 00000000..81486904
+--- /dev/null
++++ b/implementation/helper/1.78/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 <boost/asio/detail/config.hpp>
++#include <boost/asio/detail/bind_handler.hpp>
++#include <boost/asio/detail/buffer_sequence_adapter.hpp>
++#include <boost/asio/detail/fenced_block.hpp>
++#include <boost/asio/detail/handler_alloc_helpers.hpp>
++#include <boost/asio/detail/handler_invoke_helpers.hpp>
++#include <boost/asio/detail/handler_work.hpp>
++#include <boost/asio/detail/memory.hpp>
++#include <boost/asio/detail/reactor_op_ext_local.hpp>
++#include <boost/asio/detail/socket_ops_ext_local.hpp>
++#include <boost/asio/socket_base.hpp>
++
++#include <boost/asio/detail/push_options.hpp>
++
++namespace boost {
++namespace asio {
++namespace detail {
++
++template <typename MutableBufferSequence>
++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<reactive_socket_recvmsg_op_base_ext_local*>(base));
++
++ buffer_sequence_adapter<boost::asio::mutable_buffer,
++ MutableBufferSequence> 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 <typename MutableBufferSequence, typename Handler, typename IoExecutor>
++class reactive_socket_recvmsg_op_ext_local :
++ public reactive_socket_recvmsg_op_base_ext_local<MutableBufferSequence>
++{
++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<MutableBufferSequence>(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<reactive_socket_recvmsg_op_ext_local*>(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<Handler, IoExecutor> w(
++ BOOST_ASIO_MOVE_CAST2(handler_work<Handler, IoExecutor>)(
++ 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, boost::system::error_code, std::size_t, std::uint32_t, std::uint32_t>
++ 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<Handler, IoExecutor> work_;
++};
++
++} // namespace detail
++} // namespace asio
++} // namespace boost
++
++#include <boost/asio/detail/pop_options.hpp>
++
++#endif // BOOST_ASIO_DETAIL_REACTIVE_SOCKET_RECVMSG_OP_EXT_LOCAL_HPP
+diff --git a/implementation/helper/1.78/boost/asio/detail/reactive_socket_service_base_ext.hpp b/implementation/helper/1.78/boost/asio/detail/reactive_socket_service_base_ext.hpp
+new file mode 100644
+index 00000000..2e68a877
+--- /dev/null
++++ b/implementation/helper/1.78/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 <boost/asio/detail/config.hpp>
++
++#if !defined(BOOST_ASIO_HAS_IOCP) \
++ && !defined(BOOST_ASIO_WINDOWS_RUNTIME)
++
++#include <boost/asio/buffer.hpp>
++#include <boost/asio/error.hpp>
++#include <boost/asio/execution_context.hpp>
++#include <boost/asio/socket_base.hpp>
++#include <boost/asio/detail/buffer_sequence_adapter.hpp>
++#include <boost/asio/detail/memory.hpp>
++#include <boost/asio/detail/reactive_null_buffers_op.hpp>
++#include <boost/asio/detail/reactive_socket_recv_op_ext.hpp>
++#include <boost/asio/detail/reactive_socket_recvmsg_op_ext.hpp>
++#include <boost/asio/detail/reactive_socket_send_op.hpp>
++#include <boost/asio/detail/reactive_wait_op.hpp>
++#include <boost/asio/detail/reactor.hpp>
++#include <boost/asio/detail/reactor_op.hpp>
++#include <boost/asio/detail/socket_holder.hpp>
++#include <boost/asio/detail/socket_ops_ext.hpp>
++#include <boost/asio/detail/socket_types.hpp>
++
++#include <boost/asio/detail/push_options.hpp>
++
++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 <typename IO_Control_Command>
++ 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<ioctl_arg_type*>(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 <typename Handler, typename IoExecutor>
++ 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<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_, 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 <typename ConstBufferSequence>
++ size_t send(base_implementation_type& impl,
++ const ConstBufferSequence& buffers,
++ socket_base::message_flags flags, boost::system::error_code& ec)
++ {
++ buffer_sequence_adapter<boost::asio::const_buffer,
++ ConstBufferSequence> 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 <typename ConstBufferSequence, typename Handler, typename IoExecutor>
++ 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<boost::asio::const_buffer,
++ ConstBufferSequence>::all_empty(buffers)));
++ p.v = p.p = 0;
++ }
++
++ // Start an asynchronous wait until data can be sent without blocking.
++ template <typename Handler, typename IoExecutor>
++ 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<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_, 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 <typename MutableBufferSequence>
++ size_t receive(base_implementation_type& impl,
++ const MutableBufferSequence& buffers,
++ socket_base::message_flags flags, boost::system::error_code& ec)
++ {
++ buffer_sequence_adapter<boost::asio::mutable_buffer,
++ MutableBufferSequence> 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 <typename MutableBufferSequence,
++ typename Handler, typename IoExecutor>
++ 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<boost::asio::mutable_buffer,
++ MutableBufferSequence>::all_empty(buffers)));
++ p.v = p.p = 0;
++ }
++
++ // Wait until data can be received without blocking.
++ template <typename Handler, typename IoExecutor>
++ 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<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_, 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 <typename MutableBufferSequence>
++ 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<boost::asio::mutable_buffer,
++ MutableBufferSequence> 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 <typename MutableBufferSequence,
++ typename Handler, typename IoExecutor>
++ 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 <typename Handler, typename IoExecutor>
++ 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<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_, 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 <boost/asio/detail/pop_options.hpp>
++
++#if defined(BOOST_ASIO_HEADER_ONLY)
++# include <boost/asio/detail/impl/reactive_socket_service_base_ext.ipp>
++#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.78/boost/asio/detail/reactive_socket_service_base_ext_local.hpp b/implementation/helper/1.78/boost/asio/detail/reactive_socket_service_base_ext_local.hpp
+new file mode 100644
+index 00000000..a71fce5b
+--- /dev/null
++++ b/implementation/helper/1.78/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 <boost/asio/detail/config.hpp>
++
++#if !defined(BOOST_ASIO_HAS_IOCP) \
++ && !defined(BOOST_ASIO_WINDOWS_RUNTIME)
++
++#include <boost/asio/buffer.hpp>
++#include <boost/asio/error.hpp>
++#include <boost/asio/execution_context.hpp>
++#include <boost/asio/socket_base.hpp>
++#include <boost/asio/detail/buffer_sequence_adapter.hpp>
++#include <boost/asio/detail/memory.hpp>
++#include <boost/asio/detail/reactive_null_buffers_op.hpp>
++#include <boost/asio/detail/reactive_socket_recv_op_ext_local.hpp>
++#include <boost/asio/detail/reactive_socket_recvmsg_op_ext_local.hpp>
++#include <boost/asio/detail/reactive_socket_send_op.hpp>
++#include <boost/asio/detail/reactive_wait_op.hpp>
++#include <boost/asio/detail/reactor.hpp>
++#include <boost/asio/detail/reactor_op.hpp>
++#include <boost/asio/detail/socket_holder.hpp>
++#include <boost/asio/detail/socket_ops_ext_local.hpp>
++#include <boost/asio/detail/socket_types.hpp>
++
++#include <boost/asio/detail/push_options.hpp>
++
++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 <typename IO_Control_Command>
++ 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<ioctl_arg_type*>(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 <typename Handler, typename IoExecutor>
++ 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<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_, 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 <typename ConstBufferSequence>
++ size_t send(base_implementation_type& impl,
++ const ConstBufferSequence& buffers,
++ socket_base::message_flags flags, boost::system::error_code& ec)
++ {
++ buffer_sequence_adapter<boost::asio::const_buffer,
++ ConstBufferSequence> 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 <typename ConstBufferSequence, typename Handler, typename IoExecutor>
++ 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<boost::asio::const_buffer,
++ ConstBufferSequence>::all_empty(buffers)));
++ p.v = p.p = 0;
++ }
++
++ // Start an asynchronous wait until data can be sent without blocking.
++ template <typename Handler, typename IoExecutor>
++ 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<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_, 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 <typename MutableBufferSequence>
++ size_t receive(base_implementation_type& impl,
++ const MutableBufferSequence& buffers,
++ socket_base::message_flags flags, boost::system::error_code& ec)
++ {
++ buffer_sequence_adapter<boost::asio::mutable_buffer,
++ MutableBufferSequence> 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 <typename MutableBufferSequence,
++ typename Handler, typename IoExecutor>
++ 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<boost::asio::mutable_buffer,
++ MutableBufferSequence>::all_empty(buffers)));
++ p.v = p.p = 0;
++ }
++
++ // Wait until data can be received without blocking.
++ template <typename Handler, typename IoExecutor>
++ 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<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_, 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 <typename MutableBufferSequence>
++ 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<boost::asio::mutable_buffer,
++ MutableBufferSequence> 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 <typename MutableBufferSequence,
++ typename Handler, typename IoExecutor>
++ 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 <typename Handler, typename IoExecutor>
++ 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<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_, 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 <boost/asio/detail/pop_options.hpp>
++
++#if defined(BOOST_ASIO_HEADER_ONLY)
++# include <boost/asio/detail/impl/reactive_socket_service_base_ext_local.ipp>
++#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.78/boost/asio/detail/reactive_socket_service_ext.hpp b/implementation/helper/1.78/boost/asio/detail/reactive_socket_service_ext.hpp
+new file mode 100644
+index 00000000..7254ccdd
+--- /dev/null
++++ b/implementation/helper/1.78/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 <boost/asio/detail/config.hpp>
++
++#if !defined(BOOST_ASIO_HAS_IOCP)
++
++#include <boost/asio/buffer.hpp>
++#include <boost/asio/error.hpp>
++#include <boost/asio/execution_context.hpp>
++#include <boost/asio/socket_base.hpp>
++#include <boost/asio/detail/buffer_sequence_adapter.hpp>
++#include <boost/asio/detail/memory.hpp>
++#include <boost/asio/detail/noncopyable.hpp>
++#include <boost/asio/detail/reactive_null_buffers_op.hpp>
++#include <boost/asio/detail/reactive_socket_accept_op.hpp>
++#include <boost/asio/detail/reactive_socket_connect_op.hpp>
++#include <boost/asio/detail/reactive_socket_recvfrom_op_ext.hpp>
++#include <boost/asio/detail/reactive_socket_sendto_op.hpp>
++#include <boost/asio/detail/reactive_socket_service_base_ext.hpp>
++#include <boost/asio/detail/reactor.hpp>
++#include <boost/asio/detail/reactor_op.hpp>
++#include <boost/asio/detail/socket_holder.hpp>
++#include <boost/asio/detail/socket_ops.hpp>
++#include <boost/asio/detail/socket_types.hpp>
++
++#include <boost/asio/detail/push_options.hpp>
++
++namespace boost {
++namespace asio {
++namespace detail {
++
++template <typename Protocol>
++class reactive_socket_service_ext :
++ public execution_context_service_base<reactive_socket_service_ext<Protocol> >,
++ 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<Protocol> >(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 <typename Protocol1>
++ void converting_move_construct(implementation_type& impl,
++ reactive_socket_service_ext<Protocol1>&,
++ 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 <typename Option>
++ 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 <typename Option>
++ 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 <typename ConstBufferSequence>
++ 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<boost::asio::const_buffer,
++ ConstBufferSequence> 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 <typename ConstBufferSequence, typename Handler, typename IoExecutor>
++ 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<ConstBufferSequence,
++ endpoint_type, 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,
++ 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 <typename Handler, typename IoExecutor>
++ 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<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_, 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 <typename MutableBufferSequence>
++ 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<boost::asio::mutable_buffer,
++ MutableBufferSequence> 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 <typename MutableBufferSequence,
++ typename Handler, typename IoExecutor>
++ 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<MutableBufferSequence,
++ endpoint_type, Handler, IoExecutor> 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 <typename Handler, typename IoExecutor>
++ 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<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_, 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 <typename Socket>
++ 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 <typename Socket, typename Handler, typename IoExecutor>
++ 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<Socket, Protocol, 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_, 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 <typename PeerIoExecutor, typename Handler, typename IoExecutor>
++ 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<Protocol,
++ PeerIoExecutor, 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_, 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 <typename Handler, typename IoExecutor>
++ 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<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_, 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 <boost/asio/detail/pop_options.hpp>
++
++#endif // !defined(BOOST_ASIO_HAS_IOCP)
++
++#endif // BOOST_ASIO_DETAIL_REACTIVE_SOCKET_SERVICE_EXT_HPP
+diff --git a/implementation/helper/1.78/boost/asio/detail/reactive_socket_service_ext_local.hpp b/implementation/helper/1.78/boost/asio/detail/reactive_socket_service_ext_local.hpp
+new file mode 100644
+index 00000000..8ac32654
+--- /dev/null
++++ b/implementation/helper/1.78/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 <boost/asio/detail/config.hpp>
++
++#if !defined(BOOST_ASIO_HAS_IOCP)
++
++#include <boost/asio/buffer.hpp>
++#include <boost/asio/error.hpp>
++#include <boost/asio/execution_context.hpp>
++#include <boost/asio/socket_base.hpp>
++#include <boost/asio/detail/buffer_sequence_adapter.hpp>
++#include <boost/asio/detail/memory.hpp>
++#include <boost/asio/detail/noncopyable.hpp>
++#include <boost/asio/detail/reactive_null_buffers_op.hpp>
++#include <boost/asio/detail/reactive_socket_accept_op.hpp>
++#include <boost/asio/detail/reactive_socket_connect_op.hpp>
++#include <boost/asio/detail/reactive_socket_recvfrom_op_ext_local.hpp>
++#include <boost/asio/detail/reactive_socket_sendto_op.hpp>
++#include <boost/asio/detail/reactive_socket_service_base_ext_local.hpp>
++#include <boost/asio/detail/reactor.hpp>
++#include <boost/asio/detail/reactor_op.hpp>
++#include <boost/asio/detail/socket_holder.hpp>
++#include <boost/asio/detail/socket_ops.hpp>
++#include <boost/asio/detail/socket_types.hpp>
++
++#include <boost/asio/detail/push_options.hpp>
++
++namespace boost {
++namespace asio {
++namespace detail {
++
++template <typename Protocol>
++class reactive_socket_service_ext_local :
++ public execution_context_service_base<reactive_socket_service_ext_local<Protocol> >,
++ 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<Protocol> >(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 <typename Protocol1>
++ void converting_move_construct(implementation_type& impl,
++ reactive_socket_service_ext_local<Protocol1>&,
++ 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 <typename Option>
++ 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 <typename Option>
++ 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 <typename ConstBufferSequence>
++ 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<boost::asio::const_buffer,
++ ConstBufferSequence> 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 <typename ConstBufferSequence, typename Handler, typename IoExecutor>
++ 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<ConstBufferSequence,
++ endpoint_type, 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,
++ 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 <typename Handler, typename IoExecutor>
++ 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<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_, 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 <typename MutableBufferSequence>
++ 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<boost::asio::mutable_buffer,
++ MutableBufferSequence> 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 <typename MutableBufferSequence,
++ typename Handler, typename IoExecutor>
++ 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<MutableBufferSequence,
++ endpoint_type, Handler, IoExecutor> 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 <typename Handler, typename IoExecutor>
++ 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<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_, 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 <typename Socket>
++ 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 <typename Socket, typename Handler, typename IoExecutor>
++ 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<Socket, Protocol, 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_, 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 <typename PeerIoExecutor, typename Handler, typename IoExecutor>
++ 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<Protocol,
++ PeerIoExecutor, 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_, 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 <typename Handler, typename IoExecutor>
++ 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<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_, 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 <boost/asio/detail/pop_options.hpp>
++
++#endif // !defined(BOOST_ASIO_HAS_IOCP)
++
++#endif // BOOST_ASIO_DETAIL_REACTIVE_SOCKET_SERVICE_EXT_LOCAL_HPP
+diff --git a/implementation/helper/1.78/boost/asio/detail/reactor_op_ext.hpp b/implementation/helper/1.78/boost/asio/detail/reactor_op_ext.hpp
+new file mode 100644
+index 00000000..697cd9ff
+--- /dev/null
++++ b/implementation/helper/1.78/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 <boost/asio/detail/reactor_op.hpp>
++
++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.78/boost/asio/detail/reactor_op_ext_local.hpp b/implementation/helper/1.78/boost/asio/detail/reactor_op_ext_local.hpp
+new file mode 100644
+index 00000000..3d9ae5fa
+--- /dev/null
++++ b/implementation/helper/1.78/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 <boost/asio/detail/reactor_op.hpp>
++
++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.78/boost/asio/detail/socket_ops_ext.hpp b/implementation/helper/1.78/boost/asio/detail/socket_ops_ext.hpp
+new file mode 100644
+index 00000000..9285fedb
+--- /dev/null
++++ b/implementation/helper/1.78/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 <boost/asio/detail/socket_ops.hpp>
++
++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 <boost/asio/detail/impl/socket_ops_ext.ipp>
++#endif // defined(BOOST_ASIO_HEADER_ONLY)
++
++#endif // BOOST_EXT_ASIO_DETAIL_SOCKET_OPS_HPP
+diff --git a/implementation/helper/1.78/boost/asio/detail/socket_ops_ext_local.hpp b/implementation/helper/1.78/boost/asio/detail/socket_ops_ext_local.hpp
+new file mode 100644
+index 00000000..a937bb65
+--- /dev/null
++++ b/implementation/helper/1.78/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 <boost/asio/detail/config.hpp>
++
++#include <boost/system/error_code.hpp>
++#include <boost/asio/detail/memory.hpp>
++#include <boost/asio/detail/socket_types.hpp>
++
++#include <boost/asio/detail/push_options.hpp>
++
++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 <boost/asio/detail/pop_options.hpp>
++
++#if defined(BOOST_ASIO_HEADER_ONLY)
++# include <boost/asio/detail/impl/socket_ops_ext_local.ipp>
++#endif // defined(BOOST_ASIO_HEADER_ONLY)
++
++#endif // BOOST_ASIO_DETAIL_SOCKET_OPS_EXT_LOCAL_HPP
+diff --git a/implementation/helper/1.78/boost/asio/ip/udp_ext.hpp b/implementation/helper/1.78/boost/asio/ip/udp_ext.hpp
+new file mode 100644
+index 00000000..6ce2ac44
+--- /dev/null
++++ b/implementation/helper/1.78/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 <boost/asio/detail/config.hpp>
++#include <boost/asio/basic_datagram_socket_ext.hpp>
++#include <boost/asio/detail/socket_types.hpp>
++#include <boost/asio/ip/basic_endpoint.hpp>
++#include <boost/asio/ip/basic_resolver.hpp>
++#include <boost/asio/ip/basic_resolver_iterator.hpp>
++#include <boost/asio/ip/basic_resolver_query.hpp>
++#include <boost/asio/ip/udp.hpp>
++
++#include <boost/asio/detail/push_options.hpp>
++
++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<udp> 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<udp> socket;
++
++ /// The UDP resolver type.
++ typedef basic_resolver<udp> 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 <boost/asio/detail/pop_options.hpp>
++
++#endif // BOOST_ASIO_IP_UDP_EXT_HPP
+diff --git a/implementation/helper/1.78/boost/asio/local/stream_protocol_ext.hpp b/implementation/helper/1.78/boost/asio/local/stream_protocol_ext.hpp
+new file mode 100644
+index 00000000..7c57c62f
+--- /dev/null
++++ b/implementation/helper/1.78/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 <boost/asio/detail/config.hpp>
++
++#if defined(BOOST_ASIO_HAS_LOCAL_SOCKETS) \
++ || defined(GENERATING_DOCUMENTATION)
++
++#include <boost/asio/basic_socket_acceptor_ext.hpp>
++#include <boost/asio/basic_socket_iostream.hpp>
++#include <boost/asio/basic_stream_socket_ext.hpp>
++#include <boost/asio/detail/socket_types.hpp>
++#include <boost/asio/local/basic_endpoint.hpp>
++
++#include <boost/asio/detail/push_options.hpp>
++
++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<stream_protocol_ext> endpoint;
++
++ /// The UNIX domain socket type.
++ typedef basic_stream_socket_ext<stream_protocol_ext> socket;
++
++ /// The UNIX domain acceptor type.
++ typedef basic_socket_acceptor_ext<stream_protocol_ext> acceptor;
++
++#if !defined(BOOST_ASIO_NO_IOSTREAM)
++ /// The UNIX domain iostream type.
++ typedef basic_socket_iostream<stream_protocol_ext> iostream;
++#endif // !defined(BOOST_ASIO_NO_IOSTREAM)
++};
++
++} // namespace local
++} // namespace asio
++} // namespace boost
++
++#include <boost/asio/detail/pop_options.hpp>
++
++#endif // defined(BOOST_ASIO_HAS_LOCAL_SOCKETS)
++ // || defined(GENERATING_DOCUMENTATION)
++
++#endif // BOOST_ASIO_LOCAL_STREAM_PROTOCOL_EXT_HPP
+--
+2.25.1
+
new file mode 100644
@@ -0,0 +1,32 @@
+From 679f699db77cec3d79bffac23723a8fe8b940ed6 Mon Sep 17 00:00:00 2001
+From: Yi Zhao <yi.zhao@windriver.com>
+Date: Mon, 14 Nov 2022 06:56:56 +0000
+Subject: [PATCH] Support boost 1.82
+
+Add support for boost 1.82. Reuse 1.78 boost helpers.
+
+Upstream-Status: Pending
+
+Signed-off-by: Yi Zhao <yi.zhao@windriver.com>
+---
+ CMakeLists.txt | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/CMakeLists.txt b/CMakeLists.txt
+index 02172b7a..db17f1d6 100644
+--- a/CMakeLists.txt
++++ b/CMakeLists.txt
+@@ -156,8 +156,8 @@ else()
+ endif()
+
+ message( STATUS "Using boost version: ${VSOMEIP_BOOST_VERSION}" )
+-if (${VSOMEIP_BOOST_VERSION} GREATER 107800)
+-message( ERROR "boost version ${VSOMEIP_BOOST_VERSION} is not (yet) supported. Latest supported version is 1.78.0" )
++if (${VSOMEIP_BOOST_VERSION} GREATER 108200)
++message( ERROR "boost version ${VSOMEIP_BOOST_VERSION} is not (yet) supported. Latest supported version is 1.82.0" )
+ elseif(${VSOMEIP_BOOST_VERSION} GREATER 107600)
+ set(VSOMEIP_BOOST_HELPER implementation/helper/1.78)
+ elseif(${VSOMEIP_BOOST_VERSION} GREATER 107500)
+--
+2.25.1
+
new file mode 100644
@@ -0,0 +1,298 @@
+From 2e1769bf4c802342765964b55837e195a3568f9f Mon Sep 17 00:00:00 2001
+From: Stephen Smoogen <ssmoogen@redhat.com>
+Date: Wed, 3 Aug 2022 18:15:42 -0400
+Subject: [PATCH] Do general cleanup of warnings that gcc-12.1.1 fired up.
+
+Signed-off-by: Stephen Smoogen <ssmoogen@redhat.com>
+
+Upstream-Status: Backport
+[https://github.com/COVESA/vsomeip/pull/367]
+
+Signed-off-by: Yi Zhao <yi.zhao@windriver.com>
+---
+ .../configuration/src/configuration_impl.cpp | 6 +++---
+ .../endpoints/src/endpoint_manager_base.cpp | 2 +-
+ .../endpoints/src/endpoint_manager_impl.cpp | 10 +++++-----
+ .../endpoints/src/server_endpoint_impl.cpp | 2 +-
+ implementation/routing/src/eventgroupinfo.cpp | 4 ++--
+ implementation/routing/src/remote_subscription.cpp | 2 +-
+ .../routing/src/routing_manager_impl.cpp | 8 ++++----
+ .../routing/src/routing_manager_stub.cpp | 2 +-
+ implementation/security/src/policy.cpp | 5 +++--
+ implementation/security/src/security_impl.cpp | 14 +++++++-------
+ .../src/service_discovery_impl.cpp | 2 +-
+ 11 files changed, 29 insertions(+), 28 deletions(-)
+
+diff --git a/implementation/configuration/src/configuration_impl.cpp b/implementation/configuration/src/configuration_impl.cpp
+index 90f1a7bd..dc05f839 100644
+--- a/implementation/configuration/src/configuration_impl.cpp
++++ b/implementation/configuration/src/configuration_impl.cpp
+@@ -2551,7 +2551,7 @@ void configuration_impl::trim(std::string &_s) {
+ std::find_if(
+ _s.begin(),
+ _s.end(),
+- std::not1(std::ptr_fun(isspace))
++ std::not1(std::function<bool(int)>(isspace))
+ )
+ );
+
+@@ -2559,7 +2559,7 @@ void configuration_impl::trim(std::string &_s) {
+ std::find_if(
+ _s.rbegin(),
+ _s.rend(),
+- std::not1(std::ptr_fun(isspace))).base(),
++ std::not1(std::function<bool(int)>(isspace))).base(),
+ _s.end()
+ );
+ }
+@@ -3972,7 +3972,7 @@ configuration_impl::load_overlay(const std::string &_name) {
+ its_input.insert(its_overlay);
+ read_data(its_input, its_elements, its_failed, false);
+
+- for (const auto f : its_failed)
++ for (const auto& f : its_failed)
+ VSOMEIP_ERROR << "Reading configuration data from " << f << " failed!";
+
+ is_overlay_ = true;
+diff --git a/implementation/endpoints/src/endpoint_manager_base.cpp b/implementation/endpoints/src/endpoint_manager_base.cpp
+index 6c63e4f6..a79ae484 100644
+--- a/implementation/endpoints/src/endpoint_manager_base.cpp
++++ b/implementation/endpoints/src/endpoint_manager_base.cpp
+@@ -158,7 +158,7 @@ endpoint_manager_base::log_client_states() const {
+
+ {
+ std::lock_guard<std::mutex> its_lock(local_endpoint_mutex_);
+- for (const auto e : local_endpoints_) {
++ for (const auto& e : local_endpoints_) {
+ size_t its_queue_size = e.second->get_queue_size();
+ if (its_queue_size > VSOMEIP_DEFAULT_QUEUE_WARN_SIZE) {
+ its_client_queue_sizes.push_back(
+diff --git a/implementation/endpoints/src/endpoint_manager_impl.cpp b/implementation/endpoints/src/endpoint_manager_impl.cpp
+index 38dabf71..a82a1734 100644
+--- a/implementation/endpoints/src/endpoint_manager_impl.cpp
++++ b/implementation/endpoints/src/endpoint_manager_impl.cpp
+@@ -983,9 +983,9 @@ endpoint_manager_impl::log_client_states() const {
+ its_client_endpoints = client_endpoints_by_ip_;
+ }
+
+- for (const auto its_address : its_client_endpoints) {
+- for (const auto its_port : its_address.second) {
+- for (const auto its_reliability : its_port.second) {
++ for (const auto& its_address : its_client_endpoints) {
++ for (const auto& its_port : its_address.second) {
++ for (const auto& its_reliability : its_port.second) {
+ size_t its_queue_size = its_reliability.second->get_queue_size();
+ if (its_queue_size > VSOMEIP_DEFAULT_QUEUE_WARN_SIZE)
+ its_client_queue_sizes.push_back(
+@@ -1040,8 +1040,8 @@ endpoint_manager_impl::log_server_states() const {
+ its_server_endpoints = server_endpoints_;
+ }
+
+- for (const auto its_port : its_server_endpoints) {
+- for (const auto its_reliability : its_port.second) {
++ for (const auto& its_port : its_server_endpoints) {
++ for (const auto& its_reliability : its_port.second) {
+ size_t its_queue_size = its_reliability.second->get_queue_size();
+ if (its_queue_size > VSOMEIP_DEFAULT_QUEUE_WARN_SIZE)
+ its_client_queue_sizes.push_back(
+diff --git a/implementation/endpoints/src/server_endpoint_impl.cpp b/implementation/endpoints/src/server_endpoint_impl.cpp
+index 90aea966..838a69cb 100644
+--- a/implementation/endpoints/src/server_endpoint_impl.cpp
++++ b/implementation/endpoints/src/server_endpoint_impl.cpp
+@@ -756,7 +756,7 @@ size_t server_endpoint_impl<Protocol>::get_queue_size() const {
+
+ {
+ std::lock_guard<std::mutex> its_lock(mutex_);
+- for (const auto q : queues_) {
++ for (const auto& q : queues_) {
+ its_queue_size += q.second.second.size();
+ }
+ }
+diff --git a/implementation/routing/src/eventgroupinfo.cpp b/implementation/routing/src/eventgroupinfo.cpp
+index 3b3a8083..e25459c4 100644
+--- a/implementation/routing/src/eventgroupinfo.cpp
++++ b/implementation/routing/src/eventgroupinfo.cpp
+@@ -390,10 +390,10 @@ eventgroupinfo::send_initial_events(
+ }
+
+ // Send events
+- for (const auto its_event : its_reliable_events)
++ for (const auto& its_event : its_reliable_events)
+ its_event->notify_one(VSOMEIP_ROUTING_CLIENT, _reliable);
+
+- for (const auto its_event : its_unreliable_events)
++ for (const auto& its_event : its_unreliable_events)
+ its_event->notify_one(VSOMEIP_ROUTING_CLIENT, _unreliable);
+ }
+
+diff --git a/implementation/routing/src/remote_subscription.cpp b/implementation/routing/src/remote_subscription.cpp
+index 939e0d15..daec6f99 100644
+--- a/implementation/routing/src/remote_subscription.cpp
++++ b/implementation/routing/src/remote_subscription.cpp
+@@ -135,7 +135,7 @@ std::set<client_t>
+ remote_subscription::get_clients() const {
+ std::lock_guard<std::mutex> its_lock(mutex_);
+ std::set<client_t> its_clients;
+- for (const auto its_item : clients_)
++ for (const auto& its_item : clients_)
+ its_clients.insert(its_item.first);
+ return its_clients;
+ }
+diff --git a/implementation/routing/src/routing_manager_impl.cpp b/implementation/routing/src/routing_manager_impl.cpp
+index 74e556c7..19133446 100644
+--- a/implementation/routing/src/routing_manager_impl.cpp
++++ b/implementation/routing/src/routing_manager_impl.cpp
+@@ -2436,14 +2436,14 @@ void routing_manager_impl::del_routing_info(service_t _service, instance_t _inst
+ std::set<std::tuple<
+ service_t, instance_t, eventgroup_t, client_t> > its_invalid;
+
+- for (const auto its_state : remote_subscription_state_) {
++ for (const auto& its_state : remote_subscription_state_) {
+ if (std::get<0>(its_state.first) == _service
+ && std::get<1>(its_state.first) == _instance) {
+ its_invalid.insert(its_state.first);
+ }
+ }
+
+- for (const auto its_key : its_invalid)
++ for (const auto& its_key : its_invalid)
+ remote_subscription_state_.erase(its_key);
+ }
+
+@@ -4347,7 +4347,7 @@ bool routing_manager_impl::insert_event_statistics(service_t _service, instance_
+ // check list for entry with least counter value
+ uint32_t its_min_count(0xFFFFFFFF);
+ auto its_tuple_to_discard = std::make_tuple(0xFFFF, 0xFFFF, 0xFFFF);
+- for (const auto it : message_statistics_) {
++ for (const auto& it : message_statistics_) {
+ if (it.second.counter_ < its_min_count) {
+ its_min_count = it.second.counter_;
+ its_tuple_to_discard = it.first;
+@@ -4389,7 +4389,7 @@ void routing_manager_impl::statistics_log_timer_cbk(boost::system::error_code co
+ std::stringstream its_log;
+ {
+ std::lock_guard<std::mutex> its_lock(message_statistics_mutex_);
+- for (const auto s : message_statistics_) {
++ for (const auto& s : message_statistics_) {
+ if (s.second.counter_ / (its_interval / 1000) >= its_min_freq) {
+ uint16_t its_subscribed(0);
+ std::shared_ptr<event> its_event = find_event(std::get<0>(s.first), std::get<1>(s.first), std::get<2>(s.first));
+diff --git a/implementation/routing/src/routing_manager_stub.cpp b/implementation/routing/src/routing_manager_stub.cpp
+index 72668eac..8e1563b1 100644
+--- a/implementation/routing/src/routing_manager_stub.cpp
++++ b/implementation/routing/src/routing_manager_stub.cpp
+@@ -2257,7 +2257,7 @@ routing_manager_stub::send_requester_policies(const std::unordered_set<client_t>
+ pending_security_update_id_t its_policy_id;
+
+ // serialize the policies and send them...
+- for (const auto p : _policies) {
++ for (const auto& p : _policies) {
+ std::vector<byte_t> its_policy_data;
+ if (p->serialize(its_policy_data)) {
+ std::vector<byte_t> its_message;
+diff --git a/implementation/security/src/policy.cpp b/implementation/security/src/policy.cpp
+index 4babd06c..c36ccca4 100644
+--- a/implementation/security/src/policy.cpp
++++ b/implementation/security/src/policy.cpp
+@@ -203,6 +203,7 @@ policy::deserialize_id_item_list(const byte_t * &_data, uint32_t &_size,
+ uint32_t its_current_size(_size);
+
+ uint16_t its_low, its_high;
++ its_low = its_high = 0;
+ its_result = deserialize_id_item(_data, _size, its_low, its_high);
+ if (its_result == false)
+ return (false);
+@@ -305,7 +306,7 @@ policy::serialize(std::vector<byte_t> &_data) const {
+ uint32_t its_requests_size(0);
+ serialize_u32(its_requests_size, _data);
+
+- for (const auto its_request : requests_) {
++ for (const auto& its_request : requests_) {
+ for (auto its_service = its_request.first.lower();
+ its_service <= its_request.first.upper();
+ its_service++) {
+@@ -316,7 +317,7 @@ policy::serialize(std::vector<byte_t> &_data) const {
+ uint32_t its_instances_size(0);
+ serialize_u32(its_instances_size, _data);
+
+- for (const auto i : its_request.second) {
++ for (const auto& i : its_request.second) {
+ boost::icl::interval_set<instance_t> its_instances;
+ its_instances.insert(i.first);
+ serialize_interval_set(its_instances, _data);
+diff --git a/implementation/security/src/security_impl.cpp b/implementation/security/src/security_impl.cpp
+index 12bb9db2..6cb68eb2 100644
+--- a/implementation/security/src/security_impl.cpp
++++ b/implementation/security/src/security_impl.cpp
+@@ -470,7 +470,7 @@ security_impl::update_security_policy(uint32_t _uid, uint32_t _gid,
+ }
+
+ if (its_matching_policy) {
+- for (const auto r : _policy->requests_) {
++ for (const auto& r : _policy->requests_) {
+ service_t its_lower, its_upper;
+ get_bounds(r.first, its_lower, its_upper);
+ for (auto s = its_lower; s <= its_upper; s++) {
+@@ -479,7 +479,7 @@ security_impl::update_security_policy(uint32_t _uid, uint32_t _gid,
+ its_matching_policy->requests_ += std::make_pair(its_service, r.second);
+ }
+ }
+- for (const auto o : _policy->offers_) {
++ for (const auto& o : _policy->offers_) {
+ service_t its_lower, its_upper;
+ get_bounds(o.first, its_lower, its_upper);
+ for (auto s = its_lower; s <= its_upper; s++) {
+@@ -1081,8 +1081,8 @@ security_impl::get_requester_policies(const std::shared_ptr<policy> _policy,
+ }
+
+ std::lock_guard<std::mutex> its_lock(_policy->mutex_);
+- for (const auto o : _policy->offers_) {
+- for (const auto p : its_policies) {
++ for (const auto& o : _policy->offers_) {
++ for (const auto& p : its_policies) {
+ if (p == _policy)
+ continue;
+
+@@ -1091,7 +1091,7 @@ security_impl::get_requester_policies(const std::shared_ptr<policy> _policy,
+ auto its_policy = std::make_shared<policy>();
+ its_policy->credentials_ = p->credentials_;
+
+- for (const auto r : p->requests_) {
++ for (const auto& r : p->requests_) {
+ // o represents an offer by a service interval and its instances
+ // (a set of intervals)
+ // r represents a request by a service interval and its instances
+@@ -1110,7 +1110,7 @@ security_impl::get_requester_policies(const std::shared_ptr<policy> _policy,
+ auto its_service_max = std::min(its_r_upper, its_o_upper);
+
+ for (const auto i : o.second) {
+- for (const auto j : r.second) {
++ for (const auto& j : r.second) {
+ for (const auto k : j.second) {
+ instance_t its_i_lower, its_i_upper, its_k_lower, its_k_upper;
+ get_bounds(i, its_i_lower, its_i_upper);
+@@ -1151,7 +1151,7 @@ security_impl::get_clients(uid_t _uid, gid_t _gid,
+ std::unordered_set<client_t> &_clients) const {
+
+ std::lock_guard<std::mutex> its_lock(ids_mutex_);
+- for (const auto i : ids_) {
++ for (const auto& i : ids_) {
+ if (i.second.first == _uid && i.second.second == _gid)
+ _clients.insert(i.first);
+ }
+diff --git a/implementation/service_discovery/src/service_discovery_impl.cpp b/implementation/service_discovery/src/service_discovery_impl.cpp
+index b252e627..24d389a3 100644
+--- a/implementation/service_discovery/src/service_discovery_impl.cpp
++++ b/implementation/service_discovery/src/service_discovery_impl.cpp
+@@ -253,7 +253,7 @@ service_discovery_impl::subscribe(
+ if (!its_subscription->is_selective() && is_selective) {
+ its_subscription->set_selective(true);
+ its_subscription->remove_client(VSOMEIP_ROUTING_CLIENT);
+- for (const auto e : _info->get_events()) {
++ for (const auto& e : _info->get_events()) {
+ for (const auto c : e->get_subscribers(_eventgroup)) {
+ its_subscription->add_client(c);
+ }
+--
+2.25.1
+
new file mode 100644
@@ -0,0 +1,71 @@
+SUMMARY = "The implementation of SOME/IP"
+DESCRIPTION = "The vsomeip stack implements the http://some-ip.com/ \
+(Scalable service-Oriented MiddlewarE over IP (SOME/IP)) protocol."
+HOMEPAGE = "https://github.com/COVESA/vsomeip"
+SECTION = "net"
+
+LICENSE = "MPL-2.0"
+LIC_FILES_CHKSUM = "file://LICENSE;md5=815ca599c9df247a0c7f619bab123dad"
+
+SRC_URI = "git://github.com/GENIVI/${BPN}.git;branch=master;protocol=https;name=vsomeip \
+ file://0001-Fix-pkgconfig-dir-for-multilib.patch \
+ file://0002-Install-example-configuration-files-to-etc-vsomeip.patch \
+ file://0003-Do-not-build-external-gtest.patch \
+ file://0004-Support-boost-1.76.patch \
+ file://0005-Add-boost-1.78-support-so-that-vsomeip3-will-compile.patch \
+ file://0006-Support-boost-1.82.patch \
+ file://0007-Do-general-cleanup-of-warnings-that-gcc-12.1.1-fired.patch \
+ "
+
+SRCREV = "13f9c89ced6ffaeb1faf485152e27e1f40d234cd"
+
+COMPATIBLE_HOST:mips = "null"
+COMPATIBLE_HOST:mips64 = "null"
+COMPATIBLE_HOST:powerpc = "null"
+COMPATIBLE_HOST:libc-musl = 'null'
+
+DEPENDS = "boost dlt-daemon googletest"
+
+S = "${WORKDIR}/git"
+
+inherit cmake pkgconfig
+
+EXTRA_OECMAKE = "-DINSTALL_LIB_DIR:PATH=${baselib} \
+ -DINSTALL_CMAKE_DIR:PATH=${baselib}/cmake/vsomeip3 \
+ -DCMAKE_CXX_STANDARD=14 \
+ "
+
+# For vsomeip-test
+EXTRA_OECMAKE += "-DTEST_IP_MASTER=10.0.3.1 \
+ -DTEST_IP_SLAVE=10.0.3.2 \
+ -DTEST_IP_SLAVE_SECOND=10.0.3.3 \
+ "
+
+RDEPENDS:${PN}-test += "bash"
+
+do_compile:append() {
+ cmake_runcmake_build --target examples
+ cmake_runcmake_build --target build_tests
+}
+
+do_install:append() {
+ install -d ${D}/opt/${PN}-test/examples
+ install -m 0755 ${B}/examples/*-sample ${D}/opt/${PN}-test/examples
+ install -d ${D}/opt/${PN}-test/examples/routingmanagerd
+ install -m 0755 ${B}/examples/routingmanagerd/routingmanagerd \
+ ${D}/opt/${PN}-test/examples/routingmanagerd
+
+ install -d ${D}/opt/${PN}-test/test
+ cp -f ${B}/test/*test* ${D}/opt/${PN}-test/test
+
+ cp -rf ${S}/config ${D}/opt/${PN}-test
+}
+
+PACKAGES += "${PN}-test"
+
+FILES:${PN}-dbg += " \
+ /opt/${PN}-test/.debug/* \
+ "
+FILES:${PN}-test = " \
+ /opt/${PN}-test \
+ "
The vsomeip stack implements the http://some-ip.com/ (Scalable service-Oriented MiddlewarE over IP (SOME/IP)) protocol. The stack consists out of: a shared library for SOME/IP (libvsomeip3.so) a shared library for SOME/IP's configuration module (libvsomeip3-cfg.so) a shared library for SOME/IP's service discovery (libvsomeip3-sd.so) a shared library for SOME/IP's E2E protection module (libvsomeip3-e2e.so) Signed-off-by: Yi Zhao <yi.zhao@windriver.com> --- .../0001-Fix-pkgconfig-dir-for-multilib.patch | 28 + ...e-configuration-files-to-etc-vsomeip.patch | 28 + .../0003-Do-not-build-external-gtest.patch | 68 + .../vsomeip/0004-Support-boost-1.76.patch | 14220 ++++++++++++++++ ...upport-so-that-vsomeip3-will-compile.patch | 14216 +++++++++++++++ .../vsomeip/0006-Support-boost-1.82.patch | 32 + ...up-of-warnings-that-gcc-12.1.1-fired.patch | 298 + .../vsomeip/vsomeip_3.1.20.3.bb | 71 + 8 files changed, 28961 insertions(+) create mode 100644 meta-networking/recipes-protocols/vsomeip/vsomeip/0001-Fix-pkgconfig-dir-for-multilib.patch create mode 100644 meta-networking/recipes-protocols/vsomeip/vsomeip/0002-Install-example-configuration-files-to-etc-vsomeip.patch create mode 100644 meta-networking/recipes-protocols/vsomeip/vsomeip/0003-Do-not-build-external-gtest.patch create mode 100644 meta-networking/recipes-protocols/vsomeip/vsomeip/0004-Support-boost-1.76.patch create mode 100644 meta-networking/recipes-protocols/vsomeip/vsomeip/0005-Add-boost-1.78-support-so-that-vsomeip3-will-compile.patch create mode 100644 meta-networking/recipes-protocols/vsomeip/vsomeip/0006-Support-boost-1.82.patch create mode 100644 meta-networking/recipes-protocols/vsomeip/vsomeip/0007-Do-general-cleanup-of-warnings-that-gcc-12.1.1-fired.patch create mode 100644 meta-networking/recipes-protocols/vsomeip/vsomeip_3.1.20.3.bb