From patchwork Thu Jul 27 02:39:24 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yi Zhao X-Patchwork-Id: 28713 Return-Path: Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 07E42C001DE for ; Thu, 27 Jul 2023 02:40:20 +0000 (UTC) Received: from mx0a-0064b401.pphosted.com (mx0a-0064b401.pphosted.com [205.220.166.238]) by mx.groups.io with SMTP id smtpd.web10.4515.1690425609599102522 for ; Wed, 26 Jul 2023 19:40:09 -0700 Authentication-Results: mx.groups.io; dkim=pass header.i=@windriver.com header.s=PPS06212021 header.b=iJRPsPUl; spf=permerror, err=parse error for token &{10 18 %{ir}.%{v}.%{d}.spf.has.pphosted.com}: invalid domain name (domain: windriver.com, ip: 205.220.166.238, mailfrom: prvs=6572b4b065=yi.zhao@windriver.com) Received: from pps.filterd (m0250809.ppops.net [127.0.0.1]) by mx0a-0064b401.pphosted.com (8.17.1.22/8.17.1.22) with ESMTP id 36R2P2hW006132 for ; Wed, 26 Jul 2023 19:40:09 -0700 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=windriver.com; h=from:to:subject:date:message-id:content-transfer-encoding :content-type:mime-version; s=PPS06212021; bh=+cx8vb5KCVoT0YNQnw kN7Ky92si61a1FdXHafijZmg4=; b=iJRPsPUl3tvhKFJOnFehy09FQbGeDAuXVq qveT1npK3maK9phHqC2XY1I7nan6CXZd/KBHJag4W2uRPLTpOJBV2NQ0SNfHRHmD 6JjiPh+26Uvr9h8btnR6dGyeQtvr+W4T4elmVQPpxnUVUEugxxPmsCdOb1fzOC88 FgjIOx3GRHT1dn9IkzzdewyUdTaIcS8RrPnnVJLdJDYW3MIsf22Yr00f4iJvYC+o OXbqZJDpgHSzKo595tlASBMO4s7h0DfuOXOi+/pjvKcXS9iCkZdN8rb7iXiNVA/M AnDenINOe7nSeSbqPGt2vuLEPVC70j8hjCITMt4HrGR9L/4XtLRw== Received: from nam11-bn8-obe.outbound.protection.outlook.com (mail-bn8nam11lp2169.outbound.protection.outlook.com [104.47.58.169]) by mx0a-0064b401.pphosted.com (PPS) with ESMTPS id 3s3bear5sc-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT) for ; Wed, 26 Jul 2023 19:40:05 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=h37krBRLdGpnSpvSaMO1VVNnfaXox7tKolL258/ZZa/SR7BCgE+GQO60Jr5ntlq2Hci3vw+HT60jYuea2H1douwzfw/1UE6Ku+jpPf+7uJH45ftZEkohGoZshueVRoknJ18kmk/7YroxCh9bE6b+GpPTXOpNk9gi0rSbvJCnqlPAFnimU0e44k8p65F1pizl4O8C82bg6WtStnDLx6EmzTJOz1Ujo8aAJH4nkp16dA2alGy2DVLYvuqZvYrDZkGCou/EfHVzy8tDbV6pQVtGUHcrvBIDvNOzQGXmhh4Vp0QKm0MpSW5WkqkL45ydyqlLNncyZ4TXYF4JRmHK8jAOMQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=+cx8vb5KCVoT0YNQnwkN7Ky92si61a1FdXHafijZmg4=; b=gxY9FJMAPuMB4nzOwVFvzhtPrF3PVS8mZFNazDVhwu4PA0J2wURvOBhgnVCPJvVKdLg3yMrqcoy+SH9FM23QPIYno8TlWUS5luxlsFMtBZgzc+30QjM0USwnTNKxF6dsdIHkSXg36XiRNGIYBS/IpyM72rtRDorpHm3lgoA1fohPKjIghyLODPaKNORQiyXXA67gJDq0bT0HaV9+5+//URr+NiH7OZ06tmyQxVjl+dgfhgS1mA4pIUivjcqjXFaMC1a5BFyJ8yr0cPrLtO4BO6IjEy8ht2ZpVFIJAJYe5chjtgD58qrnRoiHZrxpBaRmwpD0PbsnhCI1jvQZXrQtPg== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=windriver.com; dmarc=pass action=none header.from=windriver.com; dkim=pass header.d=windriver.com; arc=none Received: from CO1PR11MB4867.namprd11.prod.outlook.com (2603:10b6:303:9a::13) by MW4PR11MB5797.namprd11.prod.outlook.com (2603:10b6:303:184::21) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.6631.29; Thu, 27 Jul 2023 02:39:39 +0000 Received: from CO1PR11MB4867.namprd11.prod.outlook.com ([fe80::f499:a2a9:85eb:97ac]) by CO1PR11MB4867.namprd11.prod.outlook.com ([fe80::f499:a2a9:85eb:97ac%3]) with mapi id 15.20.6631.026; Thu, 27 Jul 2023 02:39:39 +0000 From: Yi Zhao To: openembedded-devel@lists.openembedded.org Subject: [meta-networking][PATCH V2] vsomeip: add recipe Date: Thu, 27 Jul 2023 10:39:24 +0800 Message-Id: <20230727023924.1121571-1-yi.zhao@windriver.com> X-Mailer: git-send-email 2.25.1 X-ClientProxiedBy: SJ0PR03CA0150.namprd03.prod.outlook.com (2603:10b6:a03:33c::35) To CO1PR11MB4867.namprd11.prod.outlook.com (2603:10b6:303:9a::13) MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: CO1PR11MB4867:EE_|MW4PR11MB5797:EE_ X-MS-Office365-Filtering-Correlation-Id: 205eb637-968a-42d4-bdb5-08db8e4ab65d X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: TQ9YVcSi3gW6G/l2wY7JYNrYVL1+inn0ACkVNixWhjcSttFzNV/AJm6cHeAJ9XQf+wODI40Rrvread0f5P41bELdvYwYp95ucN1nUQetWQ3SSiHIPxxB1lKC/hCPrT2FuYXnECOC1HfjqtwuMWoOvhRApBRerqJtXk4/nczLaSnKgkvxadVREWXzd1gn14X9ax9TonRdGq9ODgz2iA1C8MZhx8qDluufi/RvjphssEobyH2wr/0tIXrajMGNjr2w5xQMVsjx9urmSyIf92xoR+KkX2jQ7i3aihW8sqSdCUJC2NBDpa0TAqHFyT/ICYgM21Z/MlueDTTHT2wZhTtOWM4QymWXJgn4+/c6U7/mydGptp+rqFjIIgQ2WR6qMHd11LA/2Gai6Us3t+/GtDqSfDqA053IV/Ru5HbJeLGQDXCsySfLpVoxp6LhHwdH+MK/a/TJHQeiLsH2DAPAmbQW9e1jSolBOTiCAnozoj3djka9ekMi79/6Hot98F5Hv4K9ZBdD9AVNUaCc4YRTEB0GfMha/rSFJMyS1NUXeOUG+706hm+ndevnAIi9q5Pnmj3Np3q2mrcoOn80XpxQpgXXy6P7G0jv4hnXTojeOfxsJDJEcR9A6lBGf2npzsF3yv17kq6fVa4RhJokGmEIUm0gjJCpMIfMq55CjYvzJYn/IU8= X-Forefront-Antispam-Report: CIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:CO1PR11MB4867.namprd11.prod.outlook.com;PTR:;CAT:NONE;SFS:(13230028)(4636009)(376002)(366004)(346002)(396003)(39850400004)(136003)(451199021)(2906002)(66899021)(41300700001)(316002)(44832011)(5660300002)(8676002)(8936002)(30864003)(36756003)(86362001)(478600001)(186003)(2616005)(52116002)(6486002)(6666004)(6512007)(966005)(26005)(1076003)(6506007)(38100700002)(38350700002)(66946007)(66476007)(66556008)(6916009)(83380400001)(562404015)(559001)(579004);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: lCqBMFcl7N/1oWqL1zJzwDKdFon1RHHN37dep54FPGiCzp3gAvHYdYqrKONuEssFgf6l9MD4xK2m59ZSv9Pavgvnf9/uqu3NLtUnS2G4lWxffsVrIohuNNGnQdppXGgruygiyh7gl3EfbBqH+FBaEGvyM/J9/UA515lZT3UDX8HfyQIlSTXru2KbIHYTxQtDduAhkI0+2gqPcgn2CyeGCAWVFVgGmnwmFsGbED+Bk+AGOtKfqZ6dW50XHslJp9VZCsAVC86/G6LH1xfJ175Y1tyIVHlpxSm7wIK5EHMWRNUmhJ/Va9r2MsF6UHT6nDdpgbO5iRdhZJEgQaIPbQvtssFTuyRGtGf+xNByl8q71m2Kb8tu1NFBhryy4oFPFRdLgRINj/Cm6xi/eazIW++hcK2PBGnSkX50cX5/G+gBeIi+RGvNfyNlTL24LlIQUY2IroB1naPuc/BbpuY53EdAf8r8cJMo5wWuAr2jDiHBgzISlL4ASNAzI++ZtIfvQBrg/PLFTkASALEYlEy2FtbwHUiYjazbU9aa0tBbVUADqCbsI97mnfLFs0oOYifocw2wiVnmQQlAyExZ3m8oroK6FiqXAOQ2tMczVJWzfZW4RagclcaleFXgNtMl6Ql0UK02bhwllZJ0kZr37Qpy2s1cI7mk1L5sz+dc9MRsTTp8e98iAcMas8BfHGBTkHpBMdn4P0eb6m0sU16fZnD7t9dTLARvbKbhxyLWPdm4jjp/kYuc0Cydpw7MA2odirg7pctkYv0Wdx93auuuXUGJ7OjI65qls0dRvkUKsi8NgayjENZVffcm4UaY6onMlTiDmy3Q3X9xoTcyejGPcA5MWRs9vFuV2Y63bANiaSWRsK3YTr9s3OArHIVySxHdyVDdF1dIb6TlQZaO0XA/JcBS+2GEhnzzWzmMnAVBC8JbheXxiOqY4cL7pCRKur2NkqTYlcqwzRiRkkUYPt2lEk1HoTwotb5QF1zvAYUMSYJM3zNQUoS9ziaw2pmcXodCVkpLOqNe556clnpV9/fYNyKqF5vdWayn3pz7NBTIF6+93ZgQpe70xG8GiQHPA/4JDKbB4y3O+ElIGIPhJbE+nnh40fSTHE5dHB20iQbVFbnR6WcSNQen39x4+7Ck1ICQRIJg9twg09Xj5s+vxe/fRq/cHwwgQ2Xrk5fjExFjiK9eMP8W4Raylf5y9LxR/Gzv+GPanK6xBo98S/CW/53SQz3FC4ZoZ+T0dfW5/zKetN9WNvrhXk4oqkiW+hZpDM0eA5ur967b3KFwuPYaAz3fpfhL5gtsHOUqRtCAGTyMfRggs00lL29fZojs7nxonB3Biy94/8ClZfYgzjpPYbZWQYgYrr7tOR1nk6o06/Fp0/2tO5O/IHUhmlph936omqiddYtu/q9hSy+Q5+uf1RrNtrBwLa0QiCB5mF7Va9Sb4+tAuh8ybs7wK/L0rwNT7QE7n62BJQZGE4Gu1VPSJzqTKr85oOD1Kr3mxVSRETc7Pj6wiNr5dM42Fpg/Xc+xNxWeiGVBiEcUKVoBurpRlEJbUV79wyrR+bweLJRrUdcT4JkfPLMtMQZ5Ly6xYOpeh2BWg3vXrMKi X-OriginatorOrg: windriver.com X-MS-Exchange-CrossTenant-Network-Message-Id: 205eb637-968a-42d4-bdb5-08db8e4ab65d X-MS-Exchange-CrossTenant-AuthSource: CO1PR11MB4867.namprd11.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 27 Jul 2023 02:39:38.9470 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 8ddb2873-a1ad-4a18-ae4e-4644631433be X-MS-Exchange-CrossTenant-MailboxType: HOSTED X-MS-Exchange-CrossTenant-UserPrincipalName: COZuGmHQfwEee5XCFIyLI49CLJCPaWj86COctpOwy8nKL+g6PE18uNaD7OmtY1acpYD6yEgYKrQGnQx4PCR5FQ== X-MS-Exchange-Transport-CrossTenantHeadersStamped: MW4PR11MB5797 X-Proofpoint-ORIG-GUID: MGDtnftX4nuvT5MrJy_TwyCbcvHCK3Qo X-Proofpoint-GUID: MGDtnftX4nuvT5MrJy_TwyCbcvHCK3Qo X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.254,Aquarius:18.0.957,Hydra:6.0.591,FMLib:17.11.176.26 definitions=2023-07-26_08,2023-07-26_01,2023-05-22_02 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 spamscore=0 adultscore=0 mlxlogscore=999 lowpriorityscore=0 malwarescore=0 suspectscore=0 impostorscore=0 mlxscore=0 priorityscore=1501 clxscore=1015 bulkscore=0 phishscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.19.0-2306200000 definitions=main-2307270023 List-Id: X-Webhook-Received: from li982-79.members.linode.com [45.33.32.79] by aws-us-west-2-korg-lkml-1.web.codeaurora.org with HTTPS for ; Thu, 27 Jul 2023 02:40:19 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-devel/message/104043 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 --- 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 --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 +Date: Wed, 2 Mar 2022 14:51:13 +0800 +Subject: [PATCH] Fix pkgconfig dir for multilib + +Upstream-Status: Pending + +Signed-off-by: Yi Zhao +--- + 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 +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 +--- + 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 +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 +--- + 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 +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 +--- + 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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++namespace boost { ++namespace asio { ++ ++#if !defined(BOOST_ASIO_BASIC_DATAGRAM_SOCKET_EXT_FWD_DECL) ++#define BOOST_ASIO_BASIC_DATAGRAM_SOCKET_EXT_FWD_DECL ++ ++// Forward declaration with defaulted arguments. ++template ++class basic_datagram_socket_ext; ++ ++#endif // !defined(BOOST_ASIO_BASIC_DATAGRAM_SOCKET_EXT_FWD_DECL) ++ ++/// Provides datagram-oriented socket functionality. ++/** ++ * The basic_datagram_socket class template provides asynchronous and blocking ++ * datagram-oriented socket functionality. ++ * ++ * @par Thread Safety ++ * @e Distinct @e objects: Safe.@n ++ * @e Shared @e objects: Unsafe. ++ */ ++template ++class basic_datagram_socket_ext ++ : public basic_socket_ext ++{ ++public: ++ /// The type of the executor associated with the object. ++ typedef Executor executor_type; ++ ++ /// Rebinds the socket type to another executor. ++ template ++ struct rebind_executor ++ { ++ /// The socket type when rebound to the specified executor. ++ typedef basic_datagram_socket_ext other; ++ }; ++ ++ /// The native representation of a socket. ++#if defined(GENERATING_DOCUMENTATION) ++ typedef implementation_defined native_handle_type; ++#else ++ typedef typename basic_socket_ext::native_handle_type native_handle_type; ++#endif ++ ++ /// The protocol type. ++ typedef Protocol protocol_type; ++ ++ /// The endpoint type. ++ typedef typename Protocol::endpoint endpoint_type; ++ ++ /// Construct a basic_datagram_socket without opening it. ++ /** ++ * This constructor creates a datagram socket without opening it. The open() ++ * function must be called before data can be sent or received on the socket. ++ * ++ * @param ex The I/O executor that the socket will use, by default, to ++ * dispatch handlers for any asynchronous operations performed on the socket. ++ */ ++ explicit basic_datagram_socket_ext(const executor_type& ex) ++ : basic_socket_ext(ex) ++ { ++ } ++ ++ /// Construct a basic_datagram_socket without opening it. ++ /** ++ * This constructor creates a datagram socket without opening it. The open() ++ * function must be called before data can be sent or received on the socket. ++ * ++ * @param context An execution context which provides the I/O executor that ++ * the socket will use, by default, to dispatch handlers for any asynchronous ++ * operations performed on the socket. ++ */ ++ template ++ explicit basic_datagram_socket_ext(ExecutionContext& context, ++ typename enable_if< ++ is_convertible::value ++ >::type* = 0) ++ : basic_socket_ext(context) ++ { ++ } ++ ++ /// Construct and open a basic_datagram_socket. ++ /** ++ * This constructor creates and opens a datagram socket. ++ * ++ * @param ex The I/O executor that the socket will use, by default, to ++ * dispatch handlers for any asynchronous operations performed on the socket. ++ * ++ * @param protocol An object specifying protocol parameters to be used. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ */ ++ basic_datagram_socket_ext(const executor_type& ex, const protocol_type& protocol) ++ : basic_socket_ext(ex, protocol) ++ { ++ } ++ ++ /// Construct and open a basic_datagram_socket. ++ /** ++ * This constructor creates and opens a datagram socket. ++ * ++ * @param context An execution context which provides the I/O executor that ++ * the socket will use, by default, to dispatch handlers for any asynchronous ++ * operations performed on the socket. ++ * ++ * @param protocol An object specifying protocol parameters to be used. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ */ ++ template ++ basic_datagram_socket_ext(ExecutionContext& context, ++ const protocol_type& protocol, ++ typename enable_if< ++ is_convertible::value ++ >::type* = 0) ++ : basic_socket_ext(context, protocol) ++ { ++ } ++ ++ /// Construct a basic_datagram_socket, opening it and binding it to the given ++ /// local endpoint. ++ /** ++ * This constructor creates a datagram socket and automatically opens it bound ++ * to the specified endpoint on the local machine. The protocol used is the ++ * protocol associated with the given endpoint. ++ * ++ * @param ex The I/O executor that the socket will use, by default, to ++ * dispatch handlers for any asynchronous operations performed on the socket. ++ * ++ * @param endpoint An endpoint on the local machine to which the datagram ++ * socket will be bound. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ */ ++ basic_datagram_socket_ext(const executor_type& ex, const endpoint_type& endpoint) ++ : basic_socket_ext(ex, endpoint) ++ { ++ } ++ ++ /// Construct a basic_datagram_socket, opening it and binding it to the given ++ /// local endpoint. ++ /** ++ * This constructor creates a datagram socket and automatically opens it bound ++ * to the specified endpoint on the local machine. The protocol used is the ++ * protocol associated with the given endpoint. ++ * ++ * @param context An execution context which provides the I/O executor that ++ * the socket will use, by default, to dispatch handlers for any asynchronous ++ * operations performed on the socket. ++ * ++ * @param endpoint An endpoint on the local machine to which the datagram ++ * socket will be bound. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ */ ++ template ++ basic_datagram_socket_ext(ExecutionContext& context, ++ const endpoint_type& endpoint, ++ typename enable_if< ++ is_convertible::value ++ >::type* = 0) ++ : basic_socket_ext(context, endpoint) ++ { ++ } ++ ++ /// Construct a basic_datagram_socket on an existing native socket. ++ /** ++ * This constructor creates a datagram socket object to hold an existing ++ * native socket. ++ * ++ * @param ex The I/O executor that the socket will use, by default, to ++ * dispatch handlers for any asynchronous operations performed on the socket. ++ * ++ * @param protocol An object specifying protocol parameters to be used. ++ * ++ * @param native_socket The new underlying socket implementation. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ */ ++ basic_datagram_socket_ext(const executor_type& ex, ++ const protocol_type& protocol, const native_handle_type& native_socket) ++ : basic_socket_ext(ex, protocol, native_socket) ++ { ++ } ++ ++ /// Construct a basic_datagram_socket on an existing native socket. ++ /** ++ * This constructor creates a datagram socket object to hold an existing ++ * native socket. ++ * ++ * @param context An execution context which provides the I/O executor that ++ * the socket will use, by default, to dispatch handlers for any asynchronous ++ * operations performed on the socket. ++ * ++ * @param protocol An object specifying protocol parameters to be used. ++ * ++ * @param native_socket The new underlying socket implementation. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ */ ++ template ++ basic_datagram_socket_ext(ExecutionContext& context, ++ const protocol_type& protocol, const native_handle_type& native_socket, ++ typename enable_if< ++ is_convertible::value ++ >::type* = 0) ++ : basic_socket_ext(context, protocol, native_socket) ++ { ++ } ++ ++#if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) ++ /// Move-construct a basic_datagram_socket from another. ++ /** ++ * This constructor moves a datagram socket from one object to another. ++ * ++ * @param other The other basic_datagram_socket object from which the move ++ * will occur. ++ * ++ * @note Following the move, the moved-from object is in the same state as if ++ * constructed using the @c basic_datagram_socket(const executor_type&) ++ * constructor. ++ */ ++ basic_datagram_socket_ext(basic_datagram_socket_ext&& other) ++ : basic_socket_ext(std::move(other)) ++ { ++ } ++ ++ /// Move-assign a basic_datagram_socket from another. ++ /** ++ * This assignment operator moves a datagram socket from one object to ++ * another. ++ * ++ * @param other The other basic_datagram_socket object from which the move ++ * will occur. ++ * ++ * @note Following the move, the moved-from object is in the same state as if ++ * constructed using the @c basic_datagram_socket(const executor_type&) ++ * constructor. ++ */ ++ basic_datagram_socket_ext& operator=(basic_datagram_socket_ext&& other) ++ { ++ basic_socket_ext::operator=(std::move(other)); ++ return *this; ++ } ++ ++ /// Move-construct a basic_datagram_socket from a socket of another protocol ++ /// type. ++ /** ++ * This constructor moves a datagram socket from one object to another. ++ * ++ * @param other The other basic_datagram_socket object from which the move ++ * will occur. ++ * ++ * @note Following the move, the moved-from object is in the same state as if ++ * constructed using the @c basic_datagram_socket(const executor_type&) ++ * constructor. ++ */ ++ template ++ basic_datagram_socket_ext(basic_datagram_socket_ext&& other, ++ typename enable_if< ++ is_convertible::value ++ && is_convertible::value ++ >::type* = 0) ++ : basic_socket_ext(std::move(other)) ++ { ++ } ++ ++ /// Move-assign a basic_datagram_socket from a socket of another protocol ++ /// type. ++ /** ++ * This assignment operator moves a datagram socket from one object to ++ * another. ++ * ++ * @param other The other basic_datagram_socket object from which the move ++ * will occur. ++ * ++ * @note Following the move, the moved-from object is in the same state as if ++ * constructed using the @c basic_datagram_socket(const executor_type&) ++ * constructor. ++ */ ++ template ++ typename enable_if< ++ is_convertible::value ++ && is_convertible::value, ++ basic_datagram_socket_ext& ++ >::type operator=(basic_datagram_socket_ext&& other) ++ { ++ basic_socket_ext::operator=(std::move(other)); ++ return *this; ++ } ++#endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) ++ ++ /// Destroys the socket. ++ /** ++ * This function destroys the socket, cancelling any outstanding asynchronous ++ * operations associated with the socket as if by calling @c cancel. ++ */ ++ ~basic_datagram_socket_ext() ++ { ++ } ++ ++ /// Send some data on a connected socket. ++ /** ++ * This function is used to send data on the datagram socket. The function ++ * call will block until the data has been sent successfully or an error ++ * occurs. ++ * ++ * @param buffers One ore more data buffers to be sent on the socket. ++ * ++ * @returns The number of bytes sent. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ * ++ * @note The send operation can only be used with a connected socket. Use ++ * the send_to function to send data on an unconnected datagram socket. ++ * ++ * @par Example ++ * To send a single data buffer use the @ref buffer function as follows: ++ * @code socket.send(boost::asio::buffer(data, size)); @endcode ++ * See the @ref buffer documentation for information on sending multiple ++ * buffers in one go, and how to use it with arrays, boost::array or ++ * std::vector. ++ */ ++ template ++ std::size_t send(const ConstBufferSequence& buffers) ++ { ++ boost::system::error_code ec; ++ std::size_t s = this->impl_.get_service().send( ++ this->impl_.get_implementation(), buffers, 0, ec); ++ boost::asio::detail::throw_error(ec, "send"); ++ return s; ++ } ++ ++ /// Send some data on a connected socket. ++ /** ++ * This function is used to send data on the datagram socket. The function ++ * call will block until the data has been sent successfully or an error ++ * occurs. ++ * ++ * @param buffers One ore more data buffers to be sent on the socket. ++ * ++ * @param flags Flags specifying how the send call is to be made. ++ * ++ * @returns The number of bytes sent. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ * ++ * @note The send operation can only be used with a connected socket. Use ++ * the send_to function to send data on an unconnected datagram socket. ++ */ ++ template ++ std::size_t send(const ConstBufferSequence& buffers, ++ socket_base::message_flags flags) ++ { ++ boost::system::error_code ec; ++ std::size_t s = this->impl_.get_service().send( ++ this->impl_.get_implementation(), buffers, flags, ec); ++ boost::asio::detail::throw_error(ec, "send"); ++ return s; ++ } ++ ++ /// Send some data on a connected socket. ++ /** ++ * This function is used to send data on the datagram socket. The function ++ * call will block until the data has been sent successfully or an error ++ * occurs. ++ * ++ * @param buffers One or more data buffers to be sent on the socket. ++ * ++ * @param flags Flags specifying how the send call is to be made. ++ * ++ * @param ec Set to indicate what error occurred, if any. ++ * ++ * @returns The number of bytes sent. ++ * ++ * @note The send operation can only be used with a connected socket. Use ++ * the send_to function to send data on an unconnected datagram socket. ++ */ ++ template ++ std::size_t send(const ConstBufferSequence& buffers, ++ socket_base::message_flags flags, boost::system::error_code& ec) ++ { ++ return this->impl_.get_service().send( ++ this->impl_.get_implementation(), buffers, flags, ec); ++ } ++ ++ /// Start an asynchronous send on a connected socket. ++ /** ++ * This function is used to asynchronously send data on the datagram socket. ++ * The function call always returns immediately. ++ * ++ * @param buffers One or more data buffers to be sent on the socket. Although ++ * the buffers object may be copied as necessary, ownership of the underlying ++ * memory blocks is retained by the caller, which must guarantee that they ++ * remain valid until the handler is called. ++ * ++ * @param handler The handler to be called when the send operation completes. ++ * Copies will be made of the handler as required. The function signature of ++ * the handler must be: ++ * @code void handler( ++ * const boost::system::error_code& error, // Result of operation. ++ * std::size_t bytes_transferred // Number of bytes sent. ++ * ); @endcode ++ * Regardless of whether the asynchronous operation completes immediately or ++ * not, the handler will not be invoked from within this function. On ++ * immediate completion, invocation of the handler will be performed in a ++ * manner equivalent to using boost::asio::post(). ++ * ++ * @note The async_send operation can only be used with a connected socket. ++ * Use the async_send_to function to send data on an unconnected datagram ++ * socket. ++ * ++ * @par Example ++ * To send a single data buffer use the @ref buffer function as follows: ++ * @code ++ * socket.async_send(boost::asio::buffer(data, size), handler); ++ * @endcode ++ * See the @ref buffer documentation for information on sending multiple ++ * buffers in one go, and how to use it with arrays, boost::array or ++ * std::vector. ++ */ ++ template ++ BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler, ++ void (boost::system::error_code, std::size_t)) ++ async_send(const ConstBufferSequence& buffers, ++ BOOST_ASIO_MOVE_ARG(WriteHandler) handler) ++ { ++ return async_initiate( ++ initiate_async_send(), handler, this, ++ buffers, socket_base::message_flags(0)); ++ } ++ ++ /// Start an asynchronous send on a connected socket. ++ /** ++ * This function is used to asynchronously send data on the datagram socket. ++ * The function call always returns immediately. ++ * ++ * @param buffers One or more data buffers to be sent on the socket. Although ++ * the buffers object may be copied as necessary, ownership of the underlying ++ * memory blocks is retained by the caller, which must guarantee that they ++ * remain valid until the handler is called. ++ * ++ * @param flags Flags specifying how the send call is to be made. ++ * ++ * @param handler The handler to be called when the send operation completes. ++ * Copies will be made of the handler as required. The function signature of ++ * the handler must be: ++ * @code void handler( ++ * const boost::system::error_code& error, // Result of operation. ++ * std::size_t bytes_transferred // Number of bytes sent. ++ * ); @endcode ++ * Regardless of whether the asynchronous operation completes immediately or ++ * not, the handler will not be invoked from within this function. On ++ * immediate completion, invocation of the handler will be performed in a ++ * manner equivalent to using boost::asio::post(). ++ * ++ * @note The async_send operation can only be used with a connected socket. ++ * Use the async_send_to function to send data on an unconnected datagram ++ * socket. ++ */ ++ template ++ BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler, ++ void (boost::system::error_code, std::size_t)) ++ async_send(const ConstBufferSequence& buffers, ++ socket_base::message_flags flags, ++ BOOST_ASIO_MOVE_ARG(WriteHandler) handler) ++ { ++ return async_initiate( ++ initiate_async_send(), handler, this, buffers, flags); ++ } ++ ++ /// Send a datagram to the specified endpoint. ++ /** ++ * This function is used to send a datagram to the specified remote endpoint. ++ * The function call will block until the data has been sent successfully or ++ * an error occurs. ++ * ++ * @param buffers One or more data buffers to be sent to the remote endpoint. ++ * ++ * @param destination The remote endpoint to which the data will be sent. ++ * ++ * @returns The number of bytes sent. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ * ++ * @par Example ++ * To send a single data buffer use the @ref buffer function as follows: ++ * @code ++ * boost::asio::ip::udp::endpoint destination( ++ * boost::asio::ip::address::from_string("1.2.3.4"), 12345); ++ * socket.send_to(boost::asio::buffer(data, size), destination); ++ * @endcode ++ * See the @ref buffer documentation for information on sending multiple ++ * buffers in one go, and how to use it with arrays, boost::array or ++ * std::vector. ++ */ ++ template ++ std::size_t send_to(const ConstBufferSequence& buffers, ++ const endpoint_type& destination) ++ { ++ boost::system::error_code ec; ++ std::size_t s = this->impl_.get_service().send_to( ++ this->impl_.get_implementation(), buffers, destination, 0, ec); ++ boost::asio::detail::throw_error(ec, "send_to"); ++ return s; ++ } ++ ++ /// Send a datagram to the specified endpoint. ++ /** ++ * This function is used to send a datagram to the specified remote endpoint. ++ * The function call will block until the data has been sent successfully or ++ * an error occurs. ++ * ++ * @param buffers One or more data buffers to be sent to the remote endpoint. ++ * ++ * @param destination The remote endpoint to which the data will be sent. ++ * ++ * @param flags Flags specifying how the send call is to be made. ++ * ++ * @returns The number of bytes sent. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ */ ++ template ++ std::size_t send_to(const ConstBufferSequence& buffers, ++ const endpoint_type& destination, socket_base::message_flags flags) ++ { ++ boost::system::error_code ec; ++ std::size_t s = this->impl_.get_service().send_to( ++ this->impl_.get_implementation(), buffers, destination, flags, ec); ++ boost::asio::detail::throw_error(ec, "send_to"); ++ return s; ++ } ++ ++ /// Send a datagram to the specified endpoint. ++ /** ++ * This function is used to send a datagram to the specified remote endpoint. ++ * The function call will block until the data has been sent successfully or ++ * an error occurs. ++ * ++ * @param buffers One or more data buffers to be sent to the remote endpoint. ++ * ++ * @param destination The remote endpoint to which the data will be sent. ++ * ++ * @param flags Flags specifying how the send call is to be made. ++ * ++ * @param ec Set to indicate what error occurred, if any. ++ * ++ * @returns The number of bytes sent. ++ */ ++ template ++ std::size_t send_to(const ConstBufferSequence& buffers, ++ const endpoint_type& destination, socket_base::message_flags flags, ++ boost::system::error_code& ec) ++ { ++ return this->impl_.get_service().send_to(this->impl_.get_implementation(), ++ buffers, destination, flags, ec); ++ } ++ ++ /// Start an asynchronous send. ++ /** ++ * This function is used to asynchronously send a datagram to the specified ++ * remote endpoint. The function call always returns immediately. ++ * ++ * @param buffers One or more data buffers to be sent to the remote endpoint. ++ * Although the buffers object may be copied as necessary, ownership of the ++ * underlying memory blocks is retained by the caller, which must guarantee ++ * that they remain valid until the handler is called. ++ * ++ * @param destination The remote endpoint to which the data will be sent. ++ * Copies will be made of the endpoint as required. ++ * ++ * @param handler The handler to be called when the send operation completes. ++ * Copies will be made of the handler as required. The function signature of ++ * the handler must be: ++ * @code void handler( ++ * const boost::system::error_code& error, // Result of operation. ++ * std::size_t bytes_transferred // Number of bytes sent. ++ * ); @endcode ++ * Regardless of whether the asynchronous operation completes immediately or ++ * not, the handler will not be invoked from within this function. On ++ * immediate completion, invocation of the handler will be performed in a ++ * manner equivalent to using boost::asio::post(). ++ * ++ * @par Example ++ * To send a single data buffer use the @ref buffer function as follows: ++ * @code ++ * boost::asio::ip::udp::endpoint destination( ++ * boost::asio::ip::address::from_string("1.2.3.4"), 12345); ++ * socket.async_send_to( ++ * boost::asio::buffer(data, size), destination, handler); ++ * @endcode ++ * See the @ref buffer documentation for information on sending multiple ++ * buffers in one go, and how to use it with arrays, boost::array or ++ * std::vector. ++ */ ++ template ++ BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler, ++ void (boost::system::error_code, std::size_t)) ++ async_send_to(const ConstBufferSequence& buffers, ++ const endpoint_type& destination, ++ BOOST_ASIO_MOVE_ARG(WriteHandler) handler) ++ { ++ return async_initiate( ++ initiate_async_send_to(), handler, this, buffers, ++ destination, socket_base::message_flags(0)); ++ } ++ ++ /// Start an asynchronous send. ++ /** ++ * This function is used to asynchronously send a datagram to the specified ++ * remote endpoint. The function call always returns immediately. ++ * ++ * @param buffers One or more data buffers to be sent to the remote endpoint. ++ * Although the buffers object may be copied as necessary, ownership of the ++ * underlying memory blocks is retained by the caller, which must guarantee ++ * that they remain valid until the handler is called. ++ * ++ * @param flags Flags specifying how the send call is to be made. ++ * ++ * @param destination The remote endpoint to which the data will be sent. ++ * Copies will be made of the endpoint as required. ++ * ++ * @param handler The handler to be called when the send operation completes. ++ * Copies will be made of the handler as required. The function signature of ++ * the handler must be: ++ * @code void handler( ++ * const boost::system::error_code& error, // Result of operation. ++ * std::size_t bytes_transferred // Number of bytes sent. ++ * ); @endcode ++ * Regardless of whether the asynchronous operation completes immediately or ++ * not, the handler will not be invoked from within this function. On ++ * immediate completion, invocation of the handler will be performed in a ++ * manner equivalent to using boost::asio::post(). ++ */ ++ template ++ BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler, ++ void (boost::system::error_code, std::size_t)) ++ async_send_to(const ConstBufferSequence& buffers, ++ const endpoint_type& destination, socket_base::message_flags flags, ++ BOOST_ASIO_MOVE_ARG(WriteHandler) handler) ++ { ++ return async_initiate( ++ initiate_async_send_to(), handler, this, buffers, destination, flags); ++ } ++ ++ /// Receive some data on a connected socket. ++ /** ++ * This function is used to receive data on the datagram socket. The function ++ * call will block until data has been received successfully or an error ++ * occurs. ++ * ++ * @param buffers One or more buffers into which the data will be received. ++ * ++ * @returns The number of bytes received. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ * ++ * @note The receive operation can only be used with a connected socket. Use ++ * the receive_from function to receive data on an unconnected datagram ++ * socket. ++ * ++ * @par Example ++ * To receive into a single data buffer use the @ref buffer function as ++ * follows: ++ * @code socket.receive(boost::asio::buffer(data, size)); @endcode ++ * See the @ref buffer documentation for information on receiving into ++ * multiple buffers in one go, and how to use it with arrays, boost::array or ++ * std::vector. ++ */ ++ template ++ std::size_t receive(const MutableBufferSequence& buffers) ++ { ++ boost::system::error_code ec; ++ std::size_t s = this->impl_.get_service().receive( ++ this->impl_.get_implementation(), buffers, 0, ec); ++ boost::asio::detail::throw_error(ec, "receive"); ++ return s; ++ } ++ ++ /// Receive some data on a connected socket. ++ /** ++ * This function is used to receive data on the datagram socket. The function ++ * call will block until data has been received successfully or an error ++ * occurs. ++ * ++ * @param buffers One or more buffers into which the data will be received. ++ * ++ * @param flags Flags specifying how the receive call is to be made. ++ * ++ * @returns The number of bytes received. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ * ++ * @note The receive operation can only be used with a connected socket. Use ++ * the receive_from function to receive data on an unconnected datagram ++ * socket. ++ */ ++ template ++ std::size_t receive(const MutableBufferSequence& buffers, ++ socket_base::message_flags flags) ++ { ++ boost::system::error_code ec; ++ std::size_t s = this->impl_.get_service().receive( ++ this->impl_.get_implementation(), buffers, flags, ec); ++ boost::asio::detail::throw_error(ec, "receive"); ++ return s; ++ } ++ ++ /// Receive some data on a connected socket. ++ /** ++ * This function is used to receive data on the datagram socket. The function ++ * call will block until data has been received successfully or an error ++ * occurs. ++ * ++ * @param buffers One or more buffers into which the data will be received. ++ * ++ * @param flags Flags specifying how the receive call is to be made. ++ * ++ * @param ec Set to indicate what error occurred, if any. ++ * ++ * @returns The number of bytes received. ++ * ++ * @note The receive operation can only be used with a connected socket. Use ++ * the receive_from function to receive data on an unconnected datagram ++ * socket. ++ */ ++ template ++ std::size_t receive(const MutableBufferSequence& buffers, ++ socket_base::message_flags flags, boost::system::error_code& ec) ++ { ++ return this->impl_.get_service().receive( ++ this->impl_.get_implementation(), buffers, flags, ec); ++ } ++ ++ /// Start an asynchronous receive on a connected socket. ++ /** ++ * This function is used to asynchronously receive data from the datagram ++ * socket. The function call always returns immediately. ++ * ++ * @param buffers One or more buffers into which the data will be received. ++ * Although the buffers object may be copied as necessary, ownership of the ++ * underlying memory blocks is retained by the caller, which must guarantee ++ * that they remain valid until the handler is called. ++ * ++ * @param handler The handler to be called when the receive operation ++ * completes. Copies will be made of the handler as required. The function ++ * signature of the handler must be: ++ * @code void handler( ++ * const boost::system::error_code& error, // Result of operation. ++ * std::size_t bytes_transferred // Number of bytes received. ++ * ); @endcode ++ * Regardless of whether the asynchronous operation completes immediately or ++ * not, the handler will not be invoked from within this function. On ++ * immediate completion, invocation of the handler will be performed in a ++ * manner equivalent to using boost::asio::post(). ++ * ++ * @note The async_receive operation can only be used with a connected socket. ++ * Use the async_receive_from function to receive data on an unconnected ++ * datagram socket. ++ * ++ * @par Example ++ * To receive into a single data buffer use the @ref buffer function as ++ * follows: ++ * @code ++ * socket.async_receive(boost::asio::buffer(data, size), handler); ++ * @endcode ++ * See the @ref buffer documentation for information on receiving into ++ * multiple buffers in one go, and how to use it with arrays, boost::array or ++ * std::vector. ++ */ ++ template ++ BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler, ++ void (boost::system::error_code, std::size_t, boost::asio::ip::address)) ++ async_receive(const MutableBufferSequence& buffers, ++ BOOST_ASIO_MOVE_ARG(ReadHandler) handler) ++ { ++ return async_initiate( ++ initiate_async_receive(), handler, this, ++ buffers, socket_base::message_flags(0)); ++ } ++ ++ /// Start an asynchronous receive on a connected socket. ++ /** ++ * This function is used to asynchronously receive data from the datagram ++ * socket. The function call always returns immediately. ++ * ++ * @param buffers One or more buffers into which the data will be received. ++ * Although the buffers object may be copied as necessary, ownership of the ++ * underlying memory blocks is retained by the caller, which must guarantee ++ * that they remain valid until the handler is called. ++ * ++ * @param flags Flags specifying how the receive call is to be made. ++ * ++ * @param handler The handler to be called when the receive operation ++ * completes. Copies will be made of the handler as required. The function ++ * signature of the handler must be: ++ * @code void handler( ++ * const boost::system::error_code& error, // Result of operation. ++ * std::size_t bytes_transferred // Number of bytes received. ++ * ); @endcode ++ * Regardless of whether the asynchronous operation completes immediately or ++ * not, the handler will not be invoked from within this function. On ++ * immediate completion, invocation of the handler will be performed in a ++ * manner equivalent to using boost::asio::post(). ++ * ++ * @note The async_receive operation can only be used with a connected socket. ++ * Use the async_receive_from function to receive data on an unconnected ++ * datagram socket. ++ */ ++ template ++ BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler, ++ void (boost::system::error_code, std::size_t, boost::asio::ip::address)) ++ async_receive(const MutableBufferSequence& buffers, ++ socket_base::message_flags flags, ++ BOOST_ASIO_MOVE_ARG(ReadHandler) handler) ++ { ++ return async_initiate( ++ initiate_async_receive(), handler, this, buffers, flags); ++ } ++ ++ /// Receive a datagram with the endpoint of the sender. ++ /** ++ * This function is used to receive a datagram. The function call will block ++ * until data has been received successfully or an error occurs. ++ * ++ * @param buffers One or more buffers into which the data will be received. ++ * ++ * @param sender_endpoint An endpoint object that receives the endpoint of ++ * the remote sender of the datagram. ++ * ++ * @returns The number of bytes received. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ * ++ * @par Example ++ * To receive into a single data buffer use the @ref buffer function as ++ * follows: ++ * @code ++ * boost::asio::ip::udp::endpoint sender_endpoint; ++ * socket.receive_from( ++ * boost::asio::buffer(data, size), sender_endpoint); ++ * @endcode ++ * See the @ref buffer documentation for information on receiving into ++ * multiple buffers in one go, and how to use it with arrays, boost::array or ++ * std::vector. ++ */ ++ template ++ std::size_t receive_from(const MutableBufferSequence& buffers, ++ endpoint_type& sender_endpoint) ++ { ++ boost::system::error_code ec; ++ std::size_t s = this->impl_.get_service().receive_from( ++ this->impl_.get_implementation(), buffers, sender_endpoint, 0, ec); ++ boost::asio::detail::throw_error(ec, "receive_from"); ++ return s; ++ } ++ ++ /// Receive a datagram with the endpoint of the sender. ++ /** ++ * This function is used to receive a datagram. The function call will block ++ * until data has been received successfully or an error occurs. ++ * ++ * @param buffers One or more buffers into which the data will be received. ++ * ++ * @param sender_endpoint An endpoint object that receives the endpoint of ++ * the remote sender of the datagram. ++ * ++ * @param flags Flags specifying how the receive call is to be made. ++ * ++ * @returns The number of bytes received. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ */ ++ template ++ std::size_t receive_from(const MutableBufferSequence& buffers, ++ endpoint_type& sender_endpoint, socket_base::message_flags flags) ++ { ++ boost::system::error_code ec; ++ std::size_t s = this->impl_.get_service().receive_from( ++ this->impl_.get_implementation(), buffers, sender_endpoint, flags, ec); ++ boost::asio::detail::throw_error(ec, "receive_from"); ++ return s; ++ } ++ ++ /// Receive a datagram with the endpoint of the sender. ++ /** ++ * This function is used to receive a datagram. The function call will block ++ * until data has been received successfully or an error occurs. ++ * ++ * @param buffers One or more buffers into which the data will be received. ++ * ++ * @param sender_endpoint An endpoint object that receives the endpoint of ++ * the remote sender of the datagram. ++ * ++ * @param flags Flags specifying how the receive call is to be made. ++ * ++ * @param ec Set to indicate what error occurred, if any. ++ * ++ * @returns The number of bytes received. ++ */ ++ template ++ std::size_t receive_from(const MutableBufferSequence& buffers, ++ endpoint_type& sender_endpoint, socket_base::message_flags flags, ++ boost::system::error_code& ec) ++ { ++ return this->impl_.get_service().receive_from( ++ this->impl_.get_implementation(), buffers, sender_endpoint, flags, ec); ++ } ++ ++ /// Start an asynchronous receive. ++ /** ++ * This function is used to asynchronously receive a datagram. The function ++ * call always returns immediately. ++ * ++ * @param buffers One or more buffers into which the data will be received. ++ * Although the buffers object may be copied as necessary, ownership of the ++ * underlying memory blocks is retained by the caller, which must guarantee ++ * that they remain valid until the handler is called. ++ * ++ * @param sender_endpoint An endpoint object that receives the endpoint of ++ * the remote sender of the datagram. Ownership of the sender_endpoint object ++ * is retained by the caller, which must guarantee that it is valid until the ++ * handler is called. ++ * ++ * @param handler The handler to be called when the receive operation ++ * completes. Copies will be made of the handler as required. The function ++ * signature of the handler must be: ++ * @code void handler( ++ * const boost::system::error_code& error, // Result of operation. ++ * std::size_t bytes_transferred // Number of bytes received. ++ * ); @endcode ++ * Regardless of whether the asynchronous operation completes immediately or ++ * not, the handler will not be invoked from within this function. On ++ * immediate completion, invocation of the handler will be performed in a ++ * manner equivalent to using boost::asio::post(). ++ * ++ * @par Example ++ * To receive into a single data buffer use the @ref buffer function as ++ * follows: ++ * @code socket.async_receive_from( ++ * boost::asio::buffer(data, size), sender_endpoint, handler); @endcode ++ * See the @ref buffer documentation for information on receiving into ++ * multiple buffers in one go, and how to use it with arrays, boost::array or ++ * std::vector. ++ */ ++ template ++ BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler, ++ void (boost::system::error_code, std::size_t, boost::asio::ip::address)) ++ async_receive_from(const MutableBufferSequence& buffers, ++ endpoint_type& sender_endpoint, ++ BOOST_ASIO_MOVE_ARG(ReadHandler) handler) ++ { ++ return async_initiate( ++ initiate_async_receive_from(), handler, this, buffers, ++ &sender_endpoint, socket_base::message_flags(0)); ++ } ++ ++ /// Start an asynchronous receive. ++ /** ++ * This function is used to asynchronously receive a datagram. The function ++ * call always returns immediately. ++ * ++ * @param buffers One or more buffers into which the data will be received. ++ * Although the buffers object may be copied as necessary, ownership of the ++ * underlying memory blocks is retained by the caller, which must guarantee ++ * that they remain valid until the handler is called. ++ * ++ * @param sender_endpoint An endpoint object that receives the endpoint of ++ * the remote sender of the datagram. Ownership of the sender_endpoint object ++ * is retained by the caller, which must guarantee that it is valid until the ++ * handler is called. ++ * ++ * @param flags Flags specifying how the receive call is to be made. ++ * ++ * @param handler The handler to be called when the receive operation ++ * completes. Copies will be made of the handler as required. The function ++ * signature of the handler must be: ++ * @code void handler( ++ * const boost::system::error_code& error, // Result of operation. ++ * std::size_t bytes_transferred // Number of bytes received. ++ * ); @endcode ++ * Regardless of whether the asynchronous operation completes immediately or ++ * not, the handler will not be invoked from within this function. On ++ * immediate completion, invocation of the handler will be performed in a ++ * manner equivalent to using boost::asio::post(). ++ */ ++ template ++ BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler, ++ void (boost::system::error_code, std::size_t, boost::asio::ip::address)) ++ async_receive_from(const MutableBufferSequence& buffers, ++ endpoint_type& sender_endpoint, socket_base::message_flags flags, ++ BOOST_ASIO_MOVE_ARG(ReadHandler) handler) ++ { ++ return async_initiate( ++ initiate_async_receive_from(), handler, ++ this, buffers, &sender_endpoint, flags); ++ } ++ ++private: ++ struct initiate_async_send ++ { ++ template ++ void operator()(BOOST_ASIO_MOVE_ARG(WriteHandler) handler, ++ basic_datagram_socket_ext* self, const ConstBufferSequence& buffers, ++ socket_base::message_flags flags) const ++ { ++ // If you get an error on the following line it means that your handler ++ // does not meet the documented type requirements for a WriteHandler. ++ BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check; ++ ++ detail::non_const_lvalue handler2(handler); ++ self->impl_.get_service().async_send( ++ self->impl_.get_implementation(), buffers, flags, ++ handler2.value, self->impl_.get_executor()); ++ } ++ }; ++ ++ struct initiate_async_send_to ++ { ++ template ++ void operator()(BOOST_ASIO_MOVE_ARG(WriteHandler) handler, ++ basic_datagram_socket_ext* self, const ConstBufferSequence& buffers, ++ const endpoint_type& destination, ++ socket_base::message_flags flags) const ++ { ++ // If you get an error on the following line it means that your handler ++ // does not meet the documented type requirements for a WriteHandler. ++ BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check; ++ ++ detail::non_const_lvalue handler2(handler); ++ self->impl_.get_service().async_send_to( ++ self->impl_.get_implementation(), buffers, destination, flags, ++ handler2.value, self->impl_.get_executor()); ++ } ++ }; ++ ++ struct initiate_async_receive ++ { ++ template ++ void operator()(BOOST_ASIO_MOVE_ARG(ReadHandler) handler, ++ basic_datagram_socket_ext* self, const MutableBufferSequence& buffers, ++ socket_base::message_flags flags) const ++ { ++ // If you get an error on the following line it means that your handler ++ // does not meet the documented type requirements for a ReadHandler. ++ BOOST_ASIO_READ_HANDLER_CHECK_EXT(ReadHandler, handler) type_check; ++ ++ detail::non_const_lvalue handler2(handler); ++ self->impl_.get_service().async_receive( ++ self->impl_.get_implementation(), buffers, flags, ++ handler2.value, self->impl_.get_executor()); ++ } ++ }; ++ ++ struct initiate_async_receive_from ++ { ++ template ++ void operator()(BOOST_ASIO_MOVE_ARG(ReadHandler) handler, ++ basic_datagram_socket_ext* self, const MutableBufferSequence& buffers, ++ endpoint_type* sender_endpoint, socket_base::message_flags flags) const ++ { ++ // If you get an error on the following line it means that your handler ++ // does not meet the documented type requirements for a ReadHandler. ++ BOOST_ASIO_READ_HANDLER_CHECK_EXT(ReadHandler, handler) type_check; ++ ++ detail::non_const_lvalue handler2(handler); ++ self->impl_.get_service().async_receive_from( ++ self->impl_.get_implementation(), buffers, *sender_endpoint, flags, ++ handler2.value, self->impl_.get_executor()); ++ } ++ }; ++}; ++ ++} // namespace asio ++} // namespace boost ++ ++#include ++ ++#endif // BOOST_ASIO_BASIC_DATAGRAM_SOCKET_EXT_HPP +diff --git a/implementation/helper/1.76/boost/asio/basic_socket_acceptor_ext.hpp b/implementation/helper/1.76/boost/asio/basic_socket_acceptor_ext.hpp +new file mode 100644 +index 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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#if defined(BOOST_ASIO_WINDOWS_RUNTIME) ++# include ++#elif defined(BOOST_ASIO_HAS_IOCP) ++# include ++#else ++# include ++#endif ++ ++#if defined(BOOST_ASIO_HAS_MOVE) ++# include ++#endif // defined(BOOST_ASIO_HAS_MOVE) ++ ++#include ++ ++namespace boost { ++namespace asio { ++ ++#if !defined(BOOST_ASIO_BASIC_SOCKET_ACCEPTOR_EXT_FWD_DECL) ++#define BOOST_ASIO_BASIC_SOCKET_ACCEPTOR_EXT_FWD_DECL ++ ++// Forward declaration with defaulted arguments. ++template ++class basic_socket_acceptor_ext; ++ ++#endif // !defined(BOOST_ASIO_BASIC_SOCKET_ACCEPTOR_EXT_FWD_DECL) ++ ++/// Provides the ability to accept new connections. ++/** ++ * The basic_socket_acceptor_ext class template is used for accepting new socket ++ * connections. ++ * ++ * @par Thread Safety ++ * @e Distinct @e objects: Safe.@n ++ * @e Shared @e objects: Unsafe. ++ * ++ * @par Example ++ * Opening a socket acceptor with the SO_REUSEADDR option enabled: ++ * @code ++ * boost::asio::ip::tcp::acceptor acceptor(my_context); ++ * boost::asio::ip::tcp::endpoint endpoint(boost::asio::ip::tcp::v4(), port); ++ * acceptor.open(endpoint.protocol()); ++ * acceptor.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true)); ++ * acceptor.bind(endpoint); ++ * acceptor.listen(); ++ * @endcode ++ */ ++template ++class basic_socket_acceptor_ext ++ : public socket_base ++{ ++public: ++ /// The type of the executor associated with the object. ++ typedef Executor executor_type; ++ ++ /// The native representation of an acceptor. ++#if defined(GENERATING_DOCUMENTATION) ++ typedef implementation_defined native_handle_type; ++#elif defined(BOOST_ASIO_WINDOWS_RUNTIME) ++ typedef typename detail::null_socket_service< ++ Protocol>::native_handle_type native_handle_type; ++#elif defined(BOOST_ASIO_HAS_IOCP) ++ typedef typename detail::win_iocp_socket_service< ++ Protocol>::native_handle_type native_handle_type; ++#else ++ typedef typename detail::reactive_socket_service_ext_local< ++ Protocol>::native_handle_type native_handle_type; ++#endif ++ ++ /// The protocol type. ++ typedef Protocol protocol_type; ++ ++ /// The endpoint type. ++ typedef typename Protocol::endpoint endpoint_type; ++ ++ /// Construct an acceptor without opening it. ++ /** ++ * This constructor creates an acceptor without opening it to listen for new ++ * connections. The open() function must be called before the acceptor can ++ * accept new socket connections. ++ * ++ * @param ex The I/O executor that the acceptor will use, by default, to ++ * dispatch handlers for any asynchronous operations performed on the ++ * acceptor. ++ */ ++ explicit basic_socket_acceptor_ext(const executor_type& ex) ++ : impl_(0, ex) ++ { ++ } ++ ++ /// Construct an acceptor without opening it. ++ /** ++ * This constructor creates an acceptor without opening it to listen for new ++ * connections. The open() function must be called before the acceptor can ++ * accept new socket connections. ++ * ++ * @param context An execution context which provides the I/O executor that ++ * the acceptor will use, by default, to dispatch handlers for any ++ * asynchronous operations performed on the acceptor. ++ */ ++ template ++ explicit basic_socket_acceptor_ext(ExecutionContext& context, ++ typename enable_if< ++ is_convertible::value ++ >::type* = 0) ++ : impl_(0, 0, context) ++ { ++ } ++ ++ /// Construct an open acceptor. ++ /** ++ * This constructor creates an acceptor and automatically opens it. ++ * ++ * @param ex The I/O executor that the acceptor will use, by default, to ++ * dispatch handlers for any asynchronous operations performed on the ++ * acceptor. ++ * ++ * @param protocol An object specifying protocol parameters to be used. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ */ ++ basic_socket_acceptor_ext(const executor_type& ex, const protocol_type& protocol) ++ : impl_(0, ex) ++ { ++ boost::system::error_code ec; ++ impl_.get_service().open(impl_.get_implementation(), protocol, ec); ++ boost::asio::detail::throw_error(ec, "open"); ++ } ++ ++ /// Construct an open acceptor. ++ /** ++ * This constructor creates an acceptor and automatically opens it. ++ * ++ * @param context An execution context which provides the I/O executor that ++ * the acceptor will use, by default, to dispatch handlers for any ++ * asynchronous operations performed on the acceptor. ++ * ++ * @param protocol An object specifying protocol parameters to be used. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ */ ++ template ++ basic_socket_acceptor_ext(ExecutionContext& context, ++ const protocol_type& protocol, ++ typename enable_if< ++ is_convertible::value ++ >::type* = 0) ++ : impl_(0, 0, context) ++ { ++ boost::system::error_code ec; ++ impl_.get_service().open(impl_.get_implementation(), protocol, ec); ++ boost::asio::detail::throw_error(ec, "open"); ++ } ++ ++ /// Construct an acceptor opened on the given endpoint. ++ /** ++ * This constructor creates an acceptor and automatically opens it to listen ++ * for new connections on the specified endpoint. ++ * ++ * @param ex The I/O executor that the acceptor will use, by default, to ++ * dispatch handlers for any asynchronous operations performed on the ++ * acceptor. ++ * ++ * @param endpoint An endpoint on the local machine on which the acceptor ++ * will listen for new connections. ++ * ++ * @param reuse_addr Whether the constructor should set the socket option ++ * socket_base::reuse_address. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ * ++ * @note This constructor is equivalent to the following code: ++ * @code ++ * basic_socket_acceptor acceptor(my_context); ++ * acceptor.open(endpoint.protocol()); ++ * if (reuse_addr) ++ * acceptor.set_option(socket_base::reuse_address(true)); ++ * acceptor.bind(endpoint); ++ * acceptor.listen(); ++ * @endcode ++ */ ++ basic_socket_acceptor_ext(const executor_type& ex, ++ const endpoint_type& endpoint, bool reuse_addr = true) ++ : impl_(0, ex) ++ { ++ boost::system::error_code ec; ++ const protocol_type protocol = endpoint.protocol(); ++ impl_.get_service().open(impl_.get_implementation(), protocol, ec); ++ boost::asio::detail::throw_error(ec, "open"); ++ if (reuse_addr) ++ { ++ impl_.get_service().set_option(impl_.get_implementation(), ++ socket_base::reuse_address(true), ec); ++ boost::asio::detail::throw_error(ec, "set_option"); ++ } ++ impl_.get_service().bind(impl_.get_implementation(), endpoint, ec); ++ boost::asio::detail::throw_error(ec, "bind"); ++ impl_.get_service().listen(impl_.get_implementation(), ++ socket_base::max_listen_connections, ec); ++ boost::asio::detail::throw_error(ec, "listen"); ++ } ++ ++ /// Construct an acceptor opened on the given endpoint. ++ /** ++ * This constructor creates an acceptor and automatically opens it to listen ++ * for new connections on the specified endpoint. ++ * ++ * @param context An execution context which provides the I/O executor that ++ * the acceptor will use, by default, to dispatch handlers for any ++ * asynchronous operations performed on the acceptor. ++ * ++ * @param endpoint An endpoint on the local machine on which the acceptor ++ * will listen for new connections. ++ * ++ * @param reuse_addr Whether the constructor should set the socket option ++ * socket_base::reuse_address. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ * ++ * @note This constructor is equivalent to the following code: ++ * @code ++ * basic_socket_acceptor acceptor(my_context); ++ * acceptor.open(endpoint.protocol()); ++ * if (reuse_addr) ++ * acceptor.set_option(socket_base::reuse_address(true)); ++ * acceptor.bind(endpoint); ++ * acceptor.listen(); ++ * @endcode ++ */ ++ template ++ basic_socket_acceptor_ext(ExecutionContext& context, ++ const endpoint_type& endpoint, bool reuse_addr = true, ++ typename enable_if< ++ is_convertible::value ++ >::type* = 0) ++ : impl_(0, 0, context) ++ { ++ boost::system::error_code ec; ++ const protocol_type protocol = endpoint.protocol(); ++ impl_.get_service().open(impl_.get_implementation(), protocol, ec); ++ boost::asio::detail::throw_error(ec, "open"); ++ if (reuse_addr) ++ { ++ impl_.get_service().set_option(impl_.get_implementation(), ++ socket_base::reuse_address(true), ec); ++ boost::asio::detail::throw_error(ec, "set_option"); ++ } ++ impl_.get_service().bind(impl_.get_implementation(), endpoint, ec); ++ boost::asio::detail::throw_error(ec, "bind"); ++ impl_.get_service().listen(impl_.get_implementation(), ++ socket_base::max_listen_connections, ec); ++ boost::asio::detail::throw_error(ec, "listen"); ++ } ++ ++ /// Construct a basic_socket_acceptor on an existing native acceptor. ++ /** ++ * This constructor creates an acceptor object to hold an existing native ++ * acceptor. ++ * ++ * @param ex The I/O executor that the acceptor will use, by default, to ++ * dispatch handlers for any asynchronous operations performed on the ++ * acceptor. ++ * ++ * @param protocol An object specifying protocol parameters to be used. ++ * ++ * @param native_acceptor A native acceptor. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ */ ++ basic_socket_acceptor_ext(const executor_type& ex, ++ const protocol_type& protocol, const native_handle_type& native_acceptor) ++ : impl_(0, ex) ++ { ++ boost::system::error_code ec; ++ impl_.get_service().assign(impl_.get_implementation(), ++ protocol, native_acceptor, ec); ++ boost::asio::detail::throw_error(ec, "assign"); ++ } ++ ++ /// Construct a basic_socket_acceptor on an existing native acceptor. ++ /** ++ * This constructor creates an acceptor object to hold an existing native ++ * acceptor. ++ * ++ * @param context An execution context which provides the I/O executor that ++ * the acceptor will use, by default, to dispatch handlers for any ++ * asynchronous operations performed on the acceptor. ++ * ++ * @param protocol An object specifying protocol parameters to be used. ++ * ++ * @param native_acceptor A native acceptor. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ */ ++ template ++ basic_socket_acceptor_ext(ExecutionContext& context, ++ const protocol_type& protocol, const native_handle_type& native_acceptor, ++ typename enable_if< ++ is_convertible::value ++ >::type* = 0) ++ : impl_(0, 0, context) ++ { ++ boost::system::error_code ec; ++ impl_.get_service().assign(impl_.get_implementation(), ++ protocol, native_acceptor, ec); ++ boost::asio::detail::throw_error(ec, "assign"); ++ } ++ ++#if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) ++ /// Move-construct a basic_socket_acceptor from another. ++ /** ++ * This constructor moves an acceptor from one object to another. ++ * ++ * @param other The other basic_socket_acceptor object from which the move ++ * will occur. ++ * ++ * @note Following the move, the moved-from object is in the same state as if ++ * constructed using the @c basic_socket_acceptor(const executor_type&) ++ * constructor. ++ */ ++ basic_socket_acceptor_ext(basic_socket_acceptor_ext&& other) ++ : impl_(std::move(other.impl_)) ++ { ++ } ++ ++ /// Move-assign a basic_socket_acceptor from another. ++ /** ++ * This assignment operator moves an acceptor from one object to another. ++ * ++ * @param other The other basic_socket_acceptor object from which the move ++ * will occur. ++ * ++ * @note Following the move, the moved-from object is in the same state as if ++ * constructed using the @c basic_socket_acceptor(const executor_type&) ++ * constructor. ++ */ ++ basic_socket_acceptor_ext& operator=(basic_socket_acceptor_ext&& other) ++ { ++ impl_ = std::move(other.impl_); ++ return *this; ++ } ++ ++ // All socket acceptors have access to each other's implementations. ++ template ++ friend class basic_socket_acceptor_ext; ++ ++ /// Move-construct a basic_socket_acceptor from an acceptor of another ++ /// protocol type. ++ /** ++ * This constructor moves an acceptor from one object to another. ++ * ++ * @param other The other basic_socket_acceptor object from which the move ++ * will occur. ++ * ++ * @note Following the move, the moved-from object is in the same state as if ++ * constructed using the @c basic_socket_acceptor(const executor_type&) ++ * constructor. ++ */ ++ template ++ basic_socket_acceptor_ext(basic_socket_acceptor_ext&& other, ++ typename enable_if< ++ is_convertible::value ++ && is_convertible::value ++ >::type* = 0) ++ : impl_(std::move(other.impl_)) ++ { ++ } ++ ++ /// Move-assign a basic_socket_acceptor from an acceptor of another protocol ++ /// type. ++ /** ++ * This assignment operator moves an acceptor from one object to another. ++ * ++ * @param other The other basic_socket_acceptor object from which the move ++ * will occur. ++ * ++ * @note Following the move, the moved-from object is in the same state as if ++ * constructed using the @c basic_socket_acceptor(const executor_type&) ++ * constructor. ++ */ ++ template ++ typename enable_if< ++ is_convertible::value ++ && is_convertible::value, ++ basic_socket_acceptor_ext& ++ >::type operator=(basic_socket_acceptor_ext&& other) ++ { ++ basic_socket_acceptor_ext tmp(std::move(other)); ++ impl_ = std::move(tmp.impl_); ++ return *this; ++ } ++#endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) ++ ++ /// Destroys the acceptor. ++ /** ++ * This function destroys the acceptor, cancelling any outstanding ++ * asynchronous operations associated with the acceptor as if by calling ++ * @c cancel. ++ */ ++ ~basic_socket_acceptor_ext() ++ { ++ } ++ ++ /// Get the executor associated with the object. ++ executor_type get_executor() BOOST_ASIO_NOEXCEPT ++ { ++ return impl_.get_executor(); ++ } ++ ++ /// Open the acceptor using the specified protocol. ++ /** ++ * This function opens the socket acceptor so that it will use the specified ++ * protocol. ++ * ++ * @param protocol An object specifying which protocol is to be used. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ * ++ * @par Example ++ * @code ++ * boost::asio::ip::tcp::acceptor acceptor(my_context); ++ * acceptor.open(boost::asio::ip::tcp::v4()); ++ * @endcode ++ */ ++ void open(const protocol_type& protocol = protocol_type()) ++ { ++ boost::system::error_code ec; ++ impl_.get_service().open(impl_.get_implementation(), protocol, ec); ++ boost::asio::detail::throw_error(ec, "open"); ++ } ++ ++ /// Open the acceptor using the specified protocol. ++ /** ++ * This function opens the socket acceptor so that it will use the specified ++ * protocol. ++ * ++ * @param protocol An object specifying which protocol is to be used. ++ * ++ * @param ec Set to indicate what error occurred, if any. ++ * ++ * @par Example ++ * @code ++ * boost::asio::ip::tcp::acceptor acceptor(my_context); ++ * boost::system::error_code ec; ++ * acceptor.open(boost::asio::ip::tcp::v4(), ec); ++ * if (ec) ++ * { ++ * // An error occurred. ++ * } ++ * @endcode ++ */ ++ BOOST_ASIO_SYNC_OP_VOID open(const protocol_type& protocol, ++ boost::system::error_code& ec) ++ { ++ impl_.get_service().open(impl_.get_implementation(), protocol, ec); ++ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); ++ } ++ ++ /// Assigns an existing native acceptor to the acceptor. ++ /* ++ * This function opens the acceptor to hold an existing native acceptor. ++ * ++ * @param protocol An object specifying which protocol is to be used. ++ * ++ * @param native_acceptor A native acceptor. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ */ ++ void assign(const protocol_type& protocol, ++ const native_handle_type& native_acceptor) ++ { ++ boost::system::error_code ec; ++ impl_.get_service().assign(impl_.get_implementation(), ++ protocol, native_acceptor, ec); ++ boost::asio::detail::throw_error(ec, "assign"); ++ } ++ ++ /// Assigns an existing native acceptor to the acceptor. ++ /* ++ * This function opens the acceptor to hold an existing native acceptor. ++ * ++ * @param protocol An object specifying which protocol is to be used. ++ * ++ * @param native_acceptor A native acceptor. ++ * ++ * @param ec Set to indicate what error occurred, if any. ++ */ ++ BOOST_ASIO_SYNC_OP_VOID assign(const protocol_type& protocol, ++ const native_handle_type& native_acceptor, boost::system::error_code& ec) ++ { ++ impl_.get_service().assign(impl_.get_implementation(), ++ protocol, native_acceptor, ec); ++ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); ++ } ++ ++ /// Determine whether the acceptor is open. ++ bool is_open() const ++ { ++ return impl_.get_service().is_open(impl_.get_implementation()); ++ } ++ ++ /// Bind the acceptor to the given local endpoint. ++ /** ++ * This function binds the socket acceptor to the specified endpoint on the ++ * local machine. ++ * ++ * @param endpoint An endpoint on the local machine to which the socket ++ * acceptor will be bound. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ * ++ * @par Example ++ * @code ++ * boost::asio::ip::tcp::acceptor acceptor(my_context); ++ * boost::asio::ip::tcp::endpoint endpoint(boost::asio::ip::tcp::v4(), 12345); ++ * acceptor.open(endpoint.protocol()); ++ * acceptor.bind(endpoint); ++ * @endcode ++ */ ++ void bind(const endpoint_type& endpoint) ++ { ++ boost::system::error_code ec; ++ impl_.get_service().bind(impl_.get_implementation(), endpoint, ec); ++ boost::asio::detail::throw_error(ec, "bind"); ++ } ++ ++ /// Bind the acceptor to the given local endpoint. ++ /** ++ * This function binds the socket acceptor to the specified endpoint on the ++ * local machine. ++ * ++ * @param endpoint An endpoint on the local machine to which the socket ++ * acceptor will be bound. ++ * ++ * @param ec Set to indicate what error occurred, if any. ++ * ++ * @par Example ++ * @code ++ * boost::asio::ip::tcp::acceptor acceptor(my_context); ++ * boost::asio::ip::tcp::endpoint endpoint(boost::asio::ip::tcp::v4(), 12345); ++ * acceptor.open(endpoint.protocol()); ++ * boost::system::error_code ec; ++ * acceptor.bind(endpoint, ec); ++ * if (ec) ++ * { ++ * // An error occurred. ++ * } ++ * @endcode ++ */ ++ BOOST_ASIO_SYNC_OP_VOID bind(const endpoint_type& endpoint, ++ boost::system::error_code& ec) ++ { ++ impl_.get_service().bind(impl_.get_implementation(), endpoint, ec); ++ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); ++ } ++ ++ /// Place the acceptor into the state where it will listen for new ++ /// connections. ++ /** ++ * This function puts the socket acceptor into the state where it may accept ++ * new connections. ++ * ++ * @param backlog The maximum length of the queue of pending connections. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ */ ++ void listen(int backlog = socket_base::max_listen_connections) ++ { ++ boost::system::error_code ec; ++ impl_.get_service().listen(impl_.get_implementation(), backlog, ec); ++ boost::asio::detail::throw_error(ec, "listen"); ++ } ++ ++ /// Place the acceptor into the state where it will listen for new ++ /// connections. ++ /** ++ * This function puts the socket acceptor into the state where it may accept ++ * new connections. ++ * ++ * @param backlog The maximum length of the queue of pending connections. ++ * ++ * @param ec Set to indicate what error occurred, if any. ++ * ++ * @par Example ++ * @code ++ * boost::asio::ip::tcp::acceptor acceptor(my_context); ++ * ... ++ * boost::system::error_code ec; ++ * acceptor.listen(boost::asio::socket_base::max_listen_connections, ec); ++ * if (ec) ++ * { ++ * // An error occurred. ++ * } ++ * @endcode ++ */ ++ BOOST_ASIO_SYNC_OP_VOID listen(int backlog, boost::system::error_code& ec) ++ { ++ impl_.get_service().listen(impl_.get_implementation(), backlog, ec); ++ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); ++ } ++ ++ /// Close the acceptor. ++ /** ++ * This function is used to close the acceptor. Any asynchronous accept ++ * operations will be cancelled immediately. ++ * ++ * A subsequent call to open() is required before the acceptor can again be ++ * used to again perform socket accept operations. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ */ ++ void close() ++ { ++ boost::system::error_code ec; ++ impl_.get_service().close(impl_.get_implementation(), ec); ++ boost::asio::detail::throw_error(ec, "close"); ++ } ++ ++ /// Close the acceptor. ++ /** ++ * This function is used to close the acceptor. Any asynchronous accept ++ * operations will be cancelled immediately. ++ * ++ * A subsequent call to open() is required before the acceptor can again be ++ * used to again perform socket accept operations. ++ * ++ * @param ec Set to indicate what error occurred, if any. ++ * ++ * @par Example ++ * @code ++ * boost::asio::ip::tcp::acceptor acceptor(my_context); ++ * ... ++ * boost::system::error_code ec; ++ * acceptor.close(ec); ++ * if (ec) ++ * { ++ * // An error occurred. ++ * } ++ * @endcode ++ */ ++ BOOST_ASIO_SYNC_OP_VOID close(boost::system::error_code& ec) ++ { ++ impl_.get_service().close(impl_.get_implementation(), ec); ++ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); ++ } ++ ++ /// Release ownership of the underlying native acceptor. ++ /** ++ * This function causes all outstanding asynchronous accept operations to ++ * finish immediately, and the handlers for cancelled operations will be ++ * passed the boost::asio::error::operation_aborted error. Ownership of the ++ * native acceptor is then transferred to the caller. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ * ++ * @note This function is unsupported on Windows versions prior to Windows ++ * 8.1, and will fail with boost::asio::error::operation_not_supported on ++ * these platforms. ++ */ ++#if defined(BOOST_ASIO_MSVC) && (BOOST_ASIO_MSVC >= 1400) \ ++ && (!defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0603) ++ __declspec(deprecated("This function always fails with " ++ "operation_not_supported when used on Windows versions " ++ "prior to Windows 8.1.")) ++#endif ++ native_handle_type release() ++ { ++ boost::system::error_code ec; ++ native_handle_type s = impl_.get_service().release( ++ impl_.get_implementation(), ec); ++ boost::asio::detail::throw_error(ec, "release"); ++ return s; ++ } ++ ++ /// Release ownership of the underlying native acceptor. ++ /** ++ * This function causes all outstanding asynchronous accept operations to ++ * finish immediately, and the handlers for cancelled operations will be ++ * passed the boost::asio::error::operation_aborted error. Ownership of the ++ * native acceptor is then transferred to the caller. ++ * ++ * @param ec Set to indicate what error occurred, if any. ++ * ++ * @note This function is unsupported on Windows versions prior to Windows ++ * 8.1, and will fail with boost::asio::error::operation_not_supported on ++ * these platforms. ++ */ ++#if defined(BOOST_ASIO_MSVC) && (BOOST_ASIO_MSVC >= 1400) \ ++ && (!defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0603) ++ __declspec(deprecated("This function always fails with " ++ "operation_not_supported when used on Windows versions " ++ "prior to Windows 8.1.")) ++#endif ++ native_handle_type release(boost::system::error_code& ec) ++ { ++ return impl_.get_service().release(impl_.get_implementation(), ec); ++ } ++ ++ /// Get the native acceptor representation. ++ /** ++ * This function may be used to obtain the underlying representation of the ++ * acceptor. This is intended to allow access to native acceptor functionality ++ * that is not otherwise provided. ++ */ ++ native_handle_type native_handle() ++ { ++ return impl_.get_service().native_handle(impl_.get_implementation()); ++ } ++ ++ /// Cancel all asynchronous operations associated with the acceptor. ++ /** ++ * This function causes all outstanding asynchronous connect, send and receive ++ * operations to finish immediately, and the handlers for cancelled operations ++ * will be passed the boost::asio::error::operation_aborted error. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ */ ++ void cancel() ++ { ++ boost::system::error_code ec; ++ impl_.get_service().cancel(impl_.get_implementation(), ec); ++ boost::asio::detail::throw_error(ec, "cancel"); ++ } ++ ++ /// Cancel all asynchronous operations associated with the acceptor. ++ /** ++ * This function causes all outstanding asynchronous connect, send and receive ++ * operations to finish immediately, and the handlers for cancelled operations ++ * will be passed the boost::asio::error::operation_aborted error. ++ * ++ * @param ec Set to indicate what error occurred, if any. ++ */ ++ BOOST_ASIO_SYNC_OP_VOID cancel(boost::system::error_code& ec) ++ { ++ impl_.get_service().cancel(impl_.get_implementation(), ec); ++ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); ++ } ++ ++ /// Set an option on the acceptor. ++ /** ++ * This function is used to set an option on the acceptor. ++ * ++ * @param option The new option value to be set on the acceptor. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ * ++ * @sa SettableSocketOption @n ++ * boost::asio::socket_base::reuse_address ++ * boost::asio::socket_base::enable_connection_aborted ++ * ++ * @par Example ++ * Setting the SOL_SOCKET/SO_REUSEADDR option: ++ * @code ++ * boost::asio::ip::tcp::acceptor acceptor(my_context); ++ * ... ++ * boost::asio::ip::tcp::acceptor::reuse_address option(true); ++ * acceptor.set_option(option); ++ * @endcode ++ */ ++ template ++ void set_option(const SettableSocketOption& option) ++ { ++ boost::system::error_code ec; ++ impl_.get_service().set_option(impl_.get_implementation(), option, ec); ++ boost::asio::detail::throw_error(ec, "set_option"); ++ } ++ ++ /// Set an option on the acceptor. ++ /** ++ * This function is used to set an option on the acceptor. ++ * ++ * @param option The new option value to be set on the acceptor. ++ * ++ * @param ec Set to indicate what error occurred, if any. ++ * ++ * @sa SettableSocketOption @n ++ * boost::asio::socket_base::reuse_address ++ * boost::asio::socket_base::enable_connection_aborted ++ * ++ * @par Example ++ * Setting the SOL_SOCKET/SO_REUSEADDR option: ++ * @code ++ * boost::asio::ip::tcp::acceptor acceptor(my_context); ++ * ... ++ * boost::asio::ip::tcp::acceptor::reuse_address option(true); ++ * boost::system::error_code ec; ++ * acceptor.set_option(option, ec); ++ * if (ec) ++ * { ++ * // An error occurred. ++ * } ++ * @endcode ++ */ ++ template ++ BOOST_ASIO_SYNC_OP_VOID set_option(const SettableSocketOption& option, ++ boost::system::error_code& ec) ++ { ++ impl_.get_service().set_option(impl_.get_implementation(), option, ec); ++ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); ++ } ++ ++ /// Get an option from the acceptor. ++ /** ++ * This function is used to get the current value of an option on the ++ * acceptor. ++ * ++ * @param option The option value to be obtained from the acceptor. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ * ++ * @sa GettableSocketOption @n ++ * boost::asio::socket_base::reuse_address ++ * ++ * @par Example ++ * Getting the value of the SOL_SOCKET/SO_REUSEADDR option: ++ * @code ++ * boost::asio::ip::tcp::acceptor acceptor(my_context); ++ * ... ++ * boost::asio::ip::tcp::acceptor::reuse_address option; ++ * acceptor.get_option(option); ++ * bool is_set = option.get(); ++ * @endcode ++ */ ++ template ++ void get_option(GettableSocketOption& option) const ++ { ++ boost::system::error_code ec; ++ impl_.get_service().get_option(impl_.get_implementation(), option, ec); ++ boost::asio::detail::throw_error(ec, "get_option"); ++ } ++ ++ /// Get an option from the acceptor. ++ /** ++ * This function is used to get the current value of an option on the ++ * acceptor. ++ * ++ * @param option The option value to be obtained from the acceptor. ++ * ++ * @param ec Set to indicate what error occurred, if any. ++ * ++ * @sa GettableSocketOption @n ++ * boost::asio::socket_base::reuse_address ++ * ++ * @par Example ++ * Getting the value of the SOL_SOCKET/SO_REUSEADDR option: ++ * @code ++ * boost::asio::ip::tcp::acceptor acceptor(my_context); ++ * ... ++ * boost::asio::ip::tcp::acceptor::reuse_address option; ++ * boost::system::error_code ec; ++ * acceptor.get_option(option, ec); ++ * if (ec) ++ * { ++ * // An error occurred. ++ * } ++ * bool is_set = option.get(); ++ * @endcode ++ */ ++ template ++ BOOST_ASIO_SYNC_OP_VOID get_option(GettableSocketOption& option, ++ boost::system::error_code& ec) const ++ { ++ impl_.get_service().get_option(impl_.get_implementation(), option, ec); ++ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); ++ } ++ ++ /// Perform an IO control command on the acceptor. ++ /** ++ * This function is used to execute an IO control command on the acceptor. ++ * ++ * @param command The IO control command to be performed on the acceptor. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ * ++ * @sa IoControlCommand @n ++ * boost::asio::socket_base::non_blocking_io ++ * ++ * @par Example ++ * Getting the number of bytes ready to read: ++ * @code ++ * boost::asio::ip::tcp::acceptor acceptor(my_context); ++ * ... ++ * boost::asio::ip::tcp::acceptor::non_blocking_io command(true); ++ * socket.io_control(command); ++ * @endcode ++ */ ++ template ++ void io_control(IoControlCommand& command) ++ { ++ boost::system::error_code ec; ++ impl_.get_service().io_control(impl_.get_implementation(), command, ec); ++ boost::asio::detail::throw_error(ec, "io_control"); ++ } ++ ++ /// Perform an IO control command on the acceptor. ++ /** ++ * This function is used to execute an IO control command on the acceptor. ++ * ++ * @param command The IO control command to be performed on the acceptor. ++ * ++ * @param ec Set to indicate what error occurred, if any. ++ * ++ * @sa IoControlCommand @n ++ * boost::asio::socket_base::non_blocking_io ++ * ++ * @par Example ++ * Getting the number of bytes ready to read: ++ * @code ++ * boost::asio::ip::tcp::acceptor acceptor(my_context); ++ * ... ++ * boost::asio::ip::tcp::acceptor::non_blocking_io command(true); ++ * boost::system::error_code ec; ++ * socket.io_control(command, ec); ++ * if (ec) ++ * { ++ * // An error occurred. ++ * } ++ * @endcode ++ */ ++ template ++ BOOST_ASIO_SYNC_OP_VOID io_control(IoControlCommand& command, ++ boost::system::error_code& ec) ++ { ++ impl_.get_service().io_control(impl_.get_implementation(), command, ec); ++ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); ++ } ++ ++ /// Gets the non-blocking mode of the acceptor. ++ /** ++ * @returns @c true if the acceptor's synchronous operations will fail with ++ * boost::asio::error::would_block if they are unable to perform the requested ++ * operation immediately. If @c false, synchronous operations will block ++ * until complete. ++ * ++ * @note The non-blocking mode has no effect on the behaviour of asynchronous ++ * operations. Asynchronous operations will never fail with the error ++ * boost::asio::error::would_block. ++ */ ++ bool non_blocking() const ++ { ++ return impl_.get_service().non_blocking(impl_.get_implementation()); ++ } ++ ++ /// Sets the non-blocking mode of the acceptor. ++ /** ++ * @param mode If @c true, the acceptor's synchronous operations will fail ++ * with boost::asio::error::would_block if they are unable to perform the ++ * requested operation immediately. If @c false, synchronous operations will ++ * block until complete. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ * ++ * @note The non-blocking mode has no effect on the behaviour of asynchronous ++ * operations. Asynchronous operations will never fail with the error ++ * boost::asio::error::would_block. ++ */ ++ void non_blocking(bool mode) ++ { ++ boost::system::error_code ec; ++ impl_.get_service().non_blocking(impl_.get_implementation(), mode, ec); ++ boost::asio::detail::throw_error(ec, "non_blocking"); ++ } ++ ++ /// Sets the non-blocking mode of the acceptor. ++ /** ++ * @param mode If @c true, the acceptor's synchronous operations will fail ++ * with boost::asio::error::would_block if they are unable to perform the ++ * requested operation immediately. If @c false, synchronous operations will ++ * block until complete. ++ * ++ * @param ec Set to indicate what error occurred, if any. ++ * ++ * @note The non-blocking mode has no effect on the behaviour of asynchronous ++ * operations. Asynchronous operations will never fail with the error ++ * boost::asio::error::would_block. ++ */ ++ BOOST_ASIO_SYNC_OP_VOID non_blocking( ++ bool mode, boost::system::error_code& ec) ++ { ++ impl_.get_service().non_blocking(impl_.get_implementation(), mode, ec); ++ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); ++ } ++ ++ /// Gets the non-blocking mode of the native acceptor implementation. ++ /** ++ * This function is used to retrieve the non-blocking mode of the underlying ++ * native acceptor. This mode has no effect on the behaviour of the acceptor ++ * object's synchronous operations. ++ * ++ * @returns @c true if the underlying acceptor is in non-blocking mode and ++ * direct system calls may fail with boost::asio::error::would_block (or the ++ * equivalent system error). ++ * ++ * @note The current non-blocking mode is cached by the acceptor object. ++ * Consequently, the return value may be incorrect if the non-blocking mode ++ * was set directly on the native acceptor. ++ */ ++ bool native_non_blocking() const ++ { ++ return impl_.get_service().native_non_blocking(impl_.get_implementation()); ++ } ++ ++ /// Sets the non-blocking mode of the native acceptor implementation. ++ /** ++ * This function is used to modify the non-blocking mode of the underlying ++ * native acceptor. It has no effect on the behaviour of the acceptor object's ++ * synchronous operations. ++ * ++ * @param mode If @c true, the underlying acceptor is put into non-blocking ++ * mode and direct system calls may fail with boost::asio::error::would_block ++ * (or the equivalent system error). ++ * ++ * @throws boost::system::system_error Thrown on failure. If the @c mode is ++ * @c false, but the current value of @c non_blocking() is @c true, this ++ * function fails with boost::asio::error::invalid_argument, as the ++ * combination does not make sense. ++ */ ++ void native_non_blocking(bool mode) ++ { ++ boost::system::error_code ec; ++ impl_.get_service().native_non_blocking( ++ impl_.get_implementation(), mode, ec); ++ boost::asio::detail::throw_error(ec, "native_non_blocking"); ++ } ++ ++ /// Sets the non-blocking mode of the native acceptor implementation. ++ /** ++ * This function is used to modify the non-blocking mode of the underlying ++ * native acceptor. It has no effect on the behaviour of the acceptor object's ++ * synchronous operations. ++ * ++ * @param mode If @c true, the underlying acceptor is put into non-blocking ++ * mode and direct system calls may fail with boost::asio::error::would_block ++ * (or the equivalent system error). ++ * ++ * @param ec Set to indicate what error occurred, if any. If the @c mode is ++ * @c false, but the current value of @c non_blocking() is @c true, this ++ * function fails with boost::asio::error::invalid_argument, as the ++ * combination does not make sense. ++ */ ++ BOOST_ASIO_SYNC_OP_VOID native_non_blocking( ++ bool mode, boost::system::error_code& ec) ++ { ++ impl_.get_service().native_non_blocking( ++ impl_.get_implementation(), mode, ec); ++ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); ++ } ++ ++ /// Get the local endpoint of the acceptor. ++ /** ++ * This function is used to obtain the locally bound endpoint of the acceptor. ++ * ++ * @returns An object that represents the local endpoint of the acceptor. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ * ++ * @par Example ++ * @code ++ * boost::asio::ip::tcp::acceptor acceptor(my_context); ++ * ... ++ * boost::asio::ip::tcp::endpoint endpoint = acceptor.local_endpoint(); ++ * @endcode ++ */ ++ endpoint_type local_endpoint() const ++ { ++ boost::system::error_code ec; ++ endpoint_type ep = impl_.get_service().local_endpoint( ++ impl_.get_implementation(), ec); ++ boost::asio::detail::throw_error(ec, "local_endpoint"); ++ return ep; ++ } ++ ++ /// Get the local endpoint of the acceptor. ++ /** ++ * This function is used to obtain the locally bound endpoint of the acceptor. ++ * ++ * @param ec Set to indicate what error occurred, if any. ++ * ++ * @returns An object that represents the local endpoint of the acceptor. ++ * Returns a default-constructed endpoint object if an error occurred and the ++ * error handler did not throw an exception. ++ * ++ * @par Example ++ * @code ++ * boost::asio::ip::tcp::acceptor acceptor(my_context); ++ * ... ++ * boost::system::error_code ec; ++ * boost::asio::ip::tcp::endpoint endpoint = acceptor.local_endpoint(ec); ++ * if (ec) ++ * { ++ * // An error occurred. ++ * } ++ * @endcode ++ */ ++ endpoint_type local_endpoint(boost::system::error_code& ec) const ++ { ++ return impl_.get_service().local_endpoint(impl_.get_implementation(), ec); ++ } ++ ++ /// Wait for the acceptor to become ready to read, ready to write, or to have ++ /// pending error conditions. ++ /** ++ * This function is used to perform a blocking wait for an acceptor to enter ++ * a ready to read, write or error condition state. ++ * ++ * @param w Specifies the desired acceptor state. ++ * ++ * @par Example ++ * Waiting for an acceptor to become readable. ++ * @code ++ * boost::asio::ip::tcp::acceptor acceptor(my_context); ++ * ... ++ * acceptor.wait(boost::asio::ip::tcp::acceptor::wait_read); ++ * @endcode ++ */ ++ void wait(wait_type w) ++ { ++ boost::system::error_code ec; ++ impl_.get_service().wait(impl_.get_implementation(), w, ec); ++ boost::asio::detail::throw_error(ec, "wait"); ++ } ++ ++ /// Wait for the acceptor to become ready to read, ready to write, or to have ++ /// pending error conditions. ++ /** ++ * This function is used to perform a blocking wait for an acceptor to enter ++ * a ready to read, write or error condition state. ++ * ++ * @param w Specifies the desired acceptor state. ++ * ++ * @param ec Set to indicate what error occurred, if any. ++ * ++ * @par Example ++ * Waiting for an acceptor to become readable. ++ * @code ++ * boost::asio::ip::tcp::acceptor acceptor(my_context); ++ * ... ++ * boost::system::error_code ec; ++ * acceptor.wait(boost::asio::ip::tcp::acceptor::wait_read, ec); ++ * @endcode ++ */ ++ BOOST_ASIO_SYNC_OP_VOID wait(wait_type w, boost::system::error_code& ec) ++ { ++ impl_.get_service().wait(impl_.get_implementation(), w, ec); ++ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); ++ } ++ ++ /// Asynchronously wait for the acceptor to become ready to read, ready to ++ /// write, or to have pending error conditions. ++ /** ++ * This function is used to perform an asynchronous wait for an acceptor to ++ * enter a ready to read, write or error condition state. ++ * ++ * @param w Specifies the desired acceptor state. ++ * ++ * @param handler The handler to be called when the wait operation completes. ++ * Copies will be made of the handler as required. The function signature of ++ * the handler must be: ++ * @code void handler( ++ * const boost::system::error_code& error // Result of operation ++ * ); @endcode ++ * Regardless of whether the asynchronous operation completes immediately or ++ * not, the handler will not be invoked from within this function. On ++ * immediate completion, invocation of the handler will be performed in a ++ * manner equivalent to using boost::asio::post(). ++ * ++ * @par Example ++ * @code ++ * void wait_handler(const boost::system::error_code& error) ++ * { ++ * if (!error) ++ * { ++ * // Wait succeeded. ++ * } ++ * } ++ * ++ * ... ++ * ++ * boost::asio::ip::tcp::acceptor acceptor(my_context); ++ * ... ++ * acceptor.async_wait( ++ * boost::asio::ip::tcp::acceptor::wait_read, ++ * wait_handler); ++ * @endcode ++ */ ++ template ++ BOOST_ASIO_INITFN_RESULT_TYPE(WaitHandler, ++ void (boost::system::error_code)) ++ async_wait(wait_type w, BOOST_ASIO_MOVE_ARG(WaitHandler) handler) ++ { ++ return async_initiate( ++ initiate_async_wait(), handler, this, w); ++ } ++ ++#if !defined(BOOST_ASIO_NO_EXTENSIONS) ++ /// Accept a new connection. ++ /** ++ * This function is used to accept a new connection from a peer into the ++ * given socket. The function call will block until a new connection has been ++ * accepted successfully or an error occurs. ++ * ++ * @param peer The socket into which the new connection will be accepted. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ * ++ * @par Example ++ * @code ++ * boost::asio::ip::tcp::acceptor acceptor(my_context); ++ * ... ++ * boost::asio::ip::tcp::socket socket(my_context); ++ * acceptor.accept(socket); ++ * @endcode ++ */ ++ template ++ void accept(basic_socket_ext_local& peer, ++ typename enable_if< ++ is_convertible::value ++ >::type* = 0) ++ { ++ boost::system::error_code ec; ++ impl_.get_service().accept(impl_.get_implementation(), ++ peer, static_cast(0), ec); ++ boost::asio::detail::throw_error(ec, "accept"); ++ } ++ ++ /// Accept a new connection. ++ /** ++ * This function is used to accept a new connection from a peer into the ++ * given socket. The function call will block until a new connection has been ++ * accepted successfully or an error occurs. ++ * ++ * @param peer The socket into which the new connection will be accepted. ++ * ++ * @param ec Set to indicate what error occurred, if any. ++ * ++ * @par Example ++ * @code ++ * boost::asio::ip::tcp::acceptor acceptor(my_context); ++ * ... ++ * boost::asio::ip::tcp::socket socket(my_context); ++ * boost::system::error_code ec; ++ * acceptor.accept(socket, ec); ++ * if (ec) ++ * { ++ * // An error occurred. ++ * } ++ * @endcode ++ */ ++ template ++ BOOST_ASIO_SYNC_OP_VOID accept( ++ basic_socket_ext_local& peer, boost::system::error_code& ec, ++ typename enable_if< ++ is_convertible::value ++ >::type* = 0) ++ { ++ impl_.get_service().accept(impl_.get_implementation(), ++ peer, static_cast(0), ec); ++ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); ++ } ++ ++ /// Start an asynchronous accept. ++ /** ++ * This function is used to asynchronously accept a new connection into a ++ * socket. The function call always returns immediately. ++ * ++ * @param peer The socket into which the new connection will be accepted. ++ * Ownership of the peer object is retained by the caller, which must ++ * guarantee that it is valid until the handler is called. ++ * ++ * @param handler The handler to be called when the accept operation ++ * completes. Copies will be made of the handler as required. The function ++ * signature of the handler must be: ++ * @code void handler( ++ * const boost::system::error_code& error // Result of operation. ++ * ); @endcode ++ * Regardless of whether the asynchronous operation completes immediately or ++ * not, the handler will not be invoked from within this function. On ++ * immediate completion, invocation of the handler will be performed in a ++ * manner equivalent to using boost::asio::post(). ++ * ++ * @par Example ++ * @code ++ * void accept_handler(const boost::system::error_code& error) ++ * { ++ * if (!error) ++ * { ++ * // Accept succeeded. ++ * } ++ * } ++ * ++ * ... ++ * ++ * boost::asio::ip::tcp::acceptor acceptor(my_context); ++ * ... ++ * boost::asio::ip::tcp::socket socket(my_context); ++ * acceptor.async_accept(socket, accept_handler); ++ * @endcode ++ */ ++ template ++ BOOST_ASIO_INITFN_RESULT_TYPE(AcceptHandler, ++ void (boost::system::error_code)) ++ async_accept(basic_socket_ext_local& peer, ++ BOOST_ASIO_MOVE_ARG(AcceptHandler) handler, ++ typename enable_if< ++ is_convertible::value ++ >::type* = 0) ++ { ++ return async_initiate( ++ initiate_async_accept(), handler, this, ++ &peer, static_cast(0)); ++ } ++ ++ /// Accept a new connection and obtain the endpoint of the peer ++ /** ++ * This function is used to accept a new connection from a peer into the ++ * given socket, and additionally provide the endpoint of the remote peer. ++ * The function call will block until a new connection has been accepted ++ * successfully or an error occurs. ++ * ++ * @param peer The socket into which the new connection will be accepted. ++ * ++ * @param peer_endpoint An endpoint object which will receive the endpoint of ++ * the remote peer. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ * ++ * @par Example ++ * @code ++ * boost::asio::ip::tcp::acceptor acceptor(my_context); ++ * ... ++ * boost::asio::ip::tcp::socket socket(my_context); ++ * boost::asio::ip::tcp::endpoint endpoint; ++ * acceptor.accept(socket, endpoint); ++ * @endcode ++ */ ++ template ++ void accept(basic_socket_ext_local& peer, ++ endpoint_type& peer_endpoint) ++ { ++ boost::system::error_code ec; ++ impl_.get_service().accept(impl_.get_implementation(), ++ peer, &peer_endpoint, ec); ++ boost::asio::detail::throw_error(ec, "accept"); ++ } ++ ++ /// Accept a new connection and obtain the endpoint of the peer ++ /** ++ * This function is used to accept a new connection from a peer into the ++ * given socket, and additionally provide the endpoint of the remote peer. ++ * The function call will block until a new connection has been accepted ++ * successfully or an error occurs. ++ * ++ * @param peer The socket into which the new connection will be accepted. ++ * ++ * @param peer_endpoint An endpoint object which will receive the endpoint of ++ * the remote peer. ++ * ++ * @param ec Set to indicate what error occurred, if any. ++ * ++ * @par Example ++ * @code ++ * boost::asio::ip::tcp::acceptor acceptor(my_context); ++ * ... ++ * boost::asio::ip::tcp::socket socket(my_context); ++ * boost::asio::ip::tcp::endpoint endpoint; ++ * boost::system::error_code ec; ++ * acceptor.accept(socket, endpoint, ec); ++ * if (ec) ++ * { ++ * // An error occurred. ++ * } ++ * @endcode ++ */ ++ template ++ BOOST_ASIO_SYNC_OP_VOID accept(basic_socket_ext_local& peer, ++ endpoint_type& peer_endpoint, boost::system::error_code& ec) ++ { ++ impl_.get_service().accept( ++ impl_.get_implementation(), peer, &peer_endpoint, ec); ++ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); ++ } ++ ++ /// Start an asynchronous accept. ++ /** ++ * This function is used to asynchronously accept a new connection into a ++ * socket, and additionally obtain the endpoint of the remote peer. The ++ * function call always returns immediately. ++ * ++ * @param peer The socket into which the new connection will be accepted. ++ * Ownership of the peer object is retained by the caller, which must ++ * guarantee that it is valid until the handler is called. ++ * ++ * @param peer_endpoint An endpoint object into which the endpoint of the ++ * remote peer will be written. Ownership of the peer_endpoint object is ++ * retained by the caller, which must guarantee that it is valid until the ++ * handler is called. ++ * ++ * @param handler The handler to be called when the accept operation ++ * completes. Copies will be made of the handler as required. The function ++ * signature of the handler must be: ++ * @code void handler( ++ * const boost::system::error_code& error // Result of operation. ++ * ); @endcode ++ * Regardless of whether the asynchronous operation completes immediately or ++ * not, the handler will not be invoked from within this function. On ++ * immediate completion, invocation of the handler will be performed in a ++ * manner equivalent to using boost::asio::post(). ++ */ ++ template ++ BOOST_ASIO_INITFN_RESULT_TYPE(AcceptHandler, ++ void (boost::system::error_code)) ++ async_accept(basic_socket_ext_local& peer, ++ endpoint_type& peer_endpoint, BOOST_ASIO_MOVE_ARG(AcceptHandler) handler) ++ { ++ return async_initiate( ++ initiate_async_accept(), handler, this, &peer, &peer_endpoint); ++ } ++#endif // !defined(BOOST_ASIO_NO_EXTENSIONS) ++ ++#if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) ++ /// Accept a new connection. ++ /** ++ * This function is used to accept a new connection from a peer. The function ++ * call will block until a new connection has been accepted successfully or ++ * an error occurs. ++ * ++ * This overload requires that the Protocol template parameter satisfy the ++ * AcceptableProtocol type requirements. ++ * ++ * @returns A socket object representing the newly accepted connection. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ * ++ * @par Example ++ * @code ++ * boost::asio::ip::tcp::acceptor acceptor(my_context); ++ * ... ++ * boost::asio::ip::tcp::socket socket(acceptor.accept()); ++ * @endcode ++ */ ++ typename Protocol::socket accept() ++ { ++ boost::system::error_code ec; ++ typename Protocol::socket peer(impl_.get_executor()); ++ impl_.get_service().accept(impl_.get_implementation(), peer, 0, ec); ++ boost::asio::detail::throw_error(ec, "accept"); ++ return peer; ++ } ++ ++ /// Accept a new connection. ++ /** ++ * This function is used to accept a new connection from a peer. The function ++ * call will block until a new connection has been accepted successfully or ++ * an error occurs. ++ * ++ * This overload requires that the Protocol template parameter satisfy the ++ * AcceptableProtocol type requirements. ++ * ++ * @param ec Set to indicate what error occurred, if any. ++ * ++ * @returns On success, a socket object representing the newly accepted ++ * connection. On error, a socket object where is_open() is false. ++ * ++ * @par Example ++ * @code ++ * boost::asio::ip::tcp::acceptor acceptor(my_context); ++ * ... ++ * boost::asio::ip::tcp::socket socket(acceptor.accept(ec)); ++ * if (ec) ++ * { ++ * // An error occurred. ++ * } ++ * @endcode ++ */ ++ typename Protocol::socket accept(boost::system::error_code& ec) ++ { ++ typename Protocol::socket peer(impl_.get_executor()); ++ impl_.get_service().accept(impl_.get_implementation(), peer, 0, ec); ++ return peer; ++ } ++ ++ /// Start an asynchronous accept. ++ /** ++ * This function is used to asynchronously accept a new connection. The ++ * function call always returns immediately. ++ * ++ * This overload requires that the Protocol template parameter satisfy the ++ * AcceptableProtocol type requirements. ++ * ++ * @param handler The handler to be called when the accept operation ++ * completes. Copies will be made of the handler as required. The function ++ * signature of the handler must be: ++ * @code void handler( ++ * const boost::system::error_code& error, // Result of operation. ++ * typename Protocol::socket peer // On success, the newly accepted socket. ++ * ); @endcode ++ * Regardless of whether the asynchronous operation completes immediately or ++ * not, the handler will not be invoked from within this function. On ++ * immediate completion, invocation of the handler will be performed in a ++ * manner equivalent to using boost::asio::post(). ++ * ++ * @par Example ++ * @code ++ * void accept_handler(const boost::system::error_code& error, ++ * boost::asio::ip::tcp::socket peer) ++ * { ++ * if (!error) ++ * { ++ * // Accept succeeded. ++ * } ++ * } ++ * ++ * ... ++ * ++ * boost::asio::ip::tcp::acceptor acceptor(my_context); ++ * ... ++ * acceptor.async_accept(accept_handler); ++ * @endcode ++ */ ++ template ++ BOOST_ASIO_INITFN_RESULT_TYPE(MoveAcceptHandler, ++ void (boost::system::error_code, typename Protocol::socket)) ++ async_accept(BOOST_ASIO_MOVE_ARG(MoveAcceptHandler) handler) ++ { ++ return async_initiate( ++ initiate_async_move_accept(), handler, this, ++ impl_.get_executor(), static_cast(0), ++ static_cast(0)); ++ } ++ ++ /// Accept a new connection. ++ /** ++ * This function is used to accept a new connection from a peer. The function ++ * call will block until a new connection has been accepted successfully or ++ * an error occurs. ++ * ++ * This overload requires that the Protocol template parameter satisfy the ++ * AcceptableProtocol type requirements. ++ * ++ * @param ex The I/O executor object to be used for the newly ++ * accepted socket. ++ * ++ * @returns A socket object representing the newly accepted connection. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ * ++ * @par Example ++ * @code ++ * boost::asio::ip::tcp::acceptor acceptor(my_context); ++ * ... ++ * boost::asio::ip::tcp::socket socket(acceptor.accept()); ++ * @endcode ++ */ ++ template ++ typename Protocol::socket::template rebind_executor::other ++ accept(const Executor1& ex, ++ typename enable_if< ++ is_executor::value ++ >::type* = 0) ++ { ++ boost::system::error_code ec; ++ typename Protocol::socket::template ++ rebind_executor::other peer(ex); ++ impl_.get_service().accept(impl_.get_implementation(), peer, 0, ec); ++ boost::asio::detail::throw_error(ec, "accept"); ++ return peer; ++ } ++ ++ /// Accept a new connection. ++ /** ++ * This function is used to accept a new connection from a peer. The function ++ * call will block until a new connection has been accepted successfully or ++ * an error occurs. ++ * ++ * This overload requires that the Protocol template parameter satisfy the ++ * AcceptableProtocol type requirements. ++ * ++ * @param context The I/O execution context object to be used for the newly ++ * accepted socket. ++ * ++ * @returns A socket object representing the newly accepted connection. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ * ++ * @par Example ++ * @code ++ * boost::asio::ip::tcp::acceptor acceptor(my_context); ++ * ... ++ * boost::asio::ip::tcp::socket socket(acceptor.accept()); ++ * @endcode ++ */ ++ template ++ typename Protocol::socket::template rebind_executor< ++ typename ExecutionContext::executor_type>::other ++ accept(ExecutionContext& context, ++ typename enable_if< ++ is_convertible::value ++ >::type* = 0) ++ { ++ boost::system::error_code ec; ++ typename Protocol::socket::template rebind_executor< ++ typename ExecutionContext::executor_type>::other peer(context); ++ impl_.get_service().accept(impl_.get_implementation(), peer, 0, ec); ++ boost::asio::detail::throw_error(ec, "accept"); ++ return peer; ++ } ++ ++ /// Accept a new connection. ++ /** ++ * This function is used to accept a new connection from a peer. The function ++ * call will block until a new connection has been accepted successfully or ++ * an error occurs. ++ * ++ * This overload requires that the Protocol template parameter satisfy the ++ * AcceptableProtocol type requirements. ++ * ++ * @param ex The I/O executor object to be used for the newly accepted ++ * socket. ++ * ++ * @param ec Set to indicate what error occurred, if any. ++ * ++ * @returns On success, a socket object representing the newly accepted ++ * connection. On error, a socket object where is_open() is false. ++ * ++ * @par Example ++ * @code ++ * boost::asio::ip::tcp::acceptor acceptor(my_context); ++ * ... ++ * boost::asio::ip::tcp::socket socket(acceptor.accept(my_context2, ec)); ++ * if (ec) ++ * { ++ * // An error occurred. ++ * } ++ * @endcode ++ */ ++ template ++ typename Protocol::socket::template rebind_executor::other ++ accept(const Executor1& ex, boost::system::error_code& ec, ++ typename enable_if< ++ is_executor::value ++ >::type* = 0) ++ { ++ typename Protocol::socket::template ++ rebind_executor::other peer(ex); ++ impl_.get_service().accept(impl_.get_implementation(), peer, 0, ec); ++ return peer; ++ } ++ ++ /// Accept a new connection. ++ /** ++ * This function is used to accept a new connection from a peer. The function ++ * call will block until a new connection has been accepted successfully or ++ * an error occurs. ++ * ++ * This overload requires that the Protocol template parameter satisfy the ++ * AcceptableProtocol type requirements. ++ * ++ * @param context The I/O execution context object to be used for the newly ++ * accepted socket. ++ * ++ * @param ec Set to indicate what error occurred, if any. ++ * ++ * @returns On success, a socket object representing the newly accepted ++ * connection. On error, a socket object where is_open() is false. ++ * ++ * @par Example ++ * @code ++ * boost::asio::ip::tcp::acceptor acceptor(my_context); ++ * ... ++ * boost::asio::ip::tcp::socket socket(acceptor.accept(my_context2, ec)); ++ * if (ec) ++ * { ++ * // An error occurred. ++ * } ++ * @endcode ++ */ ++ template ++ typename Protocol::socket::template rebind_executor< ++ typename ExecutionContext::executor_type>::other ++ accept(ExecutionContext& context, boost::system::error_code& ec, ++ typename enable_if< ++ is_convertible::value ++ >::type* = 0) ++ { ++ typename Protocol::socket::template rebind_executor< ++ typename ExecutionContext::executor_type>::other peer(context); ++ impl_.get_service().accept(impl_.get_implementation(), peer, 0, ec); ++ return peer; ++ } ++ ++ /// Start an asynchronous accept. ++ /** ++ * This function is used to asynchronously accept a new connection. The ++ * function call always returns immediately. ++ * ++ * This overload requires that the Protocol template parameter satisfy the ++ * AcceptableProtocol type requirements. ++ * ++ * @param ex The I/O executor object to be used for the newly accepted ++ * socket. ++ * ++ * @param handler The handler to be called when the accept operation ++ * completes. Copies will be made of the handler as required. The function ++ * signature of the handler must be: ++ * @code void handler( ++ * const boost::system::error_code& error, // Result of operation. ++ * typename Protocol::socket::template rebind_executor< ++ * Executor1>::other peer // On success, the newly accepted socket. ++ * ); @endcode ++ * Regardless of whether the asynchronous operation completes immediately or ++ * not, the handler will not be invoked from within this function. On ++ * immediate completion, invocation of the handler will be performed in a ++ * manner equivalent to using boost::asio::post(). ++ * ++ * @par Example ++ * @code ++ * void accept_handler(const boost::system::error_code& error, ++ * boost::asio::ip::tcp::socket peer) ++ * { ++ * if (!error) ++ * { ++ * // Accept succeeded. ++ * } ++ * } ++ * ++ * ... ++ * ++ * boost::asio::ip::tcp::acceptor acceptor(my_context); ++ * ... ++ * acceptor.async_accept(my_context2, accept_handler); ++ * @endcode ++ */ ++ template ++ BOOST_ASIO_INITFN_RESULT_TYPE(MoveAcceptHandler, ++ void (boost::system::error_code, ++ typename Protocol::socket::template rebind_executor< ++ Executor1>::other)) ++ async_accept(const Executor1& ex, ++ BOOST_ASIO_MOVE_ARG(MoveAcceptHandler) handler, ++ typename enable_if< ++ is_executor::value ++ >::type* = 0) ++ { ++ typedef typename Protocol::socket::template rebind_executor< ++ Executor1>::other other_socket_type; ++ ++ return async_initiate( ++ initiate_async_move_accept(), handler, this, ++ ex, static_cast(0), ++ static_cast(0)); ++ } ++ ++ /// Start an asynchronous accept. ++ /** ++ * This function is used to asynchronously accept a new connection. The ++ * function call always returns immediately. ++ * ++ * This overload requires that the Protocol template parameter satisfy the ++ * AcceptableProtocol type requirements. ++ * ++ * @param context The I/O execution context object to be used for the newly ++ * accepted socket. ++ * ++ * @param handler The handler to be called when the accept operation ++ * completes. Copies will be made of the handler as required. The function ++ * signature of the handler must be: ++ * @code void handler( ++ * const boost::system::error_code& error, // Result of operation. ++ * typename Protocol::socket::template rebind_executor< ++ * typename ExecutionContext::executor_type>::other peer ++ * // On success, the newly accepted socket. ++ * ); @endcode ++ * Regardless of whether the asynchronous operation completes immediately or ++ * not, the handler will not be invoked from within this function. On ++ * immediate completion, invocation of the handler will be performed in a ++ * manner equivalent to using boost::asio::post(). ++ * ++ * @par Example ++ * @code ++ * void accept_handler(const boost::system::error_code& error, ++ * boost::asio::ip::tcp::socket peer) ++ * { ++ * if (!error) ++ * { ++ * // Accept succeeded. ++ * } ++ * } ++ * ++ * ... ++ * ++ * boost::asio::ip::tcp::acceptor acceptor(my_context); ++ * ... ++ * acceptor.async_accept(my_context2, accept_handler); ++ * @endcode ++ */ ++ template ++ BOOST_ASIO_INITFN_RESULT_TYPE(MoveAcceptHandler, ++ void (boost::system::error_code, ++ typename Protocol::socket::template rebind_executor< ++ typename ExecutionContext::executor_type>::other)) ++ async_accept(ExecutionContext& context, ++ BOOST_ASIO_MOVE_ARG(MoveAcceptHandler) handler, ++ typename enable_if< ++ is_convertible::value ++ >::type* = 0) ++ { ++ typedef typename Protocol::socket::template rebind_executor< ++ typename ExecutionContext::executor_type>::other other_socket_type; ++ ++ return async_initiate( ++ initiate_async_move_accept(), handler, this, ++ context.get_executor(), static_cast(0), ++ static_cast(0)); ++ } ++ ++ /// Accept a new connection. ++ /** ++ * This function is used to accept a new connection from a peer. The function ++ * call will block until a new connection has been accepted successfully or ++ * an error occurs. ++ * ++ * This overload requires that the Protocol template parameter satisfy the ++ * AcceptableProtocol type requirements. ++ * ++ * @param peer_endpoint An endpoint object into which the endpoint of the ++ * remote peer will be written. ++ * ++ * @returns A socket object representing the newly accepted connection. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ * ++ * @par Example ++ * @code ++ * boost::asio::ip::tcp::acceptor acceptor(my_context); ++ * ... ++ * boost::asio::ip::tcp::endpoint endpoint; ++ * boost::asio::ip::tcp::socket socket(acceptor.accept(endpoint)); ++ * @endcode ++ */ ++ typename Protocol::socket accept(endpoint_type& peer_endpoint) ++ { ++ boost::system::error_code ec; ++ typename Protocol::socket peer(impl_.get_executor()); ++ impl_.get_service().accept(impl_.get_implementation(), ++ peer, &peer_endpoint, ec); ++ boost::asio::detail::throw_error(ec, "accept"); ++ return peer; ++ } ++ ++ /// Accept a new connection. ++ /** ++ * This function is used to accept a new connection from a peer. The function ++ * call will block until a new connection has been accepted successfully or ++ * an error occurs. ++ * ++ * This overload requires that the Protocol template parameter satisfy the ++ * AcceptableProtocol type requirements. ++ * ++ * @param peer_endpoint An endpoint object into which the endpoint of the ++ * remote peer will be written. ++ * ++ * @param ec Set to indicate what error occurred, if any. ++ * ++ * @returns On success, a socket object representing the newly accepted ++ * connection. On error, a socket object where is_open() is false. ++ * ++ * @par Example ++ * @code ++ * boost::asio::ip::tcp::acceptor acceptor(my_context); ++ * ... ++ * boost::asio::ip::tcp::endpoint endpoint; ++ * boost::asio::ip::tcp::socket socket(acceptor.accept(endpoint, ec)); ++ * if (ec) ++ * { ++ * // An error occurred. ++ * } ++ * @endcode ++ */ ++ typename Protocol::socket accept( ++ endpoint_type& peer_endpoint, boost::system::error_code& ec) ++ { ++ typename Protocol::socket peer(impl_.get_executor()); ++ impl_.get_service().accept(impl_.get_implementation(), ++ peer, &peer_endpoint, ec); ++ return peer; ++ } ++ ++ /// Start an asynchronous accept. ++ /** ++ * This function is used to asynchronously accept a new connection. The ++ * function call always returns immediately. ++ * ++ * This overload requires that the Protocol template parameter satisfy the ++ * AcceptableProtocol type requirements. ++ * ++ * @param peer_endpoint An endpoint object into which the endpoint of the ++ * remote peer will be written. Ownership of the peer_endpoint object is ++ * retained by the caller, which must guarantee that it is valid until the ++ * handler is called. ++ * ++ * @param handler The handler to be called when the accept operation ++ * completes. Copies will be made of the handler as required. The function ++ * signature of the handler must be: ++ * @code void handler( ++ * const boost::system::error_code& error, // Result of operation. ++ * typename Protocol::socket peer // On success, the newly accepted socket. ++ * ); @endcode ++ * Regardless of whether the asynchronous operation completes immediately or ++ * not, the handler will not be invoked from within this function. On ++ * immediate completion, invocation of the handler will be performed in a ++ * manner equivalent to using boost::asio::post(). ++ * ++ * @par Example ++ * @code ++ * void accept_handler(const boost::system::error_code& error, ++ * boost::asio::ip::tcp::socket peer) ++ * { ++ * if (!error) ++ * { ++ * // Accept succeeded. ++ * } ++ * } ++ * ++ * ... ++ * ++ * boost::asio::ip::tcp::acceptor acceptor(my_context); ++ * ... ++ * boost::asio::ip::tcp::endpoint endpoint; ++ * acceptor.async_accept(endpoint, accept_handler); ++ * @endcode ++ */ ++ template ++ BOOST_ASIO_INITFN_RESULT_TYPE(MoveAcceptHandler, ++ void (boost::system::error_code, typename Protocol::socket)) ++ async_accept(endpoint_type& peer_endpoint, ++ BOOST_ASIO_MOVE_ARG(MoveAcceptHandler) handler) ++ { ++ return async_initiate( ++ initiate_async_move_accept(), handler, this, ++ impl_.get_executor(), &peer_endpoint, ++ static_cast(0)); ++ } ++ ++ /// Accept a new connection. ++ /** ++ * This function is used to accept a new connection from a peer. The function ++ * call will block until a new connection has been accepted successfully or ++ * an error occurs. ++ * ++ * This overload requires that the Protocol template parameter satisfy the ++ * AcceptableProtocol type requirements. ++ * ++ * @param ex The I/O executor object to be used for the newly accepted ++ * socket. ++ * ++ * @param peer_endpoint An endpoint object into which the endpoint of the ++ * remote peer will be written. ++ * ++ * @returns A socket object representing the newly accepted connection. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ * ++ * @par Example ++ * @code ++ * boost::asio::ip::tcp::acceptor acceptor(my_context); ++ * ... ++ * boost::asio::ip::tcp::endpoint endpoint; ++ * boost::asio::ip::tcp::socket socket( ++ * acceptor.accept(my_context2, endpoint)); ++ * @endcode ++ */ ++ template ++ typename Protocol::socket::template rebind_executor::other ++ accept(const Executor1& ex, endpoint_type& peer_endpoint, ++ typename enable_if< ++ is_executor::value ++ >::type* = 0) ++ { ++ boost::system::error_code ec; ++ typename Protocol::socket::template ++ rebind_executor::other peer(ex); ++ impl_.get_service().accept(impl_.get_implementation(), ++ peer, &peer_endpoint, ec); ++ boost::asio::detail::throw_error(ec, "accept"); ++ return peer; ++ } ++ ++ /// Accept a new connection. ++ /** ++ * This function is used to accept a new connection from a peer. The function ++ * call will block until a new connection has been accepted successfully or ++ * an error occurs. ++ * ++ * This overload requires that the Protocol template parameter satisfy the ++ * AcceptableProtocol type requirements. ++ * ++ * @param context The I/O execution context object to be used for the newly ++ * accepted socket. ++ * ++ * @param peer_endpoint An endpoint object into which the endpoint of the ++ * remote peer will be written. ++ * ++ * @returns A socket object representing the newly accepted connection. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ * ++ * @par Example ++ * @code ++ * boost::asio::ip::tcp::acceptor acceptor(my_context); ++ * ... ++ * boost::asio::ip::tcp::endpoint endpoint; ++ * boost::asio::ip::tcp::socket socket( ++ * acceptor.accept(my_context2, endpoint)); ++ * @endcode ++ */ ++ template ++ typename Protocol::socket::template rebind_executor< ++ typename ExecutionContext::executor_type>::other ++ accept(ExecutionContext& context, endpoint_type& peer_endpoint, ++ typename enable_if< ++ is_convertible::value ++ >::type* = 0) ++ { ++ boost::system::error_code ec; ++ typename Protocol::socket::template rebind_executor< ++ typename ExecutionContext::executor_type>::other peer(context); ++ impl_.get_service().accept(impl_.get_implementation(), ++ peer, &peer_endpoint, ec); ++ boost::asio::detail::throw_error(ec, "accept"); ++ return peer; ++ } ++ ++ /// Accept a new connection. ++ /** ++ * This function is used to accept a new connection from a peer. The function ++ * call will block until a new connection has been accepted successfully or ++ * an error occurs. ++ * ++ * This overload requires that the Protocol template parameter satisfy the ++ * AcceptableProtocol type requirements. ++ * ++ * @param ex The I/O executor object to be used for the newly accepted ++ * socket. ++ * ++ * @param peer_endpoint An endpoint object into which the endpoint of the ++ * remote peer will be written. ++ * ++ * @param ec Set to indicate what error occurred, if any. ++ * ++ * @returns On success, a socket object representing the newly accepted ++ * connection. On error, a socket object where is_open() is false. ++ * ++ * @par Example ++ * @code ++ * boost::asio::ip::tcp::acceptor acceptor(my_context); ++ * ... ++ * boost::asio::ip::tcp::endpoint endpoint; ++ * boost::asio::ip::tcp::socket socket( ++ * acceptor.accept(my_context2, endpoint, ec)); ++ * if (ec) ++ * { ++ * // An error occurred. ++ * } ++ * @endcode ++ */ ++ template ++ typename Protocol::socket::template rebind_executor::other ++ accept(const executor_type& ex, ++ endpoint_type& peer_endpoint, boost::system::error_code& ec, ++ typename enable_if< ++ is_executor::value ++ >::type* = 0) ++ { ++ typename Protocol::socket::template ++ rebind_executor::other peer(ex); ++ impl_.get_service().accept(impl_.get_implementation(), ++ peer, &peer_endpoint, ec); ++ return peer; ++ } ++ ++ /// Accept a new connection. ++ /** ++ * This function is used to accept a new connection from a peer. The function ++ * call will block until a new connection has been accepted successfully or ++ * an error occurs. ++ * ++ * This overload requires that the Protocol template parameter satisfy the ++ * AcceptableProtocol type requirements. ++ * ++ * @param context The I/O execution context object to be used for the newly ++ * accepted socket. ++ * ++ * @param peer_endpoint An endpoint object into which the endpoint of the ++ * remote peer will be written. ++ * ++ * @param ec Set to indicate what error occurred, if any. ++ * ++ * @returns On success, a socket object representing the newly accepted ++ * connection. On error, a socket object where is_open() is false. ++ * ++ * @par Example ++ * @code ++ * boost::asio::ip::tcp::acceptor acceptor(my_context); ++ * ... ++ * boost::asio::ip::tcp::endpoint endpoint; ++ * boost::asio::ip::tcp::socket socket( ++ * acceptor.accept(my_context2, endpoint, ec)); ++ * if (ec) ++ * { ++ * // An error occurred. ++ * } ++ * @endcode ++ */ ++ template ++ typename Protocol::socket::template rebind_executor< ++ typename ExecutionContext::executor_type>::other ++ accept(ExecutionContext& context, ++ endpoint_type& peer_endpoint, boost::system::error_code& ec, ++ typename enable_if< ++ is_convertible::value ++ >::type* = 0) ++ { ++ typename Protocol::socket::template rebind_executor< ++ typename ExecutionContext::executor_type>::other peer(context); ++ impl_.get_service().accept(impl_.get_implementation(), ++ peer, &peer_endpoint, ec); ++ return peer; ++ } ++ ++ /// Start an asynchronous accept. ++ /** ++ * This function is used to asynchronously accept a new connection. The ++ * function call always returns immediately. ++ * ++ * This overload requires that the Protocol template parameter satisfy the ++ * AcceptableProtocol type requirements. ++ * ++ * @param ex The I/O executor object to be used for the newly accepted ++ * socket. ++ * ++ * @param peer_endpoint An endpoint object into which the endpoint of the ++ * remote peer will be written. Ownership of the peer_endpoint object is ++ * retained by the caller, which must guarantee that it is valid until the ++ * handler is called. ++ * ++ * @param handler The handler to be called when the accept operation ++ * completes. Copies will be made of the handler as required. The function ++ * signature of the handler must be: ++ * @code void handler( ++ * const boost::system::error_code& error, // Result of operation. ++ * typename Protocol::socket::template rebind_executor< ++ * Executor1>::other peer // On success, the newly accepted socket. ++ * ); @endcode ++ * Regardless of whether the asynchronous operation completes immediately or ++ * not, the handler will not be invoked from within this function. On ++ * immediate completion, invocation of the handler will be performed in a ++ * manner equivalent to using boost::asio::post(). ++ * ++ * @par Example ++ * @code ++ * void accept_handler(const boost::system::error_code& error, ++ * boost::asio::ip::tcp::socket peer) ++ * { ++ * if (!error) ++ * { ++ * // Accept succeeded. ++ * } ++ * } ++ * ++ * ... ++ * ++ * boost::asio::ip::tcp::acceptor acceptor(my_context); ++ * ... ++ * boost::asio::ip::tcp::endpoint endpoint; ++ * acceptor.async_accept(my_context2, endpoint, accept_handler); ++ * @endcode ++ */ ++ template ++ BOOST_ASIO_INITFN_RESULT_TYPE(MoveAcceptHandler, ++ void (boost::system::error_code, ++ typename Protocol::socket::template rebind_executor< ++ Executor1>::other)) ++ async_accept(const Executor1& ex, endpoint_type& peer_endpoint, ++ BOOST_ASIO_MOVE_ARG(MoveAcceptHandler) handler, ++ typename enable_if< ++ is_executor::value ++ >::type* = 0) ++ { ++ typedef typename Protocol::socket::template rebind_executor< ++ Executor1>::other other_socket_type; ++ ++ return async_initiate( ++ initiate_async_move_accept(), handler, this, ++ ex, &peer_endpoint, ++ static_cast(0)); ++ } ++ ++ /// Start an asynchronous accept. ++ /** ++ * This function is used to asynchronously accept a new connection. The ++ * function call always returns immediately. ++ * ++ * This overload requires that the Protocol template parameter satisfy the ++ * AcceptableProtocol type requirements. ++ * ++ * @param context The I/O execution context object to be used for the newly ++ * accepted socket. ++ * ++ * @param peer_endpoint An endpoint object into which the endpoint of the ++ * remote peer will be written. Ownership of the peer_endpoint object is ++ * retained by the caller, which must guarantee that it is valid until the ++ * handler is called. ++ * ++ * @param handler The handler to be called when the accept operation ++ * completes. Copies will be made of the handler as required. The function ++ * signature of the handler must be: ++ * @code void handler( ++ * const boost::system::error_code& error, // Result of operation. ++ * typename Protocol::socket::template rebind_executor< ++ * typename ExecutionContext::executor_type>::other peer ++ * // On success, the newly accepted socket. ++ * ); @endcode ++ * Regardless of whether the asynchronous operation completes immediately or ++ * not, the handler will not be invoked from within this function. On ++ * immediate completion, invocation of the handler will be performed in a ++ * manner equivalent to using boost::asio::post(). ++ * ++ * @par Example ++ * @code ++ * void accept_handler(const boost::system::error_code& error, ++ * boost::asio::ip::tcp::socket peer) ++ * { ++ * if (!error) ++ * { ++ * // Accept succeeded. ++ * } ++ * } ++ * ++ * ... ++ * ++ * boost::asio::ip::tcp::acceptor acceptor(my_context); ++ * ... ++ * boost::asio::ip::tcp::endpoint endpoint; ++ * acceptor.async_accept(my_context2, endpoint, accept_handler); ++ * @endcode ++ */ ++ template ++ BOOST_ASIO_INITFN_RESULT_TYPE(MoveAcceptHandler, ++ void (boost::system::error_code, ++ typename Protocol::socket::template rebind_executor< ++ typename ExecutionContext::executor_type>::other)) ++ async_accept(ExecutionContext& context, ++ endpoint_type& peer_endpoint, ++ BOOST_ASIO_MOVE_ARG(MoveAcceptHandler) handler, ++ typename enable_if< ++ is_convertible::value ++ >::type* = 0) ++ { ++ typedef typename Protocol::socket::template rebind_executor< ++ typename ExecutionContext::executor_type>::other other_socket_type; ++ ++ return async_initiate( ++ initiate_async_move_accept(), handler, this, ++ context.get_executor(), &peer_endpoint, ++ static_cast(0)); ++ } ++#endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) ++ ++private: ++ // Disallow copying and assignment. ++ basic_socket_acceptor_ext(const basic_socket_acceptor_ext&) BOOST_ASIO_DELETED; ++ basic_socket_acceptor_ext& operator=( ++ const basic_socket_acceptor_ext&) BOOST_ASIO_DELETED; ++ ++ struct initiate_async_wait ++ { ++ template ++ void operator()(BOOST_ASIO_MOVE_ARG(WaitHandler) handler, ++ basic_socket_acceptor_ext* self, wait_type w) const ++ { ++ // If you get an error on the following line it means that your handler ++ // does not meet the documented type requirements for a WaitHandler. ++ BOOST_ASIO_WAIT_HANDLER_CHECK(WaitHandler, handler) type_check; ++ ++ detail::non_const_lvalue handler2(handler); ++ self->impl_.get_service().async_wait( ++ self->impl_.get_implementation(), w, handler2.value, ++ self->impl_.get_implementation_executor()); ++ } ++ }; ++ ++ struct initiate_async_accept ++ { ++ template ++ void operator()(BOOST_ASIO_MOVE_ARG(AcceptHandler) handler, ++ basic_socket_acceptor_ext* self, basic_socket_ext_local* peer, ++ endpoint_type* peer_endpoint) const ++ { ++ // If you get an error on the following line it means that your handler ++ // does not meet the documented type requirements for a AcceptHandler. ++ BOOST_ASIO_ACCEPT_HANDLER_CHECK(AcceptHandler, handler) type_check; ++ ++ detail::non_const_lvalue handler2(handler); ++ self->impl_.get_service().async_accept( ++ self->impl_.get_implementation(), *peer, peer_endpoint, ++ handler2.value, self->impl_.get_executor()); ++ } ++ }; ++ ++ struct initiate_async_move_accept ++ { ++ template ++ void operator()(BOOST_ASIO_MOVE_ARG(MoveAcceptHandler) handler, ++ basic_socket_acceptor_ext* self, const Executor1& peer_ex, ++ endpoint_type* peer_endpoint, Socket*) const ++ { ++ // If you get an error on the following line it means that your handler ++ // does not meet the documented type requirements for a MoveAcceptHandler. ++ BOOST_ASIO_MOVE_ACCEPT_HANDLER_CHECK( ++ MoveAcceptHandler, handler, Socket) type_check; ++ ++ detail::non_const_lvalue handler2(handler); ++ self->impl_.get_service().async_move_accept( ++ self->impl_.get_implementation(), peer_ex, peer_endpoint, ++ handler2.value, self->impl_.get_implementation_executor()); ++ } ++ }; ++ ++#if defined(BOOST_ASIO_WINDOWS_RUNTIME) ++ detail::io_object_impl< ++ detail::null_socket_service, Executor> impl_; ++#elif defined(BOOST_ASIO_HAS_IOCP) ++ detail::io_object_impl< ++ detail::win_iocp_socket_service, Executor> impl_; ++#else ++ detail::io_object_impl< ++ detail::reactive_socket_service_ext_local, Executor> impl_; ++#endif ++}; ++ ++} // namespace asio ++} // namespace boost ++ ++#include ++ ++#endif // BOOST_ASIO_BASIC_SOCKET_ACCEPTOR_EXT_HPP +diff --git a/implementation/helper/1.76/boost/asio/basic_socket_ext.hpp b/implementation/helper/1.76/boost/asio/basic_socket_ext.hpp +new file mode 100644 +index 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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#if defined(BOOST_ASIO_WINDOWS_RUNTIME) ++# include ++#elif defined(BOOST_ASIO_HAS_IOCP) ++# include ++#else ++# include ++#endif ++ ++#if defined(BOOST_ASIO_HAS_MOVE) ++# include ++#endif // defined(BOOST_ASIO_HAS_MOVE) ++ ++#include ++ ++namespace boost { ++namespace asio { ++ ++#if !defined(BOOST_ASIO_BASIC_SOCKET_EXT_FWD_DECL) ++#define BOOST_ASIO_BASIC_SOCKET_EXT_FWD_DECL ++ ++// Forward declaration with defaulted arguments. ++template ++class basic_socket_ext; ++ ++#endif // !defined(BOOST_ASIO_BASIC_SOCKET_EXT_FWD_DECL) ++ ++/// Provides socket functionality. ++/** ++ * The basic_socket class template provides functionality that is common to both ++ * stream-oriented and datagram-oriented sockets. ++ * ++ * @par Thread Safety ++ * @e Distinct @e objects: Safe.@n ++ * @e Shared @e objects: Unsafe. ++ */ ++template ++class basic_socket_ext ++ : public socket_base ++{ ++public: ++ /// The type of the executor associated with the object. ++ typedef Executor executor_type; ++ ++ /// Rebinds the socket type to another executor. ++ template ++ struct rebind_executor ++ { ++ /// The socket type when rebound to the specified executor. ++ typedef basic_socket_ext other; ++ }; ++ ++ /// The native representation of a socket. ++#if defined(GENERATING_DOCUMENTATION) ++ typedef implementation_defined native_handle_type; ++#elif defined(BOOST_ASIO_WINDOWS_RUNTIME) ++ typedef typename detail::null_socket_service< ++ Protocol>::native_handle_type native_handle_type; ++#elif defined(BOOST_ASIO_HAS_IOCP) ++ typedef typename detail::win_iocp_socket_service< ++ Protocol>::native_handle_type native_handle_type; ++#else ++ typedef typename detail::reactive_socket_service_ext< ++ Protocol>::native_handle_type native_handle_type; ++#endif ++ ++ /// The protocol type. ++ typedef Protocol protocol_type; ++ ++ /// The endpoint type. ++ typedef typename Protocol::endpoint endpoint_type; ++ ++#if !defined(BOOST_ASIO_NO_EXTENSIONS) ++ /// A basic_socket is always the lowest layer. ++ typedef basic_socket_ext lowest_layer_type; ++#endif // !defined(BOOST_ASIO_NO_EXTENSIONS) ++ ++ /// Construct a basic_socket without opening it. ++ /** ++ * This constructor creates a socket without opening it. ++ * ++ * @param ex The I/O executor that the socket will use, by default, to ++ * dispatch handlers for any asynchronous operations performed on the socket. ++ */ ++ explicit basic_socket_ext(const executor_type& ex) ++ : impl_(0, ex) ++ { ++ } ++ ++ /// Construct a basic_socket without opening it. ++ /** ++ * This constructor creates a socket without opening it. ++ * ++ * @param context An execution context which provides the I/O executor that ++ * the socket will use, by default, to dispatch handlers for any asynchronous ++ * operations performed on the socket. ++ */ ++ template ++ explicit basic_socket_ext(ExecutionContext& context, ++ typename enable_if< ++ is_convertible::value ++ >::type* = 0) ++ : impl_(0, 0, context) ++ { ++ } ++ ++ /// Construct and open a basic_socket. ++ /** ++ * This constructor creates and opens a socket. ++ * ++ * @param ex The I/O executor that the socket will use, by default, to ++ * dispatch handlers for any asynchronous operations performed on the socket. ++ * ++ * @param protocol An object specifying protocol parameters to be used. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ */ ++ basic_socket_ext(const executor_type& ex, const protocol_type& protocol) ++ : impl_(0, ex) ++ { ++ boost::system::error_code ec; ++ impl_.get_service().open(impl_.get_implementation(), protocol, ec); ++ boost::asio::detail::throw_error(ec, "open"); ++ } ++ ++ /// Construct and open a basic_socket. ++ /** ++ * This constructor creates and opens a socket. ++ * ++ * @param context An execution context which provides the I/O executor that ++ * the socket will use, by default, to dispatch handlers for any asynchronous ++ * operations performed on the socket. ++ * ++ * @param protocol An object specifying protocol parameters to be used. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ */ ++ template ++ basic_socket_ext(ExecutionContext& context, const protocol_type& protocol, ++ typename enable_if< ++ is_convertible::value ++ >::type* = 0) ++ : impl_(0, 0, context) ++ { ++ boost::system::error_code ec; ++ impl_.get_service().open(impl_.get_implementation(), protocol, ec); ++ boost::asio::detail::throw_error(ec, "open"); ++ } ++ ++ /// Construct a basic_socket, opening it and binding it to the given local ++ /// endpoint. ++ /** ++ * This constructor creates a socket and automatically opens it bound to the ++ * specified endpoint on the local machine. The protocol used is the protocol ++ * associated with the given endpoint. ++ * ++ * @param ex The I/O executor that the socket will use, by default, to ++ * dispatch handlers for any asynchronous operations performed on the socket. ++ * ++ * @param endpoint An endpoint on the local machine to which the socket will ++ * be bound. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ */ ++ basic_socket_ext(const executor_type& ex, const endpoint_type& endpoint) ++ : impl_(0, ex) ++ { ++ boost::system::error_code ec; ++ const protocol_type protocol = endpoint.protocol(); ++ impl_.get_service().open(impl_.get_implementation(), protocol, ec); ++ boost::asio::detail::throw_error(ec, "open"); ++ impl_.get_service().bind(impl_.get_implementation(), endpoint, ec); ++ boost::asio::detail::throw_error(ec, "bind"); ++ } ++ ++ /// Construct a basic_socket, opening it and binding it to the given local ++ /// endpoint. ++ /** ++ * This constructor creates a socket and automatically opens it bound to the ++ * specified endpoint on the local machine. The protocol used is the protocol ++ * associated with the given endpoint. ++ * ++ * @param context An execution context which provides the I/O executor that ++ * the socket will use, by default, to dispatch handlers for any asynchronous ++ * operations performed on the socket. ++ * ++ * @param endpoint An endpoint on the local machine to which the socket will ++ * be bound. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ */ ++ template ++ basic_socket_ext(ExecutionContext& context, const endpoint_type& endpoint, ++ typename enable_if< ++ is_convertible::value ++ >::type* = 0) ++ : impl_(0, 0, context) ++ { ++ boost::system::error_code ec; ++ const protocol_type protocol = endpoint.protocol(); ++ impl_.get_service().open(impl_.get_implementation(), protocol, ec); ++ boost::asio::detail::throw_error(ec, "open"); ++ impl_.get_service().bind(impl_.get_implementation(), endpoint, ec); ++ boost::asio::detail::throw_error(ec, "bind"); ++ } ++ ++ /// Construct a basic_socket on an existing native socket. ++ /** ++ * This constructor creates a socket object to hold an existing native socket. ++ * ++ * @param ex The I/O executor that the socket will use, by default, to ++ * dispatch handlers for any asynchronous operations performed on the socket. ++ * ++ * @param protocol An object specifying protocol parameters to be used. ++ * ++ * @param native_socket A native socket. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ */ ++ basic_socket_ext(const executor_type& ex, const protocol_type& protocol, ++ const native_handle_type& native_socket) ++ : impl_(0, ex) ++ { ++ boost::system::error_code ec; ++ impl_.get_service().assign(impl_.get_implementation(), ++ protocol, native_socket, ec); ++ boost::asio::detail::throw_error(ec, "assign"); ++ } ++ ++ /// Construct a basic_socket on an existing native socket. ++ /** ++ * This constructor creates a socket object to hold an existing native socket. ++ * ++ * @param context An execution context which provides the I/O executor that ++ * the socket will use, by default, to dispatch handlers for any asynchronous ++ * operations performed on the socket. ++ * ++ * @param protocol An object specifying protocol parameters to be used. ++ * ++ * @param native_socket A native socket. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ */ ++ template ++ basic_socket_ext(ExecutionContext& context, const protocol_type& protocol, ++ const native_handle_type& native_socket, ++ typename enable_if< ++ is_convertible::value ++ >::type* = 0) ++ : impl_(0, 0, context) ++ { ++ boost::system::error_code ec; ++ impl_.get_service().assign(impl_.get_implementation(), ++ protocol, native_socket, ec); ++ boost::asio::detail::throw_error(ec, "assign"); ++ } ++ ++#if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) ++ /// Move-construct a basic_socket from another. ++ /** ++ * This constructor moves a socket from one object to another. ++ * ++ * @param other The other basic_socket object from which the move will ++ * occur. ++ * ++ * @note Following the move, the moved-from object is in the same state as if ++ * constructed using the @c basic_socket(const executor_type&) constructor. ++ */ ++ basic_socket_ext(basic_socket_ext&& other) ++ : impl_(std::move(other.impl_)) ++ { ++ } ++ ++ /// Move-assign a basic_socket from another. ++ /** ++ * This assignment operator moves a socket from one object to another. ++ * ++ * @param other The other basic_socket object from which the move will ++ * occur. ++ * ++ * @note Following the move, the moved-from object is in the same state as if ++ * constructed using the @c basic_socket(const executor_type&) constructor. ++ */ ++ basic_socket_ext& operator=(basic_socket_ext&& other) ++ { ++ impl_ = std::move(other.impl_); ++ return *this; ++ } ++ ++ // All sockets have access to each other's implementations. ++ template ++ friend class basic_socket_ext; ++ ++ /// Move-construct a basic_socket from a socket of another protocol type. ++ /** ++ * This constructor moves a socket from one object to another. ++ * ++ * @param other The other basic_socket object from which the move will ++ * occur. ++ * ++ * @note Following the move, the moved-from object is in the same state as if ++ * constructed using the @c basic_socket(const executor_type&) constructor. ++ */ ++ template ++ basic_socket_ext(basic_socket_ext&& other, ++ typename enable_if< ++ is_convertible::value ++ && is_convertible::value ++ >::type* = 0) ++ : impl_(std::move(other.impl_)) ++ { ++ } ++ ++ /// Move-assign a basic_socket from a socket of another protocol type. ++ /** ++ * This assignment operator moves a socket from one object to another. ++ * ++ * @param other The other basic_socket object from which the move will ++ * occur. ++ * ++ * @note Following the move, the moved-from object is in the same state as if ++ * constructed using the @c basic_socket(const executor_type&) constructor. ++ */ ++ template ++ typename enable_if< ++ is_convertible::value ++ && is_convertible::value, ++ basic_socket_ext& ++ >::type operator=(basic_socket_ext && other) ++ { ++ basic_socket_ext tmp(std::move(other)); ++ impl_ = std::move(tmp.impl_); ++ return *this; ++ } ++#endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) ++ ++ /// Get the executor associated with the object. ++ executor_type get_executor() BOOST_ASIO_NOEXCEPT ++ { ++ return impl_.get_executor(); ++ } ++ ++#if !defined(BOOST_ASIO_NO_EXTENSIONS) ++ /// Get a reference to the lowest layer. ++ /** ++ * This function returns a reference to the lowest layer in a stack of ++ * layers. Since a basic_socket cannot contain any further layers, it simply ++ * returns a reference to itself. ++ * ++ * @return A reference to the lowest layer in the stack of layers. Ownership ++ * is not transferred to the caller. ++ */ ++ lowest_layer_type& lowest_layer() ++ { ++ return *this; ++ } ++ ++ /// Get a const reference to the lowest layer. ++ /** ++ * This function returns a const reference to the lowest layer in a stack of ++ * layers. Since a basic_socket cannot contain any further layers, it simply ++ * returns a reference to itself. ++ * ++ * @return A const reference to the lowest layer in the stack of layers. ++ * Ownership is not transferred to the caller. ++ */ ++ const lowest_layer_type& lowest_layer() const ++ { ++ return *this; ++ } ++#endif // !defined(BOOST_ASIO_NO_EXTENSIONS) ++ ++ /// Open the socket using the specified protocol. ++ /** ++ * This function opens the socket so that it will use the specified protocol. ++ * ++ * @param protocol An object specifying protocol parameters to be used. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ * ++ * @par Example ++ * @code ++ * boost::asio::ip::tcp::socket socket(my_context); ++ * socket.open(boost::asio::ip::tcp::v4()); ++ * @endcode ++ */ ++ void open(const protocol_type& protocol = protocol_type()) ++ { ++ boost::system::error_code ec; ++ impl_.get_service().open(impl_.get_implementation(), protocol, ec); ++ boost::asio::detail::throw_error(ec, "open"); ++ } ++ ++ /// Open the socket using the specified protocol. ++ /** ++ * This function opens the socket so that it will use the specified protocol. ++ * ++ * @param protocol An object specifying which protocol is to be used. ++ * ++ * @param ec Set to indicate what error occurred, if any. ++ * ++ * @par Example ++ * @code ++ * boost::asio::ip::tcp::socket socket(my_context); ++ * boost::system::error_code ec; ++ * socket.open(boost::asio::ip::tcp::v4(), ec); ++ * if (ec) ++ * { ++ * // An error occurred. ++ * } ++ * @endcode ++ */ ++ BOOST_ASIO_SYNC_OP_VOID open(const protocol_type& protocol, ++ boost::system::error_code& ec) ++ { ++ impl_.get_service().open(impl_.get_implementation(), protocol, ec); ++ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); ++ } ++ ++ /// Assign an existing native socket to the socket. ++ /* ++ * This function opens the socket to hold an existing native socket. ++ * ++ * @param protocol An object specifying which protocol is to be used. ++ * ++ * @param native_socket A native socket. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ */ ++ void assign(const protocol_type& protocol, ++ const native_handle_type& native_socket) ++ { ++ boost::system::error_code ec; ++ impl_.get_service().assign(impl_.get_implementation(), ++ protocol, native_socket, ec); ++ boost::asio::detail::throw_error(ec, "assign"); ++ } ++ ++ /// Assign an existing native socket to the socket. ++ /* ++ * This function opens the socket to hold an existing native socket. ++ * ++ * @param protocol An object specifying which protocol is to be used. ++ * ++ * @param native_socket A native socket. ++ * ++ * @param ec Set to indicate what error occurred, if any. ++ */ ++ BOOST_ASIO_SYNC_OP_VOID assign(const protocol_type& protocol, ++ const native_handle_type& native_socket, boost::system::error_code& ec) ++ { ++ impl_.get_service().assign(impl_.get_implementation(), ++ protocol, native_socket, ec); ++ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); ++ } ++ ++ /// Determine whether the socket is open. ++ bool is_open() const ++ { ++ return impl_.get_service().is_open(impl_.get_implementation()); ++ } ++ ++ /// Close the socket. ++ /** ++ * This function is used to close the socket. Any asynchronous send, receive ++ * or connect operations will be cancelled immediately, and will complete ++ * with the boost::asio::error::operation_aborted error. ++ * ++ * @throws boost::system::system_error Thrown on failure. Note that, even if ++ * the function indicates an error, the underlying descriptor is closed. ++ * ++ * @note For portable behaviour with respect to graceful closure of a ++ * connected socket, call shutdown() before closing the socket. ++ */ ++ void close() ++ { ++ boost::system::error_code ec; ++ impl_.get_service().close(impl_.get_implementation(), ec); ++ boost::asio::detail::throw_error(ec, "close"); ++ } ++ ++ /// Close the socket. ++ /** ++ * This function is used to close the socket. Any asynchronous send, receive ++ * or connect operations will be cancelled immediately, and will complete ++ * with the boost::asio::error::operation_aborted error. ++ * ++ * @param ec Set to indicate what error occurred, if any. Note that, even if ++ * the function indicates an error, the underlying descriptor is closed. ++ * ++ * @par Example ++ * @code ++ * boost::asio::ip::tcp::socket socket(my_context); ++ * ... ++ * boost::system::error_code ec; ++ * socket.close(ec); ++ * if (ec) ++ * { ++ * // An error occurred. ++ * } ++ * @endcode ++ * ++ * @note For portable behaviour with respect to graceful closure of a ++ * connected socket, call shutdown() before closing the socket. ++ */ ++ BOOST_ASIO_SYNC_OP_VOID close(boost::system::error_code& ec) ++ { ++ impl_.get_service().close(impl_.get_implementation(), ec); ++ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); ++ } ++ ++ /// Release ownership of the underlying native socket. ++ /** ++ * This function causes all outstanding asynchronous connect, send and receive ++ * operations to finish immediately, and the handlers for cancelled operations ++ * will be passed the boost::asio::error::operation_aborted error. Ownership ++ * of the native socket is then transferred to the caller. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ * ++ * @note This function is unsupported on Windows versions prior to Windows ++ * 8.1, and will fail with boost::asio::error::operation_not_supported on ++ * these platforms. ++ */ ++#if defined(BOOST_ASIO_MSVC) && (BOOST_ASIO_MSVC >= 1400) \ ++ && (!defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0603) ++ __declspec(deprecated("This function always fails with " ++ "operation_not_supported when used on Windows versions " ++ "prior to Windows 8.1.")) ++#endif ++ native_handle_type release() ++ { ++ boost::system::error_code ec; ++ native_handle_type s = impl_.get_service().release( ++ impl_.get_implementation(), ec); ++ boost::asio::detail::throw_error(ec, "release"); ++ return s; ++ } ++ ++ /// Release ownership of the underlying native socket. ++ /** ++ * This function causes all outstanding asynchronous connect, send and receive ++ * operations to finish immediately, and the handlers for cancelled operations ++ * will be passed the boost::asio::error::operation_aborted error. Ownership ++ * of the native socket is then transferred to the caller. ++ * ++ * @param ec Set to indicate what error occurred, if any. ++ * ++ * @note This function is unsupported on Windows versions prior to Windows ++ * 8.1, and will fail with boost::asio::error::operation_not_supported on ++ * these platforms. ++ */ ++#if defined(BOOST_ASIO_MSVC) && (BOOST_ASIO_MSVC >= 1400) \ ++ && (!defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0603) ++ __declspec(deprecated("This function always fails with " ++ "operation_not_supported when used on Windows versions " ++ "prior to Windows 8.1.")) ++#endif ++ native_handle_type release(boost::system::error_code& ec) ++ { ++ return impl_.get_service().release(impl_.get_implementation(), ec); ++ } ++ ++ /// Get the native socket representation. ++ /** ++ * This function may be used to obtain the underlying representation of the ++ * socket. This is intended to allow access to native socket functionality ++ * that is not otherwise provided. ++ */ ++ native_handle_type native_handle() ++ { ++ return impl_.get_service().native_handle(impl_.get_implementation()); ++ } ++ ++ /// Cancel all asynchronous operations associated with the socket. ++ /** ++ * This function causes all outstanding asynchronous connect, send and receive ++ * operations to finish immediately, and the handlers for cancelled operations ++ * will be passed the boost::asio::error::operation_aborted error. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ * ++ * @note Calls to cancel() will always fail with ++ * boost::asio::error::operation_not_supported when run on Windows XP, Windows ++ * Server 2003, and earlier versions of Windows, unless ++ * BOOST_ASIO_ENABLE_CANCELIO is defined. However, the CancelIo function has ++ * two issues that should be considered before enabling its use: ++ * ++ * @li It will only cancel asynchronous operations that were initiated in the ++ * current thread. ++ * ++ * @li It can appear to complete without error, but the request to cancel the ++ * unfinished operations may be silently ignored by the operating system. ++ * Whether it works or not seems to depend on the drivers that are installed. ++ * ++ * For portable cancellation, consider using one of the following ++ * alternatives: ++ * ++ * @li Disable asio's I/O completion port backend by defining ++ * BOOST_ASIO_DISABLE_IOCP. ++ * ++ * @li Use the close() function to simultaneously cancel the outstanding ++ * operations and close the socket. ++ * ++ * When running on Windows Vista, Windows Server 2008, and later, the ++ * CancelIoEx function is always used. This function does not have the ++ * problems described above. ++ */ ++#if defined(BOOST_ASIO_MSVC) && (BOOST_ASIO_MSVC >= 1400) \ ++ && (!defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0600) \ ++ && !defined(BOOST_ASIO_ENABLE_CANCELIO) ++ __declspec(deprecated("By default, this function always fails with " ++ "operation_not_supported when used on Windows XP, Windows Server 2003, " ++ "or earlier. Consult documentation for details.")) ++#endif ++ void cancel() ++ { ++ boost::system::error_code ec; ++ impl_.get_service().cancel(impl_.get_implementation(), ec); ++ boost::asio::detail::throw_error(ec, "cancel"); ++ } ++ ++ /// Cancel all asynchronous operations associated with the socket. ++ /** ++ * This function causes all outstanding asynchronous connect, send and receive ++ * operations to finish immediately, and the handlers for cancelled operations ++ * will be passed the boost::asio::error::operation_aborted error. ++ * ++ * @param ec Set to indicate what error occurred, if any. ++ * ++ * @note Calls to cancel() will always fail with ++ * boost::asio::error::operation_not_supported when run on Windows XP, Windows ++ * Server 2003, and earlier versions of Windows, unless ++ * BOOST_ASIO_ENABLE_CANCELIO is defined. However, the CancelIo function has ++ * two issues that should be considered before enabling its use: ++ * ++ * @li It will only cancel asynchronous operations that were initiated in the ++ * current thread. ++ * ++ * @li It can appear to complete without error, but the request to cancel the ++ * unfinished operations may be silently ignored by the operating system. ++ * Whether it works or not seems to depend on the drivers that are installed. ++ * ++ * For portable cancellation, consider using one of the following ++ * alternatives: ++ * ++ * @li Disable asio's I/O completion port backend by defining ++ * BOOST_ASIO_DISABLE_IOCP. ++ * ++ * @li Use the close() function to simultaneously cancel the outstanding ++ * operations and close the socket. ++ * ++ * When running on Windows Vista, Windows Server 2008, and later, the ++ * CancelIoEx function is always used. This function does not have the ++ * problems described above. ++ */ ++#if defined(BOOST_ASIO_MSVC) && (BOOST_ASIO_MSVC >= 1400) \ ++ && (!defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0600) \ ++ && !defined(BOOST_ASIO_ENABLE_CANCELIO) ++ __declspec(deprecated("By default, this function always fails with " ++ "operation_not_supported when used on Windows XP, Windows Server 2003, " ++ "or earlier. Consult documentation for details.")) ++#endif ++ BOOST_ASIO_SYNC_OP_VOID cancel(boost::system::error_code& ec) ++ { ++ impl_.get_service().cancel(impl_.get_implementation(), ec); ++ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); ++ } ++ ++ /// Determine whether the socket is at the out-of-band data mark. ++ /** ++ * This function is used to check whether the socket input is currently ++ * positioned at the out-of-band data mark. ++ * ++ * @return A bool indicating whether the socket is at the out-of-band data ++ * mark. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ */ ++ bool at_mark() const ++ { ++ boost::system::error_code ec; ++ bool b = impl_.get_service().at_mark(impl_.get_implementation(), ec); ++ boost::asio::detail::throw_error(ec, "at_mark"); ++ return b; ++ } ++ ++ /// Determine whether the socket is at the out-of-band data mark. ++ /** ++ * This function is used to check whether the socket input is currently ++ * positioned at the out-of-band data mark. ++ * ++ * @param ec Set to indicate what error occurred, if any. ++ * ++ * @return A bool indicating whether the socket is at the out-of-band data ++ * mark. ++ */ ++ bool at_mark(boost::system::error_code& ec) const ++ { ++ return impl_.get_service().at_mark(impl_.get_implementation(), ec); ++ } ++ ++ /// Determine the number of bytes available for reading. ++ /** ++ * This function is used to determine the number of bytes that may be read ++ * without blocking. ++ * ++ * @return The number of bytes that may be read without blocking, or 0 if an ++ * error occurs. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ */ ++ std::size_t available() const ++ { ++ boost::system::error_code ec; ++ std::size_t s = impl_.get_service().available( ++ impl_.get_implementation(), ec); ++ boost::asio::detail::throw_error(ec, "available"); ++ return s; ++ } ++ ++ /// Determine the number of bytes available for reading. ++ /** ++ * This function is used to determine the number of bytes that may be read ++ * without blocking. ++ * ++ * @param ec Set to indicate what error occurred, if any. ++ * ++ * @return The number of bytes that may be read without blocking, or 0 if an ++ * error occurs. ++ */ ++ std::size_t available(boost::system::error_code& ec) const ++ { ++ return impl_.get_service().available(impl_.get_implementation(), ec); ++ } ++ ++ /// Bind the socket to the given local endpoint. ++ /** ++ * This function binds the socket to the specified endpoint on the local ++ * machine. ++ * ++ * @param endpoint An endpoint on the local machine to which the socket will ++ * be bound. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ * ++ * @par Example ++ * @code ++ * boost::asio::ip::tcp::socket socket(my_context); ++ * socket.open(boost::asio::ip::tcp::v4()); ++ * socket.bind(boost::asio::ip::tcp::endpoint( ++ * boost::asio::ip::tcp::v4(), 12345)); ++ * @endcode ++ */ ++ void bind(const endpoint_type& endpoint) ++ { ++ boost::system::error_code ec; ++ impl_.get_service().bind(impl_.get_implementation(), endpoint, ec); ++ boost::asio::detail::throw_error(ec, "bind"); ++ } ++ ++ /// Bind the socket to the given local endpoint. ++ /** ++ * This function binds the socket to the specified endpoint on the local ++ * machine. ++ * ++ * @param endpoint An endpoint on the local machine to which the socket will ++ * be bound. ++ * ++ * @param ec Set to indicate what error occurred, if any. ++ * ++ * @par Example ++ * @code ++ * boost::asio::ip::tcp::socket socket(my_context); ++ * socket.open(boost::asio::ip::tcp::v4()); ++ * boost::system::error_code ec; ++ * socket.bind(boost::asio::ip::tcp::endpoint( ++ * boost::asio::ip::tcp::v4(), 12345), ec); ++ * if (ec) ++ * { ++ * // An error occurred. ++ * } ++ * @endcode ++ */ ++ BOOST_ASIO_SYNC_OP_VOID bind(const endpoint_type& endpoint, ++ boost::system::error_code& ec) ++ { ++ impl_.get_service().bind(impl_.get_implementation(), endpoint, ec); ++ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); ++ } ++ ++ /// Connect the socket to the specified endpoint. ++ /** ++ * This function is used to connect a socket to the specified remote endpoint. ++ * The function call will block until the connection is successfully made or ++ * an error occurs. ++ * ++ * The socket is automatically opened if it is not already open. If the ++ * connect fails, and the socket was automatically opened, the socket is ++ * not returned to the closed state. ++ * ++ * @param peer_endpoint The remote endpoint to which the socket will be ++ * connected. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ * ++ * @par Example ++ * @code ++ * boost::asio::ip::tcp::socket socket(my_context); ++ * boost::asio::ip::tcp::endpoint endpoint( ++ * boost::asio::ip::address::from_string("1.2.3.4"), 12345); ++ * socket.connect(endpoint); ++ * @endcode ++ */ ++ void connect(const endpoint_type& peer_endpoint) ++ { ++ boost::system::error_code ec; ++ if (!is_open()) ++ { ++ impl_.get_service().open(impl_.get_implementation(), ++ peer_endpoint.protocol(), ec); ++ boost::asio::detail::throw_error(ec, "connect"); ++ } ++ impl_.get_service().connect(impl_.get_implementation(), peer_endpoint, ec); ++ boost::asio::detail::throw_error(ec, "connect"); ++ } ++ ++ /// Connect the socket to the specified endpoint. ++ /** ++ * This function is used to connect a socket to the specified remote endpoint. ++ * The function call will block until the connection is successfully made or ++ * an error occurs. ++ * ++ * The socket is automatically opened if it is not already open. If the ++ * connect fails, and the socket was automatically opened, the socket is ++ * not returned to the closed state. ++ * ++ * @param peer_endpoint The remote endpoint to which the socket will be ++ * connected. ++ * ++ * @param ec Set to indicate what error occurred, if any. ++ * ++ * @par Example ++ * @code ++ * boost::asio::ip::tcp::socket socket(my_context); ++ * boost::asio::ip::tcp::endpoint endpoint( ++ * boost::asio::ip::address::from_string("1.2.3.4"), 12345); ++ * boost::system::error_code ec; ++ * socket.connect(endpoint, ec); ++ * if (ec) ++ * { ++ * // An error occurred. ++ * } ++ * @endcode ++ */ ++ BOOST_ASIO_SYNC_OP_VOID connect(const endpoint_type& peer_endpoint, ++ boost::system::error_code& ec) ++ { ++ if (!is_open()) ++ { ++ impl_.get_service().open(impl_.get_implementation(), ++ peer_endpoint.protocol(), ec); ++ if (ec) ++ { ++ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); ++ } ++ } ++ ++ impl_.get_service().connect(impl_.get_implementation(), peer_endpoint, ec); ++ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); ++ } ++ ++ /// Start an asynchronous connect. ++ /** ++ * This function is used to asynchronously connect a socket to the specified ++ * remote endpoint. The function call always returns immediately. ++ * ++ * The socket is automatically opened if it is not already open. If the ++ * connect fails, and the socket was automatically opened, the socket is ++ * not returned to the closed state. ++ * ++ * @param peer_endpoint The remote endpoint to which the socket will be ++ * connected. Copies will be made of the endpoint object as required. ++ * ++ * @param handler The handler to be called when the connection operation ++ * completes. Copies will be made of the handler as required. The function ++ * signature of the handler must be: ++ * @code void handler( ++ * const boost::system::error_code& error // Result of operation ++ * ); @endcode ++ * Regardless of whether the asynchronous operation completes immediately or ++ * not, the handler will not be invoked from within this function. On ++ * immediate completion, invocation of the handler will be performed in a ++ * manner equivalent to using boost::asio::post(). ++ * ++ * @par Example ++ * @code ++ * void connect_handler(const boost::system::error_code& error) ++ * { ++ * if (!error) ++ * { ++ * // Connect succeeded. ++ * } ++ * } ++ * ++ * ... ++ * ++ * boost::asio::ip::tcp::socket socket(my_context); ++ * boost::asio::ip::tcp::endpoint endpoint( ++ * boost::asio::ip::address::from_string("1.2.3.4"), 12345); ++ * socket.async_connect(endpoint, connect_handler); ++ * @endcode ++ */ ++ template ++ BOOST_ASIO_INITFN_RESULT_TYPE(ConnectHandler, ++ void (boost::system::error_code)) ++ async_connect(const endpoint_type& peer_endpoint, ++ BOOST_ASIO_MOVE_ARG(ConnectHandler) handler) ++ { ++ boost::system::error_code open_ec; ++ if (!is_open()) ++ { ++ const protocol_type protocol = peer_endpoint.protocol(); ++ impl_.get_service().open(impl_.get_implementation(), protocol, open_ec); ++ } ++ ++ return async_initiate( ++ initiate_async_connect(), handler, this, peer_endpoint, open_ec); ++ } ++ ++ /// Set an option on the socket. ++ /** ++ * This function is used to set an option on the socket. ++ * ++ * @param option The new option value to be set on the socket. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ * ++ * @sa SettableSocketOption @n ++ * boost::asio::socket_base::broadcast @n ++ * boost::asio::socket_base::do_not_route @n ++ * boost::asio::socket_base::keep_alive @n ++ * boost::asio::socket_base::linger @n ++ * boost::asio::socket_base::receive_buffer_size @n ++ * boost::asio::socket_base::receive_low_watermark @n ++ * boost::asio::socket_base::reuse_address @n ++ * boost::asio::socket_base::send_buffer_size @n ++ * boost::asio::socket_base::send_low_watermark @n ++ * boost::asio::ip::multicast::join_group @n ++ * boost::asio::ip::multicast::leave_group @n ++ * boost::asio::ip::multicast::enable_loopback @n ++ * boost::asio::ip::multicast::outbound_interface @n ++ * boost::asio::ip::multicast::hops @n ++ * boost::asio::ip::tcp::no_delay ++ * ++ * @par Example ++ * Setting the IPPROTO_TCP/TCP_NODELAY option: ++ * @code ++ * boost::asio::ip::tcp::socket socket(my_context); ++ * ... ++ * boost::asio::ip::tcp::no_delay option(true); ++ * socket.set_option(option); ++ * @endcode ++ */ ++ template ++ void set_option(const SettableSocketOption& option) ++ { ++ boost::system::error_code ec; ++ impl_.get_service().set_option(impl_.get_implementation(), option, ec); ++ boost::asio::detail::throw_error(ec, "set_option"); ++ } ++ ++ /// Set an option on the socket. ++ /** ++ * This function is used to set an option on the socket. ++ * ++ * @param option The new option value to be set on the socket. ++ * ++ * @param ec Set to indicate what error occurred, if any. ++ * ++ * @sa SettableSocketOption @n ++ * boost::asio::socket_base::broadcast @n ++ * boost::asio::socket_base::do_not_route @n ++ * boost::asio::socket_base::keep_alive @n ++ * boost::asio::socket_base::linger @n ++ * boost::asio::socket_base::receive_buffer_size @n ++ * boost::asio::socket_base::receive_low_watermark @n ++ * boost::asio::socket_base::reuse_address @n ++ * boost::asio::socket_base::send_buffer_size @n ++ * boost::asio::socket_base::send_low_watermark @n ++ * boost::asio::ip::multicast::join_group @n ++ * boost::asio::ip::multicast::leave_group @n ++ * boost::asio::ip::multicast::enable_loopback @n ++ * boost::asio::ip::multicast::outbound_interface @n ++ * boost::asio::ip::multicast::hops @n ++ * boost::asio::ip::tcp::no_delay ++ * ++ * @par Example ++ * Setting the IPPROTO_TCP/TCP_NODELAY option: ++ * @code ++ * boost::asio::ip::tcp::socket socket(my_context); ++ * ... ++ * boost::asio::ip::tcp::no_delay option(true); ++ * boost::system::error_code ec; ++ * socket.set_option(option, ec); ++ * if (ec) ++ * { ++ * // An error occurred. ++ * } ++ * @endcode ++ */ ++ template ++ BOOST_ASIO_SYNC_OP_VOID set_option(const SettableSocketOption& option, ++ boost::system::error_code& ec) ++ { ++ impl_.get_service().set_option(impl_.get_implementation(), option, ec); ++ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); ++ } ++ ++ /// Get an option from the socket. ++ /** ++ * This function is used to get the current value of an option on the socket. ++ * ++ * @param option The option value to be obtained from the socket. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ * ++ * @sa GettableSocketOption @n ++ * boost::asio::socket_base::broadcast @n ++ * boost::asio::socket_base::do_not_route @n ++ * boost::asio::socket_base::keep_alive @n ++ * boost::asio::socket_base::linger @n ++ * boost::asio::socket_base::receive_buffer_size @n ++ * boost::asio::socket_base::receive_low_watermark @n ++ * boost::asio::socket_base::reuse_address @n ++ * boost::asio::socket_base::send_buffer_size @n ++ * boost::asio::socket_base::send_low_watermark @n ++ * boost::asio::ip::multicast::join_group @n ++ * boost::asio::ip::multicast::leave_group @n ++ * boost::asio::ip::multicast::enable_loopback @n ++ * boost::asio::ip::multicast::outbound_interface @n ++ * boost::asio::ip::multicast::hops @n ++ * boost::asio::ip::tcp::no_delay ++ * ++ * @par Example ++ * Getting the value of the SOL_SOCKET/SO_KEEPALIVE option: ++ * @code ++ * boost::asio::ip::tcp::socket socket(my_context); ++ * ... ++ * boost::asio::ip::tcp::socket::keep_alive option; ++ * socket.get_option(option); ++ * bool is_set = option.value(); ++ * @endcode ++ */ ++ template ++ void get_option(GettableSocketOption& option) const ++ { ++ boost::system::error_code ec; ++ impl_.get_service().get_option(impl_.get_implementation(), option, ec); ++ boost::asio::detail::throw_error(ec, "get_option"); ++ } ++ ++ /// Get an option from the socket. ++ /** ++ * This function is used to get the current value of an option on the socket. ++ * ++ * @param option The option value to be obtained from the socket. ++ * ++ * @param ec Set to indicate what error occurred, if any. ++ * ++ * @sa GettableSocketOption @n ++ * boost::asio::socket_base::broadcast @n ++ * boost::asio::socket_base::do_not_route @n ++ * boost::asio::socket_base::keep_alive @n ++ * boost::asio::socket_base::linger @n ++ * boost::asio::socket_base::receive_buffer_size @n ++ * boost::asio::socket_base::receive_low_watermark @n ++ * boost::asio::socket_base::reuse_address @n ++ * boost::asio::socket_base::send_buffer_size @n ++ * boost::asio::socket_base::send_low_watermark @n ++ * boost::asio::ip::multicast::join_group @n ++ * boost::asio::ip::multicast::leave_group @n ++ * boost::asio::ip::multicast::enable_loopback @n ++ * boost::asio::ip::multicast::outbound_interface @n ++ * boost::asio::ip::multicast::hops @n ++ * boost::asio::ip::tcp::no_delay ++ * ++ * @par Example ++ * Getting the value of the SOL_SOCKET/SO_KEEPALIVE option: ++ * @code ++ * boost::asio::ip::tcp::socket socket(my_context); ++ * ... ++ * boost::asio::ip::tcp::socket::keep_alive option; ++ * boost::system::error_code ec; ++ * socket.get_option(option, ec); ++ * if (ec) ++ * { ++ * // An error occurred. ++ * } ++ * bool is_set = option.value(); ++ * @endcode ++ */ ++ template ++ BOOST_ASIO_SYNC_OP_VOID get_option(GettableSocketOption& option, ++ boost::system::error_code& ec) const ++ { ++ impl_.get_service().get_option(impl_.get_implementation(), option, ec); ++ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); ++ } ++ ++ /// Perform an IO control command on the socket. ++ /** ++ * This function is used to execute an IO control command on the socket. ++ * ++ * @param command The IO control command to be performed on the socket. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ * ++ * @sa IoControlCommand @n ++ * boost::asio::socket_base::bytes_readable @n ++ * boost::asio::socket_base::non_blocking_io ++ * ++ * @par Example ++ * Getting the number of bytes ready to read: ++ * @code ++ * boost::asio::ip::tcp::socket socket(my_context); ++ * ... ++ * boost::asio::ip::tcp::socket::bytes_readable command; ++ * socket.io_control(command); ++ * std::size_t bytes_readable = command.get(); ++ * @endcode ++ */ ++ template ++ void io_control(IoControlCommand& command) ++ { ++ boost::system::error_code ec; ++ impl_.get_service().io_control(impl_.get_implementation(), command, ec); ++ boost::asio::detail::throw_error(ec, "io_control"); ++ } ++ ++ /// Perform an IO control command on the socket. ++ /** ++ * This function is used to execute an IO control command on the socket. ++ * ++ * @param command The IO control command to be performed on the socket. ++ * ++ * @param ec Set to indicate what error occurred, if any. ++ * ++ * @sa IoControlCommand @n ++ * boost::asio::socket_base::bytes_readable @n ++ * boost::asio::socket_base::non_blocking_io ++ * ++ * @par Example ++ * Getting the number of bytes ready to read: ++ * @code ++ * boost::asio::ip::tcp::socket socket(my_context); ++ * ... ++ * boost::asio::ip::tcp::socket::bytes_readable command; ++ * boost::system::error_code ec; ++ * socket.io_control(command, ec); ++ * if (ec) ++ * { ++ * // An error occurred. ++ * } ++ * std::size_t bytes_readable = command.get(); ++ * @endcode ++ */ ++ template ++ BOOST_ASIO_SYNC_OP_VOID io_control(IoControlCommand& command, ++ boost::system::error_code& ec) ++ { ++ impl_.get_service().io_control(impl_.get_implementation(), command, ec); ++ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); ++ } ++ ++ /// Gets the non-blocking mode of the socket. ++ /** ++ * @returns @c true if the socket's synchronous operations will fail with ++ * boost::asio::error::would_block if they are unable to perform the requested ++ * operation immediately. If @c false, synchronous operations will block ++ * until complete. ++ * ++ * @note The non-blocking mode has no effect on the behaviour of asynchronous ++ * operations. Asynchronous operations will never fail with the error ++ * boost::asio::error::would_block. ++ */ ++ bool non_blocking() const ++ { ++ return impl_.get_service().non_blocking(impl_.get_implementation()); ++ } ++ ++ /// Sets the non-blocking mode of the socket. ++ /** ++ * @param mode If @c true, the socket's synchronous operations will fail with ++ * boost::asio::error::would_block if they are unable to perform the requested ++ * operation immediately. If @c false, synchronous operations will block ++ * until complete. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ * ++ * @note The non-blocking mode has no effect on the behaviour of asynchronous ++ * operations. Asynchronous operations will never fail with the error ++ * boost::asio::error::would_block. ++ */ ++ void non_blocking(bool mode) ++ { ++ boost::system::error_code ec; ++ impl_.get_service().non_blocking(impl_.get_implementation(), mode, ec); ++ boost::asio::detail::throw_error(ec, "non_blocking"); ++ } ++ ++ /// Sets the non-blocking mode of the socket. ++ /** ++ * @param mode If @c true, the socket's synchronous operations will fail with ++ * boost::asio::error::would_block if they are unable to perform the requested ++ * operation immediately. If @c false, synchronous operations will block ++ * until complete. ++ * ++ * @param ec Set to indicate what error occurred, if any. ++ * ++ * @note The non-blocking mode has no effect on the behaviour of asynchronous ++ * operations. Asynchronous operations will never fail with the error ++ * boost::asio::error::would_block. ++ */ ++ BOOST_ASIO_SYNC_OP_VOID non_blocking( ++ bool mode, boost::system::error_code& ec) ++ { ++ impl_.get_service().non_blocking(impl_.get_implementation(), mode, ec); ++ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); ++ } ++ ++ /// Gets the non-blocking mode of the native socket implementation. ++ /** ++ * This function is used to retrieve the non-blocking mode of the underlying ++ * native socket. This mode has no effect on the behaviour of the socket ++ * object's synchronous operations. ++ * ++ * @returns @c true if the underlying socket is in non-blocking mode and ++ * direct system calls may fail with boost::asio::error::would_block (or the ++ * equivalent system error). ++ * ++ * @note The current non-blocking mode is cached by the socket object. ++ * Consequently, the return value may be incorrect if the non-blocking mode ++ * was set directly on the native socket. ++ * ++ * @par Example ++ * This function is intended to allow the encapsulation of arbitrary ++ * non-blocking system calls as asynchronous operations, in a way that is ++ * transparent to the user of the socket object. The following example ++ * illustrates how Linux's @c sendfile system call might be encapsulated: ++ * @code template ++ * struct sendfile_op ++ * { ++ * tcp::socket& sock_; ++ * int fd_; ++ * Handler handler_; ++ * off_t offset_; ++ * std::size_t total_bytes_transferred_; ++ * ++ * // Function call operator meeting WriteHandler requirements. ++ * // Used as the handler for the async_write_some operation. ++ * void operator()(boost::system::error_code ec, std::size_t) ++ * { ++ * // Put the underlying socket into non-blocking mode. ++ * if (!ec) ++ * if (!sock_.native_non_blocking()) ++ * sock_.native_non_blocking(true, ec); ++ * ++ * if (!ec) ++ * { ++ * for (;;) ++ * { ++ * // Try the system call. ++ * errno = 0; ++ * int n = ::sendfile(sock_.native_handle(), fd_, &offset_, 65536); ++ * ec = boost::system::error_code(n < 0 ? errno : 0, ++ * boost::asio::error::get_system_category()); ++ * total_bytes_transferred_ += ec ? 0 : n; ++ * ++ * // Retry operation immediately if interrupted by signal. ++ * if (ec == boost::asio::error::interrupted) ++ * continue; ++ * ++ * // Check if we need to run the operation again. ++ * if (ec == boost::asio::error::would_block ++ * || ec == boost::asio::error::try_again) ++ * { ++ * // We have to wait for the socket to become ready again. ++ * sock_.async_wait(tcp::socket::wait_write, *this); ++ * return; ++ * } ++ * ++ * if (ec || n == 0) ++ * { ++ * // An error occurred, or we have reached the end of the file. ++ * // Either way we must exit the loop so we can call the handler. ++ * break; ++ * } ++ * ++ * // Loop around to try calling sendfile again. ++ * } ++ * } ++ * ++ * // Pass result back to user's handler. ++ * handler_(ec, total_bytes_transferred_); ++ * } ++ * }; ++ * ++ * template ++ * void async_sendfile(tcp::socket& sock, int fd, Handler h) ++ * { ++ * sendfile_op op = { sock, fd, h, 0, 0 }; ++ * sock.async_wait(tcp::socket::wait_write, op); ++ * } @endcode ++ */ ++ bool native_non_blocking() const ++ { ++ return impl_.get_service().native_non_blocking(impl_.get_implementation()); ++ } ++ ++ /// Sets the non-blocking mode of the native socket implementation. ++ /** ++ * This function is used to modify the non-blocking mode of the underlying ++ * native socket. It has no effect on the behaviour of the socket object's ++ * synchronous operations. ++ * ++ * @param mode If @c true, the underlying socket is put into non-blocking ++ * mode and direct system calls may fail with boost::asio::error::would_block ++ * (or the equivalent system error). ++ * ++ * @throws boost::system::system_error Thrown on failure. If the @c mode is ++ * @c false, but the current value of @c non_blocking() is @c true, this ++ * function fails with boost::asio::error::invalid_argument, as the ++ * combination does not make sense. ++ * ++ * @par Example ++ * This function is intended to allow the encapsulation of arbitrary ++ * non-blocking system calls as asynchronous operations, in a way that is ++ * transparent to the user of the socket object. The following example ++ * illustrates how Linux's @c sendfile system call might be encapsulated: ++ * @code template ++ * struct sendfile_op ++ * { ++ * tcp::socket& sock_; ++ * int fd_; ++ * Handler handler_; ++ * off_t offset_; ++ * std::size_t total_bytes_transferred_; ++ * ++ * // Function call operator meeting WriteHandler requirements. ++ * // Used as the handler for the async_write_some operation. ++ * void operator()(boost::system::error_code ec, std::size_t) ++ * { ++ * // Put the underlying socket into non-blocking mode. ++ * if (!ec) ++ * if (!sock_.native_non_blocking()) ++ * sock_.native_non_blocking(true, ec); ++ * ++ * if (!ec) ++ * { ++ * for (;;) ++ * { ++ * // Try the system call. ++ * errno = 0; ++ * int n = ::sendfile(sock_.native_handle(), fd_, &offset_, 65536); ++ * ec = boost::system::error_code(n < 0 ? errno : 0, ++ * boost::asio::error::get_system_category()); ++ * total_bytes_transferred_ += ec ? 0 : n; ++ * ++ * // Retry operation immediately if interrupted by signal. ++ * if (ec == boost::asio::error::interrupted) ++ * continue; ++ * ++ * // Check if we need to run the operation again. ++ * if (ec == boost::asio::error::would_block ++ * || ec == boost::asio::error::try_again) ++ * { ++ * // We have to wait for the socket to become ready again. ++ * sock_.async_wait(tcp::socket::wait_write, *this); ++ * return; ++ * } ++ * ++ * if (ec || n == 0) ++ * { ++ * // An error occurred, or we have reached the end of the file. ++ * // Either way we must exit the loop so we can call the handler. ++ * break; ++ * } ++ * ++ * // Loop around to try calling sendfile again. ++ * } ++ * } ++ * ++ * // Pass result back to user's handler. ++ * handler_(ec, total_bytes_transferred_); ++ * } ++ * }; ++ * ++ * template ++ * void async_sendfile(tcp::socket& sock, int fd, Handler h) ++ * { ++ * sendfile_op op = { sock, fd, h, 0, 0 }; ++ * sock.async_wait(tcp::socket::wait_write, op); ++ * } @endcode ++ */ ++ void native_non_blocking(bool mode) ++ { ++ boost::system::error_code ec; ++ impl_.get_service().native_non_blocking( ++ impl_.get_implementation(), mode, ec); ++ boost::asio::detail::throw_error(ec, "native_non_blocking"); ++ } ++ ++ /// Sets the non-blocking mode of the native socket implementation. ++ /** ++ * This function is used to modify the non-blocking mode of the underlying ++ * native socket. It has no effect on the behaviour of the socket object's ++ * synchronous operations. ++ * ++ * @param mode If @c true, the underlying socket is put into non-blocking ++ * mode and direct system calls may fail with boost::asio::error::would_block ++ * (or the equivalent system error). ++ * ++ * @param ec Set to indicate what error occurred, if any. If the @c mode is ++ * @c false, but the current value of @c non_blocking() is @c true, this ++ * function fails with boost::asio::error::invalid_argument, as the ++ * combination does not make sense. ++ * ++ * @par Example ++ * This function is intended to allow the encapsulation of arbitrary ++ * non-blocking system calls as asynchronous operations, in a way that is ++ * transparent to the user of the socket object. The following example ++ * illustrates how Linux's @c sendfile system call might be encapsulated: ++ * @code template ++ * struct sendfile_op ++ * { ++ * tcp::socket& sock_; ++ * int fd_; ++ * Handler handler_; ++ * off_t offset_; ++ * std::size_t total_bytes_transferred_; ++ * ++ * // Function call operator meeting WriteHandler requirements. ++ * // Used as the handler for the async_write_some operation. ++ * void operator()(boost::system::error_code ec, std::size_t) ++ * { ++ * // Put the underlying socket into non-blocking mode. ++ * if (!ec) ++ * if (!sock_.native_non_blocking()) ++ * sock_.native_non_blocking(true, ec); ++ * ++ * if (!ec) ++ * { ++ * for (;;) ++ * { ++ * // Try the system call. ++ * errno = 0; ++ * int n = ::sendfile(sock_.native_handle(), fd_, &offset_, 65536); ++ * ec = boost::system::error_code(n < 0 ? errno : 0, ++ * boost::asio::error::get_system_category()); ++ * total_bytes_transferred_ += ec ? 0 : n; ++ * ++ * // Retry operation immediately if interrupted by signal. ++ * if (ec == boost::asio::error::interrupted) ++ * continue; ++ * ++ * // Check if we need to run the operation again. ++ * if (ec == boost::asio::error::would_block ++ * || ec == boost::asio::error::try_again) ++ * { ++ * // We have to wait for the socket to become ready again. ++ * sock_.async_wait(tcp::socket::wait_write, *this); ++ * return; ++ * } ++ * ++ * if (ec || n == 0) ++ * { ++ * // An error occurred, or we have reached the end of the file. ++ * // Either way we must exit the loop so we can call the handler. ++ * break; ++ * } ++ * ++ * // Loop around to try calling sendfile again. ++ * } ++ * } ++ * ++ * // Pass result back to user's handler. ++ * handler_(ec, total_bytes_transferred_); ++ * } ++ * }; ++ * ++ * template ++ * void async_sendfile(tcp::socket& sock, int fd, Handler h) ++ * { ++ * sendfile_op op = { sock, fd, h, 0, 0 }; ++ * sock.async_wait(tcp::socket::wait_write, op); ++ * } @endcode ++ */ ++ BOOST_ASIO_SYNC_OP_VOID native_non_blocking( ++ bool mode, boost::system::error_code& ec) ++ { ++ impl_.get_service().native_non_blocking( ++ impl_.get_implementation(), mode, ec); ++ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); ++ } ++ ++ /// Get the local endpoint of the socket. ++ /** ++ * This function is used to obtain the locally bound endpoint of the socket. ++ * ++ * @returns An object that represents the local endpoint of the socket. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ * ++ * @par Example ++ * @code ++ * boost::asio::ip::tcp::socket socket(my_context); ++ * ... ++ * boost::asio::ip::tcp::endpoint endpoint = socket.local_endpoint(); ++ * @endcode ++ */ ++ endpoint_type local_endpoint() const ++ { ++ boost::system::error_code ec; ++ endpoint_type ep = impl_.get_service().local_endpoint( ++ impl_.get_implementation(), ec); ++ boost::asio::detail::throw_error(ec, "local_endpoint"); ++ return ep; ++ } ++ ++ /// Get the local endpoint of the socket. ++ /** ++ * This function is used to obtain the locally bound endpoint of the socket. ++ * ++ * @param ec Set to indicate what error occurred, if any. ++ * ++ * @returns An object that represents the local endpoint of the socket. ++ * Returns a default-constructed endpoint object if an error occurred. ++ * ++ * @par Example ++ * @code ++ * boost::asio::ip::tcp::socket socket(my_context); ++ * ... ++ * boost::system::error_code ec; ++ * boost::asio::ip::tcp::endpoint endpoint = socket.local_endpoint(ec); ++ * if (ec) ++ * { ++ * // An error occurred. ++ * } ++ * @endcode ++ */ ++ endpoint_type local_endpoint(boost::system::error_code& ec) const ++ { ++ return impl_.get_service().local_endpoint(impl_.get_implementation(), ec); ++ } ++ ++ /// Get the remote endpoint of the socket. ++ /** ++ * This function is used to obtain the remote endpoint of the socket. ++ * ++ * @returns An object that represents the remote endpoint of the socket. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ * ++ * @par Example ++ * @code ++ * boost::asio::ip::tcp::socket socket(my_context); ++ * ... ++ * boost::asio::ip::tcp::endpoint endpoint = socket.remote_endpoint(); ++ * @endcode ++ */ ++ endpoint_type remote_endpoint() const ++ { ++ boost::system::error_code ec; ++ endpoint_type ep = impl_.get_service().remote_endpoint( ++ impl_.get_implementation(), ec); ++ boost::asio::detail::throw_error(ec, "remote_endpoint"); ++ return ep; ++ } ++ ++ /// Get the remote endpoint of the socket. ++ /** ++ * This function is used to obtain the remote endpoint of the socket. ++ * ++ * @param ec Set to indicate what error occurred, if any. ++ * ++ * @returns An object that represents the remote endpoint of the socket. ++ * Returns a default-constructed endpoint object if an error occurred. ++ * ++ * @par Example ++ * @code ++ * boost::asio::ip::tcp::socket socket(my_context); ++ * ... ++ * boost::system::error_code ec; ++ * boost::asio::ip::tcp::endpoint endpoint = socket.remote_endpoint(ec); ++ * if (ec) ++ * { ++ * // An error occurred. ++ * } ++ * @endcode ++ */ ++ endpoint_type remote_endpoint(boost::system::error_code& ec) const ++ { ++ return impl_.get_service().remote_endpoint(impl_.get_implementation(), ec); ++ } ++ ++ /// Disable sends or receives on the socket. ++ /** ++ * This function is used to disable send operations, receive operations, or ++ * both. ++ * ++ * @param what Determines what types of operation will no longer be allowed. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ * ++ * @par Example ++ * Shutting down the send side of the socket: ++ * @code ++ * boost::asio::ip::tcp::socket socket(my_context); ++ * ... ++ * socket.shutdown(boost::asio::ip::tcp::socket::shutdown_send); ++ * @endcode ++ */ ++ void shutdown(shutdown_type what) ++ { ++ boost::system::error_code ec; ++ impl_.get_service().shutdown(impl_.get_implementation(), what, ec); ++ boost::asio::detail::throw_error(ec, "shutdown"); ++ } ++ ++ /// Disable sends or receives on the socket. ++ /** ++ * This function is used to disable send operations, receive operations, or ++ * both. ++ * ++ * @param what Determines what types of operation will no longer be allowed. ++ * ++ * @param ec Set to indicate what error occurred, if any. ++ * ++ * @par Example ++ * Shutting down the send side of the socket: ++ * @code ++ * boost::asio::ip::tcp::socket socket(my_context); ++ * ... ++ * boost::system::error_code ec; ++ * socket.shutdown(boost::asio::ip::tcp::socket::shutdown_send, ec); ++ * if (ec) ++ * { ++ * // An error occurred. ++ * } ++ * @endcode ++ */ ++ BOOST_ASIO_SYNC_OP_VOID shutdown(shutdown_type what, ++ boost::system::error_code& ec) ++ { ++ impl_.get_service().shutdown(impl_.get_implementation(), what, ec); ++ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); ++ } ++ ++ /// Wait for the socket to become ready to read, ready to write, or to have ++ /// pending error conditions. ++ /** ++ * This function is used to perform a blocking wait for a socket to enter ++ * a ready to read, write or error condition state. ++ * ++ * @param w Specifies the desired socket state. ++ * ++ * @par Example ++ * Waiting for a socket to become readable. ++ * @code ++ * boost::asio::ip::tcp::socket socket(my_context); ++ * ... ++ * socket.wait(boost::asio::ip::tcp::socket::wait_read); ++ * @endcode ++ */ ++ void wait(wait_type w) ++ { ++ boost::system::error_code ec; ++ impl_.get_service().wait(impl_.get_implementation(), w, ec); ++ boost::asio::detail::throw_error(ec, "wait"); ++ } ++ ++ /// Wait for the socket to become ready to read, ready to write, or to have ++ /// pending error conditions. ++ /** ++ * This function is used to perform a blocking wait for a socket to enter ++ * a ready to read, write or error condition state. ++ * ++ * @param w Specifies the desired socket state. ++ * ++ * @param ec Set to indicate what error occurred, if any. ++ * ++ * @par Example ++ * Waiting for a socket to become readable. ++ * @code ++ * boost::asio::ip::tcp::socket socket(my_context); ++ * ... ++ * boost::system::error_code ec; ++ * socket.wait(boost::asio::ip::tcp::socket::wait_read, ec); ++ * @endcode ++ */ ++ BOOST_ASIO_SYNC_OP_VOID wait(wait_type w, boost::system::error_code& ec) ++ { ++ impl_.get_service().wait(impl_.get_implementation(), w, ec); ++ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); ++ } ++ ++ /// Asynchronously wait for the socket to become ready to read, ready to ++ /// write, or to have pending error conditions. ++ /** ++ * This function is used to perform an asynchronous wait for a socket to enter ++ * a ready to read, write or error condition state. ++ * ++ * @param w Specifies the desired socket state. ++ * ++ * @param handler The handler to be called when the wait operation completes. ++ * Copies will be made of the handler as required. The function signature of ++ * the handler must be: ++ * @code void handler( ++ * const boost::system::error_code& error // Result of operation ++ * ); @endcode ++ * Regardless of whether the asynchronous operation completes immediately or ++ * not, the handler will not be invoked from within this function. On ++ * immediate completion, invocation of the handler will be performed in a ++ * manner equivalent to using boost::asio::post(). ++ * ++ * @par Example ++ * @code ++ * void wait_handler(const boost::system::error_code& error) ++ * { ++ * if (!error) ++ * { ++ * // Wait succeeded. ++ * } ++ * } ++ * ++ * ... ++ * ++ * boost::asio::ip::tcp::socket socket(my_context); ++ * ... ++ * socket.async_wait(boost::asio::ip::tcp::socket::wait_read, wait_handler); ++ * @endcode ++ */ ++ template ++ BOOST_ASIO_INITFN_RESULT_TYPE(WaitHandler, ++ void (boost::system::error_code)) ++ async_wait(wait_type w, BOOST_ASIO_MOVE_ARG(WaitHandler) handler) ++ { ++ return async_initiate( ++ initiate_async_wait(), handler, this, w); ++ } ++ ++protected: ++ /// Protected destructor to prevent deletion through this type. ++ /** ++ * This function destroys the socket, cancelling any outstanding asynchronous ++ * operations associated with the socket as if by calling @c cancel. ++ */ ++ ~basic_socket_ext() ++ { ++ } ++ ++#if defined(BOOST_ASIO_WINDOWS_RUNTIME) ++ detail::io_object_impl< ++ detail::null_socket_service, Executor> impl_; ++#elif defined(BOOST_ASIO_HAS_IOCP) ++ detail::io_object_impl< ++ detail::win_iocp_socket_service, Executor> impl_; ++#else ++ detail::io_object_impl< ++ detail::reactive_socket_service_ext, Executor> impl_; ++#endif ++ ++private: ++ // Disallow copying and assignment. ++ basic_socket_ext(const basic_socket_ext&) BOOST_ASIO_DELETED; ++ basic_socket_ext& operator=(const basic_socket_ext&) BOOST_ASIO_DELETED; ++ ++ struct initiate_async_connect ++ { ++ template ++ void operator()(BOOST_ASIO_MOVE_ARG(ConnectHandler) handler, ++ basic_socket_ext* self, const endpoint_type& peer_endpoint, ++ const boost::system::error_code& open_ec) const ++ { ++ // If you get an error on the following line it means that your handler ++ // does not meet the documented type requirements for a ConnectHandler. ++ BOOST_ASIO_CONNECT_HANDLER_CHECK(ConnectHandler, handler) type_check; ++ ++ if (open_ec) ++ { ++ boost::asio::post(self->impl_.get_executor(), ++ boost::asio::detail::bind_handler( ++ BOOST_ASIO_MOVE_CAST(ConnectHandler)(handler), open_ec)); ++ } ++ else ++ { ++ detail::non_const_lvalue handler2(handler); ++ self->impl_.get_service().async_connect( ++ self->impl_.get_implementation(), peer_endpoint, ++ handler2.value, self->impl_.get_implementation_executor()); ++ } ++ } ++ }; ++ ++ struct initiate_async_wait ++ { ++ template ++ void operator()(BOOST_ASIO_MOVE_ARG(WaitHandler) handler, ++ basic_socket_ext* self, wait_type w) const ++ { ++ // If you get an error on the following line it means that your handler ++ // does not meet the documented type requirements for a WaitHandler. ++ BOOST_ASIO_WAIT_HANDLER_CHECK(WaitHandler, handler) type_check; ++ ++ detail::non_const_lvalue handler2(handler); ++ self->impl_.get_service().async_wait( ++ self->impl_.get_implementation(), w, handler2.value, ++ self->impl_.get_implementation_executor()); ++ } ++ }; ++}; ++ ++} // namespace asio ++} // namespace boost ++ ++#include ++ ++#endif // BOOST_ASIO_BASIC_SOCKET_EXT_HPP +diff --git a/implementation/helper/1.76/boost/asio/basic_socket_ext_local.hpp b/implementation/helper/1.76/boost/asio/basic_socket_ext_local.hpp +new file mode 100644 +index 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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#if defined(BOOST_ASIO_WINDOWS_RUNTIME) ++# include ++#elif defined(BOOST_ASIO_HAS_IOCP) ++# include ++#else ++# include ++#endif ++ ++#if defined(BOOST_ASIO_HAS_MOVE) ++# include ++#endif // defined(BOOST_ASIO_HAS_MOVE) ++ ++#include ++ ++namespace boost { ++namespace asio { ++ ++#if !defined(BOOST_ASIO_BASIC_SOCKET_EXT_LOCAL_FWD_DECL) ++#define BOOST_ASIO_BASIC_SOCKET_EXT_LOCAL_FWD_DECL ++ ++// Forward declaration with defaulted arguments. ++template ++class basic_socket_ext_local; ++ ++#endif // !defined(BOOST_ASIO_BASIC_SOCKET_EXT_LOCAL_FWD_DECL) ++ ++/// Provides socket functionality. ++/** ++ * The basic_socket class template provides functionality that is common to both ++ * stream-oriented and datagram-oriented sockets. ++ * ++ * @par Thread Safety ++ * @e Distinct @e objects: Safe.@n ++ * @e Shared @e objects: Unsafe. ++ */ ++template ++class basic_socket_ext_local ++ : public socket_base ++{ ++public: ++ /// The type of the executor associated with the object. ++ typedef Executor executor_type; ++ ++ /// Rebinds the socket type to another executor. ++ template ++ struct rebind_executor ++ { ++ /// The socket type when rebound to the specified executor. ++ typedef basic_socket_ext_local other; ++ }; ++ ++ /// The native representation of a socket. ++#if defined(GENERATING_DOCUMENTATION) ++ typedef implementation_defined native_handle_type; ++#elif defined(BOOST_ASIO_WINDOWS_RUNTIME) ++ typedef typename detail::null_socket_service< ++ Protocol>::native_handle_type native_handle_type; ++#elif defined(BOOST_ASIO_HAS_IOCP) ++ typedef typename detail::win_iocp_socket_service< ++ Protocol>::native_handle_type native_handle_type; ++#else ++ typedef typename detail::reactive_socket_service_ext_local< ++ Protocol>::native_handle_type native_handle_type; ++#endif ++ ++ /// The protocol type. ++ typedef Protocol protocol_type; ++ ++ /// The endpoint type. ++ typedef typename Protocol::endpoint endpoint_type; ++ ++#if !defined(BOOST_ASIO_NO_EXTENSIONS) ++ /// A basic_socket is always the lowest layer. ++ typedef basic_socket_ext_local lowest_layer_type; ++#endif // !defined(BOOST_ASIO_NO_EXTENSIONS) ++ ++ /// Construct a basic_socket without opening it. ++ /** ++ * This constructor creates a socket without opening it. ++ * ++ * @param ex The I/O executor that the socket will use, by default, to ++ * dispatch handlers for any asynchronous operations performed on the socket. ++ */ ++ explicit basic_socket_ext_local(const executor_type& ex) ++ : impl_(0, ex) ++ { ++ } ++ ++ /// Construct a basic_socket without opening it. ++ /** ++ * This constructor creates a socket without opening it. ++ * ++ * @param context An execution context which provides the I/O executor that ++ * the socket will use, by default, to dispatch handlers for any asynchronous ++ * operations performed on the socket. ++ */ ++ template ++ explicit basic_socket_ext_local(ExecutionContext& context, ++ typename enable_if< ++ is_convertible::value ++ >::type* = 0) ++ : impl_(0, 0, context) ++ { ++ } ++ ++ /// Construct and open a basic_socket. ++ /** ++ * This constructor creates and opens a socket. ++ * ++ * @param ex The I/O executor that the socket will use, by default, to ++ * dispatch handlers for any asynchronous operations performed on the socket. ++ * ++ * @param protocol An object specifying protocol parameters to be used. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ */ ++ basic_socket_ext_local(const executor_type& ex, const protocol_type& protocol) ++ : impl_(0, ex) ++ { ++ boost::system::error_code ec; ++ impl_.get_service().open(impl_.get_implementation(), protocol, ec); ++ boost::asio::detail::throw_error(ec, "open"); ++ } ++ ++ /// Construct and open a basic_socket. ++ /** ++ * This constructor creates and opens a socket. ++ * ++ * @param context An execution context which provides the I/O executor that ++ * the socket will use, by default, to dispatch handlers for any asynchronous ++ * operations performed on the socket. ++ * ++ * @param protocol An object specifying protocol parameters to be used. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ */ ++ template ++ basic_socket_ext_local(ExecutionContext& context, const protocol_type& protocol, ++ typename enable_if< ++ is_convertible::value ++ >::type* = 0) ++ : impl_(0, 0, context) ++ { ++ boost::system::error_code ec; ++ impl_.get_service().open(impl_.get_implementation(), protocol, ec); ++ boost::asio::detail::throw_error(ec, "open"); ++ } ++ ++ /// Construct a basic_socket, opening it and binding it to the given local ++ /// endpoint. ++ /** ++ * This constructor creates a socket and automatically opens it bound to the ++ * specified endpoint on the local machine. The protocol used is the protocol ++ * associated with the given endpoint. ++ * ++ * @param ex The I/O executor that the socket will use, by default, to ++ * dispatch handlers for any asynchronous operations performed on the socket. ++ * ++ * @param endpoint An endpoint on the local machine to which the socket will ++ * be bound. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ */ ++ basic_socket_ext_local(const executor_type& ex, const endpoint_type& endpoint) ++ : impl_(0, ex) ++ { ++ boost::system::error_code ec; ++ const protocol_type protocol = endpoint.protocol(); ++ impl_.get_service().open(impl_.get_implementation(), protocol, ec); ++ boost::asio::detail::throw_error(ec, "open"); ++ impl_.get_service().bind(impl_.get_implementation(), endpoint, ec); ++ boost::asio::detail::throw_error(ec, "bind"); ++ } ++ ++ /// Construct a basic_socket, opening it and binding it to the given local ++ /// endpoint. ++ /** ++ * This constructor creates a socket and automatically opens it bound to the ++ * specified endpoint on the local machine. The protocol used is the protocol ++ * associated with the given endpoint. ++ * ++ * @param context An execution context which provides the I/O executor that ++ * the socket will use, by default, to dispatch handlers for any asynchronous ++ * operations performed on the socket. ++ * ++ * @param endpoint An endpoint on the local machine to which the socket will ++ * be bound. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ */ ++ template ++ basic_socket_ext_local(ExecutionContext& context, const endpoint_type& endpoint, ++ typename enable_if< ++ is_convertible::value ++ >::type* = 0) ++ : impl_(0, 0, context) ++ { ++ boost::system::error_code ec; ++ const protocol_type protocol = endpoint.protocol(); ++ impl_.get_service().open(impl_.get_implementation(), protocol, ec); ++ boost::asio::detail::throw_error(ec, "open"); ++ impl_.get_service().bind(impl_.get_implementation(), endpoint, ec); ++ boost::asio::detail::throw_error(ec, "bind"); ++ } ++ ++ /// Construct a basic_socket on an existing native socket. ++ /** ++ * This constructor creates a socket object to hold an existing native socket. ++ * ++ * @param ex The I/O executor that the socket will use, by default, to ++ * dispatch handlers for any asynchronous operations performed on the socket. ++ * ++ * @param protocol An object specifying protocol parameters to be used. ++ * ++ * @param native_socket A native socket. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ */ ++ basic_socket_ext_local(const executor_type& ex, const protocol_type& protocol, ++ const native_handle_type& native_socket) ++ : impl_(0, ex) ++ { ++ boost::system::error_code ec; ++ impl_.get_service().assign(impl_.get_implementation(), ++ protocol, native_socket, ec); ++ boost::asio::detail::throw_error(ec, "assign"); ++ } ++ ++ /// Construct a basic_socket on an existing native socket. ++ /** ++ * This constructor creates a socket object to hold an existing native socket. ++ * ++ * @param context An execution context which provides the I/O executor that ++ * the socket will use, by default, to dispatch handlers for any asynchronous ++ * operations performed on the socket. ++ * ++ * @param protocol An object specifying protocol parameters to be used. ++ * ++ * @param native_socket A native socket. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ */ ++ template ++ basic_socket_ext_local(ExecutionContext& context, const protocol_type& protocol, ++ const native_handle_type& native_socket, ++ typename enable_if< ++ is_convertible::value ++ >::type* = 0) ++ : impl_(0, 0, context) ++ { ++ boost::system::error_code ec; ++ impl_.get_service().assign(impl_.get_implementation(), ++ protocol, native_socket, ec); ++ boost::asio::detail::throw_error(ec, "assign"); ++ } ++ ++#if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) ++ /// Move-construct a basic_socket from another. ++ /** ++ * This constructor moves a socket from one object to another. ++ * ++ * @param other The other basic_socket object from which the move will ++ * occur. ++ * ++ * @note Following the move, the moved-from object is in the same state as if ++ * constructed using the @c basic_socket(const executor_type&) constructor. ++ */ ++ basic_socket_ext_local(basic_socket_ext_local&& other) ++ : impl_(std::move(other.impl_)) ++ { ++ } ++ ++ /// Move-assign a basic_socket from another. ++ /** ++ * This assignment operator moves a socket from one object to another. ++ * ++ * @param other The other basic_socket object from which the move will ++ * occur. ++ * ++ * @note Following the move, the moved-from object is in the same state as if ++ * constructed using the @c basic_socket(const executor_type&) constructor. ++ */ ++ basic_socket_ext_local& operator=(basic_socket_ext_local&& other) ++ { ++ impl_ = std::move(other.impl_); ++ return *this; ++ } ++ ++ // All sockets have access to each other's implementations. ++ template ++ friend class basic_socket_ext_local; ++ ++ /// Move-construct a basic_socket from a socket of another protocol type. ++ /** ++ * This constructor moves a socket from one object to another. ++ * ++ * @param other The other basic_socket object from which the move will ++ * occur. ++ * ++ * @note Following the move, the moved-from object is in the same state as if ++ * constructed using the @c basic_socket(const executor_type&) constructor. ++ */ ++ template ++ basic_socket_ext_local(basic_socket_ext_local&& other, ++ typename enable_if< ++ is_convertible::value ++ && is_convertible::value ++ >::type* = 0) ++ : impl_(std::move(other.impl_)) ++ { ++ } ++ ++ /// Move-assign a basic_socket from a socket of another protocol type. ++ /** ++ * This assignment operator moves a socket from one object to another. ++ * ++ * @param other The other basic_socket object from which the move will ++ * occur. ++ * ++ * @note Following the move, the moved-from object is in the same state as if ++ * constructed using the @c basic_socket(const executor_type&) constructor. ++ */ ++ template ++ typename enable_if< ++ is_convertible::value ++ && is_convertible::value, ++ basic_socket_ext_local& ++ >::type operator=(basic_socket_ext_local && other) ++ { ++ basic_socket_ext_local tmp(std::move(other)); ++ impl_ = std::move(tmp.impl_); ++ return *this; ++ } ++#endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) ++ ++ /// Get the executor associated with the object. ++ executor_type get_executor() BOOST_ASIO_NOEXCEPT ++ { ++ return impl_.get_executor(); ++ } ++ ++#if !defined(BOOST_ASIO_NO_EXTENSIONS) ++ /// Get a reference to the lowest layer. ++ /** ++ * This function returns a reference to the lowest layer in a stack of ++ * layers. Since a basic_socket cannot contain any further layers, it simply ++ * returns a reference to itself. ++ * ++ * @return A reference to the lowest layer in the stack of layers. Ownership ++ * is not transferred to the caller. ++ */ ++ lowest_layer_type& lowest_layer() ++ { ++ return *this; ++ } ++ ++ /// Get a const reference to the lowest layer. ++ /** ++ * This function returns a const reference to the lowest layer in a stack of ++ * layers. Since a basic_socket cannot contain any further layers, it simply ++ * returns a reference to itself. ++ * ++ * @return A const reference to the lowest layer in the stack of layers. ++ * Ownership is not transferred to the caller. ++ */ ++ const lowest_layer_type& lowest_layer() const ++ { ++ return *this; ++ } ++#endif // !defined(BOOST_ASIO_NO_EXTENSIONS) ++ ++ /// Open the socket using the specified protocol. ++ /** ++ * This function opens the socket so that it will use the specified protocol. ++ * ++ * @param protocol An object specifying protocol parameters to be used. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ * ++ * @par Example ++ * @code ++ * boost::asio::ip::tcp::socket socket(my_context); ++ * socket.open(boost::asio::ip::tcp::v4()); ++ * @endcode ++ */ ++ void open(const protocol_type& protocol = protocol_type()) ++ { ++ boost::system::error_code ec; ++ impl_.get_service().open(impl_.get_implementation(), protocol, ec); ++ boost::asio::detail::throw_error(ec, "open"); ++ } ++ ++ /// Open the socket using the specified protocol. ++ /** ++ * This function opens the socket so that it will use the specified protocol. ++ * ++ * @param protocol An object specifying which protocol is to be used. ++ * ++ * @param ec Set to indicate what error occurred, if any. ++ * ++ * @par Example ++ * @code ++ * boost::asio::ip::tcp::socket socket(my_context); ++ * boost::system::error_code ec; ++ * socket.open(boost::asio::ip::tcp::v4(), ec); ++ * if (ec) ++ * { ++ * // An error occurred. ++ * } ++ * @endcode ++ */ ++ BOOST_ASIO_SYNC_OP_VOID open(const protocol_type& protocol, ++ boost::system::error_code& ec) ++ { ++ impl_.get_service().open(impl_.get_implementation(), protocol, ec); ++ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); ++ } ++ ++ /// Assign an existing native socket to the socket. ++ /* ++ * This function opens the socket to hold an existing native socket. ++ * ++ * @param protocol An object specifying which protocol is to be used. ++ * ++ * @param native_socket A native socket. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ */ ++ void assign(const protocol_type& protocol, ++ const native_handle_type& native_socket) ++ { ++ boost::system::error_code ec; ++ impl_.get_service().assign(impl_.get_implementation(), ++ protocol, native_socket, ec); ++ boost::asio::detail::throw_error(ec, "assign"); ++ } ++ ++ /// Assign an existing native socket to the socket. ++ /* ++ * This function opens the socket to hold an existing native socket. ++ * ++ * @param protocol An object specifying which protocol is to be used. ++ * ++ * @param native_socket A native socket. ++ * ++ * @param ec Set to indicate what error occurred, if any. ++ */ ++ BOOST_ASIO_SYNC_OP_VOID assign(const protocol_type& protocol, ++ const native_handle_type& native_socket, boost::system::error_code& ec) ++ { ++ impl_.get_service().assign(impl_.get_implementation(), ++ protocol, native_socket, ec); ++ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); ++ } ++ ++ /// Determine whether the socket is open. ++ bool is_open() const ++ { ++ return impl_.get_service().is_open(impl_.get_implementation()); ++ } ++ ++ /// Close the socket. ++ /** ++ * This function is used to close the socket. Any asynchronous send, receive ++ * or connect operations will be cancelled immediately, and will complete ++ * with the boost::asio::error::operation_aborted error. ++ * ++ * @throws boost::system::system_error Thrown on failure. Note that, even if ++ * the function indicates an error, the underlying descriptor is closed. ++ * ++ * @note For portable behaviour with respect to graceful closure of a ++ * connected socket, call shutdown() before closing the socket. ++ */ ++ void close() ++ { ++ boost::system::error_code ec; ++ impl_.get_service().close(impl_.get_implementation(), ec); ++ boost::asio::detail::throw_error(ec, "close"); ++ } ++ ++ /// Close the socket. ++ /** ++ * This function is used to close the socket. Any asynchronous send, receive ++ * or connect operations will be cancelled immediately, and will complete ++ * with the boost::asio::error::operation_aborted error. ++ * ++ * @param ec Set to indicate what error occurred, if any. Note that, even if ++ * the function indicates an error, the underlying descriptor is closed. ++ * ++ * @par Example ++ * @code ++ * boost::asio::ip::tcp::socket socket(my_context); ++ * ... ++ * boost::system::error_code ec; ++ * socket.close(ec); ++ * if (ec) ++ * { ++ * // An error occurred. ++ * } ++ * @endcode ++ * ++ * @note For portable behaviour with respect to graceful closure of a ++ * connected socket, call shutdown() before closing the socket. ++ */ ++ BOOST_ASIO_SYNC_OP_VOID close(boost::system::error_code& ec) ++ { ++ impl_.get_service().close(impl_.get_implementation(), ec); ++ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); ++ } ++ ++ /// Release ownership of the underlying native socket. ++ /** ++ * This function causes all outstanding asynchronous connect, send and receive ++ * operations to finish immediately, and the handlers for cancelled operations ++ * will be passed the boost::asio::error::operation_aborted error. Ownership ++ * of the native socket is then transferred to the caller. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ * ++ * @note This function is unsupported on Windows versions prior to Windows ++ * 8.1, and will fail with boost::asio::error::operation_not_supported on ++ * these platforms. ++ */ ++#if defined(BOOST_ASIO_MSVC) && (BOOST_ASIO_MSVC >= 1400) \ ++ && (!defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0603) ++ __declspec(deprecated("This function always fails with " ++ "operation_not_supported when used on Windows versions " ++ "prior to Windows 8.1.")) ++#endif ++ native_handle_type release() ++ { ++ boost::system::error_code ec; ++ native_handle_type s = impl_.get_service().release( ++ impl_.get_implementation(), ec); ++ boost::asio::detail::throw_error(ec, "release"); ++ return s; ++ } ++ ++ /// Release ownership of the underlying native socket. ++ /** ++ * This function causes all outstanding asynchronous connect, send and receive ++ * operations to finish immediately, and the handlers for cancelled operations ++ * will be passed the boost::asio::error::operation_aborted error. Ownership ++ * of the native socket is then transferred to the caller. ++ * ++ * @param ec Set to indicate what error occurred, if any. ++ * ++ * @note This function is unsupported on Windows versions prior to Windows ++ * 8.1, and will fail with boost::asio::error::operation_not_supported on ++ * these platforms. ++ */ ++#if defined(BOOST_ASIO_MSVC) && (BOOST_ASIO_MSVC >= 1400) \ ++ && (!defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0603) ++ __declspec(deprecated("This function always fails with " ++ "operation_not_supported when used on Windows versions " ++ "prior to Windows 8.1.")) ++#endif ++ native_handle_type release(boost::system::error_code& ec) ++ { ++ return impl_.get_service().release(impl_.get_implementation(), ec); ++ } ++ ++ /// Get the native socket representation. ++ /** ++ * This function may be used to obtain the underlying representation of the ++ * socket. This is intended to allow access to native socket functionality ++ * that is not otherwise provided. ++ */ ++ native_handle_type native_handle() ++ { ++ return impl_.get_service().native_handle(impl_.get_implementation()); ++ } ++ ++ /// Cancel all asynchronous operations associated with the socket. ++ /** ++ * This function causes all outstanding asynchronous connect, send and receive ++ * operations to finish immediately, and the handlers for cancelled operations ++ * will be passed the boost::asio::error::operation_aborted error. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ * ++ * @note Calls to cancel() will always fail with ++ * boost::asio::error::operation_not_supported when run on Windows XP, Windows ++ * Server 2003, and earlier versions of Windows, unless ++ * BOOST_ASIO_ENABLE_CANCELIO is defined. However, the CancelIo function has ++ * two issues that should be considered before enabling its use: ++ * ++ * @li It will only cancel asynchronous operations that were initiated in the ++ * current thread. ++ * ++ * @li It can appear to complete without error, but the request to cancel the ++ * unfinished operations may be silently ignored by the operating system. ++ * Whether it works or not seems to depend on the drivers that are installed. ++ * ++ * For portable cancellation, consider using one of the following ++ * alternatives: ++ * ++ * @li Disable asio's I/O completion port backend by defining ++ * BOOST_ASIO_DISABLE_IOCP. ++ * ++ * @li Use the close() function to simultaneously cancel the outstanding ++ * operations and close the socket. ++ * ++ * When running on Windows Vista, Windows Server 2008, and later, the ++ * CancelIoEx function is always used. This function does not have the ++ * problems described above. ++ */ ++#if defined(BOOST_ASIO_MSVC) && (BOOST_ASIO_MSVC >= 1400) \ ++ && (!defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0600) \ ++ && !defined(BOOST_ASIO_ENABLE_CANCELIO) ++ __declspec(deprecated("By default, this function always fails with " ++ "operation_not_supported when used on Windows XP, Windows Server 2003, " ++ "or earlier. Consult documentation for details.")) ++#endif ++ void cancel() ++ { ++ boost::system::error_code ec; ++ impl_.get_service().cancel(impl_.get_implementation(), ec); ++ boost::asio::detail::throw_error(ec, "cancel"); ++ } ++ ++ /// Cancel all asynchronous operations associated with the socket. ++ /** ++ * This function causes all outstanding asynchronous connect, send and receive ++ * operations to finish immediately, and the handlers for cancelled operations ++ * will be passed the boost::asio::error::operation_aborted error. ++ * ++ * @param ec Set to indicate what error occurred, if any. ++ * ++ * @note Calls to cancel() will always fail with ++ * boost::asio::error::operation_not_supported when run on Windows XP, Windows ++ * Server 2003, and earlier versions of Windows, unless ++ * BOOST_ASIO_ENABLE_CANCELIO is defined. However, the CancelIo function has ++ * two issues that should be considered before enabling its use: ++ * ++ * @li It will only cancel asynchronous operations that were initiated in the ++ * current thread. ++ * ++ * @li It can appear to complete without error, but the request to cancel the ++ * unfinished operations may be silently ignored by the operating system. ++ * Whether it works or not seems to depend on the drivers that are installed. ++ * ++ * For portable cancellation, consider using one of the following ++ * alternatives: ++ * ++ * @li Disable asio's I/O completion port backend by defining ++ * BOOST_ASIO_DISABLE_IOCP. ++ * ++ * @li Use the close() function to simultaneously cancel the outstanding ++ * operations and close the socket. ++ * ++ * When running on Windows Vista, Windows Server 2008, and later, the ++ * CancelIoEx function is always used. This function does not have the ++ * problems described above. ++ */ ++#if defined(BOOST_ASIO_MSVC) && (BOOST_ASIO_MSVC >= 1400) \ ++ && (!defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0600) \ ++ && !defined(BOOST_ASIO_ENABLE_CANCELIO) ++ __declspec(deprecated("By default, this function always fails with " ++ "operation_not_supported when used on Windows XP, Windows Server 2003, " ++ "or earlier. Consult documentation for details.")) ++#endif ++ BOOST_ASIO_SYNC_OP_VOID cancel(boost::system::error_code& ec) ++ { ++ impl_.get_service().cancel(impl_.get_implementation(), ec); ++ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); ++ } ++ ++ /// Determine whether the socket is at the out-of-band data mark. ++ /** ++ * This function is used to check whether the socket input is currently ++ * positioned at the out-of-band data mark. ++ * ++ * @return A bool indicating whether the socket is at the out-of-band data ++ * mark. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ */ ++ bool at_mark() const ++ { ++ boost::system::error_code ec; ++ bool b = impl_.get_service().at_mark(impl_.get_implementation(), ec); ++ boost::asio::detail::throw_error(ec, "at_mark"); ++ return b; ++ } ++ ++ /// Determine whether the socket is at the out-of-band data mark. ++ /** ++ * This function is used to check whether the socket input is currently ++ * positioned at the out-of-band data mark. ++ * ++ * @param ec Set to indicate what error occurred, if any. ++ * ++ * @return A bool indicating whether the socket is at the out-of-band data ++ * mark. ++ */ ++ bool at_mark(boost::system::error_code& ec) const ++ { ++ return impl_.get_service().at_mark(impl_.get_implementation(), ec); ++ } ++ ++ /// Determine the number of bytes available for reading. ++ /** ++ * This function is used to determine the number of bytes that may be read ++ * without blocking. ++ * ++ * @return The number of bytes that may be read without blocking, or 0 if an ++ * error occurs. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ */ ++ std::size_t available() const ++ { ++ boost::system::error_code ec; ++ std::size_t s = impl_.get_service().available( ++ impl_.get_implementation(), ec); ++ boost::asio::detail::throw_error(ec, "available"); ++ return s; ++ } ++ ++ /// Determine the number of bytes available for reading. ++ /** ++ * This function is used to determine the number of bytes that may be read ++ * without blocking. ++ * ++ * @param ec Set to indicate what error occurred, if any. ++ * ++ * @return The number of bytes that may be read without blocking, or 0 if an ++ * error occurs. ++ */ ++ std::size_t available(boost::system::error_code& ec) const ++ { ++ return impl_.get_service().available(impl_.get_implementation(), ec); ++ } ++ ++ /// Bind the socket to the given local endpoint. ++ /** ++ * This function binds the socket to the specified endpoint on the local ++ * machine. ++ * ++ * @param endpoint An endpoint on the local machine to which the socket will ++ * be bound. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ * ++ * @par Example ++ * @code ++ * boost::asio::ip::tcp::socket socket(my_context); ++ * socket.open(boost::asio::ip::tcp::v4()); ++ * socket.bind(boost::asio::ip::tcp::endpoint( ++ * boost::asio::ip::tcp::v4(), 12345)); ++ * @endcode ++ */ ++ void bind(const endpoint_type& endpoint) ++ { ++ boost::system::error_code ec; ++ impl_.get_service().bind(impl_.get_implementation(), endpoint, ec); ++ boost::asio::detail::throw_error(ec, "bind"); ++ } ++ ++ /// Bind the socket to the given local endpoint. ++ /** ++ * This function binds the socket to the specified endpoint on the local ++ * machine. ++ * ++ * @param endpoint An endpoint on the local machine to which the socket will ++ * be bound. ++ * ++ * @param ec Set to indicate what error occurred, if any. ++ * ++ * @par Example ++ * @code ++ * boost::asio::ip::tcp::socket socket(my_context); ++ * socket.open(boost::asio::ip::tcp::v4()); ++ * boost::system::error_code ec; ++ * socket.bind(boost::asio::ip::tcp::endpoint( ++ * boost::asio::ip::tcp::v4(), 12345), ec); ++ * if (ec) ++ * { ++ * // An error occurred. ++ * } ++ * @endcode ++ */ ++ BOOST_ASIO_SYNC_OP_VOID bind(const endpoint_type& endpoint, ++ boost::system::error_code& ec) ++ { ++ impl_.get_service().bind(impl_.get_implementation(), endpoint, ec); ++ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); ++ } ++ ++ /// Connect the socket to the specified endpoint. ++ /** ++ * This function is used to connect a socket to the specified remote endpoint. ++ * The function call will block until the connection is successfully made or ++ * an error occurs. ++ * ++ * The socket is automatically opened if it is not already open. If the ++ * connect fails, and the socket was automatically opened, the socket is ++ * not returned to the closed state. ++ * ++ * @param peer_endpoint The remote endpoint to which the socket will be ++ * connected. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ * ++ * @par Example ++ * @code ++ * boost::asio::ip::tcp::socket socket(my_context); ++ * boost::asio::ip::tcp::endpoint endpoint( ++ * boost::asio::ip::address::from_string("1.2.3.4"), 12345); ++ * socket.connect(endpoint); ++ * @endcode ++ */ ++ void connect(const endpoint_type& peer_endpoint) ++ { ++ boost::system::error_code ec; ++ if (!is_open()) ++ { ++ impl_.get_service().open(impl_.get_implementation(), ++ peer_endpoint.protocol(), ec); ++ boost::asio::detail::throw_error(ec, "connect"); ++ } ++ impl_.get_service().connect(impl_.get_implementation(), peer_endpoint, ec); ++ boost::asio::detail::throw_error(ec, "connect"); ++ } ++ ++ /// Connect the socket to the specified endpoint. ++ /** ++ * This function is used to connect a socket to the specified remote endpoint. ++ * The function call will block until the connection is successfully made or ++ * an error occurs. ++ * ++ * The socket is automatically opened if it is not already open. If the ++ * connect fails, and the socket was automatically opened, the socket is ++ * not returned to the closed state. ++ * ++ * @param peer_endpoint The remote endpoint to which the socket will be ++ * connected. ++ * ++ * @param ec Set to indicate what error occurred, if any. ++ * ++ * @par Example ++ * @code ++ * boost::asio::ip::tcp::socket socket(my_context); ++ * boost::asio::ip::tcp::endpoint endpoint( ++ * boost::asio::ip::address::from_string("1.2.3.4"), 12345); ++ * boost::system::error_code ec; ++ * socket.connect(endpoint, ec); ++ * if (ec) ++ * { ++ * // An error occurred. ++ * } ++ * @endcode ++ */ ++ BOOST_ASIO_SYNC_OP_VOID connect(const endpoint_type& peer_endpoint, ++ boost::system::error_code& ec) ++ { ++ if (!is_open()) ++ { ++ impl_.get_service().open(impl_.get_implementation(), ++ peer_endpoint.protocol(), ec); ++ if (ec) ++ { ++ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); ++ } ++ } ++ ++ impl_.get_service().connect(impl_.get_implementation(), peer_endpoint, ec); ++ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); ++ } ++ ++ /// Start an asynchronous connect. ++ /** ++ * This function is used to asynchronously connect a socket to the specified ++ * remote endpoint. The function call always returns immediately. ++ * ++ * The socket is automatically opened if it is not already open. If the ++ * connect fails, and the socket was automatically opened, the socket is ++ * not returned to the closed state. ++ * ++ * @param peer_endpoint The remote endpoint to which the socket will be ++ * connected. Copies will be made of the endpoint object as required. ++ * ++ * @param handler The handler to be called when the connection operation ++ * completes. Copies will be made of the handler as required. The function ++ * signature of the handler must be: ++ * @code void handler( ++ * const boost::system::error_code& error // Result of operation ++ * ); @endcode ++ * Regardless of whether the asynchronous operation completes immediately or ++ * not, the handler will not be invoked from within this function. On ++ * immediate completion, invocation of the handler will be performed in a ++ * manner equivalent to using boost::asio::post(). ++ * ++ * @par Example ++ * @code ++ * void connect_handler(const boost::system::error_code& error) ++ * { ++ * if (!error) ++ * { ++ * // Connect succeeded. ++ * } ++ * } ++ * ++ * ... ++ * ++ * boost::asio::ip::tcp::socket socket(my_context); ++ * boost::asio::ip::tcp::endpoint endpoint( ++ * boost::asio::ip::address::from_string("1.2.3.4"), 12345); ++ * socket.async_connect(endpoint, connect_handler); ++ * @endcode ++ */ ++ template ++ BOOST_ASIO_INITFN_RESULT_TYPE(ConnectHandler, ++ void (boost::system::error_code)) ++ async_connect(const endpoint_type& peer_endpoint, ++ BOOST_ASIO_MOVE_ARG(ConnectHandler) handler) ++ { ++ boost::system::error_code open_ec; ++ if (!is_open()) ++ { ++ const protocol_type protocol = peer_endpoint.protocol(); ++ impl_.get_service().open(impl_.get_implementation(), protocol, open_ec); ++ } ++ ++ return async_initiate( ++ initiate_async_connect(), handler, this, peer_endpoint, open_ec); ++ } ++ ++ /// Set an option on the socket. ++ /** ++ * This function is used to set an option on the socket. ++ * ++ * @param option The new option value to be set on the socket. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ * ++ * @sa SettableSocketOption @n ++ * boost::asio::socket_base::broadcast @n ++ * boost::asio::socket_base::do_not_route @n ++ * boost::asio::socket_base::keep_alive @n ++ * boost::asio::socket_base::linger @n ++ * boost::asio::socket_base::receive_buffer_size @n ++ * boost::asio::socket_base::receive_low_watermark @n ++ * boost::asio::socket_base::reuse_address @n ++ * boost::asio::socket_base::send_buffer_size @n ++ * boost::asio::socket_base::send_low_watermark @n ++ * boost::asio::ip::multicast::join_group @n ++ * boost::asio::ip::multicast::leave_group @n ++ * boost::asio::ip::multicast::enable_loopback @n ++ * boost::asio::ip::multicast::outbound_interface @n ++ * boost::asio::ip::multicast::hops @n ++ * boost::asio::ip::tcp::no_delay ++ * ++ * @par Example ++ * Setting the IPPROTO_TCP/TCP_NODELAY option: ++ * @code ++ * boost::asio::ip::tcp::socket socket(my_context); ++ * ... ++ * boost::asio::ip::tcp::no_delay option(true); ++ * socket.set_option(option); ++ * @endcode ++ */ ++ template ++ void set_option(const SettableSocketOption& option) ++ { ++ boost::system::error_code ec; ++ impl_.get_service().set_option(impl_.get_implementation(), option, ec); ++ boost::asio::detail::throw_error(ec, "set_option"); ++ } ++ ++ /// Set an option on the socket. ++ /** ++ * This function is used to set an option on the socket. ++ * ++ * @param option The new option value to be set on the socket. ++ * ++ * @param ec Set to indicate what error occurred, if any. ++ * ++ * @sa SettableSocketOption @n ++ * boost::asio::socket_base::broadcast @n ++ * boost::asio::socket_base::do_not_route @n ++ * boost::asio::socket_base::keep_alive @n ++ * boost::asio::socket_base::linger @n ++ * boost::asio::socket_base::receive_buffer_size @n ++ * boost::asio::socket_base::receive_low_watermark @n ++ * boost::asio::socket_base::reuse_address @n ++ * boost::asio::socket_base::send_buffer_size @n ++ * boost::asio::socket_base::send_low_watermark @n ++ * boost::asio::ip::multicast::join_group @n ++ * boost::asio::ip::multicast::leave_group @n ++ * boost::asio::ip::multicast::enable_loopback @n ++ * boost::asio::ip::multicast::outbound_interface @n ++ * boost::asio::ip::multicast::hops @n ++ * boost::asio::ip::tcp::no_delay ++ * ++ * @par Example ++ * Setting the IPPROTO_TCP/TCP_NODELAY option: ++ * @code ++ * boost::asio::ip::tcp::socket socket(my_context); ++ * ... ++ * boost::asio::ip::tcp::no_delay option(true); ++ * boost::system::error_code ec; ++ * socket.set_option(option, ec); ++ * if (ec) ++ * { ++ * // An error occurred. ++ * } ++ * @endcode ++ */ ++ template ++ BOOST_ASIO_SYNC_OP_VOID set_option(const SettableSocketOption& option, ++ boost::system::error_code& ec) ++ { ++ impl_.get_service().set_option(impl_.get_implementation(), option, ec); ++ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); ++ } ++ ++ /// Get an option from the socket. ++ /** ++ * This function is used to get the current value of an option on the socket. ++ * ++ * @param option The option value to be obtained from the socket. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ * ++ * @sa GettableSocketOption @n ++ * boost::asio::socket_base::broadcast @n ++ * boost::asio::socket_base::do_not_route @n ++ * boost::asio::socket_base::keep_alive @n ++ * boost::asio::socket_base::linger @n ++ * boost::asio::socket_base::receive_buffer_size @n ++ * boost::asio::socket_base::receive_low_watermark @n ++ * boost::asio::socket_base::reuse_address @n ++ * boost::asio::socket_base::send_buffer_size @n ++ * boost::asio::socket_base::send_low_watermark @n ++ * boost::asio::ip::multicast::join_group @n ++ * boost::asio::ip::multicast::leave_group @n ++ * boost::asio::ip::multicast::enable_loopback @n ++ * boost::asio::ip::multicast::outbound_interface @n ++ * boost::asio::ip::multicast::hops @n ++ * boost::asio::ip::tcp::no_delay ++ * ++ * @par Example ++ * Getting the value of the SOL_SOCKET/SO_KEEPALIVE option: ++ * @code ++ * boost::asio::ip::tcp::socket socket(my_context); ++ * ... ++ * boost::asio::ip::tcp::socket::keep_alive option; ++ * socket.get_option(option); ++ * bool is_set = option.value(); ++ * @endcode ++ */ ++ template ++ void get_option(GettableSocketOption& option) const ++ { ++ boost::system::error_code ec; ++ impl_.get_service().get_option(impl_.get_implementation(), option, ec); ++ boost::asio::detail::throw_error(ec, "get_option"); ++ } ++ ++ /// Get an option from the socket. ++ /** ++ * This function is used to get the current value of an option on the socket. ++ * ++ * @param option The option value to be obtained from the socket. ++ * ++ * @param ec Set to indicate what error occurred, if any. ++ * ++ * @sa GettableSocketOption @n ++ * boost::asio::socket_base::broadcast @n ++ * boost::asio::socket_base::do_not_route @n ++ * boost::asio::socket_base::keep_alive @n ++ * boost::asio::socket_base::linger @n ++ * boost::asio::socket_base::receive_buffer_size @n ++ * boost::asio::socket_base::receive_low_watermark @n ++ * boost::asio::socket_base::reuse_address @n ++ * boost::asio::socket_base::send_buffer_size @n ++ * boost::asio::socket_base::send_low_watermark @n ++ * boost::asio::ip::multicast::join_group @n ++ * boost::asio::ip::multicast::leave_group @n ++ * boost::asio::ip::multicast::enable_loopback @n ++ * boost::asio::ip::multicast::outbound_interface @n ++ * boost::asio::ip::multicast::hops @n ++ * boost::asio::ip::tcp::no_delay ++ * ++ * @par Example ++ * Getting the value of the SOL_SOCKET/SO_KEEPALIVE option: ++ * @code ++ * boost::asio::ip::tcp::socket socket(my_context); ++ * ... ++ * boost::asio::ip::tcp::socket::keep_alive option; ++ * boost::system::error_code ec; ++ * socket.get_option(option, ec); ++ * if (ec) ++ * { ++ * // An error occurred. ++ * } ++ * bool is_set = option.value(); ++ * @endcode ++ */ ++ template ++ BOOST_ASIO_SYNC_OP_VOID get_option(GettableSocketOption& option, ++ boost::system::error_code& ec) const ++ { ++ impl_.get_service().get_option(impl_.get_implementation(), option, ec); ++ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); ++ } ++ ++ /// Perform an IO control command on the socket. ++ /** ++ * This function is used to execute an IO control command on the socket. ++ * ++ * @param command The IO control command to be performed on the socket. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ * ++ * @sa IoControlCommand @n ++ * boost::asio::socket_base::bytes_readable @n ++ * boost::asio::socket_base::non_blocking_io ++ * ++ * @par Example ++ * Getting the number of bytes ready to read: ++ * @code ++ * boost::asio::ip::tcp::socket socket(my_context); ++ * ... ++ * boost::asio::ip::tcp::socket::bytes_readable command; ++ * socket.io_control(command); ++ * std::size_t bytes_readable = command.get(); ++ * @endcode ++ */ ++ template ++ void io_control(IoControlCommand& command) ++ { ++ boost::system::error_code ec; ++ impl_.get_service().io_control(impl_.get_implementation(), command, ec); ++ boost::asio::detail::throw_error(ec, "io_control"); ++ } ++ ++ /// Perform an IO control command on the socket. ++ /** ++ * This function is used to execute an IO control command on the socket. ++ * ++ * @param command The IO control command to be performed on the socket. ++ * ++ * @param ec Set to indicate what error occurred, if any. ++ * ++ * @sa IoControlCommand @n ++ * boost::asio::socket_base::bytes_readable @n ++ * boost::asio::socket_base::non_blocking_io ++ * ++ * @par Example ++ * Getting the number of bytes ready to read: ++ * @code ++ * boost::asio::ip::tcp::socket socket(my_context); ++ * ... ++ * boost::asio::ip::tcp::socket::bytes_readable command; ++ * boost::system::error_code ec; ++ * socket.io_control(command, ec); ++ * if (ec) ++ * { ++ * // An error occurred. ++ * } ++ * std::size_t bytes_readable = command.get(); ++ * @endcode ++ */ ++ template ++ BOOST_ASIO_SYNC_OP_VOID io_control(IoControlCommand& command, ++ boost::system::error_code& ec) ++ { ++ impl_.get_service().io_control(impl_.get_implementation(), command, ec); ++ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); ++ } ++ ++ /// Gets the non-blocking mode of the socket. ++ /** ++ * @returns @c true if the socket's synchronous operations will fail with ++ * boost::asio::error::would_block if they are unable to perform the requested ++ * operation immediately. If @c false, synchronous operations will block ++ * until complete. ++ * ++ * @note The non-blocking mode has no effect on the behaviour of asynchronous ++ * operations. Asynchronous operations will never fail with the error ++ * boost::asio::error::would_block. ++ */ ++ bool non_blocking() const ++ { ++ return impl_.get_service().non_blocking(impl_.get_implementation()); ++ } ++ ++ /// Sets the non-blocking mode of the socket. ++ /** ++ * @param mode If @c true, the socket's synchronous operations will fail with ++ * boost::asio::error::would_block if they are unable to perform the requested ++ * operation immediately. If @c false, synchronous operations will block ++ * until complete. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ * ++ * @note The non-blocking mode has no effect on the behaviour of asynchronous ++ * operations. Asynchronous operations will never fail with the error ++ * boost::asio::error::would_block. ++ */ ++ void non_blocking(bool mode) ++ { ++ boost::system::error_code ec; ++ impl_.get_service().non_blocking(impl_.get_implementation(), mode, ec); ++ boost::asio::detail::throw_error(ec, "non_blocking"); ++ } ++ ++ /// Sets the non-blocking mode of the socket. ++ /** ++ * @param mode If @c true, the socket's synchronous operations will fail with ++ * boost::asio::error::would_block if they are unable to perform the requested ++ * operation immediately. If @c false, synchronous operations will block ++ * until complete. ++ * ++ * @param ec Set to indicate what error occurred, if any. ++ * ++ * @note The non-blocking mode has no effect on the behaviour of asynchronous ++ * operations. Asynchronous operations will never fail with the error ++ * boost::asio::error::would_block. ++ */ ++ BOOST_ASIO_SYNC_OP_VOID non_blocking( ++ bool mode, boost::system::error_code& ec) ++ { ++ impl_.get_service().non_blocking(impl_.get_implementation(), mode, ec); ++ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); ++ } ++ ++ /// Gets the non-blocking mode of the native socket implementation. ++ /** ++ * This function is used to retrieve the non-blocking mode of the underlying ++ * native socket. This mode has no effect on the behaviour of the socket ++ * object's synchronous operations. ++ * ++ * @returns @c true if the underlying socket is in non-blocking mode and ++ * direct system calls may fail with boost::asio::error::would_block (or the ++ * equivalent system error). ++ * ++ * @note The current non-blocking mode is cached by the socket object. ++ * Consequently, the return value may be incorrect if the non-blocking mode ++ * was set directly on the native socket. ++ * ++ * @par Example ++ * This function is intended to allow the encapsulation of arbitrary ++ * non-blocking system calls as asynchronous operations, in a way that is ++ * transparent to the user of the socket object. The following example ++ * illustrates how Linux's @c sendfile system call might be encapsulated: ++ * @code template ++ * struct sendfile_op ++ * { ++ * tcp::socket& sock_; ++ * int fd_; ++ * Handler handler_; ++ * off_t offset_; ++ * std::size_t total_bytes_transferred_; ++ * ++ * // Function call operator meeting WriteHandler requirements. ++ * // Used as the handler for the async_write_some operation. ++ * void operator()(boost::system::error_code ec, std::size_t) ++ * { ++ * // Put the underlying socket into non-blocking mode. ++ * if (!ec) ++ * if (!sock_.native_non_blocking()) ++ * sock_.native_non_blocking(true, ec); ++ * ++ * if (!ec) ++ * { ++ * for (;;) ++ * { ++ * // Try the system call. ++ * errno = 0; ++ * int n = ::sendfile(sock_.native_handle(), fd_, &offset_, 65536); ++ * ec = boost::system::error_code(n < 0 ? errno : 0, ++ * boost::asio::error::get_system_category()); ++ * total_bytes_transferred_ += ec ? 0 : n; ++ * ++ * // Retry operation immediately if interrupted by signal. ++ * if (ec == boost::asio::error::interrupted) ++ * continue; ++ * ++ * // Check if we need to run the operation again. ++ * if (ec == boost::asio::error::would_block ++ * || ec == boost::asio::error::try_again) ++ * { ++ * // We have to wait for the socket to become ready again. ++ * sock_.async_wait(tcp::socket::wait_write, *this); ++ * return; ++ * } ++ * ++ * if (ec || n == 0) ++ * { ++ * // An error occurred, or we have reached the end of the file. ++ * // Either way we must exit the loop so we can call the handler. ++ * break; ++ * } ++ * ++ * // Loop around to try calling sendfile again. ++ * } ++ * } ++ * ++ * // Pass result back to user's handler. ++ * handler_(ec, total_bytes_transferred_); ++ * } ++ * }; ++ * ++ * template ++ * void async_sendfile(tcp::socket& sock, int fd, Handler h) ++ * { ++ * sendfile_op op = { sock, fd, h, 0, 0 }; ++ * sock.async_wait(tcp::socket::wait_write, op); ++ * } @endcode ++ */ ++ bool native_non_blocking() const ++ { ++ return impl_.get_service().native_non_blocking(impl_.get_implementation()); ++ } ++ ++ /// Sets the non-blocking mode of the native socket implementation. ++ /** ++ * This function is used to modify the non-blocking mode of the underlying ++ * native socket. It has no effect on the behaviour of the socket object's ++ * synchronous operations. ++ * ++ * @param mode If @c true, the underlying socket is put into non-blocking ++ * mode and direct system calls may fail with boost::asio::error::would_block ++ * (or the equivalent system error). ++ * ++ * @throws boost::system::system_error Thrown on failure. If the @c mode is ++ * @c false, but the current value of @c non_blocking() is @c true, this ++ * function fails with boost::asio::error::invalid_argument, as the ++ * combination does not make sense. ++ * ++ * @par Example ++ * This function is intended to allow the encapsulation of arbitrary ++ * non-blocking system calls as asynchronous operations, in a way that is ++ * transparent to the user of the socket object. The following example ++ * illustrates how Linux's @c sendfile system call might be encapsulated: ++ * @code template ++ * struct sendfile_op ++ * { ++ * tcp::socket& sock_; ++ * int fd_; ++ * Handler handler_; ++ * off_t offset_; ++ * std::size_t total_bytes_transferred_; ++ * ++ * // Function call operator meeting WriteHandler requirements. ++ * // Used as the handler for the async_write_some operation. ++ * void operator()(boost::system::error_code ec, std::size_t) ++ * { ++ * // Put the underlying socket into non-blocking mode. ++ * if (!ec) ++ * if (!sock_.native_non_blocking()) ++ * sock_.native_non_blocking(true, ec); ++ * ++ * if (!ec) ++ * { ++ * for (;;) ++ * { ++ * // Try the system call. ++ * errno = 0; ++ * int n = ::sendfile(sock_.native_handle(), fd_, &offset_, 65536); ++ * ec = boost::system::error_code(n < 0 ? errno : 0, ++ * boost::asio::error::get_system_category()); ++ * total_bytes_transferred_ += ec ? 0 : n; ++ * ++ * // Retry operation immediately if interrupted by signal. ++ * if (ec == boost::asio::error::interrupted) ++ * continue; ++ * ++ * // Check if we need to run the operation again. ++ * if (ec == boost::asio::error::would_block ++ * || ec == boost::asio::error::try_again) ++ * { ++ * // We have to wait for the socket to become ready again. ++ * sock_.async_wait(tcp::socket::wait_write, *this); ++ * return; ++ * } ++ * ++ * if (ec || n == 0) ++ * { ++ * // An error occurred, or we have reached the end of the file. ++ * // Either way we must exit the loop so we can call the handler. ++ * break; ++ * } ++ * ++ * // Loop around to try calling sendfile again. ++ * } ++ * } ++ * ++ * // Pass result back to user's handler. ++ * handler_(ec, total_bytes_transferred_); ++ * } ++ * }; ++ * ++ * template ++ * void async_sendfile(tcp::socket& sock, int fd, Handler h) ++ * { ++ * sendfile_op op = { sock, fd, h, 0, 0 }; ++ * sock.async_wait(tcp::socket::wait_write, op); ++ * } @endcode ++ */ ++ void native_non_blocking(bool mode) ++ { ++ boost::system::error_code ec; ++ impl_.get_service().native_non_blocking( ++ impl_.get_implementation(), mode, ec); ++ boost::asio::detail::throw_error(ec, "native_non_blocking"); ++ } ++ ++ /// Sets the non-blocking mode of the native socket implementation. ++ /** ++ * This function is used to modify the non-blocking mode of the underlying ++ * native socket. It has no effect on the behaviour of the socket object's ++ * synchronous operations. ++ * ++ * @param mode If @c true, the underlying socket is put into non-blocking ++ * mode and direct system calls may fail with boost::asio::error::would_block ++ * (or the equivalent system error). ++ * ++ * @param ec Set to indicate what error occurred, if any. If the @c mode is ++ * @c false, but the current value of @c non_blocking() is @c true, this ++ * function fails with boost::asio::error::invalid_argument, as the ++ * combination does not make sense. ++ * ++ * @par Example ++ * This function is intended to allow the encapsulation of arbitrary ++ * non-blocking system calls as asynchronous operations, in a way that is ++ * transparent to the user of the socket object. The following example ++ * illustrates how Linux's @c sendfile system call might be encapsulated: ++ * @code template ++ * struct sendfile_op ++ * { ++ * tcp::socket& sock_; ++ * int fd_; ++ * Handler handler_; ++ * off_t offset_; ++ * std::size_t total_bytes_transferred_; ++ * ++ * // Function call operator meeting WriteHandler requirements. ++ * // Used as the handler for the async_write_some operation. ++ * void operator()(boost::system::error_code ec, std::size_t) ++ * { ++ * // Put the underlying socket into non-blocking mode. ++ * if (!ec) ++ * if (!sock_.native_non_blocking()) ++ * sock_.native_non_blocking(true, ec); ++ * ++ * if (!ec) ++ * { ++ * for (;;) ++ * { ++ * // Try the system call. ++ * errno = 0; ++ * int n = ::sendfile(sock_.native_handle(), fd_, &offset_, 65536); ++ * ec = boost::system::error_code(n < 0 ? errno : 0, ++ * boost::asio::error::get_system_category()); ++ * total_bytes_transferred_ += ec ? 0 : n; ++ * ++ * // Retry operation immediately if interrupted by signal. ++ * if (ec == boost::asio::error::interrupted) ++ * continue; ++ * ++ * // Check if we need to run the operation again. ++ * if (ec == boost::asio::error::would_block ++ * || ec == boost::asio::error::try_again) ++ * { ++ * // We have to wait for the socket to become ready again. ++ * sock_.async_wait(tcp::socket::wait_write, *this); ++ * return; ++ * } ++ * ++ * if (ec || n == 0) ++ * { ++ * // An error occurred, or we have reached the end of the file. ++ * // Either way we must exit the loop so we can call the handler. ++ * break; ++ * } ++ * ++ * // Loop around to try calling sendfile again. ++ * } ++ * } ++ * ++ * // Pass result back to user's handler. ++ * handler_(ec, total_bytes_transferred_); ++ * } ++ * }; ++ * ++ * template ++ * void async_sendfile(tcp::socket& sock, int fd, Handler h) ++ * { ++ * sendfile_op op = { sock, fd, h, 0, 0 }; ++ * sock.async_wait(tcp::socket::wait_write, op); ++ * } @endcode ++ */ ++ BOOST_ASIO_SYNC_OP_VOID native_non_blocking( ++ bool mode, boost::system::error_code& ec) ++ { ++ impl_.get_service().native_non_blocking( ++ impl_.get_implementation(), mode, ec); ++ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); ++ } ++ ++ /// Get the local endpoint of the socket. ++ /** ++ * This function is used to obtain the locally bound endpoint of the socket. ++ * ++ * @returns An object that represents the local endpoint of the socket. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ * ++ * @par Example ++ * @code ++ * boost::asio::ip::tcp::socket socket(my_context); ++ * ... ++ * boost::asio::ip::tcp::endpoint endpoint = socket.local_endpoint(); ++ * @endcode ++ */ ++ endpoint_type local_endpoint() const ++ { ++ boost::system::error_code ec; ++ endpoint_type ep = impl_.get_service().local_endpoint( ++ impl_.get_implementation(), ec); ++ boost::asio::detail::throw_error(ec, "local_endpoint"); ++ return ep; ++ } ++ ++ /// Get the local endpoint of the socket. ++ /** ++ * This function is used to obtain the locally bound endpoint of the socket. ++ * ++ * @param ec Set to indicate what error occurred, if any. ++ * ++ * @returns An object that represents the local endpoint of the socket. ++ * Returns a default-constructed endpoint object if an error occurred. ++ * ++ * @par Example ++ * @code ++ * boost::asio::ip::tcp::socket socket(my_context); ++ * ... ++ * boost::system::error_code ec; ++ * boost::asio::ip::tcp::endpoint endpoint = socket.local_endpoint(ec); ++ * if (ec) ++ * { ++ * // An error occurred. ++ * } ++ * @endcode ++ */ ++ endpoint_type local_endpoint(boost::system::error_code& ec) const ++ { ++ return impl_.get_service().local_endpoint(impl_.get_implementation(), ec); ++ } ++ ++ /// Get the remote endpoint of the socket. ++ /** ++ * This function is used to obtain the remote endpoint of the socket. ++ * ++ * @returns An object that represents the remote endpoint of the socket. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ * ++ * @par Example ++ * @code ++ * boost::asio::ip::tcp::socket socket(my_context); ++ * ... ++ * boost::asio::ip::tcp::endpoint endpoint = socket.remote_endpoint(); ++ * @endcode ++ */ ++ endpoint_type remote_endpoint() const ++ { ++ boost::system::error_code ec; ++ endpoint_type ep = impl_.get_service().remote_endpoint( ++ impl_.get_implementation(), ec); ++ boost::asio::detail::throw_error(ec, "remote_endpoint"); ++ return ep; ++ } ++ ++ /// Get the remote endpoint of the socket. ++ /** ++ * This function is used to obtain the remote endpoint of the socket. ++ * ++ * @param ec Set to indicate what error occurred, if any. ++ * ++ * @returns An object that represents the remote endpoint of the socket. ++ * Returns a default-constructed endpoint object if an error occurred. ++ * ++ * @par Example ++ * @code ++ * boost::asio::ip::tcp::socket socket(my_context); ++ * ... ++ * boost::system::error_code ec; ++ * boost::asio::ip::tcp::endpoint endpoint = socket.remote_endpoint(ec); ++ * if (ec) ++ * { ++ * // An error occurred. ++ * } ++ * @endcode ++ */ ++ endpoint_type remote_endpoint(boost::system::error_code& ec) const ++ { ++ return impl_.get_service().remote_endpoint(impl_.get_implementation(), ec); ++ } ++ ++ /// Disable sends or receives on the socket. ++ /** ++ * This function is used to disable send operations, receive operations, or ++ * both. ++ * ++ * @param what Determines what types of operation will no longer be allowed. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ * ++ * @par Example ++ * Shutting down the send side of the socket: ++ * @code ++ * boost::asio::ip::tcp::socket socket(my_context); ++ * ... ++ * socket.shutdown(boost::asio::ip::tcp::socket::shutdown_send); ++ * @endcode ++ */ ++ void shutdown(shutdown_type what) ++ { ++ boost::system::error_code ec; ++ impl_.get_service().shutdown(impl_.get_implementation(), what, ec); ++ boost::asio::detail::throw_error(ec, "shutdown"); ++ } ++ ++ /// Disable sends or receives on the socket. ++ /** ++ * This function is used to disable send operations, receive operations, or ++ * both. ++ * ++ * @param what Determines what types of operation will no longer be allowed. ++ * ++ * @param ec Set to indicate what error occurred, if any. ++ * ++ * @par Example ++ * Shutting down the send side of the socket: ++ * @code ++ * boost::asio::ip::tcp::socket socket(my_context); ++ * ... ++ * boost::system::error_code ec; ++ * socket.shutdown(boost::asio::ip::tcp::socket::shutdown_send, ec); ++ * if (ec) ++ * { ++ * // An error occurred. ++ * } ++ * @endcode ++ */ ++ BOOST_ASIO_SYNC_OP_VOID shutdown(shutdown_type what, ++ boost::system::error_code& ec) ++ { ++ impl_.get_service().shutdown(impl_.get_implementation(), what, ec); ++ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); ++ } ++ ++ /// Wait for the socket to become ready to read, ready to write, or to have ++ /// pending error conditions. ++ /** ++ * This function is used to perform a blocking wait for a socket to enter ++ * a ready to read, write or error condition state. ++ * ++ * @param w Specifies the desired socket state. ++ * ++ * @par Example ++ * Waiting for a socket to become readable. ++ * @code ++ * boost::asio::ip::tcp::socket socket(my_context); ++ * ... ++ * socket.wait(boost::asio::ip::tcp::socket::wait_read); ++ * @endcode ++ */ ++ void wait(wait_type w) ++ { ++ boost::system::error_code ec; ++ impl_.get_service().wait(impl_.get_implementation(), w, ec); ++ boost::asio::detail::throw_error(ec, "wait"); ++ } ++ ++ /// Wait for the socket to become ready to read, ready to write, or to have ++ /// pending error conditions. ++ /** ++ * This function is used to perform a blocking wait for a socket to enter ++ * a ready to read, write or error condition state. ++ * ++ * @param w Specifies the desired socket state. ++ * ++ * @param ec Set to indicate what error occurred, if any. ++ * ++ * @par Example ++ * Waiting for a socket to become readable. ++ * @code ++ * boost::asio::ip::tcp::socket socket(my_context); ++ * ... ++ * boost::system::error_code ec; ++ * socket.wait(boost::asio::ip::tcp::socket::wait_read, ec); ++ * @endcode ++ */ ++ BOOST_ASIO_SYNC_OP_VOID wait(wait_type w, boost::system::error_code& ec) ++ { ++ impl_.get_service().wait(impl_.get_implementation(), w, ec); ++ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); ++ } ++ ++ /// Asynchronously wait for the socket to become ready to read, ready to ++ /// write, or to have pending error conditions. ++ /** ++ * This function is used to perform an asynchronous wait for a socket to enter ++ * a ready to read, write or error condition state. ++ * ++ * @param w Specifies the desired socket state. ++ * ++ * @param handler The handler to be called when the wait operation completes. ++ * Copies will be made of the handler as required. The function signature of ++ * the handler must be: ++ * @code void handler( ++ * const boost::system::error_code& error // Result of operation ++ * ); @endcode ++ * Regardless of whether the asynchronous operation completes immediately or ++ * not, the handler will not be invoked from within this function. On ++ * immediate completion, invocation of the handler will be performed in a ++ * manner equivalent to using boost::asio::post(). ++ * ++ * @par Example ++ * @code ++ * void wait_handler(const boost::system::error_code& error) ++ * { ++ * if (!error) ++ * { ++ * // Wait succeeded. ++ * } ++ * } ++ * ++ * ... ++ * ++ * boost::asio::ip::tcp::socket socket(my_context); ++ * ... ++ * socket.async_wait(boost::asio::ip::tcp::socket::wait_read, wait_handler); ++ * @endcode ++ */ ++ template ++ BOOST_ASIO_INITFN_RESULT_TYPE(WaitHandler, ++ void (boost::system::error_code)) ++ async_wait(wait_type w, BOOST_ASIO_MOVE_ARG(WaitHandler) handler) ++ { ++ return async_initiate( ++ initiate_async_wait(), handler, this, w); ++ } ++ ++protected: ++ /// Protected destructor to prevent deletion through this type. ++ /** ++ * This function destroys the socket, cancelling any outstanding asynchronous ++ * operations associated with the socket as if by calling @c cancel. ++ */ ++ ~basic_socket_ext_local() ++ { ++ } ++ ++#if defined(BOOST_ASIO_WINDOWS_RUNTIME) ++ detail::io_object_impl< ++ detail::null_socket_service, Executor> impl_; ++#elif defined(BOOST_ASIO_HAS_IOCP) ++ detail::io_object_impl< ++ detail::win_iocp_socket_service, Executor> impl_; ++#else ++ detail::io_object_impl< ++ detail::reactive_socket_service_ext_local, Executor> impl_; ++#endif ++ ++private: ++ // Disallow copying and assignment. ++ basic_socket_ext_local(const basic_socket_ext_local&) BOOST_ASIO_DELETED; ++ basic_socket_ext_local& operator=(const basic_socket_ext_local&) BOOST_ASIO_DELETED; ++ ++ struct initiate_async_connect ++ { ++ template ++ void operator()(BOOST_ASIO_MOVE_ARG(ConnectHandler) handler, ++ basic_socket_ext_local* self, const endpoint_type& peer_endpoint, ++ const boost::system::error_code& open_ec) const ++ { ++ // If you get an error on the following line it means that your handler ++ // does not meet the documented type requirements for a ConnectHandler. ++ BOOST_ASIO_CONNECT_HANDLER_CHECK(ConnectHandler, handler) type_check; ++ ++ if (open_ec) ++ { ++ boost::asio::post(self->impl_.get_executor(), ++ boost::asio::detail::bind_handler( ++ BOOST_ASIO_MOVE_CAST(ConnectHandler)(handler), open_ec)); ++ } ++ else ++ { ++ detail::non_const_lvalue handler2(handler); ++ self->impl_.get_service().async_connect( ++ self->impl_.get_implementation(), peer_endpoint, ++ handler2.value, self->impl_.get_implementation_executor()); ++ } ++ } ++ }; ++ ++ struct initiate_async_wait ++ { ++ template ++ void operator()(BOOST_ASIO_MOVE_ARG(WaitHandler) handler, ++ basic_socket_ext_local* self, wait_type w) const ++ { ++ // If you get an error on the following line it means that your handler ++ // does not meet the documented type requirements for a WaitHandler. ++ BOOST_ASIO_WAIT_HANDLER_CHECK(WaitHandler, handler) type_check; ++ ++ detail::non_const_lvalue handler2(handler); ++ self->impl_.get_service().async_wait( ++ self->impl_.get_implementation(), w, handler2.value, ++ self->impl_.get_implementation_executor()); ++ } ++ }; ++}; ++ ++} // namespace asio ++} // namespace boost ++ ++#include ++ ++#endif // BOOST_ASIO_BASIC_SOCKET_EXT_LOCAL_HPP +diff --git a/implementation/helper/1.76/boost/asio/basic_stream_socket_ext.hpp b/implementation/helper/1.76/boost/asio/basic_stream_socket_ext.hpp +new file mode 100644 +index 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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++namespace boost { ++namespace asio { ++ ++#if !defined(BOOST_ASIO_BASIC_STREAM_SOCKET_EXT_FWD_DECL) ++#define BOOST_ASIO_BASIC_STREAM_SOCKET_EXT_FWD_DECL ++ ++// Forward declaration with defaulted arguments. ++template ++class basic_stream_socket_ext; ++ ++#endif // !defined(BOOST_ASIO_BASIC_STREAM_SOCKET_EXT_FWD_DECL) ++ ++/// Provides stream-oriented socket functionality. ++/** ++ * The basic_stream_socket_ext class template provides asynchronous and blocking ++ * stream-oriented socket functionality. ++ * ++ * @par Thread Safety ++ * @e Distinct @e objects: Safe.@n ++ * @e Shared @e objects: Unsafe. ++ * ++ * @par Concepts: ++ * AsyncReadStream, AsyncWriteStream, Stream, SyncReadStream, SyncWriteStream. ++ */ ++template ++class basic_stream_socket_ext ++ : public basic_socket_ext_local ++{ ++public: ++ /// The type of the executor associated with the object. ++ typedef Executor executor_type; ++ ++ /// Rebinds the socket type to another executor. ++ template ++ struct rebind_executor ++ { ++ /// The socket type when rebound to the specified executor. ++ typedef basic_stream_socket_ext other; ++ }; ++ ++ /// The native representation of a socket. ++#if defined(GENERATING_DOCUMENTATION) ++ typedef implementation_defined native_handle_type; ++#else ++ typedef typename basic_socket::native_handle_type native_handle_type; ++#endif ++ ++ /// The protocol type. ++ typedef Protocol protocol_type; ++ ++ /// The endpoint type. ++ typedef typename Protocol::endpoint endpoint_type; ++ ++ /// Construct a basic_stream_socket without opening it. ++ /** ++ * This constructor creates a stream socket without opening it. The socket ++ * needs to be opened and then connected or accepted before data can be sent ++ * or received on it. ++ * ++ * @param ex The I/O executor that the socket will use, by default, to ++ * dispatch handlers for any asynchronous operations performed on the socket. ++ */ ++ explicit basic_stream_socket_ext(const executor_type& ex) ++ : basic_socket_ext_local(ex) ++ { ++ } ++ ++ /// Construct a basic_stream_socket without opening it. ++ /** ++ * This constructor creates a stream socket without opening it. The socket ++ * needs to be opened and then connected or accepted before data can be sent ++ * or received on it. ++ * ++ * @param context An execution context which provides the I/O executor that ++ * the socket will use, by default, to dispatch handlers for any asynchronous ++ * operations performed on the socket. ++ */ ++ template ++ explicit basic_stream_socket_ext(ExecutionContext& context, ++ typename enable_if< ++ is_convertible::value ++ >::type* = 0) ++ : basic_socket_ext_local(context) ++ { ++ } ++ ++ /// Construct and open a basic_stream_socket. ++ /** ++ * This constructor creates and opens a stream socket. The socket needs to be ++ * connected or accepted before data can be sent or received on it. ++ * ++ * @param ex The I/O executor that the socket will use, by default, to ++ * dispatch handlers for any asynchronous operations performed on the socket. ++ * ++ * @param protocol An object specifying protocol parameters to be used. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ */ ++ basic_stream_socket_ext(const executor_type& ex, const protocol_type& protocol) ++ : basic_socket_ext_local(ex, protocol) ++ { ++ } ++ ++ /// Construct and open a basic_stream_socket. ++ /** ++ * This constructor creates and opens a stream socket. The socket needs to be ++ * connected or accepted before data can be sent or received on it. ++ * ++ * @param context An execution context which provides the I/O executor that ++ * the socket will use, by default, to dispatch handlers for any asynchronous ++ * operations performed on the socket. ++ * ++ * @param protocol An object specifying protocol parameters to be used. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ */ ++ template ++ basic_stream_socket_ext(ExecutionContext& context, const protocol_type& protocol, ++ typename enable_if< ++ is_convertible::value ++ >::type* = 0) ++ : basic_socket_ext_local(context, protocol) ++ { ++ } ++ ++ /// Construct a basic_stream_socket, opening it and binding it to the given ++ /// local endpoint. ++ /** ++ * This constructor creates a stream socket and automatically opens it bound ++ * to the specified endpoint on the local machine. The protocol used is the ++ * protocol associated with the given endpoint. ++ * ++ * @param ex The I/O executor that the socket will use, by default, to ++ * dispatch handlers for any asynchronous operations performed on the socket. ++ * ++ * @param endpoint An endpoint on the local machine to which the stream ++ * socket will be bound. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ */ ++ basic_stream_socket_ext(const executor_type& ex, const endpoint_type& endpoint) ++ : basic_socket_ext_local(ex, endpoint) ++ { ++ } ++ ++ /// Construct a basic_stream_socket, opening it and binding it to the given ++ /// local endpoint. ++ /** ++ * This constructor creates a stream socket and automatically opens it bound ++ * to the specified endpoint on the local machine. The protocol used is the ++ * protocol associated with the given endpoint. ++ * ++ * @param context An execution context which provides the I/O executor that ++ * the socket will use, by default, to dispatch handlers for any asynchronous ++ * operations performed on the socket. ++ * ++ * @param endpoint An endpoint on the local machine to which the stream ++ * socket will be bound. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ */ ++ template ++ basic_stream_socket_ext(ExecutionContext& context, const endpoint_type& endpoint, ++ typename enable_if< ++ is_convertible::value ++ >::type* = 0) ++ : basic_socket_ext_local(context, endpoint) ++ { ++ } ++ ++ /// Construct a basic_stream_socket on an existing native socket. ++ /** ++ * This constructor creates a stream socket object to hold an existing native ++ * socket. ++ * ++ * @param ex The I/O executor that the socket will use, by default, to ++ * dispatch handlers for any asynchronous operations performed on the socket. ++ * ++ * @param protocol An object specifying protocol parameters to be used. ++ * ++ * @param native_socket The new underlying socket implementation. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ */ ++ basic_stream_socket_ext(const executor_type& ex, ++ const protocol_type& protocol, const native_handle_type& native_socket) ++ : basic_socket_ext_local(ex, protocol, native_socket) ++ { ++ } ++ ++ /// Construct a basic_stream_socket on an existing native socket. ++ /** ++ * This constructor creates a stream socket object to hold an existing native ++ * socket. ++ * ++ * @param context An execution context which provides the I/O executor that ++ * the socket will use, by default, to dispatch handlers for any asynchronous ++ * operations performed on the socket. ++ * ++ * @param protocol An object specifying protocol parameters to be used. ++ * ++ * @param native_socket The new underlying socket implementation. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ */ ++ template ++ basic_stream_socket_ext(ExecutionContext& context, ++ const protocol_type& protocol, const native_handle_type& native_socket, ++ typename enable_if< ++ is_convertible::value ++ >::type* = 0) ++ : basic_socket_ext_local(context, protocol, native_socket) ++ { ++ } ++ ++#if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) ++ /// Move-construct a basic_stream_socket from another. ++ /** ++ * This constructor moves a stream socket from one object to another. ++ * ++ * @param other The other basic_stream_socket object from which the move ++ * will occur. ++ * ++ * @note Following the move, the moved-from object is in the same state as if ++ * constructed using the @c basic_stream_socket(const executor_type&) ++ * constructor. ++ */ ++ basic_stream_socket_ext(basic_stream_socket_ext&& other) ++ : basic_socket_ext_local(std::move(other)) ++ { ++ } ++ ++ /// Move-assign a basic_stream_socket from another. ++ /** ++ * This assignment operator moves a stream socket from one object to another. ++ * ++ * @param other The other basic_stream_socket object from which the move ++ * will occur. ++ * ++ * @note Following the move, the moved-from object is in the same state as if ++ * constructed using the @c basic_stream_socket(const executor_type&) ++ * constructor. ++ */ ++ basic_stream_socket_ext& operator=(basic_stream_socket_ext&& other) ++ { ++ basic_socket_ext_local::operator=(std::move(other)); ++ return *this; ++ } ++ ++ /// Move-construct a basic_stream_socket from a socket of another protocol ++ /// type. ++ /** ++ * This constructor moves a stream socket from one object to another. ++ * ++ * @param other The other basic_stream_socket object from which the move ++ * will occur. ++ * ++ * @note Following the move, the moved-from object is in the same state as if ++ * constructed using the @c basic_stream_socket(const executor_type&) ++ * constructor. ++ */ ++ template ++ basic_stream_socket_ext(basic_stream_socket_ext&& other, ++ typename enable_if< ++ is_convertible::value ++ && is_convertible::value ++ >::type* = 0) ++ : basic_socket_ext_local(std::move(other)) ++ { ++ } ++ ++ /// Move-assign a basic_stream_socket from a socket of another protocol type. ++ /** ++ * This assignment operator moves a stream socket from one object to another. ++ * ++ * @param other The other basic_stream_socket object from which the move ++ * will occur. ++ * ++ * @note Following the move, the moved-from object is in the same state as if ++ * constructed using the @c basic_stream_socket(const executor_type&) ++ * constructor. ++ */ ++ template ++ typename enable_if< ++ is_convertible::value ++ && is_convertible::value, ++ basic_stream_socket_ext& ++ >::type operator=(basic_stream_socket_ext&& other) ++ { ++ basic_socket_ext_local::operator=(std::move(other)); ++ return *this; ++ } ++#endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) ++ ++ /// Destroys the socket. ++ /** ++ * This function destroys the socket, cancelling any outstanding asynchronous ++ * operations associated with the socket as if by calling @c cancel. ++ */ ++ ~basic_stream_socket_ext() ++ { ++ } ++ ++ /// Send some data on the socket. ++ /** ++ * This function is used to send data on the stream socket. The function ++ * call will block until one or more bytes of the data has been sent ++ * successfully, or an until error occurs. ++ * ++ * @param buffers One or more data buffers to be sent on the socket. ++ * ++ * @returns The number of bytes sent. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ * ++ * @note The send operation may not transmit all of the data to the peer. ++ * Consider using the @ref write function if you need to ensure that all data ++ * is written before the blocking operation completes. ++ * ++ * @par Example ++ * To send a single data buffer use the @ref buffer function as follows: ++ * @code ++ * socket.send(boost::asio::buffer(data, size)); ++ * @endcode ++ * See the @ref buffer documentation for information on sending multiple ++ * buffers in one go, and how to use it with arrays, boost::array or ++ * std::vector. ++ */ ++ template ++ std::size_t send(const ConstBufferSequence& buffers) ++ { ++ boost::system::error_code ec; ++ std::size_t s = this->impl_.get_service().send( ++ this->impl_.get_implementation(), buffers, 0, ec); ++ boost::asio::detail::throw_error(ec, "send"); ++ return s; ++ } ++ ++ /// Send some data on the socket. ++ /** ++ * This function is used to send data on the stream socket. The function ++ * call will block until one or more bytes of the data has been sent ++ * successfully, or an until error occurs. ++ * ++ * @param buffers One or more data buffers to be sent on the socket. ++ * ++ * @param flags Flags specifying how the send call is to be made. ++ * ++ * @returns The number of bytes sent. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ * ++ * @note The send operation may not transmit all of the data to the peer. ++ * Consider using the @ref write function if you need to ensure that all data ++ * is written before the blocking operation completes. ++ * ++ * @par Example ++ * To send a single data buffer use the @ref buffer function as follows: ++ * @code ++ * socket.send(boost::asio::buffer(data, size), 0); ++ * @endcode ++ * See the @ref buffer documentation for information on sending multiple ++ * buffers in one go, and how to use it with arrays, boost::array or ++ * std::vector. ++ */ ++ template ++ std::size_t send(const ConstBufferSequence& buffers, ++ socket_base::message_flags flags) ++ { ++ boost::system::error_code ec; ++ std::size_t s = this->impl_.get_service().send( ++ this->impl_.get_implementation(), buffers, flags, ec); ++ boost::asio::detail::throw_error(ec, "send"); ++ return s; ++ } ++ ++ /// Send some data on the socket. ++ /** ++ * This function is used to send data on the stream socket. The function ++ * call will block until one or more bytes of the data has been sent ++ * successfully, or an until error occurs. ++ * ++ * @param buffers One or more data buffers to be sent on the socket. ++ * ++ * @param flags Flags specifying how the send call is to be made. ++ * ++ * @param ec Set to indicate what error occurred, if any. ++ * ++ * @returns The number of bytes sent. Returns 0 if an error occurred. ++ * ++ * @note The send operation may not transmit all of the data to the peer. ++ * Consider using the @ref write function if you need to ensure that all data ++ * is written before the blocking operation completes. ++ */ ++ template ++ std::size_t send(const ConstBufferSequence& buffers, ++ socket_base::message_flags flags, boost::system::error_code& ec) ++ { ++ return this->impl_.get_service().send( ++ this->impl_.get_implementation(), buffers, flags, ec); ++ } ++ ++ /// Start an asynchronous send. ++ /** ++ * This function is used to asynchronously send data on the stream socket. ++ * The function call always returns immediately. ++ * ++ * @param buffers One or more data buffers to be sent on the socket. Although ++ * the buffers object may be copied as necessary, ownership of the underlying ++ * memory blocks is retained by the caller, which must guarantee that they ++ * remain valid until the handler is called. ++ * ++ * @param handler The handler to be called when the send operation completes. ++ * Copies will be made of the handler as required. The function signature of ++ * the handler must be: ++ * @code void handler( ++ * const boost::system::error_code& error, // Result of operation. ++ * std::size_t bytes_transferred // Number of bytes sent. ++ * ); @endcode ++ * Regardless of whether the asynchronous operation completes immediately or ++ * not, the handler will not be invoked from within this function. On ++ * immediate completion, invocation of the handler will be performed in a ++ * manner equivalent to using boost::asio::post(). ++ * ++ * @note The send operation may not transmit all of the data to the peer. ++ * Consider using the @ref async_write function if you need to ensure that all ++ * data is written before the asynchronous operation completes. ++ * ++ * @par Example ++ * To send a single data buffer use the @ref buffer function as follows: ++ * @code ++ * socket.async_send(boost::asio::buffer(data, size), handler); ++ * @endcode ++ * See the @ref buffer documentation for information on sending multiple ++ * buffers in one go, and how to use it with arrays, boost::array or ++ * std::vector. ++ */ ++ template ++ BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler, ++ void (boost::system::error_code, std::size_t)) ++ async_send(const ConstBufferSequence& buffers, ++ BOOST_ASIO_MOVE_ARG(WriteHandler) handler) ++ { ++ return async_initiate( ++ initiate_async_send(), handler, this, ++ buffers, socket_base::message_flags(0)); ++ } ++ ++ /// Start an asynchronous send. ++ /** ++ * This function is used to asynchronously send data on the stream socket. ++ * The function call always returns immediately. ++ * ++ * @param buffers One or more data buffers to be sent on the socket. Although ++ * the buffers object may be copied as necessary, ownership of the underlying ++ * memory blocks is retained by the caller, which must guarantee that they ++ * remain valid until the handler is called. ++ * ++ * @param flags Flags specifying how the send call is to be made. ++ * ++ * @param handler The handler to be called when the send operation completes. ++ * Copies will be made of the handler as required. The function signature of ++ * the handler must be: ++ * @code void handler( ++ * const boost::system::error_code& error, // Result of operation. ++ * std::size_t bytes_transferred // Number of bytes sent. ++ * ); @endcode ++ * Regardless of whether the asynchronous operation completes immediately or ++ * not, the handler will not be invoked from within this function. On ++ * immediate completion, invocation of the handler will be performed in a ++ * manner equivalent to using boost::asio::post(). ++ * ++ * @note The send operation may not transmit all of the data to the peer. ++ * Consider using the @ref async_write function if you need to ensure that all ++ * data is written before the asynchronous operation completes. ++ * ++ * @par Example ++ * To send a single data buffer use the @ref buffer function as follows: ++ * @code ++ * socket.async_send(boost::asio::buffer(data, size), 0, handler); ++ * @endcode ++ * See the @ref buffer documentation for information on sending multiple ++ * buffers in one go, and how to use it with arrays, boost::array or ++ * std::vector. ++ */ ++ template ++ BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler, ++ void (boost::system::error_code, std::size_t)) ++ async_send(const ConstBufferSequence& buffers, ++ socket_base::message_flags flags, ++ BOOST_ASIO_MOVE_ARG(WriteHandler) handler) ++ { ++ return async_initiate( ++ initiate_async_send(), handler, this, buffers, flags); ++ } ++ ++ /// Receive some data on the socket. ++ /** ++ * This function is used to receive data on the stream socket. The function ++ * call will block until one or more bytes of data has been received ++ * successfully, or until an error occurs. ++ * ++ * @param buffers One or more buffers into which the data will be received. ++ * ++ * @returns The number of bytes received. ++ * ++ * @throws boost::system::system_error Thrown on failure. An error code of ++ * boost::asio::error::eof indicates that the connection was closed by the ++ * peer. ++ * ++ * @note The receive operation may not receive all of the requested number of ++ * bytes. Consider using the @ref read function if you need to ensure that the ++ * requested amount of data is read before the blocking operation completes. ++ * ++ * @par Example ++ * To receive into a single data buffer use the @ref buffer function as ++ * follows: ++ * @code ++ * socket.receive(boost::asio::buffer(data, size)); ++ * @endcode ++ * See the @ref buffer documentation for information on receiving into ++ * multiple buffers in one go, and how to use it with arrays, boost::array or ++ * std::vector. ++ */ ++ template ++ std::size_t receive(const MutableBufferSequence& buffers) ++ { ++ boost::system::error_code ec; ++ std::size_t s = this->impl_.get_service().receive( ++ this->impl_.get_implementation(), buffers, 0, ec); ++ boost::asio::detail::throw_error(ec, "receive"); ++ return s; ++ } ++ ++ /// Receive some data on the socket. ++ /** ++ * This function is used to receive data on the stream socket. The function ++ * call will block until one or more bytes of data has been received ++ * successfully, or until an error occurs. ++ * ++ * @param buffers One or more buffers into which the data will be received. ++ * ++ * @param flags Flags specifying how the receive call is to be made. ++ * ++ * @returns The number of bytes received. ++ * ++ * @throws boost::system::system_error Thrown on failure. An error code of ++ * boost::asio::error::eof indicates that the connection was closed by the ++ * peer. ++ * ++ * @note The receive operation may not receive all of the requested number of ++ * bytes. Consider using the @ref read function if you need to ensure that the ++ * requested amount of data is read before the blocking operation completes. ++ * ++ * @par Example ++ * To receive into a single data buffer use the @ref buffer function as ++ * follows: ++ * @code ++ * socket.receive(boost::asio::buffer(data, size), 0); ++ * @endcode ++ * See the @ref buffer documentation for information on receiving into ++ * multiple buffers in one go, and how to use it with arrays, boost::array or ++ * std::vector. ++ */ ++ template ++ std::size_t receive(const MutableBufferSequence& buffers, ++ socket_base::message_flags flags) ++ { ++ boost::system::error_code ec; ++ std::size_t s = this->impl_.get_service().receive( ++ this->impl_.get_implementation(), buffers, flags, ec); ++ boost::asio::detail::throw_error(ec, "receive"); ++ return s; ++ } ++ ++ /// Receive some data on a connected socket. ++ /** ++ * This function is used to receive data on the stream socket. The function ++ * call will block until one or more bytes of data has been received ++ * successfully, or until an error occurs. ++ * ++ * @param buffers One or more buffers into which the data will be received. ++ * ++ * @param flags Flags specifying how the receive call is to be made. ++ * ++ * @param ec Set to indicate what error occurred, if any. ++ * ++ * @returns The number of bytes received. Returns 0 if an error occurred. ++ * ++ * @note The receive operation may not receive all of the requested number of ++ * bytes. Consider using the @ref read function if you need to ensure that the ++ * requested amount of data is read before the blocking operation completes. ++ */ ++ template ++ std::size_t receive(const MutableBufferSequence& buffers, ++ socket_base::message_flags flags, boost::system::error_code& ec) ++ { ++ return this->impl_.get_service().receive( ++ this->impl_.get_implementation(), buffers, flags, ec); ++ } ++ ++ /// Start an asynchronous receive. ++ /** ++ * This function is used to asynchronously receive data from the stream ++ * socket. The function call always returns immediately. ++ * ++ * @param buffers One or more buffers into which the data will be received. ++ * Although the buffers object may be copied as necessary, ownership of the ++ * underlying memory blocks is retained by the caller, which must guarantee ++ * that they remain valid until the handler is called. ++ * ++ * @param handler The handler to be called when the receive operation ++ * completes. Copies will be made of the handler as required. The function ++ * signature of the handler must be: ++ * @code void handler( ++ * const boost::system::error_code& error, // Result of operation. ++ * std::size_t bytes_transferred // Number of bytes received. ++ * ); @endcode ++ * Regardless of whether the asynchronous operation completes immediately or ++ * not, the handler will not be invoked from within this function. On ++ * immediate completion, invocation of the handler will be performed in a ++ * manner equivalent to using boost::asio::post(). ++ * ++ * @note The receive operation may not receive all of the requested number of ++ * bytes. Consider using the @ref async_read function if you need to ensure ++ * that the requested amount of data is received before the asynchronous ++ * operation completes. ++ * ++ * @par Example ++ * To receive into a single data buffer use the @ref buffer function as ++ * follows: ++ * @code ++ * socket.async_receive(boost::asio::buffer(data, size), handler); ++ * @endcode ++ * See the @ref buffer documentation for information on receiving into ++ * multiple buffers in one go, and how to use it with arrays, boost::array or ++ * std::vector. ++ */ ++ template ++ BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler, ++ void (boost::system::error_code, std::size_t, std::uint32_t, std::uint32_t)) ++ async_receive(const MutableBufferSequence& buffers, ++ BOOST_ASIO_MOVE_ARG(ReadHandler) handler) ++ { ++ return async_initiate( ++ initiate_async_receive(), handler, this, ++ buffers, socket_base::message_flags(0)); ++ } ++ ++ /// Start an asynchronous receive. ++ /** ++ * This function is used to asynchronously receive data from the stream ++ * socket. The function call always returns immediately. ++ * ++ * @param buffers One or more buffers into which the data will be received. ++ * Although the buffers object may be copied as necessary, ownership of the ++ * underlying memory blocks is retained by the caller, which must guarantee ++ * that they remain valid until the handler is called. ++ * ++ * @param flags Flags specifying how the receive call is to be made. ++ * ++ * @param handler The handler to be called when the receive operation ++ * completes. Copies will be made of the handler as required. The function ++ * signature of the handler must be: ++ * @code void handler( ++ * const boost::system::error_code& error, // Result of operation. ++ * std::size_t bytes_transferred // Number of bytes received. ++ * ); @endcode ++ * Regardless of whether the asynchronous operation completes immediately or ++ * not, the handler will not be invoked from within this function. On ++ * immediate completion, invocation of the handler will be performed in a ++ * manner equivalent to using boost::asio::post(). ++ * ++ * @note The receive operation may not receive all of the requested number of ++ * bytes. Consider using the @ref async_read function if you need to ensure ++ * that the requested amount of data is received before the asynchronous ++ * operation completes. ++ * ++ * @par Example ++ * To receive into a single data buffer use the @ref buffer function as ++ * follows: ++ * @code ++ * socket.async_receive(boost::asio::buffer(data, size), 0, handler); ++ * @endcode ++ * See the @ref buffer documentation for information on receiving into ++ * multiple buffers in one go, and how to use it with arrays, boost::array or ++ * std::vector. ++ */ ++ template ++ BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler, ++ void (boost::system::error_code, std::size_t, std::uint32_t, std::uint32_t)) ++ async_receive(const MutableBufferSequence& buffers, ++ socket_base::message_flags flags, ++ BOOST_ASIO_MOVE_ARG(ReadHandler) handler) ++ { ++ return async_initiate( ++ initiate_async_receive(), handler, this, buffers, flags); ++ } ++ ++ /// Write some data to the socket. ++ /** ++ * This function is used to write data to the stream socket. The function call ++ * will block until one or more bytes of the data has been written ++ * successfully, or until an error occurs. ++ * ++ * @param buffers One or more data buffers to be written to the socket. ++ * ++ * @returns The number of bytes written. ++ * ++ * @throws boost::system::system_error Thrown on failure. An error code of ++ * boost::asio::error::eof indicates that the connection was closed by the ++ * peer. ++ * ++ * @note The write_some operation may not transmit all of the data to the ++ * peer. Consider using the @ref write function if you need to ensure that ++ * all data is written before the blocking operation completes. ++ * ++ * @par Example ++ * To write a single data buffer use the @ref buffer function as follows: ++ * @code ++ * socket.write_some(boost::asio::buffer(data, size)); ++ * @endcode ++ * See the @ref buffer documentation for information on writing multiple ++ * buffers in one go, and how to use it with arrays, boost::array or ++ * std::vector. ++ */ ++ template ++ std::size_t write_some(const ConstBufferSequence& buffers) ++ { ++ boost::system::error_code ec; ++ std::size_t s = this->impl_.get_service().send( ++ this->impl_.get_implementation(), buffers, 0, ec); ++ boost::asio::detail::throw_error(ec, "write_some"); ++ return s; ++ } ++ ++ /// Write some data to the socket. ++ /** ++ * This function is used to write data to the stream socket. The function call ++ * will block until one or more bytes of the data has been written ++ * successfully, or until an error occurs. ++ * ++ * @param buffers One or more data buffers to be written to the socket. ++ * ++ * @param ec Set to indicate what error occurred, if any. ++ * ++ * @returns The number of bytes written. Returns 0 if an error occurred. ++ * ++ * @note The write_some operation may not transmit all of the data to the ++ * peer. Consider using the @ref write function if you need to ensure that ++ * all data is written before the blocking operation completes. ++ */ ++ template ++ std::size_t write_some(const ConstBufferSequence& buffers, ++ boost::system::error_code& ec) ++ { ++ return this->impl_.get_service().send( ++ this->impl_.get_implementation(), buffers, 0, ec); ++ } ++ ++ /// Start an asynchronous write. ++ /** ++ * This function is used to asynchronously write data to the stream socket. ++ * The function call always returns immediately. ++ * ++ * @param buffers One or more data buffers to be written to the socket. ++ * Although the buffers object may be copied as necessary, ownership of the ++ * underlying memory blocks is retained by the caller, which must guarantee ++ * that they remain valid until the handler is called. ++ * ++ * @param handler The handler to be called when the write operation completes. ++ * Copies will be made of the handler as required. The function signature of ++ * the handler must be: ++ * @code void handler( ++ * const boost::system::error_code& error, // Result of operation. ++ * std::size_t bytes_transferred // Number of bytes written. ++ * ); @endcode ++ * Regardless of whether the asynchronous operation completes immediately or ++ * not, the handler will not be invoked from within this function. On ++ * immediate completion, invocation of the handler will be performed in a ++ * manner equivalent to using boost::asio::post(). ++ * ++ * @note The write operation may not transmit all of the data to the peer. ++ * Consider using the @ref async_write function if you need to ensure that all ++ * data is written before the asynchronous operation completes. ++ * ++ * @par Example ++ * To write a single data buffer use the @ref buffer function as follows: ++ * @code ++ * socket.async_write_some(boost::asio::buffer(data, size), handler); ++ * @endcode ++ * See the @ref buffer documentation for information on writing multiple ++ * buffers in one go, and how to use it with arrays, boost::array or ++ * std::vector. ++ */ ++ template ++ BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler, ++ void (boost::system::error_code, std::size_t, std::uint32_t, std::uint32_t)) ++ async_write_some(const ConstBufferSequence& buffers, ++ BOOST_ASIO_MOVE_ARG(WriteHandler) handler) ++ { ++ return async_initiate( ++ initiate_async_send(), handler, this, ++ buffers, socket_base::message_flags(0)); ++ } ++ ++ /// Read some data from the socket. ++ /** ++ * This function is used to read data from the stream socket. The function ++ * call will block until one or more bytes of data has been read successfully, ++ * or until an error occurs. ++ * ++ * @param buffers One or more buffers into which the data will be read. ++ * ++ * @returns The number of bytes read. ++ * ++ * @throws boost::system::system_error Thrown on failure. An error code of ++ * boost::asio::error::eof indicates that the connection was closed by the ++ * peer. ++ * ++ * @note The read_some operation may not read all of the requested number of ++ * bytes. Consider using the @ref read function if you need to ensure that ++ * the requested amount of data is read before the blocking operation ++ * completes. ++ * ++ * @par Example ++ * To read into a single data buffer use the @ref buffer function as follows: ++ * @code ++ * socket.read_some(boost::asio::buffer(data, size)); ++ * @endcode ++ * See the @ref buffer documentation for information on reading into multiple ++ * buffers in one go, and how to use it with arrays, boost::array or ++ * std::vector. ++ */ ++ template ++ std::size_t read_some(const MutableBufferSequence& buffers) ++ { ++ boost::system::error_code ec; ++ std::size_t s = this->impl_.get_service().receive( ++ this->impl_.get_implementation(), buffers, 0, ec); ++ boost::asio::detail::throw_error(ec, "read_some"); ++ return s; ++ } ++ ++ /// Read some data from the socket. ++ /** ++ * This function is used to read data from the stream socket. The function ++ * call will block until one or more bytes of data has been read successfully, ++ * or until an error occurs. ++ * ++ * @param buffers One or more buffers into which the data will be read. ++ * ++ * @param ec Set to indicate what error occurred, if any. ++ * ++ * @returns The number of bytes read. Returns 0 if an error occurred. ++ * ++ * @note The read_some operation may not read all of the requested number of ++ * bytes. Consider using the @ref read function if you need to ensure that ++ * the requested amount of data is read before the blocking operation ++ * completes. ++ */ ++ template ++ std::size_t read_some(const MutableBufferSequence& buffers, ++ boost::system::error_code& ec) ++ { ++ return this->impl_.get_service().receive( ++ this->impl_.get_implementation(), buffers, 0, ec); ++ } ++ ++ /// Start an asynchronous read. ++ /** ++ * This function is used to asynchronously read data from the stream socket. ++ * The function call always returns immediately. ++ * ++ * @param buffers One or more buffers into which the data will be read. ++ * Although the buffers object may be copied as necessary, ownership of the ++ * underlying memory blocks is retained by the caller, which must guarantee ++ * that they remain valid until the handler is called. ++ * ++ * @param handler The handler to be called when the read operation completes. ++ * Copies will be made of the handler as required. The function signature of ++ * the handler must be: ++ * @code void handler( ++ * const boost::system::error_code& error, // Result of operation. ++ * std::size_t bytes_transferred // Number of bytes read. ++ * ); @endcode ++ * Regardless of whether the asynchronous operation completes immediately or ++ * not, the handler will not be invoked from within this function. On ++ * immediate completion, invocation of the handler will be performed in a ++ * manner equivalent to using boost::asio::post(). ++ * ++ * @note The read operation may not read all of the requested number of bytes. ++ * Consider using the @ref async_read function if you need to ensure that the ++ * requested amount of data is read before the asynchronous operation ++ * completes. ++ * ++ * @par Example ++ * To read into a single data buffer use the @ref buffer function as follows: ++ * @code ++ * socket.async_read_some(boost::asio::buffer(data, size), handler); ++ * @endcode ++ * See the @ref buffer documentation for information on reading into multiple ++ * buffers in one go, and how to use it with arrays, boost::array or ++ * std::vector. ++ */ ++ template ++ BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler, ++ void (boost::system::error_code, std::size_t, std::uint32_t, std::uint32_t)) ++ async_read_some(const MutableBufferSequence& buffers, ++ BOOST_ASIO_MOVE_ARG(ReadHandler) handler) ++ { ++ return async_initiate( ++ initiate_async_receive(), handler, this, ++ buffers, socket_base::message_flags(0)); ++ } ++ ++private: ++ struct initiate_async_send ++ { ++ template ++ void operator()(BOOST_ASIO_MOVE_ARG(WriteHandler) handler, ++ basic_stream_socket_ext* self, const ConstBufferSequence& buffers, ++ socket_base::message_flags flags) const ++ { ++ // If you get an error on the following line it means that your handler ++ // does not meet the documented type requirements for a WriteHandler. ++ BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check; ++ ++ detail::non_const_lvalue handler2(handler); ++ self->impl_.get_service().async_send( ++ self->impl_.get_implementation(), buffers, flags, ++ handler2.value, self->impl_.get_executor()); ++ } ++ }; ++ ++ struct initiate_async_receive ++ { ++ template ++ void operator()(BOOST_ASIO_MOVE_ARG(ReadHandler) handler, ++ basic_stream_socket_ext* self, const MutableBufferSequence& buffers, ++ socket_base::message_flags flags) const ++ { ++ // If you get an error on the following line it means that your handler ++ // does not meet the documented type requirements for a ReadHandler. ++ BOOST_ASIO_READ_HANDLER_CHECK_EXT_LOCAL(ReadHandler, handler) type_check; ++ ++ detail::non_const_lvalue handler2(handler); ++ self->impl_.get_service().async_receive( ++ self->impl_.get_implementation(), buffers, flags, ++ handler2.value, self->impl_.get_executor()); ++ } ++ }; ++}; ++ ++} // namespace asio ++} // namespace boost ++ ++#include ++ ++#endif // BOOST_ASIO_BASIC_STREAM_SOCKET_EXT_HPP +diff --git a/implementation/helper/1.76/boost/asio/detail/handler_type_requirements_ext.hpp b/implementation/helper/1.76/boost/asio/detail/handler_type_requirements_ext.hpp +new file mode 100644 +index 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 ++ ++// Older versions of gcc have difficulty compiling the sizeof expressions where ++// we test the handler type requirements. We'll disable checking of handler type ++// requirements for those compilers, but otherwise enable it by default. ++#if !defined(BOOST_ASIO_DISABLE_HANDLER_TYPE_REQUIREMENTS) ++# if !defined(__GNUC__) || (__GNUC__ >= 4) ++# define BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS 1 ++# endif // !defined(__GNUC__) || (__GNUC__ >= 4) ++#endif // !defined(BOOST_ASIO_DISABLE_HANDLER_TYPE_REQUIREMENTS) ++ ++// With C++0x we can use a combination of enhanced SFINAE and static_assert to ++// generate better template error messages. As this technique is not yet widely ++// portable, we'll only enable it for tested compilers. ++#if !defined(BOOST_ASIO_DISABLE_HANDLER_TYPE_REQUIREMENTS_ASSERT) ++# if defined(__GNUC__) ++# if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 5)) || (__GNUC__ > 4) ++# if defined(__GXX_EXPERIMENTAL_CXX0X__) ++# define BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS_ASSERT 1 ++# endif // defined(__GXX_EXPERIMENTAL_CXX0X__) ++# endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 5)) || (__GNUC__ > 4) ++# endif // defined(__GNUC__) ++# if defined(BOOST_ASIO_MSVC) ++# if (_MSC_VER >= 1600) ++# define BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS_ASSERT 1 ++# endif // (_MSC_VER >= 1600) ++# endif // defined(BOOST_ASIO_MSVC) ++# if defined(__clang__) ++# if __has_feature(__cxx_static_assert__) ++# define BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS_ASSERT 1 ++# endif // __has_feature(cxx_static_assert) ++# endif // defined(__clang__) ++#endif // !defined(BOOST_ASIO_DISABLE_HANDLER_TYPE_REQUIREMENTS) ++ ++#if defined(BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS) ++# include ++#endif // defined(BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS) ++ ++namespace boost { ++namespace asio { ++namespace detail { ++ ++#if defined(BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS) ++ ++# if defined(BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS_ASSERT) ++ ++template ++auto zero_arg_copyable_handler_test(Handler h, void*) ++ -> decltype( ++ sizeof(Handler(static_cast(h))), ++ ((h)()), ++ char(0)); ++ ++template ++char (&zero_arg_copyable_handler_test(Handler, ...))[2]; ++ ++template ++auto one_arg_handler_test(Handler h, Arg1* a1) ++ -> decltype( ++ sizeof(Handler(BOOST_ASIO_MOVE_CAST(Handler)(h))), ++ ((h)(*a1)), ++ char(0)); ++ ++template ++char (&one_arg_handler_test(Handler h, ...))[2]; ++ ++template ++auto two_arg_handler_test(Handler h, Arg1* a1, Arg2* a2) ++ -> decltype( ++ sizeof(Handler(BOOST_ASIO_MOVE_CAST(Handler)(h))), ++ ((h)(*a1, *a2)), ++ char(0)); ++ ++template ++char (&two_arg_handler_test(Handler, ...))[2]; ++ ++template ++auto two_arg_move_handler_test(Handler h, Arg1* a1, Arg2* a2) ++ -> decltype( ++ sizeof(Handler(BOOST_ASIO_MOVE_CAST(Handler)(h))), ++ ((h)(*a1, BOOST_ASIO_MOVE_CAST(Arg2)(*a2))), ++ char(0)); ++ ++template ++char (&two_arg_move_handler_test(Handler, ...))[2]; ++ ++template ++auto three_arg_handler_test(Handler h, Arg1* a1, Arg2* a2, Arg3* a3) ++ -> decltype( ++ sizeof(Handler(BOOST_ASIO_MOVE_CAST(Handler)(h))), ++ ((h)(*a1, *a2, *a3)), ++ char(0)); ++ ++template ++char (&three_arg_handler_test(Handler, ...))[2]; ++ ++template ++auto three_arg_move_handler_test(Handler h, Arg1* a1, Arg2* a2, Arg3 *a3) ++ -> decltype( ++ sizeof(Handler(BOOST_ASIO_MOVE_CAST(Handler)(h))), ++ ((h)(*a1, BOOST_ASIO_MOVE_CAST(Arg2)(*a2), BOOST_ASIO_MOVE_CAST(Arg3)(*a3))), ++ char(0)); ++ ++template ++char (&three_arg_move_handler_test(Handler, ...))[2]; ++ ++# define BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT(expr, msg) \ ++ static_assert(expr, msg); ++ ++# else // defined(BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS_ASSERT) ++ ++# define BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT(expr, msg) ++ ++# endif // defined(BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS_ASSERT) ++ ++template T& lvref(); ++template T& lvref(T); ++template const T& clvref(); ++template const T& clvref(T); ++#if defined(BOOST_ASIO_HAS_MOVE) ++template T rvref(); ++template T rvref(T); ++#else // defined(BOOST_ASIO_HAS_MOVE) ++template const T& rvref(); ++template const T& rvref(T); ++#endif // defined(BOOST_ASIO_HAS_MOVE) ++template char argbyv(T); ++ ++#if 0 ++template ++struct handler_type_requirements ++{ ++}; ++#endif ++ ++#define BOOST_ASIO_LEGACY_COMPLETION_HANDLER_CHECK( \ ++ handler_type, handler) \ ++ \ ++ typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \ ++ void()) asio_true_handler_type; \ ++ \ ++ BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \ ++ sizeof(boost::asio::detail::zero_arg_copyable_handler_test( \ ++ boost::asio::detail::clvref< \ ++ asio_true_handler_type>(), 0)) == 1, \ ++ "CompletionHandler type requirements not met") \ ++ \ ++ typedef boost::asio::detail::handler_type_requirements< \ ++ sizeof( \ ++ boost::asio::detail::argbyv( \ ++ boost::asio::detail::clvref< \ ++ asio_true_handler_type>())) + \ ++ sizeof( \ ++ boost::asio::detail::lvref< \ ++ asio_true_handler_type>()(), \ ++ char(0))> BOOST_ASIO_UNUSED_TYPEDEF ++ ++#define BOOST_ASIO_READ_HANDLER_CHECK_EXT( \ ++ handler_type, handler) \ ++ \ ++ typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \ ++ void(boost::system::error_code, std::size_t, \ ++ boost::asio::ip::address)) \ ++ asio_true_handler_type; \ ++ \ ++ BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \ ++ sizeof(boost::asio::detail::three_arg_handler_test( \ ++ boost::asio::detail::rvref< \ ++ asio_true_handler_type>(), \ ++ static_cast(0), \ ++ static_cast(0), \ ++ static_cast(0))) == 1, \ ++ "ReadHandler type requirements not met") \ ++ \ ++ typedef boost::asio::detail::handler_type_requirements< \ ++ sizeof( \ ++ boost::asio::detail::argbyv( \ ++ boost::asio::detail::rvref< \ ++ asio_true_handler_type>())) + \ ++ sizeof( \ ++ boost::asio::detail::lvref< \ ++ asio_true_handler_type>()( \ ++ boost::asio::detail::lvref(), \ ++ boost::asio::detail::lvref(), \ ++ boost::asio::detail::lvref()), \ ++ char(0))> BOOST_ASIO_UNUSED_TYPEDEF ++ ++#define BOOST_ASIO_WRITE_HANDLER_CHECK( \ ++ handler_type, handler) \ ++ \ ++ typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \ ++ void(boost::system::error_code, std::size_t)) \ ++ asio_true_handler_type; \ ++ \ ++ BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \ ++ sizeof(boost::asio::detail::two_arg_handler_test( \ ++ boost::asio::detail::rvref< \ ++ asio_true_handler_type>(), \ ++ static_cast(0), \ ++ static_cast(0))) == 1, \ ++ "WriteHandler type requirements not met") \ ++ \ ++ typedef boost::asio::detail::handler_type_requirements< \ ++ sizeof( \ ++ boost::asio::detail::argbyv( \ ++ boost::asio::detail::rvref< \ ++ asio_true_handler_type>())) + \ ++ sizeof( \ ++ boost::asio::detail::lvref< \ ++ asio_true_handler_type>()( \ ++ boost::asio::detail::lvref(), \ ++ boost::asio::detail::lvref()), \ ++ char(0))> BOOST_ASIO_UNUSED_TYPEDEF ++ ++#if 0 ++#define BOOST_ASIO_ACCEPT_HANDLER_CHECK( \ ++ handler_type, handler) \ ++ \ ++ typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \ ++ void(boost::system::error_code)) \ ++ asio_true_handler_type; \ ++ \ ++ BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \ ++ sizeof(boost::asio::detail::one_arg_handler_test( \ ++ boost::asio::detail::rvref< \ ++ asio_true_handler_type>(), \ ++ static_cast(0))) == 1, \ ++ "AcceptHandler type requirements not met") \ ++ \ ++ typedef boost::asio::detail::handler_type_requirements< \ ++ sizeof( \ ++ boost::asio::detail::argbyv( \ ++ boost::asio::detail::rvref< \ ++ asio_true_handler_type>())) + \ ++ sizeof( \ ++ boost::asio::detail::lvref< \ ++ asio_true_handler_type>()( \ ++ boost::asio::detail::lvref()), \ ++ char(0))> BOOST_ASIO_UNUSED_TYPEDEF ++ ++#define BOOST_ASIO_MOVE_ACCEPT_HANDLER_CHECK( \ ++ handler_type, handler, socket_type) \ ++ \ ++ typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \ ++ void(boost::system::error_code, socket_type)) \ ++ asio_true_handler_type; \ ++ \ ++ BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \ ++ sizeof(boost::asio::detail::two_arg_move_handler_test( \ ++ boost::asio::detail::rvref< \ ++ asio_true_handler_type>(), \ ++ static_cast(0), \ ++ static_cast(0))) == 1, \ ++ "MoveAcceptHandler type requirements not met") \ ++ \ ++ typedef boost::asio::detail::handler_type_requirements< \ ++ sizeof( \ ++ boost::asio::detail::argbyv( \ ++ boost::asio::detail::rvref< \ ++ asio_true_handler_type>())) + \ ++ sizeof( \ ++ boost::asio::detail::lvref< \ ++ asio_true_handler_type>()( \ ++ boost::asio::detail::lvref(), \ ++ boost::asio::detail::rvref()), \ ++ char(0))> BOOST_ASIO_UNUSED_TYPEDEF ++#endif ++ ++#define BOOST_ASIO_CONNECT_HANDLER_CHECK( \ ++ handler_type, handler) \ ++ \ ++ typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \ ++ void(boost::system::error_code)) \ ++ asio_true_handler_type; \ ++ \ ++ BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \ ++ sizeof(boost::asio::detail::one_arg_handler_test( \ ++ boost::asio::detail::rvref< \ ++ asio_true_handler_type>(), \ ++ static_cast(0))) == 1, \ ++ "ConnectHandler type requirements not met") \ ++ \ ++ typedef boost::asio::detail::handler_type_requirements< \ ++ sizeof( \ ++ boost::asio::detail::argbyv( \ ++ boost::asio::detail::rvref< \ ++ asio_true_handler_type>())) + \ ++ sizeof( \ ++ boost::asio::detail::lvref< \ ++ asio_true_handler_type>()( \ ++ boost::asio::detail::lvref()), \ ++ char(0))> BOOST_ASIO_UNUSED_TYPEDEF ++ ++#define BOOST_ASIO_RANGE_CONNECT_HANDLER_CHECK( \ ++ handler_type, handler, endpoint_type) \ ++ \ ++ typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \ ++ void(boost::system::error_code, endpoint_type)) \ ++ asio_true_handler_type; \ ++ \ ++ BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \ ++ sizeof(boost::asio::detail::two_arg_handler_test( \ ++ boost::asio::detail::rvref< \ ++ asio_true_handler_type>(), \ ++ static_cast(0), \ ++ static_cast(0))) == 1, \ ++ "RangeConnectHandler type requirements not met") \ ++ \ ++ typedef boost::asio::detail::handler_type_requirements< \ ++ sizeof( \ ++ boost::asio::detail::argbyv( \ ++ boost::asio::detail::rvref< \ ++ asio_true_handler_type>())) + \ ++ sizeof( \ ++ boost::asio::detail::lvref< \ ++ asio_true_handler_type>()( \ ++ boost::asio::detail::lvref(), \ ++ boost::asio::detail::lvref()), \ ++ char(0))> BOOST_ASIO_UNUSED_TYPEDEF ++ ++#define BOOST_ASIO_ITERATOR_CONNECT_HANDLER_CHECK( \ ++ handler_type, handler, iter_type) \ ++ \ ++ typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \ ++ void(boost::system::error_code, iter_type)) \ ++ asio_true_handler_type; \ ++ \ ++ BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \ ++ sizeof(boost::asio::detail::two_arg_handler_test( \ ++ boost::asio::detail::rvref< \ ++ asio_true_handler_type>(), \ ++ static_cast(0), \ ++ static_cast(0))) == 1, \ ++ "IteratorConnectHandler type requirements not met") \ ++ \ ++ typedef boost::asio::detail::handler_type_requirements< \ ++ sizeof( \ ++ boost::asio::detail::argbyv( \ ++ boost::asio::detail::rvref< \ ++ asio_true_handler_type>())) + \ ++ sizeof( \ ++ boost::asio::detail::lvref< \ ++ asio_true_handler_type>()( \ ++ boost::asio::detail::lvref(), \ ++ boost::asio::detail::lvref()), \ ++ char(0))> BOOST_ASIO_UNUSED_TYPEDEF ++ ++#define BOOST_ASIO_RESOLVE_HANDLER_CHECK( \ ++ handler_type, handler, range_type) \ ++ \ ++ typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \ ++ void(boost::system::error_code, range_type)) \ ++ asio_true_handler_type; \ ++ \ ++ BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \ ++ sizeof(boost::asio::detail::two_arg_handler_test( \ ++ boost::asio::detail::rvref< \ ++ asio_true_handler_type>(), \ ++ static_cast(0), \ ++ static_cast(0))) == 1, \ ++ "ResolveHandler type requirements not met") \ ++ \ ++ typedef boost::asio::detail::handler_type_requirements< \ ++ sizeof( \ ++ boost::asio::detail::argbyv( \ ++ boost::asio::detail::rvref< \ ++ asio_true_handler_type>())) + \ ++ sizeof( \ ++ boost::asio::detail::lvref< \ ++ asio_true_handler_type>()( \ ++ boost::asio::detail::lvref(), \ ++ boost::asio::detail::lvref()), \ ++ char(0))> BOOST_ASIO_UNUSED_TYPEDEF ++ ++#define BOOST_ASIO_WAIT_HANDLER_CHECK( \ ++ handler_type, handler) \ ++ \ ++ typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \ ++ void(boost::system::error_code)) \ ++ asio_true_handler_type; \ ++ \ ++ BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \ ++ sizeof(boost::asio::detail::one_arg_handler_test( \ ++ boost::asio::detail::rvref< \ ++ asio_true_handler_type>(), \ ++ static_cast(0))) == 1, \ ++ "WaitHandler type requirements not met") \ ++ \ ++ typedef boost::asio::detail::handler_type_requirements< \ ++ sizeof( \ ++ boost::asio::detail::argbyv( \ ++ boost::asio::detail::rvref< \ ++ asio_true_handler_type>())) + \ ++ sizeof( \ ++ boost::asio::detail::lvref< \ ++ asio_true_handler_type>()( \ ++ boost::asio::detail::lvref()), \ ++ char(0))> BOOST_ASIO_UNUSED_TYPEDEF ++ ++#define BOOST_ASIO_SIGNAL_HANDLER_CHECK( \ ++ handler_type, handler) \ ++ \ ++ typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \ ++ void(boost::system::error_code, int)) \ ++ asio_true_handler_type; \ ++ \ ++ BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \ ++ sizeof(boost::asio::detail::two_arg_handler_test( \ ++ boost::asio::detail::rvref< \ ++ asio_true_handler_type>(), \ ++ static_cast(0), \ ++ static_cast(0))) == 1, \ ++ "SignalHandler type requirements not met") \ ++ \ ++ typedef boost::asio::detail::handler_type_requirements< \ ++ sizeof( \ ++ boost::asio::detail::argbyv( \ ++ boost::asio::detail::rvref< \ ++ asio_true_handler_type>())) + \ ++ sizeof( \ ++ boost::asio::detail::lvref< \ ++ asio_true_handler_type>()( \ ++ boost::asio::detail::lvref(), \ ++ boost::asio::detail::lvref()), \ ++ char(0))> BOOST_ASIO_UNUSED_TYPEDEF ++ ++#define BOOST_ASIO_HANDSHAKE_HANDLER_CHECK( \ ++ handler_type, handler) \ ++ \ ++ typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \ ++ void(boost::system::error_code)) \ ++ asio_true_handler_type; \ ++ \ ++ BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \ ++ sizeof(boost::asio::detail::one_arg_handler_test( \ ++ boost::asio::detail::rvref< \ ++ asio_true_handler_type>(), \ ++ static_cast(0))) == 1, \ ++ "HandshakeHandler type requirements not met") \ ++ \ ++ typedef boost::asio::detail::handler_type_requirements< \ ++ sizeof( \ ++ boost::asio::detail::argbyv( \ ++ boost::asio::detail::rvref< \ ++ asio_true_handler_type>())) + \ ++ sizeof( \ ++ boost::asio::detail::lvref< \ ++ asio_true_handler_type>()( \ ++ boost::asio::detail::lvref()), \ ++ char(0))> BOOST_ASIO_UNUSED_TYPEDEF ++ ++#define BOOST_ASIO_BUFFERED_HANDSHAKE_HANDLER_CHECK( \ ++ handler_type, handler) \ ++ \ ++ typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \ ++ void(boost::system::error_code, std::size_t)) \ ++ asio_true_handler_type; \ ++ \ ++ BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \ ++ sizeof(boost::asio::detail::two_arg_handler_test( \ ++ boost::asio::detail::rvref< \ ++ asio_true_handler_type>(), \ ++ static_cast(0), \ ++ static_cast(0))) == 1, \ ++ "BufferedHandshakeHandler type requirements not met") \ ++ \ ++ typedef boost::asio::detail::handler_type_requirements< \ ++ sizeof( \ ++ boost::asio::detail::argbyv( \ ++ boost::asio::detail::rvref< \ ++ asio_true_handler_type>())) + \ ++ sizeof( \ ++ boost::asio::detail::lvref< \ ++ asio_true_handler_type>()( \ ++ boost::asio::detail::lvref(), \ ++ boost::asio::detail::lvref()), \ ++ char(0))> BOOST_ASIO_UNUSED_TYPEDEF ++ ++#define BOOST_ASIO_SHUTDOWN_HANDLER_CHECK( \ ++ handler_type, handler) \ ++ \ ++ typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \ ++ void(boost::system::error_code)) \ ++ asio_true_handler_type; \ ++ \ ++ BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \ ++ sizeof(boost::asio::detail::one_arg_handler_test( \ ++ boost::asio::detail::rvref< \ ++ asio_true_handler_type>(), \ ++ static_cast(0))) == 1, \ ++ "ShutdownHandler type requirements not met") \ ++ \ ++ typedef boost::asio::detail::handler_type_requirements< \ ++ sizeof( \ ++ boost::asio::detail::argbyv( \ ++ boost::asio::detail::rvref< \ ++ asio_true_handler_type>())) + \ ++ sizeof( \ ++ boost::asio::detail::lvref< \ ++ asio_true_handler_type>()( \ ++ boost::asio::detail::lvref()), \ ++ char(0))> BOOST_ASIO_UNUSED_TYPEDEF ++ ++#else // !defined(BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS) ++ ++#define BOOST_ASIO_LEGACY_COMPLETION_HANDLER_CHECK( \ ++ handler_type, handler) \ ++ typedef int BOOST_ASIO_UNUSED_TYPEDEF ++ ++#define BOOST_ASIO_READ_HANDLER_CHECK( \ ++ handler_type, handler) \ ++ typedef int BOOST_ASIO_UNUSED_TYPEDEF ++ ++#define BOOST_ASIO_WRITE_HANDLER_CHECK( \ ++ handler_type, handler) \ ++ typedef int BOOST_ASIO_UNUSED_TYPEDEF ++ ++#define BOOST_ASIO_ACCEPT_HANDLER_CHECK( \ ++ handler_type, handler) \ ++ typedef int BOOST_ASIO_UNUSED_TYPEDEF ++ ++#define BOOST_ASIO_MOVE_ACCEPT_HANDLER_CHECK( \ ++ handler_type, handler, socket_type) \ ++ typedef int BOOST_ASIO_UNUSED_TYPEDEF ++ ++#define BOOST_ASIO_CONNECT_HANDLER_CHECK( \ ++ handler_type, handler) \ ++ typedef int BOOST_ASIO_UNUSED_TYPEDEF ++ ++#define BOOST_ASIO_RANGE_CONNECT_HANDLER_CHECK( \ ++ handler_type, handler, iter_type) \ ++ typedef int BOOST_ASIO_UNUSED_TYPEDEF ++ ++#define BOOST_ASIO_ITERATOR_CONNECT_HANDLER_CHECK( \ ++ handler_type, handler, iter_type) \ ++ typedef int BOOST_ASIO_UNUSED_TYPEDEF ++ ++#define BOOST_ASIO_RESOLVE_HANDLER_CHECK( \ ++ handler_type, handler, iter_type) \ ++ typedef int BOOST_ASIO_UNUSED_TYPEDEF ++ ++#define BOOST_ASIO_WAIT_HANDLER_CHECK( \ ++ handler_type, handler) \ ++ typedef int BOOST_ASIO_UNUSED_TYPEDEF ++ ++#define BOOST_ASIO_SIGNAL_HANDLER_CHECK( \ ++ handler_type, handler) \ ++ typedef int BOOST_ASIO_UNUSED_TYPEDEF ++ ++#define BOOST_ASIO_HANDSHAKE_HANDLER_CHECK( \ ++ handler_type, handler) \ ++ typedef int BOOST_ASIO_UNUSED_TYPEDEF ++ ++#define BOOST_ASIO_BUFFERED_HANDSHAKE_HANDLER_CHECK( \ ++ handler_type, handler) \ ++ typedef int BOOST_ASIO_UNUSED_TYPEDEF ++ ++#define BOOST_ASIO_SHUTDOWN_HANDLER_CHECK( \ ++ handler_type, handler) \ ++ typedef int BOOST_ASIO_UNUSED_TYPEDEF ++ ++#endif // !defined(BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS) ++ ++} // namespace detail ++} // namespace asio ++} // namespace boost ++ ++#endif // BOOST_ASIO_DETAIL_HANDLER_TYPE_REQUIREMENTS_EXT_HPP +diff --git a/implementation/helper/1.76/boost/asio/detail/handler_type_requirements_ext_local.hpp b/implementation/helper/1.76/boost/asio/detail/handler_type_requirements_ext_local.hpp +new file mode 100644 +index 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 ++ ++// Older versions of gcc have difficulty compiling the sizeof expressions where ++// we test the handler type requirements. We'll disable checking of handler type ++// requirements for those compilers, but otherwise enable it by default. ++#if !defined(BOOST_ASIO_DISABLE_HANDLER_TYPE_REQUIREMENTS) ++# if !defined(__GNUC__) || (__GNUC__ >= 4) ++# define BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS 1 ++# endif // !defined(__GNUC__) || (__GNUC__ >= 4) ++#endif // !defined(BOOST_ASIO_DISABLE_HANDLER_TYPE_REQUIREMENTS) ++ ++// With C++0x we can use a combination of enhanced SFINAE and static_assert to ++// generate better template error messages. As this technique is not yet widely ++// portable, we'll only enable it for tested compilers. ++#if !defined(BOOST_ASIO_DISABLE_HANDLER_TYPE_REQUIREMENTS_ASSERT) ++# if defined(__GNUC__) ++# if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 5)) || (__GNUC__ > 4) ++# if defined(__GXX_EXPERIMENTAL_CXX0X__) ++# define BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS_ASSERT 1 ++# endif // defined(__GXX_EXPERIMENTAL_CXX0X__) ++# endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 5)) || (__GNUC__ > 4) ++# endif // defined(__GNUC__) ++# if defined(BOOST_ASIO_MSVC) ++# if (_MSC_VER >= 1600) ++# define BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS_ASSERT 1 ++# endif // (_MSC_VER >= 1600) ++# endif // defined(BOOST_ASIO_MSVC) ++# if defined(__clang__) ++# if __has_feature(__cxx_static_assert__) ++# define BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS_ASSERT 1 ++# endif // __has_feature(cxx_static_assert) ++# endif // defined(__clang__) ++#endif // !defined(BOOST_ASIO_DISABLE_HANDLER_TYPE_REQUIREMENTS) ++ ++#if defined(BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS) ++# include ++#endif // defined(BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS) ++ ++namespace boost { ++namespace asio { ++namespace detail { ++ ++#if defined(BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS) ++ ++# if defined(BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS_ASSERT) ++ ++template ++auto zero_arg_copyable_handler_test(Handler h, void*) ++ -> decltype( ++ sizeof(Handler(static_cast(h))), ++ ((h)()), ++ char(0)); ++ ++template ++char (&zero_arg_copyable_handler_test(Handler, ...))[2]; ++ ++template ++auto one_arg_handler_test(Handler h, Arg1* a1) ++ -> decltype( ++ sizeof(Handler(BOOST_ASIO_MOVE_CAST(Handler)(h))), ++ ((h)(*a1)), ++ char(0)); ++ ++template ++char (&one_arg_handler_test(Handler h, ...))[2]; ++ ++template ++auto two_arg_handler_test(Handler h, Arg1* a1, Arg2* a2) ++ -> decltype( ++ sizeof(Handler(BOOST_ASIO_MOVE_CAST(Handler)(h))), ++ ((h)(*a1, *a2)), ++ char(0)); ++ ++template ++char (&two_arg_handler_test(Handler, ...))[2]; ++ ++template ++auto two_arg_move_handler_test(Handler h, Arg1* a1, Arg2* a2) ++ -> decltype( ++ sizeof(Handler(BOOST_ASIO_MOVE_CAST(Handler)(h))), ++ ((h)(*a1, BOOST_ASIO_MOVE_CAST(Arg2)(*a2))), ++ char(0)); ++ ++template ++char (&two_arg_move_handler_test(Handler, ...))[2]; ++ ++template ++auto four_arg_handler_test(Handler h, Arg1* a1, Arg2* a2, Arg3* a3, Arg4* a4) ++ -> decltype( ++ sizeof(Handler(BOOST_ASIO_MOVE_CAST(Handler)(h))), ++ ((h)(*a1, *a2, *a3, *a4)), ++ char(0)); ++ ++template ++char (&four_arg_handler_test(Handler, ...))[2]; ++ ++template ++auto four_arg_move_handler_test(Handler h, Arg1* a1, Arg2* a2, Arg3* a3, Arg4* a4) ++ -> decltype( ++ sizeof(Handler(BOOST_ASIO_MOVE_CAST(Handler)(h))), ++ ((h)(*a1, BOOST_ASIO_MOVE_CAST(Arg2)(*a2), BOOST_ASIO_MOVE_CAST(Arg3)(*a3), BOOST_ASIO_MOVE_CAST(Arg4)(*a4))), ++ char(0)); ++ ++template ++char (&four_arg_move_handler_test(Handler, ...))[2]; ++ ++# define BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT(expr, msg) \ ++ static_assert(expr, msg); ++ ++# else // defined(BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS_ASSERT) ++ ++# define BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT(expr, msg) ++ ++# endif // defined(BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS_ASSERT) ++ ++template T& lvref(); ++template T& lvref(T); ++template const T& clvref(); ++template const T& clvref(T); ++#if defined(BOOST_ASIO_HAS_MOVE) ++template T rvref(); ++template T rvref(T); ++#else // defined(BOOST_ASIO_HAS_MOVE) ++template const T& rvref(); ++template const T& rvref(T); ++#endif // defined(BOOST_ASIO_HAS_MOVE) ++template char argbyv(T); ++ ++#if 0 ++template ++struct handler_type_requirements ++{ ++}; ++#endif ++ ++#define BOOST_ASIO_LEGACY_COMPLETION_HANDLER_CHECK( \ ++ handler_type, handler) \ ++ \ ++ typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \ ++ void()) asio_true_handler_type; \ ++ \ ++ BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \ ++ sizeof(boost::asio::detail::zero_arg_copyable_handler_test( \ ++ boost::asio::detail::clvref< \ ++ asio_true_handler_type>(), 0)) == 1, \ ++ "CompletionHandler type requirements not met") \ ++ \ ++ typedef boost::asio::detail::handler_type_requirements< \ ++ sizeof( \ ++ boost::asio::detail::argbyv( \ ++ boost::asio::detail::clvref< \ ++ asio_true_handler_type>())) + \ ++ sizeof( \ ++ boost::asio::detail::lvref< \ ++ asio_true_handler_type>()(), \ ++ char(0))> BOOST_ASIO_UNUSED_TYPEDEF ++ ++#define BOOST_ASIO_READ_HANDLER_CHECK_EXT_LOCAL( \ ++ handler_type, handler) \ ++ \ ++ typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \ ++ void(boost::system::error_code, std::size_t, \ ++ std::uint32_t, std::uint32_t)) \ ++ asio_true_handler_type; \ ++ \ ++ BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \ ++ sizeof(boost::asio::detail::four_arg_handler_test( \ ++ boost::asio::detail::clvref< \ ++ asio_true_handler_type>(), \ ++ static_cast(0), \ ++ static_cast(0), \ ++ static_cast(0), \ ++ static_cast(0))) == 1, \ ++ "ReadHandler type requirements not met") \ ++ \ ++ typedef boost::asio::detail::handler_type_requirements< \ ++ sizeof( \ ++ boost::asio::detail::argbyv( \ ++ boost::asio::detail::clvref< \ ++ asio_true_handler_type>())) + \ ++ sizeof( \ ++ boost::asio::detail::lvref< \ ++ asio_true_handler_type>()( \ ++ boost::asio::detail::lvref(), \ ++ boost::asio::detail::lvref(), \ ++ boost::asio::detail::lvref(), \ ++ boost::asio::detail::lvref()), \ ++ char(0))> BOOST_ASIO_UNUSED_TYPEDEF ++ ++#define BOOST_ASIO_WRITE_HANDLER_CHECK( \ ++ handler_type, handler) \ ++ \ ++ typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \ ++ void(boost::system::error_code, std::size_t)) \ ++ asio_true_handler_type; \ ++ \ ++ BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \ ++ sizeof(boost::asio::detail::two_arg_handler_test( \ ++ boost::asio::detail::rvref< \ ++ asio_true_handler_type>(), \ ++ static_cast(0), \ ++ static_cast(0))) == 1, \ ++ "WriteHandler type requirements not met") \ ++ \ ++ typedef boost::asio::detail::handler_type_requirements< \ ++ sizeof( \ ++ boost::asio::detail::argbyv( \ ++ boost::asio::detail::rvref< \ ++ asio_true_handler_type>())) + \ ++ sizeof( \ ++ boost::asio::detail::lvref< \ ++ asio_true_handler_type>()( \ ++ boost::asio::detail::lvref(), \ ++ boost::asio::detail::lvref()), \ ++ char(0))> BOOST_ASIO_UNUSED_TYPEDEF ++ ++#if 0 ++#define BOOST_ASIO_ACCEPT_HANDLER_CHECK( \ ++ handler_type, handler) \ ++ \ ++ typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \ ++ void(boost::system::error_code)) \ ++ asio_true_handler_type; \ ++ \ ++ BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \ ++ sizeof(boost::asio::detail::one_arg_handler_test( \ ++ boost::asio::detail::rvref< \ ++ asio_true_handler_type>(), \ ++ static_cast(0))) == 1, \ ++ "AcceptHandler type requirements not met") \ ++ \ ++ typedef boost::asio::detail::handler_type_requirements< \ ++ sizeof( \ ++ boost::asio::detail::argbyv( \ ++ boost::asio::detail::rvref< \ ++ asio_true_handler_type>())) + \ ++ sizeof( \ ++ boost::asio::detail::lvref< \ ++ asio_true_handler_type>()( \ ++ boost::asio::detail::lvref()), \ ++ char(0))> BOOST_ASIO_UNUSED_TYPEDEF ++ ++#define BOOST_ASIO_MOVE_ACCEPT_HANDLER_CHECK( \ ++ handler_type, handler, socket_type) \ ++ \ ++ typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \ ++ void(boost::system::error_code, socket_type)) \ ++ asio_true_handler_type; \ ++ \ ++ BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \ ++ sizeof(boost::asio::detail::two_arg_move_handler_test( \ ++ boost::asio::detail::rvref< \ ++ asio_true_handler_type>(), \ ++ static_cast(0), \ ++ static_cast(0))) == 1, \ ++ "MoveAcceptHandler type requirements not met") \ ++ \ ++ typedef boost::asio::detail::handler_type_requirements< \ ++ sizeof( \ ++ boost::asio::detail::argbyv( \ ++ boost::asio::detail::rvref< \ ++ asio_true_handler_type>())) + \ ++ sizeof( \ ++ boost::asio::detail::lvref< \ ++ asio_true_handler_type>()( \ ++ boost::asio::detail::lvref(), \ ++ boost::asio::detail::rvref()), \ ++ char(0))> BOOST_ASIO_UNUSED_TYPEDEF ++#endif ++ ++#define BOOST_ASIO_CONNECT_HANDLER_CHECK( \ ++ handler_type, handler) \ ++ \ ++ typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \ ++ void(boost::system::error_code)) \ ++ asio_true_handler_type; \ ++ \ ++ BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \ ++ sizeof(boost::asio::detail::one_arg_handler_test( \ ++ boost::asio::detail::rvref< \ ++ asio_true_handler_type>(), \ ++ static_cast(0))) == 1, \ ++ "ConnectHandler type requirements not met") \ ++ \ ++ typedef boost::asio::detail::handler_type_requirements< \ ++ sizeof( \ ++ boost::asio::detail::argbyv( \ ++ boost::asio::detail::rvref< \ ++ asio_true_handler_type>())) + \ ++ sizeof( \ ++ boost::asio::detail::lvref< \ ++ asio_true_handler_type>()( \ ++ boost::asio::detail::lvref()), \ ++ char(0))> BOOST_ASIO_UNUSED_TYPEDEF ++ ++#define BOOST_ASIO_RANGE_CONNECT_HANDLER_CHECK( \ ++ handler_type, handler, endpoint_type) \ ++ \ ++ typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \ ++ void(boost::system::error_code, endpoint_type)) \ ++ asio_true_handler_type; \ ++ \ ++ BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \ ++ sizeof(boost::asio::detail::two_arg_handler_test( \ ++ boost::asio::detail::rvref< \ ++ asio_true_handler_type>(), \ ++ static_cast(0), \ ++ static_cast(0))) == 1, \ ++ "RangeConnectHandler type requirements not met") \ ++ \ ++ typedef boost::asio::detail::handler_type_requirements< \ ++ sizeof( \ ++ boost::asio::detail::argbyv( \ ++ boost::asio::detail::rvref< \ ++ asio_true_handler_type>())) + \ ++ sizeof( \ ++ boost::asio::detail::lvref< \ ++ asio_true_handler_type>()( \ ++ boost::asio::detail::lvref(), \ ++ boost::asio::detail::lvref()), \ ++ char(0))> BOOST_ASIO_UNUSED_TYPEDEF ++ ++#define BOOST_ASIO_ITERATOR_CONNECT_HANDLER_CHECK( \ ++ handler_type, handler, iter_type) \ ++ \ ++ typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \ ++ void(boost::system::error_code, iter_type)) \ ++ asio_true_handler_type; \ ++ \ ++ BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \ ++ sizeof(boost::asio::detail::two_arg_handler_test( \ ++ boost::asio::detail::rvref< \ ++ asio_true_handler_type>(), \ ++ static_cast(0), \ ++ static_cast(0))) == 1, \ ++ "IteratorConnectHandler type requirements not met") \ ++ \ ++ typedef boost::asio::detail::handler_type_requirements< \ ++ sizeof( \ ++ boost::asio::detail::argbyv( \ ++ boost::asio::detail::rvref< \ ++ asio_true_handler_type>())) + \ ++ sizeof( \ ++ boost::asio::detail::lvref< \ ++ asio_true_handler_type>()( \ ++ boost::asio::detail::lvref(), \ ++ boost::asio::detail::lvref()), \ ++ char(0))> BOOST_ASIO_UNUSED_TYPEDEF ++ ++#define BOOST_ASIO_RESOLVE_HANDLER_CHECK( \ ++ handler_type, handler, range_type) \ ++ \ ++ typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \ ++ void(boost::system::error_code, range_type)) \ ++ asio_true_handler_type; \ ++ \ ++ BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \ ++ sizeof(boost::asio::detail::two_arg_handler_test( \ ++ boost::asio::detail::rvref< \ ++ asio_true_handler_type>(), \ ++ static_cast(0), \ ++ static_cast(0))) == 1, \ ++ "ResolveHandler type requirements not met") \ ++ \ ++ typedef boost::asio::detail::handler_type_requirements< \ ++ sizeof( \ ++ boost::asio::detail::argbyv( \ ++ boost::asio::detail::rvref< \ ++ asio_true_handler_type>())) + \ ++ sizeof( \ ++ boost::asio::detail::lvref< \ ++ asio_true_handler_type>()( \ ++ boost::asio::detail::lvref(), \ ++ boost::asio::detail::lvref()), \ ++ char(0))> BOOST_ASIO_UNUSED_TYPEDEF ++ ++#define BOOST_ASIO_WAIT_HANDLER_CHECK( \ ++ handler_type, handler) \ ++ \ ++ typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \ ++ void(boost::system::error_code)) \ ++ asio_true_handler_type; \ ++ \ ++ BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \ ++ sizeof(boost::asio::detail::one_arg_handler_test( \ ++ boost::asio::detail::rvref< \ ++ asio_true_handler_type>(), \ ++ static_cast(0))) == 1, \ ++ "WaitHandler type requirements not met") \ ++ \ ++ typedef boost::asio::detail::handler_type_requirements< \ ++ sizeof( \ ++ boost::asio::detail::argbyv( \ ++ boost::asio::detail::rvref< \ ++ asio_true_handler_type>())) + \ ++ sizeof( \ ++ boost::asio::detail::lvref< \ ++ asio_true_handler_type>()( \ ++ boost::asio::detail::lvref()), \ ++ char(0))> BOOST_ASIO_UNUSED_TYPEDEF ++ ++#define BOOST_ASIO_SIGNAL_HANDLER_CHECK( \ ++ handler_type, handler) \ ++ \ ++ typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \ ++ void(boost::system::error_code, int)) \ ++ asio_true_handler_type; \ ++ \ ++ BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \ ++ sizeof(boost::asio::detail::two_arg_handler_test( \ ++ boost::asio::detail::rvref< \ ++ asio_true_handler_type>(), \ ++ static_cast(0), \ ++ static_cast(0))) == 1, \ ++ "SignalHandler type requirements not met") \ ++ \ ++ typedef boost::asio::detail::handler_type_requirements< \ ++ sizeof( \ ++ boost::asio::detail::argbyv( \ ++ boost::asio::detail::rvref< \ ++ asio_true_handler_type>())) + \ ++ sizeof( \ ++ boost::asio::detail::lvref< \ ++ asio_true_handler_type>()( \ ++ boost::asio::detail::lvref(), \ ++ boost::asio::detail::lvref()), \ ++ char(0))> BOOST_ASIO_UNUSED_TYPEDEF ++ ++#define BOOST_ASIO_HANDSHAKE_HANDLER_CHECK( \ ++ handler_type, handler) \ ++ \ ++ typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \ ++ void(boost::system::error_code)) \ ++ asio_true_handler_type; \ ++ \ ++ BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \ ++ sizeof(boost::asio::detail::one_arg_handler_test( \ ++ boost::asio::detail::rvref< \ ++ asio_true_handler_type>(), \ ++ static_cast(0))) == 1, \ ++ "HandshakeHandler type requirements not met") \ ++ \ ++ typedef boost::asio::detail::handler_type_requirements< \ ++ sizeof( \ ++ boost::asio::detail::argbyv( \ ++ boost::asio::detail::rvref< \ ++ asio_true_handler_type>())) + \ ++ sizeof( \ ++ boost::asio::detail::lvref< \ ++ asio_true_handler_type>()( \ ++ boost::asio::detail::lvref()), \ ++ char(0))> BOOST_ASIO_UNUSED_TYPEDEF ++ ++#define BOOST_ASIO_BUFFERED_HANDSHAKE_HANDLER_CHECK( \ ++ handler_type, handler) \ ++ \ ++ typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \ ++ void(boost::system::error_code, std::size_t)) \ ++ asio_true_handler_type; \ ++ \ ++ BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \ ++ sizeof(boost::asio::detail::two_arg_handler_test( \ ++ boost::asio::detail::rvref< \ ++ asio_true_handler_type>(), \ ++ static_cast(0), \ ++ static_cast(0))) == 1, \ ++ "BufferedHandshakeHandler type requirements not met") \ ++ \ ++ typedef boost::asio::detail::handler_type_requirements< \ ++ sizeof( \ ++ boost::asio::detail::argbyv( \ ++ boost::asio::detail::rvref< \ ++ asio_true_handler_type>())) + \ ++ sizeof( \ ++ boost::asio::detail::lvref< \ ++ asio_true_handler_type>()( \ ++ boost::asio::detail::lvref(), \ ++ boost::asio::detail::lvref()), \ ++ char(0))> BOOST_ASIO_UNUSED_TYPEDEF ++ ++#define BOOST_ASIO_SHUTDOWN_HANDLER_CHECK( \ ++ handler_type, handler) \ ++ \ ++ typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \ ++ void(boost::system::error_code)) \ ++ asio_true_handler_type; \ ++ \ ++ BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \ ++ sizeof(boost::asio::detail::one_arg_handler_test( \ ++ boost::asio::detail::rvref< \ ++ asio_true_handler_type>(), \ ++ static_cast(0))) == 1, \ ++ "ShutdownHandler type requirements not met") \ ++ \ ++ typedef boost::asio::detail::handler_type_requirements< \ ++ sizeof( \ ++ boost::asio::detail::argbyv( \ ++ boost::asio::detail::rvref< \ ++ asio_true_handler_type>())) + \ ++ sizeof( \ ++ boost::asio::detail::lvref< \ ++ asio_true_handler_type>()( \ ++ boost::asio::detail::lvref()), \ ++ char(0))> BOOST_ASIO_UNUSED_TYPEDEF ++ ++#else // !defined(BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS) ++ ++#define BOOST_ASIO_LEGACY_COMPLETION_HANDLER_CHECK( \ ++ handler_type, handler) \ ++ typedef int BOOST_ASIO_UNUSED_TYPEDEF ++ ++#define BOOST_ASIO_READ_HANDLER_CHECK( \ ++ handler_type, handler) \ ++ typedef int BOOST_ASIO_UNUSED_TYPEDEF ++ ++#define BOOST_ASIO_WRITE_HANDLER_CHECK( \ ++ handler_type, handler) \ ++ typedef int BOOST_ASIO_UNUSED_TYPEDEF ++ ++#define BOOST_ASIO_ACCEPT_HANDLER_CHECK( \ ++ handler_type, handler) \ ++ typedef int BOOST_ASIO_UNUSED_TYPEDEF ++ ++#define BOOST_ASIO_MOVE_ACCEPT_HANDLER_CHECK( \ ++ handler_type, handler, socket_type) \ ++ typedef int BOOST_ASIO_UNUSED_TYPEDEF ++ ++#define BOOST_ASIO_CONNECT_HANDLER_CHECK( \ ++ handler_type, handler) \ ++ typedef int BOOST_ASIO_UNUSED_TYPEDEF ++ ++#define BOOST_ASIO_RANGE_CONNECT_HANDLER_CHECK( \ ++ handler_type, handler, iter_type) \ ++ typedef int BOOST_ASIO_UNUSED_TYPEDEF ++ ++#define BOOST_ASIO_ITERATOR_CONNECT_HANDLER_CHECK( \ ++ handler_type, handler, iter_type) \ ++ typedef int BOOST_ASIO_UNUSED_TYPEDEF ++ ++#define BOOST_ASIO_RESOLVE_HANDLER_CHECK( \ ++ handler_type, handler, iter_type) \ ++ typedef int BOOST_ASIO_UNUSED_TYPEDEF ++ ++#define BOOST_ASIO_WAIT_HANDLER_CHECK( \ ++ handler_type, handler) \ ++ typedef int BOOST_ASIO_UNUSED_TYPEDEF ++ ++#define BOOST_ASIO_SIGNAL_HANDLER_CHECK( \ ++ handler_type, handler) \ ++ typedef int BOOST_ASIO_UNUSED_TYPEDEF ++ ++#define BOOST_ASIO_HANDSHAKE_HANDLER_CHECK( \ ++ handler_type, handler) \ ++ typedef int BOOST_ASIO_UNUSED_TYPEDEF ++ ++#define BOOST_ASIO_BUFFERED_HANDSHAKE_HANDLER_CHECK( \ ++ handler_type, handler) \ ++ typedef int BOOST_ASIO_UNUSED_TYPEDEF ++ ++#define BOOST_ASIO_SHUTDOWN_HANDLER_CHECK( \ ++ handler_type, handler) \ ++ typedef int BOOST_ASIO_UNUSED_TYPEDEF ++ ++#endif // !defined(BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS) ++ ++} // namespace detail ++} // namespace asio ++} // namespace boost ++ ++#endif // BOOST_ASIO_DETAIL_HANDLER_TYPE_REQUIREMENTS_EXT_LOCAL_HPP +diff --git a/implementation/helper/1.76/boost/asio/detail/impl/reactive_socket_service_base_ext.ipp b/implementation/helper/1.76/boost/asio/detail/impl/reactive_socket_service_base_ext.ipp +new file mode 100644 +index 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 ++ ++#if !defined(BOOST_ASIO_HAS_IOCP) \ ++ && !defined(BOOST_ASIO_WINDOWS_RUNTIME) ++ ++#include ++ ++#include ++ ++namespace boost { ++namespace asio { ++namespace detail { ++ ++reactive_socket_service_base_ext::reactive_socket_service_base_ext( ++ execution_context& context) ++ : reactor_(use_service(context)) ++{ ++ reactor_.init_task(); ++} ++ ++void reactive_socket_service_base_ext::base_shutdown() ++{ ++} ++ ++void reactive_socket_service_base_ext::construct( ++ reactive_socket_service_base_ext::base_implementation_type& impl) ++{ ++ impl.socket_ = invalid_socket; ++ impl.state_ = 0; ++} ++ ++void reactive_socket_service_base_ext::base_move_construct( ++ reactive_socket_service_base_ext::base_implementation_type& impl, ++ reactive_socket_service_base_ext::base_implementation_type& other_impl) ++{ ++ impl.socket_ = other_impl.socket_; ++ other_impl.socket_ = invalid_socket; ++ ++ impl.state_ = other_impl.state_; ++ other_impl.state_ = 0; ++ ++ reactor_.move_descriptor(impl.socket_, ++ impl.reactor_data_, other_impl.reactor_data_); ++} ++ ++void reactive_socket_service_base_ext::base_move_assign( ++ reactive_socket_service_base_ext::base_implementation_type& impl, ++ reactive_socket_service_base_ext& other_service, ++ reactive_socket_service_base_ext::base_implementation_type& other_impl) ++{ ++ destroy(impl); ++ ++ impl.socket_ = other_impl.socket_; ++ other_impl.socket_ = invalid_socket; ++ ++ impl.state_ = other_impl.state_; ++ other_impl.state_ = 0; ++ ++ other_service.reactor_.move_descriptor(impl.socket_, ++ impl.reactor_data_, other_impl.reactor_data_); ++} ++ ++void reactive_socket_service_base_ext::destroy( ++ reactive_socket_service_base_ext::base_implementation_type& impl) ++{ ++ if (impl.socket_ != invalid_socket) ++ { ++ BOOST_ASIO_HANDLER_OPERATION((reactor_.context(), ++ "socket", &impl, impl.socket_, "close")); ++ ++ reactor_.deregister_descriptor(impl.socket_, impl.reactor_data_, ++ (impl.state_ & socket_ops::possible_dup) == 0); ++ ++ boost::system::error_code ignored_ec; ++ socket_ops::close(impl.socket_, impl.state_, true, ignored_ec); ++ ++ reactor_.cleanup_descriptor_data(impl.reactor_data_); ++ } ++} ++ ++boost::system::error_code reactive_socket_service_base_ext::close( ++ reactive_socket_service_base_ext::base_implementation_type& impl, ++ boost::system::error_code& ec) ++{ ++ if (is_open(impl)) ++ { ++ BOOST_ASIO_HANDLER_OPERATION((reactor_.context(), ++ "socket", &impl, impl.socket_, "close")); ++ ++ reactor_.deregister_descriptor(impl.socket_, impl.reactor_data_, ++ (impl.state_ & socket_ops::possible_dup) == 0); ++ ++ socket_ops::close(impl.socket_, impl.state_, false, ec); ++ ++ reactor_.cleanup_descriptor_data(impl.reactor_data_); ++ } ++ else ++ { ++ ec = boost::system::error_code(); ++ } ++ ++ // The descriptor is closed by the OS even if close() returns an error. ++ // ++ // (Actually, POSIX says the state of the descriptor is unspecified. On ++ // Linux the descriptor is apparently closed anyway; e.g. see ++ // http://lkml.org/lkml/2005/9/10/129 ++ // We'll just have to assume that other OSes follow the same behaviour. The ++ // known exception is when Windows's closesocket() function fails with ++ // WSAEWOULDBLOCK, but this case is handled inside socket_ops::close(). ++ construct(impl); ++ ++ return ec; ++} ++/* ++socket_type reactive_socket_service_base::release( ++ reactive_socket_service_base::base_implementation_type& impl, ++ boost::system::error_code& ec) ++{ ++ if (!is_open(impl)) ++ { ++ ec = boost::asio::error::bad_descriptor; ++ return invalid_socket; ++ } ++ ++ BOOST_ASIO_HANDLER_OPERATION((reactor_.context(), ++ "socket", &impl, impl.socket_, "release")); ++ ++ reactor_.deregister_descriptor(impl.socket_, impl.reactor_data_, false); ++ reactor_.cleanup_descriptor_data(impl.reactor_data_); ++ socket_type sock = impl.socket_; ++ construct(impl); ++ ec = boost::system::error_code(); ++ return sock; ++} ++*/ ++boost::system::error_code reactive_socket_service_base_ext::cancel( ++ reactive_socket_service_base_ext::base_implementation_type& impl, ++ boost::system::error_code& ec) ++{ ++ if (!is_open(impl)) ++ { ++ ec = boost::asio::error::bad_descriptor; ++ return ec; ++ } ++ ++ BOOST_ASIO_HANDLER_OPERATION((reactor_.context(), ++ "socket", &impl, impl.socket_, "cancel")); ++ ++ reactor_.cancel_ops(impl.socket_, impl.reactor_data_); ++ ec = boost::system::error_code(); ++ return ec; ++} ++ ++boost::system::error_code reactive_socket_service_base_ext::do_open( ++ reactive_socket_service_base_ext::base_implementation_type& impl, ++ int af, int type, int protocol, boost::system::error_code& ec) ++{ ++ if (is_open(impl)) ++ { ++ ec = boost::asio::error::already_open; ++ return ec; ++ } ++ ++ socket_holder sock(socket_ops::socket(af, type, protocol, ec)); ++ if (sock.get() == invalid_socket) ++ return ec; ++ ++ if (int err = reactor_.register_descriptor(sock.get(), impl.reactor_data_)) ++ { ++ ec = boost::system::error_code(err, ++ boost::asio::error::get_system_category()); ++ return ec; ++ } ++ ++ impl.socket_ = sock.release(); ++ switch (type) ++ { ++ case SOCK_STREAM: impl.state_ = socket_ops::stream_oriented; break; ++ case SOCK_DGRAM: impl.state_ = socket_ops::datagram_oriented; break; ++ default: impl.state_ = 0; break; ++ } ++ ec = boost::system::error_code(); ++ return ec; ++} ++ ++boost::system::error_code reactive_socket_service_base_ext::do_assign( ++ reactive_socket_service_base_ext::base_implementation_type& impl, int type, ++ const reactive_socket_service_base_ext::native_handle_type& native_socket, ++ boost::system::error_code& ec) ++{ ++ if (is_open(impl)) ++ { ++ ec = boost::asio::error::already_open; ++ return ec; ++ } ++ ++ if (int err = reactor_.register_descriptor( ++ native_socket, impl.reactor_data_)) ++ { ++ ec = boost::system::error_code(err, ++ boost::asio::error::get_system_category()); ++ return ec; ++ } ++ ++ impl.socket_ = native_socket; ++ switch (type) ++ { ++ case SOCK_STREAM: impl.state_ = socket_ops::stream_oriented; break; ++ case SOCK_DGRAM: impl.state_ = socket_ops::datagram_oriented; break; ++ default: impl.state_ = 0; break; ++ } ++ impl.state_ |= socket_ops::possible_dup; ++ ec = boost::system::error_code(); ++ return ec; ++} ++ ++void reactive_socket_service_base_ext::start_op( ++ reactive_socket_service_base_ext::base_implementation_type& impl, ++ int op_type, reactor_op* op, bool is_continuation, ++ bool is_non_blocking, bool noop) ++{ ++ if (!noop) ++ { ++ if ((impl.state_ & socket_ops::non_blocking) ++ || socket_ops::set_internal_non_blocking( ++ impl.socket_, impl.state_, true, op->ec_)) ++ { ++ reactor_.start_op(op_type, impl.socket_, ++ impl.reactor_data_, op, is_continuation, is_non_blocking); ++ return; ++ } ++ } ++ ++ reactor_.post_immediate_completion(op, is_continuation); ++} ++ ++void reactive_socket_service_base_ext::start_accept_op( ++ reactive_socket_service_base_ext::base_implementation_type& impl, ++ reactor_op* op, bool is_continuation, bool peer_is_open) ++{ ++ if (!peer_is_open) ++ start_op(impl, reactor::read_op, op, is_continuation, true, false); ++ else ++ { ++ op->ec_ = boost::asio::error::already_open; ++ reactor_.post_immediate_completion(op, is_continuation); ++ } ++} ++ ++void reactive_socket_service_base_ext::start_connect_op( ++ reactive_socket_service_base_ext::base_implementation_type& impl, ++ reactor_op* op, bool is_continuation, ++ const socket_addr_type* addr, size_t addrlen) ++{ ++ if ((impl.state_ & socket_ops::non_blocking) ++ || socket_ops::set_internal_non_blocking( ++ impl.socket_, impl.state_, true, op->ec_)) ++ { ++ if (socket_ops::connect(impl.socket_, addr, addrlen, op->ec_) != 0) ++ { ++ if (op->ec_ == boost::asio::error::in_progress ++ || op->ec_ == boost::asio::error::would_block) ++ { ++ op->ec_ = boost::system::error_code(); ++ reactor_.start_op(reactor::connect_op, impl.socket_, ++ impl.reactor_data_, op, is_continuation, false); ++ return; ++ } ++ } ++ } ++ ++ reactor_.post_immediate_completion(op, is_continuation); ++} ++ ++} // namespace detail ++} // namespace asio ++} // namespace boost ++ ++#include ++ ++#endif // !defined(BOOST_ASIO_HAS_IOCP) ++ // && !defined(BOOST_ASIO_WINDOWS_RUNTIME) ++ ++#endif // BOOST_ASIO_DETAIL_IMPL_REACTIVE_SOCKET_SERVICE_BASE_EXT_IPP +diff --git a/implementation/helper/1.76/boost/asio/detail/impl/reactive_socket_service_base_ext_local.ipp b/implementation/helper/1.76/boost/asio/detail/impl/reactive_socket_service_base_ext_local.ipp +new file mode 100644 +index 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 ++ ++#if !defined(BOOST_ASIO_HAS_IOCP) \ ++ && !defined(BOOST_ASIO_WINDOWS_RUNTIME) ++ ++#include ++ ++#include ++ ++namespace boost { ++namespace asio { ++namespace detail { ++ ++reactive_socket_service_base_ext_local::reactive_socket_service_base_ext_local( ++ execution_context& context) ++ : reactor_(use_service(context)) ++{ ++ reactor_.init_task(); ++} ++ ++void reactive_socket_service_base_ext_local::base_shutdown() ++{ ++} ++ ++void reactive_socket_service_base_ext_local::construct( ++ reactive_socket_service_base_ext_local::base_implementation_type& impl) ++{ ++ impl.socket_ = invalid_socket; ++ impl.state_ = 0; ++} ++ ++void reactive_socket_service_base_ext_local::base_move_construct( ++ reactive_socket_service_base_ext_local::base_implementation_type& impl, ++ reactive_socket_service_base_ext_local::base_implementation_type& other_impl) ++{ ++ impl.socket_ = other_impl.socket_; ++ other_impl.socket_ = invalid_socket; ++ ++ impl.state_ = other_impl.state_; ++ other_impl.state_ = 0; ++ ++ reactor_.move_descriptor(impl.socket_, ++ impl.reactor_data_, other_impl.reactor_data_); ++} ++ ++void reactive_socket_service_base_ext_local::base_move_assign( ++ reactive_socket_service_base_ext_local::base_implementation_type& impl, ++ reactive_socket_service_base_ext_local& other_service, ++ reactive_socket_service_base_ext_local::base_implementation_type& other_impl) ++{ ++ destroy(impl); ++ ++ impl.socket_ = other_impl.socket_; ++ other_impl.socket_ = invalid_socket; ++ ++ impl.state_ = other_impl.state_; ++ other_impl.state_ = 0; ++ ++ other_service.reactor_.move_descriptor(impl.socket_, ++ impl.reactor_data_, other_impl.reactor_data_); ++} ++ ++void reactive_socket_service_base_ext_local::destroy( ++ reactive_socket_service_base_ext_local::base_implementation_type& impl) ++{ ++ if (impl.socket_ != invalid_socket) ++ { ++ BOOST_ASIO_HANDLER_OPERATION((reactor_.context(), ++ "socket", &impl, impl.socket_, "close")); ++ ++ reactor_.deregister_descriptor(impl.socket_, impl.reactor_data_, ++ (impl.state_ & socket_ops::possible_dup) == 0); ++ ++ boost::system::error_code ignored_ec; ++ socket_ops::close(impl.socket_, impl.state_, true, ignored_ec); ++ ++ reactor_.cleanup_descriptor_data(impl.reactor_data_); ++ } ++} ++ ++boost::system::error_code reactive_socket_service_base_ext_local::close( ++ reactive_socket_service_base_ext_local::base_implementation_type& impl, ++ boost::system::error_code& ec) ++{ ++ if (is_open(impl)) ++ { ++ BOOST_ASIO_HANDLER_OPERATION((reactor_.context(), ++ "socket", &impl, impl.socket_, "close")); ++ ++ reactor_.deregister_descriptor(impl.socket_, impl.reactor_data_, ++ (impl.state_ & socket_ops::possible_dup) == 0); ++ ++ socket_ops::close(impl.socket_, impl.state_, false, ec); ++ ++ reactor_.cleanup_descriptor_data(impl.reactor_data_); ++ } ++ else ++ { ++ ec = boost::system::error_code(); ++ } ++ ++ // The descriptor is closed by the OS even if close() returns an error. ++ // ++ // (Actually, POSIX says the state of the descriptor is unspecified. On ++ // Linux the descriptor is apparently closed anyway; e.g. see ++ // http://lkml.org/lkml/2005/9/10/129 ++ // We'll just have to assume that other OSes follow the same behaviour. The ++ // known exception is when Windows's closesocket() function fails with ++ // WSAEWOULDBLOCK, but this case is handled inside socket_ops::close(). ++ construct(impl); ++ ++ return ec; ++} ++/* ++socket_type reactive_socket_service_base::release( ++ reactive_socket_service_base::base_implementation_type& impl, ++ boost::system::error_code& ec) ++{ ++ if (!is_open(impl)) ++ { ++ ec = boost::asio::error::bad_descriptor; ++ return invalid_socket; ++ } ++ ++ BOOST_ASIO_HANDLER_OPERATION((reactor_.context(), ++ "socket", &impl, impl.socket_, "release")); ++ ++ reactor_.deregister_descriptor(impl.socket_, impl.reactor_data_, false); ++ reactor_.cleanup_descriptor_data(impl.reactor_data_); ++ socket_type sock = impl.socket_; ++ construct(impl); ++ ec = boost::system::error_code(); ++ return sock; ++} ++*/ ++boost::system::error_code reactive_socket_service_base_ext_local::cancel( ++ reactive_socket_service_base_ext_local::base_implementation_type& impl, ++ boost::system::error_code& ec) ++{ ++ if (!is_open(impl)) ++ { ++ ec = boost::asio::error::bad_descriptor; ++ return ec; ++ } ++ ++ BOOST_ASIO_HANDLER_OPERATION((reactor_.context(), ++ "socket", &impl, impl.socket_, "cancel")); ++ ++ reactor_.cancel_ops(impl.socket_, impl.reactor_data_); ++ ec = boost::system::error_code(); ++ return ec; ++} ++ ++boost::system::error_code reactive_socket_service_base_ext_local::do_open( ++ reactive_socket_service_base_ext_local::base_implementation_type& impl, ++ int af, int type, int protocol, boost::system::error_code& ec) ++{ ++ if (is_open(impl)) ++ { ++ ec = boost::asio::error::already_open; ++ return ec; ++ } ++ ++ socket_holder sock(socket_ops::socket(af, type, protocol, ec)); ++ if (sock.get() == invalid_socket) ++ return ec; ++ ++ if (int err = reactor_.register_descriptor(sock.get(), impl.reactor_data_)) ++ { ++ ec = boost::system::error_code(err, ++ boost::asio::error::get_system_category()); ++ return ec; ++ } ++ ++ impl.socket_ = sock.release(); ++ switch (type) ++ { ++ case SOCK_STREAM: impl.state_ = socket_ops::stream_oriented; break; ++ case SOCK_DGRAM: impl.state_ = socket_ops::datagram_oriented; break; ++ default: impl.state_ = 0; break; ++ } ++ ec = boost::system::error_code(); ++ return ec; ++} ++ ++boost::system::error_code reactive_socket_service_base_ext_local::do_assign( ++ reactive_socket_service_base_ext_local::base_implementation_type& impl, int type, ++ const reactive_socket_service_base_ext_local::native_handle_type& native_socket, ++ boost::system::error_code& ec) ++{ ++ if (is_open(impl)) ++ { ++ ec = boost::asio::error::already_open; ++ return ec; ++ } ++ ++ if (int err = reactor_.register_descriptor( ++ native_socket, impl.reactor_data_)) ++ { ++ ec = boost::system::error_code(err, ++ boost::asio::error::get_system_category()); ++ return ec; ++ } ++ ++ impl.socket_ = native_socket; ++ switch (type) ++ { ++ case SOCK_STREAM: impl.state_ = socket_ops::stream_oriented; break; ++ case SOCK_DGRAM: impl.state_ = socket_ops::datagram_oriented; break; ++ default: impl.state_ = 0; break; ++ } ++ impl.state_ |= socket_ops::possible_dup; ++ ec = boost::system::error_code(); ++ return ec; ++} ++ ++void reactive_socket_service_base_ext_local::start_op( ++ reactive_socket_service_base_ext_local::base_implementation_type& impl, ++ int op_type, reactor_op* op, bool is_continuation, ++ bool is_non_blocking, bool noop) ++{ ++ if (!noop) ++ { ++ if ((impl.state_ & socket_ops::non_blocking) ++ || socket_ops::set_internal_non_blocking( ++ impl.socket_, impl.state_, true, op->ec_)) ++ { ++ reactor_.start_op(op_type, impl.socket_, ++ impl.reactor_data_, op, is_continuation, is_non_blocking); ++ return; ++ } ++ } ++ ++ reactor_.post_immediate_completion(op, is_continuation); ++} ++ ++void reactive_socket_service_base_ext_local::start_accept_op( ++ reactive_socket_service_base_ext_local::base_implementation_type& impl, ++ reactor_op* op, bool is_continuation, bool peer_is_open) ++{ ++ if (!peer_is_open) ++ start_op(impl, reactor::read_op, op, is_continuation, true, false); ++ else ++ { ++ op->ec_ = boost::asio::error::already_open; ++ reactor_.post_immediate_completion(op, is_continuation); ++ } ++} ++ ++void reactive_socket_service_base_ext_local::start_connect_op( ++ reactive_socket_service_base_ext_local::base_implementation_type& impl, ++ reactor_op* op, bool is_continuation, ++ const socket_addr_type* addr, size_t addrlen) ++{ ++ if ((impl.state_ & socket_ops::non_blocking) ++ || socket_ops::set_internal_non_blocking( ++ impl.socket_, impl.state_, true, op->ec_)) ++ { ++ if (socket_ops::connect(impl.socket_, addr, addrlen, op->ec_) != 0) ++ { ++ if (op->ec_ == boost::asio::error::in_progress ++ || op->ec_ == boost::asio::error::would_block) ++ { ++ op->ec_ = boost::system::error_code(); ++ reactor_.start_op(reactor::connect_op, impl.socket_, ++ impl.reactor_data_, op, is_continuation, false); ++ return; ++ } ++ } ++ } ++ ++ reactor_.post_immediate_completion(op, is_continuation); ++} ++ ++} // namespace detail ++} // namespace asio ++} // namespace boost ++ ++#include ++ ++#endif // !defined(BOOST_ASIO_HAS_IOCP) ++ // && !defined(BOOST_ASIO_WINDOWS_RUNTIME) ++ ++#endif // BOOST_ASIO_DETAIL_IMPL_REACTIVE_SOCKET_SERVICE_BASE_EXT_LOCAL_IPP +diff --git a/implementation/helper/1.76/boost/asio/detail/impl/socket_ops_ext.ipp b/implementation/helper/1.76/boost/asio/detail/impl/socket_ops_ext.ipp +new file mode 100644 +index 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 ++ ++#include ++ ++namespace boost { ++namespace asio { ++namespace detail { ++namespace socket_ops { ++ ++signed_size_type recvfrom(socket_type s, buf* bufs, size_t count, ++ int flags, socket_addr_type* addr, std::size_t* addrlen, ++ boost::system::error_code& ec, boost::asio::ip::address& da) ++{ ++ ++#if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) ++ GUID WSARecvMsg_GUID = WSAID_WSARECVMSG; ++ LPFN_WSARECVMSG WSARecvMsg; ++ DWORD NumberOfBytes; ++ signed_size_type result; ++ ++ result = WSAIoctl(s, SIO_GET_EXTENSION_FUNCTION_POINTER, ++ &WSARecvMsg_GUID, sizeof WSARecvMsg_GUID, ++ &WSARecvMsg, sizeof WSARecvMsg, ++ &NumberOfBytes, NULL, NULL); ++ get_last_error(ec, true); ++ if (ec.value() == SOCKET_ERROR) { ++ WSARecvMsg = NULL; ++ return 0; ++ } ++ ++ WSABUF wsaBuf; ++ WSAMSG msg; ++ char controlBuffer[1024]; ++ msg.name = addr; ++ msg.namelen = *addrlen; ++ wsaBuf.buf = bufs->buf; ++ wsaBuf.len = bufs->len; ++ msg.lpBuffers = &wsaBuf; ++ msg.dwBufferCount = count; ++ msg.Control.len = sizeof controlBuffer; ++ msg.Control.buf = controlBuffer; ++ msg.dwFlags = flags; ++ ++ DWORD dwNumberOfBytesRecvd; ++ result = WSARecvMsg(s, &msg, &dwNumberOfBytesRecvd, NULL, NULL); ++ get_last_error(ec, true); ++ ++ if (result >= 0) { ++ ec = boost::system::error_code(); ++ ++ // Find destination address ++ for (LPWSACMSGHDR cmsg = WSA_CMSG_FIRSTHDR(&msg); ++ cmsg != NULL; ++ cmsg = WSA_CMSG_NXTHDR(&msg, cmsg)) ++ { ++ if (cmsg->cmsg_level == IPPROTO_IP && cmsg->cmsg_type == IP_PKTINFO) ++ { ++ struct in_pktinfo *pi = (struct in_pktinfo *) WSA_CMSG_DATA(cmsg); ++ if (pi) ++ { ++ da = boost::asio::ip::address_v4(ntohl(pi->ipi_addr.s_addr)); ++ } ++ } else ++ if (cmsg->cmsg_level == IPPROTO_IPV6 && cmsg->cmsg_type == IPV6_PKTINFO) ++ { ++ struct in6_pktinfo *pi = (struct in6_pktinfo *) WSA_CMSG_DATA(cmsg); ++ if (pi) ++ { ++ boost::asio::ip::address_v6::bytes_type b; ++ memcpy(b.data(), pi->ipi6_addr.s6_addr, sizeof(pi->ipi6_addr.s6_addr)); ++ da = boost::asio::ip::address_v6(b); ++ } ++ } ++ } ++ } else { ++ dwNumberOfBytesRecvd = -1; ++ } ++ return dwNumberOfBytesRecvd; ++#else // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) ++ char cmbuf[0x100]; ++ msghdr msg = msghdr(); ++ init_msghdr_msg_name(msg.msg_name, addr); ++ msg.msg_namelen = static_cast(*addrlen); ++ msg.msg_iov = bufs; ++ msg.msg_iovlen = static_cast(count); ++ msg.msg_control = cmbuf; ++ msg.msg_controllen = sizeof(cmbuf); ++ signed_size_type result = ::recvmsg(s, &msg, flags); ++ get_last_error(ec, true); ++ *addrlen = msg.msg_namelen; ++ if (result >= 0) { ++ ec.assign(0, ec.category()); ++ ++ // Find destination address ++ for (struct cmsghdr *cmsg = CMSG_FIRSTHDR(&msg); ++ cmsg != NULL; ++ cmsg = CMSG_NXTHDR(&msg, cmsg)) ++ { ++ if (cmsg->cmsg_level == IPPROTO_IP && cmsg->cmsg_type == IP_PKTINFO) ++ { ++ struct in_pktinfo *pi = (struct in_pktinfo *) CMSG_DATA(cmsg); ++ if (pi) ++ { ++ da = boost::asio::ip::address_v4(ntohl(pi->ipi_addr.s_addr)); ++ } ++ } else ++ if (cmsg->cmsg_level == IPPROTO_IPV6 && cmsg->cmsg_type == IPV6_PKTINFO) ++ { ++ struct in6_pktinfo *pi = (struct in6_pktinfo *) CMSG_DATA(cmsg); ++ if (pi) ++ { ++ boost::asio::ip::address_v6::bytes_type b; ++ memcpy(b.data(), pi->ipi6_addr.s6_addr, sizeof(pi->ipi6_addr.s6_addr)); ++ da = boost::asio::ip::address_v6(b); ++ } ++ } ++ } ++ } ++ return result; ++#endif // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) ++} ++ ++size_t sync_recvfrom(socket_type s, state_type state, buf* bufs, ++ size_t count, int flags, socket_addr_type* addr, ++ std::size_t* addrlen, boost::system::error_code& ec, boost::asio::ip::address& da) ++{ ++ if (s == invalid_socket) ++ { ++ ec = boost::asio::error::bad_descriptor; ++ return 0; ++ } ++ ++ // Read some data. ++ for (;;) ++ { ++ // Try to complete the operation without blocking. ++ signed_size_type bytes = socket_ops::recvfrom( ++ s, bufs, count, flags, addr, addrlen, ec, da); ++ ++ // Check if operation succeeded. ++ if (bytes >= 0) ++ return bytes; ++ ++ // Operation failed. ++ if ((state & user_set_non_blocking) ++ || (ec != boost::asio::error::would_block ++ && ec != boost::asio::error::try_again)) ++ return 0; ++ ++ // Wait for socket to become ready. ++ if (socket_ops::poll_read(s, 0, -1, ec) < 0) ++ return 0; ++ } ++} ++ ++#if defined(BOOST_ASIO_HAS_IOCP) ++ ++void complete_iocp_recvfrom( ++ const weak_cancel_token_type& cancel_token, ++ boost::system::error_code& ec, boost::asio::ip::address& da) ++{ ++ // Map non-portable errors to their portable counterparts. ++ if (ec.value() == ERROR_NETNAME_DELETED) ++ { ++ if (cancel_token.expired()) ++ ec = boost::asio::error::operation_aborted; ++ else ++ ec = boost::asio::error::connection_reset; ++ } ++ else if (ec.value() == ERROR_PORT_UNREACHABLE) ++ { ++ ec = boost::asio::error::connection_refused; ++ } ++} ++ ++#else // defined(BOOST_ASIO_HAS_IOCP) ++ ++bool non_blocking_recvfrom(socket_type s, ++ buf* bufs, size_t count, int flags, ++ socket_addr_type* addr, std::size_t* addrlen, ++ boost::system::error_code& ec, size_t& bytes_transferred, boost::asio::ip::address& da) ++{ ++ for (;;) ++ { ++ // Read some data. ++ signed_size_type bytes = socket_ops::recvfrom( ++ s, bufs, count, flags, addr, addrlen, ec, da); ++ ++ // Retry operation if interrupted by signal. ++ if (ec == boost::asio::error::interrupted) ++ continue; ++ ++ // Check if we need to run the operation again. ++ if (ec == boost::asio::error::would_block ++ || ec == boost::asio::error::try_again) ++ return false; ++ ++ // Operation is complete. ++ if (bytes >= 0) ++ { ++ ec = boost::system::error_code(); ++ bytes_transferred = bytes; ++ } ++ else ++ bytes_transferred = 0; ++ ++ return true; ++ } ++} ++ ++#endif // defined(BOOST_ASIO_HAS_IOCP) ++ ++} // namespace socket_ops ++} // namespace detail ++} // namespace asio ++} // namespace boost ++ ++#include ++ ++#endif // BOOST_ASIO_DETAIL_SOCKET_OPS_EXT_IPP +diff --git a/implementation/helper/1.76/boost/asio/detail/impl/socket_ops_ext_local.ipp b/implementation/helper/1.76/boost/asio/detail/impl/socket_ops_ext_local.ipp +new file mode 100644 +index 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 ++ ++#include ++ ++namespace boost { ++namespace asio { ++namespace detail { ++namespace socket_ops { ++ ++signed_size_type recv(socket_type s, buf* bufs, size_t count, ++ int flags, boost::system::error_code& ec, ++ std::uint32_t& uid, std::uint32_t& gid) ++{ ++ uid = 0xFFFFFFFF; ++ gid = 0xFFFFFFFF; ++ struct ucred *ucredp; ++ ++#if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) ++ // Receive some data. ++ DWORD recv_buf_count = static_cast(count); ++ DWORD bytes_transferred = 0; ++ DWORD recv_flags = flags; ++ int result = ::WSARecv(s, bufs, ++ recv_buf_count, &bytes_transferred, &recv_flags, 0, 0); ++ get_last_error(ec, true); ++ if (ec.value() == ERROR_NETNAME_DELETED) ++ ec = boost::asio::error::connection_reset; ++ else if (ec.value() == ERROR_PORT_UNREACHABLE) ++ ec = boost::asio::error::connection_refused; ++ if (result != 0) ++ return socket_error_retval; ++ ec.assign(0, ec.category()); ++ return bytes_transferred; ++#else // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) ++ msghdr msg = msghdr(); ++ msg.msg_iov = bufs; ++ msg.msg_iovlen = static_cast(count); ++ ++ union { ++ struct cmsghdr cmh; ++ char control[CMSG_SPACE(sizeof(struct ucred))]; ++ } control_un; ++ ++ // Set 'control_un' to describe ancillary data that we want to receive ++ control_un.cmh.cmsg_len = CMSG_LEN(sizeof(struct ucred)); ++ control_un.cmh.cmsg_level = SOL_SOCKET; ++ control_un.cmh.cmsg_type = SCM_CREDENTIALS; ++ ++ // Set 'msg' fields to describe 'control_un' ++ msg.msg_control = control_un.control; ++ msg.msg_controllen = sizeof(control_un.control); ++ ++ signed_size_type result = ::recvmsg(s, &msg, flags); ++ get_last_error(ec, true); ++ if (result >= 0) { ++ ec.assign(0, ec.category()); ++ ++ // Find UID / GID ++ for (struct cmsghdr *cmsg = CMSG_FIRSTHDR(&msg); ++ cmsg != NULL; ++ cmsg = CMSG_NXTHDR(&msg, cmsg)) ++ { ++ if (cmsg->cmsg_level != SOL_SOCKET || cmsg->cmsg_type != SCM_CREDENTIALS ++ || cmsg->cmsg_len != CMSG_LEN(sizeof(struct ucred))) ++ continue; ++ ++ ucredp = (struct ucred *) CMSG_DATA(cmsg); ++ if (ucredp) { ++ uid = ucredp->uid; ++ gid = ucredp->gid; ++ } ++ } ++ } ++ return result; ++#endif // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) ++} ++ ++signed_size_type recvfrom(socket_type s, buf* bufs, size_t count, ++ int flags, socket_addr_type* addr, std::size_t* addrlen, ++ boost::system::error_code& ec, ++ std::uint32_t& uid, std::uint32_t& gid) ++{ ++ uid = 0xFFFFFFFF; ++ gid = 0xFFFFFFFF; ++ struct ucred *ucredp; ++ clear_last_error(); ++#if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) ++ // Receive some data. ++ DWORD recv_buf_count = static_cast(count); ++ DWORD bytes_transferred = 0; ++ DWORD recv_flags = flags; ++ int tmp_addrlen = (int)*addrlen; ++ int result = ::WSARecvFrom(s, bufs, recv_buf_count, ++ &bytes_transferred, &recv_flags, addr, &tmp_addrlen, 0, 0); ++ get_last_error(ec, true); ++ *addrlen = (std::size_t)tmp_addrlen; ++ if (ec.value() == ERROR_NETNAME_DELETED) ++ ec = boost::asio::error::connection_reset; ++ else if (ec.value() == ERROR_PORT_UNREACHABLE) ++ ec = boost::asio::error::connection_refused; ++ if (result != 0) ++ return socket_error_retval; ++ ec.assign(0, ec.category()); ++ return bytes_transferred; ++#else // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) ++ msghdr msg = msghdr(); ++ init_msghdr_msg_name(msg.msg_name, addr); ++ msg.msg_namelen = static_cast(*addrlen); ++ msg.msg_iov = bufs; ++ msg.msg_iovlen = static_cast(count); ++ ++ union { ++ struct cmsghdr cmh; ++ char control[CMSG_SPACE(sizeof(struct ucred))]; ++ } control_un; ++ ++ // Set 'control_un' to describe ancillary data that we want to receive ++ control_un.cmh.cmsg_len = CMSG_LEN(sizeof(struct ucred)); ++ control_un.cmh.cmsg_level = SOL_SOCKET; ++ control_un.cmh.cmsg_type = SCM_CREDENTIALS; ++ ++ // Set 'msg' fields to describe 'control_un' ++ msg.msg_control = control_un.control; ++ msg.msg_controllen = sizeof(control_un.control); ++ ++ signed_size_type result = ::recvmsg(s, &msg, flags); ++ get_last_error(ec, true); ++ *addrlen = msg.msg_namelen; ++ if (result >= 0) { ++ ec.assign(0, ec.category()); ++ ++ // Find UID / GID ++ for (struct cmsghdr *cmsg = CMSG_FIRSTHDR(&msg); ++ cmsg != NULL; ++ cmsg = CMSG_NXTHDR(&msg, cmsg)) ++ { ++ if (cmsg->cmsg_level != SOL_SOCKET || cmsg->cmsg_type != SCM_CREDENTIALS ++ || cmsg->cmsg_len != CMSG_LEN(sizeof(struct ucred))) ++ continue; ++ ++ ucredp = (struct ucred *) CMSG_DATA(cmsg); ++ if (ucredp) { ++ uid = ucredp->uid; ++ gid = ucredp->gid; ++ } ++ } ++ } ++ return result; ++#endif // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) ++} ++ ++size_t sync_recvfrom(socket_type s, state_type state, buf* bufs, ++ size_t count, int flags, socket_addr_type* addr, ++ std::size_t* addrlen, boost::system::error_code& ec, ++ std::uint32_t& uid, std::uint32_t& gid) ++{ ++ if (s == invalid_socket) ++ { ++ ec = boost::asio::error::bad_descriptor; ++ return 0; ++ } ++ ++ // Read some data. ++ for (;;) ++ { ++ // Try to complete the operation without blocking. ++ signed_size_type bytes = socket_ops::recvfrom( ++ s, bufs, count, flags, addr, addrlen, ec, uid, gid); ++ ++ // Check if operation succeeded. ++ if (bytes >= 0) ++ return bytes; ++ ++ // Operation failed. ++ if ((state & user_set_non_blocking) ++ || (ec != boost::asio::error::would_block ++ && ec != boost::asio::error::try_again)) ++ return 0; ++ ++ // Wait for socket to become ready. ++ if (socket_ops::poll_read(s, 0, -1, ec) < 0) ++ return 0; ++ } ++} ++ ++#if defined(BOOST_ASIO_HAS_IOCP) ++ ++void complete_iocp_recvfrom( ++ const weak_cancel_token_type& cancel_token, ++ boost::system::error_code& ec, ++ std::uint32_t& uid, std::uint32_t& gid) ++{ ++ uid = 0xFFFFFFFF; ++ gid = 0xFFFFFFFF; ++ // Map non-portable errors to their portable counterparts. ++ if (ec.value() == ERROR_NETNAME_DELETED) ++ { ++ if (cancel_token.expired()) ++ ec = boost::asio::error::operation_aborted; ++ else ++ ec = boost::asio::error::connection_reset; ++ } ++ else if (ec.value() == ERROR_PORT_UNREACHABLE) ++ { ++ ec = boost::asio::error::connection_refused; ++ } ++} ++ ++#else // defined(BOOST_ASIO_HAS_IOCP) ++ ++bool non_blocking_recv(socket_type s, ++ buf* bufs, size_t count, int flags, bool is_stream, ++ boost::system::error_code& ec, size_t& bytes_transferred, ++ std::uint32_t& uid, std::uint32_t& gid) ++{ ++ for (;;) ++ { ++ // Read some data. ++ signed_size_type bytes = socket_ops::recv(s, bufs, count, flags, ec, uid, gid); ++ ++ // Check for end of stream. ++ if (is_stream && bytes == 0) ++ { ++ ec = boost::asio::error::eof; ++ return true; ++ } ++ ++ // Retry operation if interrupted by signal. ++ if (ec == boost::asio::error::interrupted) ++ continue; ++ ++ // Check if we need to run the operation again. ++ if (ec == boost::asio::error::would_block ++ || ec == boost::asio::error::try_again) ++ return false; ++ ++ // Operation is complete. ++ if (bytes >= 0) ++ { ++ ec = boost::system::error_code(); ++ bytes_transferred = bytes; ++ } ++ else ++ bytes_transferred = 0; ++ ++ return true; ++ } ++} ++ ++bool non_blocking_recvfrom(socket_type s, ++ buf* bufs, size_t count, int flags, ++ socket_addr_type* addr, std::size_t* addrlen, ++ boost::system::error_code& ec, size_t& bytes_transferred, ++ std::uint32_t& uid, std::uint32_t& gid) ++{ ++ for (;;) ++ { ++ // Read some data. ++ signed_size_type bytes = socket_ops::recvfrom( ++ s, bufs, count, flags, addr, addrlen, ec, uid, gid); ++ ++ // Retry operation if interrupted by signal. ++ if (ec == boost::asio::error::interrupted) ++ continue; ++ ++ // Check if we need to run the operation again. ++ if (ec == boost::asio::error::would_block ++ || ec == boost::asio::error::try_again) ++ return false; ++ ++ // Operation is complete. ++ if (bytes >= 0) ++ { ++ ec = boost::system::error_code(); ++ bytes_transferred = bytes; ++ } ++ else ++ bytes_transferred = 0; ++ ++ return true; ++ } ++} ++ ++#endif // defined(BOOST_ASIO_HAS_IOCP) ++ ++} // namespace socket_ops ++} // namespace detail ++} // namespace asio ++} // namespace boost ++ ++#include ++ ++#endif // BOOST_ASIO_DETAIL_SOCKET_OPS_EXT_LOCAL_IPP +diff --git a/implementation/helper/1.76/boost/asio/detail/reactive_socket_recv_op_ext.hpp b/implementation/helper/1.76/boost/asio/detail/reactive_socket_recv_op_ext.hpp +new file mode 100644 +index 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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++namespace boost { ++namespace asio { ++namespace detail { ++ ++template ++class reactive_socket_recv_op_base_ext : public reactor_op_ext ++{ ++public: ++ reactive_socket_recv_op_base_ext(const boost::system::error_code& success_ec, ++ socket_type socket, socket_ops::state_type state, ++ const MutableBufferSequence& buffers, ++ socket_base::message_flags flags, func_type complete_func) ++ : reactor_op_ext(success_ec, &reactive_socket_recv_op_base_ext::do_perform, complete_func), ++ socket_(socket), ++ state_(state), ++ buffers_(buffers), ++ flags_(flags) ++ { ++ } ++ ++ static status do_perform(reactor_op* base) ++ { ++ reactive_socket_recv_op_base_ext* o( ++ static_cast(base)); ++ ++ typedef buffer_sequence_adapter bufs_type; ++ ++ status result; ++ if (bufs_type::is_single_buffer) ++ { ++ result = socket_ops::non_blocking_recv1(o->socket_, ++ bufs_type::first(o->buffers_).data(), ++ bufs_type::first(o->buffers_).size(), o->flags_, ++ (o->state_ & socket_ops::stream_oriented) != 0, ++ o->ec_, o->bytes_transferred_) ? done : not_done; ++ } ++ else ++ { ++ bufs_type bufs(o->buffers_); ++ result = socket_ops::non_blocking_recv(o->socket_, ++ bufs.buffers(), bufs.count(), o->flags_, ++ (o->state_ & socket_ops::stream_oriented) != 0, ++ o->ec_, o->bytes_transferred_) ? done : not_done; ++ } ++ ++ if (result == done) ++ if ((o->state_ & socket_ops::stream_oriented) != 0) ++ if (o->bytes_transferred_ == 0) ++ result = done_and_exhausted; ++ ++ BOOST_ASIO_HANDLER_REACTOR_OPERATION((*o, "non_blocking_recv", ++ o->ec_, o->bytes_transferred_)); ++ ++ return result; ++ } ++ ++private: ++ socket_type socket_; ++ socket_ops::state_type state_; ++ MutableBufferSequence buffers_; ++ socket_base::message_flags flags_; ++}; ++ ++template ++class reactive_socket_recv_op_ext : ++ public reactive_socket_recv_op_base_ext ++{ ++public: ++ BOOST_ASIO_DEFINE_HANDLER_PTR(reactive_socket_recv_op_ext); ++ ++ reactive_socket_recv_op_ext(const boost::system::error_code& success_ec, ++ socket_type socket, socket_ops::state_type state, ++ const MutableBufferSequence& buffers, socket_base::message_flags flags, ++ Handler& handler, const IoExecutor& io_ex) ++ : reactive_socket_recv_op_base_ext(success_ec, ++ socket, state, buffers, flags, ++ &reactive_socket_recv_op_ext::do_complete), ++ handler_(BOOST_ASIO_MOVE_CAST(Handler)(handler)), ++ work_(handler_, io_ex) ++ { ++ } ++ ++ static void do_complete(void* owner, operation* base, ++ const boost::system::error_code& /*ec*/, ++ std::size_t /*bytes_transferred*/) ++ { ++ // Take ownership of the handler object. ++ reactive_socket_recv_op_ext* o(static_cast(base)); ++ ptr p = { boost::asio::detail::addressof(o->handler_), o, o }; ++ ++ BOOST_ASIO_HANDLER_COMPLETION((*o)); ++ ++ // Take ownership of the operation's outstanding work. ++ handler_work w( ++ BOOST_ASIO_MOVE_CAST2(handler_work)( ++ o->work_)); ++ ++ // Make a copy of the handler so that the memory can be deallocated before ++ // the upcall is made. Even if we're not about to make an upcall, a ++ // sub-object of the handler may be the true owner of the memory associated ++ // with the handler. Consequently, a local copy of the handler is required ++ // to ensure that any owning sub-object remains valid until after we have ++ // deallocated the memory here. ++ detail::binder3 ++ handler(o->handler_, o->ec_, o->bytes_transferred_, o->da_); ++ p.h = boost::asio::detail::addressof(handler.handler_); ++ p.reset(); ++ ++ // Make the upcall if required. ++ if (owner) ++ { ++ fenced_block b(fenced_block::half); ++ BOOST_ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, handler.arg2_, handler.arg3_)); ++ w.complete(handler, handler.handler_); ++ BOOST_ASIO_HANDLER_INVOCATION_END; ++ } ++ } ++ ++private: ++ Handler handler_; ++ handler_work work_; ++}; ++ ++} // namespace detail ++} // namespace asio ++} // namespace boost ++ ++#include ++ ++#endif // BOOST_ASIO_DETAIL_REACTIVE_SOCKET_RECV_OP_EXT_HPP +diff --git a/implementation/helper/1.76/boost/asio/detail/reactive_socket_recv_op_ext_local.hpp b/implementation/helper/1.76/boost/asio/detail/reactive_socket_recv_op_ext_local.hpp +new file mode 100644 +index 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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++namespace boost { ++namespace asio { ++namespace detail { ++ ++template ++class reactive_socket_recv_op_base_ext_local : public reactor_op_ext_local ++{ ++public: ++ reactive_socket_recv_op_base_ext_local(const boost::system::error_code& success_ec, ++ socket_type socket, socket_ops::state_type state, ++ const MutableBufferSequence& buffers, ++ socket_base::message_flags flags, func_type complete_func) ++ : reactor_op_ext_local(success_ec, &reactive_socket_recv_op_base_ext_local::do_perform, complete_func), ++ socket_(socket), ++ state_(state), ++ buffers_(buffers), ++ flags_(flags) ++ { ++ } ++ ++ static status do_perform(reactor_op* base) ++ { ++ reactive_socket_recv_op_base_ext_local* o( ++ static_cast(base)); ++ ++ typedef buffer_sequence_adapter bufs_type; ++ ++ status result; ++ if (bufs_type::is_single_buffer) ++ { ++ result = socket_ops::non_blocking_recv1(o->socket_, ++ bufs_type::first(o->buffers_).data(), ++ bufs_type::first(o->buffers_).size(), o->flags_, ++ (o->state_ & socket_ops::stream_oriented) != 0, ++ o->ec_, o->bytes_transferred_) ? done : not_done; ++ } ++ else ++ { ++ bufs_type bufs(o->buffers_); ++ result = socket_ops::non_blocking_recv(o->socket_, ++ bufs.buffers(), bufs.count(), o->flags_, ++ (o->state_ & socket_ops::stream_oriented) != 0, ++ o->ec_, o->bytes_transferred_) ? done : not_done; ++ } ++ ++ if (result == done) ++ if ((o->state_ & socket_ops::stream_oriented) != 0) ++ if (o->bytes_transferred_ == 0) ++ result = done_and_exhausted; ++ ++ BOOST_ASIO_HANDLER_REACTOR_OPERATION((*o, "non_blocking_recv", ++ o->ec_, o->bytes_transferred_)); ++ ++ return result; ++ } ++ ++private: ++ socket_type socket_; ++ socket_ops::state_type state_; ++ MutableBufferSequence buffers_; ++ socket_base::message_flags flags_; ++}; ++ ++template ++class reactive_socket_recv_op_ext_local : ++ public reactive_socket_recv_op_base_ext_local ++{ ++public: ++ BOOST_ASIO_DEFINE_HANDLER_PTR(reactive_socket_recv_op_ext_local); ++ ++ reactive_socket_recv_op_ext_local(const boost::system::error_code& success_ec, ++ socket_type socket, socket_ops::state_type state, ++ const MutableBufferSequence& buffers, socket_base::message_flags flags, ++ Handler& handler, const IoExecutor& io_ex) ++ : reactive_socket_recv_op_base_ext_local(success_ec, ++ socket, state, buffers, flags, ++ &reactive_socket_recv_op_ext_local::do_complete), ++ handler_(BOOST_ASIO_MOVE_CAST(Handler)(handler)), ++ work_(handler_, io_ex) ++ { ++ } ++ ++ static void do_complete(void* owner, operation* base, ++ const boost::system::error_code& /*ec*/, ++ std::size_t /*bytes_transferred*/) ++ { ++ // Take ownership of the handler object. ++ reactive_socket_recv_op_ext_local* o(static_cast(base)); ++ ptr p = { boost::asio::detail::addressof(o->handler_), o, o }; ++ ++ BOOST_ASIO_HANDLER_COMPLETION((*o)); ++ ++ // Take ownership of the operation's outstanding work. ++ handler_work w( ++ BOOST_ASIO_MOVE_CAST2(handler_work)( ++ o->work_)); ++ ++ // Make a copy of the handler so that the memory can be deallocated before ++ // the upcall is made. Even if we're not about to make an upcall, a ++ // sub-object of the handler may be the true owner of the memory associated ++ // with the handler. Consequently, a local copy of the handler is required ++ // to ensure that any owning sub-object remains valid until after we have ++ // deallocated the memory here. ++ detail::binder4 ++ handler(o->handler_, o->ec_, o->bytes_transferred_, o->uid_, o->gid_); ++ p.h = boost::asio::detail::addressof(handler.handler_); ++ p.reset(); ++ ++ // Make the upcall if required. ++ if (owner) ++ { ++ fenced_block b(fenced_block::half); ++ BOOST_ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, handler.arg2_, handler.arg3, handler.arg4)); ++ w.complete(handler, handler.handler_); ++ BOOST_ASIO_HANDLER_INVOCATION_END; ++ } ++ } ++ ++private: ++ Handler handler_; ++ handler_work work_; ++}; ++ ++} // namespace detail ++} // namespace asio ++} // namespace boost ++ ++#include ++ ++#endif // BOOST_ASIO_DETAIL_REACTIVE_SOCKET_RECV_OP_EXT_LOCAL_HPP +diff --git a/implementation/helper/1.76/boost/asio/detail/reactive_socket_recvfrom_op_ext.hpp b/implementation/helper/1.76/boost/asio/detail/reactive_socket_recvfrom_op_ext.hpp +new file mode 100644 +index 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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++namespace boost { ++namespace asio { ++namespace detail { ++ ++template ++class reactive_socket_recvfrom_op_base_ext : public reactor_op_ext ++{ ++public: ++ reactive_socket_recvfrom_op_base_ext(const boost::system::error_code& success_ec, ++ socket_type socket, int protocol_type, ++ const MutableBufferSequence& buffers, Endpoint& endpoint, ++ socket_base::message_flags flags, func_type complete_func) ++ : reactor_op_ext(success_ec, &reactive_socket_recvfrom_op_base_ext::do_perform, complete_func), ++ socket_(socket), ++ protocol_type_(protocol_type), ++ buffers_(buffers), ++ sender_endpoint_(endpoint), ++ flags_(flags) ++ { ++ } ++ ++ static status do_perform(reactor_op* base) ++ { ++ reactive_socket_recvfrom_op_base_ext* o( ++ static_cast(base)); ++ ++ buffer_sequence_adapter bufs(o->buffers_); ++ ++ std::size_t addr_len = o->sender_endpoint_.capacity(); ++ status result = socket_ops::non_blocking_recvfrom(o->socket_, ++ bufs.buffers(), bufs.count(), o->flags_, ++ o->sender_endpoint_.data(), &addr_len, ++ o->ec_, o->bytes_transferred_, o->da_) ? done : not_done; ++ ++ if (result && !o->ec_) ++ o->sender_endpoint_.resize(addr_len); ++ ++ BOOST_ASIO_HANDLER_REACTOR_OPERATION((*o, "non_blocking_recvfrom", ++ o->ec_, o->bytes_transferred_)); ++ ++ return result; ++ } ++ ++private: ++ socket_type socket_; ++ int protocol_type_; ++ MutableBufferSequence buffers_; ++ Endpoint& sender_endpoint_; ++ socket_base::message_flags flags_; ++}; ++ ++template ++class reactive_socket_recvfrom_op_ext : ++ public reactive_socket_recvfrom_op_base_ext ++{ ++public: ++ BOOST_ASIO_DEFINE_HANDLER_PTR(reactive_socket_recvfrom_op_ext); ++ ++ reactive_socket_recvfrom_op_ext(const boost::system::error_code& success_ec, ++ socket_type socket, int protocol_type, ++ const MutableBufferSequence& buffers, Endpoint& endpoint, ++ socket_base::message_flags flags, Handler& handler, ++ const IoExecutor& io_ex) ++ : reactive_socket_recvfrom_op_base_ext( ++ success_ec, socket, protocol_type, buffers, endpoint, flags, ++ &reactive_socket_recvfrom_op_ext::do_complete), ++ handler_(BOOST_ASIO_MOVE_CAST(Handler)(handler)), ++ work_(handler_, io_ex) ++ { ++ } ++ ++ static void do_complete(void* owner, operation* base, ++ const boost::system::error_code& /*ec*/, ++ std::size_t /*bytes_transferred*/) ++ { ++ // Take ownership of the handler object. ++ reactive_socket_recvfrom_op_ext* o( ++ static_cast(base)); ++ ptr p = { boost::asio::detail::addressof(o->handler_), o, o }; ++ ++ BOOST_ASIO_HANDLER_COMPLETION((*o)); ++ ++ // Take ownership of the operation's outstanding work. ++ handler_work w( ++ BOOST_ASIO_MOVE_CAST2(handler_work)( ++ o->work_)); ++ ++ // Make a copy of the handler so that the memory can be deallocated before ++ // the upcall is made. Even if we're not about to make an upcall, a ++ // sub-object of the handler may be the true owner of the memory associated ++ // with the handler. Consequently, a local copy of the handler is required ++ // to ensure that any owning sub-object remains valid until after we have ++ // deallocated the memory here. ++ detail::binder3 ++ handler(o->handler_, o->ec_, o->bytes_transferred_, o->da_); ++ p.h = boost::asio::detail::addressof(handler.handler_); ++ p.reset(); ++ ++ // Make the upcall if required. ++ if (owner) ++ { ++ fenced_block b(fenced_block::half); ++ BOOST_ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, handler.arg2_, handler.arg3_)); ++ w.complete(handler, handler.handler_); ++ BOOST_ASIO_HANDLER_INVOCATION_END; ++ } ++ } ++ ++private: ++ Handler handler_; ++ handler_work work_; ++}; ++ ++} // namespace detail ++} // namespace asio ++} // namespace boost ++ ++#include ++ ++#endif // BOOST_ASIO_DETAIL_REACTIVE_SOCKET_RECVFROM_OP_EXT_HPP +diff --git a/implementation/helper/1.76/boost/asio/detail/reactive_socket_recvfrom_op_ext_local.hpp b/implementation/helper/1.76/boost/asio/detail/reactive_socket_recvfrom_op_ext_local.hpp +new file mode 100644 +index 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 ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++namespace boost { ++namespace asio { ++namespace detail { ++ ++template ++class reactive_socket_recvfrom_op_base_ext_local : public reactor_op_ext_local ++{ ++public: ++ reactive_socket_recvfrom_op_base_ext_local(socket_type socket, int protocol_type, ++ const MutableBufferSequence& buffers, Endpoint& endpoint, ++ socket_base::message_flags flags, func_type complete_func) ++ : reactor_op_ext_local(&reactive_socket_recvfrom_op_base_ext_local::do_perform, complete_func), ++ socket_(socket), ++ protocol_type_(protocol_type), ++ buffers_(buffers), ++ sender_endpoint_(endpoint), ++ flags_(flags) ++ { ++ } ++ ++ static status do_perform(reactor_op* base) ++ { ++ reactive_socket_recvfrom_op_base_ext_local* o( ++ static_cast(base)); ++ ++ buffer_sequence_adapter bufs(o->buffers_); ++ ++ std::size_t addr_len = o->sender_endpoint_.capacity(); ++ status result = socket_ops::non_blocking_recvfrom(o->socket_, ++ bufs.buffers(), bufs.count(), o->flags_, ++ o->sender_endpoint_.data(), &addr_len, ++ o->ec_, o->bytes_transferred_, o->uid_, o->gid_) ? done : not_done; ++ ++ if (result && !o->ec_) ++ o->sender_endpoint_.resize(addr_len); ++ ++ BOOST_ASIO_HANDLER_REACTOR_OPERATION((*o, "non_blocking_recvfrom", ++ o->ec_, o->bytes_transferred_)); ++ ++ return result; ++ } ++ ++private: ++ socket_type socket_; ++ int protocol_type_; ++ MutableBufferSequence buffers_; ++ Endpoint& sender_endpoint_; ++ socket_base::message_flags flags_; ++}; ++ ++template ++class reactive_socket_recvfrom_op_ext_local : ++ public reactive_socket_recvfrom_op_base_ext_local ++{ ++public: ++ BOOST_ASIO_DEFINE_HANDLER_PTR(reactive_socket_recvfrom_op_ext_local); ++ ++ reactive_socket_recvfrom_op_ext_local(socket_type socket, int protocol_type, ++ const MutableBufferSequence& buffers, Endpoint& endpoint, ++ socket_base::message_flags flags, Handler& handler, ++ const IoExecutor& io_ex) ++ : reactive_socket_recvfrom_op_base_ext_local( ++ socket, protocol_type, buffers, endpoint, flags, ++ &reactive_socket_recvfrom_op_ext_local::do_complete), ++ handler_(BOOST_ASIO_MOVE_CAST(Handler)(handler)), ++ work_(handler_, io_ex) ++ { ++ } ++ ++ static void do_complete(void* owner, operation* base, ++ const boost::system::error_code& /*ec*/, ++ std::size_t /*bytes_transferred*/) ++ { ++ // Take ownership of the handler object. ++ reactive_socket_recvfrom_op_ext_local* o( ++ static_cast(base)); ++ ptr p = { boost::asio::detail::addressof(o->handler_), o, o }; ++ ++ BOOST_ASIO_HANDLER_COMPLETION((*o)); ++ ++ // Take ownership of the operation's outstanding work. ++ handler_work w( ++ BOOST_ASIO_MOVE_CAST2(handler_work)( ++ o->work_)); ++ ++ // Make a copy of the handler so that the memory can be deallocated before ++ // the upcall is made. Even if we're not about to make an upcall, a ++ // sub-object of the handler may be the true owner of the memory associated ++ // with the handler. Consequently, a local copy of the handler is required ++ // to ensure that any owning sub-object remains valid until after we have ++ // deallocated the memory here. ++ detail::binder4 ++ handler(o->handler_, o->ec_, o->bytes_transferred_, o->uid_, o->gid_); ++ p.h = boost::asio::detail::addressof(handler.handler_); ++ p.reset(); ++ ++ // Make the upcall if required. ++ if (owner) ++ { ++ fenced_block b(fenced_block::half); ++ BOOST_ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, handler.arg2_, handler.arg3_, handler.arg4_)); ++ w.complete(handler, handler.handler_); ++ BOOST_ASIO_HANDLER_INVOCATION_END; ++ } ++ } ++ ++private: ++ Handler handler_; ++ handler_work work_; ++}; ++ ++} // namespace detail ++} // namespace asio ++} // namespace boost ++ ++#include ++ ++#endif // BOOST_ASIO_DETAIL_REACTIVE_SOCKET_RECVFROM_OP_EXT_LOCAL_HPP +diff --git a/implementation/helper/1.76/boost/asio/detail/reactive_socket_recvmsg_op_ext.hpp b/implementation/helper/1.76/boost/asio/detail/reactive_socket_recvmsg_op_ext.hpp +new file mode 100644 +index 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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++namespace boost { ++namespace asio { ++namespace detail { ++ ++template ++class reactive_socket_recvmsg_op_base_ext : public reactor_op_ext ++{ ++public: ++ reactive_socket_recvmsg_op_base_ext(const boost::system::error_code& success_ec, ++ socket_type socket, const MutableBufferSequence& buffers, socket_base::message_flags in_flags, ++ socket_base::message_flags& out_flags, func_type complete_func) ++ : reactor_op_ext(&reactive_socket_recvmsg_op_base_ext::do_perform, complete_func), ++ socket_(socket), ++ buffers_(buffers), ++ in_flags_(in_flags), ++ out_flags_(out_flags) ++ { ++ } ++ ++ static status do_perform(reactor_op* base) ++ { ++ reactive_socket_recvmsg_op_base_ext* o( ++ static_cast(base)); ++ ++ buffer_sequence_adapter bufs(o->buffers_); ++ ++ status result = socket_ops::non_blocking_recvmsg(o->socket_, ++ bufs.buffers(), bufs.count(), ++ o->in_flags_, o->out_flags_, ++ o->ec_, o->bytes_transferred_) ? done : not_done; ++ ++ BOOST_ASIO_HANDLER_REACTOR_OPERATION((*o, "non_blocking_recvmsg", ++ o->ec_, o->bytes_transferred_)); ++ ++ return result; ++ } ++ ++private: ++ socket_type socket_; ++ MutableBufferSequence buffers_; ++ socket_base::message_flags in_flags_; ++ socket_base::message_flags& out_flags_; ++}; ++ ++template ++class reactive_socket_recvmsg_op_ext : ++ public reactive_socket_recvmsg_op_base_ext ++{ ++public: ++ BOOST_ASIO_DEFINE_HANDLER_PTR(reactive_socket_recvmsg_op_ext); ++ ++ reactive_socket_recvmsg_op_ext(const boost::system::error_code& success_ec, ++ socket_type socket, const MutableBufferSequence& buffers, socket_base::message_flags in_flags, ++ socket_base::message_flags& out_flags, Handler& handler, ++ const IoExecutor& io_ex) ++ : reactive_socket_recvmsg_op_base_ext(socket, buffers, ++ in_flags, out_flags, &reactive_socket_recvmsg_op_ext::do_complete), ++ handler_(BOOST_ASIO_MOVE_CAST(Handler)(handler)), ++ work_(handler_, io_ex) ++ { ++ } ++ ++ static void do_complete(void* owner, operation* base, ++ const boost::system::error_code& /*ec*/, ++ std::size_t /*bytes_transferred*/) ++ { ++ // Take ownership of the handler object. ++ reactive_socket_recvmsg_op_ext* o( ++ static_cast(base)); ++ ptr p = { boost::asio::detail::addressof(o->handler_), o, o }; ++ ++ BOOST_ASIO_HANDLER_COMPLETION((*o)); ++ ++ // Take ownership of the operation's outstanding work. ++ handler_work w( ++ BOOST_ASIO_MOVE_CAST2(handler_work)( ++ o->work_)); ++ ++ // Make a copy of the handler so that the memory can be deallocated before ++ // the upcall is made. Even if we're not about to make an upcall, a ++ // sub-object of the handler may be the true owner of the memory associated ++ // with the handler. Consequently, a local copy of the handler is required ++ // to ensure that any owning sub-object remains valid until after we have ++ // deallocated the memory here. ++ detail::binder3 ++ handler(o->handler_, o->ec_, o->bytes_transferred_, o->da_); ++ p.h = boost::asio::detail::addressof(handler.handler_); ++ p.reset(); ++ ++ // Make the upcall if required. ++ if (owner) ++ { ++ fenced_block b(fenced_block::half); ++ BOOST_ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, handler.arg2_, handler.arg3_)); ++ w.complete(handler, handler.handler_); ++ BOOST_ASIO_HANDLER_INVOCATION_END; ++ } ++ } ++ ++private: ++ Handler handler_; ++ handler_work work_; ++}; ++ ++} // namespace detail ++} // namespace asio ++} // namespace boost ++ ++#include ++ ++#endif // BOOST_ASIO_DETAIL_REACTIVE_SOCKET_RECVMSG_OP_EXT_HPP +diff --git a/implementation/helper/1.76/boost/asio/detail/reactive_socket_recvmsg_op_ext_local.hpp b/implementation/helper/1.76/boost/asio/detail/reactive_socket_recvmsg_op_ext_local.hpp +new file mode 100644 +index 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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++namespace boost { ++namespace asio { ++namespace detail { ++ ++template ++class reactive_socket_recvmsg_op_base_ext_local : public reactor_op_ext_local ++{ ++public: ++ reactive_socket_recvmsg_op_base_ext_local(const boost::system::error_code& success_ec, ++ socket_type socket, const MutableBufferSequence& buffers, socket_base::message_flags in_flags, ++ socket_base::message_flags& out_flags, func_type complete_func) ++ : reactor_op_ext_local(success_ec, &reactive_socket_recvmsg_op_base_ext_local::do_perform, complete_func), ++ socket_(socket), ++ buffers_(buffers), ++ in_flags_(in_flags), ++ out_flags_(out_flags) ++ { ++ } ++ ++ static status do_perform(reactor_op* base) ++ { ++ reactive_socket_recvmsg_op_base_ext_local* o( ++ static_cast(base)); ++ ++ buffer_sequence_adapter bufs(o->buffers_); ++ ++ status result = socket_ops::non_blocking_recvmsg(o->socket_, ++ bufs.buffers(), bufs.count(), ++ o->in_flags_, o->out_flags_, ++ o->ec_, o->bytes_transferred_) ? done : not_done; ++ ++ BOOST_ASIO_HANDLER_REACTOR_OPERATION((*o, "non_blocking_recvmsg", ++ o->ec_, o->bytes_transferred_)); ++ ++ return result; ++ } ++ ++private: ++ socket_type socket_; ++ MutableBufferSequence buffers_; ++ socket_base::message_flags in_flags_; ++ socket_base::message_flags& out_flags_; ++}; ++ ++template ++class reactive_socket_recvmsg_op_ext_local : ++ public reactive_socket_recvmsg_op_base_ext_local ++{ ++public: ++ BOOST_ASIO_DEFINE_HANDLER_PTR(reactive_socket_recvmsg_op_ext_local); ++ ++ reactive_socket_recvmsg_op_ext_local(const boost::system::error_code& success_ec, ++ socket_type socket, const MutableBufferSequence& buffers, socket_base::message_flags in_flags, ++ socket_base::message_flags& out_flags, Handler& handler, ++ const IoExecutor& io_ex) ++ : reactive_socket_recvmsg_op_base_ext_local(success_ec, ++ socket, buffers, in_flags, out_flags, ++ &reactive_socket_recvmsg_op_ext_local::do_complete), ++ handler_(BOOST_ASIO_MOVE_CAST(Handler)(handler)), ++ work_(handler_, io_ex) ++ { ++ } ++ ++ static void do_complete(void* owner, operation* base, ++ const boost::system::error_code& /*ec*/, ++ std::size_t /*bytes_transferred*/) ++ { ++ // Take ownership of the handler object. ++ reactive_socket_recvmsg_op_ext_local* o( ++ static_cast(base)); ++ ptr p = { boost::asio::detail::addressof(o->handler_), o, o }; ++ ++ BOOST_ASIO_HANDLER_COMPLETION((*o)); ++ ++ // Take ownership of the operation's outstanding work. ++ handler_work w( ++ BOOST_ASIO_MOVE_CAST2(handler_work)( ++ o->work_)); ++ ++ // Make a copy of the handler so that the memory can be deallocated before ++ // the upcall is made. Even if we're not about to make an upcall, a ++ // sub-object of the handler may be the true owner of the memory associated ++ // with the handler. Consequently, a local copy of the handler is required ++ // to ensure that any owning sub-object remains valid until after we have ++ // deallocated the memory here. ++ detail::binder4 ++ handler(o->handler_, o->ec_, o->bytes_transferred_, o->uid_, o->gid_); ++ p.h = boost::asio::detail::addressof(handler.handler_); ++ p.reset(); ++ ++ // Make the upcall if required. ++ if (owner) ++ { ++ fenced_block b(fenced_block::half); ++ BOOST_ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, handler.arg2_, handler.arg3_, handler.arg4_)); ++ w.complete(handler, handler.handler_); ++ BOOST_ASIO_HANDLER_INVOCATION_END; ++ } ++ } ++ ++private: ++ Handler handler_; ++ handler_work work_; ++}; ++ ++} // namespace detail ++} // namespace asio ++} // namespace boost ++ ++#include ++ ++#endif // BOOST_ASIO_DETAIL_REACTIVE_SOCKET_RECVMSG_OP_EXT_LOCAL_HPP +diff --git a/implementation/helper/1.76/boost/asio/detail/reactive_socket_service_base_ext.hpp b/implementation/helper/1.76/boost/asio/detail/reactive_socket_service_base_ext.hpp +new file mode 100644 +index 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 ++ ++#if !defined(BOOST_ASIO_HAS_IOCP) \ ++ && !defined(BOOST_ASIO_WINDOWS_RUNTIME) ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++namespace boost { ++namespace asio { ++namespace detail { ++ ++class reactive_socket_service_base_ext ++{ ++public: ++ // The native type of a socket. ++ typedef socket_type native_handle_type; ++ ++ // The implementation type of the socket. ++ struct base_implementation_type ++ { ++ // The native socket representation. ++ socket_type socket_; ++ ++ // The current state of the socket. ++ socket_ops::state_type state_; ++ ++ // Per-descriptor data used by the reactor. ++ reactor::per_descriptor_data reactor_data_; ++ }; ++ ++ // Constructor. ++ BOOST_ASIO_DECL reactive_socket_service_base_ext(execution_context& context); ++ ++ // Destroy all user-defined handler objects owned by the service. ++ BOOST_ASIO_DECL void base_shutdown(); ++ ++ // Construct a new socket implementation. ++ BOOST_ASIO_DECL void construct(base_implementation_type& impl); ++ ++ // Move-construct a new socket implementation. ++ BOOST_ASIO_DECL void base_move_construct(base_implementation_type& impl, ++ base_implementation_type& other_impl); ++ ++ // Move-assign from another socket implementation. ++ BOOST_ASIO_DECL void base_move_assign(base_implementation_type& impl, ++ reactive_socket_service_base_ext& other_service, ++ base_implementation_type& other_impl); ++ ++ // Destroy a socket implementation. ++ BOOST_ASIO_DECL void destroy(base_implementation_type& impl); ++ ++ // Determine whether the socket is open. ++ bool is_open(const base_implementation_type& impl) const ++ { ++ return impl.socket_ != invalid_socket; ++ } ++ ++ // Destroy a socket implementation. ++ BOOST_ASIO_DECL boost::system::error_code close( ++ base_implementation_type& impl, boost::system::error_code& ec); ++ ++ // Release ownership of the socket. ++ BOOST_ASIO_DECL socket_type release( ++ base_implementation_type& impl, boost::system::error_code& ec); ++ ++ // Get the native socket representation. ++ native_handle_type native_handle(base_implementation_type& impl) ++ { ++ return impl.socket_; ++ } ++ ++ // Cancel all operations associated with the socket. ++ BOOST_ASIO_DECL boost::system::error_code cancel( ++ base_implementation_type& impl, boost::system::error_code& ec); ++ ++ // Determine whether the socket is at the out-of-band data mark. ++ bool at_mark(const base_implementation_type& impl, ++ boost::system::error_code& ec) const ++ { ++ return socket_ops::sockatmark(impl.socket_, ec); ++ } ++ ++ // Determine the number of bytes available for reading. ++ std::size_t available(const base_implementation_type& impl, ++ boost::system::error_code& ec) const ++ { ++ return socket_ops::available(impl.socket_, ec); ++ } ++ ++ // Place the socket into the state where it will listen for new connections. ++ boost::system::error_code listen(base_implementation_type& impl, ++ int backlog, boost::system::error_code& ec) ++ { ++ socket_ops::listen(impl.socket_, backlog, ec); ++ return ec; ++ } ++ ++ // Perform an IO control command on the socket. ++ template ++ boost::system::error_code io_control(base_implementation_type& impl, ++ IO_Control_Command& command, boost::system::error_code& ec) ++ { ++ socket_ops::ioctl(impl.socket_, impl.state_, command.name(), ++ static_cast(command.data()), ec); ++ return ec; ++ } ++ ++ // Gets the non-blocking mode of the socket. ++ bool non_blocking(const base_implementation_type& impl) const ++ { ++ return (impl.state_ & socket_ops::user_set_non_blocking) != 0; ++ } ++ ++ // Sets the non-blocking mode of the socket. ++ boost::system::error_code non_blocking(base_implementation_type& impl, ++ bool mode, boost::system::error_code& ec) ++ { ++ socket_ops::set_user_non_blocking(impl.socket_, impl.state_, mode, ec); ++ return ec; ++ } ++ ++ // Gets the non-blocking mode of the native socket implementation. ++ bool native_non_blocking(const base_implementation_type& impl) const ++ { ++ return (impl.state_ & socket_ops::internal_non_blocking) != 0; ++ } ++ ++ // Sets the non-blocking mode of the native socket implementation. ++ boost::system::error_code native_non_blocking(base_implementation_type& impl, ++ bool mode, boost::system::error_code& ec) ++ { ++ socket_ops::set_internal_non_blocking(impl.socket_, impl.state_, mode, ec); ++ return ec; ++ } ++ ++ // Wait for the socket to become ready to read, ready to write, or to have ++ // pending error conditions. ++ boost::system::error_code wait(base_implementation_type& impl, ++ socket_base::wait_type w, boost::system::error_code& ec) ++ { ++ switch (w) ++ { ++ case socket_base::wait_read: ++ socket_ops::poll_read(impl.socket_, impl.state_, -1, ec); ++ break; ++ case socket_base::wait_write: ++ socket_ops::poll_write(impl.socket_, impl.state_, -1, ec); ++ break; ++ case socket_base::wait_error: ++ socket_ops::poll_error(impl.socket_, impl.state_, -1, ec); ++ break; ++ default: ++ ec = boost::asio::error::invalid_argument; ++ break; ++ } ++ ++ return ec; ++ } ++ ++ // Asynchronously wait for the socket to become ready to read, ready to ++ // write, or to have pending error conditions. ++ template ++ void async_wait(base_implementation_type& impl, ++ socket_base::wait_type w, Handler& handler, const IoExecutor& io_ex) ++ { ++ bool is_continuation = ++ boost_asio_handler_cont_helpers::is_continuation(handler); ++ ++ // Allocate and construct an operation to wrap the handler. ++ typedef reactive_wait_op op; ++ typename op::ptr p = { boost::asio::detail::addressof(handler), ++ op::ptr::allocate(handler), 0 }; ++ p.p = new (p.v) op(success_ec_, handler, io_ex); ++ ++ BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket", ++ &impl, impl.socket_, "async_wait")); ++ ++ int op_type; ++ switch (w) ++ { ++ case socket_base::wait_read: ++ op_type = reactor::read_op; ++ break; ++ case socket_base::wait_write: ++ op_type = reactor::write_op; ++ break; ++ case socket_base::wait_error: ++ op_type = reactor::except_op; ++ break; ++ default: ++ p.p->ec_ = boost::asio::error::invalid_argument; ++ reactor_.post_immediate_completion(p.p, is_continuation); ++ p.v = p.p = 0; ++ return; ++ } ++ ++ start_op(impl, op_type, p.p, is_continuation, false, false); ++ p.v = p.p = 0; ++ } ++ ++ // Send the given data to the peer. ++ template ++ size_t send(base_implementation_type& impl, ++ const ConstBufferSequence& buffers, ++ socket_base::message_flags flags, boost::system::error_code& ec) ++ { ++ buffer_sequence_adapter bufs(buffers); ++ ++ return socket_ops::sync_send(impl.socket_, impl.state_, ++ bufs.buffers(), bufs.count(), flags, bufs.all_empty(), ec); ++ } ++ ++ // Wait until data can be sent without blocking. ++ size_t send(base_implementation_type& impl, const null_buffers&, ++ socket_base::message_flags, boost::system::error_code& ec) ++ { ++ // Wait for socket to become ready. ++ socket_ops::poll_write(impl.socket_, impl.state_, -1, ec); ++ ++ return 0; ++ } ++ ++ // Start an asynchronous send. The data being sent must be valid for the ++ // lifetime of the asynchronous operation. ++ template ++ void async_send(base_implementation_type& impl, ++ const ConstBufferSequence& buffers, socket_base::message_flags flags, ++ Handler& handler, const IoExecutor& io_ex) ++ { ++ bool is_continuation = ++ boost_asio_handler_cont_helpers::is_continuation(handler); ++ ++ // Allocate and construct an operation to wrap the handler. ++ typedef reactive_socket_send_op< ++ ConstBufferSequence, Handler, IoExecutor> op; ++ typename op::ptr p = { boost::asio::detail::addressof(handler), ++ op::ptr::allocate(handler), 0 }; ++ p.p = new (p.v) op(success_ec_, impl.socket_, impl.state_, ++ buffers, flags, handler, io_ex); ++ ++ BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket", ++ &impl, impl.socket_, "async_send")); ++ ++ start_op(impl, reactor::write_op, p.p, is_continuation, true, ++ ((impl.state_ & socket_ops::stream_oriented) ++ && buffer_sequence_adapter::all_empty(buffers))); ++ p.v = p.p = 0; ++ } ++ ++ // Start an asynchronous wait until data can be sent without blocking. ++ template ++ void async_send(base_implementation_type& impl, const null_buffers&, ++ socket_base::message_flags, Handler& handler, const IoExecutor& io_ex) ++ { ++ bool is_continuation = ++ boost_asio_handler_cont_helpers::is_continuation(handler); ++ ++ // Allocate and construct an operation to wrap the handler. ++ typedef reactive_null_buffers_op op; ++ typename op::ptr p = { boost::asio::detail::addressof(handler), ++ op::ptr::allocate(handler), 0 }; ++ p.p = new (p.v) op(success_ec_, handler, io_ex); ++ ++ BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket", ++ &impl, impl.socket_, "async_send(null_buffers)")); ++ ++ start_op(impl, reactor::write_op, p.p, is_continuation, false, false); ++ p.v = p.p = 0; ++ } ++ ++ // Receive some data from the peer. Returns the number of bytes received. ++ template ++ size_t receive(base_implementation_type& impl, ++ const MutableBufferSequence& buffers, ++ socket_base::message_flags flags, boost::system::error_code& ec) ++ { ++ buffer_sequence_adapter bufs(buffers); ++ ++ return socket_ops::sync_recv(impl.socket_, impl.state_, ++ bufs.buffers(), bufs.count(), flags, bufs.all_empty(), ec); ++ } ++ ++ // Wait until data can be received without blocking. ++ size_t receive(base_implementation_type& impl, const null_buffers&, ++ socket_base::message_flags, boost::system::error_code& ec) ++ { ++ // Wait for socket to become ready. ++ socket_ops::poll_read(impl.socket_, impl.state_, -1, ec); ++ ++ return 0; ++ } ++ ++ // Start an asynchronous receive. The buffer for the data being received ++ // must be valid for the lifetime of the asynchronous operation. ++ template ++ void async_receive(base_implementation_type& impl, ++ const MutableBufferSequence& buffers, socket_base::message_flags flags, ++ Handler& handler, const IoExecutor& io_ex) ++ { ++ bool is_continuation = ++ boost_asio_handler_cont_helpers::is_continuation(handler); ++ ++ // Allocate and construct an operation to wrap the handler. ++ typedef reactive_socket_recv_op_ext< ++ MutableBufferSequence, Handler, IoExecutor> op; ++ typename op::ptr p = { boost::asio::detail::addressof(handler), ++ op::ptr::allocate(handler), 0 }; ++ p.p = new (p.v) op(success_ec_, impl.socket_, impl.state_, ++ buffers, flags, handler, io_ex); ++ ++ BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket", ++ &impl, impl.socket_, "async_receive")); ++ ++ start_op(impl, ++ (flags & socket_base::message_out_of_band) ++ ? reactor::except_op : reactor::read_op, ++ p.p, is_continuation, ++ (flags & socket_base::message_out_of_band) == 0, ++ ((impl.state_ & socket_ops::stream_oriented) ++ && buffer_sequence_adapter::all_empty(buffers))); ++ p.v = p.p = 0; ++ } ++ ++ // Wait until data can be received without blocking. ++ template ++ void async_receive(base_implementation_type& impl, ++ const null_buffers&, socket_base::message_flags flags, ++ Handler& handler, const IoExecutor& io_ex) ++ { ++ bool is_continuation = ++ boost_asio_handler_cont_helpers::is_continuation(handler); ++ ++ // Allocate and construct an operation to wrap the handler. ++ typedef reactive_null_buffers_op op; ++ typename op::ptr p = { boost::asio::detail::addressof(handler), ++ op::ptr::allocate(handler), 0 }; ++ p.p = new (p.v) op(success_ec_, handler, io_ex); ++ ++ BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket", ++ &impl, impl.socket_, "async_receive(null_buffers)")); ++ ++ start_op(impl, ++ (flags & socket_base::message_out_of_band) ++ ? reactor::except_op : reactor::read_op, ++ p.p, is_continuation, false, false); ++ p.v = p.p = 0; ++ } ++ ++ // Receive some data with associated flags. Returns the number of bytes ++ // received. ++ template ++ size_t receive_with_flags(base_implementation_type& impl, ++ const MutableBufferSequence& buffers, ++ socket_base::message_flags in_flags, ++ socket_base::message_flags& out_flags, boost::system::error_code& ec) ++ { ++ buffer_sequence_adapter bufs(buffers); ++ ++ return socket_ops::sync_recvmsg(impl.socket_, impl.state_, ++ bufs.buffers(), bufs.count(), in_flags, out_flags, ec); ++ } ++ ++ // Wait until data can be received without blocking. ++ size_t receive_with_flags(base_implementation_type& impl, ++ const null_buffers&, socket_base::message_flags, ++ socket_base::message_flags& out_flags, boost::system::error_code& ec) ++ { ++ // Wait for socket to become ready. ++ socket_ops::poll_read(impl.socket_, impl.state_, -1, ec); ++ ++ // Clear out_flags, since we cannot give it any other sensible value when ++ // performing a null_buffers operation. ++ out_flags = 0; ++ ++ return 0; ++ } ++ ++ // Start an asynchronous receive. The buffer for the data being received ++ // must be valid for the lifetime of the asynchronous operation. ++ template ++ void async_receive_with_flags(base_implementation_type& impl, ++ const MutableBufferSequence& buffers, socket_base::message_flags in_flags, ++ socket_base::message_flags& out_flags, Handler& handler, ++ const IoExecutor& io_ex) ++ { ++ bool is_continuation = ++ boost_asio_handler_cont_helpers::is_continuation(handler); ++ ++ // Allocate and construct an operation to wrap the handler. ++ typedef reactive_socket_recvmsg_op_ext< ++ MutableBufferSequence, Handler, IoExecutor> op; ++ typename op::ptr p = { boost::asio::detail::addressof(handler), ++ op::ptr::allocate(handler), 0 }; ++ p.p = new (p.v) op(success_ec_, impl.socket_, buffers, ++ in_flags, out_flags, handler, io_ex); ++ ++ BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket", ++ &impl, impl.socket_, "async_receive_with_flags")); ++ ++ start_op(impl, ++ (in_flags & socket_base::message_out_of_band) ++ ? reactor::except_op : reactor::read_op, ++ p.p, is_continuation, ++ (in_flags & socket_base::message_out_of_band) == 0, false); ++ p.v = p.p = 0; ++ } ++ ++ // Wait until data can be received without blocking. ++ template ++ void async_receive_with_flags(base_implementation_type& impl, ++ const null_buffers&, socket_base::message_flags in_flags, ++ socket_base::message_flags& out_flags, Handler& handler, ++ const IoExecutor& io_ex) ++ { ++ bool is_continuation = ++ boost_asio_handler_cont_helpers::is_continuation(handler); ++ ++ // Allocate and construct an operation to wrap the handler. ++ typedef reactive_null_buffers_op op; ++ typename op::ptr p = { boost::asio::detail::addressof(handler), ++ op::ptr::allocate(handler), 0 }; ++ p.p = new (p.v) op(success_ec_, handler, io_ex); ++ ++ BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket", ++ &impl, impl.socket_, "async_receive_with_flags(null_buffers)")); ++ ++ // Clear out_flags, since we cannot give it any other sensible value when ++ // performing a null_buffers operation. ++ out_flags = 0; ++ ++ start_op(impl, ++ (in_flags & socket_base::message_out_of_band) ++ ? reactor::except_op : reactor::read_op, ++ p.p, is_continuation, false, false); ++ p.v = p.p = 0; ++ } ++ ++protected: ++ // Open a new socket implementation. ++ BOOST_ASIO_DECL boost::system::error_code do_open( ++ base_implementation_type& impl, int af, ++ int type, int protocol, boost::system::error_code& ec); ++ ++ // Assign a native socket to a socket implementation. ++ BOOST_ASIO_DECL boost::system::error_code do_assign( ++ base_implementation_type& impl, int type, ++ const native_handle_type& native_socket, boost::system::error_code& ec); ++ ++ // Start the asynchronous read or write operation. ++ BOOST_ASIO_DECL void start_op(base_implementation_type& impl, int op_type, ++ reactor_op* op, bool is_continuation, bool is_non_blocking, bool noop); ++ ++ // Start the asynchronous accept operation. ++ BOOST_ASIO_DECL void start_accept_op(base_implementation_type& impl, ++ reactor_op* op, bool is_continuation, bool peer_is_open); ++ ++ // Start the asynchronous connect operation. ++ BOOST_ASIO_DECL void start_connect_op(base_implementation_type& impl, ++ reactor_op* op, bool is_continuation, ++ const socket_addr_type* addr, size_t addrlen); ++ ++ // The selector that performs event demultiplexing for the service. ++ reactor& reactor_; ++ ++ // Cached success value to avoid accessing category singleton. ++ const boost::system::error_code success_ec_; ++}; ++ ++} // namespace detail ++} // namespace asio ++} // namespace boost ++ ++#include ++ ++#if defined(BOOST_ASIO_HEADER_ONLY) ++# include ++#endif // defined(BOOST_ASIO_HEADER_ONLY) ++ ++#endif // !defined(BOOST_ASIO_HAS_IOCP) ++ // && !defined(BOOST_ASIO_WINDOWS_RUNTIME) ++ ++#endif // BOOST_ASIO_DETAIL_REACTIVE_SOCKET_SERVICE_BASE_EXT_HPP +diff --git a/implementation/helper/1.76/boost/asio/detail/reactive_socket_service_base_ext_local.hpp b/implementation/helper/1.76/boost/asio/detail/reactive_socket_service_base_ext_local.hpp +new file mode 100644 +index 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 ++ ++#if !defined(BOOST_ASIO_HAS_IOCP) \ ++ && !defined(BOOST_ASIO_WINDOWS_RUNTIME) ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++namespace boost { ++namespace asio { ++namespace detail { ++ ++class reactive_socket_service_base_ext_local ++{ ++public: ++ // The native type of a socket. ++ typedef socket_type native_handle_type; ++ ++ // The implementation type of the socket. ++ struct base_implementation_type ++ { ++ // The native socket representation. ++ socket_type socket_; ++ ++ // The current state of the socket. ++ socket_ops::state_type state_; ++ ++ // Per-descriptor data used by the reactor. ++ reactor::per_descriptor_data reactor_data_; ++ }; ++ ++ // Constructor. ++ BOOST_ASIO_DECL reactive_socket_service_base_ext_local(execution_context& context); ++ ++ // Destroy all user-defined handler objects owned by the service. ++ BOOST_ASIO_DECL void base_shutdown(); ++ ++ // Construct a new socket implementation. ++ BOOST_ASIO_DECL void construct(base_implementation_type& impl); ++ ++ // Move-construct a new socket implementation. ++ BOOST_ASIO_DECL void base_move_construct(base_implementation_type& impl, ++ base_implementation_type& other_impl); ++ ++ // Move-assign from another socket implementation. ++ BOOST_ASIO_DECL void base_move_assign(base_implementation_type& impl, ++ reactive_socket_service_base_ext_local& other_service, ++ base_implementation_type& other_impl); ++ ++ // Destroy a socket implementation. ++ BOOST_ASIO_DECL void destroy(base_implementation_type& impl); ++ ++ // Determine whether the socket is open. ++ bool is_open(const base_implementation_type& impl) const ++ { ++ return impl.socket_ != invalid_socket; ++ } ++ ++ // Destroy a socket implementation. ++ BOOST_ASIO_DECL boost::system::error_code close( ++ base_implementation_type& impl, boost::system::error_code& ec); ++ ++ // Release ownership of the socket. ++ BOOST_ASIO_DECL socket_type release( ++ base_implementation_type& impl, boost::system::error_code& ec); ++ ++ // Get the native socket representation. ++ native_handle_type native_handle(base_implementation_type& impl) ++ { ++ return impl.socket_; ++ } ++ ++ // Cancel all operations associated with the socket. ++ BOOST_ASIO_DECL boost::system::error_code cancel( ++ base_implementation_type& impl, boost::system::error_code& ec); ++ ++ // Determine whether the socket is at the out-of-band data mark. ++ bool at_mark(const base_implementation_type& impl, ++ boost::system::error_code& ec) const ++ { ++ return socket_ops::sockatmark(impl.socket_, ec); ++ } ++ ++ // Determine the number of bytes available for reading. ++ std::size_t available(const base_implementation_type& impl, ++ boost::system::error_code& ec) const ++ { ++ return socket_ops::available(impl.socket_, ec); ++ } ++ ++ // Place the socket into the state where it will listen for new connections. ++ boost::system::error_code listen(base_implementation_type& impl, ++ int backlog, boost::system::error_code& ec) ++ { ++ socket_ops::listen(impl.socket_, backlog, ec); ++ return ec; ++ } ++ ++ // Perform an IO control command on the socket. ++ template ++ boost::system::error_code io_control(base_implementation_type& impl, ++ IO_Control_Command& command, boost::system::error_code& ec) ++ { ++ socket_ops::ioctl(impl.socket_, impl.state_, command.name(), ++ static_cast(command.data()), ec); ++ return ec; ++ } ++ ++ // Gets the non-blocking mode of the socket. ++ bool non_blocking(const base_implementation_type& impl) const ++ { ++ return (impl.state_ & socket_ops::user_set_non_blocking) != 0; ++ } ++ ++ // Sets the non-blocking mode of the socket. ++ boost::system::error_code non_blocking(base_implementation_type& impl, ++ bool mode, boost::system::error_code& ec) ++ { ++ socket_ops::set_user_non_blocking(impl.socket_, impl.state_, mode, ec); ++ return ec; ++ } ++ ++ // Gets the non-blocking mode of the native socket implementation. ++ bool native_non_blocking(const base_implementation_type& impl) const ++ { ++ return (impl.state_ & socket_ops::internal_non_blocking) != 0; ++ } ++ ++ // Sets the non-blocking mode of the native socket implementation. ++ boost::system::error_code native_non_blocking(base_implementation_type& impl, ++ bool mode, boost::system::error_code& ec) ++ { ++ socket_ops::set_internal_non_blocking(impl.socket_, impl.state_, mode, ec); ++ return ec; ++ } ++ ++ // Wait for the socket to become ready to read, ready to write, or to have ++ // pending error conditions. ++ boost::system::error_code wait(base_implementation_type& impl, ++ socket_base::wait_type w, boost::system::error_code& ec) ++ { ++ switch (w) ++ { ++ case socket_base::wait_read: ++ socket_ops::poll_read(impl.socket_, impl.state_, -1, ec); ++ break; ++ case socket_base::wait_write: ++ socket_ops::poll_write(impl.socket_, impl.state_, -1, ec); ++ break; ++ case socket_base::wait_error: ++ socket_ops::poll_error(impl.socket_, impl.state_, -1, ec); ++ break; ++ default: ++ ec = boost::asio::error::invalid_argument; ++ break; ++ } ++ ++ return ec; ++ } ++ ++ // Asynchronously wait for the socket to become ready to read, ready to ++ // write, or to have pending error conditions. ++ template ++ void async_wait(base_implementation_type& impl, ++ socket_base::wait_type w, Handler& handler, const IoExecutor& io_ex) ++ { ++ bool is_continuation = ++ boost_asio_handler_cont_helpers::is_continuation(handler); ++ ++ // Allocate and construct an operation to wrap the handler. ++ typedef reactive_wait_op op; ++ typename op::ptr p = { boost::asio::detail::addressof(handler), ++ op::ptr::allocate(handler), 0 }; ++ p.p = new (p.v) op(success_ec_, handler, io_ex); ++ ++ BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket", ++ &impl, impl.socket_, "async_wait")); ++ ++ int op_type; ++ switch (w) ++ { ++ case socket_base::wait_read: ++ op_type = reactor::read_op; ++ break; ++ case socket_base::wait_write: ++ op_type = reactor::write_op; ++ break; ++ case socket_base::wait_error: ++ op_type = reactor::except_op; ++ break; ++ default: ++ p.p->ec_ = boost::asio::error::invalid_argument; ++ reactor_.post_immediate_completion(p.p, is_continuation); ++ p.v = p.p = 0; ++ return; ++ } ++ ++ start_op(impl, op_type, p.p, is_continuation, false, false); ++ p.v = p.p = 0; ++ } ++ ++ // Send the given data to the peer. ++ template ++ size_t send(base_implementation_type& impl, ++ const ConstBufferSequence& buffers, ++ socket_base::message_flags flags, boost::system::error_code& ec) ++ { ++ buffer_sequence_adapter bufs(buffers); ++ ++ return socket_ops::sync_send(impl.socket_, impl.state_, ++ bufs.buffers(), bufs.count(), flags, bufs.all_empty(), ec); ++ } ++ ++ // Wait until data can be sent without blocking. ++ size_t send(base_implementation_type& impl, const null_buffers&, ++ socket_base::message_flags, boost::system::error_code& ec) ++ { ++ // Wait for socket to become ready. ++ socket_ops::poll_write(impl.socket_, impl.state_, -1, ec); ++ ++ return 0; ++ } ++ ++ // Start an asynchronous send. The data being sent must be valid for the ++ // lifetime of the asynchronous operation. ++ template ++ void async_send(base_implementation_type& impl, ++ const ConstBufferSequence& buffers, socket_base::message_flags flags, ++ Handler& handler, const IoExecutor& io_ex) ++ { ++ bool is_continuation = ++ boost_asio_handler_cont_helpers::is_continuation(handler); ++ ++ // Allocate and construct an operation to wrap the handler. ++ typedef reactive_socket_send_op< ++ ConstBufferSequence, Handler, IoExecutor> op; ++ typename op::ptr p = { boost::asio::detail::addressof(handler), ++ op::ptr::allocate(handler), 0 }; ++ p.p = new (p.v) op(success_ec_, impl.socket_, impl.state_, ++ buffers, flags, handler, io_ex); ++ ++ BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket", ++ &impl, impl.socket_, "async_send")); ++ ++ start_op(impl, reactor::write_op, p.p, is_continuation, true, ++ ((impl.state_ & socket_ops::stream_oriented) ++ && buffer_sequence_adapter::all_empty(buffers))); ++ p.v = p.p = 0; ++ } ++ ++ // Start an asynchronous wait until data can be sent without blocking. ++ template ++ void async_send(base_implementation_type& impl, const null_buffers&, ++ socket_base::message_flags, Handler& handler, const IoExecutor& io_ex) ++ { ++ bool is_continuation = ++ boost_asio_handler_cont_helpers::is_continuation(handler); ++ ++ // Allocate and construct an operation to wrap the handler. ++ typedef reactive_null_buffers_op op; ++ typename op::ptr p = { boost::asio::detail::addressof(handler), ++ op::ptr::allocate(handler), 0 }; ++ p.p = new (p.v) op(success_ec_, handler, io_ex); ++ ++ BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket", ++ &impl, impl.socket_, "async_send(null_buffers)")); ++ ++ start_op(impl, reactor::write_op, p.p, is_continuation, false, false); ++ p.v = p.p = 0; ++ } ++ ++ // Receive some data from the peer. Returns the number of bytes received. ++ template ++ size_t receive(base_implementation_type& impl, ++ const MutableBufferSequence& buffers, ++ socket_base::message_flags flags, boost::system::error_code& ec) ++ { ++ buffer_sequence_adapter bufs(buffers); ++ ++ return socket_ops::sync_recv(impl.socket_, impl.state_, ++ bufs.buffers(), bufs.count(), flags, bufs.all_empty(), ec); ++ } ++ ++ // Wait until data can be received without blocking. ++ size_t receive(base_implementation_type& impl, const null_buffers&, ++ socket_base::message_flags, boost::system::error_code& ec) ++ { ++ // Wait for socket to become ready. ++ socket_ops::poll_read(impl.socket_, impl.state_, -1, ec); ++ ++ return 0; ++ } ++ ++ // Start an asynchronous receive. The buffer for the data being received ++ // must be valid for the lifetime of the asynchronous operation. ++ template ++ void async_receive(base_implementation_type& impl, ++ const MutableBufferSequence& buffers, socket_base::message_flags flags, ++ Handler& handler, const IoExecutor& io_ex) ++ { ++ bool is_continuation = ++ boost_asio_handler_cont_helpers::is_continuation(handler); ++ ++ // Allocate and construct an operation to wrap the handler. ++ typedef reactive_socket_recv_op_ext_local< ++ MutableBufferSequence, Handler, IoExecutor> op; ++ typename op::ptr p = { boost::asio::detail::addressof(handler), ++ op::ptr::allocate(handler), 0 }; ++ p.p = new (p.v) op(success_ec_, impl.socket_, impl.state_, ++ buffers, flags, handler, io_ex); ++ ++ BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket", ++ &impl, impl.socket_, "async_receive")); ++ ++ start_op(impl, ++ (flags & socket_base::message_out_of_band) ++ ? reactor::except_op : reactor::read_op, ++ p.p, is_continuation, ++ (flags & socket_base::message_out_of_band) == 0, ++ ((impl.state_ & socket_ops::stream_oriented) ++ && buffer_sequence_adapter::all_empty(buffers))); ++ p.v = p.p = 0; ++ } ++ ++ // Wait until data can be received without blocking. ++ template ++ void async_receive(base_implementation_type& impl, ++ const null_buffers&, socket_base::message_flags flags, ++ Handler& handler, const IoExecutor& io_ex) ++ { ++ bool is_continuation = ++ boost_asio_handler_cont_helpers::is_continuation(handler); ++ ++ // Allocate and construct an operation to wrap the handler. ++ typedef reactive_null_buffers_op op; ++ typename op::ptr p = { boost::asio::detail::addressof(handler), ++ op::ptr::allocate(handler), 0 }; ++ p.p = new (p.v) op(success_ec_, handler, io_ex); ++ ++ BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket", ++ &impl, impl.socket_, "async_receive(null_buffers)")); ++ ++ start_op(impl, ++ (flags & socket_base::message_out_of_band) ++ ? reactor::except_op : reactor::read_op, ++ p.p, is_continuation, false, false); ++ p.v = p.p = 0; ++ } ++ ++ // Receive some data with associated flags. Returns the number of bytes ++ // received. ++ template ++ size_t receive_with_flags(base_implementation_type& impl, ++ const MutableBufferSequence& buffers, ++ socket_base::message_flags in_flags, ++ socket_base::message_flags& out_flags, boost::system::error_code& ec) ++ { ++ buffer_sequence_adapter bufs(buffers); ++ ++ return socket_ops::sync_recvmsg(impl.socket_, impl.state_, ++ bufs.buffers(), bufs.count(), in_flags, out_flags, ec); ++ } ++ ++ // Wait until data can be received without blocking. ++ size_t receive_with_flags(base_implementation_type& impl, ++ const null_buffers&, socket_base::message_flags, ++ socket_base::message_flags& out_flags, boost::system::error_code& ec) ++ { ++ // Wait for socket to become ready. ++ socket_ops::poll_read(impl.socket_, impl.state_, -1, ec); ++ ++ // Clear out_flags, since we cannot give it any other sensible value when ++ // performing a null_buffers operation. ++ out_flags = 0; ++ ++ return 0; ++ } ++ ++ // Start an asynchronous receive. The buffer for the data being received ++ // must be valid for the lifetime of the asynchronous operation. ++ template ++ void async_receive_with_flags(base_implementation_type& impl, ++ const MutableBufferSequence& buffers, socket_base::message_flags in_flags, ++ socket_base::message_flags& out_flags, Handler& handler, ++ const IoExecutor& io_ex) ++ { ++ bool is_continuation = ++ boost_asio_handler_cont_helpers::is_continuation(handler); ++ ++ // Allocate and construct an operation to wrap the handler. ++ typedef reactive_socket_recvmsg_op_ext_local< ++ MutableBufferSequence, Handler, IoExecutor> op; ++ typename op::ptr p = { boost::asio::detail::addressof(handler), ++ op::ptr::allocate(handler), 0 }; ++ p.p = new (p.v) op(success_ec_, impl.socket_, buffers, ++ in_flags, out_flags, handler, io_ex); ++ ++ BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket", ++ &impl, impl.socket_, "async_receive_with_flags")); ++ ++ start_op(impl, ++ (in_flags & socket_base::message_out_of_band) ++ ? reactor::except_op : reactor::read_op, ++ p.p, is_continuation, ++ (in_flags & socket_base::message_out_of_band) == 0, false); ++ p.v = p.p = 0; ++ } ++ ++ // Wait until data can be received without blocking. ++ template ++ void async_receive_with_flags(base_implementation_type& impl, ++ const null_buffers&, socket_base::message_flags in_flags, ++ socket_base::message_flags& out_flags, Handler& handler, ++ const IoExecutor& io_ex) ++ { ++ bool is_continuation = ++ boost_asio_handler_cont_helpers::is_continuation(handler); ++ ++ // Allocate and construct an operation to wrap the handler. ++ typedef reactive_null_buffers_op op; ++ typename op::ptr p = { boost::asio::detail::addressof(handler), ++ op::ptr::allocate(handler), 0 }; ++ p.p = new (p.v) op(success_ec_, handler, io_ex); ++ ++ BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket", ++ &impl, impl.socket_, "async_receive_with_flags(null_buffers)")); ++ ++ // Clear out_flags, since we cannot give it any other sensible value when ++ // performing a null_buffers operation. ++ out_flags = 0; ++ ++ start_op(impl, ++ (in_flags & socket_base::message_out_of_band) ++ ? reactor::except_op : reactor::read_op, ++ p.p, is_continuation, false, false); ++ p.v = p.p = 0; ++ } ++ ++protected: ++ // Open a new socket implementation. ++ BOOST_ASIO_DECL boost::system::error_code do_open( ++ base_implementation_type& impl, int af, ++ int type, int protocol, boost::system::error_code& ec); ++ ++ // Assign a native socket to a socket implementation. ++ BOOST_ASIO_DECL boost::system::error_code do_assign( ++ base_implementation_type& impl, int type, ++ const native_handle_type& native_socket, boost::system::error_code& ec); ++ ++ // Start the asynchronous read or write operation. ++ BOOST_ASIO_DECL void start_op(base_implementation_type& impl, int op_type, ++ reactor_op* op, bool is_continuation, bool is_non_blocking, bool noop); ++ ++ // Start the asynchronous accept operation. ++ BOOST_ASIO_DECL void start_accept_op(base_implementation_type& impl, ++ reactor_op* op, bool is_continuation, bool peer_is_open); ++ ++ // Start the asynchronous connect operation. ++ BOOST_ASIO_DECL void start_connect_op(base_implementation_type& impl, ++ reactor_op* op, bool is_continuation, ++ const socket_addr_type* addr, size_t addrlen); ++ ++ // The selector that performs event demultiplexing for the service. ++ reactor& reactor_; ++ ++ // Cached success value to avoid accessing category singleton. ++ const boost::system::error_code success_ec_; ++}; ++ ++} // namespace detail ++} // namespace asio ++} // namespace boost ++ ++#include ++ ++#if defined(BOOST_ASIO_HEADER_ONLY) ++# include ++#endif // defined(BOOST_ASIO_HEADER_ONLY) ++ ++#endif // !defined(BOOST_ASIO_HAS_IOCP) ++ // && !defined(BOOST_ASIO_WINDOWS_RUNTIME) ++ ++#endif // BOOST_ASIO_DETAIL_REACTIVE_SOCKET_SERVICE_BASE_EXT_LOCAL_HPP +diff --git a/implementation/helper/1.76/boost/asio/detail/reactive_socket_service_ext.hpp b/implementation/helper/1.76/boost/asio/detail/reactive_socket_service_ext.hpp +new file mode 100644 +index 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 ++ ++#if !defined(BOOST_ASIO_HAS_IOCP) ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++namespace boost { ++namespace asio { ++namespace detail { ++ ++template ++class reactive_socket_service_ext : ++ public execution_context_service_base >, ++ public reactive_socket_service_base_ext ++{ ++public: ++ // The protocol type. ++ typedef Protocol protocol_type; ++ ++ // The endpoint type. ++ typedef typename Protocol::endpoint endpoint_type; ++ ++ // The native type of a socket. ++ typedef socket_type native_handle_type; ++ ++ // The implementation type of the socket. ++ struct implementation_type : ++ reactive_socket_service_base_ext::base_implementation_type ++ { ++ // Default constructor. ++ implementation_type() ++ : protocol_(endpoint_type().protocol()) ++ { ++ } ++ ++ // The protocol associated with the socket. ++ protocol_type protocol_; ++ }; ++ ++ // Constructor. ++ reactive_socket_service_ext(execution_context& context) ++ : execution_context_service_base< ++ reactive_socket_service_ext >(context), ++ reactive_socket_service_base_ext(context) ++ { ++ } ++ ++ // Destroy all user-defined handler objects owned by the service. ++ void shutdown() ++ { ++ this->base_shutdown(); ++ } ++ ++ // Move-construct a new socket implementation. ++ void move_construct(implementation_type& impl, ++ implementation_type& other_impl) ++ { ++ this->base_move_construct(impl, other_impl); ++ ++ impl.protocol_ = other_impl.protocol_; ++ other_impl.protocol_ = endpoint_type().protocol(); ++ } ++ ++ // Move-assign from another socket implementation. ++ void move_assign(implementation_type& impl, ++ reactive_socket_service_base_ext& other_service, ++ implementation_type& other_impl) ++ { ++ this->base_move_assign(impl, other_service, other_impl); ++ ++ impl.protocol_ = other_impl.protocol_; ++ other_impl.protocol_ = endpoint_type().protocol(); ++ } ++ ++ // Move-construct a new socket implementation from another protocol type. ++ template ++ void converting_move_construct(implementation_type& impl, ++ reactive_socket_service_ext&, ++ typename reactive_socket_service_ext< ++ Protocol1>::implementation_type& other_impl) ++ { ++ this->base_move_construct(impl, other_impl); ++ ++ impl.protocol_ = protocol_type(other_impl.protocol_); ++ other_impl.protocol_ = typename Protocol1::endpoint().protocol(); ++ } ++ ++ // Open a new socket implementation. ++ boost::system::error_code open(implementation_type& impl, ++ const protocol_type& protocol, boost::system::error_code& ec) ++ { ++ if (!do_open(impl, protocol.family(), ++ protocol.type(), protocol.protocol(), ec)) ++ impl.protocol_ = protocol; ++ return ec; ++ } ++ ++ // Assign a native socket to a socket implementation. ++ boost::system::error_code assign(implementation_type& impl, ++ const protocol_type& protocol, const native_handle_type& native_socket, ++ boost::system::error_code& ec) ++ { ++ if (!do_assign(impl, protocol.type(), native_socket, ec)) ++ impl.protocol_ = protocol; ++ return ec; ++ } ++ ++ // Get the native socket representation. ++ native_handle_type native_handle(implementation_type& impl) ++ { ++ return impl.socket_; ++ } ++ ++ // Bind the socket to the specified local endpoint. ++ boost::system::error_code bind(implementation_type& impl, ++ const endpoint_type& endpoint, boost::system::error_code& ec) ++ { ++ socket_ops::bind(impl.socket_, endpoint.data(), endpoint.size(), ec); ++ return ec; ++ } ++ ++ // Set a socket option. ++ template ++ boost::system::error_code set_option(implementation_type& impl, ++ const Option& option, boost::system::error_code& ec) ++ { ++ socket_ops::setsockopt(impl.socket_, impl.state_, ++ option.level(impl.protocol_), option.name(impl.protocol_), ++ option.data(impl.protocol_), option.size(impl.protocol_), ec); ++ return ec; ++ } ++ ++ // Set a socket option. ++ template ++ boost::system::error_code get_option(const implementation_type& impl, ++ Option& option, boost::system::error_code& ec) const ++ { ++ std::size_t size = option.size(impl.protocol_); ++ socket_ops::getsockopt(impl.socket_, impl.state_, ++ option.level(impl.protocol_), option.name(impl.protocol_), ++ option.data(impl.protocol_), &size, ec); ++ if (!ec) ++ option.resize(impl.protocol_, size); ++ return ec; ++ } ++ ++ // Get the local endpoint. ++ endpoint_type local_endpoint(const implementation_type& impl, ++ boost::system::error_code& ec) const ++ { ++ endpoint_type endpoint; ++ std::size_t addr_len = endpoint.capacity(); ++ if (socket_ops::getsockname(impl.socket_, endpoint.data(), &addr_len, ec)) ++ return endpoint_type(); ++ endpoint.resize(addr_len); ++ return endpoint; ++ } ++ ++ // Get the remote endpoint. ++ endpoint_type remote_endpoint(const implementation_type& impl, ++ boost::system::error_code& ec) const ++ { ++ endpoint_type endpoint; ++ std::size_t addr_len = endpoint.capacity(); ++ if (socket_ops::getpeername(impl.socket_, ++ endpoint.data(), &addr_len, false, ec)) ++ return endpoint_type(); ++ endpoint.resize(addr_len); ++ return endpoint; ++ } ++ ++ // Disable sends or receives on the socket. ++ boost::system::error_code shutdown(base_implementation_type& impl, ++ socket_base::shutdown_type what, boost::system::error_code& ec) ++ { ++ socket_ops::shutdown(impl.socket_, what, ec); ++ return ec; ++ } ++ ++ // Send a datagram to the specified endpoint. Returns the number of bytes ++ // sent. ++ template ++ size_t send_to(implementation_type& impl, const ConstBufferSequence& buffers, ++ const endpoint_type& destination, socket_base::message_flags flags, ++ boost::system::error_code& ec) ++ { ++ buffer_sequence_adapter bufs(buffers); ++ ++ return socket_ops::sync_sendto(impl.socket_, impl.state_, ++ bufs.buffers(), bufs.count(), flags, ++ destination.data(), destination.size(), ec); ++ } ++ ++ // Wait until data can be sent without blocking. ++ size_t send_to(implementation_type& impl, const null_buffers&, ++ const endpoint_type&, socket_base::message_flags, ++ boost::system::error_code& ec) ++ { ++ // Wait for socket to become ready. ++ socket_ops::poll_write(impl.socket_, impl.state_, -1, ec); ++ ++ return 0; ++ } ++ ++ // Start an asynchronous send. The data being sent must be valid for the ++ // lifetime of the asynchronous operation. ++ template ++ void async_send_to(implementation_type& impl, ++ const ConstBufferSequence& buffers, ++ const endpoint_type& destination, socket_base::message_flags flags, ++ Handler& handler, const IoExecutor& io_ex) ++ { ++ bool is_continuation = ++ boost_asio_handler_cont_helpers::is_continuation(handler); ++ ++ // Allocate and construct an operation to wrap the handler. ++ typedef reactive_socket_sendto_op op; ++ typename op::ptr p = { boost::asio::detail::addressof(handler), ++ op::ptr::allocate(handler), 0 }; ++ p.p = new (p.v) op(success_ec_, impl.socket_, buffers, ++ destination, flags, handler, io_ex); ++ ++ BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket", ++ &impl, impl.socket_, "async_send_to")); ++ ++ start_op(impl, reactor::write_op, p.p, is_continuation, true, false); ++ p.v = p.p = 0; ++ } ++ ++ // Start an asynchronous wait until data can be sent without blocking. ++ template ++ void async_send_to(implementation_type& impl, const null_buffers&, ++ const endpoint_type&, socket_base::message_flags, ++ Handler& handler, const IoExecutor& io_ex) ++ { ++ bool is_continuation = ++ boost_asio_handler_cont_helpers::is_continuation(handler); ++ ++ // Allocate and construct an operation to wrap the handler. ++ typedef reactive_null_buffers_op op; ++ typename op::ptr p = { boost::asio::detail::addressof(handler), ++ op::ptr::allocate(handler), 0 }; ++ p.p = new (p.v) op(success_ec_, handler, io_ex); ++ ++ BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket", ++ &impl, impl.socket_, "async_send_to(null_buffers)")); ++ ++ start_op(impl, reactor::write_op, p.p, is_continuation, false, false); ++ p.v = p.p = 0; ++ } ++ ++ // Receive a datagram with the endpoint of the sender. Returns the number of ++ // bytes received. ++ template ++ size_t receive_from(implementation_type& impl, ++ const MutableBufferSequence& buffers, ++ endpoint_type& sender_endpoint, socket_base::message_flags flags, ++ boost::system::error_code& ec) ++ { ++ buffer_sequence_adapter bufs(buffers); ++ ++ std::size_t addr_len = sender_endpoint.capacity(); ++ std::size_t bytes_recvd = socket_ops::sync_recvfrom( ++ impl.socket_, impl.state_, bufs.buffers(), bufs.count(), ++ flags, sender_endpoint.data(), &addr_len, ec); ++ ++ if (!ec) ++ sender_endpoint.resize(addr_len); ++ ++ return bytes_recvd; ++ } ++ ++ // Wait until data can be received without blocking. ++ size_t receive_from(implementation_type& impl, const null_buffers&, ++ endpoint_type& sender_endpoint, socket_base::message_flags, ++ boost::system::error_code& ec) ++ { ++ // Wait for socket to become ready. ++ socket_ops::poll_read(impl.socket_, impl.state_, -1, ec); ++ ++ // Reset endpoint since it can be given no sensible value at this time. ++ sender_endpoint = endpoint_type(); ++ ++ return 0; ++ } ++ ++ // Start an asynchronous receive. The buffer for the data being received and ++ // the sender_endpoint object must both be valid for the lifetime of the ++ // asynchronous operation. ++ template ++ void async_receive_from(implementation_type& impl, ++ const MutableBufferSequence& buffers, endpoint_type& sender_endpoint, ++ socket_base::message_flags flags, Handler& handler, ++ const IoExecutor& io_ex) ++ { ++ bool is_continuation = ++ boost_asio_handler_cont_helpers::is_continuation(handler); ++ ++ // Allocate and construct an operation to wrap the handler. ++ typedef reactive_socket_recvfrom_op_ext op; ++ typename op::ptr p = { boost::asio::detail::addressof(handler), ++ op::ptr::allocate(handler), 0 }; ++ int protocol = impl.protocol_.type(); ++ p.p = new (p.v) op(success_ec_, impl.socket_, protocol, buffers, ++ sender_endpoint, flags, handler, io_ex); ++ ++ BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket", ++ &impl, impl.socket_, "async_receive_from")); ++ ++ start_op(impl, ++ (flags & socket_base::message_out_of_band) ++ ? reactor::except_op : reactor::read_op, ++ p.p, is_continuation, true, false); ++ p.v = p.p = 0; ++ } ++ ++ // Wait until data can be received without blocking. ++ template ++ void async_receive_from(implementation_type& impl, const null_buffers&, ++ endpoint_type& sender_endpoint, socket_base::message_flags flags, ++ Handler& handler, const IoExecutor& io_ex) ++ { ++ bool is_continuation = ++ boost_asio_handler_cont_helpers::is_continuation(handler); ++ ++ // Allocate and construct an operation to wrap the handler. ++ typedef reactive_null_buffers_op op; ++ typename op::ptr p = { boost::asio::detail::addressof(handler), ++ op::ptr::allocate(handler), 0 }; ++ p.p = new (p.v) op(success_ec_, handler, io_ex); ++ ++ BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket", ++ &impl, impl.socket_, "async_receive_from(null_buffers)")); ++ ++ // Reset endpoint since it can be given no sensible value at this time. ++ sender_endpoint = endpoint_type(); ++ ++ start_op(impl, ++ (flags & socket_base::message_out_of_band) ++ ? reactor::except_op : reactor::read_op, ++ p.p, is_continuation, false, false); ++ p.v = p.p = 0; ++ } ++ ++ // Accept a new connection. ++ template ++ boost::system::error_code accept(implementation_type& impl, ++ Socket& peer, endpoint_type* peer_endpoint, boost::system::error_code& ec) ++ { ++ // We cannot accept a socket that is already open. ++ if (peer.is_open()) ++ { ++ ec = boost::asio::error::already_open; ++ return ec; ++ } ++ ++ std::size_t addr_len = peer_endpoint ? peer_endpoint->capacity() : 0; ++ socket_holder new_socket(socket_ops::sync_accept(impl.socket_, ++ impl.state_, peer_endpoint ? peer_endpoint->data() : 0, ++ peer_endpoint ? &addr_len : 0, ec)); ++ ++ // On success, assign new connection to peer socket object. ++ if (new_socket.get() != invalid_socket) ++ { ++ if (peer_endpoint) ++ peer_endpoint->resize(addr_len); ++ peer.assign(impl.protocol_, new_socket.get(), ec); ++ if (!ec) ++ new_socket.release(); ++ } ++ ++ return ec; ++ } ++ ++ // Start an asynchronous accept. The peer and peer_endpoint objects must be ++ // valid until the accept's handler is invoked. ++ template ++ void async_accept(implementation_type& impl, Socket& peer, ++ endpoint_type* peer_endpoint, Handler& handler, const IoExecutor& io_ex) ++ { ++ bool is_continuation = ++ boost_asio_handler_cont_helpers::is_continuation(handler); ++ ++ // Allocate and construct an operation to wrap the handler. ++ typedef reactive_socket_accept_op op; ++ typename op::ptr p = { boost::asio::detail::addressof(handler), ++ op::ptr::allocate(handler), 0 }; ++ p.p = new (p.v) op(success_ec_, impl.socket_, impl.state_, peer, ++ impl.protocol_, peer_endpoint, handler, io_ex); ++ ++ BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket", ++ &impl, impl.socket_, "async_accept")); ++ ++ start_accept_op(impl, p.p, is_continuation, peer.is_open()); ++ p.v = p.p = 0; ++ } ++ ++#if defined(BOOST_ASIO_HAS_MOVE) ++ // Start an asynchronous accept. The peer_endpoint object must be valid until ++ // the accept's handler is invoked. ++ template ++ void async_move_accept(implementation_type& impl, ++ const PeerIoExecutor& peer_io_ex, endpoint_type* peer_endpoint, ++ Handler& handler, const IoExecutor& io_ex) ++ { ++ bool is_continuation = ++ boost_asio_handler_cont_helpers::is_continuation(handler); ++ ++ // Allocate and construct an operation to wrap the handler. ++ typedef reactive_socket_move_accept_op op; ++ typename op::ptr p = { boost::asio::detail::addressof(handler), ++ op::ptr::allocate(handler), 0 }; ++ p.p = new (p.v) op(success_ec_, peer_io_ex, impl.socket_, impl.state_, ++ impl.protocol_, peer_endpoint, handler, io_ex); ++ ++ BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket", ++ &impl, impl.socket_, "async_accept")); ++ ++ start_accept_op(impl, p.p, is_continuation, false); ++ p.v = p.p = 0; ++ } ++#endif // defined(BOOST_ASIO_HAS_MOVE) ++ ++ // Connect the socket to the specified endpoint. ++ boost::system::error_code connect(implementation_type& impl, ++ const endpoint_type& peer_endpoint, boost::system::error_code& ec) ++ { ++ socket_ops::sync_connect(impl.socket_, ++ peer_endpoint.data(), peer_endpoint.size(), ec); ++ return ec; ++ } ++ ++ // Start an asynchronous connect. ++ template ++ void async_connect(implementation_type& impl, ++ const endpoint_type& peer_endpoint, ++ Handler& handler, const IoExecutor& io_ex) ++ { ++ bool is_continuation = ++ boost_asio_handler_cont_helpers::is_continuation(handler); ++ ++ // Allocate and construct an operation to wrap the handler. ++ typedef reactive_socket_connect_op op; ++ typename op::ptr p = { boost::asio::detail::addressof(handler), ++ op::ptr::allocate(handler), 0 }; ++ p.p = new (p.v) op(success_ec_, impl.socket_, handler, io_ex); ++ ++ BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket", ++ &impl, impl.socket_, "async_connect")); ++ ++ start_connect_op(impl, p.p, is_continuation, ++ peer_endpoint.data(), peer_endpoint.size()); ++ p.v = p.p = 0; ++ } ++}; ++ ++} // namespace detail ++} // namespace asio ++} // namespace boost ++ ++#include ++ ++#endif // !defined(BOOST_ASIO_HAS_IOCP) ++ ++#endif // BOOST_ASIO_DETAIL_REACTIVE_SOCKET_SERVICE_EXT_HPP +diff --git a/implementation/helper/1.76/boost/asio/detail/reactive_socket_service_ext_local.hpp b/implementation/helper/1.76/boost/asio/detail/reactive_socket_service_ext_local.hpp +new file mode 100644 +index 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 ++ ++#if !defined(BOOST_ASIO_HAS_IOCP) ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++namespace boost { ++namespace asio { ++namespace detail { ++ ++template ++class reactive_socket_service_ext_local : ++ public execution_context_service_base >, ++ public reactive_socket_service_base_ext_local ++{ ++public: ++ // The protocol type. ++ typedef Protocol protocol_type; ++ ++ // The endpoint type. ++ typedef typename Protocol::endpoint endpoint_type; ++ ++ // The native type of a socket. ++ typedef socket_type native_handle_type; ++ ++ // The implementation type of the socket. ++ struct implementation_type : ++ reactive_socket_service_base_ext_local::base_implementation_type ++ { ++ // Default constructor. ++ implementation_type() ++ : protocol_(endpoint_type().protocol()) ++ { ++ } ++ ++ // The protocol associated with the socket. ++ protocol_type protocol_; ++ }; ++ ++ // Constructor. ++ reactive_socket_service_ext_local(execution_context& context) ++ : execution_context_service_base< ++ reactive_socket_service_ext_local >(context), ++ reactive_socket_service_base_ext_local(context) ++ { ++ } ++ ++ // Destroy all user-defined handler objects owned by the service. ++ void shutdown() ++ { ++ this->base_shutdown(); ++ } ++ ++ // Move-construct a new socket implementation. ++ void move_construct(implementation_type& impl, ++ implementation_type& other_impl) ++ { ++ this->base_move_construct(impl, other_impl); ++ ++ impl.protocol_ = other_impl.protocol_; ++ other_impl.protocol_ = endpoint_type().protocol(); ++ } ++ ++ // Move-assign from another socket implementation. ++ void move_assign(implementation_type& impl, ++ reactive_socket_service_base_ext_local& other_service, ++ implementation_type& other_impl) ++ { ++ this->base_move_assign(impl, other_service, other_impl); ++ ++ impl.protocol_ = other_impl.protocol_; ++ other_impl.protocol_ = endpoint_type().protocol(); ++ } ++ ++ // Move-construct a new socket implementation from another protocol type. ++ template ++ void converting_move_construct(implementation_type& impl, ++ reactive_socket_service_ext_local&, ++ typename reactive_socket_service_ext_local< ++ Protocol1>::implementation_type& other_impl) ++ { ++ this->base_move_construct(impl, other_impl); ++ ++ impl.protocol_ = protocol_type(other_impl.protocol_); ++ other_impl.protocol_ = typename Protocol1::endpoint().protocol(); ++ } ++ ++ // Open a new socket implementation. ++ boost::system::error_code open(implementation_type& impl, ++ const protocol_type& protocol, boost::system::error_code& ec) ++ { ++ if (!do_open(impl, protocol.family(), ++ protocol.type(), protocol.protocol(), ec)) ++ impl.protocol_ = protocol; ++ return ec; ++ } ++ ++ // Assign a native socket to a socket implementation. ++ boost::system::error_code assign(implementation_type& impl, ++ const protocol_type& protocol, const native_handle_type& native_socket, ++ boost::system::error_code& ec) ++ { ++ if (!do_assign(impl, protocol.type(), native_socket, ec)) ++ impl.protocol_ = protocol; ++ return ec; ++ } ++ ++ // Get the native socket representation. ++ native_handle_type native_handle(implementation_type& impl) ++ { ++ return impl.socket_; ++ } ++ ++ // Bind the socket to the specified local endpoint. ++ boost::system::error_code bind(implementation_type& impl, ++ const endpoint_type& endpoint, boost::system::error_code& ec) ++ { ++ socket_ops::bind(impl.socket_, endpoint.data(), endpoint.size(), ec); ++ return ec; ++ } ++ ++ // Set a socket option. ++ template ++ boost::system::error_code set_option(implementation_type& impl, ++ const Option& option, boost::system::error_code& ec) ++ { ++ socket_ops::setsockopt(impl.socket_, impl.state_, ++ option.level(impl.protocol_), option.name(impl.protocol_), ++ option.data(impl.protocol_), option.size(impl.protocol_), ec); ++ return ec; ++ } ++ ++ // Set a socket option. ++ template ++ boost::system::error_code get_option(const implementation_type& impl, ++ Option& option, boost::system::error_code& ec) const ++ { ++ std::size_t size = option.size(impl.protocol_); ++ socket_ops::getsockopt(impl.socket_, impl.state_, ++ option.level(impl.protocol_), option.name(impl.protocol_), ++ option.data(impl.protocol_), &size, ec); ++ if (!ec) ++ option.resize(impl.protocol_, size); ++ return ec; ++ } ++ ++ // Get the local endpoint. ++ endpoint_type local_endpoint(const implementation_type& impl, ++ boost::system::error_code& ec) const ++ { ++ endpoint_type endpoint; ++ std::size_t addr_len = endpoint.capacity(); ++ if (socket_ops::getsockname(impl.socket_, endpoint.data(), &addr_len, ec)) ++ return endpoint_type(); ++ endpoint.resize(addr_len); ++ return endpoint; ++ } ++ ++ // Get the remote endpoint. ++ endpoint_type remote_endpoint(const implementation_type& impl, ++ boost::system::error_code& ec) const ++ { ++ endpoint_type endpoint; ++ std::size_t addr_len = endpoint.capacity(); ++ if (socket_ops::getpeername(impl.socket_, ++ endpoint.data(), &addr_len, false, ec)) ++ return endpoint_type(); ++ endpoint.resize(addr_len); ++ return endpoint; ++ } ++ ++ // Disable sends or receives on the socket. ++ boost::system::error_code shutdown(base_implementation_type& impl, ++ socket_base::shutdown_type what, boost::system::error_code& ec) ++ { ++ socket_ops::shutdown(impl.socket_, what, ec); ++ return ec; ++ } ++ ++ // Send a datagram to the specified endpoint. Returns the number of bytes ++ // sent. ++ template ++ size_t send_to(implementation_type& impl, const ConstBufferSequence& buffers, ++ const endpoint_type& destination, socket_base::message_flags flags, ++ boost::system::error_code& ec) ++ { ++ buffer_sequence_adapter bufs(buffers); ++ ++ return socket_ops::sync_sendto(impl.socket_, impl.state_, ++ bufs.buffers(), bufs.count(), flags, ++ destination.data(), destination.size(), ec); ++ } ++ ++ // Wait until data can be sent without blocking. ++ size_t send_to(implementation_type& impl, const null_buffers&, ++ const endpoint_type&, socket_base::message_flags, ++ boost::system::error_code& ec) ++ { ++ // Wait for socket to become ready. ++ socket_ops::poll_write(impl.socket_, impl.state_, -1, ec); ++ ++ return 0; ++ } ++ ++ // Start an asynchronous send. The data being sent must be valid for the ++ // lifetime of the asynchronous operation. ++ template ++ void async_send_to(implementation_type& impl, ++ const ConstBufferSequence& buffers, ++ const endpoint_type& destination, socket_base::message_flags flags, ++ Handler& handler, const IoExecutor& io_ex) ++ { ++ bool is_continuation = ++ boost_asio_handler_cont_helpers::is_continuation(handler); ++ ++ // Allocate and construct an operation to wrap the handler. ++ typedef reactive_socket_sendto_op op; ++ typename op::ptr p = { boost::asio::detail::addressof(handler), ++ op::ptr::allocate(handler), 0 }; ++ p.p = new (p.v) op(success_ec_, impl.socket_, buffers, ++ destination, flags, handler, io_ex); ++ ++ BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket", ++ &impl, impl.socket_, "async_send_to")); ++ ++ start_op(impl, reactor::write_op, p.p, is_continuation, true, false); ++ p.v = p.p = 0; ++ } ++ ++ // Start an asynchronous wait until data can be sent without blocking. ++ template ++ void async_send_to(implementation_type& impl, const null_buffers&, ++ const endpoint_type&, socket_base::message_flags, ++ Handler& handler, const IoExecutor& io_ex) ++ { ++ bool is_continuation = ++ boost_asio_handler_cont_helpers::is_continuation(handler); ++ ++ // Allocate and construct an operation to wrap the handler. ++ typedef reactive_null_buffers_op op; ++ typename op::ptr p = { boost::asio::detail::addressof(handler), ++ op::ptr::allocate(handler), 0 }; ++ p.p = new (p.v) op(success_ec_, handler, io_ex); ++ ++ BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket", ++ &impl, impl.socket_, "async_send_to(null_buffers)")); ++ ++ start_op(impl, reactor::write_op, p.p, is_continuation, false, false); ++ p.v = p.p = 0; ++ } ++ ++ // Receive a datagram with the endpoint of the sender. Returns the number of ++ // bytes received. ++ template ++ size_t receive_from(implementation_type& impl, ++ const MutableBufferSequence& buffers, ++ endpoint_type& sender_endpoint, socket_base::message_flags flags, ++ boost::system::error_code& ec) ++ { ++ buffer_sequence_adapter bufs(buffers); ++ ++ std::size_t addr_len = sender_endpoint.capacity(); ++ std::size_t bytes_recvd = socket_ops::sync_recvfrom( ++ impl.socket_, impl.state_, bufs.buffers(), bufs.count(), ++ flags, sender_endpoint.data(), &addr_len, ec); ++ ++ if (!ec) ++ sender_endpoint.resize(addr_len); ++ ++ return bytes_recvd; ++ } ++ ++ // Wait until data can be received without blocking. ++ size_t receive_from(implementation_type& impl, const null_buffers&, ++ endpoint_type& sender_endpoint, socket_base::message_flags, ++ boost::system::error_code& ec) ++ { ++ // Wait for socket to become ready. ++ socket_ops::poll_read(impl.socket_, impl.state_, -1, ec); ++ ++ // Reset endpoint since it can be given no sensible value at this time. ++ sender_endpoint = endpoint_type(); ++ ++ return 0; ++ } ++ ++ // Start an asynchronous receive. The buffer for the data being received and ++ // the sender_endpoint object must both be valid for the lifetime of the ++ // asynchronous operation. ++ template ++ void async_receive_from(implementation_type& impl, ++ const MutableBufferSequence& buffers, endpoint_type& sender_endpoint, ++ socket_base::message_flags flags, Handler& handler, ++ const IoExecutor& io_ex) ++ { ++ bool is_continuation = ++ boost_asio_handler_cont_helpers::is_continuation(handler); ++ ++ // Allocate and construct an operation to wrap the handler. ++ typedef reactive_socket_recvfrom_op_ext_local op; ++ typename op::ptr p = { boost::asio::detail::addressof(handler), ++ op::ptr::allocate(handler), 0 }; ++ int protocol = impl.protocol_.type(); ++ p.p = new (p.v) op(success_ec_, impl.socket_, protocol, buffers, ++ sender_endpoint, flags, handler, io_ex); ++ ++ BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket", ++ &impl, impl.socket_, "async_receive_from")); ++ ++ start_op(impl, ++ (flags & socket_base::message_out_of_band) ++ ? reactor::except_op : reactor::read_op, ++ p.p, is_continuation, true, false); ++ p.v = p.p = 0; ++ } ++ ++ // Wait until data can be received without blocking. ++ template ++ void async_receive_from(implementation_type& impl, const null_buffers&, ++ endpoint_type& sender_endpoint, socket_base::message_flags flags, ++ Handler& handler, const IoExecutor& io_ex) ++ { ++ bool is_continuation = ++ boost_asio_handler_cont_helpers::is_continuation(handler); ++ ++ // Allocate and construct an operation to wrap the handler. ++ typedef reactive_null_buffers_op op; ++ typename op::ptr p = { boost::asio::detail::addressof(handler), ++ op::ptr::allocate(handler), 0 }; ++ p.p = new (p.v) op(success_ec_, handler, io_ex); ++ ++ BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket", ++ &impl, impl.socket_, "async_receive_from(null_buffers)")); ++ ++ // Reset endpoint since it can be given no sensible value at this time. ++ sender_endpoint = endpoint_type(); ++ ++ start_op(impl, ++ (flags & socket_base::message_out_of_band) ++ ? reactor::except_op : reactor::read_op, ++ p.p, is_continuation, false, false); ++ p.v = p.p = 0; ++ } ++ ++ // Accept a new connection. ++ template ++ boost::system::error_code accept(implementation_type& impl, ++ Socket& peer, endpoint_type* peer_endpoint, boost::system::error_code& ec) ++ { ++ // We cannot accept a socket that is already open. ++ if (peer.is_open()) ++ { ++ ec = boost::asio::error::already_open; ++ return ec; ++ } ++ ++ std::size_t addr_len = peer_endpoint ? peer_endpoint->capacity() : 0; ++ socket_holder new_socket(socket_ops::sync_accept(impl.socket_, ++ impl.state_, peer_endpoint ? peer_endpoint->data() : 0, ++ peer_endpoint ? &addr_len : 0, ec)); ++ ++ // On success, assign new connection to peer socket object. ++ if (new_socket.get() != invalid_socket) ++ { ++ if (peer_endpoint) ++ peer_endpoint->resize(addr_len); ++ peer.assign(impl.protocol_, new_socket.get(), ec); ++ if (!ec) ++ new_socket.release(); ++ } ++ ++ return ec; ++ } ++ ++ // Start an asynchronous accept. The peer and peer_endpoint objects must be ++ // valid until the accept's handler is invoked. ++ template ++ void async_accept(implementation_type& impl, Socket& peer, ++ endpoint_type* peer_endpoint, Handler& handler, const IoExecutor& io_ex) ++ { ++ bool is_continuation = ++ boost_asio_handler_cont_helpers::is_continuation(handler); ++ ++ // Allocate and construct an operation to wrap the handler. ++ typedef reactive_socket_accept_op op; ++ typename op::ptr p = { boost::asio::detail::addressof(handler), ++ op::ptr::allocate(handler), 0 }; ++ p.p = new (p.v) op(success_ec_, impl.socket_, impl.state_, peer, ++ impl.protocol_, peer_endpoint, handler, io_ex); ++ ++ BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket", ++ &impl, impl.socket_, "async_accept")); ++ ++ start_accept_op(impl, p.p, is_continuation, peer.is_open()); ++ p.v = p.p = 0; ++ } ++ ++#if defined(BOOST_ASIO_HAS_MOVE) ++ // Start an asynchronous accept. The peer_endpoint object must be valid until ++ // the accept's handler is invoked. ++ template ++ void async_move_accept(implementation_type& impl, ++ const PeerIoExecutor& peer_io_ex, endpoint_type* peer_endpoint, ++ Handler& handler, const IoExecutor& io_ex) ++ { ++ bool is_continuation = ++ boost_asio_handler_cont_helpers::is_continuation(handler); ++ ++ // Allocate and construct an operation to wrap the handler. ++ typedef reactive_socket_move_accept_op op; ++ typename op::ptr p = { boost::asio::detail::addressof(handler), ++ op::ptr::allocate(handler), 0 }; ++ p.p = new (p.v) op(success_ec_, peer_io_ex, impl.socket_, impl.state_, ++ impl.protocol_, peer_endpoint, handler, io_ex); ++ ++ BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket", ++ &impl, impl.socket_, "async_accept")); ++ ++ start_accept_op(impl, p.p, is_continuation, false); ++ p.v = p.p = 0; ++ } ++#endif // defined(BOOST_ASIO_HAS_MOVE) ++ ++ // Connect the socket to the specified endpoint. ++ boost::system::error_code connect(implementation_type& impl, ++ const endpoint_type& peer_endpoint, boost::system::error_code& ec) ++ { ++ socket_ops::sync_connect(impl.socket_, ++ peer_endpoint.data(), peer_endpoint.size(), ec); ++ return ec; ++ } ++ ++ // Start an asynchronous connect. ++ template ++ void async_connect(implementation_type& impl, ++ const endpoint_type& peer_endpoint, ++ Handler& handler, const IoExecutor& io_ex) ++ { ++ bool is_continuation = ++ boost_asio_handler_cont_helpers::is_continuation(handler); ++ ++ // Allocate and construct an operation to wrap the handler. ++ typedef reactive_socket_connect_op op; ++ typename op::ptr p = { boost::asio::detail::addressof(handler), ++ op::ptr::allocate(handler), 0 }; ++ p.p = new (p.v) op(success_ec_, impl.socket_, handler, io_ex); ++ ++ BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket", ++ &impl, impl.socket_, "async_connect")); ++ ++ start_connect_op(impl, p.p, is_continuation, ++ peer_endpoint.data(), peer_endpoint.size()); ++ p.v = p.p = 0; ++ } ++}; ++ ++} // namespace detail ++} // namespace asio ++} // namespace boost ++ ++#include ++ ++#endif // !defined(BOOST_ASIO_HAS_IOCP) ++ ++#endif // BOOST_ASIO_DETAIL_REACTIVE_SOCKET_SERVICE_EXT_LOCAL_HPP +diff --git a/implementation/helper/1.76/boost/asio/detail/reactor_op_ext.hpp b/implementation/helper/1.76/boost/asio/detail/reactor_op_ext.hpp +new file mode 100644 +index 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 ++ ++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 ++ ++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 ++ ++namespace boost { ++namespace asio { ++namespace detail { ++namespace socket_ops { ++ ++BOOST_ASIO_DECL signed_size_type recvfrom(socket_type s, buf* bufs, ++ size_t count, int flags, socket_addr_type* addr, ++ std::size_t* addrlen, boost::system::error_code& ec, ++ boost::asio::ip::address& da); ++ ++BOOST_ASIO_DECL size_t sync_recvfrom(socket_type s, state_type state, ++ buf* bufs, size_t count, int flags, socket_addr_type* addr, ++ std::size_t* addrlen, boost::system::error_code& ec, boost::asio::ip::address& da); ++ ++#if defined(BOOST_ASIO_HAS_IOCP) ++ ++BOOST_ASIO_DECL void complete_iocp_recvfrom( ++ const weak_cancel_token_type& cancel_token, ++ boost::system::error_code& ec, ++ boost::asio::ip::address& da); ++ ++#else // defined(BOOST_ASIO_HAS_IOCP) ++ ++BOOST_ASIO_DECL bool non_blocking_recvfrom(socket_type s, ++ buf* bufs, size_t count, int flags, ++ socket_addr_type* addr, std::size_t* addrlen, ++ boost::system::error_code& ec, size_t& bytes_transferred, ++ boost::asio::ip::address& da); ++ ++#endif // defined(BOOST_ASIO_HAS_IOCP) ++ ++} // namespace socket_ops ++} // namespace detail ++} // namespace asio ++} // namespace boost ++ ++ ++#if defined(BOOST_ASIO_HEADER_ONLY) ++# include ++#endif // defined(BOOST_ASIO_HEADER_ONLY) ++ ++#endif // BOOST_EXT_ASIO_DETAIL_SOCKET_OPS_HPP +diff --git a/implementation/helper/1.76/boost/asio/detail/socket_ops_ext_local.hpp b/implementation/helper/1.76/boost/asio/detail/socket_ops_ext_local.hpp +new file mode 100644 +index 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 ++ ++#include ++#include ++#include ++ ++#include ++ ++namespace boost { ++namespace asio { ++namespace detail { ++namespace socket_ops { ++ ++BOOST_ASIO_DECL signed_size_type recv(socket_type s, buf* bufs, ++ size_t count, int flags, boost::system::error_code& ec, ++ std::uint32_t& uid, std::uint32_t& gid); ++ ++BOOST_ASIO_DECL size_t sync_recv(socket_type s, state_type state, buf* bufs, ++ size_t count, int flags, bool all_empty, boost::system::error_code& ec, ++ std::uint32_t& uid, std::uint32_t& gid); ++ ++#if defined(BOOST_ASIO_HAS_IOCP) ++ ++BOOST_ASIO_DECL void complete_iocp_recv(state_type state, ++ const weak_cancel_token_type& cancel_token, bool all_empty, ++ boost::system::error_code& ec, size_t bytes_transferred, ++ std::uint32_t& uid, std::uint32_t& gid); ++ ++#else // defined(BOOST_ASIO_HAS_IOCP) ++ ++BOOST_ASIO_DECL bool non_blocking_recv(socket_type s, ++ buf* bufs, size_t count, int flags, bool is_stream, ++ boost::system::error_code& ec, size_t& bytes_transferred, ++ std::uint32_t& uid, std::uint32_t& gid); ++ ++#endif // defined(BOOST_ASIO_HAS_IOCP) ++ ++BOOST_ASIO_DECL signed_size_type recvfrom(socket_type s, buf* bufs, ++ size_t count, int flags, socket_addr_type* addr, ++ std::size_t* addrlen, boost::system::error_code& ec, ++ std::uint32_t& uid, std::uint32_t& gid); ++ ++BOOST_ASIO_DECL size_t sync_recvfrom(socket_type s, state_type state, ++ buf* bufs, size_t count, int flags, socket_addr_type* addr, ++ std::size_t* addrlen, boost::system::error_code& ec, ++ std::uint32_t& uid, std::uint32_t& gid); ++ ++#if defined(BOOST_ASIO_HAS_IOCP) ++ ++BOOST_ASIO_DECL void complete_iocp_recvfrom( ++ const weak_cancel_token_type& cancel_token, ++ boost::system::error_code& ec, ++ std::uint32_t& uid, std::uint32_t& gid); ++ ++#else // defined(BOOST_ASIO_HAS_IOCP) ++ ++BOOST_ASIO_DECL bool non_blocking_recvfrom(socket_type s, ++ buf* bufs, size_t count, int flags, ++ socket_addr_type* addr, std::size_t* addrlen, ++ boost::system::error_code& ec, size_t& bytes_transferred, ++ std::uint32_t& uid, std::uint32_t& gid); ++ ++#endif // defined(BOOST_ASIO_HAS_IOCP) ++ ++ ++} // namespace socket_ops ++} // namespace detail ++} // namespace asio ++} // namespace boost ++ ++#include ++ ++#if defined(BOOST_ASIO_HEADER_ONLY) ++# include ++#endif // defined(BOOST_ASIO_HEADER_ONLY) ++ ++#endif // BOOST_ASIO_DETAIL_SOCKET_OPS_EXT_LOCAL_HPP +diff --git a/implementation/helper/1.76/boost/asio/ip/udp_ext.hpp b/implementation/helper/1.76/boost/asio/ip/udp_ext.hpp +new file mode 100644 +index 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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++namespace boost { ++namespace asio { ++namespace ip { ++ ++/// Encapsulates the flags needed for UDP. ++/** ++ * The boost::asio::ip::udp_ext class contains flags necessary for UDP sockets. ++ * ++ * @par Thread Safety ++ * @e Distinct @e objects: Safe.@n ++ * @e Shared @e objects: Safe. ++ * ++ * @par Concepts: ++ * Protocol, InternetProtocol. ++ */ ++class udp_ext ++{ ++public: ++ /// The type of a UDP endpoint. ++ typedef basic_endpoint endpoint; ++ ++ /// Construct to represent the IPv4 UDP protocol. ++ static udp_ext v4() ++ { ++ return udp_ext(BOOST_ASIO_OS_DEF(AF_INET)); ++ } ++ ++ /// Construct to represent the IPv6 UDP protocol. ++ static udp_ext v6() ++ { ++ return udp_ext(BOOST_ASIO_OS_DEF(AF_INET6)); ++ } ++ ++ /// Obtain an identifier for the type of the protocol. ++ int type() const ++ { ++ return BOOST_ASIO_OS_DEF(SOCK_DGRAM); ++ } ++ ++ /// Obtain an identifier for the protocol. ++ int protocol() const ++ { ++ return BOOST_ASIO_OS_DEF(IPPROTO_UDP); ++ } ++ ++ /// Obtain an identifier for the protocol family. ++ int family() const ++ { ++ return family_; ++ } ++ ++ /// The UDP socket type. ++ typedef basic_datagram_socket_ext socket; ++ ++ /// The UDP resolver type. ++ typedef basic_resolver resolver; ++ ++ /// Compare two protocols for equality. ++ friend bool operator==(const udp_ext& p1, const udp_ext& p2) ++ { ++ return p1.family_ == p2.family_; ++ } ++ ++ /// Compare two protocols for inequality. ++ friend bool operator!=(const udp_ext& p1, const udp_ext& p2) ++ { ++ return p1.family_ != p2.family_; ++ } ++ ++private: ++ // Construct with a specific family. ++ explicit udp_ext(int protocol_family) ++ : family_(protocol_family) ++ { ++ } ++ ++ int family_; ++}; ++ ++} // namespace ip ++} // namespace asio ++} // namespace boost ++ ++#include ++ ++#endif // BOOST_ASIO_IP_UDP_EXT_HPP +diff --git a/implementation/helper/1.76/boost/asio/local/stream_protocol_ext.hpp b/implementation/helper/1.76/boost/asio/local/stream_protocol_ext.hpp +new file mode 100644 +index 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 ++ ++#if defined(BOOST_ASIO_HAS_LOCAL_SOCKETS) \ ++ || defined(GENERATING_DOCUMENTATION) ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++namespace boost { ++namespace asio { ++namespace local { ++ ++/// Encapsulates the flags needed for stream-oriented UNIX sockets. ++/** ++ * The boost::asio::local::stream_protocol class contains flags necessary for ++ * stream-oriented UNIX domain sockets. ++ * ++ * @par Thread Safety ++ * @e Distinct @e objects: Safe.@n ++ * @e Shared @e objects: Safe. ++ * ++ * @par Concepts: ++ * Protocol. ++ */ ++class stream_protocol_ext ++{ ++public: ++ /// Obtain an identifier for the type of the protocol. ++ int type() const ++ { ++ return SOCK_STREAM; ++ } ++ ++ /// Obtain an identifier for the protocol. ++ int protocol() const ++ { ++ return 0; ++ } ++ ++ /// Obtain an identifier for the protocol family. ++ int family() const ++ { ++ return AF_UNIX; ++ } ++ ++ /// The type of a UNIX domain endpoint. ++ typedef basic_endpoint endpoint; ++ ++ /// The UNIX domain socket type. ++ typedef basic_stream_socket_ext socket; ++ ++ /// The UNIX domain acceptor type. ++ typedef basic_socket_acceptor_ext acceptor; ++ ++#if !defined(BOOST_ASIO_NO_IOSTREAM) ++ /// The UNIX domain iostream type. ++ typedef basic_socket_iostream iostream; ++#endif // !defined(BOOST_ASIO_NO_IOSTREAM) ++}; ++ ++} // namespace local ++} // namespace asio ++} // namespace boost ++ ++#include ++ ++#endif // defined(BOOST_ASIO_HAS_LOCAL_SOCKETS) ++ // || defined(GENERATING_DOCUMENTATION) ++ ++#endif // BOOST_ASIO_LOCAL_STREAM_PROTOCOL_EXT_HPP +-- +2.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 +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 + +Upstream-Status: Backport +[https://github.com/COVESA/vsomeip/pull/367] + +Signed-off-by: Yi Zhao +--- + 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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++namespace boost { ++namespace asio { ++ ++#if !defined(BOOST_ASIO_BASIC_DATAGRAM_SOCKET_EXT_FWD_DECL) ++#define BOOST_ASIO_BASIC_DATAGRAM_SOCKET_EXT_FWD_DECL ++ ++// Forward declaration with defaulted arguments. ++template ++class basic_datagram_socket_ext; ++ ++#endif // !defined(BOOST_ASIO_BASIC_DATAGRAM_SOCKET_EXT_FWD_DECL) ++ ++/// Provides datagram-oriented socket functionality. ++/** ++ * The basic_datagram_socket class template provides asynchronous and blocking ++ * datagram-oriented socket functionality. ++ * ++ * @par Thread Safety ++ * @e Distinct @e objects: Safe.@n ++ * @e Shared @e objects: Unsafe. ++ */ ++template ++class basic_datagram_socket_ext ++ : public basic_socket_ext ++{ ++public: ++ /// The type of the executor associated with the object. ++ typedef Executor executor_type; ++ ++ /// Rebinds the socket type to another executor. ++ template ++ struct rebind_executor ++ { ++ /// The socket type when rebound to the specified executor. ++ typedef basic_datagram_socket_ext other; ++ }; ++ ++ /// The native representation of a socket. ++#if defined(GENERATING_DOCUMENTATION) ++ typedef implementation_defined native_handle_type; ++#else ++ typedef typename basic_socket_ext::native_handle_type native_handle_type; ++#endif ++ ++ /// The protocol type. ++ typedef Protocol protocol_type; ++ ++ /// The endpoint type. ++ typedef typename Protocol::endpoint endpoint_type; ++ ++ /// Construct a basic_datagram_socket without opening it. ++ /** ++ * This constructor creates a datagram socket without opening it. The open() ++ * function must be called before data can be sent or received on the socket. ++ * ++ * @param ex The I/O executor that the socket will use, by default, to ++ * dispatch handlers for any asynchronous operations performed on the socket. ++ */ ++ explicit basic_datagram_socket_ext(const executor_type& ex) ++ : basic_socket_ext(ex) ++ { ++ } ++ ++ /// Construct a basic_datagram_socket without opening it. ++ /** ++ * This constructor creates a datagram socket without opening it. The open() ++ * function must be called before data can be sent or received on the socket. ++ * ++ * @param context An execution context which provides the I/O executor that ++ * the socket will use, by default, to dispatch handlers for any asynchronous ++ * operations performed on the socket. ++ */ ++ template ++ explicit basic_datagram_socket_ext(ExecutionContext& context, ++ typename enable_if< ++ is_convertible::value ++ >::type* = 0) ++ : basic_socket_ext(context) ++ { ++ } ++ ++ /// Construct and open a basic_datagram_socket. ++ /** ++ * This constructor creates and opens a datagram socket. ++ * ++ * @param ex The I/O executor that the socket will use, by default, to ++ * dispatch handlers for any asynchronous operations performed on the socket. ++ * ++ * @param protocol An object specifying protocol parameters to be used. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ */ ++ basic_datagram_socket_ext(const executor_type& ex, const protocol_type& protocol) ++ : basic_socket_ext(ex, protocol) ++ { ++ } ++ ++ /// Construct and open a basic_datagram_socket. ++ /** ++ * This constructor creates and opens a datagram socket. ++ * ++ * @param context An execution context which provides the I/O executor that ++ * the socket will use, by default, to dispatch handlers for any asynchronous ++ * operations performed on the socket. ++ * ++ * @param protocol An object specifying protocol parameters to be used. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ */ ++ template ++ basic_datagram_socket_ext(ExecutionContext& context, ++ const protocol_type& protocol, ++ typename enable_if< ++ is_convertible::value ++ >::type* = 0) ++ : basic_socket_ext(context, protocol) ++ { ++ } ++ ++ /// Construct a basic_datagram_socket, opening it and binding it to the given ++ /// local endpoint. ++ /** ++ * This constructor creates a datagram socket and automatically opens it bound ++ * to the specified endpoint on the local machine. The protocol used is the ++ * protocol associated with the given endpoint. ++ * ++ * @param ex The I/O executor that the socket will use, by default, to ++ * dispatch handlers for any asynchronous operations performed on the socket. ++ * ++ * @param endpoint An endpoint on the local machine to which the datagram ++ * socket will be bound. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ */ ++ basic_datagram_socket_ext(const executor_type& ex, const endpoint_type& endpoint) ++ : basic_socket_ext(ex, endpoint) ++ { ++ } ++ ++ /// Construct a basic_datagram_socket, opening it and binding it to the given ++ /// local endpoint. ++ /** ++ * This constructor creates a datagram socket and automatically opens it bound ++ * to the specified endpoint on the local machine. The protocol used is the ++ * protocol associated with the given endpoint. ++ * ++ * @param context An execution context which provides the I/O executor that ++ * the socket will use, by default, to dispatch handlers for any asynchronous ++ * operations performed on the socket. ++ * ++ * @param endpoint An endpoint on the local machine to which the datagram ++ * socket will be bound. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ */ ++ template ++ basic_datagram_socket_ext(ExecutionContext& context, ++ const endpoint_type& endpoint, ++ typename enable_if< ++ is_convertible::value ++ >::type* = 0) ++ : basic_socket_ext(context, endpoint) ++ { ++ } ++ ++ /// Construct a basic_datagram_socket on an existing native socket. ++ /** ++ * This constructor creates a datagram socket object to hold an existing ++ * native socket. ++ * ++ * @param ex The I/O executor that the socket will use, by default, to ++ * dispatch handlers for any asynchronous operations performed on the socket. ++ * ++ * @param protocol An object specifying protocol parameters to be used. ++ * ++ * @param native_socket The new underlying socket implementation. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ */ ++ basic_datagram_socket_ext(const executor_type& ex, ++ const protocol_type& protocol, const native_handle_type& native_socket) ++ : basic_socket_ext(ex, protocol, native_socket) ++ { ++ } ++ ++ /// Construct a basic_datagram_socket on an existing native socket. ++ /** ++ * This constructor creates a datagram socket object to hold an existing ++ * native socket. ++ * ++ * @param context An execution context which provides the I/O executor that ++ * the socket will use, by default, to dispatch handlers for any asynchronous ++ * operations performed on the socket. ++ * ++ * @param protocol An object specifying protocol parameters to be used. ++ * ++ * @param native_socket The new underlying socket implementation. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ */ ++ template ++ basic_datagram_socket_ext(ExecutionContext& context, ++ const protocol_type& protocol, const native_handle_type& native_socket, ++ typename enable_if< ++ is_convertible::value ++ >::type* = 0) ++ : basic_socket_ext(context, protocol, native_socket) ++ { ++ } ++ ++#if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) ++ /// Move-construct a basic_datagram_socket from another. ++ /** ++ * This constructor moves a datagram socket from one object to another. ++ * ++ * @param other The other basic_datagram_socket object from which the move ++ * will occur. ++ * ++ * @note Following the move, the moved-from object is in the same state as if ++ * constructed using the @c basic_datagram_socket(const executor_type&) ++ * constructor. ++ */ ++ basic_datagram_socket_ext(basic_datagram_socket_ext&& other) ++ : basic_socket_ext(std::move(other)) ++ { ++ } ++ ++ /// Move-assign a basic_datagram_socket from another. ++ /** ++ * This assignment operator moves a datagram socket from one object to ++ * another. ++ * ++ * @param other The other basic_datagram_socket object from which the move ++ * will occur. ++ * ++ * @note Following the move, the moved-from object is in the same state as if ++ * constructed using the @c basic_datagram_socket(const executor_type&) ++ * constructor. ++ */ ++ basic_datagram_socket_ext& operator=(basic_datagram_socket_ext&& other) ++ { ++ basic_socket_ext::operator=(std::move(other)); ++ return *this; ++ } ++ ++ /// Move-construct a basic_datagram_socket from a socket of another protocol ++ /// type. ++ /** ++ * This constructor moves a datagram socket from one object to another. ++ * ++ * @param other The other basic_datagram_socket object from which the move ++ * will occur. ++ * ++ * @note Following the move, the moved-from object is in the same state as if ++ * constructed using the @c basic_datagram_socket(const executor_type&) ++ * constructor. ++ */ ++ template ++ basic_datagram_socket_ext(basic_datagram_socket_ext&& other, ++ typename enable_if< ++ is_convertible::value ++ && is_convertible::value ++ >::type* = 0) ++ : basic_socket_ext(std::move(other)) ++ { ++ } ++ ++ /// Move-assign a basic_datagram_socket from a socket of another protocol ++ /// type. ++ /** ++ * This assignment operator moves a datagram socket from one object to ++ * another. ++ * ++ * @param other The other basic_datagram_socket object from which the move ++ * will occur. ++ * ++ * @note Following the move, the moved-from object is in the same state as if ++ * constructed using the @c basic_datagram_socket(const executor_type&) ++ * constructor. ++ */ ++ template ++ typename enable_if< ++ is_convertible::value ++ && is_convertible::value, ++ basic_datagram_socket_ext& ++ >::type operator=(basic_datagram_socket_ext&& other) ++ { ++ basic_socket_ext::operator=(std::move(other)); ++ return *this; ++ } ++#endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) ++ ++ /// Destroys the socket. ++ /** ++ * This function destroys the socket, cancelling any outstanding asynchronous ++ * operations associated with the socket as if by calling @c cancel. ++ */ ++ ~basic_datagram_socket_ext() ++ { ++ } ++ ++ /// Send some data on a connected socket. ++ /** ++ * This function is used to send data on the datagram socket. The function ++ * call will block until the data has been sent successfully or an error ++ * occurs. ++ * ++ * @param buffers One ore more data buffers to be sent on the socket. ++ * ++ * @returns The number of bytes sent. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ * ++ * @note The send operation can only be used with a connected socket. Use ++ * the send_to function to send data on an unconnected datagram socket. ++ * ++ * @par Example ++ * To send a single data buffer use the @ref buffer function as follows: ++ * @code socket.send(boost::asio::buffer(data, size)); @endcode ++ * See the @ref buffer documentation for information on sending multiple ++ * buffers in one go, and how to use it with arrays, boost::array or ++ * std::vector. ++ */ ++ template ++ std::size_t send(const ConstBufferSequence& buffers) ++ { ++ boost::system::error_code ec; ++ std::size_t s = this->impl_.get_service().send( ++ this->impl_.get_implementation(), buffers, 0, ec); ++ boost::asio::detail::throw_error(ec, "send"); ++ return s; ++ } ++ ++ /// Send some data on a connected socket. ++ /** ++ * This function is used to send data on the datagram socket. The function ++ * call will block until the data has been sent successfully or an error ++ * occurs. ++ * ++ * @param buffers One ore more data buffers to be sent on the socket. ++ * ++ * @param flags Flags specifying how the send call is to be made. ++ * ++ * @returns The number of bytes sent. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ * ++ * @note The send operation can only be used with a connected socket. Use ++ * the send_to function to send data on an unconnected datagram socket. ++ */ ++ template ++ std::size_t send(const ConstBufferSequence& buffers, ++ socket_base::message_flags flags) ++ { ++ boost::system::error_code ec; ++ std::size_t s = this->impl_.get_service().send( ++ this->impl_.get_implementation(), buffers, flags, ec); ++ boost::asio::detail::throw_error(ec, "send"); ++ return s; ++ } ++ ++ /// Send some data on a connected socket. ++ /** ++ * This function is used to send data on the datagram socket. The function ++ * call will block until the data has been sent successfully or an error ++ * occurs. ++ * ++ * @param buffers One or more data buffers to be sent on the socket. ++ * ++ * @param flags Flags specifying how the send call is to be made. ++ * ++ * @param ec Set to indicate what error occurred, if any. ++ * ++ * @returns The number of bytes sent. ++ * ++ * @note The send operation can only be used with a connected socket. Use ++ * the send_to function to send data on an unconnected datagram socket. ++ */ ++ template ++ std::size_t send(const ConstBufferSequence& buffers, ++ socket_base::message_flags flags, boost::system::error_code& ec) ++ { ++ return this->impl_.get_service().send( ++ this->impl_.get_implementation(), buffers, flags, ec); ++ } ++ ++ /// Start an asynchronous send on a connected socket. ++ /** ++ * This function is used to asynchronously send data on the datagram socket. ++ * The function call always returns immediately. ++ * ++ * @param buffers One or more data buffers to be sent on the socket. Although ++ * the buffers object may be copied as necessary, ownership of the underlying ++ * memory blocks is retained by the caller, which must guarantee that they ++ * remain valid until the handler is called. ++ * ++ * @param handler The handler to be called when the send operation completes. ++ * Copies will be made of the handler as required. The function signature of ++ * the handler must be: ++ * @code void handler( ++ * const boost::system::error_code& error, // Result of operation. ++ * std::size_t bytes_transferred // Number of bytes sent. ++ * ); @endcode ++ * Regardless of whether the asynchronous operation completes immediately or ++ * not, the handler will not be invoked from within this function. On ++ * immediate completion, invocation of the handler will be performed in a ++ * manner equivalent to using boost::asio::post(). ++ * ++ * @note The async_send operation can only be used with a connected socket. ++ * Use the async_send_to function to send data on an unconnected datagram ++ * socket. ++ * ++ * @par Example ++ * To send a single data buffer use the @ref buffer function as follows: ++ * @code ++ * socket.async_send(boost::asio::buffer(data, size), handler); ++ * @endcode ++ * See the @ref buffer documentation for information on sending multiple ++ * buffers in one go, and how to use it with arrays, boost::array or ++ * std::vector. ++ */ ++ template ++ BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler, ++ void (boost::system::error_code, std::size_t)) ++ async_send(const ConstBufferSequence& buffers, ++ BOOST_ASIO_MOVE_ARG(WriteHandler) handler) ++ { ++ return async_initiate( ++ initiate_async_send(), handler, this, ++ buffers, socket_base::message_flags(0)); ++ } ++ ++ /// Start an asynchronous send on a connected socket. ++ /** ++ * This function is used to asynchronously send data on the datagram socket. ++ * The function call always returns immediately. ++ * ++ * @param buffers One or more data buffers to be sent on the socket. Although ++ * the buffers object may be copied as necessary, ownership of the underlying ++ * memory blocks is retained by the caller, which must guarantee that they ++ * remain valid until the handler is called. ++ * ++ * @param flags Flags specifying how the send call is to be made. ++ * ++ * @param handler The handler to be called when the send operation completes. ++ * Copies will be made of the handler as required. The function signature of ++ * the handler must be: ++ * @code void handler( ++ * const boost::system::error_code& error, // Result of operation. ++ * std::size_t bytes_transferred // Number of bytes sent. ++ * ); @endcode ++ * Regardless of whether the asynchronous operation completes immediately or ++ * not, the handler will not be invoked from within this function. On ++ * immediate completion, invocation of the handler will be performed in a ++ * manner equivalent to using boost::asio::post(). ++ * ++ * @note The async_send operation can only be used with a connected socket. ++ * Use the async_send_to function to send data on an unconnected datagram ++ * socket. ++ */ ++ template ++ BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler, ++ void (boost::system::error_code, std::size_t)) ++ async_send(const ConstBufferSequence& buffers, ++ socket_base::message_flags flags, ++ BOOST_ASIO_MOVE_ARG(WriteHandler) handler) ++ { ++ return async_initiate( ++ initiate_async_send(), handler, this, buffers, flags); ++ } ++ ++ /// Send a datagram to the specified endpoint. ++ /** ++ * This function is used to send a datagram to the specified remote endpoint. ++ * The function call will block until the data has been sent successfully or ++ * an error occurs. ++ * ++ * @param buffers One or more data buffers to be sent to the remote endpoint. ++ * ++ * @param destination The remote endpoint to which the data will be sent. ++ * ++ * @returns The number of bytes sent. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ * ++ * @par Example ++ * To send a single data buffer use the @ref buffer function as follows: ++ * @code ++ * boost::asio::ip::udp::endpoint destination( ++ * boost::asio::ip::address::from_string("1.2.3.4"), 12345); ++ * socket.send_to(boost::asio::buffer(data, size), destination); ++ * @endcode ++ * See the @ref buffer documentation for information on sending multiple ++ * buffers in one go, and how to use it with arrays, boost::array or ++ * std::vector. ++ */ ++ template ++ std::size_t send_to(const ConstBufferSequence& buffers, ++ const endpoint_type& destination) ++ { ++ boost::system::error_code ec; ++ std::size_t s = this->impl_.get_service().send_to( ++ this->impl_.get_implementation(), buffers, destination, 0, ec); ++ boost::asio::detail::throw_error(ec, "send_to"); ++ return s; ++ } ++ ++ /// Send a datagram to the specified endpoint. ++ /** ++ * This function is used to send a datagram to the specified remote endpoint. ++ * The function call will block until the data has been sent successfully or ++ * an error occurs. ++ * ++ * @param buffers One or more data buffers to be sent to the remote endpoint. ++ * ++ * @param destination The remote endpoint to which the data will be sent. ++ * ++ * @param flags Flags specifying how the send call is to be made. ++ * ++ * @returns The number of bytes sent. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ */ ++ template ++ std::size_t send_to(const ConstBufferSequence& buffers, ++ const endpoint_type& destination, socket_base::message_flags flags) ++ { ++ boost::system::error_code ec; ++ std::size_t s = this->impl_.get_service().send_to( ++ this->impl_.get_implementation(), buffers, destination, flags, ec); ++ boost::asio::detail::throw_error(ec, "send_to"); ++ return s; ++ } ++ ++ /// Send a datagram to the specified endpoint. ++ /** ++ * This function is used to send a datagram to the specified remote endpoint. ++ * The function call will block until the data has been sent successfully or ++ * an error occurs. ++ * ++ * @param buffers One or more data buffers to be sent to the remote endpoint. ++ * ++ * @param destination The remote endpoint to which the data will be sent. ++ * ++ * @param flags Flags specifying how the send call is to be made. ++ * ++ * @param ec Set to indicate what error occurred, if any. ++ * ++ * @returns The number of bytes sent. ++ */ ++ template ++ std::size_t send_to(const ConstBufferSequence& buffers, ++ const endpoint_type& destination, socket_base::message_flags flags, ++ boost::system::error_code& ec) ++ { ++ return this->impl_.get_service().send_to(this->impl_.get_implementation(), ++ buffers, destination, flags, ec); ++ } ++ ++ /// Start an asynchronous send. ++ /** ++ * This function is used to asynchronously send a datagram to the specified ++ * remote endpoint. The function call always returns immediately. ++ * ++ * @param buffers One or more data buffers to be sent to the remote endpoint. ++ * Although the buffers object may be copied as necessary, ownership of the ++ * underlying memory blocks is retained by the caller, which must guarantee ++ * that they remain valid until the handler is called. ++ * ++ * @param destination The remote endpoint to which the data will be sent. ++ * Copies will be made of the endpoint as required. ++ * ++ * @param handler The handler to be called when the send operation completes. ++ * Copies will be made of the handler as required. The function signature of ++ * the handler must be: ++ * @code void handler( ++ * const boost::system::error_code& error, // Result of operation. ++ * std::size_t bytes_transferred // Number of bytes sent. ++ * ); @endcode ++ * Regardless of whether the asynchronous operation completes immediately or ++ * not, the handler will not be invoked from within this function. On ++ * immediate completion, invocation of the handler will be performed in a ++ * manner equivalent to using boost::asio::post(). ++ * ++ * @par Example ++ * To send a single data buffer use the @ref buffer function as follows: ++ * @code ++ * boost::asio::ip::udp::endpoint destination( ++ * boost::asio::ip::address::from_string("1.2.3.4"), 12345); ++ * socket.async_send_to( ++ * boost::asio::buffer(data, size), destination, handler); ++ * @endcode ++ * See the @ref buffer documentation for information on sending multiple ++ * buffers in one go, and how to use it with arrays, boost::array or ++ * std::vector. ++ */ ++ template ++ BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler, ++ void (boost::system::error_code, std::size_t)) ++ async_send_to(const ConstBufferSequence& buffers, ++ const endpoint_type& destination, ++ BOOST_ASIO_MOVE_ARG(WriteHandler) handler) ++ { ++ return async_initiate( ++ initiate_async_send_to(), handler, this, buffers, ++ destination, socket_base::message_flags(0)); ++ } ++ ++ /// Start an asynchronous send. ++ /** ++ * This function is used to asynchronously send a datagram to the specified ++ * remote endpoint. The function call always returns immediately. ++ * ++ * @param buffers One or more data buffers to be sent to the remote endpoint. ++ * Although the buffers object may be copied as necessary, ownership of the ++ * underlying memory blocks is retained by the caller, which must guarantee ++ * that they remain valid until the handler is called. ++ * ++ * @param flags Flags specifying how the send call is to be made. ++ * ++ * @param destination The remote endpoint to which the data will be sent. ++ * Copies will be made of the endpoint as required. ++ * ++ * @param handler The handler to be called when the send operation completes. ++ * Copies will be made of the handler as required. The function signature of ++ * the handler must be: ++ * @code void handler( ++ * const boost::system::error_code& error, // Result of operation. ++ * std::size_t bytes_transferred // Number of bytes sent. ++ * ); @endcode ++ * Regardless of whether the asynchronous operation completes immediately or ++ * not, the handler will not be invoked from within this function. On ++ * immediate completion, invocation of the handler will be performed in a ++ * manner equivalent to using boost::asio::post(). ++ */ ++ template ++ BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler, ++ void (boost::system::error_code, std::size_t)) ++ async_send_to(const ConstBufferSequence& buffers, ++ const endpoint_type& destination, socket_base::message_flags flags, ++ BOOST_ASIO_MOVE_ARG(WriteHandler) handler) ++ { ++ return async_initiate( ++ initiate_async_send_to(), handler, this, buffers, destination, flags); ++ } ++ ++ /// Receive some data on a connected socket. ++ /** ++ * This function is used to receive data on the datagram socket. The function ++ * call will block until data has been received successfully or an error ++ * occurs. ++ * ++ * @param buffers One or more buffers into which the data will be received. ++ * ++ * @returns The number of bytes received. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ * ++ * @note The receive operation can only be used with a connected socket. Use ++ * the receive_from function to receive data on an unconnected datagram ++ * socket. ++ * ++ * @par Example ++ * To receive into a single data buffer use the @ref buffer function as ++ * follows: ++ * @code socket.receive(boost::asio::buffer(data, size)); @endcode ++ * See the @ref buffer documentation for information on receiving into ++ * multiple buffers in one go, and how to use it with arrays, boost::array or ++ * std::vector. ++ */ ++ template ++ std::size_t receive(const MutableBufferSequence& buffers) ++ { ++ boost::system::error_code ec; ++ std::size_t s = this->impl_.get_service().receive( ++ this->impl_.get_implementation(), buffers, 0, ec); ++ boost::asio::detail::throw_error(ec, "receive"); ++ return s; ++ } ++ ++ /// Receive some data on a connected socket. ++ /** ++ * This function is used to receive data on the datagram socket. The function ++ * call will block until data has been received successfully or an error ++ * occurs. ++ * ++ * @param buffers One or more buffers into which the data will be received. ++ * ++ * @param flags Flags specifying how the receive call is to be made. ++ * ++ * @returns The number of bytes received. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ * ++ * @note The receive operation can only be used with a connected socket. Use ++ * the receive_from function to receive data on an unconnected datagram ++ * socket. ++ */ ++ template ++ std::size_t receive(const MutableBufferSequence& buffers, ++ socket_base::message_flags flags) ++ { ++ boost::system::error_code ec; ++ std::size_t s = this->impl_.get_service().receive( ++ this->impl_.get_implementation(), buffers, flags, ec); ++ boost::asio::detail::throw_error(ec, "receive"); ++ return s; ++ } ++ ++ /// Receive some data on a connected socket. ++ /** ++ * This function is used to receive data on the datagram socket. The function ++ * call will block until data has been received successfully or an error ++ * occurs. ++ * ++ * @param buffers One or more buffers into which the data will be received. ++ * ++ * @param flags Flags specifying how the receive call is to be made. ++ * ++ * @param ec Set to indicate what error occurred, if any. ++ * ++ * @returns The number of bytes received. ++ * ++ * @note The receive operation can only be used with a connected socket. Use ++ * the receive_from function to receive data on an unconnected datagram ++ * socket. ++ */ ++ template ++ std::size_t receive(const MutableBufferSequence& buffers, ++ socket_base::message_flags flags, boost::system::error_code& ec) ++ { ++ return this->impl_.get_service().receive( ++ this->impl_.get_implementation(), buffers, flags, ec); ++ } ++ ++ /// Start an asynchronous receive on a connected socket. ++ /** ++ * This function is used to asynchronously receive data from the datagram ++ * socket. The function call always returns immediately. ++ * ++ * @param buffers One or more buffers into which the data will be received. ++ * Although the buffers object may be copied as necessary, ownership of the ++ * underlying memory blocks is retained by the caller, which must guarantee ++ * that they remain valid until the handler is called. ++ * ++ * @param handler The handler to be called when the receive operation ++ * completes. Copies will be made of the handler as required. The function ++ * signature of the handler must be: ++ * @code void handler( ++ * const boost::system::error_code& error, // Result of operation. ++ * std::size_t bytes_transferred // Number of bytes received. ++ * ); @endcode ++ * Regardless of whether the asynchronous operation completes immediately or ++ * not, the handler will not be invoked from within this function. On ++ * immediate completion, invocation of the handler will be performed in a ++ * manner equivalent to using boost::asio::post(). ++ * ++ * @note The async_receive operation can only be used with a connected socket. ++ * Use the async_receive_from function to receive data on an unconnected ++ * datagram socket. ++ * ++ * @par Example ++ * To receive into a single data buffer use the @ref buffer function as ++ * follows: ++ * @code ++ * socket.async_receive(boost::asio::buffer(data, size), handler); ++ * @endcode ++ * See the @ref buffer documentation for information on receiving into ++ * multiple buffers in one go, and how to use it with arrays, boost::array or ++ * std::vector. ++ */ ++ template ++ BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler, ++ void (boost::system::error_code, std::size_t, boost::asio::ip::address)) ++ async_receive(const MutableBufferSequence& buffers, ++ BOOST_ASIO_MOVE_ARG(ReadHandler) handler) ++ { ++ return async_initiate( ++ initiate_async_receive(), handler, this, ++ buffers, socket_base::message_flags(0)); ++ } ++ ++ /// Start an asynchronous receive on a connected socket. ++ /** ++ * This function is used to asynchronously receive data from the datagram ++ * socket. The function call always returns immediately. ++ * ++ * @param buffers One or more buffers into which the data will be received. ++ * Although the buffers object may be copied as necessary, ownership of the ++ * underlying memory blocks is retained by the caller, which must guarantee ++ * that they remain valid until the handler is called. ++ * ++ * @param flags Flags specifying how the receive call is to be made. ++ * ++ * @param handler The handler to be called when the receive operation ++ * completes. Copies will be made of the handler as required. The function ++ * signature of the handler must be: ++ * @code void handler( ++ * const boost::system::error_code& error, // Result of operation. ++ * std::size_t bytes_transferred // Number of bytes received. ++ * ); @endcode ++ * Regardless of whether the asynchronous operation completes immediately or ++ * not, the handler will not be invoked from within this function. On ++ * immediate completion, invocation of the handler will be performed in a ++ * manner equivalent to using boost::asio::post(). ++ * ++ * @note The async_receive operation can only be used with a connected socket. ++ * Use the async_receive_from function to receive data on an unconnected ++ * datagram socket. ++ */ ++ template ++ BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler, ++ void (boost::system::error_code, std::size_t, boost::asio::ip::address)) ++ async_receive(const MutableBufferSequence& buffers, ++ socket_base::message_flags flags, ++ BOOST_ASIO_MOVE_ARG(ReadHandler) handler) ++ { ++ return async_initiate( ++ initiate_async_receive(), handler, this, buffers, flags); ++ } ++ ++ /// Receive a datagram with the endpoint of the sender. ++ /** ++ * This function is used to receive a datagram. The function call will block ++ * until data has been received successfully or an error occurs. ++ * ++ * @param buffers One or more buffers into which the data will be received. ++ * ++ * @param sender_endpoint An endpoint object that receives the endpoint of ++ * the remote sender of the datagram. ++ * ++ * @returns The number of bytes received. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ * ++ * @par Example ++ * To receive into a single data buffer use the @ref buffer function as ++ * follows: ++ * @code ++ * boost::asio::ip::udp::endpoint sender_endpoint; ++ * socket.receive_from( ++ * boost::asio::buffer(data, size), sender_endpoint); ++ * @endcode ++ * See the @ref buffer documentation for information on receiving into ++ * multiple buffers in one go, and how to use it with arrays, boost::array or ++ * std::vector. ++ */ ++ template ++ std::size_t receive_from(const MutableBufferSequence& buffers, ++ endpoint_type& sender_endpoint) ++ { ++ boost::system::error_code ec; ++ std::size_t s = this->impl_.get_service().receive_from( ++ this->impl_.get_implementation(), buffers, sender_endpoint, 0, ec); ++ boost::asio::detail::throw_error(ec, "receive_from"); ++ return s; ++ } ++ ++ /// Receive a datagram with the endpoint of the sender. ++ /** ++ * This function is used to receive a datagram. The function call will block ++ * until data has been received successfully or an error occurs. ++ * ++ * @param buffers One or more buffers into which the data will be received. ++ * ++ * @param sender_endpoint An endpoint object that receives the endpoint of ++ * the remote sender of the datagram. ++ * ++ * @param flags Flags specifying how the receive call is to be made. ++ * ++ * @returns The number of bytes received. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ */ ++ template ++ std::size_t receive_from(const MutableBufferSequence& buffers, ++ endpoint_type& sender_endpoint, socket_base::message_flags flags) ++ { ++ boost::system::error_code ec; ++ std::size_t s = this->impl_.get_service().receive_from( ++ this->impl_.get_implementation(), buffers, sender_endpoint, flags, ec); ++ boost::asio::detail::throw_error(ec, "receive_from"); ++ return s; ++ } ++ ++ /// Receive a datagram with the endpoint of the sender. ++ /** ++ * This function is used to receive a datagram. The function call will block ++ * until data has been received successfully or an error occurs. ++ * ++ * @param buffers One or more buffers into which the data will be received. ++ * ++ * @param sender_endpoint An endpoint object that receives the endpoint of ++ * the remote sender of the datagram. ++ * ++ * @param flags Flags specifying how the receive call is to be made. ++ * ++ * @param ec Set to indicate what error occurred, if any. ++ * ++ * @returns The number of bytes received. ++ */ ++ template ++ std::size_t receive_from(const MutableBufferSequence& buffers, ++ endpoint_type& sender_endpoint, socket_base::message_flags flags, ++ boost::system::error_code& ec) ++ { ++ return this->impl_.get_service().receive_from( ++ this->impl_.get_implementation(), buffers, sender_endpoint, flags, ec); ++ } ++ ++ /// Start an asynchronous receive. ++ /** ++ * This function is used to asynchronously receive a datagram. The function ++ * call always returns immediately. ++ * ++ * @param buffers One or more buffers into which the data will be received. ++ * Although the buffers object may be copied as necessary, ownership of the ++ * underlying memory blocks is retained by the caller, which must guarantee ++ * that they remain valid until the handler is called. ++ * ++ * @param sender_endpoint An endpoint object that receives the endpoint of ++ * the remote sender of the datagram. Ownership of the sender_endpoint object ++ * is retained by the caller, which must guarantee that it is valid until the ++ * handler is called. ++ * ++ * @param handler The handler to be called when the receive operation ++ * completes. Copies will be made of the handler as required. The function ++ * signature of the handler must be: ++ * @code void handler( ++ * const boost::system::error_code& error, // Result of operation. ++ * std::size_t bytes_transferred // Number of bytes received. ++ * ); @endcode ++ * Regardless of whether the asynchronous operation completes immediately or ++ * not, the handler will not be invoked from within this function. On ++ * immediate completion, invocation of the handler will be performed in a ++ * manner equivalent to using boost::asio::post(). ++ * ++ * @par Example ++ * To receive into a single data buffer use the @ref buffer function as ++ * follows: ++ * @code socket.async_receive_from( ++ * boost::asio::buffer(data, size), sender_endpoint, handler); @endcode ++ * See the @ref buffer documentation for information on receiving into ++ * multiple buffers in one go, and how to use it with arrays, boost::array or ++ * std::vector. ++ */ ++ template ++ BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler, ++ void (boost::system::error_code, std::size_t, boost::asio::ip::address)) ++ async_receive_from(const MutableBufferSequence& buffers, ++ endpoint_type& sender_endpoint, ++ BOOST_ASIO_MOVE_ARG(ReadHandler) handler) ++ { ++ return async_initiate( ++ initiate_async_receive_from(), handler, this, buffers, ++ &sender_endpoint, socket_base::message_flags(0)); ++ } ++ ++ /// Start an asynchronous receive. ++ /** ++ * This function is used to asynchronously receive a datagram. The function ++ * call always returns immediately. ++ * ++ * @param buffers One or more buffers into which the data will be received. ++ * Although the buffers object may be copied as necessary, ownership of the ++ * underlying memory blocks is retained by the caller, which must guarantee ++ * that they remain valid until the handler is called. ++ * ++ * @param sender_endpoint An endpoint object that receives the endpoint of ++ * the remote sender of the datagram. Ownership of the sender_endpoint object ++ * is retained by the caller, which must guarantee that it is valid until the ++ * handler is called. ++ * ++ * @param flags Flags specifying how the receive call is to be made. ++ * ++ * @param handler The handler to be called when the receive operation ++ * completes. Copies will be made of the handler as required. The function ++ * signature of the handler must be: ++ * @code void handler( ++ * const boost::system::error_code& error, // Result of operation. ++ * std::size_t bytes_transferred // Number of bytes received. ++ * ); @endcode ++ * Regardless of whether the asynchronous operation completes immediately or ++ * not, the handler will not be invoked from within this function. On ++ * immediate completion, invocation of the handler will be performed in a ++ * manner equivalent to using boost::asio::post(). ++ */ ++ template ++ BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler, ++ void (boost::system::error_code, std::size_t, boost::asio::ip::address)) ++ async_receive_from(const MutableBufferSequence& buffers, ++ endpoint_type& sender_endpoint, socket_base::message_flags flags, ++ BOOST_ASIO_MOVE_ARG(ReadHandler) handler) ++ { ++ return async_initiate( ++ initiate_async_receive_from(), handler, ++ this, buffers, &sender_endpoint, flags); ++ } ++ ++private: ++ struct initiate_async_send ++ { ++ template ++ void operator()(BOOST_ASIO_MOVE_ARG(WriteHandler) handler, ++ basic_datagram_socket_ext* self, const ConstBufferSequence& buffers, ++ socket_base::message_flags flags) const ++ { ++ // If you get an error on the following line it means that your handler ++ // does not meet the documented type requirements for a WriteHandler. ++ BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check; ++ ++ detail::non_const_lvalue handler2(handler); ++ self->impl_.get_service().async_send( ++ self->impl_.get_implementation(), buffers, flags, ++ handler2.value, self->impl_.get_executor()); ++ } ++ }; ++ ++ struct initiate_async_send_to ++ { ++ template ++ void operator()(BOOST_ASIO_MOVE_ARG(WriteHandler) handler, ++ basic_datagram_socket_ext* self, const ConstBufferSequence& buffers, ++ const endpoint_type& destination, ++ socket_base::message_flags flags) const ++ { ++ // If you get an error on the following line it means that your handler ++ // does not meet the documented type requirements for a WriteHandler. ++ BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check; ++ ++ detail::non_const_lvalue handler2(handler); ++ self->impl_.get_service().async_send_to( ++ self->impl_.get_implementation(), buffers, destination, flags, ++ handler2.value, self->impl_.get_executor()); ++ } ++ }; ++ ++ struct initiate_async_receive ++ { ++ template ++ void operator()(BOOST_ASIO_MOVE_ARG(ReadHandler) handler, ++ basic_datagram_socket_ext* self, const MutableBufferSequence& buffers, ++ socket_base::message_flags flags) const ++ { ++ // If you get an error on the following line it means that your handler ++ // does not meet the documented type requirements for a ReadHandler. ++ BOOST_ASIO_READ_HANDLER_CHECK_EXT(ReadHandler, handler) type_check; ++ ++ detail::non_const_lvalue handler2(handler); ++ self->impl_.get_service().async_receive( ++ self->impl_.get_implementation(), buffers, flags, ++ handler2.value, self->impl_.get_executor()); ++ } ++ }; ++ ++ struct initiate_async_receive_from ++ { ++ template ++ void operator()(BOOST_ASIO_MOVE_ARG(ReadHandler) handler, ++ basic_datagram_socket_ext* self, const MutableBufferSequence& buffers, ++ endpoint_type* sender_endpoint, socket_base::message_flags flags) const ++ { ++ // If you get an error on the following line it means that your handler ++ // does not meet the documented type requirements for a ReadHandler. ++ BOOST_ASIO_READ_HANDLER_CHECK_EXT(ReadHandler, handler) type_check; ++ ++ detail::non_const_lvalue handler2(handler); ++ self->impl_.get_service().async_receive_from( ++ self->impl_.get_implementation(), buffers, *sender_endpoint, flags, ++ handler2.value, self->impl_.get_executor()); ++ } ++ }; ++}; ++ ++} // namespace asio ++} // namespace boost ++ ++#include ++ ++#endif // BOOST_ASIO_BASIC_DATAGRAM_SOCKET_EXT_HPP +diff --git a/implementation/helper/1.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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#if defined(BOOST_ASIO_WINDOWS_RUNTIME) ++# include ++#elif defined(BOOST_ASIO_HAS_IOCP) ++# include ++#else ++# include ++#endif ++ ++#if defined(BOOST_ASIO_HAS_MOVE) ++# include ++#endif // defined(BOOST_ASIO_HAS_MOVE) ++ ++#include ++ ++namespace boost { ++namespace asio { ++ ++#if !defined(BOOST_ASIO_BASIC_SOCKET_ACCEPTOR_EXT_FWD_DECL) ++#define BOOST_ASIO_BASIC_SOCKET_ACCEPTOR_EXT_FWD_DECL ++ ++// Forward declaration with defaulted arguments. ++template ++class basic_socket_acceptor_ext; ++ ++#endif // !defined(BOOST_ASIO_BASIC_SOCKET_ACCEPTOR_EXT_FWD_DECL) ++ ++/// Provides the ability to accept new connections. ++/** ++ * The basic_socket_acceptor_ext class template is used for accepting new socket ++ * connections. ++ * ++ * @par Thread Safety ++ * @e Distinct @e objects: Safe.@n ++ * @e Shared @e objects: Unsafe. ++ * ++ * @par Example ++ * Opening a socket acceptor with the SO_REUSEADDR option enabled: ++ * @code ++ * boost::asio::ip::tcp::acceptor acceptor(my_context); ++ * boost::asio::ip::tcp::endpoint endpoint(boost::asio::ip::tcp::v4(), port); ++ * acceptor.open(endpoint.protocol()); ++ * acceptor.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true)); ++ * acceptor.bind(endpoint); ++ * acceptor.listen(); ++ * @endcode ++ */ ++template ++class basic_socket_acceptor_ext ++ : public socket_base ++{ ++public: ++ /// The type of the executor associated with the object. ++ typedef Executor executor_type; ++ ++ /// The native representation of an acceptor. ++#if defined(GENERATING_DOCUMENTATION) ++ typedef implementation_defined native_handle_type; ++#elif defined(BOOST_ASIO_WINDOWS_RUNTIME) ++ typedef typename detail::null_socket_service< ++ Protocol>::native_handle_type native_handle_type; ++#elif defined(BOOST_ASIO_HAS_IOCP) ++ typedef typename detail::win_iocp_socket_service< ++ Protocol>::native_handle_type native_handle_type; ++#else ++ typedef typename detail::reactive_socket_service_ext_local< ++ Protocol>::native_handle_type native_handle_type; ++#endif ++ ++ /// The protocol type. ++ typedef Protocol protocol_type; ++ ++ /// The endpoint type. ++ typedef typename Protocol::endpoint endpoint_type; ++ ++ /// Construct an acceptor without opening it. ++ /** ++ * This constructor creates an acceptor without opening it to listen for new ++ * connections. The open() function must be called before the acceptor can ++ * accept new socket connections. ++ * ++ * @param ex The I/O executor that the acceptor will use, by default, to ++ * dispatch handlers for any asynchronous operations performed on the ++ * acceptor. ++ */ ++ explicit basic_socket_acceptor_ext(const executor_type& ex) ++ : impl_(0, ex) ++ { ++ } ++ ++ /// Construct an acceptor without opening it. ++ /** ++ * This constructor creates an acceptor without opening it to listen for new ++ * connections. The open() function must be called before the acceptor can ++ * accept new socket connections. ++ * ++ * @param context An execution context which provides the I/O executor that ++ * the acceptor will use, by default, to dispatch handlers for any ++ * asynchronous operations performed on the acceptor. ++ */ ++ template ++ explicit basic_socket_acceptor_ext(ExecutionContext& context, ++ typename enable_if< ++ is_convertible::value ++ >::type* = 0) ++ : impl_(0, 0, context) ++ { ++ } ++ ++ /// Construct an open acceptor. ++ /** ++ * This constructor creates an acceptor and automatically opens it. ++ * ++ * @param ex The I/O executor that the acceptor will use, by default, to ++ * dispatch handlers for any asynchronous operations performed on the ++ * acceptor. ++ * ++ * @param protocol An object specifying protocol parameters to be used. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ */ ++ basic_socket_acceptor_ext(const executor_type& ex, const protocol_type& protocol) ++ : impl_(0, ex) ++ { ++ boost::system::error_code ec; ++ impl_.get_service().open(impl_.get_implementation(), protocol, ec); ++ boost::asio::detail::throw_error(ec, "open"); ++ } ++ ++ /// Construct an open acceptor. ++ /** ++ * This constructor creates an acceptor and automatically opens it. ++ * ++ * @param context An execution context which provides the I/O executor that ++ * the acceptor will use, by default, to dispatch handlers for any ++ * asynchronous operations performed on the acceptor. ++ * ++ * @param protocol An object specifying protocol parameters to be used. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ */ ++ template ++ basic_socket_acceptor_ext(ExecutionContext& context, ++ const protocol_type& protocol, ++ typename enable_if< ++ is_convertible::value ++ >::type* = 0) ++ : impl_(0, 0, context) ++ { ++ boost::system::error_code ec; ++ impl_.get_service().open(impl_.get_implementation(), protocol, ec); ++ boost::asio::detail::throw_error(ec, "open"); ++ } ++ ++ /// Construct an acceptor opened on the given endpoint. ++ /** ++ * This constructor creates an acceptor and automatically opens it to listen ++ * for new connections on the specified endpoint. ++ * ++ * @param ex The I/O executor that the acceptor will use, by default, to ++ * dispatch handlers for any asynchronous operations performed on the ++ * acceptor. ++ * ++ * @param endpoint An endpoint on the local machine on which the acceptor ++ * will listen for new connections. ++ * ++ * @param reuse_addr Whether the constructor should set the socket option ++ * socket_base::reuse_address. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ * ++ * @note This constructor is equivalent to the following code: ++ * @code ++ * basic_socket_acceptor acceptor(my_context); ++ * acceptor.open(endpoint.protocol()); ++ * if (reuse_addr) ++ * acceptor.set_option(socket_base::reuse_address(true)); ++ * acceptor.bind(endpoint); ++ * acceptor.listen(); ++ * @endcode ++ */ ++ basic_socket_acceptor_ext(const executor_type& ex, ++ const endpoint_type& endpoint, bool reuse_addr = true) ++ : impl_(0, ex) ++ { ++ boost::system::error_code ec; ++ const protocol_type protocol = endpoint.protocol(); ++ impl_.get_service().open(impl_.get_implementation(), protocol, ec); ++ boost::asio::detail::throw_error(ec, "open"); ++ if (reuse_addr) ++ { ++ impl_.get_service().set_option(impl_.get_implementation(), ++ socket_base::reuse_address(true), ec); ++ boost::asio::detail::throw_error(ec, "set_option"); ++ } ++ impl_.get_service().bind(impl_.get_implementation(), endpoint, ec); ++ boost::asio::detail::throw_error(ec, "bind"); ++ impl_.get_service().listen(impl_.get_implementation(), ++ socket_base::max_listen_connections, ec); ++ boost::asio::detail::throw_error(ec, "listen"); ++ } ++ ++ /// Construct an acceptor opened on the given endpoint. ++ /** ++ * This constructor creates an acceptor and automatically opens it to listen ++ * for new connections on the specified endpoint. ++ * ++ * @param context An execution context which provides the I/O executor that ++ * the acceptor will use, by default, to dispatch handlers for any ++ * asynchronous operations performed on the acceptor. ++ * ++ * @param endpoint An endpoint on the local machine on which the acceptor ++ * will listen for new connections. ++ * ++ * @param reuse_addr Whether the constructor should set the socket option ++ * socket_base::reuse_address. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ * ++ * @note This constructor is equivalent to the following code: ++ * @code ++ * basic_socket_acceptor acceptor(my_context); ++ * acceptor.open(endpoint.protocol()); ++ * if (reuse_addr) ++ * acceptor.set_option(socket_base::reuse_address(true)); ++ * acceptor.bind(endpoint); ++ * acceptor.listen(); ++ * @endcode ++ */ ++ template ++ basic_socket_acceptor_ext(ExecutionContext& context, ++ const endpoint_type& endpoint, bool reuse_addr = true, ++ typename enable_if< ++ is_convertible::value ++ >::type* = 0) ++ : impl_(0, 0, context) ++ { ++ boost::system::error_code ec; ++ const protocol_type protocol = endpoint.protocol(); ++ impl_.get_service().open(impl_.get_implementation(), protocol, ec); ++ boost::asio::detail::throw_error(ec, "open"); ++ if (reuse_addr) ++ { ++ impl_.get_service().set_option(impl_.get_implementation(), ++ socket_base::reuse_address(true), ec); ++ boost::asio::detail::throw_error(ec, "set_option"); ++ } ++ impl_.get_service().bind(impl_.get_implementation(), endpoint, ec); ++ boost::asio::detail::throw_error(ec, "bind"); ++ impl_.get_service().listen(impl_.get_implementation(), ++ socket_base::max_listen_connections, ec); ++ boost::asio::detail::throw_error(ec, "listen"); ++ } ++ ++ /// Construct a basic_socket_acceptor on an existing native acceptor. ++ /** ++ * This constructor creates an acceptor object to hold an existing native ++ * acceptor. ++ * ++ * @param ex The I/O executor that the acceptor will use, by default, to ++ * dispatch handlers for any asynchronous operations performed on the ++ * acceptor. ++ * ++ * @param protocol An object specifying protocol parameters to be used. ++ * ++ * @param native_acceptor A native acceptor. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ */ ++ basic_socket_acceptor_ext(const executor_type& ex, ++ const protocol_type& protocol, const native_handle_type& native_acceptor) ++ : impl_(0, ex) ++ { ++ boost::system::error_code ec; ++ impl_.get_service().assign(impl_.get_implementation(), ++ protocol, native_acceptor, ec); ++ boost::asio::detail::throw_error(ec, "assign"); ++ } ++ ++ /// Construct a basic_socket_acceptor on an existing native acceptor. ++ /** ++ * This constructor creates an acceptor object to hold an existing native ++ * acceptor. ++ * ++ * @param context An execution context which provides the I/O executor that ++ * the acceptor will use, by default, to dispatch handlers for any ++ * asynchronous operations performed on the acceptor. ++ * ++ * @param protocol An object specifying protocol parameters to be used. ++ * ++ * @param native_acceptor A native acceptor. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ */ ++ template ++ basic_socket_acceptor_ext(ExecutionContext& context, ++ const protocol_type& protocol, const native_handle_type& native_acceptor, ++ typename enable_if< ++ is_convertible::value ++ >::type* = 0) ++ : impl_(0, 0, context) ++ { ++ boost::system::error_code ec; ++ impl_.get_service().assign(impl_.get_implementation(), ++ protocol, native_acceptor, ec); ++ boost::asio::detail::throw_error(ec, "assign"); ++ } ++ ++#if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) ++ /// Move-construct a basic_socket_acceptor from another. ++ /** ++ * This constructor moves an acceptor from one object to another. ++ * ++ * @param other The other basic_socket_acceptor object from which the move ++ * will occur. ++ * ++ * @note Following the move, the moved-from object is in the same state as if ++ * constructed using the @c basic_socket_acceptor(const executor_type&) ++ * constructor. ++ */ ++ basic_socket_acceptor_ext(basic_socket_acceptor_ext&& other) ++ : impl_(std::move(other.impl_)) ++ { ++ } ++ ++ /// Move-assign a basic_socket_acceptor from another. ++ /** ++ * This assignment operator moves an acceptor from one object to another. ++ * ++ * @param other The other basic_socket_acceptor object from which the move ++ * will occur. ++ * ++ * @note Following the move, the moved-from object is in the same state as if ++ * constructed using the @c basic_socket_acceptor(const executor_type&) ++ * constructor. ++ */ ++ basic_socket_acceptor_ext& operator=(basic_socket_acceptor_ext&& other) ++ { ++ impl_ = std::move(other.impl_); ++ return *this; ++ } ++ ++ // All socket acceptors have access to each other's implementations. ++ template ++ friend class basic_socket_acceptor_ext; ++ ++ /// Move-construct a basic_socket_acceptor from an acceptor of another ++ /// protocol type. ++ /** ++ * This constructor moves an acceptor from one object to another. ++ * ++ * @param other The other basic_socket_acceptor object from which the move ++ * will occur. ++ * ++ * @note Following the move, the moved-from object is in the same state as if ++ * constructed using the @c basic_socket_acceptor(const executor_type&) ++ * constructor. ++ */ ++ template ++ basic_socket_acceptor_ext(basic_socket_acceptor_ext&& other, ++ typename enable_if< ++ is_convertible::value ++ && is_convertible::value ++ >::type* = 0) ++ : impl_(std::move(other.impl_)) ++ { ++ } ++ ++ /// Move-assign a basic_socket_acceptor from an acceptor of another protocol ++ /// type. ++ /** ++ * This assignment operator moves an acceptor from one object to another. ++ * ++ * @param other The other basic_socket_acceptor object from which the move ++ * will occur. ++ * ++ * @note Following the move, the moved-from object is in the same state as if ++ * constructed using the @c basic_socket_acceptor(const executor_type&) ++ * constructor. ++ */ ++ template ++ typename enable_if< ++ is_convertible::value ++ && is_convertible::value, ++ basic_socket_acceptor_ext& ++ >::type operator=(basic_socket_acceptor_ext&& other) ++ { ++ basic_socket_acceptor_ext tmp(std::move(other)); ++ impl_ = std::move(tmp.impl_); ++ return *this; ++ } ++#endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) ++ ++ /// Destroys the acceptor. ++ /** ++ * This function destroys the acceptor, cancelling any outstanding ++ * asynchronous operations associated with the acceptor as if by calling ++ * @c cancel. ++ */ ++ ~basic_socket_acceptor_ext() ++ { ++ } ++ ++ /// Get the executor associated with the object. ++ executor_type get_executor() BOOST_ASIO_NOEXCEPT ++ { ++ return impl_.get_executor(); ++ } ++ ++ /// Open the acceptor using the specified protocol. ++ /** ++ * This function opens the socket acceptor so that it will use the specified ++ * protocol. ++ * ++ * @param protocol An object specifying which protocol is to be used. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ * ++ * @par Example ++ * @code ++ * boost::asio::ip::tcp::acceptor acceptor(my_context); ++ * acceptor.open(boost::asio::ip::tcp::v4()); ++ * @endcode ++ */ ++ void open(const protocol_type& protocol = protocol_type()) ++ { ++ boost::system::error_code ec; ++ impl_.get_service().open(impl_.get_implementation(), protocol, ec); ++ boost::asio::detail::throw_error(ec, "open"); ++ } ++ ++ /// Open the acceptor using the specified protocol. ++ /** ++ * This function opens the socket acceptor so that it will use the specified ++ * protocol. ++ * ++ * @param protocol An object specifying which protocol is to be used. ++ * ++ * @param ec Set to indicate what error occurred, if any. ++ * ++ * @par Example ++ * @code ++ * boost::asio::ip::tcp::acceptor acceptor(my_context); ++ * boost::system::error_code ec; ++ * acceptor.open(boost::asio::ip::tcp::v4(), ec); ++ * if (ec) ++ * { ++ * // An error occurred. ++ * } ++ * @endcode ++ */ ++ BOOST_ASIO_SYNC_OP_VOID open(const protocol_type& protocol, ++ boost::system::error_code& ec) ++ { ++ impl_.get_service().open(impl_.get_implementation(), protocol, ec); ++ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); ++ } ++ ++ /// Assigns an existing native acceptor to the acceptor. ++ /* ++ * This function opens the acceptor to hold an existing native acceptor. ++ * ++ * @param protocol An object specifying which protocol is to be used. ++ * ++ * @param native_acceptor A native acceptor. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ */ ++ void assign(const protocol_type& protocol, ++ const native_handle_type& native_acceptor) ++ { ++ boost::system::error_code ec; ++ impl_.get_service().assign(impl_.get_implementation(), ++ protocol, native_acceptor, ec); ++ boost::asio::detail::throw_error(ec, "assign"); ++ } ++ ++ /// Assigns an existing native acceptor to the acceptor. ++ /* ++ * This function opens the acceptor to hold an existing native acceptor. ++ * ++ * @param protocol An object specifying which protocol is to be used. ++ * ++ * @param native_acceptor A native acceptor. ++ * ++ * @param ec Set to indicate what error occurred, if any. ++ */ ++ BOOST_ASIO_SYNC_OP_VOID assign(const protocol_type& protocol, ++ const native_handle_type& native_acceptor, boost::system::error_code& ec) ++ { ++ impl_.get_service().assign(impl_.get_implementation(), ++ protocol, native_acceptor, ec); ++ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); ++ } ++ ++ /// Determine whether the acceptor is open. ++ bool is_open() const ++ { ++ return impl_.get_service().is_open(impl_.get_implementation()); ++ } ++ ++ /// Bind the acceptor to the given local endpoint. ++ /** ++ * This function binds the socket acceptor to the specified endpoint on the ++ * local machine. ++ * ++ * @param endpoint An endpoint on the local machine to which the socket ++ * acceptor will be bound. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ * ++ * @par Example ++ * @code ++ * boost::asio::ip::tcp::acceptor acceptor(my_context); ++ * boost::asio::ip::tcp::endpoint endpoint(boost::asio::ip::tcp::v4(), 12345); ++ * acceptor.open(endpoint.protocol()); ++ * acceptor.bind(endpoint); ++ * @endcode ++ */ ++ void bind(const endpoint_type& endpoint) ++ { ++ boost::system::error_code ec; ++ impl_.get_service().bind(impl_.get_implementation(), endpoint, ec); ++ boost::asio::detail::throw_error(ec, "bind"); ++ } ++ ++ /// Bind the acceptor to the given local endpoint. ++ /** ++ * This function binds the socket acceptor to the specified endpoint on the ++ * local machine. ++ * ++ * @param endpoint An endpoint on the local machine to which the socket ++ * acceptor will be bound. ++ * ++ * @param ec Set to indicate what error occurred, if any. ++ * ++ * @par Example ++ * @code ++ * boost::asio::ip::tcp::acceptor acceptor(my_context); ++ * boost::asio::ip::tcp::endpoint endpoint(boost::asio::ip::tcp::v4(), 12345); ++ * acceptor.open(endpoint.protocol()); ++ * boost::system::error_code ec; ++ * acceptor.bind(endpoint, ec); ++ * if (ec) ++ * { ++ * // An error occurred. ++ * } ++ * @endcode ++ */ ++ BOOST_ASIO_SYNC_OP_VOID bind(const endpoint_type& endpoint, ++ boost::system::error_code& ec) ++ { ++ impl_.get_service().bind(impl_.get_implementation(), endpoint, ec); ++ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); ++ } ++ ++ /// Place the acceptor into the state where it will listen for new ++ /// connections. ++ /** ++ * This function puts the socket acceptor into the state where it may accept ++ * new connections. ++ * ++ * @param backlog The maximum length of the queue of pending connections. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ */ ++ void listen(int backlog = socket_base::max_listen_connections) ++ { ++ boost::system::error_code ec; ++ impl_.get_service().listen(impl_.get_implementation(), backlog, ec); ++ boost::asio::detail::throw_error(ec, "listen"); ++ } ++ ++ /// Place the acceptor into the state where it will listen for new ++ /// connections. ++ /** ++ * This function puts the socket acceptor into the state where it may accept ++ * new connections. ++ * ++ * @param backlog The maximum length of the queue of pending connections. ++ * ++ * @param ec Set to indicate what error occurred, if any. ++ * ++ * @par Example ++ * @code ++ * boost::asio::ip::tcp::acceptor acceptor(my_context); ++ * ... ++ * boost::system::error_code ec; ++ * acceptor.listen(boost::asio::socket_base::max_listen_connections, ec); ++ * if (ec) ++ * { ++ * // An error occurred. ++ * } ++ * @endcode ++ */ ++ BOOST_ASIO_SYNC_OP_VOID listen(int backlog, boost::system::error_code& ec) ++ { ++ impl_.get_service().listen(impl_.get_implementation(), backlog, ec); ++ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); ++ } ++ ++ /// Close the acceptor. ++ /** ++ * This function is used to close the acceptor. Any asynchronous accept ++ * operations will be cancelled immediately. ++ * ++ * A subsequent call to open() is required before the acceptor can again be ++ * used to again perform socket accept operations. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ */ ++ void close() ++ { ++ boost::system::error_code ec; ++ impl_.get_service().close(impl_.get_implementation(), ec); ++ boost::asio::detail::throw_error(ec, "close"); ++ } ++ ++ /// Close the acceptor. ++ /** ++ * This function is used to close the acceptor. Any asynchronous accept ++ * operations will be cancelled immediately. ++ * ++ * A subsequent call to open() is required before the acceptor can again be ++ * used to again perform socket accept operations. ++ * ++ * @param ec Set to indicate what error occurred, if any. ++ * ++ * @par Example ++ * @code ++ * boost::asio::ip::tcp::acceptor acceptor(my_context); ++ * ... ++ * boost::system::error_code ec; ++ * acceptor.close(ec); ++ * if (ec) ++ * { ++ * // An error occurred. ++ * } ++ * @endcode ++ */ ++ BOOST_ASIO_SYNC_OP_VOID close(boost::system::error_code& ec) ++ { ++ impl_.get_service().close(impl_.get_implementation(), ec); ++ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); ++ } ++ ++ /// Release ownership of the underlying native acceptor. ++ /** ++ * This function causes all outstanding asynchronous accept operations to ++ * finish immediately, and the handlers for cancelled operations will be ++ * passed the boost::asio::error::operation_aborted error. Ownership of the ++ * native acceptor is then transferred to the caller. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ * ++ * @note This function is unsupported on Windows versions prior to Windows ++ * 8.1, and will fail with boost::asio::error::operation_not_supported on ++ * these platforms. ++ */ ++#if defined(BOOST_ASIO_MSVC) && (BOOST_ASIO_MSVC >= 1400) \ ++ && (!defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0603) ++ __declspec(deprecated("This function always fails with " ++ "operation_not_supported when used on Windows versions " ++ "prior to Windows 8.1.")) ++#endif ++ native_handle_type release() ++ { ++ boost::system::error_code ec; ++ native_handle_type s = impl_.get_service().release( ++ impl_.get_implementation(), ec); ++ boost::asio::detail::throw_error(ec, "release"); ++ return s; ++ } ++ ++ /// Release ownership of the underlying native acceptor. ++ /** ++ * This function causes all outstanding asynchronous accept operations to ++ * finish immediately, and the handlers for cancelled operations will be ++ * passed the boost::asio::error::operation_aborted error. Ownership of the ++ * native acceptor is then transferred to the caller. ++ * ++ * @param ec Set to indicate what error occurred, if any. ++ * ++ * @note This function is unsupported on Windows versions prior to Windows ++ * 8.1, and will fail with boost::asio::error::operation_not_supported on ++ * these platforms. ++ */ ++#if defined(BOOST_ASIO_MSVC) && (BOOST_ASIO_MSVC >= 1400) \ ++ && (!defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0603) ++ __declspec(deprecated("This function always fails with " ++ "operation_not_supported when used on Windows versions " ++ "prior to Windows 8.1.")) ++#endif ++ native_handle_type release(boost::system::error_code& ec) ++ { ++ return impl_.get_service().release(impl_.get_implementation(), ec); ++ } ++ ++ /// Get the native acceptor representation. ++ /** ++ * This function may be used to obtain the underlying representation of the ++ * acceptor. This is intended to allow access to native acceptor functionality ++ * that is not otherwise provided. ++ */ ++ native_handle_type native_handle() ++ { ++ return impl_.get_service().native_handle(impl_.get_implementation()); ++ } ++ ++ /// Cancel all asynchronous operations associated with the acceptor. ++ /** ++ * This function causes all outstanding asynchronous connect, send and receive ++ * operations to finish immediately, and the handlers for cancelled operations ++ * will be passed the boost::asio::error::operation_aborted error. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ */ ++ void cancel() ++ { ++ boost::system::error_code ec; ++ impl_.get_service().cancel(impl_.get_implementation(), ec); ++ boost::asio::detail::throw_error(ec, "cancel"); ++ } ++ ++ /// Cancel all asynchronous operations associated with the acceptor. ++ /** ++ * This function causes all outstanding asynchronous connect, send and receive ++ * operations to finish immediately, and the handlers for cancelled operations ++ * will be passed the boost::asio::error::operation_aborted error. ++ * ++ * @param ec Set to indicate what error occurred, if any. ++ */ ++ BOOST_ASIO_SYNC_OP_VOID cancel(boost::system::error_code& ec) ++ { ++ impl_.get_service().cancel(impl_.get_implementation(), ec); ++ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); ++ } ++ ++ /// Set an option on the acceptor. ++ /** ++ * This function is used to set an option on the acceptor. ++ * ++ * @param option The new option value to be set on the acceptor. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ * ++ * @sa SettableSocketOption @n ++ * boost::asio::socket_base::reuse_address ++ * boost::asio::socket_base::enable_connection_aborted ++ * ++ * @par Example ++ * Setting the SOL_SOCKET/SO_REUSEADDR option: ++ * @code ++ * boost::asio::ip::tcp::acceptor acceptor(my_context); ++ * ... ++ * boost::asio::ip::tcp::acceptor::reuse_address option(true); ++ * acceptor.set_option(option); ++ * @endcode ++ */ ++ template ++ void set_option(const SettableSocketOption& option) ++ { ++ boost::system::error_code ec; ++ impl_.get_service().set_option(impl_.get_implementation(), option, ec); ++ boost::asio::detail::throw_error(ec, "set_option"); ++ } ++ ++ /// Set an option on the acceptor. ++ /** ++ * This function is used to set an option on the acceptor. ++ * ++ * @param option The new option value to be set on the acceptor. ++ * ++ * @param ec Set to indicate what error occurred, if any. ++ * ++ * @sa SettableSocketOption @n ++ * boost::asio::socket_base::reuse_address ++ * boost::asio::socket_base::enable_connection_aborted ++ * ++ * @par Example ++ * Setting the SOL_SOCKET/SO_REUSEADDR option: ++ * @code ++ * boost::asio::ip::tcp::acceptor acceptor(my_context); ++ * ... ++ * boost::asio::ip::tcp::acceptor::reuse_address option(true); ++ * boost::system::error_code ec; ++ * acceptor.set_option(option, ec); ++ * if (ec) ++ * { ++ * // An error occurred. ++ * } ++ * @endcode ++ */ ++ template ++ BOOST_ASIO_SYNC_OP_VOID set_option(const SettableSocketOption& option, ++ boost::system::error_code& ec) ++ { ++ impl_.get_service().set_option(impl_.get_implementation(), option, ec); ++ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); ++ } ++ ++ /// Get an option from the acceptor. ++ /** ++ * This function is used to get the current value of an option on the ++ * acceptor. ++ * ++ * @param option The option value to be obtained from the acceptor. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ * ++ * @sa GettableSocketOption @n ++ * boost::asio::socket_base::reuse_address ++ * ++ * @par Example ++ * Getting the value of the SOL_SOCKET/SO_REUSEADDR option: ++ * @code ++ * boost::asio::ip::tcp::acceptor acceptor(my_context); ++ * ... ++ * boost::asio::ip::tcp::acceptor::reuse_address option; ++ * acceptor.get_option(option); ++ * bool is_set = option.get(); ++ * @endcode ++ */ ++ template ++ void get_option(GettableSocketOption& option) const ++ { ++ boost::system::error_code ec; ++ impl_.get_service().get_option(impl_.get_implementation(), option, ec); ++ boost::asio::detail::throw_error(ec, "get_option"); ++ } ++ ++ /// Get an option from the acceptor. ++ /** ++ * This function is used to get the current value of an option on the ++ * acceptor. ++ * ++ * @param option The option value to be obtained from the acceptor. ++ * ++ * @param ec Set to indicate what error occurred, if any. ++ * ++ * @sa GettableSocketOption @n ++ * boost::asio::socket_base::reuse_address ++ * ++ * @par Example ++ * Getting the value of the SOL_SOCKET/SO_REUSEADDR option: ++ * @code ++ * boost::asio::ip::tcp::acceptor acceptor(my_context); ++ * ... ++ * boost::asio::ip::tcp::acceptor::reuse_address option; ++ * boost::system::error_code ec; ++ * acceptor.get_option(option, ec); ++ * if (ec) ++ * { ++ * // An error occurred. ++ * } ++ * bool is_set = option.get(); ++ * @endcode ++ */ ++ template ++ BOOST_ASIO_SYNC_OP_VOID get_option(GettableSocketOption& option, ++ boost::system::error_code& ec) const ++ { ++ impl_.get_service().get_option(impl_.get_implementation(), option, ec); ++ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); ++ } ++ ++ /// Perform an IO control command on the acceptor. ++ /** ++ * This function is used to execute an IO control command on the acceptor. ++ * ++ * @param command The IO control command to be performed on the acceptor. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ * ++ * @sa IoControlCommand @n ++ * boost::asio::socket_base::non_blocking_io ++ * ++ * @par Example ++ * Getting the number of bytes ready to read: ++ * @code ++ * boost::asio::ip::tcp::acceptor acceptor(my_context); ++ * ... ++ * boost::asio::ip::tcp::acceptor::non_blocking_io command(true); ++ * socket.io_control(command); ++ * @endcode ++ */ ++ template ++ void io_control(IoControlCommand& command) ++ { ++ boost::system::error_code ec; ++ impl_.get_service().io_control(impl_.get_implementation(), command, ec); ++ boost::asio::detail::throw_error(ec, "io_control"); ++ } ++ ++ /// Perform an IO control command on the acceptor. ++ /** ++ * This function is used to execute an IO control command on the acceptor. ++ * ++ * @param command The IO control command to be performed on the acceptor. ++ * ++ * @param ec Set to indicate what error occurred, if any. ++ * ++ * @sa IoControlCommand @n ++ * boost::asio::socket_base::non_blocking_io ++ * ++ * @par Example ++ * Getting the number of bytes ready to read: ++ * @code ++ * boost::asio::ip::tcp::acceptor acceptor(my_context); ++ * ... ++ * boost::asio::ip::tcp::acceptor::non_blocking_io command(true); ++ * boost::system::error_code ec; ++ * socket.io_control(command, ec); ++ * if (ec) ++ * { ++ * // An error occurred. ++ * } ++ * @endcode ++ */ ++ template ++ BOOST_ASIO_SYNC_OP_VOID io_control(IoControlCommand& command, ++ boost::system::error_code& ec) ++ { ++ impl_.get_service().io_control(impl_.get_implementation(), command, ec); ++ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); ++ } ++ ++ /// Gets the non-blocking mode of the acceptor. ++ /** ++ * @returns @c true if the acceptor's synchronous operations will fail with ++ * boost::asio::error::would_block if they are unable to perform the requested ++ * operation immediately. If @c false, synchronous operations will block ++ * until complete. ++ * ++ * @note The non-blocking mode has no effect on the behaviour of asynchronous ++ * operations. Asynchronous operations will never fail with the error ++ * boost::asio::error::would_block. ++ */ ++ bool non_blocking() const ++ { ++ return impl_.get_service().non_blocking(impl_.get_implementation()); ++ } ++ ++ /// Sets the non-blocking mode of the acceptor. ++ /** ++ * @param mode If @c true, the acceptor's synchronous operations will fail ++ * with boost::asio::error::would_block if they are unable to perform the ++ * requested operation immediately. If @c false, synchronous operations will ++ * block until complete. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ * ++ * @note The non-blocking mode has no effect on the behaviour of asynchronous ++ * operations. Asynchronous operations will never fail with the error ++ * boost::asio::error::would_block. ++ */ ++ void non_blocking(bool mode) ++ { ++ boost::system::error_code ec; ++ impl_.get_service().non_blocking(impl_.get_implementation(), mode, ec); ++ boost::asio::detail::throw_error(ec, "non_blocking"); ++ } ++ ++ /// Sets the non-blocking mode of the acceptor. ++ /** ++ * @param mode If @c true, the acceptor's synchronous operations will fail ++ * with boost::asio::error::would_block if they are unable to perform the ++ * requested operation immediately. If @c false, synchronous operations will ++ * block until complete. ++ * ++ * @param ec Set to indicate what error occurred, if any. ++ * ++ * @note The non-blocking mode has no effect on the behaviour of asynchronous ++ * operations. Asynchronous operations will never fail with the error ++ * boost::asio::error::would_block. ++ */ ++ BOOST_ASIO_SYNC_OP_VOID non_blocking( ++ bool mode, boost::system::error_code& ec) ++ { ++ impl_.get_service().non_blocking(impl_.get_implementation(), mode, ec); ++ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); ++ } ++ ++ /// Gets the non-blocking mode of the native acceptor implementation. ++ /** ++ * This function is used to retrieve the non-blocking mode of the underlying ++ * native acceptor. This mode has no effect on the behaviour of the acceptor ++ * object's synchronous operations. ++ * ++ * @returns @c true if the underlying acceptor is in non-blocking mode and ++ * direct system calls may fail with boost::asio::error::would_block (or the ++ * equivalent system error). ++ * ++ * @note The current non-blocking mode is cached by the acceptor object. ++ * Consequently, the return value may be incorrect if the non-blocking mode ++ * was set directly on the native acceptor. ++ */ ++ bool native_non_blocking() const ++ { ++ return impl_.get_service().native_non_blocking(impl_.get_implementation()); ++ } ++ ++ /// Sets the non-blocking mode of the native acceptor implementation. ++ /** ++ * This function is used to modify the non-blocking mode of the underlying ++ * native acceptor. It has no effect on the behaviour of the acceptor object's ++ * synchronous operations. ++ * ++ * @param mode If @c true, the underlying acceptor is put into non-blocking ++ * mode and direct system calls may fail with boost::asio::error::would_block ++ * (or the equivalent system error). ++ * ++ * @throws boost::system::system_error Thrown on failure. If the @c mode is ++ * @c false, but the current value of @c non_blocking() is @c true, this ++ * function fails with boost::asio::error::invalid_argument, as the ++ * combination does not make sense. ++ */ ++ void native_non_blocking(bool mode) ++ { ++ boost::system::error_code ec; ++ impl_.get_service().native_non_blocking( ++ impl_.get_implementation(), mode, ec); ++ boost::asio::detail::throw_error(ec, "native_non_blocking"); ++ } ++ ++ /// Sets the non-blocking mode of the native acceptor implementation. ++ /** ++ * This function is used to modify the non-blocking mode of the underlying ++ * native acceptor. It has no effect on the behaviour of the acceptor object's ++ * synchronous operations. ++ * ++ * @param mode If @c true, the underlying acceptor is put into non-blocking ++ * mode and direct system calls may fail with boost::asio::error::would_block ++ * (or the equivalent system error). ++ * ++ * @param ec Set to indicate what error occurred, if any. If the @c mode is ++ * @c false, but the current value of @c non_blocking() is @c true, this ++ * function fails with boost::asio::error::invalid_argument, as the ++ * combination does not make sense. ++ */ ++ BOOST_ASIO_SYNC_OP_VOID native_non_blocking( ++ bool mode, boost::system::error_code& ec) ++ { ++ impl_.get_service().native_non_blocking( ++ impl_.get_implementation(), mode, ec); ++ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); ++ } ++ ++ /// Get the local endpoint of the acceptor. ++ /** ++ * This function is used to obtain the locally bound endpoint of the acceptor. ++ * ++ * @returns An object that represents the local endpoint of the acceptor. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ * ++ * @par Example ++ * @code ++ * boost::asio::ip::tcp::acceptor acceptor(my_context); ++ * ... ++ * boost::asio::ip::tcp::endpoint endpoint = acceptor.local_endpoint(); ++ * @endcode ++ */ ++ endpoint_type local_endpoint() const ++ { ++ boost::system::error_code ec; ++ endpoint_type ep = impl_.get_service().local_endpoint( ++ impl_.get_implementation(), ec); ++ boost::asio::detail::throw_error(ec, "local_endpoint"); ++ return ep; ++ } ++ ++ /// Get the local endpoint of the acceptor. ++ /** ++ * This function is used to obtain the locally bound endpoint of the acceptor. ++ * ++ * @param ec Set to indicate what error occurred, if any. ++ * ++ * @returns An object that represents the local endpoint of the acceptor. ++ * Returns a default-constructed endpoint object if an error occurred and the ++ * error handler did not throw an exception. ++ * ++ * @par Example ++ * @code ++ * boost::asio::ip::tcp::acceptor acceptor(my_context); ++ * ... ++ * boost::system::error_code ec; ++ * boost::asio::ip::tcp::endpoint endpoint = acceptor.local_endpoint(ec); ++ * if (ec) ++ * { ++ * // An error occurred. ++ * } ++ * @endcode ++ */ ++ endpoint_type local_endpoint(boost::system::error_code& ec) const ++ { ++ return impl_.get_service().local_endpoint(impl_.get_implementation(), ec); ++ } ++ ++ /// Wait for the acceptor to become ready to read, ready to write, or to have ++ /// pending error conditions. ++ /** ++ * This function is used to perform a blocking wait for an acceptor to enter ++ * a ready to read, write or error condition state. ++ * ++ * @param w Specifies the desired acceptor state. ++ * ++ * @par Example ++ * Waiting for an acceptor to become readable. ++ * @code ++ * boost::asio::ip::tcp::acceptor acceptor(my_context); ++ * ... ++ * acceptor.wait(boost::asio::ip::tcp::acceptor::wait_read); ++ * @endcode ++ */ ++ void wait(wait_type w) ++ { ++ boost::system::error_code ec; ++ impl_.get_service().wait(impl_.get_implementation(), w, ec); ++ boost::asio::detail::throw_error(ec, "wait"); ++ } ++ ++ /// Wait for the acceptor to become ready to read, ready to write, or to have ++ /// pending error conditions. ++ /** ++ * This function is used to perform a blocking wait for an acceptor to enter ++ * a ready to read, write or error condition state. ++ * ++ * @param w Specifies the desired acceptor state. ++ * ++ * @param ec Set to indicate what error occurred, if any. ++ * ++ * @par Example ++ * Waiting for an acceptor to become readable. ++ * @code ++ * boost::asio::ip::tcp::acceptor acceptor(my_context); ++ * ... ++ * boost::system::error_code ec; ++ * acceptor.wait(boost::asio::ip::tcp::acceptor::wait_read, ec); ++ * @endcode ++ */ ++ BOOST_ASIO_SYNC_OP_VOID wait(wait_type w, boost::system::error_code& ec) ++ { ++ impl_.get_service().wait(impl_.get_implementation(), w, ec); ++ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); ++ } ++ ++ /// Asynchronously wait for the acceptor to become ready to read, ready to ++ /// write, or to have pending error conditions. ++ /** ++ * This function is used to perform an asynchronous wait for an acceptor to ++ * enter a ready to read, write or error condition state. ++ * ++ * @param w Specifies the desired acceptor state. ++ * ++ * @param handler The handler to be called when the wait operation completes. ++ * Copies will be made of the handler as required. The function signature of ++ * the handler must be: ++ * @code void handler( ++ * const boost::system::error_code& error // Result of operation ++ * ); @endcode ++ * Regardless of whether the asynchronous operation completes immediately or ++ * not, the handler will not be invoked from within this function. On ++ * immediate completion, invocation of the handler will be performed in a ++ * manner equivalent to using boost::asio::post(). ++ * ++ * @par Example ++ * @code ++ * void wait_handler(const boost::system::error_code& error) ++ * { ++ * if (!error) ++ * { ++ * // Wait succeeded. ++ * } ++ * } ++ * ++ * ... ++ * ++ * boost::asio::ip::tcp::acceptor acceptor(my_context); ++ * ... ++ * acceptor.async_wait( ++ * boost::asio::ip::tcp::acceptor::wait_read, ++ * wait_handler); ++ * @endcode ++ */ ++ template ++ BOOST_ASIO_INITFN_RESULT_TYPE(WaitHandler, ++ void (boost::system::error_code)) ++ async_wait(wait_type w, BOOST_ASIO_MOVE_ARG(WaitHandler) handler) ++ { ++ return async_initiate( ++ initiate_async_wait(), handler, this, w); ++ } ++ ++#if !defined(BOOST_ASIO_NO_EXTENSIONS) ++ /// Accept a new connection. ++ /** ++ * This function is used to accept a new connection from a peer into the ++ * given socket. The function call will block until a new connection has been ++ * accepted successfully or an error occurs. ++ * ++ * @param peer The socket into which the new connection will be accepted. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ * ++ * @par Example ++ * @code ++ * boost::asio::ip::tcp::acceptor acceptor(my_context); ++ * ... ++ * boost::asio::ip::tcp::socket socket(my_context); ++ * acceptor.accept(socket); ++ * @endcode ++ */ ++ template ++ void accept(basic_socket_ext_local& peer, ++ typename enable_if< ++ is_convertible::value ++ >::type* = 0) ++ { ++ boost::system::error_code ec; ++ impl_.get_service().accept(impl_.get_implementation(), ++ peer, static_cast(0), ec); ++ boost::asio::detail::throw_error(ec, "accept"); ++ } ++ ++ /// Accept a new connection. ++ /** ++ * This function is used to accept a new connection from a peer into the ++ * given socket. The function call will block until a new connection has been ++ * accepted successfully or an error occurs. ++ * ++ * @param peer The socket into which the new connection will be accepted. ++ * ++ * @param ec Set to indicate what error occurred, if any. ++ * ++ * @par Example ++ * @code ++ * boost::asio::ip::tcp::acceptor acceptor(my_context); ++ * ... ++ * boost::asio::ip::tcp::socket socket(my_context); ++ * boost::system::error_code ec; ++ * acceptor.accept(socket, ec); ++ * if (ec) ++ * { ++ * // An error occurred. ++ * } ++ * @endcode ++ */ ++ template ++ BOOST_ASIO_SYNC_OP_VOID accept( ++ basic_socket_ext_local& peer, boost::system::error_code& ec, ++ typename enable_if< ++ is_convertible::value ++ >::type* = 0) ++ { ++ impl_.get_service().accept(impl_.get_implementation(), ++ peer, static_cast(0), ec); ++ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); ++ } ++ ++ /// Start an asynchronous accept. ++ /** ++ * This function is used to asynchronously accept a new connection into a ++ * socket. The function call always returns immediately. ++ * ++ * @param peer The socket into which the new connection will be accepted. ++ * Ownership of the peer object is retained by the caller, which must ++ * guarantee that it is valid until the handler is called. ++ * ++ * @param handler The handler to be called when the accept operation ++ * completes. Copies will be made of the handler as required. The function ++ * signature of the handler must be: ++ * @code void handler( ++ * const boost::system::error_code& error // Result of operation. ++ * ); @endcode ++ * Regardless of whether the asynchronous operation completes immediately or ++ * not, the handler will not be invoked from within this function. On ++ * immediate completion, invocation of the handler will be performed in a ++ * manner equivalent to using boost::asio::post(). ++ * ++ * @par Example ++ * @code ++ * void accept_handler(const boost::system::error_code& error) ++ * { ++ * if (!error) ++ * { ++ * // Accept succeeded. ++ * } ++ * } ++ * ++ * ... ++ * ++ * boost::asio::ip::tcp::acceptor acceptor(my_context); ++ * ... ++ * boost::asio::ip::tcp::socket socket(my_context); ++ * acceptor.async_accept(socket, accept_handler); ++ * @endcode ++ */ ++ template ++ BOOST_ASIO_INITFN_RESULT_TYPE(AcceptHandler, ++ void (boost::system::error_code)) ++ async_accept(basic_socket_ext_local& peer, ++ BOOST_ASIO_MOVE_ARG(AcceptHandler) handler, ++ typename enable_if< ++ is_convertible::value ++ >::type* = 0) ++ { ++ return async_initiate( ++ initiate_async_accept(), handler, this, ++ &peer, static_cast(0)); ++ } ++ ++ /// Accept a new connection and obtain the endpoint of the peer ++ /** ++ * This function is used to accept a new connection from a peer into the ++ * given socket, and additionally provide the endpoint of the remote peer. ++ * The function call will block until a new connection has been accepted ++ * successfully or an error occurs. ++ * ++ * @param peer The socket into which the new connection will be accepted. ++ * ++ * @param peer_endpoint An endpoint object which will receive the endpoint of ++ * the remote peer. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ * ++ * @par Example ++ * @code ++ * boost::asio::ip::tcp::acceptor acceptor(my_context); ++ * ... ++ * boost::asio::ip::tcp::socket socket(my_context); ++ * boost::asio::ip::tcp::endpoint endpoint; ++ * acceptor.accept(socket, endpoint); ++ * @endcode ++ */ ++ template ++ void accept(basic_socket_ext_local& peer, ++ endpoint_type& peer_endpoint) ++ { ++ boost::system::error_code ec; ++ impl_.get_service().accept(impl_.get_implementation(), ++ peer, &peer_endpoint, ec); ++ boost::asio::detail::throw_error(ec, "accept"); ++ } ++ ++ /// Accept a new connection and obtain the endpoint of the peer ++ /** ++ * This function is used to accept a new connection from a peer into the ++ * given socket, and additionally provide the endpoint of the remote peer. ++ * The function call will block until a new connection has been accepted ++ * successfully or an error occurs. ++ * ++ * @param peer The socket into which the new connection will be accepted. ++ * ++ * @param peer_endpoint An endpoint object which will receive the endpoint of ++ * the remote peer. ++ * ++ * @param ec Set to indicate what error occurred, if any. ++ * ++ * @par Example ++ * @code ++ * boost::asio::ip::tcp::acceptor acceptor(my_context); ++ * ... ++ * boost::asio::ip::tcp::socket socket(my_context); ++ * boost::asio::ip::tcp::endpoint endpoint; ++ * boost::system::error_code ec; ++ * acceptor.accept(socket, endpoint, ec); ++ * if (ec) ++ * { ++ * // An error occurred. ++ * } ++ * @endcode ++ */ ++ template ++ BOOST_ASIO_SYNC_OP_VOID accept(basic_socket_ext_local& peer, ++ endpoint_type& peer_endpoint, boost::system::error_code& ec) ++ { ++ impl_.get_service().accept( ++ impl_.get_implementation(), peer, &peer_endpoint, ec); ++ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); ++ } ++ ++ /// Start an asynchronous accept. ++ /** ++ * This function is used to asynchronously accept a new connection into a ++ * socket, and additionally obtain the endpoint of the remote peer. The ++ * function call always returns immediately. ++ * ++ * @param peer The socket into which the new connection will be accepted. ++ * Ownership of the peer object is retained by the caller, which must ++ * guarantee that it is valid until the handler is called. ++ * ++ * @param peer_endpoint An endpoint object into which the endpoint of the ++ * remote peer will be written. Ownership of the peer_endpoint object is ++ * retained by the caller, which must guarantee that it is valid until the ++ * handler is called. ++ * ++ * @param handler The handler to be called when the accept operation ++ * completes. Copies will be made of the handler as required. The function ++ * signature of the handler must be: ++ * @code void handler( ++ * const boost::system::error_code& error // Result of operation. ++ * ); @endcode ++ * Regardless of whether the asynchronous operation completes immediately or ++ * not, the handler will not be invoked from within this function. On ++ * immediate completion, invocation of the handler will be performed in a ++ * manner equivalent to using boost::asio::post(). ++ */ ++ template ++ BOOST_ASIO_INITFN_RESULT_TYPE(AcceptHandler, ++ void (boost::system::error_code)) ++ async_accept(basic_socket_ext_local& peer, ++ endpoint_type& peer_endpoint, BOOST_ASIO_MOVE_ARG(AcceptHandler) handler) ++ { ++ return async_initiate( ++ initiate_async_accept(), handler, this, &peer, &peer_endpoint); ++ } ++#endif // !defined(BOOST_ASIO_NO_EXTENSIONS) ++ ++#if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) ++ /// Accept a new connection. ++ /** ++ * This function is used to accept a new connection from a peer. The function ++ * call will block until a new connection has been accepted successfully or ++ * an error occurs. ++ * ++ * This overload requires that the Protocol template parameter satisfy the ++ * AcceptableProtocol type requirements. ++ * ++ * @returns A socket object representing the newly accepted connection. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ * ++ * @par Example ++ * @code ++ * boost::asio::ip::tcp::acceptor acceptor(my_context); ++ * ... ++ * boost::asio::ip::tcp::socket socket(acceptor.accept()); ++ * @endcode ++ */ ++ typename Protocol::socket accept() ++ { ++ boost::system::error_code ec; ++ typename Protocol::socket peer(impl_.get_executor()); ++ impl_.get_service().accept(impl_.get_implementation(), peer, 0, ec); ++ boost::asio::detail::throw_error(ec, "accept"); ++ return peer; ++ } ++ ++ /// Accept a new connection. ++ /** ++ * This function is used to accept a new connection from a peer. The function ++ * call will block until a new connection has been accepted successfully or ++ * an error occurs. ++ * ++ * This overload requires that the Protocol template parameter satisfy the ++ * AcceptableProtocol type requirements. ++ * ++ * @param ec Set to indicate what error occurred, if any. ++ * ++ * @returns On success, a socket object representing the newly accepted ++ * connection. On error, a socket object where is_open() is false. ++ * ++ * @par Example ++ * @code ++ * boost::asio::ip::tcp::acceptor acceptor(my_context); ++ * ... ++ * boost::asio::ip::tcp::socket socket(acceptor.accept(ec)); ++ * if (ec) ++ * { ++ * // An error occurred. ++ * } ++ * @endcode ++ */ ++ typename Protocol::socket accept(boost::system::error_code& ec) ++ { ++ typename Protocol::socket peer(impl_.get_executor()); ++ impl_.get_service().accept(impl_.get_implementation(), peer, 0, ec); ++ return peer; ++ } ++ ++ /// Start an asynchronous accept. ++ /** ++ * This function is used to asynchronously accept a new connection. The ++ * function call always returns immediately. ++ * ++ * This overload requires that the Protocol template parameter satisfy the ++ * AcceptableProtocol type requirements. ++ * ++ * @param handler The handler to be called when the accept operation ++ * completes. Copies will be made of the handler as required. The function ++ * signature of the handler must be: ++ * @code void handler( ++ * const boost::system::error_code& error, // Result of operation. ++ * typename Protocol::socket peer // On success, the newly accepted socket. ++ * ); @endcode ++ * Regardless of whether the asynchronous operation completes immediately or ++ * not, the handler will not be invoked from within this function. On ++ * immediate completion, invocation of the handler will be performed in a ++ * manner equivalent to using boost::asio::post(). ++ * ++ * @par Example ++ * @code ++ * void accept_handler(const boost::system::error_code& error, ++ * boost::asio::ip::tcp::socket peer) ++ * { ++ * if (!error) ++ * { ++ * // Accept succeeded. ++ * } ++ * } ++ * ++ * ... ++ * ++ * boost::asio::ip::tcp::acceptor acceptor(my_context); ++ * ... ++ * acceptor.async_accept(accept_handler); ++ * @endcode ++ */ ++ template ++ BOOST_ASIO_INITFN_RESULT_TYPE(MoveAcceptHandler, ++ void (boost::system::error_code, typename Protocol::socket)) ++ async_accept(BOOST_ASIO_MOVE_ARG(MoveAcceptHandler) handler) ++ { ++ return async_initiate( ++ initiate_async_move_accept(), handler, this, ++ impl_.get_executor(), static_cast(0), ++ static_cast(0)); ++ } ++ ++ /// Accept a new connection. ++ /** ++ * This function is used to accept a new connection from a peer. The function ++ * call will block until a new connection has been accepted successfully or ++ * an error occurs. ++ * ++ * This overload requires that the Protocol template parameter satisfy the ++ * AcceptableProtocol type requirements. ++ * ++ * @param ex The I/O executor object to be used for the newly ++ * accepted socket. ++ * ++ * @returns A socket object representing the newly accepted connection. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ * ++ * @par Example ++ * @code ++ * boost::asio::ip::tcp::acceptor acceptor(my_context); ++ * ... ++ * boost::asio::ip::tcp::socket socket(acceptor.accept()); ++ * @endcode ++ */ ++ template ++ typename Protocol::socket::template rebind_executor::other ++ accept(const Executor1& ex, ++ typename enable_if< ++ is_executor::value ++ >::type* = 0) ++ { ++ boost::system::error_code ec; ++ typename Protocol::socket::template ++ rebind_executor::other peer(ex); ++ impl_.get_service().accept(impl_.get_implementation(), peer, 0, ec); ++ boost::asio::detail::throw_error(ec, "accept"); ++ return peer; ++ } ++ ++ /// Accept a new connection. ++ /** ++ * This function is used to accept a new connection from a peer. The function ++ * call will block until a new connection has been accepted successfully or ++ * an error occurs. ++ * ++ * This overload requires that the Protocol template parameter satisfy the ++ * AcceptableProtocol type requirements. ++ * ++ * @param context The I/O execution context object to be used for the newly ++ * accepted socket. ++ * ++ * @returns A socket object representing the newly accepted connection. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ * ++ * @par Example ++ * @code ++ * boost::asio::ip::tcp::acceptor acceptor(my_context); ++ * ... ++ * boost::asio::ip::tcp::socket socket(acceptor.accept()); ++ * @endcode ++ */ ++ template ++ typename Protocol::socket::template rebind_executor< ++ typename ExecutionContext::executor_type>::other ++ accept(ExecutionContext& context, ++ typename enable_if< ++ is_convertible::value ++ >::type* = 0) ++ { ++ boost::system::error_code ec; ++ typename Protocol::socket::template rebind_executor< ++ typename ExecutionContext::executor_type>::other peer(context); ++ impl_.get_service().accept(impl_.get_implementation(), peer, 0, ec); ++ boost::asio::detail::throw_error(ec, "accept"); ++ return peer; ++ } ++ ++ /// Accept a new connection. ++ /** ++ * This function is used to accept a new connection from a peer. The function ++ * call will block until a new connection has been accepted successfully or ++ * an error occurs. ++ * ++ * This overload requires that the Protocol template parameter satisfy the ++ * AcceptableProtocol type requirements. ++ * ++ * @param ex The I/O executor object to be used for the newly accepted ++ * socket. ++ * ++ * @param ec Set to indicate what error occurred, if any. ++ * ++ * @returns On success, a socket object representing the newly accepted ++ * connection. On error, a socket object where is_open() is false. ++ * ++ * @par Example ++ * @code ++ * boost::asio::ip::tcp::acceptor acceptor(my_context); ++ * ... ++ * boost::asio::ip::tcp::socket socket(acceptor.accept(my_context2, ec)); ++ * if (ec) ++ * { ++ * // An error occurred. ++ * } ++ * @endcode ++ */ ++ template ++ typename Protocol::socket::template rebind_executor::other ++ accept(const Executor1& ex, boost::system::error_code& ec, ++ typename enable_if< ++ is_executor::value ++ >::type* = 0) ++ { ++ typename Protocol::socket::template ++ rebind_executor::other peer(ex); ++ impl_.get_service().accept(impl_.get_implementation(), peer, 0, ec); ++ return peer; ++ } ++ ++ /// Accept a new connection. ++ /** ++ * This function is used to accept a new connection from a peer. The function ++ * call will block until a new connection has been accepted successfully or ++ * an error occurs. ++ * ++ * This overload requires that the Protocol template parameter satisfy the ++ * AcceptableProtocol type requirements. ++ * ++ * @param context The I/O execution context object to be used for the newly ++ * accepted socket. ++ * ++ * @param ec Set to indicate what error occurred, if any. ++ * ++ * @returns On success, a socket object representing the newly accepted ++ * connection. On error, a socket object where is_open() is false. ++ * ++ * @par Example ++ * @code ++ * boost::asio::ip::tcp::acceptor acceptor(my_context); ++ * ... ++ * boost::asio::ip::tcp::socket socket(acceptor.accept(my_context2, ec)); ++ * if (ec) ++ * { ++ * // An error occurred. ++ * } ++ * @endcode ++ */ ++ template ++ typename Protocol::socket::template rebind_executor< ++ typename ExecutionContext::executor_type>::other ++ accept(ExecutionContext& context, boost::system::error_code& ec, ++ typename enable_if< ++ is_convertible::value ++ >::type* = 0) ++ { ++ typename Protocol::socket::template rebind_executor< ++ typename ExecutionContext::executor_type>::other peer(context); ++ impl_.get_service().accept(impl_.get_implementation(), peer, 0, ec); ++ return peer; ++ } ++ ++ /// Start an asynchronous accept. ++ /** ++ * This function is used to asynchronously accept a new connection. The ++ * function call always returns immediately. ++ * ++ * This overload requires that the Protocol template parameter satisfy the ++ * AcceptableProtocol type requirements. ++ * ++ * @param ex The I/O executor object to be used for the newly accepted ++ * socket. ++ * ++ * @param handler The handler to be called when the accept operation ++ * completes. Copies will be made of the handler as required. The function ++ * signature of the handler must be: ++ * @code void handler( ++ * const boost::system::error_code& error, // Result of operation. ++ * typename Protocol::socket::template rebind_executor< ++ * Executor1>::other peer // On success, the newly accepted socket. ++ * ); @endcode ++ * Regardless of whether the asynchronous operation completes immediately or ++ * not, the handler will not be invoked from within this function. On ++ * immediate completion, invocation of the handler will be performed in a ++ * manner equivalent to using boost::asio::post(). ++ * ++ * @par Example ++ * @code ++ * void accept_handler(const boost::system::error_code& error, ++ * boost::asio::ip::tcp::socket peer) ++ * { ++ * if (!error) ++ * { ++ * // Accept succeeded. ++ * } ++ * } ++ * ++ * ... ++ * ++ * boost::asio::ip::tcp::acceptor acceptor(my_context); ++ * ... ++ * acceptor.async_accept(my_context2, accept_handler); ++ * @endcode ++ */ ++ template ++ BOOST_ASIO_INITFN_RESULT_TYPE(MoveAcceptHandler, ++ void (boost::system::error_code, ++ typename Protocol::socket::template rebind_executor< ++ Executor1>::other)) ++ async_accept(const Executor1& ex, ++ BOOST_ASIO_MOVE_ARG(MoveAcceptHandler) handler, ++ typename enable_if< ++ is_executor::value ++ >::type* = 0) ++ { ++ typedef typename Protocol::socket::template rebind_executor< ++ Executor1>::other other_socket_type; ++ ++ return async_initiate( ++ initiate_async_move_accept(), handler, this, ++ ex, static_cast(0), ++ static_cast(0)); ++ } ++ ++ /// Start an asynchronous accept. ++ /** ++ * This function is used to asynchronously accept a new connection. The ++ * function call always returns immediately. ++ * ++ * This overload requires that the Protocol template parameter satisfy the ++ * AcceptableProtocol type requirements. ++ * ++ * @param context The I/O execution context object to be used for the newly ++ * accepted socket. ++ * ++ * @param handler The handler to be called when the accept operation ++ * completes. Copies will be made of the handler as required. The function ++ * signature of the handler must be: ++ * @code void handler( ++ * const boost::system::error_code& error, // Result of operation. ++ * typename Protocol::socket::template rebind_executor< ++ * typename ExecutionContext::executor_type>::other peer ++ * // On success, the newly accepted socket. ++ * ); @endcode ++ * Regardless of whether the asynchronous operation completes immediately or ++ * not, the handler will not be invoked from within this function. On ++ * immediate completion, invocation of the handler will be performed in a ++ * manner equivalent to using boost::asio::post(). ++ * ++ * @par Example ++ * @code ++ * void accept_handler(const boost::system::error_code& error, ++ * boost::asio::ip::tcp::socket peer) ++ * { ++ * if (!error) ++ * { ++ * // Accept succeeded. ++ * } ++ * } ++ * ++ * ... ++ * ++ * boost::asio::ip::tcp::acceptor acceptor(my_context); ++ * ... ++ * acceptor.async_accept(my_context2, accept_handler); ++ * @endcode ++ */ ++ template ++ BOOST_ASIO_INITFN_RESULT_TYPE(MoveAcceptHandler, ++ void (boost::system::error_code, ++ typename Protocol::socket::template rebind_executor< ++ typename ExecutionContext::executor_type>::other)) ++ async_accept(ExecutionContext& context, ++ BOOST_ASIO_MOVE_ARG(MoveAcceptHandler) handler, ++ typename enable_if< ++ is_convertible::value ++ >::type* = 0) ++ { ++ typedef typename Protocol::socket::template rebind_executor< ++ typename ExecutionContext::executor_type>::other other_socket_type; ++ ++ return async_initiate( ++ initiate_async_move_accept(), handler, this, ++ context.get_executor(), static_cast(0), ++ static_cast(0)); ++ } ++ ++ /// Accept a new connection. ++ /** ++ * This function is used to accept a new connection from a peer. The function ++ * call will block until a new connection has been accepted successfully or ++ * an error occurs. ++ * ++ * This overload requires that the Protocol template parameter satisfy the ++ * AcceptableProtocol type requirements. ++ * ++ * @param peer_endpoint An endpoint object into which the endpoint of the ++ * remote peer will be written. ++ * ++ * @returns A socket object representing the newly accepted connection. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ * ++ * @par Example ++ * @code ++ * boost::asio::ip::tcp::acceptor acceptor(my_context); ++ * ... ++ * boost::asio::ip::tcp::endpoint endpoint; ++ * boost::asio::ip::tcp::socket socket(acceptor.accept(endpoint)); ++ * @endcode ++ */ ++ typename Protocol::socket accept(endpoint_type& peer_endpoint) ++ { ++ boost::system::error_code ec; ++ typename Protocol::socket peer(impl_.get_executor()); ++ impl_.get_service().accept(impl_.get_implementation(), ++ peer, &peer_endpoint, ec); ++ boost::asio::detail::throw_error(ec, "accept"); ++ return peer; ++ } ++ ++ /// Accept a new connection. ++ /** ++ * This function is used to accept a new connection from a peer. The function ++ * call will block until a new connection has been accepted successfully or ++ * an error occurs. ++ * ++ * This overload requires that the Protocol template parameter satisfy the ++ * AcceptableProtocol type requirements. ++ * ++ * @param peer_endpoint An endpoint object into which the endpoint of the ++ * remote peer will be written. ++ * ++ * @param ec Set to indicate what error occurred, if any. ++ * ++ * @returns On success, a socket object representing the newly accepted ++ * connection. On error, a socket object where is_open() is false. ++ * ++ * @par Example ++ * @code ++ * boost::asio::ip::tcp::acceptor acceptor(my_context); ++ * ... ++ * boost::asio::ip::tcp::endpoint endpoint; ++ * boost::asio::ip::tcp::socket socket(acceptor.accept(endpoint, ec)); ++ * if (ec) ++ * { ++ * // An error occurred. ++ * } ++ * @endcode ++ */ ++ typename Protocol::socket accept( ++ endpoint_type& peer_endpoint, boost::system::error_code& ec) ++ { ++ typename Protocol::socket peer(impl_.get_executor()); ++ impl_.get_service().accept(impl_.get_implementation(), ++ peer, &peer_endpoint, ec); ++ return peer; ++ } ++ ++ /// Start an asynchronous accept. ++ /** ++ * This function is used to asynchronously accept a new connection. The ++ * function call always returns immediately. ++ * ++ * This overload requires that the Protocol template parameter satisfy the ++ * AcceptableProtocol type requirements. ++ * ++ * @param peer_endpoint An endpoint object into which the endpoint of the ++ * remote peer will be written. Ownership of the peer_endpoint object is ++ * retained by the caller, which must guarantee that it is valid until the ++ * handler is called. ++ * ++ * @param handler The handler to be called when the accept operation ++ * completes. Copies will be made of the handler as required. The function ++ * signature of the handler must be: ++ * @code void handler( ++ * const boost::system::error_code& error, // Result of operation. ++ * typename Protocol::socket peer // On success, the newly accepted socket. ++ * ); @endcode ++ * Regardless of whether the asynchronous operation completes immediately or ++ * not, the handler will not be invoked from within this function. On ++ * immediate completion, invocation of the handler will be performed in a ++ * manner equivalent to using boost::asio::post(). ++ * ++ * @par Example ++ * @code ++ * void accept_handler(const boost::system::error_code& error, ++ * boost::asio::ip::tcp::socket peer) ++ * { ++ * if (!error) ++ * { ++ * // Accept succeeded. ++ * } ++ * } ++ * ++ * ... ++ * ++ * boost::asio::ip::tcp::acceptor acceptor(my_context); ++ * ... ++ * boost::asio::ip::tcp::endpoint endpoint; ++ * acceptor.async_accept(endpoint, accept_handler); ++ * @endcode ++ */ ++ template ++ BOOST_ASIO_INITFN_RESULT_TYPE(MoveAcceptHandler, ++ void (boost::system::error_code, typename Protocol::socket)) ++ async_accept(endpoint_type& peer_endpoint, ++ BOOST_ASIO_MOVE_ARG(MoveAcceptHandler) handler) ++ { ++ return async_initiate( ++ initiate_async_move_accept(), handler, this, ++ impl_.get_executor(), &peer_endpoint, ++ static_cast(0)); ++ } ++ ++ /// Accept a new connection. ++ /** ++ * This function is used to accept a new connection from a peer. The function ++ * call will block until a new connection has been accepted successfully or ++ * an error occurs. ++ * ++ * This overload requires that the Protocol template parameter satisfy the ++ * AcceptableProtocol type requirements. ++ * ++ * @param ex The I/O executor object to be used for the newly accepted ++ * socket. ++ * ++ * @param peer_endpoint An endpoint object into which the endpoint of the ++ * remote peer will be written. ++ * ++ * @returns A socket object representing the newly accepted connection. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ * ++ * @par Example ++ * @code ++ * boost::asio::ip::tcp::acceptor acceptor(my_context); ++ * ... ++ * boost::asio::ip::tcp::endpoint endpoint; ++ * boost::asio::ip::tcp::socket socket( ++ * acceptor.accept(my_context2, endpoint)); ++ * @endcode ++ */ ++ template ++ typename Protocol::socket::template rebind_executor::other ++ accept(const Executor1& ex, endpoint_type& peer_endpoint, ++ typename enable_if< ++ is_executor::value ++ >::type* = 0) ++ { ++ boost::system::error_code ec; ++ typename Protocol::socket::template ++ rebind_executor::other peer(ex); ++ impl_.get_service().accept(impl_.get_implementation(), ++ peer, &peer_endpoint, ec); ++ boost::asio::detail::throw_error(ec, "accept"); ++ return peer; ++ } ++ ++ /// Accept a new connection. ++ /** ++ * This function is used to accept a new connection from a peer. The function ++ * call will block until a new connection has been accepted successfully or ++ * an error occurs. ++ * ++ * This overload requires that the Protocol template parameter satisfy the ++ * AcceptableProtocol type requirements. ++ * ++ * @param context The I/O execution context object to be used for the newly ++ * accepted socket. ++ * ++ * @param peer_endpoint An endpoint object into which the endpoint of the ++ * remote peer will be written. ++ * ++ * @returns A socket object representing the newly accepted connection. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ * ++ * @par Example ++ * @code ++ * boost::asio::ip::tcp::acceptor acceptor(my_context); ++ * ... ++ * boost::asio::ip::tcp::endpoint endpoint; ++ * boost::asio::ip::tcp::socket socket( ++ * acceptor.accept(my_context2, endpoint)); ++ * @endcode ++ */ ++ template ++ typename Protocol::socket::template rebind_executor< ++ typename ExecutionContext::executor_type>::other ++ accept(ExecutionContext& context, endpoint_type& peer_endpoint, ++ typename enable_if< ++ is_convertible::value ++ >::type* = 0) ++ { ++ boost::system::error_code ec; ++ typename Protocol::socket::template rebind_executor< ++ typename ExecutionContext::executor_type>::other peer(context); ++ impl_.get_service().accept(impl_.get_implementation(), ++ peer, &peer_endpoint, ec); ++ boost::asio::detail::throw_error(ec, "accept"); ++ return peer; ++ } ++ ++ /// Accept a new connection. ++ /** ++ * This function is used to accept a new connection from a peer. The function ++ * call will block until a new connection has been accepted successfully or ++ * an error occurs. ++ * ++ * This overload requires that the Protocol template parameter satisfy the ++ * AcceptableProtocol type requirements. ++ * ++ * @param ex The I/O executor object to be used for the newly accepted ++ * socket. ++ * ++ * @param peer_endpoint An endpoint object into which the endpoint of the ++ * remote peer will be written. ++ * ++ * @param ec Set to indicate what error occurred, if any. ++ * ++ * @returns On success, a socket object representing the newly accepted ++ * connection. On error, a socket object where is_open() is false. ++ * ++ * @par Example ++ * @code ++ * boost::asio::ip::tcp::acceptor acceptor(my_context); ++ * ... ++ * boost::asio::ip::tcp::endpoint endpoint; ++ * boost::asio::ip::tcp::socket socket( ++ * acceptor.accept(my_context2, endpoint, ec)); ++ * if (ec) ++ * { ++ * // An error occurred. ++ * } ++ * @endcode ++ */ ++ template ++ typename Protocol::socket::template rebind_executor::other ++ accept(const executor_type& ex, ++ endpoint_type& peer_endpoint, boost::system::error_code& ec, ++ typename enable_if< ++ is_executor::value ++ >::type* = 0) ++ { ++ typename Protocol::socket::template ++ rebind_executor::other peer(ex); ++ impl_.get_service().accept(impl_.get_implementation(), ++ peer, &peer_endpoint, ec); ++ return peer; ++ } ++ ++ /// Accept a new connection. ++ /** ++ * This function is used to accept a new connection from a peer. The function ++ * call will block until a new connection has been accepted successfully or ++ * an error occurs. ++ * ++ * This overload requires that the Protocol template parameter satisfy the ++ * AcceptableProtocol type requirements. ++ * ++ * @param context The I/O execution context object to be used for the newly ++ * accepted socket. ++ * ++ * @param peer_endpoint An endpoint object into which the endpoint of the ++ * remote peer will be written. ++ * ++ * @param ec Set to indicate what error occurred, if any. ++ * ++ * @returns On success, a socket object representing the newly accepted ++ * connection. On error, a socket object where is_open() is false. ++ * ++ * @par Example ++ * @code ++ * boost::asio::ip::tcp::acceptor acceptor(my_context); ++ * ... ++ * boost::asio::ip::tcp::endpoint endpoint; ++ * boost::asio::ip::tcp::socket socket( ++ * acceptor.accept(my_context2, endpoint, ec)); ++ * if (ec) ++ * { ++ * // An error occurred. ++ * } ++ * @endcode ++ */ ++ template ++ typename Protocol::socket::template rebind_executor< ++ typename ExecutionContext::executor_type>::other ++ accept(ExecutionContext& context, ++ endpoint_type& peer_endpoint, boost::system::error_code& ec, ++ typename enable_if< ++ is_convertible::value ++ >::type* = 0) ++ { ++ typename Protocol::socket::template rebind_executor< ++ typename ExecutionContext::executor_type>::other peer(context); ++ impl_.get_service().accept(impl_.get_implementation(), ++ peer, &peer_endpoint, ec); ++ return peer; ++ } ++ ++ /// Start an asynchronous accept. ++ /** ++ * This function is used to asynchronously accept a new connection. The ++ * function call always returns immediately. ++ * ++ * This overload requires that the Protocol template parameter satisfy the ++ * AcceptableProtocol type requirements. ++ * ++ * @param ex The I/O executor object to be used for the newly accepted ++ * socket. ++ * ++ * @param peer_endpoint An endpoint object into which the endpoint of the ++ * remote peer will be written. Ownership of the peer_endpoint object is ++ * retained by the caller, which must guarantee that it is valid until the ++ * handler is called. ++ * ++ * @param handler The handler to be called when the accept operation ++ * completes. Copies will be made of the handler as required. The function ++ * signature of the handler must be: ++ * @code void handler( ++ * const boost::system::error_code& error, // Result of operation. ++ * typename Protocol::socket::template rebind_executor< ++ * Executor1>::other peer // On success, the newly accepted socket. ++ * ); @endcode ++ * Regardless of whether the asynchronous operation completes immediately or ++ * not, the handler will not be invoked from within this function. On ++ * immediate completion, invocation of the handler will be performed in a ++ * manner equivalent to using boost::asio::post(). ++ * ++ * @par Example ++ * @code ++ * void accept_handler(const boost::system::error_code& error, ++ * boost::asio::ip::tcp::socket peer) ++ * { ++ * if (!error) ++ * { ++ * // Accept succeeded. ++ * } ++ * } ++ * ++ * ... ++ * ++ * boost::asio::ip::tcp::acceptor acceptor(my_context); ++ * ... ++ * boost::asio::ip::tcp::endpoint endpoint; ++ * acceptor.async_accept(my_context2, endpoint, accept_handler); ++ * @endcode ++ */ ++ template ++ BOOST_ASIO_INITFN_RESULT_TYPE(MoveAcceptHandler, ++ void (boost::system::error_code, ++ typename Protocol::socket::template rebind_executor< ++ Executor1>::other)) ++ async_accept(const Executor1& ex, endpoint_type& peer_endpoint, ++ BOOST_ASIO_MOVE_ARG(MoveAcceptHandler) handler, ++ typename enable_if< ++ is_executor::value ++ >::type* = 0) ++ { ++ typedef typename Protocol::socket::template rebind_executor< ++ Executor1>::other other_socket_type; ++ ++ return async_initiate( ++ initiate_async_move_accept(), handler, this, ++ ex, &peer_endpoint, ++ static_cast(0)); ++ } ++ ++ /// Start an asynchronous accept. ++ /** ++ * This function is used to asynchronously accept a new connection. The ++ * function call always returns immediately. ++ * ++ * This overload requires that the Protocol template parameter satisfy the ++ * AcceptableProtocol type requirements. ++ * ++ * @param context The I/O execution context object to be used for the newly ++ * accepted socket. ++ * ++ * @param peer_endpoint An endpoint object into which the endpoint of the ++ * remote peer will be written. Ownership of the peer_endpoint object is ++ * retained by the caller, which must guarantee that it is valid until the ++ * handler is called. ++ * ++ * @param handler The handler to be called when the accept operation ++ * completes. Copies will be made of the handler as required. The function ++ * signature of the handler must be: ++ * @code void handler( ++ * const boost::system::error_code& error, // Result of operation. ++ * typename Protocol::socket::template rebind_executor< ++ * typename ExecutionContext::executor_type>::other peer ++ * // On success, the newly accepted socket. ++ * ); @endcode ++ * Regardless of whether the asynchronous operation completes immediately or ++ * not, the handler will not be invoked from within this function. On ++ * immediate completion, invocation of the handler will be performed in a ++ * manner equivalent to using boost::asio::post(). ++ * ++ * @par Example ++ * @code ++ * void accept_handler(const boost::system::error_code& error, ++ * boost::asio::ip::tcp::socket peer) ++ * { ++ * if (!error) ++ * { ++ * // Accept succeeded. ++ * } ++ * } ++ * ++ * ... ++ * ++ * boost::asio::ip::tcp::acceptor acceptor(my_context); ++ * ... ++ * boost::asio::ip::tcp::endpoint endpoint; ++ * acceptor.async_accept(my_context2, endpoint, accept_handler); ++ * @endcode ++ */ ++ template ++ BOOST_ASIO_INITFN_RESULT_TYPE(MoveAcceptHandler, ++ void (boost::system::error_code, ++ typename Protocol::socket::template rebind_executor< ++ typename ExecutionContext::executor_type>::other)) ++ async_accept(ExecutionContext& context, ++ endpoint_type& peer_endpoint, ++ BOOST_ASIO_MOVE_ARG(MoveAcceptHandler) handler, ++ typename enable_if< ++ is_convertible::value ++ >::type* = 0) ++ { ++ typedef typename Protocol::socket::template rebind_executor< ++ typename ExecutionContext::executor_type>::other other_socket_type; ++ ++ return async_initiate( ++ initiate_async_move_accept(), handler, this, ++ context.get_executor(), &peer_endpoint, ++ static_cast(0)); ++ } ++#endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) ++ ++private: ++ // Disallow copying and assignment. ++ basic_socket_acceptor_ext(const basic_socket_acceptor_ext&) BOOST_ASIO_DELETED; ++ basic_socket_acceptor_ext& operator=( ++ const basic_socket_acceptor_ext&) BOOST_ASIO_DELETED; ++ ++ struct initiate_async_wait ++ { ++ template ++ void operator()(BOOST_ASIO_MOVE_ARG(WaitHandler) handler, ++ basic_socket_acceptor_ext* self, wait_type w) const ++ { ++ // If you get an error on the following line it means that your handler ++ // does not meet the documented type requirements for a WaitHandler. ++ BOOST_ASIO_WAIT_HANDLER_CHECK(WaitHandler, handler) type_check; ++ ++ detail::non_const_lvalue handler2(handler); ++ self->impl_.get_service().async_wait( ++ self->impl_.get_implementation(), w, handler2.value, ++ self->impl_.get_implementation_executor()); ++ } ++ }; ++ ++ struct initiate_async_accept ++ { ++ template ++ void operator()(BOOST_ASIO_MOVE_ARG(AcceptHandler) handler, ++ basic_socket_acceptor_ext* self, basic_socket_ext_local* peer, ++ endpoint_type* peer_endpoint) const ++ { ++ // If you get an error on the following line it means that your handler ++ // does not meet the documented type requirements for a AcceptHandler. ++ BOOST_ASIO_ACCEPT_HANDLER_CHECK(AcceptHandler, handler) type_check; ++ ++ detail::non_const_lvalue handler2(handler); ++ self->impl_.get_service().async_accept( ++ self->impl_.get_implementation(), *peer, peer_endpoint, ++ handler2.value, self->impl_.get_executor()); ++ } ++ }; ++ ++ struct initiate_async_move_accept ++ { ++ template ++ void operator()(BOOST_ASIO_MOVE_ARG(MoveAcceptHandler) handler, ++ basic_socket_acceptor_ext* self, const Executor1& peer_ex, ++ endpoint_type* peer_endpoint, Socket*) const ++ { ++ // If you get an error on the following line it means that your handler ++ // does not meet the documented type requirements for a MoveAcceptHandler. ++ BOOST_ASIO_MOVE_ACCEPT_HANDLER_CHECK( ++ MoveAcceptHandler, handler, Socket) type_check; ++ ++ detail::non_const_lvalue handler2(handler); ++ self->impl_.get_service().async_move_accept( ++ self->impl_.get_implementation(), peer_ex, peer_endpoint, ++ handler2.value, self->impl_.get_implementation_executor()); ++ } ++ }; ++ ++#if defined(BOOST_ASIO_WINDOWS_RUNTIME) ++ detail::io_object_impl< ++ detail::null_socket_service, Executor> impl_; ++#elif defined(BOOST_ASIO_HAS_IOCP) ++ detail::io_object_impl< ++ detail::win_iocp_socket_service, Executor> impl_; ++#else ++ detail::io_object_impl< ++ detail::reactive_socket_service_ext_local, Executor> impl_; ++#endif ++}; ++ ++} // namespace asio ++} // namespace boost ++ ++#include ++ ++#endif // BOOST_ASIO_BASIC_SOCKET_ACCEPTOR_EXT_HPP +diff --git a/implementation/helper/1.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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#if defined(BOOST_ASIO_WINDOWS_RUNTIME) ++# include ++#elif defined(BOOST_ASIO_HAS_IOCP) ++# include ++#else ++# include ++#endif ++ ++#if defined(BOOST_ASIO_HAS_MOVE) ++# include ++#endif // defined(BOOST_ASIO_HAS_MOVE) ++ ++#include ++ ++namespace boost { ++namespace asio { ++ ++#if !defined(BOOST_ASIO_BASIC_SOCKET_EXT_FWD_DECL) ++#define BOOST_ASIO_BASIC_SOCKET_EXT_FWD_DECL ++ ++// Forward declaration with defaulted arguments. ++template ++class basic_socket_ext; ++ ++#endif // !defined(BOOST_ASIO_BASIC_SOCKET_EXT_FWD_DECL) ++ ++/// Provides socket functionality. ++/** ++ * The basic_socket class template provides functionality that is common to both ++ * stream-oriented and datagram-oriented sockets. ++ * ++ * @par Thread Safety ++ * @e Distinct @e objects: Safe.@n ++ * @e Shared @e objects: Unsafe. ++ */ ++template ++class basic_socket_ext ++ : public socket_base ++{ ++public: ++ /// The type of the executor associated with the object. ++ typedef Executor executor_type; ++ ++ /// Rebinds the socket type to another executor. ++ template ++ struct rebind_executor ++ { ++ /// The socket type when rebound to the specified executor. ++ typedef basic_socket_ext other; ++ }; ++ ++ /// The native representation of a socket. ++#if defined(GENERATING_DOCUMENTATION) ++ typedef implementation_defined native_handle_type; ++#elif defined(BOOST_ASIO_WINDOWS_RUNTIME) ++ typedef typename detail::null_socket_service< ++ Protocol>::native_handle_type native_handle_type; ++#elif defined(BOOST_ASIO_HAS_IOCP) ++ typedef typename detail::win_iocp_socket_service< ++ Protocol>::native_handle_type native_handle_type; ++#else ++ typedef typename detail::reactive_socket_service_ext< ++ Protocol>::native_handle_type native_handle_type; ++#endif ++ ++ /// The protocol type. ++ typedef Protocol protocol_type; ++ ++ /// The endpoint type. ++ typedef typename Protocol::endpoint endpoint_type; ++ ++#if !defined(BOOST_ASIO_NO_EXTENSIONS) ++ /// A basic_socket is always the lowest layer. ++ typedef basic_socket_ext lowest_layer_type; ++#endif // !defined(BOOST_ASIO_NO_EXTENSIONS) ++ ++ /// Construct a basic_socket without opening it. ++ /** ++ * This constructor creates a socket without opening it. ++ * ++ * @param ex The I/O executor that the socket will use, by default, to ++ * dispatch handlers for any asynchronous operations performed on the socket. ++ */ ++ explicit basic_socket_ext(const executor_type& ex) ++ : impl_(0, ex) ++ { ++ } ++ ++ /// Construct a basic_socket without opening it. ++ /** ++ * This constructor creates a socket without opening it. ++ * ++ * @param context An execution context which provides the I/O executor that ++ * the socket will use, by default, to dispatch handlers for any asynchronous ++ * operations performed on the socket. ++ */ ++ template ++ explicit basic_socket_ext(ExecutionContext& context, ++ typename enable_if< ++ is_convertible::value ++ >::type* = 0) ++ : impl_(0, 0, context) ++ { ++ } ++ ++ /// Construct and open a basic_socket. ++ /** ++ * This constructor creates and opens a socket. ++ * ++ * @param ex The I/O executor that the socket will use, by default, to ++ * dispatch handlers for any asynchronous operations performed on the socket. ++ * ++ * @param protocol An object specifying protocol parameters to be used. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ */ ++ basic_socket_ext(const executor_type& ex, const protocol_type& protocol) ++ : impl_(0, ex) ++ { ++ boost::system::error_code ec; ++ impl_.get_service().open(impl_.get_implementation(), protocol, ec); ++ boost::asio::detail::throw_error(ec, "open"); ++ } ++ ++ /// Construct and open a basic_socket. ++ /** ++ * This constructor creates and opens a socket. ++ * ++ * @param context An execution context which provides the I/O executor that ++ * the socket will use, by default, to dispatch handlers for any asynchronous ++ * operations performed on the socket. ++ * ++ * @param protocol An object specifying protocol parameters to be used. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ */ ++ template ++ basic_socket_ext(ExecutionContext& context, const protocol_type& protocol, ++ typename enable_if< ++ is_convertible::value ++ >::type* = 0) ++ : impl_(0, 0, context) ++ { ++ boost::system::error_code ec; ++ impl_.get_service().open(impl_.get_implementation(), protocol, ec); ++ boost::asio::detail::throw_error(ec, "open"); ++ } ++ ++ /// Construct a basic_socket, opening it and binding it to the given local ++ /// endpoint. ++ /** ++ * This constructor creates a socket and automatically opens it bound to the ++ * specified endpoint on the local machine. The protocol used is the protocol ++ * associated with the given endpoint. ++ * ++ * @param ex The I/O executor that the socket will use, by default, to ++ * dispatch handlers for any asynchronous operations performed on the socket. ++ * ++ * @param endpoint An endpoint on the local machine to which the socket will ++ * be bound. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ */ ++ basic_socket_ext(const executor_type& ex, const endpoint_type& endpoint) ++ : impl_(0, ex) ++ { ++ boost::system::error_code ec; ++ const protocol_type protocol = endpoint.protocol(); ++ impl_.get_service().open(impl_.get_implementation(), protocol, ec); ++ boost::asio::detail::throw_error(ec, "open"); ++ impl_.get_service().bind(impl_.get_implementation(), endpoint, ec); ++ boost::asio::detail::throw_error(ec, "bind"); ++ } ++ ++ /// Construct a basic_socket, opening it and binding it to the given local ++ /// endpoint. ++ /** ++ * This constructor creates a socket and automatically opens it bound to the ++ * specified endpoint on the local machine. The protocol used is the protocol ++ * associated with the given endpoint. ++ * ++ * @param context An execution context which provides the I/O executor that ++ * the socket will use, by default, to dispatch handlers for any asynchronous ++ * operations performed on the socket. ++ * ++ * @param endpoint An endpoint on the local machine to which the socket will ++ * be bound. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ */ ++ template ++ basic_socket_ext(ExecutionContext& context, const endpoint_type& endpoint, ++ typename enable_if< ++ is_convertible::value ++ >::type* = 0) ++ : impl_(0, 0, context) ++ { ++ boost::system::error_code ec; ++ const protocol_type protocol = endpoint.protocol(); ++ impl_.get_service().open(impl_.get_implementation(), protocol, ec); ++ boost::asio::detail::throw_error(ec, "open"); ++ impl_.get_service().bind(impl_.get_implementation(), endpoint, ec); ++ boost::asio::detail::throw_error(ec, "bind"); ++ } ++ ++ /// Construct a basic_socket on an existing native socket. ++ /** ++ * This constructor creates a socket object to hold an existing native socket. ++ * ++ * @param ex The I/O executor that the socket will use, by default, to ++ * dispatch handlers for any asynchronous operations performed on the socket. ++ * ++ * @param protocol An object specifying protocol parameters to be used. ++ * ++ * @param native_socket A native socket. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ */ ++ basic_socket_ext(const executor_type& ex, const protocol_type& protocol, ++ const native_handle_type& native_socket) ++ : impl_(0, ex) ++ { ++ boost::system::error_code ec; ++ impl_.get_service().assign(impl_.get_implementation(), ++ protocol, native_socket, ec); ++ boost::asio::detail::throw_error(ec, "assign"); ++ } ++ ++ /// Construct a basic_socket on an existing native socket. ++ /** ++ * This constructor creates a socket object to hold an existing native socket. ++ * ++ * @param context An execution context which provides the I/O executor that ++ * the socket will use, by default, to dispatch handlers for any asynchronous ++ * operations performed on the socket. ++ * ++ * @param protocol An object specifying protocol parameters to be used. ++ * ++ * @param native_socket A native socket. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ */ ++ template ++ basic_socket_ext(ExecutionContext& context, const protocol_type& protocol, ++ const native_handle_type& native_socket, ++ typename enable_if< ++ is_convertible::value ++ >::type* = 0) ++ : impl_(0, 0, context) ++ { ++ boost::system::error_code ec; ++ impl_.get_service().assign(impl_.get_implementation(), ++ protocol, native_socket, ec); ++ boost::asio::detail::throw_error(ec, "assign"); ++ } ++ ++#if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) ++ /// Move-construct a basic_socket from another. ++ /** ++ * This constructor moves a socket from one object to another. ++ * ++ * @param other The other basic_socket object from which the move will ++ * occur. ++ * ++ * @note Following the move, the moved-from object is in the same state as if ++ * constructed using the @c basic_socket(const executor_type&) constructor. ++ */ ++ basic_socket_ext(basic_socket_ext&& other) ++ : impl_(std::move(other.impl_)) ++ { ++ } ++ ++ /// Move-assign a basic_socket from another. ++ /** ++ * This assignment operator moves a socket from one object to another. ++ * ++ * @param other The other basic_socket object from which the move will ++ * occur. ++ * ++ * @note Following the move, the moved-from object is in the same state as if ++ * constructed using the @c basic_socket(const executor_type&) constructor. ++ */ ++ basic_socket_ext& operator=(basic_socket_ext&& other) ++ { ++ impl_ = std::move(other.impl_); ++ return *this; ++ } ++ ++ // All sockets have access to each other's implementations. ++ template ++ friend class basic_socket_ext; ++ ++ /// Move-construct a basic_socket from a socket of another protocol type. ++ /** ++ * This constructor moves a socket from one object to another. ++ * ++ * @param other The other basic_socket object from which the move will ++ * occur. ++ * ++ * @note Following the move, the moved-from object is in the same state as if ++ * constructed using the @c basic_socket(const executor_type&) constructor. ++ */ ++ template ++ basic_socket_ext(basic_socket_ext&& other, ++ typename enable_if< ++ is_convertible::value ++ && is_convertible::value ++ >::type* = 0) ++ : impl_(std::move(other.impl_)) ++ { ++ } ++ ++ /// Move-assign a basic_socket from a socket of another protocol type. ++ /** ++ * This assignment operator moves a socket from one object to another. ++ * ++ * @param other The other basic_socket object from which the move will ++ * occur. ++ * ++ * @note Following the move, the moved-from object is in the same state as if ++ * constructed using the @c basic_socket(const executor_type&) constructor. ++ */ ++ template ++ typename enable_if< ++ is_convertible::value ++ && is_convertible::value, ++ basic_socket_ext& ++ >::type operator=(basic_socket_ext && other) ++ { ++ basic_socket_ext tmp(std::move(other)); ++ impl_ = std::move(tmp.impl_); ++ return *this; ++ } ++#endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) ++ ++ /// Get the executor associated with the object. ++ executor_type get_executor() BOOST_ASIO_NOEXCEPT ++ { ++ return impl_.get_executor(); ++ } ++ ++#if !defined(BOOST_ASIO_NO_EXTENSIONS) ++ /// Get a reference to the lowest layer. ++ /** ++ * This function returns a reference to the lowest layer in a stack of ++ * layers. Since a basic_socket cannot contain any further layers, it simply ++ * returns a reference to itself. ++ * ++ * @return A reference to the lowest layer in the stack of layers. Ownership ++ * is not transferred to the caller. ++ */ ++ lowest_layer_type& lowest_layer() ++ { ++ return *this; ++ } ++ ++ /// Get a const reference to the lowest layer. ++ /** ++ * This function returns a const reference to the lowest layer in a stack of ++ * layers. Since a basic_socket cannot contain any further layers, it simply ++ * returns a reference to itself. ++ * ++ * @return A const reference to the lowest layer in the stack of layers. ++ * Ownership is not transferred to the caller. ++ */ ++ const lowest_layer_type& lowest_layer() const ++ { ++ return *this; ++ } ++#endif // !defined(BOOST_ASIO_NO_EXTENSIONS) ++ ++ /// Open the socket using the specified protocol. ++ /** ++ * This function opens the socket so that it will use the specified protocol. ++ * ++ * @param protocol An object specifying protocol parameters to be used. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ * ++ * @par Example ++ * @code ++ * boost::asio::ip::tcp::socket socket(my_context); ++ * socket.open(boost::asio::ip::tcp::v4()); ++ * @endcode ++ */ ++ void open(const protocol_type& protocol = protocol_type()) ++ { ++ boost::system::error_code ec; ++ impl_.get_service().open(impl_.get_implementation(), protocol, ec); ++ boost::asio::detail::throw_error(ec, "open"); ++ } ++ ++ /// Open the socket using the specified protocol. ++ /** ++ * This function opens the socket so that it will use the specified protocol. ++ * ++ * @param protocol An object specifying which protocol is to be used. ++ * ++ * @param ec Set to indicate what error occurred, if any. ++ * ++ * @par Example ++ * @code ++ * boost::asio::ip::tcp::socket socket(my_context); ++ * boost::system::error_code ec; ++ * socket.open(boost::asio::ip::tcp::v4(), ec); ++ * if (ec) ++ * { ++ * // An error occurred. ++ * } ++ * @endcode ++ */ ++ BOOST_ASIO_SYNC_OP_VOID open(const protocol_type& protocol, ++ boost::system::error_code& ec) ++ { ++ impl_.get_service().open(impl_.get_implementation(), protocol, ec); ++ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); ++ } ++ ++ /// Assign an existing native socket to the socket. ++ /* ++ * This function opens the socket to hold an existing native socket. ++ * ++ * @param protocol An object specifying which protocol is to be used. ++ * ++ * @param native_socket A native socket. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ */ ++ void assign(const protocol_type& protocol, ++ const native_handle_type& native_socket) ++ { ++ boost::system::error_code ec; ++ impl_.get_service().assign(impl_.get_implementation(), ++ protocol, native_socket, ec); ++ boost::asio::detail::throw_error(ec, "assign"); ++ } ++ ++ /// Assign an existing native socket to the socket. ++ /* ++ * This function opens the socket to hold an existing native socket. ++ * ++ * @param protocol An object specifying which protocol is to be used. ++ * ++ * @param native_socket A native socket. ++ * ++ * @param ec Set to indicate what error occurred, if any. ++ */ ++ BOOST_ASIO_SYNC_OP_VOID assign(const protocol_type& protocol, ++ const native_handle_type& native_socket, boost::system::error_code& ec) ++ { ++ impl_.get_service().assign(impl_.get_implementation(), ++ protocol, native_socket, ec); ++ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); ++ } ++ ++ /// Determine whether the socket is open. ++ bool is_open() const ++ { ++ return impl_.get_service().is_open(impl_.get_implementation()); ++ } ++ ++ /// Close the socket. ++ /** ++ * This function is used to close the socket. Any asynchronous send, receive ++ * or connect operations will be cancelled immediately, and will complete ++ * with the boost::asio::error::operation_aborted error. ++ * ++ * @throws boost::system::system_error Thrown on failure. Note that, even if ++ * the function indicates an error, the underlying descriptor is closed. ++ * ++ * @note For portable behaviour with respect to graceful closure of a ++ * connected socket, call shutdown() before closing the socket. ++ */ ++ void close() ++ { ++ boost::system::error_code ec; ++ impl_.get_service().close(impl_.get_implementation(), ec); ++ boost::asio::detail::throw_error(ec, "close"); ++ } ++ ++ /// Close the socket. ++ /** ++ * This function is used to close the socket. Any asynchronous send, receive ++ * or connect operations will be cancelled immediately, and will complete ++ * with the boost::asio::error::operation_aborted error. ++ * ++ * @param ec Set to indicate what error occurred, if any. Note that, even if ++ * the function indicates an error, the underlying descriptor is closed. ++ * ++ * @par Example ++ * @code ++ * boost::asio::ip::tcp::socket socket(my_context); ++ * ... ++ * boost::system::error_code ec; ++ * socket.close(ec); ++ * if (ec) ++ * { ++ * // An error occurred. ++ * } ++ * @endcode ++ * ++ * @note For portable behaviour with respect to graceful closure of a ++ * connected socket, call shutdown() before closing the socket. ++ */ ++ BOOST_ASIO_SYNC_OP_VOID close(boost::system::error_code& ec) ++ { ++ impl_.get_service().close(impl_.get_implementation(), ec); ++ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); ++ } ++ ++ /// Release ownership of the underlying native socket. ++ /** ++ * This function causes all outstanding asynchronous connect, send and receive ++ * operations to finish immediately, and the handlers for cancelled operations ++ * will be passed the boost::asio::error::operation_aborted error. Ownership ++ * of the native socket is then transferred to the caller. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ * ++ * @note This function is unsupported on Windows versions prior to Windows ++ * 8.1, and will fail with boost::asio::error::operation_not_supported on ++ * these platforms. ++ */ ++#if defined(BOOST_ASIO_MSVC) && (BOOST_ASIO_MSVC >= 1400) \ ++ && (!defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0603) ++ __declspec(deprecated("This function always fails with " ++ "operation_not_supported when used on Windows versions " ++ "prior to Windows 8.1.")) ++#endif ++ native_handle_type release() ++ { ++ boost::system::error_code ec; ++ native_handle_type s = impl_.get_service().release( ++ impl_.get_implementation(), ec); ++ boost::asio::detail::throw_error(ec, "release"); ++ return s; ++ } ++ ++ /// Release ownership of the underlying native socket. ++ /** ++ * This function causes all outstanding asynchronous connect, send and receive ++ * operations to finish immediately, and the handlers for cancelled operations ++ * will be passed the boost::asio::error::operation_aborted error. Ownership ++ * of the native socket is then transferred to the caller. ++ * ++ * @param ec Set to indicate what error occurred, if any. ++ * ++ * @note This function is unsupported on Windows versions prior to Windows ++ * 8.1, and will fail with boost::asio::error::operation_not_supported on ++ * these platforms. ++ */ ++#if defined(BOOST_ASIO_MSVC) && (BOOST_ASIO_MSVC >= 1400) \ ++ && (!defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0603) ++ __declspec(deprecated("This function always fails with " ++ "operation_not_supported when used on Windows versions " ++ "prior to Windows 8.1.")) ++#endif ++ native_handle_type release(boost::system::error_code& ec) ++ { ++ return impl_.get_service().release(impl_.get_implementation(), ec); ++ } ++ ++ /// Get the native socket representation. ++ /** ++ * This function may be used to obtain the underlying representation of the ++ * socket. This is intended to allow access to native socket functionality ++ * that is not otherwise provided. ++ */ ++ native_handle_type native_handle() ++ { ++ return impl_.get_service().native_handle(impl_.get_implementation()); ++ } ++ ++ /// Cancel all asynchronous operations associated with the socket. ++ /** ++ * This function causes all outstanding asynchronous connect, send and receive ++ * operations to finish immediately, and the handlers for cancelled operations ++ * will be passed the boost::asio::error::operation_aborted error. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ * ++ * @note Calls to cancel() will always fail with ++ * boost::asio::error::operation_not_supported when run on Windows XP, Windows ++ * Server 2003, and earlier versions of Windows, unless ++ * BOOST_ASIO_ENABLE_CANCELIO is defined. However, the CancelIo function has ++ * two issues that should be considered before enabling its use: ++ * ++ * @li It will only cancel asynchronous operations that were initiated in the ++ * current thread. ++ * ++ * @li It can appear to complete without error, but the request to cancel the ++ * unfinished operations may be silently ignored by the operating system. ++ * Whether it works or not seems to depend on the drivers that are installed. ++ * ++ * For portable cancellation, consider using one of the following ++ * alternatives: ++ * ++ * @li Disable asio's I/O completion port backend by defining ++ * BOOST_ASIO_DISABLE_IOCP. ++ * ++ * @li Use the close() function to simultaneously cancel the outstanding ++ * operations and close the socket. ++ * ++ * When running on Windows Vista, Windows Server 2008, and later, the ++ * CancelIoEx function is always used. This function does not have the ++ * problems described above. ++ */ ++#if defined(BOOST_ASIO_MSVC) && (BOOST_ASIO_MSVC >= 1400) \ ++ && (!defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0600) \ ++ && !defined(BOOST_ASIO_ENABLE_CANCELIO) ++ __declspec(deprecated("By default, this function always fails with " ++ "operation_not_supported when used on Windows XP, Windows Server 2003, " ++ "or earlier. Consult documentation for details.")) ++#endif ++ void cancel() ++ { ++ boost::system::error_code ec; ++ impl_.get_service().cancel(impl_.get_implementation(), ec); ++ boost::asio::detail::throw_error(ec, "cancel"); ++ } ++ ++ /// Cancel all asynchronous operations associated with the socket. ++ /** ++ * This function causes all outstanding asynchronous connect, send and receive ++ * operations to finish immediately, and the handlers for cancelled operations ++ * will be passed the boost::asio::error::operation_aborted error. ++ * ++ * @param ec Set to indicate what error occurred, if any. ++ * ++ * @note Calls to cancel() will always fail with ++ * boost::asio::error::operation_not_supported when run on Windows XP, Windows ++ * Server 2003, and earlier versions of Windows, unless ++ * BOOST_ASIO_ENABLE_CANCELIO is defined. However, the CancelIo function has ++ * two issues that should be considered before enabling its use: ++ * ++ * @li It will only cancel asynchronous operations that were initiated in the ++ * current thread. ++ * ++ * @li It can appear to complete without error, but the request to cancel the ++ * unfinished operations may be silently ignored by the operating system. ++ * Whether it works or not seems to depend on the drivers that are installed. ++ * ++ * For portable cancellation, consider using one of the following ++ * alternatives: ++ * ++ * @li Disable asio's I/O completion port backend by defining ++ * BOOST_ASIO_DISABLE_IOCP. ++ * ++ * @li Use the close() function to simultaneously cancel the outstanding ++ * operations and close the socket. ++ * ++ * When running on Windows Vista, Windows Server 2008, and later, the ++ * CancelIoEx function is always used. This function does not have the ++ * problems described above. ++ */ ++#if defined(BOOST_ASIO_MSVC) && (BOOST_ASIO_MSVC >= 1400) \ ++ && (!defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0600) \ ++ && !defined(BOOST_ASIO_ENABLE_CANCELIO) ++ __declspec(deprecated("By default, this function always fails with " ++ "operation_not_supported when used on Windows XP, Windows Server 2003, " ++ "or earlier. Consult documentation for details.")) ++#endif ++ BOOST_ASIO_SYNC_OP_VOID cancel(boost::system::error_code& ec) ++ { ++ impl_.get_service().cancel(impl_.get_implementation(), ec); ++ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); ++ } ++ ++ /// Determine whether the socket is at the out-of-band data mark. ++ /** ++ * This function is used to check whether the socket input is currently ++ * positioned at the out-of-band data mark. ++ * ++ * @return A bool indicating whether the socket is at the out-of-band data ++ * mark. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ */ ++ bool at_mark() const ++ { ++ boost::system::error_code ec; ++ bool b = impl_.get_service().at_mark(impl_.get_implementation(), ec); ++ boost::asio::detail::throw_error(ec, "at_mark"); ++ return b; ++ } ++ ++ /// Determine whether the socket is at the out-of-band data mark. ++ /** ++ * This function is used to check whether the socket input is currently ++ * positioned at the out-of-band data mark. ++ * ++ * @param ec Set to indicate what error occurred, if any. ++ * ++ * @return A bool indicating whether the socket is at the out-of-band data ++ * mark. ++ */ ++ bool at_mark(boost::system::error_code& ec) const ++ { ++ return impl_.get_service().at_mark(impl_.get_implementation(), ec); ++ } ++ ++ /// Determine the number of bytes available for reading. ++ /** ++ * This function is used to determine the number of bytes that may be read ++ * without blocking. ++ * ++ * @return The number of bytes that may be read without blocking, or 0 if an ++ * error occurs. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ */ ++ std::size_t available() const ++ { ++ boost::system::error_code ec; ++ std::size_t s = impl_.get_service().available( ++ impl_.get_implementation(), ec); ++ boost::asio::detail::throw_error(ec, "available"); ++ return s; ++ } ++ ++ /// Determine the number of bytes available for reading. ++ /** ++ * This function is used to determine the number of bytes that may be read ++ * without blocking. ++ * ++ * @param ec Set to indicate what error occurred, if any. ++ * ++ * @return The number of bytes that may be read without blocking, or 0 if an ++ * error occurs. ++ */ ++ std::size_t available(boost::system::error_code& ec) const ++ { ++ return impl_.get_service().available(impl_.get_implementation(), ec); ++ } ++ ++ /// Bind the socket to the given local endpoint. ++ /** ++ * This function binds the socket to the specified endpoint on the local ++ * machine. ++ * ++ * @param endpoint An endpoint on the local machine to which the socket will ++ * be bound. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ * ++ * @par Example ++ * @code ++ * boost::asio::ip::tcp::socket socket(my_context); ++ * socket.open(boost::asio::ip::tcp::v4()); ++ * socket.bind(boost::asio::ip::tcp::endpoint( ++ * boost::asio::ip::tcp::v4(), 12345)); ++ * @endcode ++ */ ++ void bind(const endpoint_type& endpoint) ++ { ++ boost::system::error_code ec; ++ impl_.get_service().bind(impl_.get_implementation(), endpoint, ec); ++ boost::asio::detail::throw_error(ec, "bind"); ++ } ++ ++ /// Bind the socket to the given local endpoint. ++ /** ++ * This function binds the socket to the specified endpoint on the local ++ * machine. ++ * ++ * @param endpoint An endpoint on the local machine to which the socket will ++ * be bound. ++ * ++ * @param ec Set to indicate what error occurred, if any. ++ * ++ * @par Example ++ * @code ++ * boost::asio::ip::tcp::socket socket(my_context); ++ * socket.open(boost::asio::ip::tcp::v4()); ++ * boost::system::error_code ec; ++ * socket.bind(boost::asio::ip::tcp::endpoint( ++ * boost::asio::ip::tcp::v4(), 12345), ec); ++ * if (ec) ++ * { ++ * // An error occurred. ++ * } ++ * @endcode ++ */ ++ BOOST_ASIO_SYNC_OP_VOID bind(const endpoint_type& endpoint, ++ boost::system::error_code& ec) ++ { ++ impl_.get_service().bind(impl_.get_implementation(), endpoint, ec); ++ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); ++ } ++ ++ /// Connect the socket to the specified endpoint. ++ /** ++ * This function is used to connect a socket to the specified remote endpoint. ++ * The function call will block until the connection is successfully made or ++ * an error occurs. ++ * ++ * The socket is automatically opened if it is not already open. If the ++ * connect fails, and the socket was automatically opened, the socket is ++ * not returned to the closed state. ++ * ++ * @param peer_endpoint The remote endpoint to which the socket will be ++ * connected. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ * ++ * @par Example ++ * @code ++ * boost::asio::ip::tcp::socket socket(my_context); ++ * boost::asio::ip::tcp::endpoint endpoint( ++ * boost::asio::ip::address::from_string("1.2.3.4"), 12345); ++ * socket.connect(endpoint); ++ * @endcode ++ */ ++ void connect(const endpoint_type& peer_endpoint) ++ { ++ boost::system::error_code ec; ++ if (!is_open()) ++ { ++ impl_.get_service().open(impl_.get_implementation(), ++ peer_endpoint.protocol(), ec); ++ boost::asio::detail::throw_error(ec, "connect"); ++ } ++ impl_.get_service().connect(impl_.get_implementation(), peer_endpoint, ec); ++ boost::asio::detail::throw_error(ec, "connect"); ++ } ++ ++ /// Connect the socket to the specified endpoint. ++ /** ++ * This function is used to connect a socket to the specified remote endpoint. ++ * The function call will block until the connection is successfully made or ++ * an error occurs. ++ * ++ * The socket is automatically opened if it is not already open. If the ++ * connect fails, and the socket was automatically opened, the socket is ++ * not returned to the closed state. ++ * ++ * @param peer_endpoint The remote endpoint to which the socket will be ++ * connected. ++ * ++ * @param ec Set to indicate what error occurred, if any. ++ * ++ * @par Example ++ * @code ++ * boost::asio::ip::tcp::socket socket(my_context); ++ * boost::asio::ip::tcp::endpoint endpoint( ++ * boost::asio::ip::address::from_string("1.2.3.4"), 12345); ++ * boost::system::error_code ec; ++ * socket.connect(endpoint, ec); ++ * if (ec) ++ * { ++ * // An error occurred. ++ * } ++ * @endcode ++ */ ++ BOOST_ASIO_SYNC_OP_VOID connect(const endpoint_type& peer_endpoint, ++ boost::system::error_code& ec) ++ { ++ if (!is_open()) ++ { ++ impl_.get_service().open(impl_.get_implementation(), ++ peer_endpoint.protocol(), ec); ++ if (ec) ++ { ++ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); ++ } ++ } ++ ++ impl_.get_service().connect(impl_.get_implementation(), peer_endpoint, ec); ++ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); ++ } ++ ++ /// Start an asynchronous connect. ++ /** ++ * This function is used to asynchronously connect a socket to the specified ++ * remote endpoint. The function call always returns immediately. ++ * ++ * The socket is automatically opened if it is not already open. If the ++ * connect fails, and the socket was automatically opened, the socket is ++ * not returned to the closed state. ++ * ++ * @param peer_endpoint The remote endpoint to which the socket will be ++ * connected. Copies will be made of the endpoint object as required. ++ * ++ * @param handler The handler to be called when the connection operation ++ * completes. Copies will be made of the handler as required. The function ++ * signature of the handler must be: ++ * @code void handler( ++ * const boost::system::error_code& error // Result of operation ++ * ); @endcode ++ * Regardless of whether the asynchronous operation completes immediately or ++ * not, the handler will not be invoked from within this function. On ++ * immediate completion, invocation of the handler will be performed in a ++ * manner equivalent to using boost::asio::post(). ++ * ++ * @par Example ++ * @code ++ * void connect_handler(const boost::system::error_code& error) ++ * { ++ * if (!error) ++ * { ++ * // Connect succeeded. ++ * } ++ * } ++ * ++ * ... ++ * ++ * boost::asio::ip::tcp::socket socket(my_context); ++ * boost::asio::ip::tcp::endpoint endpoint( ++ * boost::asio::ip::address::from_string("1.2.3.4"), 12345); ++ * socket.async_connect(endpoint, connect_handler); ++ * @endcode ++ */ ++ template ++ BOOST_ASIO_INITFN_RESULT_TYPE(ConnectHandler, ++ void (boost::system::error_code)) ++ async_connect(const endpoint_type& peer_endpoint, ++ BOOST_ASIO_MOVE_ARG(ConnectHandler) handler) ++ { ++ boost::system::error_code open_ec; ++ if (!is_open()) ++ { ++ const protocol_type protocol = peer_endpoint.protocol(); ++ impl_.get_service().open(impl_.get_implementation(), protocol, open_ec); ++ } ++ ++ return async_initiate( ++ initiate_async_connect(), handler, this, peer_endpoint, open_ec); ++ } ++ ++ /// Set an option on the socket. ++ /** ++ * This function is used to set an option on the socket. ++ * ++ * @param option The new option value to be set on the socket. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ * ++ * @sa SettableSocketOption @n ++ * boost::asio::socket_base::broadcast @n ++ * boost::asio::socket_base::do_not_route @n ++ * boost::asio::socket_base::keep_alive @n ++ * boost::asio::socket_base::linger @n ++ * boost::asio::socket_base::receive_buffer_size @n ++ * boost::asio::socket_base::receive_low_watermark @n ++ * boost::asio::socket_base::reuse_address @n ++ * boost::asio::socket_base::send_buffer_size @n ++ * boost::asio::socket_base::send_low_watermark @n ++ * boost::asio::ip::multicast::join_group @n ++ * boost::asio::ip::multicast::leave_group @n ++ * boost::asio::ip::multicast::enable_loopback @n ++ * boost::asio::ip::multicast::outbound_interface @n ++ * boost::asio::ip::multicast::hops @n ++ * boost::asio::ip::tcp::no_delay ++ * ++ * @par Example ++ * Setting the IPPROTO_TCP/TCP_NODELAY option: ++ * @code ++ * boost::asio::ip::tcp::socket socket(my_context); ++ * ... ++ * boost::asio::ip::tcp::no_delay option(true); ++ * socket.set_option(option); ++ * @endcode ++ */ ++ template ++ void set_option(const SettableSocketOption& option) ++ { ++ boost::system::error_code ec; ++ impl_.get_service().set_option(impl_.get_implementation(), option, ec); ++ boost::asio::detail::throw_error(ec, "set_option"); ++ } ++ ++ /// Set an option on the socket. ++ /** ++ * This function is used to set an option on the socket. ++ * ++ * @param option The new option value to be set on the socket. ++ * ++ * @param ec Set to indicate what error occurred, if any. ++ * ++ * @sa SettableSocketOption @n ++ * boost::asio::socket_base::broadcast @n ++ * boost::asio::socket_base::do_not_route @n ++ * boost::asio::socket_base::keep_alive @n ++ * boost::asio::socket_base::linger @n ++ * boost::asio::socket_base::receive_buffer_size @n ++ * boost::asio::socket_base::receive_low_watermark @n ++ * boost::asio::socket_base::reuse_address @n ++ * boost::asio::socket_base::send_buffer_size @n ++ * boost::asio::socket_base::send_low_watermark @n ++ * boost::asio::ip::multicast::join_group @n ++ * boost::asio::ip::multicast::leave_group @n ++ * boost::asio::ip::multicast::enable_loopback @n ++ * boost::asio::ip::multicast::outbound_interface @n ++ * boost::asio::ip::multicast::hops @n ++ * boost::asio::ip::tcp::no_delay ++ * ++ * @par Example ++ * Setting the IPPROTO_TCP/TCP_NODELAY option: ++ * @code ++ * boost::asio::ip::tcp::socket socket(my_context); ++ * ... ++ * boost::asio::ip::tcp::no_delay option(true); ++ * boost::system::error_code ec; ++ * socket.set_option(option, ec); ++ * if (ec) ++ * { ++ * // An error occurred. ++ * } ++ * @endcode ++ */ ++ template ++ BOOST_ASIO_SYNC_OP_VOID set_option(const SettableSocketOption& option, ++ boost::system::error_code& ec) ++ { ++ impl_.get_service().set_option(impl_.get_implementation(), option, ec); ++ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); ++ } ++ ++ /// Get an option from the socket. ++ /** ++ * This function is used to get the current value of an option on the socket. ++ * ++ * @param option The option value to be obtained from the socket. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ * ++ * @sa GettableSocketOption @n ++ * boost::asio::socket_base::broadcast @n ++ * boost::asio::socket_base::do_not_route @n ++ * boost::asio::socket_base::keep_alive @n ++ * boost::asio::socket_base::linger @n ++ * boost::asio::socket_base::receive_buffer_size @n ++ * boost::asio::socket_base::receive_low_watermark @n ++ * boost::asio::socket_base::reuse_address @n ++ * boost::asio::socket_base::send_buffer_size @n ++ * boost::asio::socket_base::send_low_watermark @n ++ * boost::asio::ip::multicast::join_group @n ++ * boost::asio::ip::multicast::leave_group @n ++ * boost::asio::ip::multicast::enable_loopback @n ++ * boost::asio::ip::multicast::outbound_interface @n ++ * boost::asio::ip::multicast::hops @n ++ * boost::asio::ip::tcp::no_delay ++ * ++ * @par Example ++ * Getting the value of the SOL_SOCKET/SO_KEEPALIVE option: ++ * @code ++ * boost::asio::ip::tcp::socket socket(my_context); ++ * ... ++ * boost::asio::ip::tcp::socket::keep_alive option; ++ * socket.get_option(option); ++ * bool is_set = option.value(); ++ * @endcode ++ */ ++ template ++ void get_option(GettableSocketOption& option) const ++ { ++ boost::system::error_code ec; ++ impl_.get_service().get_option(impl_.get_implementation(), option, ec); ++ boost::asio::detail::throw_error(ec, "get_option"); ++ } ++ ++ /// Get an option from the socket. ++ /** ++ * This function is used to get the current value of an option on the socket. ++ * ++ * @param option The option value to be obtained from the socket. ++ * ++ * @param ec Set to indicate what error occurred, if any. ++ * ++ * @sa GettableSocketOption @n ++ * boost::asio::socket_base::broadcast @n ++ * boost::asio::socket_base::do_not_route @n ++ * boost::asio::socket_base::keep_alive @n ++ * boost::asio::socket_base::linger @n ++ * boost::asio::socket_base::receive_buffer_size @n ++ * boost::asio::socket_base::receive_low_watermark @n ++ * boost::asio::socket_base::reuse_address @n ++ * boost::asio::socket_base::send_buffer_size @n ++ * boost::asio::socket_base::send_low_watermark @n ++ * boost::asio::ip::multicast::join_group @n ++ * boost::asio::ip::multicast::leave_group @n ++ * boost::asio::ip::multicast::enable_loopback @n ++ * boost::asio::ip::multicast::outbound_interface @n ++ * boost::asio::ip::multicast::hops @n ++ * boost::asio::ip::tcp::no_delay ++ * ++ * @par Example ++ * Getting the value of the SOL_SOCKET/SO_KEEPALIVE option: ++ * @code ++ * boost::asio::ip::tcp::socket socket(my_context); ++ * ... ++ * boost::asio::ip::tcp::socket::keep_alive option; ++ * boost::system::error_code ec; ++ * socket.get_option(option, ec); ++ * if (ec) ++ * { ++ * // An error occurred. ++ * } ++ * bool is_set = option.value(); ++ * @endcode ++ */ ++ template ++ BOOST_ASIO_SYNC_OP_VOID get_option(GettableSocketOption& option, ++ boost::system::error_code& ec) const ++ { ++ impl_.get_service().get_option(impl_.get_implementation(), option, ec); ++ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); ++ } ++ ++ /// Perform an IO control command on the socket. ++ /** ++ * This function is used to execute an IO control command on the socket. ++ * ++ * @param command The IO control command to be performed on the socket. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ * ++ * @sa IoControlCommand @n ++ * boost::asio::socket_base::bytes_readable @n ++ * boost::asio::socket_base::non_blocking_io ++ * ++ * @par Example ++ * Getting the number of bytes ready to read: ++ * @code ++ * boost::asio::ip::tcp::socket socket(my_context); ++ * ... ++ * boost::asio::ip::tcp::socket::bytes_readable command; ++ * socket.io_control(command); ++ * std::size_t bytes_readable = command.get(); ++ * @endcode ++ */ ++ template ++ void io_control(IoControlCommand& command) ++ { ++ boost::system::error_code ec; ++ impl_.get_service().io_control(impl_.get_implementation(), command, ec); ++ boost::asio::detail::throw_error(ec, "io_control"); ++ } ++ ++ /// Perform an IO control command on the socket. ++ /** ++ * This function is used to execute an IO control command on the socket. ++ * ++ * @param command The IO control command to be performed on the socket. ++ * ++ * @param ec Set to indicate what error occurred, if any. ++ * ++ * @sa IoControlCommand @n ++ * boost::asio::socket_base::bytes_readable @n ++ * boost::asio::socket_base::non_blocking_io ++ * ++ * @par Example ++ * Getting the number of bytes ready to read: ++ * @code ++ * boost::asio::ip::tcp::socket socket(my_context); ++ * ... ++ * boost::asio::ip::tcp::socket::bytes_readable command; ++ * boost::system::error_code ec; ++ * socket.io_control(command, ec); ++ * if (ec) ++ * { ++ * // An error occurred. ++ * } ++ * std::size_t bytes_readable = command.get(); ++ * @endcode ++ */ ++ template ++ BOOST_ASIO_SYNC_OP_VOID io_control(IoControlCommand& command, ++ boost::system::error_code& ec) ++ { ++ impl_.get_service().io_control(impl_.get_implementation(), command, ec); ++ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); ++ } ++ ++ /// Gets the non-blocking mode of the socket. ++ /** ++ * @returns @c true if the socket's synchronous operations will fail with ++ * boost::asio::error::would_block if they are unable to perform the requested ++ * operation immediately. If @c false, synchronous operations will block ++ * until complete. ++ * ++ * @note The non-blocking mode has no effect on the behaviour of asynchronous ++ * operations. Asynchronous operations will never fail with the error ++ * boost::asio::error::would_block. ++ */ ++ bool non_blocking() const ++ { ++ return impl_.get_service().non_blocking(impl_.get_implementation()); ++ } ++ ++ /// Sets the non-blocking mode of the socket. ++ /** ++ * @param mode If @c true, the socket's synchronous operations will fail with ++ * boost::asio::error::would_block if they are unable to perform the requested ++ * operation immediately. If @c false, synchronous operations will block ++ * until complete. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ * ++ * @note The non-blocking mode has no effect on the behaviour of asynchronous ++ * operations. Asynchronous operations will never fail with the error ++ * boost::asio::error::would_block. ++ */ ++ void non_blocking(bool mode) ++ { ++ boost::system::error_code ec; ++ impl_.get_service().non_blocking(impl_.get_implementation(), mode, ec); ++ boost::asio::detail::throw_error(ec, "non_blocking"); ++ } ++ ++ /// Sets the non-blocking mode of the socket. ++ /** ++ * @param mode If @c true, the socket's synchronous operations will fail with ++ * boost::asio::error::would_block if they are unable to perform the requested ++ * operation immediately. If @c false, synchronous operations will block ++ * until complete. ++ * ++ * @param ec Set to indicate what error occurred, if any. ++ * ++ * @note The non-blocking mode has no effect on the behaviour of asynchronous ++ * operations. Asynchronous operations will never fail with the error ++ * boost::asio::error::would_block. ++ */ ++ BOOST_ASIO_SYNC_OP_VOID non_blocking( ++ bool mode, boost::system::error_code& ec) ++ { ++ impl_.get_service().non_blocking(impl_.get_implementation(), mode, ec); ++ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); ++ } ++ ++ /// Gets the non-blocking mode of the native socket implementation. ++ /** ++ * This function is used to retrieve the non-blocking mode of the underlying ++ * native socket. This mode has no effect on the behaviour of the socket ++ * object's synchronous operations. ++ * ++ * @returns @c true if the underlying socket is in non-blocking mode and ++ * direct system calls may fail with boost::asio::error::would_block (or the ++ * equivalent system error). ++ * ++ * @note The current non-blocking mode is cached by the socket object. ++ * Consequently, the return value may be incorrect if the non-blocking mode ++ * was set directly on the native socket. ++ * ++ * @par Example ++ * This function is intended to allow the encapsulation of arbitrary ++ * non-blocking system calls as asynchronous operations, in a way that is ++ * transparent to the user of the socket object. The following example ++ * illustrates how Linux's @c sendfile system call might be encapsulated: ++ * @code template ++ * struct sendfile_op ++ * { ++ * tcp::socket& sock_; ++ * int fd_; ++ * Handler handler_; ++ * off_t offset_; ++ * std::size_t total_bytes_transferred_; ++ * ++ * // Function call operator meeting WriteHandler requirements. ++ * // Used as the handler for the async_write_some operation. ++ * void operator()(boost::system::error_code ec, std::size_t) ++ * { ++ * // Put the underlying socket into non-blocking mode. ++ * if (!ec) ++ * if (!sock_.native_non_blocking()) ++ * sock_.native_non_blocking(true, ec); ++ * ++ * if (!ec) ++ * { ++ * for (;;) ++ * { ++ * // Try the system call. ++ * errno = 0; ++ * int n = ::sendfile(sock_.native_handle(), fd_, &offset_, 65536); ++ * ec = boost::system::error_code(n < 0 ? errno : 0, ++ * boost::asio::error::get_system_category()); ++ * total_bytes_transferred_ += ec ? 0 : n; ++ * ++ * // Retry operation immediately if interrupted by signal. ++ * if (ec == boost::asio::error::interrupted) ++ * continue; ++ * ++ * // Check if we need to run the operation again. ++ * if (ec == boost::asio::error::would_block ++ * || ec == boost::asio::error::try_again) ++ * { ++ * // We have to wait for the socket to become ready again. ++ * sock_.async_wait(tcp::socket::wait_write, *this); ++ * return; ++ * } ++ * ++ * if (ec || n == 0) ++ * { ++ * // An error occurred, or we have reached the end of the file. ++ * // Either way we must exit the loop so we can call the handler. ++ * break; ++ * } ++ * ++ * // Loop around to try calling sendfile again. ++ * } ++ * } ++ * ++ * // Pass result back to user's handler. ++ * handler_(ec, total_bytes_transferred_); ++ * } ++ * }; ++ * ++ * template ++ * void async_sendfile(tcp::socket& sock, int fd, Handler h) ++ * { ++ * sendfile_op op = { sock, fd, h, 0, 0 }; ++ * sock.async_wait(tcp::socket::wait_write, op); ++ * } @endcode ++ */ ++ bool native_non_blocking() const ++ { ++ return impl_.get_service().native_non_blocking(impl_.get_implementation()); ++ } ++ ++ /// Sets the non-blocking mode of the native socket implementation. ++ /** ++ * This function is used to modify the non-blocking mode of the underlying ++ * native socket. It has no effect on the behaviour of the socket object's ++ * synchronous operations. ++ * ++ * @param mode If @c true, the underlying socket is put into non-blocking ++ * mode and direct system calls may fail with boost::asio::error::would_block ++ * (or the equivalent system error). ++ * ++ * @throws boost::system::system_error Thrown on failure. If the @c mode is ++ * @c false, but the current value of @c non_blocking() is @c true, this ++ * function fails with boost::asio::error::invalid_argument, as the ++ * combination does not make sense. ++ * ++ * @par Example ++ * This function is intended to allow the encapsulation of arbitrary ++ * non-blocking system calls as asynchronous operations, in a way that is ++ * transparent to the user of the socket object. The following example ++ * illustrates how Linux's @c sendfile system call might be encapsulated: ++ * @code template ++ * struct sendfile_op ++ * { ++ * tcp::socket& sock_; ++ * int fd_; ++ * Handler handler_; ++ * off_t offset_; ++ * std::size_t total_bytes_transferred_; ++ * ++ * // Function call operator meeting WriteHandler requirements. ++ * // Used as the handler for the async_write_some operation. ++ * void operator()(boost::system::error_code ec, std::size_t) ++ * { ++ * // Put the underlying socket into non-blocking mode. ++ * if (!ec) ++ * if (!sock_.native_non_blocking()) ++ * sock_.native_non_blocking(true, ec); ++ * ++ * if (!ec) ++ * { ++ * for (;;) ++ * { ++ * // Try the system call. ++ * errno = 0; ++ * int n = ::sendfile(sock_.native_handle(), fd_, &offset_, 65536); ++ * ec = boost::system::error_code(n < 0 ? errno : 0, ++ * boost::asio::error::get_system_category()); ++ * total_bytes_transferred_ += ec ? 0 : n; ++ * ++ * // Retry operation immediately if interrupted by signal. ++ * if (ec == boost::asio::error::interrupted) ++ * continue; ++ * ++ * // Check if we need to run the operation again. ++ * if (ec == boost::asio::error::would_block ++ * || ec == boost::asio::error::try_again) ++ * { ++ * // We have to wait for the socket to become ready again. ++ * sock_.async_wait(tcp::socket::wait_write, *this); ++ * return; ++ * } ++ * ++ * if (ec || n == 0) ++ * { ++ * // An error occurred, or we have reached the end of the file. ++ * // Either way we must exit the loop so we can call the handler. ++ * break; ++ * } ++ * ++ * // Loop around to try calling sendfile again. ++ * } ++ * } ++ * ++ * // Pass result back to user's handler. ++ * handler_(ec, total_bytes_transferred_); ++ * } ++ * }; ++ * ++ * template ++ * void async_sendfile(tcp::socket& sock, int fd, Handler h) ++ * { ++ * sendfile_op op = { sock, fd, h, 0, 0 }; ++ * sock.async_wait(tcp::socket::wait_write, op); ++ * } @endcode ++ */ ++ void native_non_blocking(bool mode) ++ { ++ boost::system::error_code ec; ++ impl_.get_service().native_non_blocking( ++ impl_.get_implementation(), mode, ec); ++ boost::asio::detail::throw_error(ec, "native_non_blocking"); ++ } ++ ++ /// Sets the non-blocking mode of the native socket implementation. ++ /** ++ * This function is used to modify the non-blocking mode of the underlying ++ * native socket. It has no effect on the behaviour of the socket object's ++ * synchronous operations. ++ * ++ * @param mode If @c true, the underlying socket is put into non-blocking ++ * mode and direct system calls may fail with boost::asio::error::would_block ++ * (or the equivalent system error). ++ * ++ * @param ec Set to indicate what error occurred, if any. If the @c mode is ++ * @c false, but the current value of @c non_blocking() is @c true, this ++ * function fails with boost::asio::error::invalid_argument, as the ++ * combination does not make sense. ++ * ++ * @par Example ++ * This function is intended to allow the encapsulation of arbitrary ++ * non-blocking system calls as asynchronous operations, in a way that is ++ * transparent to the user of the socket object. The following example ++ * illustrates how Linux's @c sendfile system call might be encapsulated: ++ * @code template ++ * struct sendfile_op ++ * { ++ * tcp::socket& sock_; ++ * int fd_; ++ * Handler handler_; ++ * off_t offset_; ++ * std::size_t total_bytes_transferred_; ++ * ++ * // Function call operator meeting WriteHandler requirements. ++ * // Used as the handler for the async_write_some operation. ++ * void operator()(boost::system::error_code ec, std::size_t) ++ * { ++ * // Put the underlying socket into non-blocking mode. ++ * if (!ec) ++ * if (!sock_.native_non_blocking()) ++ * sock_.native_non_blocking(true, ec); ++ * ++ * if (!ec) ++ * { ++ * for (;;) ++ * { ++ * // Try the system call. ++ * errno = 0; ++ * int n = ::sendfile(sock_.native_handle(), fd_, &offset_, 65536); ++ * ec = boost::system::error_code(n < 0 ? errno : 0, ++ * boost::asio::error::get_system_category()); ++ * total_bytes_transferred_ += ec ? 0 : n; ++ * ++ * // Retry operation immediately if interrupted by signal. ++ * if (ec == boost::asio::error::interrupted) ++ * continue; ++ * ++ * // Check if we need to run the operation again. ++ * if (ec == boost::asio::error::would_block ++ * || ec == boost::asio::error::try_again) ++ * { ++ * // We have to wait for the socket to become ready again. ++ * sock_.async_wait(tcp::socket::wait_write, *this); ++ * return; ++ * } ++ * ++ * if (ec || n == 0) ++ * { ++ * // An error occurred, or we have reached the end of the file. ++ * // Either way we must exit the loop so we can call the handler. ++ * break; ++ * } ++ * ++ * // Loop around to try calling sendfile again. ++ * } ++ * } ++ * ++ * // Pass result back to user's handler. ++ * handler_(ec, total_bytes_transferred_); ++ * } ++ * }; ++ * ++ * template ++ * void async_sendfile(tcp::socket& sock, int fd, Handler h) ++ * { ++ * sendfile_op op = { sock, fd, h, 0, 0 }; ++ * sock.async_wait(tcp::socket::wait_write, op); ++ * } @endcode ++ */ ++ BOOST_ASIO_SYNC_OP_VOID native_non_blocking( ++ bool mode, boost::system::error_code& ec) ++ { ++ impl_.get_service().native_non_blocking( ++ impl_.get_implementation(), mode, ec); ++ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); ++ } ++ ++ /// Get the local endpoint of the socket. ++ /** ++ * This function is used to obtain the locally bound endpoint of the socket. ++ * ++ * @returns An object that represents the local endpoint of the socket. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ * ++ * @par Example ++ * @code ++ * boost::asio::ip::tcp::socket socket(my_context); ++ * ... ++ * boost::asio::ip::tcp::endpoint endpoint = socket.local_endpoint(); ++ * @endcode ++ */ ++ endpoint_type local_endpoint() const ++ { ++ boost::system::error_code ec; ++ endpoint_type ep = impl_.get_service().local_endpoint( ++ impl_.get_implementation(), ec); ++ boost::asio::detail::throw_error(ec, "local_endpoint"); ++ return ep; ++ } ++ ++ /// Get the local endpoint of the socket. ++ /** ++ * This function is used to obtain the locally bound endpoint of the socket. ++ * ++ * @param ec Set to indicate what error occurred, if any. ++ * ++ * @returns An object that represents the local endpoint of the socket. ++ * Returns a default-constructed endpoint object if an error occurred. ++ * ++ * @par Example ++ * @code ++ * boost::asio::ip::tcp::socket socket(my_context); ++ * ... ++ * boost::system::error_code ec; ++ * boost::asio::ip::tcp::endpoint endpoint = socket.local_endpoint(ec); ++ * if (ec) ++ * { ++ * // An error occurred. ++ * } ++ * @endcode ++ */ ++ endpoint_type local_endpoint(boost::system::error_code& ec) const ++ { ++ return impl_.get_service().local_endpoint(impl_.get_implementation(), ec); ++ } ++ ++ /// Get the remote endpoint of the socket. ++ /** ++ * This function is used to obtain the remote endpoint of the socket. ++ * ++ * @returns An object that represents the remote endpoint of the socket. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ * ++ * @par Example ++ * @code ++ * boost::asio::ip::tcp::socket socket(my_context); ++ * ... ++ * boost::asio::ip::tcp::endpoint endpoint = socket.remote_endpoint(); ++ * @endcode ++ */ ++ endpoint_type remote_endpoint() const ++ { ++ boost::system::error_code ec; ++ endpoint_type ep = impl_.get_service().remote_endpoint( ++ impl_.get_implementation(), ec); ++ boost::asio::detail::throw_error(ec, "remote_endpoint"); ++ return ep; ++ } ++ ++ /// Get the remote endpoint of the socket. ++ /** ++ * This function is used to obtain the remote endpoint of the socket. ++ * ++ * @param ec Set to indicate what error occurred, if any. ++ * ++ * @returns An object that represents the remote endpoint of the socket. ++ * Returns a default-constructed endpoint object if an error occurred. ++ * ++ * @par Example ++ * @code ++ * boost::asio::ip::tcp::socket socket(my_context); ++ * ... ++ * boost::system::error_code ec; ++ * boost::asio::ip::tcp::endpoint endpoint = socket.remote_endpoint(ec); ++ * if (ec) ++ * { ++ * // An error occurred. ++ * } ++ * @endcode ++ */ ++ endpoint_type remote_endpoint(boost::system::error_code& ec) const ++ { ++ return impl_.get_service().remote_endpoint(impl_.get_implementation(), ec); ++ } ++ ++ /// Disable sends or receives on the socket. ++ /** ++ * This function is used to disable send operations, receive operations, or ++ * both. ++ * ++ * @param what Determines what types of operation will no longer be allowed. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ * ++ * @par Example ++ * Shutting down the send side of the socket: ++ * @code ++ * boost::asio::ip::tcp::socket socket(my_context); ++ * ... ++ * socket.shutdown(boost::asio::ip::tcp::socket::shutdown_send); ++ * @endcode ++ */ ++ void shutdown(shutdown_type what) ++ { ++ boost::system::error_code ec; ++ impl_.get_service().shutdown(impl_.get_implementation(), what, ec); ++ boost::asio::detail::throw_error(ec, "shutdown"); ++ } ++ ++ /// Disable sends or receives on the socket. ++ /** ++ * This function is used to disable send operations, receive operations, or ++ * both. ++ * ++ * @param what Determines what types of operation will no longer be allowed. ++ * ++ * @param ec Set to indicate what error occurred, if any. ++ * ++ * @par Example ++ * Shutting down the send side of the socket: ++ * @code ++ * boost::asio::ip::tcp::socket socket(my_context); ++ * ... ++ * boost::system::error_code ec; ++ * socket.shutdown(boost::asio::ip::tcp::socket::shutdown_send, ec); ++ * if (ec) ++ * { ++ * // An error occurred. ++ * } ++ * @endcode ++ */ ++ BOOST_ASIO_SYNC_OP_VOID shutdown(shutdown_type what, ++ boost::system::error_code& ec) ++ { ++ impl_.get_service().shutdown(impl_.get_implementation(), what, ec); ++ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); ++ } ++ ++ /// Wait for the socket to become ready to read, ready to write, or to have ++ /// pending error conditions. ++ /** ++ * This function is used to perform a blocking wait for a socket to enter ++ * a ready to read, write or error condition state. ++ * ++ * @param w Specifies the desired socket state. ++ * ++ * @par Example ++ * Waiting for a socket to become readable. ++ * @code ++ * boost::asio::ip::tcp::socket socket(my_context); ++ * ... ++ * socket.wait(boost::asio::ip::tcp::socket::wait_read); ++ * @endcode ++ */ ++ void wait(wait_type w) ++ { ++ boost::system::error_code ec; ++ impl_.get_service().wait(impl_.get_implementation(), w, ec); ++ boost::asio::detail::throw_error(ec, "wait"); ++ } ++ ++ /// Wait for the socket to become ready to read, ready to write, or to have ++ /// pending error conditions. ++ /** ++ * This function is used to perform a blocking wait for a socket to enter ++ * a ready to read, write or error condition state. ++ * ++ * @param w Specifies the desired socket state. ++ * ++ * @param ec Set to indicate what error occurred, if any. ++ * ++ * @par Example ++ * Waiting for a socket to become readable. ++ * @code ++ * boost::asio::ip::tcp::socket socket(my_context); ++ * ... ++ * boost::system::error_code ec; ++ * socket.wait(boost::asio::ip::tcp::socket::wait_read, ec); ++ * @endcode ++ */ ++ BOOST_ASIO_SYNC_OP_VOID wait(wait_type w, boost::system::error_code& ec) ++ { ++ impl_.get_service().wait(impl_.get_implementation(), w, ec); ++ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); ++ } ++ ++ /// Asynchronously wait for the socket to become ready to read, ready to ++ /// write, or to have pending error conditions. ++ /** ++ * This function is used to perform an asynchronous wait for a socket to enter ++ * a ready to read, write or error condition state. ++ * ++ * @param w Specifies the desired socket state. ++ * ++ * @param handler The handler to be called when the wait operation completes. ++ * Copies will be made of the handler as required. The function signature of ++ * the handler must be: ++ * @code void handler( ++ * const boost::system::error_code& error // Result of operation ++ * ); @endcode ++ * Regardless of whether the asynchronous operation completes immediately or ++ * not, the handler will not be invoked from within this function. On ++ * immediate completion, invocation of the handler will be performed in a ++ * manner equivalent to using boost::asio::post(). ++ * ++ * @par Example ++ * @code ++ * void wait_handler(const boost::system::error_code& error) ++ * { ++ * if (!error) ++ * { ++ * // Wait succeeded. ++ * } ++ * } ++ * ++ * ... ++ * ++ * boost::asio::ip::tcp::socket socket(my_context); ++ * ... ++ * socket.async_wait(boost::asio::ip::tcp::socket::wait_read, wait_handler); ++ * @endcode ++ */ ++ template ++ BOOST_ASIO_INITFN_RESULT_TYPE(WaitHandler, ++ void (boost::system::error_code)) ++ async_wait(wait_type w, BOOST_ASIO_MOVE_ARG(WaitHandler) handler) ++ { ++ return async_initiate( ++ initiate_async_wait(), handler, this, w); ++ } ++ ++protected: ++ /// Protected destructor to prevent deletion through this type. ++ /** ++ * This function destroys the socket, cancelling any outstanding asynchronous ++ * operations associated with the socket as if by calling @c cancel. ++ */ ++ ~basic_socket_ext() ++ { ++ } ++ ++#if defined(BOOST_ASIO_WINDOWS_RUNTIME) ++ detail::io_object_impl< ++ detail::null_socket_service, Executor> impl_; ++#elif defined(BOOST_ASIO_HAS_IOCP) ++ detail::io_object_impl< ++ detail::win_iocp_socket_service, Executor> impl_; ++#else ++ detail::io_object_impl< ++ detail::reactive_socket_service_ext, Executor> impl_; ++#endif ++ ++private: ++ // Disallow copying and assignment. ++ basic_socket_ext(const basic_socket_ext&) BOOST_ASIO_DELETED; ++ basic_socket_ext& operator=(const basic_socket_ext&) BOOST_ASIO_DELETED; ++ ++ struct initiate_async_connect ++ { ++ template ++ void operator()(BOOST_ASIO_MOVE_ARG(ConnectHandler) handler, ++ basic_socket_ext* self, const endpoint_type& peer_endpoint, ++ const boost::system::error_code& open_ec) const ++ { ++ // If you get an error on the following line it means that your handler ++ // does not meet the documented type requirements for a ConnectHandler. ++ BOOST_ASIO_CONNECT_HANDLER_CHECK(ConnectHandler, handler) type_check; ++ ++ if (open_ec) ++ { ++ boost::asio::post(self->impl_.get_executor(), ++ boost::asio::detail::bind_handler( ++ BOOST_ASIO_MOVE_CAST(ConnectHandler)(handler), open_ec)); ++ } ++ else ++ { ++ detail::non_const_lvalue handler2(handler); ++ self->impl_.get_service().async_connect( ++ self->impl_.get_implementation(), peer_endpoint, ++ handler2.value, self->impl_.get_implementation_executor()); ++ } ++ } ++ }; ++ ++ struct initiate_async_wait ++ { ++ template ++ void operator()(BOOST_ASIO_MOVE_ARG(WaitHandler) handler, ++ basic_socket_ext* self, wait_type w) const ++ { ++ // If you get an error on the following line it means that your handler ++ // does not meet the documented type requirements for a WaitHandler. ++ BOOST_ASIO_WAIT_HANDLER_CHECK(WaitHandler, handler) type_check; ++ ++ detail::non_const_lvalue handler2(handler); ++ self->impl_.get_service().async_wait( ++ self->impl_.get_implementation(), w, handler2.value, ++ self->impl_.get_implementation_executor()); ++ } ++ }; ++}; ++ ++} // namespace asio ++} // namespace boost ++ ++#include ++ ++#endif // BOOST_ASIO_BASIC_SOCKET_EXT_HPP +diff --git a/implementation/helper/1.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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#if defined(BOOST_ASIO_WINDOWS_RUNTIME) ++# include ++#elif defined(BOOST_ASIO_HAS_IOCP) ++# include ++#else ++# include ++#endif ++ ++#if defined(BOOST_ASIO_HAS_MOVE) ++# include ++#endif // defined(BOOST_ASIO_HAS_MOVE) ++ ++#include ++ ++namespace boost { ++namespace asio { ++ ++#if !defined(BOOST_ASIO_BASIC_SOCKET_EXT_LOCAL_FWD_DECL) ++#define BOOST_ASIO_BASIC_SOCKET_EXT_LOCAL_FWD_DECL ++ ++// Forward declaration with defaulted arguments. ++template ++class basic_socket_ext_local; ++ ++#endif // !defined(BOOST_ASIO_BASIC_SOCKET_EXT_LOCAL_FWD_DECL) ++ ++/// Provides socket functionality. ++/** ++ * The basic_socket class template provides functionality that is common to both ++ * stream-oriented and datagram-oriented sockets. ++ * ++ * @par Thread Safety ++ * @e Distinct @e objects: Safe.@n ++ * @e Shared @e objects: Unsafe. ++ */ ++template ++class basic_socket_ext_local ++ : public socket_base ++{ ++public: ++ /// The type of the executor associated with the object. ++ typedef Executor executor_type; ++ ++ /// Rebinds the socket type to another executor. ++ template ++ struct rebind_executor ++ { ++ /// The socket type when rebound to the specified executor. ++ typedef basic_socket_ext_local other; ++ }; ++ ++ /// The native representation of a socket. ++#if defined(GENERATING_DOCUMENTATION) ++ typedef implementation_defined native_handle_type; ++#elif defined(BOOST_ASIO_WINDOWS_RUNTIME) ++ typedef typename detail::null_socket_service< ++ Protocol>::native_handle_type native_handle_type; ++#elif defined(BOOST_ASIO_HAS_IOCP) ++ typedef typename detail::win_iocp_socket_service< ++ Protocol>::native_handle_type native_handle_type; ++#else ++ typedef typename detail::reactive_socket_service_ext_local< ++ Protocol>::native_handle_type native_handle_type; ++#endif ++ ++ /// The protocol type. ++ typedef Protocol protocol_type; ++ ++ /// The endpoint type. ++ typedef typename Protocol::endpoint endpoint_type; ++ ++#if !defined(BOOST_ASIO_NO_EXTENSIONS) ++ /// A basic_socket is always the lowest layer. ++ typedef basic_socket_ext_local lowest_layer_type; ++#endif // !defined(BOOST_ASIO_NO_EXTENSIONS) ++ ++ /// Construct a basic_socket without opening it. ++ /** ++ * This constructor creates a socket without opening it. ++ * ++ * @param ex The I/O executor that the socket will use, by default, to ++ * dispatch handlers for any asynchronous operations performed on the socket. ++ */ ++ explicit basic_socket_ext_local(const executor_type& ex) ++ : impl_(0, ex) ++ { ++ } ++ ++ /// Construct a basic_socket without opening it. ++ /** ++ * This constructor creates a socket without opening it. ++ * ++ * @param context An execution context which provides the I/O executor that ++ * the socket will use, by default, to dispatch handlers for any asynchronous ++ * operations performed on the socket. ++ */ ++ template ++ explicit basic_socket_ext_local(ExecutionContext& context, ++ typename enable_if< ++ is_convertible::value ++ >::type* = 0) ++ : impl_(0, 0, context) ++ { ++ } ++ ++ /// Construct and open a basic_socket. ++ /** ++ * This constructor creates and opens a socket. ++ * ++ * @param ex The I/O executor that the socket will use, by default, to ++ * dispatch handlers for any asynchronous operations performed on the socket. ++ * ++ * @param protocol An object specifying protocol parameters to be used. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ */ ++ basic_socket_ext_local(const executor_type& ex, const protocol_type& protocol) ++ : impl_(0, ex) ++ { ++ boost::system::error_code ec; ++ impl_.get_service().open(impl_.get_implementation(), protocol, ec); ++ boost::asio::detail::throw_error(ec, "open"); ++ } ++ ++ /// Construct and open a basic_socket. ++ /** ++ * This constructor creates and opens a socket. ++ * ++ * @param context An execution context which provides the I/O executor that ++ * the socket will use, by default, to dispatch handlers for any asynchronous ++ * operations performed on the socket. ++ * ++ * @param protocol An object specifying protocol parameters to be used. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ */ ++ template ++ basic_socket_ext_local(ExecutionContext& context, const protocol_type& protocol, ++ typename enable_if< ++ is_convertible::value ++ >::type* = 0) ++ : impl_(0, 0, context) ++ { ++ boost::system::error_code ec; ++ impl_.get_service().open(impl_.get_implementation(), protocol, ec); ++ boost::asio::detail::throw_error(ec, "open"); ++ } ++ ++ /// Construct a basic_socket, opening it and binding it to the given local ++ /// endpoint. ++ /** ++ * This constructor creates a socket and automatically opens it bound to the ++ * specified endpoint on the local machine. The protocol used is the protocol ++ * associated with the given endpoint. ++ * ++ * @param ex The I/O executor that the socket will use, by default, to ++ * dispatch handlers for any asynchronous operations performed on the socket. ++ * ++ * @param endpoint An endpoint on the local machine to which the socket will ++ * be bound. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ */ ++ basic_socket_ext_local(const executor_type& ex, const endpoint_type& endpoint) ++ : impl_(0, ex) ++ { ++ boost::system::error_code ec; ++ const protocol_type protocol = endpoint.protocol(); ++ impl_.get_service().open(impl_.get_implementation(), protocol, ec); ++ boost::asio::detail::throw_error(ec, "open"); ++ impl_.get_service().bind(impl_.get_implementation(), endpoint, ec); ++ boost::asio::detail::throw_error(ec, "bind"); ++ } ++ ++ /// Construct a basic_socket, opening it and binding it to the given local ++ /// endpoint. ++ /** ++ * This constructor creates a socket and automatically opens it bound to the ++ * specified endpoint on the local machine. The protocol used is the protocol ++ * associated with the given endpoint. ++ * ++ * @param context An execution context which provides the I/O executor that ++ * the socket will use, by default, to dispatch handlers for any asynchronous ++ * operations performed on the socket. ++ * ++ * @param endpoint An endpoint on the local machine to which the socket will ++ * be bound. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ */ ++ template ++ basic_socket_ext_local(ExecutionContext& context, const endpoint_type& endpoint, ++ typename enable_if< ++ is_convertible::value ++ >::type* = 0) ++ : impl_(0, 0, context) ++ { ++ boost::system::error_code ec; ++ const protocol_type protocol = endpoint.protocol(); ++ impl_.get_service().open(impl_.get_implementation(), protocol, ec); ++ boost::asio::detail::throw_error(ec, "open"); ++ impl_.get_service().bind(impl_.get_implementation(), endpoint, ec); ++ boost::asio::detail::throw_error(ec, "bind"); ++ } ++ ++ /// Construct a basic_socket on an existing native socket. ++ /** ++ * This constructor creates a socket object to hold an existing native socket. ++ * ++ * @param ex The I/O executor that the socket will use, by default, to ++ * dispatch handlers for any asynchronous operations performed on the socket. ++ * ++ * @param protocol An object specifying protocol parameters to be used. ++ * ++ * @param native_socket A native socket. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ */ ++ basic_socket_ext_local(const executor_type& ex, const protocol_type& protocol, ++ const native_handle_type& native_socket) ++ : impl_(0, ex) ++ { ++ boost::system::error_code ec; ++ impl_.get_service().assign(impl_.get_implementation(), ++ protocol, native_socket, ec); ++ boost::asio::detail::throw_error(ec, "assign"); ++ } ++ ++ /// Construct a basic_socket on an existing native socket. ++ /** ++ * This constructor creates a socket object to hold an existing native socket. ++ * ++ * @param context An execution context which provides the I/O executor that ++ * the socket will use, by default, to dispatch handlers for any asynchronous ++ * operations performed on the socket. ++ * ++ * @param protocol An object specifying protocol parameters to be used. ++ * ++ * @param native_socket A native socket. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ */ ++ template ++ basic_socket_ext_local(ExecutionContext& context, const protocol_type& protocol, ++ const native_handle_type& native_socket, ++ typename enable_if< ++ is_convertible::value ++ >::type* = 0) ++ : impl_(0, 0, context) ++ { ++ boost::system::error_code ec; ++ impl_.get_service().assign(impl_.get_implementation(), ++ protocol, native_socket, ec); ++ boost::asio::detail::throw_error(ec, "assign"); ++ } ++ ++#if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) ++ /// Move-construct a basic_socket from another. ++ /** ++ * This constructor moves a socket from one object to another. ++ * ++ * @param other The other basic_socket object from which the move will ++ * occur. ++ * ++ * @note Following the move, the moved-from object is in the same state as if ++ * constructed using the @c basic_socket(const executor_type&) constructor. ++ */ ++ basic_socket_ext_local(basic_socket_ext_local&& other) ++ : impl_(std::move(other.impl_)) ++ { ++ } ++ ++ /// Move-assign a basic_socket from another. ++ /** ++ * This assignment operator moves a socket from one object to another. ++ * ++ * @param other The other basic_socket object from which the move will ++ * occur. ++ * ++ * @note Following the move, the moved-from object is in the same state as if ++ * constructed using the @c basic_socket(const executor_type&) constructor. ++ */ ++ basic_socket_ext_local& operator=(basic_socket_ext_local&& other) ++ { ++ impl_ = std::move(other.impl_); ++ return *this; ++ } ++ ++ // All sockets have access to each other's implementations. ++ template ++ friend class basic_socket_ext_local; ++ ++ /// Move-construct a basic_socket from a socket of another protocol type. ++ /** ++ * This constructor moves a socket from one object to another. ++ * ++ * @param other The other basic_socket object from which the move will ++ * occur. ++ * ++ * @note Following the move, the moved-from object is in the same state as if ++ * constructed using the @c basic_socket(const executor_type&) constructor. ++ */ ++ template ++ basic_socket_ext_local(basic_socket_ext_local&& other, ++ typename enable_if< ++ is_convertible::value ++ && is_convertible::value ++ >::type* = 0) ++ : impl_(std::move(other.impl_)) ++ { ++ } ++ ++ /// Move-assign a basic_socket from a socket of another protocol type. ++ /** ++ * This assignment operator moves a socket from one object to another. ++ * ++ * @param other The other basic_socket object from which the move will ++ * occur. ++ * ++ * @note Following the move, the moved-from object is in the same state as if ++ * constructed using the @c basic_socket(const executor_type&) constructor. ++ */ ++ template ++ typename enable_if< ++ is_convertible::value ++ && is_convertible::value, ++ basic_socket_ext_local& ++ >::type operator=(basic_socket_ext_local && other) ++ { ++ basic_socket_ext_local tmp(std::move(other)); ++ impl_ = std::move(tmp.impl_); ++ return *this; ++ } ++#endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) ++ ++ /// Get the executor associated with the object. ++ executor_type get_executor() BOOST_ASIO_NOEXCEPT ++ { ++ return impl_.get_executor(); ++ } ++ ++#if !defined(BOOST_ASIO_NO_EXTENSIONS) ++ /// Get a reference to the lowest layer. ++ /** ++ * This function returns a reference to the lowest layer in a stack of ++ * layers. Since a basic_socket cannot contain any further layers, it simply ++ * returns a reference to itself. ++ * ++ * @return A reference to the lowest layer in the stack of layers. Ownership ++ * is not transferred to the caller. ++ */ ++ lowest_layer_type& lowest_layer() ++ { ++ return *this; ++ } ++ ++ /// Get a const reference to the lowest layer. ++ /** ++ * This function returns a const reference to the lowest layer in a stack of ++ * layers. Since a basic_socket cannot contain any further layers, it simply ++ * returns a reference to itself. ++ * ++ * @return A const reference to the lowest layer in the stack of layers. ++ * Ownership is not transferred to the caller. ++ */ ++ const lowest_layer_type& lowest_layer() const ++ { ++ return *this; ++ } ++#endif // !defined(BOOST_ASIO_NO_EXTENSIONS) ++ ++ /// Open the socket using the specified protocol. ++ /** ++ * This function opens the socket so that it will use the specified protocol. ++ * ++ * @param protocol An object specifying protocol parameters to be used. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ * ++ * @par Example ++ * @code ++ * boost::asio::ip::tcp::socket socket(my_context); ++ * socket.open(boost::asio::ip::tcp::v4()); ++ * @endcode ++ */ ++ void open(const protocol_type& protocol = protocol_type()) ++ { ++ boost::system::error_code ec; ++ impl_.get_service().open(impl_.get_implementation(), protocol, ec); ++ boost::asio::detail::throw_error(ec, "open"); ++ } ++ ++ /// Open the socket using the specified protocol. ++ /** ++ * This function opens the socket so that it will use the specified protocol. ++ * ++ * @param protocol An object specifying which protocol is to be used. ++ * ++ * @param ec Set to indicate what error occurred, if any. ++ * ++ * @par Example ++ * @code ++ * boost::asio::ip::tcp::socket socket(my_context); ++ * boost::system::error_code ec; ++ * socket.open(boost::asio::ip::tcp::v4(), ec); ++ * if (ec) ++ * { ++ * // An error occurred. ++ * } ++ * @endcode ++ */ ++ BOOST_ASIO_SYNC_OP_VOID open(const protocol_type& protocol, ++ boost::system::error_code& ec) ++ { ++ impl_.get_service().open(impl_.get_implementation(), protocol, ec); ++ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); ++ } ++ ++ /// Assign an existing native socket to the socket. ++ /* ++ * This function opens the socket to hold an existing native socket. ++ * ++ * @param protocol An object specifying which protocol is to be used. ++ * ++ * @param native_socket A native socket. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ */ ++ void assign(const protocol_type& protocol, ++ const native_handle_type& native_socket) ++ { ++ boost::system::error_code ec; ++ impl_.get_service().assign(impl_.get_implementation(), ++ protocol, native_socket, ec); ++ boost::asio::detail::throw_error(ec, "assign"); ++ } ++ ++ /// Assign an existing native socket to the socket. ++ /* ++ * This function opens the socket to hold an existing native socket. ++ * ++ * @param protocol An object specifying which protocol is to be used. ++ * ++ * @param native_socket A native socket. ++ * ++ * @param ec Set to indicate what error occurred, if any. ++ */ ++ BOOST_ASIO_SYNC_OP_VOID assign(const protocol_type& protocol, ++ const native_handle_type& native_socket, boost::system::error_code& ec) ++ { ++ impl_.get_service().assign(impl_.get_implementation(), ++ protocol, native_socket, ec); ++ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); ++ } ++ ++ /// Determine whether the socket is open. ++ bool is_open() const ++ { ++ return impl_.get_service().is_open(impl_.get_implementation()); ++ } ++ ++ /// Close the socket. ++ /** ++ * This function is used to close the socket. Any asynchronous send, receive ++ * or connect operations will be cancelled immediately, and will complete ++ * with the boost::asio::error::operation_aborted error. ++ * ++ * @throws boost::system::system_error Thrown on failure. Note that, even if ++ * the function indicates an error, the underlying descriptor is closed. ++ * ++ * @note For portable behaviour with respect to graceful closure of a ++ * connected socket, call shutdown() before closing the socket. ++ */ ++ void close() ++ { ++ boost::system::error_code ec; ++ impl_.get_service().close(impl_.get_implementation(), ec); ++ boost::asio::detail::throw_error(ec, "close"); ++ } ++ ++ /// Close the socket. ++ /** ++ * This function is used to close the socket. Any asynchronous send, receive ++ * or connect operations will be cancelled immediately, and will complete ++ * with the boost::asio::error::operation_aborted error. ++ * ++ * @param ec Set to indicate what error occurred, if any. Note that, even if ++ * the function indicates an error, the underlying descriptor is closed. ++ * ++ * @par Example ++ * @code ++ * boost::asio::ip::tcp::socket socket(my_context); ++ * ... ++ * boost::system::error_code ec; ++ * socket.close(ec); ++ * if (ec) ++ * { ++ * // An error occurred. ++ * } ++ * @endcode ++ * ++ * @note For portable behaviour with respect to graceful closure of a ++ * connected socket, call shutdown() before closing the socket. ++ */ ++ BOOST_ASIO_SYNC_OP_VOID close(boost::system::error_code& ec) ++ { ++ impl_.get_service().close(impl_.get_implementation(), ec); ++ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); ++ } ++ ++ /// Release ownership of the underlying native socket. ++ /** ++ * This function causes all outstanding asynchronous connect, send and receive ++ * operations to finish immediately, and the handlers for cancelled operations ++ * will be passed the boost::asio::error::operation_aborted error. Ownership ++ * of the native socket is then transferred to the caller. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ * ++ * @note This function is unsupported on Windows versions prior to Windows ++ * 8.1, and will fail with boost::asio::error::operation_not_supported on ++ * these platforms. ++ */ ++#if defined(BOOST_ASIO_MSVC) && (BOOST_ASIO_MSVC >= 1400) \ ++ && (!defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0603) ++ __declspec(deprecated("This function always fails with " ++ "operation_not_supported when used on Windows versions " ++ "prior to Windows 8.1.")) ++#endif ++ native_handle_type release() ++ { ++ boost::system::error_code ec; ++ native_handle_type s = impl_.get_service().release( ++ impl_.get_implementation(), ec); ++ boost::asio::detail::throw_error(ec, "release"); ++ return s; ++ } ++ ++ /// Release ownership of the underlying native socket. ++ /** ++ * This function causes all outstanding asynchronous connect, send and receive ++ * operations to finish immediately, and the handlers for cancelled operations ++ * will be passed the boost::asio::error::operation_aborted error. Ownership ++ * of the native socket is then transferred to the caller. ++ * ++ * @param ec Set to indicate what error occurred, if any. ++ * ++ * @note This function is unsupported on Windows versions prior to Windows ++ * 8.1, and will fail with boost::asio::error::operation_not_supported on ++ * these platforms. ++ */ ++#if defined(BOOST_ASIO_MSVC) && (BOOST_ASIO_MSVC >= 1400) \ ++ && (!defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0603) ++ __declspec(deprecated("This function always fails with " ++ "operation_not_supported when used on Windows versions " ++ "prior to Windows 8.1.")) ++#endif ++ native_handle_type release(boost::system::error_code& ec) ++ { ++ return impl_.get_service().release(impl_.get_implementation(), ec); ++ } ++ ++ /// Get the native socket representation. ++ /** ++ * This function may be used to obtain the underlying representation of the ++ * socket. This is intended to allow access to native socket functionality ++ * that is not otherwise provided. ++ */ ++ native_handle_type native_handle() ++ { ++ return impl_.get_service().native_handle(impl_.get_implementation()); ++ } ++ ++ /// Cancel all asynchronous operations associated with the socket. ++ /** ++ * This function causes all outstanding asynchronous connect, send and receive ++ * operations to finish immediately, and the handlers for cancelled operations ++ * will be passed the boost::asio::error::operation_aborted error. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ * ++ * @note Calls to cancel() will always fail with ++ * boost::asio::error::operation_not_supported when run on Windows XP, Windows ++ * Server 2003, and earlier versions of Windows, unless ++ * BOOST_ASIO_ENABLE_CANCELIO is defined. However, the CancelIo function has ++ * two issues that should be considered before enabling its use: ++ * ++ * @li It will only cancel asynchronous operations that were initiated in the ++ * current thread. ++ * ++ * @li It can appear to complete without error, but the request to cancel the ++ * unfinished operations may be silently ignored by the operating system. ++ * Whether it works or not seems to depend on the drivers that are installed. ++ * ++ * For portable cancellation, consider using one of the following ++ * alternatives: ++ * ++ * @li Disable asio's I/O completion port backend by defining ++ * BOOST_ASIO_DISABLE_IOCP. ++ * ++ * @li Use the close() function to simultaneously cancel the outstanding ++ * operations and close the socket. ++ * ++ * When running on Windows Vista, Windows Server 2008, and later, the ++ * CancelIoEx function is always used. This function does not have the ++ * problems described above. ++ */ ++#if defined(BOOST_ASIO_MSVC) && (BOOST_ASIO_MSVC >= 1400) \ ++ && (!defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0600) \ ++ && !defined(BOOST_ASIO_ENABLE_CANCELIO) ++ __declspec(deprecated("By default, this function always fails with " ++ "operation_not_supported when used on Windows XP, Windows Server 2003, " ++ "or earlier. Consult documentation for details.")) ++#endif ++ void cancel() ++ { ++ boost::system::error_code ec; ++ impl_.get_service().cancel(impl_.get_implementation(), ec); ++ boost::asio::detail::throw_error(ec, "cancel"); ++ } ++ ++ /// Cancel all asynchronous operations associated with the socket. ++ /** ++ * This function causes all outstanding asynchronous connect, send and receive ++ * operations to finish immediately, and the handlers for cancelled operations ++ * will be passed the boost::asio::error::operation_aborted error. ++ * ++ * @param ec Set to indicate what error occurred, if any. ++ * ++ * @note Calls to cancel() will always fail with ++ * boost::asio::error::operation_not_supported when run on Windows XP, Windows ++ * Server 2003, and earlier versions of Windows, unless ++ * BOOST_ASIO_ENABLE_CANCELIO is defined. However, the CancelIo function has ++ * two issues that should be considered before enabling its use: ++ * ++ * @li It will only cancel asynchronous operations that were initiated in the ++ * current thread. ++ * ++ * @li It can appear to complete without error, but the request to cancel the ++ * unfinished operations may be silently ignored by the operating system. ++ * Whether it works or not seems to depend on the drivers that are installed. ++ * ++ * For portable cancellation, consider using one of the following ++ * alternatives: ++ * ++ * @li Disable asio's I/O completion port backend by defining ++ * BOOST_ASIO_DISABLE_IOCP. ++ * ++ * @li Use the close() function to simultaneously cancel the outstanding ++ * operations and close the socket. ++ * ++ * When running on Windows Vista, Windows Server 2008, and later, the ++ * CancelIoEx function is always used. This function does not have the ++ * problems described above. ++ */ ++#if defined(BOOST_ASIO_MSVC) && (BOOST_ASIO_MSVC >= 1400) \ ++ && (!defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0600) \ ++ && !defined(BOOST_ASIO_ENABLE_CANCELIO) ++ __declspec(deprecated("By default, this function always fails with " ++ "operation_not_supported when used on Windows XP, Windows Server 2003, " ++ "or earlier. Consult documentation for details.")) ++#endif ++ BOOST_ASIO_SYNC_OP_VOID cancel(boost::system::error_code& ec) ++ { ++ impl_.get_service().cancel(impl_.get_implementation(), ec); ++ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); ++ } ++ ++ /// Determine whether the socket is at the out-of-band data mark. ++ /** ++ * This function is used to check whether the socket input is currently ++ * positioned at the out-of-band data mark. ++ * ++ * @return A bool indicating whether the socket is at the out-of-band data ++ * mark. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ */ ++ bool at_mark() const ++ { ++ boost::system::error_code ec; ++ bool b = impl_.get_service().at_mark(impl_.get_implementation(), ec); ++ boost::asio::detail::throw_error(ec, "at_mark"); ++ return b; ++ } ++ ++ /// Determine whether the socket is at the out-of-band data mark. ++ /** ++ * This function is used to check whether the socket input is currently ++ * positioned at the out-of-band data mark. ++ * ++ * @param ec Set to indicate what error occurred, if any. ++ * ++ * @return A bool indicating whether the socket is at the out-of-band data ++ * mark. ++ */ ++ bool at_mark(boost::system::error_code& ec) const ++ { ++ return impl_.get_service().at_mark(impl_.get_implementation(), ec); ++ } ++ ++ /// Determine the number of bytes available for reading. ++ /** ++ * This function is used to determine the number of bytes that may be read ++ * without blocking. ++ * ++ * @return The number of bytes that may be read without blocking, or 0 if an ++ * error occurs. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ */ ++ std::size_t available() const ++ { ++ boost::system::error_code ec; ++ std::size_t s = impl_.get_service().available( ++ impl_.get_implementation(), ec); ++ boost::asio::detail::throw_error(ec, "available"); ++ return s; ++ } ++ ++ /// Determine the number of bytes available for reading. ++ /** ++ * This function is used to determine the number of bytes that may be read ++ * without blocking. ++ * ++ * @param ec Set to indicate what error occurred, if any. ++ * ++ * @return The number of bytes that may be read without blocking, or 0 if an ++ * error occurs. ++ */ ++ std::size_t available(boost::system::error_code& ec) const ++ { ++ return impl_.get_service().available(impl_.get_implementation(), ec); ++ } ++ ++ /// Bind the socket to the given local endpoint. ++ /** ++ * This function binds the socket to the specified endpoint on the local ++ * machine. ++ * ++ * @param endpoint An endpoint on the local machine to which the socket will ++ * be bound. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ * ++ * @par Example ++ * @code ++ * boost::asio::ip::tcp::socket socket(my_context); ++ * socket.open(boost::asio::ip::tcp::v4()); ++ * socket.bind(boost::asio::ip::tcp::endpoint( ++ * boost::asio::ip::tcp::v4(), 12345)); ++ * @endcode ++ */ ++ void bind(const endpoint_type& endpoint) ++ { ++ boost::system::error_code ec; ++ impl_.get_service().bind(impl_.get_implementation(), endpoint, ec); ++ boost::asio::detail::throw_error(ec, "bind"); ++ } ++ ++ /// Bind the socket to the given local endpoint. ++ /** ++ * This function binds the socket to the specified endpoint on the local ++ * machine. ++ * ++ * @param endpoint An endpoint on the local machine to which the socket will ++ * be bound. ++ * ++ * @param ec Set to indicate what error occurred, if any. ++ * ++ * @par Example ++ * @code ++ * boost::asio::ip::tcp::socket socket(my_context); ++ * socket.open(boost::asio::ip::tcp::v4()); ++ * boost::system::error_code ec; ++ * socket.bind(boost::asio::ip::tcp::endpoint( ++ * boost::asio::ip::tcp::v4(), 12345), ec); ++ * if (ec) ++ * { ++ * // An error occurred. ++ * } ++ * @endcode ++ */ ++ BOOST_ASIO_SYNC_OP_VOID bind(const endpoint_type& endpoint, ++ boost::system::error_code& ec) ++ { ++ impl_.get_service().bind(impl_.get_implementation(), endpoint, ec); ++ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); ++ } ++ ++ /// Connect the socket to the specified endpoint. ++ /** ++ * This function is used to connect a socket to the specified remote endpoint. ++ * The function call will block until the connection is successfully made or ++ * an error occurs. ++ * ++ * The socket is automatically opened if it is not already open. If the ++ * connect fails, and the socket was automatically opened, the socket is ++ * not returned to the closed state. ++ * ++ * @param peer_endpoint The remote endpoint to which the socket will be ++ * connected. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ * ++ * @par Example ++ * @code ++ * boost::asio::ip::tcp::socket socket(my_context); ++ * boost::asio::ip::tcp::endpoint endpoint( ++ * boost::asio::ip::address::from_string("1.2.3.4"), 12345); ++ * socket.connect(endpoint); ++ * @endcode ++ */ ++ void connect(const endpoint_type& peer_endpoint) ++ { ++ boost::system::error_code ec; ++ if (!is_open()) ++ { ++ impl_.get_service().open(impl_.get_implementation(), ++ peer_endpoint.protocol(), ec); ++ boost::asio::detail::throw_error(ec, "connect"); ++ } ++ impl_.get_service().connect(impl_.get_implementation(), peer_endpoint, ec); ++ boost::asio::detail::throw_error(ec, "connect"); ++ } ++ ++ /// Connect the socket to the specified endpoint. ++ /** ++ * This function is used to connect a socket to the specified remote endpoint. ++ * The function call will block until the connection is successfully made or ++ * an error occurs. ++ * ++ * The socket is automatically opened if it is not already open. If the ++ * connect fails, and the socket was automatically opened, the socket is ++ * not returned to the closed state. ++ * ++ * @param peer_endpoint The remote endpoint to which the socket will be ++ * connected. ++ * ++ * @param ec Set to indicate what error occurred, if any. ++ * ++ * @par Example ++ * @code ++ * boost::asio::ip::tcp::socket socket(my_context); ++ * boost::asio::ip::tcp::endpoint endpoint( ++ * boost::asio::ip::address::from_string("1.2.3.4"), 12345); ++ * boost::system::error_code ec; ++ * socket.connect(endpoint, ec); ++ * if (ec) ++ * { ++ * // An error occurred. ++ * } ++ * @endcode ++ */ ++ BOOST_ASIO_SYNC_OP_VOID connect(const endpoint_type& peer_endpoint, ++ boost::system::error_code& ec) ++ { ++ if (!is_open()) ++ { ++ impl_.get_service().open(impl_.get_implementation(), ++ peer_endpoint.protocol(), ec); ++ if (ec) ++ { ++ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); ++ } ++ } ++ ++ impl_.get_service().connect(impl_.get_implementation(), peer_endpoint, ec); ++ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); ++ } ++ ++ /// Start an asynchronous connect. ++ /** ++ * This function is used to asynchronously connect a socket to the specified ++ * remote endpoint. The function call always returns immediately. ++ * ++ * The socket is automatically opened if it is not already open. If the ++ * connect fails, and the socket was automatically opened, the socket is ++ * not returned to the closed state. ++ * ++ * @param peer_endpoint The remote endpoint to which the socket will be ++ * connected. Copies will be made of the endpoint object as required. ++ * ++ * @param handler The handler to be called when the connection operation ++ * completes. Copies will be made of the handler as required. The function ++ * signature of the handler must be: ++ * @code void handler( ++ * const boost::system::error_code& error // Result of operation ++ * ); @endcode ++ * Regardless of whether the asynchronous operation completes immediately or ++ * not, the handler will not be invoked from within this function. On ++ * immediate completion, invocation of the handler will be performed in a ++ * manner equivalent to using boost::asio::post(). ++ * ++ * @par Example ++ * @code ++ * void connect_handler(const boost::system::error_code& error) ++ * { ++ * if (!error) ++ * { ++ * // Connect succeeded. ++ * } ++ * } ++ * ++ * ... ++ * ++ * boost::asio::ip::tcp::socket socket(my_context); ++ * boost::asio::ip::tcp::endpoint endpoint( ++ * boost::asio::ip::address::from_string("1.2.3.4"), 12345); ++ * socket.async_connect(endpoint, connect_handler); ++ * @endcode ++ */ ++ template ++ BOOST_ASIO_INITFN_RESULT_TYPE(ConnectHandler, ++ void (boost::system::error_code)) ++ async_connect(const endpoint_type& peer_endpoint, ++ BOOST_ASIO_MOVE_ARG(ConnectHandler) handler) ++ { ++ boost::system::error_code open_ec; ++ if (!is_open()) ++ { ++ const protocol_type protocol = peer_endpoint.protocol(); ++ impl_.get_service().open(impl_.get_implementation(), protocol, open_ec); ++ } ++ ++ return async_initiate( ++ initiate_async_connect(), handler, this, peer_endpoint, open_ec); ++ } ++ ++ /// Set an option on the socket. ++ /** ++ * This function is used to set an option on the socket. ++ * ++ * @param option The new option value to be set on the socket. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ * ++ * @sa SettableSocketOption @n ++ * boost::asio::socket_base::broadcast @n ++ * boost::asio::socket_base::do_not_route @n ++ * boost::asio::socket_base::keep_alive @n ++ * boost::asio::socket_base::linger @n ++ * boost::asio::socket_base::receive_buffer_size @n ++ * boost::asio::socket_base::receive_low_watermark @n ++ * boost::asio::socket_base::reuse_address @n ++ * boost::asio::socket_base::send_buffer_size @n ++ * boost::asio::socket_base::send_low_watermark @n ++ * boost::asio::ip::multicast::join_group @n ++ * boost::asio::ip::multicast::leave_group @n ++ * boost::asio::ip::multicast::enable_loopback @n ++ * boost::asio::ip::multicast::outbound_interface @n ++ * boost::asio::ip::multicast::hops @n ++ * boost::asio::ip::tcp::no_delay ++ * ++ * @par Example ++ * Setting the IPPROTO_TCP/TCP_NODELAY option: ++ * @code ++ * boost::asio::ip::tcp::socket socket(my_context); ++ * ... ++ * boost::asio::ip::tcp::no_delay option(true); ++ * socket.set_option(option); ++ * @endcode ++ */ ++ template ++ void set_option(const SettableSocketOption& option) ++ { ++ boost::system::error_code ec; ++ impl_.get_service().set_option(impl_.get_implementation(), option, ec); ++ boost::asio::detail::throw_error(ec, "set_option"); ++ } ++ ++ /// Set an option on the socket. ++ /** ++ * This function is used to set an option on the socket. ++ * ++ * @param option The new option value to be set on the socket. ++ * ++ * @param ec Set to indicate what error occurred, if any. ++ * ++ * @sa SettableSocketOption @n ++ * boost::asio::socket_base::broadcast @n ++ * boost::asio::socket_base::do_not_route @n ++ * boost::asio::socket_base::keep_alive @n ++ * boost::asio::socket_base::linger @n ++ * boost::asio::socket_base::receive_buffer_size @n ++ * boost::asio::socket_base::receive_low_watermark @n ++ * boost::asio::socket_base::reuse_address @n ++ * boost::asio::socket_base::send_buffer_size @n ++ * boost::asio::socket_base::send_low_watermark @n ++ * boost::asio::ip::multicast::join_group @n ++ * boost::asio::ip::multicast::leave_group @n ++ * boost::asio::ip::multicast::enable_loopback @n ++ * boost::asio::ip::multicast::outbound_interface @n ++ * boost::asio::ip::multicast::hops @n ++ * boost::asio::ip::tcp::no_delay ++ * ++ * @par Example ++ * Setting the IPPROTO_TCP/TCP_NODELAY option: ++ * @code ++ * boost::asio::ip::tcp::socket socket(my_context); ++ * ... ++ * boost::asio::ip::tcp::no_delay option(true); ++ * boost::system::error_code ec; ++ * socket.set_option(option, ec); ++ * if (ec) ++ * { ++ * // An error occurred. ++ * } ++ * @endcode ++ */ ++ template ++ BOOST_ASIO_SYNC_OP_VOID set_option(const SettableSocketOption& option, ++ boost::system::error_code& ec) ++ { ++ impl_.get_service().set_option(impl_.get_implementation(), option, ec); ++ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); ++ } ++ ++ /// Get an option from the socket. ++ /** ++ * This function is used to get the current value of an option on the socket. ++ * ++ * @param option The option value to be obtained from the socket. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ * ++ * @sa GettableSocketOption @n ++ * boost::asio::socket_base::broadcast @n ++ * boost::asio::socket_base::do_not_route @n ++ * boost::asio::socket_base::keep_alive @n ++ * boost::asio::socket_base::linger @n ++ * boost::asio::socket_base::receive_buffer_size @n ++ * boost::asio::socket_base::receive_low_watermark @n ++ * boost::asio::socket_base::reuse_address @n ++ * boost::asio::socket_base::send_buffer_size @n ++ * boost::asio::socket_base::send_low_watermark @n ++ * boost::asio::ip::multicast::join_group @n ++ * boost::asio::ip::multicast::leave_group @n ++ * boost::asio::ip::multicast::enable_loopback @n ++ * boost::asio::ip::multicast::outbound_interface @n ++ * boost::asio::ip::multicast::hops @n ++ * boost::asio::ip::tcp::no_delay ++ * ++ * @par Example ++ * Getting the value of the SOL_SOCKET/SO_KEEPALIVE option: ++ * @code ++ * boost::asio::ip::tcp::socket socket(my_context); ++ * ... ++ * boost::asio::ip::tcp::socket::keep_alive option; ++ * socket.get_option(option); ++ * bool is_set = option.value(); ++ * @endcode ++ */ ++ template ++ void get_option(GettableSocketOption& option) const ++ { ++ boost::system::error_code ec; ++ impl_.get_service().get_option(impl_.get_implementation(), option, ec); ++ boost::asio::detail::throw_error(ec, "get_option"); ++ } ++ ++ /// Get an option from the socket. ++ /** ++ * This function is used to get the current value of an option on the socket. ++ * ++ * @param option The option value to be obtained from the socket. ++ * ++ * @param ec Set to indicate what error occurred, if any. ++ * ++ * @sa GettableSocketOption @n ++ * boost::asio::socket_base::broadcast @n ++ * boost::asio::socket_base::do_not_route @n ++ * boost::asio::socket_base::keep_alive @n ++ * boost::asio::socket_base::linger @n ++ * boost::asio::socket_base::receive_buffer_size @n ++ * boost::asio::socket_base::receive_low_watermark @n ++ * boost::asio::socket_base::reuse_address @n ++ * boost::asio::socket_base::send_buffer_size @n ++ * boost::asio::socket_base::send_low_watermark @n ++ * boost::asio::ip::multicast::join_group @n ++ * boost::asio::ip::multicast::leave_group @n ++ * boost::asio::ip::multicast::enable_loopback @n ++ * boost::asio::ip::multicast::outbound_interface @n ++ * boost::asio::ip::multicast::hops @n ++ * boost::asio::ip::tcp::no_delay ++ * ++ * @par Example ++ * Getting the value of the SOL_SOCKET/SO_KEEPALIVE option: ++ * @code ++ * boost::asio::ip::tcp::socket socket(my_context); ++ * ... ++ * boost::asio::ip::tcp::socket::keep_alive option; ++ * boost::system::error_code ec; ++ * socket.get_option(option, ec); ++ * if (ec) ++ * { ++ * // An error occurred. ++ * } ++ * bool is_set = option.value(); ++ * @endcode ++ */ ++ template ++ BOOST_ASIO_SYNC_OP_VOID get_option(GettableSocketOption& option, ++ boost::system::error_code& ec) const ++ { ++ impl_.get_service().get_option(impl_.get_implementation(), option, ec); ++ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); ++ } ++ ++ /// Perform an IO control command on the socket. ++ /** ++ * This function is used to execute an IO control command on the socket. ++ * ++ * @param command The IO control command to be performed on the socket. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ * ++ * @sa IoControlCommand @n ++ * boost::asio::socket_base::bytes_readable @n ++ * boost::asio::socket_base::non_blocking_io ++ * ++ * @par Example ++ * Getting the number of bytes ready to read: ++ * @code ++ * boost::asio::ip::tcp::socket socket(my_context); ++ * ... ++ * boost::asio::ip::tcp::socket::bytes_readable command; ++ * socket.io_control(command); ++ * std::size_t bytes_readable = command.get(); ++ * @endcode ++ */ ++ template ++ void io_control(IoControlCommand& command) ++ { ++ boost::system::error_code ec; ++ impl_.get_service().io_control(impl_.get_implementation(), command, ec); ++ boost::asio::detail::throw_error(ec, "io_control"); ++ } ++ ++ /// Perform an IO control command on the socket. ++ /** ++ * This function is used to execute an IO control command on the socket. ++ * ++ * @param command The IO control command to be performed on the socket. ++ * ++ * @param ec Set to indicate what error occurred, if any. ++ * ++ * @sa IoControlCommand @n ++ * boost::asio::socket_base::bytes_readable @n ++ * boost::asio::socket_base::non_blocking_io ++ * ++ * @par Example ++ * Getting the number of bytes ready to read: ++ * @code ++ * boost::asio::ip::tcp::socket socket(my_context); ++ * ... ++ * boost::asio::ip::tcp::socket::bytes_readable command; ++ * boost::system::error_code ec; ++ * socket.io_control(command, ec); ++ * if (ec) ++ * { ++ * // An error occurred. ++ * } ++ * std::size_t bytes_readable = command.get(); ++ * @endcode ++ */ ++ template ++ BOOST_ASIO_SYNC_OP_VOID io_control(IoControlCommand& command, ++ boost::system::error_code& ec) ++ { ++ impl_.get_service().io_control(impl_.get_implementation(), command, ec); ++ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); ++ } ++ ++ /// Gets the non-blocking mode of the socket. ++ /** ++ * @returns @c true if the socket's synchronous operations will fail with ++ * boost::asio::error::would_block if they are unable to perform the requested ++ * operation immediately. If @c false, synchronous operations will block ++ * until complete. ++ * ++ * @note The non-blocking mode has no effect on the behaviour of asynchronous ++ * operations. Asynchronous operations will never fail with the error ++ * boost::asio::error::would_block. ++ */ ++ bool non_blocking() const ++ { ++ return impl_.get_service().non_blocking(impl_.get_implementation()); ++ } ++ ++ /// Sets the non-blocking mode of the socket. ++ /** ++ * @param mode If @c true, the socket's synchronous operations will fail with ++ * boost::asio::error::would_block if they are unable to perform the requested ++ * operation immediately. If @c false, synchronous operations will block ++ * until complete. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ * ++ * @note The non-blocking mode has no effect on the behaviour of asynchronous ++ * operations. Asynchronous operations will never fail with the error ++ * boost::asio::error::would_block. ++ */ ++ void non_blocking(bool mode) ++ { ++ boost::system::error_code ec; ++ impl_.get_service().non_blocking(impl_.get_implementation(), mode, ec); ++ boost::asio::detail::throw_error(ec, "non_blocking"); ++ } ++ ++ /// Sets the non-blocking mode of the socket. ++ /** ++ * @param mode If @c true, the socket's synchronous operations will fail with ++ * boost::asio::error::would_block if they are unable to perform the requested ++ * operation immediately. If @c false, synchronous operations will block ++ * until complete. ++ * ++ * @param ec Set to indicate what error occurred, if any. ++ * ++ * @note The non-blocking mode has no effect on the behaviour of asynchronous ++ * operations. Asynchronous operations will never fail with the error ++ * boost::asio::error::would_block. ++ */ ++ BOOST_ASIO_SYNC_OP_VOID non_blocking( ++ bool mode, boost::system::error_code& ec) ++ { ++ impl_.get_service().non_blocking(impl_.get_implementation(), mode, ec); ++ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); ++ } ++ ++ /// Gets the non-blocking mode of the native socket implementation. ++ /** ++ * This function is used to retrieve the non-blocking mode of the underlying ++ * native socket. This mode has no effect on the behaviour of the socket ++ * object's synchronous operations. ++ * ++ * @returns @c true if the underlying socket is in non-blocking mode and ++ * direct system calls may fail with boost::asio::error::would_block (or the ++ * equivalent system error). ++ * ++ * @note The current non-blocking mode is cached by the socket object. ++ * Consequently, the return value may be incorrect if the non-blocking mode ++ * was set directly on the native socket. ++ * ++ * @par Example ++ * This function is intended to allow the encapsulation of arbitrary ++ * non-blocking system calls as asynchronous operations, in a way that is ++ * transparent to the user of the socket object. The following example ++ * illustrates how Linux's @c sendfile system call might be encapsulated: ++ * @code template ++ * struct sendfile_op ++ * { ++ * tcp::socket& sock_; ++ * int fd_; ++ * Handler handler_; ++ * off_t offset_; ++ * std::size_t total_bytes_transferred_; ++ * ++ * // Function call operator meeting WriteHandler requirements. ++ * // Used as the handler for the async_write_some operation. ++ * void operator()(boost::system::error_code ec, std::size_t) ++ * { ++ * // Put the underlying socket into non-blocking mode. ++ * if (!ec) ++ * if (!sock_.native_non_blocking()) ++ * sock_.native_non_blocking(true, ec); ++ * ++ * if (!ec) ++ * { ++ * for (;;) ++ * { ++ * // Try the system call. ++ * errno = 0; ++ * int n = ::sendfile(sock_.native_handle(), fd_, &offset_, 65536); ++ * ec = boost::system::error_code(n < 0 ? errno : 0, ++ * boost::asio::error::get_system_category()); ++ * total_bytes_transferred_ += ec ? 0 : n; ++ * ++ * // Retry operation immediately if interrupted by signal. ++ * if (ec == boost::asio::error::interrupted) ++ * continue; ++ * ++ * // Check if we need to run the operation again. ++ * if (ec == boost::asio::error::would_block ++ * || ec == boost::asio::error::try_again) ++ * { ++ * // We have to wait for the socket to become ready again. ++ * sock_.async_wait(tcp::socket::wait_write, *this); ++ * return; ++ * } ++ * ++ * if (ec || n == 0) ++ * { ++ * // An error occurred, or we have reached the end of the file. ++ * // Either way we must exit the loop so we can call the handler. ++ * break; ++ * } ++ * ++ * // Loop around to try calling sendfile again. ++ * } ++ * } ++ * ++ * // Pass result back to user's handler. ++ * handler_(ec, total_bytes_transferred_); ++ * } ++ * }; ++ * ++ * template ++ * void async_sendfile(tcp::socket& sock, int fd, Handler h) ++ * { ++ * sendfile_op op = { sock, fd, h, 0, 0 }; ++ * sock.async_wait(tcp::socket::wait_write, op); ++ * } @endcode ++ */ ++ bool native_non_blocking() const ++ { ++ return impl_.get_service().native_non_blocking(impl_.get_implementation()); ++ } ++ ++ /// Sets the non-blocking mode of the native socket implementation. ++ /** ++ * This function is used to modify the non-blocking mode of the underlying ++ * native socket. It has no effect on the behaviour of the socket object's ++ * synchronous operations. ++ * ++ * @param mode If @c true, the underlying socket is put into non-blocking ++ * mode and direct system calls may fail with boost::asio::error::would_block ++ * (or the equivalent system error). ++ * ++ * @throws boost::system::system_error Thrown on failure. If the @c mode is ++ * @c false, but the current value of @c non_blocking() is @c true, this ++ * function fails with boost::asio::error::invalid_argument, as the ++ * combination does not make sense. ++ * ++ * @par Example ++ * This function is intended to allow the encapsulation of arbitrary ++ * non-blocking system calls as asynchronous operations, in a way that is ++ * transparent to the user of the socket object. The following example ++ * illustrates how Linux's @c sendfile system call might be encapsulated: ++ * @code template ++ * struct sendfile_op ++ * { ++ * tcp::socket& sock_; ++ * int fd_; ++ * Handler handler_; ++ * off_t offset_; ++ * std::size_t total_bytes_transferred_; ++ * ++ * // Function call operator meeting WriteHandler requirements. ++ * // Used as the handler for the async_write_some operation. ++ * void operator()(boost::system::error_code ec, std::size_t) ++ * { ++ * // Put the underlying socket into non-blocking mode. ++ * if (!ec) ++ * if (!sock_.native_non_blocking()) ++ * sock_.native_non_blocking(true, ec); ++ * ++ * if (!ec) ++ * { ++ * for (;;) ++ * { ++ * // Try the system call. ++ * errno = 0; ++ * int n = ::sendfile(sock_.native_handle(), fd_, &offset_, 65536); ++ * ec = boost::system::error_code(n < 0 ? errno : 0, ++ * boost::asio::error::get_system_category()); ++ * total_bytes_transferred_ += ec ? 0 : n; ++ * ++ * // Retry operation immediately if interrupted by signal. ++ * if (ec == boost::asio::error::interrupted) ++ * continue; ++ * ++ * // Check if we need to run the operation again. ++ * if (ec == boost::asio::error::would_block ++ * || ec == boost::asio::error::try_again) ++ * { ++ * // We have to wait for the socket to become ready again. ++ * sock_.async_wait(tcp::socket::wait_write, *this); ++ * return; ++ * } ++ * ++ * if (ec || n == 0) ++ * { ++ * // An error occurred, or we have reached the end of the file. ++ * // Either way we must exit the loop so we can call the handler. ++ * break; ++ * } ++ * ++ * // Loop around to try calling sendfile again. ++ * } ++ * } ++ * ++ * // Pass result back to user's handler. ++ * handler_(ec, total_bytes_transferred_); ++ * } ++ * }; ++ * ++ * template ++ * void async_sendfile(tcp::socket& sock, int fd, Handler h) ++ * { ++ * sendfile_op op = { sock, fd, h, 0, 0 }; ++ * sock.async_wait(tcp::socket::wait_write, op); ++ * } @endcode ++ */ ++ void native_non_blocking(bool mode) ++ { ++ boost::system::error_code ec; ++ impl_.get_service().native_non_blocking( ++ impl_.get_implementation(), mode, ec); ++ boost::asio::detail::throw_error(ec, "native_non_blocking"); ++ } ++ ++ /// Sets the non-blocking mode of the native socket implementation. ++ /** ++ * This function is used to modify the non-blocking mode of the underlying ++ * native socket. It has no effect on the behaviour of the socket object's ++ * synchronous operations. ++ * ++ * @param mode If @c true, the underlying socket is put into non-blocking ++ * mode and direct system calls may fail with boost::asio::error::would_block ++ * (or the equivalent system error). ++ * ++ * @param ec Set to indicate what error occurred, if any. If the @c mode is ++ * @c false, but the current value of @c non_blocking() is @c true, this ++ * function fails with boost::asio::error::invalid_argument, as the ++ * combination does not make sense. ++ * ++ * @par Example ++ * This function is intended to allow the encapsulation of arbitrary ++ * non-blocking system calls as asynchronous operations, in a way that is ++ * transparent to the user of the socket object. The following example ++ * illustrates how Linux's @c sendfile system call might be encapsulated: ++ * @code template ++ * struct sendfile_op ++ * { ++ * tcp::socket& sock_; ++ * int fd_; ++ * Handler handler_; ++ * off_t offset_; ++ * std::size_t total_bytes_transferred_; ++ * ++ * // Function call operator meeting WriteHandler requirements. ++ * // Used as the handler for the async_write_some operation. ++ * void operator()(boost::system::error_code ec, std::size_t) ++ * { ++ * // Put the underlying socket into non-blocking mode. ++ * if (!ec) ++ * if (!sock_.native_non_blocking()) ++ * sock_.native_non_blocking(true, ec); ++ * ++ * if (!ec) ++ * { ++ * for (;;) ++ * { ++ * // Try the system call. ++ * errno = 0; ++ * int n = ::sendfile(sock_.native_handle(), fd_, &offset_, 65536); ++ * ec = boost::system::error_code(n < 0 ? errno : 0, ++ * boost::asio::error::get_system_category()); ++ * total_bytes_transferred_ += ec ? 0 : n; ++ * ++ * // Retry operation immediately if interrupted by signal. ++ * if (ec == boost::asio::error::interrupted) ++ * continue; ++ * ++ * // Check if we need to run the operation again. ++ * if (ec == boost::asio::error::would_block ++ * || ec == boost::asio::error::try_again) ++ * { ++ * // We have to wait for the socket to become ready again. ++ * sock_.async_wait(tcp::socket::wait_write, *this); ++ * return; ++ * } ++ * ++ * if (ec || n == 0) ++ * { ++ * // An error occurred, or we have reached the end of the file. ++ * // Either way we must exit the loop so we can call the handler. ++ * break; ++ * } ++ * ++ * // Loop around to try calling sendfile again. ++ * } ++ * } ++ * ++ * // Pass result back to user's handler. ++ * handler_(ec, total_bytes_transferred_); ++ * } ++ * }; ++ * ++ * template ++ * void async_sendfile(tcp::socket& sock, int fd, Handler h) ++ * { ++ * sendfile_op op = { sock, fd, h, 0, 0 }; ++ * sock.async_wait(tcp::socket::wait_write, op); ++ * } @endcode ++ */ ++ BOOST_ASIO_SYNC_OP_VOID native_non_blocking( ++ bool mode, boost::system::error_code& ec) ++ { ++ impl_.get_service().native_non_blocking( ++ impl_.get_implementation(), mode, ec); ++ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); ++ } ++ ++ /// Get the local endpoint of the socket. ++ /** ++ * This function is used to obtain the locally bound endpoint of the socket. ++ * ++ * @returns An object that represents the local endpoint of the socket. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ * ++ * @par Example ++ * @code ++ * boost::asio::ip::tcp::socket socket(my_context); ++ * ... ++ * boost::asio::ip::tcp::endpoint endpoint = socket.local_endpoint(); ++ * @endcode ++ */ ++ endpoint_type local_endpoint() const ++ { ++ boost::system::error_code ec; ++ endpoint_type ep = impl_.get_service().local_endpoint( ++ impl_.get_implementation(), ec); ++ boost::asio::detail::throw_error(ec, "local_endpoint"); ++ return ep; ++ } ++ ++ /// Get the local endpoint of the socket. ++ /** ++ * This function is used to obtain the locally bound endpoint of the socket. ++ * ++ * @param ec Set to indicate what error occurred, if any. ++ * ++ * @returns An object that represents the local endpoint of the socket. ++ * Returns a default-constructed endpoint object if an error occurred. ++ * ++ * @par Example ++ * @code ++ * boost::asio::ip::tcp::socket socket(my_context); ++ * ... ++ * boost::system::error_code ec; ++ * boost::asio::ip::tcp::endpoint endpoint = socket.local_endpoint(ec); ++ * if (ec) ++ * { ++ * // An error occurred. ++ * } ++ * @endcode ++ */ ++ endpoint_type local_endpoint(boost::system::error_code& ec) const ++ { ++ return impl_.get_service().local_endpoint(impl_.get_implementation(), ec); ++ } ++ ++ /// Get the remote endpoint of the socket. ++ /** ++ * This function is used to obtain the remote endpoint of the socket. ++ * ++ * @returns An object that represents the remote endpoint of the socket. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ * ++ * @par Example ++ * @code ++ * boost::asio::ip::tcp::socket socket(my_context); ++ * ... ++ * boost::asio::ip::tcp::endpoint endpoint = socket.remote_endpoint(); ++ * @endcode ++ */ ++ endpoint_type remote_endpoint() const ++ { ++ boost::system::error_code ec; ++ endpoint_type ep = impl_.get_service().remote_endpoint( ++ impl_.get_implementation(), ec); ++ boost::asio::detail::throw_error(ec, "remote_endpoint"); ++ return ep; ++ } ++ ++ /// Get the remote endpoint of the socket. ++ /** ++ * This function is used to obtain the remote endpoint of the socket. ++ * ++ * @param ec Set to indicate what error occurred, if any. ++ * ++ * @returns An object that represents the remote endpoint of the socket. ++ * Returns a default-constructed endpoint object if an error occurred. ++ * ++ * @par Example ++ * @code ++ * boost::asio::ip::tcp::socket socket(my_context); ++ * ... ++ * boost::system::error_code ec; ++ * boost::asio::ip::tcp::endpoint endpoint = socket.remote_endpoint(ec); ++ * if (ec) ++ * { ++ * // An error occurred. ++ * } ++ * @endcode ++ */ ++ endpoint_type remote_endpoint(boost::system::error_code& ec) const ++ { ++ return impl_.get_service().remote_endpoint(impl_.get_implementation(), ec); ++ } ++ ++ /// Disable sends or receives on the socket. ++ /** ++ * This function is used to disable send operations, receive operations, or ++ * both. ++ * ++ * @param what Determines what types of operation will no longer be allowed. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ * ++ * @par Example ++ * Shutting down the send side of the socket: ++ * @code ++ * boost::asio::ip::tcp::socket socket(my_context); ++ * ... ++ * socket.shutdown(boost::asio::ip::tcp::socket::shutdown_send); ++ * @endcode ++ */ ++ void shutdown(shutdown_type what) ++ { ++ boost::system::error_code ec; ++ impl_.get_service().shutdown(impl_.get_implementation(), what, ec); ++ boost::asio::detail::throw_error(ec, "shutdown"); ++ } ++ ++ /// Disable sends or receives on the socket. ++ /** ++ * This function is used to disable send operations, receive operations, or ++ * both. ++ * ++ * @param what Determines what types of operation will no longer be allowed. ++ * ++ * @param ec Set to indicate what error occurred, if any. ++ * ++ * @par Example ++ * Shutting down the send side of the socket: ++ * @code ++ * boost::asio::ip::tcp::socket socket(my_context); ++ * ... ++ * boost::system::error_code ec; ++ * socket.shutdown(boost::asio::ip::tcp::socket::shutdown_send, ec); ++ * if (ec) ++ * { ++ * // An error occurred. ++ * } ++ * @endcode ++ */ ++ BOOST_ASIO_SYNC_OP_VOID shutdown(shutdown_type what, ++ boost::system::error_code& ec) ++ { ++ impl_.get_service().shutdown(impl_.get_implementation(), what, ec); ++ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); ++ } ++ ++ /// Wait for the socket to become ready to read, ready to write, or to have ++ /// pending error conditions. ++ /** ++ * This function is used to perform a blocking wait for a socket to enter ++ * a ready to read, write or error condition state. ++ * ++ * @param w Specifies the desired socket state. ++ * ++ * @par Example ++ * Waiting for a socket to become readable. ++ * @code ++ * boost::asio::ip::tcp::socket socket(my_context); ++ * ... ++ * socket.wait(boost::asio::ip::tcp::socket::wait_read); ++ * @endcode ++ */ ++ void wait(wait_type w) ++ { ++ boost::system::error_code ec; ++ impl_.get_service().wait(impl_.get_implementation(), w, ec); ++ boost::asio::detail::throw_error(ec, "wait"); ++ } ++ ++ /// Wait for the socket to become ready to read, ready to write, or to have ++ /// pending error conditions. ++ /** ++ * This function is used to perform a blocking wait for a socket to enter ++ * a ready to read, write or error condition state. ++ * ++ * @param w Specifies the desired socket state. ++ * ++ * @param ec Set to indicate what error occurred, if any. ++ * ++ * @par Example ++ * Waiting for a socket to become readable. ++ * @code ++ * boost::asio::ip::tcp::socket socket(my_context); ++ * ... ++ * boost::system::error_code ec; ++ * socket.wait(boost::asio::ip::tcp::socket::wait_read, ec); ++ * @endcode ++ */ ++ BOOST_ASIO_SYNC_OP_VOID wait(wait_type w, boost::system::error_code& ec) ++ { ++ impl_.get_service().wait(impl_.get_implementation(), w, ec); ++ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); ++ } ++ ++ /// Asynchronously wait for the socket to become ready to read, ready to ++ /// write, or to have pending error conditions. ++ /** ++ * This function is used to perform an asynchronous wait for a socket to enter ++ * a ready to read, write or error condition state. ++ * ++ * @param w Specifies the desired socket state. ++ * ++ * @param handler The handler to be called when the wait operation completes. ++ * Copies will be made of the handler as required. The function signature of ++ * the handler must be: ++ * @code void handler( ++ * const boost::system::error_code& error // Result of operation ++ * ); @endcode ++ * Regardless of whether the asynchronous operation completes immediately or ++ * not, the handler will not be invoked from within this function. On ++ * immediate completion, invocation of the handler will be performed in a ++ * manner equivalent to using boost::asio::post(). ++ * ++ * @par Example ++ * @code ++ * void wait_handler(const boost::system::error_code& error) ++ * { ++ * if (!error) ++ * { ++ * // Wait succeeded. ++ * } ++ * } ++ * ++ * ... ++ * ++ * boost::asio::ip::tcp::socket socket(my_context); ++ * ... ++ * socket.async_wait(boost::asio::ip::tcp::socket::wait_read, wait_handler); ++ * @endcode ++ */ ++ template ++ BOOST_ASIO_INITFN_RESULT_TYPE(WaitHandler, ++ void (boost::system::error_code)) ++ async_wait(wait_type w, BOOST_ASIO_MOVE_ARG(WaitHandler) handler) ++ { ++ return async_initiate( ++ initiate_async_wait(), handler, this, w); ++ } ++ ++protected: ++ /// Protected destructor to prevent deletion through this type. ++ /** ++ * This function destroys the socket, cancelling any outstanding asynchronous ++ * operations associated with the socket as if by calling @c cancel. ++ */ ++ ~basic_socket_ext_local() ++ { ++ } ++ ++#if defined(BOOST_ASIO_WINDOWS_RUNTIME) ++ detail::io_object_impl< ++ detail::null_socket_service, Executor> impl_; ++#elif defined(BOOST_ASIO_HAS_IOCP) ++ detail::io_object_impl< ++ detail::win_iocp_socket_service, Executor> impl_; ++#else ++ detail::io_object_impl< ++ detail::reactive_socket_service_ext_local, Executor> impl_; ++#endif ++ ++private: ++ // Disallow copying and assignment. ++ basic_socket_ext_local(const basic_socket_ext_local&) BOOST_ASIO_DELETED; ++ basic_socket_ext_local& operator=(const basic_socket_ext_local&) BOOST_ASIO_DELETED; ++ ++ struct initiate_async_connect ++ { ++ template ++ void operator()(BOOST_ASIO_MOVE_ARG(ConnectHandler) handler, ++ basic_socket_ext_local* self, const endpoint_type& peer_endpoint, ++ const boost::system::error_code& open_ec) const ++ { ++ // If you get an error on the following line it means that your handler ++ // does not meet the documented type requirements for a ConnectHandler. ++ BOOST_ASIO_CONNECT_HANDLER_CHECK(ConnectHandler, handler) type_check; ++ ++ if (open_ec) ++ { ++ boost::asio::post(self->impl_.get_executor(), ++ boost::asio::detail::bind_handler( ++ BOOST_ASIO_MOVE_CAST(ConnectHandler)(handler), open_ec)); ++ } ++ else ++ { ++ detail::non_const_lvalue handler2(handler); ++ self->impl_.get_service().async_connect( ++ self->impl_.get_implementation(), peer_endpoint, ++ handler2.value, self->impl_.get_implementation_executor()); ++ } ++ } ++ }; ++ ++ struct initiate_async_wait ++ { ++ template ++ void operator()(BOOST_ASIO_MOVE_ARG(WaitHandler) handler, ++ basic_socket_ext_local* self, wait_type w) const ++ { ++ // If you get an error on the following line it means that your handler ++ // does not meet the documented type requirements for a WaitHandler. ++ BOOST_ASIO_WAIT_HANDLER_CHECK(WaitHandler, handler) type_check; ++ ++ detail::non_const_lvalue handler2(handler); ++ self->impl_.get_service().async_wait( ++ self->impl_.get_implementation(), w, handler2.value, ++ self->impl_.get_implementation_executor()); ++ } ++ }; ++}; ++ ++} // namespace asio ++} // namespace boost ++ ++#include ++ ++#endif // BOOST_ASIO_BASIC_SOCKET_EXT_LOCAL_HPP +diff --git a/implementation/helper/1.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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++namespace boost { ++namespace asio { ++ ++#if !defined(BOOST_ASIO_BASIC_STREAM_SOCKET_EXT_FWD_DECL) ++#define BOOST_ASIO_BASIC_STREAM_SOCKET_EXT_FWD_DECL ++ ++// Forward declaration with defaulted arguments. ++template ++class basic_stream_socket_ext; ++ ++#endif // !defined(BOOST_ASIO_BASIC_STREAM_SOCKET_EXT_FWD_DECL) ++ ++/// Provides stream-oriented socket functionality. ++/** ++ * The basic_stream_socket_ext class template provides asynchronous and blocking ++ * stream-oriented socket functionality. ++ * ++ * @par Thread Safety ++ * @e Distinct @e objects: Safe.@n ++ * @e Shared @e objects: Unsafe. ++ * ++ * @par Concepts: ++ * AsyncReadStream, AsyncWriteStream, Stream, SyncReadStream, SyncWriteStream. ++ */ ++template ++class basic_stream_socket_ext ++ : public basic_socket_ext_local ++{ ++public: ++ /// The type of the executor associated with the object. ++ typedef Executor executor_type; ++ ++ /// Rebinds the socket type to another executor. ++ template ++ struct rebind_executor ++ { ++ /// The socket type when rebound to the specified executor. ++ typedef basic_stream_socket_ext other; ++ }; ++ ++ /// The native representation of a socket. ++#if defined(GENERATING_DOCUMENTATION) ++ typedef implementation_defined native_handle_type; ++#else ++ typedef typename basic_socket::native_handle_type native_handle_type; ++#endif ++ ++ /// The protocol type. ++ typedef Protocol protocol_type; ++ ++ /// The endpoint type. ++ typedef typename Protocol::endpoint endpoint_type; ++ ++ /// Construct a basic_stream_socket without opening it. ++ /** ++ * This constructor creates a stream socket without opening it. The socket ++ * needs to be opened and then connected or accepted before data can be sent ++ * or received on it. ++ * ++ * @param ex The I/O executor that the socket will use, by default, to ++ * dispatch handlers for any asynchronous operations performed on the socket. ++ */ ++ explicit basic_stream_socket_ext(const executor_type& ex) ++ : basic_socket_ext_local(ex) ++ { ++ } ++ ++ /// Construct a basic_stream_socket without opening it. ++ /** ++ * This constructor creates a stream socket without opening it. The socket ++ * needs to be opened and then connected or accepted before data can be sent ++ * or received on it. ++ * ++ * @param context An execution context which provides the I/O executor that ++ * the socket will use, by default, to dispatch handlers for any asynchronous ++ * operations performed on the socket. ++ */ ++ template ++ explicit basic_stream_socket_ext(ExecutionContext& context, ++ typename enable_if< ++ is_convertible::value ++ >::type* = 0) ++ : basic_socket_ext_local(context) ++ { ++ } ++ ++ /// Construct and open a basic_stream_socket. ++ /** ++ * This constructor creates and opens a stream socket. The socket needs to be ++ * connected or accepted before data can be sent or received on it. ++ * ++ * @param ex The I/O executor that the socket will use, by default, to ++ * dispatch handlers for any asynchronous operations performed on the socket. ++ * ++ * @param protocol An object specifying protocol parameters to be used. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ */ ++ basic_stream_socket_ext(const executor_type& ex, const protocol_type& protocol) ++ : basic_socket_ext_local(ex, protocol) ++ { ++ } ++ ++ /// Construct and open a basic_stream_socket. ++ /** ++ * This constructor creates and opens a stream socket. The socket needs to be ++ * connected or accepted before data can be sent or received on it. ++ * ++ * @param context An execution context which provides the I/O executor that ++ * the socket will use, by default, to dispatch handlers for any asynchronous ++ * operations performed on the socket. ++ * ++ * @param protocol An object specifying protocol parameters to be used. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ */ ++ template ++ basic_stream_socket_ext(ExecutionContext& context, const protocol_type& protocol, ++ typename enable_if< ++ is_convertible::value ++ >::type* = 0) ++ : basic_socket_ext_local(context, protocol) ++ { ++ } ++ ++ /// Construct a basic_stream_socket, opening it and binding it to the given ++ /// local endpoint. ++ /** ++ * This constructor creates a stream socket and automatically opens it bound ++ * to the specified endpoint on the local machine. The protocol used is the ++ * protocol associated with the given endpoint. ++ * ++ * @param ex The I/O executor that the socket will use, by default, to ++ * dispatch handlers for any asynchronous operations performed on the socket. ++ * ++ * @param endpoint An endpoint on the local machine to which the stream ++ * socket will be bound. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ */ ++ basic_stream_socket_ext(const executor_type& ex, const endpoint_type& endpoint) ++ : basic_socket_ext_local(ex, endpoint) ++ { ++ } ++ ++ /// Construct a basic_stream_socket, opening it and binding it to the given ++ /// local endpoint. ++ /** ++ * This constructor creates a stream socket and automatically opens it bound ++ * to the specified endpoint on the local machine. The protocol used is the ++ * protocol associated with the given endpoint. ++ * ++ * @param context An execution context which provides the I/O executor that ++ * the socket will use, by default, to dispatch handlers for any asynchronous ++ * operations performed on the socket. ++ * ++ * @param endpoint An endpoint on the local machine to which the stream ++ * socket will be bound. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ */ ++ template ++ basic_stream_socket_ext(ExecutionContext& context, const endpoint_type& endpoint, ++ typename enable_if< ++ is_convertible::value ++ >::type* = 0) ++ : basic_socket_ext_local(context, endpoint) ++ { ++ } ++ ++ /// Construct a basic_stream_socket on an existing native socket. ++ /** ++ * This constructor creates a stream socket object to hold an existing native ++ * socket. ++ * ++ * @param ex The I/O executor that the socket will use, by default, to ++ * dispatch handlers for any asynchronous operations performed on the socket. ++ * ++ * @param protocol An object specifying protocol parameters to be used. ++ * ++ * @param native_socket The new underlying socket implementation. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ */ ++ basic_stream_socket_ext(const executor_type& ex, ++ const protocol_type& protocol, const native_handle_type& native_socket) ++ : basic_socket_ext_local(ex, protocol, native_socket) ++ { ++ } ++ ++ /// Construct a basic_stream_socket on an existing native socket. ++ /** ++ * This constructor creates a stream socket object to hold an existing native ++ * socket. ++ * ++ * @param context An execution context which provides the I/O executor that ++ * the socket will use, by default, to dispatch handlers for any asynchronous ++ * operations performed on the socket. ++ * ++ * @param protocol An object specifying protocol parameters to be used. ++ * ++ * @param native_socket The new underlying socket implementation. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ */ ++ template ++ basic_stream_socket_ext(ExecutionContext& context, ++ const protocol_type& protocol, const native_handle_type& native_socket, ++ typename enable_if< ++ is_convertible::value ++ >::type* = 0) ++ : basic_socket_ext_local(context, protocol, native_socket) ++ { ++ } ++ ++#if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) ++ /// Move-construct a basic_stream_socket from another. ++ /** ++ * This constructor moves a stream socket from one object to another. ++ * ++ * @param other The other basic_stream_socket object from which the move ++ * will occur. ++ * ++ * @note Following the move, the moved-from object is in the same state as if ++ * constructed using the @c basic_stream_socket(const executor_type&) ++ * constructor. ++ */ ++ basic_stream_socket_ext(basic_stream_socket_ext&& other) ++ : basic_socket_ext_local(std::move(other)) ++ { ++ } ++ ++ /// Move-assign a basic_stream_socket from another. ++ /** ++ * This assignment operator moves a stream socket from one object to another. ++ * ++ * @param other The other basic_stream_socket object from which the move ++ * will occur. ++ * ++ * @note Following the move, the moved-from object is in the same state as if ++ * constructed using the @c basic_stream_socket(const executor_type&) ++ * constructor. ++ */ ++ basic_stream_socket_ext& operator=(basic_stream_socket_ext&& other) ++ { ++ basic_socket_ext_local::operator=(std::move(other)); ++ return *this; ++ } ++ ++ /// Move-construct a basic_stream_socket from a socket of another protocol ++ /// type. ++ /** ++ * This constructor moves a stream socket from one object to another. ++ * ++ * @param other The other basic_stream_socket object from which the move ++ * will occur. ++ * ++ * @note Following the move, the moved-from object is in the same state as if ++ * constructed using the @c basic_stream_socket(const executor_type&) ++ * constructor. ++ */ ++ template ++ basic_stream_socket_ext(basic_stream_socket_ext&& other, ++ typename enable_if< ++ is_convertible::value ++ && is_convertible::value ++ >::type* = 0) ++ : basic_socket_ext_local(std::move(other)) ++ { ++ } ++ ++ /// Move-assign a basic_stream_socket from a socket of another protocol type. ++ /** ++ * This assignment operator moves a stream socket from one object to another. ++ * ++ * @param other The other basic_stream_socket object from which the move ++ * will occur. ++ * ++ * @note Following the move, the moved-from object is in the same state as if ++ * constructed using the @c basic_stream_socket(const executor_type&) ++ * constructor. ++ */ ++ template ++ typename enable_if< ++ is_convertible::value ++ && is_convertible::value, ++ basic_stream_socket_ext& ++ >::type operator=(basic_stream_socket_ext&& other) ++ { ++ basic_socket_ext_local::operator=(std::move(other)); ++ return *this; ++ } ++#endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) ++ ++ /// Destroys the socket. ++ /** ++ * This function destroys the socket, cancelling any outstanding asynchronous ++ * operations associated with the socket as if by calling @c cancel. ++ */ ++ ~basic_stream_socket_ext() ++ { ++ } ++ ++ /// Send some data on the socket. ++ /** ++ * This function is used to send data on the stream socket. The function ++ * call will block until one or more bytes of the data has been sent ++ * successfully, or an until error occurs. ++ * ++ * @param buffers One or more data buffers to be sent on the socket. ++ * ++ * @returns The number of bytes sent. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ * ++ * @note The send operation may not transmit all of the data to the peer. ++ * Consider using the @ref write function if you need to ensure that all data ++ * is written before the blocking operation completes. ++ * ++ * @par Example ++ * To send a single data buffer use the @ref buffer function as follows: ++ * @code ++ * socket.send(boost::asio::buffer(data, size)); ++ * @endcode ++ * See the @ref buffer documentation for information on sending multiple ++ * buffers in one go, and how to use it with arrays, boost::array or ++ * std::vector. ++ */ ++ template ++ std::size_t send(const ConstBufferSequence& buffers) ++ { ++ boost::system::error_code ec; ++ std::size_t s = this->impl_.get_service().send( ++ this->impl_.get_implementation(), buffers, 0, ec); ++ boost::asio::detail::throw_error(ec, "send"); ++ return s; ++ } ++ ++ /// Send some data on the socket. ++ /** ++ * This function is used to send data on the stream socket. The function ++ * call will block until one or more bytes of the data has been sent ++ * successfully, or an until error occurs. ++ * ++ * @param buffers One or more data buffers to be sent on the socket. ++ * ++ * @param flags Flags specifying how the send call is to be made. ++ * ++ * @returns The number of bytes sent. ++ * ++ * @throws boost::system::system_error Thrown on failure. ++ * ++ * @note The send operation may not transmit all of the data to the peer. ++ * Consider using the @ref write function if you need to ensure that all data ++ * is written before the blocking operation completes. ++ * ++ * @par Example ++ * To send a single data buffer use the @ref buffer function as follows: ++ * @code ++ * socket.send(boost::asio::buffer(data, size), 0); ++ * @endcode ++ * See the @ref buffer documentation for information on sending multiple ++ * buffers in one go, and how to use it with arrays, boost::array or ++ * std::vector. ++ */ ++ template ++ std::size_t send(const ConstBufferSequence& buffers, ++ socket_base::message_flags flags) ++ { ++ boost::system::error_code ec; ++ std::size_t s = this->impl_.get_service().send( ++ this->impl_.get_implementation(), buffers, flags, ec); ++ boost::asio::detail::throw_error(ec, "send"); ++ return s; ++ } ++ ++ /// Send some data on the socket. ++ /** ++ * This function is used to send data on the stream socket. The function ++ * call will block until one or more bytes of the data has been sent ++ * successfully, or an until error occurs. ++ * ++ * @param buffers One or more data buffers to be sent on the socket. ++ * ++ * @param flags Flags specifying how the send call is to be made. ++ * ++ * @param ec Set to indicate what error occurred, if any. ++ * ++ * @returns The number of bytes sent. Returns 0 if an error occurred. ++ * ++ * @note The send operation may not transmit all of the data to the peer. ++ * Consider using the @ref write function if you need to ensure that all data ++ * is written before the blocking operation completes. ++ */ ++ template ++ std::size_t send(const ConstBufferSequence& buffers, ++ socket_base::message_flags flags, boost::system::error_code& ec) ++ { ++ return this->impl_.get_service().send( ++ this->impl_.get_implementation(), buffers, flags, ec); ++ } ++ ++ /// Start an asynchronous send. ++ /** ++ * This function is used to asynchronously send data on the stream socket. ++ * The function call always returns immediately. ++ * ++ * @param buffers One or more data buffers to be sent on the socket. Although ++ * the buffers object may be copied as necessary, ownership of the underlying ++ * memory blocks is retained by the caller, which must guarantee that they ++ * remain valid until the handler is called. ++ * ++ * @param handler The handler to be called when the send operation completes. ++ * Copies will be made of the handler as required. The function signature of ++ * the handler must be: ++ * @code void handler( ++ * const boost::system::error_code& error, // Result of operation. ++ * std::size_t bytes_transferred // Number of bytes sent. ++ * ); @endcode ++ * Regardless of whether the asynchronous operation completes immediately or ++ * not, the handler will not be invoked from within this function. On ++ * immediate completion, invocation of the handler will be performed in a ++ * manner equivalent to using boost::asio::post(). ++ * ++ * @note The send operation may not transmit all of the data to the peer. ++ * Consider using the @ref async_write function if you need to ensure that all ++ * data is written before the asynchronous operation completes. ++ * ++ * @par Example ++ * To send a single data buffer use the @ref buffer function as follows: ++ * @code ++ * socket.async_send(boost::asio::buffer(data, size), handler); ++ * @endcode ++ * See the @ref buffer documentation for information on sending multiple ++ * buffers in one go, and how to use it with arrays, boost::array or ++ * std::vector. ++ */ ++ template ++ BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler, ++ void (boost::system::error_code, std::size_t)) ++ async_send(const ConstBufferSequence& buffers, ++ BOOST_ASIO_MOVE_ARG(WriteHandler) handler) ++ { ++ return async_initiate( ++ initiate_async_send(), handler, this, ++ buffers, socket_base::message_flags(0)); ++ } ++ ++ /// Start an asynchronous send. ++ /** ++ * This function is used to asynchronously send data on the stream socket. ++ * The function call always returns immediately. ++ * ++ * @param buffers One or more data buffers to be sent on the socket. Although ++ * the buffers object may be copied as necessary, ownership of the underlying ++ * memory blocks is retained by the caller, which must guarantee that they ++ * remain valid until the handler is called. ++ * ++ * @param flags Flags specifying how the send call is to be made. ++ * ++ * @param handler The handler to be called when the send operation completes. ++ * Copies will be made of the handler as required. The function signature of ++ * the handler must be: ++ * @code void handler( ++ * const boost::system::error_code& error, // Result of operation. ++ * std::size_t bytes_transferred // Number of bytes sent. ++ * ); @endcode ++ * Regardless of whether the asynchronous operation completes immediately or ++ * not, the handler will not be invoked from within this function. On ++ * immediate completion, invocation of the handler will be performed in a ++ * manner equivalent to using boost::asio::post(). ++ * ++ * @note The send operation may not transmit all of the data to the peer. ++ * Consider using the @ref async_write function if you need to ensure that all ++ * data is written before the asynchronous operation completes. ++ * ++ * @par Example ++ * To send a single data buffer use the @ref buffer function as follows: ++ * @code ++ * socket.async_send(boost::asio::buffer(data, size), 0, handler); ++ * @endcode ++ * See the @ref buffer documentation for information on sending multiple ++ * buffers in one go, and how to use it with arrays, boost::array or ++ * std::vector. ++ */ ++ template ++ BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler, ++ void (boost::system::error_code, std::size_t)) ++ async_send(const ConstBufferSequence& buffers, ++ socket_base::message_flags flags, ++ BOOST_ASIO_MOVE_ARG(WriteHandler) handler) ++ { ++ return async_initiate( ++ initiate_async_send(), handler, this, buffers, flags); ++ } ++ ++ /// Receive some data on the socket. ++ /** ++ * This function is used to receive data on the stream socket. The function ++ * call will block until one or more bytes of data has been received ++ * successfully, or until an error occurs. ++ * ++ * @param buffers One or more buffers into which the data will be received. ++ * ++ * @returns The number of bytes received. ++ * ++ * @throws boost::system::system_error Thrown on failure. An error code of ++ * boost::asio::error::eof indicates that the connection was closed by the ++ * peer. ++ * ++ * @note The receive operation may not receive all of the requested number of ++ * bytes. Consider using the @ref read function if you need to ensure that the ++ * requested amount of data is read before the blocking operation completes. ++ * ++ * @par Example ++ * To receive into a single data buffer use the @ref buffer function as ++ * follows: ++ * @code ++ * socket.receive(boost::asio::buffer(data, size)); ++ * @endcode ++ * See the @ref buffer documentation for information on receiving into ++ * multiple buffers in one go, and how to use it with arrays, boost::array or ++ * std::vector. ++ */ ++ template ++ std::size_t receive(const MutableBufferSequence& buffers) ++ { ++ boost::system::error_code ec; ++ std::size_t s = this->impl_.get_service().receive( ++ this->impl_.get_implementation(), buffers, 0, ec); ++ boost::asio::detail::throw_error(ec, "receive"); ++ return s; ++ } ++ ++ /// Receive some data on the socket. ++ /** ++ * This function is used to receive data on the stream socket. The function ++ * call will block until one or more bytes of data has been received ++ * successfully, or until an error occurs. ++ * ++ * @param buffers One or more buffers into which the data will be received. ++ * ++ * @param flags Flags specifying how the receive call is to be made. ++ * ++ * @returns The number of bytes received. ++ * ++ * @throws boost::system::system_error Thrown on failure. An error code of ++ * boost::asio::error::eof indicates that the connection was closed by the ++ * peer. ++ * ++ * @note The receive operation may not receive all of the requested number of ++ * bytes. Consider using the @ref read function if you need to ensure that the ++ * requested amount of data is read before the blocking operation completes. ++ * ++ * @par Example ++ * To receive into a single data buffer use the @ref buffer function as ++ * follows: ++ * @code ++ * socket.receive(boost::asio::buffer(data, size), 0); ++ * @endcode ++ * See the @ref buffer documentation for information on receiving into ++ * multiple buffers in one go, and how to use it with arrays, boost::array or ++ * std::vector. ++ */ ++ template ++ std::size_t receive(const MutableBufferSequence& buffers, ++ socket_base::message_flags flags) ++ { ++ boost::system::error_code ec; ++ std::size_t s = this->impl_.get_service().receive( ++ this->impl_.get_implementation(), buffers, flags, ec); ++ boost::asio::detail::throw_error(ec, "receive"); ++ return s; ++ } ++ ++ /// Receive some data on a connected socket. ++ /** ++ * This function is used to receive data on the stream socket. The function ++ * call will block until one or more bytes of data has been received ++ * successfully, or until an error occurs. ++ * ++ * @param buffers One or more buffers into which the data will be received. ++ * ++ * @param flags Flags specifying how the receive call is to be made. ++ * ++ * @param ec Set to indicate what error occurred, if any. ++ * ++ * @returns The number of bytes received. Returns 0 if an error occurred. ++ * ++ * @note The receive operation may not receive all of the requested number of ++ * bytes. Consider using the @ref read function if you need to ensure that the ++ * requested amount of data is read before the blocking operation completes. ++ */ ++ template ++ std::size_t receive(const MutableBufferSequence& buffers, ++ socket_base::message_flags flags, boost::system::error_code& ec) ++ { ++ return this->impl_.get_service().receive( ++ this->impl_.get_implementation(), buffers, flags, ec); ++ } ++ ++ /// Start an asynchronous receive. ++ /** ++ * This function is used to asynchronously receive data from the stream ++ * socket. The function call always returns immediately. ++ * ++ * @param buffers One or more buffers into which the data will be received. ++ * Although the buffers object may be copied as necessary, ownership of the ++ * underlying memory blocks is retained by the caller, which must guarantee ++ * that they remain valid until the handler is called. ++ * ++ * @param handler The handler to be called when the receive operation ++ * completes. Copies will be made of the handler as required. The function ++ * signature of the handler must be: ++ * @code void handler( ++ * const boost::system::error_code& error, // Result of operation. ++ * std::size_t bytes_transferred // Number of bytes received. ++ * ); @endcode ++ * Regardless of whether the asynchronous operation completes immediately or ++ * not, the handler will not be invoked from within this function. On ++ * immediate completion, invocation of the handler will be performed in a ++ * manner equivalent to using boost::asio::post(). ++ * ++ * @note The receive operation may not receive all of the requested number of ++ * bytes. Consider using the @ref async_read function if you need to ensure ++ * that the requested amount of data is received before the asynchronous ++ * operation completes. ++ * ++ * @par Example ++ * To receive into a single data buffer use the @ref buffer function as ++ * follows: ++ * @code ++ * socket.async_receive(boost::asio::buffer(data, size), handler); ++ * @endcode ++ * See the @ref buffer documentation for information on receiving into ++ * multiple buffers in one go, and how to use it with arrays, boost::array or ++ * std::vector. ++ */ ++ template ++ BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler, ++ void (boost::system::error_code, std::size_t, std::uint32_t, std::uint32_t)) ++ async_receive(const MutableBufferSequence& buffers, ++ BOOST_ASIO_MOVE_ARG(ReadHandler) handler) ++ { ++ return async_initiate( ++ initiate_async_receive(), handler, this, ++ buffers, socket_base::message_flags(0)); ++ } ++ ++ /// Start an asynchronous receive. ++ /** ++ * This function is used to asynchronously receive data from the stream ++ * socket. The function call always returns immediately. ++ * ++ * @param buffers One or more buffers into which the data will be received. ++ * Although the buffers object may be copied as necessary, ownership of the ++ * underlying memory blocks is retained by the caller, which must guarantee ++ * that they remain valid until the handler is called. ++ * ++ * @param flags Flags specifying how the receive call is to be made. ++ * ++ * @param handler The handler to be called when the receive operation ++ * completes. Copies will be made of the handler as required. The function ++ * signature of the handler must be: ++ * @code void handler( ++ * const boost::system::error_code& error, // Result of operation. ++ * std::size_t bytes_transferred // Number of bytes received. ++ * ); @endcode ++ * Regardless of whether the asynchronous operation completes immediately or ++ * not, the handler will not be invoked from within this function. On ++ * immediate completion, invocation of the handler will be performed in a ++ * manner equivalent to using boost::asio::post(). ++ * ++ * @note The receive operation may not receive all of the requested number of ++ * bytes. Consider using the @ref async_read function if you need to ensure ++ * that the requested amount of data is received before the asynchronous ++ * operation completes. ++ * ++ * @par Example ++ * To receive into a single data buffer use the @ref buffer function as ++ * follows: ++ * @code ++ * socket.async_receive(boost::asio::buffer(data, size), 0, handler); ++ * @endcode ++ * See the @ref buffer documentation for information on receiving into ++ * multiple buffers in one go, and how to use it with arrays, boost::array or ++ * std::vector. ++ */ ++ template ++ BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler, ++ void (boost::system::error_code, std::size_t, std::uint32_t, std::uint32_t)) ++ async_receive(const MutableBufferSequence& buffers, ++ socket_base::message_flags flags, ++ BOOST_ASIO_MOVE_ARG(ReadHandler) handler) ++ { ++ return async_initiate( ++ initiate_async_receive(), handler, this, buffers, flags); ++ } ++ ++ /// Write some data to the socket. ++ /** ++ * This function is used to write data to the stream socket. The function call ++ * will block until one or more bytes of the data has been written ++ * successfully, or until an error occurs. ++ * ++ * @param buffers One or more data buffers to be written to the socket. ++ * ++ * @returns The number of bytes written. ++ * ++ * @throws boost::system::system_error Thrown on failure. An error code of ++ * boost::asio::error::eof indicates that the connection was closed by the ++ * peer. ++ * ++ * @note The write_some operation may not transmit all of the data to the ++ * peer. Consider using the @ref write function if you need to ensure that ++ * all data is written before the blocking operation completes. ++ * ++ * @par Example ++ * To write a single data buffer use the @ref buffer function as follows: ++ * @code ++ * socket.write_some(boost::asio::buffer(data, size)); ++ * @endcode ++ * See the @ref buffer documentation for information on writing multiple ++ * buffers in one go, and how to use it with arrays, boost::array or ++ * std::vector. ++ */ ++ template ++ std::size_t write_some(const ConstBufferSequence& buffers) ++ { ++ boost::system::error_code ec; ++ std::size_t s = this->impl_.get_service().send( ++ this->impl_.get_implementation(), buffers, 0, ec); ++ boost::asio::detail::throw_error(ec, "write_some"); ++ return s; ++ } ++ ++ /// Write some data to the socket. ++ /** ++ * This function is used to write data to the stream socket. The function call ++ * will block until one or more bytes of the data has been written ++ * successfully, or until an error occurs. ++ * ++ * @param buffers One or more data buffers to be written to the socket. ++ * ++ * @param ec Set to indicate what error occurred, if any. ++ * ++ * @returns The number of bytes written. Returns 0 if an error occurred. ++ * ++ * @note The write_some operation may not transmit all of the data to the ++ * peer. Consider using the @ref write function if you need to ensure that ++ * all data is written before the blocking operation completes. ++ */ ++ template ++ std::size_t write_some(const ConstBufferSequence& buffers, ++ boost::system::error_code& ec) ++ { ++ return this->impl_.get_service().send( ++ this->impl_.get_implementation(), buffers, 0, ec); ++ } ++ ++ /// Start an asynchronous write. ++ /** ++ * This function is used to asynchronously write data to the stream socket. ++ * The function call always returns immediately. ++ * ++ * @param buffers One or more data buffers to be written to the socket. ++ * Although the buffers object may be copied as necessary, ownership of the ++ * underlying memory blocks is retained by the caller, which must guarantee ++ * that they remain valid until the handler is called. ++ * ++ * @param handler The handler to be called when the write operation completes. ++ * Copies will be made of the handler as required. The function signature of ++ * the handler must be: ++ * @code void handler( ++ * const boost::system::error_code& error, // Result of operation. ++ * std::size_t bytes_transferred // Number of bytes written. ++ * ); @endcode ++ * Regardless of whether the asynchronous operation completes immediately or ++ * not, the handler will not be invoked from within this function. On ++ * immediate completion, invocation of the handler will be performed in a ++ * manner equivalent to using boost::asio::post(). ++ * ++ * @note The write operation may not transmit all of the data to the peer. ++ * Consider using the @ref async_write function if you need to ensure that all ++ * data is written before the asynchronous operation completes. ++ * ++ * @par Example ++ * To write a single data buffer use the @ref buffer function as follows: ++ * @code ++ * socket.async_write_some(boost::asio::buffer(data, size), handler); ++ * @endcode ++ * See the @ref buffer documentation for information on writing multiple ++ * buffers in one go, and how to use it with arrays, boost::array or ++ * std::vector. ++ */ ++ template ++ BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler, ++ void (boost::system::error_code, std::size_t, std::uint32_t, std::uint32_t)) ++ async_write_some(const ConstBufferSequence& buffers, ++ BOOST_ASIO_MOVE_ARG(WriteHandler) handler) ++ { ++ return async_initiate( ++ initiate_async_send(), handler, this, ++ buffers, socket_base::message_flags(0)); ++ } ++ ++ /// Read some data from the socket. ++ /** ++ * This function is used to read data from the stream socket. The function ++ * call will block until one or more bytes of data has been read successfully, ++ * or until an error occurs. ++ * ++ * @param buffers One or more buffers into which the data will be read. ++ * ++ * @returns The number of bytes read. ++ * ++ * @throws boost::system::system_error Thrown on failure. An error code of ++ * boost::asio::error::eof indicates that the connection was closed by the ++ * peer. ++ * ++ * @note The read_some operation may not read all of the requested number of ++ * bytes. Consider using the @ref read function if you need to ensure that ++ * the requested amount of data is read before the blocking operation ++ * completes. ++ * ++ * @par Example ++ * To read into a single data buffer use the @ref buffer function as follows: ++ * @code ++ * socket.read_some(boost::asio::buffer(data, size)); ++ * @endcode ++ * See the @ref buffer documentation for information on reading into multiple ++ * buffers in one go, and how to use it with arrays, boost::array or ++ * std::vector. ++ */ ++ template ++ std::size_t read_some(const MutableBufferSequence& buffers) ++ { ++ boost::system::error_code ec; ++ std::size_t s = this->impl_.get_service().receive( ++ this->impl_.get_implementation(), buffers, 0, ec); ++ boost::asio::detail::throw_error(ec, "read_some"); ++ return s; ++ } ++ ++ /// Read some data from the socket. ++ /** ++ * This function is used to read data from the stream socket. The function ++ * call will block until one or more bytes of data has been read successfully, ++ * or until an error occurs. ++ * ++ * @param buffers One or more buffers into which the data will be read. ++ * ++ * @param ec Set to indicate what error occurred, if any. ++ * ++ * @returns The number of bytes read. Returns 0 if an error occurred. ++ * ++ * @note The read_some operation may not read all of the requested number of ++ * bytes. Consider using the @ref read function if you need to ensure that ++ * the requested amount of data is read before the blocking operation ++ * completes. ++ */ ++ template ++ std::size_t read_some(const MutableBufferSequence& buffers, ++ boost::system::error_code& ec) ++ { ++ return this->impl_.get_service().receive( ++ this->impl_.get_implementation(), buffers, 0, ec); ++ } ++ ++ /// Start an asynchronous read. ++ /** ++ * This function is used to asynchronously read data from the stream socket. ++ * The function call always returns immediately. ++ * ++ * @param buffers One or more buffers into which the data will be read. ++ * Although the buffers object may be copied as necessary, ownership of the ++ * underlying memory blocks is retained by the caller, which must guarantee ++ * that they remain valid until the handler is called. ++ * ++ * @param handler The handler to be called when the read operation completes. ++ * Copies will be made of the handler as required. The function signature of ++ * the handler must be: ++ * @code void handler( ++ * const boost::system::error_code& error, // Result of operation. ++ * std::size_t bytes_transferred // Number of bytes read. ++ * ); @endcode ++ * Regardless of whether the asynchronous operation completes immediately or ++ * not, the handler will not be invoked from within this function. On ++ * immediate completion, invocation of the handler will be performed in a ++ * manner equivalent to using boost::asio::post(). ++ * ++ * @note The read operation may not read all of the requested number of bytes. ++ * Consider using the @ref async_read function if you need to ensure that the ++ * requested amount of data is read before the asynchronous operation ++ * completes. ++ * ++ * @par Example ++ * To read into a single data buffer use the @ref buffer function as follows: ++ * @code ++ * socket.async_read_some(boost::asio::buffer(data, size), handler); ++ * @endcode ++ * See the @ref buffer documentation for information on reading into multiple ++ * buffers in one go, and how to use it with arrays, boost::array or ++ * std::vector. ++ */ ++ template ++ BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler, ++ void (boost::system::error_code, std::size_t, std::uint32_t, std::uint32_t)) ++ async_read_some(const MutableBufferSequence& buffers, ++ BOOST_ASIO_MOVE_ARG(ReadHandler) handler) ++ { ++ return async_initiate( ++ initiate_async_receive(), handler, this, ++ buffers, socket_base::message_flags(0)); ++ } ++ ++private: ++ struct initiate_async_send ++ { ++ template ++ void operator()(BOOST_ASIO_MOVE_ARG(WriteHandler) handler, ++ basic_stream_socket_ext* self, const ConstBufferSequence& buffers, ++ socket_base::message_flags flags) const ++ { ++ // If you get an error on the following line it means that your handler ++ // does not meet the documented type requirements for a WriteHandler. ++ BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check; ++ ++ detail::non_const_lvalue handler2(handler); ++ self->impl_.get_service().async_send( ++ self->impl_.get_implementation(), buffers, flags, ++ handler2.value, self->impl_.get_executor()); ++ } ++ }; ++ ++ struct initiate_async_receive ++ { ++ template ++ void operator()(BOOST_ASIO_MOVE_ARG(ReadHandler) handler, ++ basic_stream_socket_ext* self, const MutableBufferSequence& buffers, ++ socket_base::message_flags flags) const ++ { ++ // If you get an error on the following line it means that your handler ++ // does not meet the documented type requirements for a ReadHandler. ++ BOOST_ASIO_READ_HANDLER_CHECK_EXT_LOCAL(ReadHandler, handler) type_check; ++ ++ detail::non_const_lvalue handler2(handler); ++ self->impl_.get_service().async_receive( ++ self->impl_.get_implementation(), buffers, flags, ++ handler2.value, self->impl_.get_executor()); ++ } ++ }; ++}; ++ ++} // namespace asio ++} // namespace boost ++ ++#include ++ ++#endif // BOOST_ASIO_BASIC_STREAM_SOCKET_EXT_HPP +diff --git a/implementation/helper/1.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 ++ ++// Older versions of gcc have difficulty compiling the sizeof expressions where ++// we test the handler type requirements. We'll disable checking of handler type ++// requirements for those compilers, but otherwise enable it by default. ++#if !defined(BOOST_ASIO_DISABLE_HANDLER_TYPE_REQUIREMENTS) ++# if !defined(__GNUC__) || (__GNUC__ >= 4) ++# define BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS 1 ++# endif // !defined(__GNUC__) || (__GNUC__ >= 4) ++#endif // !defined(BOOST_ASIO_DISABLE_HANDLER_TYPE_REQUIREMENTS) ++ ++// With C++0x we can use a combination of enhanced SFINAE and static_assert to ++// generate better template error messages. As this technique is not yet widely ++// portable, we'll only enable it for tested compilers. ++#if !defined(BOOST_ASIO_DISABLE_HANDLER_TYPE_REQUIREMENTS_ASSERT) ++# if defined(__GNUC__) ++# if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 5)) || (__GNUC__ > 4) ++# if defined(__GXX_EXPERIMENTAL_CXX0X__) ++# define BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS_ASSERT 1 ++# endif // defined(__GXX_EXPERIMENTAL_CXX0X__) ++# endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 5)) || (__GNUC__ > 4) ++# endif // defined(__GNUC__) ++# if defined(BOOST_ASIO_MSVC) ++# if (_MSC_VER >= 1600) ++# define BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS_ASSERT 1 ++# endif // (_MSC_VER >= 1600) ++# endif // defined(BOOST_ASIO_MSVC) ++# if defined(__clang__) ++# if __has_feature(__cxx_static_assert__) ++# define BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS_ASSERT 1 ++# endif // __has_feature(cxx_static_assert) ++# endif // defined(__clang__) ++#endif // !defined(BOOST_ASIO_DISABLE_HANDLER_TYPE_REQUIREMENTS) ++ ++#if defined(BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS) ++# include ++#endif // defined(BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS) ++ ++namespace boost { ++namespace asio { ++namespace detail { ++ ++#if defined(BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS) ++ ++# if defined(BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS_ASSERT) ++ ++template ++auto zero_arg_copyable_handler_test(Handler h, void*) ++ -> decltype( ++ sizeof(Handler(static_cast(h))), ++ (BOOST_ASIO_MOVE_OR_LVALUE(Handler)(h)()), ++ char(0)); ++ ++template ++char (&zero_arg_copyable_handler_test(Handler, ...))[2]; ++ ++template ++auto one_arg_handler_test(Handler h, Arg1* a1) ++ -> decltype( ++ sizeof(Handler(BOOST_ASIO_MOVE_CAST(Handler)(h))), ++ (BOOST_ASIO_MOVE_OR_LVALUE(Handler)(h)(*a1)), ++ char(0)); ++ ++template ++char (&one_arg_handler_test(Handler h, ...))[2]; ++ ++template ++auto two_arg_handler_test(Handler h, Arg1* a1, Arg2* a2) ++ -> decltype( ++ sizeof(Handler(BOOST_ASIO_MOVE_CAST(Handler)(h))), ++ (BOOST_ASIO_MOVE_OR_LVALUE(Handler)(h)(*a1, *a2)), ++ char(0)); ++ ++template ++char (&two_arg_handler_test(Handler, ...))[2]; ++ ++template ++auto two_arg_move_handler_test(Handler h, Arg1* a1, Arg2* a2) ++ -> decltype( ++ sizeof(Handler(BOOST_ASIO_MOVE_CAST(Handler)(h))), ++ (BOOST_ASIO_MOVE_OR_LVALUE(Handler)(h)( ++ *a1, BOOST_ASIO_MOVE_CAST(Arg2)(*a2))), ++ char(0)); ++ ++template ++char (&two_arg_move_handler_test(Handler, ...))[2]; ++ ++template ++auto three_arg_handler_test(Handler h, Arg1* a1, Arg2* a2, Arg3* a3) ++ -> decltype( ++ sizeof(Handler(BOOST_ASIO_MOVE_CAST(Handler)(h))), ++ ((h)(*a1, *a2, *a3)), ++ char(0)); ++ ++template ++char (&three_arg_handler_test(Handler, ...))[2]; ++ ++template ++auto three_arg_move_handler_test(Handler h, Arg1* a1, Arg2* a2, Arg3 *a3) ++ -> decltype( ++ sizeof(Handler(BOOST_ASIO_MOVE_CAST(Handler)(h))), ++ ((h)(*a1, BOOST_ASIO_MOVE_CAST(Arg2)(*a2), BOOST_ASIO_MOVE_CAST(Arg3)(*a3))), ++ char(0)); ++ ++template ++char (&three_arg_move_handler_test(Handler, ...))[2]; ++ ++# define BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT(expr, msg) \ ++ static_assert(expr, msg); ++ ++# else // defined(BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS_ASSERT) ++ ++# define BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT(expr, msg) ++ ++# endif // defined(BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS_ASSERT) ++ ++template T& lvref(); ++template T& lvref(T); ++template const T& clvref(); ++template const T& clvref(T); ++#if defined(BOOST_ASIO_HAS_MOVE) ++template T rvref(); ++template T rvref(T); ++#else // defined(BOOST_ASIO_HAS_MOVE) ++template const T& rvref(); ++template const T& rvref(T); ++#endif // defined(BOOST_ASIO_HAS_MOVE) ++template char argbyv(T); ++ ++#if 0 ++template ++struct handler_type_requirements ++{ ++}; ++#endif ++ ++#define BOOST_ASIO_LEGACY_COMPLETION_HANDLER_CHECK( \ ++ handler_type, handler) \ ++ \ ++ typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \ ++ void()) asio_true_handler_type; \ ++ \ ++ BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \ ++ sizeof(boost::asio::detail::zero_arg_copyable_handler_test( \ ++ boost::asio::detail::clvref< \ ++ asio_true_handler_type>(), 0)) == 1, \ ++ "CompletionHandler type requirements not met") \ ++ \ ++ typedef boost::asio::detail::handler_type_requirements< \ ++ sizeof( \ ++ boost::asio::detail::argbyv( \ ++ boost::asio::detail::clvref< \ ++ asio_true_handler_type>())) + \ ++ sizeof( \ ++ boost::asio::detail::lvref< \ ++ asio_true_handler_type>()(), \ ++ char(0))> BOOST_ASIO_UNUSED_TYPEDEF ++ ++#define BOOST_ASIO_READ_HANDLER_CHECK_EXT( \ ++ handler_type, handler) \ ++ \ ++ typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \ ++ void(boost::system::error_code, std::size_t, \ ++ boost::asio::ip::address)) \ ++ asio_true_handler_type; \ ++ \ ++ BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \ ++ sizeof(boost::asio::detail::three_arg_handler_test( \ ++ boost::asio::detail::rvref< \ ++ asio_true_handler_type>(), \ ++ static_cast(0), \ ++ static_cast(0), \ ++ static_cast(0))) == 1, \ ++ "ReadHandler type requirements not met") \ ++ \ ++ typedef boost::asio::detail::handler_type_requirements< \ ++ sizeof( \ ++ boost::asio::detail::argbyv( \ ++ boost::asio::detail::rvref< \ ++ asio_true_handler_type>())) + \ ++ sizeof( \ ++ boost::asio::detail::lvref< \ ++ asio_true_handler_type>()( \ ++ boost::asio::detail::lvref(), \ ++ boost::asio::detail::lvref(), \ ++ boost::asio::detail::lvref()), \ ++ char(0))> BOOST_ASIO_UNUSED_TYPEDEF ++ ++#define BOOST_ASIO_WRITE_HANDLER_CHECK( \ ++ handler_type, handler) \ ++ \ ++ typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \ ++ void(boost::system::error_code, std::size_t)) \ ++ asio_true_handler_type; \ ++ \ ++ BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \ ++ sizeof(boost::asio::detail::two_arg_handler_test( \ ++ boost::asio::detail::rvref< \ ++ asio_true_handler_type>(), \ ++ static_cast(0), \ ++ static_cast(0))) == 1, \ ++ "WriteHandler type requirements not met") \ ++ \ ++ typedef boost::asio::detail::handler_type_requirements< \ ++ sizeof( \ ++ boost::asio::detail::argbyv( \ ++ boost::asio::detail::rvref< \ ++ asio_true_handler_type>())) + \ ++ sizeof( \ ++ boost::asio::detail::lvref< \ ++ asio_true_handler_type>()( \ ++ boost::asio::detail::lvref(), \ ++ boost::asio::detail::lvref()), \ ++ char(0))> BOOST_ASIO_UNUSED_TYPEDEF ++ ++#if 0 ++#define BOOST_ASIO_ACCEPT_HANDLER_CHECK( \ ++ handler_type, handler) \ ++ \ ++ typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \ ++ void(boost::system::error_code)) \ ++ asio_true_handler_type; \ ++ \ ++ BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \ ++ sizeof(boost::asio::detail::one_arg_handler_test( \ ++ boost::asio::detail::rvref< \ ++ asio_true_handler_type>(), \ ++ static_cast(0))) == 1, \ ++ "AcceptHandler type requirements not met") \ ++ \ ++ typedef boost::asio::detail::handler_type_requirements< \ ++ sizeof( \ ++ boost::asio::detail::argbyv( \ ++ boost::asio::detail::rvref< \ ++ asio_true_handler_type>())) + \ ++ sizeof( \ ++ boost::asio::detail::lvref< \ ++ asio_true_handler_type>()( \ ++ boost::asio::detail::lvref()), \ ++ char(0))> BOOST_ASIO_UNUSED_TYPEDEF ++ ++#define BOOST_ASIO_MOVE_ACCEPT_HANDLER_CHECK( \ ++ handler_type, handler, socket_type) \ ++ \ ++ typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \ ++ void(boost::system::error_code, socket_type)) \ ++ asio_true_handler_type; \ ++ \ ++ BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \ ++ sizeof(boost::asio::detail::two_arg_move_handler_test( \ ++ boost::asio::detail::rvref< \ ++ asio_true_handler_type>(), \ ++ static_cast(0), \ ++ static_cast(0))) == 1, \ ++ "MoveAcceptHandler type requirements not met") \ ++ \ ++ typedef boost::asio::detail::handler_type_requirements< \ ++ sizeof( \ ++ boost::asio::detail::argbyv( \ ++ boost::asio::detail::rvref< \ ++ asio_true_handler_type>())) + \ ++ sizeof( \ ++ boost::asio::detail::lvref< \ ++ asio_true_handler_type>()( \ ++ boost::asio::detail::lvref(), \ ++ boost::asio::detail::rvref()), \ ++ char(0))> BOOST_ASIO_UNUSED_TYPEDEF ++#endif ++ ++#define BOOST_ASIO_CONNECT_HANDLER_CHECK( \ ++ handler_type, handler) \ ++ \ ++ typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \ ++ void(boost::system::error_code)) \ ++ asio_true_handler_type; \ ++ \ ++ BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \ ++ sizeof(boost::asio::detail::one_arg_handler_test( \ ++ boost::asio::detail::rvref< \ ++ asio_true_handler_type>(), \ ++ static_cast(0))) == 1, \ ++ "ConnectHandler type requirements not met") \ ++ \ ++ typedef boost::asio::detail::handler_type_requirements< \ ++ sizeof( \ ++ boost::asio::detail::argbyv( \ ++ boost::asio::detail::rvref< \ ++ asio_true_handler_type>())) + \ ++ sizeof( \ ++ boost::asio::detail::lvref< \ ++ asio_true_handler_type>()( \ ++ boost::asio::detail::lvref()), \ ++ char(0))> BOOST_ASIO_UNUSED_TYPEDEF ++ ++#define BOOST_ASIO_RANGE_CONNECT_HANDLER_CHECK( \ ++ handler_type, handler, endpoint_type) \ ++ \ ++ typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \ ++ void(boost::system::error_code, endpoint_type)) \ ++ asio_true_handler_type; \ ++ \ ++ BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \ ++ sizeof(boost::asio::detail::two_arg_handler_test( \ ++ boost::asio::detail::rvref< \ ++ asio_true_handler_type>(), \ ++ static_cast(0), \ ++ static_cast(0))) == 1, \ ++ "RangeConnectHandler type requirements not met") \ ++ \ ++ typedef boost::asio::detail::handler_type_requirements< \ ++ sizeof( \ ++ boost::asio::detail::argbyv( \ ++ boost::asio::detail::rvref< \ ++ asio_true_handler_type>())) + \ ++ sizeof( \ ++ boost::asio::detail::lvref< \ ++ asio_true_handler_type>()( \ ++ boost::asio::detail::lvref(), \ ++ boost::asio::detail::lvref()), \ ++ char(0))> BOOST_ASIO_UNUSED_TYPEDEF ++ ++#define BOOST_ASIO_ITERATOR_CONNECT_HANDLER_CHECK( \ ++ handler_type, handler, iter_type) \ ++ \ ++ typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \ ++ void(boost::system::error_code, iter_type)) \ ++ asio_true_handler_type; \ ++ \ ++ BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \ ++ sizeof(boost::asio::detail::two_arg_handler_test( \ ++ boost::asio::detail::rvref< \ ++ asio_true_handler_type>(), \ ++ static_cast(0), \ ++ static_cast(0))) == 1, \ ++ "IteratorConnectHandler type requirements not met") \ ++ \ ++ typedef boost::asio::detail::handler_type_requirements< \ ++ sizeof( \ ++ boost::asio::detail::argbyv( \ ++ boost::asio::detail::rvref< \ ++ asio_true_handler_type>())) + \ ++ sizeof( \ ++ boost::asio::detail::lvref< \ ++ asio_true_handler_type>()( \ ++ boost::asio::detail::lvref(), \ ++ boost::asio::detail::lvref()), \ ++ char(0))> BOOST_ASIO_UNUSED_TYPEDEF ++ ++#define BOOST_ASIO_RESOLVE_HANDLER_CHECK( \ ++ handler_type, handler, range_type) \ ++ \ ++ typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \ ++ void(boost::system::error_code, range_type)) \ ++ asio_true_handler_type; \ ++ \ ++ BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \ ++ sizeof(boost::asio::detail::two_arg_handler_test( \ ++ boost::asio::detail::rvref< \ ++ asio_true_handler_type>(), \ ++ static_cast(0), \ ++ static_cast(0))) == 1, \ ++ "ResolveHandler type requirements not met") \ ++ \ ++ typedef boost::asio::detail::handler_type_requirements< \ ++ sizeof( \ ++ boost::asio::detail::argbyv( \ ++ boost::asio::detail::rvref< \ ++ asio_true_handler_type>())) + \ ++ sizeof( \ ++ boost::asio::detail::lvref< \ ++ asio_true_handler_type>()( \ ++ boost::asio::detail::lvref(), \ ++ boost::asio::detail::lvref()), \ ++ char(0))> BOOST_ASIO_UNUSED_TYPEDEF ++ ++#define BOOST_ASIO_WAIT_HANDLER_CHECK( \ ++ handler_type, handler) \ ++ \ ++ typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \ ++ void(boost::system::error_code)) \ ++ asio_true_handler_type; \ ++ \ ++ BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \ ++ sizeof(boost::asio::detail::one_arg_handler_test( \ ++ boost::asio::detail::rvref< \ ++ asio_true_handler_type>(), \ ++ static_cast(0))) == 1, \ ++ "WaitHandler type requirements not met") \ ++ \ ++ typedef boost::asio::detail::handler_type_requirements< \ ++ sizeof( \ ++ boost::asio::detail::argbyv( \ ++ boost::asio::detail::rvref< \ ++ asio_true_handler_type>())) + \ ++ sizeof( \ ++ boost::asio::detail::lvref< \ ++ asio_true_handler_type>()( \ ++ boost::asio::detail::lvref()), \ ++ char(0))> BOOST_ASIO_UNUSED_TYPEDEF ++ ++#define BOOST_ASIO_SIGNAL_HANDLER_CHECK( \ ++ handler_type, handler) \ ++ \ ++ typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \ ++ void(boost::system::error_code, int)) \ ++ asio_true_handler_type; \ ++ \ ++ BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \ ++ sizeof(boost::asio::detail::two_arg_handler_test( \ ++ boost::asio::detail::rvref< \ ++ asio_true_handler_type>(), \ ++ static_cast(0), \ ++ static_cast(0))) == 1, \ ++ "SignalHandler type requirements not met") \ ++ \ ++ typedef boost::asio::detail::handler_type_requirements< \ ++ sizeof( \ ++ boost::asio::detail::argbyv( \ ++ boost::asio::detail::rvref< \ ++ asio_true_handler_type>())) + \ ++ sizeof( \ ++ boost::asio::detail::lvref< \ ++ asio_true_handler_type>()( \ ++ boost::asio::detail::lvref(), \ ++ boost::asio::detail::lvref()), \ ++ char(0))> BOOST_ASIO_UNUSED_TYPEDEF ++ ++#define BOOST_ASIO_HANDSHAKE_HANDLER_CHECK( \ ++ handler_type, handler) \ ++ \ ++ typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \ ++ void(boost::system::error_code)) \ ++ asio_true_handler_type; \ ++ \ ++ BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \ ++ sizeof(boost::asio::detail::one_arg_handler_test( \ ++ boost::asio::detail::rvref< \ ++ asio_true_handler_type>(), \ ++ static_cast(0))) == 1, \ ++ "HandshakeHandler type requirements not met") \ ++ \ ++ typedef boost::asio::detail::handler_type_requirements< \ ++ sizeof( \ ++ boost::asio::detail::argbyv( \ ++ boost::asio::detail::rvref< \ ++ asio_true_handler_type>())) + \ ++ sizeof( \ ++ boost::asio::detail::lvref< \ ++ asio_true_handler_type>()( \ ++ boost::asio::detail::lvref()), \ ++ char(0))> BOOST_ASIO_UNUSED_TYPEDEF ++ ++#define BOOST_ASIO_BUFFERED_HANDSHAKE_HANDLER_CHECK( \ ++ handler_type, handler) \ ++ \ ++ typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \ ++ void(boost::system::error_code, std::size_t)) \ ++ asio_true_handler_type; \ ++ \ ++ BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \ ++ sizeof(boost::asio::detail::two_arg_handler_test( \ ++ boost::asio::detail::rvref< \ ++ asio_true_handler_type>(), \ ++ static_cast(0), \ ++ static_cast(0))) == 1, \ ++ "BufferedHandshakeHandler type requirements not met") \ ++ \ ++ typedef boost::asio::detail::handler_type_requirements< \ ++ sizeof( \ ++ boost::asio::detail::argbyv( \ ++ boost::asio::detail::rvref< \ ++ asio_true_handler_type>())) + \ ++ sizeof( \ ++ boost::asio::detail::lvref< \ ++ asio_true_handler_type>()( \ ++ boost::asio::detail::lvref(), \ ++ boost::asio::detail::lvref()), \ ++ char(0))> BOOST_ASIO_UNUSED_TYPEDEF ++ ++#define BOOST_ASIO_SHUTDOWN_HANDLER_CHECK( \ ++ handler_type, handler) \ ++ \ ++ typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \ ++ void(boost::system::error_code)) \ ++ asio_true_handler_type; \ ++ \ ++ BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \ ++ sizeof(boost::asio::detail::one_arg_handler_test( \ ++ boost::asio::detail::rvref< \ ++ asio_true_handler_type>(), \ ++ static_cast(0))) == 1, \ ++ "ShutdownHandler type requirements not met") \ ++ \ ++ typedef boost::asio::detail::handler_type_requirements< \ ++ sizeof( \ ++ boost::asio::detail::argbyv( \ ++ boost::asio::detail::rvref< \ ++ asio_true_handler_type>())) + \ ++ sizeof( \ ++ boost::asio::detail::lvref< \ ++ asio_true_handler_type>()( \ ++ boost::asio::detail::lvref()), \ ++ char(0))> BOOST_ASIO_UNUSED_TYPEDEF ++ ++#else // !defined(BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS) ++ ++#define BOOST_ASIO_LEGACY_COMPLETION_HANDLER_CHECK( \ ++ handler_type, handler) \ ++ typedef int BOOST_ASIO_UNUSED_TYPEDEF ++ ++#define BOOST_ASIO_READ_HANDLER_CHECK( \ ++ handler_type, handler) \ ++ typedef int BOOST_ASIO_UNUSED_TYPEDEF ++ ++#define BOOST_ASIO_WRITE_HANDLER_CHECK( \ ++ handler_type, handler) \ ++ typedef int BOOST_ASIO_UNUSED_TYPEDEF ++ ++#define BOOST_ASIO_ACCEPT_HANDLER_CHECK( \ ++ handler_type, handler) \ ++ typedef int BOOST_ASIO_UNUSED_TYPEDEF ++ ++#define BOOST_ASIO_MOVE_ACCEPT_HANDLER_CHECK( \ ++ handler_type, handler, socket_type) \ ++ typedef int BOOST_ASIO_UNUSED_TYPEDEF ++ ++#define BOOST_ASIO_CONNECT_HANDLER_CHECK( \ ++ handler_type, handler) \ ++ typedef int BOOST_ASIO_UNUSED_TYPEDEF ++ ++#define BOOST_ASIO_RANGE_CONNECT_HANDLER_CHECK( \ ++ handler_type, handler, iter_type) \ ++ typedef int BOOST_ASIO_UNUSED_TYPEDEF ++ ++#define BOOST_ASIO_ITERATOR_CONNECT_HANDLER_CHECK( \ ++ handler_type, handler, iter_type) \ ++ typedef int BOOST_ASIO_UNUSED_TYPEDEF ++ ++#define BOOST_ASIO_RESOLVE_HANDLER_CHECK( \ ++ handler_type, handler, iter_type) \ ++ typedef int BOOST_ASIO_UNUSED_TYPEDEF ++ ++#define BOOST_ASIO_WAIT_HANDLER_CHECK( \ ++ handler_type, handler) \ ++ typedef int BOOST_ASIO_UNUSED_TYPEDEF ++ ++#define BOOST_ASIO_SIGNAL_HANDLER_CHECK( \ ++ handler_type, handler) \ ++ typedef int BOOST_ASIO_UNUSED_TYPEDEF ++ ++#define BOOST_ASIO_HANDSHAKE_HANDLER_CHECK( \ ++ handler_type, handler) \ ++ typedef int BOOST_ASIO_UNUSED_TYPEDEF ++ ++#define BOOST_ASIO_BUFFERED_HANDSHAKE_HANDLER_CHECK( \ ++ handler_type, handler) \ ++ typedef int BOOST_ASIO_UNUSED_TYPEDEF ++ ++#define BOOST_ASIO_SHUTDOWN_HANDLER_CHECK( \ ++ handler_type, handler) \ ++ typedef int BOOST_ASIO_UNUSED_TYPEDEF ++ ++#endif // !defined(BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS) ++ ++} // namespace detail ++} // namespace asio ++} // namespace boost ++ ++#endif // BOOST_ASIO_DETAIL_HANDLER_TYPE_REQUIREMENTS_EXT_HPP +diff --git a/implementation/helper/1.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 ++ ++// Older versions of gcc have difficulty compiling the sizeof expressions where ++// we test the handler type requirements. We'll disable checking of handler type ++// requirements for those compilers, but otherwise enable it by default. ++#if !defined(BOOST_ASIO_DISABLE_HANDLER_TYPE_REQUIREMENTS) ++# if !defined(__GNUC__) || (__GNUC__ >= 4) ++# define BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS 1 ++# endif // !defined(__GNUC__) || (__GNUC__ >= 4) ++#endif // !defined(BOOST_ASIO_DISABLE_HANDLER_TYPE_REQUIREMENTS) ++ ++// With C++0x we can use a combination of enhanced SFINAE and static_assert to ++// generate better template error messages. As this technique is not yet widely ++// portable, we'll only enable it for tested compilers. ++#if !defined(BOOST_ASIO_DISABLE_HANDLER_TYPE_REQUIREMENTS_ASSERT) ++# if defined(__GNUC__) ++# if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 5)) || (__GNUC__ > 4) ++# if defined(__GXX_EXPERIMENTAL_CXX0X__) ++# define BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS_ASSERT 1 ++# endif // defined(__GXX_EXPERIMENTAL_CXX0X__) ++# endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 5)) || (__GNUC__ > 4) ++# endif // defined(__GNUC__) ++# if defined(BOOST_ASIO_MSVC) ++# if (_MSC_VER >= 1600) ++# define BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS_ASSERT 1 ++# endif // (_MSC_VER >= 1600) ++# endif // defined(BOOST_ASIO_MSVC) ++# if defined(__clang__) ++# if __has_feature(__cxx_static_assert__) ++# define BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS_ASSERT 1 ++# endif // __has_feature(cxx_static_assert) ++# endif // defined(__clang__) ++#endif // !defined(BOOST_ASIO_DISABLE_HANDLER_TYPE_REQUIREMENTS) ++ ++#if defined(BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS) ++# include ++#endif // defined(BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS) ++ ++namespace boost { ++namespace asio { ++namespace detail { ++ ++#if defined(BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS) ++ ++# if defined(BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS_ASSERT) ++ ++template ++auto zero_arg_copyable_handler_test(Handler h, void*) ++ -> decltype( ++ sizeof(Handler(static_cast(h))), ++ (BOOST_ASIO_MOVE_OR_LVALUE(Handler)(h)()), ++ char(0)); ++ ++template ++char (&zero_arg_copyable_handler_test(Handler, ...))[2]; ++ ++template ++auto one_arg_handler_test(Handler h, Arg1* a1) ++ -> decltype( ++ sizeof(Handler(BOOST_ASIO_MOVE_CAST(Handler)(h))), ++ (BOOST_ASIO_MOVE_OR_LVALUE(Handler)(h)(*a1)), ++ char(0)); ++ ++template ++char (&one_arg_handler_test(Handler h, ...))[2]; ++ ++template ++auto two_arg_handler_test(Handler h, Arg1* a1, Arg2* a2) ++ -> decltype( ++ sizeof(Handler(BOOST_ASIO_MOVE_CAST(Handler)(h))), ++ (BOOST_ASIO_MOVE_OR_LVALUE(Handler)(h)(*a1, *a2)), ++ char(0)); ++ ++template ++char (&two_arg_handler_test(Handler, ...))[2]; ++ ++template ++auto two_arg_move_handler_test(Handler h, Arg1* a1, Arg2* a2) ++ -> decltype( ++ sizeof(Handler(BOOST_ASIO_MOVE_CAST(Handler)(h))), ++ (BOOST_ASIO_MOVE_OR_LVALUE(Handler)(h)( ++ *a1, BOOST_ASIO_MOVE_CAST(Arg2)(*a2))), ++ char(0)); ++ ++template ++char (&two_arg_move_handler_test(Handler, ...))[2]; ++ ++template ++auto four_arg_handler_test(Handler h, Arg1* a1, Arg2* a2, Arg3* a3, Arg4* a4) ++ -> decltype( ++ sizeof(Handler(BOOST_ASIO_MOVE_CAST(Handler)(h))), ++ ((h)(*a1, *a2, *a3, *a4)), ++ char(0)); ++ ++template ++char (&four_arg_handler_test(Handler, ...))[2]; ++ ++template ++auto four_arg_move_handler_test(Handler h, Arg1* a1, Arg2* a2, Arg3* a3, Arg4* a4) ++ -> decltype( ++ sizeof(Handler(BOOST_ASIO_MOVE_CAST(Handler)(h))), ++ ((h)(*a1, BOOST_ASIO_MOVE_CAST(Arg2)(*a2), BOOST_ASIO_MOVE_CAST(Arg3)(*a3), BOOST_ASIO_MOVE_CAST(Arg4)(*a4))), ++ char(0)); ++ ++template ++char (&four_arg_move_handler_test(Handler, ...))[2]; ++ ++# define BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT(expr, msg) \ ++ static_assert(expr, msg); ++ ++# else // defined(BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS_ASSERT) ++ ++# define BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT(expr, msg) ++ ++# endif // defined(BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS_ASSERT) ++ ++template T& lvref(); ++template T& lvref(T); ++template const T& clvref(); ++template const T& clvref(T); ++#if defined(BOOST_ASIO_HAS_MOVE) ++template T rvref(); ++template T rvref(T); ++#else // defined(BOOST_ASIO_HAS_MOVE) ++template const T& rvref(); ++template const T& rvref(T); ++#endif // defined(BOOST_ASIO_HAS_MOVE) ++template char argbyv(T); ++ ++#if 0 ++template ++struct handler_type_requirements ++{ ++}; ++#endif ++ ++#define BOOST_ASIO_LEGACY_COMPLETION_HANDLER_CHECK( \ ++ handler_type, handler) \ ++ \ ++ typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \ ++ void()) asio_true_handler_type; \ ++ \ ++ BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \ ++ sizeof(boost::asio::detail::zero_arg_copyable_handler_test( \ ++ boost::asio::detail::clvref< \ ++ asio_true_handler_type>(), 0)) == 1, \ ++ "CompletionHandler type requirements not met") \ ++ \ ++ typedef boost::asio::detail::handler_type_requirements< \ ++ sizeof( \ ++ boost::asio::detail::argbyv( \ ++ boost::asio::detail::clvref< \ ++ asio_true_handler_type>())) + \ ++ sizeof( \ ++ boost::asio::detail::lvref< \ ++ asio_true_handler_type>()(), \ ++ char(0))> BOOST_ASIO_UNUSED_TYPEDEF ++ ++#define BOOST_ASIO_READ_HANDLER_CHECK_EXT_LOCAL( \ ++ handler_type, handler) \ ++ \ ++ typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \ ++ void(boost::system::error_code, std::size_t, \ ++ std::uint32_t, std::uint32_t)) \ ++ asio_true_handler_type; \ ++ \ ++ BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \ ++ sizeof(boost::asio::detail::four_arg_handler_test( \ ++ boost::asio::detail::clvref< \ ++ asio_true_handler_type>(), \ ++ static_cast(0), \ ++ static_cast(0), \ ++ static_cast(0), \ ++ static_cast(0))) == 1, \ ++ "ReadHandler type requirements not met") \ ++ \ ++ typedef boost::asio::detail::handler_type_requirements< \ ++ sizeof( \ ++ boost::asio::detail::argbyv( \ ++ boost::asio::detail::clvref< \ ++ asio_true_handler_type>())) + \ ++ sizeof( \ ++ boost::asio::detail::lvref< \ ++ asio_true_handler_type>()( \ ++ boost::asio::detail::lvref(), \ ++ boost::asio::detail::lvref(), \ ++ boost::asio::detail::lvref(), \ ++ boost::asio::detail::lvref()), \ ++ char(0))> BOOST_ASIO_UNUSED_TYPEDEF ++ ++#define BOOST_ASIO_WRITE_HANDLER_CHECK( \ ++ handler_type, handler) \ ++ \ ++ typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \ ++ void(boost::system::error_code, std::size_t)) \ ++ asio_true_handler_type; \ ++ \ ++ BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \ ++ sizeof(boost::asio::detail::two_arg_handler_test( \ ++ boost::asio::detail::rvref< \ ++ asio_true_handler_type>(), \ ++ static_cast(0), \ ++ static_cast(0))) == 1, \ ++ "WriteHandler type requirements not met") \ ++ \ ++ typedef boost::asio::detail::handler_type_requirements< \ ++ sizeof( \ ++ boost::asio::detail::argbyv( \ ++ boost::asio::detail::rvref< \ ++ asio_true_handler_type>())) + \ ++ sizeof( \ ++ boost::asio::detail::lvref< \ ++ asio_true_handler_type>()( \ ++ boost::asio::detail::lvref(), \ ++ boost::asio::detail::lvref()), \ ++ char(0))> BOOST_ASIO_UNUSED_TYPEDEF ++ ++#if 0 ++#define BOOST_ASIO_ACCEPT_HANDLER_CHECK( \ ++ handler_type, handler) \ ++ \ ++ typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \ ++ void(boost::system::error_code)) \ ++ asio_true_handler_type; \ ++ \ ++ BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \ ++ sizeof(boost::asio::detail::one_arg_handler_test( \ ++ boost::asio::detail::rvref< \ ++ asio_true_handler_type>(), \ ++ static_cast(0))) == 1, \ ++ "AcceptHandler type requirements not met") \ ++ \ ++ typedef boost::asio::detail::handler_type_requirements< \ ++ sizeof( \ ++ boost::asio::detail::argbyv( \ ++ boost::asio::detail::rvref< \ ++ asio_true_handler_type>())) + \ ++ sizeof( \ ++ boost::asio::detail::lvref< \ ++ asio_true_handler_type>()( \ ++ boost::asio::detail::lvref()), \ ++ char(0))> BOOST_ASIO_UNUSED_TYPEDEF ++ ++#define BOOST_ASIO_MOVE_ACCEPT_HANDLER_CHECK( \ ++ handler_type, handler, socket_type) \ ++ \ ++ typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \ ++ void(boost::system::error_code, socket_type)) \ ++ asio_true_handler_type; \ ++ \ ++ BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \ ++ sizeof(boost::asio::detail::two_arg_move_handler_test( \ ++ boost::asio::detail::rvref< \ ++ asio_true_handler_type>(), \ ++ static_cast(0), \ ++ static_cast(0))) == 1, \ ++ "MoveAcceptHandler type requirements not met") \ ++ \ ++ typedef boost::asio::detail::handler_type_requirements< \ ++ sizeof( \ ++ boost::asio::detail::argbyv( \ ++ boost::asio::detail::rvref< \ ++ asio_true_handler_type>())) + \ ++ sizeof( \ ++ boost::asio::detail::lvref< \ ++ asio_true_handler_type>()( \ ++ boost::asio::detail::lvref(), \ ++ boost::asio::detail::rvref()), \ ++ char(0))> BOOST_ASIO_UNUSED_TYPEDEF ++#endif ++ ++#define BOOST_ASIO_CONNECT_HANDLER_CHECK( \ ++ handler_type, handler) \ ++ \ ++ typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \ ++ void(boost::system::error_code)) \ ++ asio_true_handler_type; \ ++ \ ++ BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \ ++ sizeof(boost::asio::detail::one_arg_handler_test( \ ++ boost::asio::detail::rvref< \ ++ asio_true_handler_type>(), \ ++ static_cast(0))) == 1, \ ++ "ConnectHandler type requirements not met") \ ++ \ ++ typedef boost::asio::detail::handler_type_requirements< \ ++ sizeof( \ ++ boost::asio::detail::argbyv( \ ++ boost::asio::detail::rvref< \ ++ asio_true_handler_type>())) + \ ++ sizeof( \ ++ boost::asio::detail::lvref< \ ++ asio_true_handler_type>()( \ ++ boost::asio::detail::lvref()), \ ++ char(0))> BOOST_ASIO_UNUSED_TYPEDEF ++ ++#define BOOST_ASIO_RANGE_CONNECT_HANDLER_CHECK( \ ++ handler_type, handler, endpoint_type) \ ++ \ ++ typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \ ++ void(boost::system::error_code, endpoint_type)) \ ++ asio_true_handler_type; \ ++ \ ++ BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \ ++ sizeof(boost::asio::detail::two_arg_handler_test( \ ++ boost::asio::detail::rvref< \ ++ asio_true_handler_type>(), \ ++ static_cast(0), \ ++ static_cast(0))) == 1, \ ++ "RangeConnectHandler type requirements not met") \ ++ \ ++ typedef boost::asio::detail::handler_type_requirements< \ ++ sizeof( \ ++ boost::asio::detail::argbyv( \ ++ boost::asio::detail::rvref< \ ++ asio_true_handler_type>())) + \ ++ sizeof( \ ++ boost::asio::detail::lvref< \ ++ asio_true_handler_type>()( \ ++ boost::asio::detail::lvref(), \ ++ boost::asio::detail::lvref()), \ ++ char(0))> BOOST_ASIO_UNUSED_TYPEDEF ++ ++#define BOOST_ASIO_ITERATOR_CONNECT_HANDLER_CHECK( \ ++ handler_type, handler, iter_type) \ ++ \ ++ typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \ ++ void(boost::system::error_code, iter_type)) \ ++ asio_true_handler_type; \ ++ \ ++ BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \ ++ sizeof(boost::asio::detail::two_arg_handler_test( \ ++ boost::asio::detail::rvref< \ ++ asio_true_handler_type>(), \ ++ static_cast(0), \ ++ static_cast(0))) == 1, \ ++ "IteratorConnectHandler type requirements not met") \ ++ \ ++ typedef boost::asio::detail::handler_type_requirements< \ ++ sizeof( \ ++ boost::asio::detail::argbyv( \ ++ boost::asio::detail::rvref< \ ++ asio_true_handler_type>())) + \ ++ sizeof( \ ++ boost::asio::detail::lvref< \ ++ asio_true_handler_type>()( \ ++ boost::asio::detail::lvref(), \ ++ boost::asio::detail::lvref()), \ ++ char(0))> BOOST_ASIO_UNUSED_TYPEDEF ++ ++#define BOOST_ASIO_RESOLVE_HANDLER_CHECK( \ ++ handler_type, handler, range_type) \ ++ \ ++ typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \ ++ void(boost::system::error_code, range_type)) \ ++ asio_true_handler_type; \ ++ \ ++ BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \ ++ sizeof(boost::asio::detail::two_arg_handler_test( \ ++ boost::asio::detail::rvref< \ ++ asio_true_handler_type>(), \ ++ static_cast(0), \ ++ static_cast(0))) == 1, \ ++ "ResolveHandler type requirements not met") \ ++ \ ++ typedef boost::asio::detail::handler_type_requirements< \ ++ sizeof( \ ++ boost::asio::detail::argbyv( \ ++ boost::asio::detail::rvref< \ ++ asio_true_handler_type>())) + \ ++ sizeof( \ ++ boost::asio::detail::lvref< \ ++ asio_true_handler_type>()( \ ++ boost::asio::detail::lvref(), \ ++ boost::asio::detail::lvref()), \ ++ char(0))> BOOST_ASIO_UNUSED_TYPEDEF ++ ++#define BOOST_ASIO_WAIT_HANDLER_CHECK( \ ++ handler_type, handler) \ ++ \ ++ typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \ ++ void(boost::system::error_code)) \ ++ asio_true_handler_type; \ ++ \ ++ BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \ ++ sizeof(boost::asio::detail::one_arg_handler_test( \ ++ boost::asio::detail::rvref< \ ++ asio_true_handler_type>(), \ ++ static_cast(0))) == 1, \ ++ "WaitHandler type requirements not met") \ ++ \ ++ typedef boost::asio::detail::handler_type_requirements< \ ++ sizeof( \ ++ boost::asio::detail::argbyv( \ ++ boost::asio::detail::rvref< \ ++ asio_true_handler_type>())) + \ ++ sizeof( \ ++ boost::asio::detail::lvref< \ ++ asio_true_handler_type>()( \ ++ boost::asio::detail::lvref()), \ ++ char(0))> BOOST_ASIO_UNUSED_TYPEDEF ++ ++#define BOOST_ASIO_SIGNAL_HANDLER_CHECK( \ ++ handler_type, handler) \ ++ \ ++ typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \ ++ void(boost::system::error_code, int)) \ ++ asio_true_handler_type; \ ++ \ ++ BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \ ++ sizeof(boost::asio::detail::two_arg_handler_test( \ ++ boost::asio::detail::rvref< \ ++ asio_true_handler_type>(), \ ++ static_cast(0), \ ++ static_cast(0))) == 1, \ ++ "SignalHandler type requirements not met") \ ++ \ ++ typedef boost::asio::detail::handler_type_requirements< \ ++ sizeof( \ ++ boost::asio::detail::argbyv( \ ++ boost::asio::detail::rvref< \ ++ asio_true_handler_type>())) + \ ++ sizeof( \ ++ boost::asio::detail::lvref< \ ++ asio_true_handler_type>()( \ ++ boost::asio::detail::lvref(), \ ++ boost::asio::detail::lvref()), \ ++ char(0))> BOOST_ASIO_UNUSED_TYPEDEF ++ ++#define BOOST_ASIO_HANDSHAKE_HANDLER_CHECK( \ ++ handler_type, handler) \ ++ \ ++ typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \ ++ void(boost::system::error_code)) \ ++ asio_true_handler_type; \ ++ \ ++ BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \ ++ sizeof(boost::asio::detail::one_arg_handler_test( \ ++ boost::asio::detail::rvref< \ ++ asio_true_handler_type>(), \ ++ static_cast(0))) == 1, \ ++ "HandshakeHandler type requirements not met") \ ++ \ ++ typedef boost::asio::detail::handler_type_requirements< \ ++ sizeof( \ ++ boost::asio::detail::argbyv( \ ++ boost::asio::detail::rvref< \ ++ asio_true_handler_type>())) + \ ++ sizeof( \ ++ boost::asio::detail::lvref< \ ++ asio_true_handler_type>()( \ ++ boost::asio::detail::lvref()), \ ++ char(0))> BOOST_ASIO_UNUSED_TYPEDEF ++ ++#define BOOST_ASIO_BUFFERED_HANDSHAKE_HANDLER_CHECK( \ ++ handler_type, handler) \ ++ \ ++ typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \ ++ void(boost::system::error_code, std::size_t)) \ ++ asio_true_handler_type; \ ++ \ ++ BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \ ++ sizeof(boost::asio::detail::two_arg_handler_test( \ ++ boost::asio::detail::rvref< \ ++ asio_true_handler_type>(), \ ++ static_cast(0), \ ++ static_cast(0))) == 1, \ ++ "BufferedHandshakeHandler type requirements not met") \ ++ \ ++ typedef boost::asio::detail::handler_type_requirements< \ ++ sizeof( \ ++ boost::asio::detail::argbyv( \ ++ boost::asio::detail::rvref< \ ++ asio_true_handler_type>())) + \ ++ sizeof( \ ++ boost::asio::detail::lvref< \ ++ asio_true_handler_type>()( \ ++ boost::asio::detail::lvref(), \ ++ boost::asio::detail::lvref()), \ ++ char(0))> BOOST_ASIO_UNUSED_TYPEDEF ++ ++#define BOOST_ASIO_SHUTDOWN_HANDLER_CHECK( \ ++ handler_type, handler) \ ++ \ ++ typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \ ++ void(boost::system::error_code)) \ ++ asio_true_handler_type; \ ++ \ ++ BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \ ++ sizeof(boost::asio::detail::one_arg_handler_test( \ ++ boost::asio::detail::rvref< \ ++ asio_true_handler_type>(), \ ++ static_cast(0))) == 1, \ ++ "ShutdownHandler type requirements not met") \ ++ \ ++ typedef boost::asio::detail::handler_type_requirements< \ ++ sizeof( \ ++ boost::asio::detail::argbyv( \ ++ boost::asio::detail::rvref< \ ++ asio_true_handler_type>())) + \ ++ sizeof( \ ++ boost::asio::detail::lvref< \ ++ asio_true_handler_type>()( \ ++ boost::asio::detail::lvref()), \ ++ char(0))> BOOST_ASIO_UNUSED_TYPEDEF ++ ++#else // !defined(BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS) ++ ++#define BOOST_ASIO_LEGACY_COMPLETION_HANDLER_CHECK( \ ++ handler_type, handler) \ ++ typedef int BOOST_ASIO_UNUSED_TYPEDEF ++ ++#define BOOST_ASIO_READ_HANDLER_CHECK( \ ++ handler_type, handler) \ ++ typedef int BOOST_ASIO_UNUSED_TYPEDEF ++ ++#define BOOST_ASIO_WRITE_HANDLER_CHECK( \ ++ handler_type, handler) \ ++ typedef int BOOST_ASIO_UNUSED_TYPEDEF ++ ++#define BOOST_ASIO_ACCEPT_HANDLER_CHECK( \ ++ handler_type, handler) \ ++ typedef int BOOST_ASIO_UNUSED_TYPEDEF ++ ++#define BOOST_ASIO_MOVE_ACCEPT_HANDLER_CHECK( \ ++ handler_type, handler, socket_type) \ ++ typedef int BOOST_ASIO_UNUSED_TYPEDEF ++ ++#define BOOST_ASIO_CONNECT_HANDLER_CHECK( \ ++ handler_type, handler) \ ++ typedef int BOOST_ASIO_UNUSED_TYPEDEF ++ ++#define BOOST_ASIO_RANGE_CONNECT_HANDLER_CHECK( \ ++ handler_type, handler, iter_type) \ ++ typedef int BOOST_ASIO_UNUSED_TYPEDEF ++ ++#define BOOST_ASIO_ITERATOR_CONNECT_HANDLER_CHECK( \ ++ handler_type, handler, iter_type) \ ++ typedef int BOOST_ASIO_UNUSED_TYPEDEF ++ ++#define BOOST_ASIO_RESOLVE_HANDLER_CHECK( \ ++ handler_type, handler, iter_type) \ ++ typedef int BOOST_ASIO_UNUSED_TYPEDEF ++ ++#define BOOST_ASIO_WAIT_HANDLER_CHECK( \ ++ handler_type, handler) \ ++ typedef int BOOST_ASIO_UNUSED_TYPEDEF ++ ++#define BOOST_ASIO_SIGNAL_HANDLER_CHECK( \ ++ handler_type, handler) \ ++ typedef int BOOST_ASIO_UNUSED_TYPEDEF ++ ++#define BOOST_ASIO_HANDSHAKE_HANDLER_CHECK( \ ++ handler_type, handler) \ ++ typedef int BOOST_ASIO_UNUSED_TYPEDEF ++ ++#define BOOST_ASIO_BUFFERED_HANDSHAKE_HANDLER_CHECK( \ ++ handler_type, handler) \ ++ typedef int BOOST_ASIO_UNUSED_TYPEDEF ++ ++#define BOOST_ASIO_SHUTDOWN_HANDLER_CHECK( \ ++ handler_type, handler) \ ++ typedef int BOOST_ASIO_UNUSED_TYPEDEF ++ ++#endif // !defined(BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS) ++ ++} // namespace detail ++} // namespace asio ++} // namespace boost ++ ++#endif // BOOST_ASIO_DETAIL_HANDLER_TYPE_REQUIREMENTS_EXT_LOCAL_HPP +diff --git a/implementation/helper/1.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 ++ ++#if !defined(BOOST_ASIO_HAS_IOCP) \ ++ && !defined(BOOST_ASIO_WINDOWS_RUNTIME) ++ ++#include ++ ++#include ++ ++namespace boost { ++namespace asio { ++namespace detail { ++ ++reactive_socket_service_base_ext::reactive_socket_service_base_ext( ++ execution_context& context) ++ : reactor_(use_service(context)) ++{ ++ reactor_.init_task(); ++} ++ ++void reactive_socket_service_base_ext::base_shutdown() ++{ ++} ++ ++void reactive_socket_service_base_ext::construct( ++ reactive_socket_service_base_ext::base_implementation_type& impl) ++{ ++ impl.socket_ = invalid_socket; ++ impl.state_ = 0; ++} ++ ++void reactive_socket_service_base_ext::base_move_construct( ++ reactive_socket_service_base_ext::base_implementation_type& impl, ++ reactive_socket_service_base_ext::base_implementation_type& other_impl) ++{ ++ impl.socket_ = other_impl.socket_; ++ other_impl.socket_ = invalid_socket; ++ ++ impl.state_ = other_impl.state_; ++ other_impl.state_ = 0; ++ ++ reactor_.move_descriptor(impl.socket_, ++ impl.reactor_data_, other_impl.reactor_data_); ++} ++ ++void reactive_socket_service_base_ext::base_move_assign( ++ reactive_socket_service_base_ext::base_implementation_type& impl, ++ reactive_socket_service_base_ext& other_service, ++ reactive_socket_service_base_ext::base_implementation_type& other_impl) ++{ ++ destroy(impl); ++ ++ impl.socket_ = other_impl.socket_; ++ other_impl.socket_ = invalid_socket; ++ ++ impl.state_ = other_impl.state_; ++ other_impl.state_ = 0; ++ ++ other_service.reactor_.move_descriptor(impl.socket_, ++ impl.reactor_data_, other_impl.reactor_data_); ++} ++ ++void reactive_socket_service_base_ext::destroy( ++ reactive_socket_service_base_ext::base_implementation_type& impl) ++{ ++ if (impl.socket_ != invalid_socket) ++ { ++ BOOST_ASIO_HANDLER_OPERATION((reactor_.context(), ++ "socket", &impl, impl.socket_, "close")); ++ ++ reactor_.deregister_descriptor(impl.socket_, impl.reactor_data_, ++ (impl.state_ & socket_ops::possible_dup) == 0); ++ ++ boost::system::error_code ignored_ec; ++ socket_ops::close(impl.socket_, impl.state_, true, ignored_ec); ++ ++ reactor_.cleanup_descriptor_data(impl.reactor_data_); ++ } ++} ++ ++boost::system::error_code reactive_socket_service_base_ext::close( ++ reactive_socket_service_base_ext::base_implementation_type& impl, ++ boost::system::error_code& ec) ++{ ++ if (is_open(impl)) ++ { ++ BOOST_ASIO_HANDLER_OPERATION((reactor_.context(), ++ "socket", &impl, impl.socket_, "close")); ++ ++ reactor_.deregister_descriptor(impl.socket_, impl.reactor_data_, ++ (impl.state_ & socket_ops::possible_dup) == 0); ++ ++ socket_ops::close(impl.socket_, impl.state_, false, ec); ++ ++ reactor_.cleanup_descriptor_data(impl.reactor_data_); ++ } ++ else ++ { ++ ec = boost::system::error_code(); ++ } ++ ++ // The descriptor is closed by the OS even if close() returns an error. ++ // ++ // (Actually, POSIX says the state of the descriptor is unspecified. On ++ // Linux the descriptor is apparently closed anyway; e.g. see ++ // http://lkml.org/lkml/2005/9/10/129 ++ // We'll just have to assume that other OSes follow the same behaviour. The ++ // known exception is when Windows's closesocket() function fails with ++ // WSAEWOULDBLOCK, but this case is handled inside socket_ops::close(). ++ construct(impl); ++ ++ return ec; ++} ++/* ++socket_type reactive_socket_service_base::release( ++ reactive_socket_service_base::base_implementation_type& impl, ++ boost::system::error_code& ec) ++{ ++ if (!is_open(impl)) ++ { ++ ec = boost::asio::error::bad_descriptor; ++ return invalid_socket; ++ } ++ ++ BOOST_ASIO_HANDLER_OPERATION((reactor_.context(), ++ "socket", &impl, impl.socket_, "release")); ++ ++ reactor_.deregister_descriptor(impl.socket_, impl.reactor_data_, false); ++ reactor_.cleanup_descriptor_data(impl.reactor_data_); ++ socket_type sock = impl.socket_; ++ construct(impl); ++ ec = boost::system::error_code(); ++ return sock; ++} ++*/ ++boost::system::error_code reactive_socket_service_base_ext::cancel( ++ reactive_socket_service_base_ext::base_implementation_type& impl, ++ boost::system::error_code& ec) ++{ ++ if (!is_open(impl)) ++ { ++ ec = boost::asio::error::bad_descriptor; ++ return ec; ++ } ++ ++ BOOST_ASIO_HANDLER_OPERATION((reactor_.context(), ++ "socket", &impl, impl.socket_, "cancel")); ++ ++ reactor_.cancel_ops(impl.socket_, impl.reactor_data_); ++ ec = boost::system::error_code(); ++ return ec; ++} ++ ++boost::system::error_code reactive_socket_service_base_ext::do_open( ++ reactive_socket_service_base_ext::base_implementation_type& impl, ++ int af, int type, int protocol, boost::system::error_code& ec) ++{ ++ if (is_open(impl)) ++ { ++ ec = boost::asio::error::already_open; ++ return ec; ++ } ++ ++ socket_holder sock(socket_ops::socket(af, type, protocol, ec)); ++ if (sock.get() == invalid_socket) ++ return ec; ++ ++ if (int err = reactor_.register_descriptor(sock.get(), impl.reactor_data_)) ++ { ++ ec = boost::system::error_code(err, ++ boost::asio::error::get_system_category()); ++ return ec; ++ } ++ ++ impl.socket_ = sock.release(); ++ switch (type) ++ { ++ case SOCK_STREAM: impl.state_ = socket_ops::stream_oriented; break; ++ case SOCK_DGRAM: impl.state_ = socket_ops::datagram_oriented; break; ++ default: impl.state_ = 0; break; ++ } ++ ec = boost::system::error_code(); ++ return ec; ++} ++ ++boost::system::error_code reactive_socket_service_base_ext::do_assign( ++ reactive_socket_service_base_ext::base_implementation_type& impl, int type, ++ const reactive_socket_service_base_ext::native_handle_type& native_socket, ++ boost::system::error_code& ec) ++{ ++ if (is_open(impl)) ++ { ++ ec = boost::asio::error::already_open; ++ return ec; ++ } ++ ++ if (int err = reactor_.register_descriptor( ++ native_socket, impl.reactor_data_)) ++ { ++ ec = boost::system::error_code(err, ++ boost::asio::error::get_system_category()); ++ return ec; ++ } ++ ++ impl.socket_ = native_socket; ++ switch (type) ++ { ++ case SOCK_STREAM: impl.state_ = socket_ops::stream_oriented; break; ++ case SOCK_DGRAM: impl.state_ = socket_ops::datagram_oriented; break; ++ default: impl.state_ = 0; break; ++ } ++ impl.state_ |= socket_ops::possible_dup; ++ ec = boost::system::error_code(); ++ return ec; ++} ++ ++void reactive_socket_service_base_ext::start_op( ++ reactive_socket_service_base_ext::base_implementation_type& impl, ++ int op_type, reactor_op* op, bool is_continuation, ++ bool is_non_blocking, bool noop) ++{ ++ if (!noop) ++ { ++ if ((impl.state_ & socket_ops::non_blocking) ++ || socket_ops::set_internal_non_blocking( ++ impl.socket_, impl.state_, true, op->ec_)) ++ { ++ reactor_.start_op(op_type, impl.socket_, ++ impl.reactor_data_, op, is_continuation, is_non_blocking); ++ return; ++ } ++ } ++ ++ reactor_.post_immediate_completion(op, is_continuation); ++} ++ ++void reactive_socket_service_base_ext::start_accept_op( ++ reactive_socket_service_base_ext::base_implementation_type& impl, ++ reactor_op* op, bool is_continuation, bool peer_is_open) ++{ ++ if (!peer_is_open) ++ start_op(impl, reactor::read_op, op, is_continuation, true, false); ++ else ++ { ++ op->ec_ = boost::asio::error::already_open; ++ reactor_.post_immediate_completion(op, is_continuation); ++ } ++} ++ ++void reactive_socket_service_base_ext::start_connect_op( ++ reactive_socket_service_base_ext::base_implementation_type& impl, ++ reactor_op* op, bool is_continuation, ++ const socket_addr_type* addr, size_t addrlen) ++{ ++ if ((impl.state_ & socket_ops::non_blocking) ++ || socket_ops::set_internal_non_blocking( ++ impl.socket_, impl.state_, true, op->ec_)) ++ { ++ if (socket_ops::connect(impl.socket_, addr, addrlen, op->ec_) != 0) ++ { ++ if (op->ec_ == boost::asio::error::in_progress ++ || op->ec_ == boost::asio::error::would_block) ++ { ++ op->ec_ = boost::system::error_code(); ++ reactor_.start_op(reactor::connect_op, impl.socket_, ++ impl.reactor_data_, op, is_continuation, false); ++ return; ++ } ++ } ++ } ++ ++ reactor_.post_immediate_completion(op, is_continuation); ++} ++ ++} // namespace detail ++} // namespace asio ++} // namespace boost ++ ++#include ++ ++#endif // !defined(BOOST_ASIO_HAS_IOCP) ++ // && !defined(BOOST_ASIO_WINDOWS_RUNTIME) ++ ++#endif // BOOST_ASIO_DETAIL_IMPL_REACTIVE_SOCKET_SERVICE_BASE_EXT_IPP +diff --git a/implementation/helper/1.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 ++ ++#if !defined(BOOST_ASIO_HAS_IOCP) \ ++ && !defined(BOOST_ASIO_WINDOWS_RUNTIME) ++ ++#include ++ ++#include ++ ++namespace boost { ++namespace asio { ++namespace detail { ++ ++reactive_socket_service_base_ext_local::reactive_socket_service_base_ext_local( ++ execution_context& context) ++ : reactor_(use_service(context)) ++{ ++ reactor_.init_task(); ++} ++ ++void reactive_socket_service_base_ext_local::base_shutdown() ++{ ++} ++ ++void reactive_socket_service_base_ext_local::construct( ++ reactive_socket_service_base_ext_local::base_implementation_type& impl) ++{ ++ impl.socket_ = invalid_socket; ++ impl.state_ = 0; ++} ++ ++void reactive_socket_service_base_ext_local::base_move_construct( ++ reactive_socket_service_base_ext_local::base_implementation_type& impl, ++ reactive_socket_service_base_ext_local::base_implementation_type& other_impl) ++{ ++ impl.socket_ = other_impl.socket_; ++ other_impl.socket_ = invalid_socket; ++ ++ impl.state_ = other_impl.state_; ++ other_impl.state_ = 0; ++ ++ reactor_.move_descriptor(impl.socket_, ++ impl.reactor_data_, other_impl.reactor_data_); ++} ++ ++void reactive_socket_service_base_ext_local::base_move_assign( ++ reactive_socket_service_base_ext_local::base_implementation_type& impl, ++ reactive_socket_service_base_ext_local& other_service, ++ reactive_socket_service_base_ext_local::base_implementation_type& other_impl) ++{ ++ destroy(impl); ++ ++ impl.socket_ = other_impl.socket_; ++ other_impl.socket_ = invalid_socket; ++ ++ impl.state_ = other_impl.state_; ++ other_impl.state_ = 0; ++ ++ other_service.reactor_.move_descriptor(impl.socket_, ++ impl.reactor_data_, other_impl.reactor_data_); ++} ++ ++void reactive_socket_service_base_ext_local::destroy( ++ reactive_socket_service_base_ext_local::base_implementation_type& impl) ++{ ++ if (impl.socket_ != invalid_socket) ++ { ++ BOOST_ASIO_HANDLER_OPERATION((reactor_.context(), ++ "socket", &impl, impl.socket_, "close")); ++ ++ reactor_.deregister_descriptor(impl.socket_, impl.reactor_data_, ++ (impl.state_ & socket_ops::possible_dup) == 0); ++ ++ boost::system::error_code ignored_ec; ++ socket_ops::close(impl.socket_, impl.state_, true, ignored_ec); ++ ++ reactor_.cleanup_descriptor_data(impl.reactor_data_); ++ } ++} ++ ++boost::system::error_code reactive_socket_service_base_ext_local::close( ++ reactive_socket_service_base_ext_local::base_implementation_type& impl, ++ boost::system::error_code& ec) ++{ ++ if (is_open(impl)) ++ { ++ BOOST_ASIO_HANDLER_OPERATION((reactor_.context(), ++ "socket", &impl, impl.socket_, "close")); ++ ++ reactor_.deregister_descriptor(impl.socket_, impl.reactor_data_, ++ (impl.state_ & socket_ops::possible_dup) == 0); ++ ++ socket_ops::close(impl.socket_, impl.state_, false, ec); ++ ++ reactor_.cleanup_descriptor_data(impl.reactor_data_); ++ } ++ else ++ { ++ ec = boost::system::error_code(); ++ } ++ ++ // The descriptor is closed by the OS even if close() returns an error. ++ // ++ // (Actually, POSIX says the state of the descriptor is unspecified. On ++ // Linux the descriptor is apparently closed anyway; e.g. see ++ // http://lkml.org/lkml/2005/9/10/129 ++ // We'll just have to assume that other OSes follow the same behaviour. The ++ // known exception is when Windows's closesocket() function fails with ++ // WSAEWOULDBLOCK, but this case is handled inside socket_ops::close(). ++ construct(impl); ++ ++ return ec; ++} ++/* ++socket_type reactive_socket_service_base::release( ++ reactive_socket_service_base::base_implementation_type& impl, ++ boost::system::error_code& ec) ++{ ++ if (!is_open(impl)) ++ { ++ ec = boost::asio::error::bad_descriptor; ++ return invalid_socket; ++ } ++ ++ BOOST_ASIO_HANDLER_OPERATION((reactor_.context(), ++ "socket", &impl, impl.socket_, "release")); ++ ++ reactor_.deregister_descriptor(impl.socket_, impl.reactor_data_, false); ++ reactor_.cleanup_descriptor_data(impl.reactor_data_); ++ socket_type sock = impl.socket_; ++ construct(impl); ++ ec = boost::system::error_code(); ++ return sock; ++} ++*/ ++boost::system::error_code reactive_socket_service_base_ext_local::cancel( ++ reactive_socket_service_base_ext_local::base_implementation_type& impl, ++ boost::system::error_code& ec) ++{ ++ if (!is_open(impl)) ++ { ++ ec = boost::asio::error::bad_descriptor; ++ return ec; ++ } ++ ++ BOOST_ASIO_HANDLER_OPERATION((reactor_.context(), ++ "socket", &impl, impl.socket_, "cancel")); ++ ++ reactor_.cancel_ops(impl.socket_, impl.reactor_data_); ++ ec = boost::system::error_code(); ++ return ec; ++} ++ ++boost::system::error_code reactive_socket_service_base_ext_local::do_open( ++ reactive_socket_service_base_ext_local::base_implementation_type& impl, ++ int af, int type, int protocol, boost::system::error_code& ec) ++{ ++ if (is_open(impl)) ++ { ++ ec = boost::asio::error::already_open; ++ return ec; ++ } ++ ++ socket_holder sock(socket_ops::socket(af, type, protocol, ec)); ++ if (sock.get() == invalid_socket) ++ return ec; ++ ++ if (int err = reactor_.register_descriptor(sock.get(), impl.reactor_data_)) ++ { ++ ec = boost::system::error_code(err, ++ boost::asio::error::get_system_category()); ++ return ec; ++ } ++ ++ impl.socket_ = sock.release(); ++ switch (type) ++ { ++ case SOCK_STREAM: impl.state_ = socket_ops::stream_oriented; break; ++ case SOCK_DGRAM: impl.state_ = socket_ops::datagram_oriented; break; ++ default: impl.state_ = 0; break; ++ } ++ ec = boost::system::error_code(); ++ return ec; ++} ++ ++boost::system::error_code reactive_socket_service_base_ext_local::do_assign( ++ reactive_socket_service_base_ext_local::base_implementation_type& impl, int type, ++ const reactive_socket_service_base_ext_local::native_handle_type& native_socket, ++ boost::system::error_code& ec) ++{ ++ if (is_open(impl)) ++ { ++ ec = boost::asio::error::already_open; ++ return ec; ++ } ++ ++ if (int err = reactor_.register_descriptor( ++ native_socket, impl.reactor_data_)) ++ { ++ ec = boost::system::error_code(err, ++ boost::asio::error::get_system_category()); ++ return ec; ++ } ++ ++ impl.socket_ = native_socket; ++ switch (type) ++ { ++ case SOCK_STREAM: impl.state_ = socket_ops::stream_oriented; break; ++ case SOCK_DGRAM: impl.state_ = socket_ops::datagram_oriented; break; ++ default: impl.state_ = 0; break; ++ } ++ impl.state_ |= socket_ops::possible_dup; ++ ec = boost::system::error_code(); ++ return ec; ++} ++ ++void reactive_socket_service_base_ext_local::start_op( ++ reactive_socket_service_base_ext_local::base_implementation_type& impl, ++ int op_type, reactor_op* op, bool is_continuation, ++ bool is_non_blocking, bool noop) ++{ ++ if (!noop) ++ { ++ if ((impl.state_ & socket_ops::non_blocking) ++ || socket_ops::set_internal_non_blocking( ++ impl.socket_, impl.state_, true, op->ec_)) ++ { ++ reactor_.start_op(op_type, impl.socket_, ++ impl.reactor_data_, op, is_continuation, is_non_blocking); ++ return; ++ } ++ } ++ ++ reactor_.post_immediate_completion(op, is_continuation); ++} ++ ++void reactive_socket_service_base_ext_local::start_accept_op( ++ reactive_socket_service_base_ext_local::base_implementation_type& impl, ++ reactor_op* op, bool is_continuation, bool peer_is_open) ++{ ++ if (!peer_is_open) ++ start_op(impl, reactor::read_op, op, is_continuation, true, false); ++ else ++ { ++ op->ec_ = boost::asio::error::already_open; ++ reactor_.post_immediate_completion(op, is_continuation); ++ } ++} ++ ++void reactive_socket_service_base_ext_local::start_connect_op( ++ reactive_socket_service_base_ext_local::base_implementation_type& impl, ++ reactor_op* op, bool is_continuation, ++ const socket_addr_type* addr, size_t addrlen) ++{ ++ if ((impl.state_ & socket_ops::non_blocking) ++ || socket_ops::set_internal_non_blocking( ++ impl.socket_, impl.state_, true, op->ec_)) ++ { ++ if (socket_ops::connect(impl.socket_, addr, addrlen, op->ec_) != 0) ++ { ++ if (op->ec_ == boost::asio::error::in_progress ++ || op->ec_ == boost::asio::error::would_block) ++ { ++ op->ec_ = boost::system::error_code(); ++ reactor_.start_op(reactor::connect_op, impl.socket_, ++ impl.reactor_data_, op, is_continuation, false); ++ return; ++ } ++ } ++ } ++ ++ reactor_.post_immediate_completion(op, is_continuation); ++} ++ ++} // namespace detail ++} // namespace asio ++} // namespace boost ++ ++#include ++ ++#endif // !defined(BOOST_ASIO_HAS_IOCP) ++ // && !defined(BOOST_ASIO_WINDOWS_RUNTIME) ++ ++#endif // BOOST_ASIO_DETAIL_IMPL_REACTIVE_SOCKET_SERVICE_BASE_EXT_LOCAL_IPP +diff --git a/implementation/helper/1.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 ++ ++#include ++ ++namespace boost { ++namespace asio { ++namespace detail { ++namespace socket_ops { ++ ++signed_size_type recvfrom(socket_type s, buf* bufs, size_t count, ++ int flags, socket_addr_type* addr, std::size_t* addrlen, ++ boost::system::error_code& ec, boost::asio::ip::address& da) ++{ ++ ++#if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) ++ GUID WSARecvMsg_GUID = WSAID_WSARECVMSG; ++ LPFN_WSARECVMSG WSARecvMsg; ++ DWORD NumberOfBytes; ++ signed_size_type result; ++ ++ result = WSAIoctl(s, SIO_GET_EXTENSION_FUNCTION_POINTER, ++ &WSARecvMsg_GUID, sizeof WSARecvMsg_GUID, ++ &WSARecvMsg, sizeof WSARecvMsg, ++ &NumberOfBytes, NULL, NULL); ++ get_last_error(ec, true); ++ if (ec.value() == SOCKET_ERROR) { ++ WSARecvMsg = NULL; ++ return 0; ++ } ++ ++ WSABUF wsaBuf; ++ WSAMSG msg; ++ char controlBuffer[1024]; ++ msg.name = addr; ++ msg.namelen = *addrlen; ++ wsaBuf.buf = bufs->buf; ++ wsaBuf.len = bufs->len; ++ msg.lpBuffers = &wsaBuf; ++ msg.dwBufferCount = count; ++ msg.Control.len = sizeof controlBuffer; ++ msg.Control.buf = controlBuffer; ++ msg.dwFlags = flags; ++ ++ DWORD dwNumberOfBytesRecvd; ++ result = WSARecvMsg(s, &msg, &dwNumberOfBytesRecvd, NULL, NULL); ++ get_last_error(ec, true); ++ ++ if (result >= 0) { ++ ec = boost::system::error_code(); ++ ++ // Find destination address ++ for (LPWSACMSGHDR cmsg = WSA_CMSG_FIRSTHDR(&msg); ++ cmsg != NULL; ++ cmsg = WSA_CMSG_NXTHDR(&msg, cmsg)) ++ { ++ if (cmsg->cmsg_level == IPPROTO_IP && cmsg->cmsg_type == IP_PKTINFO) ++ { ++ struct in_pktinfo *pi = (struct in_pktinfo *) WSA_CMSG_DATA(cmsg); ++ if (pi) ++ { ++ da = boost::asio::ip::address_v4(ntohl(pi->ipi_addr.s_addr)); ++ } ++ } else ++ if (cmsg->cmsg_level == IPPROTO_IPV6 && cmsg->cmsg_type == IPV6_PKTINFO) ++ { ++ struct in6_pktinfo *pi = (struct in6_pktinfo *) WSA_CMSG_DATA(cmsg); ++ if (pi) ++ { ++ boost::asio::ip::address_v6::bytes_type b; ++ memcpy(b.data(), pi->ipi6_addr.s6_addr, sizeof(pi->ipi6_addr.s6_addr)); ++ da = boost::asio::ip::address_v6(b); ++ } ++ } ++ } ++ } else { ++ dwNumberOfBytesRecvd = -1; ++ } ++ return dwNumberOfBytesRecvd; ++#else // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) ++ char cmbuf[0x100]; ++ msghdr msg = msghdr(); ++ init_msghdr_msg_name(msg.msg_name, addr); ++ msg.msg_namelen = static_cast(*addrlen); ++ msg.msg_iov = bufs; ++ msg.msg_iovlen = static_cast(count); ++ msg.msg_control = cmbuf; ++ msg.msg_controllen = sizeof(cmbuf); ++ signed_size_type result = ::recvmsg(s, &msg, flags); ++ get_last_error(ec, true); ++ *addrlen = msg.msg_namelen; ++ if (result >= 0) { ++ ec.assign(0, ec.category()); ++ ++ // Find destination address ++ for (struct cmsghdr *cmsg = CMSG_FIRSTHDR(&msg); ++ cmsg != NULL; ++ cmsg = CMSG_NXTHDR(&msg, cmsg)) ++ { ++ if (cmsg->cmsg_level == IPPROTO_IP && cmsg->cmsg_type == IP_PKTINFO) ++ { ++ struct in_pktinfo *pi = (struct in_pktinfo *) CMSG_DATA(cmsg); ++ if (pi) ++ { ++ da = boost::asio::ip::address_v4(ntohl(pi->ipi_addr.s_addr)); ++ } ++ } else ++ if (cmsg->cmsg_level == IPPROTO_IPV6 && cmsg->cmsg_type == IPV6_PKTINFO) ++ { ++ struct in6_pktinfo *pi = (struct in6_pktinfo *) CMSG_DATA(cmsg); ++ if (pi) ++ { ++ boost::asio::ip::address_v6::bytes_type b; ++ memcpy(b.data(), pi->ipi6_addr.s6_addr, sizeof(pi->ipi6_addr.s6_addr)); ++ da = boost::asio::ip::address_v6(b); ++ } ++ } ++ } ++ } ++ return result; ++#endif // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) ++} ++ ++size_t sync_recvfrom(socket_type s, state_type state, buf* bufs, ++ size_t count, int flags, socket_addr_type* addr, ++ std::size_t* addrlen, boost::system::error_code& ec, boost::asio::ip::address& da) ++{ ++ if (s == invalid_socket) ++ { ++ ec = boost::asio::error::bad_descriptor; ++ return 0; ++ } ++ ++ // Read some data. ++ for (;;) ++ { ++ // Try to complete the operation without blocking. ++ signed_size_type bytes = socket_ops::recvfrom( ++ s, bufs, count, flags, addr, addrlen, ec, da); ++ ++ // Check if operation succeeded. ++ if (bytes >= 0) ++ return bytes; ++ ++ // Operation failed. ++ if ((state & user_set_non_blocking) ++ || (ec != boost::asio::error::would_block ++ && ec != boost::asio::error::try_again)) ++ return 0; ++ ++ // Wait for socket to become ready. ++ if (socket_ops::poll_read(s, 0, -1, ec) < 0) ++ return 0; ++ } ++} ++ ++#if defined(BOOST_ASIO_HAS_IOCP) ++ ++void complete_iocp_recvfrom( ++ const weak_cancel_token_type& cancel_token, ++ boost::system::error_code& ec, boost::asio::ip::address& da) ++{ ++ // Map non-portable errors to their portable counterparts. ++ if (ec.value() == ERROR_NETNAME_DELETED) ++ { ++ if (cancel_token.expired()) ++ ec = boost::asio::error::operation_aborted; ++ else ++ ec = boost::asio::error::connection_reset; ++ } ++ else if (ec.value() == ERROR_PORT_UNREACHABLE) ++ { ++ ec = boost::asio::error::connection_refused; ++ } ++} ++ ++#else // defined(BOOST_ASIO_HAS_IOCP) ++ ++bool non_blocking_recvfrom(socket_type s, ++ buf* bufs, size_t count, int flags, ++ socket_addr_type* addr, std::size_t* addrlen, ++ boost::system::error_code& ec, size_t& bytes_transferred, boost::asio::ip::address& da) ++{ ++ for (;;) ++ { ++ // Read some data. ++ signed_size_type bytes = socket_ops::recvfrom( ++ s, bufs, count, flags, addr, addrlen, ec, da); ++ ++ // Retry operation if interrupted by signal. ++ if (ec == boost::asio::error::interrupted) ++ continue; ++ ++ // Check if we need to run the operation again. ++ if (ec == boost::asio::error::would_block ++ || ec == boost::asio::error::try_again) ++ return false; ++ ++ // Operation is complete. ++ if (bytes >= 0) ++ { ++ ec = boost::system::error_code(); ++ bytes_transferred = bytes; ++ } ++ else ++ bytes_transferred = 0; ++ ++ return true; ++ } ++} ++ ++#endif // defined(BOOST_ASIO_HAS_IOCP) ++ ++} // namespace socket_ops ++} // namespace detail ++} // namespace asio ++} // namespace boost ++ ++#include ++ ++#endif // BOOST_ASIO_DETAIL_SOCKET_OPS_EXT_IPP +diff --git a/implementation/helper/1.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 ++ ++#include ++ ++namespace boost { ++namespace asio { ++namespace detail { ++namespace socket_ops { ++ ++signed_size_type recv(socket_type s, buf* bufs, size_t count, ++ int flags, boost::system::error_code& ec, ++ std::uint32_t& uid, std::uint32_t& gid) ++{ ++ uid = 0xFFFFFFFF; ++ gid = 0xFFFFFFFF; ++ struct ucred *ucredp; ++ ++#if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) ++ // Receive some data. ++ DWORD recv_buf_count = static_cast(count); ++ DWORD bytes_transferred = 0; ++ DWORD recv_flags = flags; ++ int result = ::WSARecv(s, bufs, ++ recv_buf_count, &bytes_transferred, &recv_flags, 0, 0); ++ get_last_error(ec, true); ++ if (ec.value() == ERROR_NETNAME_DELETED) ++ ec = boost::asio::error::connection_reset; ++ else if (ec.value() == ERROR_PORT_UNREACHABLE) ++ ec = boost::asio::error::connection_refused; ++ if (result != 0) ++ return socket_error_retval; ++ ec.assign(0, ec.category()); ++ return bytes_transferred; ++#else // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) ++ msghdr msg = msghdr(); ++ msg.msg_iov = bufs; ++ msg.msg_iovlen = static_cast(count); ++ ++ union { ++ struct cmsghdr cmh; ++ char control[CMSG_SPACE(sizeof(struct ucred))]; ++ } control_un; ++ ++ // Set 'control_un' to describe ancillary data that we want to receive ++ control_un.cmh.cmsg_len = CMSG_LEN(sizeof(struct ucred)); ++ control_un.cmh.cmsg_level = SOL_SOCKET; ++ control_un.cmh.cmsg_type = SCM_CREDENTIALS; ++ ++ // Set 'msg' fields to describe 'control_un' ++ msg.msg_control = control_un.control; ++ msg.msg_controllen = sizeof(control_un.control); ++ ++ signed_size_type result = ::recvmsg(s, &msg, flags); ++ get_last_error(ec, true); ++ if (result >= 0) { ++ ec.assign(0, ec.category()); ++ ++ // Find UID / GID ++ for (struct cmsghdr *cmsg = CMSG_FIRSTHDR(&msg); ++ cmsg != NULL; ++ cmsg = CMSG_NXTHDR(&msg, cmsg)) ++ { ++ if (cmsg->cmsg_level != SOL_SOCKET || cmsg->cmsg_type != SCM_CREDENTIALS ++ || cmsg->cmsg_len != CMSG_LEN(sizeof(struct ucred))) ++ continue; ++ ++ ucredp = (struct ucred *) CMSG_DATA(cmsg); ++ if (ucredp) { ++ uid = ucredp->uid; ++ gid = ucredp->gid; ++ } ++ } ++ } ++ return result; ++#endif // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) ++} ++ ++signed_size_type recvfrom(socket_type s, buf* bufs, size_t count, ++ int flags, socket_addr_type* addr, std::size_t* addrlen, ++ boost::system::error_code& ec, ++ std::uint32_t& uid, std::uint32_t& gid) ++{ ++ uid = 0xFFFFFFFF; ++ gid = 0xFFFFFFFF; ++ struct ucred *ucredp; ++ clear_last_error(); ++#if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) ++ // Receive some data. ++ DWORD recv_buf_count = static_cast(count); ++ DWORD bytes_transferred = 0; ++ DWORD recv_flags = flags; ++ int tmp_addrlen = (int)*addrlen; ++ int result = ::WSARecvFrom(s, bufs, recv_buf_count, ++ &bytes_transferred, &recv_flags, addr, &tmp_addrlen, 0, 0); ++ get_last_error(ec, true); ++ *addrlen = (std::size_t)tmp_addrlen; ++ if (ec.value() == ERROR_NETNAME_DELETED) ++ ec = boost::asio::error::connection_reset; ++ else if (ec.value() == ERROR_PORT_UNREACHABLE) ++ ec = boost::asio::error::connection_refused; ++ if (result != 0) ++ return socket_error_retval; ++ ec.assign(0, ec.category()); ++ return bytes_transferred; ++#else // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) ++ msghdr msg = msghdr(); ++ init_msghdr_msg_name(msg.msg_name, addr); ++ msg.msg_namelen = static_cast(*addrlen); ++ msg.msg_iov = bufs; ++ msg.msg_iovlen = static_cast(count); ++ ++ union { ++ struct cmsghdr cmh; ++ char control[CMSG_SPACE(sizeof(struct ucred))]; ++ } control_un; ++ ++ // Set 'control_un' to describe ancillary data that we want to receive ++ control_un.cmh.cmsg_len = CMSG_LEN(sizeof(struct ucred)); ++ control_un.cmh.cmsg_level = SOL_SOCKET; ++ control_un.cmh.cmsg_type = SCM_CREDENTIALS; ++ ++ // Set 'msg' fields to describe 'control_un' ++ msg.msg_control = control_un.control; ++ msg.msg_controllen = sizeof(control_un.control); ++ ++ signed_size_type result = ::recvmsg(s, &msg, flags); ++ get_last_error(ec, true); ++ *addrlen = msg.msg_namelen; ++ if (result >= 0) { ++ ec.assign(0, ec.category()); ++ ++ // Find UID / GID ++ for (struct cmsghdr *cmsg = CMSG_FIRSTHDR(&msg); ++ cmsg != NULL; ++ cmsg = CMSG_NXTHDR(&msg, cmsg)) ++ { ++ if (cmsg->cmsg_level != SOL_SOCKET || cmsg->cmsg_type != SCM_CREDENTIALS ++ || cmsg->cmsg_len != CMSG_LEN(sizeof(struct ucred))) ++ continue; ++ ++ ucredp = (struct ucred *) CMSG_DATA(cmsg); ++ if (ucredp) { ++ uid = ucredp->uid; ++ gid = ucredp->gid; ++ } ++ } ++ } ++ return result; ++#endif // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) ++} ++ ++size_t sync_recvfrom(socket_type s, state_type state, buf* bufs, ++ size_t count, int flags, socket_addr_type* addr, ++ std::size_t* addrlen, boost::system::error_code& ec, ++ std::uint32_t& uid, std::uint32_t& gid) ++{ ++ if (s == invalid_socket) ++ { ++ ec = boost::asio::error::bad_descriptor; ++ return 0; ++ } ++ ++ // Read some data. ++ for (;;) ++ { ++ // Try to complete the operation without blocking. ++ signed_size_type bytes = socket_ops::recvfrom( ++ s, bufs, count, flags, addr, addrlen, ec, uid, gid); ++ ++ // Check if operation succeeded. ++ if (bytes >= 0) ++ return bytes; ++ ++ // Operation failed. ++ if ((state & user_set_non_blocking) ++ || (ec != boost::asio::error::would_block ++ && ec != boost::asio::error::try_again)) ++ return 0; ++ ++ // Wait for socket to become ready. ++ if (socket_ops::poll_read(s, 0, -1, ec) < 0) ++ return 0; ++ } ++} ++ ++#if defined(BOOST_ASIO_HAS_IOCP) ++ ++void complete_iocp_recvfrom( ++ const weak_cancel_token_type& cancel_token, ++ boost::system::error_code& ec, ++ std::uint32_t& uid, std::uint32_t& gid) ++{ ++ uid = 0xFFFFFFFF; ++ gid = 0xFFFFFFFF; ++ // Map non-portable errors to their portable counterparts. ++ if (ec.value() == ERROR_NETNAME_DELETED) ++ { ++ if (cancel_token.expired()) ++ ec = boost::asio::error::operation_aborted; ++ else ++ ec = boost::asio::error::connection_reset; ++ } ++ else if (ec.value() == ERROR_PORT_UNREACHABLE) ++ { ++ ec = boost::asio::error::connection_refused; ++ } ++} ++ ++#else // defined(BOOST_ASIO_HAS_IOCP) ++ ++bool non_blocking_recv(socket_type s, ++ buf* bufs, size_t count, int flags, bool is_stream, ++ boost::system::error_code& ec, size_t& bytes_transferred, ++ std::uint32_t& uid, std::uint32_t& gid) ++{ ++ for (;;) ++ { ++ // Read some data. ++ signed_size_type bytes = socket_ops::recv(s, bufs, count, flags, ec, uid, gid); ++ ++ // Check for end of stream. ++ if (is_stream && bytes == 0) ++ { ++ ec = boost::asio::error::eof; ++ return true; ++ } ++ ++ // Retry operation if interrupted by signal. ++ if (ec == boost::asio::error::interrupted) ++ continue; ++ ++ // Check if we need to run the operation again. ++ if (ec == boost::asio::error::would_block ++ || ec == boost::asio::error::try_again) ++ return false; ++ ++ // Operation is complete. ++ if (bytes >= 0) ++ { ++ ec = boost::system::error_code(); ++ bytes_transferred = bytes; ++ } ++ else ++ bytes_transferred = 0; ++ ++ return true; ++ } ++} ++ ++bool non_blocking_recvfrom(socket_type s, ++ buf* bufs, size_t count, int flags, ++ socket_addr_type* addr, std::size_t* addrlen, ++ boost::system::error_code& ec, size_t& bytes_transferred, ++ std::uint32_t& uid, std::uint32_t& gid) ++{ ++ for (;;) ++ { ++ // Read some data. ++ signed_size_type bytes = socket_ops::recvfrom( ++ s, bufs, count, flags, addr, addrlen, ec, uid, gid); ++ ++ // Retry operation if interrupted by signal. ++ if (ec == boost::asio::error::interrupted) ++ continue; ++ ++ // Check if we need to run the operation again. ++ if (ec == boost::asio::error::would_block ++ || ec == boost::asio::error::try_again) ++ return false; ++ ++ // Operation is complete. ++ if (bytes >= 0) ++ { ++ ec = boost::system::error_code(); ++ bytes_transferred = bytes; ++ } ++ else ++ bytes_transferred = 0; ++ ++ return true; ++ } ++} ++ ++#endif // defined(BOOST_ASIO_HAS_IOCP) ++ ++} // namespace socket_ops ++} // namespace detail ++} // namespace asio ++} // namespace boost ++ ++#include ++ ++#endif // BOOST_ASIO_DETAIL_SOCKET_OPS_EXT_LOCAL_IPP +diff --git a/implementation/helper/1.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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++namespace boost { ++namespace asio { ++namespace detail { ++ ++template ++class reactive_socket_recv_op_base_ext : public reactor_op_ext ++{ ++public: ++ reactive_socket_recv_op_base_ext(const boost::system::error_code& success_ec, ++ socket_type socket, socket_ops::state_type state, ++ const MutableBufferSequence& buffers, ++ socket_base::message_flags flags, func_type complete_func) ++ : reactor_op_ext(success_ec, &reactive_socket_recv_op_base_ext::do_perform, complete_func), ++ socket_(socket), ++ state_(state), ++ buffers_(buffers), ++ flags_(flags) ++ { ++ } ++ ++ static status do_perform(reactor_op* base) ++ { ++ reactive_socket_recv_op_base_ext* o( ++ static_cast(base)); ++ ++ typedef buffer_sequence_adapter bufs_type; ++ ++ status result; ++ if (bufs_type::is_single_buffer) ++ { ++ result = socket_ops::non_blocking_recv1(o->socket_, ++ bufs_type::first(o->buffers_).data(), ++ bufs_type::first(o->buffers_).size(), o->flags_, ++ (o->state_ & socket_ops::stream_oriented) != 0, ++ o->ec_, o->bytes_transferred_) ? done : not_done; ++ } ++ else ++ { ++ bufs_type bufs(o->buffers_); ++ result = socket_ops::non_blocking_recv(o->socket_, ++ bufs.buffers(), bufs.count(), o->flags_, ++ (o->state_ & socket_ops::stream_oriented) != 0, ++ o->ec_, o->bytes_transferred_) ? done : not_done; ++ } ++ ++ if (result == done) ++ if ((o->state_ & socket_ops::stream_oriented) != 0) ++ if (o->bytes_transferred_ == 0) ++ result = done_and_exhausted; ++ ++ BOOST_ASIO_HANDLER_REACTOR_OPERATION((*o, "non_blocking_recv", ++ o->ec_, o->bytes_transferred_)); ++ ++ return result; ++ } ++ ++private: ++ socket_type socket_; ++ socket_ops::state_type state_; ++ MutableBufferSequence buffers_; ++ socket_base::message_flags flags_; ++}; ++ ++template ++class reactive_socket_recv_op_ext : ++ public reactive_socket_recv_op_base_ext ++{ ++public: ++ BOOST_ASIO_DEFINE_HANDLER_PTR(reactive_socket_recv_op_ext); ++ ++ reactive_socket_recv_op_ext(const boost::system::error_code& success_ec, ++ socket_type socket, socket_ops::state_type state, ++ const MutableBufferSequence& buffers, socket_base::message_flags flags, ++ Handler& handler, const IoExecutor& io_ex) ++ : reactive_socket_recv_op_base_ext(success_ec, ++ socket, state, buffers, flags, ++ &reactive_socket_recv_op_ext::do_complete), ++ handler_(BOOST_ASIO_MOVE_CAST(Handler)(handler)), ++ work_(handler_, io_ex) ++ { ++ } ++ ++ static void do_complete(void* owner, operation* base, ++ const boost::system::error_code& /*ec*/, ++ std::size_t /*bytes_transferred*/) ++ { ++ // Take ownership of the handler object. ++ reactive_socket_recv_op_ext* o(static_cast(base)); ++ ptr p = { boost::asio::detail::addressof(o->handler_), o, o }; ++ ++ BOOST_ASIO_HANDLER_COMPLETION((*o)); ++ ++ // Take ownership of the operation's outstanding work. ++ handler_work w( ++ BOOST_ASIO_MOVE_CAST2(handler_work)( ++ o->work_)); ++ ++ // Make a copy of the handler so that the memory can be deallocated before ++ // the upcall is made. Even if we're not about to make an upcall, a ++ // sub-object of the handler may be the true owner of the memory associated ++ // with the handler. Consequently, a local copy of the handler is required ++ // to ensure that any owning sub-object remains valid until after we have ++ // deallocated the memory here. ++ detail::binder3 ++ handler(o->handler_, o->ec_, o->bytes_transferred_, o->da_); ++ p.h = boost::asio::detail::addressof(handler.handler_); ++ p.reset(); ++ ++ // Make the upcall if required. ++ if (owner) ++ { ++ fenced_block b(fenced_block::half); ++ BOOST_ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, handler.arg2_, handler.arg3_)); ++ w.complete(handler, handler.handler_); ++ BOOST_ASIO_HANDLER_INVOCATION_END; ++ } ++ } ++ ++private: ++ Handler handler_; ++ handler_work work_; ++}; ++ ++} // namespace detail ++} // namespace asio ++} // namespace boost ++ ++#include ++ ++#endif // BOOST_ASIO_DETAIL_REACTIVE_SOCKET_RECV_OP_EXT_HPP +diff --git a/implementation/helper/1.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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++namespace boost { ++namespace asio { ++namespace detail { ++ ++template ++class reactive_socket_recv_op_base_ext_local : public reactor_op_ext_local ++{ ++public: ++ reactive_socket_recv_op_base_ext_local(const boost::system::error_code& success_ec, ++ socket_type socket, socket_ops::state_type state, ++ const MutableBufferSequence& buffers, ++ socket_base::message_flags flags, func_type complete_func) ++ : reactor_op_ext_local(success_ec, &reactive_socket_recv_op_base_ext_local::do_perform, complete_func), ++ socket_(socket), ++ state_(state), ++ buffers_(buffers), ++ flags_(flags) ++ { ++ } ++ ++ static status do_perform(reactor_op* base) ++ { ++ reactive_socket_recv_op_base_ext_local* o( ++ static_cast(base)); ++ ++ typedef buffer_sequence_adapter bufs_type; ++ ++ status result; ++ if (bufs_type::is_single_buffer) ++ { ++ result = socket_ops::non_blocking_recv1(o->socket_, ++ bufs_type::first(o->buffers_).data(), ++ bufs_type::first(o->buffers_).size(), o->flags_, ++ (o->state_ & socket_ops::stream_oriented) != 0, ++ o->ec_, o->bytes_transferred_) ? done : not_done; ++ } ++ else ++ { ++ bufs_type bufs(o->buffers_); ++ result = socket_ops::non_blocking_recv(o->socket_, ++ bufs.buffers(), bufs.count(), o->flags_, ++ (o->state_ & socket_ops::stream_oriented) != 0, ++ o->ec_, o->bytes_transferred_) ? done : not_done; ++ } ++ ++ if (result == done) ++ if ((o->state_ & socket_ops::stream_oriented) != 0) ++ if (o->bytes_transferred_ == 0) ++ result = done_and_exhausted; ++ ++ BOOST_ASIO_HANDLER_REACTOR_OPERATION((*o, "non_blocking_recv", ++ o->ec_, o->bytes_transferred_)); ++ ++ return result; ++ } ++ ++private: ++ socket_type socket_; ++ socket_ops::state_type state_; ++ MutableBufferSequence buffers_; ++ socket_base::message_flags flags_; ++}; ++ ++template ++class reactive_socket_recv_op_ext_local : ++ public reactive_socket_recv_op_base_ext_local ++{ ++public: ++ BOOST_ASIO_DEFINE_HANDLER_PTR(reactive_socket_recv_op_ext_local); ++ ++ reactive_socket_recv_op_ext_local(const boost::system::error_code& success_ec, ++ socket_type socket, socket_ops::state_type state, ++ const MutableBufferSequence& buffers, socket_base::message_flags flags, ++ Handler& handler, const IoExecutor& io_ex) ++ : reactive_socket_recv_op_base_ext_local(success_ec, ++ socket, state, buffers, flags, ++ &reactive_socket_recv_op_ext_local::do_complete), ++ handler_(BOOST_ASIO_MOVE_CAST(Handler)(handler)), ++ work_(handler_, io_ex) ++ { ++ } ++ ++ static void do_complete(void* owner, operation* base, ++ const boost::system::error_code& /*ec*/, ++ std::size_t /*bytes_transferred*/) ++ { ++ // Take ownership of the handler object. ++ reactive_socket_recv_op_ext_local* o(static_cast(base)); ++ ptr p = { boost::asio::detail::addressof(o->handler_), o, o }; ++ ++ BOOST_ASIO_HANDLER_COMPLETION((*o)); ++ ++ // Take ownership of the operation's outstanding work. ++ handler_work w( ++ BOOST_ASIO_MOVE_CAST2(handler_work)( ++ o->work_)); ++ ++ // Make a copy of the handler so that the memory can be deallocated before ++ // the upcall is made. Even if we're not about to make an upcall, a ++ // sub-object of the handler may be the true owner of the memory associated ++ // with the handler. Consequently, a local copy of the handler is required ++ // to ensure that any owning sub-object remains valid until after we have ++ // deallocated the memory here. ++ detail::binder4 ++ handler(o->handler_, o->ec_, o->bytes_transferred_, o->uid_, o->gid_); ++ p.h = boost::asio::detail::addressof(handler.handler_); ++ p.reset(); ++ ++ // Make the upcall if required. ++ if (owner) ++ { ++ fenced_block b(fenced_block::half); ++ BOOST_ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, handler.arg2_, handler.arg3, handler.arg4)); ++ w.complete(handler, handler.handler_); ++ BOOST_ASIO_HANDLER_INVOCATION_END; ++ } ++ } ++ ++private: ++ Handler handler_; ++ handler_work work_; ++}; ++ ++} // namespace detail ++} // namespace asio ++} // namespace boost ++ ++#include ++ ++#endif // BOOST_ASIO_DETAIL_REACTIVE_SOCKET_RECV_OP_EXT_LOCAL_HPP +diff --git a/implementation/helper/1.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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++namespace boost { ++namespace asio { ++namespace detail { ++ ++template ++class reactive_socket_recvfrom_op_base_ext : public reactor_op_ext ++{ ++public: ++ reactive_socket_recvfrom_op_base_ext(const boost::system::error_code& success_ec, ++ socket_type socket, int protocol_type, ++ const MutableBufferSequence& buffers, Endpoint& endpoint, ++ socket_base::message_flags flags, func_type complete_func) ++ : reactor_op_ext(success_ec, &reactive_socket_recvfrom_op_base_ext::do_perform, complete_func), ++ socket_(socket), ++ protocol_type_(protocol_type), ++ buffers_(buffers), ++ sender_endpoint_(endpoint), ++ flags_(flags) ++ { ++ } ++ ++ static status do_perform(reactor_op* base) ++ { ++ reactive_socket_recvfrom_op_base_ext* o( ++ static_cast(base)); ++ ++ buffer_sequence_adapter bufs(o->buffers_); ++ ++ std::size_t addr_len = o->sender_endpoint_.capacity(); ++ status result = socket_ops::non_blocking_recvfrom(o->socket_, ++ bufs.buffers(), bufs.count(), o->flags_, ++ o->sender_endpoint_.data(), &addr_len, ++ o->ec_, o->bytes_transferred_, o->da_) ? done : not_done; ++ ++ if (result && !o->ec_) ++ o->sender_endpoint_.resize(addr_len); ++ ++ BOOST_ASIO_HANDLER_REACTOR_OPERATION((*o, "non_blocking_recvfrom", ++ o->ec_, o->bytes_transferred_)); ++ ++ return result; ++ } ++ ++private: ++ socket_type socket_; ++ int protocol_type_; ++ MutableBufferSequence buffers_; ++ Endpoint& sender_endpoint_; ++ socket_base::message_flags flags_; ++}; ++ ++template ++class reactive_socket_recvfrom_op_ext : ++ public reactive_socket_recvfrom_op_base_ext ++{ ++public: ++ BOOST_ASIO_DEFINE_HANDLER_PTR(reactive_socket_recvfrom_op_ext); ++ ++ reactive_socket_recvfrom_op_ext(const boost::system::error_code& success_ec, ++ socket_type socket, int protocol_type, ++ const MutableBufferSequence& buffers, Endpoint& endpoint, ++ socket_base::message_flags flags, Handler& handler, ++ const IoExecutor& io_ex) ++ : reactive_socket_recvfrom_op_base_ext( ++ success_ec, socket, protocol_type, buffers, endpoint, flags, ++ &reactive_socket_recvfrom_op_ext::do_complete), ++ handler_(BOOST_ASIO_MOVE_CAST(Handler)(handler)), ++ work_(handler_, io_ex) ++ { ++ } ++ ++ static void do_complete(void* owner, operation* base, ++ const boost::system::error_code& /*ec*/, ++ std::size_t /*bytes_transferred*/) ++ { ++ // Take ownership of the handler object. ++ reactive_socket_recvfrom_op_ext* o( ++ static_cast(base)); ++ ptr p = { boost::asio::detail::addressof(o->handler_), o, o }; ++ ++ BOOST_ASIO_HANDLER_COMPLETION((*o)); ++ ++ // Take ownership of the operation's outstanding work. ++ handler_work w( ++ BOOST_ASIO_MOVE_CAST2(handler_work)( ++ o->work_)); ++ ++ // Make a copy of the handler so that the memory can be deallocated before ++ // the upcall is made. Even if we're not about to make an upcall, a ++ // sub-object of the handler may be the true owner of the memory associated ++ // with the handler. Consequently, a local copy of the handler is required ++ // to ensure that any owning sub-object remains valid until after we have ++ // deallocated the memory here. ++ detail::binder3 ++ handler(o->handler_, o->ec_, o->bytes_transferred_, o->da_); ++ p.h = boost::asio::detail::addressof(handler.handler_); ++ p.reset(); ++ ++ // Make the upcall if required. ++ if (owner) ++ { ++ fenced_block b(fenced_block::half); ++ BOOST_ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, handler.arg2_, handler.arg3_)); ++ w.complete(handler, handler.handler_); ++ BOOST_ASIO_HANDLER_INVOCATION_END; ++ } ++ } ++ ++private: ++ Handler handler_; ++ handler_work work_; ++}; ++ ++} // namespace detail ++} // namespace asio ++} // namespace boost ++ ++#include ++ ++#endif // BOOST_ASIO_DETAIL_REACTIVE_SOCKET_RECVFROM_OP_EXT_HPP +diff --git a/implementation/helper/1.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 ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++namespace boost { ++namespace asio { ++namespace detail { ++ ++template ++class reactive_socket_recvfrom_op_base_ext_local : public reactor_op_ext_local ++{ ++public: ++ reactive_socket_recvfrom_op_base_ext_local(socket_type socket, int protocol_type, ++ const MutableBufferSequence& buffers, Endpoint& endpoint, ++ socket_base::message_flags flags, func_type complete_func) ++ : reactor_op_ext_local(&reactive_socket_recvfrom_op_base_ext_local::do_perform, complete_func), ++ socket_(socket), ++ protocol_type_(protocol_type), ++ buffers_(buffers), ++ sender_endpoint_(endpoint), ++ flags_(flags) ++ { ++ } ++ ++ static status do_perform(reactor_op* base) ++ { ++ reactive_socket_recvfrom_op_base_ext_local* o( ++ static_cast(base)); ++ ++ buffer_sequence_adapter bufs(o->buffers_); ++ ++ std::size_t addr_len = o->sender_endpoint_.capacity(); ++ status result = socket_ops::non_blocking_recvfrom(o->socket_, ++ bufs.buffers(), bufs.count(), o->flags_, ++ o->sender_endpoint_.data(), &addr_len, ++ o->ec_, o->bytes_transferred_, o->uid_, o->gid_) ? done : not_done; ++ ++ if (result && !o->ec_) ++ o->sender_endpoint_.resize(addr_len); ++ ++ BOOST_ASIO_HANDLER_REACTOR_OPERATION((*o, "non_blocking_recvfrom", ++ o->ec_, o->bytes_transferred_)); ++ ++ return result; ++ } ++ ++private: ++ socket_type socket_; ++ int protocol_type_; ++ MutableBufferSequence buffers_; ++ Endpoint& sender_endpoint_; ++ socket_base::message_flags flags_; ++}; ++ ++template ++class reactive_socket_recvfrom_op_ext_local : ++ public reactive_socket_recvfrom_op_base_ext_local ++{ ++public: ++ BOOST_ASIO_DEFINE_HANDLER_PTR(reactive_socket_recvfrom_op_ext_local); ++ ++ reactive_socket_recvfrom_op_ext_local(socket_type socket, int protocol_type, ++ const MutableBufferSequence& buffers, Endpoint& endpoint, ++ socket_base::message_flags flags, Handler& handler, ++ const IoExecutor& io_ex) ++ : reactive_socket_recvfrom_op_base_ext_local( ++ socket, protocol_type, buffers, endpoint, flags, ++ &reactive_socket_recvfrom_op_ext_local::do_complete), ++ handler_(BOOST_ASIO_MOVE_CAST(Handler)(handler)), ++ work_(handler_, io_ex) ++ { ++ } ++ ++ static void do_complete(void* owner, operation* base, ++ const boost::system::error_code& /*ec*/, ++ std::size_t /*bytes_transferred*/) ++ { ++ // Take ownership of the handler object. ++ reactive_socket_recvfrom_op_ext_local* o( ++ static_cast(base)); ++ ptr p = { boost::asio::detail::addressof(o->handler_), o, o }; ++ ++ BOOST_ASIO_HANDLER_COMPLETION((*o)); ++ ++ // Take ownership of the operation's outstanding work. ++ handler_work w( ++ BOOST_ASIO_MOVE_CAST2(handler_work)( ++ o->work_)); ++ ++ // Make a copy of the handler so that the memory can be deallocated before ++ // the upcall is made. Even if we're not about to make an upcall, a ++ // sub-object of the handler may be the true owner of the memory associated ++ // with the handler. Consequently, a local copy of the handler is required ++ // to ensure that any owning sub-object remains valid until after we have ++ // deallocated the memory here. ++ detail::binder4 ++ handler(o->handler_, o->ec_, o->bytes_transferred_, o->uid_, o->gid_); ++ p.h = boost::asio::detail::addressof(handler.handler_); ++ p.reset(); ++ ++ // Make the upcall if required. ++ if (owner) ++ { ++ fenced_block b(fenced_block::half); ++ BOOST_ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, handler.arg2_, handler.arg3_, handler.arg4_)); ++ w.complete(handler, handler.handler_); ++ BOOST_ASIO_HANDLER_INVOCATION_END; ++ } ++ } ++ ++private: ++ Handler handler_; ++ handler_work work_; ++}; ++ ++} // namespace detail ++} // namespace asio ++} // namespace boost ++ ++#include ++ ++#endif // BOOST_ASIO_DETAIL_REACTIVE_SOCKET_RECVFROM_OP_EXT_LOCAL_HPP +diff --git a/implementation/helper/1.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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++namespace boost { ++namespace asio { ++namespace detail { ++ ++template ++class reactive_socket_recvmsg_op_base_ext : public reactor_op_ext ++{ ++public: ++ reactive_socket_recvmsg_op_base_ext(const boost::system::error_code& success_ec, ++ socket_type socket, const MutableBufferSequence& buffers, socket_base::message_flags in_flags, ++ socket_base::message_flags& out_flags, func_type complete_func) ++ : reactor_op_ext(&reactive_socket_recvmsg_op_base_ext::do_perform, complete_func), ++ socket_(socket), ++ buffers_(buffers), ++ in_flags_(in_flags), ++ out_flags_(out_flags) ++ { ++ } ++ ++ static status do_perform(reactor_op* base) ++ { ++ reactive_socket_recvmsg_op_base_ext* o( ++ static_cast(base)); ++ ++ buffer_sequence_adapter bufs(o->buffers_); ++ ++ status result = socket_ops::non_blocking_recvmsg(o->socket_, ++ bufs.buffers(), bufs.count(), ++ o->in_flags_, o->out_flags_, ++ o->ec_, o->bytes_transferred_) ? done : not_done; ++ ++ BOOST_ASIO_HANDLER_REACTOR_OPERATION((*o, "non_blocking_recvmsg", ++ o->ec_, o->bytes_transferred_)); ++ ++ return result; ++ } ++ ++private: ++ socket_type socket_; ++ MutableBufferSequence buffers_; ++ socket_base::message_flags in_flags_; ++ socket_base::message_flags& out_flags_; ++}; ++ ++template ++class reactive_socket_recvmsg_op_ext : ++ public reactive_socket_recvmsg_op_base_ext ++{ ++public: ++ BOOST_ASIO_DEFINE_HANDLER_PTR(reactive_socket_recvmsg_op_ext); ++ ++ reactive_socket_recvmsg_op_ext(const boost::system::error_code& success_ec, ++ socket_type socket, const MutableBufferSequence& buffers, socket_base::message_flags in_flags, ++ socket_base::message_flags& out_flags, Handler& handler, ++ const IoExecutor& io_ex) ++ : reactive_socket_recvmsg_op_base_ext(socket, buffers, ++ in_flags, out_flags, &reactive_socket_recvmsg_op_ext::do_complete), ++ handler_(BOOST_ASIO_MOVE_CAST(Handler)(handler)), ++ work_(handler_, io_ex) ++ { ++ } ++ ++ static void do_complete(void* owner, operation* base, ++ const boost::system::error_code& /*ec*/, ++ std::size_t /*bytes_transferred*/) ++ { ++ // Take ownership of the handler object. ++ reactive_socket_recvmsg_op_ext* o( ++ static_cast(base)); ++ ptr p = { boost::asio::detail::addressof(o->handler_), o, o }; ++ ++ BOOST_ASIO_HANDLER_COMPLETION((*o)); ++ ++ // Take ownership of the operation's outstanding work. ++ handler_work w( ++ BOOST_ASIO_MOVE_CAST2(handler_work)( ++ o->work_)); ++ ++ // Make a copy of the handler so that the memory can be deallocated before ++ // the upcall is made. Even if we're not about to make an upcall, a ++ // sub-object of the handler may be the true owner of the memory associated ++ // with the handler. Consequently, a local copy of the handler is required ++ // to ensure that any owning sub-object remains valid until after we have ++ // deallocated the memory here. ++ detail::binder3 ++ handler(o->handler_, o->ec_, o->bytes_transferred_, o->da_); ++ p.h = boost::asio::detail::addressof(handler.handler_); ++ p.reset(); ++ ++ // Make the upcall if required. ++ if (owner) ++ { ++ fenced_block b(fenced_block::half); ++ BOOST_ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, handler.arg2_, handler.arg3_)); ++ w.complete(handler, handler.handler_); ++ BOOST_ASIO_HANDLER_INVOCATION_END; ++ } ++ } ++ ++private: ++ Handler handler_; ++ handler_work work_; ++}; ++ ++} // namespace detail ++} // namespace asio ++} // namespace boost ++ ++#include ++ ++#endif // BOOST_ASIO_DETAIL_REACTIVE_SOCKET_RECVMSG_OP_EXT_HPP +diff --git a/implementation/helper/1.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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++namespace boost { ++namespace asio { ++namespace detail { ++ ++template ++class reactive_socket_recvmsg_op_base_ext_local : public reactor_op_ext_local ++{ ++public: ++ reactive_socket_recvmsg_op_base_ext_local(const boost::system::error_code& success_ec, ++ socket_type socket, const MutableBufferSequence& buffers, socket_base::message_flags in_flags, ++ socket_base::message_flags& out_flags, func_type complete_func) ++ : reactor_op_ext_local(success_ec, &reactive_socket_recvmsg_op_base_ext_local::do_perform, complete_func), ++ socket_(socket), ++ buffers_(buffers), ++ in_flags_(in_flags), ++ out_flags_(out_flags) ++ { ++ } ++ ++ static status do_perform(reactor_op* base) ++ { ++ reactive_socket_recvmsg_op_base_ext_local* o( ++ static_cast(base)); ++ ++ buffer_sequence_adapter bufs(o->buffers_); ++ ++ status result = socket_ops::non_blocking_recvmsg(o->socket_, ++ bufs.buffers(), bufs.count(), ++ o->in_flags_, o->out_flags_, ++ o->ec_, o->bytes_transferred_) ? done : not_done; ++ ++ BOOST_ASIO_HANDLER_REACTOR_OPERATION((*o, "non_blocking_recvmsg", ++ o->ec_, o->bytes_transferred_)); ++ ++ return result; ++ } ++ ++private: ++ socket_type socket_; ++ MutableBufferSequence buffers_; ++ socket_base::message_flags in_flags_; ++ socket_base::message_flags& out_flags_; ++}; ++ ++template ++class reactive_socket_recvmsg_op_ext_local : ++ public reactive_socket_recvmsg_op_base_ext_local ++{ ++public: ++ BOOST_ASIO_DEFINE_HANDLER_PTR(reactive_socket_recvmsg_op_ext_local); ++ ++ reactive_socket_recvmsg_op_ext_local(const boost::system::error_code& success_ec, ++ socket_type socket, const MutableBufferSequence& buffers, socket_base::message_flags in_flags, ++ socket_base::message_flags& out_flags, Handler& handler, ++ const IoExecutor& io_ex) ++ : reactive_socket_recvmsg_op_base_ext_local(success_ec, ++ socket, buffers, in_flags, out_flags, ++ &reactive_socket_recvmsg_op_ext_local::do_complete), ++ handler_(BOOST_ASIO_MOVE_CAST(Handler)(handler)), ++ work_(handler_, io_ex) ++ { ++ } ++ ++ static void do_complete(void* owner, operation* base, ++ const boost::system::error_code& /*ec*/, ++ std::size_t /*bytes_transferred*/) ++ { ++ // Take ownership of the handler object. ++ reactive_socket_recvmsg_op_ext_local* o( ++ static_cast(base)); ++ ptr p = { boost::asio::detail::addressof(o->handler_), o, o }; ++ ++ BOOST_ASIO_HANDLER_COMPLETION((*o)); ++ ++ // Take ownership of the operation's outstanding work. ++ handler_work w( ++ BOOST_ASIO_MOVE_CAST2(handler_work)( ++ o->work_)); ++ ++ // Make a copy of the handler so that the memory can be deallocated before ++ // the upcall is made. Even if we're not about to make an upcall, a ++ // sub-object of the handler may be the true owner of the memory associated ++ // with the handler. Consequently, a local copy of the handler is required ++ // to ensure that any owning sub-object remains valid until after we have ++ // deallocated the memory here. ++ detail::binder4 ++ handler(o->handler_, o->ec_, o->bytes_transferred_, o->uid_, o->gid_); ++ p.h = boost::asio::detail::addressof(handler.handler_); ++ p.reset(); ++ ++ // Make the upcall if required. ++ if (owner) ++ { ++ fenced_block b(fenced_block::half); ++ BOOST_ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, handler.arg2_, handler.arg3_, handler.arg4_)); ++ w.complete(handler, handler.handler_); ++ BOOST_ASIO_HANDLER_INVOCATION_END; ++ } ++ } ++ ++private: ++ Handler handler_; ++ handler_work work_; ++}; ++ ++} // namespace detail ++} // namespace asio ++} // namespace boost ++ ++#include ++ ++#endif // BOOST_ASIO_DETAIL_REACTIVE_SOCKET_RECVMSG_OP_EXT_LOCAL_HPP +diff --git a/implementation/helper/1.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 ++ ++#if !defined(BOOST_ASIO_HAS_IOCP) \ ++ && !defined(BOOST_ASIO_WINDOWS_RUNTIME) ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++namespace boost { ++namespace asio { ++namespace detail { ++ ++class reactive_socket_service_base_ext ++{ ++public: ++ // The native type of a socket. ++ typedef socket_type native_handle_type; ++ ++ // The implementation type of the socket. ++ struct base_implementation_type ++ { ++ // The native socket representation. ++ socket_type socket_; ++ ++ // The current state of the socket. ++ socket_ops::state_type state_; ++ ++ // Per-descriptor data used by the reactor. ++ reactor::per_descriptor_data reactor_data_; ++ }; ++ ++ // Constructor. ++ BOOST_ASIO_DECL reactive_socket_service_base_ext(execution_context& context); ++ ++ // Destroy all user-defined handler objects owned by the service. ++ BOOST_ASIO_DECL void base_shutdown(); ++ ++ // Construct a new socket implementation. ++ BOOST_ASIO_DECL void construct(base_implementation_type& impl); ++ ++ // Move-construct a new socket implementation. ++ BOOST_ASIO_DECL void base_move_construct(base_implementation_type& impl, ++ base_implementation_type& other_impl); ++ ++ // Move-assign from another socket implementation. ++ BOOST_ASIO_DECL void base_move_assign(base_implementation_type& impl, ++ reactive_socket_service_base_ext& other_service, ++ base_implementation_type& other_impl); ++ ++ // Destroy a socket implementation. ++ BOOST_ASIO_DECL void destroy(base_implementation_type& impl); ++ ++ // Determine whether the socket is open. ++ bool is_open(const base_implementation_type& impl) const ++ { ++ return impl.socket_ != invalid_socket; ++ } ++ ++ // Destroy a socket implementation. ++ BOOST_ASIO_DECL boost::system::error_code close( ++ base_implementation_type& impl, boost::system::error_code& ec); ++ ++ // Release ownership of the socket. ++ BOOST_ASIO_DECL socket_type release( ++ base_implementation_type& impl, boost::system::error_code& ec); ++ ++ // Get the native socket representation. ++ native_handle_type native_handle(base_implementation_type& impl) ++ { ++ return impl.socket_; ++ } ++ ++ // Cancel all operations associated with the socket. ++ BOOST_ASIO_DECL boost::system::error_code cancel( ++ base_implementation_type& impl, boost::system::error_code& ec); ++ ++ // Determine whether the socket is at the out-of-band data mark. ++ bool at_mark(const base_implementation_type& impl, ++ boost::system::error_code& ec) const ++ { ++ return socket_ops::sockatmark(impl.socket_, ec); ++ } ++ ++ // Determine the number of bytes available for reading. ++ std::size_t available(const base_implementation_type& impl, ++ boost::system::error_code& ec) const ++ { ++ return socket_ops::available(impl.socket_, ec); ++ } ++ ++ // Place the socket into the state where it will listen for new connections. ++ boost::system::error_code listen(base_implementation_type& impl, ++ int backlog, boost::system::error_code& ec) ++ { ++ socket_ops::listen(impl.socket_, backlog, ec); ++ return ec; ++ } ++ ++ // Perform an IO control command on the socket. ++ template ++ boost::system::error_code io_control(base_implementation_type& impl, ++ IO_Control_Command& command, boost::system::error_code& ec) ++ { ++ socket_ops::ioctl(impl.socket_, impl.state_, command.name(), ++ static_cast(command.data()), ec); ++ return ec; ++ } ++ ++ // Gets the non-blocking mode of the socket. ++ bool non_blocking(const base_implementation_type& impl) const ++ { ++ return (impl.state_ & socket_ops::user_set_non_blocking) != 0; ++ } ++ ++ // Sets the non-blocking mode of the socket. ++ boost::system::error_code non_blocking(base_implementation_type& impl, ++ bool mode, boost::system::error_code& ec) ++ { ++ socket_ops::set_user_non_blocking(impl.socket_, impl.state_, mode, ec); ++ return ec; ++ } ++ ++ // Gets the non-blocking mode of the native socket implementation. ++ bool native_non_blocking(const base_implementation_type& impl) const ++ { ++ return (impl.state_ & socket_ops::internal_non_blocking) != 0; ++ } ++ ++ // Sets the non-blocking mode of the native socket implementation. ++ boost::system::error_code native_non_blocking(base_implementation_type& impl, ++ bool mode, boost::system::error_code& ec) ++ { ++ socket_ops::set_internal_non_blocking(impl.socket_, impl.state_, mode, ec); ++ return ec; ++ } ++ ++ // Wait for the socket to become ready to read, ready to write, or to have ++ // pending error conditions. ++ boost::system::error_code wait(base_implementation_type& impl, ++ socket_base::wait_type w, boost::system::error_code& ec) ++ { ++ switch (w) ++ { ++ case socket_base::wait_read: ++ socket_ops::poll_read(impl.socket_, impl.state_, -1, ec); ++ break; ++ case socket_base::wait_write: ++ socket_ops::poll_write(impl.socket_, impl.state_, -1, ec); ++ break; ++ case socket_base::wait_error: ++ socket_ops::poll_error(impl.socket_, impl.state_, -1, ec); ++ break; ++ default: ++ ec = boost::asio::error::invalid_argument; ++ break; ++ } ++ ++ return ec; ++ } ++ ++ // Asynchronously wait for the socket to become ready to read, ready to ++ // write, or to have pending error conditions. ++ template ++ void async_wait(base_implementation_type& impl, ++ socket_base::wait_type w, Handler& handler, const IoExecutor& io_ex) ++ { ++ bool is_continuation = ++ boost_asio_handler_cont_helpers::is_continuation(handler); ++ ++ // Allocate and construct an operation to wrap the handler. ++ typedef reactive_wait_op op; ++ typename op::ptr p = { boost::asio::detail::addressof(handler), ++ op::ptr::allocate(handler), 0 }; ++ p.p = new (p.v) op(success_ec_, handler, io_ex); ++ ++ BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket", ++ &impl, impl.socket_, "async_wait")); ++ ++ int op_type; ++ switch (w) ++ { ++ case socket_base::wait_read: ++ op_type = reactor::read_op; ++ break; ++ case socket_base::wait_write: ++ op_type = reactor::write_op; ++ break; ++ case socket_base::wait_error: ++ op_type = reactor::except_op; ++ break; ++ default: ++ p.p->ec_ = boost::asio::error::invalid_argument; ++ reactor_.post_immediate_completion(p.p, is_continuation); ++ p.v = p.p = 0; ++ return; ++ } ++ ++ start_op(impl, op_type, p.p, is_continuation, false, false); ++ p.v = p.p = 0; ++ } ++ ++ // Send the given data to the peer. ++ template ++ size_t send(base_implementation_type& impl, ++ const ConstBufferSequence& buffers, ++ socket_base::message_flags flags, boost::system::error_code& ec) ++ { ++ buffer_sequence_adapter bufs(buffers); ++ ++ return socket_ops::sync_send(impl.socket_, impl.state_, ++ bufs.buffers(), bufs.count(), flags, bufs.all_empty(), ec); ++ } ++ ++ // Wait until data can be sent without blocking. ++ size_t send(base_implementation_type& impl, const null_buffers&, ++ socket_base::message_flags, boost::system::error_code& ec) ++ { ++ // Wait for socket to become ready. ++ socket_ops::poll_write(impl.socket_, impl.state_, -1, ec); ++ ++ return 0; ++ } ++ ++ // Start an asynchronous send. The data being sent must be valid for the ++ // lifetime of the asynchronous operation. ++ template ++ void async_send(base_implementation_type& impl, ++ const ConstBufferSequence& buffers, socket_base::message_flags flags, ++ Handler& handler, const IoExecutor& io_ex) ++ { ++ bool is_continuation = ++ boost_asio_handler_cont_helpers::is_continuation(handler); ++ ++ // Allocate and construct an operation to wrap the handler. ++ typedef reactive_socket_send_op< ++ ConstBufferSequence, Handler, IoExecutor> op; ++ typename op::ptr p = { boost::asio::detail::addressof(handler), ++ op::ptr::allocate(handler), 0 }; ++ p.p = new (p.v) op(success_ec_, impl.socket_, impl.state_, ++ buffers, flags, handler, io_ex); ++ ++ BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket", ++ &impl, impl.socket_, "async_send")); ++ ++ start_op(impl, reactor::write_op, p.p, is_continuation, true, ++ ((impl.state_ & socket_ops::stream_oriented) ++ && buffer_sequence_adapter::all_empty(buffers))); ++ p.v = p.p = 0; ++ } ++ ++ // Start an asynchronous wait until data can be sent without blocking. ++ template ++ void async_send(base_implementation_type& impl, const null_buffers&, ++ socket_base::message_flags, Handler& handler, const IoExecutor& io_ex) ++ { ++ bool is_continuation = ++ boost_asio_handler_cont_helpers::is_continuation(handler); ++ ++ // Allocate and construct an operation to wrap the handler. ++ typedef reactive_null_buffers_op op; ++ typename op::ptr p = { boost::asio::detail::addressof(handler), ++ op::ptr::allocate(handler), 0 }; ++ p.p = new (p.v) op(success_ec_, handler, io_ex); ++ ++ BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket", ++ &impl, impl.socket_, "async_send(null_buffers)")); ++ ++ start_op(impl, reactor::write_op, p.p, is_continuation, false, false); ++ p.v = p.p = 0; ++ } ++ ++ // Receive some data from the peer. Returns the number of bytes received. ++ template ++ size_t receive(base_implementation_type& impl, ++ const MutableBufferSequence& buffers, ++ socket_base::message_flags flags, boost::system::error_code& ec) ++ { ++ buffer_sequence_adapter bufs(buffers); ++ ++ return socket_ops::sync_recv(impl.socket_, impl.state_, ++ bufs.buffers(), bufs.count(), flags, bufs.all_empty(), ec); ++ } ++ ++ // Wait until data can be received without blocking. ++ size_t receive(base_implementation_type& impl, const null_buffers&, ++ socket_base::message_flags, boost::system::error_code& ec) ++ { ++ // Wait for socket to become ready. ++ socket_ops::poll_read(impl.socket_, impl.state_, -1, ec); ++ ++ return 0; ++ } ++ ++ // Start an asynchronous receive. The buffer for the data being received ++ // must be valid for the lifetime of the asynchronous operation. ++ template ++ void async_receive(base_implementation_type& impl, ++ const MutableBufferSequence& buffers, socket_base::message_flags flags, ++ Handler& handler, const IoExecutor& io_ex) ++ { ++ bool is_continuation = ++ boost_asio_handler_cont_helpers::is_continuation(handler); ++ ++ // Allocate and construct an operation to wrap the handler. ++ typedef reactive_socket_recv_op_ext< ++ MutableBufferSequence, Handler, IoExecutor> op; ++ typename op::ptr p = { boost::asio::detail::addressof(handler), ++ op::ptr::allocate(handler), 0 }; ++ p.p = new (p.v) op(success_ec_, impl.socket_, impl.state_, ++ buffers, flags, handler, io_ex); ++ ++ BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket", ++ &impl, impl.socket_, "async_receive")); ++ ++ start_op(impl, ++ (flags & socket_base::message_out_of_band) ++ ? reactor::except_op : reactor::read_op, ++ p.p, is_continuation, ++ (flags & socket_base::message_out_of_band) == 0, ++ ((impl.state_ & socket_ops::stream_oriented) ++ && buffer_sequence_adapter::all_empty(buffers))); ++ p.v = p.p = 0; ++ } ++ ++ // Wait until data can be received without blocking. ++ template ++ void async_receive(base_implementation_type& impl, ++ const null_buffers&, socket_base::message_flags flags, ++ Handler& handler, const IoExecutor& io_ex) ++ { ++ bool is_continuation = ++ boost_asio_handler_cont_helpers::is_continuation(handler); ++ ++ // Allocate and construct an operation to wrap the handler. ++ typedef reactive_null_buffers_op op; ++ typename op::ptr p = { boost::asio::detail::addressof(handler), ++ op::ptr::allocate(handler), 0 }; ++ p.p = new (p.v) op(success_ec_, handler, io_ex); ++ ++ BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket", ++ &impl, impl.socket_, "async_receive(null_buffers)")); ++ ++ start_op(impl, ++ (flags & socket_base::message_out_of_band) ++ ? reactor::except_op : reactor::read_op, ++ p.p, is_continuation, false, false); ++ p.v = p.p = 0; ++ } ++ ++ // Receive some data with associated flags. Returns the number of bytes ++ // received. ++ template ++ size_t receive_with_flags(base_implementation_type& impl, ++ const MutableBufferSequence& buffers, ++ socket_base::message_flags in_flags, ++ socket_base::message_flags& out_flags, boost::system::error_code& ec) ++ { ++ buffer_sequence_adapter bufs(buffers); ++ ++ return socket_ops::sync_recvmsg(impl.socket_, impl.state_, ++ bufs.buffers(), bufs.count(), in_flags, out_flags, ec); ++ } ++ ++ // Wait until data can be received without blocking. ++ size_t receive_with_flags(base_implementation_type& impl, ++ const null_buffers&, socket_base::message_flags, ++ socket_base::message_flags& out_flags, boost::system::error_code& ec) ++ { ++ // Wait for socket to become ready. ++ socket_ops::poll_read(impl.socket_, impl.state_, -1, ec); ++ ++ // Clear out_flags, since we cannot give it any other sensible value when ++ // performing a null_buffers operation. ++ out_flags = 0; ++ ++ return 0; ++ } ++ ++ // Start an asynchronous receive. The buffer for the data being received ++ // must be valid for the lifetime of the asynchronous operation. ++ template ++ void async_receive_with_flags(base_implementation_type& impl, ++ const MutableBufferSequence& buffers, socket_base::message_flags in_flags, ++ socket_base::message_flags& out_flags, Handler& handler, ++ const IoExecutor& io_ex) ++ { ++ bool is_continuation = ++ boost_asio_handler_cont_helpers::is_continuation(handler); ++ ++ // Allocate and construct an operation to wrap the handler. ++ typedef reactive_socket_recvmsg_op_ext< ++ MutableBufferSequence, Handler, IoExecutor> op; ++ typename op::ptr p = { boost::asio::detail::addressof(handler), ++ op::ptr::allocate(handler), 0 }; ++ p.p = new (p.v) op(success_ec_, impl.socket_, buffers, ++ in_flags, out_flags, handler, io_ex); ++ ++ BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket", ++ &impl, impl.socket_, "async_receive_with_flags")); ++ ++ start_op(impl, ++ (in_flags & socket_base::message_out_of_band) ++ ? reactor::except_op : reactor::read_op, ++ p.p, is_continuation, ++ (in_flags & socket_base::message_out_of_band) == 0, false); ++ p.v = p.p = 0; ++ } ++ ++ // Wait until data can be received without blocking. ++ template ++ void async_receive_with_flags(base_implementation_type& impl, ++ const null_buffers&, socket_base::message_flags in_flags, ++ socket_base::message_flags& out_flags, Handler& handler, ++ const IoExecutor& io_ex) ++ { ++ bool is_continuation = ++ boost_asio_handler_cont_helpers::is_continuation(handler); ++ ++ // Allocate and construct an operation to wrap the handler. ++ typedef reactive_null_buffers_op op; ++ typename op::ptr p = { boost::asio::detail::addressof(handler), ++ op::ptr::allocate(handler), 0 }; ++ p.p = new (p.v) op(success_ec_, handler, io_ex); ++ ++ BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket", ++ &impl, impl.socket_, "async_receive_with_flags(null_buffers)")); ++ ++ // Clear out_flags, since we cannot give it any other sensible value when ++ // performing a null_buffers operation. ++ out_flags = 0; ++ ++ start_op(impl, ++ (in_flags & socket_base::message_out_of_band) ++ ? reactor::except_op : reactor::read_op, ++ p.p, is_continuation, false, false); ++ p.v = p.p = 0; ++ } ++ ++protected: ++ // Open a new socket implementation. ++ BOOST_ASIO_DECL boost::system::error_code do_open( ++ base_implementation_type& impl, int af, ++ int type, int protocol, boost::system::error_code& ec); ++ ++ // Assign a native socket to a socket implementation. ++ BOOST_ASIO_DECL boost::system::error_code do_assign( ++ base_implementation_type& impl, int type, ++ const native_handle_type& native_socket, boost::system::error_code& ec); ++ ++ // Start the asynchronous read or write operation. ++ BOOST_ASIO_DECL void start_op(base_implementation_type& impl, int op_type, ++ reactor_op* op, bool is_continuation, bool is_non_blocking, bool noop); ++ ++ // Start the asynchronous accept operation. ++ BOOST_ASIO_DECL void start_accept_op(base_implementation_type& impl, ++ reactor_op* op, bool is_continuation, bool peer_is_open); ++ ++ // Start the asynchronous connect operation. ++ BOOST_ASIO_DECL void start_connect_op(base_implementation_type& impl, ++ reactor_op* op, bool is_continuation, ++ const socket_addr_type* addr, size_t addrlen); ++ ++ // The selector that performs event demultiplexing for the service. ++ reactor& reactor_; ++ ++ // Cached success value to avoid accessing category singleton. ++ const boost::system::error_code success_ec_; ++}; ++ ++} // namespace detail ++} // namespace asio ++} // namespace boost ++ ++#include ++ ++#if defined(BOOST_ASIO_HEADER_ONLY) ++# include ++#endif // defined(BOOST_ASIO_HEADER_ONLY) ++ ++#endif // !defined(BOOST_ASIO_HAS_IOCP) ++ // && !defined(BOOST_ASIO_WINDOWS_RUNTIME) ++ ++#endif // BOOST_ASIO_DETAIL_REACTIVE_SOCKET_SERVICE_BASE_EXT_HPP +diff --git a/implementation/helper/1.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 ++ ++#if !defined(BOOST_ASIO_HAS_IOCP) \ ++ && !defined(BOOST_ASIO_WINDOWS_RUNTIME) ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++namespace boost { ++namespace asio { ++namespace detail { ++ ++class reactive_socket_service_base_ext_local ++{ ++public: ++ // The native type of a socket. ++ typedef socket_type native_handle_type; ++ ++ // The implementation type of the socket. ++ struct base_implementation_type ++ { ++ // The native socket representation. ++ socket_type socket_; ++ ++ // The current state of the socket. ++ socket_ops::state_type state_; ++ ++ // Per-descriptor data used by the reactor. ++ reactor::per_descriptor_data reactor_data_; ++ }; ++ ++ // Constructor. ++ BOOST_ASIO_DECL reactive_socket_service_base_ext_local(execution_context& context); ++ ++ // Destroy all user-defined handler objects owned by the service. ++ BOOST_ASIO_DECL void base_shutdown(); ++ ++ // Construct a new socket implementation. ++ BOOST_ASIO_DECL void construct(base_implementation_type& impl); ++ ++ // Move-construct a new socket implementation. ++ BOOST_ASIO_DECL void base_move_construct(base_implementation_type& impl, ++ base_implementation_type& other_impl); ++ ++ // Move-assign from another socket implementation. ++ BOOST_ASIO_DECL void base_move_assign(base_implementation_type& impl, ++ reactive_socket_service_base_ext_local& other_service, ++ base_implementation_type& other_impl); ++ ++ // Destroy a socket implementation. ++ BOOST_ASIO_DECL void destroy(base_implementation_type& impl); ++ ++ // Determine whether the socket is open. ++ bool is_open(const base_implementation_type& impl) const ++ { ++ return impl.socket_ != invalid_socket; ++ } ++ ++ // Destroy a socket implementation. ++ BOOST_ASIO_DECL boost::system::error_code close( ++ base_implementation_type& impl, boost::system::error_code& ec); ++ ++ // Release ownership of the socket. ++ BOOST_ASIO_DECL socket_type release( ++ base_implementation_type& impl, boost::system::error_code& ec); ++ ++ // Get the native socket representation. ++ native_handle_type native_handle(base_implementation_type& impl) ++ { ++ return impl.socket_; ++ } ++ ++ // Cancel all operations associated with the socket. ++ BOOST_ASIO_DECL boost::system::error_code cancel( ++ base_implementation_type& impl, boost::system::error_code& ec); ++ ++ // Determine whether the socket is at the out-of-band data mark. ++ bool at_mark(const base_implementation_type& impl, ++ boost::system::error_code& ec) const ++ { ++ return socket_ops::sockatmark(impl.socket_, ec); ++ } ++ ++ // Determine the number of bytes available for reading. ++ std::size_t available(const base_implementation_type& impl, ++ boost::system::error_code& ec) const ++ { ++ return socket_ops::available(impl.socket_, ec); ++ } ++ ++ // Place the socket into the state where it will listen for new connections. ++ boost::system::error_code listen(base_implementation_type& impl, ++ int backlog, boost::system::error_code& ec) ++ { ++ socket_ops::listen(impl.socket_, backlog, ec); ++ return ec; ++ } ++ ++ // Perform an IO control command on the socket. ++ template ++ boost::system::error_code io_control(base_implementation_type& impl, ++ IO_Control_Command& command, boost::system::error_code& ec) ++ { ++ socket_ops::ioctl(impl.socket_, impl.state_, command.name(), ++ static_cast(command.data()), ec); ++ return ec; ++ } ++ ++ // Gets the non-blocking mode of the socket. ++ bool non_blocking(const base_implementation_type& impl) const ++ { ++ return (impl.state_ & socket_ops::user_set_non_blocking) != 0; ++ } ++ ++ // Sets the non-blocking mode of the socket. ++ boost::system::error_code non_blocking(base_implementation_type& impl, ++ bool mode, boost::system::error_code& ec) ++ { ++ socket_ops::set_user_non_blocking(impl.socket_, impl.state_, mode, ec); ++ return ec; ++ } ++ ++ // Gets the non-blocking mode of the native socket implementation. ++ bool native_non_blocking(const base_implementation_type& impl) const ++ { ++ return (impl.state_ & socket_ops::internal_non_blocking) != 0; ++ } ++ ++ // Sets the non-blocking mode of the native socket implementation. ++ boost::system::error_code native_non_blocking(base_implementation_type& impl, ++ bool mode, boost::system::error_code& ec) ++ { ++ socket_ops::set_internal_non_blocking(impl.socket_, impl.state_, mode, ec); ++ return ec; ++ } ++ ++ // Wait for the socket to become ready to read, ready to write, or to have ++ // pending error conditions. ++ boost::system::error_code wait(base_implementation_type& impl, ++ socket_base::wait_type w, boost::system::error_code& ec) ++ { ++ switch (w) ++ { ++ case socket_base::wait_read: ++ socket_ops::poll_read(impl.socket_, impl.state_, -1, ec); ++ break; ++ case socket_base::wait_write: ++ socket_ops::poll_write(impl.socket_, impl.state_, -1, ec); ++ break; ++ case socket_base::wait_error: ++ socket_ops::poll_error(impl.socket_, impl.state_, -1, ec); ++ break; ++ default: ++ ec = boost::asio::error::invalid_argument; ++ break; ++ } ++ ++ return ec; ++ } ++ ++ // Asynchronously wait for the socket to become ready to read, ready to ++ // write, or to have pending error conditions. ++ template ++ void async_wait(base_implementation_type& impl, ++ socket_base::wait_type w, Handler& handler, const IoExecutor& io_ex) ++ { ++ bool is_continuation = ++ boost_asio_handler_cont_helpers::is_continuation(handler); ++ ++ // Allocate and construct an operation to wrap the handler. ++ typedef reactive_wait_op op; ++ typename op::ptr p = { boost::asio::detail::addressof(handler), ++ op::ptr::allocate(handler), 0 }; ++ p.p = new (p.v) op(success_ec_, handler, io_ex); ++ ++ BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket", ++ &impl, impl.socket_, "async_wait")); ++ ++ int op_type; ++ switch (w) ++ { ++ case socket_base::wait_read: ++ op_type = reactor::read_op; ++ break; ++ case socket_base::wait_write: ++ op_type = reactor::write_op; ++ break; ++ case socket_base::wait_error: ++ op_type = reactor::except_op; ++ break; ++ default: ++ p.p->ec_ = boost::asio::error::invalid_argument; ++ reactor_.post_immediate_completion(p.p, is_continuation); ++ p.v = p.p = 0; ++ return; ++ } ++ ++ start_op(impl, op_type, p.p, is_continuation, false, false); ++ p.v = p.p = 0; ++ } ++ ++ // Send the given data to the peer. ++ template ++ size_t send(base_implementation_type& impl, ++ const ConstBufferSequence& buffers, ++ socket_base::message_flags flags, boost::system::error_code& ec) ++ { ++ buffer_sequence_adapter bufs(buffers); ++ ++ return socket_ops::sync_send(impl.socket_, impl.state_, ++ bufs.buffers(), bufs.count(), flags, bufs.all_empty(), ec); ++ } ++ ++ // Wait until data can be sent without blocking. ++ size_t send(base_implementation_type& impl, const null_buffers&, ++ socket_base::message_flags, boost::system::error_code& ec) ++ { ++ // Wait for socket to become ready. ++ socket_ops::poll_write(impl.socket_, impl.state_, -1, ec); ++ ++ return 0; ++ } ++ ++ // Start an asynchronous send. The data being sent must be valid for the ++ // lifetime of the asynchronous operation. ++ template ++ void async_send(base_implementation_type& impl, ++ const ConstBufferSequence& buffers, socket_base::message_flags flags, ++ Handler& handler, const IoExecutor& io_ex) ++ { ++ bool is_continuation = ++ boost_asio_handler_cont_helpers::is_continuation(handler); ++ ++ // Allocate and construct an operation to wrap the handler. ++ typedef reactive_socket_send_op< ++ ConstBufferSequence, Handler, IoExecutor> op; ++ typename op::ptr p = { boost::asio::detail::addressof(handler), ++ op::ptr::allocate(handler), 0 }; ++ p.p = new (p.v) op(success_ec_, impl.socket_, impl.state_, ++ buffers, flags, handler, io_ex); ++ ++ BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket", ++ &impl, impl.socket_, "async_send")); ++ ++ start_op(impl, reactor::write_op, p.p, is_continuation, true, ++ ((impl.state_ & socket_ops::stream_oriented) ++ && buffer_sequence_adapter::all_empty(buffers))); ++ p.v = p.p = 0; ++ } ++ ++ // Start an asynchronous wait until data can be sent without blocking. ++ template ++ void async_send(base_implementation_type& impl, const null_buffers&, ++ socket_base::message_flags, Handler& handler, const IoExecutor& io_ex) ++ { ++ bool is_continuation = ++ boost_asio_handler_cont_helpers::is_continuation(handler); ++ ++ // Allocate and construct an operation to wrap the handler. ++ typedef reactive_null_buffers_op op; ++ typename op::ptr p = { boost::asio::detail::addressof(handler), ++ op::ptr::allocate(handler), 0 }; ++ p.p = new (p.v) op(success_ec_, handler, io_ex); ++ ++ BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket", ++ &impl, impl.socket_, "async_send(null_buffers)")); ++ ++ start_op(impl, reactor::write_op, p.p, is_continuation, false, false); ++ p.v = p.p = 0; ++ } ++ ++ // Receive some data from the peer. Returns the number of bytes received. ++ template ++ size_t receive(base_implementation_type& impl, ++ const MutableBufferSequence& buffers, ++ socket_base::message_flags flags, boost::system::error_code& ec) ++ { ++ buffer_sequence_adapter bufs(buffers); ++ ++ return socket_ops::sync_recv(impl.socket_, impl.state_, ++ bufs.buffers(), bufs.count(), flags, bufs.all_empty(), ec); ++ } ++ ++ // Wait until data can be received without blocking. ++ size_t receive(base_implementation_type& impl, const null_buffers&, ++ socket_base::message_flags, boost::system::error_code& ec) ++ { ++ // Wait for socket to become ready. ++ socket_ops::poll_read(impl.socket_, impl.state_, -1, ec); ++ ++ return 0; ++ } ++ ++ // Start an asynchronous receive. The buffer for the data being received ++ // must be valid for the lifetime of the asynchronous operation. ++ template ++ void async_receive(base_implementation_type& impl, ++ const MutableBufferSequence& buffers, socket_base::message_flags flags, ++ Handler& handler, const IoExecutor& io_ex) ++ { ++ bool is_continuation = ++ boost_asio_handler_cont_helpers::is_continuation(handler); ++ ++ // Allocate and construct an operation to wrap the handler. ++ typedef reactive_socket_recv_op_ext_local< ++ MutableBufferSequence, Handler, IoExecutor> op; ++ typename op::ptr p = { boost::asio::detail::addressof(handler), ++ op::ptr::allocate(handler), 0 }; ++ p.p = new (p.v) op(success_ec_, impl.socket_, impl.state_, ++ buffers, flags, handler, io_ex); ++ ++ BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket", ++ &impl, impl.socket_, "async_receive")); ++ ++ start_op(impl, ++ (flags & socket_base::message_out_of_band) ++ ? reactor::except_op : reactor::read_op, ++ p.p, is_continuation, ++ (flags & socket_base::message_out_of_band) == 0, ++ ((impl.state_ & socket_ops::stream_oriented) ++ && buffer_sequence_adapter::all_empty(buffers))); ++ p.v = p.p = 0; ++ } ++ ++ // Wait until data can be received without blocking. ++ template ++ void async_receive(base_implementation_type& impl, ++ const null_buffers&, socket_base::message_flags flags, ++ Handler& handler, const IoExecutor& io_ex) ++ { ++ bool is_continuation = ++ boost_asio_handler_cont_helpers::is_continuation(handler); ++ ++ // Allocate and construct an operation to wrap the handler. ++ typedef reactive_null_buffers_op op; ++ typename op::ptr p = { boost::asio::detail::addressof(handler), ++ op::ptr::allocate(handler), 0 }; ++ p.p = new (p.v) op(success_ec_, handler, io_ex); ++ ++ BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket", ++ &impl, impl.socket_, "async_receive(null_buffers)")); ++ ++ start_op(impl, ++ (flags & socket_base::message_out_of_band) ++ ? reactor::except_op : reactor::read_op, ++ p.p, is_continuation, false, false); ++ p.v = p.p = 0; ++ } ++ ++ // Receive some data with associated flags. Returns the number of bytes ++ // received. ++ template ++ size_t receive_with_flags(base_implementation_type& impl, ++ const MutableBufferSequence& buffers, ++ socket_base::message_flags in_flags, ++ socket_base::message_flags& out_flags, boost::system::error_code& ec) ++ { ++ buffer_sequence_adapter bufs(buffers); ++ ++ return socket_ops::sync_recvmsg(impl.socket_, impl.state_, ++ bufs.buffers(), bufs.count(), in_flags, out_flags, ec); ++ } ++ ++ // Wait until data can be received without blocking. ++ size_t receive_with_flags(base_implementation_type& impl, ++ const null_buffers&, socket_base::message_flags, ++ socket_base::message_flags& out_flags, boost::system::error_code& ec) ++ { ++ // Wait for socket to become ready. ++ socket_ops::poll_read(impl.socket_, impl.state_, -1, ec); ++ ++ // Clear out_flags, since we cannot give it any other sensible value when ++ // performing a null_buffers operation. ++ out_flags = 0; ++ ++ return 0; ++ } ++ ++ // Start an asynchronous receive. The buffer for the data being received ++ // must be valid for the lifetime of the asynchronous operation. ++ template ++ void async_receive_with_flags(base_implementation_type& impl, ++ const MutableBufferSequence& buffers, socket_base::message_flags in_flags, ++ socket_base::message_flags& out_flags, Handler& handler, ++ const IoExecutor& io_ex) ++ { ++ bool is_continuation = ++ boost_asio_handler_cont_helpers::is_continuation(handler); ++ ++ // Allocate and construct an operation to wrap the handler. ++ typedef reactive_socket_recvmsg_op_ext_local< ++ MutableBufferSequence, Handler, IoExecutor> op; ++ typename op::ptr p = { boost::asio::detail::addressof(handler), ++ op::ptr::allocate(handler), 0 }; ++ p.p = new (p.v) op(success_ec_, impl.socket_, buffers, ++ in_flags, out_flags, handler, io_ex); ++ ++ BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket", ++ &impl, impl.socket_, "async_receive_with_flags")); ++ ++ start_op(impl, ++ (in_flags & socket_base::message_out_of_band) ++ ? reactor::except_op : reactor::read_op, ++ p.p, is_continuation, ++ (in_flags & socket_base::message_out_of_band) == 0, false); ++ p.v = p.p = 0; ++ } ++ ++ // Wait until data can be received without blocking. ++ template ++ void async_receive_with_flags(base_implementation_type& impl, ++ const null_buffers&, socket_base::message_flags in_flags, ++ socket_base::message_flags& out_flags, Handler& handler, ++ const IoExecutor& io_ex) ++ { ++ bool is_continuation = ++ boost_asio_handler_cont_helpers::is_continuation(handler); ++ ++ // Allocate and construct an operation to wrap the handler. ++ typedef reactive_null_buffers_op op; ++ typename op::ptr p = { boost::asio::detail::addressof(handler), ++ op::ptr::allocate(handler), 0 }; ++ p.p = new (p.v) op(success_ec_, handler, io_ex); ++ ++ BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket", ++ &impl, impl.socket_, "async_receive_with_flags(null_buffers)")); ++ ++ // Clear out_flags, since we cannot give it any other sensible value when ++ // performing a null_buffers operation. ++ out_flags = 0; ++ ++ start_op(impl, ++ (in_flags & socket_base::message_out_of_band) ++ ? reactor::except_op : reactor::read_op, ++ p.p, is_continuation, false, false); ++ p.v = p.p = 0; ++ } ++ ++protected: ++ // Open a new socket implementation. ++ BOOST_ASIO_DECL boost::system::error_code do_open( ++ base_implementation_type& impl, int af, ++ int type, int protocol, boost::system::error_code& ec); ++ ++ // Assign a native socket to a socket implementation. ++ BOOST_ASIO_DECL boost::system::error_code do_assign( ++ base_implementation_type& impl, int type, ++ const native_handle_type& native_socket, boost::system::error_code& ec); ++ ++ // Start the asynchronous read or write operation. ++ BOOST_ASIO_DECL void start_op(base_implementation_type& impl, int op_type, ++ reactor_op* op, bool is_continuation, bool is_non_blocking, bool noop); ++ ++ // Start the asynchronous accept operation. ++ BOOST_ASIO_DECL void start_accept_op(base_implementation_type& impl, ++ reactor_op* op, bool is_continuation, bool peer_is_open); ++ ++ // Start the asynchronous connect operation. ++ BOOST_ASIO_DECL void start_connect_op(base_implementation_type& impl, ++ reactor_op* op, bool is_continuation, ++ const socket_addr_type* addr, size_t addrlen); ++ ++ // The selector that performs event demultiplexing for the service. ++ reactor& reactor_; ++ ++ // Cached success value to avoid accessing category singleton. ++ const boost::system::error_code success_ec_; ++}; ++ ++} // namespace detail ++} // namespace asio ++} // namespace boost ++ ++#include ++ ++#if defined(BOOST_ASIO_HEADER_ONLY) ++# include ++#endif // defined(BOOST_ASIO_HEADER_ONLY) ++ ++#endif // !defined(BOOST_ASIO_HAS_IOCP) ++ // && !defined(BOOST_ASIO_WINDOWS_RUNTIME) ++ ++#endif // BOOST_ASIO_DETAIL_REACTIVE_SOCKET_SERVICE_BASE_EXT_LOCAL_HPP +diff --git a/implementation/helper/1.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 ++ ++#if !defined(BOOST_ASIO_HAS_IOCP) ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++namespace boost { ++namespace asio { ++namespace detail { ++ ++template ++class reactive_socket_service_ext : ++ public execution_context_service_base >, ++ public reactive_socket_service_base_ext ++{ ++public: ++ // The protocol type. ++ typedef Protocol protocol_type; ++ ++ // The endpoint type. ++ typedef typename Protocol::endpoint endpoint_type; ++ ++ // The native type of a socket. ++ typedef socket_type native_handle_type; ++ ++ // The implementation type of the socket. ++ struct implementation_type : ++ reactive_socket_service_base_ext::base_implementation_type ++ { ++ // Default constructor. ++ implementation_type() ++ : protocol_(endpoint_type().protocol()) ++ { ++ } ++ ++ // The protocol associated with the socket. ++ protocol_type protocol_; ++ }; ++ ++ // Constructor. ++ reactive_socket_service_ext(execution_context& context) ++ : execution_context_service_base< ++ reactive_socket_service_ext >(context), ++ reactive_socket_service_base_ext(context) ++ { ++ } ++ ++ // Destroy all user-defined handler objects owned by the service. ++ void shutdown() ++ { ++ this->base_shutdown(); ++ } ++ ++ // Move-construct a new socket implementation. ++ void move_construct(implementation_type& impl, ++ implementation_type& other_impl) ++ { ++ this->base_move_construct(impl, other_impl); ++ ++ impl.protocol_ = other_impl.protocol_; ++ other_impl.protocol_ = endpoint_type().protocol(); ++ } ++ ++ // Move-assign from another socket implementation. ++ void move_assign(implementation_type& impl, ++ reactive_socket_service_base_ext& other_service, ++ implementation_type& other_impl) ++ { ++ this->base_move_assign(impl, other_service, other_impl); ++ ++ impl.protocol_ = other_impl.protocol_; ++ other_impl.protocol_ = endpoint_type().protocol(); ++ } ++ ++ // Move-construct a new socket implementation from another protocol type. ++ template ++ void converting_move_construct(implementation_type& impl, ++ reactive_socket_service_ext&, ++ typename reactive_socket_service_ext< ++ Protocol1>::implementation_type& other_impl) ++ { ++ this->base_move_construct(impl, other_impl); ++ ++ impl.protocol_ = protocol_type(other_impl.protocol_); ++ other_impl.protocol_ = typename Protocol1::endpoint().protocol(); ++ } ++ ++ // Open a new socket implementation. ++ boost::system::error_code open(implementation_type& impl, ++ const protocol_type& protocol, boost::system::error_code& ec) ++ { ++ if (!do_open(impl, protocol.family(), ++ protocol.type(), protocol.protocol(), ec)) ++ impl.protocol_ = protocol; ++ return ec; ++ } ++ ++ // Assign a native socket to a socket implementation. ++ boost::system::error_code assign(implementation_type& impl, ++ const protocol_type& protocol, const native_handle_type& native_socket, ++ boost::system::error_code& ec) ++ { ++ if (!do_assign(impl, protocol.type(), native_socket, ec)) ++ impl.protocol_ = protocol; ++ return ec; ++ } ++ ++ // Get the native socket representation. ++ native_handle_type native_handle(implementation_type& impl) ++ { ++ return impl.socket_; ++ } ++ ++ // Bind the socket to the specified local endpoint. ++ boost::system::error_code bind(implementation_type& impl, ++ const endpoint_type& endpoint, boost::system::error_code& ec) ++ { ++ socket_ops::bind(impl.socket_, endpoint.data(), endpoint.size(), ec); ++ return ec; ++ } ++ ++ // Set a socket option. ++ template ++ boost::system::error_code set_option(implementation_type& impl, ++ const Option& option, boost::system::error_code& ec) ++ { ++ socket_ops::setsockopt(impl.socket_, impl.state_, ++ option.level(impl.protocol_), option.name(impl.protocol_), ++ option.data(impl.protocol_), option.size(impl.protocol_), ec); ++ return ec; ++ } ++ ++ // Set a socket option. ++ template ++ boost::system::error_code get_option(const implementation_type& impl, ++ Option& option, boost::system::error_code& ec) const ++ { ++ std::size_t size = option.size(impl.protocol_); ++ socket_ops::getsockopt(impl.socket_, impl.state_, ++ option.level(impl.protocol_), option.name(impl.protocol_), ++ option.data(impl.protocol_), &size, ec); ++ if (!ec) ++ option.resize(impl.protocol_, size); ++ return ec; ++ } ++ ++ // Get the local endpoint. ++ endpoint_type local_endpoint(const implementation_type& impl, ++ boost::system::error_code& ec) const ++ { ++ endpoint_type endpoint; ++ std::size_t addr_len = endpoint.capacity(); ++ if (socket_ops::getsockname(impl.socket_, endpoint.data(), &addr_len, ec)) ++ return endpoint_type(); ++ endpoint.resize(addr_len); ++ return endpoint; ++ } ++ ++ // Get the remote endpoint. ++ endpoint_type remote_endpoint(const implementation_type& impl, ++ boost::system::error_code& ec) const ++ { ++ endpoint_type endpoint; ++ std::size_t addr_len = endpoint.capacity(); ++ if (socket_ops::getpeername(impl.socket_, ++ endpoint.data(), &addr_len, false, ec)) ++ return endpoint_type(); ++ endpoint.resize(addr_len); ++ return endpoint; ++ } ++ ++ // Disable sends or receives on the socket. ++ boost::system::error_code shutdown(base_implementation_type& impl, ++ socket_base::shutdown_type what, boost::system::error_code& ec) ++ { ++ socket_ops::shutdown(impl.socket_, what, ec); ++ return ec; ++ } ++ ++ // Send a datagram to the specified endpoint. Returns the number of bytes ++ // sent. ++ template ++ size_t send_to(implementation_type& impl, const ConstBufferSequence& buffers, ++ const endpoint_type& destination, socket_base::message_flags flags, ++ boost::system::error_code& ec) ++ { ++ buffer_sequence_adapter bufs(buffers); ++ ++ return socket_ops::sync_sendto(impl.socket_, impl.state_, ++ bufs.buffers(), bufs.count(), flags, ++ destination.data(), destination.size(), ec); ++ } ++ ++ // Wait until data can be sent without blocking. ++ size_t send_to(implementation_type& impl, const null_buffers&, ++ const endpoint_type&, socket_base::message_flags, ++ boost::system::error_code& ec) ++ { ++ // Wait for socket to become ready. ++ socket_ops::poll_write(impl.socket_, impl.state_, -1, ec); ++ ++ return 0; ++ } ++ ++ // Start an asynchronous send. The data being sent must be valid for the ++ // lifetime of the asynchronous operation. ++ template ++ void async_send_to(implementation_type& impl, ++ const ConstBufferSequence& buffers, ++ const endpoint_type& destination, socket_base::message_flags flags, ++ Handler& handler, const IoExecutor& io_ex) ++ { ++ bool is_continuation = ++ boost_asio_handler_cont_helpers::is_continuation(handler); ++ ++ // Allocate and construct an operation to wrap the handler. ++ typedef reactive_socket_sendto_op op; ++ typename op::ptr p = { boost::asio::detail::addressof(handler), ++ op::ptr::allocate(handler), 0 }; ++ p.p = new (p.v) op(success_ec_, impl.socket_, buffers, ++ destination, flags, handler, io_ex); ++ ++ BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket", ++ &impl, impl.socket_, "async_send_to")); ++ ++ start_op(impl, reactor::write_op, p.p, is_continuation, true, false); ++ p.v = p.p = 0; ++ } ++ ++ // Start an asynchronous wait until data can be sent without blocking. ++ template ++ void async_send_to(implementation_type& impl, const null_buffers&, ++ const endpoint_type&, socket_base::message_flags, ++ Handler& handler, const IoExecutor& io_ex) ++ { ++ bool is_continuation = ++ boost_asio_handler_cont_helpers::is_continuation(handler); ++ ++ // Allocate and construct an operation to wrap the handler. ++ typedef reactive_null_buffers_op op; ++ typename op::ptr p = { boost::asio::detail::addressof(handler), ++ op::ptr::allocate(handler), 0 }; ++ p.p = new (p.v) op(success_ec_, handler, io_ex); ++ ++ BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket", ++ &impl, impl.socket_, "async_send_to(null_buffers)")); ++ ++ start_op(impl, reactor::write_op, p.p, is_continuation, false, false); ++ p.v = p.p = 0; ++ } ++ ++ // Receive a datagram with the endpoint of the sender. Returns the number of ++ // bytes received. ++ template ++ size_t receive_from(implementation_type& impl, ++ const MutableBufferSequence& buffers, ++ endpoint_type& sender_endpoint, socket_base::message_flags flags, ++ boost::system::error_code& ec) ++ { ++ buffer_sequence_adapter bufs(buffers); ++ ++ std::size_t addr_len = sender_endpoint.capacity(); ++ std::size_t bytes_recvd = socket_ops::sync_recvfrom( ++ impl.socket_, impl.state_, bufs.buffers(), bufs.count(), ++ flags, sender_endpoint.data(), &addr_len, ec); ++ ++ if (!ec) ++ sender_endpoint.resize(addr_len); ++ ++ return bytes_recvd; ++ } ++ ++ // Wait until data can be received without blocking. ++ size_t receive_from(implementation_type& impl, const null_buffers&, ++ endpoint_type& sender_endpoint, socket_base::message_flags, ++ boost::system::error_code& ec) ++ { ++ // Wait for socket to become ready. ++ socket_ops::poll_read(impl.socket_, impl.state_, -1, ec); ++ ++ // Reset endpoint since it can be given no sensible value at this time. ++ sender_endpoint = endpoint_type(); ++ ++ return 0; ++ } ++ ++ // Start an asynchronous receive. The buffer for the data being received and ++ // the sender_endpoint object must both be valid for the lifetime of the ++ // asynchronous operation. ++ template ++ void async_receive_from(implementation_type& impl, ++ const MutableBufferSequence& buffers, endpoint_type& sender_endpoint, ++ socket_base::message_flags flags, Handler& handler, ++ const IoExecutor& io_ex) ++ { ++ bool is_continuation = ++ boost_asio_handler_cont_helpers::is_continuation(handler); ++ ++ // Allocate and construct an operation to wrap the handler. ++ typedef reactive_socket_recvfrom_op_ext op; ++ typename op::ptr p = { boost::asio::detail::addressof(handler), ++ op::ptr::allocate(handler), 0 }; ++ int protocol = impl.protocol_.type(); ++ p.p = new (p.v) op(success_ec_, impl.socket_, protocol, buffers, ++ sender_endpoint, flags, handler, io_ex); ++ ++ BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket", ++ &impl, impl.socket_, "async_receive_from")); ++ ++ start_op(impl, ++ (flags & socket_base::message_out_of_band) ++ ? reactor::except_op : reactor::read_op, ++ p.p, is_continuation, true, false); ++ p.v = p.p = 0; ++ } ++ ++ // Wait until data can be received without blocking. ++ template ++ void async_receive_from(implementation_type& impl, const null_buffers&, ++ endpoint_type& sender_endpoint, socket_base::message_flags flags, ++ Handler& handler, const IoExecutor& io_ex) ++ { ++ bool is_continuation = ++ boost_asio_handler_cont_helpers::is_continuation(handler); ++ ++ // Allocate and construct an operation to wrap the handler. ++ typedef reactive_null_buffers_op op; ++ typename op::ptr p = { boost::asio::detail::addressof(handler), ++ op::ptr::allocate(handler), 0 }; ++ p.p = new (p.v) op(success_ec_, handler, io_ex); ++ ++ BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket", ++ &impl, impl.socket_, "async_receive_from(null_buffers)")); ++ ++ // Reset endpoint since it can be given no sensible value at this time. ++ sender_endpoint = endpoint_type(); ++ ++ start_op(impl, ++ (flags & socket_base::message_out_of_band) ++ ? reactor::except_op : reactor::read_op, ++ p.p, is_continuation, false, false); ++ p.v = p.p = 0; ++ } ++ ++ // Accept a new connection. ++ template ++ boost::system::error_code accept(implementation_type& impl, ++ Socket& peer, endpoint_type* peer_endpoint, boost::system::error_code& ec) ++ { ++ // We cannot accept a socket that is already open. ++ if (peer.is_open()) ++ { ++ ec = boost::asio::error::already_open; ++ return ec; ++ } ++ ++ std::size_t addr_len = peer_endpoint ? peer_endpoint->capacity() : 0; ++ socket_holder new_socket(socket_ops::sync_accept(impl.socket_, ++ impl.state_, peer_endpoint ? peer_endpoint->data() : 0, ++ peer_endpoint ? &addr_len : 0, ec)); ++ ++ // On success, assign new connection to peer socket object. ++ if (new_socket.get() != invalid_socket) ++ { ++ if (peer_endpoint) ++ peer_endpoint->resize(addr_len); ++ peer.assign(impl.protocol_, new_socket.get(), ec); ++ if (!ec) ++ new_socket.release(); ++ } ++ ++ return ec; ++ } ++ ++ // Start an asynchronous accept. The peer and peer_endpoint objects must be ++ // valid until the accept's handler is invoked. ++ template ++ void async_accept(implementation_type& impl, Socket& peer, ++ endpoint_type* peer_endpoint, Handler& handler, const IoExecutor& io_ex) ++ { ++ bool is_continuation = ++ boost_asio_handler_cont_helpers::is_continuation(handler); ++ ++ // Allocate and construct an operation to wrap the handler. ++ typedef reactive_socket_accept_op op; ++ typename op::ptr p = { boost::asio::detail::addressof(handler), ++ op::ptr::allocate(handler), 0 }; ++ p.p = new (p.v) op(success_ec_, impl.socket_, impl.state_, peer, ++ impl.protocol_, peer_endpoint, handler, io_ex); ++ ++ BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket", ++ &impl, impl.socket_, "async_accept")); ++ ++ start_accept_op(impl, p.p, is_continuation, peer.is_open()); ++ p.v = p.p = 0; ++ } ++ ++#if defined(BOOST_ASIO_HAS_MOVE) ++ // Start an asynchronous accept. The peer_endpoint object must be valid until ++ // the accept's handler is invoked. ++ template ++ void async_move_accept(implementation_type& impl, ++ const PeerIoExecutor& peer_io_ex, endpoint_type* peer_endpoint, ++ Handler& handler, const IoExecutor& io_ex) ++ { ++ bool is_continuation = ++ boost_asio_handler_cont_helpers::is_continuation(handler); ++ ++ // Allocate and construct an operation to wrap the handler. ++ typedef reactive_socket_move_accept_op op; ++ typename op::ptr p = { boost::asio::detail::addressof(handler), ++ op::ptr::allocate(handler), 0 }; ++ p.p = new (p.v) op(success_ec_, peer_io_ex, impl.socket_, impl.state_, ++ impl.protocol_, peer_endpoint, handler, io_ex); ++ ++ BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket", ++ &impl, impl.socket_, "async_accept")); ++ ++ start_accept_op(impl, p.p, is_continuation, false); ++ p.v = p.p = 0; ++ } ++#endif // defined(BOOST_ASIO_HAS_MOVE) ++ ++ // Connect the socket to the specified endpoint. ++ boost::system::error_code connect(implementation_type& impl, ++ const endpoint_type& peer_endpoint, boost::system::error_code& ec) ++ { ++ socket_ops::sync_connect(impl.socket_, ++ peer_endpoint.data(), peer_endpoint.size(), ec); ++ return ec; ++ } ++ ++ // Start an asynchronous connect. ++ template ++ void async_connect(implementation_type& impl, ++ const endpoint_type& peer_endpoint, ++ Handler& handler, const IoExecutor& io_ex) ++ { ++ bool is_continuation = ++ boost_asio_handler_cont_helpers::is_continuation(handler); ++ ++ // Allocate and construct an operation to wrap the handler. ++ typedef reactive_socket_connect_op op; ++ typename op::ptr p = { boost::asio::detail::addressof(handler), ++ op::ptr::allocate(handler), 0 }; ++ p.p = new (p.v) op(success_ec_, impl.socket_, handler, io_ex); ++ ++ BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket", ++ &impl, impl.socket_, "async_connect")); ++ ++ start_connect_op(impl, p.p, is_continuation, ++ peer_endpoint.data(), peer_endpoint.size()); ++ p.v = p.p = 0; ++ } ++}; ++ ++} // namespace detail ++} // namespace asio ++} // namespace boost ++ ++#include ++ ++#endif // !defined(BOOST_ASIO_HAS_IOCP) ++ ++#endif // BOOST_ASIO_DETAIL_REACTIVE_SOCKET_SERVICE_EXT_HPP +diff --git a/implementation/helper/1.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 ++ ++#if !defined(BOOST_ASIO_HAS_IOCP) ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++namespace boost { ++namespace asio { ++namespace detail { ++ ++template ++class reactive_socket_service_ext_local : ++ public execution_context_service_base >, ++ public reactive_socket_service_base_ext_local ++{ ++public: ++ // The protocol type. ++ typedef Protocol protocol_type; ++ ++ // The endpoint type. ++ typedef typename Protocol::endpoint endpoint_type; ++ ++ // The native type of a socket. ++ typedef socket_type native_handle_type; ++ ++ // The implementation type of the socket. ++ struct implementation_type : ++ reactive_socket_service_base_ext_local::base_implementation_type ++ { ++ // Default constructor. ++ implementation_type() ++ : protocol_(endpoint_type().protocol()) ++ { ++ } ++ ++ // The protocol associated with the socket. ++ protocol_type protocol_; ++ }; ++ ++ // Constructor. ++ reactive_socket_service_ext_local(execution_context& context) ++ : execution_context_service_base< ++ reactive_socket_service_ext_local >(context), ++ reactive_socket_service_base_ext_local(context) ++ { ++ } ++ ++ // Destroy all user-defined handler objects owned by the service. ++ void shutdown() ++ { ++ this->base_shutdown(); ++ } ++ ++ // Move-construct a new socket implementation. ++ void move_construct(implementation_type& impl, ++ implementation_type& other_impl) ++ { ++ this->base_move_construct(impl, other_impl); ++ ++ impl.protocol_ = other_impl.protocol_; ++ other_impl.protocol_ = endpoint_type().protocol(); ++ } ++ ++ // Move-assign from another socket implementation. ++ void move_assign(implementation_type& impl, ++ reactive_socket_service_base_ext_local& other_service, ++ implementation_type& other_impl) ++ { ++ this->base_move_assign(impl, other_service, other_impl); ++ ++ impl.protocol_ = other_impl.protocol_; ++ other_impl.protocol_ = endpoint_type().protocol(); ++ } ++ ++ // Move-construct a new socket implementation from another protocol type. ++ template ++ void converting_move_construct(implementation_type& impl, ++ reactive_socket_service_ext_local&, ++ typename reactive_socket_service_ext_local< ++ Protocol1>::implementation_type& other_impl) ++ { ++ this->base_move_construct(impl, other_impl); ++ ++ impl.protocol_ = protocol_type(other_impl.protocol_); ++ other_impl.protocol_ = typename Protocol1::endpoint().protocol(); ++ } ++ ++ // Open a new socket implementation. ++ boost::system::error_code open(implementation_type& impl, ++ const protocol_type& protocol, boost::system::error_code& ec) ++ { ++ if (!do_open(impl, protocol.family(), ++ protocol.type(), protocol.protocol(), ec)) ++ impl.protocol_ = protocol; ++ return ec; ++ } ++ ++ // Assign a native socket to a socket implementation. ++ boost::system::error_code assign(implementation_type& impl, ++ const protocol_type& protocol, const native_handle_type& native_socket, ++ boost::system::error_code& ec) ++ { ++ if (!do_assign(impl, protocol.type(), native_socket, ec)) ++ impl.protocol_ = protocol; ++ return ec; ++ } ++ ++ // Get the native socket representation. ++ native_handle_type native_handle(implementation_type& impl) ++ { ++ return impl.socket_; ++ } ++ ++ // Bind the socket to the specified local endpoint. ++ boost::system::error_code bind(implementation_type& impl, ++ const endpoint_type& endpoint, boost::system::error_code& ec) ++ { ++ socket_ops::bind(impl.socket_, endpoint.data(), endpoint.size(), ec); ++ return ec; ++ } ++ ++ // Set a socket option. ++ template ++ boost::system::error_code set_option(implementation_type& impl, ++ const Option& option, boost::system::error_code& ec) ++ { ++ socket_ops::setsockopt(impl.socket_, impl.state_, ++ option.level(impl.protocol_), option.name(impl.protocol_), ++ option.data(impl.protocol_), option.size(impl.protocol_), ec); ++ return ec; ++ } ++ ++ // Set a socket option. ++ template ++ boost::system::error_code get_option(const implementation_type& impl, ++ Option& option, boost::system::error_code& ec) const ++ { ++ std::size_t size = option.size(impl.protocol_); ++ socket_ops::getsockopt(impl.socket_, impl.state_, ++ option.level(impl.protocol_), option.name(impl.protocol_), ++ option.data(impl.protocol_), &size, ec); ++ if (!ec) ++ option.resize(impl.protocol_, size); ++ return ec; ++ } ++ ++ // Get the local endpoint. ++ endpoint_type local_endpoint(const implementation_type& impl, ++ boost::system::error_code& ec) const ++ { ++ endpoint_type endpoint; ++ std::size_t addr_len = endpoint.capacity(); ++ if (socket_ops::getsockname(impl.socket_, endpoint.data(), &addr_len, ec)) ++ return endpoint_type(); ++ endpoint.resize(addr_len); ++ return endpoint; ++ } ++ ++ // Get the remote endpoint. ++ endpoint_type remote_endpoint(const implementation_type& impl, ++ boost::system::error_code& ec) const ++ { ++ endpoint_type endpoint; ++ std::size_t addr_len = endpoint.capacity(); ++ if (socket_ops::getpeername(impl.socket_, ++ endpoint.data(), &addr_len, false, ec)) ++ return endpoint_type(); ++ endpoint.resize(addr_len); ++ return endpoint; ++ } ++ ++ // Disable sends or receives on the socket. ++ boost::system::error_code shutdown(base_implementation_type& impl, ++ socket_base::shutdown_type what, boost::system::error_code& ec) ++ { ++ socket_ops::shutdown(impl.socket_, what, ec); ++ return ec; ++ } ++ ++ // Send a datagram to the specified endpoint. Returns the number of bytes ++ // sent. ++ template ++ size_t send_to(implementation_type& impl, const ConstBufferSequence& buffers, ++ const endpoint_type& destination, socket_base::message_flags flags, ++ boost::system::error_code& ec) ++ { ++ buffer_sequence_adapter bufs(buffers); ++ ++ return socket_ops::sync_sendto(impl.socket_, impl.state_, ++ bufs.buffers(), bufs.count(), flags, ++ destination.data(), destination.size(), ec); ++ } ++ ++ // Wait until data can be sent without blocking. ++ size_t send_to(implementation_type& impl, const null_buffers&, ++ const endpoint_type&, socket_base::message_flags, ++ boost::system::error_code& ec) ++ { ++ // Wait for socket to become ready. ++ socket_ops::poll_write(impl.socket_, impl.state_, -1, ec); ++ ++ return 0; ++ } ++ ++ // Start an asynchronous send. The data being sent must be valid for the ++ // lifetime of the asynchronous operation. ++ template ++ void async_send_to(implementation_type& impl, ++ const ConstBufferSequence& buffers, ++ const endpoint_type& destination, socket_base::message_flags flags, ++ Handler& handler, const IoExecutor& io_ex) ++ { ++ bool is_continuation = ++ boost_asio_handler_cont_helpers::is_continuation(handler); ++ ++ // Allocate and construct an operation to wrap the handler. ++ typedef reactive_socket_sendto_op op; ++ typename op::ptr p = { boost::asio::detail::addressof(handler), ++ op::ptr::allocate(handler), 0 }; ++ p.p = new (p.v) op(success_ec_, impl.socket_, buffers, ++ destination, flags, handler, io_ex); ++ ++ BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket", ++ &impl, impl.socket_, "async_send_to")); ++ ++ start_op(impl, reactor::write_op, p.p, is_continuation, true, false); ++ p.v = p.p = 0; ++ } ++ ++ // Start an asynchronous wait until data can be sent without blocking. ++ template ++ void async_send_to(implementation_type& impl, const null_buffers&, ++ const endpoint_type&, socket_base::message_flags, ++ Handler& handler, const IoExecutor& io_ex) ++ { ++ bool is_continuation = ++ boost_asio_handler_cont_helpers::is_continuation(handler); ++ ++ // Allocate and construct an operation to wrap the handler. ++ typedef reactive_null_buffers_op op; ++ typename op::ptr p = { boost::asio::detail::addressof(handler), ++ op::ptr::allocate(handler), 0 }; ++ p.p = new (p.v) op(success_ec_, handler, io_ex); ++ ++ BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket", ++ &impl, impl.socket_, "async_send_to(null_buffers)")); ++ ++ start_op(impl, reactor::write_op, p.p, is_continuation, false, false); ++ p.v = p.p = 0; ++ } ++ ++ // Receive a datagram with the endpoint of the sender. Returns the number of ++ // bytes received. ++ template ++ size_t receive_from(implementation_type& impl, ++ const MutableBufferSequence& buffers, ++ endpoint_type& sender_endpoint, socket_base::message_flags flags, ++ boost::system::error_code& ec) ++ { ++ buffer_sequence_adapter bufs(buffers); ++ ++ std::size_t addr_len = sender_endpoint.capacity(); ++ std::size_t bytes_recvd = socket_ops::sync_recvfrom( ++ impl.socket_, impl.state_, bufs.buffers(), bufs.count(), ++ flags, sender_endpoint.data(), &addr_len, ec); ++ ++ if (!ec) ++ sender_endpoint.resize(addr_len); ++ ++ return bytes_recvd; ++ } ++ ++ // Wait until data can be received without blocking. ++ size_t receive_from(implementation_type& impl, const null_buffers&, ++ endpoint_type& sender_endpoint, socket_base::message_flags, ++ boost::system::error_code& ec) ++ { ++ // Wait for socket to become ready. ++ socket_ops::poll_read(impl.socket_, impl.state_, -1, ec); ++ ++ // Reset endpoint since it can be given no sensible value at this time. ++ sender_endpoint = endpoint_type(); ++ ++ return 0; ++ } ++ ++ // Start an asynchronous receive. The buffer for the data being received and ++ // the sender_endpoint object must both be valid for the lifetime of the ++ // asynchronous operation. ++ template ++ void async_receive_from(implementation_type& impl, ++ const MutableBufferSequence& buffers, endpoint_type& sender_endpoint, ++ socket_base::message_flags flags, Handler& handler, ++ const IoExecutor& io_ex) ++ { ++ bool is_continuation = ++ boost_asio_handler_cont_helpers::is_continuation(handler); ++ ++ // Allocate and construct an operation to wrap the handler. ++ typedef reactive_socket_recvfrom_op_ext_local op; ++ typename op::ptr p = { boost::asio::detail::addressof(handler), ++ op::ptr::allocate(handler), 0 }; ++ int protocol = impl.protocol_.type(); ++ p.p = new (p.v) op(success_ec_, impl.socket_, protocol, buffers, ++ sender_endpoint, flags, handler, io_ex); ++ ++ BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket", ++ &impl, impl.socket_, "async_receive_from")); ++ ++ start_op(impl, ++ (flags & socket_base::message_out_of_band) ++ ? reactor::except_op : reactor::read_op, ++ p.p, is_continuation, true, false); ++ p.v = p.p = 0; ++ } ++ ++ // Wait until data can be received without blocking. ++ template ++ void async_receive_from(implementation_type& impl, const null_buffers&, ++ endpoint_type& sender_endpoint, socket_base::message_flags flags, ++ Handler& handler, const IoExecutor& io_ex) ++ { ++ bool is_continuation = ++ boost_asio_handler_cont_helpers::is_continuation(handler); ++ ++ // Allocate and construct an operation to wrap the handler. ++ typedef reactive_null_buffers_op op; ++ typename op::ptr p = { boost::asio::detail::addressof(handler), ++ op::ptr::allocate(handler), 0 }; ++ p.p = new (p.v) op(success_ec_, handler, io_ex); ++ ++ BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket", ++ &impl, impl.socket_, "async_receive_from(null_buffers)")); ++ ++ // Reset endpoint since it can be given no sensible value at this time. ++ sender_endpoint = endpoint_type(); ++ ++ start_op(impl, ++ (flags & socket_base::message_out_of_band) ++ ? reactor::except_op : reactor::read_op, ++ p.p, is_continuation, false, false); ++ p.v = p.p = 0; ++ } ++ ++ // Accept a new connection. ++ template ++ boost::system::error_code accept(implementation_type& impl, ++ Socket& peer, endpoint_type* peer_endpoint, boost::system::error_code& ec) ++ { ++ // We cannot accept a socket that is already open. ++ if (peer.is_open()) ++ { ++ ec = boost::asio::error::already_open; ++ return ec; ++ } ++ ++ std::size_t addr_len = peer_endpoint ? peer_endpoint->capacity() : 0; ++ socket_holder new_socket(socket_ops::sync_accept(impl.socket_, ++ impl.state_, peer_endpoint ? peer_endpoint->data() : 0, ++ peer_endpoint ? &addr_len : 0, ec)); ++ ++ // On success, assign new connection to peer socket object. ++ if (new_socket.get() != invalid_socket) ++ { ++ if (peer_endpoint) ++ peer_endpoint->resize(addr_len); ++ peer.assign(impl.protocol_, new_socket.get(), ec); ++ if (!ec) ++ new_socket.release(); ++ } ++ ++ return ec; ++ } ++ ++ // Start an asynchronous accept. The peer and peer_endpoint objects must be ++ // valid until the accept's handler is invoked. ++ template ++ void async_accept(implementation_type& impl, Socket& peer, ++ endpoint_type* peer_endpoint, Handler& handler, const IoExecutor& io_ex) ++ { ++ bool is_continuation = ++ boost_asio_handler_cont_helpers::is_continuation(handler); ++ ++ // Allocate and construct an operation to wrap the handler. ++ typedef reactive_socket_accept_op op; ++ typename op::ptr p = { boost::asio::detail::addressof(handler), ++ op::ptr::allocate(handler), 0 }; ++ p.p = new (p.v) op(success_ec_, impl.socket_, impl.state_, peer, ++ impl.protocol_, peer_endpoint, handler, io_ex); ++ ++ BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket", ++ &impl, impl.socket_, "async_accept")); ++ ++ start_accept_op(impl, p.p, is_continuation, peer.is_open()); ++ p.v = p.p = 0; ++ } ++ ++#if defined(BOOST_ASIO_HAS_MOVE) ++ // Start an asynchronous accept. The peer_endpoint object must be valid until ++ // the accept's handler is invoked. ++ template ++ void async_move_accept(implementation_type& impl, ++ const PeerIoExecutor& peer_io_ex, endpoint_type* peer_endpoint, ++ Handler& handler, const IoExecutor& io_ex) ++ { ++ bool is_continuation = ++ boost_asio_handler_cont_helpers::is_continuation(handler); ++ ++ // Allocate and construct an operation to wrap the handler. ++ typedef reactive_socket_move_accept_op op; ++ typename op::ptr p = { boost::asio::detail::addressof(handler), ++ op::ptr::allocate(handler), 0 }; ++ p.p = new (p.v) op(success_ec_, peer_io_ex, impl.socket_, impl.state_, ++ impl.protocol_, peer_endpoint, handler, io_ex); ++ ++ BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket", ++ &impl, impl.socket_, "async_accept")); ++ ++ start_accept_op(impl, p.p, is_continuation, false); ++ p.v = p.p = 0; ++ } ++#endif // defined(BOOST_ASIO_HAS_MOVE) ++ ++ // Connect the socket to the specified endpoint. ++ boost::system::error_code connect(implementation_type& impl, ++ const endpoint_type& peer_endpoint, boost::system::error_code& ec) ++ { ++ socket_ops::sync_connect(impl.socket_, ++ peer_endpoint.data(), peer_endpoint.size(), ec); ++ return ec; ++ } ++ ++ // Start an asynchronous connect. ++ template ++ void async_connect(implementation_type& impl, ++ const endpoint_type& peer_endpoint, ++ Handler& handler, const IoExecutor& io_ex) ++ { ++ bool is_continuation = ++ boost_asio_handler_cont_helpers::is_continuation(handler); ++ ++ // Allocate and construct an operation to wrap the handler. ++ typedef reactive_socket_connect_op op; ++ typename op::ptr p = { boost::asio::detail::addressof(handler), ++ op::ptr::allocate(handler), 0 }; ++ p.p = new (p.v) op(success_ec_, impl.socket_, handler, io_ex); ++ ++ BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket", ++ &impl, impl.socket_, "async_connect")); ++ ++ start_connect_op(impl, p.p, is_continuation, ++ peer_endpoint.data(), peer_endpoint.size()); ++ p.v = p.p = 0; ++ } ++}; ++ ++} // namespace detail ++} // namespace asio ++} // namespace boost ++ ++#include ++ ++#endif // !defined(BOOST_ASIO_HAS_IOCP) ++ ++#endif // BOOST_ASIO_DETAIL_REACTIVE_SOCKET_SERVICE_EXT_LOCAL_HPP +diff --git a/implementation/helper/1.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 ++ ++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 ++ ++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 ++ ++namespace boost { ++namespace asio { ++namespace detail { ++namespace socket_ops { ++ ++BOOST_ASIO_DECL signed_size_type recvfrom(socket_type s, buf* bufs, ++ size_t count, int flags, socket_addr_type* addr, ++ std::size_t* addrlen, boost::system::error_code& ec, ++ boost::asio::ip::address& da); ++ ++BOOST_ASIO_DECL size_t sync_recvfrom(socket_type s, state_type state, ++ buf* bufs, size_t count, int flags, socket_addr_type* addr, ++ std::size_t* addrlen, boost::system::error_code& ec, boost::asio::ip::address& da); ++ ++#if defined(BOOST_ASIO_HAS_IOCP) ++ ++BOOST_ASIO_DECL void complete_iocp_recvfrom( ++ const weak_cancel_token_type& cancel_token, ++ boost::system::error_code& ec, ++ boost::asio::ip::address& da); ++ ++#else // defined(BOOST_ASIO_HAS_IOCP) ++ ++BOOST_ASIO_DECL bool non_blocking_recvfrom(socket_type s, ++ buf* bufs, size_t count, int flags, ++ socket_addr_type* addr, std::size_t* addrlen, ++ boost::system::error_code& ec, size_t& bytes_transferred, ++ boost::asio::ip::address& da); ++ ++#endif // defined(BOOST_ASIO_HAS_IOCP) ++ ++} // namespace socket_ops ++} // namespace detail ++} // namespace asio ++} // namespace boost ++ ++ ++#if defined(BOOST_ASIO_HEADER_ONLY) ++# include ++#endif // defined(BOOST_ASIO_HEADER_ONLY) ++ ++#endif // BOOST_EXT_ASIO_DETAIL_SOCKET_OPS_HPP +diff --git a/implementation/helper/1.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 ++ ++#include ++#include ++#include ++ ++#include ++ ++namespace boost { ++namespace asio { ++namespace detail { ++namespace socket_ops { ++ ++BOOST_ASIO_DECL signed_size_type recv(socket_type s, buf* bufs, ++ size_t count, int flags, boost::system::error_code& ec, ++ std::uint32_t& uid, std::uint32_t& gid); ++ ++BOOST_ASIO_DECL size_t sync_recv(socket_type s, state_type state, buf* bufs, ++ size_t count, int flags, bool all_empty, boost::system::error_code& ec, ++ std::uint32_t& uid, std::uint32_t& gid); ++ ++#if defined(BOOST_ASIO_HAS_IOCP) ++ ++BOOST_ASIO_DECL void complete_iocp_recv(state_type state, ++ const weak_cancel_token_type& cancel_token, bool all_empty, ++ boost::system::error_code& ec, size_t bytes_transferred, ++ std::uint32_t& uid, std::uint32_t& gid); ++ ++#else // defined(BOOST_ASIO_HAS_IOCP) ++ ++BOOST_ASIO_DECL bool non_blocking_recv(socket_type s, ++ buf* bufs, size_t count, int flags, bool is_stream, ++ boost::system::error_code& ec, size_t& bytes_transferred, ++ std::uint32_t& uid, std::uint32_t& gid); ++ ++#endif // defined(BOOST_ASIO_HAS_IOCP) ++ ++BOOST_ASIO_DECL signed_size_type recvfrom(socket_type s, buf* bufs, ++ size_t count, int flags, socket_addr_type* addr, ++ std::size_t* addrlen, boost::system::error_code& ec, ++ std::uint32_t& uid, std::uint32_t& gid); ++ ++BOOST_ASIO_DECL size_t sync_recvfrom(socket_type s, state_type state, ++ buf* bufs, size_t count, int flags, socket_addr_type* addr, ++ std::size_t* addrlen, boost::system::error_code& ec, ++ std::uint32_t& uid, std::uint32_t& gid); ++ ++#if defined(BOOST_ASIO_HAS_IOCP) ++ ++BOOST_ASIO_DECL void complete_iocp_recvfrom( ++ const weak_cancel_token_type& cancel_token, ++ boost::system::error_code& ec, ++ std::uint32_t& uid, std::uint32_t& gid); ++ ++#else // defined(BOOST_ASIO_HAS_IOCP) ++ ++BOOST_ASIO_DECL bool non_blocking_recvfrom(socket_type s, ++ buf* bufs, size_t count, int flags, ++ socket_addr_type* addr, std::size_t* addrlen, ++ boost::system::error_code& ec, size_t& bytes_transferred, ++ std::uint32_t& uid, std::uint32_t& gid); ++ ++#endif // defined(BOOST_ASIO_HAS_IOCP) ++ ++ ++} // namespace socket_ops ++} // namespace detail ++} // namespace asio ++} // namespace boost ++ ++#include ++ ++#if defined(BOOST_ASIO_HEADER_ONLY) ++# include ++#endif // defined(BOOST_ASIO_HEADER_ONLY) ++ ++#endif // BOOST_ASIO_DETAIL_SOCKET_OPS_EXT_LOCAL_HPP +diff --git a/implementation/helper/1.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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++namespace boost { ++namespace asio { ++namespace ip { ++ ++/// Encapsulates the flags needed for UDP. ++/** ++ * The boost::asio::ip::udp_ext class contains flags necessary for UDP sockets. ++ * ++ * @par Thread Safety ++ * @e Distinct @e objects: Safe.@n ++ * @e Shared @e objects: Safe. ++ * ++ * @par Concepts: ++ * Protocol, InternetProtocol. ++ */ ++class udp_ext ++{ ++public: ++ /// The type of a UDP endpoint. ++ typedef basic_endpoint endpoint; ++ ++ /// Construct to represent the IPv4 UDP protocol. ++ static udp_ext v4() ++ { ++ return udp_ext(BOOST_ASIO_OS_DEF(AF_INET)); ++ } ++ ++ /// Construct to represent the IPv6 UDP protocol. ++ static udp_ext v6() ++ { ++ return udp_ext(BOOST_ASIO_OS_DEF(AF_INET6)); ++ } ++ ++ /// Obtain an identifier for the type of the protocol. ++ int type() const ++ { ++ return BOOST_ASIO_OS_DEF(SOCK_DGRAM); ++ } ++ ++ /// Obtain an identifier for the protocol. ++ int protocol() const ++ { ++ return BOOST_ASIO_OS_DEF(IPPROTO_UDP); ++ } ++ ++ /// Obtain an identifier for the protocol family. ++ int family() const ++ { ++ return family_; ++ } ++ ++ /// The UDP socket type. ++ typedef basic_datagram_socket_ext socket; ++ ++ /// The UDP resolver type. ++ typedef basic_resolver resolver; ++ ++ /// Compare two protocols for equality. ++ friend bool operator==(const udp_ext& p1, const udp_ext& p2) ++ { ++ return p1.family_ == p2.family_; ++ } ++ ++ /// Compare two protocols for inequality. ++ friend bool operator!=(const udp_ext& p1, const udp_ext& p2) ++ { ++ return p1.family_ != p2.family_; ++ } ++ ++private: ++ // Construct with a specific family. ++ explicit udp_ext(int protocol_family) ++ : family_(protocol_family) ++ { ++ } ++ ++ int family_; ++}; ++ ++} // namespace ip ++} // namespace asio ++} // namespace boost ++ ++#include ++ ++#endif // BOOST_ASIO_IP_UDP_EXT_HPP +diff --git a/implementation/helper/1.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 ++ ++#if defined(BOOST_ASIO_HAS_LOCAL_SOCKETS) \ ++ || defined(GENERATING_DOCUMENTATION) ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++namespace boost { ++namespace asio { ++namespace local { ++ ++/// Encapsulates the flags needed for stream-oriented UNIX sockets. ++/** ++ * The boost::asio::local::stream_protocol class contains flags necessary for ++ * stream-oriented UNIX domain sockets. ++ * ++ * @par Thread Safety ++ * @e Distinct @e objects: Safe.@n ++ * @e Shared @e objects: Safe. ++ * ++ * @par Concepts: ++ * Protocol. ++ */ ++class stream_protocol_ext ++{ ++public: ++ /// Obtain an identifier for the type of the protocol. ++ int type() const ++ { ++ return SOCK_STREAM; ++ } ++ ++ /// Obtain an identifier for the protocol. ++ int protocol() const ++ { ++ return 0; ++ } ++ ++ /// Obtain an identifier for the protocol family. ++ int family() const ++ { ++ return AF_UNIX; ++ } ++ ++ /// The type of a UNIX domain endpoint. ++ typedef basic_endpoint endpoint; ++ ++ /// The UNIX domain socket type. ++ typedef basic_stream_socket_ext socket; ++ ++ /// The UNIX domain acceptor type. ++ typedef basic_socket_acceptor_ext acceptor; ++ ++#if !defined(BOOST_ASIO_NO_IOSTREAM) ++ /// The UNIX domain iostream type. ++ typedef basic_socket_iostream iostream; ++#endif // !defined(BOOST_ASIO_NO_IOSTREAM) ++}; ++ ++} // namespace local ++} // namespace asio ++} // namespace boost ++ ++#include ++ ++#endif // defined(BOOST_ASIO_HAS_LOCAL_SOCKETS) ++ // || defined(GENERATING_DOCUMENTATION) ++ ++#endif // BOOST_ASIO_LOCAL_STREAM_PROTOCOL_EXT_HPP +-- +2.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 +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 +--- + 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 +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 + +Upstream-Status: Backport +[https://github.com/COVESA/vsomeip/pull/367] + +Signed-off-by: Yi Zhao +--- + .../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(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(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 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::get_queue_size() const { + + { + std::lock_guard 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 + remote_subscription::get_clients() const { + std::lock_guard its_lock(mutex_); + std::set 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 > 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 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 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 + 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 its_policy_data; + if (p->serialize(its_policy_data)) { + std::vector 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 &_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 &_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 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, + } + + std::lock_guard 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, + auto its_policy = std::make_shared(); + 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, + 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 &_clients) const { + + std::lock_guard 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 +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 +--- + 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 \ + "