Merge branch develop-0.0
This commit is contained in:
253
.gitlab-ci.yml
Normal file
253
.gitlab-ci.yml
Normal file
@@ -0,0 +1,253 @@
|
||||
variables:
|
||||
GIT_STRATEGY: "clone"
|
||||
BUILD_PADDING_PREFIX: /tmp/padding_for_CPACK_RPM_BUILD_SOURCE_DIRS_PREFIX_PREFIX_PREFIX_PREFIX_PREFIX_PREFIX/
|
||||
INSTALL_PREFIX: "/opt/tsg/stellar"
|
||||
TESTING_VERSION_BUILD: 0
|
||||
BUILD_IMAGE_CENTOS7: "git.mesalab.cn:7443/mesa_platform/build-env:master"
|
||||
BUILD_IMAGE_CENTOS8: "git.mesalab.cn:7443/mesa_platform/build-env:rockylinux"
|
||||
|
||||
stages:
|
||||
- build
|
||||
- envelope
|
||||
- upload
|
||||
|
||||
.build_before_script:
|
||||
before_script:
|
||||
- mkdir -p $BUILD_PADDING_PREFIX/$CI_PROJECT_NAMESPACE/
|
||||
- ln -s $CI_PROJECT_DIR $BUILD_PADDING_PREFIX/$CI_PROJECT_PATH
|
||||
- cd $BUILD_PADDING_PREFIX/$CI_PROJECT_PATH
|
||||
- chmod +x ./ci/travis.sh
|
||||
- yum makecache
|
||||
- yum install -y elfutils-libelf-devel
|
||||
|
||||
.build_by_travis_for_centos7:
|
||||
stage: build
|
||||
image: $BUILD_IMAGE_CENTOS7
|
||||
extends: .build_before_script
|
||||
script:
|
||||
- ./ci/travis.sh
|
||||
tags:
|
||||
- share
|
||||
|
||||
.build_by_travis_for_centos8:
|
||||
stage: build
|
||||
image: $BUILD_IMAGE_CENTOS8
|
||||
extends: .build_before_script
|
||||
script:
|
||||
- ./ci/travis.sh
|
||||
tags:
|
||||
- share
|
||||
|
||||
###############################################################################
|
||||
# compile use image: build-env:master
|
||||
###############################################################################
|
||||
|
||||
branch_build_debug_for_centos7:
|
||||
extends: .build_by_travis_for_centos7
|
||||
variables:
|
||||
BUILD_TYPE: Debug
|
||||
except:
|
||||
- /^develop-.*$/i
|
||||
- /^release-.*$/i
|
||||
- tags
|
||||
|
||||
branch_build_release_for_centos7:
|
||||
variables:
|
||||
BUILD_TYPE: RelWithDebInfo
|
||||
extends: .build_by_travis_for_centos7
|
||||
except:
|
||||
- /^develop-.*$/i
|
||||
- /^release-.*$/i
|
||||
- tags
|
||||
|
||||
develop_build_debug_for_centos7:
|
||||
extends: .build_by_travis_for_centos7
|
||||
variables:
|
||||
TESTING_VERSION_BUILD: 1
|
||||
# UPLOAD_SYMBOL_FILES: 1
|
||||
BUILD_TYPE: Debug
|
||||
# ASAN_OPTION: ADDRESS
|
||||
PACKAGE: 1
|
||||
PULP3_REPO_NAME: stellar-testing-x86_64.el7
|
||||
PULP3_DIST_NAME: stellar-testing-x86_64.el7
|
||||
artifacts:
|
||||
name: "stellar-develop-$CI_COMMIT_REF_NAME-debug"
|
||||
paths:
|
||||
- build/*.rpm
|
||||
only:
|
||||
- /^develop-.*$/i
|
||||
- /^release-.*$/i
|
||||
|
||||
develop_build_release_for_centos7:
|
||||
extends: .build_by_travis_for_centos7
|
||||
variables:
|
||||
TESTING_VERSION_BUILD: 1
|
||||
# UPLOAD_SYMBOL_FILES: 1
|
||||
# ASAN_OPTION: ADDRESS
|
||||
BUILD_TYPE: RelWithDebInfo
|
||||
PACKAGE: 1
|
||||
PULP3_REPO_NAME: stellar-testing-x86_64.el7
|
||||
PULP3_DIST_NAME: stellar-testing-x86_64.el7
|
||||
artifacts:
|
||||
name: "stellar-develop-$CI_COMMIT_REF_NAME-release"
|
||||
paths:
|
||||
- build/*.rpm
|
||||
only:
|
||||
- /^develop-.*$/i
|
||||
- /^release-.*$/i
|
||||
|
||||
release_build_debug_for_centos7:
|
||||
variables:
|
||||
# UPLOAD_SYMBOL_FILES: 1
|
||||
BUILD_TYPE: Debug
|
||||
PACKAGE: 1
|
||||
PULP3_REPO_NAME: stellar-stable-x86_64.el7
|
||||
PULP3_DIST_NAME: stellar-stable-x86_64.el7
|
||||
extends: .build_by_travis_for_centos7
|
||||
artifacts:
|
||||
name: "stellar-install-$CI_COMMIT_REF_NAME-debug"
|
||||
paths:
|
||||
- build/*.rpm
|
||||
only:
|
||||
- tags
|
||||
|
||||
release_build_release_for_centos7:
|
||||
variables:
|
||||
BUILD_TYPE: RelWithDebInfo
|
||||
# UPLOAD_SYMBOL_FILES: 1
|
||||
PACKAGE: 1
|
||||
PULP3_REPO_NAME: stellar-stable-x86_64.el7
|
||||
PULP3_DIST_NAME: stellar-stable-x86_64.el7
|
||||
extends: .build_by_travis_for_centos7
|
||||
artifacts:
|
||||
name: "stellar-install-$CI_COMMIT_REF_NAME-release"
|
||||
paths:
|
||||
- build/*.rpm
|
||||
only:
|
||||
- tags
|
||||
|
||||
###############################################################################
|
||||
# compile use image: build-env:rockylinux
|
||||
###############################################################################
|
||||
|
||||
branch_build_debug_for_centos8:
|
||||
extends: .build_by_travis_for_centos8
|
||||
variables:
|
||||
BUILD_TYPE: Debug
|
||||
except:
|
||||
- /^develop-.*$/i
|
||||
- /^release-.*$/i
|
||||
- tags
|
||||
|
||||
branch_build_release_for_centos8:
|
||||
variables:
|
||||
BUILD_TYPE: RelWithDebInfo
|
||||
extends: .build_by_travis_for_centos8
|
||||
except:
|
||||
- /^develop-.*$/i
|
||||
- /^release-.*$/i
|
||||
- tags
|
||||
|
||||
develop_build_debug_for_centos8:
|
||||
extends: .build_by_travis_for_centos8
|
||||
variables:
|
||||
TESTING_VERSION_BUILD: 1
|
||||
# UPLOAD_SYMBOL_FILES: 1
|
||||
BUILD_TYPE: Debug
|
||||
# ASAN_OPTION: ADDRESS
|
||||
PACKAGE: 1
|
||||
PULP3_REPO_NAME: stellar-testing-x86_64.el8
|
||||
PULP3_DIST_NAME: stellar-testing-x86_64.el8
|
||||
artifacts:
|
||||
name: "stellar-develop-$CI_COMMIT_REF_NAME-debug"
|
||||
paths:
|
||||
- build/*.rpm
|
||||
only:
|
||||
- /^develop-.*$/i
|
||||
- /^release-.*$/i
|
||||
|
||||
develop_build_release_for_centos8:
|
||||
extends: .build_by_travis_for_centos8
|
||||
variables:
|
||||
TESTING_VERSION_BUILD: 1
|
||||
# UPLOAD_SYMBOL_FILES: 1
|
||||
# ASAN_OPTION: ADDRESS
|
||||
BUILD_TYPE: RelWithDebInfo
|
||||
PACKAGE: 1
|
||||
PULP3_REPO_NAME: stellar-testing-x86_64.el8
|
||||
PULP3_DIST_NAME: stellar-testing-x86_64.el8
|
||||
artifacts:
|
||||
name: "stellar-develop-$CI_COMMIT_REF_NAME-release"
|
||||
paths:
|
||||
- build/*.rpm
|
||||
only:
|
||||
- /^develop-.*$/i
|
||||
- /^release-.*$/i
|
||||
|
||||
release_build_debug_for_centos8:
|
||||
variables:
|
||||
# UPLOAD_SYMBOL_FILES: 1
|
||||
BUILD_TYPE: Debug
|
||||
PACKAGE: 1
|
||||
PULP3_REPO_NAME: stellar-stable-x86_64.el8
|
||||
PULP3_DIST_NAME: stellar-stable-x86_64.el8
|
||||
extends: .build_by_travis_for_centos8
|
||||
artifacts:
|
||||
name: "stellar-install-$CI_COMMIT_REF_NAME-debug"
|
||||
paths:
|
||||
- build/*.rpm
|
||||
only:
|
||||
- tags
|
||||
|
||||
release_build_release_for_centos8:
|
||||
variables:
|
||||
BUILD_TYPE: RelWithDebInfo
|
||||
# UPLOAD_SYMBOL_FILES: 1
|
||||
PACKAGE: 1
|
||||
PULP3_REPO_NAME: stellar-stable-x86_64.el8
|
||||
PULP3_DIST_NAME: stellar-stable-x86_64.el8
|
||||
extends: .build_by_travis_for_centos8
|
||||
artifacts:
|
||||
name: "stellar-install-$CI_COMMIT_REF_NAME-release"
|
||||
paths:
|
||||
- build/*.rpm
|
||||
only:
|
||||
- tags
|
||||
|
||||
###############################################################################
|
||||
# envelope and upload
|
||||
###############################################################################
|
||||
|
||||
envelope_rpm:
|
||||
stage: envelope
|
||||
image: $BUILD_IMAGE_CENTOS7
|
||||
variables:
|
||||
FEATURE_ID: 100
|
||||
APP_NAME_IN_RPM_SPEC: stellar
|
||||
script:
|
||||
- chmod +x ./ci/envelope_rpm.sh
|
||||
- ./ci/envelope_rpm.sh
|
||||
artifacts:
|
||||
name: "stellar-pr-$CI_COMMIT_REF_NAME-release"
|
||||
paths:
|
||||
- build/*-pr-*.rpm
|
||||
tags:
|
||||
- envelope
|
||||
only:
|
||||
- tags
|
||||
|
||||
upload_enveloped_rpm:
|
||||
stage: upload
|
||||
image: $BUILD_IMAGE_CENTOS7
|
||||
variables:
|
||||
PULP3_REPO_NAME_EL7: stellar-stable-x86_64.el7
|
||||
PULP3_DIST_NAME_EL7: stellar-stable-x86_64.el7
|
||||
PULP3_REPO_NAME_EL8: stellar-stable-x86_64.el8
|
||||
PULP3_DIST_NAME_EL8: stellar-stable-x86_64.el8
|
||||
script:
|
||||
- chmod +x ./ci/upload_enveloped_rpm.sh
|
||||
- ./ci/upload_enveloped_rpm.sh
|
||||
tags:
|
||||
- share
|
||||
only:
|
||||
- tags
|
||||
@@ -1,27 +1,42 @@
|
||||
cmake_minimum_required(VERSION 3.14)
|
||||
cmake_minimum_required(VERSION 3.12)
|
||||
project(stellar)
|
||||
|
||||
# GoogleTest requires at least C++11
|
||||
set(CMAKE_CXX_STANDARD 11)
|
||||
|
||||
#find required package
|
||||
set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake)
|
||||
include(Version)
|
||||
find_package(PkgConfig REQUIRED)
|
||||
find_package(Threads REQUIRED)
|
||||
find_package(PCAP REQUIRED)
|
||||
pkg_check_modules(SYSTEMD REQUIRED systemd)
|
||||
include(Package)
|
||||
|
||||
add_definitions(-D_GNU_SOURCE)
|
||||
set(CMAKE_CXX_STANDARD 11)
|
||||
set(CMAKE_C_STANDARD 11)
|
||||
|
||||
if(NOT CMAKE_BUILD_TYPE)
|
||||
set(CMAKE_BUILD_TYPE RelWithDebInfo)
|
||||
endif()
|
||||
|
||||
if (CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
|
||||
set (CMAKE_INSTALL_PREFIX "/opt/tsg/stellar" CACHE PATH "default install path" FORCE)
|
||||
endif()
|
||||
|
||||
option(ENABLE_PIC "Generate position independent code (necessary for shared libraries)" TRUE)
|
||||
option(ENABLE_WARNING_ALL "Enable all optional warnings which are desirable for normal code" TRUE)
|
||||
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall")
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -lelf")
|
||||
|
||||
add_custom_target("install-program" COMMAND ${CMAKE_COMMAND} ARGS -DCOMPONENT=Program -P cmake_install.cmake)
|
||||
add_custom_target("install-profile" COMMAND ${CMAKE_COMMAND} ARGS -DCOMPONENT=Profile -P cmake_install.cmake)
|
||||
|
||||
include_directories(${CMAKE_SOURCE_DIR}/sdk/include)
|
||||
include_directories(/opt/mrzcpd/include)
|
||||
|
||||
#add vendor and source directory
|
||||
add_subdirectory(conf)
|
||||
add_subdirectory(vendor)
|
||||
add_subdirectory(deps/toml)
|
||||
add_subdirectory(deps/sds)
|
||||
add_subdirectory(deps/timeout)
|
||||
add_subdirectory(src)
|
||||
add_subdirectory(sdk/example)
|
||||
|
||||
|
||||
#add gtest
|
||||
enable_testing()
|
||||
add_subdirectory(test)
|
||||
@@ -9,7 +9,7 @@
|
||||
|
||||
# Usage message.
|
||||
arUsage() {
|
||||
cat > "/dev/stderr" << EOF
|
||||
cat >"/dev/stderr" <<EOF
|
||||
usage: autorevision {-t output-type | -s symbol} [-o cache-file [-f] ] [-V]
|
||||
Options include:
|
||||
-t output-type = specify output type
|
||||
@@ -69,28 +69,28 @@ ARVERSION="&&ARVERSION&&"
|
||||
TARGETFILE="/dev/stdout"
|
||||
while getopts ":t:o:s:VfU" OPTION; do
|
||||
case "${OPTION}" in
|
||||
t)
|
||||
AFILETYPE="${OPTARG}"
|
||||
t)
|
||||
AFILETYPE="${OPTARG}"
|
||||
;;
|
||||
o)
|
||||
CACHEFILE="${OPTARG}"
|
||||
o)
|
||||
CACHEFILE="${OPTARG}"
|
||||
;;
|
||||
f)
|
||||
CACHEFORCE="1"
|
||||
f)
|
||||
CACHEFORCE="1"
|
||||
;;
|
||||
s)
|
||||
VAROUT="${OPTARG}"
|
||||
s)
|
||||
VAROUT="${OPTARG}"
|
||||
;;
|
||||
U)
|
||||
UNTRACKEDFILES="1"
|
||||
U)
|
||||
UNTRACKEDFILES="1"
|
||||
;;
|
||||
V)
|
||||
echo "autorevision ${ARVERSION}"
|
||||
exit 0
|
||||
V)
|
||||
echo "autorevision ${ARVERSION}"
|
||||
exit 0
|
||||
;;
|
||||
?)
|
||||
# If an unknown flag is used (or -?):
|
||||
arUsage
|
||||
?)
|
||||
# If an unknown flag is used (or -?):
|
||||
arUsage
|
||||
;;
|
||||
esac
|
||||
done
|
||||
@@ -305,7 +305,7 @@ svnRepo() {
|
||||
VCS_TYPE="svn"
|
||||
|
||||
case "${PWD}" in
|
||||
/*trunk*|/*branches*|/*tags*)
|
||||
/*trunk* | /*branches* | /*tags*)
|
||||
local fn="${PWD}"
|
||||
while [ "$(basename "${fn}")" != 'trunk' ] && [ "$(basename "${fn}")" != 'branches' ] && [ "$(basename "${fn}")" != 'tags' ] && [ "$(basename "${fn}")" != '/' ]; do
|
||||
local fn="$(dirname "${fn}")"
|
||||
@@ -328,20 +328,20 @@ svnRepo() {
|
||||
# Is the working copy clean?
|
||||
echo "${SVNVERSION}" | grep -q "M"
|
||||
case "${?}" in
|
||||
0)
|
||||
VCS_WC_MODIFIED="1"
|
||||
0)
|
||||
VCS_WC_MODIFIED="1"
|
||||
;;
|
||||
1)
|
||||
if [ ! -z "${UNTRACKEDFILES}" ]; then
|
||||
1)
|
||||
if [ ! -z "${UNTRACKEDFILES}" ]; then
|
||||
# `svnversion` does not detect untracked files and `svn status` is really slow, so only run it if we really have to.
|
||||
if [ -z "$(svn status)" ]; then
|
||||
VCS_WC_MODIFIED="0"
|
||||
else
|
||||
VCS_WC_MODIFIED="1"
|
||||
fi
|
||||
else
|
||||
if [ -z "$(svn status)" ]; then
|
||||
VCS_WC_MODIFIED="0"
|
||||
else
|
||||
VCS_WC_MODIFIED="1"
|
||||
fi
|
||||
else
|
||||
VCS_WC_MODIFIED="0"
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
|
||||
@@ -356,11 +356,10 @@ svnRepo() {
|
||||
|
||||
# Current branch
|
||||
case "${PWD}" in
|
||||
/*trunk*|/*branches*|/*tags*)
|
||||
/*trunk* | /*branches* | /*tags*)
|
||||
local lastbase=""
|
||||
local fn="${PWD}"
|
||||
while :
|
||||
do
|
||||
while :; do
|
||||
base="$(basename "${fn}")"
|
||||
if [ "${base}" = 'trunk' ]; then
|
||||
VCS_BRANCH='trunk'
|
||||
@@ -394,11 +393,10 @@ svnRepo() {
|
||||
cd "${oldPath}"
|
||||
}
|
||||
|
||||
|
||||
# Functions to output data in different formats.
|
||||
# For bash output
|
||||
shOutput() {
|
||||
cat > "${TARGETFILE}" << EOF
|
||||
cat >"${TARGETFILE}" <<EOF
|
||||
# ${GENERATED_HEADER}
|
||||
|
||||
VCS_TYPE="${VCS_TYPE}"
|
||||
@@ -423,7 +421,7 @@ EOF
|
||||
|
||||
# For source C output
|
||||
cOutput() {
|
||||
cat > "${TARGETFILE}" << EOF
|
||||
cat >"${TARGETFILE}" <<EOF
|
||||
/* ${GENERATED_HEADER} */
|
||||
|
||||
const char *VCS_TYPE = "${VCS_TYPE}";
|
||||
@@ -448,7 +446,7 @@ EOF
|
||||
|
||||
# For header output
|
||||
hOutput() {
|
||||
cat > "${TARGETFILE}" << EOF
|
||||
cat >"${TARGETFILE}" <<EOF
|
||||
/* ${GENERATED_HEADER} */
|
||||
#ifndef AUTOREVISION_H
|
||||
#define AUTOREVISION_H
|
||||
@@ -477,7 +475,7 @@ EOF
|
||||
|
||||
# A header output for use with xcode to populate info.plist strings
|
||||
xcodeOutput() {
|
||||
cat > "${TARGETFILE}" << EOF
|
||||
cat >"${TARGETFILE}" <<EOF
|
||||
/* ${GENERATED_HEADER} */
|
||||
#ifndef AUTOREVISION_H
|
||||
#define AUTOREVISION_H
|
||||
@@ -507,8 +505,8 @@ EOF
|
||||
# For Swift output
|
||||
swiftOutput() {
|
||||
case "${VCS_WC_MODIFIED}" in
|
||||
0) VCS_WC_MODIFIED="false" ;;
|
||||
1) VCS_WC_MODIFIED="true" ;;
|
||||
0) VCS_WC_MODIFIED="false" ;;
|
||||
1) VCS_WC_MODIFIED="true" ;;
|
||||
esac
|
||||
# For values that may not exist depending on the type of repo we
|
||||
# have read from, set them to `nil` when they are empty.
|
||||
@@ -533,7 +531,7 @@ swiftOutput() {
|
||||
else
|
||||
VCS_ACTION_STAMP="\"${VCS_ACTION_STAMP}\""
|
||||
fi
|
||||
cat > "${TARGETFILE}" << EOF
|
||||
cat >"${TARGETFILE}" <<EOF
|
||||
/* ${GENERATED_HEADER} */
|
||||
|
||||
let VCS_TYPE = "${VCS_TYPE}"
|
||||
@@ -559,10 +557,10 @@ EOF
|
||||
# For Python output
|
||||
pyOutput() {
|
||||
case "${VCS_WC_MODIFIED}" in
|
||||
0) VCS_WC_MODIFIED="False" ;;
|
||||
1) VCS_WC_MODIFIED="True" ;;
|
||||
0) VCS_WC_MODIFIED="False" ;;
|
||||
1) VCS_WC_MODIFIED="True" ;;
|
||||
esac
|
||||
cat > "${TARGETFILE}" << EOF
|
||||
cat >"${TARGETFILE}" <<EOF
|
||||
# ${GENERATED_HEADER}
|
||||
|
||||
VCS_TYPE = "${VCS_TYPE}"
|
||||
@@ -587,7 +585,7 @@ EOF
|
||||
|
||||
# For Perl output
|
||||
plOutput() {
|
||||
cat << EOF
|
||||
cat <<EOF
|
||||
# ${GENERATED_HEADER}
|
||||
|
||||
\$VCS_TYPE = '${VCS_TYPE}';
|
||||
@@ -614,10 +612,10 @@ EOF
|
||||
# For lua output
|
||||
luaOutput() {
|
||||
case "${VCS_WC_MODIFIED}" in
|
||||
0) VCS_WC_MODIFIED="false" ;;
|
||||
1) VCS_WC_MODIFIED="true" ;;
|
||||
0) VCS_WC_MODIFIED="false" ;;
|
||||
1) VCS_WC_MODIFIED="true" ;;
|
||||
esac
|
||||
cat > "${TARGETFILE}" << EOF
|
||||
cat >"${TARGETFILE}" <<EOF
|
||||
-- ${GENERATED_HEADER}
|
||||
|
||||
VCS_TYPE = "${VCS_TYPE}"
|
||||
@@ -643,10 +641,10 @@ EOF
|
||||
# For php output
|
||||
phpOutput() {
|
||||
case "${VCS_WC_MODIFIED}" in
|
||||
0) VCS_WC_MODIFIED="false" ;;
|
||||
1) VCS_WC_MODIFIED="true" ;;
|
||||
0) VCS_WC_MODIFIED="false" ;;
|
||||
1) VCS_WC_MODIFIED="true" ;;
|
||||
esac
|
||||
cat > "${TARGETFILE}" << EOF
|
||||
cat >"${TARGETFILE}" <<EOF
|
||||
<?php
|
||||
# ${GENERATED_HEADER}
|
||||
|
||||
@@ -674,10 +672,10 @@ EOF
|
||||
# For ini output
|
||||
iniOutput() {
|
||||
case "${VCS_WC_MODIFIED}" in
|
||||
0) VCS_WC_MODIFIED="false" ;;
|
||||
1) VCS_WC_MODIFIED="true" ;;
|
||||
0) VCS_WC_MODIFIED="false" ;;
|
||||
1) VCS_WC_MODIFIED="true" ;;
|
||||
esac
|
||||
cat > "${TARGETFILE}" << EOF
|
||||
cat >"${TARGETFILE}" <<EOF
|
||||
; ${GENERATED_HEADER}
|
||||
[VCS]
|
||||
VCS_TYPE = "${VCS_TYPE}"
|
||||
@@ -700,10 +698,10 @@ EOF
|
||||
# For javascript output
|
||||
jsOutput() {
|
||||
case "${VCS_WC_MODIFIED}" in
|
||||
1) VCS_WC_MODIFIED="true" ;;
|
||||
0) VCS_WC_MODIFIED="false" ;;
|
||||
1) VCS_WC_MODIFIED="true" ;;
|
||||
0) VCS_WC_MODIFIED="false" ;;
|
||||
esac
|
||||
cat > "${TARGETFILE}" << EOF
|
||||
cat >"${TARGETFILE}" <<EOF
|
||||
/** ${GENERATED_HEADER} */
|
||||
|
||||
var autorevision = {
|
||||
@@ -736,10 +734,10 @@ EOF
|
||||
# For JSON output
|
||||
jsonOutput() {
|
||||
case "${VCS_WC_MODIFIED}" in
|
||||
1) VCS_WC_MODIFIED="true" ;;
|
||||
0) VCS_WC_MODIFIED="false" ;;
|
||||
1) VCS_WC_MODIFIED="true" ;;
|
||||
0) VCS_WC_MODIFIED="false" ;;
|
||||
esac
|
||||
cat > "${TARGETFILE}" << EOF
|
||||
cat >"${TARGETFILE}" <<EOF
|
||||
{
|
||||
"_comment": "${GENERATED_HEADER}",
|
||||
"VCS_TYPE": "${VCS_TYPE}",
|
||||
@@ -764,10 +762,10 @@ EOF
|
||||
# For Java output
|
||||
javaOutput() {
|
||||
case "${VCS_WC_MODIFIED}" in
|
||||
1) VCS_WC_MODIFIED="true" ;;
|
||||
0) VCS_WC_MODIFIED="false" ;;
|
||||
1) VCS_WC_MODIFIED="true" ;;
|
||||
0) VCS_WC_MODIFIED="false" ;;
|
||||
esac
|
||||
cat > "${TARGETFILE}" << EOF
|
||||
cat >"${TARGETFILE}" <<EOF
|
||||
/* ${GENERATED_HEADER} */
|
||||
|
||||
public class autorevision {
|
||||
@@ -793,10 +791,10 @@ EOF
|
||||
# For Java properties output
|
||||
javapropOutput() {
|
||||
case "${VCS_WC_MODIFIED}" in
|
||||
1) VCS_WC_MODIFIED="true" ;;
|
||||
0) VCS_WC_MODIFIED="false" ;;
|
||||
1) VCS_WC_MODIFIED="true" ;;
|
||||
0) VCS_WC_MODIFIED="false" ;;
|
||||
esac
|
||||
cat > "${TARGETFILE}" << EOF
|
||||
cat >"${TARGETFILE}" <<EOF
|
||||
# ${GENERATED_HEADER}
|
||||
|
||||
VCS_TYPE=${VCS_TYPE}
|
||||
@@ -819,7 +817,7 @@ EOF
|
||||
|
||||
# For m4 output
|
||||
m4Output() {
|
||||
cat > "${TARGETFILE}" << EOF
|
||||
cat >"${TARGETFILE}" <<EOF
|
||||
dnl ${GENERATED_HEADER}
|
||||
define(\`VCS_TYPE', \`${VCS_TYPE}')dnl
|
||||
define(\`VCS_BASENAME', \`${VCS_BASENAME}')dnl
|
||||
@@ -840,10 +838,10 @@ EOF
|
||||
# For (La)TeX output
|
||||
texOutput() {
|
||||
case "${VCS_WC_MODIFIED}" in
|
||||
0) VCS_WC_MODIFIED="false" ;;
|
||||
1) VCS_WC_MODIFIED="true" ;;
|
||||
0) VCS_WC_MODIFIED="false" ;;
|
||||
1) VCS_WC_MODIFIED="true" ;;
|
||||
esac
|
||||
cat > "${TARGETFILE}" << EOF
|
||||
cat >"${TARGETFILE}" <<EOF
|
||||
% ${GENERATED_HEADER}
|
||||
\def \vcsType {${VCS_TYPE}}
|
||||
\def \vcsBasename {${VCS_BASENAME}}
|
||||
@@ -865,10 +863,10 @@ EOF
|
||||
# For scheme output
|
||||
schemeOutput() {
|
||||
case "${VCS_WC_MODIFIED}" in
|
||||
0) VCS_WC_MODIFIED="#f" ;;
|
||||
1) VCS_WC_MODIFIED="#t" ;;
|
||||
0) VCS_WC_MODIFIED="#f" ;;
|
||||
1) VCS_WC_MODIFIED="#t" ;;
|
||||
esac
|
||||
cat > "${TARGETFILE}" << EOF
|
||||
cat >"${TARGETFILE}" <<EOF
|
||||
;; ${GENERATED_HEADER}
|
||||
(define VCS_TYPE "${VCS_TYPE}")
|
||||
(define VCS_BASENAME "${VCS_BASENAME}")
|
||||
@@ -892,10 +890,10 @@ EOF
|
||||
# For clojure output
|
||||
clojureOutput() {
|
||||
case "${VCS_WC_MODIFIED}" in
|
||||
0) VCS_WC_MODIFIED="false" ;;
|
||||
1) VCS_WC_MODIFIED="true" ;;
|
||||
0) VCS_WC_MODIFIED="false" ;;
|
||||
1) VCS_WC_MODIFIED="true" ;;
|
||||
esac
|
||||
cat > "${TARGETFILE}" << EOF
|
||||
cat >"${TARGETFILE}" <<EOF
|
||||
;; ${GENERATED_HEADER}
|
||||
(def VCS_TYPE "${VCS_TYPE}")
|
||||
(def VCS_BASENAME "${VCS_BASENAME}")
|
||||
@@ -918,7 +916,7 @@ EOF
|
||||
|
||||
# For rpm spec file output
|
||||
rpmOutput() {
|
||||
cat > "${TARGETFILE}" << EOF
|
||||
cat >"${TARGETFILE}" <<EOF
|
||||
# ${GENERATED_HEADER}
|
||||
$([ "${VCS_TYPE}" ] && echo "%define vcs_type ${VCS_TYPE}")
|
||||
$([ "${VCS_BASENAME}" ] && echo "%define vcs_basename ${VCS_BASENAME}")
|
||||
@@ -942,7 +940,7 @@ EOF
|
||||
# shellcheck disable=SC2155,SC2039
|
||||
hppOutput() {
|
||||
local NAMESPACE="$(echo "${VCS_BASENAME}" | sed -e 's:_::g' | tr '[:lower:]' '[:upper:]')"
|
||||
cat > "${TARGETFILE}" << EOF
|
||||
cat >"${TARGETFILE}" <<EOF
|
||||
/* ${GENERATED_HEADER} */
|
||||
|
||||
#ifndef ${NAMESPACE}_AUTOREVISION_H
|
||||
@@ -977,10 +975,10 @@ EOF
|
||||
|
||||
matlabOutput() {
|
||||
case "${VCS_WC_MODIFIED}" in
|
||||
0) VCS_WC_MODIFIED="FALSE" ;;
|
||||
1) VCS_WC_MODIFIED="TRUE" ;;
|
||||
0) VCS_WC_MODIFIED="FALSE" ;;
|
||||
1) VCS_WC_MODIFIED="TRUE" ;;
|
||||
esac
|
||||
cat > "${TARGETFILE}" << EOF
|
||||
cat >"${TARGETFILE}" <<EOF
|
||||
% ${GENERATED_HEADER}
|
||||
|
||||
VCS_TYPE = '${VCS_TYPE}';
|
||||
@@ -1004,7 +1002,7 @@ EOF
|
||||
}
|
||||
|
||||
octaveOutput() {
|
||||
cat > "${TARGETFILE}" << EOF
|
||||
cat >"${TARGETFILE}" <<EOF
|
||||
% ${GENERATED_HEADER}
|
||||
|
||||
VCS_TYPE = '${VCS_TYPE}';
|
||||
@@ -1028,7 +1026,7 @@ EOF
|
||||
}
|
||||
|
||||
cmakeOutput() {
|
||||
cat > "${TARGETFILE}" << EOF
|
||||
cat >"${TARGETFILE}" <<EOF
|
||||
# ${GENERATED_HEADER}
|
||||
|
||||
set(VCS_TYPE ${VCS_TYPE})
|
||||
@@ -1051,7 +1049,6 @@ set(VCS_WC_MODIFIED ${VCS_WC_MODIFIED})
|
||||
EOF
|
||||
}
|
||||
|
||||
|
||||
# Helper functions
|
||||
# Count path segments
|
||||
# shellcheck disable=SC2039
|
||||
@@ -1063,7 +1060,7 @@ pathSegment() {
|
||||
# Continue until we are at / or there are no path separators left.
|
||||
while [ ! "${pathz}" = "/" ] && [ ! "${pathz}" = "$(echo "${pathz}" | sed -e 's:/::')" ]; do
|
||||
pathz="$(dirname "${pathz}")"
|
||||
depth="$((depth+1))"
|
||||
depth="$((depth + 1))"
|
||||
done
|
||||
fi
|
||||
echo "${depth}"
|
||||
@@ -1090,21 +1087,21 @@ repoTest() {
|
||||
if [ ! -z "$(git rev-parse HEAD 2>/dev/null)" ]; then
|
||||
local gitPath="$(git rev-parse --show-toplevel)"
|
||||
local gitDepth="$(pathSegment "${gitPath}")"
|
||||
REPONUM="$((REPONUM+1))"
|
||||
REPONUM="$((REPONUM + 1))"
|
||||
else
|
||||
local gitDepth="0"
|
||||
fi
|
||||
if [ ! -z "$(hg root 2>/dev/null)" ]; then
|
||||
local hgPath="$(hg root 2>/dev/null)"
|
||||
local hgDepth="$(pathSegment "${hgPath}")"
|
||||
REPONUM="$((REPONUM+1))"
|
||||
REPONUM="$((REPONUM + 1))"
|
||||
else
|
||||
local hgDepth="0"
|
||||
fi
|
||||
if [ ! -z "$(bzr root 2>/dev/null)" ]; then
|
||||
local bzrPath="$(bzr root 2>/dev/null)"
|
||||
local bzrDepth="$(pathSegment "${bzrPath}")"
|
||||
REPONUM="$((REPONUM+1))"
|
||||
REPONUM="$((REPONUM + 1))"
|
||||
else
|
||||
local bzrDepth="0"
|
||||
fi
|
||||
@@ -1114,12 +1111,12 @@ repoTest() {
|
||||
local svnPath="$(svn info --xml | sed -n -e "s:${stringz}::" -e "s:${stringx}::p")"
|
||||
# An old enough svn will not be able give us a path; default
|
||||
# to 1 for that case.
|
||||
if [ -z "${svnPath}" ]; then
|
||||
if [ -z "${svnPath}" ]; then
|
||||
local svnDepth="1"
|
||||
else
|
||||
local svnDepth="$(pathSegment "${svnPath}")"
|
||||
fi
|
||||
REPONUM="$((REPONUM+1))"
|
||||
REPONUM="$((REPONUM + 1))"
|
||||
else
|
||||
local svnDepth="0"
|
||||
fi
|
||||
@@ -1142,8 +1139,6 @@ repoTest() {
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
|
||||
# Detect which repos we are in and gather data.
|
||||
# shellcheck source=/dev/null
|
||||
if [ -f "${CACHEFILE}" ] && [ "${CACHEFORCE}" = "1" ]; then
|
||||
@@ -1165,7 +1160,6 @@ else
|
||||
fi
|
||||
fi
|
||||
|
||||
|
||||
# -s output is handled here.
|
||||
if [ ! -z "${VAROUT}" ]; then
|
||||
if [ "${VAROUT}" = "VCS_TYPE" ]; then
|
||||
@@ -1196,7 +1190,6 @@ if [ ! -z "${VAROUT}" ]; then
|
||||
fi
|
||||
fi
|
||||
|
||||
|
||||
# Detect requested output type and use it.
|
||||
if [ ! -z "${AFILETYPE}" ]; then
|
||||
if [ "${AFILETYPE}" = "c" ]; then
|
||||
@@ -1251,7 +1244,6 @@ if [ ! -z "${AFILETYPE}" ]; then
|
||||
fi
|
||||
fi
|
||||
|
||||
|
||||
# If requested, make a cache file.
|
||||
if [ ! -z "${CACHEFILE}" ] && [ ! "${CACHEFORCE}" = "1" ]; then
|
||||
TARGETFILE="${CACHEFILE}.tmp"
|
||||
12
ci/envelope_rpm.sh
Normal file
12
ci/envelope_rpm.sh
Normal file
@@ -0,0 +1,12 @@
|
||||
#!/usr/bin/env sh
|
||||
|
||||
ls $CI_PROJECT_DIR/build/*.rpm
|
||||
|
||||
BIN_TO_PROTECT_IN_RPM="${INSTALL_PREFIX}/bin/stellar"
|
||||
RPMS_FULL_PATH=$(ls $CI_PROJECT_DIR/build/*.rpm | grep -v debug | grep -v devel)
|
||||
echo "RPMS_TO_BE_ENVELOPE: " $RPMS_FULL_PATH
|
||||
|
||||
for RPM in ${RPMS_FULL_PATH[@]}; do
|
||||
echo "ENVELOPE: " $RPM
|
||||
/root/rebuildrpm_and_envelope.sh $RPM $BIN_TO_PROTECT_IN_RPM $FEATURE_ID $APP_NAME_IN_RPM_SPEC
|
||||
done
|
||||
48
ci/get-nprocessors.sh
Normal file
48
ci/get-nprocessors.sh
Normal file
@@ -0,0 +1,48 @@
|
||||
#!/usr/bin/env bash
|
||||
# Copyright 2017 Google Inc.
|
||||
# All Rights Reserved.
|
||||
#
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are
|
||||
# met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above
|
||||
# copyright notice, this list of conditions and the following disclaimer
|
||||
# in the documentation and/or other materials provided with the
|
||||
# distribution.
|
||||
# * Neither the name of Google Inc. nor the names of its
|
||||
# contributors may be used to endorse or promote products derived from
|
||||
# this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
# This file is typically sourced by another script.
|
||||
# if possible, ask for the precise number of processors,
|
||||
# otherwise take 2 processors as reasonable default; see
|
||||
# https://docs.travis-ci.com/user/speeding-up-the-build/#Makefile-optimization
|
||||
if [ -x /usr/bin/getconf ]; then
|
||||
NPROCESSORS=$(/usr/bin/getconf _NPROCESSORS_ONLN)
|
||||
else
|
||||
NPROCESSORS=2
|
||||
fi
|
||||
|
||||
# as of 2017-09-04 Travis CI reports 32 processors, but GCC build
|
||||
# crashes if parallelized too much (maybe memory consumption problem),
|
||||
# so limit to 4 processors for the time being.
|
||||
if [ $NPROCESSORS -gt 4 ]; then
|
||||
echo "$0:Note: Limiting processors to use by make from $NPROCESSORS to 4."
|
||||
NPROCESSORS=4
|
||||
fi
|
||||
3
ci/perpare_pulp3_netrc.sh
Normal file
3
ci/perpare_pulp3_netrc.sh
Normal file
@@ -0,0 +1,3 @@
|
||||
#!/usr/bin/env sh
|
||||
set -evx
|
||||
echo "machine ${PULP3_SERVER_URL}\nlogin ${PULP3_SERVER_LOGIN}\npassword ${PULP3_SERVER_PASSWORD}\n" >~/.netrc
|
||||
66
ci/travis.sh
Normal file
66
ci/travis.sh
Normal file
@@ -0,0 +1,66 @@
|
||||
#!/usr/bin/env sh
|
||||
set -evx
|
||||
|
||||
chmod +x ci/get-nprocessors.sh
|
||||
. ci/get-nprocessors.sh
|
||||
|
||||
# if possible, ask for the precise number of processors,
|
||||
# otherwise take 2 processors as reasonable default; see
|
||||
# https://docs.travis-ci.com/user/speeding-up-the-build/#Makefile-optimization
|
||||
if [ -x /usr/bin/getconf ]; then
|
||||
NPROCESSORS=$(/usr/bin/getconf _NPROCESSORS_ONLN)
|
||||
else
|
||||
NPROCESSORS=2
|
||||
fi
|
||||
|
||||
# as of 2017-09-04 Travis CI reports 32 processors, but GCC build
|
||||
# crashes if parallelized too much (maybe memory consumption problem),
|
||||
# so limit to 4 processors for the time being.
|
||||
if [ $NPROCESSORS -gt 4 ]; then
|
||||
echo "$0:Note: Limiting processors to use by make from $NPROCESSORS to 4."
|
||||
NPROCESSORS=4
|
||||
fi
|
||||
|
||||
# Tell make to use the processors. No preceding '-' required.
|
||||
MAKEFLAGS="j${NPROCESSORS}"
|
||||
export MAKEFLAGS
|
||||
|
||||
env | sort
|
||||
|
||||
# Set default values to OFF for these variables if not specified.
|
||||
: "${NO_EXCEPTION:=OFF}"
|
||||
: "${NO_RTTI:=OFF}"
|
||||
: "${COMPILER_IS_GNUCXX:=OFF}"
|
||||
|
||||
# Install dependency from YUM
|
||||
yum install -y libpcap-devel
|
||||
|
||||
if [ $ASAN_OPTION ]; then
|
||||
source /opt/rh/devtoolset-7/enable
|
||||
fi
|
||||
|
||||
mkdir build || true
|
||||
cd build
|
||||
|
||||
cmake3 -DCMAKE_CXX_FLAGS=$CXX_FLAGS \
|
||||
-DCMAKE_BUILD_TYPE=$BUILD_TYPE \
|
||||
-DASAN_OPTION=$ASAN_OPTION \
|
||||
-DCMAKE_INSTALL_PREFIX=$INSTALL_PREFIX \
|
||||
-DTFE_VERSION_DAILY_BUILD=$TESTING_VERSION_BUILD \
|
||||
..
|
||||
|
||||
make
|
||||
make test
|
||||
|
||||
if [ -n "${PACKAGE}" ]; then
|
||||
make package
|
||||
cp ~/rpm_upload_tools.py ./
|
||||
python3 rpm_upload_tools.py ${PULP3_REPO_NAME} ${PULP3_DIST_NAME} *.rpm
|
||||
fi
|
||||
|
||||
if [ -n "${UPLOAD_SYMBOL_FILES}" ]; then
|
||||
rpm -i stellar*debuginfo*.rpm
|
||||
ls -ahl /usr/lib/debug/opt/tsg/stellar/bin/
|
||||
cp /usr/lib/debug/opt/tsg/stellar/bin/stellar*debug /tmp/stellar.debuginfo.${CI_COMMIT_SHORT_SHA}
|
||||
sentry-cli upload-dif -t elf /tmp/stellar.debuginfo.${CI_COMMIT_SHORT_SHA}
|
||||
fi
|
||||
21
ci/upload_enveloped_rpm.sh
Normal file
21
ci/upload_enveloped_rpm.sh
Normal file
@@ -0,0 +1,21 @@
|
||||
#!/usr/bin/env sh
|
||||
|
||||
cd $CI_PROJECT_DIR/build/
|
||||
cp ~/rpm_upload_tools.py ./
|
||||
|
||||
ls -ahl *.rpm
|
||||
|
||||
RPM_IS_EL7=$(ls -ahl *-pr-*.rpm | grep el7 | wc -l)
|
||||
RPM_IS_EL8=$(ls -ahl *-pr-*.rpm | grep el8 | wc -l)
|
||||
|
||||
if [ $RPM_IS_EL7 -eq 1 ]; then
|
||||
echo "====== Upload the packed RPM package for CentOS7 ======"
|
||||
python3 rpm_upload_tools.py ${PULP3_REPO_NAME_EL7} ${PULP3_DIST_NAME_EL7} *-pr-*el7*.rpm
|
||||
fi
|
||||
|
||||
if [ $RPM_IS_EL8 -eq 1 ]; then
|
||||
echo "====== Upload the packed RPM package for CentOS8 ======"
|
||||
python3 rpm_upload_tools.py ${PULP3_REPO_NAME_EL8} ${PULP3_DIST_NAME_EL8} *-pr-*el8*.rpm
|
||||
fi
|
||||
|
||||
rm -rf *.rpm
|
||||
39
cmake/FindSYSTEMD.cmake
Normal file
39
cmake/FindSYSTEMD.cmake
Normal file
@@ -0,0 +1,39 @@
|
||||
# - Find SystemdDaemon
|
||||
# Find the systemd daemon library
|
||||
#
|
||||
# This module defines the following variables:
|
||||
# SYSTEMD_FOUND - True if library and include directory are found
|
||||
# If set to TRUE, the following are also defined:
|
||||
# SYSTEMD_INCLUDE_DIRS - The directory where to find the header file
|
||||
# SYSTEMD_LIBRARIES - Where to find the library file
|
||||
#
|
||||
# For conveniance, these variables are also set. They have the same values
|
||||
# than the variables above. The user can thus choose his/her prefered way
|
||||
# to write them.
|
||||
# SYSTEMD_LIBRARY
|
||||
# SYSTEMD_INCLUDE_DIR
|
||||
#
|
||||
# This file is in the public domain
|
||||
|
||||
include(FindPkgConfig)
|
||||
pkg_check_modules(SYSTEMD libsystemd)
|
||||
|
||||
if(NOT SYSTEMD_FOUND)
|
||||
find_path(SYSTEMD_INCLUDE_DIRS NAMES systemd/sd-daemon.h
|
||||
DOC "The Systemd include directory")
|
||||
|
||||
find_library(SYSTEMD_LIBRARIES NAMES systemd
|
||||
DOC "The Systemd library")
|
||||
|
||||
# Use some standard module to handle the QUIETLY and REQUIRED arguments, and
|
||||
# set SYSTEMD_FOUND to TRUE if these two variables are set.
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(SYSTEMD REQUIRED_VARS SYSTEMD_LIBRARIES SYSTEMD_INCLUDE_DIRS)
|
||||
|
||||
if(SYSTEMD_FOUND)
|
||||
set(SYSTEMD_LIBRARY ${SYSTEMD_LIBRARIES})
|
||||
set(SYSTEMD_INCLUDE_DIR ${SYSTEMD_INCLUDE_DIRS})
|
||||
endif()
|
||||
endif()
|
||||
|
||||
mark_as_advanced(SYSTEMD_INCLUDE_DIRS SYSTEMD_LIBRARIES)
|
||||
35
cmake/Package.cmake
Normal file
35
cmake/Package.cmake
Normal file
@@ -0,0 +1,35 @@
|
||||
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
|
||||
set(CPACK_PACKAGE_NAME "stellar-debug")
|
||||
else()
|
||||
set(CPACK_PACKAGE_NAME "stellar")
|
||||
endif()
|
||||
|
||||
message(STATUS "Package: ${CPACK_PACKAGE_NAME}")
|
||||
|
||||
set(CPACK_PACKAGE_VENDOR "TSG")
|
||||
set(CPACK_PACKAGE_VERSION_MAJOR "${STELLAR_VERSION_MAJOR}")
|
||||
set(CPACK_PACKAGE_VERSION_MINOR "${STELLAR_VERSION_MINOR}")
|
||||
set(CPACK_PACKAGE_VERSION_PATCH "${STELLAR_VERSION_PATCH}.${STELLAR_DESCRIBE}")
|
||||
set(CPACK_PACKAGING_INSTALL_PREFIX ${CMAKE_INSTALL_PREFIX})
|
||||
|
||||
# RPM Build
|
||||
set(CPACK_GENERATOR "RPM")
|
||||
set(CPACK_RPM_AUTO_GENERATED_FILE_NAME ON)
|
||||
set(CPACK_RPM_FILE_NAME "RPM-DEFAULT")
|
||||
set(CPACK_RPM_PACKAGE_AUTOREQPROV "no")
|
||||
set(CPACK_RPM_PACKAGE_RELEASE_DIST on)
|
||||
set(CPACK_RPM_DEBUGINFO_PACKAGE on)
|
||||
set(CPACK_RPM_POST_INSTALL_SCRIPT_FILE ${CMAKE_SOURCE_DIR}/cmake/PostInstall.in)
|
||||
set(CPACK_RPM_POST_UNINSTALL_SCRIPT_FILE ${CMAKE_SOURCE_DIR}/cmake/PostUninstall.in)
|
||||
set(CPACK_RPM_PRE_UNINSTALL_SCRIPT_FILE ${CMAKE_SOURCE_DIR}/cmake/PreUninstall.in)
|
||||
|
||||
# Must uninstall the debug package before install release package
|
||||
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
|
||||
set(CPACK_RPM_PACKAGE_CONFLICTS "stellar")
|
||||
else()
|
||||
set(CPACK_RPM_PACKAGE_CONFLICTS "stellar-debug")
|
||||
endif()
|
||||
|
||||
# Setup %config(noreplace)
|
||||
set(CPACK_RPM_USER_FILELIST "%config(noreplace) ${CMAKE_INSTALL_PREFIX}/conf/stellar/stellar.conf")
|
||||
include(CPack)
|
||||
1
cmake/PostInstall.in
Normal file
1
cmake/PostInstall.in
Normal file
@@ -0,0 +1 @@
|
||||
/sbin/ldconfig
|
||||
1
cmake/PostUninstall.in
Normal file
1
cmake/PostUninstall.in
Normal file
@@ -0,0 +1 @@
|
||||
/sbin/ldconfig
|
||||
1
cmake/PreUninstall.in
Normal file
1
cmake/PreUninstall.in
Normal file
@@ -0,0 +1 @@
|
||||
/sbin/ldconfig
|
||||
@@ -1,58 +1,47 @@
|
||||
|
||||
# Using autorevision.sh to generate version information
|
||||
|
||||
set(__SOURCE_AUTORESIVISION ${CMAKE_SOURCE_DIR}/cmake/autorevision.sh)
|
||||
set(__SOURCE_AUTORESIVISION ${CMAKE_SOURCE_DIR}/autorevision.sh)
|
||||
set(__AUTORESIVISION ${CMAKE_BINARY_DIR}/autorevision.sh)
|
||||
set(__VERSION_CACHE ${CMAKE_BINARY_DIR}/version.txt)
|
||||
set(__VERSION_CACHE ${CMAKE_SOURCE_DIR}/version.txt)
|
||||
set(__VERSION_CONFIG ${CMAKE_BINARY_DIR}/version.cmake)
|
||||
|
||||
file(COPY ${__SOURCE_AUTORESIVISION} DESTINATION ${CMAKE_BINARY_DIR}
|
||||
FILE_PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE
|
||||
WORLD_READ WORLD_EXECUTE)
|
||||
|
||||
# execute autorevision.sh to generate version information
|
||||
execute_process(COMMAND ${__AUTORESIVISION} -t cmake -o ${__VERSION_CACHE}
|
||||
OUTPUT_FILE ${__VERSION_CONFIG} ERROR_QUIET)
|
||||
# Execute autorevision.sh to generate version information
|
||||
execute_process(COMMAND ${__AUTORESIVISION} -t cmake -o ${__VERSION_CACHE} OUTPUT_FILE ${__VERSION_CONFIG})
|
||||
include(${__VERSION_CONFIG})
|
||||
|
||||
# extract major, minor, patch version from git tag
|
||||
string(REGEX REPLACE "^v([0-9]+)\\..*" "\\1" VERSION_MAJOR "${VCS_TAG}")
|
||||
string(REGEX REPLACE "^v[0-9]+\\.([0-9]+).*" "\\1" VERSION_MINOR "${VCS_TAG}")
|
||||
string(REGEX REPLACE "^v[0-9]+\\.[0-9]+\\.([0-9]+).*" "\\1" VERSION_PATCH "${VCS_TAG}")
|
||||
# Extract major, minor, patch version from git tag
|
||||
string(REGEX REPLACE "^v([0-9]+)\\..*" "\\1" STELLAR_VERSION_MAJOR "${VCS_TAG}")
|
||||
string(REGEX REPLACE "^v[0-9]+\\.([0-9]+).*" "\\1" STELLAR_VERSION_MINOR "${VCS_TAG}")
|
||||
string(REGEX REPLACE "^v[0-9]+\\.[0-9]+\\.([0-9]+).*" "\\1" STELLAR_VERSION_PATCH "${VCS_TAG}")
|
||||
string(REGEX REPLACE "[T\\:\\+\\-]" "" STELLAR_VERSION_DATE "${VCS_DATE}")
|
||||
|
||||
string(REGEX REPLACE "[T\\:\\+\\-]" "" VERSION_DATE "${VCS_DATE}")
|
||||
|
||||
if(VERSION_DAILY_BUILD)
|
||||
set(VERSION_PATCH ${VERSION_PATCH}.${VERSION_DATE})
|
||||
if(STELLAR_VERSION_DAILY_BUILD)
|
||||
set(STELLAR_VERSION_PATCH ${STELLAR_VERSION_PATCH}.${STELLAR_VERSION_DATE})
|
||||
endif()
|
||||
|
||||
|
||||
if(NOT VERSION_MAJOR)
|
||||
set(VERSION_MAJOR 1)
|
||||
if(NOT STELLAR_VERSION_MAJOR)
|
||||
set(STELLAR_VERSION_MAJOR 3)
|
||||
endif()
|
||||
|
||||
if(NOT VERSION_MINOR)
|
||||
set(VERSION_MINOR 0)
|
||||
if(NOT STELLAR_VERSION_MINOR)
|
||||
set(STELLAR_VERSION_MINOR 0)
|
||||
endif()
|
||||
|
||||
if(NOT VERSION_PATCH)
|
||||
set(VERSION_PATCH 0)
|
||||
if(NOT STELLAR_VERSION_PATCH)
|
||||
set(STELLAR_VERSION_PATCH 0)
|
||||
endif()
|
||||
|
||||
set(VERSION "${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}")
|
||||
set(VERSION_BUILD "${VCS_SHORT_HASH}")
|
||||
set(STELLAR_DESCRIBE "${VCS_SHORT_HASH}")
|
||||
set(STELLAR_VERSION "${STELLAR_VERSION_MAJOR}.${STELLAR_VERSION_MINOR}.${STELLAR_VERSION_PATCH}")
|
||||
set(STELLAR_GIT_VERSION "${STELLAR_VERSION_MAJOR}.${STELLAR_VERSION_MINOR}.${STELLAR_VERSION_PATCH}-${STELLAR_DESCRIBE}")
|
||||
|
||||
# print information
|
||||
message(STATUS "Version: ${VERSION}-${VERSION_BUILD}")
|
||||
# Replace .- with _
|
||||
string(REGEX REPLACE "[\\.\\-]" "_" STELLAR_VAR_VERSION "${STELLAR_GIT_VERSION}")
|
||||
|
||||
option(DEFINE_GIT_VERSION "Set DEFINE_GIT_VERSION to TRUE or FALSE" TRUE)
|
||||
|
||||
if(DEFINE_GIT_VERSION)
|
||||
|
||||
set(GIT_VERSION "${VERSION}-${CMAKE_BUILD_TYPE}-${VERSION_BUILD}-${VCS_BRANCH}-${VCS_DATE}")
|
||||
message(STATUS "GIT_VERSION: ${GIT_VERSION}")
|
||||
string(REGEX REPLACE "[-:+/\\.]" "_" GIT_VERSION ${GIT_VERSION})
|
||||
|
||||
add_definitions(-DGIT_VERSION=\"${GIT_VERSION}\")
|
||||
|
||||
endif()
|
||||
# Print information
|
||||
message(STATUS "Welcome to stateful network function development platform, Version: ${STELLAR_GIT_VERSION}")
|
||||
add_definitions(-DSTELLAR_GIT_VERSION=\"${STELLAR_GIT_VERSION}\")
|
||||
add_definitions(-DSTELLAR_VAR_VERSION=${STELLAR_VAR_VERSION})
|
||||
1
conf/CMakeLists.txt
Normal file
1
conf/CMakeLists.txt
Normal file
@@ -0,0 +1 @@
|
||||
install(DIRECTORY stellar DESTINATION conf COMPONENT Profile)
|
||||
3
deps/sds/CMakeLists.txt
vendored
Normal file
3
deps/sds/CMakeLists.txt
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
set(CMAKE_C_FLAGS "-std=c99")
|
||||
add_definitions(-fPIC)
|
||||
add_library(sds STATIC sds.c)
|
||||
1300
deps/sds/sds.c
vendored
Normal file
1300
deps/sds/sds.c
vendored
Normal file
File diff suppressed because it is too large
Load Diff
274
deps/sds/sds.h
vendored
Normal file
274
deps/sds/sds.h
vendored
Normal file
@@ -0,0 +1,274 @@
|
||||
/* SDSLib 2.0 -- A C dynamic strings library
|
||||
*
|
||||
* Copyright (c) 2006-2015, Salvatore Sanfilippo <antirez at gmail dot com>
|
||||
* Copyright (c) 2015, Oran Agra
|
||||
* Copyright (c) 2015, Redis Labs, Inc
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of Redis nor the names of its contributors may be used
|
||||
* to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef __SDS_H
|
||||
#define __SDS_H
|
||||
|
||||
#define SDS_MAX_PREALLOC (1024*1024)
|
||||
extern const char *SDS_NOINIT;
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdint.h>
|
||||
|
||||
typedef char *sds;
|
||||
|
||||
/* Note: sdshdr5 is never used, we just access the flags byte directly.
|
||||
* However is here to document the layout of type 5 SDS strings. */
|
||||
struct __attribute__ ((__packed__)) sdshdr5 {
|
||||
unsigned char flags; /* 3 lsb of type, and 5 msb of string length */
|
||||
char buf[];
|
||||
};
|
||||
struct __attribute__ ((__packed__)) sdshdr8 {
|
||||
uint8_t len; /* used */
|
||||
uint8_t alloc; /* excluding the header and null terminator */
|
||||
unsigned char flags; /* 3 lsb of type, 5 unused bits */
|
||||
char buf[];
|
||||
};
|
||||
struct __attribute__ ((__packed__)) sdshdr16 {
|
||||
uint16_t len; /* used */
|
||||
uint16_t alloc; /* excluding the header and null terminator */
|
||||
unsigned char flags; /* 3 lsb of type, 5 unused bits */
|
||||
char buf[];
|
||||
};
|
||||
struct __attribute__ ((__packed__)) sdshdr32 {
|
||||
uint32_t len; /* used */
|
||||
uint32_t alloc; /* excluding the header and null terminator */
|
||||
unsigned char flags; /* 3 lsb of type, 5 unused bits */
|
||||
char buf[];
|
||||
};
|
||||
struct __attribute__ ((__packed__)) sdshdr64 {
|
||||
uint64_t len; /* used */
|
||||
uint64_t alloc; /* excluding the header and null terminator */
|
||||
unsigned char flags; /* 3 lsb of type, 5 unused bits */
|
||||
char buf[];
|
||||
};
|
||||
|
||||
#define SDS_TYPE_5 0
|
||||
#define SDS_TYPE_8 1
|
||||
#define SDS_TYPE_16 2
|
||||
#define SDS_TYPE_32 3
|
||||
#define SDS_TYPE_64 4
|
||||
#define SDS_TYPE_MASK 7
|
||||
#define SDS_TYPE_BITS 3
|
||||
#define SDS_HDR_VAR(T,s) struct sdshdr##T *sh = (void*)((s)-(sizeof(struct sdshdr##T)));
|
||||
#define SDS_HDR(T,s) ((struct sdshdr##T *)((s)-(sizeof(struct sdshdr##T))))
|
||||
#define SDS_TYPE_5_LEN(f) ((f)>>SDS_TYPE_BITS)
|
||||
|
||||
static inline size_t sdslen(const sds s) {
|
||||
unsigned char flags = s[-1];
|
||||
switch(flags&SDS_TYPE_MASK) {
|
||||
case SDS_TYPE_5:
|
||||
return SDS_TYPE_5_LEN(flags);
|
||||
case SDS_TYPE_8:
|
||||
return SDS_HDR(8,s)->len;
|
||||
case SDS_TYPE_16:
|
||||
return SDS_HDR(16,s)->len;
|
||||
case SDS_TYPE_32:
|
||||
return SDS_HDR(32,s)->len;
|
||||
case SDS_TYPE_64:
|
||||
return SDS_HDR(64,s)->len;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline size_t sdsavail(const sds s) {
|
||||
unsigned char flags = s[-1];
|
||||
switch(flags&SDS_TYPE_MASK) {
|
||||
case SDS_TYPE_5: {
|
||||
return 0;
|
||||
}
|
||||
case SDS_TYPE_8: {
|
||||
SDS_HDR_VAR(8,s);
|
||||
return sh->alloc - sh->len;
|
||||
}
|
||||
case SDS_TYPE_16: {
|
||||
SDS_HDR_VAR(16,s);
|
||||
return sh->alloc - sh->len;
|
||||
}
|
||||
case SDS_TYPE_32: {
|
||||
SDS_HDR_VAR(32,s);
|
||||
return sh->alloc - sh->len;
|
||||
}
|
||||
case SDS_TYPE_64: {
|
||||
SDS_HDR_VAR(64,s);
|
||||
return sh->alloc - sh->len;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void sdssetlen(sds s, size_t newlen) {
|
||||
unsigned char flags = s[-1];
|
||||
switch(flags&SDS_TYPE_MASK) {
|
||||
case SDS_TYPE_5:
|
||||
{
|
||||
unsigned char *fp = ((unsigned char*)s)-1;
|
||||
*fp = SDS_TYPE_5 | (newlen << SDS_TYPE_BITS);
|
||||
}
|
||||
break;
|
||||
case SDS_TYPE_8:
|
||||
SDS_HDR(8,s)->len = newlen;
|
||||
break;
|
||||
case SDS_TYPE_16:
|
||||
SDS_HDR(16,s)->len = newlen;
|
||||
break;
|
||||
case SDS_TYPE_32:
|
||||
SDS_HDR(32,s)->len = newlen;
|
||||
break;
|
||||
case SDS_TYPE_64:
|
||||
SDS_HDR(64,s)->len = newlen;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void sdsinclen(sds s, size_t inc) {
|
||||
unsigned char flags = s[-1];
|
||||
switch(flags&SDS_TYPE_MASK) {
|
||||
case SDS_TYPE_5:
|
||||
{
|
||||
unsigned char *fp = ((unsigned char*)s)-1;
|
||||
unsigned char newlen = SDS_TYPE_5_LEN(flags)+inc;
|
||||
*fp = SDS_TYPE_5 | (newlen << SDS_TYPE_BITS);
|
||||
}
|
||||
break;
|
||||
case SDS_TYPE_8:
|
||||
SDS_HDR(8,s)->len += inc;
|
||||
break;
|
||||
case SDS_TYPE_16:
|
||||
SDS_HDR(16,s)->len += inc;
|
||||
break;
|
||||
case SDS_TYPE_32:
|
||||
SDS_HDR(32,s)->len += inc;
|
||||
break;
|
||||
case SDS_TYPE_64:
|
||||
SDS_HDR(64,s)->len += inc;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* sdsalloc() = sdsavail() + sdslen() */
|
||||
static inline size_t sdsalloc(const sds s) {
|
||||
unsigned char flags = s[-1];
|
||||
switch(flags&SDS_TYPE_MASK) {
|
||||
case SDS_TYPE_5:
|
||||
return SDS_TYPE_5_LEN(flags);
|
||||
case SDS_TYPE_8:
|
||||
return SDS_HDR(8,s)->alloc;
|
||||
case SDS_TYPE_16:
|
||||
return SDS_HDR(16,s)->alloc;
|
||||
case SDS_TYPE_32:
|
||||
return SDS_HDR(32,s)->alloc;
|
||||
case SDS_TYPE_64:
|
||||
return SDS_HDR(64,s)->alloc;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void sdssetalloc(sds s, size_t newlen) {
|
||||
unsigned char flags = s[-1];
|
||||
switch(flags&SDS_TYPE_MASK) {
|
||||
case SDS_TYPE_5:
|
||||
/* Nothing to do, this type has no total allocation info. */
|
||||
break;
|
||||
case SDS_TYPE_8:
|
||||
SDS_HDR(8,s)->alloc = newlen;
|
||||
break;
|
||||
case SDS_TYPE_16:
|
||||
SDS_HDR(16,s)->alloc = newlen;
|
||||
break;
|
||||
case SDS_TYPE_32:
|
||||
SDS_HDR(32,s)->alloc = newlen;
|
||||
break;
|
||||
case SDS_TYPE_64:
|
||||
SDS_HDR(64,s)->alloc = newlen;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
sds sdsnewlen(const void *init, size_t initlen);
|
||||
sds sdsnew(const char *init);
|
||||
sds sdsempty(void);
|
||||
sds sdsdup(const sds s);
|
||||
void sdsfree(sds s);
|
||||
sds sdsgrowzero(sds s, size_t len);
|
||||
sds sdscatlen(sds s, const void *t, size_t len);
|
||||
sds sdscat(sds s, const char *t);
|
||||
sds sdscatsds(sds s, const sds t);
|
||||
sds sdscpylen(sds s, const char *t, size_t len);
|
||||
sds sdscpy(sds s, const char *t);
|
||||
|
||||
sds sdscatvprintf(sds s, const char *fmt, va_list ap);
|
||||
#ifdef __GNUC__
|
||||
sds sdscatprintf(sds s, const char *fmt, ...)
|
||||
__attribute__((format(printf, 2, 3)));
|
||||
#else
|
||||
sds sdscatprintf(sds s, const char *fmt, ...);
|
||||
#endif
|
||||
|
||||
sds sdscatfmt(sds s, char const *fmt, ...);
|
||||
sds sdstrim(sds s, const char *cset);
|
||||
void sdsrange(sds s, ssize_t start, ssize_t end);
|
||||
void sdsupdatelen(sds s);
|
||||
void sdsclear(sds s);
|
||||
int sdscmp(const sds s1, const sds s2);
|
||||
sds *sdssplitlen(const char *s, ssize_t len, const char *sep, int seplen, int *count);
|
||||
void sdsfreesplitres(sds *tokens, int count);
|
||||
void sdstolower(sds s);
|
||||
void sdstoupper(sds s);
|
||||
sds sdsfromlonglong(long long value);
|
||||
sds sdscatrepr(sds s, const char *p, size_t len);
|
||||
sds *sdssplitargs(const char *line, int *argc);
|
||||
sds sdsmapchars(sds s, const char *from, const char *to, size_t setlen);
|
||||
sds sdsjoin(char **argv, int argc, char *sep);
|
||||
sds sdsjoinsds(sds *argv, int argc, const char *sep, size_t seplen);
|
||||
|
||||
/* Low level functions exposed to the user API */
|
||||
sds sdsMakeRoomFor(sds s, size_t addlen);
|
||||
void sdsIncrLen(sds s, ssize_t incr);
|
||||
sds sdsRemoveFreeSpace(sds s);
|
||||
size_t sdsAllocSize(sds s);
|
||||
void *sdsAllocPtr(sds s);
|
||||
|
||||
/* Export the allocator used by SDS to the program using SDS.
|
||||
* Sometimes the program SDS is linked to, may use a different set of
|
||||
* allocators, but may want to allocate or free things that SDS will
|
||||
* respectively free or allocate. */
|
||||
void *sds_malloc(size_t size);
|
||||
void *sds_realloc(void *ptr, size_t size);
|
||||
void sds_free(void *ptr);
|
||||
|
||||
#ifdef REDIS_TEST
|
||||
int sdsTest(int argc, char *argv[]);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
42
deps/sds/sdsalloc.h
vendored
Normal file
42
deps/sds/sdsalloc.h
vendored
Normal file
@@ -0,0 +1,42 @@
|
||||
/* SDSLib 2.0 -- A C dynamic strings library
|
||||
*
|
||||
* Copyright (c) 2006-2015, Salvatore Sanfilippo <antirez at gmail dot com>
|
||||
* Copyright (c) 2015, Oran Agra
|
||||
* Copyright (c) 2015, Redis Labs, Inc
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of Redis nor the names of its contributors may be used
|
||||
* to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/* SDS allocator selection.
|
||||
*
|
||||
* This file is used in order to change the SDS allocator at compile time.
|
||||
* Just define the following defines to what you want to use. Also add
|
||||
* the include of your alternate allocator if needed (not needed in order
|
||||
* to use the default libc allocator). */
|
||||
|
||||
#define s_malloc malloc
|
||||
#define s_realloc realloc
|
||||
#define s_free free
|
||||
3
deps/timeout/CMakeLists.txt
vendored
Normal file
3
deps/timeout/CMakeLists.txt
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
set(CMAKE_C_FLAGS "-std=c99")
|
||||
add_definitions(-fPIC)
|
||||
add_library(timeout STATIC timeout.c timeout-bitops.c)
|
||||
249
deps/timeout/timeout-bitops.c
vendored
Normal file
249
deps/timeout/timeout-bitops.c
vendored
Normal file
@@ -0,0 +1,249 @@
|
||||
#include <stdint.h>
|
||||
#ifdef _MSC_VER
|
||||
#include <intrin.h> /* _BitScanForward, _BitScanReverse */
|
||||
#endif
|
||||
|
||||
/* First define ctz and clz functions; these are compiler-dependent if
|
||||
* you want them to be fast. */
|
||||
#if defined(__GNUC__) && !defined(TIMEOUT_DISABLE_GNUC_BITOPS)
|
||||
|
||||
/* On GCC and clang and some others, we can use __builtin functions. They
|
||||
* are not defined for n==0, but timeout.s never calls them with n==0. */
|
||||
|
||||
#define ctz64(n) __builtin_ctzll(n)
|
||||
#define clz64(n) __builtin_clzll(n)
|
||||
#if LONG_BITS == 32
|
||||
#define ctz32(n) __builtin_ctzl(n)
|
||||
#define clz32(n) __builtin_clzl(n)
|
||||
#else
|
||||
#define ctz32(n) __builtin_ctz(n)
|
||||
#define clz32(n) __builtin_clz(n)
|
||||
#endif
|
||||
|
||||
#elif defined(_MSC_VER) && !defined(TIMEOUT_DISABLE_MSVC_BITOPS)
|
||||
|
||||
/* On MSVC, we have these handy functions. We can ignore their return
|
||||
* values, since we will never supply val == 0. */
|
||||
|
||||
static __inline int ctz32(unsigned long val)
|
||||
{
|
||||
DWORD zeros = 0;
|
||||
_BitScanForward(&zeros, val);
|
||||
return zeros;
|
||||
}
|
||||
static __inline int clz32(unsigned long val)
|
||||
{
|
||||
DWORD zeros = 0;
|
||||
_BitScanReverse(&zeros, val);
|
||||
return zeros;
|
||||
}
|
||||
#ifdef _WIN64
|
||||
/* According to the documentation, these only exist on Win64. */
|
||||
static __inline int ctz64(uint64_t val)
|
||||
{
|
||||
DWORD zeros = 0;
|
||||
_BitScanForward64(&zeros, val);
|
||||
return zeros;
|
||||
}
|
||||
static __inline int clz64(uint64_t val)
|
||||
{
|
||||
DWORD zeros = 0;
|
||||
_BitScanReverse64(&zeros, val);
|
||||
return zeros;
|
||||
}
|
||||
#else
|
||||
static __inline int ctz64(uint64_t val)
|
||||
{
|
||||
uint32_t lo = (uint32_t) val;
|
||||
uint32_t hi = (uint32_t) (val >> 32);
|
||||
return lo ? ctz32(lo) : 32 + ctz32(hi);
|
||||
}
|
||||
static __inline int clz64(uint64_t val)
|
||||
{
|
||||
uint32_t lo = (uint32_t) val;
|
||||
uint32_t hi = (uint32_t) (val >> 32);
|
||||
return hi ? clz32(hi) : 32 + clz32(lo);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* End of MSVC case. */
|
||||
|
||||
#else
|
||||
|
||||
/* TODO: There are more clever ways to do this in the generic case. */
|
||||
|
||||
|
||||
#define process_(one, cz_bits, bits) \
|
||||
if (x < ( one << (cz_bits - bits))) { rv += bits; x <<= bits; }
|
||||
|
||||
#define process64(bits) process_((UINT64_C(1)), 64, (bits))
|
||||
static inline int clz64(uint64_t x)
|
||||
{
|
||||
int rv = 0;
|
||||
|
||||
process64(32);
|
||||
process64(16);
|
||||
process64(8);
|
||||
process64(4);
|
||||
process64(2);
|
||||
process64(1);
|
||||
return rv;
|
||||
}
|
||||
#define process32(bits) process_((UINT32_C(1)), 32, (bits))
|
||||
static inline int clz32(uint32_t x)
|
||||
{
|
||||
int rv = 0;
|
||||
|
||||
process32(16);
|
||||
process32(8);
|
||||
process32(4);
|
||||
process32(2);
|
||||
process32(1);
|
||||
return rv;
|
||||
}
|
||||
|
||||
#undef process_
|
||||
#undef process32
|
||||
#undef process64
|
||||
#define process_(one, bits) \
|
||||
if ((x & ((one << (bits))-1)) == 0) { rv += bits; x >>= bits; }
|
||||
|
||||
#define process64(bits) process_((UINT64_C(1)), bits)
|
||||
static inline int ctz64(uint64_t x)
|
||||
{
|
||||
int rv = 0;
|
||||
|
||||
process64(32);
|
||||
process64(16);
|
||||
process64(8);
|
||||
process64(4);
|
||||
process64(2);
|
||||
process64(1);
|
||||
return rv;
|
||||
}
|
||||
|
||||
#define process32(bits) process_((UINT32_C(1)), bits)
|
||||
static inline int ctz32(uint32_t x)
|
||||
{
|
||||
int rv = 0;
|
||||
|
||||
process32(16);
|
||||
process32(8);
|
||||
process32(4);
|
||||
process32(2);
|
||||
process32(1);
|
||||
return rv;
|
||||
}
|
||||
|
||||
#undef process32
|
||||
#undef process64
|
||||
#undef process_
|
||||
|
||||
/* End of generic case */
|
||||
|
||||
#endif /* End of defining ctz */
|
||||
|
||||
#ifdef TEST_BITOPS
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
static uint64_t testcases[] = {
|
||||
13371337 * 10,
|
||||
100,
|
||||
385789752,
|
||||
82574,
|
||||
(((uint64_t)1)<<63) + (((uint64_t)1)<<31) + 10101
|
||||
};
|
||||
|
||||
static int
|
||||
naive_clz(int bits, uint64_t v)
|
||||
{
|
||||
int r = 0;
|
||||
uint64_t bit = ((uint64_t)1) << (bits-1);
|
||||
while (bit && 0 == (v & bit)) {
|
||||
r++;
|
||||
bit >>= 1;
|
||||
}
|
||||
/* printf("clz(%d,%lx) -> %d\n", bits, v, r); */
|
||||
return r;
|
||||
}
|
||||
|
||||
static int
|
||||
naive_ctz(int bits, uint64_t v)
|
||||
{
|
||||
int r = 0;
|
||||
uint64_t bit = 1;
|
||||
while (bit && 0 == (v & bit)) {
|
||||
r++;
|
||||
bit <<= 1;
|
||||
if (r == bits)
|
||||
break;
|
||||
}
|
||||
/* printf("ctz(%d,%lx) -> %d\n", bits, v, r); */
|
||||
return r;
|
||||
}
|
||||
|
||||
static int
|
||||
check(uint64_t vv)
|
||||
{
|
||||
uint32_t v32 = (uint32_t) vv;
|
||||
|
||||
if (vv == 0)
|
||||
return 1; /* c[tl]z64(0) is undefined. */
|
||||
|
||||
if (ctz64(vv) != naive_ctz(64, vv)) {
|
||||
printf("mismatch with ctz64: %d\n", ctz64(vv));
|
||||
exit(1);
|
||||
return 0;
|
||||
}
|
||||
if (clz64(vv) != naive_clz(64, vv)) {
|
||||
printf("mismatch with clz64: %d\n", clz64(vv));
|
||||
exit(1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (v32 == 0)
|
||||
return 1; /* c[lt]z(0) is undefined. */
|
||||
|
||||
if (ctz32(v32) != naive_ctz(32, v32)) {
|
||||
printf("mismatch with ctz32: %d\n", ctz32(v32));
|
||||
exit(1);
|
||||
return 0;
|
||||
}
|
||||
if (clz32(v32) != naive_clz(32, v32)) {
|
||||
printf("mismatch with clz32: %d\n", clz32(v32));
|
||||
exit(1);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
main(int c, char **v)
|
||||
{
|
||||
unsigned int i;
|
||||
const unsigned int n = sizeof(testcases)/sizeof(testcases[0]);
|
||||
int result = 0;
|
||||
|
||||
for (i = 0; i <= 63; ++i) {
|
||||
uint64_t x = 1 << i;
|
||||
if (!check(x))
|
||||
result = 1;
|
||||
--x;
|
||||
if (!check(x))
|
||||
result = 1;
|
||||
}
|
||||
|
||||
for (i = 0; i < n; ++i) {
|
||||
if (! check(testcases[i]))
|
||||
result = 1;
|
||||
}
|
||||
if (result) {
|
||||
puts("FAIL");
|
||||
} else {
|
||||
puts("OK");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
744
deps/timeout/timeout.c
vendored
Normal file
744
deps/timeout/timeout.c
vendored
Normal file
@@ -0,0 +1,744 @@
|
||||
/* ==========================================================================
|
||||
* timeout.c - Tickless hierarchical timing wheel.
|
||||
* --------------------------------------------------------------------------
|
||||
* Copyright (c) 2013, 2014 William Ahern
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to permit
|
||||
* persons to whom the Software is furnished to do so, subject to the
|
||||
* following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
||||
* NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||
* USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
* ==========================================================================
|
||||
*/
|
||||
#include <limits.h> /* CHAR_BIT */
|
||||
|
||||
#include <stddef.h> /* NULL */
|
||||
#include <stdlib.h> /* malloc(3) free(3) */
|
||||
#include <stdio.h> /* FILE fprintf(3) */
|
||||
|
||||
#include <inttypes.h> /* UINT64_C uint64_t */
|
||||
|
||||
#include <string.h> /* memset(3) */
|
||||
|
||||
#include <errno.h> /* errno */
|
||||
|
||||
#include <sys/queue.h> /* TAILQ(3) */
|
||||
|
||||
#include "timeout.h"
|
||||
|
||||
#if TIMEOUT_DEBUG - 0
|
||||
#include "timeout-debug.h"
|
||||
#endif
|
||||
|
||||
#ifdef TIMEOUT_DISABLE_RELATIVE_ACCESS
|
||||
#define TO_SET_TIMEOUTS(to, T) ((void)0)
|
||||
#else
|
||||
#define TO_SET_TIMEOUTS(to, T) ((to)->timeouts = (T))
|
||||
#endif
|
||||
|
||||
/*
|
||||
* A N C I L L A R Y R O U T I N E S
|
||||
*
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
#define abstime_t timeout_t /* for documentation purposes */
|
||||
#define reltime_t timeout_t /* "" */
|
||||
|
||||
#if !defined countof
|
||||
#define countof(a) (sizeof (a) / sizeof *(a))
|
||||
#endif
|
||||
|
||||
#if !defined endof
|
||||
#define endof(a) (&(a)[countof(a)])
|
||||
#endif
|
||||
|
||||
#if !defined MIN
|
||||
#define MIN(a, b) (((a) < (b))? (a) : (b))
|
||||
#endif
|
||||
|
||||
#if !defined MAX
|
||||
#define MAX(a, b) (((a) > (b))? (a) : (b))
|
||||
#endif
|
||||
|
||||
#if !defined TAILQ_CONCAT
|
||||
#define TAILQ_CONCAT(head1, head2, field) do { \
|
||||
if (!TAILQ_EMPTY(head2)) { \
|
||||
*(head1)->tqh_last = (head2)->tqh_first; \
|
||||
(head2)->tqh_first->field.tqe_prev = (head1)->tqh_last; \
|
||||
(head1)->tqh_last = (head2)->tqh_last; \
|
||||
TAILQ_INIT((head2)); \
|
||||
} \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
#if !defined TAILQ_FOREACH_SAFE
|
||||
#define TAILQ_FOREACH_SAFE(var, head, field, tvar) \
|
||||
for ((var) = TAILQ_FIRST(head); \
|
||||
(var) && ((tvar) = TAILQ_NEXT(var, field), 1); \
|
||||
(var) = (tvar))
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* B I T M A N I P U L A T I O N R O U T I N E S
|
||||
*
|
||||
* The macros and routines below implement wheel parameterization. The
|
||||
* inputs are:
|
||||
*
|
||||
* WHEEL_BIT - The number of value bits mapped in each wheel. The
|
||||
* lowest-order WHEEL_BIT bits index the lowest-order (highest
|
||||
* resolution) wheel, the next group of WHEEL_BIT bits the
|
||||
* higher wheel, etc.
|
||||
*
|
||||
* WHEEL_NUM - The number of wheels. WHEEL_BIT * WHEEL_NUM = the number of
|
||||
* value bits used by all the wheels. For the default of 6 and
|
||||
* 4, only the low 24 bits are processed. Any timeout value
|
||||
* larger than this will cycle through again.
|
||||
*
|
||||
* The implementation uses bit fields to remember which slot in each wheel
|
||||
* is populated, and to generate masks of expiring slots according to the
|
||||
* current update interval (i.e. the "tickless" aspect). The slots to
|
||||
* process in a wheel are (populated-set & interval-mask).
|
||||
*
|
||||
* WHEEL_BIT cannot be larger than 6 bits because 2^6 -> 64 is the largest
|
||||
* number of slots which can be tracked in a uint64_t integer bit field.
|
||||
* WHEEL_BIT cannot be smaller than 3 bits because of our rotr and rotl
|
||||
* routines, which only operate on all the value bits in an integer, and
|
||||
* there's no integer smaller than uint8_t.
|
||||
*
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
#if !defined WHEEL_BIT
|
||||
#define WHEEL_BIT 6
|
||||
#endif
|
||||
|
||||
#if !defined WHEEL_NUM
|
||||
#define WHEEL_NUM 4
|
||||
#endif
|
||||
|
||||
#define WHEEL_LEN (1U << WHEEL_BIT)
|
||||
#define WHEEL_MAX (WHEEL_LEN - 1)
|
||||
#define WHEEL_MASK (WHEEL_LEN - 1)
|
||||
#define TIMEOUT_MAX ((TIMEOUT_C(1) << (WHEEL_BIT * WHEEL_NUM)) - 1)
|
||||
|
||||
#include "timeout-bitops.c"
|
||||
|
||||
#if WHEEL_BIT == 6
|
||||
#define ctz(n) ctz64(n)
|
||||
#define clz(n) clz64(n)
|
||||
#define fls(n) ((int)(64 - clz64(n)))
|
||||
#else
|
||||
#define ctz(n) ctz32(n)
|
||||
#define clz(n) clz32(n)
|
||||
#define fls(n) ((int)(32 - clz32(n)))
|
||||
#endif
|
||||
|
||||
#if WHEEL_BIT == 6
|
||||
#define WHEEL_C(n) UINT64_C(n)
|
||||
#define WHEEL_PRIu PRIu64
|
||||
#define WHEEL_PRIx PRIx64
|
||||
|
||||
typedef uint64_t wheel_t;
|
||||
|
||||
#elif WHEEL_BIT == 5
|
||||
|
||||
#define WHEEL_C(n) UINT32_C(n)
|
||||
#define WHEEL_PRIu PRIu32
|
||||
#define WHEEL_PRIx PRIx32
|
||||
|
||||
typedef uint32_t wheel_t;
|
||||
|
||||
#elif WHEEL_BIT == 4
|
||||
|
||||
#define WHEEL_C(n) UINT16_C(n)
|
||||
#define WHEEL_PRIu PRIu16
|
||||
#define WHEEL_PRIx PRIx16
|
||||
|
||||
typedef uint16_t wheel_t;
|
||||
|
||||
#elif WHEEL_BIT == 3
|
||||
|
||||
#define WHEEL_C(n) UINT8_C(n)
|
||||
#define WHEEL_PRIu PRIu8
|
||||
#define WHEEL_PRIx PRIx8
|
||||
|
||||
typedef uint8_t wheel_t;
|
||||
|
||||
#else
|
||||
#error invalid WHEEL_BIT value
|
||||
#endif
|
||||
|
||||
|
||||
static inline wheel_t rotl(const wheel_t v, int c) {
|
||||
if (!(c &= (sizeof v * CHAR_BIT - 1)))
|
||||
return v;
|
||||
|
||||
return (v << c) | (v >> (sizeof v * CHAR_BIT - c));
|
||||
} /* rotl() */
|
||||
|
||||
|
||||
static inline wheel_t rotr(const wheel_t v, int c) {
|
||||
if (!(c &= (sizeof v * CHAR_BIT - 1)))
|
||||
return v;
|
||||
|
||||
return (v >> c) | (v << (sizeof v * CHAR_BIT - c));
|
||||
} /* rotr() */
|
||||
|
||||
|
||||
/*
|
||||
* T I M E R R O U T I N E S
|
||||
*
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
TAILQ_HEAD(timeout_list, timeout);
|
||||
|
||||
struct timeouts {
|
||||
struct timeout_list wheel[WHEEL_NUM][WHEEL_LEN], expired;
|
||||
|
||||
wheel_t pending[WHEEL_NUM];
|
||||
|
||||
timeout_t curtime;
|
||||
timeout_t hertz;
|
||||
}; /* struct timeouts */
|
||||
|
||||
|
||||
static struct timeouts *timeouts_init(struct timeouts *T, timeout_t hz) {
|
||||
unsigned i, j;
|
||||
|
||||
for (i = 0; i < countof(T->wheel); i++) {
|
||||
for (j = 0; j < countof(T->wheel[i]); j++) {
|
||||
TAILQ_INIT(&T->wheel[i][j]);
|
||||
}
|
||||
}
|
||||
|
||||
TAILQ_INIT(&T->expired);
|
||||
|
||||
for (i = 0; i < countof(T->pending); i++) {
|
||||
T->pending[i] = 0;
|
||||
}
|
||||
|
||||
T->curtime = 0;
|
||||
T->hertz = (hz)? hz : TIMEOUT_mHZ;
|
||||
|
||||
return T;
|
||||
} /* timeouts_init() */
|
||||
|
||||
|
||||
TIMEOUT_PUBLIC struct timeouts *timeouts_open(timeout_t hz, int *error) {
|
||||
struct timeouts *T;
|
||||
|
||||
if ((T = malloc(sizeof *T)))
|
||||
return timeouts_init(T, hz);
|
||||
|
||||
*error = errno;
|
||||
|
||||
return NULL;
|
||||
} /* timeouts_open() */
|
||||
|
||||
|
||||
static void timeouts_reset(struct timeouts *T) {
|
||||
struct timeout_list reset;
|
||||
struct timeout *to;
|
||||
unsigned i, j;
|
||||
|
||||
TAILQ_INIT(&reset);
|
||||
|
||||
for (i = 0; i < countof(T->wheel); i++) {
|
||||
for (j = 0; j < countof(T->wheel[i]); j++) {
|
||||
TAILQ_CONCAT(&reset, &T->wheel[i][j], tqe);
|
||||
}
|
||||
}
|
||||
|
||||
TAILQ_CONCAT(&reset, &T->expired, tqe);
|
||||
|
||||
TAILQ_FOREACH(to, &reset, tqe) {
|
||||
to->pending = NULL;
|
||||
TO_SET_TIMEOUTS(to, NULL);
|
||||
}
|
||||
} /* timeouts_reset() */
|
||||
|
||||
|
||||
TIMEOUT_PUBLIC void timeouts_close(struct timeouts *T) {
|
||||
/*
|
||||
* NOTE: Delete installed timeouts so timeout_pending() and
|
||||
* timeout_expired() worked as expected.
|
||||
*/
|
||||
timeouts_reset(T);
|
||||
|
||||
free(T);
|
||||
} /* timeouts_close() */
|
||||
|
||||
|
||||
TIMEOUT_PUBLIC timeout_t timeouts_hz(struct timeouts *T) {
|
||||
return T->hertz;
|
||||
} /* timeouts_hz() */
|
||||
|
||||
|
||||
TIMEOUT_PUBLIC void timeouts_del(struct timeouts *T, struct timeout *to) {
|
||||
if (to->pending) {
|
||||
TAILQ_REMOVE(to->pending, to, tqe);
|
||||
|
||||
if (to->pending != &T->expired && TAILQ_EMPTY(to->pending)) {
|
||||
ptrdiff_t index = to->pending - &T->wheel[0][0];
|
||||
int wheel = index / WHEEL_LEN;
|
||||
int slot = index % WHEEL_LEN;
|
||||
|
||||
T->pending[wheel] &= ~(WHEEL_C(1) << slot);
|
||||
}
|
||||
|
||||
to->pending = NULL;
|
||||
TO_SET_TIMEOUTS(to, NULL);
|
||||
}
|
||||
} /* timeouts_del() */
|
||||
|
||||
|
||||
static inline reltime_t timeout_rem(struct timeouts *T, struct timeout *to) {
|
||||
return to->expires - T->curtime;
|
||||
} /* timeout_rem() */
|
||||
|
||||
|
||||
static inline int timeout_wheel(timeout_t timeout) {
|
||||
/* must be called with timeout != 0, so fls input is nonzero */
|
||||
return (fls(MIN(timeout, TIMEOUT_MAX)) - 1) / WHEEL_BIT;
|
||||
} /* timeout_wheel() */
|
||||
|
||||
|
||||
static inline int timeout_slot(int wheel, timeout_t expires) {
|
||||
return WHEEL_MASK & ((expires >> (wheel * WHEEL_BIT)) - !!wheel);
|
||||
} /* timeout_slot() */
|
||||
|
||||
|
||||
static void timeouts_sched(struct timeouts *T, struct timeout *to, timeout_t expires) {
|
||||
timeout_t rem;
|
||||
int wheel, slot;
|
||||
|
||||
timeouts_del(T, to);
|
||||
|
||||
to->expires = expires;
|
||||
|
||||
TO_SET_TIMEOUTS(to, T);
|
||||
|
||||
if (expires > T->curtime) {
|
||||
rem = timeout_rem(T, to);
|
||||
|
||||
/* rem is nonzero since:
|
||||
* rem == timeout_rem(T,to),
|
||||
* == to->expires - T->curtime
|
||||
* and above we have expires > T->curtime.
|
||||
*/
|
||||
wheel = timeout_wheel(rem);
|
||||
slot = timeout_slot(wheel, to->expires);
|
||||
|
||||
to->pending = &T->wheel[wheel][slot];
|
||||
TAILQ_INSERT_TAIL(to->pending, to, tqe);
|
||||
|
||||
T->pending[wheel] |= WHEEL_C(1) << slot;
|
||||
} else {
|
||||
to->pending = &T->expired;
|
||||
TAILQ_INSERT_TAIL(to->pending, to, tqe);
|
||||
}
|
||||
} /* timeouts_sched() */
|
||||
|
||||
|
||||
#ifndef TIMEOUT_DISABLE_INTERVALS
|
||||
static void timeouts_readd(struct timeouts *T, struct timeout *to) {
|
||||
to->expires += to->interval;
|
||||
|
||||
if (to->expires <= T->curtime) {
|
||||
/* If we've missed the next firing of this timeout, reschedule
|
||||
* it to occur at the next multiple of its interval after
|
||||
* the last time that it fired.
|
||||
*/
|
||||
timeout_t n = T->curtime - to->expires;
|
||||
timeout_t r = n % to->interval;
|
||||
to->expires = T->curtime + (to->interval - r);
|
||||
}
|
||||
|
||||
timeouts_sched(T, to, to->expires);
|
||||
} /* timeouts_readd() */
|
||||
#endif
|
||||
|
||||
|
||||
TIMEOUT_PUBLIC void timeouts_add(struct timeouts *T, struct timeout *to, timeout_t timeout) {
|
||||
#ifndef TIMEOUT_DISABLE_INTERVALS
|
||||
if (to->flags & TIMEOUT_INT)
|
||||
to->interval = MAX(1, timeout);
|
||||
#endif
|
||||
|
||||
if (to->flags & TIMEOUT_ABS)
|
||||
timeouts_sched(T, to, timeout);
|
||||
else
|
||||
timeouts_sched(T, to, T->curtime + timeout);
|
||||
} /* timeouts_add() */
|
||||
|
||||
|
||||
TIMEOUT_PUBLIC void timeouts_update(struct timeouts *T, abstime_t curtime) {
|
||||
timeout_t elapsed = curtime - T->curtime;
|
||||
struct timeout_list todo;
|
||||
int wheel;
|
||||
|
||||
TAILQ_INIT(&todo);
|
||||
|
||||
/*
|
||||
* There's no avoiding looping over every wheel. It's best to keep
|
||||
* WHEEL_NUM smallish.
|
||||
*/
|
||||
for (wheel = 0; wheel < WHEEL_NUM; wheel++) {
|
||||
wheel_t pending;
|
||||
|
||||
/*
|
||||
* Calculate the slots expiring in this wheel
|
||||
*
|
||||
* If the elapsed time is greater than the maximum period of
|
||||
* the wheel, mark every position as expiring.
|
||||
*
|
||||
* Otherwise, to determine the expired slots fill in all the
|
||||
* bits between the last slot processed and the current
|
||||
* slot, inclusive of the last slot. We'll bitwise-AND this
|
||||
* with our pending set below.
|
||||
*
|
||||
* If a wheel rolls over, force a tick of the next higher
|
||||
* wheel.
|
||||
*/
|
||||
if ((elapsed >> (wheel * WHEEL_BIT)) > WHEEL_MAX) {
|
||||
pending = (wheel_t)~WHEEL_C(0);
|
||||
} else {
|
||||
wheel_t _elapsed = WHEEL_MASK & (elapsed >> (wheel * WHEEL_BIT));
|
||||
int oslot, nslot;
|
||||
|
||||
/*
|
||||
* TODO: It's likely that at least one of the
|
||||
* following three bit fill operations is redundant
|
||||
* or can be replaced with a simpler operation.
|
||||
*/
|
||||
oslot = WHEEL_MASK & (T->curtime >> (wheel * WHEEL_BIT));
|
||||
pending = rotl(((UINT64_C(1) << _elapsed) - 1), oslot);
|
||||
|
||||
nslot = WHEEL_MASK & (curtime >> (wheel * WHEEL_BIT));
|
||||
pending |= rotr(rotl(((WHEEL_C(1) << _elapsed) - 1), nslot), _elapsed);
|
||||
pending |= WHEEL_C(1) << nslot;
|
||||
}
|
||||
|
||||
while (pending & T->pending[wheel]) {
|
||||
/* ctz input cannot be zero: loop condition. */
|
||||
int slot = ctz(pending & T->pending[wheel]);
|
||||
TAILQ_CONCAT(&todo, &T->wheel[wheel][slot], tqe);
|
||||
T->pending[wheel] &= ~(UINT64_C(1) << slot);
|
||||
}
|
||||
|
||||
if (!(0x1 & pending))
|
||||
break; /* break if we didn't wrap around end of wheel */
|
||||
|
||||
/* if we're continuing, the next wheel must tick at least once */
|
||||
elapsed = MAX(elapsed, (WHEEL_LEN << (wheel * WHEEL_BIT)));
|
||||
}
|
||||
|
||||
T->curtime = curtime;
|
||||
|
||||
while (!TAILQ_EMPTY(&todo)) {
|
||||
struct timeout *to = TAILQ_FIRST(&todo);
|
||||
|
||||
TAILQ_REMOVE(&todo, to, tqe);
|
||||
to->pending = NULL;
|
||||
|
||||
timeouts_sched(T, to, to->expires);
|
||||
}
|
||||
|
||||
return;
|
||||
} /* timeouts_update() */
|
||||
|
||||
|
||||
TIMEOUT_PUBLIC void timeouts_step(struct timeouts *T, reltime_t elapsed) {
|
||||
timeouts_update(T, T->curtime + elapsed);
|
||||
} /* timeouts_step() */
|
||||
|
||||
|
||||
TIMEOUT_PUBLIC bool timeouts_pending(struct timeouts *T) {
|
||||
wheel_t pending = 0;
|
||||
int wheel;
|
||||
|
||||
for (wheel = 0; wheel < WHEEL_NUM; wheel++) {
|
||||
pending |= T->pending[wheel];
|
||||
}
|
||||
|
||||
return !!pending;
|
||||
} /* timeouts_pending() */
|
||||
|
||||
|
||||
TIMEOUT_PUBLIC bool timeouts_expired(struct timeouts *T) {
|
||||
return !TAILQ_EMPTY(&T->expired);
|
||||
} /* timeouts_expired() */
|
||||
|
||||
|
||||
/*
|
||||
* Calculate the interval before needing to process any timeouts pending on
|
||||
* any wheel.
|
||||
*
|
||||
* (This is separated from the public API routine so we can evaluate our
|
||||
* wheel invariant assertions irrespective of the expired queue.)
|
||||
*
|
||||
* This might return a timeout value sooner than any installed timeout if
|
||||
* only higher-order wheels have timeouts pending. We can only know when to
|
||||
* process a wheel, not precisely when a timeout is scheduled. Our timeout
|
||||
* accuracy could be off by 2^(N*M)-1 units where N is the wheel number and
|
||||
* M is WHEEL_BIT. Only timeouts which have fallen through to wheel 0 can be
|
||||
* known exactly.
|
||||
*
|
||||
* We should never return a timeout larger than the lowest actual timeout.
|
||||
*/
|
||||
static timeout_t timeouts_int(struct timeouts *T) {
|
||||
timeout_t timeout = ~TIMEOUT_C(0), _timeout;
|
||||
timeout_t relmask;
|
||||
int wheel, slot;
|
||||
|
||||
relmask = 0;
|
||||
|
||||
for (wheel = 0; wheel < WHEEL_NUM; wheel++) {
|
||||
if (T->pending[wheel]) {
|
||||
slot = WHEEL_MASK & (T->curtime >> (wheel * WHEEL_BIT));
|
||||
|
||||
/* ctz input cannot be zero: T->pending[wheel] is
|
||||
* nonzero, so rotr() is nonzero. */
|
||||
_timeout = (ctz(rotr(T->pending[wheel], slot)) + !!wheel) << (wheel * WHEEL_BIT);
|
||||
/* +1 to higher order wheels as those timeouts are one rotation in the future (otherwise they'd be on a lower wheel or expired) */
|
||||
|
||||
_timeout -= relmask & T->curtime;
|
||||
/* reduce by how much lower wheels have progressed */
|
||||
|
||||
timeout = MIN(_timeout, timeout);
|
||||
}
|
||||
|
||||
relmask <<= WHEEL_BIT;
|
||||
relmask |= WHEEL_MASK;
|
||||
}
|
||||
|
||||
return timeout;
|
||||
} /* timeouts_int() */
|
||||
|
||||
|
||||
/*
|
||||
* Calculate the interval our caller can wait before needing to process
|
||||
* events.
|
||||
*/
|
||||
TIMEOUT_PUBLIC timeout_t timeouts_timeout(struct timeouts *T) {
|
||||
if (!TAILQ_EMPTY(&T->expired))
|
||||
return 0;
|
||||
|
||||
return timeouts_int(T);
|
||||
} /* timeouts_timeout() */
|
||||
|
||||
|
||||
TIMEOUT_PUBLIC struct timeout *timeouts_get(struct timeouts *T) {
|
||||
if (!TAILQ_EMPTY(&T->expired)) {
|
||||
struct timeout *to = TAILQ_FIRST(&T->expired);
|
||||
|
||||
TAILQ_REMOVE(&T->expired, to, tqe);
|
||||
to->pending = NULL;
|
||||
TO_SET_TIMEOUTS(to, NULL);
|
||||
|
||||
#ifndef TIMEOUT_DISABLE_INTERVALS
|
||||
if ((to->flags & TIMEOUT_INT) && to->interval > 0)
|
||||
timeouts_readd(T, to);
|
||||
#endif
|
||||
|
||||
return to;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
} /* timeouts_get() */
|
||||
|
||||
|
||||
/*
|
||||
* Use dumb looping to locate the earliest timeout pending on the wheel so
|
||||
* our invariant assertions can check the result of our optimized code.
|
||||
*/
|
||||
static struct timeout *timeouts_min(struct timeouts *T) {
|
||||
struct timeout *to, *min = NULL;
|
||||
unsigned i, j;
|
||||
|
||||
for (i = 0; i < countof(T->wheel); i++) {
|
||||
for (j = 0; j < countof(T->wheel[i]); j++) {
|
||||
TAILQ_FOREACH(to, &T->wheel[i][j], tqe) {
|
||||
if (!min || to->expires < min->expires)
|
||||
min = to;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return min;
|
||||
} /* timeouts_min() */
|
||||
|
||||
|
||||
/*
|
||||
* Check some basic algorithm invariants. If these invariants fail then
|
||||
* something is definitely broken.
|
||||
*/
|
||||
#define report(...) do { \
|
||||
if ((fp)) \
|
||||
fprintf(fp, __VA_ARGS__); \
|
||||
} while (0)
|
||||
|
||||
#define check(expr, ...) do { \
|
||||
if (!(expr)) { \
|
||||
report(__VA_ARGS__); \
|
||||
return 0; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
TIMEOUT_PUBLIC bool timeouts_check(struct timeouts *T, FILE *fp) {
|
||||
timeout_t timeout;
|
||||
struct timeout *to;
|
||||
|
||||
if ((to = timeouts_min(T))) {
|
||||
check(to->expires > T->curtime, "missed timeout (expires:%" TIMEOUT_PRIu " <= curtime:%" TIMEOUT_PRIu ")\n", to->expires, T->curtime);
|
||||
|
||||
timeout = timeouts_int(T);
|
||||
check(timeout <= to->expires - T->curtime, "wrong soft timeout (soft:%" TIMEOUT_PRIu " > hard:%" TIMEOUT_PRIu ") (expires:%" TIMEOUT_PRIu "; curtime:%" TIMEOUT_PRIu ")\n", timeout, (to->expires - T->curtime), to->expires, T->curtime);
|
||||
|
||||
timeout = timeouts_timeout(T);
|
||||
check(timeout <= to->expires - T->curtime, "wrong soft timeout (soft:%" TIMEOUT_PRIu " > hard:%" TIMEOUT_PRIu ") (expires:%" TIMEOUT_PRIu "; curtime:%" TIMEOUT_PRIu ")\n", timeout, (to->expires - T->curtime), to->expires, T->curtime);
|
||||
} else {
|
||||
timeout = timeouts_timeout(T);
|
||||
|
||||
if (!TAILQ_EMPTY(&T->expired))
|
||||
check(timeout == 0, "wrong soft timeout (soft:%" TIMEOUT_PRIu " != hard:%" TIMEOUT_PRIu ")\n", timeout, TIMEOUT_C(0));
|
||||
else
|
||||
check(timeout == ~TIMEOUT_C(0), "wrong soft timeout (soft:%" TIMEOUT_PRIu " != hard:%" TIMEOUT_PRIu ")\n", timeout, ~TIMEOUT_C(0));
|
||||
}
|
||||
|
||||
return 1;
|
||||
} /* timeouts_check() */
|
||||
|
||||
|
||||
#define ENTER \
|
||||
do { \
|
||||
static const int pc0 = __LINE__; \
|
||||
switch (pc0 + it->pc) { \
|
||||
case __LINE__: (void)0
|
||||
|
||||
#define SAVE_AND_DO(do_statement) \
|
||||
do { \
|
||||
it->pc = __LINE__ - pc0; \
|
||||
do_statement; \
|
||||
case __LINE__: (void)0; \
|
||||
} while (0)
|
||||
|
||||
#define YIELD(rv) \
|
||||
SAVE_AND_DO(return (rv))
|
||||
|
||||
#define LEAVE \
|
||||
SAVE_AND_DO(break); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
TIMEOUT_PUBLIC struct timeout *timeouts_next(struct timeouts *T, struct timeouts_it *it) {
|
||||
struct timeout *to;
|
||||
|
||||
ENTER;
|
||||
|
||||
if (it->flags & TIMEOUTS_EXPIRED) {
|
||||
if (it->flags & TIMEOUTS_CLEAR) {
|
||||
while ((to = timeouts_get(T))) {
|
||||
YIELD(to);
|
||||
}
|
||||
} else {
|
||||
TAILQ_FOREACH_SAFE(to, &T->expired, tqe, it->to) {
|
||||
YIELD(to);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (it->flags & TIMEOUTS_PENDING) {
|
||||
for (it->i = 0; it->i < countof(T->wheel); it->i++) {
|
||||
for (it->j = 0; it->j < countof(T->wheel[it->i]); it->j++) {
|
||||
TAILQ_FOREACH_SAFE(to, &T->wheel[it->i][it->j], tqe, it->to) {
|
||||
YIELD(to);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LEAVE;
|
||||
|
||||
return NULL;
|
||||
} /* timeouts_next */
|
||||
|
||||
#undef LEAVE
|
||||
#undef YIELD
|
||||
#undef SAVE_AND_DO
|
||||
#undef ENTER
|
||||
|
||||
|
||||
/*
|
||||
* T I M E O U T R O U T I N E S
|
||||
*
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
TIMEOUT_PUBLIC struct timeout *timeout_init(struct timeout *to, int flags) {
|
||||
memset(to, 0, sizeof *to);
|
||||
|
||||
to->flags = flags;
|
||||
|
||||
return to;
|
||||
} /* timeout_init() */
|
||||
|
||||
|
||||
#ifndef TIMEOUT_DISABLE_RELATIVE_ACCESS
|
||||
TIMEOUT_PUBLIC bool timeout_pending(struct timeout *to) {
|
||||
return to->pending && to->pending != &to->timeouts->expired;
|
||||
} /* timeout_pending() */
|
||||
|
||||
|
||||
TIMEOUT_PUBLIC bool timeout_expired(struct timeout *to) {
|
||||
return to->pending && to->pending == &to->timeouts->expired;
|
||||
} /* timeout_expired() */
|
||||
|
||||
|
||||
TIMEOUT_PUBLIC void timeout_del(struct timeout *to) {
|
||||
timeouts_del(to->timeouts, to);
|
||||
} /* timeout_del() */
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* V E R S I O N I N T E R F A C E S
|
||||
*
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
TIMEOUT_PUBLIC int timeout_version(void) {
|
||||
return TIMEOUT_VERSION;
|
||||
} /* timeout_version() */
|
||||
|
||||
|
||||
TIMEOUT_PUBLIC const char *timeout_vendor(void) {
|
||||
return TIMEOUT_VENDOR;
|
||||
} /* timeout_version() */
|
||||
|
||||
|
||||
TIMEOUT_PUBLIC int timeout_v_rel(void) {
|
||||
return TIMEOUT_V_REL;
|
||||
} /* timeout_version() */
|
||||
|
||||
|
||||
TIMEOUT_PUBLIC int timeout_v_abi(void) {
|
||||
return TIMEOUT_V_ABI;
|
||||
} /* timeout_version() */
|
||||
|
||||
|
||||
TIMEOUT_PUBLIC int timeout_v_api(void) {
|
||||
return TIMEOUT_V_API;
|
||||
} /* timeout_version() */
|
||||
|
||||
253
deps/timeout/timeout.h
vendored
Normal file
253
deps/timeout/timeout.h
vendored
Normal file
@@ -0,0 +1,253 @@
|
||||
/* ==========================================================================
|
||||
* timeout.h - Tickless hierarchical timing wheel.
|
||||
* --------------------------------------------------------------------------
|
||||
* Copyright (c) 2013, 2014 William Ahern
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to permit
|
||||
* persons to whom the Software is furnished to do so, subject to the
|
||||
* following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
||||
* NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||
* USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
* ==========================================================================
|
||||
*/
|
||||
#ifndef TIMEOUT_H
|
||||
#define TIMEOUT_H
|
||||
|
||||
#include <stdbool.h> /* bool */
|
||||
#include <stdio.h> /* FILE */
|
||||
|
||||
#include <inttypes.h> /* PRIu64 PRIx64 PRIX64 uint64_t */
|
||||
|
||||
#include <sys/queue.h> /* TAILQ(3) */
|
||||
|
||||
|
||||
/*
|
||||
* V E R S I O N I N T E R F A C E S
|
||||
*
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
#if !defined TIMEOUT_PUBLIC
|
||||
#define TIMEOUT_PUBLIC
|
||||
#endif
|
||||
|
||||
#define TIMEOUT_VERSION TIMEOUT_V_REL
|
||||
#define TIMEOUT_VENDOR "william@25thandClement.com"
|
||||
|
||||
#define TIMEOUT_V_REL 0x20160226
|
||||
#define TIMEOUT_V_ABI 0x20160224
|
||||
#define TIMEOUT_V_API 0x20160226
|
||||
|
||||
TIMEOUT_PUBLIC int timeout_version(void);
|
||||
|
||||
TIMEOUT_PUBLIC const char *timeout_vendor(void);
|
||||
|
||||
TIMEOUT_PUBLIC int timeout_v_rel(void);
|
||||
|
||||
TIMEOUT_PUBLIC int timeout_v_abi(void);
|
||||
|
||||
TIMEOUT_PUBLIC int timeout_v_api(void);
|
||||
|
||||
|
||||
/*
|
||||
* I N T E G E R T Y P E I N T E R F A C E S
|
||||
*
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
#define TIMEOUT_C(n) UINT64_C(n)
|
||||
#define TIMEOUT_PRIu PRIu64
|
||||
#define TIMEOUT_PRIx PRIx64
|
||||
#define TIMEOUT_PRIX PRIX64
|
||||
|
||||
#define TIMEOUT_mHZ TIMEOUT_C(1000)
|
||||
#define TIMEOUT_uHZ TIMEOUT_C(1000000)
|
||||
#define TIMEOUT_nHZ TIMEOUT_C(1000000000)
|
||||
|
||||
typedef uint64_t timeout_t;
|
||||
|
||||
#define timeout_error_t int /* for documentation purposes */
|
||||
|
||||
|
||||
/*
|
||||
* C A L L B A C K I N T E R F A C E
|
||||
*
|
||||
* Callback function parameters unspecified to make embedding into existing
|
||||
* applications easier.
|
||||
*
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
#ifndef TIMEOUT_CB_OVERRIDE
|
||||
struct timeout_cb {
|
||||
void (*fn)();
|
||||
void *arg;
|
||||
}; /* struct timeout_cb */
|
||||
#endif
|
||||
|
||||
/*
|
||||
* T I M E O U T I N T E R F A C E S
|
||||
*
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
#ifndef TIMEOUT_DISABLE_INTERVALS
|
||||
#define TIMEOUT_INT 0x01 /* interval (repeating) timeout */
|
||||
#endif
|
||||
#define TIMEOUT_ABS 0x02 /* treat timeout values as absolute */
|
||||
|
||||
#define TIMEOUT_INITIALIZER(flags) { (flags) }
|
||||
|
||||
#define timeout_setcb(to, fn, arg) do { \
|
||||
(to)->callback.fn = (fn); \
|
||||
(to)->callback.arg = (arg); \
|
||||
} while (0)
|
||||
|
||||
struct timeout {
|
||||
int flags;
|
||||
|
||||
timeout_t expires;
|
||||
/* absolute expiration time */
|
||||
|
||||
struct timeout_list *pending;
|
||||
/* timeout list if pending on wheel or expiry queue */
|
||||
|
||||
TAILQ_ENTRY(timeout) tqe;
|
||||
/* entry member for struct timeout_list lists */
|
||||
|
||||
#ifndef TIMEOUT_DISABLE_CALLBACKS
|
||||
struct timeout_cb callback;
|
||||
/* optional callback information */
|
||||
#endif
|
||||
|
||||
#ifndef TIMEOUT_DISABLE_INTERVALS
|
||||
timeout_t interval;
|
||||
/* timeout interval if periodic */
|
||||
#endif
|
||||
|
||||
#ifndef TIMEOUT_DISABLE_RELATIVE_ACCESS
|
||||
struct timeouts *timeouts;
|
||||
/* timeouts collection if member of */
|
||||
#endif
|
||||
}; /* struct timeout */
|
||||
|
||||
|
||||
TIMEOUT_PUBLIC struct timeout *timeout_init(struct timeout *, int);
|
||||
/* initialize timeout structure (same as TIMEOUT_INITIALIZER) */
|
||||
|
||||
#ifndef TIMEOUT_DISABLE_RELATIVE_ACCESS
|
||||
TIMEOUT_PUBLIC bool timeout_pending(struct timeout *);
|
||||
/* true if on timing wheel, false otherwise */
|
||||
|
||||
TIMEOUT_PUBLIC bool timeout_expired(struct timeout *);
|
||||
/* true if on expired queue, false otherwise */
|
||||
|
||||
TIMEOUT_PUBLIC void timeout_del(struct timeout *);
|
||||
/* remove timeout from any timing wheel (okay if not member of any) */
|
||||
#endif
|
||||
|
||||
/*
|
||||
* T I M I N G W H E E L I N T E R F A C E S
|
||||
*
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
struct timeouts;
|
||||
|
||||
TIMEOUT_PUBLIC struct timeouts *timeouts_open(timeout_t, timeout_error_t *);
|
||||
/* open a new timing wheel, setting optional HZ (for float conversions) */
|
||||
|
||||
TIMEOUT_PUBLIC void timeouts_close(struct timeouts *);
|
||||
/* destroy timing wheel */
|
||||
|
||||
TIMEOUT_PUBLIC timeout_t timeouts_hz(struct timeouts *);
|
||||
/* return HZ setting (for float conversions) */
|
||||
|
||||
TIMEOUT_PUBLIC void timeouts_update(struct timeouts *, timeout_t);
|
||||
/* update timing wheel with current absolute time */
|
||||
|
||||
TIMEOUT_PUBLIC void timeouts_step(struct timeouts *, timeout_t);
|
||||
/* step timing wheel by relative time */
|
||||
|
||||
TIMEOUT_PUBLIC timeout_t timeouts_timeout(struct timeouts *);
|
||||
/* return interval to next required update */
|
||||
|
||||
TIMEOUT_PUBLIC void timeouts_add(struct timeouts *, struct timeout *, timeout_t);
|
||||
/* add timeout to timing wheel */
|
||||
|
||||
TIMEOUT_PUBLIC void timeouts_del(struct timeouts *, struct timeout *);
|
||||
/* remove timeout from any timing wheel or expired queue (okay if on neither) */
|
||||
|
||||
TIMEOUT_PUBLIC struct timeout *timeouts_get(struct timeouts *);
|
||||
/* return any expired timeout (caller should loop until NULL-return) */
|
||||
|
||||
TIMEOUT_PUBLIC bool timeouts_pending(struct timeouts *);
|
||||
/* return true if any timeouts pending on timing wheel */
|
||||
|
||||
TIMEOUT_PUBLIC bool timeouts_expired(struct timeouts *);
|
||||
/* return true if any timeouts on expired queue */
|
||||
|
||||
TIMEOUT_PUBLIC bool timeouts_check(struct timeouts *, FILE *);
|
||||
/* return true if invariants hold. describes failures to optional file handle. */
|
||||
|
||||
#define TIMEOUTS_PENDING 0x10
|
||||
#define TIMEOUTS_EXPIRED 0x20
|
||||
#define TIMEOUTS_ALL (TIMEOUTS_PENDING|TIMEOUTS_EXPIRED)
|
||||
#define TIMEOUTS_CLEAR 0x40
|
||||
|
||||
#define TIMEOUTS_IT_INITIALIZER(flags) { (flags), 0, 0, 0, 0 }
|
||||
|
||||
#define TIMEOUTS_IT_INIT(cur, _flags) do { \
|
||||
(cur)->flags = (_flags); \
|
||||
(cur)->pc = 0; \
|
||||
} while (0)
|
||||
|
||||
struct timeouts_it {
|
||||
int flags;
|
||||
unsigned pc, i, j;
|
||||
struct timeout *to;
|
||||
}; /* struct timeouts_it */
|
||||
|
||||
TIMEOUT_PUBLIC struct timeout *timeouts_next(struct timeouts *, struct timeouts_it *);
|
||||
/* return next timeout in pending wheel or expired queue. caller can delete
|
||||
* the returned timeout, but should not otherwise manipulate the timing
|
||||
* wheel. in particular, caller SHOULD NOT delete any other timeout as that
|
||||
* could invalidate cursor state and trigger a use-after-free.
|
||||
*/
|
||||
|
||||
#define TIMEOUTS_FOREACH(var, T, flags) \
|
||||
struct timeouts_it _it = TIMEOUTS_IT_INITIALIZER((flags)); \
|
||||
while (((var) = timeouts_next((T), &_it)))
|
||||
|
||||
|
||||
/*
|
||||
* B O N U S W H E E L I N T E R F A C E S
|
||||
*
|
||||
* I usually use floating point timeouts in all my code, but it's cleaner to
|
||||
* separate it to keep the core algorithmic code simple.
|
||||
*
|
||||
* Using macros instead of static inline routines where <math.h> routines
|
||||
* might be used to keep -lm linking optional.
|
||||
*
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
#include <math.h> /* ceil(3) */
|
||||
|
||||
#define timeouts_f2i(T, f) \
|
||||
((timeout_t)ceil((f) * timeouts_hz((T)))) /* prefer late expiration over early */
|
||||
|
||||
#define timeouts_i2f(T, i) \
|
||||
((double)(i) / timeouts_hz((T)))
|
||||
|
||||
#define timeouts_addf(T, to, timeout) \
|
||||
timeouts_add((T), (to), timeouts_f2i((T), (timeout)))
|
||||
|
||||
#endif /* TIMEOUT_H */
|
||||
3
deps/toml/CMakeLists.txt
vendored
Normal file
3
deps/toml/CMakeLists.txt
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
set(CMAKE_C_FLAGS "-std=c99")
|
||||
add_definitions(-fPIC)
|
||||
add_library(toml STATIC toml.c)
|
||||
2379
deps/toml/toml.c
vendored
Normal file
2379
deps/toml/toml.c
vendored
Normal file
File diff suppressed because it is too large
Load Diff
175
deps/toml/toml.h
vendored
Normal file
175
deps/toml/toml.h
vendored
Normal file
@@ -0,0 +1,175 @@
|
||||
/*
|
||||
MIT License
|
||||
|
||||
Copyright (c) CK Tan
|
||||
https://github.com/cktan/tomlc99
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
#ifndef TOML_H
|
||||
#define TOML_H
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(disable: 4996)
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
#define TOML_EXTERN extern "C"
|
||||
#else
|
||||
#define TOML_EXTERN extern
|
||||
#endif
|
||||
|
||||
typedef struct toml_timestamp_t toml_timestamp_t;
|
||||
typedef struct toml_table_t toml_table_t;
|
||||
typedef struct toml_array_t toml_array_t;
|
||||
typedef struct toml_datum_t toml_datum_t;
|
||||
|
||||
/* Parse a file. Return a table on success, or 0 otherwise.
|
||||
* Caller must toml_free(the-return-value) after use.
|
||||
*/
|
||||
TOML_EXTERN toml_table_t *toml_parse_file(FILE *fp, char *errbuf, int errbufsz);
|
||||
|
||||
/* Parse a string containing the full config.
|
||||
* Return a table on success, or 0 otherwise.
|
||||
* Caller must toml_free(the-return-value) after use.
|
||||
*/
|
||||
TOML_EXTERN toml_table_t *toml_parse(char *conf, /* NUL terminated, please. */
|
||||
char *errbuf, int errbufsz);
|
||||
|
||||
/* Free the table returned by toml_parse() or toml_parse_file(). Once
|
||||
* this function is called, any handles accessed through this tab
|
||||
* directly or indirectly are no longer valid.
|
||||
*/
|
||||
TOML_EXTERN void toml_free(toml_table_t *tab);
|
||||
|
||||
/* Timestamp types. The year, month, day, hour, minute, second, z
|
||||
* fields may be NULL if they are not relevant. e.g. In a DATE
|
||||
* type, the hour, minute, second and z fields will be NULLs.
|
||||
*/
|
||||
struct toml_timestamp_t {
|
||||
struct { /* internal. do not use. */
|
||||
int year, month, day;
|
||||
int hour, minute, second, millisec;
|
||||
char z[10];
|
||||
} __buffer;
|
||||
int *year, *month, *day;
|
||||
int *hour, *minute, *second, *millisec;
|
||||
char *z;
|
||||
};
|
||||
|
||||
/*-----------------------------------------------------------------
|
||||
* Enhanced access methods
|
||||
*/
|
||||
struct toml_datum_t {
|
||||
int ok;
|
||||
union {
|
||||
toml_timestamp_t *ts; /* ts must be freed after use */
|
||||
char *s; /* string value. s must be freed after use */
|
||||
int b; /* bool value */
|
||||
int64_t i; /* int value */
|
||||
double d; /* double value */
|
||||
} u;
|
||||
};
|
||||
|
||||
/* on arrays: */
|
||||
/* ... retrieve size of array. */
|
||||
TOML_EXTERN int toml_array_nelem(const toml_array_t *arr);
|
||||
/* ... retrieve values using index. */
|
||||
TOML_EXTERN toml_datum_t toml_string_at(const toml_array_t *arr, int idx);
|
||||
TOML_EXTERN toml_datum_t toml_bool_at(const toml_array_t *arr, int idx);
|
||||
TOML_EXTERN toml_datum_t toml_int_at(const toml_array_t *arr, int idx);
|
||||
TOML_EXTERN toml_datum_t toml_double_at(const toml_array_t *arr, int idx);
|
||||
TOML_EXTERN toml_datum_t toml_timestamp_at(const toml_array_t *arr, int idx);
|
||||
/* ... retrieve array or table using index. */
|
||||
TOML_EXTERN toml_array_t *toml_array_at(const toml_array_t *arr, int idx);
|
||||
TOML_EXTERN toml_table_t *toml_table_at(const toml_array_t *arr, int idx);
|
||||
|
||||
/* on tables: */
|
||||
/* ... retrieve the key in table at keyidx. Return 0 if out of range. */
|
||||
TOML_EXTERN const char *toml_key_in(const toml_table_t *tab, int keyidx);
|
||||
/* ... returns 1 if key exists in tab, 0 otherwise */
|
||||
TOML_EXTERN int toml_key_exists(const toml_table_t *tab, const char *key);
|
||||
/* ... retrieve values using key. */
|
||||
TOML_EXTERN toml_datum_t toml_string_in(const toml_table_t *arr,
|
||||
const char *key);
|
||||
TOML_EXTERN toml_datum_t toml_bool_in(const toml_table_t *arr, const char *key);
|
||||
TOML_EXTERN toml_datum_t toml_int_in(const toml_table_t *arr, const char *key);
|
||||
TOML_EXTERN toml_datum_t toml_double_in(const toml_table_t *arr,
|
||||
const char *key);
|
||||
TOML_EXTERN toml_datum_t toml_timestamp_in(const toml_table_t *arr,
|
||||
const char *key);
|
||||
/* .. retrieve array or table using key. */
|
||||
TOML_EXTERN toml_array_t *toml_array_in(const toml_table_t *tab,
|
||||
const char *key);
|
||||
TOML_EXTERN toml_table_t *toml_table_in(const toml_table_t *tab,
|
||||
const char *key);
|
||||
|
||||
/*-----------------------------------------------------------------
|
||||
* lesser used
|
||||
*/
|
||||
/* Return the array kind: 't'able, 'a'rray, 'v'alue, 'm'ixed */
|
||||
TOML_EXTERN char toml_array_kind(const toml_array_t *arr);
|
||||
|
||||
/* For array kind 'v'alue, return the type of values
|
||||
i:int, d:double, b:bool, s:string, t:time, D:date, T:timestamp, 'm'ixed
|
||||
0 if unknown
|
||||
*/
|
||||
TOML_EXTERN char toml_array_type(const toml_array_t *arr);
|
||||
|
||||
/* Return the key of an array */
|
||||
TOML_EXTERN const char *toml_array_key(const toml_array_t *arr);
|
||||
|
||||
/* Return the number of key-values in a table */
|
||||
TOML_EXTERN int toml_table_nkval(const toml_table_t *tab);
|
||||
|
||||
/* Return the number of arrays in a table */
|
||||
TOML_EXTERN int toml_table_narr(const toml_table_t *tab);
|
||||
|
||||
/* Return the number of sub-tables in a table */
|
||||
TOML_EXTERN int toml_table_ntab(const toml_table_t *tab);
|
||||
|
||||
/* Return the key of a table*/
|
||||
TOML_EXTERN const char *toml_table_key(const toml_table_t *tab);
|
||||
|
||||
/*--------------------------------------------------------------
|
||||
* misc
|
||||
*/
|
||||
TOML_EXTERN int toml_utf8_to_ucs(const char *orig, int len, int64_t *ret);
|
||||
TOML_EXTERN int toml_ucs_to_utf8(int64_t code, char buf[6]);
|
||||
TOML_EXTERN void toml_set_memutil(void *(*xxmalloc)(size_t),
|
||||
void (*xxfree)(void *));
|
||||
|
||||
/*--------------------------------------------------------------
|
||||
* deprecated
|
||||
*/
|
||||
/* A raw value, must be processed by toml_rto* before using. */
|
||||
typedef const char *toml_raw_t;
|
||||
TOML_EXTERN toml_raw_t toml_raw_in(const toml_table_t *tab, const char *key);
|
||||
TOML_EXTERN toml_raw_t toml_raw_at(const toml_array_t *arr, int idx);
|
||||
TOML_EXTERN int toml_rtos(toml_raw_t s, char **ret);
|
||||
TOML_EXTERN int toml_rtob(toml_raw_t s, int *ret);
|
||||
TOML_EXTERN int toml_rtoi(toml_raw_t s, int64_t *ret);
|
||||
TOML_EXTERN int toml_rtod(toml_raw_t s, double *ret);
|
||||
TOML_EXTERN int toml_rtod_ex(toml_raw_t s, double *ret, char *buf, int buflen);
|
||||
TOML_EXTERN int toml_rtots(toml_raw_t s, toml_timestamp_t *ret);
|
||||
|
||||
#endif /* TOML_H */
|
||||
9
deps/uthash/utarray.h
vendored
9
deps/uthash/utarray.h
vendored
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright (c) 2008-2018, Troy D. Hanson http://troydhanson.github.com/uthash/
|
||||
Copyright (c) 2008-2022, Troy D. Hanson https://troydhanson.github.io/uthash/
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
@@ -26,7 +26,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#ifndef UTARRAY_H
|
||||
#define UTARRAY_H
|
||||
|
||||
#define UTARRAY_VERSION 2.1.0
|
||||
#define UTARRAY_VERSION 2.3.0
|
||||
|
||||
#include <stddef.h> /* size_t */
|
||||
#include <string.h> /* memset, etc */
|
||||
@@ -232,8 +232,9 @@ typedef struct {
|
||||
|
||||
/* last we pre-define a few icd for common utarrays of ints and strings */
|
||||
static void utarray_str_cpy(void *dst, const void *src) {
|
||||
char **_src = (char**)src, **_dst = (char**)dst;
|
||||
*_dst = (*_src == NULL) ? NULL : strdup(*_src);
|
||||
char *const *srcc = (char *const *)src;
|
||||
char **dstc = (char**)dst;
|
||||
*dstc = (*srcc == NULL) ? NULL : strdup(*srcc);
|
||||
}
|
||||
static void utarray_str_dtor(void *elt) {
|
||||
char **eltc = (char**)elt;
|
||||
|
||||
68
deps/uthash/uthash.h
vendored
68
deps/uthash/uthash.h
vendored
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright (c) 2003-2018, Troy D. Hanson http://troydhanson.github.com/uthash/
|
||||
Copyright (c) 2003-2022, Troy D. Hanson https://troydhanson.github.io/uthash/
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
@@ -24,12 +24,22 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#ifndef UTHASH_H
|
||||
#define UTHASH_H
|
||||
|
||||
#define UTHASH_VERSION 2.1.0
|
||||
#define UTHASH_VERSION 2.3.0
|
||||
|
||||
#include <string.h> /* memcmp, memset, strlen */
|
||||
#include <stddef.h> /* ptrdiff_t */
|
||||
#include <stdlib.h> /* exit */
|
||||
|
||||
#if defined(HASH_DEFINE_OWN_STDINT) && HASH_DEFINE_OWN_STDINT
|
||||
/* This codepath is provided for backward compatibility, but I plan to remove it. */
|
||||
#warning "HASH_DEFINE_OWN_STDINT is deprecated; please use HASH_NO_STDINT instead"
|
||||
typedef unsigned int uint32_t;
|
||||
typedef unsigned char uint8_t;
|
||||
#elif defined(HASH_NO_STDINT) && HASH_NO_STDINT
|
||||
#else
|
||||
#include <stdint.h> /* uint8_t, uint32_t */
|
||||
#endif
|
||||
|
||||
/* These macros use decltype or the earlier __typeof GNU extension.
|
||||
As decltype is only available in newer compilers (VS2010 or gcc 4.3+
|
||||
when compiling c++ source) this code uses whatever method is needed
|
||||
@@ -62,23 +72,6 @@ do {
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
/* a number of the hash function use uint32_t which isn't defined on Pre VS2010 */
|
||||
#if defined(_WIN32)
|
||||
#if defined(_MSC_VER) && _MSC_VER >= 1600
|
||||
#include <stdint.h>
|
||||
#elif defined(__WATCOMC__) || defined(__MINGW32__) || defined(__CYGWIN__)
|
||||
#include <stdint.h>
|
||||
#else
|
||||
typedef unsigned int uint32_t;
|
||||
typedef unsigned char uint8_t;
|
||||
#endif
|
||||
#elif defined(__GNUC__) && !defined(__VXWORKS__)
|
||||
#include <stdint.h>
|
||||
#else
|
||||
typedef unsigned int uint32_t;
|
||||
typedef unsigned char uint8_t;
|
||||
#endif
|
||||
|
||||
#ifndef uthash_malloc
|
||||
#define uthash_malloc(sz) malloc(sz) /* malloc fcn */
|
||||
#endif
|
||||
@@ -92,15 +85,12 @@ typedef unsigned char uint8_t;
|
||||
#define uthash_strlen(s) strlen(s)
|
||||
#endif
|
||||
|
||||
#ifdef uthash_memcmp
|
||||
/* This warning will not catch programs that define uthash_memcmp AFTER including uthash.h. */
|
||||
#warning "uthash_memcmp is deprecated; please use HASH_KEYCMP instead"
|
||||
#else
|
||||
#define uthash_memcmp(a,b,n) memcmp(a,b,n)
|
||||
#ifndef HASH_FUNCTION
|
||||
#define HASH_FUNCTION(keyptr,keylen,hashv) HASH_JEN(keyptr, keylen, hashv)
|
||||
#endif
|
||||
|
||||
#ifndef HASH_KEYCMP
|
||||
#define HASH_KEYCMP(a,b,n) uthash_memcmp(a,b,n)
|
||||
#define HASH_KEYCMP(a,b,n) memcmp(a,b,n)
|
||||
#endif
|
||||
|
||||
#ifndef uthash_noexpand_fyi
|
||||
@@ -158,7 +148,7 @@ do {
|
||||
|
||||
#define HASH_VALUE(keyptr,keylen,hashv) \
|
||||
do { \
|
||||
HASH_FCN(keyptr, keylen, hashv); \
|
||||
HASH_FUNCTION(keyptr, keylen, hashv); \
|
||||
} while (0)
|
||||
|
||||
#define HASH_FIND_BYHASHVALUE(hh,head,keyptr,keylen,hashval,out) \
|
||||
@@ -408,7 +398,7 @@ do {
|
||||
do { \
|
||||
IF_HASH_NONFATAL_OOM( int _ha_oomed = 0; ) \
|
||||
(add)->hh.hashv = (hashval); \
|
||||
(add)->hh.key = (char*) (keyptr); \
|
||||
(add)->hh.key = (const void*) (keyptr); \
|
||||
(add)->hh.keylen = (unsigned) (keylen_in); \
|
||||
if (!(head)) { \
|
||||
(add)->hh.next = NULL; \
|
||||
@@ -590,13 +580,6 @@ do {
|
||||
#define HASH_EMIT_KEY(hh,head,keyptr,fieldlen)
|
||||
#endif
|
||||
|
||||
/* default to Jenkin's hash unless overridden e.g. DHASH_FUNCTION=HASH_SAX */
|
||||
#ifdef HASH_FUNCTION
|
||||
#define HASH_FCN HASH_FUNCTION
|
||||
#else
|
||||
#define HASH_FCN HASH_JEN
|
||||
#endif
|
||||
|
||||
/* The Bernstein hash function, used in Perl prior to v5.6. Note (x<<5+x)=x*33. */
|
||||
#define HASH_BER(key,keylen,hashv) \
|
||||
do { \
|
||||
@@ -610,7 +593,9 @@ do {
|
||||
|
||||
|
||||
/* SAX/FNV/OAT/JEN hash functions are macro variants of those listed at
|
||||
* http://eternallyconfuzzled.com/tuts/algorithms/jsw_tut_hashing.aspx */
|
||||
* http://eternallyconfuzzled.com/tuts/algorithms/jsw_tut_hashing.aspx
|
||||
* (archive link: https://archive.is/Ivcan )
|
||||
*/
|
||||
#define HASH_SAX(key,keylen,hashv) \
|
||||
do { \
|
||||
unsigned _sx_i; \
|
||||
@@ -695,7 +680,8 @@ do {
|
||||
case 4: _hj_i += ( (unsigned)_hj_key[3] << 24 ); /* FALLTHROUGH */ \
|
||||
case 3: _hj_i += ( (unsigned)_hj_key[2] << 16 ); /* FALLTHROUGH */ \
|
||||
case 2: _hj_i += ( (unsigned)_hj_key[1] << 8 ); /* FALLTHROUGH */ \
|
||||
case 1: _hj_i += _hj_key[0]; \
|
||||
case 1: _hj_i += _hj_key[0]; /* FALLTHROUGH */ \
|
||||
default: ; \
|
||||
} \
|
||||
HASH_JEN_MIX(_hj_i, _hj_j, hashv); \
|
||||
} while (0)
|
||||
@@ -743,6 +729,8 @@ do {
|
||||
case 1: hashv += *_sfh_key; \
|
||||
hashv ^= hashv << 10; \
|
||||
hashv += hashv >> 1; \
|
||||
break; \
|
||||
default: ; \
|
||||
} \
|
||||
\
|
||||
/* Force "avalanching" of final 127 bits */ \
|
||||
@@ -764,7 +752,7 @@ do {
|
||||
} \
|
||||
while ((out) != NULL) { \
|
||||
if ((out)->hh.hashv == (hashval) && (out)->hh.keylen == (keylen_in)) { \
|
||||
if (HASH_KEYCMP((out)->hh.key, keyptr, keylen_in) == 0) { \
|
||||
if (HASH_KEYCMP((out)->hh.key, keyptr, keylen_in) == 0) { \
|
||||
break; \
|
||||
} \
|
||||
} \
|
||||
@@ -850,12 +838,12 @@ do {
|
||||
struct UT_hash_handle *_he_thh, *_he_hh_nxt; \
|
||||
UT_hash_bucket *_he_new_buckets, *_he_newbkt; \
|
||||
_he_new_buckets = (UT_hash_bucket*)uthash_malloc( \
|
||||
2UL * (tbl)->num_buckets * sizeof(struct UT_hash_bucket)); \
|
||||
sizeof(struct UT_hash_bucket) * (tbl)->num_buckets * 2U); \
|
||||
if (!_he_new_buckets) { \
|
||||
HASH_RECORD_OOM(oomed); \
|
||||
} else { \
|
||||
uthash_bzero(_he_new_buckets, \
|
||||
2UL * (tbl)->num_buckets * sizeof(struct UT_hash_bucket)); \
|
||||
sizeof(struct UT_hash_bucket) * (tbl)->num_buckets * 2U); \
|
||||
(tbl)->ideal_chain_maxlen = \
|
||||
((tbl)->num_items >> ((tbl)->log2_num_buckets+1U)) + \
|
||||
((((tbl)->num_items & (((tbl)->num_buckets*2U)-1U)) != 0U) ? 1U : 0U); \
|
||||
@@ -1142,7 +1130,7 @@ typedef struct UT_hash_handle {
|
||||
void *next; /* next element in app order */
|
||||
struct UT_hash_handle *hh_prev; /* previous hh in bucket order */
|
||||
struct UT_hash_handle *hh_next; /* next hh in bucket order */
|
||||
void *key; /* ptr to enclosing struct's key */
|
||||
const void *key; /* ptr to enclosing struct's key */
|
||||
unsigned keylen; /* enclosing struct's key len */
|
||||
unsigned hashv; /* result of hash-fcn(key) */
|
||||
} UT_hash_handle;
|
||||
|
||||
4
deps/uthash/utlist.h
vendored
4
deps/uthash/utlist.h
vendored
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright (c) 2007-2018, Troy D. Hanson http://troydhanson.github.com/uthash/
|
||||
Copyright (c) 2007-2022, Troy D. Hanson https://troydhanson.github.io/uthash/
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
@@ -24,7 +24,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#ifndef UTLIST_H
|
||||
#define UTLIST_H
|
||||
|
||||
#define UTLIST_VERSION 2.1.0
|
||||
#define UTLIST_VERSION 2.3.0
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
|
||||
4
deps/uthash/utringbuffer.h
vendored
4
deps/uthash/utringbuffer.h
vendored
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright (c) 2015-2018, Troy D. Hanson http://troydhanson.github.com/uthash/
|
||||
Copyright (c) 2015-2022, Troy D. Hanson https://troydhanson.github.io/uthash/
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
@@ -26,7 +26,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#ifndef UTRINGBUFFER_H
|
||||
#define UTRINGBUFFER_H
|
||||
|
||||
#define UTRINGBUFFER_VERSION 2.1.0
|
||||
#define UTRINGBUFFER_VERSION 2.3.0
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
8
deps/uthash/utstack.h
vendored
8
deps/uthash/utstack.h
vendored
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright (c) 2018-2018, Troy D. Hanson http://troydhanson.github.com/uthash/
|
||||
Copyright (c) 2018-2022, Troy D. Hanson https://troydhanson.github.io/uthash/
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
@@ -24,7 +24,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#ifndef UTSTACK_H
|
||||
#define UTSTACK_H
|
||||
|
||||
#define UTSTACK_VERSION 2.1.0
|
||||
#define UTSTACK_VERSION 2.3.0
|
||||
|
||||
/*
|
||||
* This file contains macros to manipulate a singly-linked list as a stack.
|
||||
@@ -35,9 +35,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* struct item {
|
||||
* int id;
|
||||
* struct item *next;
|
||||
* }
|
||||
* };
|
||||
*
|
||||
* struct item *stack = NULL:
|
||||
* struct item *stack = NULL;
|
||||
*
|
||||
* int main() {
|
||||
* int count;
|
||||
|
||||
4
deps/uthash/utstring.h
vendored
4
deps/uthash/utstring.h
vendored
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright (c) 2008-2018, Troy D. Hanson http://troydhanson.github.com/uthash/
|
||||
Copyright (c) 2008-2022, Troy D. Hanson https://troydhanson.github.io/uthash/
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
@@ -26,7 +26,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#ifndef UTSTRING_H
|
||||
#define UTSTRING_H
|
||||
|
||||
#define UTSTRING_VERSION 2.1.0
|
||||
#define UTSTRING_VERSION 2.3.0
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
4
docs/imgs/stellar-high-level-design.svg
Normal file
4
docs/imgs/stellar-high-level-design.svg
Normal file
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 17 KiB |
100
readme.md
Normal file
100
readme.md
Normal file
@@ -0,0 +1,100 @@
|
||||
# Stellar: A stateful network functions development platform
|
||||
|
||||
A stateful network function could be a firewall, a load balancer, or an IDS.
|
||||
|
||||
## Architecture
|
||||
|
||||
The stellar components are:
|
||||
|
||||
- **Packet IO** built an abstraction of network IO devices.
|
||||
- **Session Manager** has a hash table for tracking sessions. The caller feeds packets to the session manager and may return triggered session events.
|
||||
- **Plugin Manager** loads C/Lua plugins and manages per-plugin, per-session context. When the caller feeds an event to the plugin manager, it invokes plugin callbacks.
|
||||
- **Protocol Decoders** are libraries that parse and extract information from the packet payload.
|
||||
- **Active Queue Management** is queue management algorithm libraries that schedule packets by buffering, forwarding, marking, or dropping. A plugin creates a queue instance and enqueues packets as its needs.
|
||||
- Question: Who consumes the dequeue events?
|
||||
|
||||

|
||||
|
||||
## Packet IO Library
|
||||
```
|
||||
struct stellar_packet;
|
||||
|
||||
packet_io_loop()
|
||||
{
|
||||
packet_io_device_rx(&rx_pkt)
|
||||
//ingress processing: Tunnel decoding, IP defragmentation
|
||||
session_manager();
|
||||
plugin_manager();
|
||||
//egress processing: AMQ
|
||||
rl_group_id=pkt_get_group_id(rx_pkt);
|
||||
void *raw_pkt=pkt_get_raw(rx_pkt);
|
||||
AMQ_enqueue(group_id[], raw_pkt, pkt_sz);
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
## Plugin Manager
|
||||
|
||||
Plugin Management APIs
|
||||
|
||||
```
|
||||
/*
|
||||
* The pm_session_dettach_me just sets the flag to disable this plugin and no longer call this event callback.
|
||||
* Before calling pm_session_dettach_me, the current plugin must release related resources for the current session.
|
||||
*/
|
||||
pm_session_dettach_me(session);
|
||||
|
||||
/*
|
||||
* The current plugin(cb2) takes over the current session, the pm_session_take_over setting flag disables other plugins,
|
||||
* and the current session does not call other plugins except for the SESSION_EVENT_CLOSING event.
|
||||
*
|
||||
* +-----+ +-----+ +-----+ +-----+
|
||||
* Plugin runtime callback list: | cb1 |-->| cb2 |-->| cb3 |-->| cb4 |
|
||||
* +-----+ +-----+ +-----+ +-----+
|
||||
* /|\
|
||||
* |
|
||||
* plugin cb2 run pm_session_take_over
|
||||
*
|
||||
* A plugin(cb1/cb3/cb4) that is taken over, if the plugin was called before being taken over and has a registered SESSION_EVENT_CLOSING event,
|
||||
* it will be called again when the SESSION_EVENT_CLOSING event comes. Otherwise, the plugin will not be called.
|
||||
*/
|
||||
pm_session_take_over(session);
|
||||
```
|
||||
|
||||
## Session Manager
|
||||
|
||||
Session Management APIs
|
||||
|
||||
```
|
||||
session_drop_current_packet(session);
|
||||
session_set_ratelimit_group(session, rl_group_id);
|
||||
session_set_metadata(session, const char *key, void *value, size_t val_sz, free_callback);
|
||||
session_get_metadata(session, const char *key, void **value, size_t *val_sz);
|
||||
session_del_metadata(session, key)
|
||||
session_lock(session, plug_id);
|
||||
session_unlock(session, plug_id);
|
||||
|
||||
```
|
||||
Plugin Example
|
||||
```
|
||||
plugin_entry(session, pme)
|
||||
{
|
||||
session_get_metadata(session, "fw_action", value);
|
||||
if(value==INTERCEPT)
|
||||
{
|
||||
//pm_session_dettach_me(session);
|
||||
return;
|
||||
}
|
||||
ret=check_security_policy(session);
|
||||
if(ret==INTERCEPT)
|
||||
{
|
||||
pm_session_take_over(session);
|
||||
}
|
||||
else if(ret==RATE_LIMIT)
|
||||
{
|
||||
group_id=security_policy_id;
|
||||
amq_group_create(group_id, CIR, CBS);
|
||||
session_set_ratelimit_group(session, group_id);
|
||||
}
|
||||
}
|
||||
```
|
||||
@@ -1,12 +1,9 @@
|
||||
|
||||
add_definitions(-fPIC)
|
||||
|
||||
add_library(custom_event_plugin
|
||||
add_library(custom_event_plugin SHARED
|
||||
custom_event_plugin.cpp
|
||||
)
|
||||
set_target_properties(custom_event_plugin PROPERTIES PREFIX "")
|
||||
set_target_properties(custom_event_plugin PROPERTIES PREFIX "")
|
||||
|
||||
add_library(http_event_plugin
|
||||
http_event_plugin.cpp
|
||||
add_library(http_event_plugin SHARED
|
||||
http_event_plugin.cpp
|
||||
)
|
||||
set_target_properties(http_event_plugin PROPERTIES PREFIX "")
|
||||
set_target_properties(http_event_plugin PROPERTIES PREFIX "")
|
||||
@@ -2,34 +2,133 @@
|
||||
#include "packet.h"
|
||||
#include "plugin.h"
|
||||
|
||||
struct custom_session_event *_event = nullptr;
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
void *custom_decode(const char *payload, uint32_t len, void **pme)
|
||||
static char *g_handler = NULL;
|
||||
|
||||
static void *custom_decode(const char *payload, uint16_t len, void **pme)
|
||||
{
|
||||
return nullptr;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int custom_plugin_entry(const struct session *s, int what, struct packet *p, const char *payload, uint32_t len, void **pme)
|
||||
struct tcp_session_pme
|
||||
{
|
||||
void *info= custom_decode(payload, len, pme);
|
||||
struct session *new_session=session_manager_custom_session_derive(s, _event);
|
||||
session_manager_trigger_event(new_session, SESSION_EVENT_OPENING, info);
|
||||
session_manager_trigger_event(new_session, SESSION_EVENT_META, info);
|
||||
return 0;
|
||||
char data[16];
|
||||
/* data */
|
||||
};
|
||||
|
||||
struct custom_session_pme
|
||||
{
|
||||
char data[16];
|
||||
/* data */
|
||||
};
|
||||
|
||||
static struct tcp_session_pme *tcp_session_pme_create()
|
||||
{
|
||||
struct tcp_session_pme *pme = (struct tcp_session_pme *)calloc(1, sizeof(struct tcp_session_pme));
|
||||
return pme;
|
||||
}
|
||||
|
||||
int custom_event_plugin_entry(const struct session *s, int what, struct packet *p, const char *payload, uint32_t len, void **pme)
|
||||
static void tcp_session_pme_destory(struct tcp_session_pme *pme)
|
||||
{
|
||||
return 0;
|
||||
|
||||
if (pme)
|
||||
{
|
||||
free(pme);
|
||||
pme = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
int custom_plugin_init()
|
||||
static struct custom_session_pme *custom_session_pme_create()
|
||||
{
|
||||
_event = session_manager_custom_session_event_register("SESSION_TYPE_CUSTOM", (int)(SESSION_EVENT_OPENING|SESSION_EVENT_RAW_PKT|SESSION_EVENT_META|SESSION_EVENT_CLOSING));
|
||||
plugin_session_event_register(SESSION_TYPE_TCP, custom_plugin_entry, nullptr);
|
||||
struct custom_session_pme *pme = (struct custom_session_pme *)calloc(1, sizeof(struct custom_session_pme));
|
||||
return pme;
|
||||
}
|
||||
|
||||
static void custom_session_pme_destory(struct custom_session_pme *pme)
|
||||
{
|
||||
if (pme)
|
||||
{
|
||||
free(pme);
|
||||
pme = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" void custom_event_plugin_tcp_entry(const struct stellar_session *session, enum session_event_type event, struct stellar_packet *p, const char *payload, uint16_t len, void **pme)
|
||||
{
|
||||
struct tcp_session_pme **per_tcp_session_pme = (struct tcp_session_pme **)pme;
|
||||
|
||||
printf("RUN custom_event_plugin_tcp_entry, event: %d\n", event);
|
||||
|
||||
if (event & SESSION_EVENT_OPENING)
|
||||
{
|
||||
if (*per_tcp_session_pme == NULL)
|
||||
{
|
||||
struct tcp_session_pme *cur_ctx = tcp_session_pme_create();
|
||||
memcpy(cur_ctx->data, "custom_event_plugin_tcp_entry", strlen("custom_event_plugin_tcp_entry"));
|
||||
*per_tcp_session_pme = *&cur_ctx;
|
||||
}
|
||||
}
|
||||
|
||||
if (event & SESSION_EVENT_ORDPKT)
|
||||
{
|
||||
struct stellar_session_event_extras *info = (struct stellar_session_event_extras *)custom_decode(payload, len, pme);
|
||||
struct stellar_session *new_session = session_manager_session_derive(session, "CUSTOM");
|
||||
|
||||
session_manager_trigger_event(new_session, SESSION_EVENT_OPENING, info);
|
||||
session_manager_trigger_event(new_session, SESSION_EVENT_META, info);
|
||||
}
|
||||
|
||||
if (event & SESSION_EVENT_CLOSING)
|
||||
{
|
||||
tcp_session_pme_destory(*per_tcp_session_pme);
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" void custom_event_plugin_custom_entry(const struct stellar_session *session, enum session_event_type event, struct stellar_packet *p, const char *payload, uint16_t len, void **pme)
|
||||
{
|
||||
struct custom_session_pme **per_custom_session_pme = (struct custom_session_pme **)pme;
|
||||
|
||||
printf("RUN custom_event_plugin_custom_entry, event: %d\n", event);
|
||||
|
||||
if (event & SESSION_EVENT_OPENING)
|
||||
{
|
||||
if (*per_custom_session_pme == NULL)
|
||||
{
|
||||
struct custom_session_pme *cur_ctx = custom_session_pme_create();
|
||||
memcpy(cur_ctx->data, "custom_event_plugin_custom_entry", strlen("custom_event_plugin_custom_entry"));
|
||||
*per_custom_session_pme = *&cur_ctx;
|
||||
}
|
||||
}
|
||||
|
||||
if (event & SESSION_EVENT_CLOSING)
|
||||
{
|
||||
custom_session_pme_destory(*per_custom_session_pme);
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" int custom_event_plugin_init(void)
|
||||
{
|
||||
printf("RUN custom_event_plugin_init\n");
|
||||
|
||||
if (g_handler == NULL)
|
||||
{
|
||||
g_handler = (char *)malloc(1024);
|
||||
snprintf(g_handler, 1024, "222222");
|
||||
}
|
||||
|
||||
plugin_custom_session_event_register("SESSION_TYPE_CUSTOM", custom_event_plugin_entry, nullptr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
extern "C" void custom_event_plugin_exit(void)
|
||||
{
|
||||
printf("RUN custom_event_plugin_exit\n");
|
||||
|
||||
if (g_handler)
|
||||
{
|
||||
free(g_handler);
|
||||
g_handler = NULL;
|
||||
}
|
||||
}
|
||||
@@ -1,17 +1,93 @@
|
||||
#include "session.h"
|
||||
#include "packet.h"
|
||||
#include "plugin.h"
|
||||
#include "http.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
static char *g_handler = NULL;
|
||||
|
||||
int http_event_plugin_entry(const struct session *s, int what, struct packet *p, const char *payload, uint32_t len, void **pme)
|
||||
struct http_session_pme
|
||||
{
|
||||
char data[16];
|
||||
/* data */;
|
||||
};
|
||||
|
||||
static struct http_session_pme *http_session_pme_create()
|
||||
{
|
||||
struct http_session_pme *pme = (struct http_session_pme *)calloc(1, sizeof(struct http_session_pme));
|
||||
return pme;
|
||||
}
|
||||
|
||||
static void http_session_pme_destory(struct http_session_pme *pme)
|
||||
{
|
||||
if (pme)
|
||||
{
|
||||
free(pme);
|
||||
pme = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" void http_event_plugin_entry(const struct stellar_session *session, enum session_event_type event, struct stellar_packet *p, const char *payload, uint16_t len, void **pme)
|
||||
{
|
||||
struct http_session_pme **per_http_session_pme = (struct http_session_pme **)pme;
|
||||
|
||||
printf("RUN http_event_plugin_entry, event: %d\n", event);
|
||||
|
||||
if (event & SESSION_EVENT_OPENING)
|
||||
{
|
||||
if (*per_http_session_pme == NULL)
|
||||
{
|
||||
struct http_session_pme *cur_ctx = http_session_pme_create();
|
||||
memcpy(cur_ctx->data, "http_event_plugin_entry", strlen("http_event_plugin_entry"));
|
||||
*per_http_session_pme = *&cur_ctx;
|
||||
}
|
||||
}
|
||||
|
||||
if (event & SESSION_EVENT_RAWPKT)
|
||||
{
|
||||
// TODO
|
||||
pm_session_dettach_me(session);
|
||||
}
|
||||
|
||||
if (event & SESSION_EVENT_ORDPKT)
|
||||
{
|
||||
// TODO
|
||||
pm_session_take_over(session);
|
||||
}
|
||||
|
||||
if (event & SESSION_EVENT_META)
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
|
||||
if (event & SESSION_EVENT_CLOSING)
|
||||
{
|
||||
http_session_pme_destory(*per_http_session_pme);
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" int http_event_plugin_init(void)
|
||||
{
|
||||
printf("RUN http_event_plugin_init\n");
|
||||
|
||||
if (g_handler == NULL)
|
||||
{
|
||||
g_handler = (char *)malloc(1024);
|
||||
snprintf(g_handler, 1024, "111111");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int http_event_plugin_init()
|
||||
extern "C" void http_event_plugin_exit(void)
|
||||
{
|
||||
plugin_session_event_register(SESSION_TYPE_HTTP, http_event_plugin_entry, nullptr);
|
||||
return 0;
|
||||
printf("RUN http_event_plugin_exit\n");
|
||||
|
||||
if (g_handler)
|
||||
{
|
||||
free(g_handler);
|
||||
g_handler = NULL;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
[PLUGINFO]
|
||||
INIT_FUNC="custom_event_plugin_init"
|
||||
EXIT_FUNC="custom_event_plugin_exit"
|
||||
LIBRARY_PATH="./plugins/custom_event_plugin/custom_event_plugin.so"
|
||||
|
||||
# Support SESSION_EVENT_TYPE: "SESSION_EVENT_OPENING", "SESSION_EVENT_RAWPKT", "SESSION_EVENT_ORDPKT", "SESSION_EVENT_META", "SESSION_EVENT_CLOSING", "SESSION_EVENT_ALL"
|
||||
|
||||
[SESSION_NAME.TCP]
|
||||
SESSION_EVENT_TYPE=["SESSION_EVENT_ALL"]
|
||||
SESSION_EVENT_CALLBACK="custom_event_plugin_tcp_entry"
|
||||
|
||||
[SESSION_NAME.CUSTOM]
|
||||
SESSION_EVENT_TYPE=["SESSION_EVENT_OPENING","SESSION_EVENT_ORDPKT","SESSION_EVENT_CLOSING"]
|
||||
SESSION_EVENT_CALLBACK="custom_event_plugin_custom_entry"
|
||||
10
sdk/example/plugins/http_event_plugin/http_event_plugin.inf
Normal file
10
sdk/example/plugins/http_event_plugin/http_event_plugin.inf
Normal file
@@ -0,0 +1,10 @@
|
||||
[PLUGINFO]
|
||||
INIT_FUNC="http_event_plugin_init"
|
||||
EXIT_FUNC="http_event_plugin_exit"
|
||||
LIBRARY_PATH="./plugins/http_event_plugin/http_event_plugin.so"
|
||||
|
||||
# Support SESSION_EVENT_TYPE: "SESSION_EVENT_OPENING", "SESSION_EVENT_RAWPKT", "SESSION_EVENT_ORDPKT", "SESSION_EVENT_META", "SESSION_EVENT_CLOSING", "SESSION_EVENT_ALL"
|
||||
|
||||
[SESSION_NAME.HTTP]
|
||||
SESSION_EVENT_TYPE=["SESSION_EVENT_ALL"]
|
||||
SESSION_EVENT_CALLBACK="http_event_plugin_entry"
|
||||
4
sdk/example/plugins/plugins.inf
Normal file
4
sdk/example/plugins/plugins.inf
Normal file
@@ -0,0 +1,4 @@
|
||||
# Relative path, relative to the installation path of stellar
|
||||
|
||||
./plugins/http_event_plugin/http_event_plugin.inf
|
||||
./plugins/custom_event_plugin/custom_event_plugin.inf
|
||||
12
sdk/include/event.h
Normal file
12
sdk/include/event.h
Normal file
@@ -0,0 +1,12 @@
|
||||
|
||||
struct stellar_session_event_data;
|
||||
|
||||
struct stellar_event
|
||||
{
|
||||
union
|
||||
{
|
||||
struct stellar_session_event_data *session_event_data;
|
||||
void *event_data;
|
||||
};
|
||||
};
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#include "packet.h"
|
||||
#include "session.h"
|
||||
|
||||
int http_decoder(const struct session *s, int what, struct packet *p, const char *payload, uint32_t len, void **pme);
|
||||
void http_decoder(const struct stellar_session *s, enum session_event_type event, struct stellar_packet *p, const char *payload, uint16_t len, void **pme);
|
||||
@@ -1,5 +1,3 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
struct packet;
|
||||
struct stellar_packet;
|
||||
@@ -1,9 +1,44 @@
|
||||
#pragma once
|
||||
#ifndef _PLUGIN_H
|
||||
#define _PLUGIN_H
|
||||
|
||||
#ifdef __cpluscplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
#include "session.h"
|
||||
#include <time.h>
|
||||
|
||||
int plugin_session_event_register(int session_type, fn_session_event_callback cb, void *entry_arg);
|
||||
int plugin_session_timer_register(struct session *s, fn_session_timer cb, void *timer_arg, const struct timeval *timeout);
|
||||
typedef int plugin_init_callback(void);
|
||||
typedef void plugin_exit_callback(void);
|
||||
|
||||
int plugin_custom_session_event_register(const char *event_name, fn_session_event_callback cb, void *entry_arg);
|
||||
/******************************************************************************
|
||||
* Public API For Plugin
|
||||
******************************************************************************/
|
||||
|
||||
/*
|
||||
* The pm_session_dettach_me just sets the flag to disable this plugin and no longer call this event callback.
|
||||
* Before calling pm_session_dettach_me, the current plugin must release related resources for the current session.
|
||||
*/
|
||||
void pm_session_dettach_me(const struct stellar_session *session);
|
||||
|
||||
/*
|
||||
* The current plugin(cb2) takes over the current session, the pm_session_take_over setting flag disables other plugins,
|
||||
* and the current session does not call other plugins except for the SESSION_EVENT_CLOSING event.
|
||||
*
|
||||
* +-----+ +-----+ +-----+ +-----+
|
||||
* Plugin runtime callback list: | cb1 |-->| cb2 |-->| cb3 |-->| cb4 |
|
||||
* +-----+ +-----+ +-----+ +-----+
|
||||
* /|\
|
||||
* |
|
||||
* plugin cb2 run pm_session_take_over
|
||||
*
|
||||
* A plugin(cb1/cb3/cb4) that is taken over, if the plugin was called before being taken over and has a registered SESSION_EVENT_CLOSING event,
|
||||
* it will be called again when the SESSION_EVENT_CLOSING event comes. Otherwise, the plugin will not be called.
|
||||
*/
|
||||
void pm_session_take_over(const struct stellar_session *session);
|
||||
|
||||
#ifdef __cpluscplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -1,12 +1,18 @@
|
||||
#pragma once
|
||||
#ifndef _SESSION_H
|
||||
#define _SESSION_H
|
||||
|
||||
#ifdef __cpluscplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
#include "packet.h"
|
||||
#include "event.h"
|
||||
#include <stdint.h>
|
||||
|
||||
struct session;
|
||||
struct session_event;
|
||||
struct stellar_session;
|
||||
|
||||
enum session_type
|
||||
enum stellar_session_type
|
||||
{
|
||||
SESSION_TYPE_CUSTOM,
|
||||
SESSION_TYPE_IP,
|
||||
@@ -25,26 +31,26 @@ enum session_type
|
||||
|
||||
enum session_event_type
|
||||
{
|
||||
SESSION_EVENT_OPENING=0x01,
|
||||
SESSION_EVENT_RAW_PKT=0x02,
|
||||
SESSION_EVENT_ORDERED_PKT=0x04,
|
||||
SESSION_EVENT_META=0x08,
|
||||
SESSION_EVENT_CLOSING=0x10,
|
||||
SESSION_EVENT_UNKNOWN = (0x00),
|
||||
SESSION_EVENT_OPENING = (0x01 << 1),
|
||||
SESSION_EVENT_RAWPKT = (0x01 << 2),
|
||||
SESSION_EVENT_ORDPKT = (0x01 << 3),
|
||||
SESSION_EVENT_META = (0x01 << 4),
|
||||
SESSION_EVENT_CLOSING = (0x01 << 5),
|
||||
SESSION_EVENT_ALL = (0x01 << 1 | 0x01 << 2 | 0x01 << 3 | 0x01 << 4 | 0x01 << 5),
|
||||
};
|
||||
|
||||
struct stellar_session_event_extras;
|
||||
|
||||
typedef int (*fn_session_event_callback)(const struct session *s, int what, struct packet *p, const char *payload, uint32_t len, void **pme);
|
||||
typedef int (*fn_session_timer)(const struct session *s, void **pme);
|
||||
typedef void(fn_session_event_callback)(const struct stellar_session *s, enum session_event_type event, struct stellar_packet *p, const char *payload, uint16_t len, void **pme);
|
||||
|
||||
void session_manager_trigger_event(struct session *s, session_event_type event, void *event_info);
|
||||
void session_manager_trigger_event(struct stellar_session *s, enum session_event_type type, struct stellar_session_event_extras *info);
|
||||
struct stellar_session *session_manager_session_derive(const struct stellar_session *this_session, const char *session_name);
|
||||
|
||||
const char *stellar_session_get_name(const struct stellar_session *session);
|
||||
|
||||
struct session_event *session_manager_commit(struct packet *p);
|
||||
#ifdef __cpluscplus
|
||||
}
|
||||
#endif
|
||||
|
||||
struct custom_session_event;
|
||||
|
||||
struct custom_session_event *session_manager_custom_session_event_register(const char *event_name, int available_event);
|
||||
struct session *session_manager_custom_session_derive(const struct session *cur_session, struct custom_session_event *event);
|
||||
|
||||
|
||||
struct session_event *session_manager_fetch_event();
|
||||
#endif
|
||||
@@ -14,6 +14,7 @@
|
||||
typedef enum {
|
||||
ST_OK = 0,
|
||||
ST_ERR_MEM_ALLOC,
|
||||
ST_ERR_STR_COPY,
|
||||
ST_ERR_RUN_MODE,
|
||||
ST_ERR_PIO_INSTANCE,
|
||||
ST_ERR_PIO_MARSIO_INSTANCE,
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
include_directories(${CMAKE_SOURCE_DIR}/sdk/include)
|
||||
include_directories(${CMAKE_SOURCE_DIR}/deps/)
|
||||
include_directories(${CMAKE_SOURCE_DIR}/src/common/)
|
||||
@@ -6,7 +5,6 @@ include_directories(${CMAKE_SOURCE_DIR}/src/packet_io/)
|
||||
include_directories(${CMAKE_SOURCE_DIR}/src/session_manager/)
|
||||
include_directories(${CMAKE_SOURCE_DIR}/src/plugin_manager/)
|
||||
|
||||
|
||||
enable_testing()
|
||||
add_subdirectory(packet_io)
|
||||
add_subdirectory(session_manager)
|
||||
@@ -17,4 +15,16 @@ add_executable(stellar
|
||||
main.cpp
|
||||
)
|
||||
|
||||
target_link_libraries(stellar packet_io plugin_manager session_manager http dl pcap)
|
||||
target_link_libraries(
|
||||
stellar
|
||||
pthread
|
||||
packet_io
|
||||
plugin_manager
|
||||
session_manager
|
||||
http
|
||||
toml
|
||||
dl
|
||||
pcap
|
||||
)
|
||||
|
||||
install(TARGETS stellar RUNTIME DESTINATION bin COMPONENT Program)
|
||||
@@ -8,6 +8,26 @@
|
||||
***********************************************************************************************
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "global_var.h"
|
||||
|
||||
struct stellar_engine g_engine_instance;
|
||||
struct stellar_engine g_engine_instance;
|
||||
|
||||
int strncpy_safe(char *dst, const char *src, size_t dst_size)
|
||||
{
|
||||
if (nullptr == dst || nullptr == src || dst_size == 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
size_t slen = strlen(src);
|
||||
if (slen >= dst_size) {
|
||||
strncpy(dst, src, dst_size);
|
||||
dst[dst_size - 1] = '\0';
|
||||
} else {
|
||||
strcpy(dst, src);
|
||||
dst[slen - 1] = '\0';
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -79,4 +79,11 @@ struct stellar_engine {
|
||||
struct stellar_config config;
|
||||
};
|
||||
|
||||
extern struct stellar_engine g_engine_instance;
|
||||
extern struct stellar_engine g_engine_instance;
|
||||
|
||||
/**
|
||||
* @brief string copy safely,
|
||||
*
|
||||
* @retval -1(failed), 0(success)
|
||||
*/
|
||||
int strncpy_safe(char *dst, const char *src, size_t dst_size);
|
||||
@@ -48,7 +48,7 @@ void pio_packet_enqueue(struct pio_packet_queue *q, struct pio_packet *p)
|
||||
|
||||
struct pio_packet *pio_packet_dequeue(struct pio_packet_queue *q)
|
||||
{
|
||||
struct pio_packet *p = NULL;
|
||||
struct pio_packet *p = nullptr;
|
||||
|
||||
/* if the queue is empty there are no packets left. */
|
||||
if (q->len == 0) {
|
||||
@@ -87,4 +87,4 @@ void release_pio_packet_queue(struct pio_packet_queue *q)
|
||||
q->len--;
|
||||
FREE(p);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
81
src/main.cpp
81
src/main.cpp
@@ -7,38 +7,43 @@
|
||||
***********************************************************************************************
|
||||
*/
|
||||
|
||||
#include "./common/global_var.h"
|
||||
#include "./packet_io/packet_io.h"
|
||||
#include "./session_manager/session_manager.h"
|
||||
#include "./plugin_manager/plugin_manager.h"
|
||||
#include "../sdk/include/http.h"
|
||||
#include "../sdk/include/logger.h"
|
||||
#include <pthread.h>
|
||||
#include <unistd.h>
|
||||
|
||||
struct packet_io_loop_arg
|
||||
#include "global_var.h"
|
||||
#include "logger.h"
|
||||
#include "packet_io.h"
|
||||
#include "session_manager.h"
|
||||
#include "plugin_manager.h"
|
||||
#include "http.h"
|
||||
|
||||
struct stellar_event_base_loop_arg
|
||||
{
|
||||
struct packet_io_device *dev;
|
||||
int thread_id;
|
||||
struct session_manager *session_mgr;
|
||||
struct plugin_manager *plug_mgr;
|
||||
int tid;
|
||||
};
|
||||
|
||||
void packet_io_loop(struct packet_io_loop_arg *arg)
|
||||
void *stellar_event_base_loop(void *arg)
|
||||
{
|
||||
struct packet *rx_pkt;
|
||||
struct session_event *event;
|
||||
struct stellar_packet *rx_pkt;
|
||||
struct stellar_event *event;
|
||||
struct stellar_event_base_loop_arg *thread_arg = (struct stellar_event_base_loop_arg *)arg;
|
||||
while(1)
|
||||
{
|
||||
int fetch_num = packet_io_device_rx(arg->dev, arg->thread_id, &rx_pkt, 1);
|
||||
int fetch_num = packet_io_device_rx(thread_arg->dev, thread_arg->tid, &rx_pkt, 1);
|
||||
if(fetch_num > 0)
|
||||
{
|
||||
/*
|
||||
event = session_manager_commit(rx_pkt);
|
||||
event = session_manager_commit(thread_arg->session_mgr, rx_pkt);
|
||||
while(event)
|
||||
{
|
||||
plugin_manager_dispatch(event);
|
||||
event = session_manager_fetch_event();
|
||||
}*/
|
||||
printf("fetch_num:%d\n", fetch_num);
|
||||
plugin_manager_dispatch(thread_arg->plug_mgr ,event);
|
||||
event = session_manager_fetch_event(thread_arg->session_mgr);
|
||||
}
|
||||
|
||||
//clean session_manager event queue
|
||||
packet_io_device_tx(arg->dev, arg->thread_id, &rx_pkt, 1);
|
||||
packet_io_device_tx(thread_arg->dev, thread_arg->tid, &rx_pkt, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -48,7 +53,7 @@ void packet_io_loop(struct packet_io_loop_arg *arg)
|
||||
//dispatch to trigger polling event
|
||||
}
|
||||
}
|
||||
return;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
@@ -71,23 +76,33 @@ packet_io_init(const char *instance_name, const enum packet_io_run_mode mode, co
|
||||
|
||||
int main(int argc, char ** argv)
|
||||
{
|
||||
/* global engine instance init */
|
||||
memset(&g_engine_instance, 0, sizeof(g_engine_instance));
|
||||
//packet_io_init
|
||||
struct packet_io_device *dev = packet_io_init("stellar", PACKET_IO_RUN_MODE_PCAP_LIVE, 2);
|
||||
|
||||
g_engine_instance.config.packet_io.mode = PACKET_IO_RUN_MODE_PCAP_FILE;
|
||||
strncpy(g_engine_instance.config.packet_io.dev_name[0], "./test.pcap", sizeof(NAME_MAX));
|
||||
g_engine_instance.config.packet_io.dev_cnt = 1;
|
||||
//manager_init
|
||||
struct session_manager *session_mgr = session_manager_init();
|
||||
struct plugin_manager *plug_mgr = plugin_manager_create();
|
||||
|
||||
/* packet io init */
|
||||
packet_io_init("stellar", g_engine_instance.config.packet_io.mode, 2);
|
||||
// register build-in plugin
|
||||
plugin_manager_register(plug_mgr, "HTTP", SESSION_EVENT_ALL, http_decoder);
|
||||
|
||||
// load external plugins
|
||||
char file_path[] = "./plugs/plugins.inf";
|
||||
plugin_manager_load(plug_mgr, file_path);
|
||||
|
||||
//session_manager_session_event_register(http_decoder, SESSION_TYPE_HTTP);
|
||||
struct packet_io_loop_arg arg;
|
||||
while (1) {
|
||||
//packet_io_loop();
|
||||
}
|
||||
//create_worker_thread
|
||||
|
||||
stellar_event_base_loop_arg arg = {dev, session_mgr, plug_mgr, 0};
|
||||
pthread_t worker_pid;
|
||||
pthread_create(&worker_pid, nullptr, stellar_event_base_loop, (void *)&arg);
|
||||
//main_loop
|
||||
while (1)
|
||||
{
|
||||
/* main loop code */
|
||||
usleep(1);
|
||||
}
|
||||
|
||||
plugin_manager_unload(plug_mgr);
|
||||
plugin_manager_destory(plug_mgr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -319,7 +319,7 @@ int pio_marsio_device_close(struct packet_io_device *pdev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pio_marsio_device_receive(struct packet_io_device *pdev, uint32_t rxq_id, struct packet **pkts, int nr_pkts)
|
||||
int pio_marsio_device_receive(struct packet_io_device *pdev, uint32_t rxq_id, struct stellar_packet **pkts, int nr_pkts)
|
||||
{
|
||||
struct mr_vdev *mr_dev_handle = pdev->entity.marsio_dev_ctx->mr_dev_handle;
|
||||
marsio_buff_t *rx_buff[MARSIO_BURST_PKT_MAX];
|
||||
@@ -328,14 +328,14 @@ int pio_marsio_device_receive(struct packet_io_device *pdev, uint32_t rxq_id, st
|
||||
/* receive some pkts, copy mbuf pointer to packet structure */
|
||||
if (recv_res > 0) {
|
||||
for (int i = 0; i < recv_res; i++) {
|
||||
pkts[i]= (struct packet *)rx_buff[i];
|
||||
pkts[i]= (struct stellar_packet *)rx_buff[i];
|
||||
}
|
||||
}
|
||||
|
||||
return recv_res;
|
||||
}
|
||||
|
||||
int pio_marsio_device_send(struct packet_io_device *pdev, uint32_t txq_id, struct packet **pkts, int nr_pkts)
|
||||
int pio_marsio_device_send(struct packet_io_device *pdev, uint32_t txq_id, struct stellar_packet **pkts, int nr_pkts)
|
||||
{
|
||||
struct mr_sendpath *sendpath_handle = pdev->entity.marsio_dev_ctx->mr_sendpath_handle;
|
||||
int ret = g_marsio_dll_func.marsio_send_burst(sendpath_handle, txq_id, (marsio_buff_t **)pkts, nr_pkts);
|
||||
@@ -347,7 +347,7 @@ int pio_marsio_device_send(struct packet_io_device *pdev, uint32_t txq_id, struc
|
||||
return ret;
|
||||
}
|
||||
|
||||
void pio_marsio_device_pkt_free(struct packet_io_device *pdev, uint32_t qid, struct packet **pkts, int nr_pkts)
|
||||
void pio_marsio_device_pkt_free(struct packet_io_device *pdev, uint32_t qid, struct stellar_packet **pkts, int nr_pkts)
|
||||
{
|
||||
struct mr_instance *mr_inst = pdev->ppio_inst->entity.marsio_inst_ctx->mr_inst_handle;
|
||||
g_marsio_dll_func.marsio_buff_free(mr_inst, (marsio_buff_t **)pkts, nr_pkts, MARSIO_SOCKET_ID_ANY, qid);
|
||||
@@ -424,24 +424,24 @@ void pio_marsio_instance_destroy(struct packet_io_instance *pinst)
|
||||
}
|
||||
}
|
||||
|
||||
void *pio_marsio_device_buff_ctrlzone(struct packet *p)
|
||||
void *pio_marsio_device_buff_ctrlzone(struct stellar_packet *p)
|
||||
{
|
||||
int zone_id = 0;
|
||||
|
||||
return g_marsio_dll_func.marsio_buff_ctrlzone((marsio_buff_t *)p, zone_id);
|
||||
}
|
||||
|
||||
char *pio_marsio_device_buff_mtod(struct packet *p)
|
||||
char *pio_marsio_device_buff_mtod(struct stellar_packet *p)
|
||||
{
|
||||
return g_marsio_dll_func.marsio_buff_mtod((marsio_buff_t *)p);
|
||||
}
|
||||
|
||||
uint32_t pio_marsio_device_buff_buflen(struct packet *p)
|
||||
uint32_t pio_marsio_device_buff_buflen(struct stellar_packet *p)
|
||||
{
|
||||
return g_marsio_dll_func.marsio_buff_buflen((marsio_buff_t *)p);
|
||||
}
|
||||
|
||||
uint32_t pio_marsio_device_buff_datalen(struct packet *p)
|
||||
uint32_t pio_marsio_device_buff_datalen(struct stellar_packet *p)
|
||||
{
|
||||
return g_marsio_dll_func.marsio_buff_datalen((marsio_buff_t *)p);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -136,7 +136,7 @@ int pio_marsio_device_close(struct packet_io_device *pdev);
|
||||
*
|
||||
* @retval number of packets actually received
|
||||
*/
|
||||
int pio_marsio_device_receive(struct packet_io_device *pdev, uint32_t rxq_id, struct packet **pkts, int nr_pkts);
|
||||
int pio_marsio_device_receive(struct packet_io_device *pdev, uint32_t rxq_id, struct stellar_packet **pkts, int nr_pkts);
|
||||
|
||||
/**
|
||||
* @brief send packets by device's single tx queue which specified by txq_id
|
||||
@@ -148,7 +148,7 @@ int pio_marsio_device_receive(struct packet_io_device *pdev, uint32_t rxq_id, st
|
||||
*
|
||||
* @retval if ret<0, means the sending fails; if ret==0 means the sending succeeds
|
||||
*/
|
||||
int pio_marsio_device_send(struct packet_io_device *pdev, uint32_t txq_id, struct packet **pkts, int nr_pkts);
|
||||
int pio_marsio_device_send(struct packet_io_device *pdev, uint32_t txq_id, struct stellar_packet **pkts, int nr_pkts);
|
||||
|
||||
/**
|
||||
* @brief manually free packet's memory
|
||||
@@ -158,12 +158,12 @@ int pio_marsio_device_send(struct packet_io_device *pdev, uint32_t txq_id, struc
|
||||
* @param pkts:
|
||||
* @param nr_pkts:
|
||||
*/
|
||||
void pio_marsio_device_pkt_free(struct packet_io_device *pdev, uint32_t qid, struct packet **pkts, int nr_pkts);
|
||||
void pio_marsio_device_pkt_free(struct packet_io_device *pdev, uint32_t qid, struct stellar_packet **pkts, int nr_pkts);
|
||||
|
||||
void *pio_marsio_device_buff_ctrlzone(struct packet *p);
|
||||
void *pio_marsio_device_buff_ctrlzone(struct stellar_packet *p);
|
||||
|
||||
char *pio_marsio_device_buff_mtod(struct packet *p);
|
||||
char *pio_marsio_device_buff_mtod(struct stellar_packet *p);
|
||||
|
||||
uint32_t pio_marsio_device_buff_buflen(struct packet *p);
|
||||
uint32_t pio_marsio_device_buff_buflen(struct stellar_packet *p);
|
||||
|
||||
uint32_t pio_marsio_device_buff_datalen(struct packet *p);
|
||||
uint32_t pio_marsio_device_buff_datalen(struct stellar_packet *p);
|
||||
@@ -84,11 +84,16 @@ packet_io_instance_create(const char *inst_name, const enum packet_io_run_mode m
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
strncpy(pio_instance->inst_name, inst_name, strlen(inst_name));
|
||||
int ret = strncpy_safe(pio_instance->inst_name, inst_name, sizeof(pio_instance->inst_name));
|
||||
if (ret < 0) {
|
||||
log_error(ST_ERR_STR_COPY, "packet_io instance name copy failed.");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
pio_instance->mode = mode;
|
||||
pio_instance->inst_ops = &pio_instance_ops_array[mode];
|
||||
|
||||
int ret = pio_instance->inst_ops->create(pio_instance);
|
||||
ret = pio_instance->inst_ops->create(pio_instance);
|
||||
if (ret < 0) {
|
||||
log_error(ST_ERR_PIO_INSTANCE, "packet_io instance create failed.");
|
||||
return nullptr;
|
||||
@@ -115,7 +120,12 @@ packet_io_device_open(struct packet_io_instance *pinst, const char *dev_name, ui
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
strncpy(ppio_dev->dev_name, dev_name, strlen(dev_name));
|
||||
int ret = strncpy_safe(ppio_dev->dev_name, dev_name, sizeof(ppio_dev->dev_name));
|
||||
if (ret < 0) {
|
||||
log_error(ST_ERR_STR_COPY, "packet_io device name copy failed.");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ppio_dev->rxq_num = nr_rxq;
|
||||
ppio_dev->txq_num = nr_txq;
|
||||
ppio_dev->ppio_inst = pinst;
|
||||
@@ -127,7 +137,7 @@ packet_io_device_open(struct packet_io_instance *pinst, const char *dev_name, ui
|
||||
**/
|
||||
pinst->devices[pinst->dev_cnt++] = ppio_dev;
|
||||
|
||||
int ret = ppio_dev->dev_ops->open(ppio_dev);
|
||||
ret = ppio_dev->dev_ops->open(ppio_dev);
|
||||
if (ret < 0) {
|
||||
log_error(ST_ERR_PIO_DEVICE, "packet_io device open failed.");
|
||||
FREE(ppio_dev);
|
||||
@@ -156,37 +166,37 @@ void packet_io_device_close(struct packet_io_device *pdev)
|
||||
FREE(pdev);
|
||||
}
|
||||
|
||||
int packet_io_device_rx(struct packet_io_device *pdev, uint32_t rxq_id, struct packet **pkts, int nr_pkts)
|
||||
int packet_io_device_rx(struct packet_io_device *pdev, uint32_t rxq_id, struct stellar_packet **pkts, int nr_pkts)
|
||||
{
|
||||
return pdev->dev_ops->recv(pdev, rxq_id, pkts, nr_pkts);
|
||||
}
|
||||
|
||||
int packet_io_device_tx(struct packet_io_device *pdev, uint32_t txq_id, struct packet **pkts, int nr_pkts)
|
||||
int packet_io_device_tx(struct packet_io_device *pdev, uint32_t txq_id, struct stellar_packet **pkts, int nr_pkts)
|
||||
{
|
||||
return pdev->dev_ops->send(pdev, txq_id, pkts, nr_pkts);
|
||||
}
|
||||
|
||||
void packet_io_pkts_free(struct packet_io_device *pdev, uint32_t qid, struct packet **pkts, int nr_pkts)
|
||||
void packet_io_pkts_free(struct packet_io_device *pdev, uint32_t qid, struct stellar_packet **pkts, int nr_pkts)
|
||||
{
|
||||
return pdev->dev_ops->pkt_free(pdev, qid, pkts, nr_pkts);
|
||||
}
|
||||
|
||||
void *packet_io_buff_ctrlzone(struct packet_io_device *pdev, struct packet *p)
|
||||
void *packet_io_buff_ctrlzone(struct packet_io_device *pdev, struct stellar_packet *p)
|
||||
{
|
||||
return pdev->dev_ops->buff_ctrlzone(p);
|
||||
}
|
||||
|
||||
char *packet_io_buff_mtod(struct packet_io_device *pdev, struct packet *p)
|
||||
char *packet_io_buff_mtod(struct packet_io_device *pdev, struct stellar_packet *p)
|
||||
{
|
||||
return pdev->dev_ops->buff_mtod(p);
|
||||
}
|
||||
|
||||
uint32_t packet_io_buff_buflen(struct packet_io_device *pdev, struct packet *p)
|
||||
uint32_t packet_io_buff_buflen(struct packet_io_device *pdev, struct stellar_packet *p)
|
||||
{
|
||||
return pdev->dev_ops->buff_buflen(p);
|
||||
}
|
||||
|
||||
uint32_t packet_io_buff_datalen(struct packet_io_device *pdev, struct packet *p)
|
||||
uint32_t packet_io_buff_datalen(struct packet_io_device *pdev, struct stellar_packet *p)
|
||||
{
|
||||
return pdev->dev_ops->buff_datalen(p);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -60,19 +60,19 @@ struct pio_device_operations {
|
||||
|
||||
int (*close)(struct packet_io_device *pdev);
|
||||
|
||||
int (*recv)(struct packet_io_device *pdev, uint32_t rxq_id, struct packet **pkts, int nr_pkts);
|
||||
int (*recv)(struct packet_io_device *pdev, uint32_t rxq_id, struct stellar_packet **pkts, int nr_pkts);
|
||||
|
||||
int (*send)(struct packet_io_device *pdev, uint32_t txq_id, struct packet **pkts, int nr_pkts);
|
||||
int (*send)(struct packet_io_device *pdev, uint32_t txq_id, struct stellar_packet **pkts, int nr_pkts);
|
||||
|
||||
void (*pkt_free)(struct packet_io_device *pdev, uint32_t qid, struct packet **pkts, int nr_pkts);
|
||||
void (*pkt_free)(struct packet_io_device *pdev, uint32_t qid, struct stellar_packet **pkts, int nr_pkts);
|
||||
|
||||
void *(*buff_ctrlzone)(struct packet *p);
|
||||
void *(*buff_ctrlzone)(struct stellar_packet *p);
|
||||
|
||||
char *(*buff_mtod)(struct packet *p);
|
||||
char *(*buff_mtod)(struct stellar_packet *p);
|
||||
|
||||
uint32_t (*buff_buflen)(struct packet *p);
|
||||
uint32_t (*buff_buflen)(struct stellar_packet *p);
|
||||
|
||||
uint32_t (*buff_datalen)(struct packet *p);
|
||||
uint32_t (*buff_datalen)(struct stellar_packet *p);
|
||||
};
|
||||
|
||||
struct packet_io_device {
|
||||
@@ -133,7 +133,7 @@ void packet_io_device_close(struct packet_io_device *dev);
|
||||
* @param p: received packet's pointer array
|
||||
* @param nr_p: number of received packets
|
||||
*/
|
||||
int packet_io_device_rx(struct packet_io_device *pdev, uint32_t rxq_id, struct packet **pkts, int nr_pkts);
|
||||
int packet_io_device_rx(struct packet_io_device *pdev, uint32_t rxq_id, struct stellar_packet **pkts, int nr_pkts);
|
||||
|
||||
/**
|
||||
* @brief packet_io device send function
|
||||
@@ -143,30 +143,30 @@ int packet_io_device_rx(struct packet_io_device *pdev, uint32_t rxq_id, struct p
|
||||
* @param p: prepare to send packet's pointer array
|
||||
* @param nr_p: number of packets which prepare to send
|
||||
*/
|
||||
int packet_io_device_tx(struct packet_io_device *pdev, uint32_t txq_id, struct packet **pkts, int nr_pkts);
|
||||
int packet_io_device_tx(struct packet_io_device *pdev, uint32_t txq_id, struct stellar_packet **pkts, int nr_pkts);
|
||||
|
||||
/*
|
||||
* @brief packet_io free packet buff
|
||||
*/
|
||||
void packet_io_pkts_free(struct packet_io_device *pdev, uint32_t qid, struct packet **pkts, int nr_pkts);
|
||||
void packet_io_pkts_free(struct packet_io_device *pdev, uint32_t qid, struct stellar_packet **pkts, int nr_pkts);
|
||||
|
||||
/**
|
||||
* @brief get packet_io packet's ctrlzone
|
||||
* @note ctrlzone's memory is 64 bytes, do not exceed it
|
||||
*/
|
||||
void *packet_io_buff_ctrlzone(struct packet_io_device *pdev, struct packet *p);
|
||||
void *packet_io_buff_ctrlzone(struct packet_io_device *pdev, struct stellar_packet *p);
|
||||
|
||||
/**
|
||||
* @brief get packet_io packet's data pointer
|
||||
*/
|
||||
char *packet_io_buff_mtod(struct packet_io_device *pdev, struct packet *p);
|
||||
char *packet_io_buff_mtod(struct packet_io_device *pdev, struct stellar_packet *p);
|
||||
|
||||
/**
|
||||
* @brief get packet_io packet's buffer length
|
||||
*/
|
||||
uint32_t packet_io_buff_buflen(struct packet_io_device *pdev, struct packet *p);
|
||||
uint32_t packet_io_buff_buflen(struct packet_io_device *pdev, struct stellar_packet *p);
|
||||
|
||||
/**
|
||||
* @brief get packet_io packet's data length
|
||||
*/
|
||||
uint32_t packet_io_buff_datalen(struct packet_io_device *pdev, struct packet *p);
|
||||
uint32_t packet_io_buff_datalen(struct packet_io_device *pdev, struct stellar_packet *p);
|
||||
@@ -93,7 +93,7 @@ static int init_pcap_file(struct pcap_plain_file_info *pfile_info)
|
||||
return -1;
|
||||
}
|
||||
|
||||
pthread_mutex_init(&pfile_info->handle_mutex, NULL);
|
||||
pthread_mutex_init(&pfile_info->handle_mutex, nullptr);
|
||||
|
||||
if (pfile_info->shared != nullptr && pfile_info->shared->bpf_string != nullptr) {
|
||||
if (pcap_compile(pfile_info->pcap_handle, &pfile_info->filter,
|
||||
@@ -133,9 +133,14 @@ static int pcap_plain_file_init(struct pio_pcap_file_device_context *pfile_dev_c
|
||||
}
|
||||
|
||||
/* TODO: get conf and assign pfile_info */
|
||||
strncpy(pfile_info->file_name, file_name, strlen(file_name));
|
||||
int ret = strncpy_safe(pfile_info->file_name, file_name, sizeof(pfile_info->file_name));
|
||||
if (ret < 0) {
|
||||
log_error(ST_ERR_STR_COPY, "pcap plain file name copy failed.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
pfile_info->shared = &pfile_dev_ctx->shared;
|
||||
int ret = init_pcap_file(pfile_info);
|
||||
ret = init_pcap_file(pfile_info);
|
||||
if (ret < 0) {
|
||||
log_error(ST_ERR_PIO_PCAP_FILE_DEVICE, "init_pcap_file failed.");
|
||||
FREE(pfile_info);
|
||||
@@ -161,7 +166,12 @@ static int pcap_directory_file_init(struct pio_pcap_file_device_context *pfile_d
|
||||
}
|
||||
|
||||
/* TODO: get conf and assign pdir_info */
|
||||
strncpy(pdir_info->dir_name, dir_name, strlen(dir_name));
|
||||
int ret = strncpy_safe(pdir_info->dir_name, dir_name, sizeof(pdir_info->dir_name));
|
||||
if (ret < 0) {
|
||||
log_error(ST_ERR_STR_COPY, "pcap directory name copy failed.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
//pdir_info->delay = 30;
|
||||
pdir_info->shared = &pfile_dev_ctx->shared;
|
||||
pdir_info->directory = directory;
|
||||
@@ -182,8 +192,13 @@ static int pcap_file_shared_init(struct pio_pcap_file_device_context *pfile_dev_
|
||||
/* TODO: get conf and assign pfile_dev_ctx->shared */
|
||||
if ((g_engine_instance.config.packet_io.mode == PACKET_IO_RUN_MODE_PCAP_FILE) &&
|
||||
g_engine_instance.config.packet_io.bpf_string != nullptr) {
|
||||
strncpy(pfile_dev_ctx->shared.bpf_string, g_engine_instance.config.packet_io.bpf_string,
|
||||
strlen(g_engine_instance.config.packet_io.bpf_string));
|
||||
memset(pfile_dev_ctx->shared.bpf_string, 0, sizeof(pfile_dev_ctx->shared.bpf_string));
|
||||
int ret = strncpy_safe(pfile_dev_ctx->shared.bpf_string, g_engine_instance.config.packet_io.bpf_string,
|
||||
sizeof(pfile_dev_ctx->shared.bpf_string));
|
||||
if (ret < 0) {
|
||||
log_error(ST_ERR_STR_COPY, "pcap file bpf string copy failed.");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
pfile_dev_ctx->shared.should_delete = g_engine_instance.config.packet_io.should_delete;
|
||||
@@ -315,7 +330,7 @@ void pcap_file_pkt_callback_oneshot(char *user, struct pcap_pkthdr *pkt_hdr, u_c
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t nr_rxq = pfile_dev_ctx->pio_dev->rxq_num;
|
||||
//uint32_t nr_rxq = pfile_dev_ctx->pio_dev->rxq_num;
|
||||
/*
|
||||
hash to specific queue id and enqueue
|
||||
hash_id = decode_packet(p) % nr_rxq;
|
||||
@@ -328,7 +343,7 @@ void pcap_file_pkt_callback_oneshot(char *user, struct pcap_pkthdr *pkt_hdr, u_c
|
||||
}
|
||||
|
||||
static int pcap_file_dispatch(struct pio_pcap_file_device_context *pfile_dev_ctx, uint32_t rxq_id,
|
||||
struct packet **pkts, int nr_pkts)
|
||||
struct stellar_packet **pkts, int nr_pkts)
|
||||
{
|
||||
if (pfile_dev_ctx->entity.file->first_pkt_hdr != nullptr) {
|
||||
pthread_mutex_lock(&pfile_dev_ctx->entity.file->handle_mutex);
|
||||
@@ -361,7 +376,7 @@ static int pcap_file_dispatch(struct pio_pcap_file_device_context *pfile_dev_ctx
|
||||
pthread_mutex_lock(&pfile_dev_ctx->pkt_queues[rxq_id].mutex_q);
|
||||
do {
|
||||
p = pio_packet_dequeue(&pfile_dev_ctx->pkt_queues[rxq_id]);
|
||||
pkts[i] = (struct packet *)p;
|
||||
pkts[i] = (struct stellar_packet *)p;
|
||||
i++;
|
||||
} while (p != nullptr && (i < nr_pkts));
|
||||
pthread_mutex_unlock(&pfile_dev_ctx->pkt_queues[rxq_id].mutex_q);
|
||||
@@ -401,7 +416,7 @@ find_pending_file_to_add(struct pio_pcap_file_device_context *pfile_dev_ctx, str
|
||||
{
|
||||
char abs_path[PATH_MAX] = {0};
|
||||
|
||||
snprintf(abs_path, PATH_MAX, "%s/%s", pfile_dev_ctx->entity.dir->dir_name, dir->d_name);
|
||||
snprintf(abs_path, sizeof(abs_path), "%s/%s", pfile_dev_ctx->entity.dir->dir_name, dir->d_name);
|
||||
struct timespec temp_time;
|
||||
memset(&temp_time, 0, sizeof(struct timespec));
|
||||
|
||||
@@ -420,7 +435,12 @@ find_pending_file_to_add(struct pio_pcap_file_device_context *pfile_dev_ctx, str
|
||||
}
|
||||
|
||||
struct pending_file *file_to_add = CALLOC(struct pending_file, 1);
|
||||
strncpy(file_to_add->file_name, abs_path, strlen(abs_path));
|
||||
int ret = strncpy_safe(file_to_add->file_name, abs_path, sizeof(file_to_add->file_name));
|
||||
if (ret < 0) {
|
||||
log_error(ST_ERR_STR_COPY, "file_to_add file name copy failed.");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
copy_timespec(&temp_time, &file_to_add->modified_time);
|
||||
log_info("found \"%s\" at %" PRIuMAX, file_to_add->file_name,
|
||||
(uintmax_t)timespec_to_millisecond(&file_to_add->modified_time));
|
||||
@@ -499,7 +519,7 @@ static int pcap_directory_collect_pending_files(struct pio_pcap_file_device_cont
|
||||
}
|
||||
|
||||
static int pcap_directory_dispatch(struct pio_pcap_file_device_context *pfile_dev_ctx, uint32_t rxq_id,
|
||||
struct packet **pkts, int nr_pkts)
|
||||
struct stellar_packet **pkts, int nr_pkts)
|
||||
{
|
||||
int res = -1;
|
||||
struct timespec deadline;
|
||||
@@ -535,7 +555,14 @@ static int pcap_directory_dispatch(struct pio_pcap_file_device_context *pfile_de
|
||||
return -1;
|
||||
}
|
||||
|
||||
strncpy(pfile_info->file_name, current_file->file_name, strlen(current_file->file_name));
|
||||
res = strncpy_safe(pfile_info->file_name, current_file->file_name, sizeof(pfile_info->file_name));
|
||||
if (res < 0) {
|
||||
log_error(ST_ERR_STR_COPY, "pfile_info file name copy failed.");
|
||||
FREE(current_file);
|
||||
FREE(pfile_info);
|
||||
return -1;
|
||||
}
|
||||
|
||||
pfile_info->shared = &pfile_dev_ctx->shared;
|
||||
|
||||
if (init_pcap_file(pfile_info) < 0) {
|
||||
@@ -576,13 +603,7 @@ static int pcap_directory_dispatch(struct pio_pcap_file_device_context *pfile_de
|
||||
return res;
|
||||
}
|
||||
|
||||
static int pcap_file_exit(int status, struct timespec *last_processed)
|
||||
{
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pio_pcap_file_device_receive(struct packet_io_device *pdev, uint32_t rxq_id, struct packet **pkts, int nr_pkts)
|
||||
int pio_pcap_file_device_receive(struct packet_io_device *pdev, uint32_t rxq_id, struct stellar_packet **pkts, int nr_pkts)
|
||||
{
|
||||
struct pio_pcap_file_device_context *pfile_dev_ctx = pdev->entity.pcap_file_dev_ctx;
|
||||
if (nullptr == pfile_dev_ctx) {
|
||||
@@ -599,14 +620,12 @@ int pio_pcap_file_device_receive(struct packet_io_device *pdev, uint32_t rxq_id,
|
||||
res = pcap_directory_dispatch(pfile_dev_ctx, rxq_id, pkts, nr_pkts);
|
||||
}
|
||||
|
||||
//pcap_file_exit(status, &pfile_dev_ctx->shared.last_processed_ts);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
void pio_pcap_file_device_pkt_free(__unused struct packet_io_device *pdev, __unused uint32_t qid, struct packet **pkts, int nr_pkts)
|
||||
void pio_pcap_file_device_pkt_free(__unused struct packet_io_device *pdev, __unused uint32_t qid, struct stellar_packet **pkts, int nr_pkts)
|
||||
{
|
||||
for (uint32_t i = 0; i < nr_pkts; i++) {
|
||||
for (int i = 0; i < nr_pkts; i++) {
|
||||
struct pio_packet *p = (struct pio_packet *)pkts[i];
|
||||
FREE(p);
|
||||
}
|
||||
@@ -642,26 +661,26 @@ void pio_pcap_file_instance_destroy(struct packet_io_instance *pinst)
|
||||
}
|
||||
}
|
||||
|
||||
void *pio_pcap_file_device_buff_ctrlzone(struct packet *p)
|
||||
void *pio_pcap_file_device_buff_ctrlzone(struct stellar_packet *p)
|
||||
{
|
||||
struct pio_packet *pkt = (struct pio_packet *)p;
|
||||
return pkt->pkt_hdr;
|
||||
}
|
||||
|
||||
char *pio_pcap_file_device_buff_mtod(struct packet *p)
|
||||
char *pio_pcap_file_device_buff_mtod(struct stellar_packet *p)
|
||||
{
|
||||
struct pio_packet *pkt = (struct pio_packet *)p;
|
||||
return (char *)pkt->pkt_payload;
|
||||
}
|
||||
|
||||
uint32_t pio_pcap_file_device_buff_buflen(struct packet *p)
|
||||
uint32_t pio_pcap_file_device_buff_buflen(struct stellar_packet *p)
|
||||
{
|
||||
struct pio_packet *pkt = (struct pio_packet *)p;
|
||||
return (pkt->pkt_len + CUSTOM_ZONE_LEN);
|
||||
}
|
||||
|
||||
uint32_t pio_pcap_file_device_buff_datalen(struct packet *p)
|
||||
uint32_t pio_pcap_file_device_buff_datalen(struct stellar_packet *p)
|
||||
{
|
||||
struct pio_packet *pkt = (struct pio_packet *)p;
|
||||
return (pkt->pkt_len);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -127,14 +127,14 @@ int pio_pcap_file_device_open(struct packet_io_device *pdev);
|
||||
*/
|
||||
int pio_pcap_file_device_close(struct packet_io_device *pdev);
|
||||
|
||||
int pio_pcap_file_device_receive(struct packet_io_device *pdev, uint32_t rxq_id, struct packet **pkts, int nr_pkts);
|
||||
int pio_pcap_file_device_receive(struct packet_io_device *pdev, uint32_t rxq_id, struct stellar_packet **pkts, int nr_pkts);
|
||||
|
||||
void pio_pcap_file_device_pkt_free(struct packet_io_device *pdev, uint32_t qid, struct packet **pkts, int nr_pkts);
|
||||
void pio_pcap_file_device_pkt_free(struct packet_io_device *pdev, uint32_t qid, struct stellar_packet **pkts, int nr_pkts);
|
||||
|
||||
void *pio_pcap_file_device_buff_ctrlzone(struct packet *p);
|
||||
void *pio_pcap_file_device_buff_ctrlzone(struct stellar_packet *p);
|
||||
|
||||
char *pio_pcap_file_device_buff_mtod(struct packet *p);
|
||||
char *pio_pcap_file_device_buff_mtod(struct stellar_packet *p);
|
||||
|
||||
uint32_t pio_pcap_file_device_buff_buflen(struct packet *p);
|
||||
uint32_t pio_pcap_file_device_buff_buflen(struct stellar_packet *p);
|
||||
|
||||
uint32_t pio_pcap_file_device_buff_datalen(struct packet *p);
|
||||
uint32_t pio_pcap_file_device_buff_datalen(struct stellar_packet *p);
|
||||
@@ -76,8 +76,13 @@ static int pcap_live_init(struct pio_pcap_live_device_context *pcap_live_dev_ctx
|
||||
|
||||
/* set bpf filter */
|
||||
if (strlen(g_engine_instance.config.packet_io.bpf_string) != 0) {
|
||||
strncpy(pcap_live_dev_ctx->bpf_string, g_engine_instance.config.packet_io.bpf_string,
|
||||
strlen(g_engine_instance.config.packet_io.bpf_string));
|
||||
res = strncpy_safe(pcap_live_dev_ctx->bpf_string, g_engine_instance.config.packet_io.bpf_string,
|
||||
sizeof(pcap_live_dev_ctx->bpf_string));
|
||||
if (res < 0) {
|
||||
log_error(ST_ERR_STR_COPY, "pcap_live_dev_ctx bpf string copy failed.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (pcap_compile(pcap_live_dev_ctx->pcap_handle, &pcap_live_dev_ctx->filter,
|
||||
pcap_live_dev_ctx->bpf_string, 1, 0) < 0) {
|
||||
log_error(ST_ERR_BPF, "bpf compliation error %s",
|
||||
@@ -160,7 +165,7 @@ static void pcap_live_pkt_callback_oneshot(char *user, struct pcap_pkthdr *pkt_h
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t nr_rxq = plive_dev_ctx->pio_dev->rxq_num;
|
||||
//uint32_t nr_rxq = plive_dev_ctx->pio_dev->rxq_num;
|
||||
/*
|
||||
hash to specific queue id and enqueue
|
||||
hash_id = decode_packet(p) % nr_rxq;
|
||||
@@ -172,7 +177,7 @@ static void pcap_live_pkt_callback_oneshot(char *user, struct pcap_pkthdr *pkt_h
|
||||
pthread_mutex_unlock(&plive_dev_ctx->pkt_queues[rxq_id].mutex_q);
|
||||
}
|
||||
|
||||
int pio_pcap_live_device_receive(struct packet_io_device *pdev, uint32_t rxq_id, struct packet **pkts, int nr_pkts)
|
||||
int pio_pcap_live_device_receive(struct packet_io_device *pdev, uint32_t rxq_id, struct stellar_packet **pkts, int nr_pkts)
|
||||
{
|
||||
int res = -1;
|
||||
|
||||
@@ -198,7 +203,7 @@ int pio_pcap_live_device_receive(struct packet_io_device *pdev, uint32_t rxq_id,
|
||||
pthread_mutex_lock(&plive_dev_ctx->pkt_queues[rxq_id].mutex_q);
|
||||
do {
|
||||
p = pio_packet_dequeue(&plive_dev_ctx->pkt_queues[rxq_id]);
|
||||
pkts[i] = (struct packet *)p;
|
||||
pkts[i] = (struct stellar_packet *)p;
|
||||
i++;
|
||||
} while (p != nullptr && (i < nr_pkts));
|
||||
pthread_mutex_unlock(&plive_dev_ctx->pkt_queues[rxq_id].mutex_q);
|
||||
@@ -213,7 +218,7 @@ int pio_pcap_live_device_receive(struct packet_io_device *pdev, uint32_t rxq_id,
|
||||
return res;
|
||||
}
|
||||
|
||||
int pio_pcap_live_device_send(struct packet_io_device *pdev, uint32_t txq_id, struct packet **pkts, int nr_pkts)
|
||||
int pio_pcap_live_device_send(struct packet_io_device *pdev, uint32_t txq_id, struct stellar_packet **pkts, int nr_pkts)
|
||||
{
|
||||
int res = -1;
|
||||
|
||||
@@ -223,9 +228,8 @@ int pio_pcap_live_device_send(struct packet_io_device *pdev, uint32_t txq_id, st
|
||||
return res;
|
||||
}
|
||||
|
||||
int packet_q_len = nr_pkts;
|
||||
pthread_mutex_lock(&plive_dev_ctx->handle_mutex);
|
||||
for (uint32_t i = 0; i < nr_pkts; i++) {
|
||||
for (int i = 0; i < nr_pkts; i++) {
|
||||
struct pio_packet *p = (struct pio_packet *)pkts[i];
|
||||
res = pcap_sendpacket(plive_dev_ctx->pcap_handle, (u_char *)p->pkt_payload, p->pkt_len);
|
||||
}
|
||||
@@ -235,9 +239,9 @@ int pio_pcap_live_device_send(struct packet_io_device *pdev, uint32_t txq_id, st
|
||||
return 0;
|
||||
}
|
||||
|
||||
void pio_pcap_live_device_pkt_free(__unused struct packet_io_device *pdev, __unused uint32_t qid, struct packet **pkts, int nr_pkts)
|
||||
void pio_pcap_live_device_pkt_free(__unused struct packet_io_device *pdev, __unused uint32_t qid, struct stellar_packet **pkts, int nr_pkts)
|
||||
{
|
||||
for (uint32_t i = 0; i < nr_pkts; i++) {
|
||||
for (int i = 0; i < nr_pkts; i++) {
|
||||
struct pio_packet *p = (struct pio_packet *)pkts[i];
|
||||
FREE(p);
|
||||
}
|
||||
@@ -273,26 +277,26 @@ void pio_pcap_live_instance_destroy(struct packet_io_instance *pinst)
|
||||
}
|
||||
}
|
||||
|
||||
void *pio_pcap_live_device_buff_ctrlzone(struct packet *p)
|
||||
void *pio_pcap_live_device_buff_ctrlzone(struct stellar_packet *p)
|
||||
{
|
||||
struct pio_packet *pkt = (struct pio_packet *)p;
|
||||
return pkt->pkt_hdr;
|
||||
}
|
||||
|
||||
char *pio_pcap_live_device_buff_mtod(struct packet *p)
|
||||
char *pio_pcap_live_device_buff_mtod(struct stellar_packet *p)
|
||||
{
|
||||
struct pio_packet *pkt = (struct pio_packet *)p;
|
||||
return (char *)pkt->pkt_payload;
|
||||
}
|
||||
|
||||
uint32_t pio_pcap_live_device_buff_buflen(struct packet *p)
|
||||
uint32_t pio_pcap_live_device_buff_buflen(struct stellar_packet *p)
|
||||
{
|
||||
struct pio_packet *pkt = (struct pio_packet *)p;
|
||||
return (pkt->pkt_len + CUSTOM_ZONE_LEN);
|
||||
}
|
||||
|
||||
uint32_t pio_pcap_live_device_buff_datalen(struct packet *p)
|
||||
uint32_t pio_pcap_live_device_buff_datalen(struct stellar_packet *p)
|
||||
{
|
||||
struct pio_packet *pkt = (struct pio_packet *)p;
|
||||
return (pkt->pkt_len);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -87,16 +87,16 @@ int pio_pcap_live_device_open(struct packet_io_device *pdev);
|
||||
*/
|
||||
int pio_pcap_live_device_close(struct packet_io_device *pdev);
|
||||
|
||||
int pio_pcap_live_device_receive(struct packet_io_device *pdev, uint32_t rxq_id, struct packet **pkts, int nr_pkts);
|
||||
int pio_pcap_live_device_receive(struct packet_io_device *pdev, uint32_t rxq_id, struct stellar_packet **pkts, int nr_pkts);
|
||||
|
||||
int pio_pcap_live_device_send(struct packet_io_device *pdev, uint32_t txq_id, struct packet **pkts, int nr_pkts);
|
||||
int pio_pcap_live_device_send(struct packet_io_device *pdev, uint32_t txq_id, struct stellar_packet **pkts, int nr_pkts);
|
||||
|
||||
void pio_pcap_live_device_pkt_free(struct packet_io_device *pdev, uint32_t qid, struct packet **pkts, int nr_pkts);
|
||||
void pio_pcap_live_device_pkt_free(struct packet_io_device *pdev, uint32_t qid, struct stellar_packet **pkts, int nr_pkts);
|
||||
|
||||
void *pio_pcap_live_device_buff_ctrlzone(struct packet *p);
|
||||
void *pio_pcap_live_device_buff_ctrlzone(struct stellar_packet *p);
|
||||
|
||||
char *pio_pcap_live_device_buff_mtod(struct packet *p);
|
||||
char *pio_pcap_live_device_buff_mtod(struct stellar_packet *p);
|
||||
|
||||
uint32_t pio_pcap_live_device_buff_buflen(struct packet *p);
|
||||
uint32_t pio_pcap_live_device_buff_buflen(struct stellar_packet *p);
|
||||
|
||||
uint32_t pio_pcap_live_device_buff_datalen(struct packet *p);
|
||||
uint32_t pio_pcap_live_device_buff_datalen(struct stellar_packet *p);
|
||||
@@ -4,7 +4,7 @@ add_executable(gtest_packet_io
|
||||
|
||||
target_link_libraries(
|
||||
gtest_packet_io
|
||||
gtest_main
|
||||
gtest
|
||||
packet_io
|
||||
dl
|
||||
pcap
|
||||
|
||||
@@ -1,17 +1,15 @@
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "../packet_io.h"
|
||||
#include "packet_io.h"
|
||||
|
||||
TEST(PACKET_IO_Test, packet_io_instance_create) {
|
||||
struct packet_io_config ppio_config;
|
||||
struct packet_io_instance *ppio_inst = packet_io_instance_create("stellar", PACKET_IO_RUN_MODE_PCAP_FILE);
|
||||
EXPECT_NE(ppio_inst, nullptr);
|
||||
}
|
||||
|
||||
TEST(PACKET_IO_Test, packet_io_open_device) {
|
||||
struct packet_io_config ppio_config;
|
||||
struct packet_io_instance *ppio_inst = packet_io_instance_create("stellar", PACKET_IO_RUN_MODE_PCAP_FILE);
|
||||
EXPECT_EQ(packet_io_device_open(ppio_inst, nullptr, 1, 1), nullptr);
|
||||
EXPECT_EQ(packet_io_device_open(ppio_inst, NULL, 1, 1), nullptr);
|
||||
}
|
||||
|
||||
int main(int argc, char ** argv)
|
||||
|
||||
@@ -1,4 +1,10 @@
|
||||
include_directories(${CMAKE_SOURCE_DIR}/session_manager/)
|
||||
add_library(plugin_manager
|
||||
plugin_manager.cpp
|
||||
)
|
||||
add_library(plugin_manager
|
||||
plugin_manager_config.cpp
|
||||
plugin_manager_module.cpp
|
||||
plugin_manager_util.cpp
|
||||
plugin_manager.cpp
|
||||
)
|
||||
|
||||
target_include_directories(plugin_manager PUBLIC ${CMAKE_SOURCE_DIR})
|
||||
|
||||
add_subdirectory(test)
|
||||
@@ -1,60 +1,547 @@
|
||||
#include "plugin.h"
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "uthash/uthash.h"
|
||||
|
||||
#include "session_manager.h"
|
||||
#include "plugin_manager_module.h"
|
||||
|
||||
#include "utils.h"
|
||||
/******************************************************************************
|
||||
* CallBack Runtime (For Per Session)
|
||||
******************************************************************************/
|
||||
|
||||
struct session_event_callback
|
||||
enum plugin_status
|
||||
{
|
||||
const char *session_name;
|
||||
fn_session_event_callback callback;
|
||||
TAILQ_ENTRY(session_event_callback) session_event_cb_tq_entries;
|
||||
UT_hash_handle hh;
|
||||
PLUGIN_STATUS_NORMAL = 0x00,
|
||||
PLUGIN_STATUS_DETTACH_ME = 0x01,
|
||||
PLUGIN_STATUS_TAKEN_OVER = 0x02, // Noitce: this is taken over not take over
|
||||
};
|
||||
|
||||
TAILQ_HEAD(session_event_callback_list, session_event_callback);
|
||||
|
||||
struct session_event_callback_map
|
||||
struct callback_runtime
|
||||
{
|
||||
struct session_event_callback_list session_ev_cb_list;
|
||||
UT_hash_handle hh;
|
||||
void *cb_args;
|
||||
fn_session_event_callback *event_cb;
|
||||
|
||||
enum session_event_type event;
|
||||
enum plugin_status status;
|
||||
int is_be_called;
|
||||
};
|
||||
|
||||
struct session_plugin_ctx
|
||||
{
|
||||
int callback_index;
|
||||
int callback_num;
|
||||
struct callback_runtime *callbacks;
|
||||
};
|
||||
|
||||
/******************************************************************************
|
||||
* CallBack Static (For Per Plugin Manager)
|
||||
******************************************************************************/
|
||||
|
||||
struct callback_static
|
||||
{
|
||||
enum session_event_type event;
|
||||
fn_session_event_callback *event_cb;
|
||||
};
|
||||
|
||||
struct plugin_manager_eventcb
|
||||
{
|
||||
char session_name[MAX_SESSION_NAME_LENGTH]; // key
|
||||
|
||||
int callback_num; // val size
|
||||
struct callback_static *callbacks; // val: dynamic array
|
||||
|
||||
UT_hash_handle hh;
|
||||
};
|
||||
|
||||
/******************************************************************************
|
||||
* Struct plugin_manager
|
||||
******************************************************************************/
|
||||
|
||||
struct plugin_manager
|
||||
{
|
||||
struct session_event_callback_list fixed_event_cbs[SESSION_TYPE_MAX];
|
||||
struct session_event_callback_map *session_ev_cb_map;
|
||||
int used_module_num;
|
||||
int used_config_num;
|
||||
int used_evencb_num; // only plugin register eventcb numbers
|
||||
|
||||
struct plugin_manager_module *modules[MAX_PLUGIN_NUM];
|
||||
struct plugin_manager_config *configs[MAX_PLUGIN_NUM];
|
||||
struct plugin_manager_eventcb *evcb_htable;
|
||||
};
|
||||
|
||||
struct plugin_manager g_plug_mgr;
|
||||
/******************************************************************************
|
||||
* Create/Destory plugin ctx (per session)
|
||||
******************************************************************************/
|
||||
|
||||
void plugin_manager_dispatch(struct session_event *event)
|
||||
static struct session_plugin_ctx *plugin_manager_create_plugin_ctx(struct plugin_manager *plug_mgr, const char *session_name)
|
||||
{
|
||||
struct session *s = container_of(event, struct session, cur_ev);
|
||||
struct session_event_callback_map *t_map;
|
||||
struct session_event_callback *session_ev_cb;
|
||||
HASH_FIND(hh, g_plug_mgr.session_ev_cb_map, s->name, strlen(s->name), t_map);
|
||||
if(!t_map) return;
|
||||
switch (s->state)
|
||||
if (session_name == NULL || strlen(session_name) == 0)
|
||||
{
|
||||
case SESSION_EVENT_OPENING:
|
||||
TAILQ_FOREACH(session_ev_cb, &t_map->session_ev_cb_list, session_event_cb_tq_entries)
|
||||
{
|
||||
struct session_event *ev = CALLOC(struct session_event, 1);
|
||||
ev->callback = session_ev_cb->callback;
|
||||
ev->callback(s, SESSION_EVENT_OPENING, NULL, NULL, 0, &ev->cb_pme);
|
||||
if(ev->state == 1)
|
||||
{
|
||||
TAILQ_INSERT_TAIL(&s->ev_list, ev, session_event_tq_entries);
|
||||
}
|
||||
else
|
||||
{
|
||||
FREE(ev);// TODO;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
plugin_manager_log(ERROR, "invalid parameter, session name is empty");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
struct plugin_manager_eventcb *elem;
|
||||
HASH_FIND_STR(plug_mgr->evcb_htable, session_name, elem);
|
||||
if (elem == NULL)
|
||||
{
|
||||
plugin_manager_log(ERROR, "can't find event callback for session name '%s'", session_name);
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
struct session_plugin_ctx *plug_ctx = safe_alloc(struct session_plugin_ctx, 1);
|
||||
plug_ctx->callback_num = elem->callback_num;
|
||||
plug_ctx->callbacks = safe_alloc(struct callback_runtime, plug_ctx->callback_num);
|
||||
|
||||
for (int i = 0; i < plug_ctx->callback_num; i++)
|
||||
{
|
||||
plug_ctx->callbacks[i].is_be_called = 0;
|
||||
plug_ctx->callbacks[i].status = PLUGIN_STATUS_NORMAL;
|
||||
plug_ctx->callbacks[i].event = elem->callbacks[i].event;
|
||||
plug_ctx->callbacks[i].event_cb = elem->callbacks[i].event_cb;
|
||||
plug_ctx->callbacks[i].cb_args = NULL;
|
||||
}
|
||||
|
||||
return plug_ctx;
|
||||
}
|
||||
}
|
||||
|
||||
static void plugin_manager_destory_plugin_ctx(struct session_plugin_ctx *plug_ctx)
|
||||
{
|
||||
if (plug_ctx)
|
||||
{
|
||||
safe_free(plug_ctx->callbacks);
|
||||
safe_free(plug_ctx);
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* Tools for managing plugins
|
||||
******************************************************************************/
|
||||
|
||||
static int plugin_manager_parse_plugins(struct plugin_manager *plug_mgr, const char *file)
|
||||
{
|
||||
char line_buffer[4096] = {0};
|
||||
|
||||
if (strlen(file) <= 0)
|
||||
{
|
||||
plugin_manager_log(ERROR, "Invalid parameter, plugin config file name cannot be empty");
|
||||
return -1;
|
||||
}
|
||||
|
||||
FILE *fp = fopen(file, "r");
|
||||
if (fp == NULL)
|
||||
{
|
||||
plugin_manager_log(ERROR, "can't open %s, %s", file, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
while (fgets(line_buffer, sizeof(line_buffer), fp))
|
||||
{
|
||||
if ('#' == line_buffer[0] || '\n' == line_buffer[0])
|
||||
{
|
||||
memset(line_buffer, 0, sizeof(line_buffer));
|
||||
continue;
|
||||
}
|
||||
line_buffer[strcspn(line_buffer, "\r\n")] = 0;
|
||||
|
||||
if (plug_mgr->used_config_num >= MAX_PLUGIN_NUM)
|
||||
{
|
||||
plugin_manager_log(ERROR, "the number of registered plugins exceeds the limit and cannot exceed %d", MAX_PLUGIN_NUM);
|
||||
goto err;
|
||||
}
|
||||
|
||||
struct plugin_manager_config *config = plugin_mangager_config_create();
|
||||
if (plugin_mangager_config_parse(config, line_buffer) == -1)
|
||||
{
|
||||
plugin_mangager_config_destory(config);
|
||||
goto err;
|
||||
}
|
||||
|
||||
plug_mgr->configs[plug_mgr->used_config_num] = config;
|
||||
plug_mgr->used_config_num++;
|
||||
memset(line_buffer, 0, sizeof(line_buffer));
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
|
||||
return 0;
|
||||
|
||||
err:
|
||||
|
||||
if (fp)
|
||||
{
|
||||
fclose(fp);
|
||||
fp = NULL;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int plugin_manager_open_plugins(struct plugin_manager *plug_mgr)
|
||||
{
|
||||
for (int i = 0; i < plug_mgr->used_config_num; i++)
|
||||
{
|
||||
struct plugin_manager_config *config = plug_mgr->configs[i];
|
||||
struct plugin_manager_module *module = plugin_manager_module_open(config);
|
||||
if (module == NULL)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
plugin_manager_module_dump(module, config);
|
||||
|
||||
plug_mgr->modules[plug_mgr->used_module_num] = module;
|
||||
plug_mgr->used_module_num++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int plugin_manager_register_plugins(struct plugin_manager *plug_mgr)
|
||||
{
|
||||
for (int i = 0; i < plug_mgr->used_module_num; i++)
|
||||
{
|
||||
struct plugin_manager_module *module = plug_mgr->modules[i];
|
||||
if (plugin_manager_module_register(plug_mgr, module) == -1)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
plug_mgr->used_evencb_num++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int plugin_manager_init_plugins(struct plugin_manager *plug_mgr)
|
||||
{
|
||||
for (int i = 0; i < plug_mgr->used_module_num; i++)
|
||||
{
|
||||
struct plugin_manager_module *module = plug_mgr->modules[i];
|
||||
if (plugin_manager_module_init(module) == -1)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
double percentage = ((double)(i + 1)) / ((double)plug_mgr->used_module_num) * ((double)100);
|
||||
plugin_manager_log(INFO, "Plugin initialization progress: [%.2f%%]", percentage);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void plugin_manager_exit_plugins(struct plugin_manager *plug_mgr)
|
||||
{
|
||||
if (plug_mgr && plug_mgr->used_module_num)
|
||||
{
|
||||
for (int i = 0; i < plug_mgr->used_module_num; i++)
|
||||
{
|
||||
struct plugin_manager_module *module = plug_mgr->modules[i];
|
||||
plugin_manager_module_exit(module);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void plugin_manager_close_plugins(struct plugin_manager *plug_mgr)
|
||||
{
|
||||
if (plug_mgr && plug_mgr->used_module_num)
|
||||
{
|
||||
for (int i = 0; i < plug_mgr->used_module_num; i++)
|
||||
{
|
||||
struct plugin_manager_module *module = plug_mgr->modules[i];
|
||||
plugin_manager_module_close(module);
|
||||
}
|
||||
plug_mgr->used_module_num = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// deparse for destory parse
|
||||
static void plugin_manager_deparse_plugins(struct plugin_manager *plug_mgr)
|
||||
{
|
||||
if (plug_mgr && plug_mgr->used_config_num)
|
||||
{
|
||||
for (int i = 0; i < plug_mgr->used_config_num; i++)
|
||||
{
|
||||
struct plugin_manager_config *config = plug_mgr->configs[i];
|
||||
plugin_mangager_config_destory(config);
|
||||
}
|
||||
plug_mgr->used_config_num = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* Public API for managing plugins
|
||||
******************************************************************************/
|
||||
|
||||
int plugin_manager_load(struct plugin_manager *plug_mgr, const char *file)
|
||||
{
|
||||
if (plugin_manager_parse_plugins(plug_mgr, file) == -1)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (plugin_manager_open_plugins(plug_mgr) == -1)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (plugin_manager_register_plugins(plug_mgr) == -1)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (plugin_manager_init_plugins(plug_mgr) == -1)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void plugin_manager_unload(struct plugin_manager *plug_mgr)
|
||||
{
|
||||
plugin_manager_exit_plugins(plug_mgr);
|
||||
plugin_manager_close_plugins(plug_mgr);
|
||||
plugin_manager_deparse_plugins(plug_mgr);
|
||||
}
|
||||
|
||||
struct plugin_manager *plugin_manager_create()
|
||||
{
|
||||
struct plugin_manager *plug_mgr = safe_alloc(struct plugin_manager, 1);
|
||||
|
||||
plug_mgr->used_module_num = 0;
|
||||
plug_mgr->used_config_num = 0;
|
||||
plug_mgr->used_evencb_num = 0;
|
||||
|
||||
plug_mgr->evcb_htable = NULL;
|
||||
|
||||
return plug_mgr;
|
||||
}
|
||||
|
||||
void plugin_manager_destory(struct plugin_manager *plug_mgr)
|
||||
{
|
||||
if (plug_mgr)
|
||||
{
|
||||
if (plug_mgr->evcb_htable)
|
||||
{
|
||||
struct plugin_manager_eventcb *elem;
|
||||
struct plugin_manager_eventcb *tmp;
|
||||
HASH_ITER(hh, plug_mgr->evcb_htable, elem, tmp)
|
||||
{
|
||||
HASH_DEL(plug_mgr->evcb_htable, elem);
|
||||
|
||||
safe_free(elem->callbacks);
|
||||
safe_free(elem);
|
||||
}
|
||||
|
||||
plug_mgr->evcb_htable = NULL;
|
||||
plug_mgr->used_evencb_num = 0;
|
||||
}
|
||||
|
||||
plugin_manager_unload(plug_mgr);
|
||||
safe_free(plug_mgr);
|
||||
}
|
||||
}
|
||||
|
||||
int plugin_manager_register(struct plugin_manager *plug_mgr, const char *session_name, enum session_event_type event, fn_session_event_callback *event_cb)
|
||||
{
|
||||
if (strlen(session_name) <= 0)
|
||||
{
|
||||
plugin_manager_log(ERROR, "invalid parameter, session name is empty");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (strlen(session_name) > MAX_SESSION_NAME_LENGTH)
|
||||
{
|
||||
plugin_manager_log(ERROR, "invalid parameter, session name '%s' is too long and exceeds '%d' bytes", session_name, MAX_SESSION_NAME_LENGTH);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (event_cb == NULL)
|
||||
{
|
||||
plugin_manager_log(ERROR, "invalid parameter, the event callback corresponding to the session name '%s' is null", session_name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
struct plugin_manager_eventcb *elem;
|
||||
HASH_FIND_STR(plug_mgr->evcb_htable, session_name, elem);
|
||||
// session_name exists, add a new cb to the end of the callbacks dynamic array
|
||||
if (elem)
|
||||
{
|
||||
elem->callbacks = (struct callback_static *)realloc(elem->callbacks, (elem->callback_num + 1) * sizeof(struct callback_static));
|
||||
|
||||
elem->callbacks[elem->callback_num].event = event;
|
||||
elem->callbacks[elem->callback_num].event_cb = event_cb;
|
||||
|
||||
elem->callback_num++;
|
||||
}
|
||||
// session_name does not exist, allocate a new node elem, and add elem to the hash table
|
||||
else
|
||||
{
|
||||
elem = safe_alloc(struct plugin_manager_eventcb, 1);
|
||||
memcpy(elem->session_name, session_name, strlen(session_name));
|
||||
|
||||
elem->callbacks = (struct callback_static *)realloc(elem->callbacks, (elem->callback_num + 1) * sizeof(struct callback_static));
|
||||
|
||||
elem->callbacks[elem->callback_num].event = event;
|
||||
elem->callbacks[elem->callback_num].event_cb = event_cb;
|
||||
|
||||
elem->callback_num++;
|
||||
|
||||
HASH_ADD_STR(plug_mgr->evcb_htable, session_name, elem);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void plugin_manager_dispatch(struct plugin_manager *plug_mgr, struct stellar_event *event)
|
||||
{
|
||||
const struct stellar_session *seesion = stellar_event_get_session(event);
|
||||
struct session_plugin_ctx *plug_ctx = stellar_event_get_plugin_ctx(event);
|
||||
enum session_event_type event_type = stellar_event_get_type(event);
|
||||
const char *session_name = stellar_event_get_session_name(event);
|
||||
struct stellar_packet *packet = stellar_event_get_packet(event);
|
||||
uint16_t payload_len = stellar_event_get_payload_length(event);
|
||||
const char *payload = stellar_event_get_payload(event);
|
||||
|
||||
assert(seesion);
|
||||
assert(session_name);
|
||||
|
||||
char event_str_buffer[1024] = {0};
|
||||
session_event_type_int2str(event_type, event_str_buffer, 1024);
|
||||
|
||||
// the same session may trigger multi times opening events
|
||||
if (event_type & SESSION_EVENT_OPENING)
|
||||
{
|
||||
if (plug_ctx == NULL)
|
||||
{
|
||||
plug_ctx = plugin_manager_create_plugin_ctx(plug_mgr, session_name);
|
||||
if (plug_ctx == NULL)
|
||||
{
|
||||
plugin_manager_log(ERROR, "can't create runtime plugin ctx for session '%s', Please check whether the callback is registered in the current session", session_name);
|
||||
return;
|
||||
}
|
||||
stellar_event_set_plugin_ctx(event, plug_ctx);
|
||||
}
|
||||
}
|
||||
|
||||
if (plug_ctx)
|
||||
{
|
||||
for (int i = 0; i < plug_ctx->callback_num; i++)
|
||||
{
|
||||
struct callback_runtime *runtime = &plug_ctx->callbacks[i];
|
||||
|
||||
if (runtime->status == PLUGIN_STATUS_DETTACH_ME)
|
||||
{
|
||||
plugin_manager_log(DEBUG, "dispatch, skip event_cb: %p, plugin status: 'dettach me', session: %s, event: (%d, %s)", runtime->event_cb, session_name, event_type, event_str_buffer);
|
||||
continue;
|
||||
}
|
||||
else if (runtime->status == PLUGIN_STATUS_TAKEN_OVER)
|
||||
{
|
||||
if ((event_type & SESSION_EVENT_CLOSING) && (runtime->event & SESSION_EVENT_CLOSING) && runtime->is_be_called)
|
||||
{
|
||||
plug_ctx->callback_index = i;
|
||||
plugin_manager_log(DEBUG, "dispatch, run event_cb: %p, plugin status: 'taken over', session: %s, event: (%d, %s)", runtime->event_cb, session_name, event_type, event_str_buffer);
|
||||
runtime->event_cb(seesion, SESSION_EVENT_CLOSING, packet, payload, payload_len, &runtime->cb_args);
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
plugin_manager_log(DEBUG, "dispatch, skip event_cb: %p, plugin status: 'taken over', session: %s, event: (%d, %s)", runtime->event_cb, session_name, event_type, event_str_buffer);
|
||||
}
|
||||
}
|
||||
else if (runtime->status == PLUGIN_STATUS_NORMAL)
|
||||
{
|
||||
if (runtime->event & event_type)
|
||||
{
|
||||
plug_ctx->callback_index = i;
|
||||
plugin_manager_log(DEBUG, "dispatch, run event_cb: %p, plugin status: 'normal', session: %s, event: (%d, %s)", runtime->event_cb, session_name, event_type, event_str_buffer);
|
||||
runtime->event_cb(seesion, event_type, packet, payload, payload_len, &runtime->cb_args);
|
||||
runtime->is_be_called = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
plugin_manager_log(DEBUG, "dispatch, skip event_cb: %p, plugin status: 'normal', session: %s, event: (%d, %s)", runtime->event_cb, session_name, event_type, event_str_buffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
plugin_manager_log(ERROR, "session '%s' runtime plugin ctx is null when running event callback", session_name);
|
||||
abort();
|
||||
}
|
||||
|
||||
if (event_type & SESSION_EVENT_CLOSING)
|
||||
{
|
||||
plugin_manager_destory_plugin_ctx(plug_ctx);
|
||||
stellar_event_set_plugin_ctx(event, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* Public API For Plugin
|
||||
******************************************************************************/
|
||||
|
||||
/*
|
||||
* pm_session_dettach_me just sets the flag to disable this plugin and no longer call this event callback.
|
||||
* Before calling pm_session_dettach_me, the current plugin must release related resources for the current session.
|
||||
*/
|
||||
void pm_session_dettach_me(const struct stellar_session *session)
|
||||
{
|
||||
struct session_plugin_ctx *plugin_ctx = stellar_session_get_plugin_ctx(session);
|
||||
assert(plugin_ctx);
|
||||
struct callback_runtime *runtime_me = &plugin_ctx->callbacks[plugin_ctx->callback_index];
|
||||
|
||||
runtime_me->status = PLUGIN_STATUS_DETTACH_ME;
|
||||
plugin_manager_log(DEBUG, "%p dettach me, disable event_cb: %p, session: %s", runtime_me->event_cb, runtime_me->event_cb, stellar_session_get_name(session));
|
||||
}
|
||||
|
||||
/*
|
||||
* The current plugin(cb2) takes over the current session, the pm_session_take_over setting flag disables other plugins,
|
||||
* and the current session does not call other plugins except for the SESSION_EVENT_CLOSING event.
|
||||
*
|
||||
* +-----+ +-----+ +-----+ +-----+
|
||||
* Plugin runtime callback list: | cb1 |-->| cb2 |-->| cb3 |-->| cb4 |
|
||||
* +-----+ +-----+ +-----+ +-----+
|
||||
* /|\
|
||||
* |
|
||||
* plugin cb2 run pm_session_take_over
|
||||
*
|
||||
* A plugin(cb1/cb3/cb4) that is taken over, if the plugin was called before being taken over and has a registered SESSION_EVENT_CLOSING event,
|
||||
* it will be called again when the SESSION_EVENT_CLOSING event comes. Otherwise, the plugin will not be called.
|
||||
*/
|
||||
void pm_session_take_over(const struct stellar_session *session)
|
||||
{
|
||||
struct session_plugin_ctx *plugin_ctx = stellar_session_get_plugin_ctx(session);
|
||||
assert(plugin_ctx);
|
||||
struct callback_runtime *runtime_me = &plugin_ctx->callbacks[plugin_ctx->callback_index];
|
||||
|
||||
for (int i = 0; i < plugin_ctx->callback_num; i++)
|
||||
{
|
||||
if (i != plugin_ctx->callback_index)
|
||||
{
|
||||
struct callback_runtime *runtime_other = &plugin_ctx->callbacks[i];
|
||||
runtime_other->status = PLUGIN_STATUS_TAKEN_OVER;
|
||||
plugin_manager_log(DEBUG, "%p take over, disable event_cb: %p, session: %s", runtime_me->event_cb, runtime_other->event_cb, stellar_session_get_name(session));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* Util For Gtest
|
||||
******************************************************************************/
|
||||
|
||||
void *pm_session_get_plugin_pme(const struct stellar_session *session)
|
||||
{
|
||||
struct session_plugin_ctx *plugin_ctx = stellar_session_get_plugin_ctx(session);
|
||||
assert(plugin_ctx);
|
||||
struct callback_runtime *runtime_me = &plugin_ctx->callbacks[plugin_ctx->callback_index];
|
||||
|
||||
return runtime_me->cb_args;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* Suppport LUA plugins
|
||||
******************************************************************************/
|
||||
|
||||
// TODO
|
||||
@@ -1,6 +1,29 @@
|
||||
#ifndef _PLUGIN_MANAGER_H
|
||||
#define _PLUGIN_MANAGER_H
|
||||
|
||||
#pragma once
|
||||
#ifdef __cpluscplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
#include "plugin.h"
|
||||
#include "sdk/include/session.h"
|
||||
|
||||
void plugin_manager_dispatch(struct session_event *event);
|
||||
struct plugin_manager;
|
||||
|
||||
struct plugin_manager *plugin_manager_create();
|
||||
void plugin_manager_destory(struct plugin_manager *plug_mgr);
|
||||
|
||||
int plugin_manager_load(struct plugin_manager *plug_mgr, const char *file);
|
||||
void plugin_manager_unload(struct plugin_manager *plug_mgr);
|
||||
|
||||
int plugin_manager_register(struct plugin_manager *plug_mgr, const char *session_name, enum session_event_type event, fn_session_event_callback *event_cb);
|
||||
void plugin_manager_dispatch(struct plugin_manager *plug_mgr, struct stellar_event *event);
|
||||
|
||||
// only use for gtest
|
||||
void *pm_session_get_plugin_pme(const struct stellar_session *session);
|
||||
|
||||
#ifdef __cpluscplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
281
src/plugin_manager/plugin_manager_config.cpp
Normal file
281
src/plugin_manager/plugin_manager_config.cpp
Normal file
@@ -0,0 +1,281 @@
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "toml/toml.h"
|
||||
|
||||
#include "plugin_manager_config.h"
|
||||
|
||||
/******************************************************************************
|
||||
* Private API (For Parse)
|
||||
******************************************************************************/
|
||||
|
||||
static int toml_parse_string(toml_table_t *table, const char *string_key, const char *file, char **out)
|
||||
{
|
||||
toml_datum_t string_val = toml_string_in(table, string_key);
|
||||
if (!string_val.ok)
|
||||
{
|
||||
plugin_manager_log(ERROR, "can't find '%s' configuration iterm in %s", string_key, file);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (strlen(string_val.u.s) <= 0)
|
||||
{
|
||||
plugin_manager_log(ERROR, "invalid value for '%s' configuration item in %s", string_key, file);
|
||||
safe_free(string_val.u.s);
|
||||
return -1;
|
||||
}
|
||||
|
||||
*out = safe_dup(string_val.u.s);
|
||||
safe_free(string_val.u.s);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int toml_parse_table(toml_table_t *table, const char *string_key, const char *file, toml_table_t **out)
|
||||
{
|
||||
*out = toml_table_in(table, string_key);
|
||||
if (*out == NULL)
|
||||
{
|
||||
plugin_manager_log(ERROR, "can't find '%s' section in %s", string_key, file);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int toml_parse_plugin_section(toml_table_t *root, struct plugin_manager_config *config, const char *file)
|
||||
{
|
||||
toml_table_t *plugin_section = NULL;
|
||||
|
||||
if (toml_parse_table(root, "PLUGINFO", file, &plugin_section) == -1)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (toml_parse_string(plugin_section, "INIT_FUNC", file, &config->plugin_section.init_func_name) == -1)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (toml_parse_string(plugin_section, "EXIT_FUNC", file, &config->plugin_section.exit_func_name) == -1)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (toml_parse_string(plugin_section, "LIBRARY_PATH", file, &config->plugin_section.lib_path) == -1)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int toml_parse_session_section(toml_table_t *root, struct plugin_manager_config *config, const char *file)
|
||||
{
|
||||
toml_table_t *session_section = NULL;
|
||||
toml_table_t *sub_session_section = NULL;
|
||||
const char *session_name = NULL;
|
||||
toml_array_t *event_type_array = NULL;
|
||||
toml_datum_t type_str;
|
||||
enum session_event_type type_int;
|
||||
|
||||
if (toml_parse_table(root, "SESSION_NAME", file, &session_section) == -1)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (int i = 0; i < toml_table_ntab(session_section); i++)
|
||||
{
|
||||
session_name = NULL;
|
||||
sub_session_section = NULL;
|
||||
event_type_array = NULL;
|
||||
|
||||
config->session_section = (struct session_section_config *)realloc(config->session_section, sizeof(struct session_section_config) * (config->session_section_num + 1));
|
||||
config->session_section[config->session_section_num].event = SESSION_EVENT_UNKNOWN;
|
||||
config->session_section[config->session_section_num].cb_func_name = NULL;
|
||||
memset(config->session_section[config->session_section_num].session_name, 0, MAX_SESSION_NAME_LENGTH);
|
||||
|
||||
// parse session name
|
||||
session_name = toml_key_in(session_section, i);
|
||||
int session_name_len = strlen(session_name);
|
||||
if (session_name_len <= 0)
|
||||
{
|
||||
plugin_manager_log(ERROR, "invalid value for 'SESSION_NAME' configuration item in %s", file);
|
||||
return -1;
|
||||
}
|
||||
if (session_name_len > MAX_SESSION_NAME_LENGTH)
|
||||
{
|
||||
plugin_manager_log(ERROR, "invalid value for 'SESSION_NAME' configuration item in %s, '%s' is too long and exceeds %d bytes", file, session_name, MAX_SESSION_NAME_LENGTH);
|
||||
return -1;
|
||||
}
|
||||
if (toml_parse_table(session_section, session_name, file, &sub_session_section) == -1)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
strncpy(config->session_section[config->session_section_num].session_name, session_name, session_name_len);
|
||||
|
||||
// parse session event callback
|
||||
if (toml_parse_string(sub_session_section, "SESSION_EVENT_CALLBACK", file, &config->session_section[config->session_section_num].cb_func_name) == -1)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
event_type_array = toml_array_in(sub_session_section, "SESSION_EVENT_TYPE");
|
||||
if (event_type_array == NULL)
|
||||
{
|
||||
plugin_manager_log(ERROR, "can't find 'SESSION_EVENT_TYPE' configuration iterm in '[SESSION_NAME.%s]' section of %s", session_name, file);
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (int i = 0; i < toml_array_nelem(event_type_array); i++)
|
||||
{
|
||||
type_int = SESSION_EVENT_UNKNOWN;
|
||||
|
||||
type_str = toml_string_at(event_type_array, i);
|
||||
if (!type_str.ok)
|
||||
{
|
||||
plugin_manager_log(ERROR, "can't parse 'SESSION_EVENT_TYPE' configuration iterm in '[SESSION_NAME.%s]' section of %s", session_name, file);
|
||||
return -1;
|
||||
}
|
||||
|
||||
type_int = session_event_type_str2int(type_str.u.s);
|
||||
if (type_int == SESSION_EVENT_UNKNOWN)
|
||||
{
|
||||
plugin_manager_log(ERROR, "invalid value '%s' for 'SESSION_EVENT_TYPE' configuration item in '[SESSION_NAME.%s]' section of %s", type_str.u.s, session_name, file);
|
||||
safe_free(type_str.u.s);
|
||||
return -1;
|
||||
}
|
||||
|
||||
(config->session_section[config->session_section_num].event) = (enum session_event_type)((config->session_section[config->session_section_num].event) | type_int);
|
||||
safe_free(type_str.u.s);
|
||||
}
|
||||
if ((config->session_section[config->session_section_num].event & SESSION_EVENT_CLOSING) == 0)
|
||||
{
|
||||
plugin_manager_log(WARN, "can't find 'SESSION_EVENT_CLOSING' value for 'SESSION_EVENT_TYPE' configuration item in '[SESSION_NAME.%s]' section of %s", session_name, file);
|
||||
}
|
||||
|
||||
config->session_section_num++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* Public API
|
||||
******************************************************************************/
|
||||
|
||||
struct plugin_manager_config *plugin_mangager_config_create()
|
||||
{
|
||||
struct plugin_manager_config *config = safe_alloc(struct plugin_manager_config, 1);
|
||||
|
||||
config->file_path = NULL;
|
||||
config->session_section_num = 0;
|
||||
config->session_section = NULL;
|
||||
config->plugin_section.init_func_name = NULL;
|
||||
config->plugin_section.exit_func_name = NULL;
|
||||
config->plugin_section.lib_path = NULL;
|
||||
|
||||
return config;
|
||||
}
|
||||
|
||||
void plugin_mangager_config_destory(struct plugin_manager_config *config)
|
||||
{
|
||||
if (config)
|
||||
{
|
||||
safe_free(config->file_path);
|
||||
|
||||
safe_free(config->plugin_section.init_func_name);
|
||||
safe_free(config->plugin_section.exit_func_name);
|
||||
safe_free(config->plugin_section.lib_path);
|
||||
|
||||
if (config->session_section)
|
||||
{
|
||||
for (int i = 0; i < config->session_section_num; i++)
|
||||
{
|
||||
struct session_section_config *temp = &config->session_section[i];
|
||||
safe_free(temp->cb_func_name);
|
||||
}
|
||||
config->session_section_num = 0;
|
||||
safe_free(config->session_section);
|
||||
}
|
||||
|
||||
safe_free(config);
|
||||
}
|
||||
}
|
||||
|
||||
void plugin_mangager_config_dump(struct plugin_manager_config *config)
|
||||
{
|
||||
if (config)
|
||||
{
|
||||
plugin_manager_log(DEBUG, "[CONFIG_FILE] : %s", config->file_path);
|
||||
plugin_manager_log(DEBUG, "[PLUGINFO]->INIT_FUNC : %s", config->plugin_section.init_func_name);
|
||||
plugin_manager_log(DEBUG, "[PLUGINFO]->EXIT_FUNC : %s", config->plugin_section.exit_func_name);
|
||||
plugin_manager_log(DEBUG, "[PLUGINFO]->LIBRARY_PATH : %s", config->plugin_section.lib_path);
|
||||
|
||||
if (config->session_section)
|
||||
{
|
||||
for (int i = 0; i < config->session_section_num; i++)
|
||||
{
|
||||
char tmp_buffer[1024] = {0};
|
||||
struct session_section_config *temp = &config->session_section[i];
|
||||
session_event_type_int2str(temp->event, tmp_buffer, 1024);
|
||||
plugin_manager_log(DEBUG, "[SESSION_NAME.%s]->SESSION_EVENT_TYPE : %d, %s", temp->session_name, temp->event, tmp_buffer);
|
||||
plugin_manager_log(DEBUG, "[SESSION_NAME.%s]->SESSION_EVENT_CALLBACK : %s", temp->session_name, temp->cb_func_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int plugin_mangager_config_parse(struct plugin_manager_config *config, const char *file)
|
||||
{
|
||||
FILE *fp = NULL;
|
||||
toml_table_t *root = NULL;
|
||||
char errbuf[200] = {0};
|
||||
|
||||
config->file_path = safe_dup(file);
|
||||
|
||||
fp = fopen(config->file_path, "r");
|
||||
if (fp == NULL)
|
||||
{
|
||||
plugin_manager_log(ERROR, "can't open %s, %s", config->file_path, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
root = toml_parse_file(fp, errbuf, sizeof(errbuf));
|
||||
if (root == NULL)
|
||||
{
|
||||
plugin_manager_log(ERROR, "toml parsing %s failed, %s", file, errbuf);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (toml_parse_plugin_section(root, config, file) == -1)
|
||||
{
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (toml_parse_session_section(root, config, file) == -1)
|
||||
{
|
||||
goto err;
|
||||
}
|
||||
|
||||
toml_free(root);
|
||||
fclose(fp);
|
||||
|
||||
plugin_manager_log(INFO, "plugin config file '%s' parse success", config->file_path);
|
||||
|
||||
return 0;
|
||||
|
||||
err:
|
||||
if (root)
|
||||
{
|
||||
toml_free(root);
|
||||
}
|
||||
|
||||
if (fp)
|
||||
{
|
||||
fclose(fp);
|
||||
fp = NULL;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
45
src/plugin_manager/plugin_manager_config.h
Normal file
45
src/plugin_manager/plugin_manager_config.h
Normal file
@@ -0,0 +1,45 @@
|
||||
#ifndef _PLUGIN_MANAGER_CONFIG_H
|
||||
#define _PLUGIN_MANAGER_CONFIG_H
|
||||
|
||||
#ifdef __cpluscplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
#include "plugin_manager_util.h"
|
||||
#include "sdk/include/session.h"
|
||||
|
||||
struct session_section_config
|
||||
{
|
||||
char session_name[MAX_SESSION_NAME_LENGTH];
|
||||
char *cb_func_name;
|
||||
enum session_event_type event;
|
||||
};
|
||||
|
||||
struct plugin_section_config
|
||||
{
|
||||
char *init_func_name;
|
||||
char *exit_func_name;
|
||||
char *lib_path;
|
||||
};
|
||||
|
||||
struct plugin_manager_config
|
||||
{
|
||||
char *file_path;
|
||||
|
||||
int session_section_num;
|
||||
struct session_section_config *session_section; // array
|
||||
struct plugin_section_config plugin_section;
|
||||
};
|
||||
|
||||
struct plugin_manager_config *plugin_mangager_config_create();
|
||||
void plugin_mangager_config_destory(struct plugin_manager_config *config);
|
||||
|
||||
int plugin_mangager_config_parse(struct plugin_manager_config *config, const char *file);
|
||||
void plugin_mangager_config_dump(struct plugin_manager_config *config);
|
||||
|
||||
#ifdef __cpluscplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
193
src/plugin_manager/plugin_manager_module.cpp
Normal file
193
src/plugin_manager/plugin_manager_module.cpp
Normal file
@@ -0,0 +1,193 @@
|
||||
#include <time.h>
|
||||
#include <dlfcn.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "sdk/include/plugin.h"
|
||||
#include "plugin_manager_module.h"
|
||||
#include "plugin_manager.h"
|
||||
|
||||
struct plugin_manager_module_evcb
|
||||
{
|
||||
char session_name[MAX_SESSION_NAME_LENGTH];
|
||||
fn_session_event_callback *event_cb_ptr;
|
||||
enum session_event_type event;
|
||||
};
|
||||
|
||||
struct plugin_manager_module
|
||||
{
|
||||
char *lib_path;
|
||||
void *dl_handle;
|
||||
|
||||
plugin_init_callback *init_cb_ptr;
|
||||
plugin_exit_callback *exit_cb_ptr;
|
||||
|
||||
struct plugin_manager_module_evcb *evcbs;
|
||||
int evcbs_num;
|
||||
};
|
||||
|
||||
void plugin_manager_module_close(struct plugin_manager_module *module)
|
||||
{
|
||||
if (module)
|
||||
{
|
||||
if (module->exit_cb_ptr)
|
||||
{
|
||||
module->exit_cb_ptr();
|
||||
}
|
||||
|
||||
if (module->dl_handle)
|
||||
{
|
||||
dlclose(module->dl_handle);
|
||||
module->dl_handle = NULL;
|
||||
}
|
||||
|
||||
safe_free(module->lib_path);
|
||||
safe_free(module->evcbs);
|
||||
module->evcbs_num = 0;
|
||||
|
||||
safe_free(module);
|
||||
}
|
||||
}
|
||||
|
||||
struct plugin_manager_module *plugin_manager_module_open(struct plugin_manager_config *config)
|
||||
{
|
||||
if (config == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct plugin_manager_module *module = safe_alloc(struct plugin_manager_module, 1);
|
||||
|
||||
module->lib_path = safe_dup(config->plugin_section.lib_path);
|
||||
|
||||
// RTLD_NOW | RTLD_GLOBAL
|
||||
module->evcbs_num = 0;
|
||||
module->dl_handle = dlopen(module->lib_path, RTLD_NOW | RTLD_GLOBAL | RTLD_DEEPBIND);
|
||||
if (module->dl_handle == NULL)
|
||||
{
|
||||
plugin_manager_log(ERROR, "can't dlopen %s, %s", module->lib_path, dlerror());
|
||||
goto err;
|
||||
}
|
||||
|
||||
module->init_cb_ptr = (plugin_init_callback *)(dlsym(module->dl_handle, config->plugin_section.init_func_name));
|
||||
if (module->init_cb_ptr == NULL)
|
||||
{
|
||||
plugin_manager_log(ERROR, "can't find symbol name of '%s' in dynamic library %s, %s",
|
||||
config->plugin_section.init_func_name, module->lib_path, dlerror());
|
||||
goto err;
|
||||
}
|
||||
|
||||
module->exit_cb_ptr = (plugin_exit_callback *)(dlsym(module->dl_handle, config->plugin_section.exit_func_name));
|
||||
if (module->exit_cb_ptr == NULL)
|
||||
{
|
||||
plugin_manager_log(ERROR, "can't find symbol name of '%s' in dynamic library %s, %s",
|
||||
config->plugin_section.exit_func_name, module->lib_path, dlerror());
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (config->session_section)
|
||||
{
|
||||
module->evcbs = safe_alloc(struct plugin_manager_module_evcb, config->session_section_num);
|
||||
module->evcbs_num = config->session_section_num;
|
||||
|
||||
for (int i = 0; i < config->session_section_num; i++)
|
||||
{
|
||||
struct session_section_config *session_config = &config->session_section[i];
|
||||
struct plugin_manager_module_evcb *event_cb = &module->evcbs[i];
|
||||
|
||||
strncpy(event_cb->session_name, session_config->session_name, strlen(session_config->session_name));
|
||||
event_cb->event = session_config->event;
|
||||
event_cb->event_cb_ptr = (fn_session_event_callback *)(dlsym(module->dl_handle, session_config->cb_func_name));
|
||||
if (event_cb->event_cb_ptr == NULL)
|
||||
{
|
||||
plugin_manager_log(ERROR, "can't find symbol name of '%s' in dynamic library %s, %s",
|
||||
session_config->cb_func_name, module->lib_path, dlerror());
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
plugin_manager_log(INFO, "plugin dynamic library '%s' dlopen success", module->lib_path);
|
||||
|
||||
return module;
|
||||
|
||||
err:
|
||||
plugin_manager_module_close(module);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int plugin_manager_module_init(struct plugin_manager_module *module)
|
||||
{
|
||||
struct timespec start;
|
||||
struct timespec end;
|
||||
|
||||
clock_gettime(CLOCK_MONOTONIC, &start);
|
||||
int ret = module->init_cb_ptr();
|
||||
clock_gettime(CLOCK_MONOTONIC, &end);
|
||||
if (ret == -1)
|
||||
{
|
||||
plugin_manager_log(ERROR, "dynamic library '%s' initialization failed", module->lib_path);
|
||||
return -1;
|
||||
}
|
||||
|
||||
long long elapsed = (end.tv_sec - start.tv_sec) * 1000000 + (end.tv_nsec - start.tv_nsec) / 1000;
|
||||
plugin_manager_log(INFO, "plugin dynamic library '%s' init success, using '%lld' us", module->lib_path, elapsed);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void plugin_manager_module_exit(struct plugin_manager_module *module)
|
||||
{
|
||||
struct timespec start;
|
||||
struct timespec end;
|
||||
|
||||
if (module && module->exit_cb_ptr)
|
||||
{
|
||||
clock_gettime(CLOCK_MONOTONIC, &start);
|
||||
module->exit_cb_ptr();
|
||||
clock_gettime(CLOCK_MONOTONIC, &end);
|
||||
module->exit_cb_ptr = NULL;
|
||||
|
||||
long long elapsed = (end.tv_sec - start.tv_sec) * 1000000 + (end.tv_nsec - start.tv_nsec) / 1000;
|
||||
plugin_manager_log(INFO, "plugin dynamic library '%s' exit success, using '%lld' us", module->lib_path, elapsed);
|
||||
}
|
||||
}
|
||||
|
||||
int plugin_manager_module_register(struct plugin_manager *plug_mgr, struct plugin_manager_module *module)
|
||||
{
|
||||
if (module && module->evcbs)
|
||||
{
|
||||
for (int i = 0; i < module->evcbs_num; i++)
|
||||
{
|
||||
struct plugin_manager_module_evcb *event_cb = &module->evcbs[i];
|
||||
|
||||
if (plugin_manager_register(plug_mgr, event_cb->session_name, event_cb->event, event_cb->event_cb_ptr) == -1)
|
||||
{
|
||||
plugin_manager_log(ERROR, "dynamic library '%s' failed to register the event callback function of session '%s'", module->lib_path, event_cb->session_name);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void plugin_manager_module_dump(struct plugin_manager_module *module, struct plugin_manager_config *config)
|
||||
{
|
||||
if (module)
|
||||
{
|
||||
plugin_manager_log(DEBUG, "[LIBRARY] : %s, %p", config->plugin_section.lib_path, module->dl_handle);
|
||||
plugin_manager_log(DEBUG, "[INIT_FUNC] : %s, %p", config->plugin_section.init_func_name, module->init_cb_ptr);
|
||||
plugin_manager_log(DEBUG, "[EXIT_FUNC] : %s, %p", config->plugin_section.exit_func_name, module->exit_cb_ptr);
|
||||
|
||||
for (int i = 0; i < module->evcbs_num; i++)
|
||||
{
|
||||
struct session_section_config *session_config = &config->session_section[i];
|
||||
struct plugin_manager_module_evcb *event_cb = &module->evcbs[i];
|
||||
|
||||
char event_str_buffer[1024] = {0};
|
||||
session_event_type_int2str(event_cb->event, event_str_buffer, 1024);
|
||||
plugin_manager_log(DEBUG, "[EVENT_FUNC] : %s, %p, %s, (%d: %s)", session_config->cb_func_name, event_cb->event_cb_ptr, event_cb->session_name, event_cb->event, event_str_buffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
26
src/plugin_manager/plugin_manager_module.h
Normal file
26
src/plugin_manager/plugin_manager_module.h
Normal file
@@ -0,0 +1,26 @@
|
||||
#ifndef _PLUGIN_MANAGER_MODULE_H
|
||||
#define _PLUGIN_MANAGER_MODULE_H
|
||||
|
||||
#ifdef __cpluscplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
#include "plugin_manager_config.h"
|
||||
|
||||
struct plugin_manager_module;
|
||||
|
||||
struct plugin_manager_module *plugin_manager_module_open(struct plugin_manager_config *config);
|
||||
void plugin_manager_module_close(struct plugin_manager_module *module);
|
||||
|
||||
int plugin_manager_module_init(struct plugin_manager_module *module);
|
||||
void plugin_manager_module_exit(struct plugin_manager_module *module);
|
||||
|
||||
void plugin_manager_module_dump(struct plugin_manager_module *module, struct plugin_manager_config *config);
|
||||
int plugin_manager_module_register(struct plugin_manager *plug_mgr, struct plugin_manager_module *module);
|
||||
|
||||
#ifdef __cpluscplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
98
src/plugin_manager/plugin_manager_util.cpp
Normal file
98
src/plugin_manager/plugin_manager_util.cpp
Normal file
@@ -0,0 +1,98 @@
|
||||
#include <string.h>
|
||||
|
||||
#include "plugin_manager_util.h"
|
||||
|
||||
/******************************************************************************
|
||||
* Malloc
|
||||
******************************************************************************/
|
||||
|
||||
char *safe_dup(const char *str)
|
||||
{
|
||||
if (str == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char *dup = safe_alloc(char, strlen(str) + 1);
|
||||
memcpy(dup, str, strlen(str));
|
||||
|
||||
return dup;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* Session Event Type
|
||||
******************************************************************************/
|
||||
|
||||
struct event_type_map
|
||||
{
|
||||
const char *type_str;
|
||||
enum session_event_type type_int;
|
||||
};
|
||||
|
||||
static struct event_type_map evtype_map[] = {
|
||||
{"SESSION_EVENT_UNKNOWN", SESSION_EVENT_UNKNOWN},
|
||||
{"SESSION_EVENT_OPENING", SESSION_EVENT_OPENING},
|
||||
{"SESSION_EVENT_RAWPKT", SESSION_EVENT_RAWPKT},
|
||||
{"SESSION_EVENT_ORDPKT", SESSION_EVENT_ORDPKT},
|
||||
{"SESSION_EVENT_META", SESSION_EVENT_META},
|
||||
{"SESSION_EVENT_CLOSING", SESSION_EVENT_CLOSING},
|
||||
{"SESSION_EVENT_ALL", SESSION_EVENT_ALL},
|
||||
};
|
||||
|
||||
enum session_event_type session_event_type_str2int(const char *evtype_str)
|
||||
{
|
||||
enum session_event_type evtype_int = SESSION_EVENT_UNKNOWN;
|
||||
int num = sizeof(evtype_map) / sizeof(evtype_map[0]);
|
||||
|
||||
char *buffer = safe_dup(evtype_str);
|
||||
char *token = strtok(buffer, "|");
|
||||
while (token)
|
||||
{
|
||||
for (int i = 0; i < num; i++)
|
||||
{
|
||||
if (strcmp(token, evtype_map[i].type_str) == 0)
|
||||
{
|
||||
evtype_int = (enum session_event_type)(evtype_int | evtype_map[i].type_int);
|
||||
}
|
||||
}
|
||||
token = strtok(NULL, "|");
|
||||
}
|
||||
safe_free(buffer);
|
||||
|
||||
return evtype_int;
|
||||
}
|
||||
|
||||
void session_event_type_int2str(enum session_event_type evtype_int, char *buffer, int size)
|
||||
{
|
||||
int used = 0;
|
||||
int num = sizeof(evtype_map) / sizeof(evtype_map[0]);
|
||||
|
||||
if (evtype_int == SESSION_EVENT_UNKNOWN)
|
||||
{
|
||||
snprintf(buffer, size, "%s", "SESSION_EVENT_UNKNOWN");
|
||||
return;
|
||||
}
|
||||
|
||||
if (evtype_int == SESSION_EVENT_ALL)
|
||||
{
|
||||
snprintf(buffer, size, "%s", "SESSION_EVENT_ALL");
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < num; i++)
|
||||
{
|
||||
if (evtype_map[i].type_int & evtype_int)
|
||||
{
|
||||
if (evtype_map[i].type_int == SESSION_EVENT_ALL && evtype_int != SESSION_EVENT_ALL)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
used += snprintf(buffer + used, size - used, "%s|", evtype_map[i].type_str);
|
||||
}
|
||||
}
|
||||
|
||||
if (used)
|
||||
{
|
||||
buffer[used - 1] = '\0';
|
||||
}
|
||||
}
|
||||
82
src/plugin_manager/plugin_manager_util.h
Normal file
82
src/plugin_manager/plugin_manager_util.h
Normal file
@@ -0,0 +1,82 @@
|
||||
#ifndef _PLUGIN_MANAGER_UTIL_H
|
||||
#define _PLUGIN_MANAGER_UTIL_H
|
||||
|
||||
#ifdef __cpluscplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "sdk/include/session.h"
|
||||
|
||||
#define MAX_PLUGIN_NUM 512
|
||||
#define MAX_SESSION_NAME_LENGTH 32
|
||||
|
||||
/******************************************************************************
|
||||
* Malloc
|
||||
******************************************************************************/
|
||||
|
||||
#define safe_alloc(type, number) ((type *)calloc(number, sizeof(type)))
|
||||
|
||||
#define safe_free(ptr) \
|
||||
{ \
|
||||
if (ptr) \
|
||||
{ \
|
||||
free(ptr); \
|
||||
ptr = NULL; \
|
||||
} \
|
||||
}
|
||||
|
||||
char *safe_dup(const char *str);
|
||||
|
||||
/******************************************************************************
|
||||
* Logger
|
||||
******************************************************************************/
|
||||
|
||||
enum plugin_manager_log_level
|
||||
{
|
||||
DEBUG = 0x11,
|
||||
WARN = 0x12,
|
||||
INFO = 0x13,
|
||||
ERROR = 0x14,
|
||||
};
|
||||
|
||||
#ifndef plugin_manager_log
|
||||
#define plugin_manager_log(level, format, ...) \
|
||||
{ \
|
||||
switch (level) \
|
||||
{ \
|
||||
case DEBUG: \
|
||||
fprintf(stdout, "PLUGIN_MANAGER [DEBUG] " format "\n", ##__VA_ARGS__); \
|
||||
fflush(stdout); \
|
||||
break; \
|
||||
case WARN: \
|
||||
fprintf(stdout, "PLUGIN_MANAGER [WARN] " format "\n", ##__VA_ARGS__); \
|
||||
fflush(stdout); \
|
||||
break; \
|
||||
case INFO: \
|
||||
fprintf(stdout, "PLUGIN_MANAGER [INFO] " format "\n", ##__VA_ARGS__); \
|
||||
fflush(stdout); \
|
||||
break; \
|
||||
case ERROR: \
|
||||
fprintf(stderr, "PLUGIN_MANAGER [ERROR] " format "\n", ##__VA_ARGS__); \
|
||||
fflush(stderr); \
|
||||
break; \
|
||||
} \
|
||||
}
|
||||
#endif
|
||||
|
||||
/******************************************************************************
|
||||
* Session Event Type
|
||||
******************************************************************************/
|
||||
|
||||
enum session_event_type session_event_type_str2int(const char *evtype_str);
|
||||
void session_event_type_int2str(enum session_event_type evtype_int, char *buffer, int size);
|
||||
|
||||
#ifdef __cpluscplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
21
src/plugin_manager/test/CMakeLists.txt
Normal file
21
src/plugin_manager/test/CMakeLists.txt
Normal file
@@ -0,0 +1,21 @@
|
||||
add_executable(gtest_plugin_manager
|
||||
gtest_plugin_manager.cpp
|
||||
)
|
||||
|
||||
target_link_libraries(
|
||||
gtest_plugin_manager
|
||||
gtest
|
||||
plugin_manager
|
||||
session_manager
|
||||
toml
|
||||
dl
|
||||
)
|
||||
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wl,--export-dynamic")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wl,--export-dynamic")
|
||||
|
||||
include(GoogleTest)
|
||||
gtest_discover_tests(gtest_plugin_manager)
|
||||
|
||||
add_subdirectory(test_plugins/plugins_library)
|
||||
file(COPY test_plugins/plugins_config DESTINATION ./)
|
||||
578
src/plugin_manager/test/gtest_plugin_manager.cpp
Normal file
578
src/plugin_manager/test/gtest_plugin_manager.cpp
Normal file
@@ -0,0 +1,578 @@
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "sdk/include/session.h"
|
||||
|
||||
#include "../plugin_manager_util.h"
|
||||
#include "../plugin_manager_config.h"
|
||||
#include "../plugin_manager_module.h"
|
||||
#include "../plugin_manager.h"
|
||||
#include "session_manager.h"
|
||||
|
||||
/******************************************************************************
|
||||
* Test plugin_mangager_util API
|
||||
******************************************************************************/
|
||||
|
||||
#if 1
|
||||
TEST(PLUGIN_MANAGER_TEST, plugin_mangager_util_int2str)
|
||||
{
|
||||
enum session_event_type type_int;
|
||||
char buffer[1024] = {0};
|
||||
|
||||
type_int = SESSION_EVENT_UNKNOWN;
|
||||
memset(buffer, 0, sizeof(buffer));
|
||||
session_event_type_int2str(type_int, buffer, sizeof(buffer));
|
||||
EXPECT_STREQ(buffer, "SESSION_EVENT_UNKNOWN");
|
||||
|
||||
type_int = SESSION_EVENT_OPENING;
|
||||
memset(buffer, 0, sizeof(buffer));
|
||||
session_event_type_int2str(type_int, buffer, sizeof(buffer));
|
||||
EXPECT_STREQ(buffer, "SESSION_EVENT_OPENING");
|
||||
|
||||
type_int = SESSION_EVENT_RAWPKT;
|
||||
memset(buffer, 0, sizeof(buffer));
|
||||
session_event_type_int2str(type_int, buffer, sizeof(buffer));
|
||||
EXPECT_STREQ(buffer, "SESSION_EVENT_RAWPKT");
|
||||
|
||||
type_int = SESSION_EVENT_ORDPKT;
|
||||
memset(buffer, 0, sizeof(buffer));
|
||||
session_event_type_int2str(type_int, buffer, sizeof(buffer));
|
||||
EXPECT_STREQ(buffer, "SESSION_EVENT_ORDPKT");
|
||||
|
||||
type_int = SESSION_EVENT_META;
|
||||
memset(buffer, 0, sizeof(buffer));
|
||||
session_event_type_int2str(type_int, buffer, sizeof(buffer));
|
||||
EXPECT_STREQ(buffer, "SESSION_EVENT_META");
|
||||
|
||||
type_int = SESSION_EVENT_CLOSING;
|
||||
memset(buffer, 0, sizeof(buffer));
|
||||
session_event_type_int2str(type_int, buffer, sizeof(buffer));
|
||||
EXPECT_STREQ(buffer, "SESSION_EVENT_CLOSING");
|
||||
|
||||
type_int = SESSION_EVENT_ALL;
|
||||
memset(buffer, 0, sizeof(buffer));
|
||||
session_event_type_int2str(type_int, buffer, sizeof(buffer));
|
||||
EXPECT_STREQ(buffer, "SESSION_EVENT_ALL");
|
||||
|
||||
type_int = (enum session_event_type)(SESSION_EVENT_OPENING | SESSION_EVENT_RAWPKT);
|
||||
memset(buffer, 0, sizeof(buffer));
|
||||
session_event_type_int2str(type_int, buffer, sizeof(buffer));
|
||||
EXPECT_STREQ(buffer, "SESSION_EVENT_OPENING|SESSION_EVENT_RAWPKT");
|
||||
|
||||
type_int = (enum session_event_type)(SESSION_EVENT_OPENING | SESSION_EVENT_RAWPKT | SESSION_EVENT_ORDPKT);
|
||||
memset(buffer, 0, sizeof(buffer));
|
||||
session_event_type_int2str(type_int, buffer, sizeof(buffer));
|
||||
EXPECT_STREQ(buffer, "SESSION_EVENT_OPENING|SESSION_EVENT_RAWPKT|SESSION_EVENT_ORDPKT");
|
||||
|
||||
type_int = (enum session_event_type)(SESSION_EVENT_OPENING | SESSION_EVENT_RAWPKT | SESSION_EVENT_ORDPKT | SESSION_EVENT_META);
|
||||
memset(buffer, 0, sizeof(buffer));
|
||||
session_event_type_int2str(type_int, buffer, sizeof(buffer));
|
||||
EXPECT_STREQ(buffer, "SESSION_EVENT_OPENING|SESSION_EVENT_RAWPKT|SESSION_EVENT_ORDPKT|SESSION_EVENT_META");
|
||||
|
||||
type_int = (enum session_event_type)(SESSION_EVENT_OPENING | SESSION_EVENT_RAWPKT | SESSION_EVENT_ORDPKT | SESSION_EVENT_META | SESSION_EVENT_CLOSING);
|
||||
memset(buffer, 0, sizeof(buffer));
|
||||
session_event_type_int2str(type_int, buffer, sizeof(buffer));
|
||||
EXPECT_STREQ(buffer, "SESSION_EVENT_ALL");
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 1
|
||||
TEST(PLUGIN_MANAGER_TEST, plugin_mangager_util_str2int)
|
||||
{
|
||||
enum session_event_type type_int;
|
||||
|
||||
const char *type_str1 = "SESSION_EVENT_UNKNOWN";
|
||||
const char *type_str2 = "SESSION_EVENT_OPENING";
|
||||
const char *type_str3 = "SESSION_EVENT_RAWPKT";
|
||||
const char *type_str4 = "SESSION_EVENT_ORDPKT";
|
||||
const char *type_str5 = "SESSION_EVENT_META";
|
||||
const char *type_str6 = "SESSION_EVENT_CLOSING";
|
||||
const char *type_str7 = "SESSION_EVENT_ALL";
|
||||
const char *type_str8 = "SESSION_EVENT_OPENING|SESSION_EVENT_RAWPKT";
|
||||
const char *type_str9 = "SESSION_EVENT_OPENING|SESSION_EVENT_RAWPKT|SESSION_EVENT_ORDPKT";
|
||||
const char *type_str10 = "SESSION_EVENT_OPENING|SESSION_EVENT_RAWPKT|SESSION_EVENT_ORDPKT|SESSION_EVENT_META";
|
||||
const char *type_str11 = "SESSION_EVENT_OPENING|SESSION_EVENT_RAWPKT|SESSION_EVENT_ORDPKT|SESSION_EVENT_META|SESSION_EVENT_CLOSING";
|
||||
|
||||
type_int = session_event_type_str2int(type_str1);
|
||||
EXPECT_TRUE(type_int == SESSION_EVENT_UNKNOWN);
|
||||
|
||||
type_int = session_event_type_str2int(type_str2);
|
||||
EXPECT_TRUE(type_int == SESSION_EVENT_OPENING);
|
||||
|
||||
type_int = session_event_type_str2int(type_str3);
|
||||
EXPECT_TRUE(type_int == SESSION_EVENT_RAWPKT);
|
||||
|
||||
type_int = session_event_type_str2int(type_str4);
|
||||
EXPECT_TRUE(type_int == SESSION_EVENT_ORDPKT);
|
||||
|
||||
type_int = session_event_type_str2int(type_str5);
|
||||
EXPECT_TRUE(type_int == SESSION_EVENT_META);
|
||||
|
||||
type_int = session_event_type_str2int(type_str6);
|
||||
EXPECT_TRUE(type_int == SESSION_EVENT_CLOSING);
|
||||
|
||||
type_int = session_event_type_str2int(type_str7);
|
||||
EXPECT_TRUE(type_int == SESSION_EVENT_ALL);
|
||||
|
||||
type_int = session_event_type_str2int(type_str8);
|
||||
EXPECT_TRUE(type_int == (SESSION_EVENT_OPENING | SESSION_EVENT_RAWPKT));
|
||||
|
||||
type_int = session_event_type_str2int(type_str9);
|
||||
EXPECT_TRUE(type_int == (SESSION_EVENT_OPENING | SESSION_EVENT_RAWPKT | SESSION_EVENT_ORDPKT));
|
||||
|
||||
type_int = session_event_type_str2int(type_str10);
|
||||
EXPECT_TRUE(type_int == (SESSION_EVENT_OPENING | SESSION_EVENT_RAWPKT | SESSION_EVENT_ORDPKT | SESSION_EVENT_META));
|
||||
|
||||
type_int = session_event_type_str2int(type_str11);
|
||||
EXPECT_TRUE(type_int == SESSION_EVENT_ALL);
|
||||
}
|
||||
#endif
|
||||
|
||||
/******************************************************************************
|
||||
* Test plugin_mangager_config API
|
||||
******************************************************************************/
|
||||
|
||||
#if 1
|
||||
TEST(PLUGIN_MANAGER_TEST, plugin_mangager_config_HTTP)
|
||||
{
|
||||
char file_path[] = "./plugins_config/http_event_plugin/http_event_plugin.inf";
|
||||
|
||||
struct plugin_manager_config *config = plugin_mangager_config_create();
|
||||
EXPECT_TRUE(config != nullptr);
|
||||
|
||||
EXPECT_TRUE(plugin_mangager_config_parse(config, file_path) == 0);
|
||||
|
||||
EXPECT_STREQ(config->file_path, "./plugins_config/http_event_plugin/http_event_plugin.inf");
|
||||
EXPECT_STREQ(config->plugin_section.init_func_name, "http_event_plugin_init");
|
||||
EXPECT_STREQ(config->plugin_section.exit_func_name, "http_event_plugin_exit");
|
||||
EXPECT_STREQ(config->plugin_section.lib_path, "./test_plugins/plugins_library/http_event_plugin_test.so");
|
||||
|
||||
EXPECT_TRUE(config->session_section_num == 1);
|
||||
EXPECT_STREQ(config->session_section[0].session_name, "HTTP");
|
||||
EXPECT_STREQ(config->session_section[0].cb_func_name, "http_event_plugin_entry");
|
||||
EXPECT_TRUE(config->session_section[0].event == (0x01 << 1 | 0x01 << 2 | 0x01 << 3 | 0x01 << 4 | 0x01 << 5));
|
||||
|
||||
plugin_mangager_config_dump(config);
|
||||
plugin_mangager_config_destory(config);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 1
|
||||
TEST(PLUGIN_MANAGER_TEST, plugin_mangager_config_CUSTOM)
|
||||
{
|
||||
char file_path[] = "./plugins_config/custom_event_plugin/custom_event_plugin.inf";
|
||||
|
||||
struct plugin_manager_config *config = plugin_mangager_config_create();
|
||||
EXPECT_TRUE(config != nullptr);
|
||||
|
||||
EXPECT_TRUE(plugin_mangager_config_parse(config, file_path) == 0);
|
||||
|
||||
EXPECT_STREQ(config->file_path, "./plugins_config/custom_event_plugin/custom_event_plugin.inf");
|
||||
EXPECT_STREQ(config->plugin_section.init_func_name, "custom_event_plugin_init");
|
||||
EXPECT_STREQ(config->plugin_section.exit_func_name, "custom_event_plugin_exit");
|
||||
EXPECT_STREQ(config->plugin_section.lib_path, "./test_plugins/plugins_library/custom_event_plugin_test.so");
|
||||
|
||||
EXPECT_TRUE(config->session_section_num == 3);
|
||||
EXPECT_STREQ(config->session_section[0].session_name, "TCP");
|
||||
EXPECT_STREQ(config->session_section[0].cb_func_name, "custom_event_plugin_tcp_entry");
|
||||
EXPECT_TRUE(config->session_section[0].event == (0x01 << 1 | 0x01 << 2 | 0x01 << 3 | 0x01 << 4 | 0x01 << 5));
|
||||
|
||||
EXPECT_STREQ(config->session_section[1].session_name, "HTTP");
|
||||
EXPECT_STREQ(config->session_section[1].cb_func_name, "custom_event_plugin_http_entry");
|
||||
EXPECT_TRUE(config->session_section[1].event == (0x01 << 1 | 0x01 << 2 | 0x01 << 3 | 0x01 << 4 | 0x01 << 5));
|
||||
|
||||
EXPECT_STREQ(config->session_section[2].session_name, "CUSTOM");
|
||||
EXPECT_STREQ(config->session_section[2].cb_func_name, "custom_event_plugin_custom_entry");
|
||||
EXPECT_TRUE(config->session_section[2].event == (enum session_event_type)((0x01 << 1) | (0x01 << 3) | (0x01 << 5)));
|
||||
|
||||
plugin_mangager_config_dump(config);
|
||||
plugin_mangager_config_destory(config);
|
||||
}
|
||||
#endif
|
||||
|
||||
/******************************************************************************
|
||||
* Test plugin_mangager_module API
|
||||
******************************************************************************/
|
||||
|
||||
#if 1
|
||||
TEST(PLUGIN_MANAGER_TEST, plugin_mangager_module_HTTP)
|
||||
{
|
||||
char file_path[] = "./plugins_config/http_event_plugin/http_event_plugin.inf";
|
||||
|
||||
struct plugin_manager_config *config = plugin_mangager_config_create();
|
||||
EXPECT_TRUE(config != nullptr);
|
||||
EXPECT_TRUE(plugin_mangager_config_parse(config, file_path) == 0);
|
||||
|
||||
struct plugin_manager_module *module = plugin_manager_module_open(config);
|
||||
EXPECT_TRUE(module != nullptr);
|
||||
EXPECT_TRUE(plugin_manager_module_init(module) == 0);
|
||||
plugin_manager_module_dump(module, config);
|
||||
plugin_manager_module_exit(module);
|
||||
plugin_manager_module_close(module);
|
||||
|
||||
plugin_mangager_config_destory(config);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 1
|
||||
TEST(PLUGIN_MANAGER_TEST, plugin_mangager_module_CUSTOM)
|
||||
{
|
||||
char file_path[] = "./plugins_config/custom_event_plugin/custom_event_plugin.inf";
|
||||
|
||||
struct plugin_manager_config *config = plugin_mangager_config_create();
|
||||
EXPECT_TRUE(config != nullptr);
|
||||
EXPECT_TRUE(plugin_mangager_config_parse(config, file_path) == 0);
|
||||
|
||||
struct plugin_manager_module *module = plugin_manager_module_open(config);
|
||||
EXPECT_TRUE(module != nullptr);
|
||||
EXPECT_TRUE(plugin_manager_module_init(module) == 0);
|
||||
plugin_manager_module_dump(module, config);
|
||||
plugin_manager_module_exit(module);
|
||||
plugin_manager_module_close(module);
|
||||
|
||||
plugin_mangager_config_destory(config);
|
||||
}
|
||||
#endif
|
||||
|
||||
/******************************************************************************
|
||||
* Test plugin_mangager API
|
||||
******************************************************************************/
|
||||
|
||||
#if 1
|
||||
TEST(PLUGIN_MANAGER_TEST, plugin_manager_load)
|
||||
{
|
||||
char file_path[] = "./plugins_config/plugins.inf";
|
||||
|
||||
struct plugin_manager *plug_mgr = plugin_manager_create();
|
||||
EXPECT_TRUE(plug_mgr != nullptr);
|
||||
EXPECT_TRUE(plugin_manager_load(plug_mgr, file_path) == 0);
|
||||
|
||||
plugin_manager_unload(plug_mgr);
|
||||
plugin_manager_destory(plug_mgr);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 1
|
||||
// only SESSION_EVENT_OPENING | SESSION_EVENT_ORDPKT | SESSION_EVENT_CLOSING can trigger event callback
|
||||
TEST(PLUGIN_MANAGER_TEST, plugin_manager_dispatch_CUSTOM)
|
||||
{
|
||||
/*
|
||||
* [SESSION_NAME.CUSTOM]
|
||||
* SESSION_EVENT_TYPE=["SESSION_EVENT_OPENING","SESSION_EVENT_ORDPKT","SESSION_EVENT_CLOSING"]
|
||||
* SESSION_EVENT_CALLBACK="custom_event_plugin_custom_entry"
|
||||
*/
|
||||
|
||||
struct custom_session_pme
|
||||
{
|
||||
char data[64];
|
||||
int flags;
|
||||
/* data */
|
||||
};
|
||||
|
||||
struct custom_session_pme *pme;
|
||||
char file_path[] = "./plugins_config/plugins.inf";
|
||||
|
||||
const char *session_name = "CUSTOM";
|
||||
|
||||
struct stellar_session session;
|
||||
session.name = session_name;
|
||||
|
||||
struct stellar_session_event_data event_data;
|
||||
event_data.s = &session;
|
||||
event_data.plugin_ctx = NULL; // must be init to NULL
|
||||
|
||||
struct stellar_event event;
|
||||
event.session_event_data = &event_data;
|
||||
|
||||
session.event_data = &event_data; // must be set
|
||||
|
||||
struct plugin_manager *plug_mgr = plugin_manager_create();
|
||||
EXPECT_TRUE(plug_mgr != nullptr);
|
||||
EXPECT_TRUE(plugin_manager_load(plug_mgr, file_path) == 0);
|
||||
|
||||
// run evencb
|
||||
event_data.type = SESSION_EVENT_OPENING;
|
||||
plugin_manager_dispatch(plug_mgr, &event);
|
||||
pme = (struct custom_session_pme *)pm_session_get_plugin_pme(&session);
|
||||
EXPECT_TRUE(pme->flags == SESSION_EVENT_OPENING);
|
||||
EXPECT_STREQ(pme->data, "custom_event_plugin_custom_entry");
|
||||
|
||||
// unrun evencb
|
||||
event_data.type = SESSION_EVENT_RAWPKT;
|
||||
plugin_manager_dispatch(plug_mgr, &event);
|
||||
pme = (struct custom_session_pme *)pm_session_get_plugin_pme(&session);
|
||||
EXPECT_TRUE(pme->flags == SESSION_EVENT_OPENING);
|
||||
EXPECT_STREQ(pme->data, "custom_event_plugin_custom_entry");
|
||||
|
||||
// run evencb
|
||||
event_data.type = SESSION_EVENT_ORDPKT;
|
||||
plugin_manager_dispatch(plug_mgr, &event);
|
||||
pme = (struct custom_session_pme *)pm_session_get_plugin_pme(&session);
|
||||
EXPECT_TRUE(pme->flags == SESSION_EVENT_ORDPKT);
|
||||
EXPECT_STREQ(pme->data, "custom_event_plugin_custom_entry");
|
||||
|
||||
// unrun evencb
|
||||
event_data.type = SESSION_EVENT_META;
|
||||
plugin_manager_dispatch(plug_mgr, &event);
|
||||
pme = (struct custom_session_pme *)pm_session_get_plugin_pme(&session);
|
||||
EXPECT_TRUE(pme->flags == SESSION_EVENT_ORDPKT);
|
||||
EXPECT_STREQ(pme->data, "custom_event_plugin_custom_entry");
|
||||
|
||||
// run evencb
|
||||
event_data.type = SESSION_EVENT_CLOSING;
|
||||
plugin_manager_dispatch(plug_mgr, &event);
|
||||
EXPECT_TRUE(stellar_session_get_plugin_ctx(&session) == nullptr);
|
||||
|
||||
// run evencb
|
||||
event_data.type = SESSION_EVENT_ALL;
|
||||
plugin_manager_dispatch(plug_mgr, &event);
|
||||
EXPECT_TRUE(stellar_session_get_plugin_ctx(&session) == nullptr);
|
||||
|
||||
plugin_manager_unload(plug_mgr);
|
||||
plugin_manager_destory(plug_mgr);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 1
|
||||
// ALL SESSION_EVENT can trigger event callback
|
||||
TEST(PLUGIN_MANAGER_TEST, plugin_manager_dispatch_TCP)
|
||||
{
|
||||
/*
|
||||
* [SESSION_NAME.TCP]
|
||||
* SESSION_EVENT_TYPE=["SESSION_EVENT_ALL"]
|
||||
* SESSION_EVENT_CALLBACK="custom_event_plugin_tcp_entry"
|
||||
*/
|
||||
|
||||
struct tcp_session_pme
|
||||
{
|
||||
char data[64];
|
||||
int flags;
|
||||
/* data */
|
||||
};
|
||||
struct tcp_session_pme *pme;
|
||||
|
||||
char file_path[] = "./plugins_config/plugins.inf";
|
||||
|
||||
const char *session_name = "TCP";
|
||||
|
||||
struct stellar_session session;
|
||||
session.name = session_name;
|
||||
|
||||
struct stellar_session_event_data event_data;
|
||||
event_data.s = &session;
|
||||
event_data.plugin_ctx = NULL; // must be init to NULL
|
||||
|
||||
struct stellar_event event;
|
||||
event.session_event_data = &event_data;
|
||||
|
||||
session.event_data = &event_data; // must be set
|
||||
|
||||
struct plugin_manager *plug_mgr = plugin_manager_create();
|
||||
EXPECT_TRUE(plug_mgr != nullptr);
|
||||
EXPECT_TRUE(plugin_manager_load(plug_mgr, file_path) == 0);
|
||||
|
||||
// run evencb
|
||||
event_data.type = SESSION_EVENT_OPENING;
|
||||
plugin_manager_dispatch(plug_mgr, &event);
|
||||
pme = (struct tcp_session_pme *)pm_session_get_plugin_pme(&session);
|
||||
EXPECT_TRUE(pme->flags == SESSION_EVENT_OPENING);
|
||||
EXPECT_STREQ(pme->data, "custom_event_plugin_tcp_entry");
|
||||
|
||||
// run evencb
|
||||
event_data.type = SESSION_EVENT_RAWPKT;
|
||||
plugin_manager_dispatch(plug_mgr, &event);
|
||||
pme = (struct tcp_session_pme *)pm_session_get_plugin_pme(&session);
|
||||
EXPECT_TRUE(pme->flags == SESSION_EVENT_RAWPKT);
|
||||
EXPECT_STREQ(pme->data, "custom_event_plugin_tcp_entry");
|
||||
|
||||
// run evencb
|
||||
event_data.type = SESSION_EVENT_ORDPKT;
|
||||
plugin_manager_dispatch(plug_mgr, &event);
|
||||
pme = (struct tcp_session_pme *)pm_session_get_plugin_pme(&session);
|
||||
EXPECT_TRUE(pme->flags == SESSION_EVENT_ORDPKT);
|
||||
EXPECT_STREQ(pme->data, "custom_event_plugin_tcp_entry");
|
||||
|
||||
// run evencb
|
||||
event_data.type = SESSION_EVENT_META;
|
||||
plugin_manager_dispatch(plug_mgr, &event);
|
||||
pme = (struct tcp_session_pme *)pm_session_get_plugin_pme(&session);
|
||||
EXPECT_TRUE(pme->flags == SESSION_EVENT_META);
|
||||
EXPECT_STREQ(pme->data, "custom_event_plugin_tcp_entry");
|
||||
|
||||
// run evencb
|
||||
event_data.type = SESSION_EVENT_CLOSING;
|
||||
plugin_manager_dispatch(plug_mgr, &event);
|
||||
EXPECT_TRUE(stellar_session_get_plugin_ctx(&session) == nullptr);
|
||||
|
||||
// run evencb
|
||||
event_data.type = SESSION_EVENT_ALL;
|
||||
plugin_manager_dispatch(plug_mgr, &event);
|
||||
EXPECT_TRUE(stellar_session_get_plugin_ctx(&session) == nullptr);
|
||||
|
||||
plugin_manager_unload(plug_mgr);
|
||||
plugin_manager_destory(plug_mgr);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 1
|
||||
// http_event_plugin_entry + SESSION_EVENT_RAWPKT ==> pm_session_dettach_me
|
||||
TEST(PLUGIN_MANAGER_TEST, plugin_manager_dispatch_HTTP_dettach_me)
|
||||
{
|
||||
/*
|
||||
* [SESSION_NAME.HTTP]
|
||||
* SESSION_EVENT_TYPE=["SESSION_EVENT_ALL"]
|
||||
* SESSION_EVENT_CALLBACK="http_event_plugin_entry"
|
||||
*
|
||||
* [SESSION_NAME.HTTP]
|
||||
* SESSION_EVENT_TYPE=["SESSION_EVENT_ALL"]
|
||||
* SESSION_EVENT_CALLBACK="custom_event_plugin_http_entry"
|
||||
*/
|
||||
|
||||
struct http_session_pme
|
||||
{
|
||||
char data[64];
|
||||
int flags;
|
||||
/* data */;
|
||||
};
|
||||
|
||||
struct http_session_pme *pme = NULL;
|
||||
char file_path[] = "./plugins_config/plugins.inf";
|
||||
|
||||
const char *session_name = "HTTP";
|
||||
|
||||
struct stellar_session session;
|
||||
session.name = session_name;
|
||||
|
||||
struct stellar_session_event_data event_data;
|
||||
event_data.s = &session;
|
||||
event_data.plugin_ctx = NULL; // must be init to NULL
|
||||
|
||||
struct stellar_event event;
|
||||
event.session_event_data = &event_data;
|
||||
|
||||
session.event_data = &event_data; // must be set
|
||||
|
||||
struct plugin_manager *plug_mgr = plugin_manager_create();
|
||||
EXPECT_TRUE(plug_mgr != nullptr);
|
||||
EXPECT_TRUE(plugin_manager_load(plug_mgr, file_path) == 0);
|
||||
|
||||
// run evencb
|
||||
event_data.type = SESSION_EVENT_OPENING;
|
||||
plugin_manager_dispatch(plug_mgr, &event);
|
||||
pme = (struct http_session_pme *)pm_session_get_plugin_pme(&session);
|
||||
EXPECT_TRUE(pme->flags == SESSION_EVENT_OPENING);
|
||||
EXPECT_STREQ(pme->data, "custom_event_plugin_http_entry");
|
||||
|
||||
// http_event_plugin_entry + SESSION_EVENT_RAWPKT ==> pm_session_dettach_me
|
||||
event_data.type = SESSION_EVENT_RAWPKT;
|
||||
plugin_manager_dispatch(plug_mgr, &event);
|
||||
pme = (struct http_session_pme *)pm_session_get_plugin_pme(&session);
|
||||
EXPECT_TRUE(pme->flags == SESSION_EVENT_RAWPKT);
|
||||
EXPECT_STREQ(pme->data, "custom_event_plugin_http_entry");
|
||||
|
||||
// run evencb
|
||||
event_data.type = SESSION_EVENT_META;
|
||||
plugin_manager_dispatch(plug_mgr, &event);
|
||||
pme = (struct http_session_pme *)pm_session_get_plugin_pme(&session);
|
||||
EXPECT_TRUE(pme->flags == SESSION_EVENT_META);
|
||||
EXPECT_STREQ(pme->data, "custom_event_plugin_http_entry");
|
||||
|
||||
// run evencb
|
||||
event_data.type = SESSION_EVENT_CLOSING;
|
||||
plugin_manager_dispatch(plug_mgr, &event);
|
||||
EXPECT_TRUE(stellar_session_get_plugin_ctx(&session) == nullptr);
|
||||
|
||||
// run evencb
|
||||
event_data.type = SESSION_EVENT_ALL;
|
||||
plugin_manager_dispatch(plug_mgr, &event);
|
||||
EXPECT_TRUE(stellar_session_get_plugin_ctx(&session) == nullptr);
|
||||
|
||||
plugin_manager_unload(plug_mgr);
|
||||
plugin_manager_destory(plug_mgr);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 1
|
||||
// http_event_plugin_entry + SESSION_EVENT_ORDPKT ==> pm_session_take_over
|
||||
TEST(PLUGIN_MANAGER_TEST, plugin_manager_dispatch_HTTP_take_over)
|
||||
{
|
||||
/*
|
||||
* [SESSION_NAME.HTTP]
|
||||
* SESSION_EVENT_TYPE=["SESSION_EVENT_ALL"]
|
||||
* SESSION_EVENT_CALLBACK="http_event_plugin_entry"
|
||||
*
|
||||
* [SESSION_NAME.HTTP]
|
||||
* SESSION_EVENT_TYPE=["SESSION_EVENT_ALL"]
|
||||
* SESSION_EVENT_CALLBACK="custom_event_plugin_http_entry"
|
||||
*/
|
||||
|
||||
struct http_session_pme
|
||||
{
|
||||
char data[64];
|
||||
int flags;
|
||||
/* data */;
|
||||
};
|
||||
|
||||
struct http_session_pme *pme = NULL;
|
||||
char file_path[] = "./plugins_config/plugins.inf";
|
||||
|
||||
const char *session_name = "HTTP";
|
||||
|
||||
struct stellar_session session;
|
||||
session.name = session_name;
|
||||
|
||||
struct stellar_session_event_data event_data;
|
||||
event_data.s = &session;
|
||||
event_data.plugin_ctx = NULL; // must be init to NULL
|
||||
|
||||
struct stellar_event event;
|
||||
event.session_event_data = &event_data;
|
||||
|
||||
session.event_data = &event_data; // must be set
|
||||
|
||||
struct plugin_manager *plug_mgr = plugin_manager_create();
|
||||
EXPECT_TRUE(plug_mgr != nullptr);
|
||||
EXPECT_TRUE(plugin_manager_load(plug_mgr, file_path) == 0);
|
||||
|
||||
// run evencb
|
||||
event_data.type = SESSION_EVENT_OPENING;
|
||||
plugin_manager_dispatch(plug_mgr, &event);
|
||||
pme = (struct http_session_pme *)pm_session_get_plugin_pme(&session);
|
||||
EXPECT_TRUE(pme->flags == SESSION_EVENT_OPENING);
|
||||
EXPECT_STREQ(pme->data, "custom_event_plugin_http_entry");
|
||||
|
||||
// http_event_plugin_entry + SESSION_EVENT_ORDPKT ==> pm_session_take_over
|
||||
event_data.type = SESSION_EVENT_ORDPKT;
|
||||
plugin_manager_dispatch(plug_mgr, &event);
|
||||
pme = (struct http_session_pme *)pm_session_get_plugin_pme(&session);
|
||||
EXPECT_TRUE(pme->flags == SESSION_EVENT_ORDPKT);
|
||||
EXPECT_STREQ(pme->data, "http_event_plugin_entry");
|
||||
|
||||
// run evencb
|
||||
event_data.type = SESSION_EVENT_META;
|
||||
plugin_manager_dispatch(plug_mgr, &event);
|
||||
pme = (struct http_session_pme *)pm_session_get_plugin_pme(&session);
|
||||
EXPECT_TRUE(pme->flags == SESSION_EVENT_META);
|
||||
EXPECT_STREQ(pme->data, "http_event_plugin_entry");
|
||||
|
||||
// run evencb
|
||||
event_data.type = SESSION_EVENT_CLOSING;
|
||||
plugin_manager_dispatch(plug_mgr, &event);
|
||||
EXPECT_TRUE(stellar_session_get_plugin_ctx(&session) == nullptr);
|
||||
|
||||
// run evencb
|
||||
event_data.type = SESSION_EVENT_ALL;
|
||||
plugin_manager_dispatch(plug_mgr, &event);
|
||||
EXPECT_TRUE(stellar_session_get_plugin_ctx(&session) == nullptr);
|
||||
|
||||
plugin_manager_unload(plug_mgr);
|
||||
plugin_manager_destory(plug_mgr);
|
||||
}
|
||||
#endif
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
::testing::InitGoogleTest(&argc, argv);
|
||||
int ret = RUN_ALL_TESTS();
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
[PLUGINFO]
|
||||
INIT_FUNC="custom_event_plugin_init"
|
||||
EXIT_FUNC="custom_event_plugin_exit"
|
||||
LIBRARY_PATH="./test_plugins/plugins_library/custom_event_plugin_test.so"
|
||||
|
||||
# Support SESSION_EVENT_TYPE: "SESSION_EVENT_OPENING", "SESSION_EVENT_RAWPKT", "SESSION_EVENT_ORDPKT", "SESSION_EVENT_META", "SESSION_EVENT_CLOSING", "SESSION_EVENT_ALL"
|
||||
|
||||
[SESSION_NAME.TCP]
|
||||
SESSION_EVENT_TYPE=["SESSION_EVENT_ALL"]
|
||||
SESSION_EVENT_CALLBACK="custom_event_plugin_tcp_entry"
|
||||
|
||||
[SESSION_NAME.HTTP]
|
||||
SESSION_EVENT_TYPE=["SESSION_EVENT_ALL"]
|
||||
SESSION_EVENT_CALLBACK="custom_event_plugin_http_entry"
|
||||
|
||||
[SESSION_NAME.CUSTOM]
|
||||
SESSION_EVENT_TYPE=["SESSION_EVENT_OPENING","SESSION_EVENT_ORDPKT","SESSION_EVENT_CLOSING"]
|
||||
SESSION_EVENT_CALLBACK="custom_event_plugin_custom_entry"
|
||||
@@ -0,0 +1,10 @@
|
||||
[PLUGINFO]
|
||||
INIT_FUNC="http_event_plugin_init"
|
||||
EXIT_FUNC="http_event_plugin_exit"
|
||||
LIBRARY_PATH="./test_plugins/plugins_library/http_event_plugin_test.so"
|
||||
|
||||
# Support SESSION_EVENT_TYPE: "SESSION_EVENT_OPENING", "SESSION_EVENT_RAWPKT", "SESSION_EVENT_ORDPKT", "SESSION_EVENT_META", "SESSION_EVENT_CLOSING", "SESSION_EVENT_ALL"
|
||||
|
||||
[SESSION_NAME.HTTP]
|
||||
SESSION_EVENT_TYPE=["SESSION_EVENT_ALL"]
|
||||
SESSION_EVENT_CALLBACK="http_event_plugin_entry"
|
||||
@@ -0,0 +1,4 @@
|
||||
# Relative path, relative to the installation path of stellar
|
||||
|
||||
./plugins_config/http_event_plugin/http_event_plugin.inf
|
||||
./plugins_config/custom_event_plugin/custom_event_plugin.inf
|
||||
@@ -0,0 +1,9 @@
|
||||
add_library(custom_event_plugin_test SHARED
|
||||
custom_event_plugin.cpp
|
||||
)
|
||||
set_target_properties(custom_event_plugin_test PROPERTIES PREFIX "")
|
||||
|
||||
add_library(http_event_plugin_test SHARED
|
||||
http_event_plugin.cpp
|
||||
)
|
||||
set_target_properties(http_event_plugin_test PROPERTIES PREFIX "")
|
||||
@@ -0,0 +1,216 @@
|
||||
#include "session.h"
|
||||
#include "packet.h"
|
||||
#include "plugin.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
static char *g_handler = NULL;
|
||||
|
||||
static void *custom_decode(const char *payload, uint16_t len, void **pme)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct tcp_session_pme
|
||||
{
|
||||
char data[64];
|
||||
int flags;
|
||||
/* data */
|
||||
};
|
||||
|
||||
struct custom_session_pme
|
||||
{
|
||||
char data[64];
|
||||
int flags;
|
||||
/* data */
|
||||
};
|
||||
|
||||
struct http_session_pme
|
||||
{
|
||||
char data[64];
|
||||
int flags;
|
||||
/* data */;
|
||||
};
|
||||
|
||||
static struct tcp_session_pme *tcp_session_pme_create()
|
||||
{
|
||||
struct tcp_session_pme *pme = (struct tcp_session_pme *)calloc(1, sizeof(struct tcp_session_pme));
|
||||
return pme;
|
||||
}
|
||||
|
||||
static void tcp_session_pme_destory(struct tcp_session_pme *pme)
|
||||
{
|
||||
if (pme)
|
||||
{
|
||||
free(pme);
|
||||
pme = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static struct custom_session_pme *custom_session_pme_create()
|
||||
{
|
||||
struct custom_session_pme *pme = (struct custom_session_pme *)calloc(1, sizeof(struct custom_session_pme));
|
||||
return pme;
|
||||
}
|
||||
|
||||
static void custom_session_pme_destory(struct custom_session_pme *pme)
|
||||
{
|
||||
if (pme)
|
||||
{
|
||||
free(pme);
|
||||
pme = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static struct http_session_pme *http_session_pme_create()
|
||||
{
|
||||
struct http_session_pme *pme = (struct http_session_pme *)calloc(1, sizeof(struct http_session_pme));
|
||||
return pme;
|
||||
}
|
||||
|
||||
static void http_session_pme_destory(struct http_session_pme *pme)
|
||||
{
|
||||
if (pme)
|
||||
{
|
||||
free(pme);
|
||||
pme = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" void custom_event_plugin_tcp_entry(const struct stellar_session *session, enum session_event_type event, struct stellar_packet *p, const char *payload, uint16_t len, void **pme)
|
||||
{
|
||||
struct tcp_session_pme **per_tcp_session_pme = (struct tcp_session_pme **)pme;
|
||||
|
||||
if (event & SESSION_EVENT_OPENING)
|
||||
{
|
||||
if (*per_tcp_session_pme == NULL)
|
||||
{
|
||||
struct tcp_session_pme *cur_ctx = tcp_session_pme_create();
|
||||
memcpy(cur_ctx->data, "custom_event_plugin_tcp_entry", strlen("custom_event_plugin_tcp_entry"));
|
||||
cur_ctx->flags = SESSION_EVENT_OPENING;
|
||||
*per_tcp_session_pme = *&cur_ctx;
|
||||
}
|
||||
}
|
||||
|
||||
if (event & SESSION_EVENT_RAWPKT)
|
||||
{
|
||||
(*per_tcp_session_pme)->flags = SESSION_EVENT_RAWPKT;
|
||||
}
|
||||
|
||||
if (event & SESSION_EVENT_ORDPKT)
|
||||
{
|
||||
(*per_tcp_session_pme)->flags = SESSION_EVENT_ORDPKT;
|
||||
|
||||
struct stellar_session_event_extras *info = (struct stellar_session_event_extras *)custom_decode(payload, len, pme);
|
||||
struct stellar_session *new_session = session_manager_session_derive(session, "CUSTOM");
|
||||
|
||||
session_manager_trigger_event(new_session, SESSION_EVENT_OPENING, info);
|
||||
session_manager_trigger_event(new_session, SESSION_EVENT_META, info);
|
||||
}
|
||||
|
||||
if (event & SESSION_EVENT_META)
|
||||
{
|
||||
(*per_tcp_session_pme)->flags = SESSION_EVENT_META;
|
||||
}
|
||||
|
||||
if (event & SESSION_EVENT_CLOSING)
|
||||
{
|
||||
tcp_session_pme_destory(*per_tcp_session_pme);
|
||||
*per_tcp_session_pme = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" void custom_event_plugin_custom_entry(const struct stellar_session *session, enum session_event_type event, struct stellar_packet *p, const char *payload, uint16_t len, void **pme)
|
||||
{
|
||||
struct custom_session_pme **per_custom_session_pme = (struct custom_session_pme **)pme;
|
||||
|
||||
if (event & SESSION_EVENT_OPENING)
|
||||
{
|
||||
if (*per_custom_session_pme == NULL)
|
||||
{
|
||||
struct custom_session_pme *cur_ctx = custom_session_pme_create();
|
||||
memcpy(cur_ctx->data, "custom_event_plugin_custom_entry", strlen("custom_event_plugin_custom_entry"));
|
||||
cur_ctx->flags = SESSION_EVENT_OPENING;
|
||||
*per_custom_session_pme = *&cur_ctx;
|
||||
}
|
||||
}
|
||||
|
||||
if (event & SESSION_EVENT_RAWPKT)
|
||||
{
|
||||
(*per_custom_session_pme)->flags = SESSION_EVENT_RAWPKT;
|
||||
}
|
||||
if (event & SESSION_EVENT_ORDPKT)
|
||||
{
|
||||
(*per_custom_session_pme)->flags = SESSION_EVENT_ORDPKT;
|
||||
}
|
||||
|
||||
if (event & SESSION_EVENT_META)
|
||||
{
|
||||
(*per_custom_session_pme)->flags = SESSION_EVENT_META;
|
||||
}
|
||||
|
||||
if (event & SESSION_EVENT_CLOSING)
|
||||
{
|
||||
custom_session_pme_destory(*per_custom_session_pme);
|
||||
*per_custom_session_pme = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" void custom_event_plugin_http_entry(const struct stellar_session *session, enum session_event_type event, struct stellar_packet *p, const char *payload, uint16_t len, void **pme)
|
||||
{
|
||||
struct http_session_pme **per_http_session_pme = (struct http_session_pme **)pme;
|
||||
|
||||
if (event & SESSION_EVENT_OPENING)
|
||||
{
|
||||
if (*per_http_session_pme == NULL)
|
||||
{
|
||||
struct http_session_pme *cur_ctx = http_session_pme_create();
|
||||
memcpy(cur_ctx->data, "custom_event_plugin_http_entry", strlen("custom_event_plugin_http_entry"));
|
||||
cur_ctx->flags = SESSION_EVENT_OPENING;
|
||||
*per_http_session_pme = *&cur_ctx;
|
||||
}
|
||||
}
|
||||
|
||||
if (event & SESSION_EVENT_RAWPKT)
|
||||
{
|
||||
(*per_http_session_pme)->flags = SESSION_EVENT_RAWPKT;
|
||||
}
|
||||
|
||||
if (event & SESSION_EVENT_ORDPKT)
|
||||
{
|
||||
(*per_http_session_pme)->flags = SESSION_EVENT_ORDPKT;
|
||||
}
|
||||
|
||||
if (event & SESSION_EVENT_META)
|
||||
{
|
||||
(*per_http_session_pme)->flags = SESSION_EVENT_META;
|
||||
}
|
||||
|
||||
if (event & SESSION_EVENT_CLOSING)
|
||||
{
|
||||
http_session_pme_destory(*per_http_session_pme);
|
||||
*per_http_session_pme = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" int custom_event_plugin_init(void)
|
||||
{
|
||||
if (g_handler == NULL)
|
||||
{
|
||||
g_handler = (char *)malloc(1024);
|
||||
snprintf(g_handler, 1024, "222222");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
extern "C" void custom_event_plugin_exit(void)
|
||||
{
|
||||
if (g_handler)
|
||||
{
|
||||
free(g_handler);
|
||||
g_handler = NULL;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
#include "session.h"
|
||||
#include "packet.h"
|
||||
#include "plugin.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
static char *g_handler = NULL;
|
||||
|
||||
struct http_session_pme
|
||||
{
|
||||
char data[64];
|
||||
int flags;
|
||||
/* data */;
|
||||
};
|
||||
|
||||
static struct http_session_pme *http_session_pme_create()
|
||||
{
|
||||
struct http_session_pme *pme = (struct http_session_pme *)calloc(1, sizeof(struct http_session_pme));
|
||||
return pme;
|
||||
}
|
||||
|
||||
static void http_session_pme_destory(struct http_session_pme *pme)
|
||||
{
|
||||
if (pme)
|
||||
{
|
||||
free(pme);
|
||||
pme = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" void http_event_plugin_entry(const struct stellar_session *session, enum session_event_type event, struct stellar_packet *p, const char *payload, uint16_t len, void **pme)
|
||||
{
|
||||
struct http_session_pme **per_http_session_pme = (struct http_session_pme **)pme;
|
||||
|
||||
if (event & SESSION_EVENT_OPENING)
|
||||
{
|
||||
if (*per_http_session_pme == NULL)
|
||||
{
|
||||
struct http_session_pme *cur_ctx = http_session_pme_create();
|
||||
memcpy(cur_ctx->data, "http_event_plugin_entry", strlen("http_event_plugin_entry"));
|
||||
cur_ctx->flags = SESSION_EVENT_OPENING;
|
||||
*per_http_session_pme = *&cur_ctx;
|
||||
}
|
||||
}
|
||||
|
||||
if (event & SESSION_EVENT_RAWPKT)
|
||||
{
|
||||
/*
|
||||
* Note: pm_session_dettach_me()
|
||||
* The plugin manager just set the skip flag and don't call this event callback next.
|
||||
* Before calling pm_session_dettach_me, the current plugin must release related resources for the current session.
|
||||
*/
|
||||
http_session_pme_destory(*per_http_session_pme);
|
||||
*per_http_session_pme = NULL;
|
||||
pm_session_dettach_me(session);
|
||||
return;
|
||||
}
|
||||
|
||||
if (event & SESSION_EVENT_ORDPKT)
|
||||
{
|
||||
// TODO
|
||||
(*per_http_session_pme)->flags = SESSION_EVENT_ORDPKT;
|
||||
pm_session_take_over(session);
|
||||
}
|
||||
|
||||
if (event & SESSION_EVENT_META)
|
||||
{
|
||||
// TODO
|
||||
(*per_http_session_pme)->flags = SESSION_EVENT_META;
|
||||
}
|
||||
|
||||
if (event & SESSION_EVENT_CLOSING)
|
||||
{
|
||||
http_session_pme_destory(*per_http_session_pme);
|
||||
*per_http_session_pme = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" int http_event_plugin_init(void)
|
||||
{
|
||||
if (g_handler == NULL)
|
||||
{
|
||||
g_handler = (char *)malloc(1024);
|
||||
snprintf(g_handler, 1024, "111111");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
extern "C" void http_event_plugin_exit(void)
|
||||
{
|
||||
if (g_handler)
|
||||
{
|
||||
free(g_handler);
|
||||
g_handler = NULL;
|
||||
}
|
||||
}
|
||||
@@ -2,4 +2,5 @@
|
||||
|
||||
add_library(http
|
||||
http.cpp
|
||||
)
|
||||
)
|
||||
target_include_directories(http PUBLIC ${CMAKE_SOURCE_DIR})
|
||||
@@ -1,16 +1,12 @@
|
||||
#include "http.h"
|
||||
#include "session_manager.h"
|
||||
#include <stddef.h>
|
||||
|
||||
int http_decoder(const struct session *s, int what, struct packet *p, const char *payload, uint32_t len, void **pme)
|
||||
#include "sdk/include/session.h"
|
||||
|
||||
void http_decoder(const struct stellar_session *s, enum session_event_type event, struct stellar_packet *p, const char *payload, uint16_t len, void **pme)
|
||||
{
|
||||
void *info;
|
||||
struct session *new_session=session_manager_session_derive(s, SESSION_TYPE_HTTP);
|
||||
struct stellar_session_event_extras *info = NULL;
|
||||
struct stellar_session *new_session = session_manager_session_derive(s, "HTTP");
|
||||
|
||||
session_manager_trigger_event(new_session, SESSION_EVENT_OPENING, info);
|
||||
session_manager_trigger_event(new_session, SESSION_EVENT_META, info);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int http_peek(const struct session *s, const char *payload, uint32_t len)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
|
||||
add_library(session_manager
|
||||
session_manager.cpp
|
||||
)
|
||||
)
|
||||
target_include_directories(session_manager PUBLIC ${CMAKE_SOURCE_DIR})
|
||||
@@ -1,43 +1,101 @@
|
||||
#include <stddef.h>
|
||||
|
||||
#include "sdk/include/session.h"
|
||||
#include "session_manager.h"
|
||||
|
||||
struct session_manager
|
||||
{
|
||||
struct session **tcp_table, **udp_table;
|
||||
struct stellar_session **tcp_table;
|
||||
struct stellar_session **udp_table;
|
||||
};
|
||||
|
||||
void session_manager_session_event_register(fn_session_event_callback decoder, session_type type)
|
||||
struct session_manager *session_manager_init()
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void session_manager_trigger_event(struct stellar_session *s, enum session_event_type type, struct stellar_session_event_extras *info)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
struct session *session_manager_custom_session_derive(const struct session *cur_session, struct custom_session_event *event)
|
||||
struct stellar_session *session_manager_session_derive(const struct stellar_session *this_session, const char *session_name)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void session_manager_trigger_event(struct session *s, session_event_type event, void *event_info)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
struct session_event *session_manager_commit(struct packet *p)
|
||||
struct stellar_event *session_manager_commit(struct session_manager *h, struct stellar_packet *p)
|
||||
{
|
||||
return nullptr;
|
||||
};
|
||||
|
||||
|
||||
struct custom_session_event *session_manager_custom_session_event_register(const char *event_name, int available_event)
|
||||
struct stellar_event *session_manager_fetch_event(struct session_manager *h)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
struct session *session_manager_session_derive(const struct session *cur_session, session_type type)
|
||||
/******************************************************************************
|
||||
* stellar_event API For Plugin Manager
|
||||
******************************************************************************/
|
||||
|
||||
struct session_plugin_ctx *stellar_event_get_plugin_ctx(struct stellar_event *event)
|
||||
{
|
||||
return nullptr;
|
||||
return event->session_event_data->plugin_ctx;
|
||||
}
|
||||
|
||||
struct session_event *session_manager_fetch_event()
|
||||
void stellar_event_set_plugin_ctx(struct stellar_event *event, struct session_plugin_ctx *plugin_ctx)
|
||||
{
|
||||
return nullptr;
|
||||
event->session_event_data->plugin_ctx = plugin_ctx;
|
||||
}
|
||||
|
||||
enum session_event_type stellar_event_get_type(struct stellar_event *event)
|
||||
{
|
||||
return event->session_event_data->type;
|
||||
}
|
||||
|
||||
const char *stellar_event_get_session_name(struct stellar_event *event)
|
||||
{
|
||||
return event->session_event_data->s->name;
|
||||
}
|
||||
|
||||
const struct stellar_session *stellar_event_get_session(struct stellar_event *event)
|
||||
{
|
||||
return event->session_event_data->s;
|
||||
}
|
||||
|
||||
// TODO
|
||||
struct stellar_packet *stellar_event_get_packet(struct stellar_event *event)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// TODO
|
||||
const char *stellar_event_get_payload(struct stellar_event *event)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// TODO
|
||||
uint16_t stellar_event_get_payload_length(struct stellar_event *event)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* stellar_session API For Plugin Manager
|
||||
******************************************************************************/
|
||||
|
||||
struct session_plugin_ctx *stellar_session_get_plugin_ctx(const struct stellar_session *session)
|
||||
{
|
||||
struct stellar_session_event_data *evdata = session->event_data;
|
||||
return evdata->plugin_ctx;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* stellar_session API For Plugin
|
||||
******************************************************************************/
|
||||
|
||||
const char *stellar_session_get_name(const struct stellar_session *session)
|
||||
{
|
||||
return session->name;
|
||||
}
|
||||
@@ -1,47 +1,47 @@
|
||||
#pragma once
|
||||
|
||||
#include "session.h"
|
||||
#include "uthash/uthash.h"
|
||||
#include "sdk/include/session.h"
|
||||
|
||||
#include <sys/queue.h> /* TAILQ(3) */
|
||||
|
||||
struct session_data
|
||||
struct stellar_session_event_data
|
||||
{
|
||||
/* data */
|
||||
struct stellar_session *s;
|
||||
enum session_event_type type;
|
||||
long last_active;
|
||||
struct session_plugin_ctx *plugin_ctx;
|
||||
};
|
||||
|
||||
enum session_state
|
||||
struct session_manager;
|
||||
struct session_manager *session_manager_init();
|
||||
|
||||
struct stellar_event *session_manager_commit(struct session_manager *session_mgr, struct stellar_packet *pkt);
|
||||
struct stellar_event *session_manager_fetch_event(struct session_manager *session_mgr);
|
||||
|
||||
struct stellar_session
|
||||
{
|
||||
SESSION_STATE_OPENING,
|
||||
SESSION_STATE_ACTIVE,
|
||||
SESSION_STATE_CLOSING,
|
||||
SESSION_STATE_CLOSED
|
||||
stellar_session_type type;
|
||||
const char *name;
|
||||
void *addr;
|
||||
void *data;
|
||||
struct stellar_session_event_data *event_data;
|
||||
};
|
||||
|
||||
struct session_event
|
||||
{
|
||||
enum session_state state;
|
||||
void *cb_pme;
|
||||
fn_session_event_callback callback;
|
||||
TAILQ_ENTRY(session_event) session_event_tq_entries;
|
||||
};
|
||||
/******************************************************************************
|
||||
* stellar_event API For Plugin Manager
|
||||
******************************************************************************/
|
||||
|
||||
TAILQ_HEAD(session_event_list, session_event);
|
||||
struct session_plugin_ctx *stellar_event_get_plugin_ctx(struct stellar_event *event);
|
||||
void stellar_event_set_plugin_ctx(struct stellar_event *event, struct session_plugin_ctx *plugin_ctx);
|
||||
|
||||
struct session
|
||||
{
|
||||
const char *name;
|
||||
enum session_type type;
|
||||
enum session_state state;
|
||||
struct session_data data;
|
||||
struct session_event cur_ev;
|
||||
struct session_event_list ev_list;
|
||||
TAILQ_ENTRY(session) session_tq_entries;
|
||||
UT_hash_handle hh;
|
||||
};
|
||||
enum session_event_type stellar_event_get_type(struct stellar_event *event);
|
||||
const char *stellar_event_get_session_name(struct stellar_event *event);
|
||||
const struct stellar_session *stellar_event_get_session(struct stellar_event *event);
|
||||
struct stellar_packet *stellar_event_get_packet(struct stellar_event *event);
|
||||
|
||||
const char *stellar_event_get_payload(struct stellar_event *event);
|
||||
uint16_t stellar_event_get_payload_length(struct stellar_event *event);
|
||||
|
||||
/******************************************************************************
|
||||
* stellar_session API For Plugin Manager
|
||||
******************************************************************************/
|
||||
|
||||
|
||||
void session_manager_session_event_register(fn_session_event_callback session_ev_cb, session_type type);
|
||||
struct session *session_manager_session_derive(const struct session *cur_session, session_type type);
|
||||
struct session_plugin_ctx *stellar_session_get_plugin_ctx(const struct stellar_session *session);
|
||||
@@ -7,7 +7,7 @@ add_executable(gtest_stellar
|
||||
|
||||
target_link_libraries(
|
||||
gtest_stellar
|
||||
gtest_main
|
||||
gtest
|
||||
)
|
||||
|
||||
include(GoogleTest)
|
||||
|
||||
31
vendor/CMakeLists.txt
vendored
31
vendor/CMakeLists.txt
vendored
@@ -1,10 +1,21 @@
|
||||
include(FetchContent)
|
||||
FetchContent_Declare(
|
||||
googletest
|
||||
#URL https://github.com/google/googletest/archive/609281088cfefc76f9d0ce82e1ff6c30cc3591e5.zip
|
||||
URL ${CMAKE_CURRENT_SOURCE_DIR}/googletest-release-1.8.0.tar.gz
|
||||
URL_MD5 16877098823401d1bf2ed7891d7dce36
|
||||
)
|
||||
# For Windows: Prevent overriding the parent project's compiler/linker settings
|
||||
set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
|
||||
FetchContent_MakeAvailable(googletest)
|
||||
include(ExternalProject)
|
||||
|
||||
# GoogleTest
|
||||
ExternalProject_Add(googletest PREFIX googletest
|
||||
URL ${CMAKE_CURRENT_SOURCE_DIR}/googletest-release-1.8.0.tar.gz
|
||||
URL_MD5 16877098823401d1bf2ed7891d7dce36
|
||||
CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=<INSTALL_DIR> -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE})
|
||||
|
||||
ExternalProject_Get_Property(googletest INSTALL_DIR)
|
||||
file(MAKE_DIRECTORY ${INSTALL_DIR}/include)
|
||||
|
||||
add_library(gtest STATIC IMPORTED GLOBAL)
|
||||
add_dependencies(gtest googletest)
|
||||
set_property(TARGET gtest PROPERTY IMPORTED_LOCATION ${INSTALL_DIR}/lib/libgtest.a)
|
||||
set_property(TARGET gtest PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${INSTALL_DIR}/include)
|
||||
set_property(TARGET gtest PROPERTY INTERFACE_LINK_LIBRARIES pthread)
|
||||
|
||||
add_library(gmock STATIC IMPORTED GLOBAL)
|
||||
add_dependencies(gmock googletest)
|
||||
set_property(TARGET gmock PROPERTY IMPORTED_LOCATION ${INSTALL_DIR}/lib/libgmock.a)
|
||||
set_property(TARGET gmock PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${INSTALL_DIR}/include)
|
||||
19
version.txt
Normal file
19
version.txt
Normal file
@@ -0,0 +1,19 @@
|
||||
# Generated by autorevision - do not hand-hack!
|
||||
|
||||
VCS_TYPE="git"
|
||||
VCS_BASENAME="stellar"
|
||||
VCS_UUID="4ca8c002ee6c7ebcbb5bc7360b82a391a12d4a63"
|
||||
VCS_NUM="17"
|
||||
VCS_DATE="2022-08-10T02:21:07Z"
|
||||
VCS_BRANCH="dev-liuwentan"
|
||||
VCS_TAG=""
|
||||
VCS_TICK="17"
|
||||
VCS_EXTRA=""
|
||||
|
||||
VCS_ACTION_STAMP="2022-08-10T02:21:07Z!liuwentan@geedgenetworks.com"
|
||||
VCS_FULL_HASH="e5146a6cbeda57a2b5a95fd906f62a59f727be04"
|
||||
VCS_SHORT_HASH="e5146a6"
|
||||
|
||||
VCS_WC_MODIFIED="1"
|
||||
|
||||
# end
|
||||
Reference in New Issue
Block a user