diff --git a/.travis.yml b/.travis.yml index 5c2d163e5..7e6154d4a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,61 +1,139 @@ -sudo: false +# cpp-netlib Project Travis CI configuration. + language: cpp -compiler: -- g++ -- clang +os: linux +dist: trusty +sudo: false + +cache: + - apt + - ccache + env: -- BOOST_VER=1.59.0 BUILD_SHARED_LIBS="ON" CMAKE_BUILD_TYPE="Release" ENABLE_HTTPS="ON" Uri_BUILD_TESTS=OFF Uri_DISABLE_LIBCXX=YES -- BOOST_VER=1.59.0 BUILD_SHARED_LIBS="ON" CMAKE_BUILD_TYPE="Release" ENABLE_HTTPS="OFF" Uri_BUILD_TESTS=OFF Uri_DISABLE_LIBCXX=YES -- BOOST_VER=1.59.0 BUILD_SHARED_LIBS="ON" CMAKE_BUILD_TYPE="Debug" ENABLE_HTTPS="ON" Uri_BUILD_TESTS=OFF Uri_DISABLE_LIBCXX=YES -- BOOST_VER=1.59.0 BUILD_SHARED_LIBS="ON" CMAKE_BUILD_TYPE="Debug" ENABLE_HTTPS="OFF" Uri_BUILD_TESTS=OFF Uri_DISABLE_LIBCXX=YES -- BOOST_VER=1.59.0 BUILD_SHARED_LIBS="OFF" CMAKE_BUILD_TYPE="Release" ENABLE_HTTPS="ON" Uri_BUILD_TESTS=OFF Uri_DISABLE_LIBCXX=YES -- BOOST_VER=1.59.0 BUILD_SHARED_LIBS="OFF" CMAKE_BUILD_TYPE="Release" ENABLE_HTTPS="OFF" Uri_BUILD_TESTS=OFF Uri_DISABLE_LIBCXX=YES -- BOOST_VER=1.59.0 BUILD_SHARED_LIBS="OFF" CMAKE_BUILD_TYPE="Debug" ENABLE_HTTPS="ON" Uri_BUILD_TESTS=OFF Uri_DISABLE_LIBCXX=YES -- BOOST_VER=1.59.0 BUILD_SHARED_LIBS="OFF" CMAKE_BUILD_TYPE="Debug" ENABLE_HTTPS="OFF" Uri_BUILD_TESTS=OFF Uri_DISABLE_LIBCXX=YES -# Support the sanitizers in clang only -# - BOOST_VER=1.59.0 BUILD_SHARED_LIBS="OFF" CMAKE_BUILD_TYPE="Debug" ENABLE_HTTPS="ON" CMAKE_CXX_FLAGS="-fsanitize=thread" -# - BOOST_VER=1.59.0 BUILD_SHARED_LIBS="OFF" CMAKE_BUILD_TYPE="Debug" ENABLE_HTTPS="ON" CMAKE_CXX_FLAGS="-fsanitize=address" -# TODO(deanberris): It seems Boost is not msan-clean yet; report bugs and maybe fix? -#- BOOST_VER=1.59.0 BUILD_SHARED_LIBS="OFF" CMAKE_BUILD_TYPE="Debug" ENABLE_HTTPS="ON" CMAKE_CXX_FLAGS="-fsanitize=memory -fsanitize-memory-track-origins=2" -# matrix: -# exclude: -# - compiler: g++ -# env: BOOST_VER=1.59.0 BUILD_SHARED_LIBS="OFF" CMAKE_BUILD_TYPE="Debug" ENABLE_HTTPS="ON" CMAKE_CXX_FLAGS="-fsanitize=thread" -# - compiler: g++ -# env: BOOST_VER=1.59.0 BUILD_SHARED_LIBS="OFF" CMAKE_BUILD_TYPE="Debug" ENABLE_HTTPS="ON" CMAKE_CXX_FLAGS="-fsanitize=address" -# TODO(deanberris): It seems Boost is not msan-clean yet; report bugs and maybe fix? -# - compiler: g++ -# env: BOOST_VER=1.59.0 BUILD_SHARED_LIBS="OFF" CMAKE_BUILD_TYPE="Debug" ENABLE_HTTPS="ON" CMAKE_CXX_FLAGS="-fsanitize=memory -fsanitize-memory-track-origins=2" + global: + - CCACHE_CPP2=yes + +matrix: + include: + # GCC 4.9 configurations + - env: BUILD_SHARED_LIBS="ON" CMAKE_BUILD_TYPE="Release" ENABLE_HTTPS="ON" Uri_BUILD_TESTS=OFF Uri_DISABLE_LIBCXX=YES NEWCC=gcc-4.9 NEWCXX=g++-4.9 + addons: { apt: { sources: ["ubuntu-toolchain-r-test"], packages: ["g++-4.9", "libboost1.55-all-dev"] } } + - env: BUILD_SHARED_LIBS="ON" CMAKE_BUILD_TYPE="Release" ENABLE_HTTPS="OFF" Uri_BUILD_TESTS=OFF Uri_DISABLE_LIBCXX=YES NEWCC=gcc-4.9 NEWCXX=g++-4.9 + addons: { apt: { sources: ["ubuntu-toolchain-r-test"], packages: ["g++-4.9", "libboost1.55-all-dev"] } } + - env: BUILD_SHARED_LIBS="ON" CMAKE_BUILD_TYPE="Debug" ENABLE_HTTPS="ON" Uri_BUILD_TESTS=OFF Uri_DISABLE_LIBCXX=YES NEWCC=gcc-4.9 NEWCXX=g++-4.9 + addons: { apt: { sources: ["ubuntu-toolchain-r-test"], packages: ["g++-4.9", "libboost1.55-all-dev"] } } + - env: BUILD_SHARED_LIBS="ON" CMAKE_BUILD_TYPE="Debug" ENABLE_HTTPS="OFF" Uri_BUILD_TESTS=OFF Uri_DISABLE_LIBCXX=YES NEWCC=gcc-4.9 NEWCXX=g++-4.9 + addons: { apt: { sources: ["ubuntu-toolchain-r-test"], packages: ["g++-4.9", "libboost1.55-all-dev"] } } + - env: BUILD_SHARED_LIBS="OFF" CMAKE_BUILD_TYPE="Release" ENABLE_HTTPS="ON" Uri_BUILD_TESTS=OFF Uri_DISABLE_LIBCXX=YES NEWCC=gcc-4.9 NEWCXX=g++-4.9 + addons: { apt: { sources: ["ubuntu-toolchain-r-test"], packages: ["g++-4.9", "libboost1.55-all-dev"] } } + - env: BUILD_SHARED_LIBS="OFF" CMAKE_BUILD_TYPE="Release" ENABLE_HTTPS="OFF" Uri_BUILD_TESTS=OFF Uri_DISABLE_LIBCXX=YES NEWCC=gcc-4.9 NEWCXX=g++-4.9 + addons: { apt: { sources: ["ubuntu-toolchain-r-test"], packages: ["g++-4.9", "libboost1.55-all-dev"] } } + - env: BUILD_SHARED_LIBS="OFF" CMAKE_BUILD_TYPE="Debug" ENABLE_HTTPS="ON" Uri_BUILD_TESTS=OFF Uri_DISABLE_LIBCXX=YES NEWCC=gcc-4.9 NEWCXX=g++-4.9 + addons: { apt: { sources: ["ubuntu-toolchain-r-test"], packages: ["g++-4.9", "libboost1.55-all-dev"] } } + - env: BUILD_SHARED_LIBS="OFF" CMAKE_BUILD_TYPE="Debug" ENABLE_HTTPS="OFF" Uri_BUILD_TESTS=OFF Uri_DISABLE_LIBCXX=YES NEWCC=gcc-4.9 NEWCXX=g++-4.9 + addons: { apt: { sources: ["ubuntu-toolchain-r-test"], packages: ["g++-4.9", "libboost1.55-all-dev"] } } + # GCC 5.0 configurations + - env: BUILD_SHARED_LIBS="ON" CMAKE_BUILD_TYPE="Release" ENABLE_HTTPS="ON" Uri_BUILD_TESTS=OFF Uri_DISABLE_LIBCXX=YES NEWCC=gcc-5 NEWCXX=g++-5 + addons: { apt: { sources: ["ubuntu-toolchain-r-test"], packages: ["g++-5", "libboost1.55-all-dev"] } } + - env: BUILD_SHARED_LIBS="ON" CMAKE_BUILD_TYPE="Release" ENABLE_HTTPS="OFF" Uri_BUILD_TESTS=OFF Uri_DISABLE_LIBCXX=YES NEWCC=gcc-5 NEWCXX=g++-5 + addons: { apt: { sources: ["ubuntu-toolchain-r-test"], packages: ["g++-5", "libboost1.55-all-dev"] } } + - env: BUILD_SHARED_LIBS="ON" CMAKE_BUILD_TYPE="Debug" ENABLE_HTTPS="ON" Uri_BUILD_TESTS=OFF Uri_DISABLE_LIBCXX=YES NEWCC=gcc-5 NEWCXX=g++-5 + addons: { apt: { sources: ["ubuntu-toolchain-r-test"], packages: ["g++-5", "libboost1.55-all-dev"] } } + - env: BUILD_SHARED_LIBS="ON" CMAKE_BUILD_TYPE="Debug" ENABLE_HTTPS="OFF" Uri_BUILD_TESTS=OFF Uri_DISABLE_LIBCXX=YES NEWCC=gcc-5 NEWCXX=g++-5 + addons: { apt: { sources: ["ubuntu-toolchain-r-test"], packages: ["g++-5", "libboost1.55-all-dev"] } } + - env: BUILD_SHARED_LIBS="OFF" CMAKE_BUILD_TYPE="Release" ENABLE_HTTPS="ON" Uri_BUILD_TESTS=OFF Uri_DISABLE_LIBCXX=YES NEWCC=gcc-5 NEWCXX=g++-5 + addons: { apt: { sources: ["ubuntu-toolchain-r-test"], packages: ["g++-5", "libboost1.55-all-dev"] } } + - env: BUILD_SHARED_LIBS="OFF" CMAKE_BUILD_TYPE="Release" ENABLE_HTTPS="OFF" Uri_BUILD_TESTS=OFF Uri_DISABLE_LIBCXX=YES NEWCC=gcc-5 NEWCXX=g++-5 + addons: { apt: { sources: ["ubuntu-toolchain-r-test"], packages: ["g++-5", "libboost1.55-all-dev"] } } + - env: BUILD_SHARED_LIBS="OFF" CMAKE_BUILD_TYPE="Debug" ENABLE_HTTPS="ON" Uri_BUILD_TESTS=OFF Uri_DISABLE_LIBCXX=YES NEWCC=gcc-5 NEWCXX=g++-5 + addons: { apt: { sources: ["ubuntu-toolchain-r-test"], packages: ["g++-5", "libboost1.55-all-dev"] } } + - env: BUILD_SHARED_LIBS="OFF" CMAKE_BUILD_TYPE="Debug" ENABLE_HTTPS="OFF" Uri_BUILD_TESTS=OFF Uri_DISABLE_LIBCXX=YES NEWCC=gcc-5 NEWCXX=g++-5 + addons: { apt: { sources: ["ubuntu-toolchain-r-test"], packages: ["g++-5", "libboost1.55-all-dev"] } } + # Clang 3.8 configurations + - env: BUILD_SHARED_LIBS="ON" CMAKE_BUILD_TYPE="Release" ENABLE_HTTPS="ON" Uri_BUILD_TESTS=OFF Uri_DISABLE_LIBCXX=YES NEWCC=clang-3.8 NEWCXX=clang++-3.8 + addons: { apt: { sources: ["ubuntu-toolchain-r-test", "llvm-toolchain-precise-3.8"], packages: ["clang-3.8", "libboost1.55-all-dev"] } } + - env: BUILD_SHARED_LIBS="ON" CMAKE_BUILD_TYPE="Release" ENABLE_HTTPS="OFF" Uri_BUILD_TESTS=OFF Uri_DISABLE_LIBCXX=YES NEWCC=clang-3.8 NEWCXX=clang++-3.8 + addons: { apt: { sources: ["ubuntu-toolchain-r-test", "llvm-toolchain-precise-3.8"], packages: ["clang-3.8", "libboost1.55-all-dev"] } } + - env: BUILD_SHARED_LIBS="ON" CMAKE_BUILD_TYPE="Debug" ENABLE_HTTPS="ON" Uri_BUILD_TESTS=OFF Uri_DISABLE_LIBCXX=YES NEWCC=clang-3.8 NEWCXX=clang++-3.8 + addons: { apt: { sources: ["ubuntu-toolchain-r-test", "llvm-toolchain-precise-3.8"], packages: ["clang-3.8", "libboost1.55-all-dev"] } } + - env: BUILD_SHARED_LIBS="ON" CMAKE_BUILD_TYPE="Debug" ENABLE_HTTPS="OFF" Uri_BUILD_TESTS=OFF Uri_DISABLE_LIBCXX=YES NEWCC=clang-3.8 NEWCXX=clang++-3.8 + addons: { apt: { sources: ["ubuntu-toolchain-r-test", "llvm-toolchain-precise-3.8"], packages: ["clang-3.8", "libboost1.55-all-dev"] } } + - env: BUILD_SHARED_LIBS="OFF" CMAKE_BUILD_TYPE="Release" ENABLE_HTTPS="ON" Uri_BUILD_TESTS=OFF Uri_DISABLE_LIBCXX=YES NEWCC=clang-3.8 NEWCXX=clang++-3.8 + addons: { apt: { sources: ["ubuntu-toolchain-r-test", "llvm-toolchain-precise-3.8"], packages: ["clang-3.8", "libboost1.55-all-dev"] } } + - env: BUILD_SHARED_LIBS="OFF" CMAKE_BUILD_TYPE="Release" ENABLE_HTTPS="OFF" Uri_BUILD_TESTS=OFF Uri_DISABLE_LIBCXX=YES NEWCC=clang-3.8 NEWCXX=clang++-3.8 + addons: { apt: { sources: ["ubuntu-toolchain-r-test", "llvm-toolchain-precise-3.8"], packages: ["clang-3.8", "libboost1.55-all-dev"] } } + - env: BUILD_SHARED_LIBS="OFF" CMAKE_BUILD_TYPE="Debug" ENABLE_HTTPS="ON" Uri_BUILD_TESTS=OFF Uri_DISABLE_LIBCXX=YES NEWCC=clang-3.8 NEWCXX=clang++-3.8 + addons: { apt: { sources: ["ubuntu-toolchain-r-test", "llvm-toolchain-precise-3.8"], packages: ["clang-3.8", "libboost1.55-all-dev"] } } + - env: BUILD_SHARED_LIBS="OFF" CMAKE_BUILD_TYPE="Debug" ENABLE_HTTPS="OFF" Uri_BUILD_TESTS=OFF Uri_DISABLE_LIBCXX=YES NEWCC=clang-3.8 NEWCXX=clang++-3.8 + addons: { apt: { sources: ["ubuntu-toolchain-r-test", "llvm-toolchain-precise-3.8"], packages: ["clang-3.8", "libboost1.55-all-dev"] } } + # Clang 3.9 configurations + - env: BUILD_SHARED_LIBS="ON" CMAKE_BUILD_TYPE="Release" ENABLE_HTTPS="ON" Uri_BUILD_TESTS=OFF Uri_DISABLE_LIBCXX=YES NEWCC=clang-3.9 NEWCXX=clang++-3.9 + addons: { apt: { sources: ["llvm-toolchain-trusty-3.9"], packages: ["clang-3.9", "libboost1.55-all-dev"] } } + - env: BUILD_SHARED_LIBS="ON" CMAKE_BUILD_TYPE="Release" ENABLE_HTTPS="OFF" Uri_BUILD_TESTS=OFF Uri_DISABLE_LIBCXX=YES NEWCC=clang-3.9 NEWCXX=clang++-3.9 + addons: { apt: { sources: ["llvm-toolchain-trusty-3.9"], packages: ["clang-3.9", "libboost1.55-all-dev"] } } + - env: BUILD_SHARED_LIBS="ON" CMAKE_BUILD_TYPE="Debug" ENABLE_HTTPS="ON" Uri_BUILD_TESTS=OFF Uri_DISABLE_LIBCXX=YES NEWCC=clang-3.9 NEWCXX=clang++-3.9 + addons: { apt: { sources: ["llvm-toolchain-trusty-3.9"], packages: ["clang-3.9", "libboost1.55-all-dev"] } } + - env: BUILD_SHARED_LIBS="ON" CMAKE_BUILD_TYPE="Debug" ENABLE_HTTPS="OFF" Uri_BUILD_TESTS=OFF Uri_DISABLE_LIBCXX=YES NEWCC=clang-3.9 NEWCXX=clang++-3.9 + addons: { apt: { sources: ["llvm-toolchain-trusty-3.9"], packages: ["clang-3.9", "libboost1.55-all-dev"] } } + - env: BUILD_SHARED_LIBS="OFF" CMAKE_BUILD_TYPE="Release" ENABLE_HTTPS="ON" Uri_BUILD_TESTS=OFF Uri_DISABLE_LIBCXX=YES NEWCC=clang-3.9 NEWCXX=clang++-3.9 + addons: { apt: { sources: ["llvm-toolchain-trusty-3.9"], packages: ["clang-3.9", "libboost1.55-all-dev"] } } + - env: BUILD_SHARED_LIBS="OFF" CMAKE_BUILD_TYPE="Release" ENABLE_HTTPS="OFF" Uri_BUILD_TESTS=OFF Uri_DISABLE_LIBCXX=YES NEWCC=clang-3.9 NEWCXX=clang++-3.9 + addons: { apt: { sources: ["llvm-toolchain-trusty-3.9"], packages: ["clang-3.9", "libboost1.55-all-dev"] } } + - env: BUILD_SHARED_LIBS="OFF" CMAKE_BUILD_TYPE="Debug" ENABLE_HTTPS="ON" Uri_BUILD_TESTS=OFF Uri_DISABLE_LIBCXX=YES NEWCC=clang-3.9 NEWCXX=clang++-3.9 + addons: { apt: { sources: ["llvm-toolchain-trusty-3.9"], packages: ["clang-3.9", "libboost1.55-all-dev"] } } + - env: BUILD_SHARED_LIBS="OFF" CMAKE_BUILD_TYPE="Debug" ENABLE_HTTPS="OFF" Uri_BUILD_TESTS=OFF Uri_DISABLE_LIBCXX=YES NEWCC=clang-3.9 NEWCXX=clang++-3.9 + addons: { apt: { sources: ["llvm-toolchain-trusty-3.9"], packages: ["clang-3.9", "libboost1.55-all-dev"] } } + # Clang 4.0 configurations + - env: BUILD_SHARED_LIBS="ON" CMAKE_BUILD_TYPE="Release" ENABLE_HTTPS="ON" Uri_BUILD_TESTS=OFF Uri_DISABLE_LIBCXX=YES NEWCC=clang-4.0 NEWCXX=clang++-4.0 + addons: { apt: { sources: ["llvm-toolchain-trusty-4.0"], packages: ["clang-4.0", "libboost1.55-all-dev"] } } + - env: BUILD_SHARED_LIBS="ON" CMAKE_BUILD_TYPE="Release" ENABLE_HTTPS="OFF" Uri_BUILD_TESTS=OFF Uri_DISABLE_LIBCXX=YES NEWCC=clang-4.0 NEWCXX=clang++-4.0 + addons: { apt: { sources: ["llvm-toolchain-trusty-4.0"], packages: ["clang-4.0", "libboost1.55-all-dev"] } } + - env: BUILD_SHARED_LIBS="ON" CMAKE_BUILD_TYPE="Debug" ENABLE_HTTPS="ON" Uri_BUILD_TESTS=OFF Uri_DISABLE_LIBCXX=YES NEWCC=clang-4.0 NEWCXX=clang++-4.0 + addons: { apt: { sources: ["llvm-toolchain-trusty-4.0"], packages: ["clang-4.0", "libboost1.55-all-dev"] } } + - env: BUILD_SHARED_LIBS="ON" CMAKE_BUILD_TYPE="Debug" ENABLE_HTTPS="OFF" Uri_BUILD_TESTS=OFF Uri_DISABLE_LIBCXX=YES NEWCC=clang-4.0 NEWCXX=clang++-4.0 + addons: { apt: { sources: ["llvm-toolchain-trusty-4.0"], packages: ["clang-4.0", "libboost1.55-all-dev"] } } + - env: BUILD_SHARED_LIBS="OFF" CMAKE_BUILD_TYPE="Release" ENABLE_HTTPS="ON" Uri_BUILD_TESTS=OFF Uri_DISABLE_LIBCXX=YES NEWCC=clang-4.0 NEWCXX=clang++-4.0 + addons: { apt: { sources: ["llvm-toolchain-trusty-4.0"], packages: ["clang-4.0", "libboost1.55-all-dev"] } } + - env: BUILD_SHARED_LIBS="OFF" CMAKE_BUILD_TYPE="Release" ENABLE_HTTPS="OFF" Uri_BUILD_TESTS=OFF Uri_DISABLE_LIBCXX=YES NEWCC=clang-4.0 NEWCXX=clang++-4.0 + addons: { apt: { sources: ["llvm-toolchain-trusty-4.0"], packages: ["clang-4.0", "libboost1.55-all-dev"] } } + - env: BUILD_SHARED_LIBS="OFF" CMAKE_BUILD_TYPE="Debug" ENABLE_HTTPS="ON" Uri_BUILD_TESTS=OFF Uri_DISABLE_LIBCXX=YES NEWCC=clang-4.0 NEWCXX=clang++-4.0 + addons: { apt: { sources: ["llvm-toolchain-trusty-4.0"], packages: ["clang-4.0", "libboost1.55-all-dev"] } } + - env: BUILD_SHARED_LIBS="OFF" CMAKE_BUILD_TYPE="Debug" ENABLE_HTTPS="OFF" Uri_BUILD_TESTS=OFF Uri_DISABLE_LIBCXX=YES NEWCC=clang-4.0 NEWCXX=clang++-4.0 + addons: { apt: { sources: ["llvm-toolchain-trusty-4.0"], packages: ["clang-4.0", "libboost1.55-all-dev"] } } + # Clang 5.0 configurations + - env: BUILD_SHARED_LIBS="ON" CMAKE_BUILD_TYPE="Release" ENABLE_HTTPS="ON" Uri_BUILD_TESTS=OFF Uri_DISABLE_LIBCXX=YES NEWCC=clang-5.0 NEWCXX=clang++-5.0 + addons: { apt: { sources: ["llvm-toolchain-trusty-5.0"], packages: ["clang-5.0", "libboost1.55-all-dev"] } } + - env: BUILD_SHARED_LIBS="ON" CMAKE_BUILD_TYPE="Release" ENABLE_HTTPS="OFF" Uri_BUILD_TESTS=OFF Uri_DISABLE_LIBCXX=YES NEWCC=clang-5.0 NEWCXX=clang++-5.0 + addons: { apt: { sources: ["llvm-toolchain-trusty-5.0"], packages: ["clang-5.0", "libboost1.55-all-dev"] } } + - env: BUILD_SHARED_LIBS="ON" CMAKE_BUILD_TYPE="Debug" ENABLE_HTTPS="ON" Uri_BUILD_TESTS=OFF Uri_DISABLE_LIBCXX=YES NEWCC=clang-5.0 NEWCXX=clang++-5.0 + addons: { apt: { sources: ["llvm-toolchain-trusty-5.0"], packages: ["clang-5.0", "libboost1.55-all-dev"] } } + - env: BUILD_SHARED_LIBS="ON" CMAKE_BUILD_TYPE="Debug" ENABLE_HTTPS="OFF" Uri_BUILD_TESTS=OFF Uri_DISABLE_LIBCXX=YES NEWCC=clang-5.0 NEWCXX=clang++-5.0 + addons: { apt: { sources: ["llvm-toolchain-trusty-5.0"], packages: ["clang-5.0", "libboost1.55-all-dev"] } } + - env: BUILD_SHARED_LIBS="OFF" CMAKE_BUILD_TYPE="Release" ENABLE_HTTPS="ON" Uri_BUILD_TESTS=OFF Uri_DISABLE_LIBCXX=YES NEWCC=clang-5.0 NEWCXX=clang++-5.0 + addons: { apt: { sources: ["llvm-toolchain-trusty-5.0"], packages: ["clang-5.0", "libboost1.55-all-dev"] } } + - env: BUILD_SHARED_LIBS="OFF" CMAKE_BUILD_TYPE="Release" ENABLE_HTTPS="OFF" Uri_BUILD_TESTS=OFF Uri_DISABLE_LIBCXX=YES NEWCC=clang-5.0 NEWCXX=clang++-5.0 + addons: { apt: { sources: ["llvm-toolchain-trusty-5.0"], packages: ["clang-5.0", "libboost1.55-all-dev"] } } + - env: BUILD_SHARED_LIBS="OFF" CMAKE_BUILD_TYPE="Debug" ENABLE_HTTPS="ON" Uri_BUILD_TESTS=OFF Uri_DISABLE_LIBCXX=YES NEWCC=clang-5.0 NEWCXX=clang++-5.0 + addons: { apt: { sources: ["llvm-toolchain-trusty-5.0"], packages: ["clang-5.0", "libboost1.55-all-dev"] } } + - env: BUILD_SHARED_LIBS="OFF" CMAKE_BUILD_TYPE="Debug" ENABLE_HTTPS="OFF" Uri_BUILD_TESTS=OFF Uri_DISABLE_LIBCXX=YES NEWCC=clang-5.0 NEWCXX=clang++-5.0 + addons: { apt: { sources: ["llvm-toolchain-trusty-5.0"], packages: ["clang-5.0", "libboost1.55-all-dev"] } } + install: -- mkdir -p ${HOME}/bin -- if [ "${CC}" = "gcc" ]; then export TOOLSET="gcc"; ln -s `which g++-4.8` ${HOME}/bin/g++; - ln -s `which gcc-4.8` ${HOME}/bin/gcc; fi -- if [ "${CC}" = "clang" ]; then export TOOLSET="clang"; ln -s `which clang-3.6` ${HOME}/bin/clang; - ln -s `which clang++-3.6` ${HOME}/bin/clang++; fi -- export BOOST_VERSION=${BOOST_VER//./_} -- export PATH=${HOME}/bin:${PATH} -- travis_wait ./install-boost.sh -- export BOOST_ROOT=${HOME}/${CC}-boost_${BOOST_VER//./_} -- "${CXX} --version" -cache: - directories: - - "${HOME}/${CC}-boost_${BOOST_VER//./_}" + - if [[ "${CXX}" != "" ]]; then export CXX=${NEWCXX}; fi + - if [[ "${CC}" != "" ]]; then export CC=${NEWCC}; fi + - "${CXX} --version" + - "${CC} --version" + - pwd + - export CUR_DIR=`pwd` + - mkdir -p ${CUR_DIR}/bin + script: -- pwd -- sh -x build.sh + - pwd + - sh -x build.sh + after_failure: -- cat build/Testing/Temporary/LastTest.log -addons: - apt: - sources: - - ubuntu-toolchain-r-test - - llvm-toolchain-precise-3.6 - - kalakris-cmake - packages: - - gcc-4.8 - - g++-4.8 - - clang-3.6 - - cmake + - cat build/Testing/Temporary/LastTest.log + notifications: slack: secure: Y7lLjqZ83+b/jaJ5+EKwvgCDeERi4bVbDn9tLp8sieTdu+ENsPI+JmLYSXZXPpe7JrItrXW6uJJXN2wG1h7au4mpVVTghd31HBzuzrqVxDphWPhp16NYzvbAgQQRBXvFVvfSdW/Kb/n2fX6xDApY0t6vNREb/GKg0GyzESb4ZjU= diff --git a/CMakeLists.txt b/CMakeLists.txt index 19c149b52..5946295ac 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -11,6 +11,8 @@ option( CPP-NETLIB_BUILD_SHARED_LIBS "Build cpp-netlib as shared libraries." OFF option( CPP-NETLIB_BUILD_TESTS "Build the cpp-netlib project tests." ON) option( CPP-NETLIB_BUILD_EXAMPLES "Build the cpp-netlib project examples." ON) option( CPP-NETLIB_ENABLE_HTTPS "Build cpp-netlib with support for https if OpenSSL is found." ON) +option( CPP-NETLIB_STATIC_OPENSSL "Build cpp-netlib using static OpenSSL" OFF) +option( CPP-NETLIB_STATIC_BOOST "Build cpp-netlib using static Boost" OFF) include(GNUInstallDirs) @@ -36,8 +38,10 @@ else() set(BUILD_SHARED_LIBS OFF) endif() -# Always use Boost's shared libraries. -set(Boost_USE_STATIC_LIBS OFF) +# Use Boost's static libraries +if (CPP-NETLIB_STATIC_BOOST) + set(Boost_USE_STATIC_LIBS ON) +endif() # We need this for all tests to use the dynamic version. add_definitions(-DBOOST_TEST_DYN_LINK) @@ -45,10 +49,33 @@ add_definitions(-DBOOST_TEST_DYN_LINK) # Always use multi-threaded Boost libraries. set(Boost_USE_MULTI_THREADED ON) -find_package(Boost 1.57.0 REQUIRED) +find_package(Boost 1.55.0 REQUIRED COMPONENTS system thread) if (CPP-NETLIB_ENABLE_HTTPS) - find_package( OpenSSL ) + if (APPLE) + # If we're on OSX check for Homebrew's copy of OpenSSL instead of Apple's + if (NOT OpenSSL_DIR) + find_program(HOMEBREW brew) + if (HOMEBREW STREQUAL "HOMEBREW-NOTFOUND") + message(WARNING "Homebrew not found: not using Homebrew's OpenSSL") + if (NOT OPENSSL_ROOT_DIR) + message(WARNING "Use -DOPENSSL_ROOT_DIR for non-Apple OpenSSL") + endif() + else() + execute_process(COMMAND brew --prefix openssl + OUTPUT_VARIABLE OPENSSL_ROOT_DIR + OUTPUT_STRIP_TRAILING_WHITESPACE) + endif() + endif() + endif() + if (CPP-NETLIB_STATIC_OPENSSL) + if (WIN32) + set(CMAKE_FIND_LIBRARY_SUFFIXES .lib) + else() + set(CMAKE_FIND_LIBRARY_SUFFIXES .a) + endif() + endif() + find_package(OpenSSL) endif() find_package( Threads ) @@ -74,11 +101,16 @@ if (${CMAKE_CXX_COMPILER_ID} MATCHES GNU) elseif (${CMAKE_CXX_COMPILER_ID} MATCHES Clang) # We want to link in C++11 mode in Clang too, but also set a high enough # template depth for the template metaprogramming. - set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -ftemplate-depth=256 -std=c++11") + set (CMAKE_CXX_FLAGS + "${CMAKE_CXX_FLAGS} -Wall -ftemplate-depth=256 -std=c++11 -DBOOST_ASIO_HAS_STD_CHRONO -DBOOST_ASIO_HAS_STD_ARRAY -DBOOST_ASIO_HAS_STD_SHARED_PTR -DBOOST_ASIO_HAS_STD_ATOMIC -DBOOST_ASIO_HAS_VARIADIC_TEMPLATES -DBOOST_ASIO_HAS_MOVE -DBOOST_THREAD_VERSION=3") if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin") # Use libc++ only in OS X. set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++") set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -lc++") + elseif (${CMAKE_SYSTEM_NAME} MATCHES "Linux") + # Use libstdc++ for Linux. + set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libstdc++") + set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -lstdc++") endif() endif() @@ -97,9 +129,9 @@ if (Boost_FOUND) endif(WIN32) include_directories(${Boost_INCLUDE_DIRS}) - # Asio - add_definitions(-DASIO_STANDALONE) - include_directories(deps/asio/asio/include) + # # Asio + # add_definitions(-DASIO_STANDALONE) + # include_directories(deps/asio/asio/include) enable_testing() add_subdirectory(libs/network/src) @@ -117,6 +149,13 @@ if (MSVC) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /bigobj") endif() +# See whether we can find the ccache program -- if we can, then use it for the build. +find_program(CCACHE_FOUND ccache) +if(CCACHE_FOUND) + set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE ccache) + set_property(GLOBAL PROPERTY RULE_LAUNCH_LINK ccache) +endif(CCACHE_FOUND) + enable_testing() install(DIRECTORY boost DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) diff --git a/code_of_conduct.md b/CODE_OF_CONDUCT.md similarity index 100% rename from code_of_conduct.md rename to CODE_OF_CONDUCT.md diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst new file mode 100644 index 000000000..f366794d3 --- /dev/null +++ b/CONTRIBUTING.rst @@ -0,0 +1,154 @@ +Overview +======== + +In this page we document the process by which the developers of the +project collaborate and get things done. If you're interested in +contributing or getting involved please consider the guidelines and +tips that are outlined in this page. Please check-in often as we flesh +out this document further. + +Introduction +============ + +The first thing contributors and developers have to do is introduce +themselves to the community. We'd like to have all contributors +involved in the decision making process with regards to the +development of both the community and the library. We value +individuals and their personal styles, so the more everyone knows +about everyone the better we can work together to achieve the same +goal. + +If you haven't yet, please `subscribe`_ to the developers mailing list +and introduce yourself before proceeding. + +.. _`subscribe`: https://groups.google.com/group/cpp-netlib` + +Pull Requests +============= + +The maintainers of the project review and merge `Pull Requests`_ (from +here on out referred to as PR's) from contributors using the GitHub +Pull Request feature. This allows the project to move forward using +the Git distributed development workflow. If you need an introduction +to git, please refer to the following links for git-specific +information. + +.. _`Pull Requests`: https://help.github.com/articles/using-pull-requests + +* `ProGit`_ — a website dedicated to basic and advanced git usage. +* `GitHub Git Setup`_ — the GitHub help pages on setting up git to work + with GitHub. + +.. _`ProGit`: http://git-scm.com/book +.. _`GitHub Git Setup`: https://help.github.com/articles/set-up-git + +What follows in this section assumes that you're already familiar with +the basic git workflow. + +Forking the Repo +================ + +Forking requires that you already have a GitHub account. Before +continuing, please make sure that you've signed up for a GitHub +account (it's free to develop for open source projects) and have +familiarized yourself with the different development workflows. It's +important that you understand the GitHub workflow before continuing. + +The official repository is located in GitHub at +https://github.com/cpp-netlib/cpp-netlib. Before you can submit PR's +you should first create your own fork of the repository on GitHub. You +can fork the repository by clicking on `Fork`_ at the upper right portion +of the page. + +.. _`Fork`: https://github.com/cpp-netlib/cpp-netlib/fork + +Preparing a PR +============== + +Once you have a fork of the repo, determine to which branch you'd like +to send a PR to. In the next section we describe the various branches +we'll be dealing with in the course of development of a release. + +When you've determined the branch to which you'd like to send a PR to +you can follow these steps to prepare your change for inclusion in the +library. + +1. Create an integration branch. This integration branch should be + rooted off the branch you intend to send a PR to. For example, if + you're sending a PR to cpp-netlib/master and your fork is + user/master, you should create a user/master-integration branch. +2. Create a topic branch. From the integration branch, you can then + create as many topic branches as you want. It's recommended that you + isolate all experimentation to branches — once you're resonably sure + that your work is good to go, merge your topic branch into the + integration branch in your local repo, then push the changes to your + GitHub repo. +3. Make sure your integration branch is up to date. To do this you + should first pull changes to your local master (assuming that's where + you'd like to send a pull request to), rebase your integration branch + to the tip of master, then make sure all merge conflicts are dealt + with. Proceed only when your integration branch is up-to-date with the + official branch you're going to send your PR to. +4. Send the PR. Once you're reasonably happy with the state of your + integration branch, send off a PR to the official repo and set the + destination branch as the branch you intend to send the change to. +5. Address Comments The maintainers will be reviewing your changes, and + sometimes they may have comments they will ask you to address in + your PR. You can do this by going back to the second step of this + process, but you don't need to send another PR -- all you have to do + is push your changes to your GitHub hosted integration branch and + your PR will be updated automatically. That said, don't forget to + update the discussion on the PR that you're ready for the PR to be + reviewed again. +6. Your PR is merged. If you've done everything correctly up to this + point, your PR should be cleanly merge-able into the branch you sent + the PR to. A maintiner will merge you change into the project and + you're now officially a contributor to the project! + + +In case you have multiple PR's in flight, you may want to have +multiple integration branches — that is, one integration branch per PR +should be good to keep. + +Working Branches +================ + +The project always has the latest bleeding edge versions of the +library under development in the master branch. This version is +explicitly unstable and subject to (potentially massive) changes over +time. + +Once the state of master has stabilized and a release process is +initiated by the project maintainers (it will be announced on the +mailing list) a version-devel branch is started from master and a +release candidate is prepared. For example, if a 1.0 release is +initiated, a branch 1.0-devel is started off master. + +A release candidate is tagged off of the version-devel branch on a +regular basis, and is publicized as widely as possible. The tag name +should be of the form version-rcN. Again as an example, the first +release candidate for a 1.0 release will be tagged as 1.0.0-rc0. + +All PR's for the upcoming version should go directly to the +version-devel branch. + +During the stabilization of the version-devel branch, master remains +open for PR's for new functionality, new accepted libraries, and API +breaking changes. + +Once a release candidate is deemed "good to go" by the maintainers we +tag the library (and submodules appropriately) with a tag of the form +version-final. As with earlier examples, the tag for the 1.0 release +would be 1.0.0-final. + +Patch Releases +============== + +Critical bug fixes go into the version-devel branch after a final +release has been packaged. In case there's a need for update releases, +the release candidate process is followed until another final version +of the patch release is tagged. + +In our on-going example, this will be of the form 1.0.1-rc0, +1.0.1-rc1, and so on until it's stabilized — at which time a +1.0.1-final is tagged and packaged. diff --git a/RATIONALE.txt b/RATIONALE.txt index c9e8960f0..55ed22204 100644 --- a/RATIONALE.txt +++ b/RATIONALE.txt @@ -35,7 +35,7 @@ Goals * Implement an efficient easy to use URI class/parser. * Implement a fully compliant cross-platform asynchronous DNS resolver - either as a wrapper to external (C) libraries, or as hand-rolled + either as a wrapper to external (C) libraries or as hand-rolled implementation. * Implement a MIME handler which builds message objects from either diff --git a/README.rst b/README.rst index 8eb2abdd2..4a19a91d5 100644 --- a/README.rst +++ b/README.rst @@ -34,12 +34,12 @@ follow these instructions for cloning the project repository:: Introduction ------------ -cpp-netlib is a collection of network related routines/implementations +cpp-netlib is a collection of network-related routines/implementations geared towards providing a robust cross-platform networking library. cpp-netlib offers the following implementations: * Common Message Type -- A generic message type which can be used - to encapsulate and store message related information, used by all + to encapsulate and store message-related information, used by all network implementations as the primary means of data exchange. * Network protocol message parsers -- A collection of parsers which generate message objects from strings. @@ -81,6 +81,19 @@ you can now build the tests and run them:: $ make $ make test +You can also download and install cpp-netlib using the ` vcpkg`_ dependency manager: + + $ git clone https://github.com/Microsoft/vcpkg.git + $ cd vcpkg + $ ./bootstrap-vcpkg.sh + $ ./vcpkg integrate install + $ vcpkg install cpp-netlib + +The cpp-netlib port in vcpkg is kept up to date by Microsoft team members and community contributors. If the version is out of date, please create an issue or pull request on the ` vcpkg`_ repository. + +.. _`vcpkg`: https://github.com/Microsoft/vcpkg + + If for some reason some of the tests fail, you can send the files in ``Testing/Temporary/`` as attachments to the cpp-netlib `developers mailing list`_. @@ -104,7 +117,7 @@ you will need. These are: Hacking on cpp-netlib --------------------- -cpp-netlib uses git_ for tracking work, and is hosted on GitHub_. +cpp-netlib uses git_ for tracking work and is hosted on GitHub_. cpp-netlib is hosted on GitHub_ following the GitHub recommended practice of forking the repository and submitting pull requests to the source repository. You can read more about the forking_ process and submitting `pull requests`_ if diff --git a/boost/network/message/directives/detail/string_directive.hpp b/boost/network/message/directives/detail/string_directive.hpp index db07eceb4..3c1e652db 100644 --- a/boost/network/message/directives/detail/string_directive.hpp +++ b/boost/network/message/directives/detail/string_directive.hpp @@ -34,8 +34,8 @@ #define BOOST_NETWORK_STRING_DIRECTIVE(name, value, body, pod_body) \ template \ struct name##_directive { \ - ValueType const&((value)); \ - explicit name##_directive(ValueType const& value_) : value(value_) {} \ + ValueType const& value; \ + explicit name##_directive(ValueType const& v) : value(v) {} \ name##_directive(name##_directive const& other) : value(other.value) {} \ template class Message> \ typename enable_if, void>::type operator()( \ diff --git a/boost/network/message/directives/detail/string_value.hpp b/boost/network/message/directives/detail/string_value.hpp index 53bea1546..8a3fa7d26 100644 --- a/boost/network/message/directives/detail/string_value.hpp +++ b/boost/network/message/directives/detail/string_value.hpp @@ -6,10 +6,10 @@ // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) -#include #include #include #include +#include #include #include #include @@ -20,7 +20,7 @@ namespace detail { template struct string_value - : mpl::if_, std::shared_future::type>, + : mpl::if_, boost::shared_future::type>, typename mpl::if_< mpl::or_, is_same, is_same >, diff --git a/boost/network/message/modifiers/clear_headers.hpp b/boost/network/message/modifiers/clear_headers.hpp index 1f54af0d9..ef758073f 100644 --- a/boost/network/message/modifiers/clear_headers.hpp +++ b/boost/network/message/modifiers/clear_headers.hpp @@ -6,11 +6,11 @@ // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) -#include #include #include #include #include +#include #include namespace boost { @@ -34,8 +34,8 @@ template inline typename enable_if >, is_async >, void>::type clear_headers(Message const &message, Tag const &) { - std::promise header_promise; - std::shared_future headers_future( + boost::promise header_promise; + boost::shared_future headers_future( header_promise.get_future()); message.headers(headers_future); header_promise.set_value(typename Message::headers_container_type()); diff --git a/boost/network/message/traits/body.hpp b/boost/network/message/traits/body.hpp index 495fe2d9b..cd0c56b1f 100644 --- a/boost/network/message/traits/body.hpp +++ b/boost/network/message/traits/body.hpp @@ -8,12 +8,12 @@ // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) -#include #include #include #include #include #include +#include #include namespace boost { @@ -27,7 +27,7 @@ template struct body : mpl::if_< is_async, - std::shared_future::type>, + boost::shared_future::type>, typename mpl::if_< mpl::or_, is_same #include #include #include #include #include +#include #include namespace boost { @@ -26,7 +26,7 @@ struct unsupported_tag; template struct destination : mpl::if_, - std::shared_future::type>, + boost::shared_future::type>, typename mpl::if_< mpl::or_, is_same #include #include #include @@ -15,6 +14,7 @@ #include #include #include +#include namespace boost { namespace network { @@ -28,7 +28,7 @@ template struct header_key : mpl::if_< is_async, - std::shared_future::type>, + boost::shared_future::type>, typename mpl::if_< mpl::or_, is_same, @@ -40,7 +40,7 @@ template struct header_value : mpl::if_< is_async, - std::shared_future::type>, + boost::shared_future::type>, typename mpl::if_< mpl::or_, is_same, diff --git a/boost/network/message/traits/source.hpp b/boost/network/message/traits/source.hpp index ad037a4a6..17f9b188e 100644 --- a/boost/network/message/traits/source.hpp +++ b/boost/network/message/traits/source.hpp @@ -6,12 +6,12 @@ // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) -#include #include #include #include #include #include +#include #include namespace boost { @@ -24,7 +24,7 @@ struct unsupported_tag; template struct source : mpl::if_, - std::shared_future::type>, + boost::shared_future::type>, typename mpl::if_< mpl::or_, is_same #include #include -#include -#include +#include +#include #include namespace boost { @@ -31,27 +31,28 @@ struct async_client typedef typename resolver::type resolver_type; typedef typename string::type string_type; - typedef std::function const&, - std::error_code const&)> + typedef std::function::type, 1024>::const_iterator> const&, + boost::system::error_code const&)> body_callback_function_type; typedef std::function body_generator_function_type; async_client(bool cache_resolved, bool follow_redirect, - bool always_verify_peer, int timeout, - std::shared_ptr<::asio::io_service> service, + bool always_verify_peer, int timeout, bool remove_chunk_markers, + std::shared_ptr service, optional certificate_filename, optional verify_path, optional certificate_file, optional private_key_file, optional ciphers, optional sni_hostname, long ssl_options) - : connection_base(cache_resolved, follow_redirect, timeout), + : connection_base(cache_resolved, follow_redirect, timeout, + remove_chunk_markers), service_ptr(service.get() ? service - : std::make_shared<::asio::io_service>()), + : std::make_shared()), service_(*service_ptr), resolver_(service_), - sentinel_(new ::asio::io_service::work(service_)), + sentinel_(new boost::asio::io_service::work(service_)), certificate_filename_(std::move(certificate_filename)), verify_path_(std::move(verify_path)), certificate_file_(std::move(certificate_file)), @@ -61,7 +62,7 @@ struct async_client ssl_options_(ssl_options), always_verify_peer_(always_verify_peer) { connection_base::resolver_strand_.reset( - new ::asio::io_service::strand(service_)); + new boost::asio::io_service::strand(service_)); if (!service) lifetime_thread_.reset(new std::thread([this]() { service_.run(); })); } @@ -89,10 +90,10 @@ struct async_client generator); } - std::shared_ptr<::asio::io_service> service_ptr; - ::asio::io_service& service_; + std::shared_ptr service_ptr; + boost::asio::io_service& service_; resolver_type resolver_; - std::shared_ptr<::asio::io_service::work> sentinel_; + std::shared_ptr sentinel_; std::shared_ptr lifetime_thread_; optional certificate_filename_; optional verify_path_; diff --git a/boost/network/protocol/http/client/connection/async_base.hpp b/boost/network/protocol/http/client/connection/async_base.hpp index d92d254be..b1c1aa67a 100644 --- a/boost/network/protocol/http/client/connection/async_base.hpp +++ b/boost/network/protocol/http/client/connection/async_base.hpp @@ -33,7 +33,7 @@ struct async_connection_base { typedef basic_response response; typedef typename std::array::type, 1024>::const_iterator const_iterator; typedef iterator_range char_const_range; - typedef std::function + typedef std::function body_callback_function_type; typedef std::function body_generator_function_type; typedef std::shared_ptr connection_ptr; @@ -44,6 +44,7 @@ struct async_connection_base { static connection_ptr new_connection( resolve_function resolve, resolver_type &resolver, bool follow_redirect, bool always_verify_peer, bool https, int timeout, + bool remove_chunk_markers, optional certificate_filename = optional(), optional const &verify_path = optional(), optional certificate_file = optional(), @@ -59,7 +60,8 @@ struct async_connection_base { certificate_filename, verify_path, certificate_file, private_key_file, ciphers, sni_hostname, ssl_options); auto temp = std::make_shared( - resolver, resolve, follow_redirect, timeout, std::move(delegate)); + resolver, resolve, follow_redirect, timeout, remove_chunk_markers, + std::move(delegate)); BOOST_ASSERT(temp != nullptr); return temp; } diff --git a/boost/network/protocol/http/client/connection/async_normal.hpp b/boost/network/protocol/http/client/connection/async_normal.hpp index b12e2cb2f..ac10407c0 100644 --- a/boost/network/protocol/http/client/connection/async_normal.hpp +++ b/boost/network/protocol/http/client/connection/async_normal.hpp @@ -12,10 +12,10 @@ #include #include #include -#include -#include -#include -#include +#include +#include +#include +#include #include #include #include @@ -30,6 +30,7 @@ #include #include #include +#include #include namespace boost { @@ -37,10 +38,86 @@ namespace network { namespace http { namespace impl { +template +struct chunk_encoding_parser { + chunk_encoding_parser() : state(state_t::header), chunk_size(0) {} + + enum class state_t { header, header_end, data, data_end }; + + state_t state; + size_t chunk_size; + std::array::type, 1024> buffer; + + void update_chunk_size( + boost::iterator_range::type, 1024>::const_iterator> const &range) { + if (range.empty()) return; + std::stringstream ss; + ss << std::hex << range; + size_t size; + ss >> size; + // New digits are appended as LSBs + chunk_size = (chunk_size << (range.size() * 4)) | size; + } + + boost::iterator_range< + typename std::array::type, 1024>::const_iterator> + operator()( + boost::iterator_range::type, 1024>::const_iterator> const &range) { + auto iter = boost::begin(range); + auto begin = iter; + auto pos = boost::begin(buffer); + + while (iter != boost::end(range)) switch (state) { + case state_t::header: + iter = std::find(iter, boost::end(range), '\r'); + update_chunk_size(boost::make_iterator_range(begin, iter)); + if (iter != boost::end(range)) { + state = state_t::header_end; + ++iter; + } + break; + + case state_t::header_end: + BOOST_ASSERT(*iter == '\n'); + ++iter; + state = state_t::data; + break; + + case state_t::data: + if (chunk_size == 0) { + BOOST_ASSERT(*iter == '\r'); + ++iter; + state = state_t::data_end; + } else { + auto len = std::min(chunk_size, + (size_t)std::distance(iter, boost::end(range))); + begin = iter; + iter = std::next(iter, len); + pos = std::copy(begin, iter, pos); + chunk_size -= len; + } + break; + + case state_t::data_end: + BOOST_ASSERT(*iter == '\n'); + ++iter; + begin = iter; + state = state_t::header; + break; + + default: + BOOST_ASSERT(false && "Bug, report this to the developers!"); + } + return boost::make_iterator_range(boost::begin(buffer), pos); + } +}; + template struct async_connection_base; -namespace placeholders = ::asio::placeholders; +namespace placeholders = boost::asio::placeholders; template struct http_async_connection @@ -71,9 +148,11 @@ struct http_async_connection connection_delegate_ptr; http_async_connection(resolver_type& resolver, resolve_function resolve, - bool follow_redirect, int timeout, + bool follow_redirect, int64_t timeout, + bool remove_chunk_markers, connection_delegate_ptr delegate) : timeout_(timeout), + remove_chunk_markers_(remove_chunk_markers), timer_(resolver.get_io_service()), is_timedout_(false), follow_redirect_(follow_redirect), @@ -82,11 +161,9 @@ struct http_async_connection request_strand_(resolver.get_io_service()), delegate_(std::move(delegate)) {} - // This is the main entry point for the connection/request pipeline. - // We're - // overriding async_connection_base<...>::start(...) here which is - // called - // by the client. + // This is the main entry point for the connection/request pipeline. We're + // overriding async_connection_base<...>::start(...) here which is called by + // the client. virtual response start(request const& request, string_type const& method, bool get_body, body_callback_function_type callback, body_generator_function_type generator) { @@ -101,38 +178,44 @@ struct http_async_connection std::uint16_t source_port = request.source_port(); auto self = this->shared_from_this(); + if (timeout_ > 0) { +#if defined(BOOST_ASIO_HAS_STD_CHRONO) + timer_.expires_from_now(std::chrono::seconds(timeout_)); +#elif defined(BOOST_ASIO_HAS_BOOST_CHRONO) + timer_.expires_from_now(boost::chrono::seconds(timeout_)); +#else +#error Need a chrono implementation +#endif + timer_.async_wait(request_strand_.wrap([=] (boost::system::error_code const &ec) { + self->handle_timeout(ec); + })); + } resolve_(resolver_, host_, port_, request_strand_.wrap( - [=] (std::error_code const &ec, + [=] (boost::system::error_code const &ec, resolver_iterator_pair endpoint_range) { self->handle_resolved(host_, port_, source_port, get_body, callback, generator, ec, endpoint_range); })); - if (timeout_ > 0) { - timer_.expires_from_now(std::chrono::seconds(timeout_)); - timer_.async_wait(request_strand_.wrap([=] (std::error_code const &ec) { - self->handle_timeout(ec); - })); - } return response_; } private: - void set_errors(std::error_code const& ec, body_callback_function_type callback) { - std::system_error error(ec); - this->version_promise.set_exception(std::make_exception_ptr(error)); - this->status_promise.set_exception(std::make_exception_ptr(error)); - this->status_message_promise.set_exception(std::make_exception_ptr(error)); - this->headers_promise.set_exception(std::make_exception_ptr(error)); - this->source_promise.set_exception(std::make_exception_ptr(error)); - this->destination_promise.set_exception(std::make_exception_ptr(error)); - this->body_promise.set_exception(std::make_exception_ptr(error)); + void set_errors(boost::system::error_code const& ec, body_callback_function_type callback) { + boost::system::system_error error(ec); + this->version_promise.set_exception(boost::copy_exception(error)); + this->status_promise.set_exception(boost::copy_exception(error)); + this->status_message_promise.set_exception(boost::copy_exception(error)); + this->headers_promise.set_exception(boost::copy_exception(error)); + this->source_promise.set_exception(boost::copy_exception(error)); + this->destination_promise.set_exception(boost::copy_exception(error)); + this->body_promise.set_exception(boost::copy_exception(error)); if ( callback ) - callback( boost::iterator_range(), ec ); + callback( boost::iterator_range::type, 1024>::const_iterator>(), ec ); this->timer_.cancel(); } - void handle_timeout(std::error_code const& ec) { + void handle_timeout(boost::system::error_code const& ec) { if (!ec) delegate_->disconnect(); is_timedout_ = true; } @@ -141,23 +224,23 @@ struct http_async_connection std::uint16_t source_port, bool get_body, body_callback_function_type callback, body_generator_function_type generator, - std::error_code const& ec, + boost::system::error_code const& ec, resolver_iterator_pair endpoint_range) { if (!ec && !boost::empty(endpoint_range)) { // Here we deal with the case that there was an error encountered and // that there's still more endpoints to try connecting to. resolver_iterator iter = boost::begin(endpoint_range); - ::asio::ip::tcp::endpoint endpoint(iter->endpoint().address(), port); + boost::asio::ip::tcp::endpoint endpoint(iter->endpoint().address(), port); auto self = this->shared_from_this(); delegate_->connect( endpoint, host, source_port, - request_strand_.wrap([=] (std::error_code const &ec) { + request_strand_.wrap([=] (boost::system::error_code const &ec) { auto iter_copy = iter; self->handle_connected(host, port, source_port, get_body, callback, generator, std::make_pair(++iter_copy, resolver_iterator()), ec); })); } else { - set_errors((ec ? ec : ::asio::error::host_not_found), callback); + set_errors((ec ? ec : boost::asio::error::host_not_found), callback); } } @@ -166,15 +249,15 @@ struct http_async_connection body_callback_function_type callback, body_generator_function_type generator, resolver_iterator_pair endpoint_range, - std::error_code const& ec) { + boost::system::error_code const& ec) { if (is_timedout_) { - set_errors(::asio::error::timed_out, callback); + set_errors(boost::asio::error::timed_out, callback); } else if (!ec) { BOOST_ASSERT(delegate_.get() != 0); auto self = this->shared_from_this(); delegate_->write( command_streambuf, - request_strand_.wrap([=] (std::error_code const &ec, + request_strand_.wrap([=] (boost::system::error_code const &ec, std::size_t bytes_transferred) { self->handle_sent_request(get_body, callback, generator, ec, bytes_transferred); @@ -182,18 +265,18 @@ struct http_async_connection } else { if (!boost::empty(endpoint_range)) { resolver_iterator iter = boost::begin(endpoint_range); - ::asio::ip::tcp::endpoint endpoint(iter->endpoint().address(), port); + boost::asio::ip::tcp::endpoint endpoint(iter->endpoint().address(), port); auto self = this->shared_from_this(); delegate_->connect( endpoint, host, source_port, - request_strand_.wrap([=] (std::error_code const &ec) { + request_strand_.wrap([=] (boost::system::error_code const &ec) { auto iter_copy = iter; self->handle_connected(host, port, source_port, get_body, callback, generator, std::make_pair(++iter_copy, resolver_iterator()), ec); })); } else { - set_errors((ec ? ec : ::asio::error::host_not_found), callback); + set_errors((ec ? ec : boost::asio::error::host_not_found), callback); } } } @@ -202,7 +285,7 @@ struct http_async_connection void handle_sent_request(bool get_body, body_callback_function_type callback, body_generator_function_type generator, - std::error_code const& ec, + boost::system::error_code const& ec, std::size_t bytes_transferred) { if (!is_timedout_ && !ec) { if (generator) { @@ -218,7 +301,7 @@ struct http_async_connection auto self = this->shared_from_this(); delegate_->write( command_streambuf, - request_strand_.wrap([=] (std::error_code const &ec, + request_strand_.wrap([=] (boost::system::error_code const &ec, std::size_t bytes_transferred) { self->handle_sent_request(get_body, callback, generator, ec, bytes_transferred); @@ -229,41 +312,41 @@ struct http_async_connection auto self = this->shared_from_this(); delegate_->read_some( - ::asio::mutable_buffers_1(this->part.data(), + boost::asio::mutable_buffers_1(this->part.data(), this->part.size()), - request_strand_.wrap([=] (std::error_code const &ec, + request_strand_.wrap([=] (boost::system::error_code const &ec, std::size_t bytes_transferred) { self->handle_received_data(version, get_body, callback, ec, bytes_transferred); })); } else { - set_errors((is_timedout_ ? ::asio::error::timed_out : ec), callback); + set_errors((is_timedout_ ? boost::asio::error::timed_out : ec), callback); } } void handle_received_data(state_t state, bool get_body, body_callback_function_type callback, - std::error_code const& ec, + boost::system::error_code const& ec, std::size_t bytes_transferred) { static const long short_read_error = 335544539; bool is_ssl_short_read_error = #ifdef BOOST_NETWORK_ENABLE_HTTPS - ec.category() == ::asio::error::ssl_category && + ec.category() == boost::asio::error::ssl_category && ec.value() == short_read_error; #else false && short_read_error; #endif if (!is_timedout_ && - (!ec || ec == ::asio::error::eof || is_ssl_short_read_error)) { + (!ec || ec == boost::asio::error::eof || is_ssl_short_read_error)) { logic::tribool parsed_ok; size_t remainder; auto self = this->shared_from_this(); switch (state) { case version: - if (ec == ::asio::error::eof) return; + if (ec == boost::asio::error::eof) return; parsed_ok = this->parse_version( delegate_, - request_strand_.wrap([=] (std::error_code const &ec, + request_strand_.wrap([=] (boost::system::error_code const &ec, std::size_t bytes_transferred) { self->handle_received_data(version, get_body, callback, ec, bytes_transferred); @@ -273,10 +356,10 @@ struct http_async_connection return; } case status: - if (ec == ::asio::error::eof) return; + if (ec == boost::asio::error::eof) return; parsed_ok = this->parse_status( delegate_, - request_strand_.wrap([=] (std::error_code const &ec, + request_strand_.wrap([=] (boost::system::error_code const &ec, std::size_t bytes_transferred) { self->handle_received_data(status, get_body, callback, ec, bytes_transferred); @@ -286,9 +369,9 @@ struct http_async_connection return; } case status_message: - if (ec == ::asio::error::eof) return; + if (ec == boost::asio::error::eof) return; parsed_ok = this->parse_status_message( - delegate_, request_strand_.wrap([=] (std::error_code const &, + delegate_, request_strand_.wrap([=] (boost::system::error_code const &, std::size_t bytes_transferred) { self->handle_received_data(status_message, get_body, callback, ec, bytes_transferred); @@ -298,14 +381,14 @@ struct http_async_connection return; } case headers: - if (ec == ::asio::error::eof) return; + if (ec == boost::asio::error::eof) return; // In the following, remainder is the number of bytes that remain in // the buffer. We need this in the body processing to make sure that // the data remaining in the buffer is dealt with before another call // to get more data for the body is scheduled. std::tie(parsed_ok, remainder) = this->parse_headers( delegate_, - request_strand_.wrap([=] (std::error_code const &ec, + request_strand_.wrap([=] (boost::system::error_code const &ec, std::size_t bytes_transferred) { self->handle_received_data(headers, get_body, callback, ec, bytes_transferred); @@ -321,7 +404,7 @@ struct http_async_connection // body (in the case of a HEAD request). this->body_promise.set_value(""); if ( callback ) - callback( boost::iterator_range(), ::asio::error::eof ); + callback( boost::iterator_range::type, 1024>::const_iterator>(), boost::asio::error::eof ); this->destination_promise.set_value(""); this->source_promise.set_value(""); // this->part.assign('\0'); @@ -348,13 +431,16 @@ struct http_async_connection // The invocation of the callback is synchronous to allow us to // wait before scheduling another read. - callback(make_iterator_range(begin, end), ec); - + if (this->is_chunk_encoding && remove_chunk_markers_) { + callback(parse_chunk_encoding(make_iterator_range(begin, end)), ec); + } else { + callback(make_iterator_range(begin, end), ec); + } auto self = this->shared_from_this(); delegate_->read_some( - ::asio::mutable_buffers_1(this->part.data(), + boost::asio::mutable_buffers_1(this->part.data(), this->part.size()), - request_strand_.wrap([=] (std::error_code const &ec, + request_strand_.wrap([=] (boost::system::error_code const &ec, std::size_t bytes_transferred) { self->handle_received_data(body, get_body, callback, ec, bytes_transferred); @@ -365,7 +451,7 @@ struct http_async_connection auto self = this->shared_from_this(); this->parse_body( delegate_, - request_strand_.wrap([=] (std::error_code const &ec, + request_strand_.wrap([=] (boost::system::error_code const &ec, std::size_t bytes_transferred) { self->handle_received_data(body, get_body, callback, ec, bytes_transferred); @@ -374,7 +460,7 @@ struct http_async_connection } return; case body: - if (ec == ::asio::error::eof || is_ssl_short_read_error) { + if (ec == boost::asio::error::eof || is_ssl_short_read_error) { // Here we're handling the case when the connection has been closed // from the server side, or at least that the end of file has been // reached while reading the socket. This signals the end of the @@ -388,14 +474,33 @@ struct http_async_connection // We call the callback function synchronously passing the error // condition (in this case, end of file) so that it can handle it // appropriately. - callback(make_iterator_range(begin, end), ec); + if (this->is_chunk_encoding && remove_chunk_markers_) { + callback(parse_chunk_encoding(make_iterator_range(begin, end)), ec); + } else { + callback(make_iterator_range(begin, end), ec); + } } else { string_type body_string; - std::swap(body_string, this->partial_parsed); - body_string.append(this->part.begin(), bytes_transferred); - if (this->is_chunk_encoding) { - this->body_promise.set_value(parse_chunk_encoding(body_string)); + if (this->is_chunk_encoding && remove_chunk_markers_) { + for (size_t i = 0; i < this->partial_parsed.size(); i += 1024) { + auto range = parse_chunk_encoding(boost::make_iterator_range( + static_cast::type, 1024>::const_iterator>( + this->partial_parsed.data()) + i, + static_cast::type, 1024>::const_iterator>( + this->partial_parsed.data()) + + std::min(i + 1024, this->partial_parsed.size()))); + body_string.append(boost::begin(range), boost::end(range)); + } + this->partial_parsed.clear(); + auto range = parse_chunk_encoding(boost::make_iterator_range( + this->part.begin(), + this->part.begin() + bytes_transferred)); + body_string.append(boost::begin(range), boost::end(range)); + this->body_promise.set_value(body_string); } else { + std::swap(body_string, this->partial_parsed); + body_string.append(this->part.begin(), + this->part.begin() + bytes_transferred); this->body_promise.set_value(body_string); } } @@ -417,12 +522,16 @@ struct http_async_connection this->part.begin(); typename protocol_base::buffer_type::const_iterator end = begin; std::advance(end, bytes_transferred); - callback(make_iterator_range(begin, end), ec); + if (this->is_chunk_encoding && remove_chunk_markers_) { + callback(parse_chunk_encoding(make_iterator_range(begin, end)), ec); + } else { + callback(make_iterator_range(begin, end), ec); + } auto self = this->shared_from_this(); delegate_->read_some( - ::asio::mutable_buffers_1(this->part.data(), + boost::asio::mutable_buffers_1(this->part.data(), this->part.size()), - request_strand_.wrap([=] (std::error_code const &ec, + request_strand_.wrap([=] (boost::system::error_code const &ec, std::size_t bytes_transferred) { self->handle_received_data(body, get_body, callback, ec, bytes_transferred); @@ -433,7 +542,7 @@ struct http_async_connection // have data that's still in the buffer. this->parse_body( delegate_, - request_strand_.wrap([=] (std::error_code const &ec, + request_strand_.wrap([=] (boost::system::error_code const &ec, std::size_t bytes_transferred) { self->handle_received_data(body, get_body, callback, ec, bytes_transferred); @@ -446,8 +555,8 @@ struct http_async_connection BOOST_ASSERT(false && "Bug, report this to the developers!"); } } else { - std::error_code report_code = is_timedout_ ? ::asio::error::timed_out : ec; - std::system_error error(report_code); + boost::system::error_code report_code = is_timedout_ ? boost::asio::error::timed_out : ec; + boost::system::system_error error(report_code); this->source_promise.set_exception(std::make_exception_ptr(error)); this->destination_promise.set_exception(std::make_exception_ptr(error)); switch (state) { @@ -468,7 +577,7 @@ struct http_async_connection this->body_promise.set_exception(std::make_exception_ptr(error)); } else - callback( boost::iterator_range(), report_code ); + callback( boost::iterator_range::type, 1024>::const_iterator>(), report_code ); break; default: BOOST_ASSERT(false && "Bug, report this to the developers!"); @@ -476,47 +585,18 @@ struct http_async_connection } } - string_type parse_chunk_encoding(string_type& body_string) { - string_type body; - string_type crlf = "\r\n"; - - typename string_type::iterator begin = body_string.begin(); - for (typename string_type::iterator iter = - std::search(begin, body_string.end(), crlf.begin(), crlf.end()); - iter != body_string.end(); - iter = - std::search(begin, body_string.end(), crlf.begin(), crlf.end())) { - string_type line(begin, iter); - if (line.empty()) { - break; - } - std::stringstream stream(line); - int len; - stream >> std::hex >> len; - std::advance(iter, 2); - if (len == 0) { - break; - } - if (len <= body_string.end() - iter) { - body.insert(body.end(), iter, iter + len); - std::advance(iter, len + 2); - } - begin = iter; - } - - return body; - } - - int timeout_; - ::asio::steady_timer timer_; + int64_t timeout_; + bool remove_chunk_markers_; + boost::asio::steady_timer timer_; bool is_timedout_; bool follow_redirect_; resolver_type& resolver_; resolve_function resolve_; - ::asio::io_service::strand request_strand_; + boost::asio::io_service::strand request_strand_; connection_delegate_ptr delegate_; - ::asio::streambuf command_streambuf; + boost::asio::streambuf command_streambuf; string_type method; + chunk_encoding_parser parse_chunk_encoding; }; } // namespace impl diff --git a/boost/network/protocol/http/client/connection/async_protocol_handler.hpp b/boost/network/protocol/http/client/connection/async_protocol_handler.hpp index b35086206..a0ce75bce 100644 --- a/boost/network/protocol/http/client/connection/async_protocol_handler.hpp +++ b/boost/network/protocol/http/client/connection/async_protocol_handler.hpp @@ -17,6 +17,7 @@ #include #include #include +#include namespace boost { namespace network { @@ -57,30 +58,30 @@ struct http_async_protocol_handler { // TODO(dberris): review parameter necessity. (void)get_body; - std::shared_future source_future( + boost::shared_future source_future( source_promise.get_future()); source(response_, source_future); - std::shared_future destination_future( + boost::shared_future destination_future( destination_promise.get_future()); destination(response_, destination_future); - std::shared_future::type> headers_future( + boost::shared_future::type> headers_future( headers_promise.get_future()); headers(response_, headers_future); - std::shared_future body_future(body_promise.get_future()); + boost::shared_future body_future(body_promise.get_future()); body(response_, body_future); - std::shared_future version_future( + boost::shared_future version_future( version_promise.get_future()); version(response_, version_future); - std::shared_future status_future( + boost::shared_future status_future( status_promise.get_future()); status(response_, status_future); - std::shared_future status_message_future( + boost::shared_future status_message_future( status_message_promise.get_future()); status_message(response_, status_message_future); } @@ -139,7 +140,7 @@ struct http_async_protocol_handler { std::end(result_range)); part_begin = part.begin(); delegate_->read_some( - ::asio::mutable_buffers_1(part.data(), part.size()), + boost::asio::mutable_buffers_1(part.data(), part.size()), callback); } return parsed_ok; @@ -185,7 +186,7 @@ struct http_async_protocol_handler { std::end(result_range)); part_begin = part.begin(); delegate_->read_some( - ::asio::mutable_buffers_1(part.data(), part.size()), + boost::asio::mutable_buffers_1(part.data(), part.size()), callback); } return parsed_ok; @@ -230,7 +231,7 @@ struct http_async_protocol_handler { std::end(result_range)); part_begin = part.begin(); delegate_->read_some( - ::asio::mutable_buffers_1(part.data(), part.size()), + boost::asio::mutable_buffers_1(part.data(), part.size()), callback); } return parsed_ok; @@ -245,6 +246,10 @@ struct http_async_protocol_handler { response_parser_type::http_header_line_done); typename headers_container::type headers; std::pair header_pair; + //init params + is_content_length = false; + content_length = -1; + is_chunk_end = false; while (!boost::empty(input_range)) { std::tie(parsed_ok, result_range) = headers_parser.parse_until( response_parser_type::http_header_colon, input_range); @@ -265,6 +270,16 @@ struct http_async_protocol_handler { } trim(header_pair.second); headers.insert(header_pair); + if (!is_content_length && + boost::iequals(header_pair.first, "Content-Length")) { + try { + content_length = std::stoll(header_pair.second); + is_content_length = true; + } + catch (std::exception&) { + //is_content_length = false; + } + } } // determine if the body parser will need to handle chunked encoding typename headers_range >::type transfer_encoding_range = @@ -317,21 +332,68 @@ struct http_async_protocol_handler { std::end(result_range)); part_begin = part.begin(); delegate_->read_some( - ::asio::mutable_buffers_1(part.data(), part.size()), + boost::asio::mutable_buffers_1(part.data(), part.size()), callback); } return std::make_tuple( parsed_ok, std::distance(std::end(result_range), part_end)); } + inline bool check_parse_body_complete() const { + if (this->is_chunk_encoding) { + return parse_chunk_encoding_complete(); + } + if (this->is_content_length && this->content_length >= 0) { + return parse_content_length_complete(); + } + return false; + } + + inline bool parse_content_length_complete() const { + return static_cast(this->partial_parsed.length()) >= this->content_length; + } + + bool parse_chunk_encoding_complete() const { + string_type body; + string_type crlf = "\r\n"; + + typename string_type::const_iterator begin = partial_parsed.begin(); + for (typename string_type::const_iterator iter = + std::search(begin, partial_parsed.end(), crlf.begin(), crlf.end()); + iter != partial_parsed.end(); + iter = + std::search(begin, partial_parsed.end(), crlf.begin(), crlf.end())) { + string_type line(begin, iter); + if (line.empty()) { + std::advance(iter, 2); + begin = iter; + continue; + } + std::stringstream stream(line); + int len; + stream >> std::hex >> len; + std::advance(iter, 2); + if (!len) return true; + if (len <= partial_parsed.end() - iter) { + std::advance(iter, len + 2); + } + begin = iter; + } + return false; + } + template void parse_body(Delegate& delegate_, Callback callback, size_t bytes) { // TODO(dberris): we should really not use a string for the partial body // buffer. - partial_parsed.append(part_begin, bytes); + partial_parsed.append(part_begin, part_begin + bytes); part_begin = part.begin(); - delegate_->read_some( - ::asio::mutable_buffers_1(part.data(), part.size()), callback); + if (check_parse_body_complete()) { + callback(boost::asio::error::eof, 0); + } else { + delegate_->read_some( + boost::asio::mutable_buffers_1(part.data(), part.size()), callback); + } } typedef response_parser response_parser_type; @@ -339,17 +401,20 @@ struct http_async_protocol_handler { typedef std::array::type, 1024> buffer_type; response_parser_type response_parser_; - std::promise version_promise; - std::promise status_promise; - std::promise status_message_promise; - std::promise::type> headers_promise; - std::promise source_promise; - std::promise destination_promise; - std::promise body_promise; + boost::promise version_promise; + boost::promise status_promise; + boost::promise status_message_promise; + boost::promise::type> headers_promise; + boost::promise source_promise; + boost::promise destination_promise; + boost::promise body_promise; buffer_type part; typename buffer_type::const_iterator part_begin; string_type partial_parsed; bool is_chunk_encoding; + bool is_chunk_end; + bool is_content_length; + long long content_length; }; } // namespace impl diff --git a/boost/network/protocol/http/client/connection/connection_delegate.hpp b/boost/network/protocol/http/client/connection/connection_delegate.hpp index c3a2f2acb..4e223864e 100644 --- a/boost/network/protocol/http/client/connection/connection_delegate.hpp +++ b/boost/network/protocol/http/client/connection/connection_delegate.hpp @@ -9,8 +9,8 @@ #include #include -#include -#include +#include +#include namespace boost { namespace network { @@ -18,15 +18,15 @@ namespace http { namespace impl { struct connection_delegate { - virtual void connect(::asio::ip::tcp::endpoint &endpoint, std::string host, + virtual void connect(boost::asio::ip::tcp::endpoint &endpoint, std::string host, std::uint16_t source_port, - std::function handler) = 0; + std::function handler) = 0; virtual void write( - ::asio::streambuf &command_streambuf, - std::function handler) = 0; + boost::asio::streambuf &command_streambuf, + std::function handler) = 0; virtual void read_some( - ::asio::mutable_buffers_1 const &read_buffer, - std::function handler) = 0; + boost::asio::mutable_buffers_1 const &read_buffer, + std::function handler) = 0; virtual void disconnect() = 0; virtual ~connection_delegate() = default; }; diff --git a/boost/network/protocol/http/client/connection/connection_delegate_factory.hpp b/boost/network/protocol/http/client/connection/connection_delegate_factory.hpp index f2b17e57e..fa419e1e6 100644 --- a/boost/network/protocol/http/client/connection/connection_delegate_factory.hpp +++ b/boost/network/protocol/http/client/connection/connection_delegate_factory.hpp @@ -34,7 +34,7 @@ struct connection_delegate_factory { // This is the factory method that actually returns the delegate instance. // TODO(dberris): Support passing in proxy settings when crafting connections. static connection_delegate_ptr new_connection_delegate( - ::asio::io_service& service, bool https, bool always_verify_peer, + boost::asio::io_service& service, bool https, bool always_verify_peer, optional certificate_filename, optional verify_path, optional certificate_file, optional private_key_file, optional ciphers, diff --git a/boost/network/protocol/http/client/connection/normal_delegate.hpp b/boost/network/protocol/http/client/connection/normal_delegate.hpp index daa711299..a4187f7fc 100644 --- a/boost/network/protocol/http/client/connection/normal_delegate.hpp +++ b/boost/network/protocol/http/client/connection/normal_delegate.hpp @@ -10,10 +10,10 @@ #include #include #include -#include -#include -#include -#include +#include +#include +#include +#include #include namespace boost { @@ -22,16 +22,16 @@ namespace http { namespace impl { struct normal_delegate : connection_delegate { - explicit normal_delegate(::asio::io_service &service); + explicit normal_delegate(boost::asio::io_service &service); - void connect(::asio::ip::tcp::endpoint &endpoint, std::string host, + void connect(boost::asio::ip::tcp::endpoint &endpoint, std::string host, std::uint16_t source_port, - std::function handler) override; - void write(::asio::streambuf &command_streambuf, - std::function handler) + std::function handler) override; + void write(boost::asio::streambuf &command_streambuf, + std::function handler) override; - void read_some(::asio::mutable_buffers_1 const &read_buffer, - std::function handler) + void read_some(boost::asio::mutable_buffers_1 const &read_buffer, + std::function handler) override; void disconnect() override; ~normal_delegate() override = default; @@ -40,8 +40,8 @@ struct normal_delegate : connection_delegate { normal_delegate &operator=(normal_delegate) = delete; private: - ::asio::io_service &service_; - std::unique_ptr<::asio::ip::tcp::socket> socket_; + boost::asio::io_service &service_; + std::unique_ptr socket_; }; } // namespace impl diff --git a/boost/network/protocol/http/client/connection/normal_delegate.ipp b/boost/network/protocol/http/client/connection/normal_delegate.ipp index 78f529263..552f50417 100644 --- a/boost/network/protocol/http/client/connection/normal_delegate.ipp +++ b/boost/network/protocol/http/client/connection/normal_delegate.ipp @@ -9,46 +9,46 @@ #include #include -#include -#include -#include -#include +#include +#include +#include +#include #include boost::network::http::impl::normal_delegate::normal_delegate( - ::asio::io_service &service) + boost::asio::io_service &service) : service_(service) {} void boost::network::http::impl::normal_delegate::connect( - ::asio::ip::tcp::endpoint &endpoint, std::string host, + boost::asio::ip::tcp::endpoint &endpoint, std::string host, std::uint16_t source_port, - std::function handler) { + std::function handler) { // TODO(dberris): review parameter necessity. (void)host; - socket_.reset(new ::asio::ip::tcp::socket( + socket_.reset(new boost::asio::ip::tcp::socket( service_, - ::asio::ip::tcp::endpoint(::asio::ip::address(), source_port))); + boost::asio::ip::tcp::endpoint(boost::asio::ip::address(), source_port))); socket_->async_connect(endpoint, handler); } void boost::network::http::impl::normal_delegate::write( - ::asio::streambuf &command_streambuf, - std::function handler) { - ::asio::async_write(*socket_, command_streambuf, handler); + boost::asio::streambuf &command_streambuf, + std::function handler) { + boost::asio::async_write(*socket_, command_streambuf, handler); } void boost::network::http::impl::normal_delegate::read_some( - ::asio::mutable_buffers_1 const &read_buffer, - std::function handler) { + boost::asio::mutable_buffers_1 const &read_buffer, + std::function handler) { socket_->async_read_some(read_buffer, handler); } void boost::network::http::impl::normal_delegate::disconnect() { if (socket_.get() && socket_->is_open()) { - std::error_code ignored; - socket_->shutdown(::asio::ip::tcp::socket::shutdown_both, ignored); + boost::system::error_code ignored; + socket_->shutdown(boost::asio::ip::tcp::socket::shutdown_both, ignored); if (!ignored) { socket_->close(ignored); } diff --git a/boost/network/protocol/http/client/connection/ssl_delegate.hpp b/boost/network/protocol/http/client/connection/ssl_delegate.hpp index d6fcee3fe..63adc1818 100644 --- a/boost/network/protocol/http/client/connection/ssl_delegate.hpp +++ b/boost/network/protocol/http/client/connection/ssl_delegate.hpp @@ -10,8 +10,8 @@ #include #include #include -#include -#include +#include +#include #include #include #include @@ -24,7 +24,7 @@ namespace impl { struct ssl_delegate : public connection_delegate, public std::enable_shared_from_this { - ssl_delegate(::asio::io_service &service, bool always_verify_peer, + ssl_delegate(boost::asio::io_service &service, bool always_verify_peer, optional certificate_filename, optional verify_path, optional certificate_file, @@ -32,20 +32,20 @@ struct ssl_delegate : public connection_delegate, optional ciphers, optional sni_hostname, long ssl_options); - void connect(::asio::ip::tcp::endpoint &endpoint, std::string host, + void connect(boost::asio::ip::tcp::endpoint &endpoint, std::string host, std::uint16_t source_port, - std::function handler) override; + std::function handler) override; void write( - ::asio::streambuf &command_streambuf, - std::function handler) override; + boost::asio::streambuf &command_streambuf, + std::function handler) override; void read_some( - ::asio::mutable_buffers_1 const &read_buffer, - std::function handler) override; + boost::asio::mutable_buffers_1 const &read_buffer, + std::function handler) override; void disconnect() override; ~ssl_delegate() override; private: - ::asio::io_service &service_; + boost::asio::io_service &service_; optional certificate_filename_; optional verify_path_; optional certificate_file_; @@ -53,16 +53,16 @@ struct ssl_delegate : public connection_delegate, optional ciphers_; optional sni_hostname_; long ssl_options_; - std::unique_ptr<::asio::ssl::context> context_; - std::unique_ptr<::asio::ip::tcp::socket> tcp_socket_; - std::unique_ptr<::asio::ssl::stream<::asio::ip::tcp::socket &> > socket_; + std::unique_ptr context_; + std::unique_ptr tcp_socket_; + std::unique_ptr > socket_; bool always_verify_peer_; ssl_delegate(ssl_delegate const &); // = delete ssl_delegate &operator=(ssl_delegate); // = delete - void handle_connected(std::error_code const &ec, - std::function handler); + void handle_connected(boost::system::error_code const &ec, + std::function handler); }; } // namespace impl diff --git a/boost/network/protocol/http/client/connection/ssl_delegate.ipp b/boost/network/protocol/http/client/connection/ssl_delegate.ipp index f3b179d01..e9d955b40 100644 --- a/boost/network/protocol/http/client/connection/ssl_delegate.ipp +++ b/boost/network/protocol/http/client/connection/ssl_delegate.ipp @@ -9,11 +9,11 @@ #include #include -#include +#include #include boost::network::http::impl::ssl_delegate::ssl_delegate( - ::asio::io_service &service, bool always_verify_peer, + boost::asio::io_service &service, bool always_verify_peer, optional certificate_filename, optional verify_path, optional certificate_file, optional private_key_file, optional ciphers, @@ -29,11 +29,11 @@ boost::network::http::impl::ssl_delegate::ssl_delegate( always_verify_peer_(always_verify_peer) {} void boost::network::http::impl::ssl_delegate::connect( - ::asio::ip::tcp::endpoint &endpoint, std::string host, + boost::asio::ip::tcp::endpoint &endpoint, std::string host, std::uint16_t source_port, - std::function handler) { + std::function handler) { context_.reset( - new ::asio::ssl::context(::asio::ssl::context::method::sslv23_client)); + new boost::asio::ssl::context(boost::asio::ssl::context::method::sslv23_client)); if (ciphers_) { ::SSL_CTX_set_cipher_list(context_->native_handle(), ciphers_->c_str()); } @@ -41,69 +41,69 @@ void boost::network::http::impl::ssl_delegate::connect( context_->set_options(ssl_options_); } else { // By default, disable v3 support. - context_->set_options(::asio::ssl::context::no_sslv3); + context_->set_options(boost::asio::ssl::context::no_sslv3); } if (certificate_filename_ || verify_path_) { - context_->set_verify_mode(::asio::ssl::context::verify_peer); + context_->set_verify_mode(boost::asio::ssl::context::verify_peer); if (certificate_filename_) context_->load_verify_file(*certificate_filename_); if (verify_path_) context_->add_verify_path(*verify_path_); } else { if (always_verify_peer_) { - context_->set_verify_mode(::asio::ssl::context::verify_peer); + context_->set_verify_mode(boost::asio::ssl::context::verify_peer); // use openssl default verify paths. uses openssl environment variables // SSL_CERT_DIR, SSL_CERT_FILE context_->set_default_verify_paths(); } else { - context_->set_verify_mode(::asio::ssl::context::verify_none); + context_->set_verify_mode(boost::asio::ssl::context::verify_none); } } if (certificate_file_) - context_->use_certificate_file(*certificate_file_, ::asio::ssl::context::pem); + context_->use_certificate_file(*certificate_file_, boost::asio::ssl::context::pem); if (private_key_file_) - context_->use_private_key_file(*private_key_file_, ::asio::ssl::context::pem); + context_->use_private_key_file(*private_key_file_, boost::asio::ssl::context::pem); - tcp_socket_.reset(new ::asio::ip::tcp::socket( - service_, ::asio::ip::tcp::endpoint(::asio::ip::tcp::v4(), source_port))); - socket_.reset(new ::asio::ssl::stream<::asio::ip::tcp::socket &>( + tcp_socket_.reset(new boost::asio::ip::tcp::socket( + service_, boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), source_port))); + socket_.reset(new boost::asio::ssl::stream( *(tcp_socket_.get()), *context_)); if (sni_hostname_) SSL_set_tlsext_host_name(socket_->native_handle(), sni_hostname_->c_str()); if (always_verify_peer_) - socket_->set_verify_callback(::asio::ssl::rfc2818_verification(host)); + socket_->set_verify_callback(boost::asio::ssl::rfc2818_verification(host)); auto self = this->shared_from_this(); socket_->lowest_layer().async_connect( endpoint, - [=](std::error_code const &ec) { self->handle_connected(ec, handler); }); + [=](boost::system::error_code const &ec) { self->handle_connected(ec, handler); }); } void boost::network::http::impl::ssl_delegate::handle_connected( - std::error_code const &ec, - std::function handler) { + boost::system::error_code const &ec, + std::function handler) { if (!ec) { - socket_->async_handshake(::asio::ssl::stream_base::client, handler); + socket_->async_handshake(boost::asio::ssl::stream_base::client, handler); } else { handler(ec); } } void boost::network::http::impl::ssl_delegate::write( - ::asio::streambuf &command_streambuf, - std::function handler) { - ::asio::async_write(*socket_, command_streambuf, handler); + boost::asio::streambuf &command_streambuf, + std::function handler) { + boost::asio::async_write(*socket_, command_streambuf, handler); } void boost::network::http::impl::ssl_delegate::read_some( - ::asio::mutable_buffers_1 const &read_buffer, - std::function handler) { + boost::asio::mutable_buffers_1 const &read_buffer, + std::function handler) { socket_->async_read_some(read_buffer, handler); } void boost::network::http::impl::ssl_delegate::disconnect() { if (socket_.get() && socket_->lowest_layer().is_open()) { - std::error_code ignored; - socket_->lowest_layer().shutdown(::asio::ip::tcp::socket::shutdown_both, + boost::system::error_code ignored; + socket_->lowest_layer().shutdown(boost::asio::ip::tcp::socket::shutdown_both, ignored); if (!ignored) { socket_->lowest_layer().close(ignored); diff --git a/boost/network/protocol/http/client/connection/sync_base.hpp b/boost/network/protocol/http/client/connection/sync_base.hpp index 4cf9abeba..efe488c11 100644 --- a/boost/network/protocol/http/client/connection/sync_base.hpp +++ b/boost/network/protocol/http/client/connection/sync_base.hpp @@ -8,10 +8,10 @@ // http://www.boost.org/LICENSE_1_0.txt) #include -#include -#include -#include -#include +#include +#include +#include +#include #include #include #include @@ -41,8 +41,8 @@ struct sync_connection_base_impl { void init_socket(Socket& socket_, resolver_type& resolver_, string_type /*unused*/ const& hostname, string_type const& port, resolver_function_type resolve_) { - using ::asio::ip::tcp; - std::error_code error = ::asio::error::host_not_found; + using boost::asio::ip::tcp; + boost::system::error_code error = boost::asio::error::host_not_found; typename resolver_type::iterator endpoint_iterator, end; boost::tie(endpoint_iterator, end) = resolve_(resolver_, hostname, port); while (error && endpoint_iterator != end) { @@ -53,13 +53,13 @@ struct sync_connection_base_impl { ++endpoint_iterator; } - if (error) throw std::system_error(error); + if (error) throw boost::system::system_error(error); } template void read_status(Socket& socket_, basic_response& response_, - ::asio::streambuf& response_buffer) { - ::asio::read_until(socket_, response_buffer, "\r\n"); + boost::asio::streambuf& response_buffer) { + boost::asio::read_until(socket_, response_buffer, "\r\n"); std::istream response_stream(&response_buffer); string_type http_version; unsigned int status_code; @@ -78,8 +78,8 @@ struct sync_connection_base_impl { template void read_headers(Socket& socket_, basic_response& response_, - ::asio::streambuf& response_buffer) { - ::asio::read_until(socket_, response_buffer, "\r\n\r\n"); + boost::asio::streambuf& response_buffer) { + boost::asio::read_until(socket_, response_buffer, "\r\n\r\n"); std::istream response_stream(&response_buffer); string_type header_line, name; while (std::getline(response_stream, header_line) && header_line != "\r") { @@ -101,7 +101,7 @@ struct sync_connection_base_impl { template void send_request_impl(Socket& socket_, string_type /*unused*/ const& method, - ::asio::streambuf& request_buffer) { + boost::asio::streambuf& request_buffer) { // TODO(dberris): review parameter necessity. (void)method; @@ -110,15 +110,15 @@ struct sync_connection_base_impl { template void read_body_normal(Socket& socket_, basic_response& response_, - ::asio::streambuf& response_buffer, + boost::asio::streambuf& response_buffer, typename ostringstream::type& body_stream) { // TODO(dberris): review parameter necessity. (void)response_; - std::error_code error; + boost::system::error_code error; if (response_buffer.size() > 0) body_stream << &response_buffer; - while (::asio::read(socket_, response_buffer, ::asio::transfer_at_least(1), + while (boost::asio::read(socket_, response_buffer, boost::asio::transfer_at_least(1), error)) { body_stream << &response_buffer; } @@ -127,9 +127,9 @@ struct sync_connection_base_impl { template void read_body_transfer_chunk_encoding( Socket& socket_, basic_response& response_, - ::asio::streambuf& response_buffer, + boost::asio::streambuf& response_buffer, typename ostringstream::type& body_stream) { - std::error_code error; + boost::system::error_code error; // look for the content-length header typename headers_range >::type content_length_range = headers(response_)["Content-Length"]; @@ -146,8 +146,8 @@ struct sync_connection_base_impl { do { std::size_t chunk_size_line = read_until(socket_, response_buffer, "\r\n", error); - if ((chunk_size_line == 0) && (error != ::asio::error::eof)) - throw std::system_error(error); + if ((chunk_size_line == 0) && (error != boost::asio::error::eof)) + throw boost::system::system_error(error); std::size_t chunk_size = 0; string_type data; { @@ -159,8 +159,8 @@ struct sync_connection_base_impl { if (chunk_size == 0) { stopping = true; if (!read_until(socket_, response_buffer, "\r\n", error) && - (error != ::asio::error::eof)) - throw std::system_error(error); + (error != boost::asio::error::eof)) + throw boost::system::system_error(error); } else { bool stopping_inner = false; do { @@ -169,9 +169,9 @@ struct sync_connection_base_impl { (chunk_size + 2) - response_buffer.size(); std::size_t chunk_bytes_read = read(socket_, response_buffer, - ::asio::transfer_at_least(bytes_to_read), error); + boost::asio::transfer_at_least(bytes_to_read), error); if (chunk_bytes_read == 0) { - if (error != ::asio::error::eof) throw std::system_error(error); + if (error != boost::asio::error::eof) throw boost::system::system_error(error); stopping_inner = true; } } @@ -200,8 +200,8 @@ struct sync_connection_base_impl { return; } size_t bytes_read = 0; - while ((bytes_read = ::asio::read(socket_, response_buffer, - ::asio::transfer_at_least(1), error))) { + while ((bytes_read = boost::asio::read(socket_, response_buffer, + boost::asio::transfer_at_least(1), error))) { body_stream << &response_buffer; length -= bytes_read; if ((length <= 0) || error) break; @@ -211,7 +211,7 @@ struct sync_connection_base_impl { template void read_body(Socket& socket_, basic_response& response_, - ::asio::streambuf& response_buffer) { + boost::asio::streambuf& response_buffer) { typename ostringstream::type body_stream; // TODO(dberris): tag dispatch based on whether it's HTTP 1.0 or HTTP 1.1 if (version_major == 1 && version_minor == 0) { @@ -282,11 +282,11 @@ struct sync_connection_base { basic_request const& request_, body_generator_function_type generator) = 0; virtual void read_status(basic_response& response_, - ::asio::streambuf& response_buffer) = 0; + boost::asio::streambuf& response_buffer) = 0; virtual void read_headers(basic_response& response_, - ::asio::streambuf& response_buffer) = 0; + boost::asio::streambuf& response_buffer) = 0; virtual void read_body(basic_response& response_, - ::asio::streambuf& response_buffer) = 0; + boost::asio::streambuf& response_buffer) = 0; virtual bool is_open() = 0; virtual void close_socket() = 0; virtual ~sync_connection_base() = default; diff --git a/boost/network/protocol/http/client/connection/sync_normal.hpp b/boost/network/protocol/http/client/connection/sync_normal.hpp index 899976234..c5909e131 100644 --- a/boost/network/protocol/http/client/connection/sync_normal.hpp +++ b/boost/network/protocol/http/client/connection/sync_normal.hpp @@ -10,8 +10,8 @@ #include #include -#include -#include +#include +#include #include #include #include @@ -61,7 +61,7 @@ struct http_sync_connection void send_request_impl(string_type const& method, basic_request const& request_, body_generator_function_type generator) { - ::asio::streambuf request_buffer; + boost::asio::streambuf request_buffer; linearize( request_, method, version_major, version_minor, std::ostreambuf_iterator::type>(&request_buffer)); @@ -77,26 +77,32 @@ struct http_sync_connection } } if (timeout_ > 0) { +#if defined(BOOST_ASIO_HAS_STD_CHRONO) timer_.expires_from_now(std::chrono::seconds(timeout_)); +#elif defined(BOOST_ASIO_HAS_BOOST_CHRONO) + timer_.expires_from_now(boost::chrono::seconds(timeout_)); +#else +#error Need a chrono implementation +#endif auto self = this->shared_from_this(); - timer_.async_wait([=] (std::error_code const &ec) { + timer_.async_wait([=] (boost::system::error_code const &ec) { self->handle_timeout(ec); }); } } void read_status(basic_response& response_, - ::asio::streambuf& response_buffer) { + boost::asio::streambuf& response_buffer) { connection_base::read_status(socket_, response_, response_buffer); } void read_headers(basic_response& response, - ::asio::streambuf& response_buffer) { + boost::asio::streambuf& response_buffer) { connection_base::read_headers(socket_, response, response_buffer); } void read_body(basic_response& response_, - ::asio::streambuf& response_buffer) { + boost::asio::streambuf& response_buffer) { connection_base::read_body(socket_, response_, response_buffer); typename headers_range >::type connection_range = headers(response_)["Connection"]; @@ -116,8 +122,8 @@ struct http_sync_connection if (!is_open()) { return; } - std::error_code ignored; - socket_.shutdown(::asio::ip::tcp::socket::shutdown_both, ignored); + boost::system::error_code ignored; + socket_.shutdown(boost::asio::ip::tcp::socket::shutdown_both, ignored); if (ignored) { return; } @@ -125,17 +131,17 @@ struct http_sync_connection } private: - void handle_timeout(std::error_code const& ec) { + void handle_timeout(boost::system::error_code const& ec) { if (!ec) { close_socket(); } } int timeout_; - ::asio::steady_timer timer_; + boost::asio::steady_timer timer_; resolver_type& resolver_; resolver_function_type resolve_; - ::asio::ip::tcp::socket socket_; + boost::asio::ip::tcp::socket socket_; }; } // namespace impl diff --git a/boost/network/protocol/http/client/connection/sync_ssl.hpp b/boost/network/protocol/http/client/connection/sync_ssl.hpp index 18fa379b5..c7d5ac72e 100644 --- a/boost/network/protocol/http/client/connection/sync_ssl.hpp +++ b/boost/network/protocol/http/client/connection/sync_ssl.hpp @@ -9,10 +9,10 @@ // http://www.boost.org/LICENSE_1_0.txt) #include -#include -#include -#include -#include +#include +#include +#include +#include #include #include #include @@ -63,7 +63,7 @@ struct https_sync_connection timer_(resolver.get_io_service()), resolver_(resolver), resolve_(std::move(resolve)), - context_(resolver.get_io_service(), ::asio::ssl::context::sslv23_client), + context_(resolver.get_io_service(), boost::asio::ssl::context::sslv23_client), socket_(resolver.get_io_service(), context_) { if (ciphers) { ::SSL_CTX_set_cipher_list(context_.native_handle(), ciphers->c_str()); @@ -72,7 +72,7 @@ struct https_sync_connection context_.set_options(ssl_options); } if (certificate_filename || verify_path) { - context_.set_verify_mode(::asio::ssl::context::verify_peer); + context_.set_verify_mode(boost::asio::ssl::context::verify_peer); // FIXME make the certificate filename and verify path parameters // be // optional ranges @@ -81,14 +81,14 @@ struct https_sync_connection if (verify_path) context_.add_verify_path(*verify_path); } else { if (always_verify_peer) - context_.set_verify_mode(::asio::ssl::context_base::verify_peer); + context_.set_verify_mode(boost::asio::ssl::context_base::verify_peer); else - context_.set_verify_mode(::asio::ssl::context_base::verify_none); + context_.set_verify_mode(boost::asio::ssl::context_base::verify_none); } if (certificate_file) - context_.use_certificate_file(*certificate_file, ::asio::ssl::context::pem); + context_.use_certificate_file(*certificate_file, boost::asio::ssl::context::pem); if (private_key_file) - context_.use_private_key_file(*private_key_file, ::asio::ssl::context::pem); + context_.use_private_key_file(*private_key_file, boost::asio::ssl::context::pem); if (sni_hostname) SSL_set_tlsext_host_name(socket_.native_handle(), sni_hostname->c_str()); } @@ -97,13 +97,13 @@ struct https_sync_connection string_type const& port) { connection_base::init_socket(socket_.lowest_layer(), resolver_, hostname, port, resolve_); - socket_.handshake(::asio::ssl::stream_base::client); + socket_.handshake(boost::asio::ssl::stream_base::client); } void send_request_impl(string_type /*unused*/ const& method, basic_request const& request_, body_generator_function_type generator) { - ::asio::streambuf request_buffer; + boost::asio::streambuf request_buffer; linearize( request_, method, version_major, version_minor, std::ostreambuf_iterator::type>(&request_buffer)); @@ -119,25 +119,31 @@ struct https_sync_connection } } if (timeout_ > 0) { +#if defined(BOOST_ASIO_HAS_STD_CHRONO) timer_.expires_from_now(std::chrono::seconds(timeout_)); +#elif defined(BOOST_ASIO_HAS_BOOST_CHRONO) + timer_.expires_from_now(boost::chrono::seconds(timeout_)); +#else +#error Need a chrono implementation +#endif auto self = this->shared_from_this(); timer_.async_wait( - [=](std::error_code const& ec) { self->handle_timeout(ec); }); + [=](boost::system::error_code const& ec) { self->handle_timeout(ec); }); } } void read_status(basic_response& response_, - ::asio::streambuf& response_buffer) { + boost::asio::streambuf& response_buffer) { connection_base::read_status(socket_, response_, response_buffer); } void read_headers(basic_response& response_, - ::asio::streambuf& response_buffer) { + boost::asio::streambuf& response_buffer) { connection_base::read_headers(socket_, response_, response_buffer); } void read_body(basic_response& response_, - ::asio::streambuf& response_buffer) { + boost::asio::streambuf& response_buffer) { connection_base::read_body(socket_, response_, response_buffer); typename headers_range >::type connection_range = headers(response_)["Connection"]; @@ -154,8 +160,8 @@ struct https_sync_connection void close_socket() { timer_.cancel(); - std::error_code ignored; - socket_.lowest_layer().shutdown(::asio::ip::tcp::socket::shutdown_both, + boost::system::error_code ignored; + socket_.lowest_layer().shutdown(boost::asio::ip::tcp::socket::shutdown_both, ignored); if (ignored) { return; @@ -166,18 +172,18 @@ struct https_sync_connection ~https_sync_connection() { close_socket(); } private: - void handle_timeout(std::error_code const& ec) { + void handle_timeout(boost::system::error_code const& ec) { if (!ec) { close_socket(); } } int timeout_; - ::asio::steady_timer timer_; + boost::asio::steady_timer timer_; resolver_type& resolver_; resolver_function_type resolve_; - ::asio::ssl::context context_; - ::asio::ssl::stream<::asio::ip::tcp::socket> socket_; + boost::asio::ssl::context context_; + boost::asio::ssl::stream socket_; }; } // namespace impl diff --git a/boost/network/protocol/http/client/facade.hpp b/boost/network/protocol/http/client/facade.hpp index 985344a63..07ddbd8af 100644 --- a/boost/network/protocol/http/client/facade.hpp +++ b/boost/network/protocol/http/client/facade.hpp @@ -39,8 +39,8 @@ class basic_client_facade { * body as it comes in. In case of errors, the second argument is an error * code. */ - typedef std::function const&, - std::error_code const&)> + typedef std::function::type, 1024>::const_iterator> const&, + boost::system::error_code const&)> body_callback_function_type; /** @@ -122,7 +122,7 @@ class basic_client_facade { } else { if (boost::empty(content_type_headers)) { typedef typename char_::type char_type; - static char_type content_type[] = "x-application/octet-stream"; + static char_type* content_type = "x-application/octet-stream"; request << header("Content-Type", content_type); } } @@ -227,7 +227,7 @@ class basic_client_facade { } else { if (boost::empty(content_type_headers)) { typedef typename char_::type char_type; - static char_type content_type[] = "x-application/octet-stream"; + static char_type* content_type = "x-application/octet-stream"; request << header("Content-Type", content_type); } } @@ -303,7 +303,8 @@ class basic_client_facade { options.openssl_verify_path(), options.openssl_certificate_file(), options.openssl_private_key_file(), options.openssl_ciphers(), options.openssl_sni_hostname(), options.openssl_options(), - options.io_service(), options.timeout())); + options.io_service(), options.timeout(), + options.remove_chunk_markers())); } }; diff --git a/boost/network/protocol/http/client/macros.hpp b/boost/network/protocol/http/client/macros.hpp index 81135f548..6a46ac2a1 100644 --- a/boost/network/protocol/http/client/macros.hpp +++ b/boost/network/protocol/http/client/macros.hpp @@ -6,14 +6,16 @@ // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) +#include #include +#include #include #ifndef BOOST_NETWORK_HTTP_BODY_CALLBACK #define BOOST_NETWORK_HTTP_BODY_CALLBACK(function_name, range_name, \ error_name) \ - void function_name(boost::iterator_range const& (range_name), \ - std::error_code const& (error_name)) + void function_name(boost::iterator_range::const_iterator> const& (range_name), \ + boost::system::error_code const& (error_name)) #endif #endif /* BOOST_NETWORK_PROTOCOL_HTTP_CLIENT_MACROS_HPP_20110430 */ diff --git a/boost/network/protocol/http/client/options.hpp b/boost/network/protocol/http/client/options.hpp index d91e9fe5a..bcc266789 100644 --- a/boost/network/protocol/http/client/options.hpp +++ b/boost/network/protocol/http/client/options.hpp @@ -8,7 +8,7 @@ // http://www.boost.org/LICENSE_1_0.txt) #include -#include +#include #include #include @@ -34,7 +34,8 @@ class client_options { openssl_options_(0), io_service_(), always_verify_peer_(true), - timeout_(0) {} + timeout_(0), + remove_chunk_markers_(true) {} client_options(client_options const& other) : cache_resolved_(other.cache_resolved_), @@ -48,7 +49,8 @@ class client_options { openssl_options_(other.openssl_options_), io_service_(other.io_service_), always_verify_peer_(other.always_verify_peer_), - timeout_(other.timeout_) {} + timeout_(other.timeout_), + remove_chunk_markers_(other.remove_chunk_markers_) {} client_options& operator=(client_options other) { other.swap(*this); @@ -69,6 +71,7 @@ class client_options { swap(io_service_, other.io_service_); swap(always_verify_peer_, other.always_verify_peer_); swap(timeout_, other.timeout_); + swap(remove_chunk_markers_, other.remove_chunk_markers_); } /// Specify whether the client should cache resolved endpoints. @@ -133,8 +136,8 @@ class client_options { return *this; } - /// Provide an `::asio::io_service` hosted in a shared pointer. - client_options& io_service(std::shared_ptr<::asio::io_service> v) { + /// Provide an `boost::asio::io_service` hosted in a shared pointer. + client_options& io_service(std::shared_ptr v) { io_service_ = v; return *this; } @@ -154,6 +157,12 @@ class client_options { return *this; } + /// Set whether we process chunked-encoded streams. + client_options& remove_chunk_markers(bool v) { + remove_chunk_markers_ = v; + return *this; + } + bool cache_resolved() const { return cache_resolved_; } bool follow_redirects() const { return follow_redirects_; } @@ -184,12 +193,14 @@ class client_options { long openssl_options() const { return openssl_options_; } - std::shared_ptr<::asio::io_service> io_service() const { return io_service_; } + std::shared_ptr io_service() const { return io_service_; } bool always_verify_peer() const { return always_verify_peer_; } int timeout() const { return timeout_; } + bool remove_chunk_markers() const { return remove_chunk_markers_; } + private: bool cache_resolved_; bool follow_redirects_; @@ -200,9 +211,10 @@ class client_options { boost::optional openssl_ciphers_; boost::optional openssl_sni_hostname_; long openssl_options_; - std::shared_ptr<::asio::io_service> io_service_; + std::shared_ptr io_service_; bool always_verify_peer_; int timeout_; + bool remove_chunk_markers_; }; template diff --git a/boost/network/protocol/http/client/pimpl.hpp b/boost/network/protocol/http/client/pimpl.hpp index 33dc5ae92..01c77ca70 100644 --- a/boost/network/protocol/http/client/pimpl.hpp +++ b/boost/network/protocol/http/client/pimpl.hpp @@ -7,7 +7,7 @@ // http://www.boost.org/LICENSE_1_0.txt) #include -#include +#include #include #include #include @@ -74,10 +74,12 @@ struct basic_client_impl optional const& private_key_file, optional const& ciphers, optional const& sni_hostname, long ssl_options, - std::shared_ptr<::asio::io_service> service, int timeout) - : base_type(cache_resolved, follow_redirect, always_verify_peer, timeout, - service, certificate_filename, verify_path, certificate_file, - private_key_file, ciphers, sni_hostname, ssl_options) {} + std::shared_ptr service, int timeout, + bool remove_chunk_markers) + : base_type(cache_resolved, follow_redirect, always_verify_peer, timeout, + remove_chunk_markers, service, certificate_filename, verify_path, + certificate_file, private_key_file, ciphers, sni_hostname, + ssl_options) {} ~basic_client_impl() = default; }; diff --git a/boost/network/protocol/http/client/sync_impl.hpp b/boost/network/protocol/http/client/sync_impl.hpp index f902b73a9..354dfd3eb 100644 --- a/boost/network/protocol/http/client/sync_impl.hpp +++ b/boost/network/protocol/http/client/sync_impl.hpp @@ -32,13 +32,13 @@ struct sync_client connection_base; typedef typename resolver::type resolver_type; typedef std::function const&, - std::error_code const&)> + boost::system::error_code const&)> body_callback_function_type; typedef std::function body_generator_function_type; friend struct basic_client_impl; - std::shared_ptr<::asio::io_service> service_ptr; - ::asio::io_service& service_; + std::shared_ptr service_ptr; + boost::asio::io_service& service_; resolver_type resolver_; optional certificate_filename_; optional verify_path_; @@ -51,7 +51,7 @@ struct sync_client sync_client( bool cache_resolved, bool follow_redirect, bool always_verify_peer, - int timeout, std::shared_ptr<::asio::io_service> service, + int timeout, std::shared_ptr service, optional certificate_filename = optional(), optional verify_path = optional(), optional certificate_file = optional(), @@ -61,7 +61,7 @@ struct sync_client long ssl_options = 0) : connection_base(cache_resolved, follow_redirect, timeout), service_ptr(service.get() ? service - : std::make_shared<::asio::io_service>()), + : std::make_shared()), service_(*service_ptr), resolver_(service_), certificate_filename_(std::move(certificate_filename)), diff --git a/boost/network/protocol/http/impl/response.ipp b/boost/network/protocol/http/impl/response.ipp index 18039e6a7..a685a2169 100644 --- a/boost/network/protocol/http/impl/response.ipp +++ b/boost/network/protocol/http/impl/response.ipp @@ -16,7 +16,7 @@ #ifndef BOOST_NETWORK_PROTOCOL_HTTP_IMPL_RESPONSE_RESPONSE_IPP #define BOOST_NETWORK_PROTOCOL_HTTP_IMPL_RESPONSE_RESPONSE_IPP -#include +#include #include #include #include @@ -100,9 +100,9 @@ struct basic_response { /// underlying memory blocks, therefore the reply object must remain /// valid and /// not be changed until the write operation has completed. - std::vector<::asio::const_buffer> to_buffers() { - using ::asio::const_buffer; - using ::asio::buffer; + std::vector to_buffers() { + using boost::asio::const_buffer; + using boost::asio::buffer; static const char name_value_separator[] = {':', ' '}; static const char crlf[] = {'\r', '\n'}; std::vector buffers; @@ -408,13 +408,13 @@ struct basic_response { } } - ::asio::const_buffer trim_null(::asio::const_buffer buffer) { - std::size_t size = ::asio::buffer_size(buffer); - return ::asio::buffer(buffer, size - 1); + boost::asio::const_buffer trim_null(boost::asio::const_buffer buffer) { + std::size_t size = boost::asio::buffer_size(buffer); + return boost::asio::buffer(buffer, size - 1); } - ::asio::const_buffer to_buffer(status_type status) { - using ::asio::buffer; + boost::asio::const_buffer to_buffer(status_type status) { + using boost::asio::buffer; switch (status) { // 2xx Success case basic_response::ok: diff --git a/boost/network/protocol/http/message/async_message.hpp b/boost/network/protocol/http/message/async_message.hpp index bca9148b2..747a962ed 100644 --- a/boost/network/protocol/http/message/async_message.hpp +++ b/boost/network/protocol/http/message/async_message.hpp @@ -9,13 +9,13 @@ // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) -#include -#include #include +#include // FIXME move this out to a trait -#include #include +#include +#include namespace boost { namespace network { @@ -26,12 +26,11 @@ namespace impl { template struct ready_wrapper; -} // namespace impl - /* impl */ +} // namespace impl + /* impl */ template struct async_message { - typedef typename string::type string_type; typedef typename headers_container::type headers_container_type; typedef typename headers_container_type::value_type header_type; @@ -54,65 +53,97 @@ struct async_message { headers_(other.headers_), body_(other.body_) {} - string_type const status_message() const { return status_message_.get(); } + string_type status_message() const { + status_message_.wait(); + if (status_message_.has_exception()) + boost::rethrow_exception(status_message_.get_exception_ptr()); + return status_message_.get(); + } - void status_message(std::shared_future const& future) const { + void status_message(boost::shared_future const& future) const { status_message_ = future; } - string_type const version() const { return version_.get(); } + string_type version() const { + version_.wait(); + if (version_.has_exception()) + boost::rethrow_exception(version_.get_exception_ptr()); + return version_.get(); + } - void version(std::shared_future const& future) const { + void version(boost::shared_future const& future) const { version_ = future; } - std::uint16_t status() const { return status_.get(); } + std::uint16_t status() const { + status_.wait(); + if (status_.has_exception()) + boost::rethrow_exception(status_.get_exception_ptr()); + return status_.get(); + } - void status(std::shared_future const& future) const { + void status(boost::shared_future const& future) const { status_ = future; } - string_type const source() const { return source_.get(); } + string_type source() const { + source_.wait(); + if (source_.has_exception()) + boost::rethrow_exception(source_.get_exception_ptr()); + return source_.get(); + } - void source(std::shared_future const& future) const { + void source(boost::shared_future const& future) const { source_ = future; } - string_type const destination() const { return destination_.get(); } + string_type destination() const { + destination_.wait(); + if (destination_.has_exception()) + boost::rethrow_exception(source_.get_exception_ptr()); + return destination_.get(); + } - void destination(std::shared_future const& future) const { + void destination(boost::shared_future const& future) const { destination_ = future; } headers_container_type const& headers() const { if (retrieved_headers_) return *retrieved_headers_; + if (headers_.has_exception()) + boost::rethrow_exception(headers_.get_exception_ptr()); headers_container_type raw_headers = headers_.get(); raw_headers.insert(added_headers.begin(), added_headers.end()); - for (string_type const & key : removed_headers) { + for (string_type const& key : removed_headers) { raw_headers.erase(key); } retrieved_headers_ = raw_headers; return *retrieved_headers_; } - void headers(std::shared_future const& future) - const { + void headers( + boost::shared_future const& future) const { headers_ = future; } - void add_header(typename headers_container_type::value_type const& pair_) - const { + void add_header( + typename headers_container_type::value_type const& pair_) const { added_headers.insert(added_headers.end(), pair_); } - void remove_header(typename headers_container_type::key_type const& key_) - const { + void remove_header( + typename headers_container_type::key_type const& key_) const { removed_headers.insert(key_); } - string_type const body() const { return body_.get(); } + string_type body() const { + body_.wait(); + if (body_.has_exception()) + boost::rethrow_exception(body_.get_exception_ptr()); + return body_.get(); + } - void body(std::shared_future const& future) const { + void body(boost::shared_future const& future) const { body_ = future; } @@ -132,13 +163,13 @@ struct async_message { } private: - mutable std::shared_future status_message_, version_, source_, + mutable boost::shared_future status_message_, version_, source_, destination_; - mutable std::shared_future status_; - mutable std::shared_future headers_; + mutable boost::shared_future status_; + mutable boost::shared_future headers_; mutable headers_container_type added_headers; mutable std::set removed_headers; - mutable std::shared_future body_; + mutable boost::shared_future body_; mutable boost::optional retrieved_headers_; friend struct boost::network::http::impl::ready_wrapper; diff --git a/boost/network/protocol/http/message/directives/status.hpp b/boost/network/protocol/http/message/directives/status.hpp index 010ad2f2a..f64cb94d3 100644 --- a/boost/network/protocol/http/message/directives/status.hpp +++ b/boost/network/protocol/http/message/directives/status.hpp @@ -7,11 +7,11 @@ // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) -#include #include #include #include #include +#include #include #include #include @@ -25,18 +25,18 @@ struct basic_response; struct status_directive { - boost::variant > + boost::variant > status_; explicit status_directive(std::uint16_t status) : status_(status) {} - explicit status_directive(std::shared_future const &status) + explicit status_directive(boost::shared_future const &status) : status_(status) {} status_directive(status_directive const &other) : status_(other.status_) {} template - struct value : mpl::if_, std::shared_future, + struct value : mpl::if_, boost::shared_future, std::uint16_t> {}; template diff --git a/boost/network/protocol/http/message/traits/status.hpp b/boost/network/protocol/http/message/traits/status.hpp index ce1b551a8..92c6c3d6c 100644 --- a/boost/network/protocol/http/message/traits/status.hpp +++ b/boost/network/protocol/http/message/traits/status.hpp @@ -9,6 +9,7 @@ #include #include #include +#include namespace boost { namespace network { @@ -23,7 +24,7 @@ template struct status : mpl::if_< is_async, - std::shared_future, + boost::shared_future, typename mpl::if_, std::uint16_t, unsupported_tag >::type> {}; diff --git a/boost/network/protocol/http/message/traits/status_message.hpp b/boost/network/protocol/http/message/traits/status_message.hpp index 544d55b3f..61b89ec02 100644 --- a/boost/network/protocol/http/message/traits/status_message.hpp +++ b/boost/network/protocol/http/message/traits/status_message.hpp @@ -6,11 +6,11 @@ // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) -#include #include #include #include #include +#include namespace boost { namespace network { @@ -25,7 +25,7 @@ template struct status_message : mpl::if_< is_async, - std::shared_future::type>, + boost::shared_future::type>, typename mpl::if_< mpl::or_, is_same, diff --git a/boost/network/protocol/http/message/traits/version.hpp b/boost/network/protocol/http/message/traits/version.hpp index 103483fcc..3fbcc7348 100644 --- a/boost/network/protocol/http/message/traits/version.hpp +++ b/boost/network/protocol/http/message/traits/version.hpp @@ -6,12 +6,12 @@ // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) -#include #include #include #include #include #include +#include namespace boost { namespace network { @@ -30,7 +30,7 @@ struct version { template struct version >::type> { - typedef std::shared_future::type> + typedef boost::shared_future::type> type; }; diff --git a/boost/network/protocol/http/policies/async_connection.hpp b/boost/network/protocol/http/policies/async_connection.hpp index 34a1f0c21..900a37e59 100644 --- a/boost/network/protocol/http/policies/async_connection.hpp +++ b/boost/network/protocol/http/policies/async_connection.hpp @@ -30,15 +30,15 @@ struct async_connection_policy : resolver_policy::type { typedef typename resolver_base::resolve_function resolve_function; typedef typename resolver_base::resolve_completion_function resolve_completion_function; - typedef std::function const&, - std::error_code const&)> + typedef std::function::type, 1024>::const_iterator> const&, + boost::system::error_code const&)> body_callback_function_type; typedef std::function body_generator_function_type; struct connection_impl { connection_impl( bool follow_redirect, bool always_verify_peer, resolve_function resolve, - resolver_type& resolver, bool https, int timeout, + resolver_type& resolver, bool https, int timeout, bool remove_chunk_markers, optional /*unused*/ const& certificate_filename, optional const& verify_path, optional const& certificate_file, @@ -47,9 +47,9 @@ struct async_connection_policy : resolver_policy::type { optional const& sni_hostname, long ssl_options) { pimpl = impl::async_connection_base:: new_connection(resolve, resolver, follow_redirect, always_verify_peer, - https, timeout, certificate_filename, verify_path, - certificate_file, private_key_file, ciphers, - sni_hostname, ssl_options); + https, timeout, remove_chunk_markers, + certificate_filename, verify_path, certificate_file, + private_key_file, ciphers, sni_hostname, ssl_options); } basic_response send_request(string_type /*unused*/ const& method, @@ -86,20 +86,22 @@ struct async_connection_policy : resolver_policy::type { this->resolve(resolver, host, port, once_resolved); }, resolver, boost::iequals(protocol_, string_type("https")), timeout_, - certificate_filename, verify_path, certificate_file, private_key_file, - ciphers, sni_hostname, ssl_options); + remove_chunk_markers_, certificate_filename, verify_path, + certificate_file, private_key_file, ciphers, sni_hostname, ssl_options); } void cleanup() {} async_connection_policy(bool cache_resolved, bool follow_redirect, - int timeout) + int timeout, bool remove_chunk_markers) : resolver_base(cache_resolved), follow_redirect_(follow_redirect), - timeout_(timeout) {} + timeout_(timeout), + remove_chunk_markers_(remove_chunk_markers) {} bool follow_redirect_; int timeout_; + bool remove_chunk_markers_; }; } // namespace http diff --git a/boost/network/protocol/http/policies/async_resolver.hpp b/boost/network/protocol/http/policies/async_resolver.hpp index ebbba6679..4e508364a 100644 --- a/boost/network/protocol/http/policies/async_resolver.hpp +++ b/boost/network/protocol/http/policies/async_resolver.hpp @@ -10,8 +10,8 @@ #include #include #include -#include -#include +#include +#include #include #include #include @@ -31,27 +31,30 @@ struct async_resolver : std::enable_shared_from_this > { typedef typename string::type string_type; typedef std::unordered_map endpoint_cache; - typedef std::function + typedef std::function resolve_completion_function; typedef std::function resolve_function; + void clear_resolved_cache() { clear_cache_.store(true); } + protected: bool cache_resolved_; + std::atomic clear_cache_; endpoint_cache endpoint_cache_; - std::shared_ptr<::asio::io_service> service_; - std::shared_ptr<::asio::io_service::strand> resolver_strand_; + std::shared_ptr service_; + std::shared_ptr resolver_strand_; explicit async_resolver(bool cache_resolved) - : cache_resolved_(cache_resolved), endpoint_cache_() {} + : cache_resolved_(cache_resolved), clear_cache_(false), endpoint_cache_() {} void resolve(resolver_type &resolver_, string_type const &host, std::uint16_t port, resolve_completion_function once_resolved) { - if (cache_resolved_) { + if (cache_resolved_ && !clear_cache_.load()) { typename endpoint_cache::iterator iter = endpoint_cache_.find(boost::to_lower_copy(host)); if (iter != endpoint_cache_.end()) { - std::error_code ignored; + boost::system::error_code ignored; once_resolved(ignored, iter->second); return; } @@ -60,7 +63,7 @@ struct async_resolver : std::enable_shared_from_this > { typename resolver_type::query q(host, std::to_string(port)); auto self = this->shared_from_this(); resolver_.async_resolve( - q, resolver_strand_->wrap([=](std::error_code const &ec, + q, resolver_strand_->wrap([=](boost::system::error_code const &ec, resolver_iterator endpoint_iterator) { self->handle_resolve(boost::to_lower_copy(host), once_resolved, ec, endpoint_iterator); @@ -69,11 +72,14 @@ struct async_resolver : std::enable_shared_from_this > { void handle_resolve(string_type /*unused*/ const &host, resolve_completion_function once_resolved, - std::error_code const &ec, + boost::system::error_code const &ec, resolver_iterator endpoint_iterator) { typename endpoint_cache::iterator iter; bool inserted = false; if (!ec && cache_resolved_) { + if (clear_cache_.exchange(false)) { + endpoint_cache_.clear(); + } std::tie(iter, inserted) = endpoint_cache_.insert(std::make_pair( host, std::make_pair(endpoint_iterator, resolver_iterator()))); once_resolved(ec, iter->second); diff --git a/boost/network/protocol/http/policies/pooled_connection.hpp b/boost/network/protocol/http/policies/pooled_connection.hpp index ab5ebca57..34339367d 100644 --- a/boost/network/protocol/http/policies/pooled_connection.hpp +++ b/boost/network/protocol/http/policies/pooled_connection.hpp @@ -35,7 +35,7 @@ struct pooled_connection_policy : resolver_policy::type { resolver_type&, string_type const&, string_type const&)> resolver_function_type; typedef std::function const&, - std::error_code const&)> + boost::system::error_code const&)> body_callback_function_type; typedef std::function body_generator_function_type; @@ -110,12 +110,12 @@ struct pooled_connection_policy : resolver_policy::type { response_ << ::boost::network::source(request_.host()); pimpl->send_request_impl(method, request_, generator); - ::asio::streambuf response_buffer; + boost::asio::streambuf response_buffer; try { pimpl->read_status(response_, response_buffer); - } catch (std::system_error& e) { - if (!retry && e.code() == ::asio::error::eof) { + } catch (boost::system::system_error& e) { + if (!retry && e.code() == boost::asio::error::eof) { retry = true; pimpl->init_socket(request_.host(), std::to_string(request_.port())); diff --git a/boost/network/protocol/http/policies/simple_connection.hpp b/boost/network/protocol/http/policies/simple_connection.hpp index 118b41096..dca2fb354 100644 --- a/boost/network/protocol/http/policies/simple_connection.hpp +++ b/boost/network/protocol/http/policies/simple_connection.hpp @@ -36,7 +36,7 @@ struct simple_connection_policy : resolver_policy::type { typedef typename resolver_base::resolver_completion_function resolver_completion_function; typedef std::function const&, - std::error_code const&)> + boost::system::error_code const&)> body_callback_function_type; typedef std::function body_generator_function_type; @@ -80,7 +80,7 @@ struct simple_connection_policy : resolver_policy::type { response_ = basic_response(); response_ << network::source(request_.host()); - ::asio::streambuf response_buffer; + boost::asio::streambuf response_buffer; pimpl->read_status(response_, response_buffer); pimpl->read_headers(response_, response_buffer); if (get_body) pimpl->read_body(response_, response_buffer); diff --git a/boost/network/protocol/http/policies/sync_resolver.hpp b/boost/network/protocol/http/policies/sync_resolver.hpp index 7c9c2c7f4..09d373b87 100644 --- a/boost/network/protocol/http/policies/sync_resolver.hpp +++ b/boost/network/protocol/http/policies/sync_resolver.hpp @@ -27,19 +27,26 @@ struct sync_resolver { typedef std::pair resolver_iterator_pair; + void clear_resolved_cache() { clear_cache_.store(true); } + protected: typedef typename string::type string_type; typedef std::unordered_map resolved_cache; resolved_cache endpoint_cache_; bool cache_resolved_; + std::atomic clear_cache_; - explicit sync_resolver(bool cache_resolved) : cache_resolved_(cache_resolved) {} + explicit sync_resolver(bool cache_resolved) + : cache_resolved_(cache_resolved), clear_cache_(false) {} resolver_iterator_pair resolve(resolver_type& resolver_, string_type /*unused*/const& hostname, string_type const& port) { if (cache_resolved_) { + if (clear_cache_.exchange(false)) { + endpoint_cache_.clear(); + } typename resolved_cache::iterator cached_iterator = endpoint_cache_.find(hostname); if (cached_iterator == endpoint_cache_.end()) { diff --git a/boost/network/protocol/http/server/async_connection.hpp b/boost/network/protocol/http/server/async_connection.hpp index 007f6bb7c..b2a736f7b 100644 --- a/boost/network/protocol/http/server/async_connection.hpp +++ b/boost/network/protocol/http/server/async_connection.hpp @@ -16,11 +16,11 @@ #include #include #include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include #include #include #include @@ -183,7 +183,7 @@ struct async_connection public: async_connection( - ::asio::io_service& io_service, Handler& handler, + boost::asio::io_service& io_service, Handler& handler, utils::thread_pool& thread_pool, std::shared_ptr ctx = std::shared_ptr()) : strand(io_service), @@ -205,8 +205,8 @@ struct async_connection } ~async_connection() throw() { - std::error_code ignored; - socket_.shutdown(::asio::ip::tcp::socket::shutdown_receive, ignored); + boost::system::error_code ignored; + socket_.shutdown(boost::asio::ip::tcp::socket::shutdown_receive, ignored); } /** @@ -228,7 +228,7 @@ struct async_connection std::logic_error("Headers have already been sent.")); if (error_encountered) - boost::throw_exception(std::system_error(*error_encountered)); + boost::throw_exception(boost::system::system_error(*error_encountered)); typedef constants consts; { @@ -264,7 +264,7 @@ struct async_connection boost::throw_exception(std::logic_error( "Headers have already been sent, cannot reset status.")); if (error_encountered) - boost::throw_exception(std::system_error(*error_encountered)); + boost::throw_exception(boost::system::system_error(*error_encountered)); status = new_status; } @@ -289,7 +289,7 @@ struct async_connection * set_status and/or set_headers before any calls to write. * * @param[in] range A Boost.Range ``Single Pass Range`` of char's for writing. - * @throw std::system_error The encountered underlying error in previous + * @throw boost::system::system_error The encountered underlying error in previous * operations. * @post Status and headers have been sent, contents in the range have been * serialized. @@ -298,9 +298,9 @@ struct async_connection void write(Range const& range) { lock_guard lock(headers_mutex); if (error_encountered) - boost::throw_exception(std::system_error(*error_encountered)); + boost::throw_exception(boost::system::system_error(*error_encountered)); auto self = this->shared_from_this(); - auto f = [this, self](std::error_code ec) { this->default_error(ec); }; + auto f = [this, self](boost::system::error_code ec) { this->default_error(ec); }; write_impl(boost::make_iterator_range(range), f); } @@ -313,32 +313,32 @@ struct async_connection * memory at once. * * @param[in] range A Boost.Range ``Single Pass Range`` of char's for writing. - * @param[in] callback A function of type `void(std::error_code)`. - * @throw std::system_error The encountered underlying error in previous + * @param[in] callback A function of type `void(boost::system::error_code)`. + * @throw boost::system::system_error The encountered underlying error in previous * operations. * @post Status and headers have been sent, contents in the range have been * serialized and scheduled for writing through the socket. */ template typename disable_if< - is_base_of<::asio::const_buffer, typename Range::value_type>, void>::type + is_base_of, void>::type write(Range const& range, Callback const& callback) { lock_guard lock(headers_mutex); if (error_encountered) - boost::throw_exception(std::system_error(*error_encountered)); + boost::throw_exception(boost::system::system_error(*error_encountered)); write_impl(boost::make_iterator_range(range), callback); } /** - * Writes a given set of `::asio::const_buffer`s out using a more efficient + * Writes a given set of `boost::asio::const_buffer`s out using a more efficient * implementation. * - * @param[in] seq A sequence of `::asio::const_buffer` objects. - * @param[in] callback A function of type `void(std::error_code)`. + * @param[in] seq A sequence of `boost::asio::const_buffer` objects. + * @param[in] callback A function of type `void(boost::system::error_code)`. */ template typename enable_if< - is_base_of<::asio::const_buffer, typename ConstBufferSeq::value_type>, + is_base_of, void>::type write(ConstBufferSeq const& seq, Callback const& callback) { write_vec_impl(seq, callback, shared_array_list(), shared_buffers()); @@ -355,7 +355,7 @@ struct async_connection /// Type required for ``read`` callbacks. Takes an input range, an error /// code, the number of bytes read, and a connection pointer. - typedef std::function read_callback_function; /** @@ -370,12 +370,12 @@ struct async_connection * void(input_range, error_code, size_t, connection_ptr) * * @param[in] callback Invoked when the read has data ready for processing. - * @throw std::system_error The underlying error encountered in previous + * @throw boost::system::system_error The underlying error encountered in previous * operations. */ void read(read_callback_function callback) { if (error_encountered) - boost::throw_exception(std::system_error(*error_encountered)); + boost::throw_exception(boost::system::system_error(*error_encountered)); if (new_start != read_buffer_.begin()) { input_range input = boost::make_iterator_range(new_start, data_end); @@ -389,9 +389,9 @@ struct async_connection } auto self = this->shared_from_this(); - socket().async_read_some(::asio::buffer(read_buffer_), + socket().async_read_some(boost::asio::buffer(read_buffer_), strand.wrap([this, self, callback]( - std::error_code ec, size_t bytes_transferred) { + boost::system::error_code ec, size_t bytes_transferred) { this->wrap_read_handler(callback, ec, bytes_transferred); })); @@ -408,13 +408,13 @@ struct async_connection bool has_error() { return (!!error_encountered); } /// Returns the most recent error encountered. - optional error() { return error_encountered; } + optional error() { return error_encountered; } private: void wrap_read_handler(read_callback_function callback, - std::error_code const& ec, + boost::system::error_code const& ec, std::size_t bytes_transferred) { - if (ec) error_encountered = in_place(ec); + if (ec) error_encountered = in_place(ec); buffer_type::const_iterator data_start = read_buffer_.begin(), data_end = read_buffer_.begin(); std::advance(data_end, bytes_transferred); @@ -425,23 +425,23 @@ struct async_connection }); } - void default_error(std::error_code const& ec) { - if (ec) error_encountered = in_place(ec); + void default_error(boost::system::error_code const& ec) { + if (ec) error_encountered = in_place(ec); } typedef std::array array; typedef std::list > array_list; typedef std::shared_ptr shared_array_list; - typedef std::shared_ptr > shared_buffers; + typedef std::shared_ptr > shared_buffers; typedef request_parser request_parser_type; typedef std::lock_guard lock_guard; typedef std::list > pending_actions_list; - ::asio::io_service::strand strand; + boost::asio::io_service::strand strand; Handler& handler; utils::thread_pool& thread_pool_; - ::asio::streambuf headers_buffer; + boost::asio::streambuf headers_buffer; boost::network::stream_handler socket_; bool handshake_done; volatile bool headers_already_sent, headers_in_progress; @@ -453,7 +453,7 @@ struct async_connection request request_; buffer_type::iterator new_start, data_end; string_type partial_parsed; - optional error_encountered; + optional error_encountered; pending_actions_list pending_actions; template @@ -473,15 +473,15 @@ struct async_connection auto self = this->shared_from_this(); #ifdef BOOST_NETWORK_ENABLE_HTTPS if (socket_.is_ssl_enabled() && !handshake_done) { - socket_.async_handshake(::asio::ssl::stream_base::server, - [this, self, state](std::error_code ec) { + socket_.async_handshake(boost::asio::ssl::stream_base::server, + [this, self, state](boost::system::error_code ec) { handle_handshake(ec, state); }); } else { #endif socket_.async_read_some( - ::asio::buffer(read_buffer_), - strand.wrap([this, self, state](std::error_code ec, + boost::asio::buffer(read_buffer_), + strand.wrap([this, self, state](boost::system::error_code ec, size_t bytes_transferred) { handle_read_data(state, ec, bytes_transferred); })); @@ -490,7 +490,7 @@ struct async_connection #endif } - void handle_read_data(state_t state, std::error_code const& ec, + void handle_read_data(state_t state, boost::system::error_code const& ec, std::size_t bytes_transferred) { if (!ec) { logic::tribool parsed_ok; @@ -579,7 +579,7 @@ struct async_connection } new_start = std::end(result_range); auto self = this->shared_from_this(); - thread_pool().post([this, self] { handler(request_, self); }); + thread_pool().post([this, self] { this->handler(this->request_, self); }); return; } else { partial_parsed.append(std::begin(result_range), @@ -595,7 +595,7 @@ struct async_connection std::abort(); } } else { - error_encountered = in_place(ec); + error_encountered = in_place(ec); } } @@ -605,20 +605,20 @@ struct async_connection "text/plain\r\nContent-Length: 12\r\n\r\nBad Request."; auto self = this->shared_from_this(); - ::asio::async_write( - socket(), ::asio::buffer(bad_request, strlen(bad_request)), - strand.wrap([this, self](std::error_code ec, size_t bytes_transferred) { + boost::asio::async_write( + socket(), boost::asio::buffer(bad_request, strlen(bad_request)), + strand.wrap([this, self](boost::system::error_code ec, size_t bytes_transferred) { client_error_sent(ec, bytes_transferred); })); } - void client_error_sent(std::error_code const& ec, std::size_t) { + void client_error_sent(boost::system::error_code const& ec, std::size_t) { if (!ec) { - std::error_code ignored; - socket().shutdown(::asio::ip::tcp::socket::shutdown_both, ignored); + boost::system::error_code ignored; + socket().shutdown(boost::asio::ip::tcp::socket::shutdown_both, ignored); socket().close(ignored); } else { - error_encountered = in_place(ec); + error_encountered = in_place(ec); } } @@ -626,15 +626,15 @@ struct async_connection if (headers_in_progress) return; headers_in_progress = true; auto self = this->shared_from_this(); - ::asio::async_write(socket(), headers_buffer, + boost::asio::async_write(socket(), headers_buffer, strand.wrap([this, self, callback]( - std::error_code ec, size_t bytes_transferred) { + boost::system::error_code ec, size_t bytes_transferred) { handle_write_headers(callback, ec, bytes_transferred); })); } void handle_write_headers(std::function callback, - std::error_code const& ec, std::size_t) { + boost::system::error_code const& ec, std::size_t) { lock_guard lock(headers_mutex); if (!ec) { headers_buffer.consume(headers_buffer.size()); @@ -646,19 +646,19 @@ struct async_connection } pending_actions_list().swap(pending_actions); } else { - error_encountered = in_place(ec); + error_encountered = in_place(ec); } } - void handle_write(std::function callback, + void handle_write(std::function callback, shared_array_list, shared_buffers, - std::error_code const& ec, std::size_t) { + boost::system::error_code const& ec, std::size_t) { // we want to forget the temporaries and buffers thread_pool().post([callback, ec] { callback(ec); }); } template - void write_impl(Range range, std::function callback) { + void write_impl(Range range, std::function callback) { // linearize the whole range into a vector // of fixed-sized buffers, then schedule an asynchronous // write of these buffers -- make sure they are live @@ -676,7 +676,7 @@ struct async_connection BOOST_NETWORK_HTTP_SERVER_CONNECTION_BUFFER_SIZE; shared_array_list temporaries = std::make_shared(); shared_buffers buffers = - std::make_shared >(0); + std::make_shared >(0); std::size_t range_size = boost::distance(range); buffers->reserve((range_size / connection_buffer_size) + @@ -688,7 +688,7 @@ struct async_connection std::shared_ptr new_array = std::make_shared(); boost::copy(range | sliced(0, slice_size), new_array->begin()); temporaries->push_back(new_array); - buffers->push_back(::asio::buffer(new_array->data(), slice_size)); + buffers->push_back(boost::asio::buffer(new_array->data(), slice_size)); std::advance(start, slice_size); range = boost::make_iterator_range(start, end); range_size = boost::distance(range); @@ -705,7 +705,7 @@ struct async_connection shared_array_list temporaries, shared_buffers buffers) { lock_guard lock(headers_mutex); if (error_encountered) - boost::throw_exception(std::system_error(*error_encountered)); + boost::throw_exception(boost::system::system_error(*error_encountered)); auto self = this->shared_from_this(); auto continuation = [this, self, seq, callback, temporaries, buffers] { write_vec_impl(seq, callback, temporaries, buffers); @@ -718,19 +718,19 @@ struct async_connection pending_actions.push_back(continuation); return; } - ::asio::async_write( + boost::asio::async_write( socket_, seq, [this, self, callback, temporaries, buffers]( - std::error_code ec, size_t bytes_transferred) { + boost::system::error_code ec, size_t bytes_transferred) { handle_write(callback, temporaries, buffers, ec, bytes_transferred); }); } - void handle_handshake(const std::error_code& ec, state_t state) { + void handle_handshake(const boost::system::error_code& ec, state_t state) { if (!ec) { handshake_done = true; read_more(state); } else { - error_encountered = in_place(ec); + error_encountered = in_place(ec); } } }; diff --git a/boost/network/protocol/http/server/async_server.hpp b/boost/network/protocol/http/server/async_server.hpp index 8c12aee74..c1e3c662e 100644 --- a/boost/network/protocol/http/server/async_server.hpp +++ b/boost/network/protocol/http/server/async_server.hpp @@ -35,13 +35,17 @@ struct async_server_base : server_storage_base, socket_options_base { /// Defines the type for the connection pointer. typedef std::shared_ptr connection_ptr; + /// Defines the type for the options. + typedef server_options options; + /// Constructs and initializes the asynchronous server core. - explicit async_server_base(server_options const &options) + explicit async_server_base(options const &options) : server_storage_base(options), socket_options_base(options), handler(options.handler()), address_(options.address()), port_(options.port()), + protocol_family(options.protocol_family()), thread_pool(options.thread_pool() ? options.thread_pool() : std::make_shared()), @@ -86,7 +90,7 @@ struct async_server_base : server_storage_base, socket_options_base { // listening scoped_mutex_lock stopping_lock(stopping_mutex_); stopping = true; - std::error_code ignored; + boost::system::error_code ignored; acceptor.close(ignored); listening = false; service_.post([this]() { this->handle_stop(); }); @@ -108,13 +112,21 @@ struct async_server_base : server_storage_base, socket_options_base { } } + /// Returns the server socket address, either IPv4 or IPv6 depending on + /// options.protocol_family() + const string_type& address() const { return address_; } + + /// Returns the server socket port + const string_type& port() const { return port_; } + private: typedef std::unique_lock scoped_mutex_lock; Handler &handler; string_type address_, port_; + typename options::protocol_family_t protocol_family; std::shared_ptr thread_pool; - ::asio::ip::tcp::acceptor acceptor; + boost::asio::ip::tcp::acceptor acceptor; bool stopping; connection_ptr new_connection; std::mutex listening_mutex_; @@ -129,7 +141,7 @@ struct async_server_base : server_storage_base, socket_options_base { // the stop command is reached } - void handle_accept(std::error_code const &ec) { + void handle_accept(boost::system::error_code const &ec) { { scoped_mutex_lock stopping_lock(stopping_mutex_); if (stopping) @@ -156,16 +168,24 @@ struct async_server_base : server_storage_base, socket_options_base { #else new_connection->socket(), #endif - [this](std::error_code const &ec) { this->handle_accept(ec); }); + [this](boost::system::error_code const &ec) { this->handle_accept(ec); }); } void start_listening() { - using ::asio::ip::tcp; - std::error_code error; + using boost::asio::ip::tcp; + boost::system::error_code error; // this allows repeated cycles of run -> stop -> run service_.reset(); tcp::resolver resolver(service_); - tcp::resolver::query query(address_, port_); + tcp::resolver::query query( [&]{ + switch(protocol_family) { + case options::ipv4: + return tcp::resolver::query(tcp::v4(), address_, port_); + case options::ipv6: + return tcp::resolver::query(tcp::v6(), address_, port_); + default: + return tcp::resolver::query(address_, port_); + }}()); tcp::resolver::iterator endpoint_iterator = resolver.resolve(query, error); if (error) { BOOST_NETWORK_MESSAGE("Error resolving '" << address_ << ':' << port_); @@ -185,7 +205,9 @@ struct async_server_base : server_storage_base, socket_options_base { << port_); return; } - acceptor.listen(::asio::socket_base::max_connections, error); + address_ = acceptor.local_endpoint().address().to_string(); + port_ = std::to_string(acceptor.local_endpoint().port()); + acceptor.listen(boost::asio::socket_base::max_connections, error); if (error) { BOOST_NETWORK_MESSAGE("Error listening on socket: '" << error << "' on " << address_ << ":" << port_); @@ -198,7 +220,7 @@ struct async_server_base : server_storage_base, socket_options_base { #else new_connection->socket(), #endif - [this](std::error_code const &ec) { this->handle_accept(ec); }); + [this](boost::system::error_code const &ec) { this->handle_accept(ec); }); listening = true; scoped_mutex_lock stopping_lock(stopping_mutex_); stopping = false; // if we were in the process of stopping, we revoke diff --git a/boost/network/protocol/http/server/options.hpp b/boost/network/protocol/http/server/options.hpp index fd90cc0a7..e84188bf3 100644 --- a/boost/network/protocol/http/server/options.hpp +++ b/boost/network/protocol/http/server/options.hpp @@ -9,8 +9,8 @@ // http://www.boost.org/LICENSE_1_0.txt) #include -#include -#include +#include +#include #include #include #include @@ -34,6 +34,7 @@ struct server_options { handler_(handler), address_("localhost"), port_("80"), + protocol_family_(undefined), reuse_address_(false), report_aborted_(false), non_blocking_io_(true), @@ -71,7 +72,7 @@ struct server_options { } /// Provides an Asio io_service for the server. Default is nullptr. - server_options &io_service(std::shared_ptr<::asio::io_service> v) { + server_options &io_service(std::shared_ptr v) { io_service_ = v; return *this; } @@ -88,6 +89,14 @@ struct server_options { return *this; } + enum protocol_family_t { ipv4, ipv6, undefined }; + + /// Set the protocol family for address resolving. Default is AF_UNSPEC. + server_options &protocol_family(protocol_family_t v) { + protocol_family_ = v; + return *this; + } + /// Set whether to reuse the address (SO_REUSE_ADDR). Default is false. server_options &reuse_address(bool v) { reuse_address_ = v; @@ -120,26 +129,26 @@ struct server_options { /// Set the socket receive buffer size. Unset by default. server_options &receive_buffer_size( - ::asio::socket_base::receive_buffer_size v) { + boost::asio::socket_base::receive_buffer_size v) { receive_buffer_size_ = v; return *this; } /// Set the send buffer size. Unset by default. - server_options &send_buffer_size(::asio::socket_base::send_buffer_size v) { + server_options &send_buffer_size(boost::asio::socket_base::send_buffer_size v) { send_buffer_size_ = v; return *this; } /// Set the socket receive low watermark. Unset by default. server_options &receive_low_watermark( - ::asio::socket_base::receive_low_watermark v) { + boost::asio::socket_base::receive_low_watermark v) { receive_low_watermark_ = v; return *this; } /// Set the socket send low watermark. Unset by default. - server_options &send_low_watermark(::asio::socket_base::send_low_watermark v) { + server_options &send_low_watermark(boost::asio::socket_base::send_low_watermark v) { send_low_watermark_ = v; return *this; } @@ -151,7 +160,7 @@ struct server_options { } /// Returns the provided Asio io_service. - std::shared_ptr<::asio::io_service> io_service() const { return io_service_; } + std::shared_ptr io_service() const { return io_service_; } /// Returns the address to listen on. string_type address() const { return address_; } @@ -159,6 +168,9 @@ struct server_options { /// Returns the port to listen on. string_type port() const { return port_; } + /// Returns the protocol family used for address resolving. + protocol_family_t protocol_family() const { return protocol_family_; } + /// Returns a reference to the provided handler. Handler &handler() const { return handler_; } @@ -178,25 +190,25 @@ struct server_options { size_t linger_timeout() const { return linger_timeout_; } /// Returns the optional receive buffer size. - boost::optional<::asio::socket_base::receive_buffer_size> receive_buffer_size() + boost::optional receive_buffer_size() const { return receive_buffer_size_; } /// Returns the optional send buffer size. - boost::optional<::asio::socket_base::send_buffer_size> send_buffer_size() + boost::optional send_buffer_size() const { return send_buffer_size_; } /// Returns the optional receive low watermark. - boost::optional<::asio::socket_base::receive_low_watermark> + boost::optional receive_low_watermark() const { return receive_low_watermark_; } /// Returns the optional send low watermark. - boost::optional<::asio::socket_base::send_low_watermark> send_low_watermark() + boost::optional send_low_watermark() const { return send_low_watermark_; } @@ -215,6 +227,7 @@ struct server_options { swap(io_service_, other.io_service_); swap(address_, other.address_); swap(port_, other.port_); + swap(protocol_family_, other.protocol_family_); swap(reuse_address_, other.reuse_address_); swap(report_aborted_, other.report_aborted_); swap(non_blocking_io_, other.non_blocking_io_); @@ -229,20 +242,21 @@ struct server_options { } private: - std::shared_ptr<::asio::io_service> io_service_; + std::shared_ptr io_service_; Handler &handler_; string_type address_; string_type port_; + protocol_family_t protocol_family_; bool reuse_address_; bool report_aborted_; bool non_blocking_io_; bool linger_; size_t linger_timeout_; - boost::optional<::asio::socket_base::receive_buffer_size> receive_buffer_size_; - boost::optional<::asio::socket_base::send_buffer_size> send_buffer_size_; - boost::optional<::asio::socket_base::receive_low_watermark> + boost::optional receive_buffer_size_; + boost::optional send_buffer_size_; + boost::optional receive_low_watermark_; - boost::optional<::asio::socket_base::send_low_watermark> send_low_watermark_; + boost::optional send_low_watermark_; std::shared_ptr thread_pool_; std::shared_ptr context_; }; diff --git a/boost/network/protocol/http/server/socket_options_base.hpp b/boost/network/protocol/http/server/socket_options_base.hpp index 4e5aa6390..f82a3d7b9 100644 --- a/boost/network/protocol/http/server/socket_options_base.hpp +++ b/boost/network/protocol/http/server/socket_options_base.hpp @@ -14,15 +14,15 @@ namespace http { struct socket_options_base { protected: - ::asio::socket_base::reuse_address acceptor_reuse_address; - ::asio::socket_base::enable_connection_aborted acceptor_report_aborted; - boost::optional<::asio::socket_base::receive_buffer_size> receive_buffer_size; - boost::optional<::asio::socket_base::send_buffer_size> send_buffer_size; - boost::optional<::asio::socket_base::receive_low_watermark> + boost::asio::socket_base::reuse_address acceptor_reuse_address; + boost::asio::socket_base::enable_connection_aborted acceptor_report_aborted; + boost::optional receive_buffer_size; + boost::optional send_buffer_size; + boost::optional receive_low_watermark; - boost::optional<::asio::socket_base::send_low_watermark> send_low_watermark; + boost::optional send_low_watermark; bool non_blocking_io; - ::asio::socket_base::linger linger; + boost::asio::socket_base::linger linger; template explicit socket_options_base(server_options const &options) @@ -35,13 +35,13 @@ struct socket_options_base { non_blocking_io(options.non_blocking_io()), linger(options.linger(), options.linger_timeout()) {} - void acceptor_options(::asio::ip::tcp::acceptor &acceptor) { + void acceptor_options(boost::asio::ip::tcp::acceptor &acceptor) { acceptor.set_option(acceptor_reuse_address); acceptor.set_option(acceptor_report_aborted); } - void socket_options(::asio::ip::tcp::socket &socket) { - std::error_code ignored; + void socket_options(boost::asio::ip::tcp::socket &socket) { + boost::system::error_code ignored; socket.non_blocking(non_blocking_io); socket.set_option(linger, ignored); if (receive_buffer_size) socket.set_option(*receive_buffer_size, ignored); diff --git a/boost/network/protocol/http/server/storage_base.hpp b/boost/network/protocol/http/server/storage_base.hpp index 9e83ce2e6..ec134a9f3 100644 --- a/boost/network/protocol/http/server/storage_base.hpp +++ b/boost/network/protocol/http/server/storage_base.hpp @@ -22,11 +22,11 @@ struct server_storage_base { explicit server_storage_base(server_options const& options) : self_service_(options.io_service() ? options.io_service() - : std::make_shared<::asio::io_service>()), + : std::make_shared()), service_(*self_service_) {} - std::shared_ptr<::asio::io_service> self_service_; - ::asio::io_service& service_; + std::shared_ptr self_service_; + boost::asio::io_service& service_; }; } /* http */ diff --git a/boost/network/protocol/http/traits/resolver.hpp b/boost/network/protocol/http/traits/resolver.hpp index 350fa2396..dec498745 100644 --- a/boost/network/protocol/http/traits/resolver.hpp +++ b/boost/network/protocol/http/traits/resolver.hpp @@ -6,8 +6,8 @@ // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) -#include -#include +#include +#include #include #include #include @@ -26,9 +26,9 @@ struct unsupported_tag; template struct resolver : mpl::if_, is_http >, - ::asio::ip::tcp::resolver, + boost::asio::ip::tcp::resolver, typename mpl::if_, is_http >, - ::asio::ip::udp::resolver, + boost::asio::ip::udp::resolver, unsupported_tag >::type> { static_assert(mpl::not_, is_tcp > >::value, "Transport protocol must be TCP or UDP"); diff --git a/boost/network/protocol/stream_handler.hpp b/boost/network/protocol/stream_handler.hpp index 1e828b046..cd98b6875 100644 --- a/boost/network/protocol/stream_handler.hpp +++ b/boost/network/protocol/stream_handler.hpp @@ -11,32 +11,32 @@ #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) #include -#include -#include -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include +#include +#include #include #ifdef BOOST_NETWORK_ENABLE_HTTPS -#include +#include #endif namespace boost { namespace network { -typedef ::asio::ip::tcp::socket tcp_socket; +typedef boost::asio::ip::tcp::socket tcp_socket; #ifndef BOOST_NETWORK_ENABLE_HTTPS typedef tcp_socket stream_handler; typedef void ssl_context; #else -typedef ::asio::ssl::stream<::asio::ip::tcp::socket> ssl_socket; -typedef ::asio::ssl::context ssl_context; +typedef boost::asio::ssl::stream ssl_socket; +typedef boost::asio::ssl::context ssl_context; struct stream_handler { public: @@ -48,7 +48,7 @@ struct stream_handler { stream_handler(std::shared_ptr socket) : ssl_sock_(std::move(socket)), ssl_enabled(true) {} - stream_handler(::asio::io_service& io, + stream_handler(boost::asio::io_service& io, std::shared_ptr ctx = std::shared_ptr()) { tcp_sock_ = std::make_shared(boost::ref(io)); @@ -62,10 +62,10 @@ struct stream_handler { } template - ASIO_INITFN_RESULT_TYPE(WriteHandler, - void(std::error_code, std::size_t)) + BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler, + void(boost::system::error_code, std::size_t)) async_write_some(const ConstBufferSequence& buffers, - ASIO_MOVE_ARG(WriteHandler) handler) { + BOOST_ASIO_MOVE_ARG(WriteHandler) handler) { try { if (ssl_enabled) { ssl_sock_->async_write_some(buffers, handler); @@ -73,16 +73,16 @@ struct stream_handler { tcp_sock_->async_write_some(buffers, handler); } } - catch (const std::system_error&) { + catch (const boost::system::system_error&) { // print system error } } template - ASIO_INITFN_RESULT_TYPE(ReadHandler, - void(std::error_code, std::size_t)) + BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler, + void(boost::system::error_code, std::size_t)) async_read_some(const MutableBufferSequence& buffers, - ASIO_MOVE_ARG(ReadHandler) handler) { + BOOST_ASIO_MOVE_ARG(ReadHandler) handler) { try { if (ssl_enabled) { ssl_sock_->async_read_some(buffers, handler); @@ -90,12 +90,12 @@ struct stream_handler { tcp_sock_->async_read_some(buffers, handler); } } - catch (const std::system_error& e) { + catch (const boost::system::system_error& e) { // print system error } } - void close(std::error_code& e) { + void close(boost::system::error_code& e) { if (ssl_enabled) { ssl_sock_->next_layer().close(); } else { @@ -111,16 +111,16 @@ struct stream_handler { } } - void shutdown(::asio::socket_base::shutdown_type st, - std::error_code& e) { + void shutdown(boost::asio::socket_base::shutdown_type st, + boost::system::error_code& e) { try { if (ssl_enabled) { ssl_sock_->shutdown(e); } else { - tcp_sock_->shutdown(::asio::ip::tcp::socket::shutdown_send, e); + tcp_sock_->shutdown(boost::asio::ip::tcp::socket::shutdown_send, e); } } - catch (const std::system_error& e) { + catch (const boost::system::system_error& e) { } } @@ -142,10 +142,10 @@ struct stream_handler { } template - ASIO_INITFN_RESULT_TYPE(HandshakeHandler, - void(std::error_code)) + BOOST_ASIO_INITFN_RESULT_TYPE(HandshakeHandler, + void(boost::system::error_code)) async_handshake(ssl_socket::handshake_type type, - ASIO_MOVE_ARG(HandshakeHandler) handler) { + BOOST_ASIO_MOVE_ARG(HandshakeHandler) handler) { try { if (ssl_enabled) { return ssl_sock_->async_handshake(type, handler); @@ -153,7 +153,7 @@ struct stream_handler { // NOOP } } - catch (const std::system_error& e) { + catch (const boost::system::system_error& e) { } } diff --git a/boost/network/utils/thread_pool.hpp b/boost/network/utils/thread_pool.hpp index 0d1e2c0d1..08549881b 100644 --- a/boost/network/utils/thread_pool.hpp +++ b/boost/network/utils/thread_pool.hpp @@ -9,7 +9,7 @@ #include #include #include -#include +#include #include #include @@ -17,9 +17,9 @@ namespace boost { namespace network { namespace utils { -typedef std::shared_ptr<::asio::io_service> io_service_ptr; +typedef std::shared_ptr io_service_ptr; typedef std::shared_ptr worker_threads_ptr; -typedef std::shared_ptr<::asio::io_service::work> sentinel_ptr; +typedef std::shared_ptr sentinel_ptr; class thread_pool { public: @@ -52,7 +52,7 @@ class thread_pool { BOOST_SCOPE_EXIT_END if (!io_service_.get()) { - io_service_.reset(new ::asio::io_service); + io_service_.reset(new boost::asio::io_service); } if (!worker_threads_.get()) { @@ -60,7 +60,7 @@ class thread_pool { } if (!sentinel_.get()) { - sentinel_.reset(new ::asio::io_service::work(*io_service_)); + sentinel_.reset(new boost::asio::io_service::work(*io_service_)); } for (std::size_t counter = 0; counter < threads_; ++counter) { diff --git a/build.sh b/build.sh index b3e3bb880..8e3e31d7e 100755 --- a/build.sh +++ b/build.sh @@ -11,10 +11,8 @@ cmake -DCMAKE_BUILD_TYPE=$CMAKE_BUILD_TYPE \ -DUri_BUILD_TESTS=$BUILD_TESTS \ -DUri_BUILD_DOCS=$BUILD_DOCS \ -DUri_DISABLE_LIBCXX=$Uri_DISABLE_LIBCXX \ - -DBOOST_INCLUDEDIR="${HOME}/${CC}-boost_${BOOST_VERSION}/include" \ - -DBOOST_LIBRARYDIR="${HOME}/${CC}-boost_${BOOST_VERSION}/lib" \ -DCMAKE_CXX_FLAGS="-std=c++11 ${CMAKE_CXX_FLAGS}" \ .. -make -j8 +make make test cd .. diff --git a/contrib/cpp-netlib-devel.spec b/contrib/cpp-netlib-devel.spec new file mode 100644 index 000000000..8c138cb05 --- /dev/null +++ b/contrib/cpp-netlib-devel.spec @@ -0,0 +1,38 @@ +Name: cpp-netlib-devel +Version: 0.9.4 +Release: 1%{?dist} +Summary: The C++ Network Library Project +License: Boost +URL: http://cpp-netlib.org/ +Source: https://github.com/downloads/cpp-netlib/cpp-netlib/cpp-netlib-%{version}.tar.gz +BuildArch: noarch + +%description +The project aims to build upon the latest C++ standard (currently +C++11) to provide easy to use libraries for network programming. We use +the latest compiler versions and features with an eye on pushing the +boundaries on leveraging what's available in C++. + +Currently the library contains an HTTP client and server implementation, +a stand-alone URI library, a network message framework, and some +concurrency tools. + +%prep +%setup -q -n cpp-netlib-%{version} + +%build + +# The source file will contain the header files needed, so there is no need to build anything + +%install +mkdir -p %{buildroot}%{_includedir} +tar cf - boost | (cd %{buildroot}%{_includedir}; tar xf -) + +%files +%doc RATIONALE.txt README.rst +%license LICENSE_1_0.txt +%{_includedir}/boost + +%changelog +* Fri Jul 15 2016 Håkon Løvdal - 0.9.4-1 +- Created diff --git a/deps/asio b/deps/asio index 66e76b9e4..22afb8608 160000 --- a/deps/asio +++ b/deps/asio @@ -1 +1 @@ -Subproject commit 66e76b9e4252ff4681227d0d8e34374ec1fa20e5 +Subproject commit 22afb86087a77037cd296d27134756c9b0d2cb75 diff --git a/deps/cxxopts b/deps/cxxopts index aec97a6f5..3d405ef16 160000 --- a/deps/cxxopts +++ b/deps/cxxopts @@ -1 +1 @@ -Subproject commit aec97a6f53c3486fc51e0d9857f10b683180d668 +Subproject commit 3d405ef1639a918ea8798666e2b02eb9cef889c0 diff --git a/deps/googletest b/deps/googletest index d225acc90..3880b13e4 160000 --- a/deps/googletest +++ b/deps/googletest @@ -1 +1 @@ -Subproject commit d225acc90bc3a8c420a9bcd1f033033c1ccd7fe0 +Subproject commit 3880b13e4c0b04ca88f69b9c93da6058bd836c34 diff --git a/deps/uri b/deps/uri index c16a46ecb..76f0781f4 160000 --- a/deps/uri +++ b/deps/uri @@ -1 +1 @@ -Subproject commit c16a46ecb6bf0c936179e324891a74b5e6d8f4d3 +Subproject commit 76f0781f45d9a79c2a2bde9cabe76368cc6892c1 diff --git a/libs/network/doc/_ext/breathe b/libs/network/doc/_ext/breathe index 853385ef4..1767274e0 160000 --- a/libs/network/doc/_ext/breathe +++ b/libs/network/doc/_ext/breathe @@ -1 +1 @@ -Subproject commit 853385ef4f0c3dd126887750e20d5f7456065998 +Subproject commit 1767274e0f59eb707f2b6256d51b12a3a4341da8 diff --git a/libs/network/doc/reference/http_response.rst b/libs/network/doc/reference/http_response.rst index d0a973991..d76bcba28 100644 --- a/libs/network/doc/reference/http_response.rst +++ b/libs/network/doc/reference/http_response.rst @@ -307,3 +307,7 @@ effect: ``template `` *unspecified* ``status_message(basic_response const & response)`` Returns a wrapper convertible to ``typename string::type`` that provides the status message of the given response. +``template `` *unspecified* ``ready(basic_response const & response)`` + Returns a wrapper convertible to ``bool``. The return value is equivalent + to ``true`` if all the response parts have been fetched and it is guaranteed + that a successive call to any wrapper will not block. diff --git a/libs/network/example/CMakeLists.txt b/libs/network/example/CMakeLists.txt index ceca8052e..e647a8e69 100644 --- a/libs/network/example/CMakeLists.txt +++ b/libs/network/example/CMakeLists.txt @@ -5,6 +5,7 @@ include_directories(${CPP-NETLIB_SOURCE_DIR}) include_directories(${CPP-NETLIB_SOURCE_DIR}/deps/cxxopts/src) +include_directories(${CPP-NETLIB_SOURCE_DIR}/deps/cxxopts/include) if (OPENSSL_FOUND) include_directories(${OPENSSL_INCLUDE_DIR}) endif (OPENSSL_FOUND) @@ -28,40 +29,48 @@ add_dependencies(rss_reader network-uri cppnetlib-client-connections) add_dependencies(trivial_google network-uri cppnetlib-client-connections) target_link_libraries(http_client + ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} network-uri cppnetlib-client-connections) target_link_libraries(simple_wget + ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} network-uri cppnetlib-client-connections) target_link_libraries(atom_reader + ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} network-uri cppnetlib-client-connections) target_link_libraries(rss_reader + ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} network-uri cppnetlib-client-connections) target_link_libraries(trivial_google - ${CMAKE_THREAD_LIBS_INIT} - network-uri - cppnetlib-client-connections) + ${Boost_LIBRARIES} + ${CMAKE_THREAD_LIBS_INIT} + network-uri + cppnetlib-client-connections) target_link_libraries(hello_world_server + ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} cppnetlib-server-parsers) target_link_libraries(hello_world_client + ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} network-uri cppnetlib-client-connections) target_link_libraries(hello_world_async_server_with_work_queue + ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} network-uri cppnetlib-client-connections @@ -71,6 +80,7 @@ if (OPENSSL_FOUND) add_executable(ssl_server http/ssl/ssl_server.cpp) add_dependencies(ssl_server network-uri cppnetlib-client-connections) target_link_libraries(ssl_server + ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} cppnetlib-server-parsers network-uri @@ -118,6 +128,7 @@ endif() if (UNIX) target_link_libraries(fileserver + ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} cppnetlib-server-parsers) if (${CMAKE_SYSTEM_NAME} MATCHES "Linux") diff --git a/libs/network/example/http/echo_async_server.cpp b/libs/network/example/http/echo_async_server.cpp new file mode 100644 index 000000000..c017a32b6 --- /dev/null +++ b/libs/network/example/http/echo_async_server.cpp @@ -0,0 +1,247 @@ +// Copyright 2018 Martin Trenkmann +// Based on cpp-netlib/libs/network/example/http/fileserver.cpp +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// This example implements a minimal echo server that receives plain text via +// POST requests and sends the same text back to the client (with an additional +// newline appended for nicer output). Since the server uses asynchronous I/O, +// the body data is not available through request.body, but must be read using +// connection->read(callback). +// +// This code is minimal, it does not... +// - handle any kinds of errors, +// - look at the URI path (request.destination), +// - handle request methods other than POST (request.method), +// - check for too large bodies (which make the server vulnerable to attacks), +// - model state, e.g. database connections (this type of context should be +// injected into the post_request_handler constructor). +// +// About handling large body data: +// According to https://tools.ietf.org/html/rfc2616#section-8.2.3, HTTP clients +// may send a "Expect: 100-continue" header before sending large body data in +// order to negotiate whether the server is willing to accept the data. If the +// server agrees, it should send an interim response with a "100 Continue" +// status code. The client then should start sending the data and upon +// completion, the server should send a final response including a status code +// and possibly headers and body data. +// +// About cpp-netlib 0.13 and the "Expect: 100-continue" header: +// When a client sends a POST request with a "Expect: 100-continue" header, the +// callback passed into connection->read() gets triggered with an empty chunk of +// data. As described before, the server should then send an "100 Continue" +// interim response, but this seems to be not supported by the library at the +// moment, because trying to set and send a status code on the connection object +// more than once throws an exception. However, since clients are allowed to +// send data even though they never received a "100 Continue", the server should +// continue reading data from the connection, by calling connection->read() +// again, until the expected number of bytes, based on the "Content-Length" +// header, has been received. +// +// About curl and the "Expect: 100-continue" header: +// According to https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Expect +// no common browsers make use of the "Expect" header, but some other clients +// such as curl do so by default. In fact, curl sends a "Expect: 100-continue" +// header with POST requests that contain at least 1KiB of data (see example +// session below). Fortunately, curl also starts sending the data if it does +// not receive a "100 Continue" status code after a timeout of 1 second, which +// makes it "compatible" with servers that cannot send interim responses such as +// cpp-netlib 0.13. +// +// The timeout in curl is configurable via "--expect100-timeout " +// command line argument. The minimum value seems to be 1 second. +// +// Example session: +// Two POST requests are sent to the echo server using curl. The first one with +// data less than 1KiB, the second one with data more than 1KiB which shows the +// use of the "Expect: 100-continue" header. +// +// The "lorem" command generates lorem ipsum text. It can be installed via +// "sudo apt-get install libtext-lorem-perl" on Debian-based systems. +// +// 1. Sending less than 1KiB +// ------------------------- +// +// $ curl -v -H 'Content-Type: text/plain' -d "$(lorem -s 3 | fold)" http://localhost:8000 +// * Rebuilt URL to: http://localhost:8000/ +// * Trying 127.0.0.1... +// * Connected to localhost (127.0.0.1) port 8000 (#0) +// > POST / HTTP/1.1 +// > Host: localhost:8000 +// > User-Agent: curl/7.47.0 +// > Accept: */* +// > Content-Type: text/plain +// > Content-Length: 155 +// > +// * upload completely sent off: 155 out of 155 bytes +// < HTTP/1.1 200 OK +// < Content-Type: text/plain +// < Content-Length: 156 +// < +// Iusto autem omnis necessitatibus quia omnis nemo sequi. Occaecati est explicabo +// qui placeat ipsa debitis fugit sit. Quasi sequi in est eius qui molestiae. +// * Connection #0 to host localhost left intact +// +// SERVER OUTPUT +// +// Host: localhost:8000 +// User-Agent: curl/7.47.0 +// Accept: */* +// Content-Type: text/plain +// Content-Length: 155 +// Chunk size: 155 +// +// 2. Sending more than 1KiB +// ------------------------- +// +// $ curl -v -H 'Content-Type: text/plain' -d "$(lorem -s 30 | fold)" http://localhost:8000 +// * Rebuilt URL to: http://localhost:8000/ +// * Trying 127.0.0.1... +// * Connected to localhost (127.0.0.1) port 8000 (#0) +// > POST / HTTP/1.1 +// > Host: localhost:8000 +// > User-Agent: curl/7.47.0 +// > Accept: */* +// > Content-Type: text/plain +// > Content-Length: 1324 +// > Expect: 100-continue +// > +// * Done waiting for 100-continue +// * We are completely uploaded and fine +// < HTTP/1.1 200 OK +// < Content-Type: text/plain +// < Content-Length: 1325 +// < +// Fugit quo aliquid in et consectetur sed id. Aliquam dolor optio labore sit autem +// . Culpa at omnis et consectetur minima nostrum sed. Veniam similique dolorum des +// erunt aut et et aut quo. Laudantium nesciunt est repellat. Dolores adipisci alia +// s dicta dicta. Impedit porro pariatur quisquam sit ex ducimus a. Consequatur ius +// to possimus in sint nesciunt molestiae fugiat et. Est praesentium quos quam libe +// ro vel nostrum placeat consequuntur. Tempora nihil aut aliquam. Atque ab sunt ut +// sed quo ut. Quia qui omnis non. In laboriosam possimus laboriosam consequatur v +// el dolores. Reprehenderit totam quis dolore debitis ullam. Aut iure omnis invent +// ore quaerat aut veniam vel magni. Temporibus voluptatibus accusamus qui facilis +// at aut. Voluptatem provident incidunt officia. Quos quo autem quae illo. Modi am +// et quis eveniet. Nemo tenetur quia unde. Velit molestiae laborum eum. Repellat m +// olestias eos eos accusantium dolorem molestias pariatur ex. Nihil dolorum possim +// us ut ut beatae. Quia nam sit aut voluptatum maiores quibusdam id aliquid. Nulla +// numquam rem quo doloremque ut ut. Aspernatur accusamus illo illo dolores repudi +// andae dicta reiciendis. Quis laborum magni et incidunt nihil. Ea quia consequunt +// ur quos minima aut veniam ratione sed. Ea deleniti accusamus est quo nisi. Quia +// quibusdam et aut reiciendis. +// * Connection #0 to host localhost left intact +// +// SERVER OUTPUT +// +// Host: localhost:8000 +// User-Agent: curl/7.47.0 +// Accept: */* +// Content-Type: text/plain +// Content-Length: 1324 +// Expect: 100-continue +// Chunk size: 0 +// Chunk size: 1024 +// Chunk size: 300 + +#include +#include +#include +#include +#include +#include + +namespace http = boost::network::http; + +struct request_handler; +using echo_server = http::server; + +struct post_request_handler + : public std::enable_shared_from_this { + explicit post_request_handler(const echo_server::request& request) + : content_length_(0) { + for (const auto& header : request.headers) { + std::cout << header.name << ": " << header.value << '\n'; + if (boost::iequals(header.name, "content-length")) { + content_length_ = std::stoul(header.value); + } + } + } + + void operator()(echo_server::connection::input_range chunk, + boost::system::error_code ec, size_t chunk_size, + echo_server::connection_ptr connection) { + assert(chunk.size() == chunk_size); + std::cout << "Chunk size: " << chunk_size << '\n'; + + if (ec) { + std::cerr << "Error code: " << ec << '\n'; + return; + } + + body_.append(chunk.begin(), chunk.end()); + if (body_.size() < content_length_) { + auto self = this->shared_from_this(); + connection->read([self](echo_server::connection::input_range chunk, + boost::system::error_code ec, size_t chunk_size, + echo_server::connection_ptr connection) { + (*self)(chunk, ec, chunk_size, connection); + }); + return; + } + + body_.push_back('\n'); + std::vector headers; + headers.push_back({"Content-Type", "text/plain"}); + headers.push_back({"Content-Length", std::to_string(body_.size())}); + connection->set_status(echo_server::connection::ok); + connection->set_headers(headers); + connection->write(body_); + } + + private: + size_t content_length_; + std::string body_; +}; + +struct request_handler { + void operator()(const echo_server::request& request, + echo_server::connection_ptr connection) { + if (request.method == "POST") { + auto h = std::make_shared(request); + connection->read([h](echo_server::connection::input_range chunk, + boost::system::error_code ec, size_t chunk_size, + echo_server::connection_ptr connection) { + (*h)(chunk, ec, chunk_size, connection); + }); + } + } +}; + +int main() { + try { + request_handler handler; + auto io_service = std::make_shared(); + echo_server server( + echo_server::options(handler).io_service(io_service).port("8000")); + + // Clean shutdown when pressing Ctrl+C. + boost::asio::signal_set signals(*io_service, SIGINT, SIGTERM); + signals.async_wait([&server](const boost::system::error_code& ec, + int /* signal_number */) { + if (!ec) { + std::cout << "Stopping server... "; + server.stop(); + std::cout << "done.\n"; + } + }); + + std::cout << "Press Ctrl+C to stop the server.\n"; + server.run(); + + return EXIT_SUCCESS; + } catch (const std::exception& error) { + std::cerr << error.what() << std::endl; + return EXIT_FAILURE; + } +} diff --git a/libs/network/example/http/fileserver.cpp b/libs/network/example/http/fileserver.cpp index 8f74ae9a1..d11eb1951 100644 --- a/libs/network/example/http/fileserver.cpp +++ b/libs/network/example/http/fileserver.cpp @@ -134,17 +134,17 @@ struct connection_handler : std::enable_shared_from_this { off_t rightmost_bound = std::min(mmaped_region.second, adjusted_offset); auto self = this->shared_from_this(); connection->write( - asio::const_buffers_1( + boost::asio::const_buffers_1( static_cast(mmaped_region.first) + offset, rightmost_bound - offset), - [=](std::error_code const &ec) { + [=](boost::system::error_code const &ec) { self->handle_chunk(mmaped_region, rightmost_bound, connection, ec); }); } void handle_chunk(std::pair mmaped_region, off_t offset, server::connection_ptr connection, - std::error_code const &ec) { + boost::system::error_code const &ec) { assert(offset >= 0); if (!ec && static_cast(offset) < mmaped_region.second) send_file(mmaped_region, offset, connection); @@ -169,11 +169,11 @@ struct input_consumer : public std::enable_shared_from_this { } } - void operator()(server::connection::input_range input, std::error_code ec, + void operator()(server::connection::input_range input, boost::system::error_code ec, std::size_t bytes_transferred, server::connection_ptr connection) { std::cerr << "Callback: " << bytes_transferred << "; ec = " << ec << '\n'; - if (ec == asio::error::eof) return; + if (ec == boost::asio::error::eof) return; if (!ec) { if (empty(input)) return (*handler_)(request_.destination, connection, true); @@ -194,7 +194,7 @@ struct input_consumer : public std::enable_shared_from_this { std::cerr << "Scheduling another read...\n"; auto self = this->shared_from_this(); connection->read([self](server::connection::input_range input, - std::error_code ec, std::size_t bytes_transferred, + boost::system::error_code ec, std::size_t bytes_transferred, server::connection_ptr connection) { (*self)(input, ec, bytes_transferred, connection); }); @@ -221,7 +221,7 @@ struct file_server { auto h = std::make_shared(cache_); auto c = std::make_shared(h, request); connection->read([c](server::connection::input_range input, - std::error_code ec, std::size_t bytes_transferred, + boost::system::error_code ec, std::size_t bytes_transferred, server::connection_ptr connection) { (*c)(input, ec, bytes_transferred, connection); }); diff --git a/libs/network/example/http/hello_world_async_server_with_work_queue.cpp b/libs/network/example/http/hello_world_async_server_with_work_queue.cpp index d35593422..126388aae 100644 --- a/libs/network/example/http/hello_world_async_server_with_work_queue.cpp +++ b/libs/network/example/http/hello_world_async_server_with_work_queue.cpp @@ -13,7 +13,7 @@ #include #include #include -#include +#include #include #include #include @@ -107,7 +107,7 @@ struct handler { * @param signal * @param server */ -void shut_me_down(const std::error_code& error, int signal, +void shut_me_down(const boost::system::error_code& error, int signal, std::shared_ptr server) { if (!error) server->stop(); } @@ -125,7 +125,12 @@ void process_request(work_queue& queue) { // some heavy work! std::this_thread::sleep_for(std::chrono::seconds(10)); + std::map headers = { + {"Content-Type", "text/plain"}, + }; + request->conn->set_status(server::connection::ok); + request->conn->set_headers(headers); request->conn->write("Hello, world!"); } @@ -139,8 +144,8 @@ int main() { auto threads(std::make_shared()); // setup asio::io_service - auto io_service(std::make_shared()); - auto work(std::make_shared(std::ref(*io_service))); + auto io_service(std::make_shared()); + auto work(std::make_shared(std::ref(*io_service))); // io_service threads { @@ -173,8 +178,8 @@ int main() { 2, io_service, threads)))); // setup clean shutdown - asio::signal_set signals(*io_service, SIGINT, SIGTERM); - signals.async_wait([=] (std::error_code const &ec, int signal) { + boost::asio::signal_set signals(*io_service, SIGINT, SIGTERM); + signals.async_wait([=] (boost::system::error_code const &ec, int signal) { shut_me_down(ec, signal, server); }); diff --git a/libs/network/example/http/ssl/ssl_server.cpp b/libs/network/example/http/ssl/ssl_server.cpp index 2208d1263..70f23df05 100644 --- a/libs/network/example/http/ssl/ssl_server.cpp +++ b/libs/network/example/http/ssl/ssl_server.cpp @@ -13,8 +13,8 @@ #include #include -#include -#include +#include +#include #include #include @@ -23,7 +23,7 @@ typedef boost::network::http::server server; std::string password_callback( std::size_t max_length, - asio::ssl::context_base::password_purpose purpose) { + boost::asio::ssl::context_base::password_purpose purpose) { return std::string("test"); } @@ -55,29 +55,29 @@ struct handler { * @param signal * @param p_server_instance */ -void shut_me_down(const std::error_code& error, int signal, +void shut_me_down(const boost::system::error_code& error, int signal, std::shared_ptr p_server_instance) { if (!error) p_server_instance->stop(); } int main(void) try { - // setup asio::io_service - std::shared_ptr p_io_service( - std::make_shared()); + // setup boost::asio::io_service + std::shared_ptr p_io_service( + std::make_shared()); // Initialize SSL context - std::shared_ptr ctx = - std::make_shared( - asio::ssl::context::sslv23); - ctx->set_options(asio::ssl::context::default_workarounds | - asio::ssl::context::no_sslv2 | - asio::ssl::context::single_dh_use); + std::shared_ptr ctx = + std::make_shared( + boost::asio::ssl::context::sslv23); + ctx->set_options(boost::asio::ssl::context::default_workarounds | + boost::asio::ssl::context::no_sslv2 | + boost::asio::ssl::context::single_dh_use); // Set keys ctx->set_password_callback(password_callback); ctx->use_certificate_chain_file("server.pem"); - ctx->use_private_key_file("server.pem", asio::ssl::context::pem); + ctx->use_private_key_file("server.pem", boost::asio::ssl::context::pem); ctx->use_tmp_dh_file("dh2048.pem"); // setup the async server @@ -93,8 +93,8 @@ int main(void) try { .context(ctx))); // setup clean shutdown - asio::signal_set signals(*p_io_service, SIGINT, SIGTERM); - signals.async_wait([=] (std::error_code const &ec, int signal) { + boost::asio::signal_set signals(*p_io_service, SIGINT, SIGTERM); + signals.async_wait([=] (boost::system::error_code const &ec, int signal) { shut_me_down(ec, signal, p_server_instance); }); diff --git a/libs/network/example/http_client.cpp b/libs/network/example/http_client.cpp index 439176192..1a717805c 100644 --- a/libs/network/example/http_client.cpp +++ b/libs/network/example/http_client.cpp @@ -29,22 +29,22 @@ int main(int argc, char* argv[]) { ; options.parse_positional(std::vector{"source"}); - options.parse(argc, argv); + auto optionsResults = options.parse(argc, argv); - if (options.count("help")) { + if (optionsResults.count("help")) { std::cout << options.help({"", "Group"}) << std::endl; return EXIT_SUCCESS; } - if (options.count("source") < 1) { + if (optionsResults.count("source") < 1) { std::cout << "Error: Source URL required." << std::endl; std::cout << options.help({"", "Group"}) << std::endl; return EXIT_FAILURE; } - std::string source = options["source"].as(); - bool show_headers = options.count("headers") ? true : false; - bool show_status = options.count("status") ? true : false; + std::string source = optionsResults["source"].as(); + bool show_headers = optionsResults.count("headers") ? true : false; + bool show_status = optionsResults.count("status") ? true : false; http::client::request request(source); http::client::string_type destination_ = host(request); diff --git a/libs/network/src/CMakeLists.txt b/libs/network/src/CMakeLists.txt index 7a2ec731a..44617f827 100644 --- a/libs/network/src/CMakeLists.txt +++ b/libs/network/src/CMakeLists.txt @@ -29,9 +29,14 @@ set_target_properties(cppnetlib-client-connections PROPERTIES VERSION ${CPPNETLIB_VERSION_STRING} SOVERSION ${CPPNETLIB_VERSION_MAJOR} PUBLIC_HEADER "${CPP-NETLIB_HEADERS}") -target_link_libraries(cppnetlib-client-connections ${CMAKE_THREAD_LIBS_INIT}) +target_link_libraries(cppnetlib-client-connections ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT}) if (OPENSSL_FOUND) target_link_libraries(cppnetlib-client-connections ${OPENSSL_LIBRARIES}) + if (CPP-NETLIB_STATIC_OPENSSL) + if (NOT MSVC AND NOT MINGW AND NOT ${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD") # dynlinker functions are built into libc on FreeBSD + target_link_libraries(cppnetlib-client-connections "-ldl") + endif() + endif() endif () install(TARGETS cppnetlib-client-connections EXPORT cppnetlibTargets diff --git a/libs/network/src/server_request_parsers_impl.cpp b/libs/network/src/server_request_parsers_impl.cpp index 43c0d4721..d3670e924 100644 --- a/libs/network/src/server_request_parsers_impl.cpp +++ b/libs/network/src/server_request_parsers_impl.cpp @@ -6,10 +6,13 @@ #include #include +#include + #define BOOST_SPIRIT_UNICODE #include -#include +#include #include +#include namespace boost { namespace spirit { @@ -20,7 +23,7 @@ typedef std::basic_string u32_string; template <> // struct assign_to_container_from_value { static void call(u32_string const& val, std::string& attr) { - u32_to_u8_iterator begin = val.begin(), + boost::u32_to_u8_iterator begin = val.begin(), end = val.end(); for (; begin != end; ++begin) attr += *begin; } @@ -37,22 +40,20 @@ namespace http { void parse_version( std::string const& partial_parsed, std::tuple& version_pair) { - using namespace boost::spirit::qi; - parse(partial_parsed.begin(), partial_parsed.end(), - (lit("HTTP/") >> ushort_ >> '.' >> ushort_), version_pair); + boost::spirit::qi::parse(partial_parsed.begin(), partial_parsed.end(), + (boost::spirit::qi::lit("HTTP/") >> boost::spirit::qi::ushort_ >> '.' >> boost::spirit::qi::ushort_), version_pair); } void parse_headers( std::string const& input, std::vector& container) { - using namespace boost::spirit::qi; u8_to_u32_iterator begin = input.begin(), end = input.end(); - typedef as as_u32_string; - parse(begin, end, - *(+((alnum | punct) - ':') >> lit(": ") >> - as_u32_string()[+((unicode::alnum | space | punct) - '\r' - '\n')] >> - lit("\r\n")) >> - lit("\r\n"), + typedef boost::spirit::qi::as as_u32_string; + boost::spirit::qi::parse(begin, end, + *(+((boost::spirit::qi::alnum | boost::spirit::qi::punct) - ':') >> boost::spirit::qi::lit(": ") >> + as_u32_string()[+((boost::spirit::qi::unicode::alnum | boost::spirit::qi::space | boost::spirit::qi::punct) - '\r' - '\n')] >> + boost::spirit::qi::lit("\r\n")) >> + boost::spirit::qi::lit("\r\n"), container); } diff --git a/libs/network/test/CMakeLists.txt b/libs/network/test/CMakeLists.txt index b8ee7a59d..f4677c60a 100644 --- a/libs/network/test/CMakeLists.txt +++ b/libs/network/test/CMakeLists.txt @@ -20,7 +20,7 @@ if (Boost_FOUND) endif() add_executable(cpp-netlib-${test} ${test}.cpp) add_dependencies(cpp-netlib-${test} network-uri gtest_main) - target_link_libraries(cpp-netlib-${test} ${CMAKE_THREAD_LIBS_INIT} network-uri gtest_main) + target_link_libraries(cpp-netlib-${test} ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} network-uri gtest_main) if (OPENSSL_FOUND) target_link_libraries(cpp-netlib-${test} ${OPENSSL_LIBRARIES}) endif() diff --git a/libs/network/test/http/CMakeLists.txt b/libs/network/test/http/CMakeLists.txt index 5644c48b1..4565e21c8 100644 --- a/libs/network/test/http/CMakeLists.txt +++ b/libs/network/test/http/CMakeLists.txt @@ -21,7 +21,7 @@ if (Boost_FOUND) add_dependencies(cpp-netlib-http-${test} gtest_main network-uri) target_link_libraries(cpp-netlib-http-${test} - ${CMAKE_THREAD_LIBS_INIT} gtest_main + ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} gtest_main network-uri) if (${CMAKE_CXX_COMPILER_ID} MATCHES GNU AND ${CMAKE_SYSTEM_NAME} MATCHES "Windows") target_link_libraries(cpp-netlib-http-${test} ws2_32) @@ -39,13 +39,14 @@ if (Boost_FOUND) client_get_test client_get_different_port_test # client_get_timeout_test + client_get_ready_test client_get_streaming_test) foreach ( test ${TESTS} ) add_executable(cpp-netlib-http-${test} ${test}.cpp) add_dependencies(cpp-netlib-http-${test} network-uri cppnetlib-client-connections gtest_main) target_link_libraries(cpp-netlib-http-${test} - ${CMAKE_THREAD_LIBS_INIT} network-uri gtest_main cppnetlib-client-connections) + ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} network-uri gtest_main cppnetlib-client-connections) if (OPENSSL_FOUND) target_link_libraries(cpp-netlib-http-${test} ${OPENSSL_LIBRARIES}) endif() @@ -67,7 +68,7 @@ if (Boost_FOUND) add_executable(cpp-netlib-http-${test} ${test}.cpp) add_dependencies(cpp-netlib-http-${test} cppnetlib-server-parsers) target_link_libraries(cpp-netlib-http-${test} - ${CMAKE_THREAD_LIBS_INIT} cppnetlib-server-parsers gtest_main) + ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} cppnetlib-server-parsers gtest_main) if (OPENSSL_FOUND) target_link_libraries(cpp-netlib-http-${test} ${OPENSSL_LIBRARIES}) endif() @@ -89,7 +90,7 @@ if (Boost_FOUND) add_dependencies(cpp-netlib-http-server_async_run_stop_concurrency cppnetlib-server-parsers) target_link_libraries(cpp-netlib-http-server_async_run_stop_concurrency - ${CMAKE_THREAD_LIBS_INIT} cppnetlib-server-parsers) + ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} cppnetlib-server-parsers) if (OPENSSL_FOUND) target_link_libraries(cpp-netlib-http-server_async_run_stop_concurrency ${OPENSSL_LIBRARIES}) diff --git a/libs/network/test/http/client/CMakeLists.txt b/libs/network/test/http/client/CMakeLists.txt index 0bb197884..a0046a021 100644 --- a/libs/network/test/http/client/CMakeLists.txt +++ b/libs/network/test/http/client/CMakeLists.txt @@ -16,7 +16,7 @@ foreach(test ${TESTS}) add_executable(${test_name} ${test}.cpp) add_dependencies(${test_name} network-uri gtest_main) target_link_libraries(${test_name} - ${CMAKE_THREAD_LIBS_INIT} network-uri gtest_main) + ${CMAKE_THREAD_LIBS_INIT} ${Boost_LIBRARIES} network-uri gtest_main) set_target_properties(${test_name} PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/tests) add_test(${test_name} diff --git a/libs/network/test/http/client_constructor_test.cpp b/libs/network/test/http/client_constructor_test.cpp index 280e64070..735e5fc65 100644 --- a/libs/network/test/http/client_constructor_test.cpp +++ b/libs/network/test/http/client_constructor_test.cpp @@ -19,7 +19,7 @@ TYPED_TEST(HTTPClientTest, Constructors) { typename TypeParam::options options; TypeParam instance; TypeParam instance2( - options.io_service(std::make_shared())); + options.io_service(std::make_shared())); } TYPED_TEST(HTTPClientTest, ConstructorsWithOptions) { @@ -31,6 +31,6 @@ TYPED_TEST(HTTPClientTest, ConstructorsWithOptions) { options.openssl_certificate_file("foo").openssl_private_key_file("bar")); TypeParam instance4( options.follow_redirects(true) - .io_service(std::make_shared()) + .io_service(std::make_shared()) .cache_resolved(true)); } diff --git a/libs/network/test/http/client_get_different_port_test.cpp b/libs/network/test/http/client_get_different_port_test.cpp index 99a524874..a94839827 100644 --- a/libs/network/test/http/client_get_different_port_test.cpp +++ b/libs/network/test/http/client_get_different_port_test.cpp @@ -15,9 +15,12 @@ namespace http = boost::network::http; TYPED_TEST_CASE(HTTPClientTest, ClientTypes); TYPED_TEST(HTTPClientTest, GetDifferentPort) { - TypeParam client; - typename TypeParam::request r("http://www.boost.org:80/"); - auto response_ = client.get(r); + using client = TypeParam; + typename client::options options; + options.remove_chunk_markers(true); + client client_; + typename TypeParam::request request("http://www.boost.org:80/"); + auto response_ = client_.get(request); auto range = headers(response_)["Content-Type"]; EXPECT_TRUE(std::begin(range) != std::end(range)); EXPECT_NE(0, body(response_).size()); diff --git a/libs/network/test/http/client_get_ready_test.cpp b/libs/network/test/http/client_get_ready_test.cpp new file mode 100644 index 000000000..2aaf0fe49 --- /dev/null +++ b/libs/network/test/http/client_get_ready_test.cpp @@ -0,0 +1,34 @@ +// Copyright 2010 Dean Michael Berris. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#include +#include +#include "client_types.hpp" + +namespace net = boost::network; +namespace http = boost::network::http; +using tclock = std::chrono::high_resolution_clock; + +TYPED_TEST_CASE(HTTPClientTest, ClientTypes); + +TYPED_TEST(HTTPClientTest, GetTest) { + using client = TypeParam; + typename client::request request("http://cpp-netlib.org/"); + client client_; + auto response = client_.get(request); + while (!http::ready(response)) { + std::this_thread::sleep_for(std::chrono::milliseconds(10)); + } + auto t0 = tclock::now(); + auto data = body(response); + auto t1 = tclock::now(); + EXPECT_TRUE(response.status() == 200u || + (response.status() >= 300 && response.status() < 400)); + EXPECT_TRUE(data.size() > 0); + + // XXX we should find a better way to check if `ready()` has done his job + namespace c = std::chrono; + EXPECT_TRUE(c::duration_cast(t1-t0).count() < 1); +} diff --git a/libs/network/test/http/client_get_streaming_test.cpp b/libs/network/test/http/client_get_streaming_test.cpp index 9934f6dc5..f08d24a6a 100644 --- a/libs/network/test/http/client_get_streaming_test.cpp +++ b/libs/network/test/http/client_get_streaming_test.cpp @@ -25,14 +25,18 @@ struct body_handler { TYPED_TEST_CASE(HTTPClientTest, ClientTypes); +#ifdef BOOST_NETWORK_ENABLE_HTTPS TYPED_TEST(HTTPClientTest, GetStreamingTest) { - typename TypeParam::request request("http://www.boost.org"); + typename TypeParam::request request("https://www.boost.org"); typename TypeParam::response response; typename TypeParam::string_type body_string; typename TypeParam::string_type dummy_body; body_handler handler_instance(body_string); { - TypeParam client_; + using client = TypeParam; + typename client::options options; + options.remove_chunk_markers(true); + client client_(options); ASSERT_NO_THROW(response = client_.get(request, handler_instance)); auto range = headers(response)["Content-Type"]; ASSERT_TRUE(!boost::empty(range)); @@ -44,3 +48,4 @@ TYPED_TEST(HTTPClientTest, GetStreamingTest) { } EXPECT_EQ(dummy_body, typename TypeParam::string_type()); } +#endif diff --git a/libs/network/test/http/client_get_test.cpp b/libs/network/test/http/client_get_test.cpp index 75b437e24..15997bd83 100644 --- a/libs/network/test/http/client_get_test.cpp +++ b/libs/network/test/http/client_get_test.cpp @@ -1,4 +1,5 @@ // Copyright 2010 Dean Michael Berris. +// Copyright 2017 Google, Inc. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) @@ -15,7 +16,9 @@ TYPED_TEST_CASE(HTTPClientTest, ClientTypes); TYPED_TEST(HTTPClientTest, GetTest) { using client = TypeParam; typename client::request request("http://cpp-netlib.org/"); - client client_; + typename client::options options; + options.remove_chunk_markers(true); + client client_(options); typename client::response response; ASSERT_NO_THROW(response = client_.get(request)); try { @@ -34,7 +37,9 @@ TYPED_TEST(HTTPClientTest, GetTest) { TYPED_TEST(HTTPClientTest, GetHTTPSTest) { using client = TypeParam; typename client::request request("https://www.github.com/"); - client client_; + typename client::options options; + options.remove_chunk_markers(true); + client client_(options); typename client::response response = client_.get(request); EXPECT_TRUE(response.status() == 200 || (response.status() >= 300 && response.status() < 400)); @@ -52,7 +57,9 @@ TYPED_TEST(HTTPClientTest, TemporaryClientObjectTest) { using client = TypeParam; typename client::request request("http://cpp-netlib.org/"); typename client::response response; - ASSERT_NO_THROW(response = client().get(request)); + typename client::options options; + options.remove_chunk_markers(true); + ASSERT_NO_THROW(response = client(options).get(request)); auto range = headers(response); ASSERT_TRUE(!boost::empty(range)); try { @@ -65,3 +72,13 @@ TYPED_TEST(HTTPClientTest, TemporaryClientObjectTest) { EXPECT_TRUE(response.status() == 200u || (response.status() >= 300 && response.status() < 400)); } + +TYPED_TEST(HTTPClientTest, PropagatesResolutionErrorsTest) { + using client = TypeParam; + typename client::request request("http://malformed.google.comq"); + typename client::response response; + typename client::options options; + typename client::string_type response_body; + ASSERT_NO_THROW(response = client(options).get(request)); + EXPECT_THROW(response_body = body(response), std::exception); +} diff --git a/libs/network/test/http/request_incremental_parser_test.cpp b/libs/network/test/http/request_incremental_parser_test.cpp index 9120294f5..f8c8f5577 100644 --- a/libs/network/test/http/request_incremental_parser_test.cpp +++ b/libs/network/test/http/request_incremental_parser_test.cpp @@ -52,7 +52,7 @@ TEST(IncrementalRequestParserTest, ParseMethod) { p.reset(); std::tie(parsed_ok, result_range) = p.parse_until(request_parser_type::method_done, invalid_http_method); - EXPECT_EQ(false, parsed_ok); + EXPECT_FALSE(parsed_ok); parsed.assign(std::begin(result_range), std::end(result_range)); std::cout << "PARSED: " << parsed << " [state:" << p.state() << "] " << std::endl; @@ -68,7 +68,7 @@ TEST(IncrementalRequestParserTest, ParseURI) { std::string valid_http_request = "GET / HTTP/1.1\r\n"; std::tie(parsed_ok, result_range) = p.parse_until(request_parser_type::uri_done, valid_http_request); - EXPECT_EQ(true, parsed_ok); + EXPECT_TRUE(parsed_ok); EXPECT_FALSE(boost::empty(result_range)); std::string parsed(std::begin(result_range), std::end(result_range)); std::cout << "PARSED: " << parsed << " [state:" << p.state() << "] " @@ -78,7 +78,7 @@ TEST(IncrementalRequestParserTest, ParseURI) { p.reset(); std::tie(parsed_ok, result_range) = p.parse_until(request_parser_type::uri_done, invalid_http_request); - EXPECT_EQ(false, parsed_ok); + EXPECT_FALSE(parsed_ok); parsed.assign(std::begin(result_range), std::end(result_range)); std::cout << "PARSED: " << parsed << " [state:" << p.state() << "] " << std::endl; @@ -104,7 +104,7 @@ TEST(IncrementalRequestParserTest, ParseHTTPVersion) { p.reset(); std::tie(parsed_ok, result_range) = p.parse_until(request_parser_type::version_done, invalid_http_request); - EXPECT_EQ(false, parsed_ok); + EXPECT_FALSE(parsed_ok); parsed.assign(std::begin(result_range), std::end(result_range)); std::cout << "PARSED: " << parsed << " [state:" << p.state() << "] " << std::endl; @@ -121,7 +121,7 @@ TEST(IncrementalRequestParserTest, ParseHTTPHeaders) { "GET / HTTP/1.1\r\nHost: cpp-netlib.org\r\n\r\n"; std::tie(parsed_ok, result_range) = p.parse_until(request_parser_type::headers_done, valid_http_request); - EXPECT_EQ(true, parsed_ok); + EXPECT_TRUE(parsed_ok); EXPECT_FALSE(boost::empty(result_range)); std::string parsed(std::begin(result_range), std::end(result_range)); std::cout << "PARSED: " << parsed << " [state:" << p.state() << "] " diff --git a/libs/network/test/http/response_incremental_parser_test.cpp b/libs/network/test/http/response_incremental_parser_test.cpp index 0642ce803..aeaa88cc5 100644 --- a/libs/network/test/http/response_incremental_parser_test.cpp +++ b/libs/network/test/http/response_incremental_parser_test.cpp @@ -82,7 +82,7 @@ TEST(IncrementalResponseParserTest, ParseHTTPVersion) { std::string valid_http_version = "HTTP/1.0 "; std::tie(parsed_ok, result_range) = p.parse_until( response_parser_type::http_version_done, valid_http_version); - EXPECT_EQ(true, parsed_ok); + EXPECT_TRUE(parsed_ok); EXPECT_FALSE(boost::empty(result_range)); std::string parsed(std::begin(result_range), std::end(result_range)); std::cout << "PARSED: " << parsed << " state=" << p.state() << std::endl; @@ -90,7 +90,7 @@ TEST(IncrementalResponseParserTest, ParseHTTPVersion) { valid_http_version = "HTTP/1.1 "; std::tie(parsed_ok, result_range) = p.parse_until( response_parser_type::http_version_done, valid_http_version); - EXPECT_EQ(true, parsed_ok); + EXPECT_TRUE(parsed_ok); EXPECT_FALSE(boost::empty(result_range)); parsed.assign(std::begin(result_range), std::end(result_range)); std::cout << "PARSED: " << parsed << " state=" << p.state() << std::endl; @@ -100,7 +100,7 @@ TEST(IncrementalResponseParserTest, ParseHTTPVersion) { parsed_ok = logic::indeterminate; std::tie(parsed_ok, result_range) = p.parse_until( response_parser_type::http_version_done, invalid_http_version); - EXPECT_EQ(false, parsed_ok); + EXPECT_FALSE(parsed_ok); parsed.assign(std::begin(result_range), std::end(result_range)); std::cout << "PARSED: " << parsed << " state=" << p.state() << std::endl; @@ -109,7 +109,7 @@ TEST(IncrementalResponseParserTest, ParseHTTPVersion) { parsed_ok = logic::indeterminate; std::tie(parsed_ok, result_range) = p.parse_until( response_parser_type::http_version_done, valid_http_version); - EXPECT_EQ(true, parsed_ok); + EXPECT_TRUE(parsed_ok); parsed.assign(std::begin(result_range), std::end(result_range)); std::cout << "PARSED: " << parsed << " state=" << p.state() << std::endl; } @@ -137,7 +137,7 @@ TYPED_TEST(IncrementalResponseEOLTypeTest, ParseStatus) { range_type result_range; std::tie(parsed_ok, result_range) = p.parse_until(response_parser_type::http_status_done, valid_status); - EXPECT_EQ(true, parsed_ok); + EXPECT_TRUE(parsed_ok); std::string parsed = std::string(std::begin(result_range), std::end(result_range)); std::cout << "PARSED: " << parsed << " state=" << p.state() << std::endl; @@ -153,7 +153,7 @@ TYPED_TEST(IncrementalResponseEOLTypeTest, ParseStatus) { valid_status = "200" + TypeParam::literal; std::tie(parsed_ok, result_range) = p.parse_until(response_parser_type::http_status_done, valid_status); - EXPECT_EQ(true, parsed_ok); + EXPECT_TRUE(parsed_ok); parsed = std::string(std::begin(result_range), std::end(result_range)); std::cout << "PARSED: " << parsed << " state=" << p.state() << std::endl; } @@ -171,7 +171,7 @@ TYPED_TEST(IncrementalResponseEOLTypeTest, ParseStatusMessage) { range_type result_range; std::tie(parsed_ok, result_range) = p.parse_until( response_parser_type::http_status_message_done, valid_status_message); - EXPECT_EQ(true, parsed_ok); + EXPECT_TRUE(parsed_ok); std::string parsed = std::string(std::begin(result_range), std::end(result_range)); std::cout << "PARSED: " << parsed << " state=" << p.state() << std::endl; @@ -180,7 +180,7 @@ TYPED_TEST(IncrementalResponseEOLTypeTest, ParseStatusMessage) { valid_status_message = "OK" + TypeParam::literal; std::tie(parsed_ok, result_range) = p.parse_until( response_parser_type::http_status_message_done, valid_status_message); - EXPECT_EQ(true, parsed_ok); + EXPECT_TRUE(parsed_ok); parsed = std::string(std::begin(result_range), std::end(result_range)); std::cout << "PARSED: " << parsed << " state=" << p.state() << std::endl; @@ -188,7 +188,7 @@ TYPED_TEST(IncrementalResponseEOLTypeTest, ParseStatusMessage) { valid_status_message = "Internal Server Error" + TypeParam::literal; std::tie(parsed_ok, result_range) = p.parse_until( response_parser_type::http_status_message_done, valid_status_message); - EXPECT_EQ(true, parsed_ok); + EXPECT_TRUE(parsed_ok); parsed = std::string(std::begin(result_range), std::end(result_range)); std::cout << "PARSED: " << parsed << " state=" << p.state() << std::endl; @@ -196,7 +196,7 @@ TYPED_TEST(IncrementalResponseEOLTypeTest, ParseStatusMessage) { valid_status_message = TypeParam::literal; std::tie(parsed_ok, result_range) = p.parse_until( response_parser_type::http_status_message_done, valid_status_message); - EXPECT_EQ(true, parsed_ok); + EXPECT_TRUE(parsed_ok); parsed = std::string(std::begin(result_range), std::end(result_range)); std::cout << "PARSED: " << parsed << " state=" << p.state() << std::endl; @@ -204,7 +204,7 @@ TYPED_TEST(IncrementalResponseEOLTypeTest, ParseStatusMessage) { valid_status_message = "한글메시지" + TypeParam::literal; std::tie(parsed_ok, result_range) = p.parse_until( response_parser_type::http_status_message_done, valid_status_message); - EXPECT_EQ(true, parsed_ok); + EXPECT_TRUE(parsed_ok); parsed = std::string(std::begin(result_range), std::end(result_range)); std::cout << "PARSED: " << parsed << " state=" << p.state() << std::endl; } @@ -224,7 +224,7 @@ TYPED_TEST(IncrementalResponseEOLTypeTest, ParseHTTPHeaders) { range_type result_range; std::tie(parsed_ok, result_range) = p.parse_until(response_parser_type::http_header_line_done, valid_headers); - EXPECT_EQ(true, parsed_ok); + EXPECT_TRUE(parsed_ok); std::string parsed1 = std::string(std::begin(result_range), std::end(result_range)); std::cout << "PARSED: " << parsed1 << " state=" << p.state() << std::endl; @@ -233,7 +233,7 @@ TYPED_TEST(IncrementalResponseEOLTypeTest, ParseHTTPHeaders) { valid_headers.assign(std::end(result_range), end); std::tie(parsed_ok, result_range) = p.parse_until(response_parser_type::http_header_line_done, valid_headers); - EXPECT_EQ(true, parsed_ok); + EXPECT_TRUE(parsed_ok); std::string parsed2 = std::string(std::begin(result_range), std::end(result_range)); std::cout << "PARSED: " << parsed2 << " state=" << p.state() << std::endl; @@ -241,7 +241,7 @@ TYPED_TEST(IncrementalResponseEOLTypeTest, ParseHTTPHeaders) { p.reset(response_parser_type::http_status_message_done); std::tie(parsed_ok, result_range) = p.parse_until(response_parser_type::http_headers_done, valid_headers); - EXPECT_EQ(true, parsed_ok); + EXPECT_TRUE(parsed_ok); EXPECT_NE(parsed1, parsed2); p.reset(response_parser_type::http_status_message_done); @@ -250,7 +250,7 @@ TYPED_TEST(IncrementalResponseEOLTypeTest, ParseHTTPHeaders) { eol::literal; std::tie(parsed_ok, result_range) = p.parse_until(response_parser_type::http_header_line_done, valid_headers); - EXPECT_EQ(true, parsed_ok); + EXPECT_TRUE(parsed_ok); parsed1 = std::string(std::begin(result_range), std::end(result_range)); std::cout << "PARSED: " << parsed1 << " state=" << p.state() << std::endl; p.reset(response_parser_type::http_status_message_done); @@ -258,14 +258,14 @@ TYPED_TEST(IncrementalResponseEOLTypeTest, ParseHTTPHeaders) { valid_headers.assign(std::end(result_range), end); std::tie(parsed_ok, result_range) = p.parse_until(response_parser_type::http_header_line_done, valid_headers); - EXPECT_EQ(true, parsed_ok); + EXPECT_TRUE(parsed_ok); parsed2 = std::string(std::begin(result_range), std::end(result_range)); std::cout << "PARSED: " << parsed2 << " state=" << p.state() << std::endl; valid_headers.assign(std::end(result_range), end); p.reset(response_parser_type::http_status_message_done); std::tie(parsed_ok, result_range) = p.parse_until(response_parser_type::http_headers_done, valid_headers); - EXPECT_EQ(true, parsed_ok); + EXPECT_TRUE(parsed_ok); EXPECT_NE(parsed1, parsed2); p.reset(response_parser_type::http_status_message_done); @@ -274,7 +274,7 @@ TYPED_TEST(IncrementalResponseEOLTypeTest, ParseHTTPHeaders) { eol::literal; std::tie(parsed_ok, result_range) = p.parse_until(response_parser_type::http_header_line_done, valid_headers); - EXPECT_EQ(true, parsed_ok); + EXPECT_TRUE(parsed_ok); parsed1 = std::string(std::begin(result_range), std::end(result_range)); std::cout << "PARSED: " << parsed1 << " state=" << p.state() << std::endl; p.reset(response_parser_type::http_status_message_done); @@ -282,14 +282,14 @@ TYPED_TEST(IncrementalResponseEOLTypeTest, ParseHTTPHeaders) { valid_headers.assign(std::end(result_range), end); std::tie(parsed_ok, result_range) = p.parse_until(response_parser_type::http_header_line_done, valid_headers); - EXPECT_EQ(true, parsed_ok); + EXPECT_TRUE(parsed_ok); parsed2 = std::string(std::begin(result_range), std::end(result_range)); std::cout << "PARSED: " << parsed2 << " state=" << p.state() << std::endl; valid_headers.assign(std::end(result_range), end); p.reset(response_parser_type::http_status_message_done); std::tie(parsed_ok, result_range) = p.parse_until(response_parser_type::http_headers_done, valid_headers); - EXPECT_EQ(true, parsed_ok); + EXPECT_TRUE(parsed_ok); EXPECT_NE(parsed1, parsed2); p.reset(response_parser_type::http_status_message_done); @@ -297,7 +297,7 @@ TYPED_TEST(IncrementalResponseEOLTypeTest, ParseHTTPHeaders) { eol::literal + eol::literal; std::tie(parsed_ok, result_range) = p.parse_until(response_parser_type::http_header_line_done, valid_headers); - EXPECT_EQ(true, parsed_ok); + EXPECT_TRUE(parsed_ok); parsed1 = std::string(std::begin(result_range), std::end(result_range)); std::cout << "PARSED: " << parsed1 << " state=" << p.state() << std::endl; p.reset(response_parser_type::http_status_message_done); @@ -305,14 +305,14 @@ TYPED_TEST(IncrementalResponseEOLTypeTest, ParseHTTPHeaders) { valid_headers.assign(std::end(result_range), end); std::tie(parsed_ok, result_range) = p.parse_until(response_parser_type::http_header_line_done, valid_headers); - EXPECT_EQ(true, parsed_ok); + EXPECT_TRUE(parsed_ok); parsed2 = std::string(std::begin(result_range), std::end(result_range)); std::cout << "PARSED: " << parsed2 << " state=" << p.state() << std::endl; valid_headers.assign(std::end(result_range), end); p.reset(response_parser_type::http_status_message_done); std::tie(parsed_ok, result_range) = p.parse_until(response_parser_type::http_headers_done, valid_headers); - EXPECT_EQ(true, parsed_ok); + EXPECT_TRUE(parsed_ok); EXPECT_NE(parsed1, parsed2); p.reset(response_parser_type::http_status_message_done); @@ -321,7 +321,7 @@ TYPED_TEST(IncrementalResponseEOLTypeTest, ParseHTTPHeaders) { eol::literal; std::tie(parsed_ok, result_range) = p.parse_until(response_parser_type::http_header_line_done, valid_headers); - EXPECT_EQ(true, parsed_ok); + EXPECT_TRUE(parsed_ok); parsed1 = std::string(std::begin(result_range), std::end(result_range)); std::cout << "PARSED: " << parsed1 << " state=" << p.state() << std::endl; p.reset(response_parser_type::http_status_message_done); @@ -329,14 +329,14 @@ TYPED_TEST(IncrementalResponseEOLTypeTest, ParseHTTPHeaders) { valid_headers.assign(std::end(result_range), end); std::tie(parsed_ok, result_range) = p.parse_until(response_parser_type::http_header_line_done, valid_headers); - EXPECT_EQ(true, parsed_ok); + EXPECT_TRUE(parsed_ok); parsed2 = std::string(std::begin(result_range), std::end(result_range)); std::cout << "PARSED: " << parsed2 << " state=" << p.state() << std::endl; valid_headers.assign(std::end(result_range), end); p.reset(response_parser_type::http_status_message_done); std::tie(parsed_ok, result_range) = p.parse_until(response_parser_type::http_headers_done, valid_headers); - EXPECT_EQ(true, parsed_ok); + EXPECT_TRUE(parsed_ok); EXPECT_NE(parsed1, parsed2); p.reset(response_parser_type::http_status_message_done); @@ -344,7 +344,7 @@ TYPED_TEST(IncrementalResponseEOLTypeTest, ParseHTTPHeaders) { eol::literal + eol::literal; std::tie(parsed_ok, result_range) = p.parse_until(response_parser_type::http_header_line_done, valid_headers); - EXPECT_EQ(true, parsed_ok); + EXPECT_TRUE(parsed_ok); parsed1 = std::string(std::begin(result_range), std::end(result_range)); std::cout << "PARSED: " << parsed1 << " state=" << p.state() << std::endl; p.reset(response_parser_type::http_status_message_done); @@ -352,13 +352,13 @@ TYPED_TEST(IncrementalResponseEOLTypeTest, ParseHTTPHeaders) { valid_headers.assign(std::end(result_range), end); std::tie(parsed_ok, result_range) = p.parse_until(response_parser_type::http_header_line_done, valid_headers); - EXPECT_EQ(true, parsed_ok); + EXPECT_TRUE(parsed_ok); parsed2 = std::string(std::begin(result_range), std::end(result_range)); std::cout << "PARSED: " << parsed2 << " state=" << p.state() << std::endl; valid_headers.assign(std::end(result_range), end); p.reset(response_parser_type::http_status_message_done); std::tie(parsed_ok, result_range) = p.parse_until(response_parser_type::http_headers_done, valid_headers); - EXPECT_EQ(true, parsed_ok); + EXPECT_TRUE(parsed_ok); EXPECT_NE(parsed1, parsed2); } diff --git a/libs/network/test/http/server_constructor_test.cpp b/libs/network/test/http/server_constructor_test.cpp index ea38f50b3..11b08720a 100644 --- a/libs/network/test/http/server_constructor_test.cpp +++ b/libs/network/test/http/server_constructor_test.cpp @@ -31,7 +31,7 @@ TEST(HTTPServerTest, MinimalConstructor) { TEST(HTTPServerTest, WithIOServiceParameter) { dummy_async_handler async_handler; std::shared_ptr thread_pool; - std::shared_ptr io_service; + std::shared_ptr io_service; async_server::options async_options(async_handler); ASSERT_NO_THROW(async_server async_instance(async_options.address("127.0.0.1") @@ -43,7 +43,7 @@ TEST(HTTPServerTest, WithIOServiceParameter) { TEST(HTTPServerTes, ThrowsOnFailure) { dummy_async_handler async_handler; std::shared_ptr thread_pool; - std::shared_ptr io_service; + std::shared_ptr io_service; async_server::options async_options(async_handler); async_server async_instance(async_options.address("127.0.0.1") .port("80") diff --git a/libs/network/test/http_server_async_less_copy.cpp b/libs/network/test/http_server_async_less_copy.cpp index a957f05ff..d4a234d41 100644 --- a/libs/network/test/http_server_async_less_copy.cpp +++ b/libs/network/test/http_server_async_less_copy.cpp @@ -55,11 +55,11 @@ struct async_hello_world { connection->set_headers(boost::make_iterator_range(headers, headers + 3)); std::vector iovec; iovec.push_back(asio::const_buffer(hello_world, 13)); - connection->write(iovec, [this] (std::error_code const &ec) { error(ec); }); + connection->write(iovec, [this] (boost::system::error_code const &ec) { error(ec); }); } } - void error(std::error_code const& ec) { + void error(boost::system::error_code const& ec) { // do nothing here. } };