Compare commits
131 Commits
0.33.0-hf1
...
0.40.0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7fc780dd70 | ||
|
|
4d7b1a3b61 | ||
|
|
9a9dffa4ff | ||
|
|
51e7f595bb | ||
|
|
293e520efc | ||
|
|
9e960ff6b8 | ||
|
|
0a8e690917 | ||
|
|
cf60d4c30e | ||
|
|
8f2480225b | ||
|
|
44167a6bcb | ||
|
|
db95808206 | ||
|
|
fd901f8081 | ||
|
|
b6ce0aa75a | ||
|
|
b712125bc0 | ||
|
|
d69b16895c | ||
|
|
d198b439fd | ||
|
|
83aa5517c0 | ||
|
|
5711e7caa9 | ||
|
|
8d0c93691d | ||
|
|
d8d0cb17ba | ||
|
|
47a919faf0 | ||
|
|
d572de769b | ||
|
|
810a6b0f30 | ||
|
|
665ad180cb | ||
|
|
361917e902 | ||
|
|
4b261b12a4 | ||
|
|
afd4b45036 | ||
|
|
47adc728db | ||
|
|
7e39d645b9 | ||
|
|
35504f1723 | ||
|
|
61d9dda4e0 | ||
|
|
38ca9d4a97 | ||
|
|
f37aa1d6c8 | ||
|
|
db13ddf844 | ||
|
|
bf642404c7 | ||
|
|
d53d5cfc42 | ||
|
|
bbf52056f9 | ||
|
|
b8cae2dfaf | ||
|
|
795ee8bb5e | ||
|
|
cfcd618aa6 | ||
|
|
19258cf980 | ||
|
|
cdaafeb4b6 | ||
|
|
7688a97d95 | ||
|
|
027b289c91 | ||
|
|
b55edfa8f0 | ||
|
|
7d46d153c6 | ||
|
|
96b17749af | ||
|
|
f27348c4d5 | ||
|
|
c6923dcf88 | ||
|
|
f456355da2 | ||
|
|
97806b42c4 | ||
|
|
ed02b0717e | ||
|
|
2963e91752 | ||
|
|
aa11effdd6 | ||
|
|
6e9c15af92 | ||
|
|
0ddeb29c35 | ||
|
|
a7630aaa55 | ||
|
|
1d15af6afd | ||
|
|
dd0075f2b8 | ||
|
|
4b0d8b630c | ||
|
|
b421559a47 | ||
|
|
05e7373086 | ||
|
|
bb0b97f46b | ||
|
|
3b639afac2 | ||
|
|
bd93ecbd6b | ||
|
|
79159ffd87 | ||
|
|
231a5ae6fb | ||
|
|
45249e8746 | ||
|
|
e6ed9ae4d8 | ||
|
|
aca6db5601 | ||
|
|
8e9f9599b8 | ||
|
|
71d7d87bf3 | ||
|
|
7ffef30f1c | ||
|
|
7c90b9ef88 | ||
|
|
4bb74196c0 | ||
|
|
35fa20a110 | ||
|
|
633cf86ad8 | ||
|
|
66ce8779e8 | ||
|
|
a9b3042d7e | ||
|
|
4df24c0e8e | ||
|
|
9a988963e9 | ||
|
|
5be33a650d | ||
|
|
5b09dc731f | ||
|
|
51d7e7336f | ||
|
|
ad9be4dbf6 | ||
|
|
2f9a8440c2 | ||
|
|
a40dd2690a | ||
|
|
104f12a9e2 | ||
|
|
e499743cdd | ||
|
|
241795cd73 | ||
|
|
411b2534ed | ||
|
|
253f138aff | ||
|
|
dadbab4c0f | ||
|
|
d9017a3f76 | ||
|
|
aedfaab93d | ||
|
|
d263d4d449 | ||
|
|
b39e4817e5 | ||
|
|
4dfa250a34 | ||
|
|
8a6908c072 | ||
|
|
d8fe737ad7 | ||
|
|
61023c3f4a | ||
|
|
b607d47bd3 | ||
|
|
878c0f2a19 | ||
|
|
19dd983d2b | ||
|
|
c15751ced6 | ||
|
|
a55d9aa4c3 | ||
|
|
037d52114a | ||
|
|
3ff56eb071 | ||
|
|
9e8a5a5765 | ||
|
|
461a8ea846 | ||
|
|
8d9c0daa9d | ||
|
|
1537527927 | ||
|
|
8204d9524e | ||
|
|
07bf106cd3 | ||
|
|
225b5a1204 | ||
|
|
054d5de877 | ||
|
|
5349bcc1c5 | ||
|
|
17fd2ef2e2 | ||
|
|
e199c0555c | ||
|
|
42557b800c | ||
|
|
ef2330d477 | ||
|
|
f8a1ec0348 | ||
|
|
8375ae647e | ||
|
|
69da298aa7 | ||
|
|
6765507cc4 | ||
|
|
e2c67a1666 | ||
|
|
6397025435 | ||
|
|
2a448065da | ||
|
|
5c7130e4fd | ||
|
|
bbad20c66f | ||
|
|
c4c8a620c8 |
5
.gitignore
vendored
@@ -1,5 +1,9 @@
|
||||
# .gitignore
|
||||
|
||||
bin/boostbook_catalog.xml
|
||||
bin/config.log
|
||||
bin/project-cache.jam
|
||||
|
||||
# Ignore vim swap files.
|
||||
*.swp
|
||||
|
||||
@@ -89,3 +93,4 @@ Builds/VisualStudio2015/*.sdf
|
||||
|
||||
# MSVC
|
||||
*.pdb
|
||||
.vs/
|
||||
|
||||
12
.gitmodules
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
[submodule "docs/docca"]
|
||||
path = docs/docca
|
||||
url = https://github.com/vinniefalco/docca.git
|
||||
[submodule "src/nudb/extras/beast"]
|
||||
path = src/nudb/extras/beast
|
||||
url = https://github.com/vinniefalco/Beast.git
|
||||
[submodule "src/nudb/extras/rocksdb"]
|
||||
path = src/nudb/extras/rocksdb
|
||||
url = https://github.com/facebook/rocksdb.git
|
||||
[submodule "src/nudb/doc/docca"]
|
||||
path = src/nudb/doc/docca
|
||||
url = https://github.com/vinniefalco/docca.git
|
||||
48
.travis.yml
@@ -11,51 +11,57 @@ env:
|
||||
# to boost's .tar.gz.
|
||||
- LCOV_ROOT=$HOME/lcov
|
||||
- BOOST_ROOT=$HOME/boost_1_60_0
|
||||
- BOOST_URL='http://downloads.sourceforge.net/project/boost/boost/1.60.0/boost_1_60_0.tar.gz?r=https%3A%2F%2Fsourceforge.net%2Fprojects%2Fboost%2Ffiles%2Fboost%2F1.60.0%2Fboost_1_60_0.tar.gz&ts=1460417589&use_mirror=netix'
|
||||
- BOOST_URL='http://sourceforge.net/projects/boost/files/boost/1.60.0/boost_1_60_0.tar.gz'
|
||||
|
||||
packages: &gcc5_pkgs
|
||||
- gcc-5
|
||||
- g++-5
|
||||
- python-software-properties
|
||||
- protobuf-compiler
|
||||
- libprotobuf-dev
|
||||
- libssl-dev
|
||||
- libstdc++6
|
||||
- binutils-gold
|
||||
# Provides a backtrace if the unittests crash
|
||||
- gdb
|
||||
addons:
|
||||
apt:
|
||||
sources: ['ubuntu-toolchain-r-test']
|
||||
packages:
|
||||
- gcc-5
|
||||
- g++-5
|
||||
- python-software-properties
|
||||
- protobuf-compiler
|
||||
- libprotobuf-dev
|
||||
- libssl-dev
|
||||
- libstdc++6
|
||||
- binutils-gold
|
||||
# Provides a backtrace if the unittests crash
|
||||
- gdb
|
||||
|
||||
matrix:
|
||||
include:
|
||||
# Default BUILD is "scons".
|
||||
|
||||
- compiler: gcc
|
||||
env: GCC_VER=5 TARGET=debug.nounity
|
||||
addons: &ao_gcc5
|
||||
apt:
|
||||
sources: ['ubuntu-toolchain-r-test']
|
||||
packages: *gcc5_pkgs
|
||||
env: GCC_VER=5 BUILD=cmake TARGET=debug.nounity PATH=$PWD/cmake/bin:$PATH
|
||||
|
||||
- compiler: gcc
|
||||
env: GCC_VER=5 TARGET=coverage
|
||||
addons: *ao_gcc5
|
||||
|
||||
- compiler: clang
|
||||
env: GCC_VER=5 TARGET=debug CLANG_VER=3.8 PATH=$PWD/llvm-$LLVM_VERSION/bin:$PATH
|
||||
addons: *ao_gcc5
|
||||
|
||||
- compiler: clang
|
||||
env: GCC_VER=5 TARGET=debug.nounity CLANG_VER=3.8 PATH=$PWD/llvm-$LLVM_VERSION/bin:$PATH
|
||||
addons: *ao_gcc5
|
||||
|
||||
# The clang cmake builds do not link.
|
||||
# - compiler: clang
|
||||
# env: GCC_VER=5 BUILD=cmake TARGET=debug CLANG_VER=3.8 PATH=$PWD/llvm-$LLVM_VERSION/bin:$PWD/cmake/bin:$PATH
|
||||
|
||||
# - compiler: clang
|
||||
# env: GCC_VER=5 BUILD=cmake TARGET=debug.nounity CLANG_VER=3.8 PATH=$PWD/llvm-$LLVM_VERSION/bin:$PWD/cmake/bin:$PATH
|
||||
|
||||
cache:
|
||||
directories:
|
||||
- $BOOST_ROOT
|
||||
- llvm-$LLVM_VERSION
|
||||
- cmake
|
||||
|
||||
before_install:
|
||||
- bin/ci/ubuntu/install-dependencies.sh
|
||||
|
||||
script:
|
||||
- bin/ci/ubuntu/build-and-test.sh
|
||||
- travis_retry bin/ci/ubuntu/build-and-test.sh
|
||||
|
||||
notifications:
|
||||
email:
|
||||
|
||||
658
Builds/CMake/CMakeFuncs.cmake
Normal file
@@ -0,0 +1,658 @@
|
||||
# This is a set of common functions and settings for rippled
|
||||
# and derived products.
|
||||
|
||||
############################################################
|
||||
|
||||
cmake_minimum_required(VERSION 3.1.0)
|
||||
|
||||
if("${CMAKE_SOURCE_DIR}" STREQUAL "${CMAKE_BINARY_DIR}")
|
||||
message(WARNING "Builds are strongly discouraged in "
|
||||
"${CMAKE_SOURCE_DIR}.")
|
||||
endif()
|
||||
|
||||
macro(parse_target)
|
||||
|
||||
if (NOT target AND NOT CMAKE_BUILD_TYPE)
|
||||
if (APPLE)
|
||||
set(target clang.debug)
|
||||
elseif(WIN32)
|
||||
set(target msvc)
|
||||
else()
|
||||
set(target gcc.debug)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if (target)
|
||||
# Parse the target
|
||||
set(remaining ${target})
|
||||
while (remaining)
|
||||
# get the component up to the next dot or end
|
||||
string(REGEX REPLACE "^\\.?([^\\.]+).*$" "\\1" cur_component ${remaining})
|
||||
string(REGEX REPLACE "^\\.?[^\\.]+(.*$)" "\\1" remaining ${remaining})
|
||||
|
||||
if (${cur_component} STREQUAL gcc)
|
||||
if (DEFINED ENV{GNU_CC})
|
||||
set(CMAKE_C_COMPILER $ENV{GNU_CC})
|
||||
elseif ($ENV{CXX} MATCHES .*gcc.*)
|
||||
set(CMAKE_CXX_COMPILER $ENV{CC})
|
||||
else()
|
||||
find_program(CMAKE_C_COMPILER gcc)
|
||||
endif()
|
||||
|
||||
if (DEFINED ENV{GNU_CXX})
|
||||
set(CMAKE_C_COMPILER $ENV{GNU_CXX})
|
||||
elseif ($ENV{CXX} MATCHES .*g\\+\\+.*)
|
||||
set(CMAKE_C_COMPILER $ENV{CC})
|
||||
else()
|
||||
find_program(CMAKE_CXX_COMPILER g++)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if (${cur_component} STREQUAL clang)
|
||||
if (DEFINED ENV{CLANG_CC})
|
||||
set(CMAKE_C_COMPILER $ENV{CLANG_CC})
|
||||
elseif ($ENV{CXX} MATCHES .*clang.*)
|
||||
set(CMAKE_CXX_COMPILER $ENV{CC})
|
||||
else()
|
||||
find_program(CMAKE_C_COMPILER clang)
|
||||
endif()
|
||||
|
||||
if (DEFINED ENV{CLANG_CXX})
|
||||
set(CMAKE_C_COMPILER $ENV{CLANG_CXX})
|
||||
elseif ($ENV{CXX} MATCHES .*clang.*)
|
||||
set(CMAKE_C_COMPILER $ENV{CC})
|
||||
else()
|
||||
find_program(CMAKE_CXX_COMPILER clang++)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if (${cur_component} STREQUAL msvc)
|
||||
# TBD
|
||||
endif()
|
||||
|
||||
if (${cur_component} STREQUAL unity)
|
||||
set(unity true)
|
||||
set(nonunity false)
|
||||
endif()
|
||||
|
||||
if (${cur_component} STREQUAL nounity)
|
||||
set(unity false)
|
||||
set(nonunity true)
|
||||
endif()
|
||||
|
||||
if (${cur_component} STREQUAL debug)
|
||||
set(release false)
|
||||
endif()
|
||||
|
||||
if (${cur_component} STREQUAL release)
|
||||
set(release true)
|
||||
endif()
|
||||
|
||||
if (${cur_component} STREQUAL coverage)
|
||||
set(coverage true)
|
||||
set(debug true)
|
||||
endif()
|
||||
|
||||
if (${cur_component} STREQUAL profile)
|
||||
set(profile true)
|
||||
endif()
|
||||
|
||||
if (${cur_component} STREQUAL ci)
|
||||
# Workarounds that make various CI builds work, but that
|
||||
# we don't want in the general case.
|
||||
set(ci true)
|
||||
set(openssl_min 1.0.1)
|
||||
endif()
|
||||
|
||||
endwhile()
|
||||
|
||||
if (release)
|
||||
set(CMAKE_BUILD_TYPE Release)
|
||||
else()
|
||||
set(CMAKE_BUILD_TYPE Debug)
|
||||
endif()
|
||||
|
||||
if (NOT unity)
|
||||
set(CMAKE_BUILD_TYPE ${CMAKE_BUILD_TYPE}Classic)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
endmacro()
|
||||
|
||||
############################################################
|
||||
|
||||
macro(setup_build_cache)
|
||||
set(san "" CACHE STRING "On gcc & clang, add sanitizer
|
||||
instrumentation")
|
||||
set_property(CACHE san PROPERTY STRINGS ";address;thread")
|
||||
set(assert false CACHE BOOL "Enables asserts, even in release builds")
|
||||
set(static false CACHE BOOL
|
||||
"On linux, link protobuf, openssl, libc++, and boost statically")
|
||||
|
||||
if (static AND (WIN32 OR APPLE))
|
||||
message(FATAL_ERROR "Static linking is only supported on linux.")
|
||||
endif()
|
||||
|
||||
if (${CMAKE_GENERATOR} STREQUAL "Unix Makefiles" AND NOT CMAKE_BUILD_TYPE)
|
||||
set(CMAKE_BUILD_TYPE Debug)
|
||||
endif()
|
||||
|
||||
# Can't exclude files from configurations, so can't support both
|
||||
# unity and nonunity configurations at the same time
|
||||
if (NOT DEFINED unity OR unity)
|
||||
set(CMAKE_CONFIGURATION_TYPES
|
||||
Debug
|
||||
Release)
|
||||
else()
|
||||
set(CMAKE_CONFIGURATION_TYPES
|
||||
DebugClassic
|
||||
ReleaseClassic)
|
||||
if(${CMAKE_BUILD_TYPE} STREQUAL "Debug")
|
||||
set(CMAKE_BUILD_TYPE DebugClassic)
|
||||
elseif(${CMAKE_BUILD_TYPE} STREQUAL "Release")
|
||||
set(CMAKE_BUILD_TYPE ReleaseClassic)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set(CMAKE_CONFIGURATION_TYPES
|
||||
${CMAKE_CONFIGURATION_TYPES} CACHE STRING "" FORCE)
|
||||
endmacro()
|
||||
|
||||
############################################################
|
||||
|
||||
function(prepend var prefix)
|
||||
set(listVar "")
|
||||
foreach(f ${ARGN})
|
||||
list(APPEND listVar "${prefix}${f}")
|
||||
endforeach(f)
|
||||
set(${var} "${listVar}" PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
macro(append_flags name)
|
||||
foreach (arg ${ARGN})
|
||||
set(${name} "${${name}} ${arg}")
|
||||
endforeach()
|
||||
endmacro()
|
||||
|
||||
macro(group_sources curdir)
|
||||
file(GLOB children RELATIVE ${PROJECT_SOURCE_DIR}/${curdir}
|
||||
${PROJECT_SOURCE_DIR}/${curdir}/*)
|
||||
foreach (child ${children})
|
||||
if (IS_DIRECTORY ${PROJECT_SOURCE_DIR}/${curdir}/${child})
|
||||
group_sources(${curdir}/${child})
|
||||
else()
|
||||
string(REPLACE "/" "\\" groupname ${curdir})
|
||||
source_group(${groupname} FILES
|
||||
${PROJECT_SOURCE_DIR}/${curdir}/${child})
|
||||
endif()
|
||||
endforeach()
|
||||
endmacro()
|
||||
|
||||
macro(add_with_props src_var files)
|
||||
list(APPEND ${src_var} ${files})
|
||||
foreach (arg ${ARGN})
|
||||
set(props "${props} ${arg}")
|
||||
endforeach()
|
||||
set_source_files_properties(
|
||||
${files}
|
||||
PROPERTIES COMPILE_FLAGS
|
||||
${props})
|
||||
endmacro()
|
||||
|
||||
############################################################
|
||||
|
||||
macro(determine_build_type)
|
||||
if ("${CMAKE_CXX_COMPILER_ID}" MATCHES ".*Clang") # both Clang and AppleClang
|
||||
set(is_clang true)
|
||||
elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
|
||||
set(is_gcc true)
|
||||
elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
|
||||
set(is_msvc true)
|
||||
endif()
|
||||
|
||||
if (${CMAKE_GENERATOR} STREQUAL "Xcode")
|
||||
set(is_xcode true)
|
||||
else()
|
||||
set(is_xcode false)
|
||||
endif()
|
||||
|
||||
if (NOT is_gcc AND NOT is_clang AND NOT is_msvc)
|
||||
message("Current compiler is ${CMAKE_CXX_COMPILER_ID}")
|
||||
message(FATAL_ERROR "Missing compiler. Must be GNU, Clang, or MSVC")
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
############################################################
|
||||
|
||||
macro(check_gcc4_abi)
|
||||
# Check if should use gcc4's ABI
|
||||
set(gcc4_abi false)
|
||||
|
||||
if ($ENV{RIPPLED_OLD_GCC_ABI})
|
||||
set(gcc4_abi true)
|
||||
endif()
|
||||
|
||||
if (is_gcc AND NOT gcc4_abi)
|
||||
if (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 5)
|
||||
execute_process(COMMAND lsb_release -si OUTPUT_VARIABLE lsb)
|
||||
string(STRIP "${lsb}" lsb)
|
||||
if ("${lsb}" STREQUAL "Ubuntu")
|
||||
execute_process(COMMAND lsb_release -sr OUTPUT_VARIABLE lsb)
|
||||
string(STRIP ${lsb} lsb)
|
||||
if (${lsb} VERSION_LESS 15.1)
|
||||
set(gcc4_abi true)
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if (gcc4_abi)
|
||||
add_definitions(-D_GLIBCXX_USE_CXX11_ABI=0)
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
############################################################
|
||||
|
||||
macro(special_build_flags)
|
||||
if (coverage)
|
||||
add_compile_options(-fprofile-arcs -ftest-coverage)
|
||||
append_flags(CMAKE_EXE_LINKER_FLAGS -fprofile-arcs -ftest-coverage)
|
||||
endif()
|
||||
|
||||
if (profile)
|
||||
add_compile_options(-p -pg)
|
||||
append_flags(CMAKE_EXE_LINKER_FLAGS -p -pg)
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
############################################################
|
||||
|
||||
# Params: Boost components to search for.
|
||||
macro(use_boost)
|
||||
if(WIN32 OR CYGWIN)
|
||||
# Workaround for MSVC having two boost versions - x86 and x64 on same PC in stage folders
|
||||
if ((NOT DEFINED BOOST_ROOT) AND (DEFINED ENV{BOOST_ROOT}))
|
||||
set(BOOST_ROOT $ENV{BOOST_ROOT})
|
||||
endif()
|
||||
if(DEFINED BOOST_ROOT)
|
||||
if(CMAKE_SIZEOF_VOID_P EQUAL 8 AND IS_DIRECTORY ${BOOST_ROOT}/stage64/lib)
|
||||
set(Boost_LIBRARY_DIR ${BOOST_ROOT}/stage64/lib)
|
||||
else()
|
||||
set(Boost_LIBRARY_DIR ${BOOST_ROOT}/stage/lib)
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if (is_clang AND DEFINED ENV{CLANG_BOOST_ROOT})
|
||||
set(BOOST_ROOT $ENV{CLANG_BOOST_ROOT})
|
||||
endif()
|
||||
|
||||
set(Boost_USE_STATIC_LIBS on)
|
||||
set(Boost_USE_MULTITHREADED on)
|
||||
set(Boost_USE_STATIC_RUNTIME off)
|
||||
find_package(Boost COMPONENTS
|
||||
${ARGN})
|
||||
|
||||
if (Boost_FOUND OR
|
||||
((CYGWIN OR WIN32) AND Boost_INCLUDE_DIRS AND Boost_LIBRARY_DIRS))
|
||||
if(NOT Boost_FOUND)
|
||||
message(WARNING "Boost directory found, but not all components. May not be able to build.")
|
||||
endif()
|
||||
include_directories(SYSTEM ${Boost_INCLUDE_DIRS})
|
||||
link_directories(${Boost_LIBRARY_DIRS})
|
||||
else()
|
||||
message(FATAL_ERROR "Boost not found")
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
macro(use_pthread)
|
||||
if (NOT WIN32)
|
||||
set(THREADS_PREFER_PTHREAD_FLAG ON)
|
||||
find_package(Threads)
|
||||
add_compile_options(${CMAKE_THREAD_LIBS_INIT})
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
macro(use_openssl openssl_min)
|
||||
if (APPLE AND NOT DEFINED ENV{OPENSSL_ROOT_DIR})
|
||||
find_program(HOMEBREW brew)
|
||||
if (NOT HOMEBREW STREQUAL "HOMEBREW-NOTFOUND")
|
||||
execute_process(COMMAND brew --prefix openssl
|
||||
OUTPUT_VARIABLE OPENSSL_ROOT_DIR
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if (WIN32)
|
||||
if (DEFINED ENV{OPENSSL_ROOT})
|
||||
include_directories($ENV{OPENSSL_ROOT}/include)
|
||||
link_directories($ENV{OPENSSL_ROOT}/lib)
|
||||
endif()
|
||||
else()
|
||||
if (static)
|
||||
set(tmp CMAKE_FIND_LIBRARY_SUFFIXES)
|
||||
set(CMAKE_FIND_LIBRARY_SUFFIXES .a)
|
||||
endif()
|
||||
|
||||
find_package(OpenSSL)
|
||||
|
||||
if (static)
|
||||
set(CMAKE_FIND_LIBRARY_SUFFIXES tmp)
|
||||
endif()
|
||||
|
||||
if (OPENSSL_FOUND)
|
||||
include_directories(${OPENSSL_INCLUDE_DIR})
|
||||
else()
|
||||
message(FATAL_ERROR "OpenSSL not found")
|
||||
endif()
|
||||
if (UNIX AND NOT APPLE AND ${OPENSSL_VERSION} VERSION_LESS ${openssl_min})
|
||||
message(FATAL_ERROR
|
||||
"Your openssl is Version: ${OPENSSL_VERSION}, ${openssl_min} or better is required.")
|
||||
endif()
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
macro(use_protobuf)
|
||||
if (WIN32)
|
||||
if (DEFINED ENV{PROTOBUF_ROOT})
|
||||
include_directories($ENV{PROTOBUF_ROOT}/src)
|
||||
link_directories($ENV{PROTOBUF_ROOT}/src/.libs)
|
||||
endif()
|
||||
|
||||
# Modified from FindProtobuf.cmake
|
||||
FUNCTION(PROTOBUF_GENERATE_CPP SRCS HDRS PROTOFILES)
|
||||
# argument parsing
|
||||
IF(NOT PROTOFILES)
|
||||
MESSAGE(SEND_ERROR "Error: PROTOBUF_GENERATE_CPP() called without any proto files")
|
||||
RETURN()
|
||||
ENDIF()
|
||||
|
||||
SET(OUTPATH ${CMAKE_CURRENT_BINARY_DIR})
|
||||
SET(PROTOROOT ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
# the real logic
|
||||
SET(${SRCS})
|
||||
SET(${HDRS})
|
||||
FOREACH(PROTOFILE ${PROTOFILES})
|
||||
# ensure that the file ends with .proto
|
||||
STRING(REGEX MATCH "\\.proto$$" PROTOEND ${PROTOFILE})
|
||||
IF(NOT PROTOEND)
|
||||
MESSAGE(SEND_ERROR "Proto file '${PROTOFILE}' does not end with .proto")
|
||||
ENDIF()
|
||||
|
||||
GET_FILENAME_COMPONENT(PROTO_PATH ${PROTOFILE} PATH)
|
||||
GET_FILENAME_COMPONENT(ABS_FILE ${PROTOFILE} ABSOLUTE)
|
||||
GET_FILENAME_COMPONENT(FILE_WE ${PROTOFILE} NAME_WE)
|
||||
|
||||
STRING(REGEX MATCH "^${PROTOROOT}" IN_ROOT_PATH ${PROTOFILE})
|
||||
STRING(REGEX MATCH "^${PROTOROOT}" IN_ROOT_ABS_FILE ${ABS_FILE})
|
||||
|
||||
IF(IN_ROOT_PATH)
|
||||
SET(MATCH_PATH ${PROTOFILE})
|
||||
ELSEIF(IN_ROOT_ABS_FILE)
|
||||
SET(MATCH_PATH ${ABS_FILE})
|
||||
ELSE()
|
||||
MESSAGE(SEND_ERROR "Proto file '${PROTOFILE}' is not in protoroot '${PROTOROOT}'")
|
||||
ENDIF()
|
||||
|
||||
# build the result file name
|
||||
STRING(REGEX REPLACE "^${PROTOROOT}(/?)" "" ROOT_CLEANED_FILE ${MATCH_PATH})
|
||||
STRING(REGEX REPLACE "\\.proto$$" "" EXT_CLEANED_FILE ${ROOT_CLEANED_FILE})
|
||||
|
||||
SET(CPP_FILE "${OUTPATH}/${EXT_CLEANED_FILE}.pb.cc")
|
||||
SET(H_FILE "${OUTPATH}/${EXT_CLEANED_FILE}.pb.h")
|
||||
|
||||
LIST(APPEND ${SRCS} "${CPP_FILE}")
|
||||
LIST(APPEND ${HDRS} "${H_FILE}")
|
||||
|
||||
ADD_CUSTOM_COMMAND(
|
||||
OUTPUT "${CPP_FILE}" "${H_FILE}"
|
||||
COMMAND ${CMAKE_COMMAND} -E make_directory ${OUTPATH}
|
||||
COMMAND ${PROTOBUF_PROTOC_EXECUTABLE}
|
||||
ARGS "--cpp_out=${OUTPATH}" --proto_path "${PROTOROOT}" "${MATCH_PATH}"
|
||||
DEPENDS ${ABS_FILE}
|
||||
COMMENT "Running C++ protocol buffer compiler on ${MATCH_PATH} with root ${PROTOROOT}, generating: ${CPP_FILE}"
|
||||
VERBATIM)
|
||||
|
||||
ENDFOREACH()
|
||||
|
||||
SET_SOURCE_FILES_PROPERTIES(${${SRCS}} ${${HDRS}} PROPERTIES GENERATED TRUE)
|
||||
SET(${SRCS} ${${SRCS}} PARENT_SCOPE)
|
||||
SET(${HDRS} ${${HDRS}} PARENT_SCOPE)
|
||||
|
||||
ENDFUNCTION()
|
||||
|
||||
set(PROTOBUF_PROTOC_EXECUTABLE Protoc) # must be on path
|
||||
else()
|
||||
if (static)
|
||||
set(tmp CMAKE_FIND_LIBRARY_SUFFIXES)
|
||||
set(CMAKE_FIND_LIBRARY_SUFFIXES .a)
|
||||
endif()
|
||||
|
||||
find_package(Protobuf REQUIRED)
|
||||
|
||||
if (static)
|
||||
set(CMAKE_FIND_LIBRARY_SUFFIXES tmp)
|
||||
endif()
|
||||
|
||||
if (is_clang AND DEFINED ENV{CLANG_PROTOBUF_ROOT})
|
||||
link_directories($ENV{CLANG_PROTOBUF_ROOT}/src/.libs)
|
||||
include_directories($ENV{CLANG_PROTOBUF_ROOT}/src)
|
||||
else()
|
||||
include_directories(${PROTOBUF_INCLUDE_DIRS})
|
||||
endif()
|
||||
endif()
|
||||
include_directories(${CMAKE_CURRENT_BINARY_DIR})
|
||||
|
||||
file(GLOB ripple_proto src/ripple/proto/*.proto)
|
||||
PROTOBUF_GENERATE_CPP(PROTO_SRCS PROTO_HDRS ${ripple_proto})
|
||||
|
||||
if (WIN32)
|
||||
include_directories(src/protobuf/src
|
||||
src/protobuf/vsprojects
|
||||
${CMAKE_CURRENT_BINARY_DIR}/src/ripple/proto)
|
||||
endif()
|
||||
|
||||
endmacro()
|
||||
|
||||
############################################################
|
||||
|
||||
macro(setup_build_boilerplate)
|
||||
if (NOT WIN32 AND san)
|
||||
add_compile_options(-fsanitize=${san} -fno-omit-frame-pointer)
|
||||
|
||||
append_flags(CMAKE_EXE_LINKER_FLAGS
|
||||
-fsanitize=${san})
|
||||
|
||||
string(TOLOWER ${san} ci_san)
|
||||
if (${ci_san} STREQUAL address)
|
||||
set(SANITIZER_LIBRARIES asan)
|
||||
add_definitions(-DSANITIZER=ASAN)
|
||||
endif()
|
||||
if (${ci_san} STREQUAL thread)
|
||||
set(SANITIZER_LIBRARIES tsan)
|
||||
add_definitions(-DSANITIZER=TSAN)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
############################################################
|
||||
|
||||
add_definitions(
|
||||
-DOPENSSL_NO_SSL2
|
||||
-DDEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER
|
||||
-DHAVE_USLEEP=1
|
||||
-DSOCI_CXX_C11=1
|
||||
-D_SILENCE_STDEXT_HASH_DEPRECATION_WARNINGS
|
||||
-DBOOST_NO_AUTO_PTR
|
||||
)
|
||||
|
||||
if (is_gcc)
|
||||
add_compile_options(-Wno-unused-but-set-variable -Wno-deprecated)
|
||||
endif()
|
||||
|
||||
# Generator expressions are not supported in add_definitions, use set_property instead
|
||||
set_property(
|
||||
DIRECTORY
|
||||
APPEND
|
||||
PROPERTY COMPILE_DEFINITIONS
|
||||
$<$<OR:$<CONFIG:Debug>,$<CONFIG:DebugClassic>>:DEBUG _DEBUG>)
|
||||
|
||||
if (NOT assert)
|
||||
set_property(
|
||||
DIRECTORY
|
||||
APPEND
|
||||
PROPERTY COMPILE_DEFINITIONS
|
||||
$<$<OR:$<BOOL:${profile}>,$<CONFIG:Release>,$<CONFIG:ReleaseClassic>>:NDEBUG>)
|
||||
endif()
|
||||
|
||||
if (NOT WIN32)
|
||||
add_definitions(-D_FILE_OFFSET_BITS=64)
|
||||
append_flags(CMAKE_CXX_FLAGS -frtti -std=c++14 -Wno-invalid-offsetof
|
||||
-DBOOST_COROUTINE_NO_DEPRECATION_WARNING -DBOOST_COROUTINES_NO_DEPRECATION_WARNING)
|
||||
add_compile_options(-Wall -Wno-sign-compare -Wno-char-subscripts -Wno-format
|
||||
-Wno-unused-local-typedefs -g)
|
||||
# There seems to be an issue using generator experssions with multiple values,
|
||||
# split the expression
|
||||
add_compile_options($<$<OR:$<CONFIG:Release>,$<CONFIG:ReleaseClassic>>:-O3>)
|
||||
add_compile_options($<$<OR:$<CONFIG:Release>,$<CONFIG:ReleaseClassic>>:-fno-strict-aliasing>)
|
||||
append_flags(CMAKE_EXE_LINKER_FLAGS -rdynamic -g)
|
||||
|
||||
if (is_clang)
|
||||
add_compile_options(
|
||||
-Wno-redeclared-class-member -Wno-mismatched-tags -Wno-deprecated-register)
|
||||
add_definitions(-DBOOST_ASIO_HAS_STD_ARRAY)
|
||||
endif()
|
||||
|
||||
if (APPLE)
|
||||
add_definitions(-DBEAST_COMPILE_OBJECTIVE_CPP=1
|
||||
-DNO_LOG_UNHANDLED_EXCEPTIONS)
|
||||
add_compile_options(
|
||||
-Wno-deprecated -Wno-deprecated-declarations -Wno-unused-variable -Wno-unused-function)
|
||||
endif()
|
||||
|
||||
if (is_gcc)
|
||||
add_compile_options(-Wno-unused-but-set-variable -Wno-unused-local-typedefs)
|
||||
add_compile_options($<$<OR:$<CONFIG:Debug>,$<CONFIG:DebugClassic>>:-O0>)
|
||||
endif (is_gcc)
|
||||
else(NOT WIN32)
|
||||
add_compile_options(
|
||||
/bigobj # Increase object file max size
|
||||
/EHa # ExceptionHandling all
|
||||
/fp:precise # Floating point behavior
|
||||
/Gd # __cdecl calling convention
|
||||
/Gm- # Minimal rebuild: disabled
|
||||
/GR # Enable RTTI
|
||||
/Gy- # Function level linking: disabled
|
||||
/FS
|
||||
/MP # Multiprocessor compilation
|
||||
/openmp- # pragma omp: disabled
|
||||
/Zc:forScope # Language extension: for scope
|
||||
/Zi # Generate complete debug info
|
||||
/errorReport:none # No error reporting to Internet
|
||||
/nologo # Suppress login banner
|
||||
/W3 # Warning level 3
|
||||
/WX- # Disable warnings as errors
|
||||
/wd"4018"
|
||||
/wd"4244"
|
||||
/wd"4267"
|
||||
/wd"4800" # Disable C4800(int to bool performance)
|
||||
/wd"4503" # Decorated name length exceeded, name was truncated
|
||||
)
|
||||
add_definitions(
|
||||
-D_WIN32_WINNT=0x6000
|
||||
-D_SCL_SECURE_NO_WARNINGS
|
||||
-D_CRT_SECURE_NO_WARNINGS
|
||||
-DWIN32_CONSOLE
|
||||
-DNOMINMAX
|
||||
-DBOOST_COROUTINE_NO_DEPRECATION_WARNING
|
||||
-DBOOST_COROUTINES_NO_DEPRECATION_WARNING)
|
||||
append_flags(CMAKE_EXE_LINKER_FLAGS
|
||||
/DEBUG
|
||||
/DYNAMICBASE
|
||||
/ERRORREPORT:NONE
|
||||
/MACHINE:X64
|
||||
/MANIFEST
|
||||
/nologo
|
||||
/NXCOMPAT
|
||||
/SUBSYSTEM:CONSOLE
|
||||
/TLBID:1)
|
||||
|
||||
|
||||
# There seems to be an issue using generator experssions with multiple values,
|
||||
# split the expression
|
||||
# /GS Buffers security check: enable
|
||||
add_compile_options($<$<OR:$<CONFIG:Debug>,$<CONFIG:DebugClassic>>:/GS>)
|
||||
# /MTd Language: Multi-threaded Debug CRT
|
||||
add_compile_options($<$<OR:$<CONFIG:Debug>,$<CONFIG:DebugClassic>>:/MTd>)
|
||||
# /Od Optimization: Disabled
|
||||
add_compile_options($<$<OR:$<CONFIG:Debug>,$<CONFIG:DebugClassic>>:/Od>)
|
||||
# /RTC1 Run-time error checks:
|
||||
add_compile_options($<$<OR:$<CONFIG:Debug>,$<CONFIG:DebugClassic>>:/RTC1>)
|
||||
|
||||
# Generator expressions are not supported in add_definitions, use set_property instead
|
||||
set_property(
|
||||
DIRECTORY
|
||||
APPEND
|
||||
PROPERTY COMPILE_DEFINITIONS
|
||||
$<$<OR:$<CONFIG:Debug>,$<CONFIG:DebugClassic>>:_CRTDBG_MAP_ALLOC>)
|
||||
|
||||
# /MT Language: Multi-threaded CRT
|
||||
add_compile_options($<$<OR:$<CONFIG:Release>,$<CONFIG:ReleaseClassic>>:/MT>)
|
||||
add_compile_options($<$<OR:$<CONFIG:Release>,$<CONFIG:ReleaseClassic>>:/Ox>)
|
||||
# /Ox Optimization: Full
|
||||
|
||||
endif (NOT WIN32)
|
||||
|
||||
if (static)
|
||||
append_flags(CMAKE_EXE_LINKER_FLAGS -static-libstdc++)
|
||||
# set_target_properties(ripple-libpp PROPERTIES LINK_SEARCH_START_STATIC 1)
|
||||
# set_target_properties(ripple-libpp PROPERTIES LINK_SEARCH_END_STATIC 1)
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
############################################################
|
||||
|
||||
macro(create_build_folder cur_project)
|
||||
if (NOT WIN32)
|
||||
ADD_CUSTOM_TARGET(build_folder ALL
|
||||
COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_CURRENT_BINARY_DIR}
|
||||
COMMENT "Creating build output folder")
|
||||
add_dependencies(${cur_project} build_folder)
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
macro(set_startup_project cur_project)
|
||||
if (WIN32 AND NOT ci)
|
||||
if (CMAKE_VERSION VERSION_LESS 3.6)
|
||||
message(WARNING
|
||||
"Setting the VS startup project requires cmake 3.6 or later. Please upgrade.")
|
||||
endif()
|
||||
set_property(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY
|
||||
VS_STARTUP_PROJECT ${cur_project})
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
macro(link_common_libraries cur_project)
|
||||
if (NOT MSVC)
|
||||
target_link_libraries(${cur_project} ${Boost_LIBRARIES})
|
||||
target_link_libraries(${cur_project} dl)
|
||||
target_link_libraries(${cur_project} Threads::Threads)
|
||||
if (APPLE)
|
||||
find_library(app_kit AppKit)
|
||||
find_library(foundation Foundation)
|
||||
target_link_libraries(${cur_project}
|
||||
crypto ssl ${app_kit} ${foundation})
|
||||
else()
|
||||
target_link_libraries(${cur_project} rt)
|
||||
endif()
|
||||
else(NOT MSVC)
|
||||
target_link_libraries(${cur_project}
|
||||
$<$<OR:$<CONFIG:Debug>,$<CONFIG:DebugClassic>>:VC/static/ssleay32MTd>
|
||||
$<$<OR:$<CONFIG:Debug>,$<CONFIG:DebugClassic>>:VC/static/libeay32MTd>)
|
||||
target_link_libraries(${cur_project}
|
||||
$<$<OR:$<CONFIG:Release>,$<CONFIG:ReleaseClassic>>:VC/static/ssleay32MT>
|
||||
$<$<OR:$<CONFIG:Release>,$<CONFIG:ReleaseClassic>>:VC/static/libeay32MT>)
|
||||
target_link_libraries(${cur_project}
|
||||
legacy_stdio_definitions.lib Shlwapi kernel32 user32 gdi32 winspool comdlg32
|
||||
advapi32 shell32 ole32 oleaut32 uuid odbc32 odbccp32)
|
||||
endif (NOT MSVC)
|
||||
endmacro()
|
||||
@@ -17,7 +17,7 @@ software components:
|
||||
* [Google Protocol Buffers Compiler](README.md#install-google-protocol-buffers-compiler)
|
||||
* (Optional) [Python and Scons](README.md#optional-install-python-and-scons)
|
||||
* [OpenSSL Library](README.md#install-openssl)
|
||||
* [Boost 1.59 library](README.md#build-boost)
|
||||
* [Boost library](README.md#build-boost)
|
||||
* [Node.js](README.md#install-nodejs)
|
||||
|
||||
## Install Software
|
||||
@@ -84,8 +84,8 @@ for Visual Studio 2015 support.
|
||||
[Download OpenSSL.](http://slproweb.com/products/Win32OpenSSL.html)
|
||||
There will be four variants available:
|
||||
|
||||
1. 64-bit. Use this if you are running 64-bit windows. As of this writing, the link is called: "Win64 OpenSSL v1.0.2d".
|
||||
2. 64-bit light - Don't use this. It is missing files needed to build rippled. As of this writing, the link is called: "Win64 OpenSSL v1.0.2d Light"
|
||||
1. 64-bit. Use this if you are running 64-bit windows. As of this writing, the link is called: "Win64 OpenSSL v1.0.2j".
|
||||
2. 64-bit light - Don't use this. It is missing files needed to build rippled. As of this writing, the link is called: "Win64 OpenSSL v1.0.2j Light"
|
||||
|
||||
Run the installer, and choose an appropriate location for your OpenSSL
|
||||
installation. In this guide we use **C:\lib\OpenSSL-Win64** as the
|
||||
@@ -108,8 +108,13 @@ unpacking it, open a **Developer Command Prompt** for
|
||||
Visual Studio, change to the directory containing boost, then
|
||||
bootstrap the build tools:
|
||||
|
||||
(As of this writing, the most recent version of boost is 1.62.0, which
|
||||
will unpack into a directory named `boost_1_62_0`. For higher versions
|
||||
of boost, adjust the directories provided in these examples as
|
||||
appropriate.)
|
||||
|
||||
```powershell
|
||||
cd C:\lib\boost_1_59_0
|
||||
cd C:\lib\boost_1_62_0
|
||||
bootstrap
|
||||
```
|
||||
|
||||
@@ -119,7 +124,7 @@ affected by changes in outside files. Therefore, it is necessary to build the
|
||||
required boost static libraries using this command:
|
||||
|
||||
```powershell
|
||||
bjam --toolset=msvc-14.0 --build-type=complete variant=debug,release link=static runtime-link=static address-model=64
|
||||
bjam --toolset=msvc-14.0 address-model=64 architecture=x86 link=static threading=multi runtime-link=shared,static stage --stagedir=stage64
|
||||
```
|
||||
|
||||
Building the boost libraries may take considerable time. When the build process
|
||||
@@ -161,7 +166,7 @@ git checkout master
|
||||
### Configure Library Paths
|
||||
|
||||
Open the solution file located at **Builds/Visual Studio 2015/ripple.sln**
|
||||
and select the "View->Other Windows->Property Manager" to bring up the Property Manager.
|
||||
and select the "View->Property Manager" to bring up the Property Manager.
|
||||
Expand the *debug | x64* section and
|
||||
double click the *Microsoft.Cpp.x64.user* property sheet to bring up the
|
||||
*Property Pages* dialog. These are global properties applied to all
|
||||
|
||||
@@ -86,8 +86,8 @@
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='debug.classic|x64'">
|
||||
<ClCompile>
|
||||
<PreprocessorDefinitions>HAVE_USLEEP=1;SOCI_CXX_C11=1;_WIN32_WINNT=0x6000;BOOST_NO_AUTO_PTR;DEBUG;DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER;NOMINMAX;OPENSSL_NO_SSL2;WIN32_CONSOLE;_CRTDBG_MAP_ALLOC;_CRT_SECURE_NO_WARNINGS;_DEBUG;_SCL_SECURE_NO_WARNINGS;_SILENCE_STDEXT_HASH_DEPRECATION_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories>..\..\build\proto;..\..\src;..\..\src\beast;..\..\src\beast\extras;..\..\src\beast\include;..\..\src\protobuf\src;..\..\src\protobuf\vsprojects;..\..\src\soci\include;..\..\src\soci\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>HAVE_USLEEP=1;SOCI_CXX_C11=1;_WIN32_WINNT=0x6000;BOOST_COROUTINES_NO_DEPRECATION_WARNING;BOOST_COROUTINE_NO_DEPRECATION_WARNING;BOOST_NO_AUTO_PTR;DEBUG;DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER;NOMINMAX;OPENSSL_NO_SSL2;WIN32_CONSOLE;_CRTDBG_MAP_ALLOC;_CRT_SECURE_NO_WARNINGS;_DEBUG;_SCL_SECURE_NO_WARNINGS;_SILENCE_STDEXT_HASH_DEPRECATION_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories>..\..\build\proto;..\..\src;..\..\src\beast;..\..\src\beast\extras;..\..\src\beast\include;..\..\src\nudb\include;..\..\src\protobuf\src;..\..\src\protobuf\vsprojects;..\..\src\soci\include;..\..\src\soci\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<DisableSpecificWarnings>4800;4244;4267;4503;4018</DisableSpecificWarnings>
|
||||
<ExceptionHandling>Async</ExceptionHandling>
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
@@ -123,8 +123,8 @@
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='debug|x64'">
|
||||
<ClCompile>
|
||||
<PreprocessorDefinitions>HAVE_USLEEP=1;SOCI_CXX_C11=1;_WIN32_WINNT=0x6000;BOOST_NO_AUTO_PTR;DEBUG;DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER;NOMINMAX;OPENSSL_NO_SSL2;WIN32_CONSOLE;_CRTDBG_MAP_ALLOC;_CRT_SECURE_NO_WARNINGS;_DEBUG;_SCL_SECURE_NO_WARNINGS;_SILENCE_STDEXT_HASH_DEPRECATION_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories>..\..\build\proto;..\..\src;..\..\src\beast;..\..\src\beast\extras;..\..\src\beast\include;..\..\src\protobuf\src;..\..\src\protobuf\vsprojects;..\..\src\soci\include;..\..\src\soci\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>HAVE_USLEEP=1;SOCI_CXX_C11=1;_WIN32_WINNT=0x6000;BOOST_COROUTINES_NO_DEPRECATION_WARNING;BOOST_COROUTINE_NO_DEPRECATION_WARNING;BOOST_NO_AUTO_PTR;DEBUG;DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER;NOMINMAX;OPENSSL_NO_SSL2;WIN32_CONSOLE;_CRTDBG_MAP_ALLOC;_CRT_SECURE_NO_WARNINGS;_DEBUG;_SCL_SECURE_NO_WARNINGS;_SILENCE_STDEXT_HASH_DEPRECATION_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories>..\..\build\proto;..\..\src;..\..\src\beast;..\..\src\beast\extras;..\..\src\beast\include;..\..\src\nudb\include;..\..\src\protobuf\src;..\..\src\protobuf\vsprojects;..\..\src\soci\include;..\..\src\soci\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<DisableSpecificWarnings>4800;4244;4267;4503;4018</DisableSpecificWarnings>
|
||||
<ExceptionHandling>Async</ExceptionHandling>
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
@@ -160,8 +160,8 @@
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='release.classic|x64'">
|
||||
<ClCompile>
|
||||
<PreprocessorDefinitions>HAVE_USLEEP=1;SOCI_CXX_C11=1;_WIN32_WINNT=0x6000;BOOST_NO_AUTO_PTR;DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER;NDEBUG;NOMINMAX;OPENSSL_NO_SSL2;WIN32_CONSOLE;_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;_SILENCE_STDEXT_HASH_DEPRECATION_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories>..\..\build\proto;..\..\src;..\..\src\beast;..\..\src\beast\extras;..\..\src\beast\include;..\..\src\protobuf\src;..\..\src\protobuf\vsprojects;..\..\src\soci\include;..\..\src\soci\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>HAVE_USLEEP=1;SOCI_CXX_C11=1;_WIN32_WINNT=0x6000;BOOST_COROUTINES_NO_DEPRECATION_WARNING;BOOST_COROUTINE_NO_DEPRECATION_WARNING;BOOST_NO_AUTO_PTR;DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER;NDEBUG;NOMINMAX;OPENSSL_NO_SSL2;WIN32_CONSOLE;_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;_SILENCE_STDEXT_HASH_DEPRECATION_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories>..\..\build\proto;..\..\src;..\..\src\beast;..\..\src\beast\extras;..\..\src\beast\include;..\..\src\nudb\include;..\..\src\protobuf\src;..\..\src\protobuf\vsprojects;..\..\src\soci\include;..\..\src\soci\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<DisableSpecificWarnings>4800;4244;4267;4503;4018</DisableSpecificWarnings>
|
||||
<ExceptionHandling>Async</ExceptionHandling>
|
||||
<FloatingPointModel>Precise</FloatingPointModel>
|
||||
@@ -195,8 +195,8 @@
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='release|x64'">
|
||||
<ClCompile>
|
||||
<PreprocessorDefinitions>HAVE_USLEEP=1;SOCI_CXX_C11=1;_WIN32_WINNT=0x6000;BOOST_NO_AUTO_PTR;DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER;NDEBUG;NOMINMAX;OPENSSL_NO_SSL2;WIN32_CONSOLE;_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;_SILENCE_STDEXT_HASH_DEPRECATION_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories>..\..\build\proto;..\..\src;..\..\src\beast;..\..\src\beast\extras;..\..\src\beast\include;..\..\src\protobuf\src;..\..\src\protobuf\vsprojects;..\..\src\soci\include;..\..\src\soci\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>HAVE_USLEEP=1;SOCI_CXX_C11=1;_WIN32_WINNT=0x6000;BOOST_COROUTINES_NO_DEPRECATION_WARNING;BOOST_COROUTINE_NO_DEPRECATION_WARNING;BOOST_NO_AUTO_PTR;DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER;NDEBUG;NOMINMAX;OPENSSL_NO_SSL2;WIN32_CONSOLE;_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;_SILENCE_STDEXT_HASH_DEPRECATION_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories>..\..\build\proto;..\..\src;..\..\src\beast;..\..\src\beast\extras;..\..\src\beast\include;..\..\src\nudb\include;..\..\src\protobuf\src;..\..\src\protobuf\vsprojects;..\..\src\soci\include;..\..\src\soci\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<DisableSpecificWarnings>4800;4244;4267;4503;4018</DisableSpecificWarnings>
|
||||
<ExceptionHandling>Async</ExceptionHandling>
|
||||
<FloatingPointModel>Precise</FloatingPointModel>
|
||||
@@ -509,6 +509,86 @@
|
||||
</ClCompile>
|
||||
<ClInclude Include="..\..\src\lz4\lib\xxhash.h">
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\nudb\include\nudb\basic_store.hpp">
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\nudb\include\nudb\concepts.hpp">
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\nudb\include\nudb\create.hpp">
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\nudb\include\nudb\detail\arena.hpp">
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\nudb\include\nudb\detail\bucket.hpp">
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\nudb\include\nudb\detail\buffer.hpp">
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\nudb\include\nudb\detail\bulkio.hpp">
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\nudb\include\nudb\detail\cache.hpp">
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\nudb\include\nudb\detail\endian.hpp">
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\nudb\include\nudb\detail\field.hpp">
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\nudb\include\nudb\detail\format.hpp">
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\nudb\include\nudb\detail\gentex.hpp">
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\nudb\include\nudb\detail\mutex.hpp">
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\nudb\include\nudb\detail\pool.hpp">
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\nudb\include\nudb\detail\stream.hpp">
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\nudb\include\nudb\detail\xxhash.hpp">
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\nudb\include\nudb\error.hpp">
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\nudb\include\nudb\file.hpp">
|
||||
</ClInclude>
|
||||
<None Include="..\..\src\nudb\include\nudb\impl\basic_store.ipp">
|
||||
</None>
|
||||
<None Include="..\..\src\nudb\include\nudb\impl\create.ipp">
|
||||
</None>
|
||||
<None Include="..\..\src\nudb\include\nudb\impl\error.ipp">
|
||||
</None>
|
||||
<None Include="..\..\src\nudb\include\nudb\impl\posix_file.ipp">
|
||||
</None>
|
||||
<None Include="..\..\src\nudb\include\nudb\impl\recover.ipp">
|
||||
</None>
|
||||
<None Include="..\..\src\nudb\include\nudb\impl\rekey.ipp">
|
||||
</None>
|
||||
<None Include="..\..\src\nudb\include\nudb\impl\verify.ipp">
|
||||
</None>
|
||||
<None Include="..\..\src\nudb\include\nudb\impl\visit.ipp">
|
||||
</None>
|
||||
<None Include="..\..\src\nudb\include\nudb\impl\win32_file.ipp">
|
||||
</None>
|
||||
<ClInclude Include="..\..\src\nudb\include\nudb\native_file.hpp">
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\nudb\include\nudb\nudb.hpp">
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\nudb\include\nudb\posix_file.hpp">
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\nudb\include\nudb\progress.hpp">
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\nudb\include\nudb\recover.hpp">
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\nudb\include\nudb\rekey.hpp">
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\nudb\include\nudb\store.hpp">
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\nudb\include\nudb\type_traits.hpp">
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\nudb\include\nudb\verify.hpp">
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\nudb\include\nudb\version.hpp">
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\nudb\include\nudb\visit.hpp">
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\nudb\include\nudb\win32_file.hpp">
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\nudb\include\nudb\xxhasher.hpp">
|
||||
</ClInclude>
|
||||
<ClCompile Include="..\..\src\protobuf\src\google\protobuf\compiler\importer.cc">
|
||||
<ExcludedFromBuild>True</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
@@ -703,6 +783,14 @@
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\protobuf\vsprojects\config.h">
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\ripple\app\consensus\RCLCxPos.h">
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\ripple\app\consensus\RCLCxTraits.h">
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\ripple\app\consensus\RCLCxTx.h">
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\ripple\app\ledger\AbstractFetchPackContainer.h">
|
||||
</ClInclude>
|
||||
<ClCompile Include="..\..\src\ripple\app\ledger\AcceptedLedger.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
|
||||
@@ -741,10 +829,6 @@
|
||||
</ClCompile>
|
||||
<ClInclude Include="..\..\src\ripple\app\ledger\impl\ConsensusImp.h">
|
||||
</ClInclude>
|
||||
<ClCompile Include="..\..\src\ripple\app\ledger\impl\DisputedTx.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClInclude Include="..\..\src\ripple\app\ledger\impl\DisputedTx.h">
|
||||
</ClInclude>
|
||||
<ClCompile Include="..\..\src\ripple\app\ledger\impl\InboundLedger.cpp">
|
||||
@@ -1642,56 +1726,6 @@
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\ripple\beast\net\IPEndpoint.h">
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\ripple\beast\nudb.h">
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\ripple\beast\nudb\api.h">
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\ripple\beast\nudb\common.h">
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\ripple\beast\nudb\create.h">
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\ripple\beast\nudb\detail\arena.h">
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\ripple\beast\nudb\detail\bucket.h">
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\ripple\beast\nudb\detail\buffer.h">
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\ripple\beast\nudb\detail\bulkio.h">
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\ripple\beast\nudb\detail\cache.h">
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\ripple\beast\nudb\detail\field.h">
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\ripple\beast\nudb\detail\format.h">
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\ripple\beast\nudb\detail\gentex.h">
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\ripple\beast\nudb\detail\pool.h">
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\ripple\beast\nudb\detail\stream.h">
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\ripple\beast\nudb\file.h">
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\ripple\beast\nudb\identity.h">
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\ripple\beast\nudb\posix_file.h">
|
||||
</ClInclude>
|
||||
<None Include="..\..\src\ripple\beast\nudb\README.md">
|
||||
</None>
|
||||
<ClInclude Include="..\..\src\ripple\beast\nudb\recover.h">
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\ripple\beast\nudb\store.h">
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\ripple\beast\nudb\test\common.h">
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\ripple\beast\nudb\test\fail_file.h">
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\ripple\beast\nudb\verify.h">
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\ripple\beast\nudb\visit.h">
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\ripple\beast\nudb\win32_file.h">
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\ripple\beast\rfc2616.h">
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\ripple\beast\type_name.h">
|
||||
@@ -1746,10 +1780,44 @@
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\ripple\beast\xor_shift_engine.h">
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\ripple\conditions\Condition.h">
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\ripple\conditions\Ed25519.h">
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\ripple\conditions\Fulfillment.h">
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\ripple\conditions\impl\base64.h">
|
||||
</ClInclude>
|
||||
<ClCompile Include="..\..\src\ripple\conditions\impl\Condition.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\ripple\conditions\impl\Ed25519.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\ripple\conditions\impl\Fulfillment.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\ripple\conditions\impl\RsaSha256.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClInclude Include="..\..\src\ripple\conditions\impl\utils.h">
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\ripple\conditions\PrefixSha256.h">
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\ripple\conditions\PreimageSha256.h">
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\ripple\conditions\RsaSha256.h">
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\ripple\core\Config.h">
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\ripple\core\ConfigSections.h">
|
||||
</ClInclude>
|
||||
<None Include="..\..\src\ripple\core\Coro.ipp">
|
||||
</None>
|
||||
<ClInclude Include="..\..\src\ripple\core\DatabaseCon.h">
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\ripple\core\DeadlineTimer.h">
|
||||
@@ -1846,10 +1914,6 @@
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\ripple\core\Job.h">
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\ripple\core\JobCoro.h">
|
||||
</ClInclude>
|
||||
<None Include="..\..\src\ripple\core\JobCoro.ipp">
|
||||
</None>
|
||||
<ClInclude Include="..\..\src\ripple\core\JobQueue.h">
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\ripple\core\JobTypeData.h">
|
||||
@@ -3294,6 +3358,10 @@
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\ripple\unity\beast.cpp">
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\ripple\unity\conditions.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug.classic|x64'">True</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release.classic|x64'">True</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\ripple\unity\core.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug.classic|x64'">True</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release.classic|x64'">True</ExcludedFromBuild>
|
||||
@@ -3302,7 +3370,7 @@
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug.classic|x64'">True</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release.classic|x64'">True</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\ripple\unity\ed25519.c">
|
||||
<ClCompile Include="..\..\src\ripple\unity\ed25519_donna.c">
|
||||
<AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='debug.classic|x64'">..\..\src\ed25519-donna;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='debug|x64'">..\..\src\ed25519-donna;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='release.classic|x64'">..\..\src\ed25519-donna;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
@@ -4352,6 +4420,10 @@
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\test\app\SetTrust_test.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\test\app\SHAMapStore_test.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
|
||||
@@ -4364,10 +4436,18 @@
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\test\app\Ticket_test.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\test\app\Transaction_ordering_test.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\test\app\TrustAndBalance_test.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\test\app\TxQ_test.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
|
||||
@@ -4384,6 +4464,10 @@
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\test\basics\Buffer_test.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\test\basics\CheckLibraryVersions_test.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
|
||||
@@ -4440,22 +4524,6 @@
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\test\beast\beast_nudb_callgrind_test.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\test\beast\beast_nudb_recover_test.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\test\beast\beast_nudb_store_test.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\test\beast\beast_nudb_verify_test.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\test\beast\beast_PropertyStream_test.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
|
||||
@@ -4496,6 +4564,18 @@
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\test\conditions\Ed25519_test.cpp">
|
||||
<ExcludedFromBuild>True</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\test\conditions\PrefixSha256_test.cpp">
|
||||
<ExcludedFromBuild>True</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\test\conditions\PreimageSha256_test.cpp">
|
||||
<ExcludedFromBuild>True</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\test\conditions\RsaSha256_test.cpp">
|
||||
<ExcludedFromBuild>True</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\test\core\Config_test.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
|
||||
@@ -4720,6 +4800,10 @@
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\test\rpc\LedgerClosed_test.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\test\rpc\LedgerData_test.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
|
||||
@@ -4728,6 +4812,14 @@
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\test\rpc\LedgerRPC_test.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\test\rpc\NoRipple_test.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\test\rpc\RobustTransaction_test.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
|
||||
@@ -4780,6 +4872,10 @@
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug.classic|x64'">True</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release.classic|x64'">True</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\unity\conditions_test_unity.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug.classic|x64'">True</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release.classic|x64'">True</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\unity\core_test_unity.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug.classic|x64'">True</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release.classic|x64'">True</ExcludedFromBuild>
|
||||
|
||||
|
Before Width: | Height: | Size: 59 KiB After Width: | Height: | Size: 67 KiB |
|
Before Width: | Height: | Size: 59 KiB After Width: | Height: | Size: 66 KiB |
242
Builds/XCode/README.md
Normal file
@@ -0,0 +1,242 @@
|
||||
# macos Build Instructions
|
||||
|
||||
## Important
|
||||
|
||||
We don't recommend OS X for rippled production use at this time. Currently, the
|
||||
Ubuntu platform has received the highest level of quality assurance and
|
||||
testing.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
You'll need OSX 10.8 or later
|
||||
|
||||
To clone the source code repository, create branches for inspection or
|
||||
modification, build rippled using clang, and run the system tests you will need
|
||||
these software components:
|
||||
|
||||
* [XCode](https://developer.apple.com/xcode/)
|
||||
* [Homebrew](http://brew.sh/)
|
||||
* [Git](http://git-scm.com/)
|
||||
* [Scons](http://www.scons.org/)
|
||||
* [Node.js](http://nodejs.org/download/)
|
||||
|
||||
## Install Software
|
||||
|
||||
### Install XCode
|
||||
|
||||
If not already installed on your system, download and install XCode using the
|
||||
appstore or by using [this link](https://developer.apple.com/xcode/).
|
||||
|
||||
For more info, see "Step 1: Download and Install the Command Line Tools"
|
||||
[here](http://www.moncefbelyamani.com/how-to-install-xcode-homebrew-git-rvm-ruby-on-mac)
|
||||
|
||||
The command line tools can be installed through the terminal with the command:
|
||||
|
||||
```
|
||||
xcode-select --install
|
||||
```
|
||||
|
||||
### Install Homebrew
|
||||
|
||||
> "[Homebrew](http://brew.sh/) installs the stuff you need that Apple didn’t."
|
||||
|
||||
Open a terminal and type:
|
||||
|
||||
```
|
||||
ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
|
||||
```
|
||||
|
||||
For more info, see "Step 3: Install Homebrew"
|
||||
[here](http://www.moncefbelyamani.com/how-to-install-xcode-homebrew-git-rvm-ruby-on-mac)
|
||||
|
||||
### Install Git
|
||||
|
||||
```
|
||||
brew update brew install git
|
||||
```
|
||||
|
||||
For more info, see "Step 4: Install Git"
|
||||
[here](http://www.moncefbelyamani.com/how-to-install-xcode-homebrew-git-rvm-ruby-on-mac)
|
||||
|
||||
**NOTE**: To gain full featured access to the
|
||||
[git-subtree](http://blogs.atlassian.com/2013/05/alternatives-to-git-submodule-git-subtree/)
|
||||
functionality used in the rippled repository, we suggest Git version 1.8.3.2 or
|
||||
later.
|
||||
|
||||
### Install Scons
|
||||
|
||||
Requires version 2.3.0 or later
|
||||
|
||||
```
|
||||
brew install scons
|
||||
```
|
||||
|
||||
`brew` will generally install the latest stable version of any package, which
|
||||
will satisfy the scons minimum version requirement for rippled.
|
||||
|
||||
### Install Package Config
|
||||
|
||||
```
|
||||
brew install pkg-config
|
||||
```
|
||||
|
||||
## Install/Build/Configure Dependencies
|
||||
|
||||
### Build Google Protocol Buffers Compiler
|
||||
|
||||
Building rippled on osx requires `protoc` version 2.5.x or 2.6.x (later versions
|
||||
do not work with rippled at this time).
|
||||
|
||||
Download [this](https://github.com/google/protobuf/releases/download/v2.6.1/protobuf-2.6.1.tar.bz2)
|
||||
|
||||
We want to compile protocol buffers with clang/libc++:
|
||||
|
||||
```
|
||||
tar xfvj protobuf-2.6.1.tar.bz2
|
||||
cd protobuf-2.6.1
|
||||
./configure CC=clang CXX=clang++ CXXFLAGS='-std=c++11 -stdlib=libc++ -O3 -g' LDFLAGS='-stdlib=libc++' LIBS="-lc++ -lc++abi"
|
||||
make -j 4
|
||||
sudo make install
|
||||
```
|
||||
|
||||
If you have installed `protobuf` via brew - either directly or indirectly as a
|
||||
dependency of some other package - this is likely to conflict with our specific
|
||||
version requirements. The simplest way to avoid conflicts is to uninstall it.
|
||||
`brew ls --versions protobuf` will list any versions of protobuf
|
||||
you currently have installed.
|
||||
|
||||
### Install OpenSSL
|
||||
|
||||
```
|
||||
brew install openssl
|
||||
```
|
||||
|
||||
### Build Boost
|
||||
|
||||
We want to compile boost with clang/libc++
|
||||
|
||||
Download [a release](https://sourceforge.net/projects/boost/files/boost/1.61.0/boost_1_61_0.tar.bz2)
|
||||
|
||||
Extract it to a folder, making note of where, open a terminal, then:
|
||||
|
||||
```
|
||||
./bootstrap.sh ./b2 toolset=clang threading=multi runtime-link=static link=static cxxflags="-stdlib=libc++" linkflags="-stdlib=libc++" address-model=64
|
||||
```
|
||||
|
||||
Create an environment variable `BOOST_ROOT` in one of your `rc` files, pointing
|
||||
to the root of the extracted directory.
|
||||
|
||||
### Clone the rippled repository
|
||||
|
||||
From the terminal
|
||||
|
||||
```
|
||||
git clone git@github.com:ripple/rippled.git
|
||||
cd rippled
|
||||
```
|
||||
|
||||
Choose the master branch or one of the tagged releases listed on
|
||||
[GitHub](https://github.com/ripple/rippled/releases GitHub).
|
||||
|
||||
```
|
||||
git checkout master
|
||||
```
|
||||
|
||||
or to test the latest release candidate, choose the `release` branch.
|
||||
|
||||
```
|
||||
git checkout release
|
||||
```
|
||||
|
||||
### Configure Library Paths
|
||||
|
||||
If you didn't persistently set the `BOOST_ROOT` environment variable to the
|
||||
root of the extracted directory above, then you should set it temporarily.
|
||||
|
||||
For example, assuming your username were `Abigail` and you extracted Boost
|
||||
1.61.0 in `/Users/Abigail/Downloads/boost_1_61_0`, you would do for any
|
||||
shell in which you want to build:
|
||||
|
||||
```
|
||||
export BOOST_ROOT=/Users/Abigail/Downloads/boost_1_61_0
|
||||
```
|
||||
|
||||
## Build
|
||||
|
||||
```
|
||||
scons
|
||||
```
|
||||
|
||||
See: [here](https://ripple.com/wiki/Rippled_build_instructions#Building)
|
||||
|
||||
## Unit Tests (Recommended)
|
||||
|
||||
rippled builds a set of unit tests into the server executable. To run these unit
|
||||
tests after building, pass the `--unittest` option to the compiled `rippled`
|
||||
executable. The executable will exit after running the unit tests.
|
||||
|
||||
## System Tests (Recommended)
|
||||
|
||||
The external rippled system tests are written in Javascript using Node.js, and
|
||||
utilize the buster system test framework. To run the system tests, it will be
|
||||
necessary to perform the following steps:
|
||||
|
||||
### Install Node.js
|
||||
|
||||
Install [Node.js](http://nodejs.org/download/). We recommend the macos
|
||||
installer (`.pkg` file) since it takes care of updating the `PATH`
|
||||
environment variable so that scripts can find the command. On macos systems,
|
||||
`Node.js` comes with `npm`. A separate installation of `npm` is not
|
||||
necessary.
|
||||
|
||||
### Create node_modules
|
||||
|
||||
From the root of your local rippled repository, invoke `npm` to
|
||||
bring in the necessary components:
|
||||
|
||||
```
|
||||
npm install
|
||||
```
|
||||
|
||||
### Run Tests
|
||||
|
||||
```
|
||||
npm test
|
||||
```
|
||||
|
||||
### Development ripple-lib
|
||||
|
||||
If you want to use the latest branch of `ripple-lib` during the system tests:
|
||||
|
||||
1. clone the repository in a new location outside of your rippled repository.
|
||||
2. update the submodules in that repo.
|
||||
3. run `npm install` to set up the `node_modules` directory.
|
||||
4. install the `grunt` command line tools required to run `grunt` and build `ripple-lib`.
|
||||
|
||||
i.e.:
|
||||
|
||||
```
|
||||
git clone https://github.com/ripple/rippled.git
|
||||
cd ripple-lib
|
||||
git submodule update --init
|
||||
npm install
|
||||
npm install -g grunt-cli
|
||||
grunt
|
||||
```
|
||||
|
||||
Now link this version of `ripple-lib` into the global packages:
|
||||
|
||||
```
|
||||
sudo npm link
|
||||
```
|
||||
|
||||
To make rippled use the newly linked global `ripple-lib` package instead of
|
||||
the one installed under `node_modules`, change directories to the local
|
||||
rippled repository and delete the old `ripple-lib` then link to the new
|
||||
one:
|
||||
|
||||
```
|
||||
rm -rf node_modules/ripple-lib
|
||||
npm link ripple-lib
|
||||
```
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
Place XCode project file here!
|
||||
918
CMakeLists.txt
11
Jamroot
Normal file
@@ -0,0 +1,11 @@
|
||||
#
|
||||
# Copyright (c) 2013-2016 Vinnie Falco (vinnie dot falco at gmail dot com)
|
||||
#
|
||||
# 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)
|
||||
#
|
||||
|
||||
import boost ;
|
||||
|
||||
boost.use-project ;
|
||||
|
||||
@@ -5,7 +5,7 @@ Ripple is a network of computers which use the [Ripple consensus algorithm]
|
||||
(https://www.youtube.com/watch?v=pj1QVb1vlC0) to atomically settle and record
|
||||
transactions on a secure distributed database, the Ripple Consensus Ledger
|
||||
(RCL). Because of its distributed nature, the RCL offers transaction immutability
|
||||
without a central operator. The RCL contains a built-incurrency exchange and its
|
||||
without a central operator. The RCL contains a built-in currency exchange and its
|
||||
path-finding algorithm finds competitive exchange rates across order books
|
||||
and currency pairs.
|
||||
|
||||
|
||||
60
SConstruct
@@ -115,6 +115,7 @@ TODO
|
||||
|
||||
import collections
|
||||
import os
|
||||
import platform
|
||||
import subprocess
|
||||
import sys
|
||||
import textwrap
|
||||
@@ -122,6 +123,10 @@ import time
|
||||
import glob
|
||||
import SCons.Action
|
||||
|
||||
if (platform.architecture()[0] != '64bit'):
|
||||
print('Warning: Detected {} architecture. Rippled requires a 64-bit OS.'.format(
|
||||
platform.architecture()[0]));
|
||||
|
||||
sys.path.append(os.path.join('src', 'ripple', 'beast', 'site_scons'))
|
||||
sys.path.append(os.path.join('src', 'ripple', 'site_scons'))
|
||||
|
||||
@@ -380,11 +385,13 @@ def config_base(env):
|
||||
except KeyError:
|
||||
pass
|
||||
elif Beast.system.osx:
|
||||
OSX_OPENSSL_ROOT = '/usr/local/Cellar/openssl/'
|
||||
most_recent = sorted(os.listdir(OSX_OPENSSL_ROOT))[-1]
|
||||
openssl = os.path.join(OSX_OPENSSL_ROOT, most_recent)
|
||||
env.Prepend(CPPPATH='%s/include' % openssl)
|
||||
env.Prepend(LIBPATH=['%s/lib' % openssl])
|
||||
try:
|
||||
openssl = subprocess.check_output(['brew', '--prefix','openssl'],
|
||||
stderr=subprocess.STDOUT).strip()
|
||||
env.Prepend(CPPPATH='%s/include' % openssl)
|
||||
env.Prepend(LIBPATH=['%s/lib' % openssl])
|
||||
except:
|
||||
pass
|
||||
if not 'vcxproj' in COMMAND_LINE_TARGETS:
|
||||
env.Append(CPPDEFINES=['NO_LOG_UNHANDLED_EXCEPTIONS'])
|
||||
|
||||
@@ -456,9 +463,15 @@ def add_boost_and_protobuf(toolchain, env):
|
||||
br_cands = ['CLANG_BOOST_ROOT'] if toolchain == 'clang' else []
|
||||
br_cands.append('BOOST_ROOT')
|
||||
BOOST_ROOT = os.path.normpath(get_environ_value(br_cands))
|
||||
env.Append(LIBPATH=[
|
||||
os.path.join(BOOST_ROOT, 'stage', 'lib'),
|
||||
])
|
||||
stage64_path = os.path.join(BOOST_ROOT, 'stage64', 'lib')
|
||||
if os.path.exists(stage64_path):
|
||||
env.Append(LIBPATH=[
|
||||
stage64_path,
|
||||
])
|
||||
else:
|
||||
env.Append(LIBPATH=[
|
||||
os.path.join(BOOST_ROOT, 'stage', 'lib'),
|
||||
])
|
||||
env['BOOST_ROOT'] = BOOST_ROOT
|
||||
if toolchain in ['gcc', 'clang']:
|
||||
env.Append(CCFLAGS=['-isystem' + env['BOOST_ROOT']])
|
||||
@@ -487,6 +500,10 @@ def enable_asserts ():
|
||||
# Set toolchain and variant specific construction variables
|
||||
def config_env(toolchain, variant, env):
|
||||
add_boost_and_protobuf(toolchain, env)
|
||||
env.Append(CPPDEFINES=[
|
||||
'BOOST_COROUTINE_NO_DEPRECATION_WARNING',
|
||||
'BOOST_COROUTINES_NO_DEPRECATION_WARNING'
|
||||
])
|
||||
if is_debug_variant(variant):
|
||||
env.Append(CPPDEFINES=['DEBUG', '_DEBUG'])
|
||||
|
||||
@@ -541,7 +558,8 @@ def config_env(toolchain, variant, env):
|
||||
env.Append(CXXFLAGS=[
|
||||
'-frtti',
|
||||
'-std=c++14',
|
||||
'-Wno-invalid-offsetof'])
|
||||
'-Wno-invalid-offsetof'
|
||||
])
|
||||
|
||||
env.Append(CPPDEFINES=['_FILE_OFFSET_BITS=64'])
|
||||
|
||||
@@ -575,6 +593,9 @@ def config_env(toolchain, variant, env):
|
||||
])
|
||||
|
||||
boost_libs = [
|
||||
# resist the temptation to alphabetize these. coroutine
|
||||
# must come before context.
|
||||
'boost_chrono',
|
||||
'boost_coroutine',
|
||||
'boost_context',
|
||||
'boost_date_time',
|
||||
@@ -591,9 +612,13 @@ def config_env(toolchain, variant, env):
|
||||
else:
|
||||
# We prefer static libraries for boost
|
||||
if env.get('BOOST_ROOT'):
|
||||
static_libs64 = ['%s/stage64/lib/lib%s.a' % (env['BOOST_ROOT'], l) for
|
||||
l in boost_libs]
|
||||
static_libs = ['%s/stage/lib/lib%s.a' % (env['BOOST_ROOT'], l) for
|
||||
l in boost_libs]
|
||||
if all(os.path.exists(f) for f in static_libs):
|
||||
if all(os.path.exists(f) for f in static_libs64):
|
||||
boost_libs = [File(f) for f in static_libs64]
|
||||
elif all(os.path.exists(f) for f in static_libs):
|
||||
boost_libs = [File(f) for f in static_libs]
|
||||
env.Append(LIBS=boost_libs)
|
||||
|
||||
@@ -771,6 +796,7 @@ base.Append(CPPPATH=[
|
||||
os.path.join('src', 'beast'),
|
||||
os.path.join('src', 'beast', 'include'),
|
||||
os.path.join('src', 'beast', 'extras'),
|
||||
os.path.join('src', 'nudb', 'include'),
|
||||
os.path.join(build_dir, 'proto'),
|
||||
os.path.join('src','soci','src'),
|
||||
os.path.join('src','soci','include'),
|
||||
@@ -908,10 +934,10 @@ def get_classic_sources(toolchain):
|
||||
append_sources(result, *list_sources('src/ripple/beast/container', '.cpp'))
|
||||
append_sources(result, *list_sources('src/ripple/beast/insight', '.cpp'))
|
||||
append_sources(result, *list_sources('src/ripple/beast/net', '.cpp'))
|
||||
append_sources(result, *list_sources('src/ripple/beast/nudb', '.cpp'))
|
||||
append_sources(result, *list_sources('src/ripple/beast/utility', '.cpp'))
|
||||
append_sources(result, *list_sources('src/ripple/app', '.cpp'))
|
||||
append_sources(result, *list_sources('src/ripple/basics', '.cpp'))
|
||||
append_sources(result, *list_sources('src/ripple/conditions', '.cpp'))
|
||||
append_sources(result, *list_sources('src/ripple/crypto', '.cpp'))
|
||||
append_sources(result, *list_sources('src/ripple/json', '.cpp'))
|
||||
append_sources(result, *list_sources('src/ripple/ledger', '.cpp'))
|
||||
@@ -974,6 +1000,7 @@ def get_unity_sources(toolchain):
|
||||
'src/ripple/unity/app_misc.cpp',
|
||||
'src/ripple/unity/app_paths.cpp',
|
||||
'src/ripple/unity/app_tx.cpp',
|
||||
'src/ripple/unity/conditions.cpp',
|
||||
'src/ripple/unity/core.cpp',
|
||||
'src/ripple/unity/basics.cpp',
|
||||
'src/ripple/unity/crypto.cpp',
|
||||
@@ -991,6 +1018,7 @@ def get_unity_sources(toolchain):
|
||||
'src/unity/basics_test_unity.cpp',
|
||||
'src/unity/beast_test_unity.cpp',
|
||||
'src/unity/core_test_unity.cpp',
|
||||
'src/unity/conditions_test_unity.cpp',
|
||||
'src/unity/json_test_unity.cpp',
|
||||
'src/unity/ledger_test_unity.cpp',
|
||||
'src/unity/overlay_test_unity.cpp',
|
||||
@@ -1150,7 +1178,7 @@ for tu_style in ['classic', 'unity']:
|
||||
cc_flags = {}
|
||||
|
||||
object_builder.add_source_files(
|
||||
'src/ripple/unity/ed25519.c',
|
||||
'src/ripple/unity/ed25519_donna.c',
|
||||
CPPPATH=[
|
||||
'src/ed25519-donna',
|
||||
]
|
||||
@@ -1219,7 +1247,13 @@ for key, value in aliases.iteritems():
|
||||
vcxproj = base.VSProject(
|
||||
os.path.join('Builds', 'VisualStudio2015', 'RippleD'),
|
||||
source = [],
|
||||
VSPROJECT_ROOT_DIRS = ['src/beast', 'src/beast/include', 'src/beast/extras', 'src', '.'],
|
||||
VSPROJECT_ROOT_DIRS = [
|
||||
'build/',
|
||||
'src/beast/extras',
|
||||
'src/beast/include',
|
||||
'src/nudb/include',
|
||||
'src',
|
||||
'.'],
|
||||
VSPROJECT_CONFIGS = msvc_configs)
|
||||
base.Alias('vcxproj', vcxproj)
|
||||
|
||||
|
||||
113
appveyor.yml
@@ -6,22 +6,39 @@ environment:
|
||||
# that it's a small download. We also use appveyor's free cache, avoiding fees
|
||||
# downloading from S3 each time.
|
||||
# TODO: script to create this package.
|
||||
RIPPLED_DEPS_URL: https://ripple.github.io/Downloads/appveyor/rippled_deps15.01.zip
|
||||
RIPPLED_DEPS_PATH: rippled_deps15.02
|
||||
RIPPLED_DEPS_URL: https://ripple.github.io/Downloads/appveyor/%RIPPLED_DEPS_PATH%.zip
|
||||
|
||||
# Other dependencies we just download each time.
|
||||
PIP_URL: https://bootstrap.pypa.io/get-pip.py
|
||||
PIP_PATH: get-pip.py
|
||||
PIP_URL: https://bootstrap.pypa.io/%PIP_PATH%
|
||||
# The % in this URL messes up variable substition, so any updates will
|
||||
# need to update both PYWIN32_PATH and PYWIN32_URL
|
||||
PYWIN32_PATH: pywin32-220.win-amd64-py2.7.exe
|
||||
PYWIN32_URL: https://downloads.sourceforge.net/project/pywin32/pywin32/Build%20220/pywin32-220.win-amd64-py2.7.exe
|
||||
|
||||
# Scons honours these environment variables, setting the include/lib paths.
|
||||
BOOST_ROOT: C:/rippled_deps15.01/boost
|
||||
OPENSSL_ROOT: C:/rippled_deps15.01/openssl
|
||||
BOOST_ROOT: C:/%RIPPLED_DEPS_PATH%/boost
|
||||
OPENSSL_ROOT: C:/%RIPPLED_DEPS_PATH%/openssl
|
||||
|
||||
matrix:
|
||||
# This build works, but our current Appveyor config runs matrix builds
|
||||
# sequentially, and the one build is already slow enough.
|
||||
# - build: scons
|
||||
# target: msvc.debug
|
||||
- build: cmake
|
||||
target: msvc.debug
|
||||
buildconfig: Debug
|
||||
|
||||
os: Visual Studio 2015
|
||||
|
||||
# At the end of each successful build we cache this directory. It must be less
|
||||
# than 100MB total compressed.
|
||||
# At the end of each successful build we cache this directory.
|
||||
# https://www.appveyor.com/docs/build-cache/
|
||||
# Resulting archive should not exceed 100 MB.
|
||||
cache:
|
||||
- "C:\\rippled_deps15.01"
|
||||
- 'C:\%RIPPLED_DEPS_PATH%'
|
||||
- '%PIP_PATH%'
|
||||
- '%PYWIN32_PATH%'
|
||||
|
||||
# This means we'll download a zip of the branch we want, rather than the full
|
||||
# history.
|
||||
@@ -29,38 +46,36 @@ shallow_clone: true
|
||||
|
||||
install:
|
||||
# We want easy_install, python and protoc.exe on PATH.
|
||||
- SET PATH=%PYTHON%;%PYTHON%/Scripts;C:/rippled_deps15.01;%PATH%
|
||||
- SET PATH=%PYTHON%;%PYTHON%/Scripts;C:/%RIPPLED_DEPS_PATH%;%PATH%
|
||||
|
||||
# `ps` prefix means the command is executed by powershell.
|
||||
- ps: Start-FileDownload $env:PIP_URL
|
||||
- ps: Start-FileDownload $env:PYWIN32_URL
|
||||
|
||||
# Installing pip will install setuptools/easy_install.
|
||||
- python get-pip.py
|
||||
|
||||
# Pip has some problems installing scons on windows so we use easy install.
|
||||
# - easy_install scons
|
||||
# Workaround
|
||||
- easy_install https://pypi.python.org/packages/source/S/SCons/scons-2.5.0.tar.gz#md5=bda5530a70a41a7831d83c8b191c021e
|
||||
|
||||
# Scons has problems with parallel builds on windows without pywin32.
|
||||
- easy_install pywin32-220.win-amd64-py2.7.exe
|
||||
# (easy_install can do headless installs of .exe wizards)
|
||||
- ps: |
|
||||
if ($env:build -eq "scons") {
|
||||
if(-not(Test-Path $env:PIP_PATH)) {
|
||||
echo "Download from $env:PIP_URL"
|
||||
Start-FileDownload $env:PIP_URL
|
||||
}
|
||||
if(-not(Test-Path $env:PYWIN32_PATH)) {
|
||||
echo "Download from $env:PYWIN32_URL"
|
||||
Start-FileDownload $env:PYWIN32_URL
|
||||
}
|
||||
}
|
||||
- bin/ci/windows/install-dependencies.bat
|
||||
|
||||
# Download dependencies if appveyor didn't restore them from the cache.
|
||||
# Use 7zip to unzip.
|
||||
- ps: |
|
||||
if (-not(Test-Path 'C:/rippled_deps15.01')) {
|
||||
if (-not(Test-Path 'C:/$env:RIPPLED_DEPS_PATH')) {
|
||||
echo "Download from $env:RIPPLED_DEPS_URL"
|
||||
Start-FileDownload "$env:RIPPLED_DEPS_URL"
|
||||
7z x rippled_deps15.01.zip -oC:\ -y > $null
|
||||
7z x "$($env:RIPPLED_DEPS_PATH).zip" -oC:\ -y > $null
|
||||
}
|
||||
|
||||
# Newer DEPS include a versions file.
|
||||
# Dump it so we can verify correct behavior.
|
||||
- ps: |
|
||||
if (Test-Path 'C:/rippled_deps15.01/versions.txt') {
|
||||
cat 'C:/rippled_deps15.01/versions.txt'
|
||||
if (Test-Path "C:/$env:RIPPLED_DEPS_PATH/versions.txt") {
|
||||
cat "C:/$env:RIPPLED_DEPS_PATH/versions.txt"
|
||||
}
|
||||
|
||||
# TODO: This is giving me grief
|
||||
@@ -73,17 +88,45 @@ build_script:
|
||||
- '"%VS140COMNTOOLS%../../VC/vcvarsall.bat" x86_amd64'
|
||||
# Show which version of the compiler we are using.
|
||||
- cl
|
||||
- scons msvc.debug -j%NUMBER_OF_PROCESSORS%
|
||||
- ps: |
|
||||
if ($env:build -eq "scons") {
|
||||
# Build with scons
|
||||
scons $env:target -j%NUMBER_OF_PROCESSORS%
|
||||
}
|
||||
else
|
||||
{
|
||||
# Build with cmake
|
||||
cmake --version
|
||||
$cmake_target="$($env:target).ci"
|
||||
"$cmake_target"
|
||||
New-Item -ItemType Directory -Force -Path "build/$cmake_target"
|
||||
Push-Location "build/$cmake_target"
|
||||
cmake -G"Visual Studio 14 2015 Win64" -Dtarget="$cmake_target" ../..
|
||||
cmake --build . --config $env:buildconfig -- -m
|
||||
Pop-Location
|
||||
}
|
||||
|
||||
after_build:
|
||||
# Put our executable in a place where npm test can find it.
|
||||
- ps: cp build/msvc.debug/rippled.exe build
|
||||
- ps: ls build
|
||||
- ps: |
|
||||
if ($env:build -eq "scons") {
|
||||
# Put our executable in a place where npm test can find it.
|
||||
cp build/$($env:target)/rippled.exe build
|
||||
ls build
|
||||
$exe="build/rippled"
|
||||
}
|
||||
else
|
||||
{
|
||||
$exe="build/$cmake_target/$env:buildconfig/rippled"
|
||||
}
|
||||
"Exe is at $exe"
|
||||
|
||||
test_script:
|
||||
# Run the unit tests
|
||||
- build\\rippled --unittest
|
||||
- ps: |
|
||||
# Run the rippled unit tests
|
||||
& $exe --unittest
|
||||
|
||||
# Run the rippled integration tests
|
||||
& npm install --progress=false
|
||||
& npm test --rippled="$exe"
|
||||
|
||||
|
||||
# Run the integration tests
|
||||
- npm install --progress=false
|
||||
- npm test
|
||||
|
||||
@@ -1,25 +1,59 @@
|
||||
#!/bin/bash -u
|
||||
# We use set -e and bash with -u to bail on first non zero exit code of any
|
||||
# processes launched or upon any unbound variable
|
||||
set -e
|
||||
# processes launched or upon any unbound variable.
|
||||
# We use set -x to print commands before running them to help with
|
||||
# debugging.
|
||||
set -ex
|
||||
__dirname=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
|
||||
echo "using CC: $CC"
|
||||
echo "using TARGET: $TARGET"
|
||||
export RIPPLED_PATH="$PWD/build/$CC.$TARGET/rippled"
|
||||
echo "using RIPPLED_PATH: $RIPPLED_PATH"
|
||||
# Make sure vcxproj is up to date
|
||||
scons vcxproj
|
||||
git diff --exit-code
|
||||
# $CC will be either `clang` or `gcc`
|
||||
# http://docs.travis-ci.com/user/migrating-from-legacy/?utm_source=legacy-notice&utm_medium=banner&utm_campaign=legacy-upgrade
|
||||
# indicates that 2 cores are available to containers.
|
||||
scons -j${NUM_PROCESSORS:-2} $CC.$TARGET
|
||||
|
||||
# Ensure APP defaults to rippled if it's not set.
|
||||
: ${APP:=rippled}
|
||||
if [[ ${BUILD:-scons} == "cmake" ]]; then
|
||||
echo "cmake building ${APP}"
|
||||
CMAKE_TARGET=$CC.$TARGET
|
||||
if [[ ${CI:-} == true ]]; then
|
||||
CMAKE_TARGET=$CMAKE_TARGET.ci
|
||||
fi
|
||||
mkdir -p "build/${CMAKE_TARGET}"
|
||||
pushd "build/${CMAKE_TARGET}"
|
||||
cmake ../.. -Dtarget=$CMAKE_TARGET
|
||||
cmake --build . -- -j${NUM_PROCESSORS:-2}
|
||||
popd
|
||||
export APP_PATH="$PWD/build/${CMAKE_TARGET}/${APP}"
|
||||
echo "using APP_PATH: $APP_PATH"
|
||||
|
||||
else
|
||||
export APP_PATH="$PWD/build/$CC.$TARGET/${APP}"
|
||||
echo "using APP_PATH: $APP_PATH"
|
||||
# Make sure vcxproj is up to date
|
||||
scons vcxproj
|
||||
git diff --exit-code
|
||||
# $CC will be either `clang` or `gcc`
|
||||
# http://docs.travis-ci.com/user/migrating-from-legacy/?utm_source=legacy-notice&utm_medium=banner&utm_campaign=legacy-upgrade
|
||||
# indicates that 2 cores are available to containers.
|
||||
scons -j${NUM_PROCESSORS:-2} $CC.$TARGET
|
||||
fi
|
||||
# We can be sure we're using the build/$CC.$TARGET variant
|
||||
# (-f so never err)
|
||||
rm -f build/rippled
|
||||
rm -f build/${APP}
|
||||
|
||||
# See what we've actually built
|
||||
ldd $RIPPLED_PATH
|
||||
ldd $APP_PATH
|
||||
|
||||
if [[ ${APP} == "rippled" ]]; then
|
||||
export APP_ARGS="--unittest"
|
||||
# Only report on src/ripple files
|
||||
export LCOV_FILES="*/src/ripple/*"
|
||||
# Exclude */src/ripple/test directory
|
||||
export LCOV_EXCLUDE_FILES="*/src/ripple/test/*"
|
||||
else
|
||||
: ${APP_ARGS:=}
|
||||
: ${LCOV_FILES:="*/src/*"}
|
||||
# Don't exclude anything
|
||||
: ${LCOV_EXCLUDE_FILES:="LCOV_NO_EXCLUDE"}
|
||||
fi
|
||||
|
||||
if [[ $TARGET == "coverage" ]]; then
|
||||
export PATH=$PATH:$LCOV_ROOT/usr/bin
|
||||
@@ -36,7 +70,7 @@ gdb -return-child-result -quiet -batch \
|
||||
-ex run \
|
||||
-ex "thread apply all backtrace full" \
|
||||
-ex "quit" \
|
||||
--args $RIPPLED_PATH --unittest
|
||||
--args $APP_PATH --unittest
|
||||
|
||||
if [[ $TARGET == "coverage" ]]; then
|
||||
# Create test coverage data file
|
||||
@@ -45,16 +79,18 @@ if [[ $TARGET == "coverage" ]]; then
|
||||
# Combine baseline and test coverage data
|
||||
lcov -a baseline.info -a tests.info -o lcov-all.info
|
||||
|
||||
# Only report on src/ripple files
|
||||
lcov -e "lcov-all.info" "*/src/ripple/*" -o lcov.pre.info
|
||||
# Included files
|
||||
lcov -e "lcov-all.info" "${LCOV_FILES}" -o lcov.pre.info
|
||||
|
||||
# Exclude */src/test directory
|
||||
lcov --remove lcov.pre.info "*/src/ripple/test/*" -o lcov.info
|
||||
# Excluded files
|
||||
lcov --remove lcov.pre.info "${LCOV_EXCLUDE_FILES}" -o lcov.info
|
||||
|
||||
# Push the results (lcov.info) to codecov
|
||||
codecov -X gcov # don't even try and look for .gcov files ;)
|
||||
fi
|
||||
|
||||
# Run NPM tests
|
||||
npm install --progress=false
|
||||
npm test --rippled=$RIPPLED_PATH
|
||||
if [[ ${APP} == "rippled" ]]; then
|
||||
# Run NPM tests
|
||||
npm install --progress=false
|
||||
npm test --rippled=$APP_PATH
|
||||
fi
|
||||
|
||||
@@ -1,6 +1,11 @@
|
||||
#!/bin/bash -u
|
||||
# Exit if anything fails.
|
||||
set -e
|
||||
# Exit if anything fails. Echo commands to aid debugging.
|
||||
set -ex
|
||||
|
||||
# Target working dir - defaults to current dir.
|
||||
# Can be set from caller, or in the first parameter
|
||||
TWD=$( cd ${TWD:-${1:-${PWD:-$( pwd )}}}; pwd )
|
||||
echo "Target path is: $TWD"
|
||||
# Override gcc version to $GCC_VER.
|
||||
# Put an appropriate symlink at the front of the path.
|
||||
mkdir -v $HOME/bin
|
||||
@@ -13,16 +18,34 @@ done
|
||||
if [[ -n ${CLANG_VER:-} ]]; then
|
||||
# There are cases where the directory exists, but the exe is not available.
|
||||
# Use this workaround for now.
|
||||
if [[ ! -x llvm-${LLVM_VERSION}/bin/llvm-config ]] && [[ -d llvm-${LLVM_VERSION} ]]; then
|
||||
rm -fr llvm-${LLVM_VERSION}
|
||||
if [[ ! -x ${TWD}/llvm-${LLVM_VERSION}/bin/llvm-config && -d ${TWD}/llvm-${LLVM_VERSION} ]]; then
|
||||
rm -fr ${TWD}/llvm-${LLVM_VERSION}
|
||||
fi
|
||||
if [[ ! -d llvm-${LLVM_VERSION} ]]; then
|
||||
mkdir llvm-${LLVM_VERSION}
|
||||
if [[ ! -d ${TWD}/llvm-${LLVM_VERSION} ]]; then
|
||||
mkdir ${TWD}/llvm-${LLVM_VERSION}
|
||||
LLVM_URL="http://llvm.org/releases/${LLVM_VERSION}/clang+llvm-${LLVM_VERSION}-x86_64-linux-gnu-ubuntu-14.04.tar.xz"
|
||||
wget -O - ${LLVM_URL} | tar -Jxvf - --strip 1 -C llvm-${LLVM_VERSION}
|
||||
wget -O - ${LLVM_URL} | tar -Jxvf - --strip 1 -C ${TWD}/llvm-${LLVM_VERSION}
|
||||
fi
|
||||
${TWD}/llvm-${LLVM_VERSION}/bin/llvm-config --version;
|
||||
export LLVM_CONFIG="${TWD}/llvm-${LLVM_VERSION}/bin/llvm-config";
|
||||
fi
|
||||
|
||||
if [[ ${BUILD:-} == cmake ]]; then
|
||||
# There are cases where the directory exists, but the exe is not available.
|
||||
# Use this workaround for now.
|
||||
if [[ ! -x ${TWD}/cmake/bin/cmake && -d ${TWD}/cmake ]]; then
|
||||
rm -fr ${TWD}/cmake
|
||||
fi
|
||||
if [[ ! -d ${TWD}/cmake ]]; then
|
||||
CMAKE_URL="https://www.cmake.org/files/v3.6/cmake-3.6.1-Linux-x86_64.tar.gz"
|
||||
wget --version
|
||||
# wget version 1.13.4 thinks this certificate is invalid, even though it's fine.
|
||||
# "ERROR: no certificate subject alternative name matches"
|
||||
# See also: https://github.com/travis-ci/travis-ci/issues/5059
|
||||
mkdir ${TWD}/cmake &&
|
||||
wget -O - --no-check-certificate ${CMAKE_URL} | tar --strip-components=1 -xz -C ${TWD}/cmake
|
||||
cmake --version
|
||||
fi
|
||||
llvm-${LLVM_VERSION}/bin/llvm-config --version;
|
||||
export LLVM_CONFIG="llvm-${LLVM_VERSION}/bin/llvm-config";
|
||||
fi
|
||||
|
||||
# What versions are we ACTUALLY running?
|
||||
|
||||
13
bin/ci/windows/install-dependencies.bat
Normal file
@@ -0,0 +1,13 @@
|
||||
if "%build%" == "scons" (
|
||||
rem Installing pip will install setuptools/easy_install.
|
||||
python "%PIP_PATH%"
|
||||
|
||||
rem Pip has some problems installing scons on windows so we use easy install.
|
||||
rem - easy_install scons
|
||||
rem Workaround
|
||||
easy_install https://pypi.python.org/packages/source/S/SCons/scons-2.5.0.tar.gz#md5=bda5530a70a41a7831d83c8b191c021e
|
||||
|
||||
rem Scons has problems with parallel builds on windows without pywin32.
|
||||
easy_install "%PYWIN32_PATH%"
|
||||
rem (easy_install can do headless installs of .exe wizards)
|
||||
)
|
||||
@@ -5,4 +5,11 @@ To run the Python unit tests, execute:
|
||||
|
||||
python -m unittest discover
|
||||
|
||||
from this directory.
|
||||
from this directory.
|
||||
|
||||
To run Python unit tests from a particular file (such as
|
||||
`ripple/util/test_Sign.py`), execute:
|
||||
|
||||
python -m unittest ripple.util.test_Sign
|
||||
|
||||
Add `-v` to run tests in verbose mode.
|
||||
|
||||
@@ -52,7 +52,7 @@ class DatumInContext(object):
|
||||
"""
|
||||
Represents a datum along a path from a context.
|
||||
|
||||
Essentially a zipper but with a structure represented by JsonPath,
|
||||
Essentially a zipper but with a structure represented by JSONPath,
|
||||
and where the context is more of a parent pointer than a proper
|
||||
representation of the context.
|
||||
|
||||
|
||||
@@ -49,3 +49,4 @@ sfSequence = field_code(STI_UINT32, 4)
|
||||
sfPublicKey = field_code(STI_VL, 1)
|
||||
sfSigningPubKey = field_code(STI_VL, 3)
|
||||
sfSignature = field_code(STI_VL, 6)
|
||||
sfMasterSignature = field_code(STI_VL, 18)
|
||||
|
||||
@@ -5,11 +5,12 @@ from __future__ import print_function
|
||||
import base64, os, random, struct, sys
|
||||
import ed25519
|
||||
import ecdsa
|
||||
import hashlib
|
||||
from ripple.util import Base58
|
||||
from ripple.ledger import SField
|
||||
|
||||
ED25519_BYTE = chr(0xed)
|
||||
WRAP_COLUMNS = 60
|
||||
WRAP_COLUMNS = 72
|
||||
|
||||
USAGE = """\
|
||||
Usage:
|
||||
@@ -22,12 +23,9 @@ Usage:
|
||||
check <key>
|
||||
Check an existing key for validity.
|
||||
|
||||
sign <sequence> <validator-public> <master-secret>
|
||||
sign <sequence> <validation-public-key> <validation-private-key> <master-secret>
|
||||
Create a new signed manifest with the given sequence
|
||||
number, validator public key, and master secret key.
|
||||
|
||||
verify <sequence> <validator-public> <signature> <master-public>
|
||||
Verify hex-encoded manifest signature with master public key.
|
||||
number and keys.
|
||||
"""
|
||||
|
||||
def prepend_length_byte(b):
|
||||
@@ -44,17 +42,17 @@ def make_seed(urandom=os.urandom):
|
||||
return urandom(16)
|
||||
|
||||
def make_ed25519_keypair(urandom=os.urandom):
|
||||
private_key = urandom(32)
|
||||
return private_key, ed25519.publickey(private_key)
|
||||
sk = urandom(32)
|
||||
return sk, ed25519.publickey(sk)
|
||||
|
||||
def make_ecdsa_keypair():
|
||||
def make_ecdsa_keypair(urandom=None):
|
||||
# This is not used.
|
||||
private_key = ecdsa.SigningKey.generate(curve=ecdsa.SECP256k1)
|
||||
sk = ecdsa.SigningKey.generate(curve=ecdsa.SECP256k1, entropy=urandom)
|
||||
# Can't be unit tested easily - need a mock for ecdsa.
|
||||
vk = private_key.get_verifying_key()
|
||||
sig = private_key.sign('message')
|
||||
vk = sk.get_verifying_key()
|
||||
sig = sk.sign('message')
|
||||
assert vk.verify(sig, 'message')
|
||||
return private_key, vk
|
||||
return sk, vk
|
||||
|
||||
def make_seed_from_passphrase(passphrase):
|
||||
# For convenience, like say testing against rippled we can hash a passphrase
|
||||
@@ -62,18 +60,58 @@ def make_seed_from_passphrase(passphrase):
|
||||
# an optional arg, which can be a base58 encoded seed, or a passphrase.
|
||||
return hashlib.sha512(passphrase).digest()[:16]
|
||||
|
||||
def make_manifest(public_key, validator_public_key, seq):
|
||||
def make_manifest(master_pk, validation_pk, seq):
|
||||
"""create a manifest
|
||||
|
||||
Parameters
|
||||
----------
|
||||
master_pk : string
|
||||
validator's master public key (binary, _not_ BASE58 encoded)
|
||||
validation_pk : string
|
||||
validator's validation public key (binary, _not_ BASE58 encoded)
|
||||
seq : int
|
||||
manifest sequence number
|
||||
|
||||
Returns
|
||||
----------
|
||||
string
|
||||
String with fields for seq, master_pk, validation_pk
|
||||
"""
|
||||
return ''.join([
|
||||
SField.sfSequence,
|
||||
to_int32(seq),
|
||||
SField.sfPublicKey, # Master public key.
|
||||
prepend_length_byte(public_key),
|
||||
SField.sfSigningPubKey, # Ephemeral public key.
|
||||
prepend_length_byte(validator_public_key)])
|
||||
SField.sfPublicKey,
|
||||
prepend_length_byte(master_pk),
|
||||
SField.sfSigningPubKey,
|
||||
prepend_length_byte(validation_pk)])
|
||||
|
||||
def sign_manifest(manifest, private_key, public_key):
|
||||
sig = ed25519.signature('MAN\0' + manifest, private_key, public_key)
|
||||
return manifest + SField.sfSignature + prepend_length_byte(sig)
|
||||
def sign_manifest(manifest, validation_sk, master_sk, master_pk):
|
||||
"""sign a validator manifest
|
||||
|
||||
Parameters
|
||||
----------
|
||||
manifest : string
|
||||
manifest to sign
|
||||
validation_sk : string
|
||||
validator's validation secret key (binary, _not_ BASE58 encoded)
|
||||
This is one of the keys that will sign the manifest.
|
||||
master_sk : string
|
||||
validator's master secret key (binary, _not_ BASE58 encoded)
|
||||
This is one of the keys that will sign the manifest.
|
||||
master_pk : string
|
||||
validator's master public key (binary, _not_ BASE58 encoded)
|
||||
|
||||
Returns
|
||||
----------
|
||||
string
|
||||
manifest signed by both the validation and master keys
|
||||
"""
|
||||
man_hash = hashlib.sha512('MAN\0' + manifest).digest()[:32]
|
||||
validation_sig = validation_sk.sign_digest_deterministic(
|
||||
man_hash, hashfunc=hashlib.sha256, sigencode=ecdsa.util.sigencode_der_canonize)
|
||||
master_sig = ed25519.signature('MAN\0' + manifest, master_sk, master_pk)
|
||||
return manifest + SField.sfSignature + prepend_length_byte(validation_sig) + \
|
||||
SField.sfMasterSignature + prepend_length_byte(master_sig)
|
||||
|
||||
def wrap(s, cols=WRAP_COLUMNS):
|
||||
if s:
|
||||
@@ -83,72 +121,64 @@ def wrap(s, cols=WRAP_COLUMNS):
|
||||
return s
|
||||
|
||||
def create_ed_keys(urandom=os.urandom):
|
||||
private_key, public_key = make_ed25519_keypair(urandom)
|
||||
public_key_human = Base58.encode_version(
|
||||
Base58.VER_NODE_PUBLIC, ED25519_BYTE + public_key)
|
||||
private_key_human = Base58.encode_version(
|
||||
Base58.VER_NODE_PRIVATE, private_key)
|
||||
return public_key_human, private_key_human
|
||||
sk, pk = make_ed25519_keypair(urandom)
|
||||
pk_human = Base58.encode_version(
|
||||
Base58.VER_NODE_PUBLIC, ED25519_BYTE + pk)
|
||||
sk_human = Base58.encode_version(
|
||||
Base58.VER_NODE_PRIVATE, sk)
|
||||
return pk_human, sk_human
|
||||
|
||||
def create_ed_public_key(private_key_human):
|
||||
v, private_key = Base58.decode_version(private_key_human)
|
||||
check_master_secret(v, private_key)
|
||||
def create_ed_public_key(sk_human):
|
||||
v, sk = Base58.decode_version(sk_human)
|
||||
check_secret_key(v, sk)
|
||||
|
||||
public_key = ed25519.publickey(private_key)
|
||||
public_key_human = Base58.encode_version(
|
||||
Base58.VER_NODE_PUBLIC, ED25519_BYTE + public_key)
|
||||
return public_key_human
|
||||
pk = ed25519.publickey(sk)
|
||||
pk_human = Base58.encode_version(
|
||||
Base58.VER_NODE_PUBLIC, ED25519_BYTE + pk)
|
||||
return pk_human
|
||||
|
||||
def check_validator_public(v, validator_public_key):
|
||||
def check_validation_public_key(v, pk):
|
||||
Base58.check_version(v, Base58.VER_NODE_PUBLIC)
|
||||
if len(validator_public_key) != 33:
|
||||
raise ValueError('Validator key should be length 33, is %s' %
|
||||
len(validator_public_key))
|
||||
b = ord(validator_public_key[0])
|
||||
if len(pk) != 33:
|
||||
raise ValueError('Validation public key should be length 33, is %s' %
|
||||
len(pk))
|
||||
b = ord(pk[0])
|
||||
if b not in (2, 3):
|
||||
raise ValueError('First validator key byte must be 2 or 3, is %d' % b)
|
||||
raise ValueError('First validation public key byte must be 2 or 3, is %d' % b)
|
||||
|
||||
def check_master_secret(v, private_key):
|
||||
def check_secret_key(v, sk):
|
||||
Base58.check_version(v, Base58.VER_NODE_PRIVATE)
|
||||
if len(private_key) != 32:
|
||||
if len(sk) != 32:
|
||||
raise ValueError('Length of master secret should be 32, is %s' %
|
||||
len(private_key))
|
||||
len(sk))
|
||||
|
||||
def get_signature(seq, validation_pk_human, validation_sk_human, master_sk_human):
|
||||
v, validation_pk = Base58.decode_version(validation_pk_human)
|
||||
check_validation_public_key(v, validation_pk)
|
||||
|
||||
def get_signature(seq, validator_public_key_human, private_key_human):
|
||||
v, validator_public_key = Base58.decode_version(validator_public_key_human)
|
||||
check_validator_public(v, validator_public_key)
|
||||
v, validation_sk_str = Base58.decode_version(validation_sk_human)
|
||||
check_secret_key(v, validation_sk_str)
|
||||
validation_sk = ecdsa.SigningKey.from_string(validation_sk_str, curve=ecdsa.SECP256k1)
|
||||
|
||||
v, private_key = Base58.decode_version(private_key_human)
|
||||
check_master_secret(v, private_key)
|
||||
v, master_sk = Base58.decode_version(master_sk_human)
|
||||
check_secret_key(v, master_sk)
|
||||
|
||||
pk = ed25519.publickey(private_key)
|
||||
pk = ed25519.publickey(master_sk)
|
||||
apk = ED25519_BYTE + pk
|
||||
m = make_manifest(apk, validator_public_key, seq)
|
||||
m1 = sign_manifest(m, private_key, pk)
|
||||
m = make_manifest(apk, validation_pk, seq)
|
||||
m1 = sign_manifest(m, validation_sk, master_sk, pk)
|
||||
return base64.b64encode(m1)
|
||||
|
||||
def verify_signature(seq, validator_public_key_human, public_key_human, signature):
|
||||
v, validator_public_key = Base58.decode_version(validator_public_key_human)
|
||||
check_validator_public(v, validator_public_key)
|
||||
|
||||
v, public_key = Base58.decode_version(public_key_human)
|
||||
|
||||
m = make_manifest(public_key, validator_public_key, seq)
|
||||
public_key = public_key[1:] # Remove ED25519_BYTE
|
||||
sig = signature.decode('hex')
|
||||
ed25519.checkvalid(sig, 'MAN\0' + m, public_key)
|
||||
|
||||
# Testable versions of functions.
|
||||
def perform_create(urandom=os.urandom, print=print):
|
||||
public, private = create_ed_keys(urandom)
|
||||
print('[validator_keys]', public, '', '[master_secret]', private, sep='\n')
|
||||
pk, sk = create_ed_keys(urandom)
|
||||
print('[validator_keys]', pk, '', '[master_secret]', sk, sep='\n')
|
||||
|
||||
def perform_create_public(private_key_human, print=print):
|
||||
public_key_human = create_ed_public_key(private_key_human)
|
||||
def perform_create_public(sk_human, print=print):
|
||||
pk_human = create_ed_public_key(sk_human)
|
||||
print(
|
||||
'[validator_keys]',public_key_human, '',
|
||||
'[master_secret]', private_key_human, sep='\n')
|
||||
'[validator_keys]',pk_human, '',
|
||||
'[master_secret]', sk_human, sep='\n')
|
||||
|
||||
def perform_check(s, print=print):
|
||||
version, b = Base58.decode_version(s)
|
||||
@@ -157,32 +187,29 @@ def perform_check(s, print=print):
|
||||
assert Base58.encode_version(version, b) == s
|
||||
|
||||
def perform_sign(
|
||||
seq, validator_public_key_human, private_key_human, print=print):
|
||||
seq, validation_pk_human, validation_sk_human, master_sk_human, print=print):
|
||||
print('[validation_manifest]')
|
||||
print(wrap(get_signature(
|
||||
int(seq), validator_public_key_human, private_key_human)))
|
||||
int(seq), validation_pk_human, validation_sk_human, master_sk_human)))
|
||||
|
||||
def perform_verify(
|
||||
seq, validator_public_key_human, public_key_human, signature, print=print):
|
||||
seq, validation_pk_human, master_pk_human, signature, print=print):
|
||||
verify_signature(
|
||||
int(seq), validator_public_key_human, public_key_human, signature)
|
||||
print('Signature valid for', public_key_human)
|
||||
int(seq), validation_pk_human, master_pk_human, signature)
|
||||
print('Signature valid for', master_pk_human)
|
||||
|
||||
# Externally visible versions of functions.
|
||||
def create(private_key_human=None):
|
||||
if private_key_human:
|
||||
perform_create_public(private_key_human)
|
||||
def create(sk_human=None):
|
||||
if sk_human:
|
||||
perform_create_public(sk_human)
|
||||
else:
|
||||
perform_create()
|
||||
|
||||
def check(s):
|
||||
perform_check(s)
|
||||
|
||||
def sign(seq, validator_public_key_human, private_key_human):
|
||||
perform_sign(seq, validator_public_key_human, private_key_human)
|
||||
|
||||
def verify(seq, validator_public_key_human, public_key_human, signature):
|
||||
perform_verify(seq, validator_public_key_human, public_key_human, signature)
|
||||
def sign(seq, validation_pk_human, validation_sk_human, master_sk_human):
|
||||
perform_sign(seq, validation_pk_human, validation_sk_human, master_sk_human)
|
||||
|
||||
def usage(*errors):
|
||||
if errors:
|
||||
@@ -190,7 +217,7 @@ def usage(*errors):
|
||||
print(USAGE)
|
||||
return not errors
|
||||
|
||||
_COMMANDS = dict((f.__name__, f) for f in (create, check, sign, verify))
|
||||
_COMMANDS = dict((f.__name__, f) for f in (create, check, sign))
|
||||
|
||||
def run_command(args):
|
||||
if not args:
|
||||
|
||||
@@ -10,14 +10,7 @@ BINARY = 'nN9kfUnKTf7PpgLG'
|
||||
|
||||
class test_Sign(TestCase):
|
||||
SEQUENCE = 23
|
||||
SIGNATURE = (
|
||||
'JAAAABdxIe2DIKUZd9jDjKikknxnDfWCHkSXYZReFenvsmoVCdIw6nMhAnZ2dnZ2'
|
||||
'dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dkDOjlWtQSvRTjuwe+4iNusg0sJM'
|
||||
'zqkBJwDz30b2SkxZ7Fte/Vx4htM/kkfUfJCaxmxE5N4dHSKuiO9iDHsktqIA')
|
||||
VALIDATOR_KEY_HUMAN = 'n9JijuoCv8ubEy5ag3LiX3hyq27GaLJsitZPbQ6APkwx2MkUXq8E'
|
||||
SIGNATURE_HEX = (
|
||||
'0a1546caa29c887f9fcb5e6143ea101b31fb5895a5cdfa24939301c66ff51794'
|
||||
'a0b729e0ebbf576f2cc7cdb9f68c2366324a53b8e1ecf16f3c17bebbdb8d7102')
|
||||
|
||||
def setUp(self):
|
||||
self.results = []
|
||||
@@ -59,13 +52,17 @@ class test_Sign(TestCase):
|
||||
'\xef*\x97\x16n<\xa6\xf2\xe4\xfb\xfc\xcd\x80P[\xf1s\x06verify')
|
||||
|
||||
def test_sign_manifest(self):
|
||||
ssk, spk = Sign.make_ecdsa_keypair(self.urandom)
|
||||
sk, pk = Sign.make_ed25519_keypair(self.urandom)
|
||||
s = Sign.sign_manifest('manifest', sk, pk)
|
||||
s = Sign.sign_manifest('manifest', ssk, sk, pk)
|
||||
self.assertEquals(
|
||||
s, 'manifestv@\xe5\x84\xbe\xc4\x80N\xa0v"\xb2\x80A\x88\x06\xc0'
|
||||
'\xd2\xbae\x92\x89\xa8\'!\xdd\x00\x88\x06s\xe0\xf74\xe3Yg\xad{$'
|
||||
'\x17\xd3\x99\xaa\x16\xb0\xeaZ\xd7]\r\xb3\xdc\x1b\x8f\xc1Z\xdfHU'
|
||||
'\xb5\x92\xac\x82jI\x02')
|
||||
s, 'manifestvF0D\x02 \x04\x85\x95p\x0f\xb8\x17\x7f\xdf\xdd\x04'
|
||||
'\xaa+\x16q1W\xf6\xfd\xe8X\xb12l\xd5\xc3\xf1\xd6\x05\x1b\x1c\x9a'
|
||||
'\x02 \x18\\.(o\xa8 \xeb\x87\xfa&~\xbd\xe6,\xfb\xa61\xd1\xcd\xcd'
|
||||
'\xc8\r\x16[\x81\x9a\x19\xda\x93i\xcdp\x12@\xe5\x84\xbe\xc4\x80N'
|
||||
'\xa0v"\xb2\x80A\x88\x06\xc0\xd2\xbae\x92\x89\xa8\'!\xdd\x00\x88'
|
||||
'\x06s\xe0\xf74\xe3Yg\xad{$\x17\xd3\x99\xaa\x16\xb0\xeaZ\xd7]\r'
|
||||
'\xb3\xdc\x1b\x8f\xc1Z\xdfHU\xb5\x92\xac\x82jI\x02')
|
||||
|
||||
def test_wrap(self):
|
||||
wrap = lambda s: Sign.wrap(s, 5)
|
||||
@@ -93,23 +90,21 @@ class test_Sign(TestCase):
|
||||
public = (Base58.VER_NODE_PUBLIC, '\x02' + (32 * 'v'))
|
||||
private = (Base58.VER_NODE_PRIVATE, 32 * 'k')
|
||||
|
||||
Sign.check_validator_public(*public)
|
||||
Sign.check_master_secret(*private)
|
||||
Sign.check_validation_public_key(*public)
|
||||
Sign.check_secret_key(*private)
|
||||
|
||||
return (Base58.encode_version(*public), Base58.encode_version(*private))
|
||||
|
||||
def test_get_signature(self):
|
||||
signature = Sign.get_signature(self.SEQUENCE, *self.get_test_keypair())
|
||||
pk, sk = self.get_test_keypair()
|
||||
signature = Sign.get_signature(self.SEQUENCE, pk, sk, sk)
|
||||
self.assertEquals(
|
||||
signature,
|
||||
'JAAAABdxIe2DIKUZd9jDjKikknxnDfWCHkSXYZReFenvsmoVCdIw6nMhAnZ2dnZ2'
|
||||
'dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dkDOjlWtQSvRTjuwe+4iNusg0sJM'
|
||||
'zqkBJwDz30b2SkxZ7Fte/Vx4htM/kkfUfJCaxmxE5N4dHSKuiO9iDHsktqIA')
|
||||
|
||||
def test_verify_signature(self):
|
||||
Sign.verify_signature(self.SEQUENCE, self.VALIDATOR_KEY_HUMAN,
|
||||
'nHUUaKHpxyRP4TZZ79tTpXuTpoM8pRNs5crZpGVA5jdrjib5easY',
|
||||
self.SIGNATURE_HEX)
|
||||
'dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dkYwRAIgXyobHA8sDQxmDJNLE6HI'
|
||||
'aARlzvcd79/wT068e113gUkCIHkI540JQT2LHwAD7/y3wFE5X3lEXMfgZRkpLZTx'
|
||||
'kpticBJAzo5VrUEr0U47sHvuIjbrINLCTM6pAScA899G9kpMWexbXv1ceIbTP5JH'
|
||||
'1HyQmsZsROTeHR0irojvYgx7JLaiAA==')
|
||||
|
||||
def test_check(self):
|
||||
public = Base58.encode_version(Base58.VER_NODE_PRIVATE, 32 * 'k')
|
||||
@@ -143,17 +138,12 @@ class test_Sign(TestCase):
|
||||
|
||||
def test_sign(self):
|
||||
public, private = self.get_test_keypair()
|
||||
Sign.perform_sign(self.SEQUENCE, public, private, print=self.print)
|
||||
Sign.perform_sign(self.SEQUENCE, public, private, private, print=self.print)
|
||||
self.assertEquals(
|
||||
self.results,
|
||||
[[['[validation_manifest]'], {}],
|
||||
[['JAAAABdxIe2DIKUZd9jDjKikknxnDfWCHkSXYZReFenvsmo\n'
|
||||
'VCdIw6nMhAnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dn\n'
|
||||
'Z2dnZ2dkDOjlWtQSvRTjuwe+4iNusg0sJMzqkBJwDz30b2S\n'
|
||||
'kxZ7Fte/Vx4htM/kkfUfJCaxmxE5N4dHSKuiO9iDHsktqIA'],
|
||||
[['JAAAABdxIe2DIKUZd9jDjKikknxnDfWCHkSXYZReFenvsmoVCdIw6nMhAnZ2dnZ2dnZ2dnZ2\n'
|
||||
'dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dkYwRAIgXyobHA8sDQxmDJNLE6HIaARlzvcd79/wT068\n'
|
||||
'e113gUkCIHkI540JQT2LHwAD7/y3wFE5X3lEXMfgZRkpLZTxkpticBJAzo5VrUEr0U47sHvu\n'
|
||||
'IjbrINLCTM6pAScA899G9kpMWexbXv1ceIbTP5JH1HyQmsZsROTeHR0irojvYgx7JLaiAA=='],
|
||||
{}]])
|
||||
|
||||
def test_verify(self):
|
||||
Sign.perform_verify(self.SEQUENCE, self.VALIDATOR_KEY_HUMAN,
|
||||
'nHUUaKHpxyRP4TZZ79tTpXuTpoM8pRNs5crZpGVA5jdrjib5easY',
|
||||
self.SIGNATURE_HEX, print=self.print)
|
||||
|
||||
@@ -22,10 +22,10 @@ master key pair:
|
||||
Sample output:
|
||||
```
|
||||
[validator_keys]
|
||||
nHUSSzGw4A9zEmFtK2Q2NcWDH9xmGdXMHc1MsVej3QkLTgvDNeBr
|
||||
nHDwNP6jbJgVKj5zSEjMn8SJhTnPV54Fx5sSiNpwqLbb42nmh3Ln
|
||||
|
||||
[master_secret]
|
||||
pnxayCakmZRQE2qhEVRbFjiWCunReSbN1z64vPL36qwyLgogyYc
|
||||
paamfhAn5m1NM4UUu5mmvVaHQy8Fb65bkpbaNrvKwX3YMKdjzi2
|
||||
```
|
||||
|
||||
The first value is the master public key. Add the public key to the config
|
||||
@@ -54,10 +54,11 @@ Sample output:
|
||||
Securely connecting to 127.0.0.1:5005
|
||||
{
|
||||
"result" : {
|
||||
"status" : "success",
|
||||
"validation_key" : "TOO EDNA SHUN FEUD STAB JOAN BIAS FLEA WISE BOHR LOSS WEEK",
|
||||
"validation_public_key" : "n9JzKV3ZrcZ3DW5pwjakj4hpijJ9oMiyrPDGJc3mpsndL6Gf3zwd",
|
||||
"validation_seed" : "sahzkAajS2dyhjXg2yovjdZhXmjsx"
|
||||
"status" : "success",
|
||||
"validation_key" : "MIN HEAT NUN FAWN HIP KAHN BORG PHI BALK ANN TWIG RACY",
|
||||
"validation_private_key" : "pn6kTqE4WyeRQzZrRp5FnJ5J2vLdSCB5KD3DEyfVw6C9woDBfED",
|
||||
"validation_public_key" : "n9LtZ9haqYMbzJ92cDd3pu3Lko6uEznrXuYea3ehuhVcwDHF5coX",
|
||||
"validation_seed" : "sh8bLqqkGBknGcsgRTrFMxcciwytm"
|
||||
}
|
||||
}
|
||||
```
|
||||
@@ -68,36 +69,37 @@ number as a comment as well (sequence numbers are be explained below):
|
||||
|
||||
```
|
||||
[validation_seed]
|
||||
sahzkAajS2dyhjXg2yovjdZhXmjsx
|
||||
# validation_public_key: n9JzKV3ZrcZ3DW5pwjakj4hpijJ9oMiyrPDGJc3mpsndL6Gf3zwd
|
||||
sh8bLqqkGBknGcsgRTrFMxcciwytm
|
||||
# validation_public_key: n9LtZ9haqYMbzJ92cDd3pu3Lko6uEznrXuYea3ehuhVcwDHF5coX
|
||||
# sequence number: 1
|
||||
```
|
||||
|
||||
A manifest is a signed message used to inform other servers of this validator's
|
||||
ephemeral public key. A manifest contains a sequence number, the new ephemeral
|
||||
public key, and it is signed with the master secret key. The sequence number
|
||||
should be higher than the previous sequence number (if it is not, the manifest
|
||||
will be ignored). Usually the previous sequence number will be incremented by
|
||||
one. Use the `manifest` script to create a manifest. It has the form:
|
||||
public key, and it is signed with both the ephemeral and master secret keys.
|
||||
The sequence number should be higher than the previous sequence number (if it
|
||||
is not, the manifest will be ignored). Usually the previous sequence number
|
||||
will be incremented by one. Use the `manifest` script to create a manifest.
|
||||
It has the form:
|
||||
|
||||
```
|
||||
$ bin/manifest sign sequence_number validation_public_key master_secret
|
||||
$ bin/manifest sign sequence validation_public_key validation_private_key master_secret
|
||||
```
|
||||
|
||||
For example:
|
||||
|
||||
```
|
||||
$ bin/manifest sign 1 n9JzKV3Z...L6Gf3zwd pnxayCak...yLgogyYc
|
||||
$ bin/manifest sign 1 n9LtZ9ha...wDHF5coX pn6kTqE4...9woDBfED paamfhAn...YMKdjzi2
|
||||
```
|
||||
|
||||
Sample output:
|
||||
|
||||
```
|
||||
[validation_manifest]
|
||||
JAAAAAFxIe2PEzNhe996gykB1PJQNoDxvr/Y0XhDELw8d/i
|
||||
Fcgz3A3MhAjqhKsgZTmK/3BPEI+kzjV1p9ip7pl/AtF7CKd
|
||||
NSfAH9dkCxezV6apS4FLYzAcQilONx315HvebwAB/pLPaM4
|
||||
2sWCEppSuLNKN/JJjTABOo9tmAiNnnstF83yvecKMJzniwN
|
||||
JAAAAAFxIe3t8rIb4Ba8JHI97CbwpxmTq0LhN/7ZAbsNaSwrbHaypHMhAzTuu07YGOvVvB3+
|
||||
aS0jhP+q0TVgTjGJKhx+yTY1Da3ddkYwRAIgDkmIt3dPNsfeCH3ApMZgpwqG4JwtIlKEymqK
|
||||
S7v+VqkCIFQXg20ZMpXXT86vmLdlmPspgeUN1scWsuFoPYUUJywycBJAl93+/bZbfZ4quTeM
|
||||
5y80/OSIcVoWPcHajwrAl68eiAW4MVFeJXvShXNfnT+XsxMjDh0VpOkhvyp971i1MgjBAA==
|
||||
```
|
||||
|
||||
Copy this to the config for this validator. Don't forget to update the comment
|
||||
@@ -107,4 +109,4 @@ noting the sequence number.
|
||||
|
||||
If a master key is compromised, the key may be revoked permanently. To revoke a
|
||||
master key, sign a manifest with the highest possible sequence number:
|
||||
`4,294,967,295`
|
||||
`4294967295`
|
||||
|
||||
3
docs/.gitignore
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
html
|
||||
temp
|
||||
out.txt
|
||||
22
docs/Dockerfile
Normal file
@@ -0,0 +1,22 @@
|
||||
FROM ubuntu:16.04
|
||||
|
||||
RUN apt-get update
|
||||
RUN apt-get -y install build-essential g++ git libbz2-dev wget python-dev
|
||||
|
||||
# Install Boost
|
||||
ENV BOOST_SHA 440a59f8bc4023dbe6285c9998b0f7fa288468b889746b1ef00e8b36c559dce1
|
||||
RUN wget https://sourceforge.net/projects/boost/files/boost/1.62.0/boost_1_62_0.tar.gz
|
||||
RUN echo "$BOOST_SHA boost_1_62_0.tar.gz" | sha256sum -c
|
||||
RUN tar xzf boost_1_62_0.tar.gz
|
||||
RUN cd boost_1_62_0 && ./bootstrap.sh --prefix=/usr/local
|
||||
RUN cd boost_1_62_0 && ./b2 install
|
||||
ENV BOOST_ROOT=/boost_1_62_0
|
||||
|
||||
# Install dependencies
|
||||
RUN apt-get -y install doxygen
|
||||
RUN apt-get -y install xsltproc
|
||||
|
||||
CMD cd /opt/rippled/docs && \
|
||||
chmod +x makeqbk.sh && \
|
||||
./makeqbk.sh && \
|
||||
$BOOST_ROOT/b2
|
||||
71
docs/Jamfile.v2
Normal file
@@ -0,0 +1,71 @@
|
||||
#
|
||||
# Copyright (c) 2015-2016 Vinnie Falco (vinnie dot falco at gmail dot com)
|
||||
#
|
||||
# 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)
|
||||
#
|
||||
|
||||
import os ;
|
||||
|
||||
local broot = [ os.environ BOOST_ROOT ] ;
|
||||
|
||||
project rippled/doc ;
|
||||
|
||||
using boostbook ;
|
||||
using quickbook ;
|
||||
using doxygen ;
|
||||
|
||||
path-constant out : . ;
|
||||
|
||||
install stylesheets
|
||||
:
|
||||
$(broot)/doc/src/boostbook.css
|
||||
:
|
||||
<location>$(out)/html
|
||||
;
|
||||
|
||||
explicit stylesheets ;
|
||||
|
||||
install images
|
||||
:
|
||||
[ glob $(broot)/doc/src/images/*.png ]
|
||||
:
|
||||
<location>$(out)/html/images
|
||||
;
|
||||
|
||||
explicit images ;
|
||||
|
||||
install callouts
|
||||
:
|
||||
[ glob $(broot)/doc/src/images/callouts/*.png ]
|
||||
:
|
||||
<location>$(out)/html/images/callouts
|
||||
;
|
||||
|
||||
explicit callout ;
|
||||
|
||||
xml doc
|
||||
:
|
||||
main.qbk
|
||||
:
|
||||
<location>temp
|
||||
<include>$(broot)/tools/boostbook/dtd
|
||||
;
|
||||
|
||||
boostbook boostdoc
|
||||
:
|
||||
doc
|
||||
:
|
||||
<xsl:param>chapter.autolabel=0
|
||||
<xsl:param>boost.root=$(broot)
|
||||
<xsl:param>chunk.first.sections=1 # Chunk the first top-level section?
|
||||
<xsl:param>chunk.section.depth=8 # Depth to which sections should be chunked
|
||||
<xsl:param>generate.section.toc.level=1 # Control depth of TOC generation in sections
|
||||
<xsl:param>toc.max.depth=2 # How many levels should be created for each TOC?
|
||||
<xsl:param>toc.section.depth=2 # How deep should recursive sections appear in the TOC?
|
||||
<xsl:param>generate.toc="chapter toc section toc"
|
||||
:
|
||||
<location>temp
|
||||
<dependency>stylesheets
|
||||
<dependency>images
|
||||
;
|
||||
84
docs/README.md
Normal file
@@ -0,0 +1,84 @@
|
||||
# Building documentation
|
||||
|
||||
## Specifying Files
|
||||
|
||||
To specify the source files for which to build documentation, modify `INPUT`
|
||||
and its related fields in `docs/source.dox`. Note that the `INPUT` paths are
|
||||
relative to the `docs/` directory.
|
||||
|
||||
## Install Dependencies
|
||||
|
||||
### Windows
|
||||
|
||||
Install these dependencies:
|
||||
|
||||
1. Install [Doxygen](http://www.stack.nl/~dimitri/doxygen/download.html)
|
||||
2. Download the following zip files from [xsltproc](https://www.zlatkovic.com/pub/libxml/)
|
||||
(Alternate download: ftp://ftp.zlatkovic.com/libxml/),
|
||||
and extract the `bin\` folder contents into any folder in your path.
|
||||
* iconv
|
||||
* libxml2
|
||||
* libxslt
|
||||
* zlib
|
||||
3. Download [Boost](http://www.boost.org/users/download/)
|
||||
1. Extract the compressed file contents to your (new) `$BOOST_ROOT` location.
|
||||
2. Open a command prompt or shell in the `$BOOST_ROOT`.
|
||||
3. `./bootstrap.bat`
|
||||
4. (Optional, if you also plan to build rippled) `./bjam.exe --toolset=msvc-14.0
|
||||
--build-type=complete variant=debug,release link=static runtime-link=static
|
||||
address-model=64 stage`
|
||||
5. If it is not already there, add your `$BOOST_ROOT` to your environment `$PATH`.
|
||||
|
||||
### MacOS
|
||||
|
||||
1. Install doxygen:
|
||||
* Use homebrew to install: `brew install doxygen`. The executable will be
|
||||
installed in `/usr/local/bin` which is already in your path.
|
||||
* Alternatively, install from here: [doxygen](http://www.stack.nl/~dimitri/doxygen/download.html).
|
||||
You'll then need to make doxygen available to your command line. You can
|
||||
do this by adding a symbolic link from `/usr/local/bin` to the doxygen
|
||||
executable. For example, `$ ln -s /Applications/Doxygen.app/Contents/Resources/doxygen /usr/local/bin/doxygen`
|
||||
2. Install [Boost](http://www.boost.org/users/download/)
|
||||
1. Extract the compressed file contents to your (new) `$BOOST_ROOT` location.
|
||||
2. Open a command prompt or shell in the `$BOOST_ROOT`.
|
||||
3. `$ ./bootstrap.bat`
|
||||
4. (Optional, if you also plan to build rippled)
|
||||
`$ ./b2 toolset=clang threading=multi runtime-link=static link=static
|
||||
cxxflags="-stdlib=libc++" linkflags="-stdlib=libc++" adress-model=64`
|
||||
5. If it is not already there, add your `$BOOST_ROOT` to your environment
|
||||
`$PATH`. This makes the `b2` command available to the command line.
|
||||
3. That should be all that's required. In OS X 10.11, at least, libxml2 and
|
||||
libxslt come pre-installed.
|
||||
|
||||
### Linux
|
||||
|
||||
1. Install [Docker](https://docs.docker.com/engine/installation/)
|
||||
2. Build Docker image. From the rippled root folder:
|
||||
```
|
||||
sudo docker build -t rippled-docs docs/
|
||||
```
|
||||
|
||||
## Setup project submodules
|
||||
|
||||
1. Open a shell in your rippled root folder.
|
||||
2. `git submodule init`
|
||||
3. `git submodule update docs/docca`
|
||||
|
||||
## Do it
|
||||
|
||||
### Windows & MacOS
|
||||
|
||||
From the rippled root folder:
|
||||
```
|
||||
cd docs
|
||||
./makeqbk.sh && b2
|
||||
```
|
||||
The output will be in `docs/html`.
|
||||
|
||||
### Linux
|
||||
|
||||
From the rippled root folder:
|
||||
```
|
||||
sudo docker run -v $PWD:/opt/rippled --rm rippled-docs
|
||||
```
|
||||
The output will be in `docs/html`.
|
||||
439
docs/boostbook.dtd
Normal file
@@ -0,0 +1,439 @@
|
||||
<!--
|
||||
BoostBook DTD - development version
|
||||
|
||||
For further information, see: http://www.crystalclearsoftware.com/cgi-bin/boost_wiki/wiki.pl?Boost_Documentation_Format
|
||||
|
||||
Copyright (c) 2002 by Peter Simons <simons@cryp.to>
|
||||
Copyright (c) 2003-2004 by Douglas Gregor <doug.gregor -at- gmail.com>
|
||||
Copyright (c) 2007 by Frank Mori Hess <fmhess@users.sourceforge.net>
|
||||
|
||||
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)
|
||||
|
||||
The latest stable DTD module is identified by the PUBLIC and SYSTEM identifiers:
|
||||
|
||||
PUBLIC "-//Boost//DTD BoostBook XML V1.1//EN"
|
||||
SYSTEM "http://www.boost.org/tools/boostbook/dtd/1.1/boostbook.dtd"
|
||||
|
||||
$Revision$
|
||||
$Date$
|
||||
-->
|
||||
|
||||
<!--========== Define XInclude features. ==========-->
|
||||
<!-- This is not really integrated into the DTD yet. Needs more
|
||||
research. -->
|
||||
<!--
|
||||
<!ELEMENT xi:include (xi:fallback)?>
|
||||
<!ATTLIST xi:include
|
||||
xmlns:xi CDATA #FIXED "http://www.w3.org/2001/XInclude"
|
||||
href CDATA #REQUIRED
|
||||
parse (xml|text) "xml"
|
||||
encoding CDATA #IMPLIED>
|
||||
|
||||
<!ELEMENT xi:fallback ANY>
|
||||
<!ATTLIST xi:fallback
|
||||
xmlns:xi CDATA #FIXED "http://www.w3.org/2001/XInclude">
|
||||
-->
|
||||
|
||||
<!ENTITY % local.common.attrib "last-revision CDATA #IMPLIED">
|
||||
|
||||
<!--========== Define the BoostBook extensions ==========-->
|
||||
<!ENTITY % boost.common.attrib "%local.common.attrib;
|
||||
id CDATA #IMPLIED">
|
||||
|
||||
<!ENTITY % boost.namespace.mix
|
||||
"class|class-specialization|struct|struct-specialization|
|
||||
union|union-specialization|typedef|enum|
|
||||
free-function-group|function|overloaded-function|
|
||||
namespace">
|
||||
|
||||
<!ENTITY % boost.template.mix
|
||||
"template-type-parameter|template-nontype-parameter|template-varargs">
|
||||
|
||||
<!ENTITY % boost.class.members
|
||||
"static-constant|typedef|enum|
|
||||
copy-assignment|constructor|destructor|method-group|
|
||||
method|overloaded-method|data-member|class|class-specialization|struct|
|
||||
struct-specialization|union|union-specialization">
|
||||
|
||||
<!ENTITY % boost.class.mix
|
||||
"%boost.class.members;|free-function-group|function|overloaded-function">
|
||||
|
||||
<!ENTITY % boost.class.content
|
||||
"template?, inherit*, purpose?, description?,
|
||||
(%boost.class.mix;|access)*">
|
||||
|
||||
<!ENTITY % boost.class-specialization.content
|
||||
"template?, specialization?, inherit?, purpose?, description?,
|
||||
(%boost.class.mix;|access)*">
|
||||
|
||||
<!ENTITY % boost.function.semantics
|
||||
"purpose?, description?, requires?, effects?, postconditions?,
|
||||
returns?, throws?, complexity?, notes?, rationale?">
|
||||
|
||||
<!ENTITY % library.content
|
||||
"libraryinfo, (title, ((section|library-reference|testsuite))+)?">
|
||||
|
||||
<!ELEMENT library (%library.content;)>
|
||||
<!ATTLIST library
|
||||
name CDATA #REQUIRED
|
||||
dirname CDATA #REQUIRED
|
||||
html-only CDATA #IMPLIED
|
||||
url CDATA #IMPLIED
|
||||
%boost.common.attrib;>
|
||||
|
||||
<!ELEMENT boostbook (title, (chapter|library)*)>
|
||||
<!ATTLIST boostbook %boost.common.attrib;>
|
||||
|
||||
<!ELEMENT libraryinfo (author+, copyright*, legalnotice*, librarypurpose, librarycategory*)>
|
||||
<!ATTLIST libraryinfo %boost.common.attrib;>
|
||||
|
||||
<!ELEMENT librarypurpose (#PCDATA|code|ulink|functionname|methodname|classname|macroname|headername|enumname|globalname)*>
|
||||
<!ATTLIST librarypurpose %boost.common.attrib;>
|
||||
|
||||
<!ELEMENT librarycategory (#PCDATA)>
|
||||
<!ATTLIST librarycategory
|
||||
name CDATA #REQUIRED
|
||||
%boost.common.attrib;>
|
||||
|
||||
<!ELEMENT libraryname (#PCDATA)>
|
||||
<!ATTLIST libraryname %boost.common.attrib;>
|
||||
|
||||
<!ELEMENT library-reference ANY>
|
||||
<!ATTLIST library-reference
|
||||
%boost.common.attrib;>
|
||||
|
||||
<!ELEMENT librarylist EMPTY>
|
||||
<!ATTLIST librarylist %boost.common.attrib;>
|
||||
|
||||
<!ELEMENT librarycategorylist (librarycategorydef)*>
|
||||
<!ATTLIST librarycategorylist %boost.common.attrib;>
|
||||
|
||||
<!ELEMENT librarycategorydef (#PCDATA)>
|
||||
<!ATTLIST librarycategorydef
|
||||
name CDATA #REQUIRED
|
||||
%boost.common.attrib;>
|
||||
|
||||
<!ELEMENT header ANY>
|
||||
<!ATTLIST header
|
||||
name CDATA #REQUIRED
|
||||
%boost.common.attrib;>
|
||||
|
||||
<!ELEMENT namespace (%boost.namespace.mix;)*>
|
||||
<!ATTLIST namespace
|
||||
name CDATA #REQUIRED
|
||||
%boost.common.attrib;>
|
||||
|
||||
<!ELEMENT class (%boost.class.content;)>
|
||||
<!ATTLIST class
|
||||
name CDATA #REQUIRED
|
||||
%boost.common.attrib;>
|
||||
|
||||
<!ELEMENT struct (%boost.class.content;)>
|
||||
<!ATTLIST struct
|
||||
name CDATA #REQUIRED
|
||||
%boost.common.attrib;>
|
||||
|
||||
<!ELEMENT union (%boost.class.content;)>
|
||||
<!ATTLIST union
|
||||
name CDATA #REQUIRED
|
||||
%boost.common.attrib;>
|
||||
|
||||
<!ELEMENT class-specialization (%boost.class-specialization.content;)>
|
||||
<!ATTLIST class-specialization
|
||||
name CDATA #REQUIRED
|
||||
%boost.common.attrib;>
|
||||
|
||||
<!ELEMENT struct-specialization (%boost.class-specialization.content;)>
|
||||
<!ATTLIST struct-specialization
|
||||
name CDATA #REQUIRED
|
||||
%boost.common.attrib;>
|
||||
|
||||
<!ELEMENT union-specialization (%boost.class-specialization.content;)>
|
||||
<!ATTLIST union-specialization
|
||||
name CDATA #REQUIRED
|
||||
%boost.common.attrib;>
|
||||
|
||||
<!ELEMENT access (%boost.class.members;)+>
|
||||
<!ATTLIST access
|
||||
name CDATA #REQUIRED
|
||||
%boost.common.attrib;>
|
||||
|
||||
<!--========= C++ Templates =========-->
|
||||
<!ELEMENT template (%boost.template.mix;)*>
|
||||
<!ATTLIST template %boost.common.attrib;>
|
||||
|
||||
<!ELEMENT template-type-parameter (default?, purpose?)>
|
||||
<!ATTLIST template-type-parameter
|
||||
name CDATA #REQUIRED
|
||||
pack CDATA #IMPLIED
|
||||
%boost.common.attrib;>
|
||||
|
||||
<!ELEMENT template-nontype-parameter (type, default?, purpose?)>
|
||||
<!ATTLIST template-nontype-parameter
|
||||
name CDATA #REQUIRED
|
||||
pack CDATA #IMPLIED
|
||||
%boost.common.attrib;>
|
||||
|
||||
<!ELEMENT template-varargs EMPTY>
|
||||
<!ATTLIST template-varargs %boost.common.attrib;>
|
||||
|
||||
<!ELEMENT specialization (template-arg)*>
|
||||
<!ATTLIST specialization %boost.common.attrib;>
|
||||
|
||||
<!ELEMENT template-arg ANY>
|
||||
<!ATTLIST template-arg
|
||||
pack CDATA #IMPLIED
|
||||
%boost.common.attrib;>
|
||||
|
||||
<!ELEMENT default ANY>
|
||||
<!ATTLIST default %boost.common.attrib;>
|
||||
|
||||
<!ELEMENT inherit (type, purpose?)>
|
||||
<!ATTLIST inherit
|
||||
access CDATA #IMPLIED
|
||||
pack CDATA #IMPLIED
|
||||
%boost.common.attrib;>
|
||||
|
||||
<!ELEMENT purpose ANY>
|
||||
<!ATTLIST purpose %boost.common.attrib;>
|
||||
|
||||
<!ELEMENT description ANY>
|
||||
<!ATTLIST description %boost.common.attrib;>
|
||||
|
||||
<!ELEMENT type ANY>
|
||||
<!ATTLIST type %boost.common.attrib;>
|
||||
|
||||
<!ELEMENT typedef (type, purpose?, description?)>
|
||||
<!ATTLIST typedef
|
||||
name CDATA #REQUIRED
|
||||
%boost.common.attrib;>
|
||||
|
||||
<!ELEMENT enum (enumvalue*, purpose?, description?)>
|
||||
<!ATTLIST enum
|
||||
name CDATA #REQUIRED
|
||||
%boost.common.attrib;>
|
||||
|
||||
<!ELEMENT enumvalue (default?, purpose?, description?)>
|
||||
<!ATTLIST enumvalue
|
||||
name CDATA #REQUIRED
|
||||
%boost.common.attrib;>
|
||||
|
||||
<!ELEMENT static-constant (type, default, purpose?, description?)>
|
||||
<!ATTLIST static-constant
|
||||
name CDATA #REQUIRED
|
||||
%boost.common.attrib;>
|
||||
|
||||
<!ELEMENT data-member (type, purpose?, description?)>
|
||||
<!ATTLIST data-member
|
||||
name CDATA #REQUIRED
|
||||
specifiers CDATA #IMPLIED
|
||||
%boost.common.attrib;>
|
||||
|
||||
<!ELEMENT paramtype ANY>
|
||||
<!ATTLIST paramtype %boost.common.attrib;>
|
||||
|
||||
<!ELEMENT effects ANY>
|
||||
<!ATTLIST effects %boost.common.attrib;>
|
||||
|
||||
<!ELEMENT postconditions ANY>
|
||||
<!ATTLIST postconditions %boost.common.attrib;>
|
||||
|
||||
<!ELEMENT method-group (method|overloaded-method)*>
|
||||
<!ATTLIST method-group
|
||||
name CDATA #REQUIRED
|
||||
%boost.common.attrib;>
|
||||
|
||||
<!ELEMENT constructor (template?, parameter*, %boost.function.semantics;)>
|
||||
<!ATTLIST constructor
|
||||
specifiers CDATA #IMPLIED
|
||||
%boost.common.attrib;>
|
||||
|
||||
<!ELEMENT destructor (%boost.function.semantics;)>
|
||||
<!ATTLIST destructor
|
||||
specifiers CDATA #IMPLIED
|
||||
%boost.common.attrib;>
|
||||
|
||||
<!ELEMENT method (template?, type, parameter*, %boost.function.semantics;)>
|
||||
<!ATTLIST method
|
||||
name CDATA #REQUIRED
|
||||
cv CDATA #IMPLIED
|
||||
specifiers CDATA #IMPLIED
|
||||
%boost.common.attrib;>
|
||||
|
||||
<!ELEMENT function (template?, type, parameter*, %boost.function.semantics;)>
|
||||
<!ATTLIST function
|
||||
name CDATA #REQUIRED
|
||||
specifiers CDATA #IMPLIED
|
||||
%boost.common.attrib;>
|
||||
|
||||
<!ELEMENT overloaded-method (signature*, %boost.function.semantics;)>
|
||||
<!ATTLIST overloaded-method
|
||||
name CDATA #REQUIRED
|
||||
%boost.common.attrib;>
|
||||
|
||||
<!ELEMENT overloaded-function (signature*, %boost.function.semantics;)>
|
||||
<!ATTLIST overloaded-function
|
||||
name CDATA #REQUIRED
|
||||
%boost.common.attrib;>
|
||||
|
||||
<!ELEMENT signature (template?, type, parameter*)>
|
||||
<!ATTLIST signature
|
||||
cv CDATA #IMPLIED
|
||||
specifiers CDATA #IMPLIED
|
||||
%boost.common.attrib;>
|
||||
|
||||
<!ELEMENT requires ANY>
|
||||
<!ATTLIST requires %boost.common.attrib;>
|
||||
|
||||
<!ELEMENT returns ANY>
|
||||
<!ATTLIST returns %boost.common.attrib;>
|
||||
|
||||
<!ELEMENT throws ANY>
|
||||
<!ATTLIST throws %boost.common.attrib;>
|
||||
|
||||
<!ELEMENT complexity ANY>
|
||||
<!ATTLIST complexity %boost.common.attrib;>
|
||||
|
||||
<!ELEMENT notes ANY>
|
||||
<!ATTLIST notes %boost.common.attrib;>
|
||||
|
||||
<!ELEMENT rationale ANY>
|
||||
<!ATTLIST rationale %boost.common.attrib;>
|
||||
|
||||
<!ELEMENT functionname (#PCDATA)>
|
||||
<!ATTLIST functionname
|
||||
alt CDATA #IMPLIED
|
||||
%boost.common.attrib;>
|
||||
|
||||
<!ELEMENT enumname (#PCDATA)>
|
||||
<!ATTLIST enumname
|
||||
alt CDATA #IMPLIED
|
||||
%boost.common.attrib;>
|
||||
|
||||
<!ELEMENT macroname (#PCDATA)>
|
||||
<!ATTLIST macroname
|
||||
alt CDATA #IMPLIED
|
||||
%boost.common.attrib;>
|
||||
|
||||
<!ELEMENT headername (#PCDATA)>
|
||||
<!ATTLIST headername
|
||||
alt CDATA #IMPLIED
|
||||
%boost.common.attrib;>
|
||||
|
||||
<!ELEMENT globalname (#PCDATA)>
|
||||
<!ATTLIST globalname
|
||||
alt CDATA #IMPLIED
|
||||
%boost.common.attrib;>
|
||||
|
||||
<!ELEMENT copy-assignment
|
||||
(template?, type?, parameter*, %boost.function.semantics;)>
|
||||
<!ATTLIST copy-assignment
|
||||
cv CDATA #IMPLIED
|
||||
specifiers CDATA #IMPLIED
|
||||
%boost.common.attrib;>
|
||||
|
||||
<!ELEMENT free-function-group (function|overloaded-function)*>
|
||||
<!ATTLIST free-function-group
|
||||
name CDATA #REQUIRED
|
||||
%boost.common.attrib;>
|
||||
|
||||
<!ELEMENT precondition ANY>
|
||||
<!ATTLIST precondition %boost.common.attrib;>
|
||||
|
||||
<!ELEMENT code ANY>
|
||||
<!ATTLIST code %boost.common.attrib;>
|
||||
|
||||
<!ELEMENT using-namespace EMPTY>
|
||||
<!ATTLIST using-namespace
|
||||
name CDATA #REQUIRED
|
||||
%boost.common.attrib;>
|
||||
|
||||
<!ELEMENT using-class EMPTY>
|
||||
<!ATTLIST using-class
|
||||
name CDATA #REQUIRED
|
||||
%boost.common.attrib;>
|
||||
|
||||
<!--========== Boost Testsuite Extensions ==========-->
|
||||
<!ENTITY % boost.testsuite.tests
|
||||
"compile-test|link-test|run-test|
|
||||
compile-fail-test|link-fail-test|run-fail-test">
|
||||
<!ENTITY % boost.testsuite.test.content
|
||||
"source*, lib*, requirement*, purpose, if-fails?">
|
||||
|
||||
<!ELEMENT testsuite ((%boost.testsuite.tests;)+)>
|
||||
<!ATTLIST testsuite %boost.common.attrib;>
|
||||
|
||||
<!ELEMENT compile-test (%boost.testsuite.test.content;)>
|
||||
<!ATTLIST compile-test
|
||||
filename CDATA #REQUIRED
|
||||
name CDATA #IMPLIED>
|
||||
|
||||
<!ELEMENT link-test (%boost.testsuite.test.content;)>
|
||||
<!ATTLIST link-test
|
||||
filename CDATA #REQUIRED
|
||||
name CDATA #IMPLIED>
|
||||
|
||||
<!ELEMENT run-test (%boost.testsuite.test.content;)>
|
||||
<!ATTLIST run-test
|
||||
filename CDATA #REQUIRED
|
||||
name CDATA #IMPLIED>
|
||||
|
||||
<!ELEMENT compile-fail-test (%boost.testsuite.test.content;)>
|
||||
<!ATTLIST compile-fail-test
|
||||
filename CDATA #REQUIRED
|
||||
name CDATA #IMPLIED>
|
||||
|
||||
<!ELEMENT link-fail-test (%boost.testsuite.test.content;)>
|
||||
<!ATTLIST link-fail-test
|
||||
filename CDATA #REQUIRED
|
||||
name CDATA #IMPLIED>
|
||||
|
||||
<!ELEMENT run-fail-test (%boost.testsuite.test.content;)>
|
||||
<!ATTLIST run-fail-test
|
||||
filename CDATA #REQUIRED
|
||||
name CDATA #IMPLIED>
|
||||
|
||||
<!ELEMENT source (#PCDATA|snippet)*>
|
||||
|
||||
<!ELEMENT snippet EMPTY>
|
||||
<!ATTLIST snippet
|
||||
name CDATA #REQUIRED>
|
||||
|
||||
<!ELEMENT lib (#PCDATA)>
|
||||
|
||||
<!ELEMENT requirement (#PCDATA)>
|
||||
<!ATTLIST requirement
|
||||
name CDATA #REQUIRED>
|
||||
|
||||
<!ELEMENT if-fails ANY>
|
||||
|
||||
<!ELEMENT parameter (paramtype, default?, description?)>
|
||||
<!ATTLIST parameter
|
||||
name CDATA #IMPLIED
|
||||
pack CDATA #IMPLIED>
|
||||
|
||||
<!ELEMENT programlisting ANY>
|
||||
<!ATTLIST programlisting
|
||||
name CDATA #IMPLIED>
|
||||
|
||||
<!--========== Customize the DocBook DTD ==========-->
|
||||
<!ENTITY % local.tech.char.class "|functionname|libraryname|enumname|headername|macroname|code">
|
||||
<!ENTITY % local.para.class
|
||||
"|using-namespace|using-class|librarylist|librarycategorylist">
|
||||
<!ENTITY % local.descobj.class "|libraryinfo">
|
||||
<!ENTITY % local.classname.attrib "alt CDATA #IMPLIED">
|
||||
<!ENTITY % local.methodname.attrib "alt CDATA #IMPLIED">
|
||||
<!ENTITY % local.refentry.class "|library-reference|testsuite">
|
||||
<!ENTITY % local.title.char.mix "">
|
||||
<!ENTITY % programlisting.module "IGNORE">
|
||||
<!ENTITY % parameter.module "IGNORE">
|
||||
<!ENTITY % function.module "IGNORE">
|
||||
<!ENTITY % type.module "IGNORE">
|
||||
|
||||
<!--========== Import DocBook DTD ==========-->
|
||||
<!ENTITY % DocBook PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
|
||||
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
|
||||
|
||||
%DocBook;
|
||||
1
docs/docca
Submodule
14
docs/index.xml
Normal file
@@ -0,0 +1,14 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!DOCTYPE library PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN" "boostbook.dtd">
|
||||
|
||||
<!--
|
||||
Copyright (c) 2013-2016 Vinnie Falco (vinnie dot falco at gmail dot com)
|
||||
|
||||
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)
|
||||
-->
|
||||
|
||||
<section id="rippled.index">
|
||||
<title>Index</title>
|
||||
<index/>
|
||||
</section>
|
||||
37
docs/main.qbk
Normal file
@@ -0,0 +1,37 @@
|
||||
[/
|
||||
Copyright (c) Copyright (c) 2012, 2013 Ripple Labs Inc.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
]
|
||||
|
||||
[library rippled
|
||||
[quickbook 1.6]
|
||||
[copyright 2012 - 2016 Ripple Labs Inc.]
|
||||
[purpose C++ Library]
|
||||
[license
|
||||
Distributed under the ISC License
|
||||
]
|
||||
[authors [Labs, Ripple]]
|
||||
[category template]
|
||||
[category generic]
|
||||
]
|
||||
|
||||
[template mdash[] '''— ''']
|
||||
[template indexterm1[term1] '''<indexterm><primary>'''[term1]'''</primary></indexterm>''']
|
||||
[template indexterm2[term1 term2] '''<indexterm><primary>'''[term1]'''</primary><secondary>'''[term2]'''</secondary></indexterm>''']
|
||||
|
||||
[section:ref Reference]
|
||||
[include temp/reference.qbk]
|
||||
[endsect]
|
||||
|
||||
[xinclude index.xml]
|
||||
11
docs/makeqbk.sh
Executable file
@@ -0,0 +1,11 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Copyright (c) 2013-2016 Vinnie Falco (vinnie dot falco at gmail dot com)
|
||||
#
|
||||
# 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)
|
||||
|
||||
mkdir -p temp
|
||||
doxygen source.dox
|
||||
xsltproc temp/combine.xslt temp/index.xml > temp/all.xml
|
||||
xsltproc reference.xsl temp/all.xml > temp/reference.qbk
|
||||
61
docs/quickref.xml
Normal file
@@ -0,0 +1,61 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!DOCTYPE library PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN" "boostbook.dtd">
|
||||
|
||||
<!--
|
||||
Copyright (c) Copyright (c) 2012, 2013 Ripple Labs Inc.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
-->
|
||||
|
||||
<informaltable frame="all">
|
||||
<tgroup cols="3">
|
||||
<colspec colname="a"/>
|
||||
<colspec colname="b"/>
|
||||
<colspec colname="c"/>
|
||||
<thead>
|
||||
<row>
|
||||
<entry valign="center" namest="a" nameend="c">
|
||||
<bridgehead renderas="sect2">Core</bridgehead>
|
||||
</entry>
|
||||
</row>
|
||||
</thead>
|
||||
<tbody>
|
||||
<row>
|
||||
<entry valign="top">
|
||||
<bridgehead renderas="sect3">Classes</bridgehead>
|
||||
<simplelist type="vert" columns="1">
|
||||
</simplelist>
|
||||
<bridgehead renderas="sect3">Constants</bridgehead>
|
||||
<simplelist type="vert" columns="1">
|
||||
</simplelist>
|
||||
</entry>
|
||||
<entry valign="top">
|
||||
<bridgehead renderas="sect3">Functions</bridgehead>
|
||||
<simplelist type="vert" columns="1">
|
||||
</simplelist>
|
||||
<bridgehead renderas="sect3">Type Traits</bridgehead>
|
||||
<simplelist type="vert" columns="1">
|
||||
</simplelist>
|
||||
</entry>
|
||||
<entry valign="top">
|
||||
<bridgehead renderas="sect3">Types</bridgehead>
|
||||
<simplelist type="vert" columns="1">
|
||||
</simplelist>
|
||||
<bridgehead renderas="sect3">Concepts</bridgehead>
|
||||
<simplelist type="vert" columns="1">
|
||||
</simplelist>
|
||||
</entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
</informaltable>
|
||||
14
docs/reference.xsl
Normal file
@@ -0,0 +1,14 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
|
||||
|
||||
<!-- Variables (Edit for your project) -->
|
||||
<xsl:variable name="doc-ref" select="'rippled.ref.'"/>
|
||||
<xsl:variable name="doc-ns" select="'ripple'"/>
|
||||
<xsl:variable name="debug" select="0"/>
|
||||
<xsl:variable name="private" select="0"/>
|
||||
<!-- End Variables -->
|
||||
|
||||
<xsl:include href="docca/include/docca/doxygen.xsl"/>
|
||||
|
||||
</xsl:stylesheet>
|
||||
|
||||
337
docs/source.dox
Normal file
@@ -0,0 +1,337 @@
|
||||
#---------------------------------------------------------------------------
|
||||
# Project related configuration options
|
||||
#---------------------------------------------------------------------------
|
||||
DOXYFILE_ENCODING = UTF-8
|
||||
PROJECT_NAME = "rippled"
|
||||
PROJECT_NUMBER =
|
||||
PROJECT_BRIEF = C++ Library
|
||||
PROJECT_LOGO =
|
||||
OUTPUT_DIRECTORY =
|
||||
CREATE_SUBDIRS = NO
|
||||
ALLOW_UNICODE_NAMES = NO
|
||||
OUTPUT_LANGUAGE = English
|
||||
BRIEF_MEMBER_DESC = YES
|
||||
REPEAT_BRIEF = YES
|
||||
ABBREVIATE_BRIEF =
|
||||
ALWAYS_DETAILED_SEC = NO
|
||||
INLINE_INHERITED_MEMB = YES
|
||||
FULL_PATH_NAMES = NO
|
||||
STRIP_FROM_PATH = ../src/
|
||||
STRIP_FROM_INC_PATH =
|
||||
SHORT_NAMES = NO
|
||||
JAVADOC_AUTOBRIEF = YES
|
||||
QT_AUTOBRIEF = NO
|
||||
MULTILINE_CPP_IS_BRIEF = NO
|
||||
INHERIT_DOCS = YES
|
||||
SEPARATE_MEMBER_PAGES = NO
|
||||
TAB_SIZE = 4
|
||||
ALIASES =
|
||||
TCL_SUBST =
|
||||
OPTIMIZE_OUTPUT_FOR_C = NO
|
||||
OPTIMIZE_OUTPUT_JAVA = NO
|
||||
OPTIMIZE_FOR_FORTRAN = NO
|
||||
OPTIMIZE_OUTPUT_VHDL = NO
|
||||
EXTENSION_MAPPING =
|
||||
MARKDOWN_SUPPORT = YES
|
||||
AUTOLINK_SUPPORT = YES
|
||||
BUILTIN_STL_SUPPORT = NO
|
||||
CPP_CLI_SUPPORT = NO
|
||||
SIP_SUPPORT = NO
|
||||
IDL_PROPERTY_SUPPORT = YES
|
||||
DISTRIBUTE_GROUP_DOC = NO
|
||||
GROUP_NESTED_COMPOUNDS = NO
|
||||
SUBGROUPING = YES
|
||||
INLINE_GROUPED_CLASSES = NO
|
||||
INLINE_SIMPLE_STRUCTS = NO
|
||||
TYPEDEF_HIDES_STRUCT = NO
|
||||
LOOKUP_CACHE_SIZE = 0
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Build related configuration options
|
||||
#---------------------------------------------------------------------------
|
||||
EXTRACT_ALL = YES
|
||||
EXTRACT_PRIVATE = YES
|
||||
EXTRACT_PACKAGE = NO
|
||||
EXTRACT_STATIC = YES
|
||||
EXTRACT_LOCAL_CLASSES = YES
|
||||
EXTRACT_LOCAL_METHODS = YES
|
||||
EXTRACT_ANON_NSPACES = NO
|
||||
HIDE_UNDOC_MEMBERS = NO
|
||||
HIDE_UNDOC_CLASSES = NO
|
||||
HIDE_FRIEND_COMPOUNDS = NO
|
||||
HIDE_IN_BODY_DOCS = NO
|
||||
INTERNAL_DOCS = NO
|
||||
CASE_SENSE_NAMES = YES
|
||||
HIDE_SCOPE_NAMES = NO
|
||||
HIDE_COMPOUND_REFERENCE= NO
|
||||
SHOW_INCLUDE_FILES = NO
|
||||
SHOW_GROUPED_MEMB_INC = NO
|
||||
FORCE_LOCAL_INCLUDES = NO
|
||||
INLINE_INFO = NO
|
||||
SORT_MEMBER_DOCS = NO
|
||||
SORT_BRIEF_DOCS = NO
|
||||
SORT_MEMBERS_CTORS_1ST = YES
|
||||
SORT_GROUP_NAMES = NO
|
||||
SORT_BY_SCOPE_NAME = NO
|
||||
STRICT_PROTO_MATCHING = NO
|
||||
GENERATE_TODOLIST = NO
|
||||
GENERATE_TESTLIST = NO
|
||||
GENERATE_BUGLIST = NO
|
||||
GENERATE_DEPRECATEDLIST= NO
|
||||
ENABLED_SECTIONS =
|
||||
MAX_INITIALIZER_LINES = 30
|
||||
SHOW_USED_FILES = NO
|
||||
SHOW_FILES = NO
|
||||
SHOW_NAMESPACES = NO
|
||||
FILE_VERSION_FILTER =
|
||||
LAYOUT_FILE =
|
||||
CITE_BIB_FILES =
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to warning and progress messages
|
||||
#---------------------------------------------------------------------------
|
||||
QUIET = NO
|
||||
WARNINGS = YES
|
||||
WARN_IF_UNDOCUMENTED = YES
|
||||
WARN_IF_DOC_ERROR = YES
|
||||
WARN_NO_PARAMDOC = NO
|
||||
WARN_AS_ERROR = NO
|
||||
WARN_FORMAT = "$file:$line: $text"
|
||||
WARN_LOGFILE =
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the input files
|
||||
#---------------------------------------------------------------------------
|
||||
INPUT = \
|
||||
\
|
||||
../src/ripple/protocol/STObject.h \
|
||||
|
||||
|
||||
INPUT_ENCODING = UTF-8
|
||||
FILE_PATTERNS =
|
||||
RECURSIVE = NO
|
||||
EXCLUDE =
|
||||
EXCLUDE_SYMLINKS = NO
|
||||
EXCLUDE_PATTERNS =
|
||||
EXCLUDE_SYMBOLS =
|
||||
EXAMPLE_PATH =
|
||||
EXAMPLE_PATTERNS =
|
||||
EXAMPLE_RECURSIVE = NO
|
||||
IMAGE_PATH =
|
||||
INPUT_FILTER =
|
||||
FILTER_PATTERNS =
|
||||
FILTER_SOURCE_FILES = NO
|
||||
FILTER_SOURCE_PATTERNS =
|
||||
USE_MDFILE_AS_MAINPAGE =
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to source browsing
|
||||
#---------------------------------------------------------------------------
|
||||
SOURCE_BROWSER = NO
|
||||
INLINE_SOURCES = NO
|
||||
STRIP_CODE_COMMENTS = YES
|
||||
REFERENCED_BY_RELATION = NO
|
||||
REFERENCES_RELATION = NO
|
||||
REFERENCES_LINK_SOURCE = YES
|
||||
SOURCE_TOOLTIPS = YES
|
||||
USE_HTAGS = NO
|
||||
VERBATIM_HEADERS = YES
|
||||
CLANG_ASSISTED_PARSING = NO
|
||||
CLANG_OPTIONS =
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the alphabetical class index
|
||||
#---------------------------------------------------------------------------
|
||||
ALPHABETICAL_INDEX = YES
|
||||
COLS_IN_ALPHA_INDEX = 5
|
||||
IGNORE_PREFIX =
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the HTML output
|
||||
#---------------------------------------------------------------------------
|
||||
GENERATE_HTML = NO
|
||||
HTML_OUTPUT = dhtm
|
||||
HTML_FILE_EXTENSION = .html
|
||||
HTML_HEADER =
|
||||
HTML_FOOTER =
|
||||
HTML_STYLESHEET =
|
||||
HTML_EXTRA_STYLESHEET =
|
||||
HTML_EXTRA_FILES =
|
||||
HTML_COLORSTYLE_HUE = 220
|
||||
HTML_COLORSTYLE_SAT = 100
|
||||
HTML_COLORSTYLE_GAMMA = 80
|
||||
HTML_TIMESTAMP = NO
|
||||
HTML_DYNAMIC_SECTIONS = NO
|
||||
HTML_INDEX_NUM_ENTRIES = 100
|
||||
GENERATE_DOCSET = NO
|
||||
DOCSET_FEEDNAME = "Doxygen generated docs"
|
||||
DOCSET_BUNDLE_ID = org.doxygen.Project
|
||||
DOCSET_PUBLISHER_ID = org.doxygen.Publisher
|
||||
DOCSET_PUBLISHER_NAME = Publisher
|
||||
GENERATE_HTMLHELP = NO
|
||||
CHM_FILE =
|
||||
HHC_LOCATION =
|
||||
GENERATE_CHI = NO
|
||||
CHM_INDEX_ENCODING =
|
||||
BINARY_TOC = NO
|
||||
TOC_EXPAND = NO
|
||||
GENERATE_QHP = NO
|
||||
QCH_FILE =
|
||||
QHP_NAMESPACE = org.doxygen.Project
|
||||
QHP_VIRTUAL_FOLDER = doc
|
||||
QHP_CUST_FILTER_NAME =
|
||||
QHP_CUST_FILTER_ATTRS =
|
||||
QHP_SECT_FILTER_ATTRS =
|
||||
QHG_LOCATION =
|
||||
GENERATE_ECLIPSEHELP = NO
|
||||
ECLIPSE_DOC_ID = org.doxygen.Project
|
||||
DISABLE_INDEX = NO
|
||||
GENERATE_TREEVIEW = NO
|
||||
ENUM_VALUES_PER_LINE = 4
|
||||
TREEVIEW_WIDTH = 250
|
||||
EXT_LINKS_IN_WINDOW = NO
|
||||
FORMULA_FONTSIZE = 10
|
||||
FORMULA_TRANSPARENT = YES
|
||||
USE_MATHJAX = NO
|
||||
MATHJAX_FORMAT = HTML-CSS
|
||||
MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest
|
||||
MATHJAX_EXTENSIONS =
|
||||
MATHJAX_CODEFILE =
|
||||
SEARCHENGINE = YES
|
||||
SERVER_BASED_SEARCH = NO
|
||||
EXTERNAL_SEARCH = NO
|
||||
SEARCHENGINE_URL =
|
||||
SEARCHDATA_FILE = searchdata.xml
|
||||
EXTERNAL_SEARCH_ID =
|
||||
EXTRA_SEARCH_MAPPINGS =
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the LaTeX output
|
||||
#---------------------------------------------------------------------------
|
||||
GENERATE_LATEX = NO
|
||||
LATEX_OUTPUT = latex
|
||||
LATEX_CMD_NAME = latex
|
||||
MAKEINDEX_CMD_NAME = makeindex
|
||||
COMPACT_LATEX = NO
|
||||
PAPER_TYPE = a4
|
||||
EXTRA_PACKAGES =
|
||||
LATEX_HEADER =
|
||||
LATEX_FOOTER =
|
||||
LATEX_EXTRA_STYLESHEET =
|
||||
LATEX_EXTRA_FILES =
|
||||
PDF_HYPERLINKS = YES
|
||||
USE_PDFLATEX = YES
|
||||
LATEX_BATCHMODE = NO
|
||||
LATEX_HIDE_INDICES = NO
|
||||
LATEX_SOURCE_CODE = NO
|
||||
LATEX_BIB_STYLE = plain
|
||||
LATEX_TIMESTAMP = NO
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the RTF output
|
||||
#---------------------------------------------------------------------------
|
||||
GENERATE_RTF = NO
|
||||
RTF_OUTPUT = rtf
|
||||
COMPACT_RTF = NO
|
||||
RTF_HYPERLINKS = NO
|
||||
RTF_STYLESHEET_FILE =
|
||||
RTF_EXTENSIONS_FILE =
|
||||
RTF_SOURCE_CODE = NO
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the man page output
|
||||
#---------------------------------------------------------------------------
|
||||
GENERATE_MAN = NO
|
||||
MAN_OUTPUT = man
|
||||
MAN_EXTENSION = .3
|
||||
MAN_SUBDIR =
|
||||
MAN_LINKS = NO
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the XML output
|
||||
#---------------------------------------------------------------------------
|
||||
GENERATE_XML = YES
|
||||
XML_OUTPUT = temp/
|
||||
XML_PROGRAMLISTING = YES
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the DOCBOOK output
|
||||
#---------------------------------------------------------------------------
|
||||
GENERATE_DOCBOOK = NO
|
||||
DOCBOOK_OUTPUT = docbook
|
||||
DOCBOOK_PROGRAMLISTING = NO
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options for the AutoGen Definitions output
|
||||
#---------------------------------------------------------------------------
|
||||
GENERATE_AUTOGEN_DEF = NO
|
||||
GENERATE_PERLMOD = NO
|
||||
PERLMOD_LATEX = NO
|
||||
PERLMOD_PRETTY = YES
|
||||
PERLMOD_MAKEVAR_PREFIX =
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the preprocessor
|
||||
#---------------------------------------------------------------------------
|
||||
ENABLE_PREPROCESSING = YES
|
||||
MACRO_EXPANSION = YES
|
||||
EXPAND_ONLY_PREDEF = YES
|
||||
SEARCH_INCLUDES = YES
|
||||
INCLUDE_PATH = ../
|
||||
INCLUDE_FILE_PATTERNS =
|
||||
PREDEFINED = DOXYGEN \
|
||||
GENERATING_DOCS \
|
||||
_MSC_VER \
|
||||
NUDB_POSIX_FILE=1
|
||||
|
||||
EXPAND_AS_DEFINED =
|
||||
SKIP_FUNCTION_MACROS = YES
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to external references
|
||||
#---------------------------------------------------------------------------
|
||||
TAGFILES =
|
||||
GENERATE_TAGFILE =
|
||||
ALLEXTERNALS = NO
|
||||
EXTERNAL_GROUPS = YES
|
||||
EXTERNAL_PAGES = YES
|
||||
PERL_PATH = /usr/bin/perl
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the dot tool
|
||||
#---------------------------------------------------------------------------
|
||||
CLASS_DIAGRAMS = NO
|
||||
MSCGEN_PATH =
|
||||
DIA_PATH =
|
||||
HIDE_UNDOC_RELATIONS = YES
|
||||
HAVE_DOT = NO
|
||||
DOT_NUM_THREADS = 0
|
||||
DOT_FONTNAME = Helvetica
|
||||
DOT_FONTSIZE = 10
|
||||
DOT_FONTPATH =
|
||||
CLASS_GRAPH = YES
|
||||
COLLABORATION_GRAPH = YES
|
||||
GROUP_GRAPHS = YES
|
||||
UML_LOOK = NO
|
||||
UML_LIMIT_NUM_FIELDS = 10
|
||||
TEMPLATE_RELATIONS = NO
|
||||
INCLUDE_GRAPH = YES
|
||||
INCLUDED_BY_GRAPH = YES
|
||||
CALL_GRAPH = NO
|
||||
CALLER_GRAPH = NO
|
||||
GRAPHICAL_HIERARCHY = YES
|
||||
DIRECTORY_GRAPH = YES
|
||||
DOT_IMAGE_FORMAT = png
|
||||
INTERACTIVE_SVG = NO
|
||||
DOT_PATH =
|
||||
DOTFILE_DIRS =
|
||||
MSCFILE_DIRS =
|
||||
DIAFILE_DIRS =
|
||||
PLANTUML_JAR_PATH =
|
||||
PLANTUML_INCLUDE_PATH =
|
||||
DOT_GRAPH_MAX_NODES = 50
|
||||
MAX_DOT_GRAPH_DEPTH = 0
|
||||
DOT_TRANSPARENT = NO
|
||||
DOT_MULTI_TARGETS = NO
|
||||
GENERATE_LEGEND = YES
|
||||
DOT_CLEANUP = YES
|
||||
30
src/beast/.gitignore
vendored
@@ -1,30 +1,2 @@
|
||||
docs/
|
||||
._*
|
||||
*.mode1v3
|
||||
*.pbxuser
|
||||
*.perspectivev3
|
||||
*.user
|
||||
*.ncb
|
||||
*.suo
|
||||
*.obj
|
||||
*.ilk
|
||||
*.pch
|
||||
*.pdb
|
||||
*.dep
|
||||
*.idb
|
||||
*.manifest
|
||||
*.manifest.res
|
||||
*.o
|
||||
*.opensdf
|
||||
*.d
|
||||
*.sdf
|
||||
xcuserdata
|
||||
contents.xcworkspacedata
|
||||
.DS_Store
|
||||
.svn
|
||||
profile
|
||||
bin/
|
||||
node_modules/
|
||||
cov-int/
|
||||
nohup.out
|
||||
venv/
|
||||
bin64/
|
||||
|
||||
@@ -2,6 +2,7 @@ language: cpp
|
||||
|
||||
env:
|
||||
global:
|
||||
- LLVM_VERSION=3.8.0
|
||||
# Maintenance note: to move to a new version
|
||||
# of boost, update both BOOST_ROOT and BOOST_URL.
|
||||
# Note that for simplicity, BOOST_ROOT's final
|
||||
@@ -27,57 +28,50 @@ packages: &gcc5_pkgs
|
||||
- autotools-dev
|
||||
- libc6-dbg
|
||||
|
||||
packages: &clang38_pkgs
|
||||
- clang-3.8
|
||||
- g++-5
|
||||
- python-software-properties
|
||||
- libssl-dev
|
||||
- libffi-dev
|
||||
- libstdc++6
|
||||
- binutils-gold
|
||||
# Provides a backtrace if the unittests crash
|
||||
- gdb
|
||||
# Needed for installing valgrind
|
||||
- subversion
|
||||
- automake
|
||||
- autotools-dev
|
||||
- libc6-dbg
|
||||
|
||||
matrix:
|
||||
include:
|
||||
# GCC/Coverage
|
||||
# GCC/Coverage/Autobahn
|
||||
- compiler: gcc
|
||||
env: GCC_VER=5 VARIANT=coverage ADDRESS_MODEL=64
|
||||
env:
|
||||
- GCC_VER=5
|
||||
- VARIANT=coverage
|
||||
- ADDRESS_MODEL=64
|
||||
- BUILD_SYSTEM=cmake
|
||||
- PATH=$PWD/cmake/bin:$PATH
|
||||
addons: &ao_gcc5
|
||||
apt:
|
||||
sources: ['ubuntu-toolchain-r-test']
|
||||
packages: *gcc5_pkgs
|
||||
|
||||
# # GCC/Debug
|
||||
# - compiler: gcc
|
||||
# env: GCC_VER=5 VARIANT=debug ADDRESS_MODEL=64
|
||||
# addons: *ao_gcc5
|
||||
# branches: # NOTE: this does NOT work, though it SHOULD
|
||||
# - master
|
||||
# - develop
|
||||
|
||||
# Clang/UndefinedBehaviourSanitizer
|
||||
- compiler: clang
|
||||
env: GCC_VER=5 VARIANT=usan CLANG_VER=3.8 ADDRESS_MODEL=64 UBSAN_OPTIONS='print_stacktrace=1'
|
||||
addons: &ao_clang38
|
||||
apt:
|
||||
sources: ['ubuntu-toolchain-r-test', 'llvm-toolchain-precise-3.8']
|
||||
packages: *clang38_pkgs
|
||||
env:
|
||||
- GCC_VER=5
|
||||
- VARIANT=usan
|
||||
- CLANG_VER=3.8
|
||||
- ADDRESS_MODEL=64
|
||||
- UBSAN_OPTIONS='print_stacktrace=1'
|
||||
- BUILD_SYSTEM=cmake
|
||||
- PATH=$PWD/cmake/bin:$PATH
|
||||
- PATH=$PWD/llvm-$LLVM_VERSION/bin:$PATH
|
||||
addons: *ao_gcc5
|
||||
|
||||
# Clang/AddressSanitizer
|
||||
- compiler: clang
|
||||
env: GCC_VER=5 VARIANT=asan CLANG_VER=3.8 ADDRESS_MODEL=64
|
||||
addons: *ao_clang38
|
||||
env:
|
||||
- GCC_VER=5
|
||||
- VARIANT=asan
|
||||
- CLANG_VER=3.8
|
||||
- ADDRESS_MODEL=64
|
||||
- PATH=$PWD/llvm-$LLVM_VERSION/bin:$PATH
|
||||
addons: *ao_gcc5
|
||||
|
||||
cache:
|
||||
directories:
|
||||
- $BOOST_ROOT
|
||||
- $VALGRIND_ROOT
|
||||
- llvm-$LLVM_VERSION
|
||||
- cmake
|
||||
|
||||
before_install:
|
||||
- scripts/install-dependencies.sh
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
1.0.0-b6
|
||||
|
||||
* Use SFINAE on return values
|
||||
* Use beast::error_code instead of nested types
|
||||
* Tidy up use of GENERATING_DOCS
|
||||
* Remove obsolete RFC2616 functions
|
||||
* Add message swap members and free functions
|
||||
* Add HTTP field value parser containers: ext_list, param_list, token_list
|
||||
* Fixes for some corner cases in basic_parser_v1
|
||||
* Configurable limits on headers and body sizes in basic_parser_v1
|
||||
|
||||
API Changes:
|
||||
|
||||
* ci_equal is moved to beast::http namespace, in rfc7230.hpp
|
||||
|
||||
* "DynamicBuffer","dynabuf" renamed from "Streambuf", "streambuf". See:
|
||||
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4478.html#requirements.dynamic_buffers
|
||||
|
||||
* basic_parser_v1 adheres to rfc7230 as strictly as possible
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
86
src/beast/CHANGELOG.md
Normal file
@@ -0,0 +1,86 @@
|
||||
1.0.0-b13
|
||||
|
||||
* dstream improvements
|
||||
* Remove bin and bin64 directories
|
||||
* Tidy up .vcxproj file groupings
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
1.0.0-b12
|
||||
|
||||
* Use -p to print suites from unit test main.
|
||||
* BEAST_EXPECTS to add a reason string to test failures
|
||||
* Fix unit test runner to output all case names
|
||||
* Update README for build requirements
|
||||
* Rename to CHANGELOG.md
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
1.0.0-b11
|
||||
|
||||
* Set URI in generated WebSocket Upgrade requests
|
||||
* Rename echo server class and file names
|
||||
* Rename to DynamicBuffer in some code and documentation
|
||||
* Fix integer warnings in Windows builds
|
||||
* Add 32 and 64 bit Windows build support
|
||||
* Update README for build instructions and more
|
||||
* Add repository and documention banners
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
1.0.0-b10
|
||||
|
||||
* Fix compilation warnings
|
||||
* Add websocketpp comparison to HTML documentation
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
1.0.0-b9
|
||||
|
||||
* Fix CMakeLists.txt
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
1.0.0-b8
|
||||
|
||||
* Fix include in example code
|
||||
* Fix basic_headers rfc2616 Section 4.2 compliance
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
1.0.0-b7
|
||||
|
||||
* Fix prepare by calling init. prepare() can throw depending on the
|
||||
implementation of Writer. Publicly provided beast::http writers never throw.
|
||||
* Fixes to example HTTP server
|
||||
* Fully qualify ambiguous calls to read and parse
|
||||
* Remove deprecated http::stream wrapper
|
||||
* Example HTTP server now calculates the MIME-type
|
||||
* Fixes and documentation for teardown and use with SSL:
|
||||
* Add example code to rfc7230 javadocs
|
||||
* Remove extraneous header file <beast/http/status.hpp>
|
||||
* Add skip_body parser option
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
1.0.0-b6
|
||||
|
||||
* Use SFINAE on return values
|
||||
* Use beast::error_code instead of nested types
|
||||
* Tidy up use of GENERATING_DOCS
|
||||
* Remove obsolete RFC2616 functions
|
||||
* Add message swap members and free functions
|
||||
* Add HTTP field value parser containers: ext_list, param_list, token_list
|
||||
* Fixes for some corner cases in basic_parser_v1
|
||||
* Configurable limits on headers and body sizes in basic_parser_v1
|
||||
|
||||
API Changes:
|
||||
|
||||
* ci_equal is moved to beast::http namespace, in rfc7230.hpp
|
||||
|
||||
* "DynamicBuffer","dynabuf" renamed from "Streambuf", "streambuf". See:
|
||||
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4478.html#requirements.dynamic_buffers
|
||||
|
||||
* basic_parser_v1 adheres to rfc7230 as strictly as possible
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
@@ -7,7 +7,7 @@ project (Beast)
|
||||
set_property (GLOBAL PROPERTY USE_FOLDERS ON)
|
||||
|
||||
if (WIN32)
|
||||
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP /W4 /wd4100 /D_SCL_SECURE_NO_WARNINGS=1 /D_CRT_SECURE_NO_WARNINGS=1")
|
||||
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP /W4 /wd4100 /bigobj /D _WIN32_WINNT=0x0601 /D_SCL_SECURE_NO_WARNINGS=1 /D_CRT_SECURE_NO_WARNINGS=1")
|
||||
set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /SAFESEH:NO")
|
||||
else()
|
||||
set(Boost_USE_STATIC_LIBS ON)
|
||||
@@ -20,10 +20,29 @@ else()
|
||||
find_package(Threads)
|
||||
|
||||
set(CMAKE_CXX_FLAGS
|
||||
"${CMAKE_CXX_FLAGS} -g -std=c++11 -Wall -Wpedantic")
|
||||
"${CMAKE_CXX_FLAGS} -std=c++11 -Wall -Wpedantic")
|
||||
endif()
|
||||
|
||||
message ("cxx Flags: " ${CMAKE_CXX_FLAGS})
|
||||
if ("${VARIANT}" STREQUAL "coverage")
|
||||
set(CMAKE_CXX_FLAGS
|
||||
"${CMAKE_CXX_FLAGS} -fprofile-arcs -ftest-coverage")
|
||||
set(CMAKE_BUILD_TYPE RELWITHDEBINFO)
|
||||
set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -lgcov")
|
||||
elseif ("${VARIANT}" STREQUAL "asan")
|
||||
set(CMAKE_CXX_FLAGS
|
||||
"${CMAKE_CXX_FLAGS} -fsanitize=address -fno-omit-frame-pointer")
|
||||
set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=address")
|
||||
set(CMAKE_BUILD_TYPE RELWITHDEBINFO)
|
||||
elseif ("${VARIANT}" STREQUAL "usan")
|
||||
set(CMAKE_CXX_FLAGS
|
||||
"${CMAKE_CXX_FLAGS} -fsanitize=undefined -fno-omit-frame-pointer")
|
||||
set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=undefined")
|
||||
set(CMAKE_BUILD_TYPE RELWITHDEBINFO)
|
||||
elseif ("${VARIANT}" STREQUAL "debug")
|
||||
set(CMAKE_BUILD_TYPE DEBUG)
|
||||
elseif ("${VARIANT}" STREQUAL "release")
|
||||
set(CMAKE_BUILD_TYPE RELEASE)
|
||||
endif()
|
||||
|
||||
function(DoGroupSources curdir rootdir folder)
|
||||
file(GLOB children RELATIVE ${PROJECT_SOURCE_DIR}/${curdir} ${PROJECT_SOURCE_DIR}/${curdir}/*)
|
||||
@@ -51,6 +70,9 @@ include_directories (include)
|
||||
file(GLOB_RECURSE BEAST_INCLUDES
|
||||
${PROJECT_SOURCE_DIR}/include/beast/*.hpp
|
||||
${PROJECT_SOURCE_DIR}/include/beast/*.ipp
|
||||
)
|
||||
|
||||
file(GLOB_RECURSE EXTRAS_INCLUDES
|
||||
${PROJECT_SOURCE_DIR}/extras/beast/*.hpp
|
||||
${PROJECT_SOURCE_DIR}/extras/beast/*.ipp
|
||||
)
|
||||
@@ -60,5 +82,3 @@ add_subdirectory (test)
|
||||
add_subdirectory (test/core)
|
||||
add_subdirectory (test/http)
|
||||
add_subdirectory (test/websocket)
|
||||
|
||||
#enable_testing()
|
||||
|
||||
@@ -100,6 +100,7 @@ project beast
|
||||
<toolset>clang:<cxxflags>-std=c++11
|
||||
<toolset>msvc:<define>_SCL_SECURE_NO_WARNINGS=1
|
||||
<toolset>msvc:<define>_CRT_SECURE_NO_WARNINGS=1
|
||||
<toolset>msvc:<cxxflags>-bigobj
|
||||
<os>LINUX:<define>_XOPEN_SOURCE=600
|
||||
<os>LINUX:<define>_GNU_SOURCE=1
|
||||
<os>SOLARIS:<define>_XOPEN_SOURCE=500
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
# Beast
|
||||
<img width="880" height = "80" alt = "Beast"
|
||||
src="https://raw.githubusercontent.com/vinniefalco/Beast/master/doc/images/readme.png">
|
||||
|
||||
[](https://gitter.im/vinniefalco/Beast?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) [![Build Status]
|
||||
(https://travis-ci.org/vinniefalco/Beast.svg?branch=master)](https://travis-ci.org/vinniefalco/Beast) [![codecov]
|
||||
@@ -7,23 +8,151 @@
|
||||
(https://img.shields.io/badge/documentation-master-brightgreen.svg)](http://vinniefalco.github.io/beast/) [![License]
|
||||
(https://img.shields.io/badge/license-boost-brightgreen.svg)](LICENSE_1_0.txt)
|
||||
|
||||
Beast provides implementations of the HTTP and WebSocket protocols
|
||||
built on top of Boost.Asio and other parts of boost.
|
||||
# HTTP and WebSocket implementations built on Boost.Asio
|
||||
|
||||
Requirements:
|
||||
---
|
||||
|
||||
* Boost
|
||||
* C++11 or greater
|
||||
* OpenSSL (optional)
|
||||
## CppCon 2016
|
||||
|
||||
This software is currently in beta: interfaces are subject to change. For
|
||||
recent changes see [CHANGELOG](CHANGELOG).
|
||||
I will be giving a lightning talk on Beast at CppCon 2016 in Bellevue,
|
||||
Washington from September 18 to September 22. If you'd like to meet me
|
||||
and hear the talk or ask questions about Beast feel free to approach
|
||||
me in person or send me an email at vinnie.falco@gmail.com to schedule
|
||||
some time.
|
||||
|
||||
About CppCon 2016:
|
||||
http://cppcon.org
|
||||
|
||||
---
|
||||
|
||||
## Contents
|
||||
|
||||
- [Introduction](#introduction)
|
||||
- [Description](#description)
|
||||
- [Requirements](#requirements)
|
||||
- [Building](#building)
|
||||
- [Usage](#usage)
|
||||
- [Licence](#licence)
|
||||
- [Contact](#contact)
|
||||
|
||||
## Introduction
|
||||
|
||||
Beast is a header-only, cross-platform C++ library built on Boost.Asio and
|
||||
Boost, containing two modules implementing widely used network protocols.
|
||||
Beast.HTTP offers a universal model for describing, sending, and receiving
|
||||
HTTP messages while Beast.WebSocket provides a complete implementation of
|
||||
the WebSocket protocol. Their design achieves these goals:
|
||||
|
||||
* **Symmetry.** Interfaces are role-agnostic; the same interfaces can be
|
||||
used to build clients, servers, or both.
|
||||
|
||||
* **Ease of Use.** HTTP messages are modeled using simple, readily
|
||||
accessible objects. Functions and classes used to send and receive HTTP
|
||||
or WebSocket messages are designed to resemble Boost.Asio as closely as
|
||||
possible. Users familiar with Boost.Asio will be immediately comfortable
|
||||
using this library.
|
||||
|
||||
* **Flexibility.** Interfaces do not mandate specific implementation
|
||||
strategies; important decisions such as buffer or thread management are
|
||||
left to users of the library.
|
||||
|
||||
* **Performance.** The implementation performs competitively, making it a
|
||||
realistic choice for building high performance network servers.
|
||||
|
||||
* **Scalability.** Development of network applications that scale to thousands
|
||||
of concurrent connections is possible with the implementation.
|
||||
|
||||
* **Basis for further abstraction.** The interfaces facilitate the
|
||||
development of other libraries that provide higher levels of abstraction.
|
||||
|
||||
Beast is used in [rippled](https://github.com/ripple/rippled), an
|
||||
open source server application that implements a decentralized
|
||||
cryptocurrency system.
|
||||
|
||||
## Description
|
||||
|
||||
This software is currently in beta: interfaces may change.
|
||||
For recent changes see the [CHANGELOG](CHANGELOG.md).
|
||||
The library has been submitted to the
|
||||
[Boost Library Incubator](http://rrsd.com/blincubator.com/bi_library/beast-2/?gform_post_id=1579)
|
||||
|
||||
* [Project Site](http://vinniefalco.github.io/)
|
||||
* [Repository](https://github.com/vinniefalco/Beast)
|
||||
* [Project Documentation](http://vinniefalco.github.io/beast/)
|
||||
* [Autobahn.testsuite results](http://vinniefalco.github.io/autobahn/index.html)
|
||||
|
||||
## Requirements
|
||||
|
||||
* Boost 1.58 or higher
|
||||
* C++11 or greater
|
||||
* OpenSSL (optional)
|
||||
|
||||
## Building
|
||||
|
||||
Beast is header-only so there are no libraries to build or link with.
|
||||
To use Beast in your project, simply copy the Beast sources to your
|
||||
project's source tree (alternatively, bring Beast into your Git repository
|
||||
using the `git subtree` or `git submodule` commands). Then, edit your
|
||||
build scripts to add the `include/` directory to the list of paths checked
|
||||
by the C++ compiler when searching for includes. Beast `#include` lines
|
||||
will look like this:
|
||||
```
|
||||
#include <beast/http.hpp>
|
||||
#include <beast/websocket.hpp>
|
||||
```
|
||||
|
||||
To link your program successfully, you'll need to add the Boost.System
|
||||
library to link with. If you use coroutines you'll also need the
|
||||
Boost.Coroutine library. Please visit the Boost documentation for
|
||||
instructions on how to do this for your particular build system.
|
||||
|
||||
For the examples and tests, Beast provides build scripts for Boost.Build (bjam)
|
||||
and CMake. Developers using Microsoft Visual Studio can generate Visual Studio
|
||||
project files by executing these commands from the root of the repository:
|
||||
|
||||
|
||||
```
|
||||
cd bin
|
||||
cmake .. # for 32-bit Windows build
|
||||
|
||||
cd ../bin64
|
||||
cmake .. # for Linux/Mac builds, OR
|
||||
cmake -G"Visual Studio 14 2015 Win64" .. # for 64-bit Windows builds
|
||||
```
|
||||
|
||||
To build with Boost.Build, it is necessary to have the bjam executable
|
||||
in your path. And bjam needs to know how to find the Boost sources. The
|
||||
easiest way to do this is make sure that the version of bjam in your path
|
||||
is the one at the root of the Boost source tree, which is built when
|
||||
running `bootstrap.sh` (or `bootstrap.bat` on Windows).
|
||||
|
||||
Once bjam is in your path, simply run bjam in the root of the Beast
|
||||
repository to automatically build the required Boost libraries if they
|
||||
are not already built, build the examples, then build and run the unit
|
||||
tests.
|
||||
|
||||
The files in the repository are laid out thusly:
|
||||
|
||||
```
|
||||
./
|
||||
bin/ Holds executables and project files
|
||||
bin64/ Holds 64-bit Windows executables and project files
|
||||
include/ Add this to your compiler includes
|
||||
beast/
|
||||
extras/ Additional APIs, may change
|
||||
examples/ Self contained example programs
|
||||
test/ Unit tests and benchmarks
|
||||
```
|
||||
|
||||
|
||||
## Usage
|
||||
|
||||
These examples are complete, self-contained programs that you can build
|
||||
and run yourself (they are in the `examples` directory).
|
||||
|
||||
Example WebSocket program:
|
||||
```C++
|
||||
#include <beast/to_string.hpp>
|
||||
#include <beast/core/to_string.hpp>
|
||||
#include <beast/websocket.hpp>
|
||||
#include <boost/asio.hpp>
|
||||
#include <iostream>
|
||||
@@ -34,13 +163,13 @@ int main()
|
||||
// Normal boost::asio setup
|
||||
std::string const host = "echo.websocket.org";
|
||||
boost::asio::io_service ios;
|
||||
boost::asio::ip::tcp::resolver r(ios);
|
||||
boost::asio::ip::tcp::socket sock(ios);
|
||||
boost::asio::ip::tcp::resolver r{ios};
|
||||
boost::asio::ip::tcp::socket sock{ios};
|
||||
boost::asio::connect(sock,
|
||||
r.resolve(boost::asio::ip::tcp::resolver::query{host, "80"}));
|
||||
|
||||
// WebSocket connect and send message using beast
|
||||
beast::websocket::stream<boost::asio::ip::tcp::socket&> ws(sock);
|
||||
beast::websocket::stream<boost::asio::ip::tcp::socket&> ws{sock};
|
||||
ws.handshake(host, "/");
|
||||
ws.write(boost::asio::buffer("Hello, world!"));
|
||||
|
||||
@@ -65,8 +194,8 @@ int main()
|
||||
// Normal boost::asio setup
|
||||
std::string const host = "boost.org";
|
||||
boost::asio::io_service ios;
|
||||
boost::asio::ip::tcp::resolver r(ios);
|
||||
boost::asio::ip::tcp::socket sock(ios);
|
||||
boost::asio::ip::tcp::resolver r{ios};
|
||||
boost::asio::ip::tcp::socket sock{ios};
|
||||
boost::asio::connect(sock,
|
||||
r.resolve(boost::asio::ip::tcp::resolver::query{host, "http"}));
|
||||
|
||||
@@ -88,12 +217,13 @@ int main()
|
||||
}
|
||||
```
|
||||
|
||||
Links:
|
||||
## License
|
||||
|
||||
* [Home](http://vinniefalco.github.io/)
|
||||
* [Repository](https://github.com/vinniefalco/Beast)
|
||||
* [Documentation](http://vinniefalco.github.io/beast/)
|
||||
* [Autobahn.testsuite results](http://vinniefalco.github.io/autobahn/index.html)
|
||||
Distributed under the Boost Software License, Version 1.0.
|
||||
(See accompanying file [LICENSE_1_0.txt](LICENSE_1_0.txt) or copy at
|
||||
http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
## Contact
|
||||
|
||||
Please report issues or questions here:
|
||||
https://github.com/vinniefalco/Beast/issues
|
||||
|
||||
@@ -15,7 +15,7 @@ using boostbook ;
|
||||
using quickbook ;
|
||||
using doxygen ;
|
||||
|
||||
xml beast_boostbook : beast.qbk ;
|
||||
xml beast_boostbook : master.qbk ;
|
||||
|
||||
path-constant out : . ;
|
||||
|
||||
@@ -56,8 +56,8 @@ boostbook doc
|
||||
<xsl:param>chapter.autolabel=0
|
||||
<xsl:param>boost.image.src=images/beast.png
|
||||
<xsl:param>boost.image.alt="Beast Logo"
|
||||
<xsl:param>boost.image.w=1007
|
||||
<xsl:param>boost.image.h=107
|
||||
<xsl:param>boost.image.w=2400
|
||||
<xsl:param>boost.image.h=80
|
||||
<xsl:param>boost.root=$(broot)
|
||||
<xsl:param>chapter.autolabel=0
|
||||
<xsl:param>chunk.first.sections=1 # Chunk the first top-level section?
|
||||
|
||||
@@ -8,9 +8,9 @@
|
||||
[section:design Design choices]
|
||||
|
||||
The implementations are driven by business needs of cryptocurrency server
|
||||
applications ([@https://ripple.com Ripple] written in C++. These
|
||||
needs were not met by existing solutions so new code was written. The new
|
||||
code tries to avoid design flaws encountered in the already-existing software
|
||||
applications (e.g. [@https://ripple.com Ripple]) written in C++. These
|
||||
needs were not met by existing solutions so Beast was written from scratch
|
||||
as a solution. Beast's design philosophy avoid flaws exhibited by other
|
||||
libraries:
|
||||
|
||||
* Don't sacrifice performance.
|
||||
@@ -44,11 +44,13 @@ to address those issues.
|
||||
in production. That would give some evidence that the design
|
||||
works in practice.""
|
||||
][
|
||||
Beast.HTTP and Beast.WebSocket will be used in [*rippled], an
|
||||
asynchronous peer to peer server that implements the
|
||||
[*Ripple Consensus Protocol]. These servers are deployed in multiple
|
||||
production environments, with banks in many countries running client
|
||||
applications that connect to [*rippled].
|
||||
Beast.HTTP and Beast.WebSocket are production ready and currently
|
||||
running on public servers receiving traffic and handling millions of
|
||||
dollars worth of financial transactions daily. The servers run [*rippled],
|
||||
open source software ([@https://github.com/ripple/rippled repository])
|
||||
implementing the
|
||||
[@https://ripple.com/files/ripple_consensus_whitepaper.pdf [*Ripple Consensus Protocol]],
|
||||
technology provided by [@http://ripple.com Ripple].
|
||||
]]
|
||||
|
||||
]
|
||||
@@ -171,26 +173,453 @@ start. Other design goals:
|
||||
[section:websocket WebSocket]
|
||||
|
||||
[variablelist
|
||||
|
||||
[[
|
||||
How does this compare to [@https://www.zaphoyd.com/websocketpp websocketpp],
|
||||
an alternate header-only WebSocket implementation?
|
||||
][
|
||||
[variablelist
|
||||
|
||||
[[1. Synchronous Interface][
|
||||
|
||||
Beast offers full support for WebSockets using a synchronous interface. It
|
||||
uses the same style of interfaces found in Boost.Asio: versions that throw
|
||||
exceptions, or versions that return the error code in a reference parameter:
|
||||
|
||||
[table
|
||||
[
|
||||
[[@https://github.com/vinniefalco/Beast/blob/6c8b4b2f8dde72b01507e4ac7fde4ffea57ebc99/include/beast/websocket/stream.hpp#L774 Beast]]
|
||||
[websocketpp]
|
||||
][
|
||||
[```
|
||||
template<class DynamicBuffer>
|
||||
void
|
||||
read(opcode& op, DynamicBuffer& dynabuf)
|
||||
```]
|
||||
[
|
||||
/<not available>/
|
||||
]
|
||||
]]]]
|
||||
|
||||
[[2. Connection Model][
|
||||
|
||||
websocketpp supports multiple transports by utilizing a trait, the `config::transport_type`
|
||||
([@https://github.com/zaphoyd/websocketpp/blob/378437aecdcb1dfe62096ffd5d944bf1f640ccc3/websocketpp/transport/asio/connection.hpp#L60 asio transport example])
|
||||
To get an idea of the complexity involved with implementing a transport,
|
||||
compare the asio transport to the
|
||||
[@https://github.com/zaphoyd/websocketpp/blob/378437aecdcb1dfe62096ffd5d944bf1f640ccc3/websocketpp/transport/iostream/connection.hpp#L59 `iostream` transport]
|
||||
(a layer that allows websocket communication over a std iostream).
|
||||
|
||||
In contrast, Beast abstracts the transport by defining just one [*`NextLayer`]
|
||||
template argument The type requirements for [*`NextLayer`] are
|
||||
already familiar to users as they are documented in Asio:
|
||||
[@http://www.boost.org/doc/libs/1_60_0/doc/html/boost_asio/reference/SyncReadStream.html SyncReadStream],
|
||||
[@http://www.boost.org/doc/libs/1_60_0/doc/html/boost_asio/reference/SyncWriteStream.html SyncWriteStream],
|
||||
[@http://www.boost.org/doc/libs/1_60_0/doc/html/boost_asio/reference/AsyncReadStream.html AsyncReadStream], and
|
||||
[@http://www.boost.org/doc/libs/1_60_0/doc/html/boost_asio/reference/AsyncWriteStream.html AsyncWriteStream].
|
||||
The type requirements for instantiating `beast::websocket::stream` versus
|
||||
`websocketpp::connection` with user defined types are vastly reduced
|
||||
(18 functions versus 2). Note that websocketpp connections are passed by
|
||||
`shared_ptr`. Beast does not use `shared_ptr` anywhere in its public interface.
|
||||
A `beast::websocket::stream` is constructible and movable in a manner identical
|
||||
`to a boost::asio::ip::tcp::socket`. Callers can put such objects in a
|
||||
`shared_ptr` if they want to, but there is no requirement to do so.
|
||||
|
||||
[table
|
||||
[
|
||||
[[@https://github.com/vinniefalco/Beast/blob/6c8b4b2f8dde72b01507e4ac7fde4ffea57ebc99/include/beast/websocket/stream.hpp Beast]]
|
||||
[[@https://github.com/zaphoyd/websocketpp/blob/378437aecdcb1dfe62096ffd5d944bf1f640ccc3/websocketpp/connection.hpp#L234 websocketpp]]
|
||||
][
|
||||
[```
|
||||
template<class NextLayer>
|
||||
class stream
|
||||
{
|
||||
NextLayer next_layer_;
|
||||
...
|
||||
}
|
||||
```]
|
||||
[```
|
||||
template <typename config>
|
||||
class connection
|
||||
: public config::transport_type::transport_con_type
|
||||
, public config::connection_base
|
||||
{
|
||||
public:
|
||||
typedef lib::shared_ptr<type> ptr;
|
||||
...
|
||||
}
|
||||
```]
|
||||
]]]]
|
||||
|
||||
[[3. Client and Server Role][
|
||||
|
||||
websocketpp provides multi-role support through a hierarchy of
|
||||
different classes. A `beast::websocket::stream` is role-agnostic, it
|
||||
offers member functions to perform both client and server handshakes
|
||||
in the same class. The same types are used for client and server
|
||||
streams.
|
||||
|
||||
[table
|
||||
[
|
||||
[Beast]
|
||||
[[@https://github.com/zaphoyd/websocketpp/blob/378437aecdcb1dfe62096ffd5d944bf1f640ccc3/websocketpp/roles/server_endpoint.hpp#L39 websocketpp],
|
||||
[@https://github.com/zaphoyd/websocketpp/blob/378437aecdcb1dfe62096ffd5d944bf1f640ccc3/websocketpp/roles/client_endpoint.hpp#L42 also]]
|
||||
][
|
||||
[
|
||||
/<not needed>/
|
||||
]
|
||||
[```
|
||||
template <typename config>
|
||||
class client : public endpoint<connection<config>,config>;
|
||||
template <typename config>
|
||||
class server : public endpoint<connection<config>,config>;
|
||||
```]
|
||||
]]]]
|
||||
|
||||
[[4. Thread Safety][
|
||||
|
||||
websocketpp uses mutexes to protect shared data from concurrent
|
||||
access. In contrast, Beast does not use mutexes anywhere in its
|
||||
implementation. Instead, it follows the Asio pattern. Calls to
|
||||
asynchronous initiation functions use the same method to invoke
|
||||
intermediate handlers as the method used to invoke the final handler,
|
||||
through the
|
||||
[@http://www.boost.org/doc/libs/1_60_0/doc/html/boost_asio/reference/asio_handler_invoke.html asio_handler_invoke] mechanism.
|
||||
|
||||
The only requirement in Beast is that calls to asynchronous initiation
|
||||
functions are made from the same implicit or explicit strand. For
|
||||
example, if the `io_service` associated with a `beast::websocket::stream`
|
||||
is single threaded, this counts as an implicit strand and no performance
|
||||
costs associated with mutexes are incurred.
|
||||
|
||||
[table
|
||||
[
|
||||
[[@https://github.com/vinniefalco/Beast/blob/6c8b4b2f8dde72b01507e4ac7fde4ffea57ebc99/include/beast/websocket/impl/read_frame_op.ipp#L118 Beast]]
|
||||
[[@https://github.com/zaphoyd/websocketpp/blob/378437aecdcb1dfe62096ffd5d944bf1f640ccc3/websocketpp/transport/iostream/connection.hpp#L706 websocketpp]]
|
||||
][
|
||||
[```
|
||||
template <class Function>
|
||||
friend
|
||||
void asio_handler_invoke(Function&& f, read_frame_op* op)
|
||||
{
|
||||
return boost_asio_handler_invoke_helpers::invoke(f, op->d_->h);
|
||||
}
|
||||
```]
|
||||
[```
|
||||
mutex_type m_read_mutex;
|
||||
```]
|
||||
]]]]
|
||||
|
||||
[[5. Callback Model][
|
||||
|
||||
websocketpp requires a one-time call to set the handler for each event
|
||||
in its interface (for example, upon message receipt). The handler is
|
||||
represented by a `std::function equivalent`. Its important to recognize
|
||||
that the websocketpp interface performs type-erasure on this handler.
|
||||
|
||||
In comparison, Beast handlers are specified in a manner identical to
|
||||
Boost.Asio. They are function objects which can be copied or moved but
|
||||
most importantly they are not type erased. The compiler can see
|
||||
through the type directly to the implementation, permitting
|
||||
optimization. Furthermore, Beast follows the Asio rules for treatment
|
||||
of handlers. It respects any allocation, continuation, or invocation
|
||||
customizations associated with the handler through the use of argument
|
||||
dependent lookup overloads of functions such as `asio_handler_allocate`.
|
||||
|
||||
The Beast completion handler is provided at the call site. For each
|
||||
call to an asynchronous initiation function, it is guaranteed that
|
||||
there will be exactly one final call to the handler. This functions
|
||||
exactly the same way as the asynchronous initiation functions found in
|
||||
Boost.Asio, allowing the composition of higher level abstractions.
|
||||
|
||||
[table
|
||||
[
|
||||
[[@https://github.com/vinniefalco/Beast/blob/6c8b4b2f8dde72b01507e4ac7fde4ffea57ebc99/include/beast/websocket/stream.hpp#L834 Beast]]
|
||||
[[@https://github.com/zaphoyd/websocketpp/blob/378437aecdcb1dfe62096ffd5d944bf1f640ccc3/websocketpp/connection.hpp#L281 websocketpp],
|
||||
[@https://github.com/zaphoyd/websocketpp/blob/378437aecdcb1dfe62096ffd5d944bf1f640ccc3/websocketpp/connection.hpp#L473 also]]
|
||||
][
|
||||
[```
|
||||
template<class DynamicBuffer, class ReadHandler>
|
||||
typename async_completion<ReadHandler, void(error_code)>::result_type
|
||||
async_read(opcode& op, DynamicBuffer& dynabuf, ReadHandler&& handler);
|
||||
```]
|
||||
[```
|
||||
typedef lib::function<void(connection_hdl,message_ptr)> message_handler;
|
||||
void set_message_handler(message_handler h);
|
||||
```]
|
||||
]]]]
|
||||
|
||||
[[6. Extensible Asynchronous Model][
|
||||
|
||||
Beast fully supports the
|
||||
[@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n3896.pdf Extensible Asynchronous Model]
|
||||
developed by Christopher Kohlhoff, author of Boost.Asio (see Section 8).
|
||||
|
||||
Beast websocket asynchronous interfaces may be used seamlessly with
|
||||
`std::future` stackful/stackless coroutines, or user defined customizations.
|
||||
|
||||
[table
|
||||
[
|
||||
[[@https://github.com/vinniefalco/Beast/blob/6c8b4b2f8dde72b01507e4ac7fde4ffea57ebc99/include/beast/websocket/impl/stream.ipp#L378 Beast]]
|
||||
[websocketpp]
|
||||
][
|
||||
[```
|
||||
beast::async_completion<ReadHandler, void(error_code)> completion(handler);
|
||||
read_op<DynamicBuffer, decltype(completion.handler)>{
|
||||
completion.handler, *this, op, streambuf};
|
||||
return completion.result.get();
|
||||
```]
|
||||
[
|
||||
/<not available>/
|
||||
]
|
||||
]]]]
|
||||
|
||||
[[7. Message Buffering][
|
||||
|
||||
websocketpp defines a message buffer, passed in arguments by
|
||||
`shared_ptr`, and an associated message manager which permits
|
||||
aggregation and memory reuse of memory. The implementation of
|
||||
`websocketpp::message` uses a `std::string` to hold the payload. If an
|
||||
incoming message is broken up into multiple frames, the string may be
|
||||
reallocated for each continuation frame. The std::string always uses
|
||||
the standard allocator, it is not possible to customize the choice of
|
||||
allocator.
|
||||
|
||||
Beast allows callers to specify the object for receiving the message
|
||||
or frame data, which is of any type meeting the requirements of
|
||||
[@http://vinniefalco.github.io/beast/beast/types/DynamicBuffer.html [*DynamicBuffer]]
|
||||
(modeled after `boost::asio::streambuf`).
|
||||
|
||||
Beast comes with the class `beast::basic_streambuf`, an efficient
|
||||
implementation of the [*DynamicBuffer] concept which makes use of multiple
|
||||
allocated octet arrays. If an incoming message is broken up into
|
||||
multiple pieces, no reallocation occurs. Instead, new allocations are
|
||||
appended to the sequence when existing allocations are filled. Beast
|
||||
does not impose any particular memory management model on callers. The
|
||||
`basic_streambuf` provided by beast supports standard allocators through
|
||||
a template argument. Use the [*DynamicBuffer] that comes with beast,
|
||||
customize the allocator if you desire, or provide your own type that
|
||||
meets the
|
||||
[@https://github.com/vinniefalco/Beast/blob/6c8b4b2f8dde72b01507e4ac7fde4ffea57ebc99/include/beast/basic_streambuf.hpp#L21 concept requirements].
|
||||
|
||||
[table
|
||||
[
|
||||
[[@https://github.com/vinniefalco/Beast/blob/6c8b4b2f8dde72b01507e4ac7fde4ffea57ebc99/include/beast/websocket/stream.hpp#L774 Beast]]
|
||||
[[@https://github.com/zaphoyd/websocketpp/blob/378437aecdcb1dfe62096ffd5d944bf1f640ccc3/websocketpp/message_buffer/message.hpp#L78 websocketpp]]
|
||||
][
|
||||
[```
|
||||
template<class DynamicBuffer>
|
||||
read(opcode& op, DynamicBuffer& dynabuf);
|
||||
```]
|
||||
[```
|
||||
template <template<class> class con_msg_manager>
|
||||
class message {
|
||||
public:
|
||||
typedef lib::shared_ptr<message> ptr;
|
||||
...
|
||||
std::string m_payload;
|
||||
...
|
||||
};
|
||||
```]
|
||||
]]]]
|
||||
|
||||
[[8. Sending Messages][
|
||||
|
||||
When sending a message, websocketpp requires that the payload is
|
||||
packaged in a `websocketpp::message` object using `std::string` as the
|
||||
storage, or it requires a copy of the caller provided buffer by
|
||||
constructing a new message object. Messages are placed onto an
|
||||
outgoing queue. An asynchronous write operation runs in the background
|
||||
to clear the queue. No user facing handler can be registered to be
|
||||
notified when messages or frames have completed sending.
|
||||
|
||||
Beast doesn't allocate or make copies of buffers when sending data. The
|
||||
caller's buffers are sent in-place. You can use any object meeting the
|
||||
requirements of
|
||||
[@http://www.boost.org/doc/libs/1_60_0/doc/html/boost_asio/reference/ConstBufferSequence.html ConstBufferSequence],
|
||||
permitting efficient scatter-gather I/O.
|
||||
|
||||
The [*ConstBufferSequence] interface allows callers to send data from
|
||||
memory-mapped regions (not possible in websocketpp). Callers can also
|
||||
use the same buffers to send data to multiple streams, for example
|
||||
broadcasting common subscription data to many clients at once. For
|
||||
each call to `async_write` the completion handler is called once when
|
||||
the data finishes sending, in a manner identical to `boost::asio::async_write`.
|
||||
|
||||
[table
|
||||
[
|
||||
[[@https://github.com/vinniefalco/Beast/blob/6c8b4b2f8dde72b01507e4ac7fde4ffea57ebc99/include/beast/websocket/stream.hpp#L1048 Beast]]
|
||||
[[@https://github.com/zaphoyd/websocketpp/blob/378437aecdcb1dfe62096ffd5d944bf1f640ccc3/websocketpp/connection.hpp#L672 websocketpp]]
|
||||
][
|
||||
[```
|
||||
template<class ConstBufferSequence>
|
||||
void
|
||||
write(ConstBufferSequence const& buffers);
|
||||
```]
|
||||
[```
|
||||
lib::error_code send(std::string const & payload,
|
||||
frame::opcode::value op = frame::opcode::text);
|
||||
...
|
||||
lib::error_code send(message_ptr msg);
|
||||
```]
|
||||
]]]]
|
||||
|
||||
[[9. Streaming Messages][
|
||||
|
||||
websocketpp requires that the entire message fit into memory, and that
|
||||
the size is known ahead of time.
|
||||
|
||||
Beast allows callers to compose messages in individual frames. This is
|
||||
useful when the size of the data is not known ahead of time or if it
|
||||
is not desired to buffer the entire message in memory at once before
|
||||
sending it. For example, sending periodic output of a database query
|
||||
running on a coroutine. Or sending the contents of a file in pieces,
|
||||
without bringing it all into memory.
|
||||
|
||||
[table
|
||||
[
|
||||
[[@https://github.com/vinniefalco/Beast/blob/6c8b4b2f8dde72b01507e4ac7fde4ffea57ebc99/include/beast/websocket/stream.hpp#L1151 Beast]]
|
||||
[websocketpp]
|
||||
][
|
||||
[```
|
||||
template<class ConstBufferSequence>
|
||||
void
|
||||
write_frame(bool fin,
|
||||
ConstBufferSequence const& buffers);
|
||||
```]
|
||||
[
|
||||
/<not available>/
|
||||
]
|
||||
]]]]
|
||||
|
||||
[[10. Flow Control][
|
||||
|
||||
The websocketpp read implementation continuously reads asynchronously
|
||||
from the network and buffers message data. To prevent unbounded growth
|
||||
and leverage TCP/IP's flow control mechanism, callers can periodically
|
||||
turn this 'read pump' off and back on.
|
||||
|
||||
In contrast a `beast::websocket::stream` does not independently begin
|
||||
background activity, nor does it buffer messages. It receives data only
|
||||
when there is a call to an asynchronous initiation function (for
|
||||
example `beast::websocket::stream::async_read`) with an associated handler.
|
||||
Applications do not need to implement explicit logic to regulate the
|
||||
flow of data. Instead, they follow the traditional model of issuing a
|
||||
read, receiving a read completion, processing the message, then
|
||||
issuing a new read and repeating the process.
|
||||
|
||||
[table
|
||||
[
|
||||
[Beast]
|
||||
[[@https://github.com/zaphoyd/websocketpp/blob/378437aecdcb1dfe62096ffd5d944bf1f640ccc3/websocketpp/connection.hpp#L728 websocketpp]]
|
||||
][
|
||||
[
|
||||
/<implicit>/
|
||||
]
|
||||
[```
|
||||
lib::error_code pause_reading();
|
||||
lib::error_code resume_reading();
|
||||
```]
|
||||
]]]]
|
||||
|
||||
[[11. Connection Establishment][
|
||||
|
||||
websocketpp offers the `endpoint` class which can handle binding and
|
||||
listening to a port, and spawning connection objects.
|
||||
|
||||
Beast does not reinvent the wheel here, callers use the interfaces
|
||||
already in `boost::asio` for receiving incoming connections resolving
|
||||
host names, or establishing outgoing connections. After the socket (or
|
||||
`boost::asio::ssl::stream`) is connected, the `beast::websocket::stream`
|
||||
is constructed around it and the WebSocket handshake can be performed.
|
||||
|
||||
Beast users are free to implement their own "connection manager", but
|
||||
there is no requirement to do so.
|
||||
|
||||
[table
|
||||
[
|
||||
[[@http://www.boost.org/doc/libs/1_60_0/doc/html/boost_asio/reference/async_connect.html Beast],
|
||||
[@http://www.boost.org/doc/libs/1_60_0/doc/html/boost_asio/reference/basic_socket_acceptor/async_accept.html also]]
|
||||
[[@https://github.com/zaphoyd/websocketpp/blob/378437aecdcb1dfe62096ffd5d944bf1f640ccc3/websocketpp/transport/asio/endpoint.hpp#L52 websocketpp]]
|
||||
][
|
||||
[```
|
||||
#include <boost/asio.hpp>
|
||||
```]
|
||||
[```
|
||||
template <typename config>
|
||||
class endpoint : public config::socket_type;
|
||||
```]
|
||||
]]]]
|
||||
|
||||
[[12. WebSocket Handshaking][
|
||||
|
||||
Callers invoke `beast::websocket::accept` to perform the WebSocket
|
||||
handshake, but there is no requirement to use this function. Advanced
|
||||
users can perform the WebSocket handshake themselves. Beast WebSocket
|
||||
provides the tools for composing the request or response, and the
|
||||
Beast HTTP interface provides the container and algorithms for sending
|
||||
and receiving HTTP/1 messages including the necessary HTTP Upgrade
|
||||
request for establishing the WebSocket session.
|
||||
|
||||
Beast allows the caller to pass the incoming HTTP Upgrade request for
|
||||
the cases where the caller has already received an HTTP message.
|
||||
This flexibility permits novel and robust implementations. For example,
|
||||
a listening socket that can handshake in multiple protocols on the
|
||||
same port.
|
||||
|
||||
Sometimes callers want to read some bytes on the socket before reading
|
||||
the WebSocket HTTP Upgrade request. Beast allows these already-received
|
||||
bytes to be supplied to an overload of the accepting function to permit
|
||||
sophisticated features. For example, a listening socket that can
|
||||
accept both regular WebSocket and Secure WebSocket (SSL) connections.
|
||||
|
||||
[table
|
||||
[
|
||||
[[@https://github.com/vinniefalco/Beast/blob/6c8b4b2f8dde72b01507e4ac7fde4ffea57ebc99/include/beast/websocket/stream.hpp#L501 Beast],
|
||||
[@https://github.com/vinniefalco/Beast/blob/6c8b4b2f8dde72b01507e4ac7fde4ffea57ebc99/include/beast/websocket/stream.hpp#L401 also]]
|
||||
[websocketpp]
|
||||
][
|
||||
[```
|
||||
template<class ConstBufferSequence>
|
||||
void
|
||||
accept(ConstBufferSequence const& buffers);
|
||||
|
||||
template<class Body, class Headers>
|
||||
void
|
||||
accept(http::request_v1<Body, Headers> const& request);
|
||||
```]
|
||||
[
|
||||
/<not available>/
|
||||
]
|
||||
]]]]
|
||||
|
||||
]
|
||||
]]
|
||||
|
||||
[[
|
||||
What about message compression?
|
||||
][
|
||||
The feature is not currently present in the library, but the choice
|
||||
of type requirements for buffers passed to the read functions have been
|
||||
made with compression in mind. There is the plan to add this feature;
|
||||
however, we feel that even without compression users can begin taking
|
||||
advantage of the WebSocket protocol immediately with this library.
|
||||
The author is currently porting ZLib 1.2.8 to modern, header-only C++11
|
||||
that does not use macros or try to support ancient architectures. This
|
||||
deflate implementation will be available as its own individually
|
||||
usable interface, and also will be used to power Beast WebSocket's
|
||||
permessage-deflate implementation, due Q4 of 2016.
|
||||
|
||||
However, Beast currently has sufficient functionality that users can
|
||||
begin taking advantage of the WebSocket protocol using this library
|
||||
immediately.
|
||||
]]
|
||||
|
||||
[[
|
||||
Where is the TLS/SSL interface?
|
||||
][
|
||||
The `websocket::stream` just wraps the socket or stream that you
|
||||
provide (for example, a `boost::asio::ip::tcp::socket` or a
|
||||
`boost::asio::ssl::stream`). You establish your TLS connection
|
||||
using the interface on `ssl::stream` like shown in all of the Asio
|
||||
examples, they construct your `websocket::stream` around it.
|
||||
It works perfectly fine - Beast.WebSocket doesn't try to reinvent the
|
||||
wheel or put a fresh coat of interface paint on the `ssl::stream`.
|
||||
The `websocket::stream` wraps the socket or stream that you provide
|
||||
(for example, a `boost::asio::ip::tcp::socket` or a
|
||||
`boost::asio::ssl::stream`). You establish your TLS connection using the
|
||||
interface on `ssl::stream` like shown in all of the Asio examples, they
|
||||
construct your `websocket::stream` around it. It works perfectly fine;
|
||||
Beast.WebSocket doesn't try to reinvent the wheel or put a fresh coat of
|
||||
interface paint on the `ssl::stream`.
|
||||
|
||||
The WebSocket implementation [*does] provides support for shutting down
|
||||
the TLS connection through the use of the ADL compile-time virtual functions
|
||||
@@ -200,14 +629,11 @@ start. Other design goals:
|
||||
for TLS streams. Callers may provide their own overloads of these functions
|
||||
for user-defined next layer types.
|
||||
]]
|
||||
|
||||
]
|
||||
|
||||
[endsect]
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
[endsect]
|
||||
|
||||
@@ -92,19 +92,20 @@ and its customization points in more depth, for advanced applications.
|
||||
[heading Declarations]
|
||||
|
||||
To do anything, a message must be declared. The message class template
|
||||
requires at mininum, a value indicating whether the message is a request
|
||||
requires at minimum, a value indicating whether the message is a request
|
||||
(versus a response), and a `Body` type. The choice of `Body` determines the
|
||||
kind of container used to represent the message body. Here we will
|
||||
declare a request that has a `std::string` for the body container:
|
||||
declare a HTTP/1 request that has a `std::string` for the body container:
|
||||
```
|
||||
http::message<true, http::string_body> req;
|
||||
http::message_v1<true, http::string_body> req;
|
||||
```
|
||||
|
||||
Two type aliases are provided for notational convenience when declaring
|
||||
messages. These two statements declare a request and a response respectively:
|
||||
HTTP/1 messages. These two statements declare a request and a response
|
||||
respectively:
|
||||
```
|
||||
http::request<http::string_body> req;
|
||||
http::response<http::string_body> resp;
|
||||
http::request_v1<http::string_body> req;
|
||||
http::response_v1<http::string_body> resp;
|
||||
```
|
||||
|
||||
[heading Members]
|
||||
@@ -113,14 +114,14 @@ Message objects are default constructible, with public access to data members.
|
||||
Request and response objects have some common members, and some members unique
|
||||
to the message type. These statements set all the members in each message:
|
||||
```
|
||||
http::request<http::string_body> req;
|
||||
req.method = http::method_t::http_get;
|
||||
http::request_v1<http::string_body> req;
|
||||
req.method = "GET";
|
||||
req.url = "/index.html";
|
||||
req.version = 11; // HTTP/1.1
|
||||
req.headers.insert("User-Agent", "hello_world");
|
||||
req.body = "";
|
||||
|
||||
http::response<http::string_body> resp;
|
||||
http::response_v1<http::string_body> resp;
|
||||
resp.status = 404;
|
||||
resp.reason = "Not Found";
|
||||
resp.version = 10; // HTTP/1.0
|
||||
@@ -128,17 +129,6 @@ to the message type. These statements set all the members in each message:
|
||||
resp.body = "The requested resource was not found.";
|
||||
```
|
||||
|
||||
The following statements achieve the same effects as the statements above:
|
||||
```
|
||||
http::request<http::string_body> req({http::method_t::http_get, "/index.html", 11});
|
||||
req.headers.insert("User-Agent", "hello_world");
|
||||
req.body = "";
|
||||
|
||||
http::response<http::string_body> resp({404, "Not Found", 10});
|
||||
resp.headers.insert("Server", "Beast.HTTP");
|
||||
resp.body = "The requested resource was not found.";
|
||||
```
|
||||
|
||||
[heading Headers]
|
||||
|
||||
The `message::headers` member is a container for setting the field/value
|
||||
@@ -146,7 +136,7 @@ pairs in the message. These statements change the values of the headers
|
||||
in the message passed:
|
||||
```
|
||||
template<class Body>
|
||||
void set_fields(http::request<Body>& req)
|
||||
void set_fields(http::request_v1<Body>& req)
|
||||
{
|
||||
if(! req.exists("User-Agent"))
|
||||
req.insert("User-Agent", "myWebClient");
|
||||
@@ -168,7 +158,10 @@ following types, provided by the library, are suitable choices for the
|
||||
* [link beast.ref.http__empty_body [*`empty_body`:]] An empty message body.
|
||||
Used in GET requests where there is no message body. Example:
|
||||
```
|
||||
http::request<http::empty_body> req({http::method_t::http_get, "/index.html", 11});
|
||||
http::request_v1<http::empty_body> req;
|
||||
req.version = 11;
|
||||
req.method = "GET";
|
||||
req.url = "/index.html";
|
||||
```
|
||||
|
||||
* [link beast.ref.http__string_body [*`string_body`:]] A body with a
|
||||
@@ -177,7 +170,7 @@ or response with simple text in the message body (such as an error message).
|
||||
Has the same insertion complexity of `std::string`. This is the type of body
|
||||
used in the examples:
|
||||
```
|
||||
http::response<http::string_body> resp;
|
||||
http::response_v1<http::string_body> resp;
|
||||
static_assert(std::is_same<decltype(resp.body), std::string>::value);
|
||||
resp.body = "Here is the data you requested";
|
||||
```
|
||||
@@ -197,7 +190,10 @@ functions:
|
||||
```
|
||||
void send_request(boost::asio::ip::tcp::socket& sock)
|
||||
{
|
||||
http::request<http::empty_body> req({http::method_t::http_get, "/index.html", 11});
|
||||
http::request<http::empty_body> req;
|
||||
req.version = 11;
|
||||
req.method = "GET";
|
||||
req.url = "/index.html";
|
||||
...
|
||||
http::write(sock, req); // Throws exception on error
|
||||
...
|
||||
@@ -213,7 +209,7 @@ An asynchronous interface is available:
|
||||
```
|
||||
void handle_write(boost::system::error_code);
|
||||
...
|
||||
http::request<http::empty_body> req;
|
||||
http::request_v1<http::empty_body> req;
|
||||
...
|
||||
http::async_write(sock, req, std::bind(&handle_write, std::placeholders::_1));
|
||||
```
|
||||
@@ -222,13 +218,13 @@ When the implementation reads messages from a socket, it can read bytes lying
|
||||
after the end of the message if they are present (the alternative is to read
|
||||
a single byte at a time which is unsuitable for performance reasons). To
|
||||
store and re-use these extra bytes on subsequent messages, the read interface
|
||||
requires an additional paramter: a [link beast.types.DynamicBuffer [*`DynamicBuffer`]]
|
||||
requires an additional parameter: a [link beast.types.DynamicBuffer [*`DynamicBuffer`]]
|
||||
object. This example reads a message from the socket, with the extra bytes
|
||||
stored in the streambuf parameter for use in a subsequent call to read:
|
||||
```
|
||||
boost::asio::streambuf sb;
|
||||
...
|
||||
http::response<http::string_body> resp;
|
||||
http::response_v1<http::string_body> resp;
|
||||
http::read(sock, sb, resp); // Throws exception on error
|
||||
...
|
||||
// Alternatively
|
||||
@@ -245,7 +241,7 @@ called:
|
||||
void handle_read(boost::system::error_code);
|
||||
...
|
||||
boost::asio::streambuf sb;
|
||||
http::response<http::string_body> resp;
|
||||
http::response_v1<http::string_body> resp;
|
||||
...
|
||||
http::async_read(sock, resp, std::bind(&handle_read, std::placeholders::_1));
|
||||
```
|
||||
@@ -257,7 +253,7 @@ An alternative to using a `boost::asio::streambuf` is to use a
|
||||
void handle_read(boost::system::error_code);
|
||||
...
|
||||
beast::streambuf sb;
|
||||
http::response<http::string_body> resp;
|
||||
http::response_v1<http::string_body> resp;
|
||||
http::read(sock, sb, resp);
|
||||
```
|
||||
|
||||
|
||||
|
Before Width: | Height: | Size: 42 KiB After Width: | Height: | Size: 241 KiB |
BIN
src/beast/doc/images/readme.png
Normal file
|
After Width: | Height: | Size: 92 KiB |
@@ -6,7 +6,7 @@
|
||||
# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
mkdir -p ../bin/doc/xml
|
||||
doxygen beast.dox
|
||||
doxygen source.dox
|
||||
cd ../bin/doc/xml
|
||||
xsltproc combine.xslt index.xml > all.xml
|
||||
cd ../../../doc
|
||||
|
||||
@@ -39,11 +39,11 @@
|
||||
|
||||
[section:intro Introduction]
|
||||
|
||||
Beast is a cross-platform C++ library built on Boost.Asio and Boost, containing
|
||||
two modules implementing widely used network protocols. Beast.HTTP offers a
|
||||
universal model for describing, sending, and receiving HTTP messages while
|
||||
Beast.WebSocket provides a complete implementation of the WebSocket protocol.
|
||||
Their design achieves these goals:
|
||||
Beast is a header-only, cross-platform C++ library built on Boost.Asio and
|
||||
Boost, containing two modules implementing widely used network protocols.
|
||||
Beast.HTTP offers a universal model for describing, sending, and receiving
|
||||
HTTP messages while Beast.WebSocket provides a complete implementation of
|
||||
the WebSocket protocol. Their design achieves these goals:
|
||||
|
||||
* [*Symmetry.] Interfaces are role-agnostic; the same interfaces can be
|
||||
used to build clients, servers, or both.
|
||||
@@ -106,8 +106,8 @@ int main()
|
||||
// Normal boost::asio setup
|
||||
std::string const host = "boost.org";
|
||||
boost::asio::io_service ios;
|
||||
boost::asio::ip::tcp::resolver r(ios);
|
||||
boost::asio::ip::tcp::socket sock(ios);
|
||||
boost::asio::ip::tcp::resolver r{ios};
|
||||
boost::asio::ip::tcp::socket sock{ios};
|
||||
boost::asio::connect(sock,
|
||||
r.resolve(boost::asio::ip::tcp::resolver::query{host, "http"}));
|
||||
|
||||
@@ -131,7 +131,7 @@ int main()
|
||||
|
||||
Establish a WebSocket connection, send a message and receive the reply:
|
||||
```
|
||||
#include <beast/to_string.hpp>
|
||||
#include <beast/core/to_string.hpp>
|
||||
#include <beast/websocket.hpp>
|
||||
#include <boost/asio.hpp>
|
||||
#include <iostream>
|
||||
@@ -142,13 +142,13 @@ int main()
|
||||
// Normal boost::asio setup
|
||||
std::string const host = "echo.websocket.org";
|
||||
boost::asio::io_service ios;
|
||||
boost::asio::ip::tcp::resolver r(ios);
|
||||
boost::asio::ip::tcp::socket sock(ios);
|
||||
boost::asio::ip::tcp::resolver r{ios};
|
||||
boost::asio::ip::tcp::socket sock{ios};
|
||||
boost::asio::connect(sock,
|
||||
r.resolve(boost::asio::ip::tcp::resolver::query{host, "80"}));
|
||||
|
||||
// WebSocket connect and send message using beast
|
||||
beast::websocket::stream<boost::asio::ip::tcp::socket&> ws(sock);
|
||||
beast::websocket::stream<boost::asio::ip::tcp::socket&> ws{sock};
|
||||
ws.handshake(host, "/");
|
||||
ws.write(boost::asio::buffer("Hello, world!"));
|
||||
|
||||
@@ -43,6 +43,7 @@
|
||||
<simplelist type="vert" columns="1">
|
||||
<member><link linkend="beast.ref.http__body_max_size">body_max_size</link></member>
|
||||
<member><link linkend="beast.ref.http__headers_max_size">headers_max_size</link></member>
|
||||
<member><link linkend="beast.ref.http__skip_body">skip_body</link></member>
|
||||
</simplelist>
|
||||
<bridgehead renderas="sect3">Type Traits</bridgehead>
|
||||
<simplelist type="vert" columns="1">
|
||||
@@ -85,6 +86,7 @@
|
||||
<member><link linkend="beast.ref.websocket__ping_data">ping_data</link></member>
|
||||
<member><link linkend="beast.ref.websocket__stream">stream</link></member>
|
||||
<member><link linkend="beast.ref.websocket__reason_string">reason_string</link></member>
|
||||
<member><link linkend="beast.ref.websocket__teardown_tag">teardown_tag</link></member>
|
||||
</simplelist>
|
||||
<bridgehead renderas="sect3">Options</bridgehead>
|
||||
<simplelist type="vert" columns="1">
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at http://www.beast.org/LICENSE_1_0.txt)
|
||||
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
-->
|
||||
|
||||
<xsl:output method="text"/>
|
||||
|
||||
@@ -66,7 +66,7 @@ both Boost.Asio and the WebSocket protocol specification described in
|
||||
|
||||
|
||||
|
||||
[section:creating Creating the socket]
|
||||
[section:creation Creation]
|
||||
|
||||
The interface to Beast's WebSocket implementation is a single template
|
||||
class [link beast.ref.websocket__stream `beast::websocket::stream`] which
|
||||
@@ -75,24 +75,40 @@ of [link beast.types.streams.SyncStream [*`SyncReadStream`]] if synchronous
|
||||
operations are performed, or
|
||||
[link beast.types.streams.AsyncStream [*`AsyncStream`]] if asynchronous
|
||||
operations are performed, or both. Arguments supplied during construction are
|
||||
passed to next layer's constructor. Here we declare two websockets which have
|
||||
ownership of the next layer:
|
||||
passed to next layer's constructor. Here we declare a websocket stream over
|
||||
a TCP/IP socket with ownership of the socket:
|
||||
```
|
||||
boost::asio::io_service ios;
|
||||
beast::websocket::stream<boost::asio::ip::tcp::socket> ws(ios);
|
||||
|
||||
boost::asio::ssl::context ctx(boost::asio::ssl::context::sslv23);
|
||||
beast::websocket::stream<
|
||||
boost::asio::ssl::stream<boost::asio::ip::tcp::socket>> wss(ios, ctx);
|
||||
```
|
||||
|
||||
[heading Using SSL]
|
||||
|
||||
To use WebSockets over SSL, choose an SSL stream for the next layer template
|
||||
argument when constructing the stream.
|
||||
```
|
||||
#include <beast/websocket/ssl.hpp>
|
||||
#include <beast/websocket.hpp>
|
||||
#include <boost/asio/ssl.hpp>
|
||||
|
||||
boost::asio::io_service ios;
|
||||
boost::asio::ssl::context ctx(boost::asio::ssl::context::sslv23);
|
||||
beast::websocket::stream<boost::asio::ssl::stream<boost::asio::ip::tcp::socket> ws(ios, ctx);
|
||||
```
|
||||
|
||||
[note
|
||||
When creating websocket stream objects using SSL, it is necessary
|
||||
to include the file `<beast/websocket/ssl.hpp>`.
|
||||
]
|
||||
|
||||
[heading Non-owning references]
|
||||
|
||||
For servers that can handshake in multiple protocols, it may be desired
|
||||
to wrap an object that already exists. This socket can be moved in:
|
||||
```
|
||||
boost::asio::ip::tcp::socket&& sock;
|
||||
...
|
||||
beast::websocket::stream<
|
||||
boost::asio::ip::tcp::socket> ws(std::move(sock));
|
||||
beast::websocket::stream<boost::asio::ip::tcp::socket> ws(std::move(sock));
|
||||
```
|
||||
|
||||
Or, the wrapper can be constructed with a non-owning reference. In
|
||||
@@ -108,8 +124,7 @@ The layer being wrapped can be accessed through the websocket's "next layer",
|
||||
permitting callers to interact directly with its interface.
|
||||
```
|
||||
boost::asio::ssl::context ctx(boost::asio::ssl::context::sslv23);
|
||||
beast::websocket::stream<
|
||||
boost::asio::ssl::stream<boost::asio::ip::tcp::socket>> ws(ios, ctx);
|
||||
beast::websocket::stream<boost::asio::ssl::stream<boost::asio::ip::tcp::socket>> ws(ios, ctx);
|
||||
...
|
||||
ws.next_layer().shutdown(); // ssl::stream shutdown
|
||||
```
|
||||
|
||||
@@ -1,49 +1,52 @@
|
||||
# Part of Beast
|
||||
|
||||
GroupSources(extras/beast beast)
|
||||
GroupSources(extras/beast extras)
|
||||
GroupSources(include/beast beast)
|
||||
|
||||
GroupSources(examples "/")
|
||||
|
||||
add_executable (http-crawl
|
||||
${BEAST_INCLUDES}
|
||||
${EXTRAS_INCLUDES}
|
||||
urls_large_data.hpp
|
||||
urls_large_data.cpp
|
||||
http_crawl.cpp
|
||||
)
|
||||
|
||||
if (NOT WIN32)
|
||||
target_link_libraries(http-crawl ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT})
|
||||
target_link_libraries(http-crawl ${Boost_LIBRARIES} Threads::Threads)
|
||||
endif()
|
||||
|
||||
add_executable (http-server
|
||||
${BEAST_INCLUDES}
|
||||
${EXTRAS_INCLUDES}
|
||||
file_body.hpp
|
||||
mime_type.hpp
|
||||
http_async_server.hpp
|
||||
http_stream.hpp
|
||||
http_stream.ipp
|
||||
http_sync_server.hpp
|
||||
http_server.cpp
|
||||
)
|
||||
|
||||
if (NOT WIN32)
|
||||
target_link_libraries(http-server ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT})
|
||||
target_link_libraries(http-server ${Boost_LIBRARIES} Threads::Threads)
|
||||
endif()
|
||||
|
||||
add_executable (http-example
|
||||
${BEAST_INCLUDES}
|
||||
${EXTRAS_INCLUDES}
|
||||
http_example.cpp
|
||||
)
|
||||
|
||||
if (NOT WIN32)
|
||||
target_link_libraries(http-example ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT})
|
||||
target_link_libraries(http-example ${Boost_LIBRARIES} Threads::Threads)
|
||||
endif()
|
||||
|
||||
add_executable (websocket-example
|
||||
${BEAST_INCLUDES}
|
||||
${EXTRAS_INCLUDES}
|
||||
websocket_example.cpp
|
||||
)
|
||||
|
||||
if (NOT WIN32)
|
||||
target_link_libraries(websocket-example ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT})
|
||||
target_link_libraries(websocket-example ${Boost_LIBRARIES} Threads::Threads)
|
||||
endif()
|
||||
|
||||
@@ -23,7 +23,7 @@ struct file_body
|
||||
|
||||
class writer
|
||||
{
|
||||
std::uint64_t size_;
|
||||
std::uint64_t size_ = 0;
|
||||
std::uint64_t offset_ = 0;
|
||||
std::string const& path_;
|
||||
FILE* file_ = nullptr;
|
||||
|
||||
@@ -9,10 +9,13 @@
|
||||
#define BEAST_EXAMPLE_HTTP_ASYNC_SERVER_H_INCLUDED
|
||||
|
||||
#include "file_body.hpp"
|
||||
#include "http_stream.hpp"
|
||||
#include "mime_type.hpp"
|
||||
|
||||
#include <beast/http.hpp>
|
||||
#include <beast/core/placeholders.hpp>
|
||||
#include <beast/core/streambuf.hpp>
|
||||
#include <boost/asio.hpp>
|
||||
#include <cstddef>
|
||||
#include <cstdio>
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
@@ -32,17 +35,19 @@ class http_async_server
|
||||
using req_type = request_v1<string_body>;
|
||||
using resp_type = response_v1<file_body>;
|
||||
|
||||
std::mutex m_;
|
||||
bool log_ = true;
|
||||
boost::asio::io_service ios_;
|
||||
socket_type sock_;
|
||||
boost::asio::ip::tcp::acceptor acceptor_;
|
||||
socket_type sock_;
|
||||
std::string root_;
|
||||
std::vector<std::thread> thread_;
|
||||
|
||||
public:
|
||||
http_async_server(endpoint_type const& ep,
|
||||
int threads, std::string const& root)
|
||||
: sock_(ios_)
|
||||
, acceptor_(ios_)
|
||||
std::size_t threads, std::string const& root)
|
||||
: acceptor_(ios_)
|
||||
, sock_(ios_)
|
||||
, root_(root)
|
||||
{
|
||||
acceptor_.open(ep.protocol());
|
||||
@@ -53,7 +58,7 @@ public:
|
||||
std::bind(&http_async_server::on_accept, this,
|
||||
beast::asio::placeholders::error));
|
||||
thread_.reserve(threads);
|
||||
for(int i = 0; i < threads; ++i)
|
||||
for(std::size_t i = 0; i < threads; ++i)
|
||||
thread_.emplace_back(
|
||||
[&] { ios_.run(); });
|
||||
}
|
||||
@@ -67,13 +72,124 @@ public:
|
||||
t.join();
|
||||
}
|
||||
|
||||
template<class... Args>
|
||||
void
|
||||
log(Args const&... args)
|
||||
{
|
||||
if(log_)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_);
|
||||
log_args(args...);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
template<class Stream, class Handler,
|
||||
bool isRequest, class Body, class Headers>
|
||||
class write_op
|
||||
{
|
||||
using alloc_type =
|
||||
handler_alloc<char, Handler>;
|
||||
|
||||
struct data
|
||||
{
|
||||
Stream& s;
|
||||
message_v1<isRequest, Body, Headers> m;
|
||||
Handler h;
|
||||
bool cont;
|
||||
|
||||
template<class DeducedHandler>
|
||||
data(DeducedHandler&& h_, Stream& s_,
|
||||
message_v1<isRequest, Body, Headers>&& m_)
|
||||
: s(s_)
|
||||
, m(std::move(m_))
|
||||
, h(std::forward<DeducedHandler>(h_))
|
||||
, cont(boost_asio_handler_cont_helpers::
|
||||
is_continuation(h))
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
std::shared_ptr<data> d_;
|
||||
|
||||
public:
|
||||
write_op(write_op&&) = default;
|
||||
write_op(write_op const&) = default;
|
||||
|
||||
template<class DeducedHandler, class... Args>
|
||||
write_op(DeducedHandler&& h, Stream& s, Args&&... args)
|
||||
: d_(std::allocate_shared<data>(alloc_type{h},
|
||||
std::forward<DeducedHandler>(h), s,
|
||||
std::forward<Args>(args)...))
|
||||
{
|
||||
(*this)(error_code{}, false);
|
||||
}
|
||||
|
||||
void
|
||||
operator()(error_code ec, bool again = true)
|
||||
{
|
||||
auto& d = *d_;
|
||||
d.cont = d.cont || again;
|
||||
if(! again)
|
||||
{
|
||||
beast::http::async_write(d.s, d.m, std::move(*this));
|
||||
return;
|
||||
}
|
||||
d.h(ec);
|
||||
}
|
||||
|
||||
friend
|
||||
void* asio_handler_allocate(
|
||||
std::size_t size, write_op* op)
|
||||
{
|
||||
return boost_asio_handler_alloc_helpers::
|
||||
allocate(size, op->d_->h);
|
||||
}
|
||||
|
||||
friend
|
||||
void asio_handler_deallocate(
|
||||
void* p, std::size_t size, write_op* op)
|
||||
{
|
||||
return boost_asio_handler_alloc_helpers::
|
||||
deallocate(p, size, op->d_->h);
|
||||
}
|
||||
|
||||
friend
|
||||
bool asio_handler_is_continuation(write_op* op)
|
||||
{
|
||||
return op->d_->cont;
|
||||
}
|
||||
|
||||
template<class Function>
|
||||
friend
|
||||
void asio_handler_invoke(Function&& f, write_op* op)
|
||||
{
|
||||
return boost_asio_handler_invoke_helpers::
|
||||
invoke(f, op->d_->h);
|
||||
}
|
||||
};
|
||||
|
||||
template<class Stream,
|
||||
bool isRequest, class Body, class Headers,
|
||||
class DeducedHandler>
|
||||
static
|
||||
void
|
||||
async_write(Stream& stream, message_v1<
|
||||
isRequest, Body, Headers>&& msg,
|
||||
DeducedHandler&& handler)
|
||||
{
|
||||
write_op<Stream, typename std::decay<DeducedHandler>::type,
|
||||
isRequest, Body, Headers>{std::forward<DeducedHandler>(
|
||||
handler), stream, std::move(msg)};
|
||||
}
|
||||
|
||||
class peer : public std::enable_shared_from_this<peer>
|
||||
{
|
||||
int id_;
|
||||
stream<socket_type> stream_;
|
||||
streambuf sb_;
|
||||
socket_type sock_;
|
||||
http_async_server& server_;
|
||||
boost::asio::io_service::strand strand_;
|
||||
std::string root_;
|
||||
req_type req_;
|
||||
|
||||
public:
|
||||
@@ -82,16 +198,22 @@ private:
|
||||
peer& operator=(peer&&) = delete;
|
||||
peer& operator=(peer const&) = delete;
|
||||
|
||||
explicit
|
||||
peer(socket_type&& sock, std::string const& root)
|
||||
: stream_(std::move(sock))
|
||||
, strand_(stream_.get_io_service())
|
||||
, root_(root)
|
||||
peer(socket_type&& sock, http_async_server& server)
|
||||
: sock_(std::move(sock))
|
||||
, server_(server)
|
||||
, strand_(sock_.get_io_service())
|
||||
{
|
||||
static int n = 0;
|
||||
id_ = ++n;
|
||||
}
|
||||
|
||||
void
|
||||
fail(error_code ec, std::string what)
|
||||
{
|
||||
if(ec != boost::asio::error::operation_aborted)
|
||||
server_.log("#", id_, " ", what, ": ", ec.message(), "\n");
|
||||
}
|
||||
|
||||
void run()
|
||||
{
|
||||
do_read();
|
||||
@@ -99,43 +221,58 @@ private:
|
||||
|
||||
void do_read()
|
||||
{
|
||||
stream_.async_read(req_, strand_.wrap(
|
||||
async_read(sock_, sb_, req_, strand_.wrap(
|
||||
std::bind(&peer::on_read, shared_from_this(),
|
||||
asio::placeholders::error)));
|
||||
}
|
||||
|
||||
void on_read(error_code ec)
|
||||
void on_read(error_code const& ec)
|
||||
{
|
||||
if(ec)
|
||||
return fail(ec, "read");
|
||||
do_read();
|
||||
auto path = req_.url;
|
||||
if(path == "/")
|
||||
path = "/index.html";
|
||||
path = root_ + path;
|
||||
path = server_.root_ + path;
|
||||
if(! boost::filesystem::exists(path))
|
||||
{
|
||||
response_v1<string_body> resp;
|
||||
resp.status = 404;
|
||||
resp.reason = "Not Found";
|
||||
resp.version = req_.version;
|
||||
resp.headers.replace("Server", "http_async_server");
|
||||
resp.body = "The file '" + path + "' was not found";
|
||||
prepare(resp);
|
||||
stream_.async_write(std::move(resp),
|
||||
response_v1<string_body> res;
|
||||
res.status = 404;
|
||||
res.reason = "Not Found";
|
||||
res.version = req_.version;
|
||||
res.headers.insert("Server", "http_async_server");
|
||||
res.headers.insert("Content-Type", "text/html");
|
||||
res.body = "The file '" + path + "' was not found";
|
||||
prepare(res);
|
||||
async_write(sock_, std::move(res),
|
||||
std::bind(&peer::on_write, shared_from_this(),
|
||||
asio::placeholders::error));
|
||||
return;
|
||||
}
|
||||
resp_type resp;
|
||||
resp.status = 200;
|
||||
resp.reason = "OK";
|
||||
resp.version = req_.version;
|
||||
resp.headers.replace("Server", "http_async_server");
|
||||
resp.headers.replace("Content-Type", "text/html");
|
||||
resp.body = path;
|
||||
prepare(resp);
|
||||
stream_.async_write(std::move(resp),
|
||||
resp_type res;
|
||||
res.status = 200;
|
||||
res.reason = "OK";
|
||||
res.version = req_.version;
|
||||
res.headers.insert("Server", "http_async_server");
|
||||
res.headers.insert("Content-Type", mime_type(path));
|
||||
res.body = path;
|
||||
try
|
||||
{
|
||||
prepare(res);
|
||||
}
|
||||
catch(std::exception const& e)
|
||||
{
|
||||
res = {};
|
||||
res.status = 500;
|
||||
res.reason = "Internal Error";
|
||||
res.version = req_.version;
|
||||
res.headers.insert("Server", "http_async_server");
|
||||
res.headers.insert("Content-Type", "text/html");
|
||||
res.body =
|
||||
std::string{"An internal error occurred"} + e.what();
|
||||
prepare(res);
|
||||
}
|
||||
async_write(sock_, std::move(res),
|
||||
std::bind(&peer::on_write, shared_from_this(),
|
||||
asio::placeholders::error));
|
||||
}
|
||||
@@ -144,36 +281,27 @@ private:
|
||||
{
|
||||
if(ec)
|
||||
fail(ec, "write");
|
||||
}
|
||||
|
||||
private:
|
||||
void
|
||||
fail(error_code ec, std::string what)
|
||||
{
|
||||
if(ec != boost::asio::error::operation_aborted)
|
||||
{
|
||||
std::cerr <<
|
||||
"#" << std::to_string(id_) << " " <<
|
||||
what << ": " << ec.message() << std::endl;
|
||||
}
|
||||
do_read();
|
||||
}
|
||||
};
|
||||
|
||||
void
|
||||
fail(error_code ec, std::string what)
|
||||
log_args()
|
||||
{
|
||||
std::cerr <<
|
||||
what << ": " << ec.message() << std::endl;
|
||||
}
|
||||
|
||||
template<class Arg, class... Args>
|
||||
void
|
||||
log_args(Arg const& arg, Args const&... args)
|
||||
{
|
||||
std::cerr << arg;
|
||||
log_args(args...);
|
||||
}
|
||||
|
||||
void
|
||||
maybe_throw(error_code ec, std::string what)
|
||||
fail(error_code ec, std::string what)
|
||||
{
|
||||
if(ec)
|
||||
{
|
||||
fail(ec, what);
|
||||
throw ec;
|
||||
}
|
||||
log(what, ": ", ec.message(), "\n");
|
||||
}
|
||||
|
||||
void
|
||||
@@ -181,12 +309,13 @@ private:
|
||||
{
|
||||
if(! acceptor_.is_open())
|
||||
return;
|
||||
maybe_throw(ec, "accept");
|
||||
if(ec)
|
||||
return fail(ec, "accept");
|
||||
socket_type sock(std::move(sock_));
|
||||
acceptor_.async_accept(sock_,
|
||||
std::bind(&http_async_server::on_accept, this,
|
||||
asio::placeholders::error));
|
||||
std::make_shared<peer>(std::move(sock), root_)->run();
|
||||
std::make_shared<peer>(std::move(sock), *this)->run();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -5,9 +5,10 @@
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#include "http_stream.hpp"
|
||||
#include "urls_large_data.hpp"
|
||||
|
||||
#include <beast/core/streambuf.hpp>
|
||||
#include <beast/http.hpp>
|
||||
#include <boost/asio.hpp>
|
||||
#include <iostream>
|
||||
|
||||
@@ -31,9 +32,9 @@ int main(int, char const*[])
|
||||
ip::tcp::resolver r(ios);
|
||||
auto it = r.resolve(
|
||||
ip::tcp::resolver::query{host, "http"});
|
||||
stream<ip::tcp::socket> hs(ios);
|
||||
connect(hs.lowest_layer(), it);
|
||||
auto ep = hs.lowest_layer().remote_endpoint();
|
||||
ip::tcp::socket sock(ios);
|
||||
connect(sock, it);
|
||||
auto ep = sock.remote_endpoint();
|
||||
request_v1<empty_body> req;
|
||||
req.method = "GET";
|
||||
req.url = "/";
|
||||
@@ -42,10 +43,11 @@ int main(int, char const*[])
|
||||
std::string(":") + std::to_string(ep.port()));
|
||||
req.headers.insert("User-Agent", "beast/http");
|
||||
prepare(req);
|
||||
hs.write(req);
|
||||
response_v1<string_body> resp;
|
||||
hs.read(resp);
|
||||
std::cout << resp;
|
||||
write(sock, req);
|
||||
response_v1<string_body> res;
|
||||
streambuf sb;
|
||||
beast::http::read(sock, sb, res);
|
||||
std::cout << res;
|
||||
}
|
||||
catch(boost::system::system_error const& ec)
|
||||
{
|
||||
|
||||
@@ -15,8 +15,8 @@ int main()
|
||||
// Normal boost::asio setup
|
||||
std::string const host = "boost.org";
|
||||
boost::asio::io_service ios;
|
||||
boost::asio::ip::tcp::resolver r(ios);
|
||||
boost::asio::ip::tcp::socket sock(ios);
|
||||
boost::asio::ip::tcp::resolver r{ios};
|
||||
boost::asio::ip::tcp::socket sock{ios};
|
||||
boost::asio::connect(sock,
|
||||
r.resolve(boost::asio::ip::tcp::resolver::query{host, "http"}));
|
||||
|
||||
|
||||
@@ -57,8 +57,13 @@ int main(int ac, char const* av[])
|
||||
endpoint_type ep{address_type::from_string(ip), port};
|
||||
|
||||
if(sync)
|
||||
{
|
||||
http_sync_server server(ep, root);
|
||||
beast::test::sig_wait();
|
||||
}
|
||||
else
|
||||
{
|
||||
http_async_server server(ep, threads, root);
|
||||
beast::test::sig_wait();
|
||||
beast::test::sig_wait();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,480 +0,0 @@
|
||||
//
|
||||
// Copyright (c) 2013-2016 Vinnie Falco (vinnie dot falco at gmail dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#ifndef BEAST_HTTP_STREAM_H_INCLUDED
|
||||
#define BEAST_HTTP_STREAM_H_INCLUDED
|
||||
|
||||
#include <beast/core/async_completion.hpp>
|
||||
#include <beast/core/basic_streambuf.hpp>
|
||||
#include <beast/http.hpp>
|
||||
#include <boost/asio/io_service.hpp>
|
||||
#include <boost/intrusive/list.hpp>
|
||||
#include <memory>
|
||||
|
||||
namespace beast {
|
||||
namespace http {
|
||||
|
||||
namespace detail {
|
||||
|
||||
class stream_base
|
||||
{
|
||||
protected:
|
||||
struct op
|
||||
: boost::intrusive::list_base_hook<
|
||||
boost::intrusive::link_mode<
|
||||
boost::intrusive::normal_link>>
|
||||
{
|
||||
virtual ~op() = default;
|
||||
virtual void operator()() = 0;
|
||||
virtual void cancel() = 0;
|
||||
};
|
||||
|
||||
using op_list = typename boost::intrusive::make_list<
|
||||
op, boost::intrusive::constant_time_size<false>>::type;
|
||||
|
||||
op_list wr_q_;
|
||||
bool wr_active_ = false;
|
||||
};
|
||||
|
||||
} // detail
|
||||
|
||||
/** Provides message-oriented functionality using HTTP.
|
||||
|
||||
The stream class template provides asynchronous and blocking
|
||||
message-oriented functionality necessary for clients and servers
|
||||
to utilize the HTTP protocol.
|
||||
|
||||
@par Thread Safety
|
||||
@e Distinct @e objects: Safe.@n
|
||||
@e Shared @e objects: Unsafe. The application must ensure that
|
||||
all asynchronous operations are performed within the same
|
||||
implicit or explicit strand.
|
||||
|
||||
@par Example
|
||||
|
||||
To use the class template with an `ip::tcp::socket`, you would write:
|
||||
|
||||
@code
|
||||
http::stream<ip::tcp::socket> hs(io_service);
|
||||
@endcode
|
||||
Alternatively, you can write:
|
||||
@code
|
||||
ip::tcp::socket sock(io_service);
|
||||
http::stream<ip::tcp::socket&> hs(sock);
|
||||
@endcode
|
||||
|
||||
@note A stream object must not be destroyed while there are
|
||||
pending asynchronous operations associated with it.
|
||||
|
||||
@par Concepts
|
||||
AsyncReadStream, AsyncWriteStream, Stream, SyncReadStream, SyncWriteStream.
|
||||
*/
|
||||
template<class NextLayer,
|
||||
class Allocator = std::allocator<char>>
|
||||
class stream : public detail::stream_base
|
||||
{
|
||||
NextLayer next_layer_;
|
||||
basic_streambuf<Allocator> rd_buf_;
|
||||
|
||||
public:
|
||||
/// The type of the next layer.
|
||||
using next_layer_type =
|
||||
typename std::remove_reference<NextLayer>::type;
|
||||
|
||||
/// The type of the lowest layer.
|
||||
using lowest_layer_type =
|
||||
typename next_layer_type::lowest_layer_type;
|
||||
|
||||
/// The type of endpoint of the lowest layer.
|
||||
using endpoint_type =
|
||||
typename lowest_layer_type::endpoint_type;
|
||||
|
||||
/// The protocol of the next layer.
|
||||
using protocol_type =
|
||||
typename lowest_layer_type::protocol_type;
|
||||
|
||||
/// The type of resolver of the next layer.
|
||||
using resolver_type =
|
||||
typename protocol_type::resolver;
|
||||
|
||||
/** Destructor.
|
||||
|
||||
@note A stream object must not be destroyed while there
|
||||
are pending asynchronous operations associated with it.
|
||||
*/
|
||||
~stream();
|
||||
|
||||
/** Move constructor.
|
||||
|
||||
Undefined behavior if operations are active or pending.
|
||||
*/
|
||||
stream(stream&&) = default;
|
||||
|
||||
/** Move assignment.
|
||||
|
||||
Undefined behavior if operations are active or pending.
|
||||
*/
|
||||
stream& operator=(stream&&) = default;
|
||||
|
||||
/** Construct a HTTP stream.
|
||||
|
||||
This constructor creates a HTTP stream and initialises
|
||||
the next layer.
|
||||
|
||||
@throws Any exceptions thrown by the Stream constructor.
|
||||
|
||||
@param args The arguments to be passed to initialise the
|
||||
next layer. The arguments are forwarded to the next layer's
|
||||
constructor.
|
||||
*/
|
||||
template<class... Args>
|
||||
explicit
|
||||
stream(Args&&... args);
|
||||
|
||||
/** Get the io_service associated with the stream.
|
||||
|
||||
This function may be used to obtain the io_service object
|
||||
that the stream uses to dispatch handlers for asynchronous
|
||||
operations.
|
||||
|
||||
@return A reference to the io_service object that the stream
|
||||
will use to dispatch handlers. Ownership is not transferred
|
||||
to the caller.
|
||||
*/
|
||||
boost::asio::io_service&
|
||||
get_io_service()
|
||||
{
|
||||
return next_layer_.lowest_layer().get_io_service();
|
||||
}
|
||||
|
||||
/** Get a reference to the next layer.
|
||||
|
||||
This function returns a reference to the next layer
|
||||
in a stack of stream layers.
|
||||
|
||||
@return A reference to the next layer in the stack of
|
||||
stream layers. Ownership is not transferred to the caller.
|
||||
*/
|
||||
next_layer_type&
|
||||
next_layer()
|
||||
{
|
||||
return next_layer_;
|
||||
}
|
||||
|
||||
/** Get a reference to the next layer.
|
||||
|
||||
This function returns a reference to the next layer in a
|
||||
stack of stream layers.
|
||||
|
||||
@return A reference to the next layer in the stack of
|
||||
stream layers. Ownership is not transferred to the caller.
|
||||
*/
|
||||
next_layer_type const&
|
||||
next_layer() const
|
||||
{
|
||||
return next_layer_;
|
||||
}
|
||||
|
||||
/** Get a reference to the lowest layer.
|
||||
|
||||
This function returns a reference to the lowest layer
|
||||
in a stack of stream layers.
|
||||
|
||||
@return A reference to the lowest layer in the stack of
|
||||
stream layers. Ownership is not transferred to the caller.
|
||||
*/
|
||||
lowest_layer_type&
|
||||
lowest_layer()
|
||||
{
|
||||
return next_layer_.lowest_layer();
|
||||
}
|
||||
|
||||
/** Get a reference to the lowest layer.
|
||||
|
||||
This function returns a reference to the lowest layer
|
||||
in a stack of stream layers.
|
||||
|
||||
@return A reference to the lowest layer in the stack of
|
||||
stream layers. Ownership is not transferred to the caller.
|
||||
*/
|
||||
lowest_layer_type const&
|
||||
lowest_layer() const
|
||||
{
|
||||
return next_layer_.lowest_layer();
|
||||
}
|
||||
|
||||
/** Cancel pending operations.
|
||||
|
||||
This will cancel all of the asynchronous operations pending,
|
||||
including pipelined writes that have not been started. Handlers for
|
||||
canceled writes will be called with
|
||||
`boost::asio::error::operation_aborted`.
|
||||
|
||||
@throws boost::system::system_error Thrown on failure.
|
||||
*/
|
||||
void
|
||||
cancel()
|
||||
{
|
||||
error_code ec;
|
||||
cancel(ec);
|
||||
if(ec)
|
||||
throw system_error{ec};
|
||||
}
|
||||
|
||||
/** Cancel pending operations.
|
||||
|
||||
This will cancel all of the asynchronous operations pending,
|
||||
including pipelined writes that have not been started. Handlers for
|
||||
canceled writes will be called with
|
||||
`boost::asio::error::operation_aborted`.
|
||||
|
||||
@param ec Set to indicate what error occurred, if any.
|
||||
*/
|
||||
void
|
||||
cancel(error_code& ec);
|
||||
|
||||
/** Read a HTTP message from the stream.
|
||||
|
||||
This function is used to read a single HTTP message from the stream.
|
||||
The call will block until one of the followign conditions is true:
|
||||
|
||||
@li A message has been read.
|
||||
|
||||
@li An error occurred.
|
||||
|
||||
The operation is implemented in terms of zero or more calls to the
|
||||
next layer's `read_some` function.
|
||||
|
||||
@param msg An object used to store the message. The previous
|
||||
contents of the object will be overwritten.
|
||||
|
||||
@throws boost::system::system_error Thrown on failure.
|
||||
*/
|
||||
template<bool isRequest, class Body, class Headers>
|
||||
void
|
||||
read(message_v1<isRequest, Body, Headers>& msg)
|
||||
{
|
||||
error_code ec;
|
||||
read(msg, ec);
|
||||
if(ec)
|
||||
throw system_error{ec};
|
||||
}
|
||||
|
||||
/** Read a HTTP message from the stream.
|
||||
|
||||
This function is used to read a single HTTP message from the stream.
|
||||
The call will block until one of the followign conditions is true:
|
||||
|
||||
@li A message has been read.
|
||||
|
||||
@li An error occurred.
|
||||
|
||||
The operation is implemented in terms of zero or more calls to the
|
||||
next layer's `read_some` function.
|
||||
|
||||
@param msg An object used to store the message. The previous
|
||||
contents of the object will be overwritten.
|
||||
|
||||
@param ec Set to indicate what error occurred, if any.
|
||||
*/
|
||||
template<bool isRequest, class Body, class Headers>
|
||||
void
|
||||
read(message_v1<isRequest, Body, Headers>& msg,
|
||||
error_code& ec);
|
||||
|
||||
/** Start reading a HTTP message from the stream asynchronously.
|
||||
|
||||
This function is used to asynchronously read a single HTTP message
|
||||
from the stream. The function call always returns immediately. The
|
||||
asynchronous operation will continue until one of the following
|
||||
conditions is true:
|
||||
|
||||
@li The message has been written.
|
||||
|
||||
@li An error occurred.
|
||||
|
||||
This operation is implemented in terms of zero or more calls to the
|
||||
next layer's async_read_some function, and is known as a composed
|
||||
operation. The program must ensure that the stream performs no other
|
||||
read operations or any other composed operations that perform reads
|
||||
until this operation completes.
|
||||
|
||||
@param msg An object used to store the message. The previous
|
||||
contents of the object will be overwritten. Ownership of the message
|
||||
is not transferred; the caller must guarantee that the object remains
|
||||
valid until the handler is called.
|
||||
|
||||
@param handler The handler to be called when the request completes.
|
||||
Copies will be made of the handler as required. The equivalent
|
||||
function signature of the handler must be:
|
||||
@code void handler(
|
||||
error_code const& error // result of operation
|
||||
); @endcode
|
||||
Regardless of whether the asynchronous operation completes
|
||||
immediately or not, the handler will not be invoked from within
|
||||
this function. Invocation of the handler will be performed in a
|
||||
manner equivalent to using boost::asio::io_service::post().
|
||||
*/
|
||||
template<bool isRequest, class Body, class Headers,
|
||||
class ReadHandler>
|
||||
#if GENERATING_DOCS
|
||||
void_or_deduced
|
||||
#else
|
||||
typename async_completion<
|
||||
ReadHandler, void(error_code)>::result_type
|
||||
#endif
|
||||
async_read(message_v1<isRequest, Body, Headers>& msg,
|
||||
ReadHandler&& handler);
|
||||
|
||||
/** Write a HTTP message to the stream.
|
||||
|
||||
This function is used to write a single HTTP message to the
|
||||
stream. The call will block until one of the following conditions
|
||||
is true:
|
||||
|
||||
@li The entire message is sent.
|
||||
|
||||
@li An error occurred.
|
||||
|
||||
If the semantics of the message require that the connection is
|
||||
closed to indicate the end of the content body,
|
||||
`boost::asio::error::eof` is thrown after the message is sent.
|
||||
successfuly. The caller is responsible for actually closing the
|
||||
connection. For regular TCP/IP streams this means shutting down the
|
||||
send side, while SSL streams may call the SSL shutdown function.
|
||||
|
||||
@param msg The message to send.
|
||||
|
||||
@throws boost::system::system_error Thrown on failure.
|
||||
*/
|
||||
template<bool isRequest, class Body, class Headers>
|
||||
void
|
||||
write(message_v1<isRequest, Body, Headers> const& msg)
|
||||
{
|
||||
error_code ec;
|
||||
write(msg, ec);
|
||||
if(ec)
|
||||
throw system_error{ec};
|
||||
}
|
||||
|
||||
/** Write a HTTP message to the stream.
|
||||
|
||||
This function is used to write a single HTTP message to the
|
||||
stream. The call will block until one of the following conditions
|
||||
is true:
|
||||
|
||||
@li The entire message is sent.
|
||||
|
||||
@li An error occurred.
|
||||
|
||||
If the semantics of the message require that the connection is
|
||||
closed to indicate the end of the content body,
|
||||
`boost::asio::error::eof` is returned after the message is sent.
|
||||
successfuly. The caller is responsible for actually closing the
|
||||
connection. For regular TCP/IP streams this means shutting down the
|
||||
send side, while SSL streams may call the SSL shutdown function.
|
||||
|
||||
@param msg The message to send.
|
||||
|
||||
@param ec Set to the error, if any occurred.
|
||||
*/
|
||||
template<bool isRequest, class Body, class Headers>
|
||||
void
|
||||
write(message_v1<isRequest, Body, Headers> const& msg,
|
||||
error_code& ec);
|
||||
|
||||
/** Start pipelining a HTTP message to the stream asynchronously.
|
||||
|
||||
This function is used to queue a message to be sent on the stream.
|
||||
Unlike the free function, this version will place the message on an
|
||||
outgoing message queue if there is already a write pending.
|
||||
|
||||
If the semantics of the message require that the connection is
|
||||
closed to indicate the end of the content body, the handler
|
||||
is called with the error `boost::asio::error::eof` after the message
|
||||
has been sent successfully. The caller is responsible for actually
|
||||
closing the connection. For regular TCP/IP streams this means
|
||||
shutting down the send side, while SSL streams may call the SSL
|
||||
`async_shutdown` function.
|
||||
|
||||
@param msg The message to send. A copy of the message will be made.
|
||||
|
||||
@param handler The handler to be called when the request completes.
|
||||
Copies will be made of the handler as required. The equivalent
|
||||
function signature of the handler must be:
|
||||
@code void handler(
|
||||
error_code const& error // result of operation
|
||||
); @endcode
|
||||
Regardless of whether the asynchronous operation completes
|
||||
immediately or not, the handler will not be invoked from within
|
||||
this function. Invocation of the handler will be performed in a
|
||||
manner equivalent to using boost::asio::io_service::post().
|
||||
*/
|
||||
template<bool isRequest, class Body, class Headers,
|
||||
class WriteHandler>
|
||||
#if GENERATING_DOCS
|
||||
void_or_deduced
|
||||
#else
|
||||
typename async_completion<
|
||||
WriteHandler, void(error_code)>::result_type
|
||||
#endif
|
||||
async_write(message_v1<isRequest, Body, Headers> const& msg,
|
||||
WriteHandler&& handler);
|
||||
|
||||
/** Start pipelining a HTTP message to the stream asynchronously.
|
||||
|
||||
This function is used to queue a message to be sent on the stream.
|
||||
Unlike the free function, this version will place the message on an
|
||||
outgoing message queue if there is already a write pending.
|
||||
|
||||
If the semantics of the message require that the connection is
|
||||
closed to indicate the end of the content body, the handler
|
||||
is called with the error boost::asio::error::eof. The caller is
|
||||
responsible for actually closing the connection. For regular
|
||||
TCP/IP streams this means shutting down the send side, while SSL
|
||||
streams may call the SSL async_shutdown function.
|
||||
|
||||
@param msg The message to send. Ownership of the message, which
|
||||
must be movable, is transferred to the implementation. The message
|
||||
will not be destroyed until the asynchronous operation completes.
|
||||
|
||||
@param handler The handler to be called when the request completes.
|
||||
Copies will be made of the handler as required. The equivalent
|
||||
function signature of the handler must be:
|
||||
@code void handler(
|
||||
error_code const& error // result of operation
|
||||
); @endcode
|
||||
Regardless of whether the asynchronous operation completes
|
||||
immediately or not, the handler will not be invoked from within
|
||||
this function. Invocation of the handler will be performed in a
|
||||
manner equivalent to using boost::asio::io_service::post().
|
||||
*/
|
||||
template<bool isRequest, class Body, class Headers,
|
||||
class WriteHandler>
|
||||
#if GENERATING_DOCS
|
||||
void_or_deduced
|
||||
#else
|
||||
typename async_completion<
|
||||
WriteHandler, void(error_code)>::result_type
|
||||
#endif
|
||||
async_write(message_v1<isRequest, Body, Headers>&& msg,
|
||||
WriteHandler&& handler);
|
||||
|
||||
private:
|
||||
template<bool, class, class, class> class read_op;
|
||||
template<bool, class, class, class> class write_op;
|
||||
|
||||
void
|
||||
cancel_all();
|
||||
};
|
||||
|
||||
} // http
|
||||
} // beast
|
||||
|
||||
#include "http_stream.ipp"
|
||||
|
||||
#endif
|
||||
@@ -1,412 +0,0 @@
|
||||
//
|
||||
// Copyright (c) 2013-2016 Vinnie Falco (vinnie dot falco at gmail dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#ifndef BEAST_HTTP_STREAM_IPP_INCLUDED
|
||||
#define BEAST_HTTP_STREAM_IPP_INCLUDED
|
||||
|
||||
#include <beast/core/bind_handler.hpp>
|
||||
#include <beast/core/handler_alloc.hpp>
|
||||
#include <beast/http/message_v1.hpp>
|
||||
#include <beast/http/read.hpp>
|
||||
#include <beast/http/write.hpp>
|
||||
#include <cassert>
|
||||
|
||||
namespace beast {
|
||||
namespace http {
|
||||
|
||||
template<class NextLayer, class Allocator>
|
||||
template<bool isRequest, class Body, class Headers,
|
||||
class Handler>
|
||||
class stream<NextLayer, Allocator>::read_op
|
||||
{
|
||||
using alloc_type =
|
||||
handler_alloc<char, Handler>;
|
||||
|
||||
struct data
|
||||
{
|
||||
stream<NextLayer>& s;
|
||||
message_v1<isRequest, Body, Headers>& m;
|
||||
Handler h;
|
||||
bool cont;
|
||||
int state = 0;
|
||||
|
||||
template<class DeducedHandler>
|
||||
data(DeducedHandler&& h_, stream<NextLayer>& s_,
|
||||
message_v1<isRequest, Body, Headers>& m_)
|
||||
: s(s_)
|
||||
, m(m_)
|
||||
, h(std::forward<DeducedHandler>(h_))
|
||||
, cont(boost_asio_handler_cont_helpers::
|
||||
is_continuation(h))
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
std::shared_ptr<data> d_;
|
||||
|
||||
public:
|
||||
read_op(read_op&&) = default;
|
||||
read_op(read_op const&) = default;
|
||||
|
||||
template<class DeducedHandler, class... Args>
|
||||
read_op(DeducedHandler&& h,
|
||||
stream<NextLayer>& s, Args&&... args)
|
||||
: d_(std::allocate_shared<data>(alloc_type{h},
|
||||
std::forward<DeducedHandler>(h), s,
|
||||
std::forward<Args>(args)...))
|
||||
{
|
||||
(*this)(error_code{}, false);
|
||||
}
|
||||
|
||||
void operator()(error_code const& ec, bool again = true);
|
||||
|
||||
friend
|
||||
void* asio_handler_allocate(
|
||||
std::size_t size, read_op* op)
|
||||
{
|
||||
return boost_asio_handler_alloc_helpers::
|
||||
allocate(size, op->d_->h);
|
||||
}
|
||||
|
||||
friend
|
||||
void asio_handler_deallocate(
|
||||
void* p, std::size_t size, read_op* op)
|
||||
{
|
||||
return boost_asio_handler_alloc_helpers::
|
||||
deallocate(p, size, op->d_->h);
|
||||
}
|
||||
|
||||
friend
|
||||
bool asio_handler_is_continuation(read_op* op)
|
||||
{
|
||||
return op->d_->cont;
|
||||
}
|
||||
|
||||
template <class Function>
|
||||
friend
|
||||
void asio_handler_invoke(Function&& f, read_op* op)
|
||||
{
|
||||
return boost_asio_handler_invoke_helpers::
|
||||
invoke(f, op->d_->h);
|
||||
}
|
||||
};
|
||||
|
||||
template<class NextLayer, class Allocator>
|
||||
template<bool isRequest, class Body, class Headers, class Handler>
|
||||
void
|
||||
stream<NextLayer, Allocator>::
|
||||
read_op<isRequest, Body, Headers, Handler>::
|
||||
operator()(error_code const& ec, bool again)
|
||||
{
|
||||
auto& d = *d_;
|
||||
d.cont = d.cont || again;
|
||||
while(! ec && d.state != 99)
|
||||
{
|
||||
switch(d.state)
|
||||
{
|
||||
case 0:
|
||||
d.state = 99;
|
||||
beast::http::async_read(d.s.next_layer_,
|
||||
d.s.rd_buf_, d.m, std::move(*this));
|
||||
return;
|
||||
}
|
||||
}
|
||||
d.h(ec);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template<class NextLayer, class Allocator>
|
||||
template<bool isRequest, class Body, class Headers,
|
||||
class Handler>
|
||||
class stream<NextLayer, Allocator>::write_op : public op
|
||||
{
|
||||
using alloc_type =
|
||||
handler_alloc<char, Handler>;
|
||||
|
||||
struct data
|
||||
{
|
||||
stream<NextLayer>& s;
|
||||
message_v1<isRequest, Body, Headers> m;
|
||||
Handler h;
|
||||
bool cont;
|
||||
int state = 0;
|
||||
|
||||
template<class DeducedHandler>
|
||||
data(DeducedHandler&& h_, stream<NextLayer>& s_,
|
||||
message_v1<isRequest, Body, Headers> const& m_,
|
||||
bool cont_)
|
||||
: s(s_)
|
||||
, m(m_)
|
||||
, h(std::forward<DeducedHandler>(h_))
|
||||
, cont(cont_)
|
||||
{
|
||||
}
|
||||
|
||||
template<class DeducedHandler>
|
||||
data(DeducedHandler&& h_, stream<NextLayer>& s_,
|
||||
message_v1<isRequest, Body, Headers>&& m_,
|
||||
bool cont_)
|
||||
: s(s_)
|
||||
, m(std::move(m_))
|
||||
, h(std::forward<DeducedHandler>(h_))
|
||||
, cont(cont_)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
std::shared_ptr<data> d_;
|
||||
|
||||
public:
|
||||
write_op(write_op&&) = default;
|
||||
write_op(write_op const&) = default;
|
||||
|
||||
template<class DeducedHandler, class... Args>
|
||||
write_op(DeducedHandler&& h,
|
||||
stream<NextLayer>& s, Args&&... args)
|
||||
: d_(std::allocate_shared<data>(alloc_type{h},
|
||||
std::forward<DeducedHandler>(h), s,
|
||||
std::forward<Args>(args)...))
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
operator()() override
|
||||
{
|
||||
(*this)(error_code{}, false);
|
||||
}
|
||||
|
||||
void cancel() override;
|
||||
|
||||
void operator()(error_code const& ec, bool again = true);
|
||||
|
||||
friend
|
||||
void* asio_handler_allocate(
|
||||
std::size_t size, write_op* op)
|
||||
{
|
||||
return boost_asio_handler_alloc_helpers::
|
||||
allocate(size, op->d_->h);
|
||||
}
|
||||
|
||||
friend
|
||||
void asio_handler_deallocate(
|
||||
void* p, std::size_t size, write_op* op)
|
||||
{
|
||||
return boost_asio_handler_alloc_helpers::
|
||||
deallocate(p, size, op->d_->h);
|
||||
}
|
||||
|
||||
friend
|
||||
bool asio_handler_is_continuation(write_op* op)
|
||||
{
|
||||
return op->d_->cont;
|
||||
}
|
||||
|
||||
template <class Function>
|
||||
friend
|
||||
void asio_handler_invoke(Function&& f, write_op* op)
|
||||
{
|
||||
return boost_asio_handler_invoke_helpers::
|
||||
invoke(f, op->d_->h);
|
||||
}
|
||||
};
|
||||
|
||||
template<class NextLayer, class Allocator>
|
||||
template<bool isRequest, class Body, class Headers, class Handler>
|
||||
void
|
||||
stream<NextLayer, Allocator>::
|
||||
write_op<isRequest, Body, Headers, Handler>::
|
||||
cancel()
|
||||
{
|
||||
auto& d = *d_;
|
||||
d.s.get_io_service().post(
|
||||
bind_handler(std::move(*this),
|
||||
boost::asio::error::operation_aborted));
|
||||
}
|
||||
|
||||
template<class NextLayer, class Allocator>
|
||||
template<bool isRequest, class Body, class Headers, class Handler>
|
||||
void
|
||||
stream<NextLayer, Allocator>::
|
||||
write_op<isRequest, Body, Headers, Handler>::
|
||||
operator()(error_code const& ec, bool again)
|
||||
{
|
||||
auto& d = *d_;
|
||||
d.cont = d.cont || again;
|
||||
while(! ec && d.state != 99)
|
||||
{
|
||||
switch(d.state)
|
||||
{
|
||||
case 0:
|
||||
d.state = 99;
|
||||
beast::http::async_write(d.s.next_layer_,
|
||||
d.m, std::move(*this));
|
||||
return;
|
||||
}
|
||||
}
|
||||
d.h(ec);
|
||||
if(! d.s.wr_q_.empty())
|
||||
{
|
||||
auto& op = d.s.wr_q_.front();
|
||||
op();
|
||||
// VFALCO Use allocator
|
||||
delete &op;
|
||||
d.s.wr_q_.pop_front();
|
||||
}
|
||||
else
|
||||
{
|
||||
d.s.wr_active_ = false;
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template<class NextLayer, class Allocator>
|
||||
stream<NextLayer, Allocator>::
|
||||
~stream()
|
||||
{
|
||||
// Can't destroy with pending operations!
|
||||
assert(wr_q_.empty());
|
||||
}
|
||||
|
||||
template<class NextLayer, class Allocator>
|
||||
template<class... Args>
|
||||
stream<NextLayer, Allocator>::
|
||||
stream(Args&&... args)
|
||||
: next_layer_(std::forward<Args>(args)...)
|
||||
{
|
||||
}
|
||||
|
||||
template<class NextLayer, class Allocator>
|
||||
void
|
||||
stream<NextLayer, Allocator>::
|
||||
cancel(error_code& ec)
|
||||
{
|
||||
cancel_all();
|
||||
lowest_layer().cancel(ec);
|
||||
}
|
||||
|
||||
template<class NextLayer, class Allocator>
|
||||
template<bool isRequest, class Body, class Headers>
|
||||
void
|
||||
stream<NextLayer, Allocator>::
|
||||
read(message_v1<isRequest, Body, Headers>& msg,
|
||||
error_code& ec)
|
||||
{
|
||||
beast::http::read(next_layer_, rd_buf_, msg, ec);
|
||||
}
|
||||
|
||||
template<class NextLayer, class Allocator>
|
||||
template<bool isRequest, class Body, class Headers,
|
||||
class ReadHandler>
|
||||
auto
|
||||
stream<NextLayer, Allocator>::
|
||||
async_read(message_v1<isRequest, Body, Headers>& msg,
|
||||
ReadHandler&& handler) ->
|
||||
typename async_completion<
|
||||
ReadHandler, void(error_code)>::result_type
|
||||
{
|
||||
async_completion<
|
||||
ReadHandler, void(error_code)
|
||||
> completion(handler);
|
||||
read_op<isRequest, Body, Headers,
|
||||
decltype(completion.handler)>{
|
||||
completion.handler, *this, msg};
|
||||
return completion.result.get();
|
||||
}
|
||||
|
||||
template<class NextLayer, class Allocator>
|
||||
template<bool isRequest, class Body, class Headers>
|
||||
void
|
||||
stream<NextLayer, Allocator>::
|
||||
write(message_v1<isRequest, Body, Headers> const& msg,
|
||||
error_code& ec)
|
||||
{
|
||||
beast::http::write(next_layer_, msg, ec);
|
||||
}
|
||||
|
||||
template<class NextLayer, class Allocator>
|
||||
template<bool isRequest, class Body, class Headers,
|
||||
class WriteHandler>
|
||||
auto
|
||||
stream<NextLayer, Allocator>::
|
||||
async_write(message_v1<isRequest, Body, Headers> const& msg,
|
||||
WriteHandler&& handler) ->
|
||||
typename async_completion<
|
||||
WriteHandler, void(error_code)>::result_type
|
||||
{
|
||||
async_completion<
|
||||
WriteHandler, void(error_code)> completion(handler);
|
||||
auto const cont = wr_active_ ||
|
||||
boost_asio_handler_cont_helpers::is_continuation(handler);
|
||||
if(! wr_active_)
|
||||
{
|
||||
wr_active_ = true;
|
||||
write_op<isRequest, Body, Headers,
|
||||
decltype(completion.handler)>{
|
||||
completion.handler, *this, msg, cont }();
|
||||
}
|
||||
else
|
||||
{
|
||||
// VFALCO Use allocator
|
||||
wr_q_.push_back(*new write_op<isRequest, Body, Headers,
|
||||
decltype(completion.handler)>(
|
||||
completion.handler, *this, msg, cont));
|
||||
}
|
||||
return completion.result.get();
|
||||
}
|
||||
|
||||
template<class NextLayer, class Allocator>
|
||||
template<bool isRequest, class Body, class Headers,
|
||||
class WriteHandler>
|
||||
auto
|
||||
stream<NextLayer, Allocator>::
|
||||
async_write(message_v1<isRequest, Body, Headers>&& msg,
|
||||
WriteHandler&& handler) ->
|
||||
typename async_completion<
|
||||
WriteHandler, void(error_code)>::result_type
|
||||
{
|
||||
async_completion<
|
||||
WriteHandler, void(error_code)> completion(handler);
|
||||
auto const cont = wr_active_ ||
|
||||
boost_asio_handler_cont_helpers::is_continuation(handler);
|
||||
if(! wr_active_)
|
||||
{
|
||||
wr_active_ = true;
|
||||
write_op<isRequest, Body, Headers,
|
||||
decltype(completion.handler)>{completion.handler,
|
||||
*this, std::move(msg), cont}();
|
||||
}
|
||||
else
|
||||
{
|
||||
// VFALCO Use allocator
|
||||
wr_q_.push_back(*new write_op<isRequest, Body, Headers,
|
||||
decltype(completion.handler)>(completion.handler,
|
||||
*this, std::move(msg), cont));
|
||||
}
|
||||
return completion.result.get();
|
||||
}
|
||||
|
||||
template<class NextLayer, class Allocator>
|
||||
void
|
||||
stream<NextLayer, Allocator>::
|
||||
cancel_all()
|
||||
{
|
||||
for(auto it = wr_q_.begin(); it != wr_q_.end();)
|
||||
{
|
||||
auto& op = *it++;
|
||||
op.cancel();
|
||||
// VFALCO Use allocator
|
||||
delete &op;
|
||||
}
|
||||
wr_q_.clear();
|
||||
}
|
||||
|
||||
} // http
|
||||
} // beast
|
||||
|
||||
#endif
|
||||
@@ -9,8 +9,9 @@
|
||||
#define BEAST_EXAMPLE_HTTP_SYNC_SERVER_H_INCLUDED
|
||||
|
||||
#include "file_body.hpp"
|
||||
#include "http_stream.hpp"
|
||||
#include "mime_type.hpp"
|
||||
|
||||
#include <beast/core/streambuf.hpp>
|
||||
#include <boost/asio.hpp>
|
||||
#include <cstdint>
|
||||
#include <cstdio>
|
||||
@@ -34,6 +35,8 @@ class http_sync_server
|
||||
using req_type = request_v1<string_body>;
|
||||
using resp_type = response_v1<file_body>;
|
||||
|
||||
bool log_ = true;
|
||||
std::mutex m_;
|
||||
boost::asio::io_service ios_;
|
||||
socket_type sock_;
|
||||
boost::asio::ip::tcp::acceptor acceptor_;
|
||||
@@ -65,21 +68,43 @@ public:
|
||||
thread_.join();
|
||||
}
|
||||
|
||||
template<class... Args>
|
||||
void
|
||||
fail(error_code ec, std::string what)
|
||||
log(Args const&... args)
|
||||
{
|
||||
std::cerr <<
|
||||
what << ": " << ec.message() << std::endl;
|
||||
if(log_)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_);
|
||||
log_args(args...);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
void
|
||||
log_args()
|
||||
{
|
||||
}
|
||||
|
||||
template<class Arg, class... Args>
|
||||
void
|
||||
log_args(Arg const& arg, Args const&... args)
|
||||
{
|
||||
std::cerr << arg;
|
||||
log_args(args...);
|
||||
}
|
||||
|
||||
void
|
||||
maybe_throw(error_code ec, std::string what)
|
||||
fail(error_code ec, std::string what)
|
||||
{
|
||||
if(ec)
|
||||
{
|
||||
fail(ec, what);
|
||||
throw ec;
|
||||
}
|
||||
log(what, ": ", ec.message(), "\n");
|
||||
}
|
||||
|
||||
void
|
||||
fail(int id, error_code const& ec)
|
||||
{
|
||||
if(ec != boost::asio::error::operation_aborted &&
|
||||
ec != boost::asio::error::eof)
|
||||
log("#", id, " ", ec.message(), "\n");
|
||||
}
|
||||
|
||||
struct lambda
|
||||
@@ -109,7 +134,8 @@ public:
|
||||
{
|
||||
if(! acceptor_.is_open())
|
||||
return;
|
||||
maybe_throw(ec, "accept");
|
||||
if(ec)
|
||||
return fail(ec, "accept");
|
||||
static int id_ = 0;
|
||||
std::thread{lambda{++id_, *this, std::move(sock_)}}.detach();
|
||||
acceptor_.async_accept(sock_,
|
||||
@@ -118,23 +144,15 @@ public:
|
||||
}
|
||||
|
||||
void
|
||||
fail(int id, error_code const& ec)
|
||||
do_peer(int id, socket_type&& sock0)
|
||||
{
|
||||
if(ec != boost::asio::error::operation_aborted &&
|
||||
ec != boost::asio::error::eof)
|
||||
std::cerr <<
|
||||
"#" << std::to_string(id) << " " << std::endl;
|
||||
}
|
||||
|
||||
void
|
||||
do_peer(int id, socket_type&& sock)
|
||||
{
|
||||
http::stream<socket_type> hs(std::move(sock));
|
||||
socket_type sock(std::move(sock0));
|
||||
streambuf sb;
|
||||
error_code ec;
|
||||
for(;;)
|
||||
{
|
||||
req_type req;
|
||||
hs.read(req, ec);
|
||||
http::read(sock, sb, req, ec);
|
||||
if(ec)
|
||||
break;
|
||||
auto path = req.url;
|
||||
@@ -143,26 +161,42 @@ public:
|
||||
path = root_ + path;
|
||||
if(! boost::filesystem::exists(path))
|
||||
{
|
||||
response_v1<string_body> resp;
|
||||
resp.status = 404;
|
||||
resp.reason = "Not Found";
|
||||
resp.version = req.version;
|
||||
resp.headers.replace("Server", "http_sync_server");
|
||||
resp.body = "The file '" + path + "' was not found";
|
||||
prepare(resp);
|
||||
hs.write(resp, ec);
|
||||
response_v1<string_body> res;
|
||||
res.status = 404;
|
||||
res.reason = "Not Found";
|
||||
res.version = req.version;
|
||||
res.headers.insert("Server", "http_sync_server");
|
||||
res.headers.insert("Content-Type", "text/html");
|
||||
res.body = "The file '" + path + "' was not found";
|
||||
prepare(res);
|
||||
write(sock, res, ec);
|
||||
if(ec)
|
||||
break;
|
||||
}
|
||||
resp_type resp;
|
||||
resp.status = 200;
|
||||
resp.reason = "OK";
|
||||
resp.version = req.version;
|
||||
resp.headers.replace("Server", "http_sync_server");
|
||||
resp.headers.replace("Content-Type", "text/html");
|
||||
resp.body = path;
|
||||
prepare(resp);
|
||||
hs.write(resp, ec);
|
||||
resp_type res;
|
||||
res.status = 200;
|
||||
res.reason = "OK";
|
||||
res.version = req.version;
|
||||
res.headers.insert("Server", "http_sync_server");
|
||||
res.headers.insert("Content-Type", mime_type(path));
|
||||
res.body = path;
|
||||
try
|
||||
{
|
||||
prepare(res);
|
||||
}
|
||||
catch(std::exception const& e)
|
||||
{
|
||||
res = {};
|
||||
res.status = 500;
|
||||
res.reason = "Internal Error";
|
||||
res.version = req.version;
|
||||
res.headers.insert("Server", "http_sync_server");
|
||||
res.headers.insert("Content-Type", "text/html");
|
||||
res.body =
|
||||
std::string{"An internal error occurred"} + e.what();
|
||||
prepare(res);
|
||||
}
|
||||
write(sock, res, ec);
|
||||
if(ec)
|
||||
break;
|
||||
}
|
||||
|
||||
51
src/beast/examples/mime_type.hpp
Normal file
@@ -0,0 +1,51 @@
|
||||
//
|
||||
// Copyright (c) 2013-2016 Vinnie Falco (vinnie dot falco at gmail dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#ifndef BEAST_EXAMPLE_HTTP_MIME_TYPE_H_INCLUDED
|
||||
#define BEAST_EXAMPLE_HTTP_MIME_TYPE_H_INCLUDED
|
||||
|
||||
#include <string>
|
||||
#include <boost/filesystem/path.hpp>
|
||||
|
||||
namespace beast {
|
||||
namespace http {
|
||||
|
||||
// Return the Mime-Type for a given file extension
|
||||
template<class = void>
|
||||
std::string
|
||||
mime_type(std::string const& path)
|
||||
{
|
||||
auto const ext =
|
||||
boost::filesystem::path{path}.extension().string();
|
||||
if(ext == ".txt") return "text/plain";
|
||||
if(ext == ".htm") return "text/html";
|
||||
if(ext == ".html") return "text/html";
|
||||
if(ext == ".php") return "text/html";
|
||||
if(ext == ".css") return "text/css";
|
||||
if(ext == ".js") return "application/javascript";
|
||||
if(ext == ".json") return "application/json";
|
||||
if(ext == ".xml") return "application/xml";
|
||||
if(ext == ".swf") return "application/x-shockwave-flash";
|
||||
if(ext == ".flv") return "video/x-flv";
|
||||
if(ext == ".png") return "image/png";
|
||||
if(ext == ".jpe") return "image/jpeg";
|
||||
if(ext == ".jpeg") return "image/jpeg";
|
||||
if(ext == ".jpg") return "image/jpeg";
|
||||
if(ext == ".gif") return "image/gif";
|
||||
if(ext == ".bmp") return "image/bmp";
|
||||
if(ext == ".ico") return "image/vnd.microsoft.icon";
|
||||
if(ext == ".tiff") return "image/tiff";
|
||||
if(ext == ".tif") return "image/tiff";
|
||||
if(ext == ".svg") return "image/svg+xml";
|
||||
if(ext == ".svgz") return "image/svg+xml";
|
||||
return "application/text";
|
||||
}
|
||||
|
||||
} // http
|
||||
} // beast
|
||||
|
||||
#endif
|
||||
@@ -16,13 +16,13 @@ int main()
|
||||
// Normal boost::asio setup
|
||||
std::string const host = "echo.websocket.org";
|
||||
boost::asio::io_service ios;
|
||||
boost::asio::ip::tcp::resolver r(ios);
|
||||
boost::asio::ip::tcp::socket sock(ios);
|
||||
boost::asio::ip::tcp::resolver r{ios};
|
||||
boost::asio::ip::tcp::socket sock{ios};
|
||||
boost::asio::connect(sock,
|
||||
r.resolve(boost::asio::ip::tcp::resolver::query{host, "80"}));
|
||||
|
||||
// WebSocket connect and send message using beast
|
||||
beast::websocket::stream<boost::asio::ip::tcp::socket&> ws(sock);
|
||||
beast::websocket::stream<boost::asio::ip::tcp::socket&> ws{sock};
|
||||
ws.handshake(host, "/");
|
||||
ws.write(boost::asio::buffer("Hello, world!"));
|
||||
|
||||
|
||||
@@ -15,7 +15,9 @@ namespace test {
|
||||
|
||||
enum error
|
||||
{
|
||||
fail_error = 1
|
||||
success = 0,
|
||||
|
||||
fail_error
|
||||
};
|
||||
|
||||
namespace detail {
|
||||
|
||||
@@ -161,19 +161,21 @@ public:
|
||||
|
||||
friend
|
||||
void
|
||||
teardown(fail_stream<NextLayer>& stream,
|
||||
boost::system::error_code& ec)
|
||||
teardown(websocket::teardown_tag,
|
||||
fail_stream<NextLayer>& stream,
|
||||
boost::system::error_code& ec)
|
||||
{
|
||||
if(stream.pfc_->fail(ec))
|
||||
return;
|
||||
websocket_helpers::call_teardown(stream.next_layer(), ec);
|
||||
beast::websocket_helpers::call_teardown(stream.next_layer(), ec);
|
||||
}
|
||||
|
||||
template<class TeardownHandler>
|
||||
friend
|
||||
void
|
||||
async_teardown(fail_stream<NextLayer>& stream,
|
||||
TeardownHandler&& handler)
|
||||
async_teardown(websocket::teardown_tag,
|
||||
fail_stream<NextLayer>& stream,
|
||||
TeardownHandler&& handler)
|
||||
{
|
||||
error_code ec;
|
||||
if(stream.pfc_->fail(ec))
|
||||
@@ -182,7 +184,7 @@ public:
|
||||
bind_handler(std::move(handler), ec));
|
||||
return;
|
||||
}
|
||||
websocket_helpers::call_async_teardown(
|
||||
beast::websocket_helpers::call_async_teardown(
|
||||
stream.next_layer(), std::forward<TeardownHandler>(handler));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -23,29 +23,29 @@ private:
|
||||
std::string const& what_;
|
||||
|
||||
public:
|
||||
amount (amount const&) = default;
|
||||
amount& operator= (amount const&) = delete;
|
||||
amount(amount const&) = default;
|
||||
amount& operator=(amount const&) = delete;
|
||||
|
||||
template <class = void>
|
||||
amount (std::size_t n, std::string const& what);
|
||||
template<class = void>
|
||||
amount(std::size_t n, std::string const& what);
|
||||
|
||||
friend
|
||||
std::ostream&
|
||||
operator<< (std::ostream& s, amount const& t);
|
||||
operator<<(std::ostream& s, amount const& t);
|
||||
};
|
||||
|
||||
template <class>
|
||||
amount::amount (std::size_t n, std::string const& what)
|
||||
: n_ (n)
|
||||
, what_ (what)
|
||||
template<class>
|
||||
amount::amount(std::size_t n, std::string const& what)
|
||||
: n_(n)
|
||||
, what_(what)
|
||||
{
|
||||
}
|
||||
|
||||
inline
|
||||
std::ostream&
|
||||
operator<< (std::ostream& s, amount const& t)
|
||||
operator<<(std::ostream& s, amount const& t)
|
||||
{
|
||||
s << t.n_ << " " << t.what_ << ((t.n_ != 1) ? "s" : "");
|
||||
s << t.n_ << " " << t.what_ <<((t.n_ != 1) ? "s" : "");
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ namespace detail {
|
||||
The interface allows for limited read only operations. Derived classes
|
||||
provide additional behavior.
|
||||
*/
|
||||
template <class Container>
|
||||
template<class Container>
|
||||
class const_container
|
||||
{
|
||||
private:
|
||||
|
||||
@@ -8,11 +8,10 @@
|
||||
#ifndef BEAST_UNIT_TEST_DSTREAM_HPP
|
||||
#define BEAST_UNIT_TEST_DSTREAM_HPP
|
||||
|
||||
#include <boost/utility/base_from_member.hpp>
|
||||
#include <iostream>
|
||||
#include <ios>
|
||||
#include <memory>
|
||||
#include <ostream>
|
||||
#include <sstream>
|
||||
#include <streambuf>
|
||||
#include <string>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
@@ -30,15 +29,18 @@
|
||||
namespace beast {
|
||||
namespace unit_test {
|
||||
|
||||
namespace detail {
|
||||
|
||||
#ifdef _MSC_VER
|
||||
|
||||
namespace detail {
|
||||
|
||||
template<class CharT, class Traits, class Allocator>
|
||||
class dstream_buf
|
||||
: public std::basic_stringbuf<CharT, Traits, Allocator>
|
||||
{
|
||||
using ostream = std::basic_ostream<CharT, Traits>;
|
||||
|
||||
bool dbg_;
|
||||
ostream& os_;
|
||||
|
||||
template<class T>
|
||||
void write(T const*) = delete;
|
||||
@@ -47,21 +49,21 @@ class dstream_buf
|
||||
{
|
||||
if(dbg_)
|
||||
OutputDebugStringA(s);
|
||||
else
|
||||
std::cout << s;
|
||||
os_ << s;
|
||||
}
|
||||
|
||||
void write(wchar_t const* s)
|
||||
{
|
||||
if(dbg_)
|
||||
OutputDebugStringW(s);
|
||||
else
|
||||
std::wcout << s;
|
||||
os_ << s;
|
||||
}
|
||||
|
||||
public:
|
||||
dstream_buf()
|
||||
: dbg_(IsDebuggerPresent() != FALSE)
|
||||
explicit
|
||||
dstream_buf(ostream& os)
|
||||
: os_(os)
|
||||
, dbg_(IsDebuggerPresent() != FALSE)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -79,66 +81,52 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
#else
|
||||
|
||||
template<class CharT, class Traits, class Allocator>
|
||||
class dstream_buf
|
||||
: public std::basic_stringbuf<CharT, Traits, Allocator>
|
||||
{
|
||||
template<class T>
|
||||
void write(T const*) = delete;
|
||||
|
||||
void write(char const* s)
|
||||
{
|
||||
std::cout << s;
|
||||
}
|
||||
|
||||
void write(wchar_t const* s)
|
||||
{
|
||||
std::wcout << s;
|
||||
}
|
||||
|
||||
public:
|
||||
~dstream_buf()
|
||||
{
|
||||
sync();
|
||||
}
|
||||
|
||||
int
|
||||
sync() override
|
||||
{
|
||||
write(this->str().c_str());
|
||||
this->str("");
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
} // detail
|
||||
|
||||
/// A std::ostream that redirects output to the debugger if attached.
|
||||
/** std::ostream with Visual Studio IDE redirection.
|
||||
|
||||
Instances of this stream wrap a specified `std::ostream`
|
||||
(such as `std::cout` or `std::cerr`). If the IDE debugger
|
||||
is attached when the stream is created, output will be
|
||||
additionally copied to the Visual Studio Output window.
|
||||
*/
|
||||
template<
|
||||
class CharT,
|
||||
class Traits = std::char_traits<CharT>,
|
||||
class Allocator = std::allocator<CharT>
|
||||
>
|
||||
class basic_dstream
|
||||
: private boost::base_from_member<
|
||||
detail::dstream_buf<CharT, Traits, Allocator>>
|
||||
, public std::basic_ostream<CharT, Traits>
|
||||
: public std::basic_ostream<CharT, Traits>
|
||||
{
|
||||
detail::dstream_buf<
|
||||
CharT, Traits, Allocator> buf_;
|
||||
|
||||
public:
|
||||
basic_dstream()
|
||||
: std::basic_ostream<CharT, Traits>(&this->member)
|
||||
/** Construct a stream.
|
||||
|
||||
@param os The output stream to wrap.
|
||||
*/
|
||||
explicit
|
||||
basic_dstream(std::ostream& os)
|
||||
: std::basic_ostream<CharT, Traits>(&buf_)
|
||||
, buf_(os)
|
||||
{
|
||||
if(os.flags() && std::ios::unitbuf)
|
||||
std::unitbuf(*this);
|
||||
}
|
||||
};
|
||||
|
||||
using dstream = basic_dstream<char>;
|
||||
using dwstream = basic_dstream<wchar_t>;
|
||||
|
||||
} // test
|
||||
#else
|
||||
|
||||
using dstream = std::ostream&;
|
||||
using dwstream = std::wostream&;
|
||||
|
||||
#endif
|
||||
|
||||
} // unit_test
|
||||
} // beast
|
||||
|
||||
#endif
|
||||
|
||||
@@ -33,7 +33,7 @@ static
|
||||
std::string
|
||||
prefix(suite_info const& s)
|
||||
{
|
||||
if (s.manual())
|
||||
if(s.manual())
|
||||
return "|M| ";
|
||||
return " ";
|
||||
}
|
||||
@@ -45,7 +45,7 @@ print(std::ostream& os, suite_list const& c)
|
||||
std::size_t manual = 0;
|
||||
for(auto const& s : c)
|
||||
{
|
||||
os << prefix (s) << s.full_name() << '\n';
|
||||
os << prefix(s) << s.full_name() << '\n';
|
||||
if(s.manual())
|
||||
++manual;
|
||||
}
|
||||
@@ -80,18 +80,18 @@ int main(int ac, char const* av[])
|
||||
|
||||
#ifdef _MSC_VER
|
||||
{
|
||||
int flags = _CrtSetDbgFlag (_CRTDBG_REPORT_FLAG);
|
||||
int flags = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG);
|
||||
flags |= _CRTDBG_LEAK_CHECK_DF;
|
||||
_CrtSetDbgFlag (flags);
|
||||
_CrtSetDbgFlag(flags);
|
||||
}
|
||||
#endif
|
||||
|
||||
namespace po = boost::program_options;
|
||||
po::options_description desc("Options");
|
||||
desc.add_options()
|
||||
("help,h", "Produce a help message")
|
||||
("print,r", "Print the list of available test suites")
|
||||
("suites,s", po::value<string>(), "suites to run")
|
||||
("help,h", "Produce a help message")
|
||||
("print,p", "Print the list of available test suites")
|
||||
("suites,s", po::value<string>(), "suites to run")
|
||||
;
|
||||
|
||||
po::positional_options_description p;
|
||||
@@ -99,7 +99,8 @@ int main(int ac, char const* av[])
|
||||
po::store(po::parse_command_line(ac, av, desc), vm);
|
||||
po::notify(vm);
|
||||
|
||||
dstream log;
|
||||
dstream log{std::cerr};
|
||||
std::unitbuf(log);
|
||||
|
||||
if(vm.count("help"))
|
||||
{
|
||||
@@ -121,7 +122,7 @@ int main(int ac, char const* av[])
|
||||
match_auto(suites));
|
||||
else
|
||||
failed = r.run_each(global_suites());
|
||||
if (failed)
|
||||
if(failed)
|
||||
return EXIT_FAILURE;
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -45,42 +45,42 @@ private:
|
||||
std::string library_;
|
||||
|
||||
public:
|
||||
template <class = void>
|
||||
template<class = void>
|
||||
explicit
|
||||
selector (mode_t mode, std::string const& pattern = "");
|
||||
selector(mode_t mode, std::string const& pattern = "");
|
||||
|
||||
template <class = void>
|
||||
template<class = void>
|
||||
bool
|
||||
operator() (suite_info const& s);
|
||||
operator()(suite_info const& s);
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template <class>
|
||||
selector::selector (mode_t mode, std::string const& pattern)
|
||||
: mode_ (mode)
|
||||
, pat_ (pattern)
|
||||
template<class>
|
||||
selector::selector(mode_t mode, std::string const& pattern)
|
||||
: mode_(mode)
|
||||
, pat_(pattern)
|
||||
{
|
||||
if (mode_ == automatch && pattern.empty())
|
||||
if(mode_ == automatch && pattern.empty())
|
||||
mode_ = all;
|
||||
}
|
||||
|
||||
template <class>
|
||||
template<class>
|
||||
bool
|
||||
selector::operator() (suite_info const& s)
|
||||
selector::operator()(suite_info const& s)
|
||||
{
|
||||
switch (mode_)
|
||||
switch(mode_)
|
||||
{
|
||||
case automatch:
|
||||
// suite or full name
|
||||
if (s.name() == pat_ || s.full_name() == pat_)
|
||||
if(s.name() == pat_ || s.full_name() == pat_)
|
||||
{
|
||||
mode_ = none;
|
||||
return true;
|
||||
}
|
||||
|
||||
// check module
|
||||
if (pat_ == s.module())
|
||||
if(pat_ == s.module())
|
||||
{
|
||||
mode_ = module;
|
||||
library_ = s.library();
|
||||
@@ -88,7 +88,7 @@ selector::operator() (suite_info const& s)
|
||||
}
|
||||
|
||||
// check library
|
||||
if (pat_ == s.library())
|
||||
if(pat_ == s.library())
|
||||
{
|
||||
mode_ = library;
|
||||
return ! s.manual();
|
||||
@@ -138,9 +138,9 @@ selector::operator() (suite_info const& s)
|
||||
*/
|
||||
inline
|
||||
selector
|
||||
match_auto (std::string const& name)
|
||||
match_auto(std::string const& name)
|
||||
{
|
||||
return selector (selector::automatch, name);
|
||||
return selector(selector::automatch, name);
|
||||
}
|
||||
|
||||
/** Return a predicate that matches all suites not marked manual. */
|
||||
@@ -148,23 +148,23 @@ inline
|
||||
selector
|
||||
match_all()
|
||||
{
|
||||
return selector (selector::all);
|
||||
return selector(selector::all);
|
||||
}
|
||||
|
||||
/** Returns a predicate that matches a specific suite. */
|
||||
inline
|
||||
selector
|
||||
match_suite (std::string const& name)
|
||||
match_suite(std::string const& name)
|
||||
{
|
||||
return selector (selector::suite, name);
|
||||
return selector(selector::suite, name);
|
||||
}
|
||||
|
||||
/** Returns a predicate that matches all suites in a library. */
|
||||
inline
|
||||
selector
|
||||
match_library (std::string const& name)
|
||||
match_library(std::string const& name)
|
||||
{
|
||||
return selector (selector::library, name);
|
||||
return selector(selector::library, name);
|
||||
}
|
||||
|
||||
} // unit_test
|
||||
|
||||
@@ -24,8 +24,8 @@ private:
|
||||
|
||||
public:
|
||||
recorder() = default;
|
||||
recorder (recorder const&) = default;
|
||||
recorder& operator= (recorder const&) = default;
|
||||
recorder(recorder const&) = default;
|
||||
recorder& operator=(recorder const&) = default;
|
||||
|
||||
/** Returns a report with the results of all completed suites. */
|
||||
results const&
|
||||
@@ -37,31 +37,31 @@ public:
|
||||
private:
|
||||
virtual
|
||||
void
|
||||
on_suite_begin (suite_info const& info) override
|
||||
on_suite_begin(suite_info const& info) override
|
||||
{
|
||||
m_suite = suite_results (info.full_name());
|
||||
m_suite = suite_results(info.full_name());
|
||||
}
|
||||
|
||||
virtual
|
||||
void
|
||||
on_suite_end() override
|
||||
{
|
||||
m_results.insert (std::move (m_suite));
|
||||
m_results.insert(std::move(m_suite));
|
||||
}
|
||||
|
||||
virtual
|
||||
void
|
||||
on_case_begin (std::string const& name) override
|
||||
on_case_begin(std::string const& name) override
|
||||
{
|
||||
m_case = case_results (name);
|
||||
m_case = case_results(name);
|
||||
}
|
||||
|
||||
virtual
|
||||
void
|
||||
on_case_end() override
|
||||
{
|
||||
if (m_case.tests.size() > 0)
|
||||
m_suite.insert (std::move (m_case));
|
||||
if(m_case.tests.size() > 0)
|
||||
m_suite.insert(std::move(m_case));
|
||||
}
|
||||
|
||||
virtual
|
||||
@@ -73,16 +73,16 @@ private:
|
||||
|
||||
virtual
|
||||
void
|
||||
on_fail (std::string const& reason) override
|
||||
on_fail(std::string const& reason) override
|
||||
{
|
||||
m_case.tests.fail (reason);
|
||||
m_case.tests.fail(reason);
|
||||
}
|
||||
|
||||
virtual
|
||||
void
|
||||
on_log (std::string const& s) override
|
||||
on_log(std::string const& s) override
|
||||
{
|
||||
m_case.log.insert (s);
|
||||
m_case.log.insert(s);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -56,7 +56,7 @@ private:
|
||||
typename clock_type::time_point start = clock_type::now();
|
||||
|
||||
explicit
|
||||
suite_results(std::string const& name_ = "")
|
||||
suite_results(std::string name_ = "")
|
||||
: name(std::move(name_))
|
||||
{
|
||||
}
|
||||
@@ -83,7 +83,7 @@ private:
|
||||
typename clock_type::time_point start = clock_type::now();
|
||||
|
||||
void
|
||||
add (suite_results const& r);
|
||||
add(suite_results const& r);
|
||||
};
|
||||
|
||||
std::ostream& os_;
|
||||
@@ -107,7 +107,7 @@ private:
|
||||
|
||||
virtual
|
||||
void
|
||||
on_suite_begin (suite_info const& info) override;
|
||||
on_suite_begin(suite_info const& info) override;
|
||||
|
||||
virtual
|
||||
void
|
||||
@@ -115,7 +115,7 @@ private:
|
||||
|
||||
virtual
|
||||
void
|
||||
on_case_begin (std::string const& name) override;
|
||||
on_case_begin(std::string const& name) override;
|
||||
|
||||
virtual
|
||||
void
|
||||
@@ -127,11 +127,11 @@ private:
|
||||
|
||||
virtual
|
||||
void
|
||||
on_fail (std::string const& reason) override;
|
||||
on_fail(std::string const& reason) override;
|
||||
|
||||
virtual
|
||||
void
|
||||
on_log (std::string const& s) override;
|
||||
on_log(std::string const& s) override;
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
@@ -156,7 +156,7 @@ results::add(suite_results const& r)
|
||||
cases += r.cases;
|
||||
failed += r.failed;
|
||||
auto const elapsed = clock_type::now() - r.start;
|
||||
if (elapsed >= std::chrono::seconds{1})
|
||||
if(elapsed >= std::chrono::seconds{1})
|
||||
{
|
||||
auto const iter = std::lower_bound(top.begin(),
|
||||
top.end(), elapsed,
|
||||
@@ -165,13 +165,13 @@ results::add(suite_results const& r)
|
||||
{
|
||||
return t1.second > t2;
|
||||
});
|
||||
if (iter != top.end())
|
||||
if(iter != top.end())
|
||||
{
|
||||
if (top.size() == max_top)
|
||||
if(top.size() == max_top)
|
||||
top.resize(top.size() - 1);
|
||||
top.emplace(iter, r.name, elapsed);
|
||||
}
|
||||
else if (top.size() < max_top)
|
||||
else if(top.size() < max_top)
|
||||
{
|
||||
top.emplace_back(r.name, elapsed);
|
||||
}
|
||||
@@ -213,11 +213,11 @@ reporter<_>::fmtdur(typename clock_type::duration const& d)
|
||||
{
|
||||
using namespace std::chrono;
|
||||
auto const ms = duration_cast<milliseconds>(d);
|
||||
if (ms < seconds{1})
|
||||
if(ms < seconds{1})
|
||||
return std::to_string(ms.count()) + "ms";
|
||||
std::stringstream ss;
|
||||
ss << std::fixed << std::setprecision(1) <<
|
||||
(ms.count()/1000.) << "s";
|
||||
(ms.count()/1000.) << "s";
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
@@ -241,11 +241,10 @@ void
|
||||
reporter<_>::
|
||||
on_case_begin(std::string const& name)
|
||||
{
|
||||
case_results_ = case_results (name);
|
||||
os_ <<
|
||||
suite_results_.name <<
|
||||
(case_results_.name.empty() ?
|
||||
"" : (" " + case_results_.name)) << std::endl;
|
||||
case_results_ = case_results(name);
|
||||
os_ << suite_results_.name <<
|
||||
(case_results_.name.empty() ? "" :
|
||||
(" " + case_results_.name)) << std::endl;
|
||||
}
|
||||
|
||||
template<class _>
|
||||
@@ -273,7 +272,7 @@ on_fail(std::string const& reason)
|
||||
++case_results_.total;
|
||||
os_ <<
|
||||
"#" << case_results_.total << " failed" <<
|
||||
(reason.empty() ? "" : ": ") << reason << std::endl;
|
||||
(reason.empty() ? "" : ": ") << reason << std::endl;
|
||||
}
|
||||
|
||||
template<class _>
|
||||
|
||||
@@ -23,14 +23,14 @@ public:
|
||||
/** Holds the result of evaluating one test condition. */
|
||||
struct test
|
||||
{
|
||||
explicit test (bool pass_)
|
||||
: pass (pass_)
|
||||
explicit test(bool pass_)
|
||||
: pass(pass_)
|
||||
{
|
||||
}
|
||||
|
||||
test (bool pass_, std::string const& reason_)
|
||||
: pass (pass_)
|
||||
, reason (reason_)
|
||||
test(bool pass_, std::string const& reason_)
|
||||
: pass(pass_)
|
||||
, reason(reason_)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -46,8 +46,8 @@ private:
|
||||
std::size_t failed_;
|
||||
|
||||
public:
|
||||
tests_t ()
|
||||
: failed_ (0)
|
||||
tests_t()
|
||||
: failed_(0)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -69,15 +69,15 @@ private:
|
||||
void
|
||||
pass()
|
||||
{
|
||||
cont().emplace_back (true);
|
||||
cont().emplace_back(true);
|
||||
}
|
||||
|
||||
/** Register a failed test condition. */
|
||||
void
|
||||
fail (std::string const& reason = "")
|
||||
fail(std::string const& reason = "")
|
||||
{
|
||||
++failed_;
|
||||
cont().emplace_back (false, reason);
|
||||
cont().emplace_back(false, reason);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -87,17 +87,17 @@ private:
|
||||
public:
|
||||
/** Insert a string into the log. */
|
||||
void
|
||||
insert (std::string const& s)
|
||||
insert(std::string const& s)
|
||||
{
|
||||
cont().push_back (s);
|
||||
cont().push_back(s);
|
||||
}
|
||||
};
|
||||
|
||||
std::string name_;
|
||||
|
||||
public:
|
||||
explicit case_results (std::string const& name = "")
|
||||
: name_ (name)
|
||||
explicit case_results(std::string const& name = "")
|
||||
: name_(name)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -127,8 +127,8 @@ private:
|
||||
std::size_t failed_ = 0;
|
||||
|
||||
public:
|
||||
explicit suite_results (std::string const& name = "")
|
||||
: name_ (name)
|
||||
explicit suite_results(std::string const& name = "")
|
||||
: name_(name)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -156,17 +156,17 @@ public:
|
||||
/** Insert a set of testcase results. */
|
||||
/** @{ */
|
||||
void
|
||||
insert (case_results&& r)
|
||||
insert(case_results&& r)
|
||||
{
|
||||
cont().emplace_back (std::move (r));
|
||||
cont().emplace_back(std::move(r));
|
||||
total_ += r.tests.total();
|
||||
failed_ += r.tests.failed();
|
||||
}
|
||||
|
||||
void
|
||||
insert (case_results const& r)
|
||||
insert(case_results const& r)
|
||||
{
|
||||
cont().push_back (r);
|
||||
cont().push_back(r);
|
||||
total_ += r.tests.total();
|
||||
failed_ += r.tests.failed();
|
||||
}
|
||||
@@ -187,9 +187,9 @@ private:
|
||||
|
||||
public:
|
||||
results()
|
||||
: m_cases (0)
|
||||
, total_ (0)
|
||||
, failed_ (0)
|
||||
: m_cases(0)
|
||||
, total_(0)
|
||||
, failed_(0)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -217,21 +217,21 @@ public:
|
||||
/** Insert a set of suite results. */
|
||||
/** @{ */
|
||||
void
|
||||
insert (suite_results&& r)
|
||||
insert(suite_results&& r)
|
||||
{
|
||||
m_cases += r.size();
|
||||
total_ += r.total();
|
||||
failed_ += r.failed();
|
||||
cont().emplace_back (std::move (r));
|
||||
cont().emplace_back(std::move(r));
|
||||
}
|
||||
|
||||
void
|
||||
insert (suite_results const& r)
|
||||
insert(suite_results const& r)
|
||||
{
|
||||
m_cases += r.size();
|
||||
total_ += r.total();
|
||||
failed_ += r.failed();
|
||||
cont().push_back (r);
|
||||
cont().push_back(r);
|
||||
}
|
||||
/** @} */
|
||||
};
|
||||
|
||||
@@ -18,6 +18,7 @@ namespace beast {
|
||||
namespace unit_test {
|
||||
|
||||
/** Unit test runner interface.
|
||||
|
||||
Derived classes can customize the reporting behavior. This interface is
|
||||
injected into the unit_test class to receive the results of the tests.
|
||||
*/
|
||||
@@ -60,7 +61,7 @@ public:
|
||||
*/
|
||||
template<class = void>
|
||||
bool
|
||||
run (suite_info const& s);
|
||||
run(suite_info const& s);
|
||||
|
||||
/** Run a sequence of suites.
|
||||
The expression
|
||||
@@ -68,44 +69,40 @@ public:
|
||||
must be convertible to `suite_info`.
|
||||
@return `true` if any conditions failed.
|
||||
*/
|
||||
template <class FwdIter>
|
||||
template<class FwdIter>
|
||||
bool
|
||||
run (FwdIter first, FwdIter last);
|
||||
run(FwdIter first, FwdIter last);
|
||||
|
||||
/** Conditionally run a sequence of suites.
|
||||
pred will be called as:
|
||||
@code
|
||||
bool pred (suite_info const&);
|
||||
bool pred(suite_info const&);
|
||||
@endcode
|
||||
@return `true` if any conditions failed.
|
||||
*/
|
||||
template <class FwdIter, class Pred>
|
||||
template<class FwdIter, class Pred>
|
||||
bool
|
||||
run_if (FwdIter first, FwdIter last, Pred pred = Pred{});
|
||||
run_if(FwdIter first, FwdIter last, Pred pred = Pred{});
|
||||
|
||||
/** Run all suites in a container.
|
||||
@return `true` if any conditions failed.
|
||||
*/
|
||||
template <class SequenceContainer>
|
||||
template<class SequenceContainer>
|
||||
bool
|
||||
run_each (SequenceContainer const& c);
|
||||
run_each(SequenceContainer const& c);
|
||||
|
||||
/** Conditionally run suites in a container.
|
||||
pred will be called as:
|
||||
@code
|
||||
bool pred (suite_info const&);
|
||||
bool pred(suite_info const&);
|
||||
@endcode
|
||||
@return `true` if any conditions failed.
|
||||
*/
|
||||
template <class SequenceContainer, class Pred>
|
||||
template<class SequenceContainer, class Pred>
|
||||
bool
|
||||
run_each_if (SequenceContainer const& c, Pred pred = Pred{});
|
||||
run_each_if(SequenceContainer const& c, Pred pred = Pred{});
|
||||
|
||||
protected:
|
||||
//
|
||||
// Overrides
|
||||
//
|
||||
|
||||
/// Called when a new suite starts.
|
||||
virtual
|
||||
void
|
||||
@@ -159,130 +156,130 @@ private:
|
||||
friend class suite;
|
||||
|
||||
// Start a new testcase.
|
||||
template <class = void>
|
||||
template<class = void>
|
||||
void
|
||||
testcase (std::string const& name);
|
||||
testcase(std::string const& name);
|
||||
|
||||
template <class = void>
|
||||
template<class = void>
|
||||
void
|
||||
pass();
|
||||
|
||||
template <class = void>
|
||||
template<class = void>
|
||||
void
|
||||
fail (std::string const& reason);
|
||||
fail(std::string const& reason);
|
||||
|
||||
template <class = void>
|
||||
template<class = void>
|
||||
void
|
||||
log (std::string const& s);
|
||||
log(std::string const& s);
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template <class>
|
||||
template<class>
|
||||
bool
|
||||
runner::run (suite_info const& s)
|
||||
runner::run(suite_info const& s)
|
||||
{
|
||||
// Enable 'default' testcase
|
||||
default_ = true;
|
||||
failed_ = false;
|
||||
on_suite_begin (s);
|
||||
s.run (*this);
|
||||
on_suite_begin(s);
|
||||
s.run(*this);
|
||||
// Forgot to call pass or fail.
|
||||
assert (cond_);
|
||||
assert(cond_);
|
||||
on_case_end();
|
||||
on_suite_end();
|
||||
return failed_;
|
||||
}
|
||||
|
||||
template <class FwdIter>
|
||||
template<class FwdIter>
|
||||
bool
|
||||
runner::run (FwdIter first, FwdIter last)
|
||||
runner::run(FwdIter first, FwdIter last)
|
||||
{
|
||||
bool failed (false);
|
||||
for (;first != last; ++first)
|
||||
failed = run (*first) || failed;
|
||||
bool failed(false);
|
||||
for(;first != last; ++first)
|
||||
failed = run(*first) || failed;
|
||||
return failed;
|
||||
}
|
||||
|
||||
template <class FwdIter, class Pred>
|
||||
template<class FwdIter, class Pred>
|
||||
bool
|
||||
runner::run_if (FwdIter first, FwdIter last, Pred pred)
|
||||
runner::run_if(FwdIter first, FwdIter last, Pred pred)
|
||||
{
|
||||
bool failed (false);
|
||||
for (;first != last; ++first)
|
||||
if (pred (*first))
|
||||
failed = run (*first) || failed;
|
||||
bool failed(false);
|
||||
for(;first != last; ++first)
|
||||
if(pred(*first))
|
||||
failed = run(*first) || failed;
|
||||
return failed;
|
||||
}
|
||||
|
||||
template <class SequenceContainer>
|
||||
template<class SequenceContainer>
|
||||
bool
|
||||
runner::run_each (SequenceContainer const& c)
|
||||
runner::run_each(SequenceContainer const& c)
|
||||
{
|
||||
bool failed (false);
|
||||
for (auto const& s : c)
|
||||
failed = run (s) || failed;
|
||||
bool failed(false);
|
||||
for(auto const& s : c)
|
||||
failed = run(s) || failed;
|
||||
return failed;
|
||||
}
|
||||
|
||||
template <class SequenceContainer, class Pred>
|
||||
template<class SequenceContainer, class Pred>
|
||||
bool
|
||||
runner::run_each_if (SequenceContainer const& c, Pred pred)
|
||||
runner::run_each_if(SequenceContainer const& c, Pred pred)
|
||||
{
|
||||
bool failed (false);
|
||||
for (auto const& s : c)
|
||||
if (pred (s))
|
||||
failed = run (s) || failed;
|
||||
bool failed(false);
|
||||
for(auto const& s : c)
|
||||
if(pred(s))
|
||||
failed = run(s) || failed;
|
||||
return failed;
|
||||
}
|
||||
|
||||
template <class>
|
||||
template<class>
|
||||
void
|
||||
runner::testcase (std::string const& name)
|
||||
runner::testcase(std::string const& name)
|
||||
{
|
||||
std::lock_guard<std::recursive_mutex> lock(mutex_);
|
||||
// Name may not be empty
|
||||
assert (default_ || ! name.empty());
|
||||
assert(default_ || ! name.empty());
|
||||
// Forgot to call pass or fail
|
||||
assert (default_ || cond_);
|
||||
if (! default_)
|
||||
assert(default_ || cond_);
|
||||
if(! default_)
|
||||
on_case_end();
|
||||
default_ = false;
|
||||
cond_ = false;
|
||||
on_case_begin (name);
|
||||
on_case_begin(name);
|
||||
}
|
||||
|
||||
template <class>
|
||||
template<class>
|
||||
void
|
||||
runner::pass()
|
||||
{
|
||||
std::lock_guard<std::recursive_mutex> lock(mutex_);
|
||||
if (default_)
|
||||
testcase ("");
|
||||
if(default_)
|
||||
testcase("");
|
||||
on_pass();
|
||||
cond_ = true;
|
||||
}
|
||||
|
||||
template <class>
|
||||
template<class>
|
||||
void
|
||||
runner::fail (std::string const& reason)
|
||||
runner::fail(std::string const& reason)
|
||||
{
|
||||
std::lock_guard<std::recursive_mutex> lock(mutex_);
|
||||
if (default_)
|
||||
testcase ("");
|
||||
on_fail (reason);
|
||||
if(default_)
|
||||
testcase("");
|
||||
on_fail(reason);
|
||||
failed_ = true;
|
||||
cond_ = true;
|
||||
}
|
||||
|
||||
template <class>
|
||||
template<class>
|
||||
void
|
||||
runner::log (std::string const& s)
|
||||
runner::log(std::string const& s)
|
||||
{
|
||||
std::lock_guard<std::recursive_mutex> lock(mutex_);
|
||||
if (default_)
|
||||
testcase ("");
|
||||
on_log (s);
|
||||
if(default_)
|
||||
testcase("");
|
||||
on_log(s);
|
||||
}
|
||||
|
||||
} // unit_test
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#define BEAST_UNIT_TEST_SUITE_HPP
|
||||
|
||||
#include <beast/unit_test/runner.hpp>
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <ostream>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
@@ -72,7 +73,7 @@ private:
|
||||
{
|
||||
auto const& s = this->str();
|
||||
if(s.size() > 0)
|
||||
suite_.runner_->on_log(s);
|
||||
suite_.runner_->log(s);
|
||||
this->str("");
|
||||
return 0;
|
||||
}
|
||||
@@ -127,7 +128,7 @@ private:
|
||||
scoped_testcase
|
||||
operator()(abort_t abort);
|
||||
|
||||
template <class T>
|
||||
template<class T>
|
||||
scoped_testcase
|
||||
operator<<(T const& t);
|
||||
};
|
||||
@@ -146,7 +147,9 @@ public:
|
||||
/** Returns the "current" running suite.
|
||||
If no suite is running, nullptr is returned.
|
||||
*/
|
||||
static suite* this_suite()
|
||||
static
|
||||
suite*
|
||||
this_suite()
|
||||
{
|
||||
return *p_this_suite();
|
||||
}
|
||||
@@ -158,6 +161,7 @@ public:
|
||||
}
|
||||
|
||||
/** Invokes the test using the specified runner.
|
||||
|
||||
Data members are set up here instead of the constructor as a
|
||||
convenience to writing the derived class to avoid repetition of
|
||||
forwarded constructor arguments to the base.
|
||||
@@ -165,67 +169,95 @@ public:
|
||||
*/
|
||||
template<class = void>
|
||||
void
|
||||
operator() (runner& r);
|
||||
operator()(runner& r);
|
||||
|
||||
/** Record a successful test condition. */
|
||||
template<class = void>
|
||||
void
|
||||
pass();
|
||||
|
||||
/** Record a failure.
|
||||
|
||||
@param reason
|
||||
*/
|
||||
template<class = void>
|
||||
void
|
||||
fail(std::string const& reason = "");
|
||||
|
||||
/** Evaluate a test condition.
|
||||
The condition is passed as a template argument instead of `bool` so
|
||||
that implicit conversion is not required. The `reason` argument is
|
||||
logged if the condition is false.
|
||||
|
||||
This function provides improved logging by incorporating the
|
||||
file name and line number into the reported output on failure,
|
||||
as well as additional text specified by the caller.
|
||||
|
||||
@param shouldBeTrue The condition to test. The condition
|
||||
is evaluated in a boolean context.
|
||||
|
||||
@param reason Optional added text to output on a failure.
|
||||
|
||||
@param file The source code file where the test failed.
|
||||
|
||||
@param line The source code line number where the test failed.
|
||||
|
||||
@return `true` if the test condition indicates success.
|
||||
*/
|
||||
template<class Condition, class String>
|
||||
bool
|
||||
expect(Condition const& shouldBeTrue,
|
||||
String const& reason);
|
||||
|
||||
/** @{ */
|
||||
template<class Condition>
|
||||
bool
|
||||
expect(Condition const& shouldBeTrue)
|
||||
{
|
||||
return expect(shouldBeTrue, "");
|
||||
return expect(shouldBeTrue, {});
|
||||
}
|
||||
|
||||
/** Expect an exception from f() */
|
||||
/** @{ */
|
||||
template <class F, class String>
|
||||
template<class Condition>
|
||||
bool
|
||||
except (F&& f, String const& reason);
|
||||
expect(Condition const& shouldBeTrue, std::string const& reason);
|
||||
|
||||
template <class F>
|
||||
template<class Condition>
|
||||
bool
|
||||
except (F&& f)
|
||||
expect(Condition const& shouldBeTrue,
|
||||
char const* file, int line)
|
||||
{
|
||||
return expect(shouldBeTrue, {}, file, line);
|
||||
}
|
||||
|
||||
template<class Condition>
|
||||
bool
|
||||
expect(Condition const& shouldBeTrue,
|
||||
std::string const& reason, char const* file, int line);
|
||||
/** @} */
|
||||
|
||||
//
|
||||
// DEPRECATED
|
||||
//
|
||||
// Expect an exception from f()
|
||||
template<class F, class String>
|
||||
bool
|
||||
except(F&& f, String const& reason);
|
||||
template<class F>
|
||||
bool
|
||||
except(F&& f)
|
||||
{
|
||||
return except(f, "");
|
||||
}
|
||||
/** @} */
|
||||
|
||||
/** Expect an exception of the given type from f() */
|
||||
/** @{ */
|
||||
template <class E, class F, class String>
|
||||
template<class E, class F, class String>
|
||||
bool
|
||||
except (F&& f, String const& reason);
|
||||
|
||||
template <class E, class F>
|
||||
except(F&& f, String const& reason);
|
||||
template<class E, class F>
|
||||
bool
|
||||
except (F&& f)
|
||||
except(F&& f)
|
||||
{
|
||||
return except<E>(f, "");
|
||||
}
|
||||
/** @} */
|
||||
|
||||
/** Fail if f() throws */
|
||||
/** @{ */
|
||||
template <class F, class String>
|
||||
template<class F, class String>
|
||||
bool
|
||||
unexcept (F&& f, String const& reason);
|
||||
|
||||
template <class F>
|
||||
unexcept(F&& f, String const& reason);
|
||||
template<class F>
|
||||
bool
|
||||
unexcept (F&& f)
|
||||
unexcept(F&& f)
|
||||
{
|
||||
return unexcept(f, "");
|
||||
}
|
||||
/** @} */
|
||||
|
||||
/** Return the argument associated with the runner. */
|
||||
std::string const&
|
||||
@@ -235,29 +267,19 @@ public:
|
||||
}
|
||||
|
||||
// DEPRECATED
|
||||
// @return `true` if the test condition indicates success (a false value)
|
||||
template <class Condition, class String>
|
||||
// @return `true` if the test condition indicates success(a false value)
|
||||
template<class Condition, class String>
|
||||
bool
|
||||
unexpected (Condition shouldBeFalse,
|
||||
unexpected(Condition shouldBeFalse,
|
||||
String const& reason);
|
||||
|
||||
template <class Condition>
|
||||
template<class Condition>
|
||||
bool
|
||||
unexpected (Condition shouldBeFalse)
|
||||
unexpected(Condition shouldBeFalse)
|
||||
{
|
||||
return unexpected (shouldBeFalse, "");
|
||||
return unexpected(shouldBeFalse, "");
|
||||
}
|
||||
|
||||
/** Record a successful test condition. */
|
||||
template <class = void>
|
||||
void
|
||||
pass();
|
||||
|
||||
/** Record a failure. */
|
||||
template <class = void>
|
||||
void
|
||||
fail (std::string const& reason = "");
|
||||
|
||||
private:
|
||||
friend class thread;
|
||||
|
||||
@@ -277,9 +299,9 @@ private:
|
||||
void
|
||||
propagate_abort();
|
||||
|
||||
template <class = void>
|
||||
template<class = void>
|
||||
void
|
||||
run (runner& r);
|
||||
run(runner& r);
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
@@ -298,7 +320,10 @@ public:
|
||||
{
|
||||
auto const& name = ss_.str();
|
||||
if(! name.empty())
|
||||
suite_.runner_->testcase (name);
|
||||
{
|
||||
suite_.log.flush();
|
||||
suite_.runner_->testcase(name);
|
||||
}
|
||||
}
|
||||
|
||||
scoped_testcase(suite& self, std::stringstream& ss)
|
||||
@@ -333,16 +358,17 @@ public:
|
||||
|
||||
inline
|
||||
void
|
||||
suite::testcase_t::operator() (std::string const& name,
|
||||
abort_t abort)
|
||||
suite::testcase_t::operator()(
|
||||
std::string const& name, abort_t abort)
|
||||
{
|
||||
suite_.abort_ = abort == abort_on_fail;
|
||||
suite_.runner_->testcase (name);
|
||||
suite_.log.flush();
|
||||
suite_.runner_->testcase(name);
|
||||
}
|
||||
|
||||
inline
|
||||
suite::scoped_testcase
|
||||
suite::testcase_t::operator() (abort_t abort)
|
||||
suite::testcase_t::operator()(abort_t abort)
|
||||
{
|
||||
suite_.abort_ = abort == abort_on_fail;
|
||||
return { suite_, ss_ };
|
||||
@@ -351,7 +377,7 @@ suite::testcase_t::operator() (abort_t abort)
|
||||
template<class T>
|
||||
inline
|
||||
suite::scoped_testcase
|
||||
suite::testcase_t::operator<< (T const& t)
|
||||
suite::testcase_t::operator<<(T const& t)
|
||||
{
|
||||
return { suite_, ss_, t };
|
||||
}
|
||||
@@ -360,7 +386,8 @@ suite::testcase_t::operator<< (T const& t)
|
||||
|
||||
template<class>
|
||||
void
|
||||
suite::operator()(runner& r)
|
||||
suite::
|
||||
operator()(runner& r)
|
||||
{
|
||||
*p_this_suite() = this;
|
||||
try
|
||||
@@ -375,11 +402,11 @@ suite::operator()(runner& r)
|
||||
}
|
||||
}
|
||||
|
||||
template <class Condition, class String>
|
||||
inline
|
||||
template<class Condition>
|
||||
bool
|
||||
suite::expect(Condition const& shouldBeTrue,
|
||||
String const& reason)
|
||||
suite::
|
||||
expect(
|
||||
Condition const& shouldBeTrue, std::string const& reason)
|
||||
{
|
||||
if(shouldBeTrue)
|
||||
{
|
||||
@@ -390,9 +417,35 @@ suite::expect(Condition const& shouldBeTrue,
|
||||
return false;
|
||||
}
|
||||
|
||||
template <class F, class String>
|
||||
template<class Condition>
|
||||
bool
|
||||
suite::except (F&& f, String const& reason)
|
||||
suite::
|
||||
expect(Condition const& shouldBeTrue,
|
||||
std::string const& reason, char const* file, int line)
|
||||
{
|
||||
if(shouldBeTrue)
|
||||
{
|
||||
pass();
|
||||
return true;
|
||||
}
|
||||
std::string s;
|
||||
if(! reason.empty())
|
||||
{
|
||||
s += reason;
|
||||
s += " ";
|
||||
}
|
||||
s += boost::filesystem::path{file}.filename().string() +
|
||||
"(" + std::to_string(line) + ")";
|
||||
fail(s);
|
||||
return false;
|
||||
}
|
||||
|
||||
// DEPRECATED
|
||||
|
||||
template<class F, class String>
|
||||
bool
|
||||
suite::
|
||||
except(F&& f, String const& reason)
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -407,9 +460,10 @@ suite::except (F&& f, String const& reason)
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class E, class F, class String>
|
||||
template<class E, class F, class String>
|
||||
bool
|
||||
suite::except (F&& f, String const& reason)
|
||||
suite::
|
||||
except(F&& f, String const& reason)
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -424,9 +478,10 @@ suite::except (F&& f, String const& reason)
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class F, class String>
|
||||
template<class F, class String>
|
||||
bool
|
||||
suite::unexcept (F&& f, String const& reason)
|
||||
suite::
|
||||
unexcept(F&& f, String const& reason)
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -441,36 +496,39 @@ suite::unexcept (F&& f, String const& reason)
|
||||
return false;
|
||||
}
|
||||
|
||||
template <class Condition, class String>
|
||||
inline
|
||||
template<class Condition, class String>
|
||||
bool
|
||||
suite::unexpected (Condition shouldBeFalse,
|
||||
String const& reason)
|
||||
suite::
|
||||
unexpected(
|
||||
Condition shouldBeFalse, String const& reason)
|
||||
{
|
||||
bool const b =
|
||||
static_cast<bool>(shouldBeFalse);
|
||||
if (! b)
|
||||
if(! b)
|
||||
pass();
|
||||
else
|
||||
fail (reason);
|
||||
fail(reason);
|
||||
return ! b;
|
||||
}
|
||||
|
||||
template <class>
|
||||
template<class>
|
||||
void
|
||||
suite::pass()
|
||||
suite::
|
||||
pass()
|
||||
{
|
||||
propagate_abort();
|
||||
runner_->pass();
|
||||
}
|
||||
|
||||
template <class>
|
||||
// ::fail
|
||||
template<class>
|
||||
void
|
||||
suite::fail (std::string const& reason)
|
||||
suite::
|
||||
fail(std::string const& reason)
|
||||
{
|
||||
propagate_abort();
|
||||
runner_->fail (reason);
|
||||
if (abort_)
|
||||
runner_->fail(reason);
|
||||
if(abort_)
|
||||
{
|
||||
aborted_ = true;
|
||||
throw abort_exception();
|
||||
@@ -479,15 +537,17 @@ suite::fail (std::string const& reason)
|
||||
|
||||
inline
|
||||
void
|
||||
suite::propagate_abort()
|
||||
suite::
|
||||
propagate_abort()
|
||||
{
|
||||
if (abort_ && aborted_)
|
||||
if(abort_ && aborted_)
|
||||
throw abort_exception();
|
||||
}
|
||||
|
||||
template <class>
|
||||
template<class>
|
||||
void
|
||||
suite::run (runner& r)
|
||||
suite::
|
||||
run(runner& r)
|
||||
{
|
||||
runner_ = &r;
|
||||
|
||||
@@ -495,21 +555,37 @@ suite::run (runner& r)
|
||||
{
|
||||
run();
|
||||
}
|
||||
catch (abort_exception const&)
|
||||
catch(abort_exception const&)
|
||||
{
|
||||
// ends the suite
|
||||
}
|
||||
catch (std::exception const& e)
|
||||
catch(std::exception const& e)
|
||||
{
|
||||
runner_->fail ("unhandled exception: " +
|
||||
std::string (e.what()));
|
||||
runner_->fail("unhandled exception: " +
|
||||
std::string(e.what()));
|
||||
}
|
||||
catch (...)
|
||||
catch(...)
|
||||
{
|
||||
runner_->fail ("unhandled exception");
|
||||
runner_->fail("unhandled exception");
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef BEAST_EXPECT
|
||||
/** Check a precondition.
|
||||
|
||||
If the condition is false, the file and line number are reported.
|
||||
*/
|
||||
#define BEAST_EXPECT(cond) expect(cond, __FILE__, __LINE__)
|
||||
#endif
|
||||
|
||||
#ifndef BEAST_EXPECTS
|
||||
/** Check a precondition.
|
||||
|
||||
If the condition is false, the file and line number are reported.
|
||||
*/
|
||||
#define BEAST_EXPECTS(cond, reason) expect(cond, reason, __FILE__, __LINE__)
|
||||
#endif
|
||||
|
||||
} // unit_test
|
||||
} // beast
|
||||
|
||||
@@ -519,7 +595,7 @@ suite::run (runner& r)
|
||||
// This inserts the suite with the given manual flag
|
||||
#define BEAST_DEFINE_TESTSUITE_INSERT(Class,Module,Library,manual) \
|
||||
static beast::unit_test::detail::insert_suite <Class##_test> \
|
||||
Library ## Module ## Class ## _test_instance ( \
|
||||
Library ## Module ## Class ## _test_instance( \
|
||||
#Class, #Module, #Library, manual)
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
@@ -80,7 +80,7 @@ public:
|
||||
void
|
||||
run(runner& r) const
|
||||
{
|
||||
run_ (r);
|
||||
run_(r);
|
||||
}
|
||||
|
||||
friend
|
||||
|
||||
@@ -33,7 +33,7 @@ public:
|
||||
|
||||
The suite must not already exist.
|
||||
*/
|
||||
template <class Suite>
|
||||
template<class Suite>
|
||||
void
|
||||
insert(
|
||||
char const* name,
|
||||
@@ -44,7 +44,7 @@ public:
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template <class Suite>
|
||||
template<class Suite>
|
||||
void
|
||||
suite_list::insert(
|
||||
char const* name,
|
||||
@@ -56,14 +56,14 @@ suite_list::insert(
|
||||
{
|
||||
std::string s;
|
||||
s = std::string(library) + "." + module + "." + name;
|
||||
auto const result (names_.insert(s));
|
||||
assert (result.second); // Duplicate name
|
||||
auto const result(names_.insert(s));
|
||||
assert(result.second); // Duplicate name
|
||||
}
|
||||
|
||||
{
|
||||
auto const result (classes_.insert (
|
||||
std::type_index (typeid(Suite))));
|
||||
assert (result.second); // Duplicate type
|
||||
auto const result(classes_.insert(
|
||||
std::type_index(typeid(Suite))));
|
||||
assert(result.second); // Duplicate type
|
||||
}
|
||||
#endif
|
||||
cont().emplace(make_suite_info<Suite>(
|
||||
|
||||
@@ -28,31 +28,31 @@ public:
|
||||
using native_handle_type = std::thread::native_handle_type;
|
||||
|
||||
thread() = default;
|
||||
thread (thread const&) = delete;
|
||||
thread& operator= (thread const&) = delete;
|
||||
thread(thread const&) = delete;
|
||||
thread& operator=(thread const&) = delete;
|
||||
|
||||
thread (thread&& other)
|
||||
: s_ (other.s_)
|
||||
, t_ (std::move(other.t_))
|
||||
thread(thread&& other)
|
||||
: s_(other.s_)
|
||||
, t_(std::move(other.t_))
|
||||
{
|
||||
}
|
||||
|
||||
thread& operator= (thread&& other)
|
||||
thread& operator=(thread&& other)
|
||||
{
|
||||
s_ = other.s_;
|
||||
t_ = std::move(other.t_);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class F, class... Args>
|
||||
template<class F, class... Args>
|
||||
explicit
|
||||
thread (suite& s, F&& f, Args&&... args)
|
||||
: s_ (&s)
|
||||
thread(suite& s, F&& f, Args&&... args)
|
||||
: s_(&s)
|
||||
{
|
||||
std::function<void(void)> b =
|
||||
std::bind(std::forward<F>(f),
|
||||
std::forward<Args>(args)...);
|
||||
t_ = std::thread (&thread::run, this,
|
||||
t_ = std::thread(&thread::run, this,
|
||||
std::move(b));
|
||||
}
|
||||
|
||||
@@ -89,7 +89,7 @@ public:
|
||||
}
|
||||
|
||||
void
|
||||
swap (thread& other)
|
||||
swap(thread& other)
|
||||
{
|
||||
std::swap(s_, other.s_);
|
||||
std::swap(t_, other.t_);
|
||||
@@ -97,23 +97,23 @@ public:
|
||||
|
||||
private:
|
||||
void
|
||||
run (std::function <void(void)> f)
|
||||
run(std::function <void(void)> f)
|
||||
{
|
||||
try
|
||||
{
|
||||
f();
|
||||
}
|
||||
catch (suite::abort_exception const&)
|
||||
catch(suite::abort_exception const&)
|
||||
{
|
||||
}
|
||||
catch (std::exception const& e)
|
||||
catch(std::exception const& e)
|
||||
{
|
||||
s_->fail ("unhandled exception: " +
|
||||
std::string (e.what()));
|
||||
s_->fail("unhandled exception: " +
|
||||
std::string(e.what()));
|
||||
}
|
||||
catch (...)
|
||||
catch(...)
|
||||
{
|
||||
s_->fail ("unhandled exception");
|
||||
s_->fail("unhandled exception");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -47,7 +47,7 @@ namespace beast {
|
||||
@note See <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n3896.pdf">
|
||||
Library Foundations For Asynchronous Operations</a>
|
||||
*/
|
||||
template <class CompletionHandler, class Signature>
|
||||
template<class CompletionHandler, class Signature>
|
||||
struct async_completion
|
||||
{
|
||||
/** The type of the final handler called by the asynchronous initiation function.
|
||||
|
||||
@@ -14,10 +14,10 @@
|
||||
|
||||
namespace beast {
|
||||
|
||||
/** Adapts a @b `MutableBufferSequence` into a @b `Streambuf`.
|
||||
/** Adapts a @b `MutableBufferSequence` into a @b `DynamicBuffer`.
|
||||
|
||||
This class wraps a @b `MutableBufferSequence` to meet the requirements
|
||||
of @b `Streambuf`. Upon construction the input and output sequences are
|
||||
of @b `DynamicBuffer`. Upon construction the input and output sequences are
|
||||
empty. A copy of the mutable buffer sequence object is stored; however,
|
||||
ownership of the underlying memory is not transferred. The caller is
|
||||
responsible for making sure that referenced memory remains valid
|
||||
|
||||
@@ -44,7 +44,7 @@ namespace detail {
|
||||
|
||||
*/
|
||||
|
||||
template <class = void>
|
||||
template<class = void>
|
||||
std::string const&
|
||||
base64_alphabet()
|
||||
{
|
||||
@@ -62,7 +62,7 @@ is_base64(unsigned char c)
|
||||
return (std::isalnum(c) || (c == '+') || (c == '/'));
|
||||
}
|
||||
|
||||
template <class = void>
|
||||
template<class = void>
|
||||
std::string
|
||||
base64_encode (std::uint8_t const* data,
|
||||
std::size_t in_len)
|
||||
@@ -112,7 +112,7 @@ base64_encode (std::uint8_t const* data,
|
||||
|
||||
}
|
||||
|
||||
template <class = void>
|
||||
template<class = void>
|
||||
std::string
|
||||
base64_encode (std::string const& s)
|
||||
{
|
||||
@@ -120,11 +120,11 @@ base64_encode (std::string const& s)
|
||||
std::uint8_t const*> (s.data()), s.size());
|
||||
}
|
||||
|
||||
template <class = void>
|
||||
template<class = void>
|
||||
std::string
|
||||
base64_decode(std::string const& data)
|
||||
{
|
||||
int in_len = data.size();
|
||||
auto in_len = data.size();
|
||||
unsigned char c3[3], c4[4];
|
||||
int i = 0;
|
||||
int j = 0;
|
||||
|
||||
@@ -54,14 +54,14 @@ public:
|
||||
operator()()
|
||||
{
|
||||
invoke(h_, args_,
|
||||
index_sequence_for<Args...> ());
|
||||
index_sequence_for<Args...>());
|
||||
}
|
||||
|
||||
void
|
||||
operator()() const
|
||||
{
|
||||
invoke(h_, args_,
|
||||
index_sequence_for<Args...> ());
|
||||
index_sequence_for<Args...>());
|
||||
}
|
||||
|
||||
friend
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
namespace beast {
|
||||
namespace detail {
|
||||
|
||||
template <class T>
|
||||
template<class T>
|
||||
struct empty_base_optimization_decide
|
||||
: std::integral_constant <bool,
|
||||
std::is_empty <T>::value
|
||||
@@ -25,7 +25,7 @@ struct empty_base_optimization_decide
|
||||
{
|
||||
};
|
||||
|
||||
template <
|
||||
template<
|
||||
class T,
|
||||
int UniqueID = 0,
|
||||
bool ShouldDeriveFrom =
|
||||
@@ -57,7 +57,7 @@ public:
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template <
|
||||
template<
|
||||
class T,
|
||||
int UniqueID
|
||||
>
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
namespace beast {
|
||||
namespace detail {
|
||||
|
||||
template <class R, class C, class ...A>
|
||||
template<class R, class C, class ...A>
|
||||
auto
|
||||
is_call_possible_test(C&& c, int, A&& ...a)
|
||||
-> decltype(std::is_convertible<
|
||||
@@ -21,7 +21,7 @@ is_call_possible_test(C&& c, int, A&& ...a)
|
||||
std::is_same<R, void>::value,
|
||||
std::true_type());
|
||||
|
||||
template <class R, class C, class ...A>
|
||||
template<class R, class C, class ...A>
|
||||
std::false_type
|
||||
is_call_possible_test(C&& c, long, A&& ...a);
|
||||
|
||||
@@ -30,13 +30,13 @@ is_call_possible_test(C&& c, long, A&& ...a);
|
||||
is_call_possible<T, void(std::string)>
|
||||
*/
|
||||
/** @{ */
|
||||
template <class C, class F>
|
||||
template<class C, class F>
|
||||
struct is_call_possible
|
||||
: std::false_type
|
||||
{
|
||||
};
|
||||
|
||||
template <class C, class R, class ...A>
|
||||
template<class C, class R, class ...A>
|
||||
struct is_call_possible<C, R(A...)>
|
||||
: decltype(is_call_possible_test<R>(
|
||||
std::declval<C>(), 1, std::declval<A>()...))
|
||||
|
||||
@@ -281,10 +281,10 @@ finish(sha1_context& ctx, void* digest) noexcept
|
||||
ctx.buf[ctx.buflen++] = 0x00;
|
||||
std::uint32_t block[BLOCK_INTS];
|
||||
sha1::make_block(ctx.buf, block);
|
||||
if (buflen > BLOCK_BYTES - 8)
|
||||
if(buflen > BLOCK_BYTES - 8)
|
||||
{
|
||||
sha1::transform(ctx.digest, block);
|
||||
for (size_t i = 0; i < BLOCK_INTS - 2; i++)
|
||||
for(size_t i = 0; i < BLOCK_INTS - 2; i++)
|
||||
block[i] = 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@ class has_get_io_service
|
||||
decltype(std::declval<U>().get_io_service()),
|
||||
boost::asio::io_service&>>
|
||||
static R check(int);
|
||||
template <class>
|
||||
template<class>
|
||||
static std::false_type check(...);
|
||||
public:
|
||||
using type = decltype(check<T>(0));
|
||||
|
||||
@@ -227,7 +227,7 @@ public:
|
||||
|
||||
/// Write the given data to the stream. Returns the number of bytes written,
|
||||
/// or 0 if an error occurred.
|
||||
template <class ConstBufferSequence>
|
||||
template<class ConstBufferSequence>
|
||||
std::size_t
|
||||
write_some(ConstBufferSequence const& buffers,
|
||||
error_code& ec)
|
||||
|
||||
@@ -34,10 +34,10 @@ namespace beast {
|
||||
caller is still responsible for freeing memory.
|
||||
*/
|
||||
#if GENERATING_DOCS
|
||||
template <class T, class CompletionHandler>
|
||||
template<class T, class CompletionHandler>
|
||||
class handler_alloc;
|
||||
#else
|
||||
template <class T, class CompletionHandler>
|
||||
template<class T, class CompletionHandler>
|
||||
class handler_alloc
|
||||
{
|
||||
private:
|
||||
@@ -46,7 +46,7 @@ private:
|
||||
// should produce a compile error if CompletionHandler is not
|
||||
// constructible from H.
|
||||
//
|
||||
template <class U, class H>
|
||||
template<class U, class H>
|
||||
friend class handler_alloc;
|
||||
|
||||
CompletionHandler h_;
|
||||
|
||||
@@ -85,7 +85,7 @@ public:
|
||||
is_continuation(op->d_->h);
|
||||
}
|
||||
|
||||
template <class Function>
|
||||
template<class Function>
|
||||
friend
|
||||
void asio_handler_invoke(Function&& f, read_some_op* op)
|
||||
{
|
||||
|
||||
@@ -129,7 +129,7 @@ protected:
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** A `Streambuf` with a fixed size internal buffer.
|
||||
/** A `DynamicBuffer` with a fixed size internal buffer.
|
||||
|
||||
@tparam N The number of bytes in the internal buffer.
|
||||
|
||||
|
||||
@@ -12,14 +12,14 @@
|
||||
|
||||
namespace beast {
|
||||
|
||||
/** A @b `Streambuf` that uses multiple buffers internally.
|
||||
/** A @b `DynamicBuffer` that uses multiple buffers internally.
|
||||
|
||||
The implementation uses a sequence of one or more character arrays
|
||||
of varying sizes. Additional character array objects are appended to
|
||||
the sequence to accommodate changes in the size of the character
|
||||
sequence.
|
||||
|
||||
@note Meets the requirements of @b `Streambuf`.
|
||||
@note Meets the requirements of @b `DynamicBuffer`.
|
||||
*/
|
||||
using streambuf = basic_streambuf<std::allocator<char>>;
|
||||
|
||||
|
||||
@@ -105,7 +105,7 @@ protected:
|
||||
using list_t = typename boost::intrusive::make_list<
|
||||
element, boost::intrusive::constant_time_size<false>>::type;
|
||||
|
||||
using set_t = typename boost::intrusive::make_set<
|
||||
using set_t = typename boost::intrusive::make_multiset<
|
||||
element, boost::intrusive::constant_time_size<true>,
|
||||
boost::intrusive::compare<less>>::type;
|
||||
|
||||
@@ -117,7 +117,6 @@ protected:
|
||||
: set_(std::move(set))
|
||||
, list_(std::move(list))
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public:
|
||||
@@ -244,9 +243,10 @@ public:
|
||||
value.
|
||||
|
||||
Field names are stored as-is, but comparison are case-insensitive.
|
||||
The container preserves the order of insertion of fields with
|
||||
different names. For fields with the same name, the implementation
|
||||
concatenates values inserted with duplicate names as per rfc7230.
|
||||
When the container is iterated, the fields are presented in the order
|
||||
of insertion. For fields with the same name, the container behaves
|
||||
as a std::multiset; there will be a separate value for each occurrence
|
||||
of the field name.
|
||||
|
||||
@note Meets the requirements of @b `FieldSequence`.
|
||||
*/
|
||||
@@ -359,27 +359,44 @@ public:
|
||||
return set_.size();
|
||||
}
|
||||
|
||||
/** Returns `true` if the specified field exists. */
|
||||
/// Returns `true` if the specified field exists.
|
||||
bool
|
||||
exists(boost::string_ref const& name) const
|
||||
{
|
||||
return set_.find(name, less{}) != set_.end();
|
||||
}
|
||||
|
||||
/** Returns an iterator to the case-insensitive matching header. */
|
||||
/// Returns the number of values for the specified field.
|
||||
std::size_t
|
||||
count(boost::string_ref const& name) const;
|
||||
|
||||
/** Returns an iterator to the case-insensitive matching field name.
|
||||
|
||||
If more than one field with the specified name exists, the
|
||||
first field defined by insertion order is returned.
|
||||
*/
|
||||
iterator
|
||||
find(boost::string_ref const& name) const;
|
||||
|
||||
/** Returns the value for a case-insensitive matching header, or "" */
|
||||
/** Returns the value for a case-insensitive matching header, or `""`.
|
||||
|
||||
If more than one field with the specified name exists, the
|
||||
first field defined by insertion order is returned.
|
||||
*/
|
||||
boost::string_ref
|
||||
operator[](boost::string_ref const& name) const;
|
||||
|
||||
/** Clear the contents of the basic_headers. */
|
||||
/// Clear the contents of the basic_headers.
|
||||
void
|
||||
clear() noexcept;
|
||||
|
||||
/** Remove a field.
|
||||
|
||||
If more than one field with the specified name exists, all
|
||||
matching fields will be removed.
|
||||
|
||||
@param name The name of the field(s) to remove.
|
||||
|
||||
@return The number of fields removed.
|
||||
*/
|
||||
std::size_t
|
||||
@@ -387,39 +404,57 @@ public:
|
||||
|
||||
/** Insert a field value.
|
||||
|
||||
If a field value already exists the new value will be
|
||||
extended as per RFC2616 Section 4.2.
|
||||
If a field with the same name already exists, the
|
||||
existing field is untouched and a new field value pair
|
||||
is inserted into the container.
|
||||
|
||||
@param name The name of the field.
|
||||
|
||||
@param value A string holding the value of the field.
|
||||
*/
|
||||
// VFALCO TODO Consider allowing rvalue references for std::move?
|
||||
void
|
||||
insert(boost::string_ref const& name, boost::string_ref value);
|
||||
|
||||
/** Insert a field value.
|
||||
|
||||
If a field value already exists the new value will be
|
||||
extended as per RFC2616 Section 4.2.
|
||||
If a field with the same name already exists, the
|
||||
existing field is untouched and a new field value pair
|
||||
is inserted into the container.
|
||||
|
||||
@param name The name of the field
|
||||
|
||||
@param value The value of the field. The object will be
|
||||
converted to a string using `boost::lexical_cast`.
|
||||
*/
|
||||
template<class T>
|
||||
typename std::enable_if<
|
||||
! std::is_constructible<boost::string_ref, T>::value>::type
|
||||
insert(boost::string_ref name, T const& value)
|
||||
{
|
||||
insert(name,
|
||||
boost::lexical_cast<std::string>(value));
|
||||
insert(name, boost::lexical_cast<std::string>(value));
|
||||
}
|
||||
|
||||
/** Replace a field value.
|
||||
|
||||
The current field value, if any, is removed. Then the
|
||||
specified value is inserted as if by `insert(field, value)`.
|
||||
First removes any values with matching field names, then
|
||||
inserts the new field value.
|
||||
|
||||
@param name The name of the field.
|
||||
|
||||
@param value A string holding the value of the field.
|
||||
*/
|
||||
void
|
||||
replace(boost::string_ref const& name, boost::string_ref value);
|
||||
|
||||
/** Replace a field value.
|
||||
|
||||
The current field value, if any, is removed. Then the
|
||||
specified value is inserted as if by `insert(field, value)`.
|
||||
First removes any values with matching field names, then
|
||||
inserts the new field value.
|
||||
|
||||
@param name The name of the field
|
||||
|
||||
@param value The value of the field. The object will be
|
||||
converted to a string using `boost::lexical_cast`.
|
||||
*/
|
||||
template<class T>
|
||||
typename std::enable_if<
|
||||
|
||||
@@ -482,7 +482,7 @@ private:
|
||||
std::declval<error_code&>()),
|
||||
std::true_type{})>
|
||||
static R check(int);
|
||||
template <class>
|
||||
template<class>
|
||||
static std::false_type check(...);
|
||||
using type = decltype(check<C>(0));
|
||||
public:
|
||||
@@ -501,7 +501,7 @@ private:
|
||||
std::declval<error_code&>()),
|
||||
std::true_type{})>
|
||||
static R check(int);
|
||||
template <class>
|
||||
template<class>
|
||||
static std::false_type check(...);
|
||||
using type = decltype(check<C>(0));
|
||||
public:
|
||||
@@ -520,7 +520,7 @@ private:
|
||||
std::declval<error_code&>()),
|
||||
std::true_type{})>
|
||||
static R check(int);
|
||||
template <class>
|
||||
template<class>
|
||||
static std::false_type check(...);
|
||||
using type = decltype(check<C>(0));
|
||||
public:
|
||||
@@ -539,7 +539,7 @@ private:
|
||||
std::declval<error_code&>()),
|
||||
std::true_type{})>
|
||||
static R check(int);
|
||||
template <class>
|
||||
template<class>
|
||||
static std::false_type check(...);
|
||||
using type = decltype(check<C>(0));
|
||||
public:
|
||||
@@ -557,7 +557,7 @@ private:
|
||||
std::declval<error_code&>()),
|
||||
std::true_type{})>
|
||||
static R check(int);
|
||||
template <class>
|
||||
template<class>
|
||||
static std::false_type check(...);
|
||||
using type = decltype(check<C>(0));
|
||||
public:
|
||||
@@ -575,7 +575,7 @@ private:
|
||||
std::declval<error_code&>()),
|
||||
std::true_type{})>
|
||||
static R check(int);
|
||||
template <class>
|
||||
template<class>
|
||||
static std::false_type check(...);
|
||||
using type = decltype(check<C>(0));
|
||||
public:
|
||||
@@ -594,7 +594,7 @@ private:
|
||||
std::declval<error_code&>()),
|
||||
std::true_type{})>
|
||||
static R check(int);
|
||||
template <class>
|
||||
template<class>
|
||||
static std::false_type check(...);
|
||||
using type = decltype(check<C>(0));
|
||||
public:
|
||||
@@ -613,7 +613,7 @@ private:
|
||||
std::declval<error_code&>()),
|
||||
std::true_type{})>
|
||||
static R check(int);
|
||||
template <class>
|
||||
template<class>
|
||||
static std::false_type check(...);
|
||||
using type = decltype(check<C>(0));
|
||||
public:
|
||||
@@ -630,7 +630,7 @@ private:
|
||||
decltype(std::declval<T>().on_headers(
|
||||
std::declval<std::uint64_t>(), std::declval<error_code&>()))>>
|
||||
static R check(int);
|
||||
template <class>
|
||||
template<class>
|
||||
static std::false_type check(...);
|
||||
using type = decltype(check<C>(0));
|
||||
public:
|
||||
@@ -649,7 +649,7 @@ private:
|
||||
std::declval<error_code&>()),
|
||||
std::true_type{})>
|
||||
static R check(int);
|
||||
template <class>
|
||||
template<class>
|
||||
static std::false_type check(...);
|
||||
using type = decltype(check<C>(0));
|
||||
public:
|
||||
@@ -667,7 +667,7 @@ private:
|
||||
std::declval<error_code&>()),
|
||||
std::true_type{})>
|
||||
static R check(int);
|
||||
template <class>
|
||||
template<class>
|
||||
static std::false_type check(...);
|
||||
using type = decltype(check<C>(0));
|
||||
public:
|
||||
|
||||
@@ -29,7 +29,7 @@ class chunk_encode_text
|
||||
// Storage for the longest hex string we might need, plus delimiters.
|
||||
std::array<char, 2 * sizeof(std::size_t) + 2> buf_;
|
||||
|
||||
template <class OutIter>
|
||||
template<class OutIter>
|
||||
static
|
||||
OutIter
|
||||
to_hex(OutIter last, std::size_t n)
|
||||
|
||||
@@ -22,7 +22,7 @@ class has_content_length_value
|
||||
decltype(std::declval<U>().content_length()),
|
||||
std::uint64_t>>
|
||||
static R check(int);
|
||||
template <class>
|
||||
template<class>
|
||||
static std::false_type check(...);
|
||||
using type = decltype(check<T>(0));
|
||||
public:
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#define BEAST_HTTP_IMPL_BASIC_HEADERS_IPP
|
||||
|
||||
#include <beast/http/detail/rfc7230.hpp>
|
||||
#include <algorithm>
|
||||
|
||||
namespace beast {
|
||||
namespace http {
|
||||
@@ -204,6 +205,18 @@ basic_headers(FwdIt first, FwdIt last)
|
||||
insert(first->name(), first->value());
|
||||
}
|
||||
|
||||
template<class Allocator>
|
||||
std::size_t
|
||||
basic_headers<Allocator>::
|
||||
count(boost::string_ref const& name) const
|
||||
{
|
||||
auto const it = set_.find(name, less{});
|
||||
if(it == set_.end())
|
||||
return 0;
|
||||
auto const last = set_.upper_bound(name, less{});
|
||||
return static_cast<std::size_t>(std::distance(it, last));
|
||||
}
|
||||
|
||||
template<class Allocator>
|
||||
auto
|
||||
basic_headers<Allocator>::
|
||||
@@ -221,11 +234,9 @@ boost::string_ref
|
||||
basic_headers<Allocator>::
|
||||
operator[](boost::string_ref const& name) const
|
||||
{
|
||||
// VFALCO This none object looks sketchy
|
||||
static boost::string_ref const none;
|
||||
auto const it = find(name);
|
||||
if(it == end())
|
||||
return none;
|
||||
return {};
|
||||
return it->second;
|
||||
}
|
||||
|
||||
@@ -244,15 +255,23 @@ std::size_t
|
||||
basic_headers<Allocator>::
|
||||
erase(boost::string_ref const& name)
|
||||
{
|
||||
auto const it = set_.find(name, less{});
|
||||
auto it = set_.find(name, less{});
|
||||
if(it == set_.end())
|
||||
return 0;
|
||||
auto& e = *it;
|
||||
set_.erase(set_.iterator_to(e));
|
||||
list_.erase(list_.iterator_to(e));
|
||||
alloc_traits::destroy(this->member(), &e);
|
||||
alloc_traits::deallocate(this->member(), &e, 1);
|
||||
return 1;
|
||||
auto const last = set_.upper_bound(name, less{});
|
||||
std::size_t n = 1;
|
||||
for(;;)
|
||||
{
|
||||
auto& e = *it++;
|
||||
set_.erase(set_.iterator_to(e));
|
||||
list_.erase(list_.iterator_to(e));
|
||||
alloc_traits::destroy(this->member(), &e);
|
||||
alloc_traits::deallocate(this->member(), &e, 1);
|
||||
if(it == last)
|
||||
break;
|
||||
++n;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
template<class Allocator>
|
||||
@@ -262,25 +281,10 @@ insert(boost::string_ref const& name,
|
||||
boost::string_ref value)
|
||||
{
|
||||
value = detail::trim(value);
|
||||
typename set_t::insert_commit_data d;
|
||||
auto const result =
|
||||
set_.insert_check(name, less{}, d);
|
||||
if(result.second)
|
||||
{
|
||||
auto const p = alloc_traits::allocate(
|
||||
this->member(), 1);
|
||||
alloc_traits::construct(
|
||||
this->member(), p, name, value);
|
||||
list_.push_back(*p);
|
||||
set_.insert_commit(*p, d);
|
||||
return;
|
||||
}
|
||||
// If field already exists, insert comma
|
||||
// separated value as per RFC2616 section 4.2
|
||||
auto& cur = result.first->data.second;
|
||||
cur.reserve(cur.size() + 1 + value.size());
|
||||
cur.append(1, ',');
|
||||
cur.append(value.data(), value.size());
|
||||
auto const p = alloc_traits::allocate(this->member(), 1);
|
||||
alloc_traits::construct(this->member(), p, name, value);
|
||||
set_.insert_before(set_.upper_bound(name, less{}), *p);
|
||||
list_.push_back(*p);
|
||||
}
|
||||
|
||||
template<class Allocator>
|
||||
|
||||