mirror of
https://github.com/XRPLF/rippled.git
synced 2025-11-20 19:15:54 +00:00
refactor: Remove dead headers (#5081)
This commit is contained in:
@@ -1,26 +0,0 @@
|
|||||||
# Continuous Integration (CI) Scripts
|
|
||||||
|
|
||||||
In this directory are two scripts, `build.sh` and `test.sh` used for building
|
|
||||||
and testing rippled.
|
|
||||||
|
|
||||||
(For now, they assume Bash and Linux. Once I get Windows containers for
|
|
||||||
testing, I'll try them there, but if Bash is not available, then they will
|
|
||||||
soon be joined by PowerShell scripts `build.ps` and `test.ps`.)
|
|
||||||
|
|
||||||
We don't want these scripts to require arcane invocations that can only be
|
|
||||||
pieced together from within a CI configuration. We want something that humans
|
|
||||||
can easily invoke, read, and understand, for when we eventually have to test
|
|
||||||
and debug them interactively. That means:
|
|
||||||
|
|
||||||
(1) They should work with no arguments.
|
|
||||||
(2) They should document their arguments.
|
|
||||||
(3) They should expand short arguments into long arguments.
|
|
||||||
|
|
||||||
While we want to provide options for common use cases, we don't need to offer
|
|
||||||
the kitchen sink. We can rightfully expect users with esoteric, complicated
|
|
||||||
needs to write their own scripts.
|
|
||||||
|
|
||||||
To make argument-handling easy for us, the implementers, we can just take all
|
|
||||||
arguments from environment variables. They have the nice advantage that every
|
|
||||||
command-line uses named arguments. For the benefit of us and our users, we
|
|
||||||
document those variables at the top of each script.
|
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
set -o xtrace
|
|
||||||
set -o errexit
|
|
||||||
|
|
||||||
# The build system. Either 'Unix Makefiles' or 'Ninja'.
|
|
||||||
GENERATOR=${GENERATOR:-Unix Makefiles}
|
|
||||||
# The compiler. Either 'gcc' or 'clang'.
|
|
||||||
COMPILER=${COMPILER:-gcc}
|
|
||||||
# The build type. Either 'Debug' or 'Release'.
|
|
||||||
BUILD_TYPE=${BUILD_TYPE:-Debug}
|
|
||||||
# Additional arguments to CMake.
|
|
||||||
# We use the `-` substitution here instead of `:-` so that callers can erase
|
|
||||||
# the default by setting `$CMAKE_ARGS` to the empty string.
|
|
||||||
CMAKE_ARGS=${CMAKE_ARGS-'-Dwerr=ON'}
|
|
||||||
|
|
||||||
# https://gitlab.kitware.com/cmake/cmake/issues/18865
|
|
||||||
CMAKE_ARGS="-DBoost_NO_BOOST_CMAKE=ON ${CMAKE_ARGS}"
|
|
||||||
|
|
||||||
if [[ ${COMPILER} == 'gcc' ]]; then
|
|
||||||
export CC='gcc'
|
|
||||||
export CXX='g++'
|
|
||||||
elif [[ ${COMPILER} == 'clang' ]]; then
|
|
||||||
export CC='clang'
|
|
||||||
export CXX='clang++'
|
|
||||||
fi
|
|
||||||
|
|
||||||
mkdir build
|
|
||||||
cd build
|
|
||||||
cmake -G "${GENERATOR}" -DCMAKE_BUILD_TYPE=${BUILD_TYPE} ${CMAKE_ARGS} ..
|
|
||||||
cmake --build . -- -j $(nproc)
|
|
||||||
@@ -1,41 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
set -o xtrace
|
|
||||||
set -o errexit
|
|
||||||
|
|
||||||
# Set to 'true' to run the known "manual" tests in rippled.
|
|
||||||
MANUAL_TESTS=${MANUAL_TESTS:-false}
|
|
||||||
# The maximum number of concurrent tests.
|
|
||||||
CONCURRENT_TESTS=${CONCURRENT_TESTS:-$(nproc)}
|
|
||||||
# The path to rippled.
|
|
||||||
RIPPLED=${RIPPLED:-build/rippled}
|
|
||||||
# Additional arguments to rippled.
|
|
||||||
RIPPLED_ARGS=${RIPPLED_ARGS:-}
|
|
||||||
|
|
||||||
function join_by { local IFS="$1"; shift; echo "$*"; }
|
|
||||||
|
|
||||||
declare -a manual_tests=(
|
|
||||||
'beast.chrono.abstract_clock'
|
|
||||||
'beast.unit_test.print'
|
|
||||||
'ripple.NodeStore.Timing'
|
|
||||||
'ripple.app.Flow_manual'
|
|
||||||
'ripple.app.NoRippleCheckLimits'
|
|
||||||
'ripple.app.PayStrandAllPairs'
|
|
||||||
'ripple.consensus.ByzantineFailureSim'
|
|
||||||
'ripple.consensus.DistributedValidators'
|
|
||||||
'ripple.consensus.ScaleFreeSim'
|
|
||||||
'ripple.tx.CrossingLimits'
|
|
||||||
'ripple.tx.FindOversizeCross'
|
|
||||||
'ripple.tx.Offer_manual'
|
|
||||||
'ripple.tx.OversizeMeta'
|
|
||||||
'ripple.tx.PlumpBook'
|
|
||||||
)
|
|
||||||
|
|
||||||
if [[ ${MANUAL_TESTS} == 'true' ]]; then
|
|
||||||
RIPPLED_ARGS+=" --unittest=$(join_by , "${manual_tests[@]}")"
|
|
||||||
else
|
|
||||||
RIPPLED_ARGS+=" --unittest --quiet --unittest-log"
|
|
||||||
fi
|
|
||||||
RIPPLED_ARGS+=" --unittest-jobs ${CONCURRENT_TESTS}"
|
|
||||||
|
|
||||||
${RIPPLED} ${RIPPLED_ARGS}
|
|
||||||
@@ -1,274 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
set -ex
|
|
||||||
|
|
||||||
function version_ge() { test "$(echo "$@" | tr " " "\n" | sort -rV | head -n 1)" == "$1"; }
|
|
||||||
|
|
||||||
__dirname=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
|
|
||||||
echo "using CC: ${CC}"
|
|
||||||
"${CC}" --version
|
|
||||||
export CC
|
|
||||||
|
|
||||||
COMPNAME=$(basename $CC)
|
|
||||||
echo "using CXX: ${CXX:-notset}"
|
|
||||||
if [[ $CXX ]]; then
|
|
||||||
"${CXX}" --version
|
|
||||||
export CXX
|
|
||||||
fi
|
|
||||||
: ${BUILD_TYPE:=Debug}
|
|
||||||
echo "BUILD TYPE: ${BUILD_TYPE}"
|
|
||||||
|
|
||||||
: ${TARGET:=install}
|
|
||||||
echo "BUILD TARGET: ${TARGET}"
|
|
||||||
|
|
||||||
JOBS=${NUM_PROCESSORS:-2}
|
|
||||||
if [[ ${TRAVIS:-false} != "true" ]]; then
|
|
||||||
JOBS=$((JOBS+1))
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ ! -z "${CMAKE_EXE:-}" ]] ; then
|
|
||||||
export PATH="$(dirname ${CMAKE_EXE}):$PATH"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ -x /usr/bin/time ] ; then
|
|
||||||
: ${TIME:="Duration: %E"}
|
|
||||||
export TIME
|
|
||||||
time=/usr/bin/time
|
|
||||||
else
|
|
||||||
time=
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "Building rippled"
|
|
||||||
: ${CMAKE_EXTRA_ARGS:=""}
|
|
||||||
if [[ ${NINJA_BUILD:-} == true ]]; then
|
|
||||||
CMAKE_EXTRA_ARGS+=" -G Ninja"
|
|
||||||
fi
|
|
||||||
|
|
||||||
coverage=false
|
|
||||||
if [[ "${TARGET}" == "coverage" ]] ; then
|
|
||||||
echo "coverage option detected."
|
|
||||||
coverage=true
|
|
||||||
fi
|
|
||||||
|
|
||||||
cmake --version
|
|
||||||
CMAKE_VER=$(cmake --version | cut -d " " -f 3 | head -1)
|
|
||||||
|
|
||||||
#
|
|
||||||
# allow explicit setting of the name of the build
|
|
||||||
# dir, otherwise default to the compiler.build_type
|
|
||||||
#
|
|
||||||
: "${BUILD_DIR:=${COMPNAME}.${BUILD_TYPE}}"
|
|
||||||
BUILDARGS="--target ${TARGET}"
|
|
||||||
BUILDTOOLARGS=""
|
|
||||||
if version_ge $CMAKE_VER "3.12.0" ; then
|
|
||||||
BUILDARGS+=" --parallel"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ ${NINJA_BUILD:-} == false ]]; then
|
|
||||||
if version_ge $CMAKE_VER "3.12.0" ; then
|
|
||||||
BUILDARGS+=" ${JOBS}"
|
|
||||||
else
|
|
||||||
BUILDTOOLARGS+=" -j ${JOBS}"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ ${VERBOSE_BUILD:-} == true ]]; then
|
|
||||||
CMAKE_EXTRA_ARGS+=" -DCMAKE_VERBOSE_MAKEFILE=ON"
|
|
||||||
if version_ge $CMAKE_VER "3.14.0" ; then
|
|
||||||
BUILDARGS+=" --verbose"
|
|
||||||
else
|
|
||||||
if [[ ${NINJA_BUILD:-} == false ]]; then
|
|
||||||
BUILDTOOLARGS+=" verbose=1"
|
|
||||||
else
|
|
||||||
BUILDTOOLARGS+=" -v"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ ${USE_CCACHE:-} == true ]]; then
|
|
||||||
echo "using ccache with basedir [${CCACHE_BASEDIR:-}]"
|
|
||||||
CMAKE_EXTRA_ARGS+=" -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache"
|
|
||||||
fi
|
|
||||||
if [ -d "build/${BUILD_DIR}" ]; then
|
|
||||||
rm -rf "build/${BUILD_DIR}"
|
|
||||||
fi
|
|
||||||
|
|
||||||
mkdir -p "build/${BUILD_DIR}"
|
|
||||||
pushd "build/${BUILD_DIR}"
|
|
||||||
|
|
||||||
# cleanup possible artifacts
|
|
||||||
rm -fv CMakeFiles/CMakeOutput.log CMakeFiles/CMakeError.log
|
|
||||||
# Clean up NIH directories which should be git repos, but aren't
|
|
||||||
for nih_path in ${NIH_CACHE_ROOT}/*/*/*/src ${NIH_CACHE_ROOT}/*/*/src
|
|
||||||
do
|
|
||||||
for dir in lz4 snappy rocksdb
|
|
||||||
do
|
|
||||||
if [ -e ${nih_path}/${dir} -a \! -e ${nih_path}/${dir}/.git ]
|
|
||||||
then
|
|
||||||
ls -la ${nih_path}/${dir}*
|
|
||||||
rm -rfv ${nih_path}/${dir}*
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
done
|
|
||||||
|
|
||||||
# generate
|
|
||||||
${time} cmake ../.. -DCMAKE_BUILD_TYPE=${BUILD_TYPE} ${CMAKE_EXTRA_ARGS}
|
|
||||||
# Display the cmake output, to help with debugging if something fails
|
|
||||||
for file in CMakeOutput.log CMakeError.log
|
|
||||||
do
|
|
||||||
if [ -f CMakeFiles/${file} ]
|
|
||||||
then
|
|
||||||
ls -l CMakeFiles/${file}
|
|
||||||
cat CMakeFiles/${file}
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
# build
|
|
||||||
export DESTDIR=$(pwd)/_INSTALLED_
|
|
||||||
|
|
||||||
${time} eval cmake --build . ${BUILDARGS} -- ${BUILDTOOLARGS}
|
|
||||||
|
|
||||||
if [[ ${TARGET} == "docs" ]]; then
|
|
||||||
## mimic the standard test output for docs build
|
|
||||||
## to make controlling processes like jenkins happy
|
|
||||||
if [ -f docs/html/index.html ]; then
|
|
||||||
echo "1 case, 1 test total, 0 failures"
|
|
||||||
else
|
|
||||||
echo "1 case, 1 test total, 1 failures"
|
|
||||||
fi
|
|
||||||
exit
|
|
||||||
fi
|
|
||||||
popd
|
|
||||||
|
|
||||||
if [[ "${TARGET}" == "validator-keys" ]] ; then
|
|
||||||
export APP_PATH="$PWD/build/${BUILD_DIR}/validator-keys/validator-keys"
|
|
||||||
else
|
|
||||||
export APP_PATH="$PWD/build/${BUILD_DIR}/rippled"
|
|
||||||
fi
|
|
||||||
echo "using APP_PATH: ${APP_PATH}"
|
|
||||||
|
|
||||||
# See what we've actually built
|
|
||||||
ldd ${APP_PATH}
|
|
||||||
|
|
||||||
: ${APP_ARGS:=}
|
|
||||||
|
|
||||||
if [[ "${TARGET}" == "validator-keys" ]] ; then
|
|
||||||
APP_ARGS="--unittest"
|
|
||||||
else
|
|
||||||
function join_by { local IFS="$1"; shift; echo "$*"; }
|
|
||||||
|
|
||||||
# This is a list of manual tests
|
|
||||||
# in rippled that we want to run
|
|
||||||
# ORDER matters here...sorted in approximately
|
|
||||||
# descending execution time (longest running tests at top)
|
|
||||||
declare -a manual_tests=(
|
|
||||||
'ripple.ripple_data.reduce_relay_simulate'
|
|
||||||
'ripple.tx.Offer_manual'
|
|
||||||
'ripple.tx.CrossingLimits'
|
|
||||||
'ripple.tx.PlumpBook'
|
|
||||||
'ripple.app.Flow_manual'
|
|
||||||
'ripple.tx.OversizeMeta'
|
|
||||||
'ripple.consensus.DistributedValidators'
|
|
||||||
'ripple.app.NoRippleCheckLimits'
|
|
||||||
'ripple.ripple_data.compression'
|
|
||||||
'ripple.NodeStore.Timing'
|
|
||||||
'ripple.consensus.ByzantineFailureSim'
|
|
||||||
'beast.chrono.abstract_clock'
|
|
||||||
'beast.unit_test.print'
|
|
||||||
)
|
|
||||||
if [[ ${TRAVIS:-false} != "true" ]]; then
|
|
||||||
# these two tests cause travis CI to run out of memory.
|
|
||||||
# TODO: investigate possible workarounds.
|
|
||||||
manual_tests=(
|
|
||||||
'ripple.consensus.ScaleFreeSim'
|
|
||||||
'ripple.tx.FindOversizeCross'
|
|
||||||
"${manual_tests[@]}"
|
|
||||||
)
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ ${MANUAL_TESTS:-} == true ]]; then
|
|
||||||
APP_ARGS+=" --unittest=$(join_by , "${manual_tests[@]}")"
|
|
||||||
else
|
|
||||||
APP_ARGS+=" --unittest --quiet --unittest-log"
|
|
||||||
fi
|
|
||||||
if [[ ${coverage} == false && ${PARALLEL_TESTS:-} == true ]]; then
|
|
||||||
APP_ARGS+=" --unittest-jobs ${JOBS}"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ ${IPV6_TESTS:-} == true ]]; then
|
|
||||||
APP_ARGS+=" --unittest-ipv6"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ ${coverage} == true && $CC =~ ^gcc ]]; then
|
|
||||||
# Push the results (lcov.info) to codecov
|
|
||||||
codecov -X gcov # don't even try and look for .gcov files ;)
|
|
||||||
find . -name "*.gcda" | xargs rm -f
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ ${SKIP_TESTS:-} == true ]]; then
|
|
||||||
echo "skipping tests."
|
|
||||||
exit
|
|
||||||
fi
|
|
||||||
|
|
||||||
ulimit -a
|
|
||||||
corepat=$(cat /proc/sys/kernel/core_pattern)
|
|
||||||
if [[ ${corepat} =~ ^[:space:]*\| ]] ; then
|
|
||||||
echo "WARNING: core pattern is piping - can't search for core files"
|
|
||||||
look_core=false
|
|
||||||
else
|
|
||||||
look_core=true
|
|
||||||
coredir=$(dirname ${corepat})
|
|
||||||
fi
|
|
||||||
if [[ ${look_core} == true ]]; then
|
|
||||||
before=$(ls -A1 ${coredir})
|
|
||||||
fi
|
|
||||||
|
|
||||||
set +e
|
|
||||||
echo "Running tests for ${APP_PATH}"
|
|
||||||
if [[ ${MANUAL_TESTS:-} == true && ${PARALLEL_TESTS:-} != true ]]; then
|
|
||||||
for t in "${manual_tests[@]}" ; do
|
|
||||||
${APP_PATH} --unittest=${t}
|
|
||||||
TEST_STAT=$?
|
|
||||||
if [[ $TEST_STAT -ne 0 ]] ; then
|
|
||||||
break
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
else
|
|
||||||
${APP_PATH} ${APP_ARGS}
|
|
||||||
TEST_STAT=$?
|
|
||||||
fi
|
|
||||||
set -e
|
|
||||||
|
|
||||||
if [[ ${look_core} == true ]]; then
|
|
||||||
after=$(ls -A1 ${coredir})
|
|
||||||
oIFS="${IFS}"
|
|
||||||
IFS=$'\n\r'
|
|
||||||
found_core=false
|
|
||||||
for l in $(diff -w --suppress-common-lines <(echo "$before") <(echo "$after")) ; do
|
|
||||||
if [[ "$l" =~ ^[[:space:]]*\>[[:space:]]*(.+)$ ]] ; then
|
|
||||||
corefile="${BASH_REMATCH[1]}"
|
|
||||||
echo "FOUND core dump file at '${coredir}/${corefile}'"
|
|
||||||
gdb_output=$(/bin/mktemp /tmp/gdb_output_XXXXXXXXXX.txt)
|
|
||||||
found_core=true
|
|
||||||
gdb \
|
|
||||||
-ex "set height 0" \
|
|
||||||
-ex "set logging file ${gdb_output}" \
|
|
||||||
-ex "set logging on" \
|
|
||||||
-ex "print 'ripple::BuildInfo::versionString'" \
|
|
||||||
-ex "thread apply all backtrace full" \
|
|
||||||
-ex "info inferiors" \
|
|
||||||
-ex quit \
|
|
||||||
"$APP_PATH" \
|
|
||||||
"${coredir}/${corefile}" &> /dev/null
|
|
||||||
|
|
||||||
echo -e "CORE INFO: \n\n $(cat ${gdb_output}) \n\n)"
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
IFS="${oIFS}"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ ${found_core} == true ]]; then
|
|
||||||
exit -1
|
|
||||||
else
|
|
||||||
exit $TEST_STAT
|
|
||||||
fi
|
|
||||||
|
|
||||||
@@ -1,36 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
# run our build script in a docker container
|
|
||||||
# using travis-ci hosts
|
|
||||||
set -eux
|
|
||||||
|
|
||||||
function join_by { local IFS="$1"; shift; echo "$*"; }
|
|
||||||
|
|
||||||
set +x
|
|
||||||
echo "VERBOSE_BUILD=true" > /tmp/co.env
|
|
||||||
matchers=(
|
|
||||||
'TRAVIS.*' 'CI' 'CC' 'CXX'
|
|
||||||
'BUILD_TYPE' 'TARGET' 'MAX_TIME'
|
|
||||||
'CODECOV.+' 'CMAKE.*' '.+_TESTS'
|
|
||||||
'.+_OPTIONS' 'NINJA.*' 'NUM_.+'
|
|
||||||
'NIH_.+' 'BOOST.*' '.*CCACHE.*')
|
|
||||||
|
|
||||||
matchstring=$(join_by '|' "${matchers[@]}")
|
|
||||||
echo "MATCHSTRING IS:: $matchstring"
|
|
||||||
env | grep -E "^(${matchstring})=" >> /tmp/co.env
|
|
||||||
set -x
|
|
||||||
# need to eliminate TRAVIS_CMD...don't want to pass it to the container
|
|
||||||
cat /tmp/co.env | grep -v TRAVIS_CMD > /tmp/co.env.2
|
|
||||||
mv /tmp/co.env.2 /tmp/co.env
|
|
||||||
cat /tmp/co.env
|
|
||||||
mkdir -p -m 0777 ${TRAVIS_BUILD_DIR}/cores
|
|
||||||
echo "${TRAVIS_BUILD_DIR}/cores/%e.%p" | sudo tee /proc/sys/kernel/core_pattern
|
|
||||||
docker run \
|
|
||||||
-t --env-file /tmp/co.env \
|
|
||||||
-v ${TRAVIS_HOME}:${TRAVIS_HOME} \
|
|
||||||
-w ${TRAVIS_BUILD_DIR} \
|
|
||||||
--cap-add SYS_PTRACE \
|
|
||||||
--ulimit "core=-1" \
|
|
||||||
$DOCKER_IMAGE \
|
|
||||||
/bin/bash -c 'if [[ $CC =~ ([[:alpha:]]+)-([[:digit:].]+) ]] ; then sudo update-alternatives --set ${BASH_REMATCH[1]} /usr/bin/$CC; fi; bin/ci/ubuntu/build-and-test.sh'
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,44 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
# some cached files create churn, so save them here for
|
|
||||||
# later restoration before packing the cache
|
|
||||||
set -eux
|
|
||||||
clean_cache="travis_clean_cache"
|
|
||||||
if [[ ! ( "${TRAVIS_JOB_NAME}" =~ "windows" || \
|
|
||||||
"${TRAVIS_JOB_NAME}" =~ "prereq-keep" ) ]] && \
|
|
||||||
( [[ "${TRAVIS_COMMIT_MESSAGE}" =~ "${clean_cache}" ]] || \
|
|
||||||
( [[ -v TRAVIS_PULL_REQUEST_SHA && \
|
|
||||||
"${TRAVIS_PULL_REQUEST_SHA}" != "" ]] && \
|
|
||||||
git log -1 "${TRAVIS_PULL_REQUEST_SHA}" | grep -cq "${clean_cache}" -
|
|
||||||
)
|
|
||||||
)
|
|
||||||
then
|
|
||||||
find ${TRAVIS_HOME}/_cache -maxdepth 2 -type d
|
|
||||||
rm -rf ${TRAVIS_HOME}/_cache
|
|
||||||
mkdir -p ${TRAVIS_HOME}/_cache
|
|
||||||
fi
|
|
||||||
|
|
||||||
pushd ${TRAVIS_HOME}
|
|
||||||
if [ -f cache_ignore.tar ] ; then
|
|
||||||
rm -f cache_ignore.tar
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ -d _cache/nih_c ] ; then
|
|
||||||
find _cache/nih_c -name "build.ninja" | tar rf cache_ignore.tar --files-from -
|
|
||||||
find _cache/nih_c -name ".ninja_deps" | tar rf cache_ignore.tar --files-from -
|
|
||||||
find _cache/nih_c -name ".ninja_log" | tar rf cache_ignore.tar --files-from -
|
|
||||||
find _cache/nih_c -name "*.log" | tar rf cache_ignore.tar --files-from -
|
|
||||||
find _cache/nih_c -name "*.tlog" | tar rf cache_ignore.tar --files-from -
|
|
||||||
# show .a files in the cache, for sanity checking
|
|
||||||
find _cache/nih_c -name "*.a" -ls
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ -d _cache/ccache ] ; then
|
|
||||||
find _cache/ccache -name "stats" | tar rf cache_ignore.tar --files-from -
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ -f cache_ignore.tar ] ; then
|
|
||||||
tar -tf cache_ignore.tar
|
|
||||||
fi
|
|
||||||
popd
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,160 +0,0 @@
|
|||||||
//
|
|
||||||
// Copyright (c) 2013-2017 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_TEST_FAIL_COUNTER_HPP
|
|
||||||
#define BEAST_TEST_FAIL_COUNTER_HPP
|
|
||||||
|
|
||||||
#include <xrpl/beast/core/error.hpp>
|
|
||||||
#include <boost/throw_exception.hpp>
|
|
||||||
|
|
||||||
namespace beast {
|
|
||||||
namespace test {
|
|
||||||
|
|
||||||
enum class error { fail_error = 1 };
|
|
||||||
|
|
||||||
namespace detail {
|
|
||||||
|
|
||||||
class fail_error_category : public boost::system::error_category
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
const char*
|
|
||||||
name() const noexcept override
|
|
||||||
{
|
|
||||||
return "test";
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string
|
|
||||||
message(int ev) const override
|
|
||||||
{
|
|
||||||
switch (static_cast<error>(ev))
|
|
||||||
{
|
|
||||||
default:
|
|
||||||
case error::fail_error:
|
|
||||||
return "test error";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
boost::system::error_condition
|
|
||||||
default_error_condition(int ev) const noexcept override
|
|
||||||
{
|
|
||||||
return boost::system::error_condition{ev, *this};
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
equivalent(int ev, boost::system::error_condition const& condition)
|
|
||||||
const noexcept override
|
|
||||||
{
|
|
||||||
return condition.value() == ev && &condition.category() == this;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
equivalent(error_code const& error, int ev) const noexcept override
|
|
||||||
{
|
|
||||||
return error.value() == ev && &error.category() == this;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
inline boost::system::error_category const&
|
|
||||||
get_error_category()
|
|
||||||
{
|
|
||||||
static fail_error_category const cat{};
|
|
||||||
return cat;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace detail
|
|
||||||
|
|
||||||
inline error_code
|
|
||||||
make_error_code(error ev)
|
|
||||||
{
|
|
||||||
return error_code{
|
|
||||||
static_cast<std::underlying_type<error>::type>(ev),
|
|
||||||
detail::get_error_category()};
|
|
||||||
}
|
|
||||||
|
|
||||||
/** An error code with an error set on default construction
|
|
||||||
|
|
||||||
Default constructed versions of this object will have
|
|
||||||
an error code set right away. This helps tests find code
|
|
||||||
which forgets to clear the error code on success.
|
|
||||||
*/
|
|
||||||
struct fail_error_code : error_code
|
|
||||||
{
|
|
||||||
fail_error_code() : error_code(make_error_code(error::fail_error))
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class Arg0, class... ArgN>
|
|
||||||
fail_error_code(Arg0&& arg0, ArgN&&... argn)
|
|
||||||
: error_code(arg0, std::forward<ArgN>(argn)...)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/** A countdown to simulated failure.
|
|
||||||
|
|
||||||
On the Nth operation, the class will fail with the specified
|
|
||||||
error code, or the default error code of @ref error::fail_error.
|
|
||||||
*/
|
|
||||||
class fail_counter
|
|
||||||
{
|
|
||||||
std::size_t n_;
|
|
||||||
error_code ec_;
|
|
||||||
|
|
||||||
public:
|
|
||||||
fail_counter(fail_counter&&) = default;
|
|
||||||
|
|
||||||
/** Construct a counter.
|
|
||||||
|
|
||||||
@param The 0-based index of the operation to fail on or after.
|
|
||||||
*/
|
|
||||||
explicit fail_counter(
|
|
||||||
std::size_t n,
|
|
||||||
error_code ev = make_error_code(error::fail_error))
|
|
||||||
: n_(n), ec_(ev)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Throw an exception on the Nth failure
|
|
||||||
void
|
|
||||||
fail()
|
|
||||||
{
|
|
||||||
if (n_ > 0)
|
|
||||||
--n_;
|
|
||||||
if (!n_)
|
|
||||||
BOOST_THROW_EXCEPTION(system_error{ec_});
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Set an error code on the Nth failure
|
|
||||||
bool
|
|
||||||
fail(error_code& ec)
|
|
||||||
{
|
|
||||||
if (n_ > 0)
|
|
||||||
--n_;
|
|
||||||
if (!n_)
|
|
||||||
{
|
|
||||||
ec = ec_;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
ec.assign(0, ec.category());
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace test
|
|
||||||
} // namespace beast
|
|
||||||
|
|
||||||
namespace boost {
|
|
||||||
namespace system {
|
|
||||||
template <>
|
|
||||||
struct is_error_code_enum<beast::test::error>
|
|
||||||
{
|
|
||||||
static bool const value = true;
|
|
||||||
};
|
|
||||||
} // namespace system
|
|
||||||
} // namespace boost
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,182 +0,0 @@
|
|||||||
//
|
|
||||||
// Copyright (c) 2013-2017 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_TEST_FAIL_STREAM_HPP
|
|
||||||
#define BEAST_TEST_FAIL_STREAM_HPP
|
|
||||||
|
|
||||||
#include <xrpl/beast/core/async_result.hpp>
|
|
||||||
#include <xrpl/beast/core/bind_handler.hpp>
|
|
||||||
#include <xrpl/beast/core/detail/type_traits.hpp>
|
|
||||||
#include <xrpl/beast/core/error.hpp>
|
|
||||||
#include <xrpl/beast/test/fail_counter.hpp>
|
|
||||||
#include <xrpl/beast/websocket/teardown.hpp>
|
|
||||||
#include <boost/optional.hpp>
|
|
||||||
|
|
||||||
namespace beast {
|
|
||||||
namespace test {
|
|
||||||
|
|
||||||
/** A stream wrapper that fails.
|
|
||||||
|
|
||||||
On the Nth operation, the stream will fail with the specified
|
|
||||||
error code, or the default error code of invalid_argument.
|
|
||||||
*/
|
|
||||||
template <class NextLayer>
|
|
||||||
class fail_stream
|
|
||||||
{
|
|
||||||
boost::optional<fail_counter> fc_;
|
|
||||||
fail_counter* pfc_;
|
|
||||||
NextLayer next_layer_;
|
|
||||||
|
|
||||||
public:
|
|
||||||
using next_layer_type = typename std::remove_reference<NextLayer>::type;
|
|
||||||
|
|
||||||
using lowest_layer_type = typename get_lowest_layer<next_layer_type>::type;
|
|
||||||
|
|
||||||
fail_stream(fail_stream&&) = delete;
|
|
||||||
fail_stream(fail_stream const&) = delete;
|
|
||||||
fail_stream&
|
|
||||||
operator=(fail_stream&&) = delete;
|
|
||||||
fail_stream&
|
|
||||||
operator=(fail_stream const&) = delete;
|
|
||||||
|
|
||||||
template <class... Args>
|
|
||||||
explicit fail_stream(std::size_t n, Args&&... args)
|
|
||||||
: fc_(n), pfc_(&*fc_), next_layer_(std::forward<Args>(args)...)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class... Args>
|
|
||||||
explicit fail_stream(fail_counter& fc, Args&&... args)
|
|
||||||
: pfc_(&fc), next_layer_(std::forward<Args>(args)...)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
next_layer_type&
|
|
||||||
next_layer()
|
|
||||||
{
|
|
||||||
return next_layer_;
|
|
||||||
}
|
|
||||||
|
|
||||||
lowest_layer_type&
|
|
||||||
lowest_layer()
|
|
||||||
{
|
|
||||||
return next_layer_.lowest_layer();
|
|
||||||
}
|
|
||||||
|
|
||||||
lowest_layer_type const&
|
|
||||||
lowest_layer() const
|
|
||||||
{
|
|
||||||
return next_layer_.lowest_layer();
|
|
||||||
}
|
|
||||||
|
|
||||||
boost::asio::io_service&
|
|
||||||
get_io_service()
|
|
||||||
{
|
|
||||||
return next_layer_.get_io_service();
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class MutableBufferSequence>
|
|
||||||
std::size_t
|
|
||||||
read_some(MutableBufferSequence const& buffers)
|
|
||||||
{
|
|
||||||
pfc_->fail();
|
|
||||||
return next_layer_.read_some(buffers);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class MutableBufferSequence>
|
|
||||||
std::size_t
|
|
||||||
read_some(MutableBufferSequence const& buffers, error_code& ec)
|
|
||||||
{
|
|
||||||
if (pfc_->fail(ec))
|
|
||||||
return 0;
|
|
||||||
return next_layer_.read_some(buffers, ec);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class MutableBufferSequence, class ReadHandler>
|
|
||||||
async_return_type<ReadHandler, void(error_code, std::size_t)>
|
|
||||||
async_read_some(MutableBufferSequence const& buffers, ReadHandler&& handler)
|
|
||||||
{
|
|
||||||
error_code ec;
|
|
||||||
if (pfc_->fail(ec))
|
|
||||||
{
|
|
||||||
async_completion<ReadHandler, void(error_code, std::size_t)> init{
|
|
||||||
handler};
|
|
||||||
next_layer_.get_io_service().post(
|
|
||||||
bind_handler(init.completion_handler, ec, 0));
|
|
||||||
return init.result.get();
|
|
||||||
}
|
|
||||||
return next_layer_.async_read_some(
|
|
||||||
buffers, std::forward<ReadHandler>(handler));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class ConstBufferSequence>
|
|
||||||
std::size_t
|
|
||||||
write_some(ConstBufferSequence const& buffers)
|
|
||||||
{
|
|
||||||
pfc_->fail();
|
|
||||||
return next_layer_.write_some(buffers);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class ConstBufferSequence>
|
|
||||||
std::size_t
|
|
||||||
write_some(ConstBufferSequence const& buffers, error_code& ec)
|
|
||||||
{
|
|
||||||
if (pfc_->fail(ec))
|
|
||||||
return 0;
|
|
||||||
return next_layer_.write_some(buffers, ec);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class ConstBufferSequence, class WriteHandler>
|
|
||||||
async_return_type<WriteHandler, void(error_code, std::size_t)>
|
|
||||||
async_write_some(ConstBufferSequence const& buffers, WriteHandler&& handler)
|
|
||||||
{
|
|
||||||
error_code ec;
|
|
||||||
if (pfc_->fail(ec))
|
|
||||||
{
|
|
||||||
async_completion<WriteHandler, void(error_code, std::size_t)> init{
|
|
||||||
handler};
|
|
||||||
next_layer_.get_io_service().post(
|
|
||||||
bind_handler(init.completion_handler, ec, 0));
|
|
||||||
return init.result.get();
|
|
||||||
}
|
|
||||||
return next_layer_.async_write_some(
|
|
||||||
buffers, std::forward<WriteHandler>(handler));
|
|
||||||
}
|
|
||||||
|
|
||||||
friend void
|
|
||||||
teardown(
|
|
||||||
websocket::teardown_tag,
|
|
||||||
fail_stream<NextLayer>& stream,
|
|
||||||
boost::system::error_code& ec)
|
|
||||||
{
|
|
||||||
if (stream.pfc_->fail(ec))
|
|
||||||
return;
|
|
||||||
beast::websocket_helpers::call_teardown(stream.next_layer(), ec);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class TeardownHandler>
|
|
||||||
friend void
|
|
||||||
async_teardown(
|
|
||||||
websocket::teardown_tag,
|
|
||||||
fail_stream<NextLayer>& stream,
|
|
||||||
TeardownHandler&& handler)
|
|
||||||
{
|
|
||||||
error_code ec;
|
|
||||||
if (stream.pfc_->fail(ec))
|
|
||||||
{
|
|
||||||
stream.get_io_service().post(bind_handler(std::move(handler), ec));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
beast::websocket_helpers::call_async_teardown(
|
|
||||||
stream.next_layer(), std::forward<TeardownHandler>(handler));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace test
|
|
||||||
} // namespace beast
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,482 +0,0 @@
|
|||||||
//
|
|
||||||
// Copyright (c) 2013-2017 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_TEST_PIPE_STREAM_HPP
|
|
||||||
#define BEAST_TEST_PIPE_STREAM_HPP
|
|
||||||
|
|
||||||
#include <xrpl/beast/core/async_result.hpp>
|
|
||||||
#include <xrpl/beast/core/bind_handler.hpp>
|
|
||||||
#include <xrpl/beast/core/flat_buffer.hpp>
|
|
||||||
#include <xrpl/beast/core/string.hpp>
|
|
||||||
#include <xrpl/beast/core/type_traits.hpp>
|
|
||||||
#include <xrpl/beast/test/fail_counter.hpp>
|
|
||||||
#include <xrpl/beast/websocket/teardown.hpp>
|
|
||||||
#include <boost/asio/buffer.hpp>
|
|
||||||
#include <boost/asio/io_service.hpp>
|
|
||||||
#include <boost/assert.hpp>
|
|
||||||
#include <boost/throw_exception.hpp>
|
|
||||||
#include <condition_variable>
|
|
||||||
#include <limits>
|
|
||||||
#include <mutex>
|
|
||||||
#include <utility>
|
|
||||||
|
|
||||||
namespace beast {
|
|
||||||
namespace test {
|
|
||||||
|
|
||||||
/** A bidirectional in-memory communication channel
|
|
||||||
|
|
||||||
An instance of this class provides a client and server
|
|
||||||
endpoint that are automatically connected to each other
|
|
||||||
similarly to a connected socket.
|
|
||||||
|
|
||||||
Test pipes are used to facilitate writing unit tests
|
|
||||||
where the behavior of the transport is tightly controlled
|
|
||||||
to help illuminate all code paths (for code coverage)
|
|
||||||
*/
|
|
||||||
class pipe
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
using buffer_type = flat_buffer;
|
|
||||||
|
|
||||||
private:
|
|
||||||
struct read_op
|
|
||||||
{
|
|
||||||
virtual ~read_op() = default;
|
|
||||||
virtual void
|
|
||||||
operator()() = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct state
|
|
||||||
{
|
|
||||||
std::mutex m;
|
|
||||||
buffer_type b;
|
|
||||||
std::condition_variable cv;
|
|
||||||
std::unique_ptr<read_op> op;
|
|
||||||
bool eof = false;
|
|
||||||
};
|
|
||||||
|
|
||||||
state s_[2];
|
|
||||||
|
|
||||||
public:
|
|
||||||
/** Represents an endpoint.
|
|
||||||
|
|
||||||
Each pipe has a client stream and a server stream.
|
|
||||||
*/
|
|
||||||
class stream
|
|
||||||
{
|
|
||||||
friend class pipe;
|
|
||||||
|
|
||||||
template <class Handler, class Buffers>
|
|
||||||
class read_op_impl;
|
|
||||||
|
|
||||||
state& in_;
|
|
||||||
state& out_;
|
|
||||||
boost::asio::io_service& ios_;
|
|
||||||
fail_counter* fc_ = nullptr;
|
|
||||||
std::size_t read_max_ = (std::numeric_limits<std::size_t>::max)();
|
|
||||||
std::size_t write_max_ = (std::numeric_limits<std::size_t>::max)();
|
|
||||||
|
|
||||||
stream(state& in, state& out, boost::asio::io_service& ios)
|
|
||||||
: in_(in), out_(out), ios_(ios), buffer(in_.b)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
using buffer_type = pipe::buffer_type;
|
|
||||||
|
|
||||||
/// Direct access to the underlying buffer
|
|
||||||
buffer_type& buffer;
|
|
||||||
|
|
||||||
/// Counts the number of read calls
|
|
||||||
std::size_t nread = 0;
|
|
||||||
|
|
||||||
/// Counts the number of write calls
|
|
||||||
std::size_t nwrite = 0;
|
|
||||||
|
|
||||||
~stream() = default;
|
|
||||||
stream(stream&&) = default;
|
|
||||||
|
|
||||||
/// Set the fail counter on the object
|
|
||||||
void
|
|
||||||
fail(fail_counter& fc)
|
|
||||||
{
|
|
||||||
fc_ = &fc;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return the `io_service` associated with the object
|
|
||||||
boost::asio::io_service&
|
|
||||||
get_io_service()
|
|
||||||
{
|
|
||||||
return ios_;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Set the maximum number of bytes returned by read_some
|
|
||||||
void
|
|
||||||
read_size(std::size_t n)
|
|
||||||
{
|
|
||||||
read_max_ = n;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Set the maximum number of bytes returned by write_some
|
|
||||||
void
|
|
||||||
write_size(std::size_t n)
|
|
||||||
{
|
|
||||||
write_max_ = n;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns a string representing the pending input data
|
|
||||||
string_view
|
|
||||||
str() const
|
|
||||||
{
|
|
||||||
using boost::asio::buffer_cast;
|
|
||||||
using boost::asio::buffer_size;
|
|
||||||
return {
|
|
||||||
buffer_cast<char const*>(*in_.b.data().begin()),
|
|
||||||
buffer_size(*in_.b.data().begin())};
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Clear the buffer holding the input data
|
|
||||||
void
|
|
||||||
clear()
|
|
||||||
{
|
|
||||||
in_.b.consume((std::numeric_limits<std::size_t>::max)());
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Close the stream.
|
|
||||||
|
|
||||||
The other end of the pipe will see
|
|
||||||
`boost::asio::error::eof` on read.
|
|
||||||
*/
|
|
||||||
template <class = void>
|
|
||||||
void
|
|
||||||
close();
|
|
||||||
|
|
||||||
template <class MutableBufferSequence>
|
|
||||||
std::size_t
|
|
||||||
read_some(MutableBufferSequence const& buffers);
|
|
||||||
|
|
||||||
template <class MutableBufferSequence>
|
|
||||||
std::size_t
|
|
||||||
read_some(MutableBufferSequence const& buffers, error_code& ec);
|
|
||||||
|
|
||||||
template <class MutableBufferSequence, class ReadHandler>
|
|
||||||
async_return_type<ReadHandler, void(error_code, std::size_t)>
|
|
||||||
async_read_some(
|
|
||||||
MutableBufferSequence const& buffers,
|
|
||||||
ReadHandler&& handler);
|
|
||||||
|
|
||||||
template <class ConstBufferSequence>
|
|
||||||
std::size_t
|
|
||||||
write_some(ConstBufferSequence const& buffers);
|
|
||||||
|
|
||||||
template <class ConstBufferSequence>
|
|
||||||
std::size_t
|
|
||||||
write_some(ConstBufferSequence const& buffers, error_code&);
|
|
||||||
|
|
||||||
template <class ConstBufferSequence, class WriteHandler>
|
|
||||||
async_return_type<WriteHandler, void(error_code, std::size_t)>
|
|
||||||
async_write_some(
|
|
||||||
ConstBufferSequence const& buffers,
|
|
||||||
WriteHandler&& handler);
|
|
||||||
|
|
||||||
friend void
|
|
||||||
teardown(
|
|
||||||
websocket::teardown_tag,
|
|
||||||
stream&,
|
|
||||||
boost::system::error_code& ec)
|
|
||||||
{
|
|
||||||
ec.assign(0, ec.category());
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class TeardownHandler>
|
|
||||||
friend void
|
|
||||||
async_teardown(
|
|
||||||
websocket::teardown_tag,
|
|
||||||
stream& s,
|
|
||||||
TeardownHandler&& handler)
|
|
||||||
{
|
|
||||||
s.get_io_service().post(
|
|
||||||
bind_handler(std::move(handler), error_code{}));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/** Constructor.
|
|
||||||
|
|
||||||
The client and server endpoints will use the same `io_service`.
|
|
||||||
*/
|
|
||||||
explicit pipe(boost::asio::io_service& ios)
|
|
||||||
: client(s_[0], s_[1], ios), server(s_[1], s_[0], ios)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Constructor.
|
|
||||||
|
|
||||||
The client and server endpoints will different `io_service` objects.
|
|
||||||
*/
|
|
||||||
explicit pipe(boost::asio::io_service& ios1, boost::asio::io_service& ios2)
|
|
||||||
: client(s_[0], s_[1], ios1), server(s_[1], s_[0], ios2)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Represents the client endpoint
|
|
||||||
stream client;
|
|
||||||
|
|
||||||
/// Represents the server endpoint
|
|
||||||
stream server;
|
|
||||||
};
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
template <class Handler, class Buffers>
|
|
||||||
class pipe::stream::read_op_impl : public pipe::read_op
|
|
||||||
{
|
|
||||||
stream& s_;
|
|
||||||
Buffers b_;
|
|
||||||
Handler h_;
|
|
||||||
|
|
||||||
public:
|
|
||||||
read_op_impl(stream& s, Buffers const& b, Handler&& h)
|
|
||||||
: s_(s), b_(b), h_(std::move(h))
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
read_op_impl(stream& s, Buffers const& b, Handler const& h)
|
|
||||||
: s_(s), b_(b), h_(h)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
operator()() override;
|
|
||||||
};
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
template <class Handler, class Buffers>
|
|
||||||
void
|
|
||||||
pipe::stream::read_op_impl<Handler, Buffers>::operator()()
|
|
||||||
{
|
|
||||||
using boost::asio::buffer_copy;
|
|
||||||
using boost::asio::buffer_size;
|
|
||||||
s_.ios_.post([&]() {
|
|
||||||
BOOST_ASSERT(s_.in_.op);
|
|
||||||
std::unique_lock<std::mutex> lock{s_.in_.m};
|
|
||||||
if (s_.in_.b.size() > 0)
|
|
||||||
{
|
|
||||||
auto const bytes_transferred =
|
|
||||||
buffer_copy(b_, s_.in_.b.data(), s_.read_max_);
|
|
||||||
s_.in_.b.consume(bytes_transferred);
|
|
||||||
auto& s = s_;
|
|
||||||
Handler h{std::move(h_)};
|
|
||||||
lock.unlock();
|
|
||||||
s.in_.op.reset(nullptr);
|
|
||||||
++s.nread;
|
|
||||||
s.ios_.post(
|
|
||||||
bind_handler(std::move(h), error_code{}, bytes_transferred));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
BOOST_ASSERT(s_.in_.eof);
|
|
||||||
auto& s = s_;
|
|
||||||
Handler h{std::move(h_)};
|
|
||||||
lock.unlock();
|
|
||||||
s.in_.op.reset(nullptr);
|
|
||||||
++s.nread;
|
|
||||||
s.ios_.post(bind_handler(std::move(h), boost::asio::error::eof, 0));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
template <class>
|
|
||||||
void
|
|
||||||
pipe::stream::close()
|
|
||||||
{
|
|
||||||
std::lock_guard lock{out_.m};
|
|
||||||
out_.eof = true;
|
|
||||||
if (out_.op)
|
|
||||||
out_.op.get()->operator()();
|
|
||||||
else
|
|
||||||
out_.cv.notify_all();
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class MutableBufferSequence>
|
|
||||||
std::size_t
|
|
||||||
pipe::stream::read_some(MutableBufferSequence const& buffers)
|
|
||||||
{
|
|
||||||
static_assert(
|
|
||||||
is_mutable_buffer_sequence<MutableBufferSequence>::value,
|
|
||||||
"MutableBufferSequence requirements not met");
|
|
||||||
error_code ec;
|
|
||||||
auto const n = read_some(buffers, ec);
|
|
||||||
if (ec)
|
|
||||||
BOOST_THROW_EXCEPTION(system_error{ec});
|
|
||||||
return n;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class MutableBufferSequence>
|
|
||||||
std::size_t
|
|
||||||
pipe::stream::read_some(MutableBufferSequence const& buffers, error_code& ec)
|
|
||||||
{
|
|
||||||
static_assert(
|
|
||||||
is_mutable_buffer_sequence<MutableBufferSequence>::value,
|
|
||||||
"MutableBufferSequence requirements not met");
|
|
||||||
using boost::asio::buffer_copy;
|
|
||||||
using boost::asio::buffer_size;
|
|
||||||
BOOST_ASSERT(!in_.op);
|
|
||||||
BOOST_ASSERT(buffer_size(buffers) > 0);
|
|
||||||
if (fc_ && fc_->fail(ec))
|
|
||||||
return 0;
|
|
||||||
std::unique_lock<std::mutex> lock{in_.m};
|
|
||||||
in_.cv.wait(lock, [&]() { return in_.b.size() > 0 || in_.eof; });
|
|
||||||
std::size_t bytes_transferred;
|
|
||||||
if (in_.b.size() > 0)
|
|
||||||
{
|
|
||||||
ec.assign(0, ec.category());
|
|
||||||
bytes_transferred = buffer_copy(buffers, in_.b.data(), read_max_);
|
|
||||||
in_.b.consume(bytes_transferred);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
BOOST_ASSERT(in_.eof);
|
|
||||||
bytes_transferred = 0;
|
|
||||||
ec = boost::asio::error::eof;
|
|
||||||
}
|
|
||||||
++nread;
|
|
||||||
return bytes_transferred;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class MutableBufferSequence, class ReadHandler>
|
|
||||||
async_return_type<ReadHandler, void(error_code, std::size_t)>
|
|
||||||
pipe::stream::async_read_some(
|
|
||||||
MutableBufferSequence const& buffers,
|
|
||||||
ReadHandler&& handler)
|
|
||||||
{
|
|
||||||
static_assert(
|
|
||||||
is_mutable_buffer_sequence<MutableBufferSequence>::value,
|
|
||||||
"MutableBufferSequence requirements not met");
|
|
||||||
using boost::asio::buffer_copy;
|
|
||||||
using boost::asio::buffer_size;
|
|
||||||
BOOST_ASSERT(!in_.op);
|
|
||||||
BOOST_ASSERT(buffer_size(buffers) > 0);
|
|
||||||
async_completion<ReadHandler, void(error_code, std::size_t)> init{handler};
|
|
||||||
if (fc_)
|
|
||||||
{
|
|
||||||
error_code ec;
|
|
||||||
if (fc_->fail(ec))
|
|
||||||
return ios_.post(bind_handler(init.completion_handler, ec, 0));
|
|
||||||
}
|
|
||||||
{
|
|
||||||
std::unique_lock<std::mutex> lock{in_.m};
|
|
||||||
if (in_.eof)
|
|
||||||
{
|
|
||||||
lock.unlock();
|
|
||||||
++nread;
|
|
||||||
ios_.post(bind_handler(
|
|
||||||
init.completion_handler, boost::asio::error::eof, 0));
|
|
||||||
}
|
|
||||||
else if (buffer_size(buffers) == 0 || buffer_size(in_.b.data()) > 0)
|
|
||||||
{
|
|
||||||
auto const bytes_transferred =
|
|
||||||
buffer_copy(buffers, in_.b.data(), read_max_);
|
|
||||||
in_.b.consume(bytes_transferred);
|
|
||||||
lock.unlock();
|
|
||||||
++nread;
|
|
||||||
ios_.post(bind_handler(
|
|
||||||
init.completion_handler, error_code{}, bytes_transferred));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
in_.op.reset(
|
|
||||||
new read_op_impl<
|
|
||||||
handler_type<ReadHandler, void(error_code, std::size_t)>,
|
|
||||||
MutableBufferSequence>{
|
|
||||||
*this, buffers, init.completion_handler});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return init.result.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class ConstBufferSequence>
|
|
||||||
std::size_t
|
|
||||||
pipe::stream::write_some(ConstBufferSequence const& buffers)
|
|
||||||
{
|
|
||||||
static_assert(
|
|
||||||
is_const_buffer_sequence<ConstBufferSequence>::value,
|
|
||||||
"ConstBufferSequence requirements not met");
|
|
||||||
BOOST_ASSERT(!out_.eof);
|
|
||||||
error_code ec;
|
|
||||||
auto const bytes_transferred = write_some(buffers, ec);
|
|
||||||
if (ec)
|
|
||||||
BOOST_THROW_EXCEPTION(system_error{ec});
|
|
||||||
return bytes_transferred;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class ConstBufferSequence>
|
|
||||||
std::size_t
|
|
||||||
pipe::stream::write_some(ConstBufferSequence const& buffers, error_code& ec)
|
|
||||||
{
|
|
||||||
static_assert(
|
|
||||||
is_const_buffer_sequence<ConstBufferSequence>::value,
|
|
||||||
"ConstBufferSequence requirements not met");
|
|
||||||
using boost::asio::buffer_copy;
|
|
||||||
using boost::asio::buffer_size;
|
|
||||||
BOOST_ASSERT(!out_.eof);
|
|
||||||
if (fc_ && fc_->fail(ec))
|
|
||||||
return 0;
|
|
||||||
auto const n = (std::min)(buffer_size(buffers), write_max_);
|
|
||||||
std::unique_lock<std::mutex> lock{out_.m};
|
|
||||||
auto const bytes_transferred = buffer_copy(out_.b.prepare(n), buffers);
|
|
||||||
out_.b.commit(bytes_transferred);
|
|
||||||
lock.unlock();
|
|
||||||
if (out_.op)
|
|
||||||
out_.op.get()->operator()();
|
|
||||||
else
|
|
||||||
out_.cv.notify_all();
|
|
||||||
++nwrite;
|
|
||||||
ec.assign(0, ec.category());
|
|
||||||
return bytes_transferred;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class ConstBufferSequence, class WriteHandler>
|
|
||||||
async_return_type<WriteHandler, void(error_code, std::size_t)>
|
|
||||||
pipe::stream::async_write_some(
|
|
||||||
ConstBufferSequence const& buffers,
|
|
||||||
WriteHandler&& handler)
|
|
||||||
{
|
|
||||||
static_assert(
|
|
||||||
is_const_buffer_sequence<ConstBufferSequence>::value,
|
|
||||||
"ConstBufferSequence requirements not met");
|
|
||||||
using boost::asio::buffer_copy;
|
|
||||||
using boost::asio::buffer_size;
|
|
||||||
BOOST_ASSERT(!out_.eof);
|
|
||||||
async_completion<WriteHandler, void(error_code, std::size_t)> init{handler};
|
|
||||||
if (fc_)
|
|
||||||
{
|
|
||||||
error_code ec;
|
|
||||||
if (fc_->fail(ec))
|
|
||||||
return ios_.post(bind_handler(init.completion_handler, ec, 0));
|
|
||||||
}
|
|
||||||
auto const n = (std::min)(buffer_size(buffers), write_max_);
|
|
||||||
std::unique_lock<std::mutex> lock{out_.m};
|
|
||||||
auto const bytes_transferred = buffer_copy(out_.b.prepare(n), buffers);
|
|
||||||
out_.b.commit(bytes_transferred);
|
|
||||||
lock.unlock();
|
|
||||||
if (out_.op)
|
|
||||||
out_.op.get()->operator()();
|
|
||||||
else
|
|
||||||
out_.cv.notify_all();
|
|
||||||
++nwrite;
|
|
||||||
ios_.post(
|
|
||||||
bind_handler(init.completion_handler, error_code{}, bytes_transferred));
|
|
||||||
return init.result.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace test
|
|
||||||
} // namespace beast
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
//
|
|
||||||
// Copyright (c) 2013-2017 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_TEST_SIG_WAIT_HPP
|
|
||||||
#define BEAST_TEST_SIG_WAIT_HPP
|
|
||||||
|
|
||||||
#include <boost/asio.hpp>
|
|
||||||
|
|
||||||
namespace beast {
|
|
||||||
namespace test {
|
|
||||||
|
|
||||||
/// Block until SIGINT or SIGTERM is received.
|
|
||||||
inline void
|
|
||||||
sig_wait()
|
|
||||||
{
|
|
||||||
boost::asio::io_service ios;
|
|
||||||
boost::asio::signal_set signals(ios, SIGINT, SIGTERM);
|
|
||||||
signals.async_wait([&](boost::system::error_code const&, int) {});
|
|
||||||
ios.run();
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace test
|
|
||||||
} // namespace beast
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,166 +0,0 @@
|
|||||||
//
|
|
||||||
// Copyright (c) 2013-2017 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_TEST_STRING_IOSTREAM_HPP
|
|
||||||
#define BEAST_TEST_STRING_IOSTREAM_HPP
|
|
||||||
|
|
||||||
#include <xrpl/beast/core/async_result.hpp>
|
|
||||||
#include <xrpl/beast/core/bind_handler.hpp>
|
|
||||||
#include <xrpl/beast/core/buffer_prefix.hpp>
|
|
||||||
#include <xrpl/beast/core/error.hpp>
|
|
||||||
#include <xrpl/beast/websocket/teardown.hpp>
|
|
||||||
#include <boost/asio/buffer.hpp>
|
|
||||||
#include <boost/asio/io_service.hpp>
|
|
||||||
#include <boost/throw_exception.hpp>
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
namespace beast {
|
|
||||||
namespace test {
|
|
||||||
|
|
||||||
/** A SyncStream and AsyncStream that reads from a string and writes to another
|
|
||||||
string.
|
|
||||||
|
|
||||||
This class behaves like a socket, except that written data is
|
|
||||||
appended to a string exposed as a public data member, and when
|
|
||||||
data is read it comes from a string provided at construction.
|
|
||||||
*/
|
|
||||||
class string_iostream
|
|
||||||
{
|
|
||||||
std::string s_;
|
|
||||||
boost::asio::const_buffer cb_;
|
|
||||||
boost::asio::io_service& ios_;
|
|
||||||
std::size_t read_max_;
|
|
||||||
|
|
||||||
public:
|
|
||||||
std::string str;
|
|
||||||
|
|
||||||
string_iostream(
|
|
||||||
boost::asio::io_service& ios,
|
|
||||||
std::string s,
|
|
||||||
std::size_t read_max = (std::numeric_limits<std::size_t>::max)())
|
|
||||||
: s_(std::move(s))
|
|
||||||
, cb_(boost::asio::buffer(s_))
|
|
||||||
, ios_(ios)
|
|
||||||
, read_max_(read_max)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
boost::asio::io_service&
|
|
||||||
get_io_service()
|
|
||||||
{
|
|
||||||
return ios_;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class MutableBufferSequence>
|
|
||||||
std::size_t
|
|
||||||
read_some(MutableBufferSequence const& buffers)
|
|
||||||
{
|
|
||||||
error_code ec;
|
|
||||||
auto const n = read_some(buffers, ec);
|
|
||||||
if (ec)
|
|
||||||
BOOST_THROW_EXCEPTION(system_error{ec});
|
|
||||||
return n;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class MutableBufferSequence>
|
|
||||||
std::size_t
|
|
||||||
read_some(MutableBufferSequence const& buffers, error_code& ec)
|
|
||||||
{
|
|
||||||
auto const n =
|
|
||||||
boost::asio::buffer_copy(buffers, buffer_prefix(read_max_, cb_));
|
|
||||||
if (n > 0)
|
|
||||||
{
|
|
||||||
ec.assign(0, ec.category());
|
|
||||||
cb_ = cb_ + n;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ec = boost::asio::error::eof;
|
|
||||||
}
|
|
||||||
return n;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class MutableBufferSequence, class ReadHandler>
|
|
||||||
async_return_type<ReadHandler, void(error_code, std::size_t)>
|
|
||||||
async_read_some(MutableBufferSequence const& buffers, ReadHandler&& handler)
|
|
||||||
{
|
|
||||||
auto const n =
|
|
||||||
boost::asio::buffer_copy(buffers, boost::asio::buffer(s_));
|
|
||||||
error_code ec;
|
|
||||||
if (n > 0)
|
|
||||||
s_.erase(0, n);
|
|
||||||
else
|
|
||||||
ec = boost::asio::error::eof;
|
|
||||||
async_completion<ReadHandler, void(error_code, std::size_t)> init{
|
|
||||||
handler};
|
|
||||||
ios_.post(bind_handler(init.completion_handler, ec, n));
|
|
||||||
return init.result.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class ConstBufferSequence>
|
|
||||||
std::size_t
|
|
||||||
write_some(ConstBufferSequence const& buffers)
|
|
||||||
{
|
|
||||||
error_code ec;
|
|
||||||
auto const n = write_some(buffers, ec);
|
|
||||||
if (ec)
|
|
||||||
BOOST_THROW_EXCEPTION(system_error{ec});
|
|
||||||
return n;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class ConstBufferSequence>
|
|
||||||
std::size_t
|
|
||||||
write_some(ConstBufferSequence const& buffers, error_code& ec)
|
|
||||||
{
|
|
||||||
ec.assign(0, ec.category());
|
|
||||||
using boost::asio::buffer_cast;
|
|
||||||
using boost::asio::buffer_size;
|
|
||||||
auto const n = buffer_size(buffers);
|
|
||||||
str.reserve(str.size() + n);
|
|
||||||
for (boost::asio::const_buffer buffer : buffers)
|
|
||||||
str.append(buffer_cast<char const*>(buffer), buffer_size(buffer));
|
|
||||||
return n;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class ConstBufferSequence, class WriteHandler>
|
|
||||||
async_return_type<WriteHandler, void(error_code, std::size_t)>
|
|
||||||
async_write_some(ConstBufferSequence const& buffers, WriteHandler&& handler)
|
|
||||||
{
|
|
||||||
error_code ec;
|
|
||||||
auto const bytes_transferred = write_some(buffers, ec);
|
|
||||||
async_completion<WriteHandler, void(error_code, std::size_t)> init{
|
|
||||||
handler};
|
|
||||||
get_io_service().post(
|
|
||||||
bind_handler(init.completion_handler, ec, bytes_transferred));
|
|
||||||
return init.result.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
friend void
|
|
||||||
teardown(
|
|
||||||
websocket::teardown_tag,
|
|
||||||
string_iostream&,
|
|
||||||
boost::system::error_code& ec)
|
|
||||||
{
|
|
||||||
ec.assign(0, ec.category());
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class TeardownHandler>
|
|
||||||
friend void
|
|
||||||
async_teardown(
|
|
||||||
websocket::teardown_tag,
|
|
||||||
string_iostream& stream,
|
|
||||||
TeardownHandler&& handler)
|
|
||||||
{
|
|
||||||
stream.get_io_service().post(
|
|
||||||
bind_handler(std::move(handler), error_code{}));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace test
|
|
||||||
} // namespace beast
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,155 +0,0 @@
|
|||||||
//
|
|
||||||
// Copyright (c) 2013-2017 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_TEST_STRING_ISTREAM_HPP
|
|
||||||
#define BEAST_TEST_STRING_ISTREAM_HPP
|
|
||||||
|
|
||||||
#include <xrpl/beast/core/async_result.hpp>
|
|
||||||
#include <xrpl/beast/core/bind_handler.hpp>
|
|
||||||
#include <xrpl/beast/core/error.hpp>
|
|
||||||
#include <xrpl/beast/websocket/teardown.hpp>
|
|
||||||
#include <boost/asio/buffer.hpp>
|
|
||||||
#include <boost/asio/io_service.hpp>
|
|
||||||
#include <boost/throw_exception.hpp>
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
namespace beast {
|
|
||||||
namespace test {
|
|
||||||
|
|
||||||
/** A SyncStream and AsyncStream that reads from a string.
|
|
||||||
|
|
||||||
This class behaves like a socket, except that written data is simply
|
|
||||||
discarded, and when data is read it comes from a string provided
|
|
||||||
at construction.
|
|
||||||
*/
|
|
||||||
class string_istream
|
|
||||||
{
|
|
||||||
std::string s_;
|
|
||||||
boost::asio::const_buffer cb_;
|
|
||||||
boost::asio::io_service& ios_;
|
|
||||||
std::size_t read_max_;
|
|
||||||
|
|
||||||
public:
|
|
||||||
string_istream(
|
|
||||||
boost::asio::io_service& ios,
|
|
||||||
std::string s,
|
|
||||||
std::size_t read_max = (std::numeric_limits<std::size_t>::max)())
|
|
||||||
: s_(std::move(s))
|
|
||||||
, cb_(boost::asio::buffer(s_))
|
|
||||||
, ios_(ios)
|
|
||||||
, read_max_(read_max)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
boost::asio::io_service&
|
|
||||||
get_io_service()
|
|
||||||
{
|
|
||||||
return ios_;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class MutableBufferSequence>
|
|
||||||
std::size_t
|
|
||||||
read_some(MutableBufferSequence const& buffers)
|
|
||||||
{
|
|
||||||
error_code ec;
|
|
||||||
auto const n = read_some(buffers, ec);
|
|
||||||
if (ec)
|
|
||||||
BOOST_THROW_EXCEPTION(system_error{ec});
|
|
||||||
return n;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class MutableBufferSequence>
|
|
||||||
std::size_t
|
|
||||||
read_some(MutableBufferSequence const& buffers, error_code& ec)
|
|
||||||
{
|
|
||||||
auto const n = boost::asio::buffer_copy(buffers, cb_, read_max_);
|
|
||||||
if (n > 0)
|
|
||||||
{
|
|
||||||
ec.assign(0, ec.category());
|
|
||||||
cb_ = cb_ + n;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ec = boost::asio::error::eof;
|
|
||||||
}
|
|
||||||
return n;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class MutableBufferSequence, class ReadHandler>
|
|
||||||
async_return_type<ReadHandler, void(error_code, std::size_t)>
|
|
||||||
async_read_some(MutableBufferSequence const& buffers, ReadHandler&& handler)
|
|
||||||
{
|
|
||||||
auto const n =
|
|
||||||
boost::asio::buffer_copy(buffers, boost::asio::buffer(s_));
|
|
||||||
error_code ec;
|
|
||||||
if (n > 0)
|
|
||||||
s_.erase(0, n);
|
|
||||||
else
|
|
||||||
ec = boost::asio::error::eof;
|
|
||||||
async_completion<ReadHandler, void(error_code, std::size_t)> init{
|
|
||||||
handler};
|
|
||||||
ios_.post(bind_handler(init.completion_handler, ec, n));
|
|
||||||
return init.result.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class ConstBufferSequence>
|
|
||||||
std::size_t
|
|
||||||
write_some(ConstBufferSequence const& buffers)
|
|
||||||
{
|
|
||||||
error_code ec;
|
|
||||||
auto const n = write_some(buffers, ec);
|
|
||||||
if (ec)
|
|
||||||
BOOST_THROW_EXCEPTION(system_error{ec});
|
|
||||||
return n;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class ConstBufferSequence>
|
|
||||||
std::size_t
|
|
||||||
write_some(ConstBufferSequence const& buffers, error_code& ec)
|
|
||||||
{
|
|
||||||
ec.assign(0, ec.category());
|
|
||||||
return boost::asio::buffer_size(buffers);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class ConstBuffeSequence, class WriteHandler>
|
|
||||||
async_return_type<WriteHandler, void(error_code, std::size_t)>
|
|
||||||
async_write_some(ConstBuffeSequence const& buffers, WriteHandler&& handler)
|
|
||||||
{
|
|
||||||
async_completion<WriteHandler, void(error_code, std::size_t)> init{
|
|
||||||
handler};
|
|
||||||
ios_.post(bind_handler(
|
|
||||||
init.completion_handler,
|
|
||||||
error_code{},
|
|
||||||
boost::asio::buffer_size(buffers)));
|
|
||||||
return init.result.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
friend void
|
|
||||||
teardown(
|
|
||||||
websocket::teardown_tag,
|
|
||||||
string_istream&,
|
|
||||||
boost::system::error_code& ec)
|
|
||||||
{
|
|
||||||
ec.assign(0, ec.category());
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class TeardownHandler>
|
|
||||||
friend void
|
|
||||||
async_teardown(
|
|
||||||
websocket::teardown_tag,
|
|
||||||
string_istream& stream,
|
|
||||||
TeardownHandler&& handler)
|
|
||||||
{
|
|
||||||
stream.get_io_service().post(
|
|
||||||
bind_handler(std::move(handler), error_code{}));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace test
|
|
||||||
} // namespace beast
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,137 +0,0 @@
|
|||||||
//
|
|
||||||
// Copyright (c) 2013-2017 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_TEST_STRING_OSTREAM_HPP
|
|
||||||
#define BEAST_TEST_STRING_OSTREAM_HPP
|
|
||||||
|
|
||||||
#include <xrpl/beast/core/async_result.hpp>
|
|
||||||
#include <xrpl/beast/core/bind_handler.hpp>
|
|
||||||
#include <xrpl/beast/core/buffer_prefix.hpp>
|
|
||||||
#include <xrpl/beast/core/error.hpp>
|
|
||||||
#include <xrpl/beast/websocket/teardown.hpp>
|
|
||||||
#include <boost/asio/buffer.hpp>
|
|
||||||
#include <boost/asio/io_service.hpp>
|
|
||||||
#include <boost/throw_exception.hpp>
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
namespace beast {
|
|
||||||
namespace test {
|
|
||||||
|
|
||||||
class string_ostream
|
|
||||||
{
|
|
||||||
boost::asio::io_service& ios_;
|
|
||||||
std::size_t write_max_;
|
|
||||||
|
|
||||||
public:
|
|
||||||
std::string str;
|
|
||||||
|
|
||||||
explicit string_ostream(
|
|
||||||
boost::asio::io_service& ios,
|
|
||||||
std::size_t write_max = (std::numeric_limits<std::size_t>::max)())
|
|
||||||
: ios_(ios), write_max_(write_max)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
boost::asio::io_service&
|
|
||||||
get_io_service()
|
|
||||||
{
|
|
||||||
return ios_;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class MutableBufferSequence>
|
|
||||||
std::size_t
|
|
||||||
read_some(MutableBufferSequence const& buffers)
|
|
||||||
{
|
|
||||||
error_code ec;
|
|
||||||
auto const n = read_some(buffers, ec);
|
|
||||||
if (ec)
|
|
||||||
BOOST_THROW_EXCEPTION(system_error{ec});
|
|
||||||
return n;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class MutableBufferSequence>
|
|
||||||
std::size_t
|
|
||||||
read_some(MutableBufferSequence const&, error_code& ec)
|
|
||||||
{
|
|
||||||
ec = boost::asio::error::eof;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class MutableBufferSequence, class ReadHandler>
|
|
||||||
async_return_type<ReadHandler, void(error_code, std::size_t)>
|
|
||||||
async_read_some(MutableBufferSequence const&, ReadHandler&& handler)
|
|
||||||
{
|
|
||||||
async_completion<ReadHandler, void(error_code, std::size_t)> init{
|
|
||||||
handler};
|
|
||||||
ios_.post(
|
|
||||||
bind_handler(init.completion_handler, boost::asio::error::eof, 0));
|
|
||||||
return init.result.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class ConstBufferSequence>
|
|
||||||
std::size_t
|
|
||||||
write_some(ConstBufferSequence const& buffers)
|
|
||||||
{
|
|
||||||
error_code ec;
|
|
||||||
auto const n = write_some(buffers, ec);
|
|
||||||
if (ec)
|
|
||||||
BOOST_THROW_EXCEPTION(system_error{ec});
|
|
||||||
return n;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class ConstBufferSequence>
|
|
||||||
std::size_t
|
|
||||||
write_some(ConstBufferSequence const& buffers, error_code& ec)
|
|
||||||
{
|
|
||||||
ec.assign(0, ec.category());
|
|
||||||
using boost::asio::buffer_cast;
|
|
||||||
using boost::asio::buffer_size;
|
|
||||||
auto const n = (std::min)(buffer_size(buffers), write_max_);
|
|
||||||
str.reserve(str.size() + n);
|
|
||||||
for (boost::asio::const_buffer buffer : buffer_prefix(n, buffers))
|
|
||||||
str.append(buffer_cast<char const*>(buffer), buffer_size(buffer));
|
|
||||||
return n;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class ConstBufferSequence, class WriteHandler>
|
|
||||||
async_return_type<WriteHandler, void(error_code, std::size_t)>
|
|
||||||
async_write_some(ConstBufferSequence const& buffers, WriteHandler&& handler)
|
|
||||||
{
|
|
||||||
error_code ec;
|
|
||||||
auto const bytes_transferred = write_some(buffers, ec);
|
|
||||||
async_completion<WriteHandler, void(error_code, std::size_t)> init{
|
|
||||||
handler};
|
|
||||||
get_io_service().post(
|
|
||||||
bind_handler(init.completion_handler, ec, bytes_transferred));
|
|
||||||
return init.result.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
friend void
|
|
||||||
teardown(
|
|
||||||
websocket::teardown_tag,
|
|
||||||
string_ostream&,
|
|
||||||
boost::system::error_code& ec)
|
|
||||||
{
|
|
||||||
ec.assign(0, ec.category());
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class TeardownHandler>
|
|
||||||
friend void
|
|
||||||
async_teardown(
|
|
||||||
websocket::teardown_tag,
|
|
||||||
string_ostream& stream,
|
|
||||||
TeardownHandler&& handler)
|
|
||||||
{
|
|
||||||
stream.get_io_service().post(
|
|
||||||
bind_handler(std::move(handler), error_code{}));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace test
|
|
||||||
} // namespace beast
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,159 +0,0 @@
|
|||||||
//
|
|
||||||
// Copyright (c) 2013-2017 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_TEST_TEST_ALLOCATOR_HPP
|
|
||||||
#define BEAST_TEST_TEST_ALLOCATOR_HPP
|
|
||||||
|
|
||||||
#include <atomic>
|
|
||||||
#include <cstddef>
|
|
||||||
#include <memory>
|
|
||||||
|
|
||||||
namespace beast {
|
|
||||||
namespace test {
|
|
||||||
|
|
||||||
struct test_allocator_info
|
|
||||||
{
|
|
||||||
std::size_t id;
|
|
||||||
std::size_t ncopy = 0;
|
|
||||||
std::size_t nmove = 0;
|
|
||||||
std::size_t nmassign = 0;
|
|
||||||
std::size_t ncpassign = 0;
|
|
||||||
std::size_t nselect = 0;
|
|
||||||
|
|
||||||
test_allocator_info()
|
|
||||||
: id([] {
|
|
||||||
static std::atomic<std::size_t> sid(0);
|
|
||||||
return ++sid;
|
|
||||||
}())
|
|
||||||
{
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <class T, bool Equal, bool Assign, bool Move, bool Swap, bool Select>
|
|
||||||
class test_allocator;
|
|
||||||
|
|
||||||
template <class T, bool Equal, bool Assign, bool Move, bool Swap, bool Select>
|
|
||||||
struct test_allocator_base
|
|
||||||
{
|
|
||||||
};
|
|
||||||
|
|
||||||
template <class T, bool Equal, bool Assign, bool Move, bool Swap>
|
|
||||||
struct test_allocator_base<T, Equal, Assign, Move, Swap, true>
|
|
||||||
{
|
|
||||||
static test_allocator<T, Equal, Assign, Move, Swap, true>
|
|
||||||
select_on_container_copy_construction(
|
|
||||||
test_allocator<T, Equal, Assign, Move, Swap, true> const& a)
|
|
||||||
{
|
|
||||||
return test_allocator<T, Equal, Assign, Move, Swap, true>{};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <class T, bool Equal, bool Assign, bool Move, bool Swap, bool Select>
|
|
||||||
class test_allocator
|
|
||||||
: public test_allocator_base<T, Equal, Assign, Move, Swap, Select>
|
|
||||||
{
|
|
||||||
std::shared_ptr<test_allocator_info> info_;
|
|
||||||
|
|
||||||
template <class, bool, bool, bool, bool, bool>
|
|
||||||
friend class test_allocator;
|
|
||||||
|
|
||||||
public:
|
|
||||||
using value_type = T;
|
|
||||||
|
|
||||||
using propagate_on_container_copy_assignment =
|
|
||||||
std::integral_constant<bool, Assign>;
|
|
||||||
|
|
||||||
using propagate_on_container_move_assignment =
|
|
||||||
std::integral_constant<bool, Move>;
|
|
||||||
|
|
||||||
using propagate_on_container_swap = std::integral_constant<bool, Swap>;
|
|
||||||
|
|
||||||
template <class U>
|
|
||||||
struct rebind
|
|
||||||
{
|
|
||||||
using other = test_allocator<U, Equal, Assign, Move, Swap, Select>;
|
|
||||||
};
|
|
||||||
|
|
||||||
test_allocator() : info_(std::make_shared<test_allocator_info>())
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
test_allocator(test_allocator const& u) noexcept : info_(u.info_)
|
|
||||||
{
|
|
||||||
++info_->ncopy;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class U>
|
|
||||||
test_allocator(
|
|
||||||
test_allocator<U, Equal, Assign, Move, Swap, Select> const& u) noexcept
|
|
||||||
: info_(u.info_)
|
|
||||||
{
|
|
||||||
++info_->ncopy;
|
|
||||||
}
|
|
||||||
|
|
||||||
test_allocator(test_allocator&& t) : info_(t.info_)
|
|
||||||
{
|
|
||||||
++info_->nmove;
|
|
||||||
}
|
|
||||||
|
|
||||||
test_allocator&
|
|
||||||
operator=(test_allocator const& u) noexcept
|
|
||||||
{
|
|
||||||
info_ = u.info_;
|
|
||||||
++info_->ncpassign;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
test_allocator&
|
|
||||||
operator=(test_allocator&& u) noexcept
|
|
||||||
{
|
|
||||||
info_ = u.info_;
|
|
||||||
++info_->nmassign;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
value_type*
|
|
||||||
allocate(std::size_t n)
|
|
||||||
{
|
|
||||||
return static_cast<value_type*>(::operator new(n * sizeof(value_type)));
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
deallocate(value_type* p, std::size_t) noexcept
|
|
||||||
{
|
|
||||||
::operator delete(p);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
operator==(test_allocator const& other) const
|
|
||||||
{
|
|
||||||
return id() == other.id() || Equal;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
operator!=(test_allocator const& other) const
|
|
||||||
{
|
|
||||||
return !this->operator==(other);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::size_t
|
|
||||||
id() const
|
|
||||||
{
|
|
||||||
return info_->id;
|
|
||||||
}
|
|
||||||
|
|
||||||
test_allocator_info const*
|
|
||||||
operator->() const
|
|
||||||
{
|
|
||||||
return info_.get();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace test
|
|
||||||
} // namespace beast
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,121 +0,0 @@
|
|||||||
//
|
|
||||||
// Copyright (c) 2013-2017 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_UNIT_TEST_DSTREAM_HPP
|
|
||||||
#define BEAST_UNIT_TEST_DSTREAM_HPP
|
|
||||||
|
|
||||||
#include <boost/config.hpp>
|
|
||||||
#include <ios>
|
|
||||||
#include <memory>
|
|
||||||
#include <ostream>
|
|
||||||
#include <streambuf>
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
#ifdef BOOST_WINDOWS
|
|
||||||
#include <boost/detail/winapi/basic_types.hpp>
|
|
||||||
//#include <boost/detail/winapi/debugapi.hpp>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace beast {
|
|
||||||
namespace unit_test {
|
|
||||||
|
|
||||||
#ifdef BOOST_WINDOWS
|
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
void
|
|
||||||
write(char const* s)
|
|
||||||
{
|
|
||||||
if (dbg_)
|
|
||||||
/*boost::detail::winapi*/ ::OutputDebugStringA(s);
|
|
||||||
os_ << s;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
write(wchar_t const* s)
|
|
||||||
{
|
|
||||||
if (dbg_)
|
|
||||||
/*boost::detail::winapi*/ ::OutputDebugStringW(s);
|
|
||||||
os_ << s;
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
explicit dstream_buf(ostream& os)
|
|
||||||
: os_(os), dbg_(/*boost::detail::winapi*/ ::IsDebuggerPresent() != 0)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
~dstream_buf()
|
|
||||||
{
|
|
||||||
sync();
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
sync() override
|
|
||||||
{
|
|
||||||
write(this->str().c_str());
|
|
||||||
this->str("");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace detail
|
|
||||||
|
|
||||||
/** 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 : public std::basic_ostream<CharT, Traits>
|
|
||||||
{
|
|
||||||
detail::dstream_buf<CharT, Traits, Allocator> buf_;
|
|
||||||
|
|
||||||
public:
|
|
||||||
/** 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>;
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
using dstream = std::ostream&;
|
|
||||||
using dwstream = std::wostream&;
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
} // namespace unit_test
|
|
||||||
} // namespace beast
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,72 +0,0 @@
|
|||||||
//------------------------------------------------------------------------------
|
|
||||||
/*
|
|
||||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
|
||||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
|
||||||
|
|
||||||
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.
|
|
||||||
*/
|
|
||||||
//==============================================================================
|
|
||||||
|
|
||||||
#ifndef BEAST_UTILITY_HASH_PAIR_H_INCLUDED
|
|
||||||
#define BEAST_UTILITY_HASH_PAIR_H_INCLUDED
|
|
||||||
|
|
||||||
#include <functional>
|
|
||||||
#include <utility>
|
|
||||||
|
|
||||||
#include <boost/functional/hash.hpp>
|
|
||||||
#include <boost/utility/base_from_member.hpp>
|
|
||||||
|
|
||||||
namespace std {
|
|
||||||
|
|
||||||
/** Specialization of std::hash for any std::pair type. */
|
|
||||||
template <class First, class Second>
|
|
||||||
struct hash<std::pair<First, Second>>
|
|
||||||
: private boost::base_from_member<std::hash<First>, 0>,
|
|
||||||
private boost::base_from_member<std::hash<Second>, 1>
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
using first_hash = boost::base_from_member<std::hash<First>, 0>;
|
|
||||||
using second_hash = boost::base_from_member<std::hash<Second>, 1>;
|
|
||||||
|
|
||||||
public:
|
|
||||||
hash()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
hash(
|
|
||||||
std::hash<First> const& first_hash_,
|
|
||||||
std::hash<Second> const& second_hash_)
|
|
||||||
: first_hash(first_hash_), second_hash(second_hash_)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
std::size_t
|
|
||||||
operator()(std::pair<First, Second> const& value)
|
|
||||||
{
|
|
||||||
std::size_t result(first_hash::member(value.first));
|
|
||||||
boost::hash_combine(result, second_hash::member(value.second));
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::size_t
|
|
||||||
operator()(std::pair<First, Second> const& value) const
|
|
||||||
{
|
|
||||||
std::size_t result(first_hash::member(value.first));
|
|
||||||
boost::hash_combine(result, second_hash::member(value.second));
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace std
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -26,7 +26,6 @@
|
|||||||
#include <xrpld/peerfinder/detail/Fixed.h>
|
#include <xrpld/peerfinder/detail/Fixed.h>
|
||||||
#include <xrpld/peerfinder/detail/Handouts.h>
|
#include <xrpld/peerfinder/detail/Handouts.h>
|
||||||
#include <xrpld/peerfinder/detail/Livecache.h>
|
#include <xrpld/peerfinder/detail/Livecache.h>
|
||||||
#include <xrpld/peerfinder/detail/Reporting.h>
|
|
||||||
#include <xrpld/peerfinder/detail/SlotImp.h>
|
#include <xrpld/peerfinder/detail/SlotImp.h>
|
||||||
#include <xrpld/peerfinder/detail/Source.h>
|
#include <xrpld/peerfinder/detail/Source.h>
|
||||||
#include <xrpld/peerfinder/detail/Store.h>
|
#include <xrpld/peerfinder/detail/Store.h>
|
||||||
|
|||||||
@@ -1,49 +0,0 @@
|
|||||||
//------------------------------------------------------------------------------
|
|
||||||
/*
|
|
||||||
This file is part of rippled: https://github.com/ripple/rippled
|
|
||||||
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.
|
|
||||||
*/
|
|
||||||
//==============================================================================
|
|
||||||
|
|
||||||
#ifndef RIPPLE_PEERFINDER_REPORTING_H_INCLUDED
|
|
||||||
#define RIPPLE_PEERFINDER_REPORTING_H_INCLUDED
|
|
||||||
|
|
||||||
namespace ripple {
|
|
||||||
namespace PeerFinder {
|
|
||||||
|
|
||||||
/** Severity levels for test reporting.
|
|
||||||
This allows more fine grained control over reporting for diagnostics.
|
|
||||||
*/
|
|
||||||
struct Reporting
|
|
||||||
{
|
|
||||||
explicit Reporting() = default;
|
|
||||||
|
|
||||||
// Report simulation parameters
|
|
||||||
static bool const params = true;
|
|
||||||
|
|
||||||
// Report simulation crawl time-evolution
|
|
||||||
static bool const crawl = true;
|
|
||||||
|
|
||||||
// Report nodes aggregate statistics
|
|
||||||
static bool const nodes = true;
|
|
||||||
|
|
||||||
// Report nodes detailed information
|
|
||||||
static bool const dump_nodes = false;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace PeerFinder
|
|
||||||
} // namespace ripple
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,100 +0,0 @@
|
|||||||
//------------------------------------------------------------------------------
|
|
||||||
/*
|
|
||||||
This file is part of rippled: https://github.com/ripple/rippled
|
|
||||||
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.
|
|
||||||
*/
|
|
||||||
//==============================================================================
|
|
||||||
|
|
||||||
#ifndef RIPPLE_PEERFINDER_SIM_FUNCTIONQUEUE_H_INCLUDED
|
|
||||||
#define RIPPLE_PEERFINDER_SIM_FUNCTIONQUEUE_H_INCLUDED
|
|
||||||
|
|
||||||
namespace ripple {
|
|
||||||
namespace PeerFinder {
|
|
||||||
namespace Sim {
|
|
||||||
|
|
||||||
/** Maintains a queue of functors that can be called later. */
|
|
||||||
class FunctionQueue
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
explicit FunctionQueue() = default;
|
|
||||||
|
|
||||||
private:
|
|
||||||
class BasicWork
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
virtual ~BasicWork()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
virtual void
|
|
||||||
operator()() = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename Function>
|
|
||||||
class Work : public BasicWork
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
explicit Work(Function f) : m_f(f)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
void
|
|
||||||
operator()()
|
|
||||||
{
|
|
||||||
(m_f)();
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
Function m_f;
|
|
||||||
};
|
|
||||||
|
|
||||||
std::list<std::unique_ptr<BasicWork>> m_work;
|
|
||||||
|
|
||||||
public:
|
|
||||||
/** Returns `true` if there is no remaining work */
|
|
||||||
bool
|
|
||||||
empty()
|
|
||||||
{
|
|
||||||
return m_work.empty();
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Queue a function.
|
|
||||||
Function must be callable with this signature:
|
|
||||||
void (void)
|
|
||||||
*/
|
|
||||||
template <typename Function>
|
|
||||||
void
|
|
||||||
post(Function f)
|
|
||||||
{
|
|
||||||
m_work.emplace_back(std::make_unique<Work<Function>>(f));
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Run all pending functions.
|
|
||||||
The functions will be invoked in the order they were queued.
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
run()
|
|
||||||
{
|
|
||||||
while (!m_work.empty())
|
|
||||||
{
|
|
||||||
(*m_work.front())();
|
|
||||||
m_work.pop_front();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace Sim
|
|
||||||
} // namespace PeerFinder
|
|
||||||
} // namespace ripple
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,76 +0,0 @@
|
|||||||
//------------------------------------------------------------------------------
|
|
||||||
/*
|
|
||||||
This file is part of rippled: https://github.com/ripple/rippled
|
|
||||||
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.
|
|
||||||
*/
|
|
||||||
//==============================================================================
|
|
||||||
|
|
||||||
#ifndef RIPPLE_PEERFINDER_SIM_GRAPHALGORITHMS_H_INCLUDED
|
|
||||||
#define RIPPLE_PEERFINDER_SIM_GRAPHALGORITHMS_H_INCLUDED
|
|
||||||
|
|
||||||
namespace ripple {
|
|
||||||
namespace PeerFinder {
|
|
||||||
namespace Sim {
|
|
||||||
|
|
||||||
template <typename Vertex>
|
|
||||||
struct VertexTraits;
|
|
||||||
|
|
||||||
/** Call a function for each vertex in a connected graph.
|
|
||||||
Function will be called with this signature:
|
|
||||||
void (Vertex&, std::size_t diameter);
|
|
||||||
*/
|
|
||||||
|
|
||||||
template <typename Vertex, typename Function>
|
|
||||||
void
|
|
||||||
breadth_first_traverse(Vertex& start, Function f)
|
|
||||||
{
|
|
||||||
using Traits = VertexTraits<Vertex>;
|
|
||||||
using Edges = typename Traits::Edges;
|
|
||||||
using Edge = typename Traits::Edge;
|
|
||||||
|
|
||||||
using Probe = std::pair<Vertex*, int>;
|
|
||||||
using Work = std::deque<Probe>;
|
|
||||||
using Visited = std::set<Vertex*>;
|
|
||||||
Work work;
|
|
||||||
Visited visited;
|
|
||||||
work.emplace_back(&start, 0);
|
|
||||||
int diameter(0);
|
|
||||||
while (!work.empty())
|
|
||||||
{
|
|
||||||
Probe const p(work.front());
|
|
||||||
work.pop_front();
|
|
||||||
if (visited.find(p.first) != visited.end())
|
|
||||||
continue;
|
|
||||||
diameter = std::max(p.second, diameter);
|
|
||||||
visited.insert(p.first);
|
|
||||||
for (typename Edges::iterator iter(Traits::edges(*p.first).begin());
|
|
||||||
iter != Traits::edges(*p.first).end();
|
|
||||||
++iter)
|
|
||||||
{
|
|
||||||
Vertex* v(Traits::vertex(*iter));
|
|
||||||
if (visited.find(v) != visited.end())
|
|
||||||
continue;
|
|
||||||
if (!iter->closed())
|
|
||||||
work.emplace_back(v, p.second + 1);
|
|
||||||
}
|
|
||||||
f(*p.first, diameter);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace Sim
|
|
||||||
} // namespace PeerFinder
|
|
||||||
} // namespace ripple
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,47 +0,0 @@
|
|||||||
//------------------------------------------------------------------------------
|
|
||||||
/*
|
|
||||||
This file is part of rippled: https://github.com/ripple/rippled
|
|
||||||
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.
|
|
||||||
*/
|
|
||||||
//==============================================================================
|
|
||||||
|
|
||||||
#ifndef RIPPLE_PEERFINDER_SIM_MESSAGE_H_INCLUDED
|
|
||||||
#define RIPPLE_PEERFINDER_SIM_MESSAGE_H_INCLUDED
|
|
||||||
|
|
||||||
namespace ripple {
|
|
||||||
namespace PeerFinder {
|
|
||||||
namespace Sim {
|
|
||||||
|
|
||||||
class Message
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
explicit Message(Endpoints const& endpoints) : m_payload(endpoints)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
Endpoints const&
|
|
||||||
payload() const
|
|
||||||
{
|
|
||||||
return m_payload;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
Endpoints m_payload;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace Sim
|
|
||||||
} // namespace PeerFinder
|
|
||||||
} // namespace ripple
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,37 +0,0 @@
|
|||||||
//------------------------------------------------------------------------------
|
|
||||||
/*
|
|
||||||
This file is part of rippled: https://github.com/ripple/rippled
|
|
||||||
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.
|
|
||||||
*/
|
|
||||||
//==============================================================================
|
|
||||||
|
|
||||||
#ifndef RIPPLE_PEERFINDER_SIM_NODESNAPSHOT_H_INCLUDED
|
|
||||||
#define RIPPLE_PEERFINDER_SIM_NODESNAPSHOT_H_INCLUDED
|
|
||||||
|
|
||||||
namespace ripple {
|
|
||||||
namespace PeerFinder {
|
|
||||||
namespace Sim {
|
|
||||||
|
|
||||||
/** A snapshot of a Node in the network simulator. */
|
|
||||||
struct NodeSnapshot
|
|
||||||
{
|
|
||||||
explicit NodeSnapshot() = default;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace Sim
|
|
||||||
} // namespace PeerFinder
|
|
||||||
} // namespace ripple
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,45 +0,0 @@
|
|||||||
//------------------------------------------------------------------------------
|
|
||||||
/*
|
|
||||||
This file is part of rippled: https://github.com/ripple/rippled
|
|
||||||
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.
|
|
||||||
*/
|
|
||||||
//==============================================================================
|
|
||||||
|
|
||||||
#ifndef RIPPLE_PEERFINDER_SIM_PARAMS_H_INCLUDED
|
|
||||||
#define RIPPLE_PEERFINDER_SIM_PARAMS_H_INCLUDED
|
|
||||||
|
|
||||||
namespace ripple {
|
|
||||||
namespace PeerFinder {
|
|
||||||
namespace Sim {
|
|
||||||
|
|
||||||
/** Defines the parameters for a network simulation. */
|
|
||||||
struct Params
|
|
||||||
{
|
|
||||||
Params() : steps(50), nodes(10), maxPeers(20), outPeers(9.5), firewalled(0)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
int steps;
|
|
||||||
int nodes;
|
|
||||||
int maxPeers;
|
|
||||||
double outPeers;
|
|
||||||
double firewalled; // [0, 1)
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace Sim
|
|
||||||
} // namespace PeerFinder
|
|
||||||
} // namespace ripple
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,87 +0,0 @@
|
|||||||
//------------------------------------------------------------------------------
|
|
||||||
/*
|
|
||||||
This file is part of rippled: https://github.com/ripple/rippled
|
|
||||||
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.
|
|
||||||
*/
|
|
||||||
//==============================================================================
|
|
||||||
|
|
||||||
#ifndef RIPPLE_PEERFINDER_SIM_PREDICATES_H_INCLUDED
|
|
||||||
#define RIPPLE_PEERFINDER_SIM_PREDICATES_H_INCLUDED
|
|
||||||
|
|
||||||
namespace ripple {
|
|
||||||
namespace PeerFinder {
|
|
||||||
namespace Sim {
|
|
||||||
|
|
||||||
/** UnaryPredicate, returns `true` if the 'to' node on a Link matches. */
|
|
||||||
/** @{ */
|
|
||||||
template <typename Node>
|
|
||||||
class is_remote_node_pred
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
is_remote_node_pred(Node const& n) : node(n)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
template <typename Link>
|
|
||||||
bool
|
|
||||||
operator()(Link const& l) const
|
|
||||||
{
|
|
||||||
return &node == &l.remote_node();
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
Node const& node;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename Node>
|
|
||||||
is_remote_node_pred<Node>
|
|
||||||
is_remote_node(Node const& node)
|
|
||||||
{
|
|
||||||
return is_remote_node_pred<Node>(node);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Node>
|
|
||||||
is_remote_node_pred<Node>
|
|
||||||
is_remote_node(Node const* node)
|
|
||||||
{
|
|
||||||
return is_remote_node_pred<Node>(*node);
|
|
||||||
}
|
|
||||||
/** @} */
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
/** UnaryPredicate, `true` if the remote address matches. */
|
|
||||||
class is_remote_endpoint
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
explicit is_remote_endpoint(beast::IP::Endpoint const& address)
|
|
||||||
: m_endpoint(address)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
template <typename Link>
|
|
||||||
bool
|
|
||||||
operator()(Link const& link) const
|
|
||||||
{
|
|
||||||
return link.remote_endpoint() == m_endpoint;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
beast::IP::Endpoint const m_endpoint;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace Sim
|
|
||||||
} // namespace PeerFinder
|
|
||||||
} // namespace ripple
|
|
||||||
|
|
||||||
#endif
|
|
||||||
Reference in New Issue
Block a user