Merge branch develop-0.0

This commit is contained in:
liuwentan
2022-08-11 09:38:38 +08:00
87 changed files with 9132 additions and 522 deletions

253
.gitlab-ci.yml Normal file
View 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

View File

@@ -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)

View File

@@ -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
View 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
View 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

View 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
View 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

View 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
View 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
View 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
View File

@@ -0,0 +1 @@
/sbin/ldconfig

1
cmake/PostUninstall.in Normal file
View File

@@ -0,0 +1 @@
/sbin/ldconfig

1
cmake/PreUninstall.in Normal file
View File

@@ -0,0 +1 @@
/sbin/ldconfig

View File

@@ -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
View File

@@ -0,0 +1 @@
install(DIRECTORY stellar DESTINATION conf COMPONENT Profile)

3
deps/sds/CMakeLists.txt vendored Normal file
View 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

File diff suppressed because it is too large Load Diff

274
deps/sds/sds.h vendored Normal file
View 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
View 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
View 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
View 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
View 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
View 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
View 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

File diff suppressed because it is too large Load Diff

175
deps/toml/toml.h vendored Normal file
View 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 */

View File

@@ -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
View File

@@ -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;

View File

@@ -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>

View File

@@ -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>

View File

@@ -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;

View File

@@ -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>

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 17 KiB

100
readme.md Normal file
View 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?
![stellar-high-level-design](./docs/imgs/stellar-high-level-design.svg)
## 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);
}
}
```

View File

@@ -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 "")

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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"

View 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"

View 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
View 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;
};
};

View File

@@ -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);

View File

@@ -1,5 +1,3 @@
#pragma once
#include <stdint.h>
struct packet;
struct stellar_packet;

View File

@@ -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

View File

@@ -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

View File

@@ -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,

View File

@@ -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)

View File

@@ -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;
}

View File

@@ -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);

View File

@@ -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);
}
}
}

View File

@@ -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;
}

View File

@@ -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);
}
}

View File

@@ -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);

View File

@@ -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);
}
}

View File

@@ -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);

View File

@@ -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);
}
}

View File

@@ -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);

View File

@@ -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);
}
}

View File

@@ -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);

View File

@@ -4,7 +4,7 @@ add_executable(gtest_packet_io
target_link_libraries(
gtest_packet_io
gtest_main
gtest
packet_io
dl
pcap

View File

@@ -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)

View File

@@ -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)

View File

@@ -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

View File

@@ -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

View 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;
}

View 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

View 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);
}
}
}

View 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

View 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';
}
}

View 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

View 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 ./)

View 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;
}

View File

@@ -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"

View File

@@ -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"

View File

@@ -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

View File

@@ -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 "")

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -2,4 +2,5 @@
add_library(http
http.cpp
)
)
target_include_directories(http PUBLIC ${CMAKE_SOURCE_DIR})

View File

@@ -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;
}

View File

@@ -1,4 +1,4 @@
add_library(session_manager
session_manager.cpp
)
)
target_include_directories(session_manager PUBLIC ${CMAKE_SOURCE_DIR})

View File

@@ -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;
}

View File

@@ -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);

View File

@@ -7,7 +7,7 @@ add_executable(gtest_stellar
target_link_libraries(
gtest_stellar
gtest_main
gtest
)
include(GoogleTest)

31
vendor/CMakeLists.txt vendored
View File

@@ -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
View 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