diff --git a/.gitignore b/.gitignore index 49f694a391..8fc8285e16 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,4 @@ -#Visual Studio files +# Visual Studio files *.o *.d *.so @@ -38,7 +38,7 @@ *~ ipch/ obj/ -#OSX files +# OSX files *.xccheckout *.pbxuser *.mode1v3 @@ -67,7 +67,9 @@ Intermediate/ # Ignore cmake building directories build.*/ docs/ -# ignore NuGet artifacts +# Ignore NuGet artifacts .nuget/ - -Generated Files/ \ No newline at end of file +Build_android/build/ +Generated Files/ +# Ignore iOS temp build directories +Build_iOS/Apple-Boost-BuildScript diff --git a/.gitmodules b/.gitmodules index 3c19d8d07f..5a33829602 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,6 @@ [submodule "vcpkg"] path = vcpkg url = https://github.com/Microsoft/vcpkg +[submodule "websocketspp"] + path = Release/libs/websocketpp + url = https://github.com/zaphoyd/websocketpp/ diff --git a/Build_android/configure.sh b/Build_android/configure.sh index fd17fb7007..13a7cfb02f 100755 --- a/Build_android/configure.sh +++ b/Build_android/configure.sh @@ -13,9 +13,8 @@ set -e -# Note: we require android ndk r10e available from -# http://dl.google.com/android/ndk/android-ndk-r10e-linux-x86_64.tar.bz2 -# http://dl.google.com/android/ndk/android-ndk-r10e-windows-x86_64.zip +# The Android NDK r10e or later may work, but we test with r18b. To download, see the following link: +# https://developer.android.com/ndk/downloads/index.html # ----------------- # Parse args @@ -25,40 +24,58 @@ DO_BOOST=1 DO_OPENSSL=1 DO_CPPRESTSDK=1 +BOOSTVER=1.65.1 +OPENSSLVER=1.0.2k + +API=15 +STL=c++_static + function usage { echo "Usage: $0 [--skip-boost] [--skip-openssl] [--skip-cpprestsdk] [-h] [--ndk ]" echo "" echo " --skip-boost Skip fetching and compiling boost" echo " --skip-openssl Skip fetching and compiling openssl" echo " --skip-cpprestsdk Skip compiling cpprestsdk" - echo " -h,--help,-? Display this information" + echo " --boost Override the Boost version to build (default is ${BOOSTVER})" + echo " --openssl Override the OpenSSL version to build (default is ${OPENSSLVER})" echo " --ndk If specified, overrides the ANDROID_NDK environment variable" + echo " -h,--help,-? Display this information" } while [[ $# > 0 ]] do case $1 in - "--skip-boost") - DO_BOOST=0 - ;; - "--skip-openssl") - DO_OPENSSL=0 - ;; - "--skip-cpprestsdk") - DO_CPPRESTSDK=0 - ;; - "-?"|"-h"|"--help") - usage - exit - ;; - "--ndk") - shift - export ANDROID_NDK=$1 - ;; - *) - usage - exit 1 - ;; + "--skip-boost") + DO_BOOST=0 + ;; + "--skip-openssl") + DO_OPENSSL=0 + ;; + "--skip-cpprestsdk") + DO_CPPRESTSDK=0 + ;; + "--boost") + shift + DO_BOOST=1 + BOOSTVER=$1 + ;; + "--openssl") + shift + DO_OPENSSL=1 + OPENSSLVER=$1 + ;; + "--ndk") + shift + export ANDROID_NDK=$1 + ;; + "-?"|"-h"|"--help") + usage + exit + ;; + *) + usage + exit 1 + ;; esac shift done @@ -74,6 +91,13 @@ fi NDK_DIR=`cd "${ANDROID_NDK}" && pwd` SRC_DIR=`pwd` +if [ -z "$NCPU" ]; then + NCPU=4 + if uname -s | grep -i "linux" > /dev/null ; then + NCPU=`cat /proc/cpuinfo | grep -c -i processor` + fi +fi + # ----------------------- # Identify the script dir # ----------------------- @@ -102,140 +126,55 @@ fi # This steps are based on the official openssl build instructions # http://wiki.openssl.org/index.php/Android -if [ "${DO_OPENSSL}" == "1" ] -then -( +if [ "${DO_OPENSSL}" == "1" ]; then ( if [ ! -d "openssl" ]; then mkdir openssl; fi cd openssl - cp "${DIR}/openssl/Makefile" . - export ANDROID_NDK_ROOT="${NDK_DIR}" - make all -) -fi - + cp -af "${DIR}/openssl/." . + make all ANDROID_NDK="${NDK_DIR}" ANDROID_TOOLCHAIN=clang ANDROID_GCC_VERSION=4.9 ANDROID_ABI=armeabi-v7a OPENSSL_PREFIX=armeabi-v7a OPENSSL_VERSION=$OPENSSLVER + make all ANDROID_NDK="${NDK_DIR}" ANDROID_TOOLCHAIN=clang ANDROID_GCC_VERSION=4.9 ANDROID_ABI=x86 OPENSSL_PREFIX=x86 OPENSSL_VERSION=$OPENSSLVER +) fi # ----- # Boost # ----- -# Uses the script from MysticTreeGames - -if [ "${DO_BOOST}" == "1" ] -then -( - ( - if [ ! -d "Boost-for-Android" ] - then - git clone https://github.com/MysticTreeGames/Boost-for-Android.git - fi - cd Boost-for-Android - if [ ! -e "cpprestsdk.patched.stamp" ] - then - git checkout 1c95d349d5f92c5ac1c24e0ec6985272a3e3883c - git reset --hard HEAD - git apply "$DIR/boost-for-android.patch" - touch cpprestsdk.patched.stamp - fi - - PATH="$PATH:$NDK_DIR" ./build-android.sh --boost=1.55.0 --with-libraries=random,date_time,filesystem,system,thread,chrono "${NDK_DIR}" || exit 1 - ) - - ( - if [ ! -d "Boost-for-Android-x86" ] - then - git clone Boost-for-Android Boost-for-Android-x86 - fi - cd Boost-for-Android-x86 - if [ ! -e "cpprestsdk.patched.stamp" ] - then - git checkout 1c95d349d5f92c5ac1c24e0ec6985272a3e3883c - git reset --hard HEAD - git apply "$DIR/boost-for-android-x86.patch" - ln -s ../Boost-for-Android/boost_1_55_0.tar.bz2 . - touch cpprestsdk.patched.stamp - fi - - PATH="$PATH:$NDK_DIR" ./build-android.sh --boost=1.55.0 --with-libraries=atomic,random,date_time,filesystem,system,thread,chrono "${NDK_DIR}" || exit 1 - ) -) -fi - -if [ "${DO_CPPRESTSDK}" == "1" ] -then -( -# ------------- -# android-cmake -# ------------- - if [ ! -e android-cmake ] - then - git clone https://github.com/taka-no-me/android-cmake.git - fi +# Uses the build script from Moritz Wundke (formerly MysticTreeGames) +# https://github.com/moritz-wundke/Boost-for-Android + +if [ "${DO_BOOST}" == "1" ]; then ( + if [ ! -d 'Boost-for-Android' ]; then git clone https://github.com/moritz-wundke/Boost-for-Android; fi + cd Boost-for-Android + git checkout 84973078a3d7668067d422d4654696ef59ab9d6d + PATH="$PATH:$NDK_DIR" \ + CXXFLAGS="-std=gnu++11" \ + ./build-android.sh \ + --boost=$BOOSTVER \ + --arch=armeabi-v7a,x86 \ + --with-libraries=atomic,random,date_time,filesystem,system,thread,chrono \ + "${NDK_DIR}" || exit 1 +) fi # ---------- # casablanca # ---------- - ( - mkdir -p build.armv7.debug - cd build.armv7.debug - cmake "$DIR/../Release/" \ - -DCMAKE_TOOLCHAIN_FILE=../android-cmake/android.toolchain.cmake \ - -DANDROID_ABI=armeabi-v7a \ - -DANDROID_TOOLCHAIN_NAME=arm-linux-androideabi-clang3.8 \ - -DANDROID_STL=none \ - -DANDROID_STL_FORCE_FEATURES=ON \ - -DANDROID_NATIVE_API_LEVEL=android-9 \ - -DANDROID_GOLD_LINKER=OFF \ - -DCMAKE_BUILD_TYPE=Debug \ - -DANDROID_NDK="${ANDROID_NDK}" - make -j 1 - ) - - ( - mkdir -p build.armv7.release - cd build.armv7.release - cmake "$DIR/../Release/" \ - -DCMAKE_TOOLCHAIN_FILE=../android-cmake/android.toolchain.cmake \ - -DANDROID_ABI=armeabi-v7a \ - -DANDROID_TOOLCHAIN_NAME=arm-linux-androideabi-clang3.8 \ - -DANDROID_STL=none \ - -DANDROID_STL_FORCE_FEATURES=ON \ - -DANDROID_NDK="${ANDROID_NDK}" \ - -DANDROID_NATIVE_API_LEVEL=android-9 \ - -DANDROID_GOLD_LINKER=OFF \ - -DCMAKE_BUILD_TYPE=Release - make -j 1 - ) - - ( - mkdir -p build.x86.debug - cd build.x86.debug - cmake "$DIR/../Release/" \ - -DCMAKE_TOOLCHAIN_FILE=../android-cmake/android.toolchain.cmake \ - -DANDROID_ABI=x86 \ - -DANDROID_TOOLCHAIN_NAME=x86-clang3.8 \ - -DANDROID_STL=none \ - -DANDROID_STL_FORCE_FEATURES=ON \ - -DANDROID_NATIVE_API_LEVEL=android-9 \ - -DANDROID_GOLD_LINKER=OFF \ - -DCMAKE_BUILD_TYPE=Debug \ - -DANDROID_NDK="${ANDROID_NDK}" - make -j 1 - ) - - ( - mkdir -p build.x86.release - cd build.x86.release - cmake "$DIR/../Release/" \ - -DCMAKE_TOOLCHAIN_FILE=../android-cmake/android.toolchain.cmake \ - -DANDROID_ABI=x86 \ - -DANDROID_TOOLCHAIN_NAME=x86-clang3.8 \ - -DANDROID_STL=none \ - -DANDROID_STL_FORCE_FEATURES=ON \ - -DANDROID_NDK="${ANDROID_NDK}" \ - -DANDROID_NATIVE_API_LEVEL=android-9 \ - -DANDROID_GOLD_LINKER=OFF \ - -DCMAKE_BUILD_TYPE=Release - make -j 1 - ) -) +if [ "${DO_CPPRESTSDK}" == "1" ]; then + # Use the builtin CMake toolchain configuration that comes with the NDK + function build_cpprestsdk { ( + mkdir -p $1 + cd $1 + cmake "${DIR}/.." \ + -DCMAKE_TOOLCHAIN_FILE="${ANDROID_NDK}/build/cmake/android.toolchain.cmake" \ + -DANDROID_NDK="${ANDROID_NDK}" \ + -DANDROID_TOOLCHAIN=clang \ + -DANDROID_ABI=$2 \ + -DBOOST_VERSION="${BOOSTVER}" \ + -DCMAKE_BUILD_TYPE=$3 + make -j $NCPU + ) } + + # Build the cpprestsdk for each target configuration + build_cpprestsdk build.armv7.debug armeabi-v7a Debug + build_cpprestsdk build.armv7.release armeabi-v7a Release + build_cpprestsdk build.x86.debug x86 Debug + build_cpprestsdk build.x86.release x86 Release fi diff --git a/Build_android/openssl/Makefile b/Build_android/openssl/Makefile index 71a992164d..2da8fa48c9 100644 --- a/Build_android/openssl/Makefile +++ b/Build_android/openssl/Makefile @@ -1,60 +1,176 @@ -SHELL := /bin/bash -OPENSSL_VER = openssl-1.0.2k +# Configuration parameters +ANDROID_API = 18 +ANDROID_ABI = armeabi-v7a +ANDROID_HOST = linux-x86_64 +ANDROID_TOOLCHAIN = gcc +ANDROID_GCC_VERSION = 4.8 +OPENSSL_VERSION = 1.0.2k +OPENSSL_PACKAGE = openssl-$(OPENSSL_VERSION) +OPENSSL_PATCH = $(OPENSSL_PACKAGE).patch +OPENSSL_TARBALL = $(OPENSSL_PACKAGE).tar.gz +OPENSSL_URL = https://www.openssl.org/source/$(OPENSSL_TARBALL) +OPENSSL_OPTIONS = -no-ssl2 -no-ssl3 -no-comp -no-hw -no-engine +OPENSSL_PREFIX = android-$(ANDROID_API)-$(ANDROID_ABI)-$(ANDROID_TOOLCHAIN) +OPENSSL_SOURCE = $(OPENSSL_PACKAGE)-$(ANDROID_ABI) -all: armeabi-v7a/lib/libssl.a x86/lib/libssl.a +# Setup target parameters from ABI +ifneq ($(findstring armeabi,$(ANDROID_ABI)),) +ANDROID_ARCH := arm +ANDROID_TRIPLE := arm-linux-androideabi +ANDROID_TOOLARCH := $(ANDROID_TRIPLE) +OPENSSL_MACHINE := armv7 +OPENSSL_SYSTEM := android +OPENSSL_TARGET := android-armeabi +endif -clean: - rm -rf $(OPENSSL_VER) - rm -rf $(OPENSSL_VER)-armeabi-v7a - rm -rf armeabi-v7a - rm -rf setenv-android-x86.sh - -setenv-android.sh: - wget https://wiki.openssl.org/images/7/70/Setenv-android.sh - mv Setenv-android.sh setenv-android.sh - chmod a+x setenv-android.sh - -setenv-android-x86.sh: setenv-android.sh - cp setenv-android.sh setenv-android-x86.sh.tmp - sed -i -e 's/_ANDROID_EABI="arm-linux-androideabi-4.8"/_ANDROID_EABI="x86-4.8"/g' setenv-android-x86.sh.tmp - sed -i -e 's/_ANDROID_ARCH=arch-arm/_ANDROID_ARCH=arch-x86/g' setenv-android-x86.sh.tmp - mv setenv-android-x86.sh.tmp setenv-android-x86.sh - -$(OPENSSL_VER).tar.gz: - wget https://www.openssl.org/source/$(OPENSSL_VER).tar.gz - -armeabi-v7a/lib/libssl.a: setenv-android.sh $(OPENSSL_VER).tar.gz - [ -d "$(ANDROID_NDK_ROOT)" ] - export ANDROID_NDK_ROOT="$(ANDROID_NDK_ROOT)"; \ - . ./setenv-android.sh; \ +ifneq ($(findstring aarch64,$(ANDROID_ABI)),) +ANDROID_ARCH := arm64 +ANDROID_TRIPLE := aarch64-linux-android +ANDROID_TOOLARCH := $(ANDROID_TRIPLE) +OPENSSL_MACHINE := aarch64 +OPENSSL_SYSTEM := android64 +OPENSSL_TARGET := android64-aarch64 +endif + +ifneq ($(findstring x86,$(ANDROID_ABI)),) +ANDROID_ARCH := x86 +ANDROID_TRIPLE := i686-linux-android +ANDROID_TOOLARCH := $(ANDROID_ARCH) +OPENSSL_MACHINE := i686 +OPENSSL_SYSTEM := android +OPENSSL_TARGET := android-x86 +endif + +# Validate Android NDK directory paths and use fallback directories where applicable +define direxists = +$(if $(wildcard $(1)),$(strip $(1)),"") +endef + +define findfirstdir = +$(call direxists,$(firstword $(filter-out "",$(foreach val,$(3),$(call direxists,$(subst $(2),$(strip $(val)),$(1))))))) +endef + +ifeq ($(call direxists,$(ANDROID_NDK)),"") +$(error invalid Android NDK root directory) +endif + +ANDROID_LINK_SYSROOT := $(ANDROID_NDK)/platforms/android-$(ANDROID_API)/arch-$(ANDROID_ARCH) +ifeq ($(call direxists,$(ANDROID_LINK_SYSROOT)),"") +$(error invalid Android ABI or API level, could not locate Android NDK sysroot directory) +endif + +ANDROID_SYSROOT := $(ANDROID_NDK)/sysroot +ifeq ($(call direxists,$(ANDROID_SYSROOT)),"") +ANDROID_SYSROOT := $(ANDROID_LINK_SYSROOT) +endif + +ANDROID_GCC_VERSIONS := $(ANDROID_GCC_VERSION) 4.9 4.8 +ANDROID_GCC_PREBUILT_template := $(ANDROID_NDK)/toolchains/$(ANDROID_TOOLARCH)-<>/prebuilt +ANDROID_GCC_PREBUILT := $(call findfirstdir,$(ANDROID_GCC_PREBUILT_template),<>,$(ANDROID_GCC_VERSIONS)) +ifeq ($(ANDROID_GCC_PREBUILT),"") +$(error could not determine Android NDK GCC toolchain prebuilt directory) +endif + +ANDROID_HOSTS := $(ANDROID_HOST) linux-x86_64 linux-x86 darwin-x86_64 darwin-x86 +ANDROID_GCC_TOOLCHAIN_template := $(ANDROID_GCC_PREBUILT)/<> +ANDROID_GCC_TOOLCHAIN := $(call findfirstdir,$(ANDROID_GCC_TOOLCHAIN_template),<>,$(ANDROID_HOSTS)) +ifeq ($(ANDROID_GCC_TOOLCHAIN),"") +$(error could not determine Android NDK GCC toolchain host directory) +endif + +ANDROID_LLVM_VERSIONS := llvm llvm-3.6 llvm-3.5 llvm-3.4 +ANDROID_LLVM_TOOLCHAIN_template := $(ANDROID_NDK)/toolchains/<>/prebuilt/$(notdir $(ANDROID_GCC_TOOLCHAIN)) +ANDROID_LLVM_TOOLCHAIN := $(call findfirstdir,$(ANDROID_LLVM_TOOLCHAIN_template),<>,$(ANDROID_LLVM_VERSIONS)) +ifeq ($(ANDROID_LLVM_TOOLCHAIN),"") +$(error could not determine Android NDK LLVM toolchain directory) +endif + +# Configure toolchain +OPENSSL_CROSS_COMPILE := +OPENSSL_CC := +OPENSSL_RANLIB := $(ANDROID_GCC_TOOLCHAIN)/bin/$(ANDROID_TRIPLE)-ranlib + +ifneq ($(findstring clang,$(ANDROID_TOOLCHAIN)),) +OPENSSL_TARGET := $(OPENSSL_TARGET)-clang +OPENSSL_CC := $(ANDROID_LLVM_TOOLCHAIN)/bin/clang +endif + +ifneq ($(findstring gcc,$(ANDROID_TOOLCHAIN)),) +OPENSSL_CROSS_COMPILE := $(ANDROID_TRIPLE)- +OPENSSL_CC := $(ANDROID_GCC_TOOLCHAIN)/bin/$(ANDROID_TRIPLE)-gcc +endif + +ifeq ($(OPENSSL_CC),) +$(error invalid toolchain specified for ANDROID_TOOLCHAIN) +endif + +all: info $(OPENSSL_PREFIX)/lib/libssl.a + +$(OPENSSL_TARBALL): + @echo "Downloading OpenSSL tarball" + wget $(OPENSSL_URL) + +$(OPENSSL_PREFIX)/lib/libssl.a: $(OPENSSL_TARBALL) + @echo "Decompressing OpenSSL package" && \ ( \ set -e; \ - rm -rf $(OPENSSL_VER)/; \ - tar xzf $(OPENSSL_VER).tar.gz; \ - rm -rf $(OPENSSL_VER)-armeabi-v7a/ \ + rm -rf $(OPENSSL_SOURCE); \ + rm -rf $(OPENSSL_PACKAGE); \ + tar xzf $(OPENSSL_TARBALL); \ ) && \ - mv $(OPENSSL_VER) $(OPENSSL_VER)-armeabi-v7a && \ - cd $(OPENSSL_VER)-armeabi-v7a && \ - perl -pi -e 's/install: all install_docs install_sw/install: install_docs install_sw/g' Makefile.org && \ - ./config shared -no-ssl2 -no-ssl3 -no-comp -no-hw -no-engine --openssldir="`pwd`/../armeabi-v7a" && \ - make depend && \ - make all && \ - make install CC=$${ANDROID_TOOLCHAIN}/arm-linux-androideabi-gcc RANLIB=$${ANDROID_TOOLCHAIN}/arm-linux-androideabi-ranlib - -x86/lib/libssl.a: setenv-android-x86.sh $(OPENSSL_VER).tar.gz - [ -d "$(ANDROID_NDK_ROOT)" ] - export ANDROID_NDK_ROOT="$(ANDROID_NDK_ROOT)"; \ - . ./setenv-android-x86.sh; \ + mv $(OPENSSL_PACKAGE) $(OPENSSL_SOURCE) + @if test -f $(OPENSSL_PATCH); then \ + echo "Patching OpenSSL source tree"; \ + ( cd $(OPENSSL_SOURCE) && patch -p1 < ../$(OPENSSL_PATCH) ); \ + fi + @echo "Building OpenSSL" && \ + export ANDROID_NDK="$(ANDROID_NDK)" && \ + export ANDROID_API="$(ANDROID_API)" && \ + export ANDROID_ARCH="$(ANDROID_ARCH)" && \ + export ANDROID_TRIPLE="$(ANDROID_TRIPLE)" && \ + export ANDROID_SYSROOT="$(ANDROID_SYSROOT)" && \ + export ANDROID_LINK_SYSROOT="$(ANDROID_LINK_SYSROOT)" && \ + export ANDROID_GCC_TOOLCHAIN="$(ANDROID_GCC_TOOLCHAIN)" && \ + export CROSS_SYSROOT="$(ANDROID_SYSROOT)" && \ + export SYSROOT="$(ANDROID_SYSROOT)" && \ + export ARCH="$(ANDROID_ARCH)" && \ + export MACHINE="$(OPENSSL_MACHINE)" && \ + export SYSTEM="$(OPENSSL_SYSTEM)" && \ + export CROSS_COMPILE="$(OPENSSL_CROSS_COMPILE)" && \ + export HOSTCC="$(ANDROID_TOOLCHAIN)" && \ + export PATH="$(ANDROID_GCC_TOOLCHAIN)/bin:$(ANDROID_LLVM_TOOLCHAIN)/bin:$(PATH)" && \ ( \ - set -e; \ - rm -rf $(OPENSSL_VER)/; \ - tar xzf $(OPENSSL_VER).tar.gz; \ - rm -rf $(OPENSSL_VER)-x86/ \ - ) && \ - mv $(OPENSSL_VER) $(OPENSSL_VER)-x86 && \ - cd $(OPENSSL_VER)-x86 && \ - perl -pi -e 's/install: all install_docs install_sw/install: install_docs install_sw/g' Makefile.org && \ - ./config shared -no-ssl2 -no-ssl3 -no-comp -no-hw -no-engine --openssldir="`pwd`/../x86" && \ - make depend && \ - make all && \ - make install CC=$${ANDROID_TOOLCHAIN}/i686-linux-android-gcc RANLIB=$${ANDROID_TOOLCHAIN}/i686-linux-android-ranlib + cd $(OPENSSL_SOURCE); \ + perl Configure $(OPENSSL_TARGET) shared $(OPENSSL_OPTIONS) --prefix="`pwd`/../$(OPENSSL_PREFIX)" $(OPENSSL_CFLAGS) && \ + make depend && \ + make all && \ + make install CC=$(OPENSSL_CC) RANLIB=$(OPENSSL_RANLIB); \ + ) + +clean: + @echo "Cleaning" + rm -rf $(OPENSSL_SOURCE) + rm -rf $(OPENSSL_PACKAGE) + rm -rf $(OPENSSL_PREFIX) + +info: + @echo "OpenSSL build options" + @echo "ANDROID_NDK = $(ANDROID_NDK)" + @echo "ANDROID_API = $(ANDROID_API)" + @echo "ANDROID_ABI = $(ANDROID_ABI)" + @echo "ANDROID_HOST = $(ANDROID_HOST)" + @echo "ANDROID_TOOLCHAIN = $(ANDROID_TOOLCHAIN)" + @echo "ANDROID_TRIPLE = $(ANDROID_TRIPLE)" + @echo "ANDROID_SYSROOT = $(ANDROID_SYSROOT)" + @echo "ANDROID_LINK_SYSROOT = $(ANDROID_LINK_SYSROOT)" + @echo "ANDROID_GCC_TOOLCHAIN = $(ANDROID_GCC_TOOLCHAIN)" + @echo "ANDROID_LLVM_TOOLCHAIN = $(ANDROID_LLVM_TOOLCHAIN)" + @echo "OPENSSL_VERSION = $(OPENSSL_VERSION)" + @echo "OPENSSL_URL = $(OPENSSL_URL)" + @echo "OPENSSL_OPTIONS = $(OPENSSL_OPTIONS)" + @echo "OPENSSL_PREFIX = $(OPENSSL_PREFIX)" + @echo "OPENSSL_CFLAGS = $(OPENSSL_CFLAGS)" + @echo "OPENSSL_CC = $(OPENSSL_CC)" + @echo "OPENSSL_RANLIB = $(OPENSSL_RANLIB)" + +.PHONY: all clean info diff --git a/Build_android/openssl/openssl-1.0.2k.patch b/Build_android/openssl/openssl-1.0.2k.patch new file mode 100644 index 0000000000..992a27e9f9 --- /dev/null +++ b/Build_android/openssl/openssl-1.0.2k.patch @@ -0,0 +1,108 @@ +This patch applies several changes that enable OpenSSL 1.0.2k to be built +for Android using either Clang or GCC toolchains. + +An alias for the android-armv7 target, named android-armeabi, is added for +compatability with the OpenSSL 1.1.0 configuration target names. Support for +the AArch64 archicture is also added, as well as targets using the Clang +compiler. + +Clang does not recognize some of the ARM assembly nmenonics that are used in +OpenSSL. In particular, the 'adrl' pseudo instruction is not supported. To +further complicate matters, Clang doesn't support immediate fixup values so +the alternative adr/sub sequence used for the Thumb2 code path cannot be +used either. Instead it is replaced with a sequence of instructions that +computes the offset at runtime. It utilizes register r4 for computing the +intermediate result, which is first saved to and later restored from the +stack. The upstream bug in LLVM can be found here: +https://llvm.org/bugs/show_bug.cgi?id=24350 + +diff -Naur org/Configure mod/Configure +--- org/Configure 2017-01-26 05:22:03.000000000 -0800 ++++ mod/Configure 2018-01-17 14:25:44.712943600 -0800 +@@ -471,10 +471,17 @@ + "linux-alpha+bwx-ccc","ccc:-fast -readonly_strings -DL_ENDIAN::-D_REENTRANT:::SIXTY_FOUR_BIT_LONG RC4_CHAR RC4_CHUNK DES_INT DES_PTR DES_RISC1 DES_UNROLL:${alpha_asm}", + + # Android: linux-* but without pointers to headers and libs. +-"android","gcc:-mandroid -I\$(ANDROID_DEV)/include -B\$(ANDROID_DEV)/lib -O3 -fomit-frame-pointer -Wall::-D_REENTRANT::-ldl:BN_LLONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${no_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", +-"android-x86","gcc:-mandroid -I\$(ANDROID_DEV)/include -B\$(ANDROID_DEV)/lib -O3 -fomit-frame-pointer -Wall::-D_REENTRANT::-ldl:BN_LLONG ${x86_gcc_des} ${x86_gcc_opts}:".eval{my $asm=${x86_elf_asm};$asm=~s/:elf/:android/;$asm}.":dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", +-"android-armv7","gcc:-march=armv7-a -mandroid -I\$(ANDROID_DEV)/include -B\$(ANDROID_DEV)/lib -O3 -fomit-frame-pointer -Wall::-D_REENTRANT::-ldl:BN_LLONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${armv4_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", +-"android-mips","gcc:-mandroid -I\$(ANDROID_DEV)/include -B\$(ANDROID_DEV)/lib -O3 -Wall::-D_REENTRANT::-ldl:BN_LLONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${mips32_asm}:o32:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", ++"android","gcc:-mandroid --sysroot \$(ANDROID_LINK_SYSROOT) -isystem \$(ANDROID_SYSROOT)/usr/include -isystem \$(ANDROID_SYSROOT)/usr/include/\$(ANDROID_TRIPLE) -B\$(ANDROID_LINK_SYSROOT)/lib -D__ANDROID_API__=\$(ANDROID_API) -O3 -fomit-frame-pointer -Wall::-D_REENTRANT::-ldl:BN_LLONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${no_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", ++"android-x86","gcc:-mandroid --sysroot \$(ANDROID_LINK_SYSROOT) -isystem \$(ANDROID_SYSROOT)/usr/include -isystem \$(ANDROID_SYSROOT)/usr/include/\$(ANDROID_TRIPLE) -B\$(ANDROID_LINK_SYSROOT)/lib -D__ANDROID_API__=\$(ANDROID_API) -O3 -fomit-frame-pointer -Wall::-D_REENTRANT::-ldl:BN_LLONG ${x86_gcc_des} ${x86_gcc_opts}:".eval{my $asm=${x86_elf_asm};$asm=~s/:elf/:android/;$asm}.":dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", ++"android-armv7","gcc:-march=armv7-a -mandroid --sysroot \$(ANDROID_LINK_SYSROOT) -isystem \$(ANDROID_SYSROOT)/usr/include -isystem \$(ANDROID_SYSROOT)/usr/include/\$(ANDROID_TRIPLE) -B\$(ANDROID_LINK_SYSROOT)/lib -D__ANDROID_API__=\$(ANDROID_API) -O3 -fomit-frame-pointer -Wall::-D_REENTRANT::-ldl:BN_LLONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${armv4_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", ++"android-armeabi","gcc:-march=armv7-a -mandroid --sysroot \$(ANDROID_LINK_SYSROOT) -isystem \$(ANDROID_SYSROOT)/usr/include -isystem \$(ANDROID_SYSROOT)/usr/include/\$(ANDROID_TRIPLE) -B\$(ANDROID_LINK_SYSROOT)/lib -D__ANDROID_API__=\$(ANDROID_API) -O3 -fomit-frame-pointer -Wall::-D_REENTRANT::-ldl:BN_LLONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${armv4_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", ++"android64-aarch64","gcc:-march=armv8-a -mandroid --sysroot \$(ANDROID_LINK_SYSROOT) -isystem \$(ANDROID_SYSROOT)/usr/include -isystem \$(ANDROID_SYSROOT)/usr/include/\$(ANDROID_TRIPLE) -B\$(ANDROID_LINK_SYSROOT)/lib -D__ANDROID_API__=\$(ANDROID_API) -O3 -fomit-frame-pointer -Wall::-D_REENTRANT::-ldl:SIXTY_FOUR_BIT_LONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${aarch64_asm}:linux64:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", ++"android-mips","gcc:-mandroid --sysroot \$(ANDROID_LINK_SYSROOT) -isystem \$(ANDROID_SYSROOT)/usr/include -isystem \$(ANDROID_SYSROOT)/usr/include/\$(ANDROID_TRIPLE) -B\$(ANDROID_LINK_SYSROOT)/lib -D__ANDROID_API__=\$(ANDROID_API) -O3 -Wall::-D_REENTRANT::-ldl:BN_LLONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${mips32_asm}:o32:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", ++"android-x86-clang","clang:-target i686-none-linux-android --gcc-toolchain=\$(ANDROID_GCC_TOOLCHAIN) --sysroot \$(ANDROID_LINK_SYSROOT) -isystem \$(ANDROID_SYSROOT)/usr/include -isystem \$(ANDROID_SYSROOT)/usr/include/\$(ANDROID_TRIPLE) -B\$(ANDROID_LINK_SYSROOT)/lib -D__ANDROID_API__=\$(ANDROID_API) -O3 -fomit-frame-pointer -Wall::-D_REENTRANT::-ldl:BN_LLONG ${x86_gcc_des} ${x86_gcc_opts}:".eval{my $asm=${x86_elf_asm};$asm=~s/:elf/:android/;$asm}.":dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", ++"android-armv7-clang","clang:-target armv7-none-linux-androideabi --gcc-toolchain=\$(ANDROID_GCC_TOOLCHAIN) --sysroot \$(ANDROID_LINK_SYSROOT) -isystem \$(ANDROID_SYSROOT)/usr/include -isystem \$(ANDROID_SYSROOT)/usr/include/\$(ANDROID_TRIPLE) -B\$(ANDROID_LINK_SYSROOT)/lib -D__ANDROID_API__=\$(ANDROID_API) -O3 -fomit-frame-pointer -Wall::-D_REENTRANT::-ldl:BN_LLONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${armv4_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", ++"android-armeabi-clang","clang:-target armv7-none-linux-androideabi --gcc-toolchain=\$(ANDROID_GCC_TOOLCHAIN) --sysroot \$(ANDROID_LINK_SYSROOT) -isystem \$(ANDROID_SYSROOT)/usr/include -isystem \$(ANDROID_SYSROOT)/usr/include/\$(ANDROID_TRIPLE) -B\$(ANDROID_LINK_SYSROOT)/lib -D__ANDROID_API__=\$(ANDROID_API) -O3 -fomit-frame-pointer -Wall::-D_REENTRANT::-ldl:BN_LLONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${armv4_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", ++"android64-aarch64-clang","clang:-target aarch64-none-linux-android --gcc-toolchain=\$(ANDROID_GCC_TOOLCHAIN) --sysroot \$(ANDROID_LINK_SYSROOT) -isystem \$(ANDROID_SYSROOT)/usr/include -isystem \$(ANDROID_SYSROOT)/usr/include/\$(ANDROID_TRIPLE) -B\$(ANDROID_LINK_SYSROOT)/lib -D__ANDROID_API__=\$(ANDROID_API) -O3 -fomit-frame-pointer -Wall::-D_REENTRANT::-ldl:SIXTY_FOUR_BIT_LONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${aarch64_asm}:linux64:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", ++"android-mips-clang","clang:-target mipsel-none-linux-android --gcc-toolchain=\$(ANDROID_GCC_TOOLCHAIN) --sysroot \$(ANDROID_LINK_SYSROOT) -isystem \$(ANDROID_SYSROOT)/usr/include -isystem \$(ANDROID_SYSROOT)/usr/include/\$(ANDROID_TRIPLE) -B\$(ANDROID_LINK_SYSROOT)/lib -D__ANDROID_API__=\$(ANDROID_API) -O3 -Wall::-D_REENTRANT::-ldl:BN_LLONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${mips32_asm}:o32:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", + + #### *BSD [do see comment about ${BSDthreads} above!] + "BSD-generic32","gcc:-O3 -fomit-frame-pointer -Wall::${BSDthreads}:::BN_LLONG RC2_CHAR RC4_INDEX DES_INT DES_UNROLL:${no_asm}:dlfcn:bsd-gcc-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", +diff -Naur org/crypto/bn/asm/armv4-gf2m.pl mod/crypto/bn/asm/armv4-gf2m.pl +--- org/crypto/bn/asm/armv4-gf2m.pl 2017-01-26 05:22:03.000000000 -0800 ++++ mod/crypto/bn/asm/armv4-gf2m.pl 2018-01-17 11:38:57.297482700 -0800 +@@ -213,8 +213,8 @@ + .align 5 + .LNEON: + ldr r12, [sp] @ 5th argument +- vmov.32 $a, r2, r1 +- vmov.32 $b, r12, r3 ++ vmov $a, r2, r1 ++ vmov $b, r12, r3 + vmov.i64 $k48, #0x0000ffffffffffff + vmov.i64 $k32, #0x00000000ffffffff + vmov.i64 $k16, #0x000000000000ffff +diff -Naur org/crypto/sha/asm/sha256-armv4.pl mod/crypto/sha/asm/sha256-armv4.pl +--- org/crypto/sha/asm/sha256-armv4.pl 2017-01-26 05:22:03.000000000 -0800 ++++ mod/crypto/sha/asm/sha256-armv4.pl 2018-01-17 11:38:57.306342000 -0800 +@@ -576,6 +576,7 @@ + my @MSG=map("q$_",(8..11)); + my ($W0,$W1,$ABCD_SAVE,$EFGH_SAVE)=map("q$_",(12..15)); + my $Ktbl="r3"; ++my $Temp="r4"; + + $code.=<<___; + #if __ARM_MAX_ARCH__>=7 && !defined(__KERNEL__) +@@ -591,7 +592,13 @@ + sha256_block_data_order_armv8: + .LARMv8: + vld1.32 {$ABCD,$EFGH},[$ctx] +-# ifdef __thumb2__ ++# if defined(__clang__) ++ stmdb sp!,{r4,lr} ++ adr $Ktbl,.LARMv8 ++ ldr $Temp,=K256 ++ sub $Temp,$Ktbl,$Temp ++ sub $Ktbl,$Ktbl,$Temp ++# elif defined(__thumb2__) + adr $Ktbl,.LARMv8 + sub $Ktbl,$Ktbl,#.LARMv8-K256 + # else +@@ -655,7 +662,12 @@ + + vst1.32 {$ABCD,$EFGH},[$ctx] + ++# ifdef __clang__ ++ ldmia sp!,{r4,pc} ++# else + ret @ bx lr ++# endif ++ + .size sha256_block_data_order_armv8,.-sha256_block_data_order_armv8 + #endif + ___ +diff -Naur org/Makefile.org mod/Makefile.org +--- org/Makefile.org 2017-01-26 05:22:03.000000000 -0800 ++++ mod/Makefile.org 2018-01-17 14:26:20.623418300 -0800 +@@ -532,7 +532,7 @@ + @$(MAKE) SDIRS='$(SDIRS)' clean + @$(MAKE) TAR='$(TAR)' TARFLAGS='$(TARFLAGS)' $(DISTTARVARS) tar + +-install: all install_docs install_sw ++install: install_docs install_sw + + install_sw: + @$(PERL) $(TOP)/util/mkdir-p.pl $(INSTALL_PREFIX)$(INSTALLTOP)/bin \ diff --git a/Build_android/openssl/openssl-1.0.2l.patch b/Build_android/openssl/openssl-1.0.2l.patch new file mode 100644 index 0000000000..03acbee7c0 --- /dev/null +++ b/Build_android/openssl/openssl-1.0.2l.patch @@ -0,0 +1,108 @@ +This patch applies several changes that enable OpenSSL 1.0.2l to be built +for Android using either Clang or GCC toolchains. + +An alias for the android-armv7 target, named android-armeabi, is added for +compatability with the OpenSSL 1.1.0 configuration target names. Support for +the AArch64 archicture is also added, as well as targets using the Clang +compiler. + +Clang does not recognize some of the ARM assembly nmenonics that are used in +OpenSSL. In particular, the 'adrl' pseudo instruction is not supported. To +further complicate matters, Clang doesn't support immediate fixup values so +the alternative adr/sub sequence used for the Thumb2 code path cannot be +used either. Instead it is replaced with a sequence of instructions that +computes the offset at runtime. It utilizes register r4 for computing the +intermediate result, which is first saved to and later restored from the +stack. The upstream bug in LLVM can be found here: +https://llvm.org/bugs/show_bug.cgi?id=24350 + +diff -Naur org/Configure mod/Configure +--- org/Configure 2017-05-25 05:54:38.000000000 -0700 ++++ mod/Configure 2018-01-17 20:36:12.497485400 -0800 +@@ -471,10 +471,17 @@ + "linux-alpha+bwx-ccc","ccc:-fast -readonly_strings -DL_ENDIAN::-D_REENTRANT:::SIXTY_FOUR_BIT_LONG RC4_CHAR RC4_CHUNK DES_INT DES_PTR DES_RISC1 DES_UNROLL:${alpha_asm}", + + # Android: linux-* but without pointers to headers and libs. +-"android","gcc:-mandroid -I\$(ANDROID_DEV)/include -B\$(ANDROID_DEV)/lib -O3 -fomit-frame-pointer -Wall::-D_REENTRANT::-ldl:BN_LLONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${no_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", +-"android-x86","gcc:-mandroid -I\$(ANDROID_DEV)/include -B\$(ANDROID_DEV)/lib -O3 -fomit-frame-pointer -Wall::-D_REENTRANT::-ldl:BN_LLONG ${x86_gcc_des} ${x86_gcc_opts}:".eval{my $asm=${x86_elf_asm};$asm=~s/:elf/:android/;$asm}.":dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", +-"android-armv7","gcc:-march=armv7-a -mandroid -I\$(ANDROID_DEV)/include -B\$(ANDROID_DEV)/lib -O3 -fomit-frame-pointer -Wall::-D_REENTRANT::-ldl:BN_LLONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${armv4_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", +-"android-mips","gcc:-mandroid -I\$(ANDROID_DEV)/include -B\$(ANDROID_DEV)/lib -O3 -Wall::-D_REENTRANT::-ldl:BN_LLONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${mips32_asm}:o32:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", ++"android","gcc:-mandroid --sysroot \$(ANDROID_LINK_SYSROOT) -isystem \$(ANDROID_SYSROOT)/usr/include -isystem \$(ANDROID_SYSROOT)/usr/include/\$(ANDROID_TRIPLE) -B\$(ANDROID_LINK_SYSROOT)/lib -D__ANDROID_API__=\$(ANDROID_API) -O3 -fomit-frame-pointer -Wall::-D_REENTRANT::-ldl:BN_LLONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${no_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", ++"android-x86","gcc:-mandroid --sysroot \$(ANDROID_LINK_SYSROOT) -isystem \$(ANDROID_SYSROOT)/usr/include -isystem \$(ANDROID_SYSROOT)/usr/include/\$(ANDROID_TRIPLE) -B\$(ANDROID_LINK_SYSROOT)/lib -D__ANDROID_API__=\$(ANDROID_API) -O3 -fomit-frame-pointer -Wall::-D_REENTRANT::-ldl:BN_LLONG ${x86_gcc_des} ${x86_gcc_opts}:".eval{my $asm=${x86_elf_asm};$asm=~s/:elf/:android/;$asm}.":dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", ++"android-armv7","gcc:-march=armv7-a -mandroid --sysroot \$(ANDROID_LINK_SYSROOT) -isystem \$(ANDROID_SYSROOT)/usr/include -isystem \$(ANDROID_SYSROOT)/usr/include/\$(ANDROID_TRIPLE) -B\$(ANDROID_LINK_SYSROOT)/lib -D__ANDROID_API__=\$(ANDROID_API) -O3 -fomit-frame-pointer -Wall::-D_REENTRANT::-ldl:BN_LLONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${armv4_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", ++"android-armeabi","gcc:-march=armv7-a -mandroid --sysroot \$(ANDROID_LINK_SYSROOT) -isystem \$(ANDROID_SYSROOT)/usr/include -isystem \$(ANDROID_SYSROOT)/usr/include/\$(ANDROID_TRIPLE) -B\$(ANDROID_LINK_SYSROOT)/lib -D__ANDROID_API__=\$(ANDROID_API) -O3 -fomit-frame-pointer -Wall::-D_REENTRANT::-ldl:BN_LLONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${armv4_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", ++"android64-aarch64","gcc:-march=armv8-a -mandroid --sysroot \$(ANDROID_LINK_SYSROOT) -isystem \$(ANDROID_SYSROOT)/usr/include -isystem \$(ANDROID_SYSROOT)/usr/include/\$(ANDROID_TRIPLE) -B\$(ANDROID_LINK_SYSROOT)/lib -D__ANDROID_API__=\$(ANDROID_API) -O3 -fomit-frame-pointer -Wall::-D_REENTRANT::-ldl:SIXTY_FOUR_BIT_LONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${aarch64_asm}:linux64:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", ++"android-mips","gcc:-mandroid --sysroot \$(ANDROID_LINK_SYSROOT) -isystem \$(ANDROID_SYSROOT)/usr/include -isystem \$(ANDROID_SYSROOT)/usr/include/\$(ANDROID_TRIPLE) -B\$(ANDROID_LINK_SYSROOT)/lib -D__ANDROID_API__=\$(ANDROID_API) -O3 -Wall::-D_REENTRANT::-ldl:BN_LLONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${mips32_asm}:o32:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", ++"android-x86-clang","clang:-target i686-none-linux-android --gcc-toolchain=\$(ANDROID_GCC_TOOLCHAIN) --sysroot \$(ANDROID_LINK_SYSROOT) -isystem \$(ANDROID_SYSROOT)/usr/include -isystem \$(ANDROID_SYSROOT)/usr/include/\$(ANDROID_TRIPLE) -B\$(ANDROID_LINK_SYSROOT)/lib -D__ANDROID_API__=\$(ANDROID_API) -O3 -fomit-frame-pointer -Wall::-D_REENTRANT::-ldl:BN_LLONG ${x86_gcc_des} ${x86_gcc_opts}:".eval{my $asm=${x86_elf_asm};$asm=~s/:elf/:android/;$asm}.":dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", ++"android-armv7-clang","clang:-target armv7-none-linux-androideabi --gcc-toolchain=\$(ANDROID_GCC_TOOLCHAIN) --sysroot \$(ANDROID_LINK_SYSROOT) -isystem \$(ANDROID_SYSROOT)/usr/include -isystem \$(ANDROID_SYSROOT)/usr/include/\$(ANDROID_TRIPLE) -B\$(ANDROID_LINK_SYSROOT)/lib -D__ANDROID_API__=\$(ANDROID_API) -O3 -fomit-frame-pointer -Wall::-D_REENTRANT::-ldl:BN_LLONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${armv4_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", ++"android-armeabi-clang","clang:-target armv7-none-linux-androideabi --gcc-toolchain=\$(ANDROID_GCC_TOOLCHAIN) --sysroot \$(ANDROID_LINK_SYSROOT) -isystem \$(ANDROID_SYSROOT)/usr/include -isystem \$(ANDROID_SYSROOT)/usr/include/\$(ANDROID_TRIPLE) -B\$(ANDROID_LINK_SYSROOT)/lib -D__ANDROID_API__=\$(ANDROID_API) -O3 -fomit-frame-pointer -Wall::-D_REENTRANT::-ldl:BN_LLONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${armv4_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", ++"android64-aarch64-clang","clang:-target aarch64-none-linux-android --gcc-toolchain=\$(ANDROID_GCC_TOOLCHAIN) --sysroot \$(ANDROID_LINK_SYSROOT) -isystem \$(ANDROID_SYSROOT)/usr/include -isystem \$(ANDROID_SYSROOT)/usr/include/\$(ANDROID_TRIPLE) -B\$(ANDROID_LINK_SYSROOT)/lib -D__ANDROID_API__=\$(ANDROID_API) -O3 -fomit-frame-pointer -Wall::-D_REENTRANT::-ldl:SIXTY_FOUR_BIT_LONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${aarch64_asm}:linux64:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", ++"android-mips-clang","clang:-target mipsel-none-linux-android --gcc-toolchain=\$(ANDROID_GCC_TOOLCHAIN) --sysroot \$(ANDROID_LINK_SYSROOT) -isystem \$(ANDROID_SYSROOT)/usr/include -isystem \$(ANDROID_SYSROOT)/usr/include/\$(ANDROID_TRIPLE) -B\$(ANDROID_LINK_SYSROOT)/lib -D__ANDROID_API__=\$(ANDROID_API) -O3 -Wall::-D_REENTRANT::-ldl:BN_LLONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${mips32_asm}:o32:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", + + #### *BSD [do see comment about ${BSDthreads} above!] + "BSD-generic32","gcc:-O3 -fomit-frame-pointer -Wall::${BSDthreads}:::BN_LLONG RC2_CHAR RC4_INDEX DES_INT DES_UNROLL:${no_asm}:dlfcn:bsd-gcc-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", +diff -Naur org/crypto/bn/asm/armv4-gf2m.pl mod/crypto/bn/asm/armv4-gf2m.pl +--- org/crypto/bn/asm/armv4-gf2m.pl 2017-05-25 05:54:34.000000000 -0700 ++++ mod/crypto/bn/asm/armv4-gf2m.pl 2018-01-17 20:36:12.508421200 -0800 +@@ -213,8 +213,8 @@ + .align 5 + .LNEON: + ldr r12, [sp] @ 5th argument +- vmov.32 $a, r2, r1 +- vmov.32 $b, r12, r3 ++ vmov $a, r2, r1 ++ vmov $b, r12, r3 + vmov.i64 $k48, #0x0000ffffffffffff + vmov.i64 $k32, #0x00000000ffffffff + vmov.i64 $k16, #0x000000000000ffff +diff -Naur org/crypto/sha/asm/sha256-armv4.pl mod/crypto/sha/asm/sha256-armv4.pl +--- org/crypto/sha/asm/sha256-armv4.pl 2017-05-25 05:54:34.000000000 -0700 ++++ mod/crypto/sha/asm/sha256-armv4.pl 2018-01-17 20:36:12.518242800 -0800 +@@ -576,6 +576,7 @@ + my @MSG=map("q$_",(8..11)); + my ($W0,$W1,$ABCD_SAVE,$EFGH_SAVE)=map("q$_",(12..15)); + my $Ktbl="r3"; ++my $Temp="r4"; + + $code.=<<___; + #if __ARM_MAX_ARCH__>=7 && !defined(__KERNEL__) +@@ -591,7 +592,13 @@ + sha256_block_data_order_armv8: + .LARMv8: + vld1.32 {$ABCD,$EFGH},[$ctx] +-# ifdef __thumb2__ ++# if defined(__clang__) ++ stmdb sp!,{r4,lr} ++ adr $Ktbl,.LARMv8 ++ ldr $Temp,=K256 ++ sub $Temp,$Ktbl,$Temp ++ sub $Ktbl,$Ktbl,$Temp ++# elif defined(__thumb2__) + adr $Ktbl,.LARMv8 + sub $Ktbl,$Ktbl,#.LARMv8-K256 + # else +@@ -655,7 +662,12 @@ + + vst1.32 {$ABCD,$EFGH},[$ctx] + ++# ifdef __clang__ ++ ldmia sp!,{r4,pc} ++# else + ret @ bx lr ++# endif ++ + .size sha256_block_data_order_armv8,.-sha256_block_data_order_armv8 + #endif + ___ +diff -Naur org/Makefile.org mod/Makefile.org +--- org/Makefile.org 2017-05-25 05:54:38.000000000 -0700 ++++ mod/Makefile.org 2018-01-17 20:36:12.532553700 -0800 +@@ -540,7 +540,7 @@ + @$(MAKE) SDIRS='$(SDIRS)' clean + @$(MAKE) TAR='$(TAR)' TARFLAGS='$(TARFLAGS)' $(DISTTARVARS) tar + +-install: all install_docs install_sw ++install: install_docs install_sw + + install_sw: + @$(PERL) $(TOP)/util/mkdir-p.pl $(INSTALL_PREFIX)$(INSTALLTOP)/bin \ diff --git a/Build_android/openssl/openssl-1.0.2m.patch b/Build_android/openssl/openssl-1.0.2m.patch new file mode 100644 index 0000000000..8314b1e7fd --- /dev/null +++ b/Build_android/openssl/openssl-1.0.2m.patch @@ -0,0 +1,108 @@ +This patch applies several changes that enable OpenSSL 1.0.2m to be built +for Android using either Clang or GCC toolchains. + +An alias for the android-armv7 target, named android-armeabi, is added for +compatability with the OpenSSL 1.1.0 configuration target names. Support for +the AArch64 archicture is also added, as well as targets using the Clang +compiler. + +Clang does not recognize some of the ARM assembly nmenonics that are used in +OpenSSL. In particular, the 'adrl' pseudo instruction is not supported. To +further complicate matters, Clang doesn't support immediate fixup values so +the alternative adr/sub sequence used for the Thumb2 code path cannot be +used either. Instead it is replaced with a sequence of instructions that +computes the offset at runtime. It utilizes register r4 for computing the +intermediate result, which is first saved to and later restored from the +stack. The upstream bug in LLVM can be found here: +https://llvm.org/bugs/show_bug.cgi?id=24350 + +diff -Naur org/Configure mod/Configure +--- org/Configure 2017-11-02 07:32:57.000000000 -0700 ++++ mod/Configure 2018-01-17 20:39:03.152448900 -0800 +@@ -471,10 +471,17 @@ + "linux-alpha+bwx-ccc","ccc:-fast -readonly_strings -DL_ENDIAN::-D_REENTRANT:::SIXTY_FOUR_BIT_LONG RC4_CHAR RC4_CHUNK DES_INT DES_PTR DES_RISC1 DES_UNROLL:${alpha_asm}", + + # Android: linux-* but without pointers to headers and libs. +-"android","gcc:-mandroid -I\$(ANDROID_DEV)/include -B\$(ANDROID_DEV)/lib -O3 -fomit-frame-pointer -Wall::-D_REENTRANT::-ldl:BN_LLONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${no_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", +-"android-x86","gcc:-mandroid -I\$(ANDROID_DEV)/include -B\$(ANDROID_DEV)/lib -O3 -fomit-frame-pointer -Wall::-D_REENTRANT::-ldl:BN_LLONG ${x86_gcc_des} ${x86_gcc_opts}:".eval{my $asm=${x86_elf_asm};$asm=~s/:elf/:android/;$asm}.":dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", +-"android-armv7","gcc:-march=armv7-a -mandroid -I\$(ANDROID_DEV)/include -B\$(ANDROID_DEV)/lib -O3 -fomit-frame-pointer -Wall::-D_REENTRANT::-ldl:BN_LLONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${armv4_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", +-"android-mips","gcc:-mandroid -I\$(ANDROID_DEV)/include -B\$(ANDROID_DEV)/lib -O3 -Wall::-D_REENTRANT::-ldl:BN_LLONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${mips32_asm}:o32:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", ++"android","gcc:-mandroid --sysroot \$(ANDROID_LINK_SYSROOT) -isystem \$(ANDROID_SYSROOT)/usr/include -isystem \$(ANDROID_SYSROOT)/usr/include/\$(ANDROID_TRIPLE) -B\$(ANDROID_LINK_SYSROOT)/lib -D__ANDROID_API__=\$(ANDROID_API) -O3 -fomit-frame-pointer -Wall::-D_REENTRANT::-ldl:BN_LLONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${no_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", ++"android-x86","gcc:-mandroid --sysroot \$(ANDROID_LINK_SYSROOT) -isystem \$(ANDROID_SYSROOT)/usr/include -isystem \$(ANDROID_SYSROOT)/usr/include/\$(ANDROID_TRIPLE) -B\$(ANDROID_LINK_SYSROOT)/lib -D__ANDROID_API__=\$(ANDROID_API) -O3 -fomit-frame-pointer -Wall::-D_REENTRANT::-ldl:BN_LLONG ${x86_gcc_des} ${x86_gcc_opts}:".eval{my $asm=${x86_elf_asm};$asm=~s/:elf/:android/;$asm}.":dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", ++"android-armv7","gcc:-march=armv7-a -mandroid --sysroot \$(ANDROID_LINK_SYSROOT) -isystem \$(ANDROID_SYSROOT)/usr/include -isystem \$(ANDROID_SYSROOT)/usr/include/\$(ANDROID_TRIPLE) -B\$(ANDROID_LINK_SYSROOT)/lib -D__ANDROID_API__=\$(ANDROID_API) -O3 -fomit-frame-pointer -Wall::-D_REENTRANT::-ldl:BN_LLONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${armv4_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", ++"android-armeabi","gcc:-march=armv7-a -mandroid --sysroot \$(ANDROID_LINK_SYSROOT) -isystem \$(ANDROID_SYSROOT)/usr/include -isystem \$(ANDROID_SYSROOT)/usr/include/\$(ANDROID_TRIPLE) -B\$(ANDROID_LINK_SYSROOT)/lib -D__ANDROID_API__=\$(ANDROID_API) -O3 -fomit-frame-pointer -Wall::-D_REENTRANT::-ldl:BN_LLONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${armv4_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", ++"android64-aarch64","gcc:-march=armv8-a -mandroid --sysroot \$(ANDROID_LINK_SYSROOT) -isystem \$(ANDROID_SYSROOT)/usr/include -isystem \$(ANDROID_SYSROOT)/usr/include/\$(ANDROID_TRIPLE) -B\$(ANDROID_LINK_SYSROOT)/lib -D__ANDROID_API__=\$(ANDROID_API) -O3 -fomit-frame-pointer -Wall::-D_REENTRANT::-ldl:SIXTY_FOUR_BIT_LONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${aarch64_asm}:linux64:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", ++"android-mips","gcc:-mandroid --sysroot \$(ANDROID_LINK_SYSROOT) -isystem \$(ANDROID_SYSROOT)/usr/include -isystem \$(ANDROID_SYSROOT)/usr/include/\$(ANDROID_TRIPLE) -B\$(ANDROID_LINK_SYSROOT)/lib -D__ANDROID_API__=\$(ANDROID_API) -O3 -Wall::-D_REENTRANT::-ldl:BN_LLONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${mips32_asm}:o32:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", ++"android-x86-clang","clang:-target i686-none-linux-android --gcc-toolchain=\$(ANDROID_GCC_TOOLCHAIN) --sysroot \$(ANDROID_LINK_SYSROOT) -isystem \$(ANDROID_SYSROOT)/usr/include -isystem \$(ANDROID_SYSROOT)/usr/include/\$(ANDROID_TRIPLE) -B\$(ANDROID_LINK_SYSROOT)/lib -D__ANDROID_API__=\$(ANDROID_API) -O3 -fomit-frame-pointer -Wall::-D_REENTRANT::-ldl:BN_LLONG ${x86_gcc_des} ${x86_gcc_opts}:".eval{my $asm=${x86_elf_asm};$asm=~s/:elf/:android/;$asm}.":dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", ++"android-armv7-clang","clang:-target armv7-none-linux-androideabi --gcc-toolchain=\$(ANDROID_GCC_TOOLCHAIN) --sysroot \$(ANDROID_LINK_SYSROOT) -isystem \$(ANDROID_SYSROOT)/usr/include -isystem \$(ANDROID_SYSROOT)/usr/include/\$(ANDROID_TRIPLE) -B\$(ANDROID_LINK_SYSROOT)/lib -D__ANDROID_API__=\$(ANDROID_API) -O3 -fomit-frame-pointer -Wall::-D_REENTRANT::-ldl:BN_LLONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${armv4_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", ++"android-armeabi-clang","clang:-target armv7-none-linux-androideabi --gcc-toolchain=\$(ANDROID_GCC_TOOLCHAIN) --sysroot \$(ANDROID_LINK_SYSROOT) -isystem \$(ANDROID_SYSROOT)/usr/include -isystem \$(ANDROID_SYSROOT)/usr/include/\$(ANDROID_TRIPLE) -B\$(ANDROID_LINK_SYSROOT)/lib -D__ANDROID_API__=\$(ANDROID_API) -O3 -fomit-frame-pointer -Wall::-D_REENTRANT::-ldl:BN_LLONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${armv4_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", ++"android64-aarch64-clang","clang:-target aarch64-none-linux-android --gcc-toolchain=\$(ANDROID_GCC_TOOLCHAIN) --sysroot \$(ANDROID_LINK_SYSROOT) -isystem \$(ANDROID_SYSROOT)/usr/include -isystem \$(ANDROID_SYSROOT)/usr/include/\$(ANDROID_TRIPLE) -B\$(ANDROID_LINK_SYSROOT)/lib -D__ANDROID_API__=\$(ANDROID_API) -O3 -fomit-frame-pointer -Wall::-D_REENTRANT::-ldl:SIXTY_FOUR_BIT_LONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${aarch64_asm}:linux64:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", ++"android-mips-clang","clang:-target mipsel-none-linux-android --gcc-toolchain=\$(ANDROID_GCC_TOOLCHAIN) --sysroot \$(ANDROID_LINK_SYSROOT) -isystem \$(ANDROID_SYSROOT)/usr/include -isystem \$(ANDROID_SYSROOT)/usr/include/\$(ANDROID_TRIPLE) -B\$(ANDROID_LINK_SYSROOT)/lib -D__ANDROID_API__=\$(ANDROID_API) -O3 -Wall::-D_REENTRANT::-ldl:BN_LLONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${mips32_asm}:o32:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", + + #### *BSD [do see comment about ${BSDthreads} above!] + "BSD-generic32","gcc:-O3 -fomit-frame-pointer -Wall::${BSDthreads}:::BN_LLONG RC2_CHAR RC4_INDEX DES_INT DES_UNROLL:${no_asm}:dlfcn:bsd-gcc-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", +diff -Naur org/crypto/bn/asm/armv4-gf2m.pl mod/crypto/bn/asm/armv4-gf2m.pl +--- org/crypto/bn/asm/armv4-gf2m.pl 2017-11-02 07:32:57.000000000 -0700 ++++ mod/crypto/bn/asm/armv4-gf2m.pl 2018-01-17 20:39:03.163187500 -0800 +@@ -213,8 +213,8 @@ + .align 5 + .LNEON: + ldr r12, [sp] @ 5th argument +- vmov.32 $a, r2, r1 +- vmov.32 $b, r12, r3 ++ vmov $a, r2, r1 ++ vmov $b, r12, r3 + vmov.i64 $k48, #0x0000ffffffffffff + vmov.i64 $k32, #0x00000000ffffffff + vmov.i64 $k16, #0x000000000000ffff +diff -Naur org/crypto/sha/asm/sha256-armv4.pl mod/crypto/sha/asm/sha256-armv4.pl +--- org/crypto/sha/asm/sha256-armv4.pl 2017-11-02 07:32:58.000000000 -0700 ++++ mod/crypto/sha/asm/sha256-armv4.pl 2018-01-17 20:39:03.173547800 -0800 +@@ -576,6 +576,7 @@ + my @MSG=map("q$_",(8..11)); + my ($W0,$W1,$ABCD_SAVE,$EFGH_SAVE)=map("q$_",(12..15)); + my $Ktbl="r3"; ++my $Temp="r4"; + + $code.=<<___; + #if __ARM_MAX_ARCH__>=7 && !defined(__KERNEL__) +@@ -591,7 +592,13 @@ + sha256_block_data_order_armv8: + .LARMv8: + vld1.32 {$ABCD,$EFGH},[$ctx] +-# ifdef __thumb2__ ++# if defined(__clang__) ++ stmdb sp!,{r4,lr} ++ adr $Ktbl,.LARMv8 ++ ldr $Temp,=K256 ++ sub $Temp,$Ktbl,$Temp ++ sub $Ktbl,$Ktbl,$Temp ++# elif defined(__thumb2__) + adr $Ktbl,.LARMv8 + sub $Ktbl,$Ktbl,#.LARMv8-K256 + # else +@@ -655,7 +662,12 @@ + + vst1.32 {$ABCD,$EFGH},[$ctx] + ++# ifdef __clang__ ++ ldmia sp!,{r4,pc} ++# else + ret @ bx lr ++# endif ++ + .size sha256_block_data_order_armv8,.-sha256_block_data_order_armv8 + #endif + ___ +diff -Naur org/Makefile.org mod/Makefile.org +--- org/Makefile.org 2017-11-02 07:32:57.000000000 -0700 ++++ mod/Makefile.org 2018-01-17 20:39:03.187911200 -0800 +@@ -540,7 +540,7 @@ + @$(MAKE) SDIRS='$(SDIRS)' clean + @$(MAKE) TAR='$(TAR)' TARFLAGS='$(TARFLAGS)' $(DISTTARVARS) tar + +-install: all install_docs install_sw ++install: install_docs install_sw + + install_sw: + @$(PERL) $(TOP)/util/mkdir-p.pl $(INSTALL_PREFIX)$(INSTALLTOP)/bin \ diff --git a/Build_android/openssl/openssl-1.0.2n.patch b/Build_android/openssl/openssl-1.0.2n.patch new file mode 100644 index 0000000000..7e96205923 --- /dev/null +++ b/Build_android/openssl/openssl-1.0.2n.patch @@ -0,0 +1,108 @@ +This patch applies several changes that enable OpenSSL 1.0.2n to be built +for Android using either Clang or GCC toolchains. + +An alias for the android-armv7 target, named android-armeabi, is added for +compatability with the OpenSSL 1.1.0 configuration target names. Support for +the AArch64 archicture is also added, as well as targets using the Clang +compiler. + +Clang does not recognize some of the ARM assembly nmenonics that are used in +OpenSSL. In particular, the 'adrl' pseudo instruction is not supported. To +further complicate matters, Clang doesn't support immediate fixup values so +the alternative adr/sub sequence used for the Thumb2 code path cannot be +used either. Instead it is replaced with a sequence of instructions that +computes the offset at runtime. It utilizes register r4 for computing the +intermediate result, which is first saved to and later restored from the +stack. The upstream bug in LLVM can be found here: +https://llvm.org/bugs/show_bug.cgi?id=24350 + +diff -Naur org/Configure mod/Configure +--- org/Configure 2017-12-07 05:16:38.000000000 -0800 ++++ mod/Configure 2018-01-17 20:41:03.880613500 -0800 +@@ -471,10 +471,17 @@ + "linux-alpha+bwx-ccc","ccc:-fast -readonly_strings -DL_ENDIAN::-D_REENTRANT:::SIXTY_FOUR_BIT_LONG RC4_CHAR RC4_CHUNK DES_INT DES_PTR DES_RISC1 DES_UNROLL:${alpha_asm}", + + # Android: linux-* but without pointers to headers and libs. +-"android","gcc:-mandroid -I\$(ANDROID_DEV)/include -B\$(ANDROID_DEV)/lib -O3 -fomit-frame-pointer -Wall::-D_REENTRANT::-ldl:BN_LLONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${no_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", +-"android-x86","gcc:-mandroid -I\$(ANDROID_DEV)/include -B\$(ANDROID_DEV)/lib -O3 -fomit-frame-pointer -Wall::-D_REENTRANT::-ldl:BN_LLONG ${x86_gcc_des} ${x86_gcc_opts}:".eval{my $asm=${x86_elf_asm};$asm=~s/:elf/:android/;$asm}.":dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", +-"android-armv7","gcc:-march=armv7-a -mandroid -I\$(ANDROID_DEV)/include -B\$(ANDROID_DEV)/lib -O3 -fomit-frame-pointer -Wall::-D_REENTRANT::-ldl:BN_LLONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${armv4_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", +-"android-mips","gcc:-mandroid -I\$(ANDROID_DEV)/include -B\$(ANDROID_DEV)/lib -O3 -Wall::-D_REENTRANT::-ldl:BN_LLONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${mips32_asm}:o32:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", ++"android","gcc:-mandroid --sysroot \$(ANDROID_LINK_SYSROOT) -isystem \$(ANDROID_SYSROOT)/usr/include -isystem \$(ANDROID_SYSROOT)/usr/include/\$(ANDROID_TRIPLE) -B\$(ANDROID_LINK_SYSROOT)/lib -D__ANDROID_API__=\$(ANDROID_API) -O3 -fomit-frame-pointer -Wall::-D_REENTRANT::-ldl:BN_LLONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${no_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", ++"android-x86","gcc:-mandroid --sysroot \$(ANDROID_LINK_SYSROOT) -isystem \$(ANDROID_SYSROOT)/usr/include -isystem \$(ANDROID_SYSROOT)/usr/include/\$(ANDROID_TRIPLE) -B\$(ANDROID_LINK_SYSROOT)/lib -D__ANDROID_API__=\$(ANDROID_API) -O3 -fomit-frame-pointer -Wall::-D_REENTRANT::-ldl:BN_LLONG ${x86_gcc_des} ${x86_gcc_opts}:".eval{my $asm=${x86_elf_asm};$asm=~s/:elf/:android/;$asm}.":dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", ++"android-armv7","gcc:-march=armv7-a -mandroid --sysroot \$(ANDROID_LINK_SYSROOT) -isystem \$(ANDROID_SYSROOT)/usr/include -isystem \$(ANDROID_SYSROOT)/usr/include/\$(ANDROID_TRIPLE) -B\$(ANDROID_LINK_SYSROOT)/lib -D__ANDROID_API__=\$(ANDROID_API) -O3 -fomit-frame-pointer -Wall::-D_REENTRANT::-ldl:BN_LLONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${armv4_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", ++"android-armeabi","gcc:-march=armv7-a -mandroid --sysroot \$(ANDROID_LINK_SYSROOT) -isystem \$(ANDROID_SYSROOT)/usr/include -isystem \$(ANDROID_SYSROOT)/usr/include/\$(ANDROID_TRIPLE) -B\$(ANDROID_LINK_SYSROOT)/lib -D__ANDROID_API__=\$(ANDROID_API) -O3 -fomit-frame-pointer -Wall::-D_REENTRANT::-ldl:BN_LLONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${armv4_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", ++"android64-aarch64","gcc:-march=armv8-a -mandroid --sysroot \$(ANDROID_LINK_SYSROOT) -isystem \$(ANDROID_SYSROOT)/usr/include -isystem \$(ANDROID_SYSROOT)/usr/include/\$(ANDROID_TRIPLE) -B\$(ANDROID_LINK_SYSROOT)/lib -D__ANDROID_API__=\$(ANDROID_API) -O3 -fomit-frame-pointer -Wall::-D_REENTRANT::-ldl:SIXTY_FOUR_BIT_LONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${aarch64_asm}:linux64:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", ++"android-mips","gcc:-mandroid --sysroot \$(ANDROID_LINK_SYSROOT) -isystem \$(ANDROID_SYSROOT)/usr/include -isystem \$(ANDROID_SYSROOT)/usr/include/\$(ANDROID_TRIPLE) -B\$(ANDROID_LINK_SYSROOT)/lib -D__ANDROID_API__=\$(ANDROID_API) -O3 -Wall::-D_REENTRANT::-ldl:BN_LLONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${mips32_asm}:o32:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", ++"android-x86-clang","clang:-target i686-none-linux-android --gcc-toolchain=\$(ANDROID_GCC_TOOLCHAIN) --sysroot \$(ANDROID_LINK_SYSROOT) -isystem \$(ANDROID_SYSROOT)/usr/include -isystem \$(ANDROID_SYSROOT)/usr/include/\$(ANDROID_TRIPLE) -B\$(ANDROID_LINK_SYSROOT)/lib -D__ANDROID_API__=\$(ANDROID_API) -O3 -fomit-frame-pointer -Wall::-D_REENTRANT::-ldl:BN_LLONG ${x86_gcc_des} ${x86_gcc_opts}:".eval{my $asm=${x86_elf_asm};$asm=~s/:elf/:android/;$asm}.":dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", ++"android-armv7-clang","clang:-target armv7-none-linux-androideabi --gcc-toolchain=\$(ANDROID_GCC_TOOLCHAIN) --sysroot \$(ANDROID_LINK_SYSROOT) -isystem \$(ANDROID_SYSROOT)/usr/include -isystem \$(ANDROID_SYSROOT)/usr/include/\$(ANDROID_TRIPLE) -B\$(ANDROID_LINK_SYSROOT)/lib -D__ANDROID_API__=\$(ANDROID_API) -O3 -fomit-frame-pointer -Wall::-D_REENTRANT::-ldl:BN_LLONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${armv4_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", ++"android-armeabi-clang","clang:-target armv7-none-linux-androideabi --gcc-toolchain=\$(ANDROID_GCC_TOOLCHAIN) --sysroot \$(ANDROID_LINK_SYSROOT) -isystem \$(ANDROID_SYSROOT)/usr/include -isystem \$(ANDROID_SYSROOT)/usr/include/\$(ANDROID_TRIPLE) -B\$(ANDROID_LINK_SYSROOT)/lib -D__ANDROID_API__=\$(ANDROID_API) -O3 -fomit-frame-pointer -Wall::-D_REENTRANT::-ldl:BN_LLONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${armv4_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", ++"android64-aarch64-clang","clang:-target aarch64-none-linux-android --gcc-toolchain=\$(ANDROID_GCC_TOOLCHAIN) --sysroot \$(ANDROID_LINK_SYSROOT) -isystem \$(ANDROID_SYSROOT)/usr/include -isystem \$(ANDROID_SYSROOT)/usr/include/\$(ANDROID_TRIPLE) -B\$(ANDROID_LINK_SYSROOT)/lib -D__ANDROID_API__=\$(ANDROID_API) -O3 -fomit-frame-pointer -Wall::-D_REENTRANT::-ldl:SIXTY_FOUR_BIT_LONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${aarch64_asm}:linux64:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", ++"android-mips-clang","clang:-target mipsel-none-linux-android --gcc-toolchain=\$(ANDROID_GCC_TOOLCHAIN) --sysroot \$(ANDROID_LINK_SYSROOT) -isystem \$(ANDROID_SYSROOT)/usr/include -isystem \$(ANDROID_SYSROOT)/usr/include/\$(ANDROID_TRIPLE) -B\$(ANDROID_LINK_SYSROOT)/lib -D__ANDROID_API__=\$(ANDROID_API) -O3 -Wall::-D_REENTRANT::-ldl:BN_LLONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${mips32_asm}:o32:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", + + #### *BSD [do see comment about ${BSDthreads} above!] + "BSD-generic32","gcc:-O3 -fomit-frame-pointer -Wall::${BSDthreads}:::BN_LLONG RC2_CHAR RC4_INDEX DES_INT DES_UNROLL:${no_asm}:dlfcn:bsd-gcc-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", +diff -Naur org/crypto/bn/asm/armv4-gf2m.pl mod/crypto/bn/asm/armv4-gf2m.pl +--- org/crypto/bn/asm/armv4-gf2m.pl 2017-12-07 05:16:38.000000000 -0800 ++++ mod/crypto/bn/asm/armv4-gf2m.pl 2018-01-17 20:41:03.891956700 -0800 +@@ -213,8 +213,8 @@ + .align 5 + .LNEON: + ldr r12, [sp] @ 5th argument +- vmov.32 $a, r2, r1 +- vmov.32 $b, r12, r3 ++ vmov $a, r2, r1 ++ vmov $b, r12, r3 + vmov.i64 $k48, #0x0000ffffffffffff + vmov.i64 $k32, #0x00000000ffffffff + vmov.i64 $k16, #0x000000000000ffff +diff -Naur org/crypto/sha/asm/sha256-armv4.pl mod/crypto/sha/asm/sha256-armv4.pl +--- org/crypto/sha/asm/sha256-armv4.pl 2017-12-07 05:16:38.000000000 -0800 ++++ mod/crypto/sha/asm/sha256-armv4.pl 2018-01-17 20:41:03.901983600 -0800 +@@ -576,6 +576,7 @@ + my @MSG=map("q$_",(8..11)); + my ($W0,$W1,$ABCD_SAVE,$EFGH_SAVE)=map("q$_",(12..15)); + my $Ktbl="r3"; ++my $Temp="r4"; + + $code.=<<___; + #if __ARM_MAX_ARCH__>=7 && !defined(__KERNEL__) +@@ -591,7 +592,13 @@ + sha256_block_data_order_armv8: + .LARMv8: + vld1.32 {$ABCD,$EFGH},[$ctx] +-# ifdef __thumb2__ ++# if defined(__clang__) ++ stmdb sp!,{r4,lr} ++ adr $Ktbl,.LARMv8 ++ ldr $Temp,=K256 ++ sub $Temp,$Ktbl,$Temp ++ sub $Ktbl,$Ktbl,$Temp ++# elif defined(__thumb2__) + adr $Ktbl,.LARMv8 + sub $Ktbl,$Ktbl,#.LARMv8-K256 + # else +@@ -655,7 +662,12 @@ + + vst1.32 {$ABCD,$EFGH},[$ctx] + ++# ifdef __clang__ ++ ldmia sp!,{r4,pc} ++# else + ret @ bx lr ++# endif ++ + .size sha256_block_data_order_armv8,.-sha256_block_data_order_armv8 + #endif + ___ +diff -Naur org/Makefile.org mod/Makefile.org +--- org/Makefile.org 2017-12-07 05:16:38.000000000 -0800 ++++ mod/Makefile.org 2018-01-17 20:41:03.916748800 -0800 +@@ -540,7 +540,7 @@ + @$(MAKE) SDIRS='$(SDIRS)' clean + @$(MAKE) TAR='$(TAR)' TARFLAGS='$(TARFLAGS)' $(DISTTARVARS) tar + +-install: all install_docs install_sw ++install: install_docs install_sw + + install_sw: + @$(PERL) $(TOP)/util/mkdir-p.pl $(INSTALL_PREFIX)$(INSTALLTOP)/bin \ diff --git a/Build_android/openssl/openssl-1.1.0g.patch b/Build_android/openssl/openssl-1.1.0g.patch new file mode 100644 index 0000000000..77a92779d7 --- /dev/null +++ b/Build_android/openssl/openssl-1.1.0g.patch @@ -0,0 +1,76 @@ +This patch applies several changes that enable OpenSSL 1.1.0g to be built +for Android using either Clang or GCC toolchains. + +diff -Naur org/Configurations/10-main.conf mod/Configurations/10-main.conf +--- org/Configurations/10-main.conf 2017-11-02 07:29:01.000000000 -0700 ++++ mod/Configurations/10-main.conf 2018-01-18 10:59:41.675138500 -0800 +@@ -910,15 +910,27 @@ + # systems are perfectly capable of executing binaries targeting + # Froyo. Keep in mind that in the nutshell Android builds are + # about JNI, i.e. shared libraries, not applications. +- cflags => add(picker(default => "-mandroid -fPIC --sysroot=\$(CROSS_SYSROOT) -Wa,--noexecstack")), ++ cflags => add(picker(default => "-mandroid -fPIC --sysroot=\$(ANDROID_LINK_SYSROOT) -isystem \$(ANDROID_SYSROOT)/usr/include -isystem \$(ANDROID_SYSROOT)/usr/include/\$(ANDROID_TRIPLE) -D__ANDROID_API__=\$(ANDROID_API) -Wa,--noexecstack")), + bin_cflags => "-pie", + }, ++ "android-clang" => { ++ inherit_from => [ "linux-generic32" ], ++ cc => "clang", ++ cflags => add(picker(default => "-fPIC --gcc-toolchain=\$(ANDROID_GCC_TOOLCHAIN) --sysroot=\$(ANDROID_LINK_SYSROOT) -isystem \$(ANDROID_SYSROOT)/usr/include -isystem \$(ANDROID_SYSROOT)/usr/include/\$(ANDROID_TRIPLE) -D__ANDROID_API__=\$(ANDROID_API) -Wextra -Wno-missing-field-initializers -Wno-unused-parameter -Qunused-arguments -Wa,--noexecstack")), ++}, + "android-x86" => { + inherit_from => [ "android", asm("x86_asm") ], + cflags => add(picker(release => "-fomit-frame-pointer")), + bn_ops => "BN_LLONG", + perlasm_scheme => "android", + }, ++ "android-x86-clang" => { ++ inherit_from => [ "android-clang", asm("x86_asm") ], ++ cflags => add(picker(default => "-target i686-none-linux-android", ++ release => "-fomit-frame-pointer")), ++ bn_ops => "BN_LLONG", ++ perlasm_scheme => "android", ++ }, + ################################################################ + # Contemporary Android applications can provide multiple JNI + # providers in .apk, targeting multiple architectures. Among +@@ -943,20 +955,38 @@ + "android-armeabi" => { + inherit_from => [ "android", asm("armv4_asm") ], + }, ++ "android-armeabi-clang" => { ++ inherit_from => [ "android-clang", asm("armv4_asm") ], ++ cflags => add("-target armv7-none-linux-androideabi"), ++ }, + "android-mips" => { + inherit_from => [ "android", asm("mips32_asm") ], + perlasm_scheme => "o32", + }, +- ++ "android-mips-clang" => { ++ inherit_from => [ "android-clang", asm("mips32_asm") ], ++ cflags => add("-target mipsel-none-linux-android"), ++ perlasm_scheme => "o32", ++ }, + "android64" => { + inherit_from => [ "linux-generic64" ], +- cflags => add(picker(default => "-mandroid -fPIC --sysroot=\$(CROSS_SYSROOT) -Wa,--noexecstack")), ++ cflags => add(picker(default => "-mandroid -fPIC --sysroot=\$(ANDROID_LINK_SYSROOT) -isystem \$(ANDROID_SYSROOT)/usr/include -isystem \$(ANDROID_SYSROOT)/usr/include/\$(ANDROID_TRIPLE) -D__ANDROID_API__=\$(ANDROID_API) -Wa,--noexecstack")), + bin_cflags => "-pie", + }, ++ "android64-clang" => { ++ inherit_from => [ "linux-generic64" ], ++ cc => "clang", ++ cflags => add(picker(default => "-fPIC --gcc-toolchain=\$(ANDROID_GCC_TOOLCHAIN) --sysroot=\$(ANDROID_LINK_SYSROOT) -isystem \$(ANDROID_SYSROOT)/usr/include -isystem \$(ANDROID_SYSROOT)/usr/include/\$(ANDROID_TRIPLE) -D__ANDROID_API__=\$(ANDROID_API) -Wextra -Wno-missing-field-initializers -Wno-unused-parameter -Qunused-arguments -Wa,--noexecstack")), ++ }, + "android64-aarch64" => { + inherit_from => [ "android64", asm("aarch64_asm") ], + perlasm_scheme => "linux64", + }, ++ "android64-aarch64-clang" => { ++ inherit_from => [ "android64-clang", asm("aarch64_asm") ], ++ cflags => add("-target aarch64-none-linux-android"), ++ perlasm_scheme => "linux64", ++ }, + + #### *BSD + "BSD-generic32" => { diff --git a/Build_iOS/CMakeLists.txt b/Build_iOS/CMakeLists.txt index 1c1ea90152..3c1e37c130 100644 --- a/Build_iOS/CMakeLists.txt +++ b/Build_iOS/CMakeLists.txt @@ -1,5 +1,5 @@ project(casablanca-ios NONE) -cmake_minimum_required(VERSION 2.6) +cmake_minimum_required(VERSION 3.1) enable_testing() @@ -7,33 +7,18 @@ if (CMAKE_XCODE_ATTRIBUTE_IPHONEOS_DEPLOYMENT_TARGET) set (ENV{CMAKE_XCODE_ATTRIBUTE_IPHONEOS_DEPLOYMENT_TARGET} ${CMAKE_XCODE_ATTRIBUTE_IPHONEOS_DEPLOYMENT_TARGET}) endif() -set(TOOLCHAIN_FILE "${CMAKE_CURRENT_SOURCE_DIR}/iOS.cmake") - -set(SIM_BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/build.i386" CACHE INTERNAL "") -set(SIM_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../Release" CACHE INTERNAL "") +set(TOOLCHAIN_FILE "${CMAKE_CURRENT_SOURCE_DIR}/ios-cmake/ios.toolchain.cmake") set(SIM64_BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/build.x86_64" CACHE INTERNAL "") set(SIM64_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../Release" CACHE INTERNAL "") -set(ARM_BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/build.arm" CACHE INTERNAL "") -set(ARM_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../Release" CACHE INTERNAL "") +set(ARM64_BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/build.arm64" CACHE INTERNAL "") +set(ARM64_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../Release" CACHE INTERNAL "") add_test(NAME ios_runner WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/../Release/tests/common/testrunner/ios COMMAND xcodebuild test -project ios_runner.xcodeproj -configuration=${CMAKE_BUILD_TYPE} -scheme ios_runner -destination "platform=iOS Simulator,name=iPhone 6" LIBRARY_SEARCH_PATH=${SIM_BINARY_DIR} ) -file(MAKE_DIRECTORY ${SIM_BINARY_DIR}) -execute_process(WORKING_DIRECTORY ${SIM_BINARY_DIR} - COMMAND ${CMAKE_COMMAND} - -GXcode - -DCMAKE_TOOLCHAIN_FILE=${TOOLCHAIN_FILE} - -DIOS_PLATFORM=SIMULATOR - -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} - -DCMAKE_C_COMPILER=${CLANG_C_COMPILER} - -DCMAKE_CXX_COMPILER=${CLANG_CXX_COMPILER} - "${SIM_SOURCE_DIR}" - ) - file(MAKE_DIRECTORY ${SIM64_BINARY_DIR}) execute_process(WORKING_DIRECTORY ${SIM64_BINARY_DIR} COMMAND ${CMAKE_COMMAND} @@ -41,33 +26,20 @@ execute_process(WORKING_DIRECTORY ${SIM64_BINARY_DIR} -DCMAKE_TOOLCHAIN_FILE=${TOOLCHAIN_FILE} -DIOS_PLATFORM=SIMULATOR64 -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} - -DCMAKE_C_COMPILER=${CLANG_C_COMPILER} - -DCMAKE_CXX_COMPILER=${CLANG_CXX_COMPILER} "${SIM64_SOURCE_DIR}" ) -file(MAKE_DIRECTORY ${ARM_BINARY_DIR}) -execute_process(WORKING_DIRECTORY ${ARM_BINARY_DIR} +file(MAKE_DIRECTORY ${ARM64_BINARY_DIR}) +execute_process(WORKING_DIRECTORY ${ARM64_BINARY_DIR} COMMAND ${CMAKE_COMMAND} -GXcode -DCMAKE_TOOLCHAIN_FILE=${TOOLCHAIN_FILE} - -DIOS_PLATFORM=OS + -DIOS_PLATFORM=OS64 -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} - -DCMAKE_C_COMPILER=${CLANG_C_COMPILER} - -DCMAKE_CXX_COMPILER=${CLANG_CXX_COMPILER} - "${ARM_SOURCE_DIR}" + "${ARM64_SOURCE_DIR}" ) -## Simulator i386 version -add_custom_target(sim - COMMAND ${CMAKE_COMMAND} - --build ${SIM_BINARY_DIR} - --config ${CMAKE_BUILD_TYPE} - COMMENT "Building for i386 (simulator)" - VERBATIM -) - ## Simulator x86_64 version add_custom_target(sim64 COMMAND ${CMAKE_COMMAND} @@ -77,12 +49,12 @@ add_custom_target(sim64 VERBATIM ) -## ARM version -add_custom_target(arm +## ARM64 version +add_custom_target(arm64 COMMAND ${CMAKE_COMMAND} - --build ${ARM_BINARY_DIR} + --build ${ARM64_BINARY_DIR} --config ${CMAKE_BUILD_TYPE} - COMMENT "Building for armv7, armv7s, arm64" + COMMENT "Building for arm64" VERBATIM ) @@ -91,16 +63,13 @@ add_custom_command( OUTPUT ${LIB_CPPREST} COMMAND lipo -create -output "${CMAKE_CURRENT_BINARY_DIR}/${LIB_CPPREST}" - ${SIM_BINARY_DIR}/Binaries/${CMAKE_BUILD_TYPE}/${LIB_CPPREST} ${SIM64_BINARY_DIR}/Binaries/${CMAKE_BUILD_TYPE}/${LIB_CPPREST} - ${ARM_BINARY_DIR}/Binaries/${CMAKE_BUILD_TYPE}/${LIB_CPPREST} + ${ARM64_BINARY_DIR}/Binaries/${CMAKE_BUILD_TYPE}/${LIB_CPPREST} DEPENDS - sim sim64 - arm - "${SIM_BINARY_DIR}/Binaries/${CMAKE_BUILD_TYPE}/${LIB_CPPREST}" + arm64 "${SIM64_BINARY_DIR}/Binaries/${CMAKE_BUILD_TYPE}/${LIB_CPPREST}" - "${ARM_BINARY_DIR}/Binaries/${CMAKE_BUILD_TYPE}/${LIB_CPPREST}" + "${ARM64_BINARY_DIR}/Binaries/${CMAKE_BUILD_TYPE}/${LIB_CPPREST}" VERBATIM ) diff --git a/Build_iOS/configure.sh b/Build_iOS/configure.sh index 8b0599512c..1c97e5c238 100755 --- a/Build_iOS/configure.sh +++ b/Build_iOS/configure.sh @@ -2,42 +2,52 @@ set -e if [ ! -e boost.framework ] - then - git clone -n https://github.com/faithfracture/Apple-Boost-BuildScript Apple-Boost-BuildScript - pushd Apple-Boost-BuildScript - git checkout 86f7570fceaef00846cc75f59c61474758fc65cb - BOOST_LIBS="thread chrono filesystem regex system random" ./boost.sh - popd - mv Apple-Boost-BuildScript/build/boost/1.63.0/ios/framework/boost.framework . - mv boost.framework/Versions/A/Headers boost.headers - mkdir -p boost.framework/Versions/A/Headers - mv boost.headers boost.framework/Versions/A/Headers/boost +then + git clone https://github.com/faithfracture/Apple-Boost-BuildScript Apple-Boost-BuildScript + pushd ./Apple-Boost-BuildScript + git checkout 1b94ec2e2b5af1ee036d9559b96e70c113846392 + BOOST_LIBS="thread chrono filesystem regex system random" ./boost.sh -ios -tvos + popd + mv Apple-Boost-BuildScript/build/boost/1.67.0/ios/framework/boost.framework . + mv boost.framework/Versions/A/Headers boost.headers + mkdir -p boost.framework/Versions/A/Headers + mv boost.headers boost.framework/Versions/A/Headers/boost fi if [ ! -e openssl/lib/libcrypto.a ] - then - git clone --depth=1 https://github.com/x2on/OpenSSL-for-iPhone.git - pushd OpenSSL-for-iPhone - ./build-libssl.sh - popd - mkdir -p openssl/lib - cp -r OpenSSL-for-iPhone/bin/iPhoneOS9.2-armv7.sdk/include openssl - cp OpenSSL-for-iPhone/include/LICENSE openssl - lipo -create -output openssl/lib/libssl.a OpenSSL-for-iPhone/bin/iPhone*/lib/libssl.a - lipo -create -output openssl/lib/libcrypto.a OpenSSL-for-iPhone/bin/iPhone*/lib/libcrypto.a +then + git clone --depth=1 https://github.com/x2on/OpenSSL-for-iPhone.git + pushd OpenSSL-for-iPhone + git checkout 10019638e80e8a8a5fc19642a840d8a69fac7349 + ./build-libssl.sh + popd + mkdir -p openssl/lib + if [ -e OpenSSL-for-iPhone/bin/iPhoneOS11.4-arm64.sdk/include ] + then + cp -r OpenSSL-for-iPhone/bin/iPhoneOS11.4-arm64.sdk/include openssl + elif [ -e OpenSSL-for-iPhone/bin/iPhoneOS12.0-arm64.sdk/include ] + then + cp -r OpenSSL-for-iPhone/bin/iPhoneOS12.0-arm64.sdk/include openssl + else + echo 'Could not find OpenSSL for iPhone' + exit 1 + fi + cp OpenSSL-for-iPhone/include/LICENSE openssl + lipo -create -output openssl/lib/libssl.a OpenSSL-for-iPhone/bin/iPhone*/lib/libssl.a + lipo -create -output openssl/lib/libcrypto.a OpenSSL-for-iPhone/bin/iPhone*/lib/libcrypto.a fi -if [ ! -e ios-cmake/toolchain/iOS.cmake ] - then - git clone https://github.com/cristeab/ios-cmake.git - pushd ios-cmake - git apply ../fix_ios_cmake_compiler.patch - popd +if [ ! -e ios-cmake/ios.toolchain.cmake ] +then + git clone https://github.com/leetal/ios-cmake + pushd ios-cmake + git checkout 6b30f4cfeab5567041d38e79507e642056fb9fd4 + popd fi -mkdir -p build.ios -pushd build.ios -cmake .. -DCMAKE_BUILD_TYPE=Release +mkdir -p build.release.ios +pushd build.release.ios +cmake -DCMAKE_BUILD_TYPE=Release .. make popd echo "====" diff --git a/CONTRIBUTORS.txt b/CONTRIBUTORS.txt index ca43881905..7e11cc2478 100644 --- a/CONTRIBUTORS.txt +++ b/CONTRIBUTORS.txt @@ -22,6 +22,7 @@ adish LeonidCSIT kreuzerkrieg evanc +Jesse Towner (jwtowner) Abinsula s.r.l. Gianfranco Costamagna (LocutusOfBorg) diff --git a/README.md b/README.md index 6739483ebf..391027675b 100644 --- a/README.md +++ b/README.md @@ -21,6 +21,10 @@ With [apt-get](https://launchpad.net/ubuntu/+source/casablanca/2.8.0-2build2) on ``` $ sudo apt-get install libcpprest-dev ``` +With [dnf](https://apps.fedoraproject.org/packages/cpprest) on Fedora +``` +$ sudo dnf install cpprest-devel +``` With [brew](https://github.com/Homebrew/homebrew-core/blob/master/Formula/cpprestsdk.rb) on OSX ``` $ brew install cpprestsdk diff --git a/Release/CMakeLists.txt b/Release/CMakeLists.txt index 398ca41e73..94cebe51bf 100644 --- a/Release/CMakeLists.txt +++ b/Release/CMakeLists.txt @@ -11,7 +11,7 @@ endif() set(CPPREST_VERSION_MAJOR 2) set(CPPREST_VERSION_MINOR 10) -set(CPPREST_VERSION_REVISION 6) +set(CPPREST_VERSION_REVISION 7) enable_testing() @@ -113,7 +113,7 @@ else() endif() set(WARNINGS) -set(ANDROID_STL_FLAGS) +set(ANDROID_LIBS) add_definitions(-DBOOST_ALL_DYN_LINK) @@ -122,27 +122,8 @@ if(IOS) # The cxx_flags must be reset here, because the ios-cmake toolchain file unfortunately sets "-headerpad_max_install_names" which is not a valid clang flag. set(CMAKE_CXX_FLAGS "-fvisibility=hidden") elseif(ANDROID) - if(ARM) - set(LIBCXX_STL "${ANDROID_NDK}/sources/cxx-stl/gnu-libstdc++/4.8/libs/armeabi-v7a/thumb/libgnustl_static.a") - else() - set(LIBCXX_STL "${ANDROID_NDK}/sources/cxx-stl/gnu-libstdc++/4.8/libs/x86/libgnustl_static.a") - endif() # These are used in the shared library case - set(ANDROID_STL_FLAGS - ${LIBCXX_STL} - atomic - dl - gcc - c - m - -nodefaultlibs - ) - - include_directories(SYSTEM - "${ANDROID_NDK}/sources/cxx-stl/gnu-libstdc++/4.8/include" - "${ANDROID_NDK}/sources/cxx-stl/gnu-libstdc++/4.8/libs/armeabi-v7a/include" - "${ANDROID_NDK}/sources/cxx-stl/gnu-libstdc++/4.8/include/backward" - ) + set(ANDROID_LIBS atomic dl) elseif(UNIX) # This includes OSX elseif(WIN32) add_definitions(-DUNICODE -D_UNICODE -DWIN32 -D_SCL_SECURE_NO_WARNINGS) @@ -167,16 +148,15 @@ if(CMAKE_CXX_COMPILER_ID MATCHES "Clang" OR IOS) message("-- Setting clang options") if(ANDROID) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-pedantic") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-attributes -Wno-pointer-arith") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-pedantic -Wno-attributes -Wno-pointer-arith") elseif(CMAKE_SYSTEM_NAME MATCHES "Linux") set(WARNINGS -Wall -Wextra -Wcast-qual -Wconversion -Wformat=2 -Winit-self -Winvalid-pch -Wmissing-format-attribute -Wmissing-include-dirs -Wpacked -Wredundant-decls) - set(LINUX_SUPPRESSIONS -Wno-overloaded-virtual -Wno-sign-conversion -Wno-deprecated -Wno-unknown-pragmas -Wno-reorder -Wno-char-subscripts -Wno-switch -Wno-unused-parameter -Wno-unused-variable -Wno-deprecated -Wno-unused-value -Wno-unknown-warning-option -Wno-return-type-c-linkage -Wno-unused-function -Wno-sign-compare -Wno-shorten-64-to-32 -Wno-unused-local-typedefs -Wno-delete-non-virtual-dtor -Wno-unused-lambda-capture) + set(LINUX_SUPPRESSIONS -Wno-overloaded-virtual -Wno-sign-conversion -Wno-deprecated -Wno-unknown-pragmas -Wno-reorder -Wno-char-subscripts -Wno-switch -Wno-unused-parameter -Wno-unused-variable -Wno-deprecated -Wno-unused-value -Wno-unknown-warning-option -Wno-return-type-c-linkage -Wno-unused-function -Wno-sign-compare -Wno-shorten-64-to-32 -Wno-unused-local-typedefs) set(WARNINGS ${WARNINGS} ${LINUX_SUPPRESSIONS}) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-return-type-c-linkage -Wno-unneeded-internal-declaration") else() set(WARNINGS -Wall -Wextra -Wcast-qual -Wconversion -Wformat=2 -Winit-self -Winvalid-pch -Wmissing-format-attribute -Wmissing-include-dirs -Wpacked -Wredundant-decls) - set(OSX_SUPPRESSIONS -Wno-overloaded-virtual -Wno-sign-conversion -Wno-deprecated -Wno-unknown-pragmas -Wno-reorder -Wno-char-subscripts -Wno-switch -Wno-unused-parameter -Wno-unused-variable -Wno-deprecated -Wno-unused-value -Wno-unknown-warning-option -Wno-return-type-c-linkage -Wno-unused-function -Wno-sign-compare -Wno-shorten-64-to-32 -Wno-unused-local-typedefs -Wno-delete-non-virtual-dtor -Wno-unused-lambda-capture) + set(OSX_SUPPRESSIONS -Wno-overloaded-virtual -Wno-sign-conversion -Wno-deprecated -Wno-unknown-pragmas -Wno-reorder -Wno-char-subscripts -Wno-switch -Wno-unused-parameter -Wno-unused-variable -Wno-deprecated -Wno-unused-value -Wno-unknown-warning-option -Wno-return-type-c-linkage -Wno-unused-function -Wno-sign-compare -Wno-shorten-64-to-32 -Wno-unused-local-typedefs) set(WARNINGS ${WARNINGS} ${OSX_SUPPRESSIONS}) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++ -Wno-return-type-c-linkage -Wno-unneeded-internal-declaration") @@ -190,10 +170,6 @@ elseif(CMAKE_CXX_COMPILER_ID MATCHES "GNU") message("-- Setting gcc options") set(WARNINGS -Wall -Wextra -Wunused-parameter -Wcast-align -Wcast-qual -Wconversion -Wformat=2 -Winit-self -Winvalid-pch -Wmissing-format-attribute -Wmissing-include-dirs -Wpacked -Wredundant-decls -Wunreachable-code) - if (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS "6.0") - set(WARNINGS ${WARNINGS} -Wno-format-truncation) - endif() - set(LD_FLAGS "${LD_FLAGS} -Wl,-z,defs") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -fno-strict-aliasing") @@ -247,7 +223,7 @@ function(add_casablanca_test NAME SOURCES_VAR) cpprest common_utilities unittestpp - ${ANDROID_STL_FLAGS} + ${ANDROID_LIBS} ) if (BUILD_SHARED_LIBS) add_test(NAME ${NAME} diff --git a/Release/cmake/cpprest_find_boost.cmake b/Release/cmake/cpprest_find_boost.cmake index 67f5dad9b8..0138893bd6 100644 --- a/Release/cmake/cpprest_find_boost.cmake +++ b/Release/cmake/cpprest_find_boost.cmake @@ -1,3 +1,23 @@ +macro(cpprestsdk_find_boost_android_package) + set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE NEVER) + set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY NEVER) + set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) + if(CMAKE_HOST_WIN32) + set(WIN32 1) + set(UNIX) + elseif(CMAKE_HOST_APPLE) + set(APPLE 1) + set(UNIX) + endif() + find_package(${ARGN}) + set(APPLE) + set(WIN32) + set(UNIX 1) + set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) + set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) + set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM ONLY) +endmacro() + function(cpprest_find_boost) if(TARGET cpprestsdk_boost_internal) return() @@ -16,13 +36,13 @@ function(cpprest_find_boost) elseif(ANDROID) set(Boost_COMPILER "-clang") if(ARM) - set(BOOST_ROOT "${CMAKE_BINARY_DIR}/../Boost-for-Android/build" CACHE INTERNAL "") - set(BOOST_LIBRARYDIR "${CMAKE_BINARY_DIR}/../Boost-for-Android/build/lib" CACHE INTERNAL "") + set(BOOST_ROOT "${CMAKE_BINARY_DIR}/../Boost-for-Android/build/out/armeabi-v7a" CACHE INTERNAL "") + set(BOOST_LIBRARYDIR "${CMAKE_BINARY_DIR}/../Boost-for-Android/build/out/armeabi-v7a/lib" CACHE INTERNAL "") else() - set(BOOST_ROOT "${CMAKE_BINARY_DIR}/../Boost-for-Android-x86/build" CACHE INTERNAL "") - set(BOOST_LIBRARYDIR "${CMAKE_BINARY_DIR}/../Boost-for-Android-x86/build/lib" CACHE INTERNAL "") + set(BOOST_ROOT "${CMAKE_BINARY_DIR}/../Boost-for-Android/build/out/x86" CACHE INTERNAL "") + set(BOOST_LIBRARYDIR "${CMAKE_BINARY_DIR}/../Boost-for-Android/build/out/x86/lib" CACHE INTERNAL "") endif() - find_host_package(Boost 1.55 EXACT REQUIRED COMPONENTS random system thread filesystem chrono atomic) + cpprestsdk_find_boost_android_package(Boost ${BOOST_VERSION} EXACT REQUIRED COMPONENTS random system thread filesystem chrono atomic) elseif(UNIX) find_package(Boost REQUIRED COMPONENTS random system thread filesystem chrono atomic date_time regex) else() diff --git a/Release/cmake/cpprest_find_websocketpp.cmake b/Release/cmake/cpprest_find_websocketpp.cmake index 260311f0a3..94ea81a473 100644 --- a/Release/cmake/cpprest_find_websocketpp.cmake +++ b/Release/cmake/cpprest_find_websocketpp.cmake @@ -7,9 +7,11 @@ function(cpprest_find_websocketpp) if(WEBSOCKETPP_FOUND) message("-- Found websocketpp version " ${WEBSOCKETPP_VERSION} " on system") set(WEBSOCKETPP_INCLUDE_DIR ${WEBSOCKETPP_INCLUDE_DIR} CACHE INTERNAL "") - else() + elseif(EXISTS ${PROJECT_SOURCE_DIR}/libs/websocketpp/CMakeLists.txt) message("-- websocketpp not found, using the embedded version") set(WEBSOCKETPP_INCLUDE_DIR ${PROJECT_SOURCE_DIR}/libs/websocketpp CACHE INTERNAL "") + else() + message(FATAL_ERROR "-- websocketpp not found and embedded version not present; try `git submodule update --init` and run CMake again") endif() cpprest_find_boost() @@ -22,4 +24,4 @@ function(cpprest_find_websocketpp) cpprestsdk_boost_internal cpprestsdk_openssl_internal ) -endfunction() \ No newline at end of file +endfunction() diff --git a/Release/include/cpprest/astreambuf.h b/Release/include/cpprest/astreambuf.h index baff9a934d..30e8962e5d 100644 --- a/Release/include/cpprest/astreambuf.h +++ b/Release/include/cpprest/astreambuf.h @@ -13,10 +13,11 @@ ****/ #pragma once +#include +#include +#include #include #include -#include -#include #include "pplx/pplxtasks.h" #include "cpprest/details/basic_types.h" @@ -342,7 +343,7 @@ namespace streams /// Gets a pointer to the next already allocated contiguous block of data. /// /// A reference to a pointer variable that will hold the address of the block on success. - /// The number of contiguous characters available at the address in 'ptr.' + /// The number of contiguous characters available at the address in 'ptr'. /// true if the operation succeeded, false otherwise. /// /// A return of false does not necessarily indicate that a subsequent read operation would fail, only that @@ -745,7 +746,10 @@ namespace streams std::exception_ptr m_currentException; // The in/out mode for the buffer - bool m_stream_can_read, m_stream_can_write, m_stream_read_eof, m_alloced; + std::atomic m_stream_can_read; + std::atomic m_stream_can_write; + std::atomic m_stream_read_eof; + std::atomic m_alloced; private: @@ -1016,7 +1020,7 @@ namespace streams /// Gets a pointer to the next already allocated contiguous block of data. /// /// A reference to a pointer variable that will hold the address of the block on success. - /// The number of contiguous characters available at the address in 'ptr.' + /// The number of contiguous characters available at the address in 'ptr'. /// true if the operation succeeded, false otherwise. /// /// A return of false does not necessarily indicate that a subsequent read operation would fail, only that @@ -1208,5 +1212,3 @@ namespace streams }; }} - - diff --git a/Release/include/cpprest/asyncrt_utils.h b/Release/include/cpprest/asyncrt_utils.h index 03bd6fbf90..963d88771e 100644 --- a/Release/include/cpprest/asyncrt_utils.h +++ b/Release/include/cpprest/asyncrt_utils.h @@ -424,7 +424,7 @@ namespace details } /// - /// Cross platform utility function for performing case insensitive string equality comparision. + /// Cross platform utility function for performing case insensitive string equality comparison. /// /// First string to compare. /// Second strong to compare. @@ -432,7 +432,7 @@ namespace details _ASYNCRTIMP bool __cdecl str_iequal(const std::string &left, const std::string &right) CPPREST_NOEXCEPT; /// - /// Cross platform utility function for performing case insensitive string equality comparision. + /// Cross platform utility function for performing case insensitive string equality comparison. /// /// First string to compare. /// Second strong to compare. @@ -440,7 +440,7 @@ namespace details _ASYNCRTIMP bool __cdecl str_iequal(const std::wstring &left, const std::wstring &right) CPPREST_NOEXCEPT; /// - /// Cross platform utility function for performing case insensitive string less-than comparision. + /// Cross platform utility function for performing case insensitive string less-than comparison. /// /// First string to compare. /// Second strong to compare. @@ -448,7 +448,7 @@ namespace details _ASYNCRTIMP bool __cdecl str_iless(const std::string &left, const std::string &right) CPPREST_NOEXCEPT; /// - /// Cross platform utility function for performing case insensitive string less-than comparision. + /// Cross platform utility function for performing case insensitive string less-than comparison. /// /// First string to compare. /// Second strong to compare. diff --git a/Release/include/cpprest/base_uri.h b/Release/include/cpprest/base_uri.h index 9448bb5d35..1aaefe9c2f 100644 --- a/Release/include/cpprest/base_uri.h +++ b/Release/include/cpprest/base_uri.h @@ -94,7 +94,7 @@ namespace web { /// /// A flexible, protocol independent URI implementation. /// - /// URI instances are immutable. Querying the various fields on an emtpy URI will return empty strings. Querying + /// URI instances are immutable. Querying the various fields on an empty URI will return empty strings. Querying /// various diagnostic members on an empty URI will return false. /// /// @@ -305,7 +305,7 @@ namespace web { /// A loopback URI is one which refers to a hostname or ip address with meaning only on the local machine. /// /// - /// Examples include "locahost", or ip addresses in the loopback range (127.0.0.0/24). + /// Examples include "localhost", or ip addresses in the loopback range (127.0.0.0/24). /// /// true if this URI references the local host, false otherwise. bool is_host_loopback() const diff --git a/Release/include/cpprest/containerstream.h b/Release/include/cpprest/containerstream.h index 63ead19f9b..71b2da843a 100644 --- a/Release/include/cpprest/containerstream.h +++ b/Release/include/cpprest/containerstream.h @@ -170,7 +170,7 @@ namespace Concurrency { namespace streams { /// Gets a pointer to the next already allocated contiguous block of data. /// /// A reference to a pointer variable that will hold the address of the block on success. - /// The number of contiguous characters available at the address in 'ptr.' + /// The number of contiguous characters available at the address in 'ptr'. /// true if the operation succeeded, false otherwise. /// /// A return of false does not necessarily indicate that a subsequent read operation would fail, only that diff --git a/Release/include/cpprest/details/basic_types.h b/Release/include/cpprest/details/basic_types.h index eadba01684..e9477c736a 100644 --- a/Release/include/cpprest/details/basic_types.h +++ b/Release/include/cpprest/details/basic_types.h @@ -20,8 +20,10 @@ #include "cpprest/details/cpprest_compat.h" #ifndef _WIN32 -# define __STDC_LIMIT_MACROS -# include +#ifndef __STDC_LIMIT_MACROS +#define __STDC_LIMIT_MACROS +#endif +#include #else #include #endif diff --git a/Release/include/cpprest/details/cpprest_compat.h b/Release/include/cpprest/details/cpprest_compat.h index 1c48552eff..25b3e45bda 100644 --- a/Release/include/cpprest/details/cpprest_compat.h +++ b/Release/include/cpprest/details/cpprest_compat.h @@ -14,7 +14,7 @@ #pragma once -#if defined(_WIN32) // Settings specific to Windows +#if defined(_WIN32) #if _MSC_VER >= 1900 #define CPPREST_NOEXCEPT noexcept @@ -22,15 +22,13 @@ #else #define CPPREST_NOEXCEPT #define CPPREST_CONSTEXPR const -#endif +#endif // _MSC_VER >= 1900 #define CASABLANCA_UNREFERENCED_PARAMETER(x) (x) #include -#else // End settings specific to Windows - -// Settings common to all but Windows +#else // ^^^ _WIN32 ^^^ // vvv !_WIN32 vvv #define __declspec(x) __attribute__ ((x)) #define dllimport @@ -49,9 +47,10 @@ #if not defined __cdecl #if defined cdecl #define __cdecl __attribute__ ((cdecl)) -#else +#else // ^^^ defined cdecl ^^^ // vvv !defined cdecl vvv #define __cdecl -#endif +#endif // defined cdecl +#endif // not defined __cdecl #if defined(__ANDROID__) // This is needed to disable the use of __thread inside the boost library. @@ -61,30 +60,27 @@ // the .so from loading. #if not defined BOOST_ASIO_DISABLE_THREAD_KEYWORD_EXTENSION #define BOOST_ASIO_DISABLE_THREAD_KEYWORD_EXTENSION -#endif -#endif +#endif // not defined BOOST_ASIO_DISABLE_THREAD_KEYWORD_EXTENSION +#endif // defined(__ANDROID__) #ifdef __clang__ #include -#endif - -#endif // defined(__APPLE__) - -#endif +#endif // __clang__ +#endif // _WIN32 #ifdef _NO_ASYNCRTIMP #define _ASYNCRTIMP -#else +#else // ^^^ _NO_ASYNCRTIMP ^^^ // vvv !_NO_ASYNCRTIMP vvv #ifdef _ASYNCRT_EXPORT #define _ASYNCRTIMP __declspec(dllexport) -#else +#else // ^^^ _ASYNCRT_EXPORT ^^^ // vvv !_ASYNCRT_EXPORT vvv #define _ASYNCRTIMP __declspec(dllimport) -#endif -#endif +#endif // _ASYNCRT_EXPORT +#endif // _NO_ASYNCRTIMP #ifdef CASABLANCA_DEPRECATION_NO_WARNINGS #define CASABLANCA_DEPRECATED(x) #else #define CASABLANCA_DEPRECATED(x) __declspec(deprecated(x)) -#endif +#endif // CASABLANCA_DEPRECATION_NO_WARNINGS diff --git a/Release/include/cpprest/filestream.h b/Release/include/cpprest/filestream.h index b8b982556a..de1e0d60a5 100644 --- a/Release/include/cpprest/filestream.h +++ b/Release/include/cpprest/filestream.h @@ -12,8 +12,8 @@ ****/ #pragma once -#ifndef _CASA_FILE_STREAMS_H -#define _CASA_FILE_STREAMS_H +#ifndef CASA_FILE_STREAMS_H +#define CASA_FILE_STREAMS_H #include "cpprest/details/fileio.h" #include "cpprest/astreambuf.h" @@ -311,7 +311,7 @@ namespace details { /// /// Submits a block already allocated by the stream buffer. /// - /// Count of characters to be commited. + /// Count of characters to be committed. void _commit(size_t) { } @@ -320,7 +320,7 @@ namespace details { /// Gets a pointer to the next already allocated contiguous block of data. /// /// A reference to a pointer variable that will hold the address of the block on success. - /// The number of contiguous characters available at the address in 'ptr.' + /// The number of contiguous characters available at the address in 'ptr'. /// true if the operation succeeded, false otherwise. /// /// A return of false does not necessarily indicate that a subsequent read operation would fail, only that @@ -1033,7 +1033,7 @@ namespace details { } /// - /// Open a new ouput stream representing the given file. + /// Open a new output stream representing the given file. /// If the file does not exist, it will be create unless the folder or directory /// where it is to be found also does not exist. /// @@ -1079,7 +1079,7 @@ namespace details { } /// - /// Open a new ouput stream representing the given file. + /// Open a new output stream representing the given file. /// If the file does not exist, it will be create unless the folder or directory /// where it is to be found also does not exist. /// diff --git a/Release/include/cpprest/http_client.h b/Release/include/cpprest/http_client.h index 9ccd19e61f..935bad50ec 100644 --- a/Release/include/cpprest/http_client.h +++ b/Release/include/cpprest/http_client.h @@ -12,8 +12,8 @@ ****/ #pragma once -#ifndef _CASA_HTTP_CLIENT_H -#define _CASA_HTTP_CLIENT_H +#ifndef CASA_HTTP_CLIENT_H +#define CASA_HTTP_CLIENT_H #if defined (__cplusplus_winrt) #if !defined(__WRL_NO_DEFAULT_LIB__) @@ -257,7 +257,7 @@ class http_client_config /// /// Request that the server respond with a compressed body using Content-Encoding; to use Transfer-Encoding, do not - /// set this, and specify a vector of pointers + /// set this, and specify a vector of pointers /// to the set_decompress_factories method of the object for the request. /// If true and the server does not support compression, this will have no effect. /// The response body is internally decompressed before the consumer receives the data. diff --git a/Release/include/cpprest/http_compression.h b/Release/include/cpprest/http_compression.h index b6df43e026..0430ab2285 100644 --- a/Release/include/cpprest/http_compression.h +++ b/Release/include/cpprest/http_compression.h @@ -117,9 +117,15 @@ _ASYNCRTIMP bool supported(); /// namespace algorithm { -constexpr const utility::char_t *GZIP = _XPLATSTR("gzip"); -constexpr const utility::char_t *DEFLATE = _XPLATSTR("deflate"); -constexpr const utility::char_t *BROTLI = _XPLATSTR("br"); +#if defined(_MSC_VER) && _MSC_VER < 1900 +const utility::char_t * const GZIP = _XPLATSTR("gzip"); +const utility::char_t * const DEFLATE = _XPLATSTR("deflate"); +const utility::char_t * const BROTLI = _XPLATSTR("br"); +#else // ^^^ VS2013 and before ^^^ // vvv VS2015+, and everything else vvv +constexpr const utility::char_t * const GZIP = _XPLATSTR("gzip"); +constexpr const utility::char_t * const DEFLATE = _XPLATSTR("deflate"); +constexpr const utility::char_t * const BROTLI = _XPLATSTR("br"); +#endif /// /// Test whether cpprestsdk was built with built-in compression support and diff --git a/Release/include/cpprest/http_listener.h b/Release/include/cpprest/http_listener.h index c8059e02ba..ccb0ae9659 100644 --- a/Release/include/cpprest/http_listener.h +++ b/Release/include/cpprest/http_listener.h @@ -10,8 +10,8 @@ ****/ #pragma once -#ifndef _CASA_HTTP_LISTENER_H -#define _CASA_HTTP_LISTENER_H +#ifndef CASA_HTTP_LISTENER_H +#define CASA_HTTP_LISTENER_H #include #include @@ -270,7 +270,16 @@ class http_listener /// Destructor frees any held resources. /// /// Call close() before allowing a listener to be destroyed. - _ASYNCRTIMP ~http_listener(); + ~http_listener() { + if (m_impl) { + // As a safe guard close the listener if not already done. + // Users are required to call close, but this is just a safeguard. + try { + m_impl->close().wait(); + } catch (...) { + } + } + } /// /// Asynchronously open the listener, i.e. start accepting requests. diff --git a/Release/include/cpprest/http_msg.h b/Release/include/cpprest/http_msg.h index 39649ef833..ae7c498e4d 100644 --- a/Release/include/cpprest/http_msg.h +++ b/Release/include/cpprest/http_msg.h @@ -432,7 +432,7 @@ class http_msg_base /// By default this is an invalid stream. The user could set the instream on /// a request by calling set_request_stream(...). This would also be set when /// set_body() is called - a stream from the body is constructed and set. - /// Even in the presense of msg body this stream could be invalid. An example + /// Even in the presence of msg body this stream could be invalid. An example /// would be when the user sets an ostream for the response. With that API the /// user does not provide the ability to read the msg body. /// Thus m_instream is valid when there is a msg body and it can actually be read @@ -878,6 +878,9 @@ class _http_request final : public http::details::http_msg_base, public std::ena http::method m_method; // Tracks whether or not a response has already been started for this message. + // 0 = No reply sent + // 1 = Usual reply sent + // 2 = Reply aborted by another thread; e.g. server shutdown pplx::details::atomic_long m_initiated_response; std::unique_ptr m_server_context; diff --git a/Release/include/cpprest/json.h b/Release/include/cpprest/json.h index 1e88ddd2f0..e817da4fba 100644 --- a/Release/include/cpprest/json.h +++ b/Release/include/cpprest/json.h @@ -12,8 +12,8 @@ ****/ #pragma once -#ifndef _CASA_JSON_H -#define _CASA_JSON_H +#ifndef CASA_JSON_H +#define CASA_JSON_H #include #include @@ -524,14 +524,14 @@ namespace json /// Compares two JSON values for equality. /// /// The JSON value to compare with. - /// True iff the values are equal. + /// True if the values are equal. _ASYNCRTIMP bool operator==(const value& other) const; /// /// Compares two JSON values for inequality. /// /// The JSON value to compare with. - /// True iff the values are unequal. + /// True if the values are unequal. bool operator!=(const value& other) const { return !((*this) == other); @@ -1226,7 +1226,7 @@ namespace json /// /// Checks if there are any elements in the JSON object. /// - /// True iff empty. + /// True if empty. bool empty() const { return m_elements.empty(); @@ -1374,7 +1374,7 @@ namespace json /// /// Converts the JSON number to unsigned int32. /// - /// An usigned int32 representation of the number + /// An unsigned int32 representation of the number uint32_t to_uint32() const { if (m_type == double_type) @@ -1420,7 +1420,7 @@ namespace json /// Compares two JSON numbers for equality. /// /// The JSON number to compare with. - /// True iff the numbers are equal. + /// True if the numbers are equal. bool operator==(const number &other) const { if (m_type != other.m_type) @@ -1689,7 +1689,7 @@ namespace json utility::string_t m_string; - // There are significant performance gains that can be made by knowning whether + // There are significant performance gains that can be made by knowing whether // or not a character that requires escaping is present. bool m_has_escape_char; static bool has_escape_chars(const _String &str); @@ -1797,7 +1797,7 @@ namespace json for(auto iter = m_object.begin(); iter != m_object.end(); ++iter) { reserveSize += iter->first.length() + 2; // 2 for quotes - size_t valueSize = iter->second.size() * 20; // Multipler by each object/array element + size_t valueSize = iter->second.size() * 20; // Multiply by each object/array element if(valueSize == 0) { if(iter->second.type() == json::value::String) diff --git a/Release/include/cpprest/oauth1.h b/Release/include/cpprest/oauth1.h index 24a10c7d79..c15c1d1723 100644 --- a/Release/include/cpprest/oauth1.h +++ b/Release/include/cpprest/oauth1.h @@ -12,8 +12,8 @@ ****/ #pragma once -#ifndef _CASA_OAUTH1_H -#define _CASA_OAUTH1_H +#ifndef CASA_OAUTH1_H +#define CASA_OAUTH1_H #include "cpprest/http_msg.h" #include "cpprest/details/web_utilities.h" diff --git a/Release/include/cpprest/oauth2.h b/Release/include/cpprest/oauth2.h index 7afccdc3e1..016eba83ff 100644 --- a/Release/include/cpprest/oauth2.h +++ b/Release/include/cpprest/oauth2.h @@ -12,8 +12,8 @@ ****/ #pragma once -#ifndef _CASA_OAUTH2_H -#define _CASA_OAUTH2_H +#ifndef CASA_OAUTH2_H +#define CASA_OAUTH2_H #include "cpprest/http_msg.h" #include "cpprest/details/web_utilities.h" diff --git a/Release/include/cpprest/producerconsumerstream.h b/Release/include/cpprest/producerconsumerstream.h index 4e10872f45..b2467a7ca7 100644 --- a/Release/include/cpprest/producerconsumerstream.h +++ b/Release/include/cpprest/producerconsumerstream.h @@ -13,8 +13,8 @@ ****/ #pragma once -#ifndef _CASA_PRODUCER_CONSUMER_STREAMS_H -#define _CASA_PRODUCER_CONSUMER_STREAMS_H +#ifndef CASA_PRODUCER_CONSUMER_STREAMS_H +#define CASA_PRODUCER_CONSUMER_STREAMS_H #include #include @@ -178,7 +178,7 @@ namespace Concurrency { namespace streams { /// Gets a pointer to the next already allocated contiguous block of data. /// /// A reference to a pointer variable that will hold the address of the block on success. - /// The number of contiguous characters available at the address in 'ptr.' + /// The number of contiguous characters available at the address in 'ptr'. /// true if the operation succeeded, false otherwise. /// /// A return of false does not necessarily indicate that a subsequent read operation would fail, only that diff --git a/Release/include/cpprest/rawptrstream.h b/Release/include/cpprest/rawptrstream.h index 3fdbb99cb3..fe6e930a59 100644 --- a/Release/include/cpprest/rawptrstream.h +++ b/Release/include/cpprest/rawptrstream.h @@ -13,8 +13,8 @@ ****/ #pragma once -#ifndef _CASA_RAWPTR_STREAMS_H -#define _CASA_RAWPTR_STREAMS_H +#ifndef CASA_RAWPTR_STREAMS_H +#define CASA_RAWPTR_STREAMS_H #include #include @@ -205,7 +205,7 @@ namespace Concurrency { namespace streams { /// Gets a pointer to the next already allocated contiguous block of data. /// /// A reference to a pointer variable that will hold the address of the block on success. - /// The number of contiguous characters available at the address in 'ptr.' + /// The number of contiguous characters available at the address in 'ptr'. /// true if the operation succeeded, false otherwise. /// /// A return of false does not necessarily indicate that a subsequent read operation would fail, only that diff --git a/Release/include/cpprest/streams.h b/Release/include/cpprest/streams.h index d2923d3774..cf3ceb1140 100644 --- a/Release/include/cpprest/streams.h +++ b/Release/include/cpprest/streams.h @@ -12,8 +12,8 @@ ****/ #pragma once -#ifndef _CASA_STREAMS_H -#define _CASA_STREAMS_H +#ifndef CASA_STREAMS_H +#define CASA_STREAMS_H #include "cpprest/astreambuf.h" #include @@ -496,7 +496,7 @@ namespace Concurrency { namespace streams }; /// - /// Class used to handle asychronous parsing for basic_istream::extract. To support new + /// Class used to handle asynchronous parsing for basic_istream::extract. To support new /// types create a new template specialization and implement the parse function. /// template diff --git a/Release/include/cpprest/uri.h b/Release/include/cpprest/uri.h index a26618cf89..58f0434471 100644 --- a/Release/include/cpprest/uri.h +++ b/Release/include/cpprest/uri.h @@ -12,8 +12,8 @@ ****/ #pragma once -#ifndef _CASA_URI_H -#define _CASA_URI_H +#ifndef CASA_URI_H +#define CASA_URI_H #include "cpprest/base_uri.h" #include "cpprest/uri_builder.h" diff --git a/Release/include/cpprest/version.h b/Release/include/cpprest/version.h index cb47ab9d05..ef38ad4fe9 100644 --- a/Release/include/cpprest/version.h +++ b/Release/include/cpprest/version.h @@ -3,9 +3,8 @@ * Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. * */ -#define CPPREST_VERSION_REVISION 6 #define CPPREST_VERSION_MINOR 10 #define CPPREST_VERSION_MAJOR 2 +#define CPPREST_VERSION_REVISION 7 #define CPPREST_VERSION (CPPREST_VERSION_MAJOR*100000+CPPREST_VERSION_MINOR*100+CPPREST_VERSION_REVISION) - diff --git a/Release/include/cpprest/ws_client.h b/Release/include/cpprest/ws_client.h index 98f933e149..2ab1b665ff 100644 --- a/Release/include/cpprest/ws_client.h +++ b/Release/include/cpprest/ws_client.h @@ -10,8 +10,8 @@ ****/ #pragma once -#ifndef _CASA_WS_CLIENT_H -#define _CASA_WS_CLIENT_H +#ifndef CASA_WS_CLIENT_H +#define CASA_WS_CLIENT_H #include "cpprest/details/basic_types.h" @@ -142,7 +142,7 @@ class websocket_client_config } /// - /// Gets the server host name to usefor TLS Server Name Indication (SNI). + /// Gets the server host name to use for TLS Server Name Indication (SNI). /// /// Host name as a string. const utf8string & server_name() const diff --git a/Release/include/pplx/pplxcancellation_token.h b/Release/include/pplx/pplxcancellation_token.h index 634e4fafb3..ad729809b7 100644 --- a/Release/include/pplx/pplxcancellation_token.h +++ b/Release/include/pplx/pplxcancellation_token.h @@ -506,7 +506,7 @@ namespace details // // If a cancellation has occurred, the registration list is guaranteed to be empty if we've observed it under the auspices of the - // lock. In this case, we must synchronize with the cancelling thread to guarantee that the cancellation is finished by the time + // lock. In this case, we must synchronize with the canceling thread to guarantee that the cancellation is finished by the time // we return from this method. // if (!_M_registrations.empty()) diff --git a/Release/include/pplx/pplxlinux.h b/Release/include/pplx/pplxlinux.h index 78b6e1801a..fe75bc5e8a 100644 --- a/Release/include/pplx/pplxlinux.h +++ b/Release/include/pplx/pplxlinux.h @@ -29,7 +29,8 @@ #include #include #else -#include +#include +#include #include #endif @@ -58,7 +59,7 @@ namespace platform _PPLXIMP void _pplx_cdecl YieldExecution(); /// - /// Caputeres the callstack + /// Captures the callstack /// __declspec(noinline) inline static size_t CaptureCallstack(void **, size_t, size_t) { @@ -80,7 +81,7 @@ namespace platform static const unsigned int timeout_infinite = 0xFFFFFFFF; event_impl() - : _signaled(false) + : _signaled(false) { } @@ -209,7 +210,7 @@ namespace platform _M_cs.lock(); _M_owner = id; _M_recursionCount = 1; - } + } } void unlock() @@ -223,12 +224,12 @@ namespace platform { _M_owner = -1; _M_cs.unlock(); - } + } } private: cpprest_synchronization::mutex _M_cs; - volatile long _M_owner; + std::atomic _M_owner; long _M_recursionCount; }; @@ -298,7 +299,7 @@ namespace extensibility #else typedef details::linux_scheduler default_scheduler_t; #endif - + namespace details { /// diff --git a/Release/include/pplx/pplxtasks.h b/Release/include/pplx/pplxtasks.h index e784306d40..f7c3f58346 100644 --- a/Release/include/pplx/pplxtasks.h +++ b/Release/include/pplx/pplxtasks.h @@ -16,9 +16,27 @@ #ifndef _PPLXTASKS_H #define _PPLXTASKS_H +#include "cpprest/details/cpprest_compat.h" + #if (defined(_MSC_VER) && (_MSC_VER >= 1800)) && !CPPREST_FORCE_PPLX #include namespace pplx = Concurrency; + +namespace Concurrency +{ + +/// +/// Sets the ambient scheduler to be used by the PPL constructs. +/// +_ASYNCRTIMP void __cdecl set_cpprestsdk_ambient_scheduler(const std::shared_ptr& _Scheduler); + +/// +/// Gets the ambient scheduler to be used by the PPL constructs +/// +_ASYNCRTIMP const std::shared_ptr& __cdecl get_cpprestsdk_ambient_scheduler(); + +} // namespace Concurrency + #if (_MSC_VER >= 1900) #include namespace Concurrency { @@ -58,6 +76,7 @@ void cpprest_init(JavaVM*); #include #include #include +#include #if defined(_MSC_VER) #include @@ -175,7 +194,7 @@ template <> class task; #endif /// -/// Helper macro to determine how many stack frames need to be saved. When any number less or equal to 1 is specified, +/// Helper macro to determine how many stack frames need to be saved. When any number less or equal to 1 is specified, /// only one frame is captured and no stackwalk will be involved. Otherwise, the number of callstack frames will be captured. /// /// @@ -184,7 +203,7 @@ template <> class task; /// #if PPL_TASK_SAVE_FRAME_COUNT > 1 #if defined(__cplusplus_winrt) && !defined(_DEBUG) -#pragma message ("WARNING: Redefinning PPL_TASK_SAVE_FRAME_COUNT under Release build for non-desktop applications is not supported; only one frame will be captured!") +#pragma message ("WARNING: Redefining PPL_TASK_SAVE_FRAME_COUNT under Release build for non-desktop applications is not supported; only one frame will be captured!") #define _CAPTURE_CALLSTACK() ::pplx::details::_TaskCreationCallstack::_CaptureSingleFrameCallstack(_ReturnAddress()) #else #define _CAPTURE_CALLSTACK() ::pplx::details::_TaskCreationCallstack::_CaptureMultiFramesCallstack(PPL_TASK_SAVE_FRAME_COUNT) @@ -209,7 +228,7 @@ template <> class task; /// the canceled state. If you do not respond and continue execution, or return instead of calling /// cancel_current_task, the task will enter the completed state when it is done. /// state. -/// A task is not cancellable if it was created without a cancellation token. +/// A task is not cancelable if it was created without a cancellation token. /// /// /// @@ -270,7 +289,7 @@ namespace details { _TaskCreationCallstack _csc; _csc._M_frames.resize(_CaptureFrames); - // skip 2 frames to make sure callstack starts from user code + // skip 2 frames to make sure callstack starts from user code _csc._M_frames.resize(::pplx::details::platform::CaptureCallstack(&_csc._M_frames[0], 2, _CaptureFrames)); return _csc; } @@ -439,10 +458,10 @@ namespace details template task<_Type> _To_task(_Type t); - + template task _To_task_void(_Func f); - + struct _BadContinuationParamType{}; template auto _ReturnTypeHelper(_Type t, _Function _Func, int, int) -> decltype(_Func(_To_task(t))); @@ -739,7 +758,7 @@ namespace details { // We determine the origin of a task continuation by looking at where .then is called, so we can tell whether // to need to marshal the continuation back to the originating apartment. If an STA thread is in executing in - // a neutral aparment when it schedules a continuation, we will not marshal continuations back to the STA, + // a neutral apartment when it schedules a continuation, we will not marshal continuations back to the STA, // since variables used within a neutral apartment are expected to be apartment neutral. switch(_AptType) { @@ -871,13 +890,13 @@ namespace details std::vector<_Type^> Get() { - // Return vectory with the objects that are marshaled in the proper appartment + // Return vectory with the objects that are marshaled in the proper apartment std::vector<_Type^> _Return; _Return.reserve(_Result.size()); for (auto _PTask = _Result.begin(); _PTask != _Result.end(); ++_PTask) { - _Return.push_back(_PTask->Get()); // Platform::Agile will marshal the object to appropriate appartment if neccessary + _Return.push_back(_PTask->Get()); // Platform::Agile will marshal the object to appropriate apartment if necessary } return _Return; @@ -1128,7 +1147,7 @@ class task_continuation_context : public details::_ContextCallback /// The default continuation context. /// /// - /// The default context is used if you don't specifiy a continuation context when you call the then method. In Windows + /// The default context is used if you don't specify a continuation context when you call the then method. In Windows /// applications for Windows 7 and below, as well as desktop applications on Windows 8 and higher, the runtime determines where /// task continuations will execute. However, in a Windows Store app, the default continuation context for a continuation on an /// apartment aware task is the apartment where then is invoked. @@ -1322,7 +1341,7 @@ class task_options _M_CancellationToken(_TaskOptions.get_cancellation_token()), _M_ContinuationContext(_TaskOptions.get_continuation_context()), _M_HasCancellationToken(_TaskOptions.has_cancellation_token()), - _M_HasScheduler(_TaskOptions.has_scheduler()) + _M_HasScheduler(_TaskOptions.has_scheduler()) { } @@ -1430,10 +1449,10 @@ namespace details // This field gives inlining scheduling policy for current chore. _TaskInliningMode_t _M_inliningMode; - + virtual _Task_ptr_base _GetTaskImplBase() const = 0; - _ContinuationTaskHandleBase() : + _ContinuationTaskHandleBase() : _M_next(nullptr), _M_continuationContext(task_continuation_context::use_default()), _M_isTaskBasedContinuation(false), _M_inliningMode(details::_NoInline) { } @@ -1464,7 +1483,7 @@ namespace details VER_SET_CONDITION( _conditionMask, VER_MAJORVERSION, VER_GREATER_EQUAL ); VER_SET_CONDITION( _conditionMask, VER_MINORVERSION, VER_GREATER_EQUAL ); - if ( ::VerifyVersionInfo(&_osvi, VER_MAJORVERSION | VER_MINORVERSION, _conditionMask)) + if ( ::VerifyVersionInfo(&_osvi, VER_MAJORVERSION | VER_MINORVERSION, _conditionMask)) { _causality = 2; } @@ -1479,7 +1498,7 @@ namespace details #endif } - // Stateful logger rests inside task_impl_base. + // Stateful logger rests inside task_impl_base. struct _TaskEventLogger { _Task_impl_base *_M_task; @@ -1491,11 +1510,11 @@ namespace details { if (details::_IsCausalitySupported()) { - ::Windows::Foundation::Diagnostics::AsyncCausalityTracer::TraceOperationCreation(::Windows::Foundation::Diagnostics::CausalityTraceLevel::Required, ::Windows::Foundation::Diagnostics::CausalitySource::Library, - _PPLTaskCausalityPlatformID, reinterpret_cast(_M_task), + ::Windows::Foundation::Diagnostics::AsyncCausalityTracer::TraceOperationCreation(::Windows::Foundation::Diagnostics::CausalityTraceLevel::Required, ::Windows::Foundation::Diagnostics::CausalitySource::Library, + _PPLTaskCausalityPlatformID, reinterpret_cast(_M_task), _isContinuation ? "pplx::PPLTask::ScheduleContinuationTask" : "pplx::PPLTask::ScheduleTask", 0); _M_scheduled = true; - } + } } // It will log the cancel event but not canceled state. _LogTaskCompleted will log the terminal state, which includes cancel state. @@ -1506,7 +1525,7 @@ namespace details ::Windows::Foundation::Diagnostics::AsyncCausalityTracer::TraceOperationRelation(::Windows::Foundation::Diagnostics::CausalityTraceLevel::Important, ::Windows::Foundation::Diagnostics::CausalitySource::Library, _PPLTaskCausalityPlatformID, reinterpret_cast(_M_task), ::Windows::Foundation::Diagnostics::CausalityRelation::Cancel); - } + } } // Log when task reaches terminal state. Note: the task can reach a terminal state (by cancellation or exception) without having run @@ -1548,7 +1567,7 @@ namespace details _M_taskPostEventStarted = true; } } - + _TaskEventLogger(_Task_impl_base *_task): _M_task(_task) { _M_scheduled = false; @@ -1613,7 +1632,7 @@ namespace details { } - virtual ~_PPLTaskHandle() + virtual ~_PPLTaskHandle() { // Here is the sink of all task completion code paths _M_pTask->_M_taskEventLogger._LogTaskCompleted(); @@ -1690,13 +1709,13 @@ namespace details #pragma warning(push) #pragma warning(disable: 4355) #endif - _Task_impl_base(_CancellationTokenState * _PTokenState, scheduler_ptr _Scheduler_arg) + _Task_impl_base(_CancellationTokenState * _PTokenState, scheduler_ptr _Scheduler_arg) : _M_TaskState(_Created), _M_fFromAsync(false), _M_fUnwrappedTask(false), _M_pRegistration(nullptr), _M_Continuations(nullptr), _M_TaskCollection(_Scheduler_arg), - _M_taskEventLogger(this) + _M_taskEventLogger(this) { - // Set cancelation token + // Set cancellation token _M_pTokenState = _PTokenState; _ASSERTE(_M_pTokenState != nullptr); if (_M_pTokenState != _CancellationTokenState::_None()) @@ -1731,7 +1750,7 @@ namespace details else { // Task Continuations are 'scheduled' *inside* the chore that is executing on the ancestors's task group. If a continuation - // needs to be marshalled to a different apartment, instead of scheduling, we make a synchronous cross apartment COM + // needs to be marshaled to a different apartment, instead of scheduling, we make a synchronous cross apartment COM // call to execute the continuation. If it then happens to do something which waits on the ancestor (say it calls .get(), which // task based continuations are wont to do), waiting on the task group results in on the chore that is making this // synchronous callback, which causes a deadlock. To avoid this, we test the state ancestor's event , and we will NOT wait on @@ -1761,8 +1780,8 @@ namespace details // call to wait will receive this status. However, both cancellation and exceptions flowing through // tasks set state in the task impl itself. - // When it returns cancelled, either work chore or the cancel thread should already have set task's state - // properly -- cancelled state or completed state (because there was no interruption point). + // When it returns canceled, either work chore or the cancel thread should already have set task's state + // properly -- canceled state or completed state (because there was no interruption point). // For tasks with unwrapped tasks, we should not change the state of current task, since the unwrapped task are still running. _M_TaskCollection._RunAndWait(); } @@ -2041,7 +2060,7 @@ namespace details // Schedule a continuation to run void _ScheduleContinuationTask(_ContinuationTaskHandleBase * _PTaskHandle) { - + _M_taskEventLogger._LogScheduleTask(true); // Ensure that the continuation runs in proper context (this might be on a Concurrency Runtime thread or in a different Windows Runtime apartment) if (_PTaskHandle->_M_continuationContext._HasCapturedContext()) @@ -2227,7 +2246,7 @@ namespace details } #if _UITHREADCTXT_SUPPORT - // This method is used to throw an exepection in _Wait() if called within STA. We + // This method is used to throw an exception in _Wait() if called within STA. We // want the same behavior if _Wait is called on the UI thread. if (SUCCEEDED(CaptureUiThreadContext(nullptr))) { @@ -2286,11 +2305,11 @@ namespace details static void _AsyncInit(const typename _Task_ptr<_ReturnType>::_Type& _OuterTask, const task<_InternalReturnType> & _UnwrappedTask) { _ASSERTE(_OuterTask->_M_fUnwrappedTask && !_OuterTask->_IsCanceled()); - + // // We must ensure that continuations off _OuterTask (especially exception handling ones) continue to function in the // presence of an exception flowing out of the inner task _UnwrappedTask. This requires an exception handling continuation - // off the inner task which does the appropriate funnelling to the outer one. We use _Then instead of then to prevent + // off the inner task which does the appropriate funneling to the outer one. We use _Then instead of then to prevent // the exception from being marked as observed by our internal continuation. This continuation must be scheduled regardless // of whether or not the _OuterTask task is canceled. // @@ -2324,7 +2343,7 @@ namespace details } // Tracks the internal state of the task - volatile _TaskInternalState _M_TaskState; + std::atomic<_TaskInternalState> _M_TaskState; // Set to true either if the ancestor task had the flag set to true, or if the lambda that does the work of this task returns an // async operation or async action that is unwrapped by the runtime. bool _M_fFromAsync; @@ -2381,7 +2400,7 @@ namespace details } } #endif - + /// /// The implementation of a first-class task. This structure contains the task group used to execute /// the task function and handles the scheduling. The _Task_impl is created as a shared_ptr @@ -2431,7 +2450,7 @@ namespace details if (_M_TaskState == _Canceled) { - // If the task has finished cancelling there should not be any continuation records in the array. + // If the task has finished canceling there should not be any continuation records in the array. return false; } else @@ -2455,7 +2474,7 @@ namespace details if (_SynchronousCancel) { // Be aware that this set must be done BEFORE _M_Scheduled being set, or race will happen between this and wait() - _M_TaskState = _Canceled; + _M_TaskState = _Canceled; // Cancellation completes the task, so all dependent tasks must be run to cancel them // They are canceled when they begin running (see _RunContinuation) and see that their // ancestor has been canceled. @@ -2485,7 +2504,7 @@ namespace details _M_taskEventLogger._LogCancelTask(); } - + } // Only execute continuations and mark the task as completed if we were able to move the task to the _Canceled state. @@ -2563,7 +2582,7 @@ namespace details // Return true if the task has reached a terminal state bool _IsDone() - { + { return _IsCompleted() || _IsCanceled(); } @@ -2613,9 +2632,9 @@ namespace details _TaskList _M_tasks; ::pplx::extensibility::critical_section_t _M_taskListCritSec; _ResultHolder<_ResultType> _M_value; - std::shared_ptr<_ExceptionHolder> _M_exceptionHolder; - bool _M_fHasValue; - bool _M_fIsCanceled; + std::shared_ptr<_ExceptionHolder> _M_exceptionHolder; + std::atomic _M_fHasValue; + std::atomic _M_fIsCanceled; }; // Utility method for dealing with void functions @@ -2667,8 +2686,8 @@ class task_completion_event /// Constructs a task_completion_event object. /// /**/ - task_completion_event() - : _M_Impl(std::make_shared>()) + task_completion_event() + : _M_Impl(std::make_shared>()) { } @@ -2715,7 +2734,7 @@ class task_completion_event { for( auto _TaskIt = _Tasks.begin(); _TaskIt != _Tasks.end(); ++_TaskIt ) { - // If current task was cancelled by a cancellation_token, it would be in cancel pending state. + // If current task was canceled by a cancellation_token, it would be in cancel pending state. if ((*_TaskIt)->_IsPendingCancel()) (*_TaskIt)->_Cancel(true); else @@ -3227,8 +3246,8 @@ class task /// cancellation_token_source the token was obtained from. Tasks created without a cancellation token are not cancelable. /// Tasks created from a Windows::Foundation::IAsyncInfo interface or a lambda that returns an IAsyncInfo interface /// reach their terminal state when the enclosed Windows Runtime asynchronous operation or action completes. Similarly, tasks created - /// from a lamda that returns a task<result_type> reach their terminal state when the inner task reaches its terminal state, - /// and not when the lamda returns. + /// from a lambda that returns a task<result_type> reach their terminal state when the inner task reaches its terminal state, + /// and not when the lambda returns. /// task behaves like a smart pointer and is safe to pass around by value. It can be accessed by multiple threads /// without the need for locks. /// The constructor overloads that take a Windows::Foundation::IAsyncInfo interface or a lambda returning such an interface, are only available @@ -3268,8 +3287,8 @@ class task /// cancellation_token_source the token was obtained from. Tasks created without a cancellation token are not cancelable. /// Tasks created from a Windows::Foundation::IAsyncInfo interface or a lambda that returns an IAsyncInfo interface /// reach their terminal state when the enclosed Windows Runtime asynchronous operation or action completes. Similarly, tasks created - /// from a lamda that returns a task<result_type> reach their terminal state when the inner task reaches its terminal state, - /// and not when the lamda returns. + /// from a lambda that returns a task<result_type> reach their terminal state when the inner task reaches its terminal state, + /// and not when the lambda returns. /// task behaves like a smart pointer and is safe to pass around by value. It can be accessed by multiple threads /// without the need for locks. /// The constructor overloads that take a Windows::Foundation::IAsyncInfo interface or a lambda returning such an interface, are only available @@ -3316,8 +3335,8 @@ class task /// cancellation_token_source the token was obtained from. Tasks created without a cancellation token are not cancelable. /// Tasks created from a Windows::Foundation::IAsyncInfo interface or a lambda that returns an IAsyncInfo interface /// reach their terminal state when the enclosed Windows Runtime asynchronous operation or action completes. Similarly, tasks created - /// from a lamda that returns a task<result_type> reach their terminal state when the inner task reaches its terminal state, - /// and not when the lamda returns. + /// from a lambda that returns a task<result_type> reach their terminal state when the inner task reaches its terminal state, + /// and not when the lambda returns. /// task behaves like a smart pointer and is safe to pass around by value. It can be accessed by multiple threads /// without the need for locks. /// The constructor overloads that take a Windows::Foundation::IAsyncInfo interface or a lambda returning such an interface, are only available @@ -3334,7 +3353,7 @@ class task _CreateImpl(_TaskOptions.get_cancellation_token()._GetImplValue(), _TaskOptions.get_scheduler()); // Do not move the next line out of this function. It is important that _CAPTURE_CALLSTACK() evaluate to the the call site of the task constructor. _SetTaskCreationCallstack(details::_get_internal_task_options(_TaskOptions)._M_hasPresetCreationCallstack ? details::_get_internal_task_options(_TaskOptions)._M_presetCreationCallstack : _CAPTURE_CALLSTACK()); - + _TaskInitMaybeFunctor(_Param, details::_IsCallable(_Param,0)); } @@ -3354,8 +3373,8 @@ class task /// cancellation_token_source the token was obtained from. Tasks created without a cancellation token are not cancelable. /// Tasks created from a Windows::Foundation::IAsyncInfo interface or a lambda that returns an IAsyncInfo interface /// reach their terminal state when the enclosed Windows Runtime asynchronous operation or action completes. Similarly, tasks created - /// from a lamda that returns a task<result_type> reach their terminal state when the inner task reaches its terminal state, - /// and not when the lamda returns. + /// from a lambda that returns a task<result_type> reach their terminal state when the inner task reaches its terminal state, + /// and not when the lambda returns. /// task behaves like a smart pointer and is safe to pass around by value. It can be accessed by multiple threads /// without the need for locks. /// The constructor overloads that take a Windows::Foundation::IAsyncInfo interface or a lambda returning such an interface, are only available @@ -3381,8 +3400,8 @@ class task /// cancellation_token_source the token was obtained from. Tasks created without a cancellation token are not cancelable. /// Tasks created from a Windows::Foundation::IAsyncInfo interface or a lambda that returns an IAsyncInfo interface /// reach their terminal state when the enclosed Windows Runtime asynchronous operation or action completes. Similarly, tasks created - /// from a lamda that returns a task<result_type> reach their terminal state when the inner task reaches its terminal state, - /// and not when the lamda returns. + /// from a lambda that returns a task<result_type> reach their terminal state when the inner task reaches its terminal state, + /// and not when the lambda returns. /// task behaves like a smart pointer and is safe to pass around by value. It can be accessed by multiple threads /// without the need for locks. /// The constructor overloads that take a Windows::Foundation::IAsyncInfo interface or a lambda returning such an interface, are only available @@ -3570,7 +3589,7 @@ class task if (_M_Impl->_Wait() == canceled) { - throw task_canceled(); + throw task_canceled(); } return _M_Impl->_GetResult(); @@ -3673,7 +3692,7 @@ class task } /// - /// Set the implementation of the task to be the supplied implementaion. + /// Set the implementation of the task to be the supplied implementation. /// void _SetImpl(const typename details::_Task_ptr<_ReturnType>::_Type & _Impl) { @@ -3682,7 +3701,7 @@ class task } /// - /// Set the implementation of the task to be the supplied implementaion using a move instead of a copy. + /// Set the implementation of the task to be the supplied implementation using a move instead of a copy. /// void _SetImpl(typename details::_Task_ptr<_ReturnType>::_Type && _Impl) { @@ -3712,7 +3731,7 @@ class task /// This function is Used for runtime internal continuations only. /// template - auto _Then(_Function&& _Func, details::_CancellationTokenState *_PTokenState, + auto _Then(_Function&& _Func, details::_CancellationTokenState *_PTokenState, details::_TaskInliningMode_t _InliningMode = details::_ForceInline) const -> typename details::_ContinuationTypeTraits<_Function, _ReturnType>::_TaskOfType { // inherit from antecedent @@ -3724,10 +3743,10 @@ class task private: template friend class task; - + // The task handle type used to construct an 'initial task' - a task with no dependents. template - struct _InitialTaskHandle : + struct _InitialTaskHandle : details::_PPLTaskHandle<_ReturnType, _InitialTaskHandle<_InternalReturnType, _Function, _TypeSelection>, details::_UnrealizedChore_t> { _Function _M_function; @@ -3768,7 +3787,7 @@ class task } // - // Overload 1: returns IAsyncOperation<_InternalReturnType>^ (only uder /ZW) + // Overload 1: returns IAsyncOperation<_InternalReturnType>^ (only under /ZW) // or // returns task<_InternalReturnType> // @@ -3813,7 +3832,7 @@ class task { typedef details::_GetProgressType::_Value _ProgressType; - details::_Task_impl_base::_AsyncInit<_ReturnType, _InternalReturnType>(this->_M_pTask, + details::_Task_impl_base::_AsyncInit<_ReturnType, _InternalReturnType>(this->_M_pTask, ref new details::_IAsyncActionWithProgressToAsyncOperationConverter<_ProgressType>(_LogWorkItemAndInvokeUserLambda(_M_function))); } #endif /* defined (__cplusplus_winrt) */ @@ -3892,7 +3911,7 @@ class task } // - // Overload 0-1: _InternalReturnType -> IAsyncOperation<_TaskType>^ (only uder /ZW) + // Overload 0-1: _InternalReturnType -> IAsyncOperation<_TaskType>^ (only under /ZW) // or // _InternalReturnType -> task<_TaskType> // @@ -3904,7 +3923,7 @@ class task typedef typename details::_FunctionTypeTraits<_Function, _InternalReturnType>::_FuncRetType _FuncOutputType; details::_Task_impl_base::_AsyncInit<_NormalizedContinuationReturnType, _ContinuationReturnType>( - this->_M_pTask, + this->_M_pTask, _LogWorkItemAndInvokeUserLambda(_Continuation_func_transformer<_InternalReturnType, _FuncOutputType>::_Perform(_M_function), _M_ancestorTaskImpl->_GetResult()) ); } @@ -3989,7 +4008,7 @@ class task // The continuation takes a parameter of type task<_Input>, which is the same as the ancestor task. task<_InternalReturnType> _ResultTask; _ResultTask._SetImpl(std::move(_M_ancestorTaskImpl)); - details::_Task_impl_base::_AsyncInit<_NormalizedContinuationReturnType, _ContinuationReturnType>(this->_M_pTask, + details::_Task_impl_base::_AsyncInit<_NormalizedContinuationReturnType, _ContinuationReturnType>(this->_M_pTask, _LogWorkItemAndInvokeUserLambda(_M_function, std::move(_ResultTask))); } @@ -4223,8 +4242,8 @@ class task /// cancellation_token_source the token was obtained from. Tasks created without a cancellation token are not cancelable. /// Tasks created from a Windows::Foundation::IAsyncInfo interface or a lambda that returns an IAsyncInfo interface /// reach their terminal state when the enclosed Windows Runtime asynchronous operation or action completes. Similarly, tasks created - /// from a lamda that returns a task<result_type> reach their terminal state when the inner task reaches its terminal state, - /// and not when the lamda returns. + /// from a lambda that returns a task<result_type> reach their terminal state when the inner task reaches its terminal state, + /// and not when the lambda returns. /// task behaves like a smart pointer and is safe to pass around by value. It can be accessed by multiple threads /// without the need for locks. /// The constructor overloads that take a Windows::Foundation::IAsyncInfo interface or a lambda returning such an interface, are only available @@ -4260,8 +4279,8 @@ class task /// cancellation_token_source the token was obtained from. Tasks created without a cancellation token are not cancelable. /// Tasks created from a Windows::Foundation::IAsyncInfo interface or a lambda that returns an IAsyncInfo interface /// reach their terminal state when the enclosed Windows Runtime asynchronous operation or action completes. Similarly, tasks created - /// from a lamda that returns a task<result_type> reach their terminal state when the inner task reaches its terminal state, - /// and not when the lamda returns. + /// from a lambda that returns a task<result_type> reach their terminal state when the inner task reaches its terminal state, + /// and not when the lambda returns. /// task behaves like a smart pointer and is safe to pass around by value. It can be accessed by multiple threads /// without the need for locks. /// The constructor overloads that take a Windows::Foundation::IAsyncInfo interface or a lambda returning such an interface, are only available @@ -4298,8 +4317,8 @@ class task /// cancellation_token_source the token was obtained from. Tasks created without a cancellation token are not cancelable. /// Tasks created from a Windows::Foundation::IAsyncInfo interface or a lambda that returns an IAsyncInfo interface /// reach their terminal state when the enclosed Windows Runtime asynchronous operation or action completes. Similarly, tasks created - /// from a lamda that returns a task<result_type> reach their terminal state when the inner task reaches its terminal state, - /// and not when the lamda returns. + /// from a lambda that returns a task<result_type> reach their terminal state when the inner task reaches its terminal state, + /// and not when the lambda returns. /// task behaves like a smart pointer and is safe to pass around by value. It can be accessed by multiple threads /// without the need for locks. /// The constructor overloads that take a Windows::Foundation::IAsyncInfo interface or a lambda returning such an interface, are only available @@ -4325,8 +4344,8 @@ class task /// cancellation_token_source the token was obtained from. Tasks created without a cancellation token are not cancelable. /// Tasks created from a Windows::Foundation::IAsyncInfo interface or a lambda that returns an IAsyncInfo interface /// reach their terminal state when the enclosed Windows Runtime asynchronous operation or action completes. Similarly, tasks created - /// from a lamda that returns a task<result_type> reach their terminal state when the inner task reaches its terminal state, - /// and not when the lamda returns. + /// from a lambda that returns a task<result_type> reach their terminal state when the inner task reaches its terminal state, + /// and not when the lambda returns. /// task behaves like a smart pointer and is safe to pass around by value. It can be accessed by multiple threads /// without the need for locks. /// The constructor overloads that take a Windows::Foundation::IAsyncInfo interface or a lambda returning such an interface, are only available @@ -4551,7 +4570,7 @@ class task } /// - /// Set the implementation of the task to be the supplied implementaion. + /// Set the implementation of the task to be the supplied implementation. /// void _SetImpl(const details::_Task_ptr::_Type & _Impl) { @@ -4559,7 +4578,7 @@ class task } /// - /// Set the implementation of the task to be the supplied implementaion using a move instead of a copy. + /// Set the implementation of the task to be the supplied implementation using a move instead of a copy. /// void _SetImpl(details::_Task_ptr::_Type && _Impl) { @@ -4586,7 +4605,7 @@ class task /// An internal version of then that takes additional flags and executes the continuation inline. Used for runtime internal continuations only. /// template - auto _Then(_Function&& _Func, details::_CancellationTokenState *_PTokenState, + auto _Then(_Function&& _Func, details::_CancellationTokenState *_PTokenState, details::_TaskInliningMode_t _InliningMode = details::_ForceInline) const -> typename details::_ContinuationTypeTraits<_Function, void>::_TaskOfType { // inherit from antecedent @@ -4672,7 +4691,7 @@ namespace details template _Ty _GetUnwrappedType(task<_Ty>); - // Unwrap all supportted types + // Unwrap all supported types template auto _GetUnwrappedReturnType(_Ty _Arg, int) -> decltype(_GetUnwrappedType(_Arg)); // fallback @@ -5651,8 +5670,8 @@ namespace details { internal: - _AsyncInfoBase() : - _M_currentStatus(_AsyncStatusInternal::_AsyncCreated), + _AsyncInfoBase() : + _M_currentStatus(_AsyncStatusInternal::_AsyncCreated), _M_errorCode(S_OK), _M_completeDelegate(nullptr), _M_CompleteDelegateAssigned(0), @@ -5702,7 +5721,7 @@ namespace details _AsyncStatusInternal _Current = _M_currentStatus; // - // Map our internal cancel pending to cancelled. This way "pending cancelled" looks to the outside as "cancelled" but + // Map our internal cancel pending to canceled. This way "pending canceled" looks to the outside as "canceled" but // can still transition to "completed" if the operation completes without acknowledging the cancellation request // switch(_Current) @@ -6225,7 +6244,7 @@ namespace details /// The return type of the lambda determines whether the construct is an action or an operation. /// Lambdas that return void cause the creation of actions. Lambdas that return a result of type TResult cause the creation of /// operations of TResult. -/// The lambda may also return a task<TResult> which encapsulates the aysnchronous work within itself or is the continuation of +/// The lambda may also return a task<TResult> which encapsulates the asynchronous work within itself or is the continuation of /// a chain of tasks that represent the asynchronous work. In this case, the lambda itself is executed inline, since the tasks are the ones that /// execute asynchronously, and the return type of the lambda is unwrapped to produce the asynchronous construct returned by create_async. /// This implies that a lambda that returns a task<void> will cause the creation of actions, and a lambda that returns a task<TResult> will @@ -6236,10 +6255,10 @@ namespace details /// construct which reports progress of type TProgress each time the report method of the progress_reporter object is called. A lambda that /// takes a cancellation_token may use that token to check for cancellation, or pass it to tasks that it creates so that cancellation of the /// asynchronous construct causes cancellation of those tasks. -/// If the body of the lambda or function object returns a result (and not a task<TResult>), the lamdba will be executed +/// If the body of the lambda or function object returns a result (and not a task<TResult>), the lambda will be executed /// asynchronously within the process MTA in the context of a task the Runtime implicitly creates for it. The IAsyncInfo::Cancel method will /// cause cancellation of the implicit task. -/// If the body of the lambda returns a task, the lamba executes inline, and by declaring the lambda to take an argument of type +/// If the body of the lambda returns a task, the lambda executes inline, and by declaring the lambda to take an argument of type /// cancellation_token you can trigger cancellation of any tasks you create within the lambda by passing that token in when you create them. /// You may also use the register_callback method on the token to cause the Runtime to invoke a callback when you call IAsyncInfo::Cancel on /// the async operation or action produced.. @@ -6296,7 +6315,7 @@ namespace details void _Resize(size_t _Len, bool _SkipVector = false) { _M_numTasks = _Len; - + if (!_SkipVector) { _M_vector.resize(_Len); @@ -6433,7 +6452,7 @@ namespace details }; _WhenAllContinuationWrapper(_PParam, _Func, _ResultTask); - }, _CancellationTokenState::_None()); + }, _CancellationTokenState::_None()); _Index++; } @@ -6598,7 +6617,7 @@ namespace details auto _mergeVal = _PParam->_M_mergeVal.Get(); if (_OutputVectorFirst == true) - { + { _Result.push_back(_mergeVal); } else @@ -6655,18 +6674,18 @@ namespace details /// The position of the first element beyond the range of elements to be combined into the resulting task. /// /// -/// A task that completes sucessfully when all of the input tasks have completed successfully. If the input tasks are of type T, +/// A task that completes successfully when all of the input tasks have completed successfully. If the input tasks are of type T, /// the output of this function will be a task<std::vector<T>>. If the input tasks are of type void the output /// task will also be a task<void>. /// /// /// If one of the tasks is canceled or throws an exception, the returned task will complete early, in the canceled state, and the exception, -/// if one is encoutered, will be thrown if you call get() or wait() on that task. +/// if one is encountered, will be thrown if you call get() or wait() on that task. /// /// /**/ template -auto when_all(_Iterator _Begin, _Iterator _End, const task_options& _TaskOptions = task_options()) +auto when_all(_Iterator _Begin, _Iterator _End, const task_options& _TaskOptions = task_options()) -> decltype (details::_WhenAllImpl::value_type::result_type, _Iterator>::_Perform(_TaskOptions, _Begin, _End)) { typedef typename std::iterator_traits<_Iterator>::value_type::result_type _ElementType; @@ -6674,7 +6693,7 @@ auto when_all(_Iterator _Begin, _Iterator _End, const task_options& _TaskOptions } /// -/// Creates a task that will complete succesfully when both of the tasks supplied as arguments complete successfully. +/// Creates a task that will complete successfully when both of the tasks supplied as arguments complete successfully. /// /// /// The type of the returned task. @@ -6694,7 +6713,7 @@ auto when_all(_Iterator _Begin, _Iterator _End, const task_options& _TaskOptions /// /// /// If one of the tasks is canceled or throws an exception, the returned task will complete early, in the canceled state, and the exception, -/// if one is encoutered, will be thrown if you call get() or wait() on that task. +/// if one is encountered, will be thrown if you call get() or wait() on that task. /// /// /**/ @@ -6706,7 +6725,7 @@ auto operator&&(const task<_ReturnType> & _Lhs, const task<_ReturnType> & _Rhs) } /// -/// Creates a task that will complete succesfully when both of the tasks supplied as arguments complete successfully. +/// Creates a task that will complete successfully when both of the tasks supplied as arguments complete successfully. /// /// /// The type of the returned task. @@ -6726,7 +6745,7 @@ auto operator&&(const task<_ReturnType> & _Lhs, const task<_ReturnType> & _Rhs) /// /// /// If one of the tasks is canceled or throws an exception, the returned task will complete early, in the canceled state, and the exception, -/// if one is encoutered, will be thrown if you call get() or wait() on that task. +/// if one is encountered, will be thrown if you call get() or wait() on that task. /// /// /**/ @@ -6737,7 +6756,7 @@ auto operator&&(const task> & _Lhs, const task<_ReturnT } /// -/// Creates a task that will complete succesfully when both of the tasks supplied as arguments complete successfully. +/// Creates a task that will complete successfully when both of the tasks supplied as arguments complete successfully. /// /// /// The type of the returned task. @@ -6757,7 +6776,7 @@ auto operator&&(const task> & _Lhs, const task<_ReturnT /// /// /// If one of the tasks is canceled or throws an exception, the returned task will complete early, in the canceled state, and the exception, -/// if one is encoutered, will be thrown if you call get() or wait() on that task. +/// if one is encountered, will be thrown if you call get() or wait() on that task. /// /// /**/ @@ -6768,7 +6787,7 @@ auto operator&&(const task<_ReturnType> & _Lhs, const task -/// Creates a task that will complete succesfully when both of the tasks supplied as arguments complete successfully. +/// Creates a task that will complete successfully when both of the tasks supplied as arguments complete successfully. /// /// /// The type of the returned task. @@ -6788,7 +6807,7 @@ auto operator&&(const task<_ReturnType> & _Lhs, const task /// /// If one of the tasks is canceled or throws an exception, the returned task will complete early, in the canceled state, and the exception, -/// if one is encoutered, will be thrown if you call get() or wait() on that task. +/// if one is encountered, will be thrown if you call get() or wait() on that task. /// /// /**/ @@ -6850,7 +6869,7 @@ namespace details } } } - + if (atomic_increment(_PParam->_M_completeCount) == _PParam->_M_numTasks) { // If no one has be completed so far, we need to make some final cancellation decision. @@ -6889,16 +6908,16 @@ namespace details } _CancellationTokenState *_PTokenState = _TaskOptions.has_cancellation_token() ? _TaskOptions.get_cancellation_token()._GetImplValue() : nullptr; auto _PParam = new _RunAnyParam, _CancellationTokenState *>>(); - + if (_PTokenState) { _JoinAllTokens_Add(_PParam->_M_cancellationSource, _PTokenState); _PParam->_M_fHasExplicitToken = true; } - + task_options _Options(_TaskOptions); _Options.set_cancellation_token(_PParam->_M_cancellationSource.get_token()); - task, _CancellationTokenState *>> _Any_tasks_completed(_PParam->_M_Completed, _Options); + task, _CancellationTokenState *>> _Any_tasks_completed(_PParam->_M_Completed, _Options); // Keep a copy ref to the token source auto _CancellationSource = _PParam->_M_cancellationSource; @@ -6949,7 +6968,7 @@ namespace details _CancellationTokenState *_PTokenState = _TaskOptions.has_cancellation_token() ? _TaskOptions.get_cancellation_token()._GetImplValue() : nullptr; auto _PParam = new _RunAnyParam>(); - + if (_PTokenState) { _JoinAllTokens_Add(_PParam->_M_cancellationSource, _PTokenState); @@ -7070,7 +7089,7 @@ auto when_any(_Iterator _Begin, _Iterator _End, cancellation_token _Cancellation /// The second task to combine into the resulting task. /// /// -/// A task that completes sucessfully when either of the input tasks has completed successfully. If the input tasks are of type T, +/// A task that completes successfully when either of the input tasks has completed successfully. If the input tasks are of type T, /// the output of this function will be a task<std::vector<T>. If the input tasks are of type void the output task /// will also be a task<void>. /// To allow for a construct of the sort taskA || taskB && taskC, which are combined in pairs, with && taking precedence @@ -7131,7 +7150,7 @@ task<_ReturnType> operator||(const task<_ReturnType> & _Lhs, const task<_ReturnT /// The second task to combine into the resulting task. /// /// -/// A task that completes sucessfully when either of the input tasks has completed successfully. If the input tasks are of type T, +/// A task that completes successfully when either of the input tasks has completed successfully. If the input tasks are of type T, /// the output of this function will be a task<std::vector<T>. If the input tasks are of type void the output task /// will also be a task<void>. /// To allow for a construct of the sort taskA || taskB && taskC, which are combined in pairs, with && taking precedence @@ -7175,8 +7194,8 @@ task> operator||(const task> & _WhenAnyContinuationWrapper(_PParam, _Func, _ResultTask); }, details::_CancellationTokenState::_None()); - - _Rhs._Then([_PParam](task<_ReturnType> _ResultTask) + + _Rhs._Then([_PParam](task<_ReturnType> _ResultTask) { auto _PParamCopy = _PParam; auto _Func = [&_ResultTask, _PParamCopy]() { @@ -7205,7 +7224,7 @@ task> operator||(const task> & /// The second task to combine into the resulting task. /// /// -/// A task that completes sucessfully when either of the input tasks has completed successfully. If the input tasks are of type T, +/// A task that completes successfully when either of the input tasks has completed successfully. If the input tasks are of type T, /// the output of this function will be a task<std::vector<T>. If the input tasks are of type void the output task /// will also be a task<void>. /// To allow for a construct of the sort taskA || taskB && taskC, which are combined in pairs, with && taking precedence @@ -7237,7 +7256,7 @@ auto operator||(const task<_ReturnType> & _Lhs, const task /// -/// A task that completes sucessfully when either of the input tasks has completed successfully. If the input tasks are of type T, +/// A task that completes successfully when either of the input tasks has completed successfully. If the input tasks are of type T, /// the output of this function will be a task<std::vector<T>. If the input tasks are of type void the output task /// will also be a task<void>. /// To allow for a construct of the sort taskA || taskB && taskC, which are combined in pairs, with && taking precedence @@ -7332,5 +7351,3 @@ namespace concurrency = Concurrency; #endif #endif // _PPLXTASKS_H - - diff --git a/Release/samples/BlackJack/BlackJack_Server/Table.cpp b/Release/samples/BlackJack/BlackJack_Server/Table.cpp index 9473b37945..af54397889 100644 --- a/Release/samples/BlackJack/BlackJack_Server/Table.cpp +++ b/Release/samples/BlackJack/BlackJack_Server/Table.cpp @@ -456,8 +456,7 @@ void DealerTable::FillShoe(size_t decks) // // Stack the decks. // - std::shared_ptr ss(new int[decks * 52]); - auto shoe = ss.get(); + std::vector shoe(decks * 52); for (size_t d = 0; d < decks ; d++) { diff --git a/Release/src/CMakeLists.txt b/Release/src/CMakeLists.txt index eceaad7437..5f77deea1f 100644 --- a/Release/src/CMakeLists.txt +++ b/Release/src/CMakeLists.txt @@ -16,12 +16,13 @@ set(SOURCES ${HEADERS_DETAILS} pch/stdafx.h http/client/http_client.cpp - http/client/http_client_msg.cpp http/client/http_client_impl.h - http/common/internal_http_helpers.h + http/client/http_client_msg.cpp + http/common/connection_pool_helpers.h + http/common/http_compression.cpp http/common/http_helpers.cpp http/common/http_msg.cpp - http/common/http_compression.cpp + http/common/internal_http_helpers.h http/listener/http_listener.cpp http/listener/http_listener_msg.cpp http/listener/http_server_api.cpp @@ -102,6 +103,7 @@ elseif(CPPREST_PPLX_IMPL STREQUAL "linux") install(FILES ../include/pplx/threadpool.h DESTINATION include/pplx) endif() elseif(CPPREST_PPLX_IMPL STREQUAL "win") + target_sources(cpprest PRIVATE pplx/pplxwin.cpp) if(CPPREST_WEBSOCKETS_IMPL STREQUAL "wspp") target_sources(cpprest PRIVATE pplx/threadpool.cpp ../include/pplx/threadpool.h) if(CPPREST_INSTALL_HEADERS) diff --git a/Release/src/http/client/http_client_asio.cpp b/Release/src/http/client/http_client_asio.cpp index 645b45466c..0ef90695a5 100644 --- a/Release/src/http/client/http_client_asio.cpp +++ b/Release/src/http/client/http_client_asio.cpp @@ -17,6 +17,7 @@ #include #include "../common/internal_http_helpers.h" +#include "../common/connection_pool_helpers.h" #include "cpprest/asyncrt_utils.h" #if defined(__clang__) @@ -345,48 +346,6 @@ class asio_connection bool m_closed; }; -class connection_pool_stack -{ -public: - // attempts to acquire a connection from the deque; returns nullptr if no connection is - // available - std::shared_ptr try_acquire() CPPREST_NOEXCEPT - { - const size_t oldConnectionsSize = m_connections.size(); - if (m_highWater > oldConnectionsSize) - { - m_highWater = oldConnectionsSize; - } - - if (oldConnectionsSize == 0) - { - return nullptr; - } - - auto result = std::move(m_connections.back()); - m_connections.pop_back(); - return result; - } - - // releases `released` back to the connection pool - void release(std::shared_ptr&& released) - { - m_connections.push_back(std::move(released)); - } - - bool free_stale_connections() CPPREST_NOEXCEPT - { - m_connections.erase(m_connections.begin(), m_connections.begin() + m_highWater); - const size_t connectionsSize = m_connections.size(); - m_highWater = connectionsSize; - return (connectionsSize != 0); - } - -private: - size_t m_highWater = 0; - std::vector> m_connections; -}; - /// Implements a connection pool with adaptive connection removal /// /// Every 30 seconds, the lambda in `start_epoch_interval` fires, triggering the @@ -501,7 +460,7 @@ class asio_connection_pool final : public std::enable_shared_from_this m_connections; + std::map> m_connections; bool m_is_timer_running; boost::asio::deadline_timer m_pool_epoch_timer; }; @@ -1883,7 +1842,7 @@ class asio_context final : public request_context, public std::enable_shared_fro timedout }; -#if defined(ANDROID) || defined(__ANDROID__) +#if (defined(ANDROID) || defined(__ANDROID__)) && !defined(_LIBCPP_VERSION) boost::chrono::microseconds m_duration; #else std::chrono::microseconds m_duration; diff --git a/Release/src/http/client/http_client_winhttp.cpp b/Release/src/http/client/http_client_winhttp.cpp index ab415bb8b4..6976fbc771 100644 --- a/Release/src/http/client/http_client_winhttp.cpp +++ b/Release/src/http/client/http_client_winhttp.cpp @@ -302,6 +302,36 @@ class winhttp_request_context final : public request_context { } +#if defined(_MSC_VER) && _MSC_VER < 1900 + compression_state(const compression_state&) = delete; + compression_state(compression_state&& other) + : m_buffer(std::move(other.m_buffer)) + , m_acquired(other.m_acquired) + , m_bytes_read(other.m_bytes_read) + , m_bytes_processed(other.m_bytes_processed) + , m_needs_flush(other.m_needs_flush) + , m_started(other.m_started) + , m_done(other.m_done) + , m_chunked(other.m_chunked) + , m_chunk_bytes(other.m_chunk_bytes) + , m_chunk(std::move(other.m_chunk)) + {} + compression_state& operator=(const compression_state&) = delete; + compression_state& operator=(compression_state&& other) { + m_buffer = std::move(other.m_buffer); + m_acquired = other.m_acquired; + m_bytes_read = other.m_bytes_read; + m_bytes_processed = other.m_bytes_processed; + m_needs_flush = other.m_needs_flush; + m_started = other.m_started; + m_done = other.m_done; + m_chunked = other.m_chunked; + m_chunk_bytes = other.m_chunk_bytes; + m_chunk = std::move(other.m_chunk); + return *this; + } +#endif // defined(_MSC_VER) && _MSC_VER < 1900 + // Minimal state for on-the-fly decoding of "chunked" encoded data class _chunk_helper { @@ -425,12 +455,12 @@ class winhttp_request_context final : public request_context } else if (buffer[n] == '\r') { - // We've reached the end of the size, and there's no chunk extention + // We've reached the end of the size, and there's no chunk extension m_expect_linefeed = true; } else if (buffer[n] == ';') { - // We've reached the end of the size, and there's a chunk extention; + // We've reached the end of the size, and there's a chunk extension; // we don't support extensions, so we ignore them per RFC m_ignore = true; } @@ -1288,7 +1318,7 @@ class winhttp_client final : public _http_client_communicator { const bool defaultChunkSize = pContext->m_http_client->client_config().is_default_chunksize(); - // If user specified a chunk size then read in chunks instead of using query data avaliable. + // If user specified a chunk size then read in chunks instead of using query data available. if (defaultChunkSize) { if (!WinHttpQueryDataAvailable(pContext->m_request_handle, nullptr)) @@ -2263,7 +2293,7 @@ class winhttp_client final : public _http_client_communicator return true; }; - Concurrency::details::_do_while([p_request_context, chunk_size, process_buffer]() -> pplx::task + pplx::details::_do_while([p_request_context, chunk_size, process_buffer]() -> pplx::task { uint8_t *buffer; diff --git a/Release/src/http/common/connection_pool_helpers.h b/Release/src/http/common/connection_pool_helpers.h new file mode 100644 index 0000000000..580b82af23 --- /dev/null +++ b/Release/src/http/common/connection_pool_helpers.h @@ -0,0 +1,66 @@ +#pragma once + +#include "cpprest/details/cpprest_compat.h" +#include +#include +#include + +namespace web +{ +namespace http +{ +namespace client +{ +namespace details +{ + +template +class connection_pool_stack +{ +public: + // attempts to acquire a connection from the deque; returns nullptr if no connection is + // available + std::shared_ptr try_acquire() CPPREST_NOEXCEPT + { + const size_t oldConnectionsSize = m_connections.size(); + if (oldConnectionsSize == 0) + { + m_staleBefore = 0; + return nullptr; + } + + auto result = std::move(m_connections.back()); + m_connections.pop_back(); + const size_t newConnectionsSize = m_connections.size(); + if (m_staleBefore > newConnectionsSize) + { + m_staleBefore = newConnectionsSize; + } + + return result; + } + + // releases `released` back to the connection pool + void release(std::shared_ptr&& released) + { + m_connections.push_back(std::move(released)); + } + + bool free_stale_connections() CPPREST_NOEXCEPT + { + assert(m_staleBefore <= m_connections.size()); + m_connections.erase(m_connections.begin(), m_connections.begin() + m_staleBefore); + const size_t connectionsSize = m_connections.size(); + m_staleBefore = connectionsSize; + return (connectionsSize != 0); + } + +private: + std::vector> m_connections; + size_t m_staleBefore = 0; +}; + +} // details +} // client +} // http +} // web diff --git a/Release/src/http/common/http_msg.cpp b/Release/src/http/common/http_msg.cpp index 91da2c2c3e..7c8a6713f6 100644 --- a/Release/src/http/common/http_msg.cpp +++ b/Release/src/http/common/http_msg.cpp @@ -376,7 +376,7 @@ size_t http_msg_base::_get_content_length(bool honor_compression) content_length = _get_stream_length(); if (content_length != std::numeric_limits::max()) { - // The content length wasn't explcitly set, but we figured it out; + // The content length wasn't explicitly set, but we figured it out; // use it, since sending this way is more efficient than chunking headers().add(header_names::content_length, content_length); return content_length; diff --git a/Release/src/http/listener/http_listener.cpp b/Release/src/http/listener/http_listener.cpp index baa204b56d..423adfe00b 100644 --- a/Release/src/http/listener/http_listener.cpp +++ b/Release/src/http/listener/http_listener.cpp @@ -63,21 +63,6 @@ details::http_listener_impl::http_listener_impl(http::uri address, http_listener check_listener_uri(m_uri); } -http_listener::~http_listener() -{ - if(m_impl) - { - // As a safe guard close the listener if not already done. - // Users are required to call close, but this is just a safeguard. - try - { - close().wait(); - } catch(...) - { - } - } -} - pplx::task details::http_listener_impl::open() { // Do nothing if the open operation was already attempted diff --git a/Release/src/http/listener/http_listener_msg.cpp b/Release/src/http/listener/http_listener_msg.cpp index 82c285cfbc..dfdb4e95f2 100644 --- a/Release/src/http/listener/http_listener_msg.cpp +++ b/Release/src/http/listener/http_listener_msg.cpp @@ -58,7 +58,7 @@ pplx::task details::_http_request::_reply_impl(http_response response) pplx::task details::_http_request::_reply_if_not_already(status_code status) { const long expected = 0; - const long desired = 1; + const long desired = 2; if (pplx::details::atomic_compare_exchange(m_initiated_response, desired, expected) == expected) { return _reply_impl(http_response(status)); @@ -68,11 +68,18 @@ pplx::task details::_http_request::_reply_if_not_already(status_code statu pplx::task details::_http_request::reply(const http_response &response) { - if(pplx::details::atomic_increment(m_initiated_response) != 1l) - { - throw http_exception(U("Error: trying to send multiple responses to an HTTP request")); + const long expected = 0; + const long desired = 1; + switch (pplx::details::atomic_compare_exchange(m_initiated_response, desired, expected)) { + case 0: + return _reply_impl(response); // success + case 1: + throw http_exception(U("Error: trying to send multiple responses to an HTTP request")); + case 2: + return pplx::task_from_result(); // already handled + default: + abort(); } - return _reply_impl(response); } }} // namespace web::http diff --git a/Release/src/http/listener/http_server_asio.cpp b/Release/src/http/listener/http_server_asio.cpp index 591e623d82..0d162f41df 100644 --- a/Release/src/http/listener/http_server_asio.cpp +++ b/Release/src/http/listener/http_server_asio.cpp @@ -250,7 +250,7 @@ struct crlfcrlf_nonascii_searcher_t State state = State::none; while (cur != end) { - char c = *cur; + const auto c = static_cast(*cur); if (c == '\r') { if (state == State::crlf) @@ -282,12 +282,7 @@ struct crlfcrlf_nonascii_searcher_t state = State::none; } } - else if (c <= '\x1F' && c >= '\x00') - { - ++cur; - return std::make_pair(cur, true); - } - else if (c <= '\xFF' && c >= '\x80') + else if (c <= 0x1Fu || c >= 0x80) { ++cur; return std::make_pair(cur, true); @@ -320,7 +315,19 @@ class asio_server_connection boost::asio::streambuf m_response_buf; http_linux_server* m_p_server; hostport_listener* m_p_parent; - http_request m_request; + mutable std::mutex m_request_mtx; + http_request m_request_tmp; + + void set_request(http_request req) { + std::lock_guard lck(m_request_mtx); + m_request_tmp = std::move(req); + } + + http_request get_request() const { + std::lock_guard lck(m_request_mtx); + return m_request_tmp; + } + size_t m_read, m_write; size_t m_read_size, m_write_size; bool m_close; @@ -409,7 +416,7 @@ class asio_server_connection will_erase_from_parent_t do_response() { auto unique_reference = this->get_reference(); - m_request.get_response().then([=](pplx::task r_task) + get_request().get_response().then([=](pplx::task r_task) { http_response response; try @@ -424,7 +431,7 @@ class asio_server_connection serialize_headers(response); // before sending response, the full incoming message need to be processed. - return m_request.content_ready().then([=](pplx::task) + return get_request().content_ready().then([=](pplx::task) { (will_deref_and_erase_t)this->async_write(&asio_server_connection::handle_headers_written, response); }); @@ -435,7 +442,7 @@ class asio_server_connection will_erase_from_parent_t do_bad_response() { auto unique_reference = this->get_reference(); - m_request.get_response().then([=](pplx::task r_task) + get_request().get_response().then([=](pplx::task r_task) { http_response response; try @@ -540,7 +547,7 @@ void asio_server_connection::close() sock->shutdown(tcp::socket::shutdown_both, ec); sock->close(ec); } - m_request._reply_if_not_already(status_codes::InternalError); + get_request()._reply_if_not_already(status_codes::InternalError); } will_deref_and_erase_t asio_server_connection::start_request_response() @@ -617,7 +624,8 @@ void hostport_listener::on_accept(std::unique_ptr socket, const will_deref_and_erase_t asio_server_connection::handle_http_line(const boost::system::error_code& ec) { - m_request = http_request::_create_request(make_unique()); + auto thisRequest = http_request::_create_request(make_unique()); + set_request(thisRequest); if (ec) { // client closed connection @@ -632,7 +640,7 @@ will_deref_and_erase_t asio_server_connection::handle_http_line(const boost::sys } else { - m_request._reply_if_not_already(status_codes::BadRequest); + thisRequest._reply_if_not_already(status_codes::BadRequest); m_close = true; (will_erase_from_parent_t)do_bad_response(); (will_deref_t)deref(); @@ -669,14 +677,14 @@ will_deref_and_erase_t asio_server_connection::handle_http_line(const boost::sys // Check to see if there is not allowed character on the input if (!web::http::details::validate_method(http_verb)) { - m_request.reply(status_codes::BadRequest); + thisRequest.reply(status_codes::BadRequest); m_close = true; (will_erase_from_parent_t)do_bad_response(); (will_deref_t)deref(); return will_deref_and_erase_t{}; } - m_request.set_method(http_verb); + thisRequest.set_method(http_verb); std::string http_path_and_version; std::getline(request_stream, http_path_and_version); @@ -685,7 +693,7 @@ will_deref_and_erase_t asio_server_connection::handle_http_line(const boost::sys // Make sure path and version is long enough to contain the HTTP version if(http_path_and_version.size() < VersionPortionSize + 2) { - m_request.reply(status_codes::BadRequest); + thisRequest.reply(status_codes::BadRequest); m_close = true; (will_erase_from_parent_t)do_bad_response(); (will_deref_t)deref(); @@ -695,12 +703,12 @@ will_deref_and_erase_t asio_server_connection::handle_http_line(const boost::sys // Get the path - remove the version portion and prefix space try { - m_request.set_request_uri(utility::conversions::to_string_t( + thisRequest.set_request_uri(utility::conversions::to_string_t( http_path_and_version.substr(1, http_path_and_version.size() - VersionPortionSize - 1))); } catch (const std::exception& e) // may be std::range_error indicating invalid Unicode, or web::uri_exception { - m_request.reply(status_codes::BadRequest, e.what()); + thisRequest.reply(status_codes::BadRequest, e.what()); m_close = true; (will_erase_from_parent_t)do_bad_response(); (will_deref_t)deref(); @@ -710,9 +718,9 @@ will_deref_and_erase_t asio_server_connection::handle_http_line(const boost::sys // Get the version std::string http_version = http_path_and_version.substr(http_path_and_version.size() - VersionPortionSize + 1, VersionPortionSize - 2); - auto m_request_impl = m_request._get_impl().get(); + auto requestImpl = thisRequest._get_impl().get(); web::http::http_version parsed_version = web::http::http_version::from_string(http_version); - m_request_impl->_set_http_version(parsed_version); + requestImpl->_set_http_version(parsed_version); // if HTTP version is 1.0 then disable pipelining if (parsed_version == web::http::http_versions::HTTP_1_0) @@ -725,7 +733,7 @@ will_deref_and_erase_t asio_server_connection::handle_http_line(const boost::sys auto endpoint = m_socket->remote_endpoint(socket_ec); if (!socket_ec) { - m_request._get_impl()->_set_remote_address(utility::conversions::to_string_t( + requestImpl->_set_remote_address(utility::conversions::to_string_t( endpoint.address().to_string())); } @@ -739,7 +747,8 @@ will_deref_and_erase_t asio_server_connection::handle_headers() request_stream.imbue(std::locale::classic()); std::string header; - auto& headers = m_request.headers(); + auto currentRequest = get_request(); + auto& headers = currentRequest.headers(); while (std::getline(request_stream, header) && header != "\r") { @@ -763,7 +772,7 @@ will_deref_and_erase_t asio_server_connection::handle_headers() } else { - m_request.reply(status_codes::BadRequest); + currentRequest.reply(status_codes::BadRequest); m_close = true; (will_erase_from_parent_t)do_bad_response(); (will_deref_t)deref(); @@ -774,17 +783,17 @@ will_deref_and_erase_t asio_server_connection::handle_headers() m_chunked = false; utility::string_t name; // check if the client has requested we close the connection - if (m_request.headers().match(header_names::connection, name)) + if (currentRequest.headers().match(header_names::connection, name)) { m_close = boost::iequals(name, U("close")); } - if (m_request.headers().match(header_names::transfer_encoding, name)) + if (currentRequest.headers().match(header_names::transfer_encoding, name)) { m_chunked = boost::ifind_first(name, U("chunked")); } - m_request._get_impl()->_prepare_to_receive_data(); + currentRequest._get_impl()->_prepare_to_receive_data(); if (m_chunked) { ++m_refs; @@ -792,14 +801,14 @@ will_deref_and_erase_t asio_server_connection::handle_headers() return dispatch_request_to_listener(); } - if (!m_request.headers().match(header_names::content_length, m_read_size)) + if (!currentRequest.headers().match(header_names::content_length, m_read_size)) { m_read_size = 0; } if (m_read_size == 0) { - m_request._get_impl()->_complete(0); + currentRequest._get_impl()->_complete(0); } else // need to read the sent data { @@ -816,9 +825,10 @@ will_deref_and_erase_t asio_server_connection::handle_headers() will_deref_t asio_server_connection::handle_chunked_header(const boost::system::error_code& ec) { + auto requestImpl = get_request()._get_impl(); if (ec) { - m_request._get_impl()->_complete(0, std::make_exception_ptr(http_exception(ec.value()))); + requestImpl->_complete(0, std::make_exception_ptr(http_exception(ec.value()))); return deref(); } else @@ -831,7 +841,7 @@ will_deref_t asio_server_connection::handle_chunked_header(const boost::system:: m_read += len; if (len == 0) { - m_request._get_impl()->_complete(m_read); + requestImpl->_complete(m_read); return deref(); } else @@ -847,14 +857,15 @@ will_deref_t asio_server_connection::handle_chunked_header(const boost::system:: will_deref_t asio_server_connection::handle_chunked_body(const boost::system::error_code& ec, int toWrite) { + auto requestImpl = get_request()._get_impl(); if (ec) { - m_request._get_impl()->_complete(0, std::make_exception_ptr(http_exception(ec.value()))); + requestImpl->_complete(0, std::make_exception_ptr(http_exception(ec.value()))); return deref(); } else { - auto writebuf = m_request._get_impl()->outstream().streambuf(); + auto writebuf = requestImpl->outstream().streambuf(); writebuf.putn_nocopy(buffer_cast(m_request_buf.data()), toWrite).then([=](pplx::task writeChunkTask) -> will_deref_t { try @@ -863,7 +874,7 @@ will_deref_t asio_server_connection::handle_chunked_body(const boost::system::er } catch (...) { - m_request._get_impl()->_complete(0, std::current_exception()); + requestImpl->_complete(0, std::current_exception()); return deref(); } @@ -876,16 +887,17 @@ will_deref_t asio_server_connection::handle_chunked_body(const boost::system::er will_deref_t asio_server_connection::handle_body(const boost::system::error_code& ec) { + auto requestImpl = get_request()._get_impl(); // read body if (ec) { - m_request._get_impl()->_complete(0, std::make_exception_ptr(http_exception(ec.value()))); + requestImpl->_complete(0, std::make_exception_ptr(http_exception(ec.value()))); return deref(); } else if (m_read < m_read_size) // there is more to read { - auto writebuf = m_request._get_impl()->outstream().streambuf(); - writebuf.putn_nocopy(boost::asio::buffer_cast(m_request_buf.data()), std::min(m_request_buf.size(), m_read_size - m_read)).then([=](pplx::task writtenSizeTask) -> will_deref_t + auto writebuf = requestImpl->outstream().streambuf(); + writebuf.putn_nocopy(boost::asio::buffer_cast(m_request_buf.data()), std::min(m_request_buf.size(), m_read_size - m_read)).then([this](pplx::task writtenSizeTask) -> will_deref_t { size_t writtenSize = 0; try @@ -894,7 +906,7 @@ will_deref_t asio_server_connection::handle_body(const boost::system::error_code } catch (...) { - m_request._get_impl()->_complete(0, std::current_exception()); + get_request()._get_impl()->_complete(0, std::current_exception()); return deref(); } m_read += writtenSize; @@ -910,7 +922,7 @@ will_deref_t asio_server_connection::handle_body(const boost::system::error_code } else // have read request body { - m_request._get_impl()->_complete(m_read); + requestImpl->_complete(m_read); return deref(); } } @@ -981,14 +993,14 @@ will_deref_and_erase_t asio_server_connection::dispatch_request_to_listener() { // locate the listener: http_listener_impl* pListener = nullptr; - + auto currentRequest = get_request(); try { - pListener = m_p_parent->find_listener(m_request.relative_uri()); + pListener = m_p_parent->find_listener(currentRequest.relative_uri()); } catch (const std::exception&) // may be web::uri_exception, or std::range_error indicating invalid Unicode { - m_request.reply(status_codes::BadRequest); + currentRequest.reply(status_codes::BadRequest); (will_erase_from_parent_t)do_response(); (will_deref_t)deref(); return will_deref_and_erase_t{}; @@ -996,13 +1008,13 @@ will_deref_and_erase_t asio_server_connection::dispatch_request_to_listener() if (pListener == nullptr) { - m_request.reply(status_codes::NotFound); + currentRequest.reply(status_codes::NotFound); (will_erase_from_parent_t)do_response(); (will_deref_t)deref(); return will_deref_and_erase_t{}; } - m_request._set_listener_path(pListener->uri().path()); + currentRequest._set_listener_path(pListener->uri().path()); (will_erase_from_parent_t)do_response(); // Look up the lock for the http_listener. @@ -1013,7 +1025,7 @@ will_deref_and_erase_t asio_server_connection::dispatch_request_to_listener() // It is possible the listener could have unregistered. if(m_p_server->m_registered_listeners.find(pListener) == m_p_server->m_registered_listeners.end()) { - m_request.reply(status_codes::NotFound); + currentRequest.reply(status_codes::NotFound); (will_deref_t)deref(); return will_deref_and_erase_t{}; @@ -1027,13 +1039,13 @@ will_deref_and_erase_t asio_server_connection::dispatch_request_to_listener() try { - pListener->handle_request(m_request); + pListener->handle_request(currentRequest); pListenerLock->unlock(); } catch(...) { pListenerLock->unlock(); - m_request._reply_if_not_already(status_codes::InternalError); + currentRequest._reply_if_not_already(status_codes::InternalError); } (will_deref_t)deref(); @@ -1330,7 +1342,7 @@ pplx::task http_linux_server::register_listener(http_listener_impl* listen } catch (...) { - // Future improvement - really this API should entirely be asychronously. + // Future improvement - really this API should entirely be asynchronously. // the hostport_listener::start() method should be made to return a task // throwing the exception. m_registered_listeners.erase(listener); diff --git a/Release/src/http/listener/http_server_httpsys.cpp b/Release/src/http/listener/http_server_httpsys.cpp index 9cde3f522e..e882870cbf 100644 --- a/Release/src/http/listener/http_server_httpsys.cpp +++ b/Release/src/http/listener/http_server_httpsys.cpp @@ -420,7 +420,7 @@ void http_windows_server::receive_requests() // Oversubscribe since this is a blocking call and we don't want to count // towards the concurrency runtime's thread count. A more proper fix // would be to use Overlapped I/O and asynchronously call HttpReceiveHttpRequest. - // This requires additional work to be careful sychronizing with the listener + // This requires additional work to be careful synchronizing with the listener // shutdown. This is much easier especially given the http_listener is 'experimental' // and with VS2015 PPL tasks run on the threadpool. #if _MSC_VER < 1900 @@ -918,7 +918,7 @@ void windows_request_context::async_process_response() } if (!m_response._get_impl()->compressor()) { - // Temporarily move the compressor to the reponse, so _get_content_length() will honor it + // Temporarily move the compressor to the response, so _get_content_length() will honor it m_response._get_impl()->set_compressor(std::move(m_compressor)); } // else one was already set from a callback, and we'll (blindly) use it content_length = m_response._get_impl()->_get_content_length_and_set_compression(); diff --git a/Release/src/json/json_parsing.cpp b/Release/src/json/json_parsing.cpp index 9863f0db5b..ffa631aac1 100644 --- a/Release/src/json/json_parsing.cpp +++ b/Release/src/json/json_parsing.cpp @@ -1029,7 +1029,7 @@ std::unique_ptr JSON_Parser::_ParseObject( ::std::sort(elems.begin(), elems.end(), json::object::compare_pairs); } - return std::move(obj); + return std::unique_ptr(obj.release()); error: if (!tkn.m_error) @@ -1076,7 +1076,7 @@ std::unique_ptr JSON_Parser::_ParseArray(t GetNextToken(tkn); if (tkn.m_error) return utility::details::make_unique(); - return std::move(result); + return std::unique_ptr(result.release()); } template diff --git a/Release/src/pch/stdafx.h b/Release/src/pch/stdafx.h index dc909d5afd..811786cacf 100644 --- a/Release/src/pch/stdafx.h +++ b/Release/src/pch/stdafx.h @@ -52,7 +52,7 @@ #include #include #include "pthread.h" -#if (defined(ANDROID) || defined(__ANDROID__)) +#if (defined(ANDROID) || defined(__ANDROID__)) && !defined(_LIBCPP_VERSION) // Boost doesn't recognize libstdcpp on top of clang correctly #include "boost/config.hpp" #include "boost/config/stdlib/libstdcpp3.hpp" diff --git a/Release/src/pplx/pplxwin.cpp b/Release/src/pplx/pplxwin.cpp index e511c0ad5d..c414397c16 100644 --- a/Release/src/pplx/pplxwin.cpp +++ b/Release/src/pplx/pplxwin.cpp @@ -275,4 +275,19 @@ namespace details } // namespace pplx +#else +namespace Concurrency +{ + +void __cdecl set_cpprestsdk_ambient_scheduler(const std::shared_ptr& _Scheduler) +{ + pplx::set_ambient_scheduler(_Scheduler); +} + +const std::shared_ptr& __cdecl get_cpprestsdk_ambient_scheduler() +{ + return pplx::get_ambient_scheduler(); +} + +} // namespace pplx #endif \ No newline at end of file diff --git a/Release/src/pplx/threadpool.cpp b/Release/src/pplx/threadpool.cpp index cd6c1168ea..f6a0366a4c 100644 --- a/Release/src/pplx/threadpool.cpp +++ b/Release/src/pplx/threadpool.cpp @@ -25,6 +25,17 @@ namespace // This pointer will be 0-initialized by default (at load time). std::atomic JVM; +static void abort_if_no_jvm() +{ + if (JVM == nullptr) + { + __android_log_print(ANDROID_LOG_ERROR, "CPPRESTSDK", "%s", + "The CppREST SDK must be initialized before first use on android: " + "https://github.com/Microsoft/cpprestsdk/wiki/How-to-build-for-Android"); + std::abort(); + } +} + JNIEnv* get_jvm_env() { abort_if_no_jvm(); @@ -37,17 +48,6 @@ JNIEnv* get_jvm_env() return env; } - -static void abort_if_no_jvm() -{ - if (JVM == nullptr) - { - __android_log_print(ANDROID_LOG_ERROR, "CPPRESTSDK", "%s", - "The CppREST SDK must be initialized before first use on android: " - "https://github.com/Microsoft/cpprestsdk/wiki/How-to-build-for-Android"); - std::abort(); - } -} #endif // __ANDROID__ struct threadpool_impl final : crossplat::threadpool @@ -110,7 +110,7 @@ struct threadpool_impl final : crossplat::threadpool #if defined(_WIN32) struct shared_threadpool { - typename std::aligned_union<0, threadpool_impl>::type shared_storage; + std::aligned_union<0, threadpool_impl>::type shared_storage; threadpool_impl& get_shared() { diff --git a/Release/src/streams/fileio_posix.cpp b/Release/src/streams/fileio_posix.cpp index ce166957ce..a3690f1070 100644 --- a/Release/src/streams/fileio_posix.cpp +++ b/Release/src/streams/fileio_posix.cpp @@ -54,7 +54,7 @@ struct _file_info_impl : _file_info bool m_buffer_reads; /// - /// A list of callback waiting to be signalled that there are no outstanding writes. + /// A list of callback waiting to be signaled that there are no outstanding writes. /// std::vector<_filestream_callback *> m_sync_waiters; diff --git a/Release/src/streams/fileio_win32.cpp b/Release/src/streams/fileio_win32.cpp index a27c74e11f..cebe72a171 100644 --- a/Release/src/streams/fileio_win32.cpp +++ b/Release/src/streams/fileio_win32.cpp @@ -414,11 +414,11 @@ size_t _write_file_async(_In_ streams::details::_file_info_impl *fInfo, _In_ str DWORD error = GetLastError(); // 1. If WriteFile returned true, it must be because the operation completed immediately. - // The xp threadpool immediatly creates a workerthread to run "_WriteFileCompletionRoutine". + // The xp threadpool immediately creates a workerthread to run "_WriteFileCompletionRoutine". // If this function return value > 0, the condition "if (written == sizeof(_CharType))" in the filestreams.h "_getcImpl()" function will be satisfied. // The main thread will delete the input "callback", while the threadpool workerthread is accessing this "callback"; there will be a race condition and AV error. // We directly return 0 and leave all the completion callbacks working on the workerthread. - // We do not need to call GetOverlappedResult, the workerthread will call the "on_error()" if the WriteFaile falied. + // We do not need to call GetOverlappedResult, the workerthread will call the "on_error()" if the WriteFaile failed. // "req" is deleted in "_WriteFileCompletionRoutine, "pOverlapped" is deleted in io_scheduler::FileIOCompletionRoutine. if (wrResult == TRUE) { @@ -508,11 +508,11 @@ size_t _read_file_async(_In_ streams::details::_file_info_impl *fInfo, _In_ stre DWORD error = GetLastError(); // 1. If ReadFile returned true, it must be because the operation completed immediately. - // The xp threadpool immediatly creates a workerthread to run "_WriteFileCompletionRoutine". + // The xp threadpool immediately creates a workerthread to run "_WriteFileCompletionRoutine". // If this function return value > 0, the condition "if ( ch == sizeof(_CharType) )" in the filestreams.h "_getcImpl()" function will be satisfied. // The main thread will delete the input "callback", while the threadpool workerthread is accessing this "callback"; there will be a race condition and AV error. // We can directly return 0 and leave all the completion callbacks working on the workerthread. - // We do not need to call GetOverlappedResult, the workerthread will call the "on_error()" if the ReadFile falied. + // We do not need to call GetOverlappedResult, the workerthread will call the "on_error()" if the ReadFile failed. // "req" is deleted in "_ReadFileCompletionRoutine, "pOverlapped" is deleted in io_scheduler::FileIOCompletionRoutine. if (wrResult == TRUE) { diff --git a/Release/src/streams/fileio_winrt.cpp b/Release/src/streams/fileio_winrt.cpp index 7585ac15ba..1a206b4e74 100644 --- a/Release/src/streams/fileio_winrt.cpp +++ b/Release/src/streams/fileio_winrt.cpp @@ -540,7 +540,7 @@ size_t __cdecl _putn_fsb(_In_ Concurrency::streams::details::_file_info *info, _ // In most of the time, we preserve the writer so that it would have better performance. - // However, after uer call seek, we will despose old writer. By doing so, users could + // However, after user call seek, we will dispose old writer. By doing so, users could // write to new writer in new position while the old writer is still flushing data into stream. if (fInfo->m_writer == nullptr) { diff --git a/Release/src/utilities/asyncrt_utils.cpp b/Release/src/utilities/asyncrt_utils.cpp index eb20f91f0e..2878c52aae 100644 --- a/Release/src/utilities/asyncrt_utils.cpp +++ b/Release/src/utilities/asyncrt_utils.cpp @@ -347,19 +347,33 @@ const std::error_category & __cdecl linux_category() #define H_SURROGATE_END 0xDBFF #define SURROGATE_PAIR_START 0x10000 +// Create a dedicated type for characters to avoid the issue +// of different platforms defaulting char to be either signed +// or unsigned. +using UtilCharInternal_t = signed char; + + inline size_t count_utf8_to_utf16(const std::string& s) { const size_t sSize = s.size(); - const char* const sData = s.data(); + auto sData = reinterpret_cast(s.data()); size_t result{ sSize }; + for (size_t index = 0; index < sSize;) { - const char c{ sData[index++] }; - if ((c & BIT8) == 0) + if( sData[index] > 0 ) { - continue; + // use fast inner loop to skip single byte code points (which are + // expected to be the most frequent) + while ((++index < sSize) && (sData[index] > 0)) + ; + + if (index >= sSize) break; } + // start special handling for multi-byte code points + const UtilCharInternal_t c{ sData[index++] }; + if ((c & BIT7) == 0) { throw std::range_error("UTF-8 string character can never start with 10xxxxxx"); @@ -371,7 +385,7 @@ inline size_t count_utf8_to_utf16(const std::string& s) throw std::range_error("UTF-8 string is missing bytes in character"); } - const char c2{ sData[index++] }; + const UtilCharInternal_t c2{ sData[index++] }; if ((c2 & 0xC0) != BIT8) { throw std::range_error("UTF-8 continuation byte is missing leading bit mask"); @@ -387,8 +401,8 @@ inline size_t count_utf8_to_utf16(const std::string& s) throw std::range_error("UTF-8 string is missing bytes in character"); } - const char c2{ sData[index++] }; - const char c3{ sData[index++] }; + const UtilCharInternal_t c2{ sData[index++] }; + const UtilCharInternal_t c3{ sData[index++] }; if (((c2 | c3) & 0xC0) != BIT8) { throw std::range_error("UTF-8 continuation byte is missing leading bit mask"); @@ -403,9 +417,9 @@ inline size_t count_utf8_to_utf16(const std::string& s) throw std::range_error("UTF-8 string is missing bytes in character"); } - const char c2{ sData[index++] }; - const char c3{ sData[index++] }; - const char c4{ sData[index++] }; + const UtilCharInternal_t c2{ sData[index++] }; + const UtilCharInternal_t c3{ sData[index++] }; + const UtilCharInternal_t c4{ sData[index++] }; if (((c2 | c3 | c4) & 0xC0) != BIT8) { throw std::range_error("UTF-8 continuation byte is missing leading bit mask"); @@ -427,21 +441,21 @@ utf16string __cdecl conversions::utf8_to_utf16(const std::string &s) { // Save repeated heap allocations, use the length of resulting sequence. const size_t srcSize = s.size(); - const std::string::value_type* const srcData = &s[0]; + auto srcData = reinterpret_cast(s.data()); utf16string dest(count_utf8_to_utf16(s), L'\0'); utf16string::value_type* const destData = &dest[0]; size_t destIndex = 0; for (size_t index = 0; index < srcSize; ++index) { - std::string::value_type src = srcData[index]; + UtilCharInternal_t src = srcData[index]; switch (src & 0xF0) { case 0xF0: // 4 byte character, 0x10000 to 0x10FFFF { - const char c2{ srcData[++index] }; - const char c3{ srcData[++index] }; - const char c4{ srcData[++index] }; + const UtilCharInternal_t c2{ srcData[++index] }; + const UtilCharInternal_t c3{ srcData[++index] }; + const UtilCharInternal_t c4{ srcData[++index] }; uint32_t codePoint = ((src & LOW_3BITS) << 18) | ((c2 & LOW_6BITS) << 12) | ((c3 & LOW_6BITS) << 6) | (c4 & LOW_6BITS); if (codePoint >= SURROGATE_PAIR_START) { @@ -464,20 +478,27 @@ utf16string __cdecl conversions::utf8_to_utf16(const std::string &s) break; case 0xE0: // 3 byte character, 0x800 to 0xFFFF { - const char c2{ srcData[++index] }; - const char c3{ srcData[++index] }; + const UtilCharInternal_t c2{ srcData[++index] }; + const UtilCharInternal_t c3{ srcData[++index] }; destData[destIndex++] = static_cast(((src & LOW_4BITS) << 12) | ((c2 & LOW_6BITS) << 6) | (c3 & LOW_6BITS)); } break; case 0xD0: // 2 byte character, 0x80 to 0x7FF case 0xC0: { - const char c2{ srcData[++index] }; + const UtilCharInternal_t c2{ srcData[++index] }; destData[destIndex++] = static_cast(((src & LOW_5BITS) << 6) | (c2 & LOW_6BITS)); } break; default: // single byte character, 0x0 to 0x7F - destData[destIndex++] = static_cast(src); + // try to use a fast inner loop for following single byte characters, + // since they are quite probable + do + { + destData[destIndex++] = static_cast(srcData[index++]); + } while (index < srcSize && srcData[index] > 0); + // adjust index since it will be incremented by the for loop + --index; } } return dest; diff --git a/Release/src/websockets/client/ws_client_wspp.cpp b/Release/src/websockets/client/ws_client_wspp.cpp index 5ba93d25eb..0715249f16 100644 --- a/Release/src/websockets/client/ws_client_wspp.cpp +++ b/Release/src/websockets/client/ws_client_wspp.cpp @@ -24,23 +24,26 @@ // Force websocketpp to use C++ std::error_code instead of Boost. #define _WEBSOCKETPP_CPP11_SYSTEM_ERROR_ #if defined(_MSC_VER) -#pragma warning( push ) -#pragma warning( disable : 4100 4127 4512 4996 4701 4267 ) -#define _WEBSOCKETPP_CPP11_STL_ -#define _WEBSOCKETPP_CONSTEXPR_TOKEN_ -#if _MSC_VER < 1900 -#define _WEBSOCKETPP_NOEXCEPT_TOKEN_ -#endif -#elif defined(__GNUC__) -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wconversion" -#pragma GCC diagnostic ignored "-Wunused-parameter" -#pragma GCC diagnostic ignored "-Wignored-qualifiers" -#pragma GCC diagnostic ignored "-Wcast-qual" + #pragma warning( push ) + #pragma warning( disable : 4100 4127 4512 4996 4701 4267 ) + #define _WEBSOCKETPP_CPP11_STL_ + #define _WEBSOCKETPP_CONSTEXPR_TOKEN_ + #if _MSC_VER < 1900 + #define _WEBSOCKETPP_NOEXCEPT_TOKEN_ + #endif #elif defined(__clang__) -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wconversion" -#pragma clang diagnostic ignored "-Winfinite-recursion" + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wconversion" + #pragma clang diagnostic ignored "-Winfinite-recursion" + #pragma clang diagnostic ignored "-Wtautological-constant-compare" + #pragma clang diagnostic ignored "-Wtautological-unsigned-enum-zero-compare" + #pragma clang diagnostic ignored "-Wcast-qual" +#elif defined(__GNUC__) + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wconversion" + #pragma GCC diagnostic ignored "-Wunused-parameter" + #pragma GCC diagnostic ignored "-Wignored-qualifiers" + #pragma GCC diagnostic ignored "-Wcast-qual" #endif #include @@ -49,10 +52,10 @@ #if defined(_WIN32) #pragma warning( pop ) -#elif defined(__GNUC__) -#pragma GCC diagnostic pop #elif defined(__clang__) #pragma clang diagnostic pop +#elif defined(__GNUC__) +#pragma GCC diagnostic pop #endif diff --git a/Release/tests/common/UnitTestpp/src/CurrentTest.cpp b/Release/tests/common/UnitTestpp/src/CurrentTest.cpp index 08916e9d2f..35aa1a9cba 100644 --- a/Release/tests/common/UnitTestpp/src/CurrentTest.cpp +++ b/Release/tests/common/UnitTestpp/src/CurrentTest.cpp @@ -1,10 +1,10 @@ /*** * This file is based on or incorporates material from the UnitTest++ r30 open source project. -* Microsoft is not the original author of this code but has modified it and is licensing the code under -* the MIT License. Microsoft reserves all other rights not expressly granted under the MIT License, -* whether by implication, estoppel or otherwise. +* Microsoft is not the original author of this code but has modified it and is licensing the code under +* the MIT License. Microsoft reserves all other rights not expressly granted under the MIT License, +* whether by implication, estoppel or otherwise. * -* UnitTest++ r30 +* UnitTest++ r30 * * Copyright (c) 2006 Noel Llopis and Charles Nicholson * Portions Copyright (c) Microsoft Corporation @@ -13,36 +13,48 @@ * * MIT License * -* Permission is hereby granted, free of charge, to any person obtaining a copy of this software -* and associated documentation files (the "Software"), to deal in the Software without restriction, -* including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, -* and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, +* Permission is hereby granted, free of charge, to any person obtaining a copy of this software +* and associated documentation files (the "Software"), to deal in the Software without restriction, +* including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, +* and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, * subject to the following conditions: * -* The above copyright notice and this permission notice shall be included in all copies or +* The above copyright notice and this permission notice shall be included in all copies or * substantial portions of the Software. * -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, -* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE -* AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE +* AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ***/ #include "stdafx.h" +#include + +namespace { + std::atomic testResults; + std::atomic testDetails; // non-const pointer to avoid VS2013 STL bug +} namespace UnitTest { -UNITTEST_LINKAGE TestResults*& CurrentTest::Results() +UNITTEST_LINKAGE TestResults* CurrentTest::Results() { - static TestResults* testResults = NULL; return testResults; } -UNITTEST_LINKAGE const TestDetails*& CurrentTest::Details() +UNITTEST_LINKAGE void CurrentTest::SetResults(TestResults * r) { + testResults.store(r); +} + +UNITTEST_LINKAGE const TestDetails* CurrentTest::Details() { - static const TestDetails* testDetails = NULL; return testDetails; } +UNITTEST_LINKAGE void CurrentTest::SetDetails(const UnitTest::TestDetails * d) { + testDetails.store(const_cast(d)); +} + } diff --git a/Release/tests/common/UnitTestpp/src/CurrentTest.h b/Release/tests/common/UnitTestpp/src/CurrentTest.h index 0b64ade5e7..4dbe6eff94 100644 --- a/Release/tests/common/UnitTestpp/src/CurrentTest.h +++ b/Release/tests/common/UnitTestpp/src/CurrentTest.h @@ -1,10 +1,10 @@ /*** * This file is based on or incorporates material from the UnitTest++ r30 open source project. -* Microsoft is not the original author of this code but has modified it and is licensing the code under -* the MIT License. Microsoft reserves all other rights not expressly granted under the MIT License, -* whether by implication, estoppel or otherwise. +* Microsoft is not the original author of this code but has modified it and is licensing the code under +* the MIT License. Microsoft reserves all other rights not expressly granted under the MIT License, +* whether by implication, estoppel or otherwise. * -* UnitTest++ r30 +* UnitTest++ r30 * * Copyright (c) 2006 Noel Llopis and Charles Nicholson * Portions Copyright (c) Microsoft Corporation @@ -13,19 +13,19 @@ * * MIT License * -* Permission is hereby granted, free of charge, to any person obtaining a copy of this software -* and associated documentation files (the "Software"), to deal in the Software without restriction, -* including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, -* and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, +* Permission is hereby granted, free of charge, to any person obtaining a copy of this software +* and associated documentation files (the "Software"), to deal in the Software without restriction, +* including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, +* and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, * subject to the following conditions: * -* The above copyright notice and this permission notice shall be included in all copies or +* The above copyright notice and this permission notice shall be included in all copies or * substantial portions of the Software. * -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, -* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE -* AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE +* AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ***/ @@ -41,8 +41,10 @@ class TestDetails; namespace CurrentTest { - UNITTEST_LINKAGE TestResults*& __cdecl Results(); - UNITTEST_LINKAGE const TestDetails*& __cdecl Details(); + UNITTEST_LINKAGE TestResults* __cdecl Results(); + UNITTEST_LINKAGE void __cdecl SetResults(TestResults*); + UNITTEST_LINKAGE const TestDetails* __cdecl Details(); + UNITTEST_LINKAGE void __cdecl SetDetails(const TestDetails *); } } diff --git a/Release/tests/common/UnitTestpp/src/ExecuteTest.h b/Release/tests/common/UnitTestpp/src/ExecuteTest.h index 8cd5ed74b3..ef87c48dc3 100644 --- a/Release/tests/common/UnitTestpp/src/ExecuteTest.h +++ b/Release/tests/common/UnitTestpp/src/ExecuteTest.h @@ -1,10 +1,10 @@ /*** * This file is based on or incorporates material from the UnitTest++ r30 open source project. -* Microsoft is not the original author of this code but has modified it and is licensing the code under -* the MIT License. Microsoft reserves all other rights not expressly granted under the MIT License, -* whether by implication, estoppel or otherwise. +* Microsoft is not the original author of this code but has modified it and is licensing the code under +* the MIT License. Microsoft reserves all other rights not expressly granted under the MIT License, +* whether by implication, estoppel or otherwise. * -* UnitTest++ r30 +* UnitTest++ r30 * * Copyright (c) 2006 Noel Llopis and Charles Nicholson * Portions Copyright (c) Microsoft Corporation @@ -13,19 +13,19 @@ * * MIT License * -* Permission is hereby granted, free of charge, to any person obtaining a copy of this software -* and associated documentation files (the "Software"), to deal in the Software without restriction, -* including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, -* and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, +* Permission is hereby granted, free of charge, to any person obtaining a copy of this software +* and associated documentation files (the "Software"), to deal in the Software without restriction, +* including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, +* and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, * subject to the following conditions: * -* The above copyright notice and this permission notice shall be included in all copies or +* The above copyright notice and this permission notice shall be included in all copies or * substantial portions of the Software. * -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, -* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE -* AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE +* AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ***/ @@ -57,7 +57,7 @@ void ExecuteTest(T& testObject, TestDetails const& details, bool isMockTest) { if (isMockTest == false) { - CurrentTest::Details() = &details; + CurrentTest::SetDetails(&details); } #ifdef UNITTEST_NO_EXCEPTIONS diff --git a/Release/tests/common/UnitTestpp/src/TestRunner.cpp b/Release/tests/common/UnitTestpp/src/TestRunner.cpp index 6b249404b7..3f523cf9a8 100644 --- a/Release/tests/common/UnitTestpp/src/TestRunner.cpp +++ b/Release/tests/common/UnitTestpp/src/TestRunner.cpp @@ -1,10 +1,10 @@ /*** * This file is based on or incorporates material from the UnitTest++ r30 open source project. -* Microsoft is not the original author of this code but has modified it and is licensing the code under -* the MIT License. Microsoft reserves all other rights not expressly granted under the MIT License, -* whether by implication, estoppel or otherwise. +* Microsoft is not the original author of this code but has modified it and is licensing the code under +* the MIT License. Microsoft reserves all other rights not expressly granted under the MIT License, +* whether by implication, estoppel or otherwise. * -* UnitTest++ r30 +* UnitTest++ r30 * * Copyright (c) 2006 Noel Llopis and Charles Nicholson * Portions Copyright (c) Microsoft Corporation @@ -13,19 +13,19 @@ * * MIT License * -* Permission is hereby granted, free of charge, to any person obtaining a copy of this software -* and associated documentation files (the "Software"), to deal in the Software without restriction, -* including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, -* and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, +* Permission is hereby granted, free of charge, to any person obtaining a copy of this software +* and associated documentation files (the "Software"), to deal in the Software without restriction, +* including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, +* and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, * subject to the following conditions: * -* The above copyright notice and this permission notice shall be included in all copies or +* The above copyright notice and this permission notice shall be included in all copies or * substantial portions of the Software. * -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, -* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE -* AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE +* AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ***/ @@ -78,11 +78,11 @@ TestResults* TestRunner::GetTestResults() int TestRunner::Finish() const { float const secondsElapsed = static_cast(m_timer->GetTimeInMs() / 1000.0); - m_reporter->ReportSummary(m_result->GetTotalTestCount(), - m_result->GetFailedTestCount(), - m_result->GetFailureCount(), + m_reporter->ReportSummary(m_result->GetTotalTestCount(), + m_result->GetFailedTestCount(), + m_result->GetFailureCount(), secondsElapsed); - + return m_result->GetFailureCount(); } @@ -97,8 +97,8 @@ bool TestRunner::IsTestInSuite(const Test* const curTest, char const* suiteName) // to use agent. class TestRunnerAgent : public Concurrency::agent { -public: - TestRunnerAgent(std::tr1::function func) : m_func(func) {} +public: + TestRunnerAgent(std::tr1::function func) : m_func(func) {} protected: void run() { @@ -137,7 +137,7 @@ int TestRunner::GetTestTimeout(Test* const curTest, int const defaultTestTimeInM void TestRunner::RunTest(TestResults* const result, Test* const curTest, int const defaultTestTimeInMs) const { if (curTest->m_isMockTest == false) - CurrentTest::Results() = result; + CurrentTest::SetResults(result); int maxTestTimeInMs = GetTestTimeout(curTest, defaultTestTimeInMs); @@ -158,7 +158,7 @@ void TestRunner::RunTest(TestResults* const result, Test* const curTest, int con try { Concurrency::agent::wait(&testRunnerAgent, maxTestTimeInMs); - } + } catch(const Concurrency::operation_timed_out &) { timedOut = true; @@ -196,7 +196,7 @@ void TestRunner::RunTest(TestResults* const result, Test* const curTest, int con abort(); } - } + } else { curTest->Run(); diff --git a/Release/tests/functional/http/client/CMakeLists.txt b/Release/tests/functional/http/client/CMakeLists.txt index d92b477481..45f0d9af02 100644 --- a/Release/tests/functional/http/client/CMakeLists.txt +++ b/Release/tests/functional/http/client/CMakeLists.txt @@ -2,8 +2,11 @@ set(SOURCES authentication_tests.cpp building_request_tests.cpp client_construction.cpp + compression_tests.cpp + connection_pool_tests.cpp connections_and_errors.cpp header_tests.cpp + http_client_fuzz_tests.cpp http_client_tests.cpp http_methods_tests.cpp multiple_requests.cpp @@ -20,8 +23,6 @@ set(SOURCES response_stream_tests.cpp status_code_reason_phrase_tests.cpp to_string_tests.cpp - http_client_fuzz_tests.cpp - compression_tests.cpp ) add_casablanca_test(httpclient_test SOURCES) diff --git a/Release/tests/functional/http/client/building_request_tests.cpp b/Release/tests/functional/http/client/building_request_tests.cpp index a12ddfe8fc..72925b7152 100644 --- a/Release/tests/functional/http/client/building_request_tests.cpp +++ b/Release/tests/functional/http/client/building_request_tests.cpp @@ -113,7 +113,7 @@ TEST_FIXTURE(uri_address, body_types) p_request->reply(200); }); http_asserts::assert_response_equals(client.request(msg).get(), status_codes::OK); - + // string - no content type. msg = http_request(method); msg.set_body(std::move(str_move_body)); @@ -143,7 +143,7 @@ TEST(set_body_string_with_charset) { http_request request; VERIFY_THROWS(request.set_body( - ::utility::conversions::to_utf16string("body_data"), + ::utility::conversions::to_utf16string("body_data"), ::utility::conversions::to_utf16string("text/plain;charset=utf-16")), std::invalid_argument); } @@ -236,7 +236,7 @@ TEST_FIXTURE(uri_address, set_body_with_charset) http_request msg(methods::PUT); msg.set_body("datadatadata", "text/plain;charset=us-ascii"); VERIFY_THROWS(msg.set_body( - ::utility::conversions::to_utf16string("datadatadata"), + ::utility::conversions::to_utf16string("datadatadata"), ::utility::conversions::to_utf16string("text/plain;charset=us-ascii")), std::invalid_argument); } @@ -321,4 +321,4 @@ TEST_FIXTURE(uri_address, reuse_request) } -}}}} \ No newline at end of file +}}}} diff --git a/Release/tests/functional/http/client/compression_tests.cpp b/Release/tests/functional/http/client/compression_tests.cpp index 889ab71797..d6d8ea1732 100644 --- a/Release/tests/functional/http/client/compression_tests.cpp +++ b/Release/tests/functional/http/client/compression_tests.cpp @@ -642,7 +642,7 @@ SUITE(compression_tests) // Null decompressor - effectively forces no compression algorithms dv.push_back(std::shared_ptr()); builtin = web::http::compression::details::build_supported_header(ctype, dv); - VERIFY_ARE_EQUAL((bool)transfer, builtin.empty()); + VERIFY_ARE_EQUAL(transfer != 0, builtin.empty()); dv.pop_back(); if (web::http::compression::builtin::supported()) @@ -693,17 +693,17 @@ SUITE(compression_tests) if (c) { VERIFY_IS_TRUE(web::http::compression::builtin::supported()); - VERIFY_IS_FALSE((bool)fake); + VERIFY_IS_FALSE(fake != 0); VERIFY_ARE_EQUAL(c->algorithm(), gzip); } else { - VERIFY_IS_TRUE((bool)fake || !web::http::compression::builtin::supported()); + VERIFY_IS_TRUE(fake != 0 || !web::http::compression::builtin::supported()); } // Supplied compressor - both matching and non-matching c = web::http::compression::details::get_compressor_from_header(*te, ctype, fcv); - VERIFY_ARE_EQUAL((bool)c, (bool)fake); + VERIFY_ARE_EQUAL(c != 0, fake != 0); if (c) { VERIFY_ARE_EQUAL(c->algorithm(), fake_provider::FAKE); @@ -1108,7 +1108,7 @@ SUITE(compression_tests) } else { - memcpy(vv.data(), v.data(), v.size()); + std::copy(v.begin(), v.end(), vv.begin()); got = v.size(); } VERIFY_ARE_EQUAL(buffer_size, got); diff --git a/Release/tests/functional/http/client/connection_pool_tests.cpp b/Release/tests/functional/http/client/connection_pool_tests.cpp new file mode 100644 index 0000000000..037ed69d88 --- /dev/null +++ b/Release/tests/functional/http/client/connection_pool_tests.cpp @@ -0,0 +1,45 @@ +#include "stdafx.h" +#include +#include "../../../src/http/common/connection_pool_helpers.h" + +using namespace web::http::client::details; + +SUITE(connection_pooling) { + TEST(empty_returns_nullptr) { + connection_pool_stack connectionStack; + VERIFY_ARE_EQUAL(connectionStack.try_acquire(), std::shared_ptr{}); + } + + static int noisyCount = 0; + struct noisy { + noisy() = delete; + noisy(int) { ++noisyCount; } + noisy(const noisy&) = delete; + noisy(noisy&&) { ++noisyCount; } + noisy& operator=(const noisy&) = delete; + noisy& operator=(noisy&&) = delete; + ~noisy() { --noisyCount; } + }; + + TEST(cycled_connections_survive) { + connection_pool_stack connectionStack; + VERIFY_ARE_EQUAL(0, noisyCount); + connectionStack.release(std::make_shared(42)); + connectionStack.release(std::make_shared(42)); + connectionStack.release(std::make_shared(42)); + VERIFY_ARE_EQUAL(3, noisyCount); + VERIFY_IS_TRUE(connectionStack.free_stale_connections()); + auto tmp = connectionStack.try_acquire(); + VERIFY_ARE_NOT_EQUAL(tmp, std::shared_ptr{}); + connectionStack.release(std::move(tmp)); + VERIFY_ARE_EQUAL(tmp, std::shared_ptr{}); + tmp = connectionStack.try_acquire(); + VERIFY_ARE_NOT_EQUAL(tmp, std::shared_ptr{}); + connectionStack.release(std::move(tmp)); + VERIFY_IS_TRUE(connectionStack.free_stale_connections()); + VERIFY_ARE_EQUAL(1, noisyCount); + VERIFY_IS_FALSE(connectionStack.free_stale_connections()); + VERIFY_ARE_EQUAL(0, noisyCount); + VERIFY_IS_FALSE(connectionStack.free_stale_connections()); + } +}; diff --git a/Release/tests/functional/http/client/outside_tests.cpp b/Release/tests/functional/http/client/outside_tests.cpp index bec9b0c458..bb5909d35e 100644 --- a/Release/tests/functional/http/client/outside_tests.cpp +++ b/Release/tests/functional/http/client/outside_tests.cpp @@ -111,6 +111,43 @@ TEST_FIXTURE(uri_address, multiple_https_requests) }); } +#if (defined(_MSC_VER) && (_MSC_VER >= 1800)) && !CPPREST_FORCE_PPLX +TEST_FIXTURE(uri_address, multiple_https_requests_sync_scheduler) +{ + struct sync_scheduler : public scheduler_interface + { + public: + virtual void schedule(TaskProc_t function, PVOID context) override + { + function(context); + } + }; + + // Save the current ambient scheduler + const auto scheduler = get_cpprestsdk_ambient_scheduler(); + + // Change the ambient scheduler to one that schedules synchronously + static std::shared_ptr syncScheduler = std::make_shared(); + set_cpprestsdk_ambient_scheduler(syncScheduler); + + handle_timeout([&] { + // Use code.google.com instead of www.google.com, which redirects + http_client client(U("https://code.google.com")); + + http_response response; + for (int i = 0; i < 5; ++i) + { + response = client.request(methods::GET).get(); + VERIFY_ARE_EQUAL(status_codes::OK, response.status_code()); + response.content_ready().wait(); + } + }); + + // Revert to the original scheduler + set_cpprestsdk_ambient_scheduler(scheduler); +} +#endif + TEST_FIXTURE(uri_address, reading_google_stream) { handle_timeout([&] diff --git a/Release/tests/functional/http/client/progress_handler_tests.cpp b/Release/tests/functional/http/client/progress_handler_tests.cpp index 4b9568c36e..a4e1c8a968 100644 --- a/Release/tests/functional/http/client/progress_handler_tests.cpp +++ b/Release/tests/functional/http/client/progress_handler_tests.cpp @@ -37,13 +37,13 @@ TEST_FIXTURE(uri_address, set_progress_handler_no_bodies) http_request msg(mtd); msg.set_progress_handler( - [&](message_direction::direction direction, utility::size64_t so_far) - { + [&](message_direction::direction direction, utility::size64_t so_far) + { calls += 1; - if (direction == message_direction::upload) - upsize = so_far; - else - downsize = so_far; + if (direction == message_direction::upload) + upsize = so_far; + else + downsize = so_far; }); test_http_server::scoped_server scoped(m_uri); @@ -123,19 +123,19 @@ TEST_FIXTURE(uri_address, set_progress_handler_download) http_client client(m_uri, config); const method mtd = methods::GET; - + utility::size64_t upsize = 4711u, downsize = 4711u; int calls = 0; http_request msg(mtd); msg.set_progress_handler( - [&](message_direction::direction direction, utility::size64_t so_far) - { + [&](message_direction::direction direction, utility::size64_t so_far) + { calls += 1; - if (direction == message_direction::upload) - upsize = so_far; - else - downsize = so_far; + if (direction == message_direction::upload) + upsize = so_far; + else + downsize = so_far; }); const size_t repeats = 6000; @@ -179,19 +179,19 @@ TEST_FIXTURE(uri_address, set_progress_handler_upload_and_download) const size_t repeats = 5500; for (size_t i = 0; i < repeats; ++i) data.append(U("abcdefghihklmnopqrstuvwxyz")); - + utility::size64_t upsize = 4711u, downsize = 4711u; int calls = 0; http_request msg(mtd); msg.set_progress_handler( - [&](message_direction::direction direction, utility::size64_t so_far) - { + [&](message_direction::direction direction, utility::size64_t so_far) + { calls += 1; - if (direction == message_direction::upload) - upsize = so_far; - else - downsize = so_far; + if (direction == message_direction::upload) + upsize = so_far; + else + downsize = so_far; }); msg.set_body(data); @@ -274,7 +274,7 @@ TEST_FIXTURE(uri_address, set_progress_handler_request_timeout) const size_t repeats = 5500; for (size_t i = 0; i < repeats; ++i) data.append(U("abcdefghihklmnopqrstuvwxyz")); - + utility::size64_t upsize = 4711u, downsize = 4711u; int calls = 0; @@ -282,19 +282,19 @@ TEST_FIXTURE(uri_address, set_progress_handler_request_timeout) // We should never see this handler called for download, but for upload should still happen, since // there's a server (just not a very responsive one) and we're sending data to it. msg.set_progress_handler( - [&](message_direction::direction direction, utility::size64_t so_far) - { + [&](message_direction::direction direction, utility::size64_t so_far) + { calls += 1; - if (direction == message_direction::upload) - upsize = so_far; - else - downsize = so_far; + if (direction == message_direction::upload) + upsize = so_far; + else + downsize = so_far; }); msg.set_body(data); auto t = scoped.server()->next_request(); auto response = client.request(msg); - + #ifdef __APPLE__ // CodePlex 295 VERIFY_THROWS(response.get(), http_exception); diff --git a/Release/tests/functional/misc/version/version.cpp b/Release/tests/functional/misc/version/version.cpp index 68d4fcb44e..dd7cc98bb3 100644 --- a/Release/tests/functional/misc/version/version.cpp +++ b/Release/tests/functional/misc/version/version.cpp @@ -20,12 +20,11 @@ TEST(VersionTest1) { // If these tests fail, this means that version.props and version.h are out of sync // When the version number if changed, both files must change - VERIFY_ARE_EQUAL(_VER_REVISION, CPPREST_VERSION_REVISION); VERIFY_ARE_EQUAL(_VER_MINOR, CPPREST_VERSION_MINOR); VERIFY_ARE_EQUAL(_VER_MAJOR, CPPREST_VERSION_MAJOR); + VERIFY_ARE_EQUAL(_VER_REVISION, CPPREST_VERSION_REVISION); } } }}}} - diff --git a/Release/tests/functional/pplx/pplx_test/pplxtask_tests.cpp b/Release/tests/functional/pplx/pplx_test/pplxtask_tests.cpp index a1f6580edf..7f4f247f1b 100644 --- a/Release/tests/functional/pplx/pplx_test/pplxtask_tests.cpp +++ b/Release/tests/functional/pplx/pplx_test/pplxtask_tests.cpp @@ -203,7 +203,7 @@ TEST(TestTasks_default_construction) t1.wait(); LogFailure(L"t1.wait() should have thrown an exception"); } - catch (invalid_operation) + catch (invalid_operation) { } @@ -212,7 +212,7 @@ TEST(TestTasks_default_construction) t1.get(); LogFailure(L"t1.get() should have thrown an exception"); } - catch (invalid_operation) + catch (invalid_operation) { } @@ -224,7 +224,7 @@ TEST(TestTasks_default_construction) LogFailure(L"t1.then() should have thrown an exception"); } - catch (invalid_operation) + catch (invalid_operation) { } } @@ -268,7 +268,7 @@ TEST(TestTasks_void_tasks_default_construction) t1.wait(); LogFailure(L"t1.wait() should have thrown an exception"); } - catch (invalid_operation) + catch (invalid_operation) { } @@ -277,7 +277,7 @@ TEST(TestTasks_void_tasks_default_construction) t1.get(); LogFailure(L"t1.get() should have thrown an exception"); } - catch (invalid_operation) + catch (invalid_operation) { } @@ -286,7 +286,7 @@ TEST(TestTasks_void_tasks_default_construction) t1.then([] () { }); LogFailure(L"t1.contiue_with() should have thrown an exception"); } - catch (invalid_operation) + catch (invalid_operation) { } } @@ -332,7 +332,7 @@ TEST(TestTasks_constant_this) return 0; }); - auto func = [t1]() -> int + auto func = [t1]() -> int { t1.then([](int last) -> int { return last; @@ -344,7 +344,7 @@ TEST(TestTasks_constant_this) IsTrue(func() == 0, L"Tasks should be able to used inside a Lambda."); } #endif // _MSC_VER < 1700 -#endif // _MSC_VER +#endif // _MSC_VER } TEST(TestTasks_fire_and_forget) @@ -400,7 +400,7 @@ TEST(TestTaskCompletionEvents_basic2) task_completion_event tce; task completion(tce); auto completion2 = create_task(tce); - + task setEvent([=]() { tce.set(); }); @@ -496,7 +496,7 @@ TEST(TestTaskCompletionEvents_multiple_tasks) task t1(tce); task t2(tce); tce.set_exception(1); - + t1.then([=](task p) { try { @@ -639,7 +639,7 @@ TEST(TestTaskOperators_and_or2) IsTrue(vec[2] == 147, L"operator&& did not produce a correct vector[2]. Expected: 147, Actual: %d", vec[2]); IsTrue(vec[3] == 192, L"operator&& did not produce a correct vector[3]. Expected: 192, Actual: %d", vec[3]); int count = 0; - for(unsigned i = 0; i < vec.size(); i++) + for(unsigned i = 0; i < vec.size(); i++) count += vec[i]; return count; }); @@ -674,7 +674,7 @@ TEST(TestTaskOperators_and_or3) IsTrue(vec[2] == 147, L"operator&& did not produce a correct vector[2]. Expected: 147, Actual: %d", vec[2]); IsTrue(vec[3] == 192, L"operator&& did not produce a correct vector[3]. Expected: 192, Actual: %d", vec[3]); int count = 0; - for(unsigned i = 0; i < vec.size(); i++) + for(unsigned i = 0; i < vec.size(); i++) count += vec[i]; return count; }); @@ -862,7 +862,7 @@ TEST(TestTaskOperators_cancellation) auto t4 = (t1 && t2 && t3).then([=](std::vector vec) -> int { return vec[0] + vec[1] + vec[3]; }); - + ct.cancel(); tce.set(); @@ -885,7 +885,7 @@ TEST(TestTaskOperators_cancellation_and) task t3 ([]() -> void {}); auto t4 = (t1 && t2 && t3).then([=]() {}); - + ct.cancel(); tce.set(); @@ -918,7 +918,7 @@ TEST(TestTaskOperators_cancellation_or) auto t4 = (t1 || t2 || t3).then([=](int result) -> int { return result; }); - + ct1.cancel(); ct2.cancel(); ct3.cancel(); @@ -945,7 +945,7 @@ TEST(TestTaskOperators_cancellation_or2) task t3 = starter.then([]() -> void {}, ct3.get_token()); auto t4 = (t1 || t2 || t3).then([=]() {}); - + ct1.cancel(); ct2.cancel(); ct3.cancel(); @@ -1087,7 +1087,7 @@ TEST(TestTaskOperators_cancellation_exception) } task t3 = t1.then([&n](){ - pplx::details::atomic_add(n, 1L); // this should NOT execute, + pplx::details::atomic_add(n, 1L); // this should NOT execute, }); task t4 = t1.then([&n](task taskResult){ @@ -1381,249 +1381,247 @@ static int ThrowFunc() throw 42; } -TEST(TestContinuationsWithTask) +TEST(TestContinuationsWithTask1) { - { - int n2 = 0; + int n2 = 0; - task t([&]() -> int { - return 10; - }); + task t([&]() -> int { + return 10; + }); - t.then([&] (task ti) { - n2 = ti.get(); - }).wait(); + t.then([&] (task ti) { + n2 = ti.get(); + }).wait(); - VERIFY_IS_TRUE(n2 == 10); - } + VERIFY_IS_TRUE(n2 == 10); +} - { - int n = 0; +TEST(TestContinuationsWithTask2) +{ + int n = 0; - task tt1([](){}); - auto tt2 = tt1.then([&]()-> task { - task tt3([&](){ - n = 1; - }); - return tt3; + task tt1([](){}); + auto tt2 = tt1.then([&]()-> task { + task tt3([&](){ + n = 1; }); + return tt3; + }); - tt2.get(); - VERIFY_IS_TRUE(n == 1); + tt2.get(); + VERIFY_IS_TRUE(n == 1); - task tt4 = tt2.then([&]()-> task { - task tt5([&](){ - n = 2; - }); - return tt5; + task tt4 = tt2.then([&]()-> task { + task tt5([&](){ + n = 2; }); - tt4.get(); - VERIFY_IS_TRUE(n == 2); - } + return tt5; + }); + tt4.get(); + VERIFY_IS_TRUE(n == 2); +} - { - bool gotException = true; - int n2 = 0; - task t(ThrowFunc); - t.then([&] (task ti) { - try - { - ti.get(); - gotException = false; - } - catch (int) - { - n2 = 20; - } - }).wait(); +TEST(TestContinuationsWithTask3) +{ + bool gotException = true; + int n2 = 0; + task t(ThrowFunc); + t.then([&] (task ti) { + try + { + ti.get(); + gotException = false; + } + catch (int) + { + n2 = 20; + } + }).wait(); - VERIFY_IS_TRUE(gotException); - VERIFY_IS_TRUE(n2 == 20); - } + VERIFY_IS_TRUE(gotException); + VERIFY_IS_TRUE(n2 == 20); +} - { - int n2 = 0; +TEST(TestContinuationsWithTask4) +{ + int n2 = 0; - task t([&]() -> int { - return 10; + task t([&]() -> int { + return 10; + }); + + t.then([&] (int n) -> task { + task t2([n]() -> int { + return n+10; }); + return t2; + }).then([&](int n) { + n2 = n; + }).wait(); - t.then([&] (int n) -> task { - task t2([n]() -> int { - return n+10; - }); - return t2; - }).then([&](int n) { - n2 = n; - }).wait(); + VERIFY_IS_TRUE(n2 == 20); +} - VERIFY_IS_TRUE(n2 == 20); - } +TEST(TestContinuationsWithTask5) +{ + int n2 = 0; - { - int n2 = 0; + task t([&]() -> int { + return 10; + }); - task t([&]() -> int { - return 10; + t.then([&] (task tn) -> task { + int n = tn.get(); + task t2([n]() -> int { + return n+10; }); + return t2; + }).then([&](task n) { + n2 = n.get(); + }).wait(); - t.then([&] (task tn) -> task { - int n = tn.get(); - task t2([n]() -> int { - return n+10; - }); - return t2; - }).then([&](task n) { - n2 = n.get(); - }).wait(); - - VERIFY_IS_TRUE(n2 == 20); - } - - { - pplx::details::atomic_long hit(0); - auto * hitptr = &hit; - task t([](){ - return 10; - }); + VERIFY_IS_TRUE(n2 == 20); +} - auto ot = t.then([hitptr](int n) -> task { - auto hitptr1 = hitptr; - task it([n, hitptr1]() -> int { - os_utilities::sleep(100); - pplx::details::atomic_exchange(*hitptr1, 1L); - return n * 2; - }); +TEST(TestContinuationsWithTask6) +{ + pplx::details::atomic_long hit(0); + auto * hitptr = &hit; + task t([](){ + return 10; + }); - return it; + auto ot = t.then([hitptr](int n) -> task { + auto hitptr1 = hitptr; + task it([n, hitptr1]() -> int { + os_utilities::sleep(100); + pplx::details::atomic_exchange(*hitptr1, 1L); + return n * 2; }); - int value = ot.get(); - VERIFY_IS_TRUE(value == 20 && hit != 0); - } - - { - volatile long hit = 0; - volatile long * hitptr = &hit; + return it; + }); - task t([](){ - return 10; - }); + int value = ot.get(); + VERIFY_IS_TRUE(value == 20 && hit != 0); +} - auto ot = t.then( [hitptr](int n) -> task { - volatile long * hitptr1 = hitptr; - task it([n, hitptr1]() -> int { - os_utilities::sleep(100); - os_utilities::interlocked_exchange(hitptr1, 1); - return n * 3; - }); +TEST(TestContinuationsWithTask7) +{ + volatile long hit = 0; + volatile long * hitptr = &hit; - // This test is needed to disable an optimizer dead-code check that - // winds up generating errors in VS 2010. - if ( n == 10 ) - throw TestException1(); + task t([](){ + return 10; + }); - return it; + auto ot = t.then( [hitptr](int n) -> task { + task it([n, hitptr]() -> int { + throw TestException1(); }); - VERIFY_IS_TRUE(helpers::VerifyException(ot)); - } + return it; + }); - { - volatile long hit = 0; - volatile long * hitptr = &hit; + VERIFY_IS_TRUE(helpers::VerifyException(ot)); +} - task t([](){ - return 10; - }); +TEST(TestContinuationsWithTask8) +{ + volatile long hit = 0; + volatile long * hitptr = &hit; - auto ot = t.then( [hitptr](int n) -> task { - volatile long * hitptr1 = hitptr; - task it([n, hitptr1]() -> int { - os_utilities::sleep(100); - os_utilities::interlocked_exchange(hitptr1, 1); + task t([](){ + return 10; + }); - // This test is needed to disable an optimizer dead-code check that - // winds up generating errors in VS 2010. - if ( n == 10 ) - throw TestException2(); + auto ot = t.then( [hitptr](int n) -> task { + volatile long * hitptr1 = hitptr; + task it([n, hitptr1]() -> int { + os_utilities::sleep(100); + os_utilities::interlocked_exchange(hitptr1, 1); - return n * 3; - }); + // This test is needed to disable an optimizer dead-code check that + // winds up generating errors in VS 2010. + if ( n == 10 ) + throw TestException2(); - return it; + return n * 3; }); - VERIFY_IS_TRUE(helpers::VerifyException(ot), "(7) Inner task exception not propagated out of outer .get()"); - VERIFY_IS_TRUE(hit != 0, "(7) Expected inner task hit marker to be set!"); - } + return it; + }); - { - volatile long hit = 0; - volatile long * hitptr = &hit; - extensibility::event_t e; - task it; + VERIFY_IS_TRUE(helpers::VerifyException(ot), "(7) Inner task exception not propagated out of outer .get()"); + VERIFY_IS_TRUE(hit != 0, "(7) Expected inner task hit marker to be set!"); +} - task t([](){ - return 10; - }); +TEST(TestContinuationsWithTask9) +{ + volatile long hit = 0; + volatile long * hitptr = &hit; + extensibility::event_t e; + task it; - auto ot = t.then( [hitptr, &it, &e](int n) -> task { - volatile long * hitptr1 = hitptr; - it = task([hitptr1, n]() -> int { - os_utilities::interlocked_exchange(hitptr1, 1); - // This test is needed to disable an optimizer dead-code check that - // winds up generating errors in VS 2010. - if ( n == 10 ) - throw TestException1(); - return n * 5; - }); + task t([](){ + return 10; + }); - e.set(); - os_utilities::sleep(100); + auto ot = t.then( [hitptr, &it, &e](int n) -> task { + volatile long * hitptr1 = hitptr; + it = task([hitptr1, n]() -> int { + os_utilities::interlocked_exchange(hitptr1, 1); // This test is needed to disable an optimizer dead-code check that // winds up generating errors in VS 2010. if ( n == 10 ) - throw TestException2(); - return it; + throw TestException1(); + return n * 5; }); - e.wait(); + e.set(); + os_utilities::sleep(100); + // This test is needed to disable an optimizer dead-code check that + // winds up generating errors in VS 2010. + if ( n == 10 ) + throw TestException2(); + return it; + }); - VERIFY_IS_TRUE(helpers::VerifyException(ot), "(8) Outer task exception not propagated when inner task also throws"); - VERIFY_IS_TRUE(helpers::VerifyException(it), "(8) Inner task exception not explicitly propgated on pass out / get"); - VERIFY_IS_TRUE(hit != 0, "(8) Inner hit marker expected!"); - } + e.wait(); - { - volatile long hit = 0; + VERIFY_IS_TRUE(helpers::VerifyException(ot), "(8) Outer task exception not propagated when inner task also throws"); + VERIFY_IS_TRUE(helpers::VerifyException(it), "(8) Inner task exception not explicitly propgated on pass out / get"); + VERIFY_IS_TRUE(hit != 0, "(8) Inner hit marker expected!"); +} - task t([](){ - return 10; - }); +TEST(TestContinuationsWithTask10) +{ + volatile long hit = 0; - auto ot = t.then( [&](int n) -> task { - task it([&, n]() -> int { - os_utilities::sleep(100); - // This test is needed to disable an optimizer dead-code check that - // winds up generating errors in VS 2010. - if ( n == 10 ) - throw TestException1(); - return n * 6; - }); - return it; - }); + task t([](){ + return 10; + }); - auto otc = ot.then( [&](task itp){ - os_utilities::interlocked_exchange(&hit, 1); - VERIFY_IS_TRUE(helpers::VerifyException(itp), "(9) Outer task exception handling continuation did not get plumbed inner exception"); + auto ot = t.then( [&](int n) -> task { + task it([&, n]() -> int { + os_utilities::sleep(100); + // This test is needed to disable an optimizer dead-code check that + // winds up generating errors in VS 2010. + if ( n == 10 ) + throw TestException1(); + return n * 6; }); + return it; + }); - VERIFY_IS_TRUE(helpers::VerifyException(ot), "(9) Inner task exception not propagated correctly"); - helpers::ObserveException(otc); - VERIFY_IS_TRUE(hit != 0, "(9) Outer task exception handling continuation did not run!"); - } + auto otc = ot.then( [&](task itp){ + os_utilities::interlocked_exchange(&hit, 1); + VERIFY_IS_TRUE(helpers::VerifyException(itp), "(9) Outer task exception handling continuation did not get plumbed inner exception"); + }); + VERIFY_IS_TRUE(helpers::VerifyException(ot), "(9) Inner task exception not propagated correctly"); + helpers::ObserveException(otc); + VERIFY_IS_TRUE(hit != 0, "(9) Outer task exception handling continuation did not run!"); } TEST(TestUnwrappingCtors) @@ -1734,7 +1732,7 @@ TEST(TestUnwrappingCtors) }); }).get(); VERIFY_IS_TRUE(res==1, "unexpected value in TestUnwrappingCtors, create_task, location 1"); - + create_task([]() -> task { return create_task([]() { }); @@ -1748,10 +1746,10 @@ TEST(TestUnwrappingCtors) // Create a task that is always cancelled auto falseTask = create_task([]() {}, cts.get_token()); cancellation_token ct2 = cts2.get_token(); - create_task([falseTask]() { + create_task([falseTask]() { // Task unwrapping! // This should not crash - return falseTask; + return falseTask; }, ct2).then([this, falseTask, ct2](task t) -> task { VERIFY_IS_TRUE(t.wait() == canceled, "unexpected value in TestUnwrappingCtors, cancellation token, location 1"); VERIFY_IS_TRUE(!ct2.is_canceled(), "unexpected value in TestUnwrappingCtors, cancellation token, location 2"); @@ -1776,7 +1774,7 @@ TEST(TestNestedTasks) return task([=]() -> int { return val1 + 22; }); - }); + }); }); int n = resultTask.get().get(); @@ -1789,17 +1787,17 @@ TEST(TestNestedTasks) int * flagptr = &flag; task rootTask([&]() { flag++; }); - task> resultTask = rootTask.then([flagptr]() -> task> + task> resultTask = rootTask.then([flagptr]() -> task> { auto flag1 = flagptr; - return task>([flag1]() -> task + return task>([flag1]() -> task { auto flag2 = flag1; - return task([flag2]() + return task([flag2]() { ++(flag2[0]); }); - }); + }); }); resultTask.get().wait(); @@ -1809,7 +1807,7 @@ TEST(TestNestedTasks) { task rootTask([]() -> int { return 234; }); - task>> + task>> resultTask = rootTask.then([](int value) -> task>> { return task>>([=]() -> task> { auto v1 = value; @@ -1818,7 +1816,7 @@ TEST(TestNestedTasks) return task([=]() -> int { return v2 + 22; }); - }); + }); }); }); diff --git a/Release/tests/functional/utils/strings.cpp b/Release/tests/functional/utils/strings.cpp index 80b7758083..19d1b43cfd 100644 --- a/Release/tests/functional/utils/strings.cpp +++ b/Release/tests/functional/utils/strings.cpp @@ -205,6 +205,31 @@ TEST(utf8_to_utf16) #else VERIFY_ARE_EQUAL(conversion.from_bytes(input), result); #endif + + + // 1 byte character followed by 4 byte character + input.clear(); + input.push_back( 51u); // 00110011 + // U+10000 + input.push_back(244u); // 11110100 + input.push_back(128u); // 10000000 + input.push_back(128u); // 10000000 + input.push_back(128u); // 10000000 + // U+10FFFF + input.push_back(244u); // 11110100 + input.push_back(143u); // 10001111 + input.push_back(191u); // 10111111 + input.push_back(191u); // 10111111 + result = utility::conversions::utf8_to_utf16(input); +#if defined(__GLIBCXX__) + VERIFY_ARE_EQUAL(51, result[0]); + VERIFY_ARE_EQUAL(56256, result[1]); + VERIFY_ARE_EQUAL(56320, result[2]); + VERIFY_ARE_EQUAL(56319, result[3]); + VERIFY_ARE_EQUAL(57343, result[4]); +#else + VERIFY_ARE_EQUAL(conversion.from_bytes(input), result); +#endif } TEST(utf16_to_utf8_errors) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index a5d63c55df..993b92accf 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -205,6 +205,16 @@ jobs: cd build.release/Release/Binaries ./test_runner *test.so displayName: 'Run tests, release' + - job: Android + pool: + vmImage: 'Ubuntu 16.04' + steps: + - script: | + mkdir Build_android/build + cd Build_android/build + export NCPU=2 + ../configure.sh --ndk /usr/local/lib/android/sdk/ndk-bundle + displayName: 'Build for Android' - job: MacOS_Homebrew pool: vmImage: 'macOS-10.13' @@ -285,3 +295,11 @@ jobs: cd build.release/Release/Binaries ./test_runner *test.dylib displayName: 'Run tests, release' + - job: MacOS_iOS + pool: + vmImage: 'macOS-10.13' + steps: + - script: | + cd Build_iOS + ./configure.sh + displayName: 'Build for iOS' \ No newline at end of file diff --git a/changelog.md b/changelog.md index dd190b70a9..188c0cd822 100644 --- a/changelog.md +++ b/changelog.md @@ -1,3 +1,23 @@ +cpprestsdk (2.10.7) +---------------------- +* cpprestsdk now has Azure Pipelines continuous integration. +* Builds for Android and iOS were repaired, now checked in Azure Pipelines to make sure that doesn't bit-rot in the future. +* Several race conditions in the listener were worked around; the listeners remain experimental and are unlikely to productized in their current form; the race conditions are structural, but at least the client tests pass most of the time. +* Incorrect handling of connection pooling bug that caused segfaults on Ubuntu introduced in 2.10.4 has been repaired. +* websocketpp checked in 0.5.1 version has been changed to a submodule and updated to 0.8.1. +* Added an API to set the number of threads in the asio thread pool, see PR#883 +* Legacy unmaintained Visual Studio project files have been deleted, please use CMake instead. +* PR#670 Export methods to set/get the ambient scheduler in cpprest dll +* PR#866 Add Transfer-Encoding compression support and extensible compression API +* PR#892 Improve utf8_to_utf16 speed for common path +* PR#897 added URI resolution according to RFC3986 +* PR#935 Fix spelling mistakes across the library +* PR#936 Use pplx namespace consistently +* PR#937 Remove _ASYNCRTIMP from ~http_listener() and implement inline +* PR#940 Avoid using identifiers reserved by C++ in header guards +* PR#943 blackjack sample: use vector instead of shared pointer for array +-- cpprestsdk team MON, 30 Oct 2018 20:32:00 -0800 + cpprestsdk (2.10.6) ---------------------- * PR#844 Fix clang build error