diff mbox series

[meta-networking,V2] vsomeip: add recipe

Message ID 20230727023924.1121571-1-yi.zhao@windriver.com
State New
Headers show
Series [meta-networking,V2] vsomeip: add recipe | expand

Commit Message

Yi Zhao July 27, 2023, 2:39 a.m. UTC
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>
---
V2 Change: fix build with nodistro
 .../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 +
 ...8-Do-not-specify-PIE-flag-explicitly.patch |    41 +
 .../vsomeip/vsomeip_3.1.20.3.bb               |    72 +
 9 files changed, 29003 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/0008-Do-not-specify-PIE-flag-explicitly.patch
 create mode 100644 meta-networking/recipes-protocols/vsomeip/vsomeip_3.1.20.3.bb
diff mbox series

Patch

diff --git a/meta-networking/recipes-protocols/vsomeip/vsomeip/0001-Fix-pkgconfig-dir-for-multilib.patch b/meta-networking/recipes-protocols/vsomeip/vsomeip/0001-Fix-pkgconfig-dir-for-multilib.patch
new file mode 100644
index 000000000..f8b50947e
--- /dev/null
+++ b/meta-networking/recipes-protocols/vsomeip/vsomeip/0001-Fix-pkgconfig-dir-for-multilib.patch
@@ -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
+
diff --git a/meta-networking/recipes-protocols/vsomeip/vsomeip/0002-Install-example-configuration-files-to-etc-vsomeip.patch b/meta-networking/recipes-protocols/vsomeip/vsomeip/0002-Install-example-configuration-files-to-etc-vsomeip.patch
new file mode 100644
index 000000000..87fc18846
--- /dev/null
+++ b/meta-networking/recipes-protocols/vsomeip/vsomeip/0002-Install-example-configuration-files-to-etc-vsomeip.patch
@@ -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
+
diff --git a/meta-networking/recipes-protocols/vsomeip/vsomeip/0003-Do-not-build-external-gtest.patch b/meta-networking/recipes-protocols/vsomeip/vsomeip/0003-Do-not-build-external-gtest.patch
new file mode 100644
index 000000000..1ce5824e1
--- /dev/null
+++ b/meta-networking/recipes-protocols/vsomeip/vsomeip/0003-Do-not-build-external-gtest.patch
@@ -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
+
diff --git a/meta-networking/recipes-protocols/vsomeip/vsomeip/0004-Support-boost-1.76.patch b/meta-networking/recipes-protocols/vsomeip/vsomeip/0004-Support-boost-1.76.patch
new file mode 100644
index 000000000..733bf910e
--- /dev/null
+++ b/meta-networking/recipes-protocols/vsomeip/vsomeip/0004-Support-boost-1.76.patch
@@ -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
+
diff --git a/meta-networking/recipes-protocols/vsomeip/vsomeip/0005-Add-boost-1.78-support-so-that-vsomeip3-will-compile.patch b/meta-networking/recipes-protocols/vsomeip/vsomeip/0005-Add-boost-1.78-support-so-that-vsomeip3-will-compile.patch
new file mode 100644
index 000000000..4b71edbe0
--- /dev/null
+++ b/meta-networking/recipes-protocols/vsomeip/vsomeip/0005-Add-boost-1.78-support-so-that-vsomeip3-will-compile.patch
@@ -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
+
diff --git a/meta-networking/recipes-protocols/vsomeip/vsomeip/0006-Support-boost-1.82.patch b/meta-networking/recipes-protocols/vsomeip/vsomeip/0006-Support-boost-1.82.patch
new file mode 100644
index 000000000..34a02584c
--- /dev/null
+++ b/meta-networking/recipes-protocols/vsomeip/vsomeip/0006-Support-boost-1.82.patch
@@ -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
+
diff --git a/meta-networking/recipes-protocols/vsomeip/vsomeip/0007-Do-general-cleanup-of-warnings-that-gcc-12.1.1-fired.patch b/meta-networking/recipes-protocols/vsomeip/vsomeip/0007-Do-general-cleanup-of-warnings-that-gcc-12.1.1-fired.patch
new file mode 100644
index 000000000..35f96df41
--- /dev/null
+++ b/meta-networking/recipes-protocols/vsomeip/vsomeip/0007-Do-general-cleanup-of-warnings-that-gcc-12.1.1-fired.patch
@@ -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
+
diff --git a/meta-networking/recipes-protocols/vsomeip/vsomeip/0008-Do-not-specify-PIE-flag-explicitly.patch b/meta-networking/recipes-protocols/vsomeip/vsomeip/0008-Do-not-specify-PIE-flag-explicitly.patch
new file mode 100644
index 000000000..626d84815
--- /dev/null
+++ b/meta-networking/recipes-protocols/vsomeip/vsomeip/0008-Do-not-specify-PIE-flag-explicitly.patch
@@ -0,0 +1,41 @@ 
+From ea555f757323b13e95e2358262e5a90a18042d35 Mon Sep 17 00:00:00 2001
+From: Yi Zhao <yi.zhao@windriver.com>
+Date: Mon, 17 Jul 2023 14:33:32 +0800
+Subject: [PATCH] Do not specify PIE flag explicitly
+
+For nodistro distro, packages are built without PIE because
+security_flags.inc is not included by default. But in vsomeip, the PIE
+flag is explicitly specified in CMAKE_CXX_FLAGS, which will cause 
+building with PIE even in nodistro, causing an error when linking the
+googletest static library:
+
+TOPDIR/tmp-glibc/work/cortexa53-oe-linux/vsomeip/3.1.20.3-r0/recipe-sysroot-native/usr/bin/aarch64-oe-linux/../../libexec/aarch64-oe-linux/gcc/aarch64-oe-linux/12.2.0/ld:
+TOPDIR/tmp-glibc/work/cortexa53-oe-linux/vsomeip/3.1.20.3-r0/recipe-sysroot/usr/lib/libgtest.a(gtest-all.cc.o)(.text+0x4a90):
+unresolvable R_AARCH64_ADR_PREL_PG_HI21 relocation against symbol `_ZSt4cerr@@GLIBCXX_3.4'
+
+Remove PIE flag from CMAKE_CXX_FLAGS and only enable PIE flag by
+including security_flags.inc.
+
+Upstream-Status: Inappropriate [embedded specific]
+
+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 db17f1d..9d6ffa6 100644
+--- a/CMakeLists.txt
++++ b/CMakeLists.txt
+@@ -52,7 +52,7 @@ if (${CMAKE_SYSTEM_NAME} MATCHES "Linux")
+     set(EXPORTSYMBOLS "-Wl,-export-dynamic -Wl,--version-script=${CMAKE_CURRENT_SOURCE_DIR}/exportmap.gcc")
+     set(NO_DEPRECATED "")
+     set(OPTIMIZE "")
+-    set(OS_CXX_FLAGS "-D_GLIBCXX_USE_NANOSLEEP -pthread -O -Wall -Wextra -Wformat -Wformat-security -Wconversion -fexceptions -fstrict-aliasing -fstack-protector-strong -fasynchronous-unwind-tables -fno-omit-frame-pointer -D_FORTIFY_SOURCE=2 -Wformat -Wformat-security -Werror=format-security -fPIE -pie -Wl,-z,relro,-z,now")
++    set(OS_CXX_FLAGS "-D_GLIBCXX_USE_NANOSLEEP -pthread -O -Wall -Wextra -Wformat -Wformat-security -Wconversion -fexceptions -fstrict-aliasing -fstack-protector-strong -fasynchronous-unwind-tables -fno-omit-frame-pointer -D_FORTIFY_SOURCE=2 -Wformat -Wformat-security -Werror=format-security -Wl,-z,relro,-z,now")
+ endif (${CMAKE_SYSTEM_NAME} MATCHES "Linux")
+ 
+ if (${CMAKE_SYSTEM_NAME} MATCHES "Android")
+-- 
+2.25.1
+
diff --git a/meta-networking/recipes-protocols/vsomeip/vsomeip_3.1.20.3.bb b/meta-networking/recipes-protocols/vsomeip/vsomeip_3.1.20.3.bb
new file mode 100644
index 000000000..03bdc45c4
--- /dev/null
+++ b/meta-networking/recipes-protocols/vsomeip/vsomeip_3.1.20.3.bb
@@ -0,0 +1,72 @@ 
+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 \
+           file://0008-Do-not-specify-PIE-flag-explicitly.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 \
+   "