diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml new file mode 100644 index 0000000..fe33922 --- /dev/null +++ b/.gitlab-ci.yml @@ -0,0 +1,134 @@ +image: "docker:stable" + +services: + - docker:dind + +variables: + GIT_STRATEGY: "clone" + IMAGE_TAG: $CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG + +stages: + - build + - fvt + - package + - release + +.build_before_script: + before_script: + - mkdir -p /tmp/padding_for_CPACK_RPM_BUILD_SOURCE_DIRS_PREFIX/$CI_PROJECT_NAMESPACE/ + - ln -s $CI_PROJECT_DIR /tmp/padding_for_CPACK_RPM_BUILD_SOURCE_DIRS_PREFIX/$CI_PROJECT_PATH + - cd /tmp/padding_for_CPACK_RPM_BUILD_SOURCE_DIRS_PREFIX/$CI_PROJECT_PATH + +.build_ntc_radius_plug: + extends: .build_before_script + image: git.mesalab.cn:7443/mesa_platform/radius:master + script: + - source /etc/profile.d/MESA.sh + - mkdir -p build + - cd build + - cmake .. -DCMAKE_BUILD_TYPE=$BUILD_TYPE + - make + - make package + +.fvt: + script: + - source /etc/profile.d/MESA.sh + - rpm -ivh ./build/*.rpm + - sed -i 's/LOG_LEVEL=30/LOG_LEVEL=10/g' /home/mesasoft/sapp_run/conf/radius/radius.conf + - sed -i 's/.\/plug\/business\/gtest_sapp\/gtest_sapp.inf/#.\/plug\/business\/gtest_sapp\/gtest_sapp.inf/g' /home/mesasoft/sapp_run/plug/conflist.inf + - sed -i 's/.\/plug\/business\/test_app\/test_app.inf/#.\/plug\/business\/test_app\/test_app.inf/g' /home/mesasoft/sapp_run/plug/conflist.inf + - cd /home/mesasoft/ + - git clone https://$USER_NAME:$CI_TOKEN@git.mesalab.cn/tango/fvt.git + - cd fvt/ + - sh +x fvt_verify.sh /home/mesasoft/sapp_run/ /home/mesasoft/sapp_run/conf/radius/radius_maat.json /home/mesasoft/sapp_run/log/ntc_radius_plug/ntc_radius_plug /home/mesasoft/fvt/radius/ + +.package_ntc_radius_plug: + extends: .build_before_script + image: git.mesalab.cn:7443/mesa_platform/radius:master + script: + - source /etc/profile.d/MESA.sh + - mkdir -p build + - cd build + - cmake .. -DCMAKE_BUILD_TYPE=$BUILD_TYPE + - make package + +build: + stage: build + extends: .build_ntc_radius_plug + tags: + - share + variables: + BUILD_TYPE: "Release" + artifacts: + name: "$CI_JOB_NAME-$CI_COMMIT_SHORT_SHA" + paths: + - ./build/*.rpm + except: + - tags + +fvt: + stage: fvt + image: git.mesalab.cn:7443/mesa_platform/radius:master + extends: .fvt + tags: + - share + except: + - tags + +ntc_radius_plug-release-package: + stage: package + extends: .package_ntc_radius_plug + tags: + - share + variables: + BUILD_TYPE: "Release" + artifacts: + name: "$CI_JOB_NAME-$CI_COMMIT_REF_NAME" + paths: + - ./build/*.rpm + expire_in: "2 years" + only: + - tags + +ntc_radius_plug-debug-package: + stage: package + extends: .package_ntc_radius_plug + tags: + - share + variables: + BUILD_TYPE: "Debug" + artifacts: + name: "$CI_JOB_NAME-$CI_COMMIT_REF_NAME" + paths: + - ./build/*.rpm + expire_in: "2 years" + only: + - tags + +release-ntc_radius_plug-release: + stage: release + image: git.mesalab.cn:7443/mesa_platform/radius:master + tags: + - share + only: + - tags + variables: + ARTIFACTS_JOB: "ntc_radius_plug-release-package" + PROJECT_NAME: "ntc_radius_plug" + USER_DEFINE: "release" + script: + - /bin/bash -x ./autorelease.sh $CI_API_V4_URL $CI_PROJECT_URL $CI_PROJECT_ID $CI_TOKEN $CI_COMMIT_TAG $ARTIFACTS_JOB $CI_PROJECT_NAME $USER_DEFINE + +release-ntc_radius_plug-debug: + stage: release + image: git.mesalab.cn:7443/mesa_platform/radius:master + tags: + - share + only: + - tags + variables: + ARTIFACTS_JOB: "ntc_radius_plug-debug-package" + PROJECT_NAME: "ntc_radius_plug" + USER_DEFINE: "debug" + script: + - /bin/bash -x ./autorelease.sh $CI_API_V4_URL $CI_PROJECT_URL $CI_PROJECT_ID $CI_TOKEN $CI_COMMIT_TAG $ARTIFACTS_JOB $CI_PROJECT_NAME $USER_DEFINE diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..5745582 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,38 @@ +cmake_minimum_required (VERSION 2.8) + +project(ntc_radius_plug) + +set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake) +include(Version) + +set(CMAKE_MACOSX_RPATH 0) + +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g") + +include_directories(/opt/MESA/include/) + +option(ENABLE_WARNING_ALL "Enable all optional warnings which are desirable for normal code" TRUE) +option(ENABLE_SANITIZE_ADDRESS "Enable AddressSanitizer" FALSE) +option(ENABLE_SANITIZE_THREAD "Enable ThreadSanitizer" FALSE) + +if(ENABLE_SANITIZE_ADDRESS) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address -fno-omit-frame-pointer") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address -fno-omit-frame-pointer") + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -lasan") + set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -lasan") +elseif(ENABLE_SANITIZE_THREAD) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=thread -fno-omit-frame-pointer") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=thread -fno-omit-frame-pointer") + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -lasan") + set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -lasan") +endif() + +set(CMAKE_INSTALL_PREFIX /home/mesasoft/sapp_run) + +add_subdirectory (src) + +SET(CPACK_RPM_PRE_INSTALL_SCRIPT_FILE "${PROJECT_SOURCE_DIR}/preinstall/install.sh") +SET(CPACK_RPM_PRE_UNINSTALL_SCRIPT_FILE "${PROJECT_SOURCE_DIR}/preinstall/uninstall.sh") + +include(Package) diff --git a/autorelease.sh b/autorelease.sh new file mode 100644 index 0000000..34eaefb --- /dev/null +++ b/autorelease.sh @@ -0,0 +1,34 @@ +#!/bin/sh +if [ $# -lt 8 ] ; then + echo "USAGE: ./autorelease.sh [API_V4_URL] [PROJECT_URL] + [PROJECT_ID] [TOKEN] + [COMMIT_TAG] [JOB] [PROJECT_NAME] [USER_DEFINE]" + echo "$1; $2; $3; $4; $5; $6; $7; $8" +exit 1; +fi + +CI_API_V4_URL=$1 +CI_PROJECT_URL=$2 +CI_PROJECT_ID=$3 +CI_TOKEN=$4 +CI_COMMIT_TAG=$5 +ARTIFACTS_JOB=$6 +CI_PROJECT_NAME=$7 +USER_DEFINE=$8 + +res=`echo -e "curl --header \"PRIVATE-TOKEN: $CI_TOKEN\" $CI_API_V4_URL/projects/$CI_PROJECT_ID/releases/$CI_COMMIT_TAG -o /dev/null -s -w %{http_code}"| /bin/bash` + +if [[ $res == "200" ]]; then + eval $(echo -e "curl --request POST --header \"PRIVATE-TOKEN: $CI_TOKEN\" \ + --data name=\"$CI_PROJECT_NAME-$USER_DEFINE-$CI_COMMIT_TAG.zip\" \ + --data url=\"$CI_PROJECT_URL/-/jobs/artifacts/$CI_COMMIT_TAG/download?job=$ARTIFACTS_JOB\"\ + $CI_API_V4_URL/projects/$CI_PROJECT_ID/releases/$CI_COMMIT_TAG/assets/links") +else + eval $(echo -e "curl --header 'Content-Type: application/json' --header \ + \"PRIVATE-TOKEN: $CI_TOKEN\" --data '{ \"name\": \"$CI_COMMIT_TAG\", \ + \"tag_name\": \"$CI_COMMIT_TAG\", \"description\": \"auto_release\",\ + \"assets\": { \"links\": [{ \"name\": \ + \"$CI_PROJECT_NAME-$USER_DEFINE-$CI_COMMIT_TAG.zip\", \"url\": \ + \"$CI_PROJECT_URL/-/jobs/artifacts/$CI_COMMIT_TAG/download?job=$ARTIFACTS_JOB\"\ + }] } }' --request POST $CI_API_V4_URL/projects/$CI_PROJECT_ID/releases/") +fi \ No newline at end of file diff --git a/autorevision.sh b/autorevision.sh new file mode 100644 index 0000000..3baa179 --- /dev/null +++ b/autorevision.sh @@ -0,0 +1,1268 @@ +#!/bin/sh + +# Copyright (c) 2012 - 2016 dak180 and contributors. See +# https://opensource.org/licenses/mit-license.php or the included +# COPYING.md for licence terms. +# +# autorevision - extracts metadata about the head version from your +# repository. + +# Usage message. +arUsage() { + cat > "/dev/stderr" << EOF +usage: autorevision {-t output-type | -s symbol} [-o cache-file [-f] ] [-V] + Options include: + -t output-type = specify output type + -s symbol = specify symbol output + -o cache-file = specify cache file location + -f = force the use of cache data + -U = check for untracked files in svn + -V = emit version and exit + -? = help message + +The following are valid output types: + clojure = clojure file + c = C/C++ file + h = Header for use with c/c++ + hpp = Alternate C++ header strings with namespace + ini = INI file + java = Java file + javaprop = Java properties file + js = javascript file + json = JSON file + lua = Lua file + m4 = m4 file + matlab = matlab file + octave = octave file + php = PHP file + pl = Perl file + py = Python file + rpm = rpm file + scheme = scheme file + sh = Bash sytax + swift = Swift file + tex = (La)TeX file + xcode = Header useful for populating info.plist files + cmake = CMake file + + +The following are valid symbols: + VCS_TYPE + VCS_BASENAME + VCS_UUID + VCS_NUM + VCS_DATE + VCS_BRANCH + VCS_TAG + VCS_TICK + VCS_EXTRA + VCS_FULL_HASH + VCS_SHORT_HASH + VCS_WC_MODIFIED + VCS_ACTION_STAMP +EOF + exit 1 +} + +# Config +ARVERSION="&&ARVERSION&&" +TARGETFILE="/dev/stdout" +while getopts ":t:o:s:VfU" OPTION; do + case "${OPTION}" in + t) + AFILETYPE="${OPTARG}" + ;; + o) + CACHEFILE="${OPTARG}" + ;; + f) + CACHEFORCE="1" + ;; + s) + VAROUT="${OPTARG}" + ;; + U) + UNTRACKEDFILES="1" + ;; + V) + echo "autorevision ${ARVERSION}" + exit 0 + ;; + ?) + # If an unknown flag is used (or -?): + arUsage + ;; + esac +done + +if [ ! -z "${VAROUT}" ] && [ ! -z "${AFILETYPE}" ]; then + # If both -s and -t are specified: + echo "error: Improper argument combination." 1>&2 + exit 1 +elif [ -z "${VAROUT}" ] && [ -z "${AFILETYPE}" ]; then + # If neither -s or -t are specified: + arUsage +elif [ -z "${CACHEFILE}" ] && [ "${CACHEFORCE}" = "1" ]; then + # If -f is specified without -o: + arUsage +elif [ ! -f "${CACHEFILE}" ] && [ "${CACHEFORCE}" = "1" ]; then + # If we are forced to use the cache but it does not exist. + echo "error: Cache forced but no cache found." 1>&2 + exit 1 +fi + +# Make sure that the path we are given is one we can source +# (dash, we are looking at you). +if [ ! -z "${CACHEFILE}" ] && ! echo "${CACHEFILE}" | grep -q '^\.*/'; then + CACHEFILE="./${CACHEFILE}" +fi + +GENERATED_HEADER="Generated by autorevision - do not hand-hack!" + +# Functions to extract data from different repo types. +# For git repos +# shellcheck disable=SC2039,SC2164,SC2155 +gitRepo() { + local oldPath="${PWD}" + + cd "$(git rev-parse --show-toplevel)" + + VCS_TYPE="git" + + VCS_BASENAME="$(basename "${PWD}")" + + VCS_UUID="$(git rev-list --max-parents=0 --date-order --reverse HEAD 2>/dev/null | sed -n 1p)" + if [ -z "${VCS_UUID}" ]; then + VCS_UUID="$(git rev-list --topo-order HEAD | tail -n 1)" + fi + + # Is the working copy clean? + test -z "$(git status --untracked-files=normal --porcelain)" + VCS_WC_MODIFIED="${?}" + + # Enumeration of changesets + VCS_NUM="$(git rev-list --count HEAD 2>/dev/null)" + if [ -z "${VCS_NUM}" ]; then + echo "warning: Counting the number of revisions may be slower due to an outdated git version less than 1.7.2.3. If something breaks, please update it." 1>&2 + VCS_NUM="$(git rev-list HEAD | wc -l)" + fi + + # This may be a git-svn remote. If so, report the Subversion revision. + if [ -z "$(git config svn-remote.svn.url 2>/dev/null)" ]; then + # The full revision hash + VCS_FULL_HASH="$(git rev-parse HEAD)" + + # The short hash + VCS_SHORT_HASH="$(echo "${VCS_FULL_HASH}" | cut -b 1-7)" + else + # The git-svn revision number + VCS_FULL_HASH="$(git svn find-rev HEAD)" + VCS_SHORT_HASH="${VCS_FULL_HASH}" + fi + + # Current branch + VCS_BRANCH="$(git rev-parse --symbolic-full-name --verify "$(git name-rev --name-only --no-undefined HEAD 2>/dev/null)" 2>/dev/null | sed -e 's:refs/heads/::' | sed -e 's:refs/::')" + + # Cache the description + local DESCRIPTION="$(git describe --long --tags 2>/dev/null)" + + # Current or last tag ancestor (empty if no tags) + VCS_TAG="$(echo "${DESCRIPTION}" | sed -e "s:-g${VCS_SHORT_HASH}\$::" -e 's:-[0-9]*$::')" + + # Distance to last tag or an alias of VCS_NUM if there is no tag + if [ ! -z "${DESCRIPTION}" ]; then + VCS_TICK="$(echo "${DESCRIPTION}" | sed -e "s:${VCS_TAG}-::" -e "s:-g${VCS_SHORT_HASH}::")" + else + VCS_TICK="${VCS_NUM}" + fi + + # Date of the current commit + VCS_DATE="$(TZ=UTC git show -s --date=iso-strict-local --pretty=format:%ad | sed -e 's|+00:00|Z|')" + if [ -z "${VCS_DATE}" ]; then + echo "warning: Action stamps require git version 2.7+." 1>&2 + VCS_DATE="$(git log -1 --pretty=format:%ci | sed -e 's: :T:' -e 's: ::' -e 's|+00:00|Z|')" + local ASdis="1" + fi + + # Action Stamp + if [ -z "${ASdis}" ]; then + VCS_ACTION_STAMP="${VCS_DATE}!$(git show -s --pretty=format:%cE)" + else + VCS_ACTION_STAMP="" + fi + + cd "${oldPath}" +} + +# For hg repos +# shellcheck disable=SC2039,SC2164 +hgRepo() { + local oldPath="${PWD}" + + cd "$(hg root)" + + VCS_TYPE="hg" + + VCS_BASENAME="$(basename "${PWD}")" + + VCS_UUID="$(hg log -r "0" -l 1 --template '{node}\n')" + + # Is the working copy clean? + test -z "$(hg status -duram)" + VCS_WC_MODIFIED="${?}" + + # Enumeration of changesets + VCS_NUM="$(hg id -n | tr -d '+')" + + # The full revision hash + VCS_FULL_HASH="$(hg log -r "${VCS_NUM}" -l 1 --template '{node}\n')" + + # The short hash + VCS_SHORT_HASH="$(hg id -i | tr -d '+')" + + # Current bookmark (bookmarks are roughly equivalent to git's branches) + # or branch if no bookmark + VCS_BRANCH="$(hg id -B | cut -d ' ' -f 1)" + # Fall back to the branch if there are no bookmarks + if [ -z "${VCS_BRANCH}" ]; then + VCS_BRANCH="$(hg id -b)" + fi + + # Current or last tag ancestor (excluding auto tags, empty if no tags) + VCS_TAG="$(hg log -r "${VCS_NUM}" -l 1 --template '{latesttag}\n' 2>/dev/null | sed -e 's:qtip::' -e 's:tip::' -e 's:qbase::' -e 's:qparent::' -e "s:$(hg --config 'extensions.color=' --config 'extensions.mq=' --color never qtop 2>/dev/null)::" | cut -d ' ' -f 1)" + + # Distance to last tag or an alias of VCS_NUM if there is no tag + if [ ! -z "${VCS_TAG}" ]; then + VCS_TICK="$(hg log -r "${VCS_NUM}" -l 1 --template '{latesttagdistance}\n' 2>/dev/null)" + else + VCS_TICK="${VCS_NUM}" + fi + + # Date of the current commit + VCS_DATE="$(hg log -r "${VCS_NUM}" -l 1 --template '{date|isodatesec}\n' 2>/dev/null | sed -e 's: :T:' -e 's: ::' -e 's|+00:00|Z|')" + + # Action Stamp + VCS_ACTION_STAMP="$(TZ=UTC hg log -r "${VCS_NUM}" -l 1 --template '{date|localdate|rfc3339date}\n' 2>/dev/null | sed -e 's|+00:00|Z|')!$(hg log -r "${VCS_NUM}" -l 1 --template '{author|email}\n' 2>/dev/null)" + + cd "${oldPath}" +} + +# For bzr repos +# shellcheck disable=SC2039,SC2164 +bzrRepo() { + local oldPath="${PWD}" + + cd "$(bzr root)" + + VCS_TYPE="bzr" + + VCS_BASENAME="$(basename "${PWD}")" + + # Currently unimplemented because more investigation is needed. + VCS_UUID="" + + # Is the working copy clean? + bzr version-info --custom --template='{clean}\n' | grep -q '1' + VCS_WC_MODIFIED="${?}" + + # Enumeration of changesets + VCS_NUM="$(bzr revno)" + + # The full revision hash + VCS_FULL_HASH="$(bzr version-info --custom --template='{revision_id}\n')" + + # The short hash + VCS_SHORT_HASH="${VCS_NUM}" + + # Nick of the current branch + VCS_BRANCH="$(bzr nick)" + + # Current or last tag ancestor (excluding auto tags, empty if no tags) + VCS_TAG="$(bzr tags --sort=time | sed '/?$/d' | tail -n1 | cut -d ' ' -f1)" + + # Distance to last tag or an alias of VCS_NUM if there is no tag + if [ ! -z "${VCS_TAG}" ]; then + VCS_TICK="$(bzr log --line -r "tag:${VCS_TAG}.." | tail -n +2 | wc -l | sed -e 's:^ *::')" + else + VCS_TICK="${VCS_NUM}" + fi + + # Date of the current commit + VCS_DATE="$(bzr version-info --custom --template='{date}\n' | sed -e 's: :T:' -e 's: ::')" + + # Action Stamp + # Currently unimplemented because more investigation is needed. + VCS_ACTION_STAMP="" + + cd "${oldPath}" +} + +# For svn repos +# shellcheck disable=SC2039,SC2164,SC2155 +svnRepo() { + local oldPath="${PWD}" + + VCS_TYPE="svn" + + case "${PWD}" in + /*trunk*|/*branches*|/*tags*) + local fn="${PWD}" + while [ "$(basename "${fn}")" != 'trunk' ] && [ "$(basename "${fn}")" != 'branches' ] && [ "$(basename "${fn}")" != 'tags' ] && [ "$(basename "${fn}")" != '/' ]; do + local fn="$(dirname "${fn}")" + done + local fn="$(dirname "${fn}")" + if [ "${fn}" = '/' ]; then + VCS_BASENAME="$(basename "${PWD}")" + else + VCS_BASENAME="$(basename "${fn}")" + fi + ;; + *) VCS_BASENAME="$(basename "${PWD}")" ;; + esac + + VCS_UUID="$(svn info --xml | sed -n -e 's:::' -e 's:::p')" + + # Cache svnversion output + local SVNVERSION="$(svnversion)" + + # Is the working copy clean? + echo "${SVNVERSION}" | grep -q "M" + case "${?}" in + 0) + VCS_WC_MODIFIED="1" + ;; + 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 + VCS_WC_MODIFIED="0" + fi + ;; + esac + + # Enumeration of changesets + VCS_NUM="$(echo "${SVNVERSION}" | cut -d : -f 1 | sed -e 's:M::' -e 's:S::' -e 's:P::')" + + # The full revision hash + VCS_FULL_HASH="${SVNVERSION}" + + # The short hash + VCS_SHORT_HASH="${VCS_NUM}" + + # Current branch + case "${PWD}" in + /*trunk*|/*branches*|/*tags*) + local lastbase="" + local fn="${PWD}" + while : + do + base="$(basename "${fn}")" + if [ "${base}" = 'trunk' ]; then + VCS_BRANCH='trunk' + break + elif [ "${base}" = 'branches' ] || [ "${base}" = 'tags' ]; then + VCS_BRANCH="${lastbase}" + break + elif [ "${base}" = '/' ]; then + VCS_BRANCH="" + break + fi + local lastbase="${base}" + local fn="$(dirname "${fn}")" + done + ;; + *) VCS_BRANCH="" ;; + esac + + # Current or last tag ancestor (empty if no tags). But "current + # tag" can't be extracted reliably because Subversion doesn't + # have tags the way other VCSes do. + VCS_TAG="" + VCS_TICK="" + + # Date of the current commit + VCS_DATE="$(svn info --xml | sed -n -e 's:::' -e 's:::p')" + + # Action Stamp + VCS_ACTION_STAMP="${VCS_DATE}!$(svn log --xml -l 1 -r "${VCS_SHORT_HASH}" | sed -n -e 's:::' -e 's:::p')" + + cd "${oldPath}" +} + + +# Functions to output data in different formats. +# For bash output +shOutput() { + cat > "${TARGETFILE}" << EOF +# ${GENERATED_HEADER} + +VCS_TYPE="${VCS_TYPE}" +VCS_BASENAME="${VCS_BASENAME}" +VCS_UUID="${VCS_UUID}" +VCS_NUM="${VCS_NUM}" +VCS_DATE="${VCS_DATE}" +VCS_BRANCH="${VCS_BRANCH}" +VCS_TAG="${VCS_TAG}" +VCS_TICK="${VCS_TICK}" +VCS_EXTRA="${VCS_EXTRA}" + +VCS_ACTION_STAMP="${VCS_ACTION_STAMP}" +VCS_FULL_HASH="${VCS_FULL_HASH}" +VCS_SHORT_HASH="${VCS_SHORT_HASH}" + +VCS_WC_MODIFIED="${VCS_WC_MODIFIED}" + +# end +EOF +} + +# For source C output +cOutput() { + cat > "${TARGETFILE}" << EOF +/* ${GENERATED_HEADER} */ + +const char *VCS_TYPE = "${VCS_TYPE}"; +const char *VCS_BASENAME = "${VCS_BASENAME}"; +const char *VCS_UUID = "${VCS_UUID}"; +const int VCS_NUM = ${VCS_NUM}; +const char *VCS_DATE = "${VCS_DATE}"; +const char *VCS_BRANCH = "${VCS_BRANCH}"; +const char *VCS_TAG = "${VCS_TAG}"; +const int VCS_TICK = ${VCS_TICK}; +const char *VCS_EXTRA = "${VCS_EXTRA}"; + +const char *VCS_ACTION_STAMP = "${VCS_ACTION_STAMP}"; +const char *VCS_FULL_HASH = "${VCS_FULL_HASH}"; +const char *VCS_SHORT_HASH = "${VCS_SHORT_HASH}"; + +const int VCS_WC_MODIFIED = ${VCS_WC_MODIFIED}; + +/* end */ +EOF +} + +# For header output +hOutput() { + cat > "${TARGETFILE}" << EOF +/* ${GENERATED_HEADER} */ +#ifndef AUTOREVISION_H +#define AUTOREVISION_H + +#define VCS_TYPE "${VCS_TYPE}" +#define VCS_BASENAME "${VCS_BASENAME}" +#define VCS_UUID "${VCS_UUID}" +#define VCS_NUM ${VCS_NUM} +#define VCS_DATE "${VCS_DATE}" +#define VCS_BRANCH "${VCS_BRANCH}" +#define VCS_TAG "${VCS_TAG}" +#define VCS_TICK ${VCS_TICK} +#define VCS_EXTRA "${VCS_EXTRA}" + +#define VCS_ACTION_STAMP "${VCS_ACTION_STAMP}" +#define VCS_FULL_HASH "${VCS_FULL_HASH}" +#define VCS_SHORT_HASH "${VCS_SHORT_HASH}" + +#define VCS_WC_MODIFIED ${VCS_WC_MODIFIED} + +#endif + +/* end */ +EOF +} + +# A header output for use with xcode to populate info.plist strings +xcodeOutput() { + cat > "${TARGETFILE}" << EOF +/* ${GENERATED_HEADER} */ +#ifndef AUTOREVISION_H +#define AUTOREVISION_H + +#define VCS_TYPE ${VCS_TYPE} +#define VCS_BASENAME ${VCS_BASENAME} +#define VCS_UUID ${VCS_UUID} +#define VCS_NUM ${VCS_NUM} +#define VCS_DATE ${VCS_DATE} +#define VCS_BRANCH ${VCS_BRANCH} +#define VCS_TAG ${VCS_TAG} +#define VCS_TICK ${VCS_TICK} +#define VCS_EXTRA ${VCS_EXTRA} + +#define VCS_ACTION_STAMP ${VCS_ACTION_STAMP} +#define VCS_FULL_HASH ${VCS_FULL_HASH} +#define VCS_SHORT_HASH ${VCS_SHORT_HASH} + +#define VCS_WC_MODIFIED ${VCS_WC_MODIFIED} + +#endif + +/* end */ +EOF +} + +# For Swift output +swiftOutput() { + case "${VCS_WC_MODIFIED}" in + 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. + if [ -z "${VCS_UUID}" ]; then + VCS_UUID="nil" + else + VCS_UUID="\"${VCS_UUID}\"" + fi + if [ -z "${VCS_TAG}" ]; then + VCS_TAG="nil" + else + VCS_TAG="\"${VCS_TAG}\"" + fi + : "${VCS_TICK:="nil"}" + if [ -z "${VCS_EXTRA}" ]; then + VCS_EXTRA="nil" + else + VCS_EXTRA="\"${VCS_EXTRA}\"" + fi + if [ -z "${VCS_ACTION_STAMP}" ]; then + VCS_ACTION_STAMP="nil" + else + VCS_ACTION_STAMP="\"${VCS_ACTION_STAMP}\"" + fi + cat > "${TARGETFILE}" << EOF +/* ${GENERATED_HEADER} */ + +let VCS_TYPE = "${VCS_TYPE}" +let VCS_BASENAME = "${VCS_BASENAME}" +let VCS_UUID: String? = ${VCS_UUID} +let VCS_NUM: Int = ${VCS_NUM} +let VCS_DATE = "${VCS_DATE}" +let VCS_BRANCH: String = "${VCS_BRANCH}" +let VCS_TAG: String? = ${VCS_TAG} +let VCS_TICK: Int? = ${VCS_TICK} +let VCS_EXTRA: String? = ${VCS_EXTRA} + +let VCS_ACTION_STAMP: String? = ${VCS_ACTION_STAMP} +let VCS_FULL_HASH: String = "${VCS_FULL_HASH}" +let VCS_SHORT_HASH: String = "${VCS_SHORT_HASH}" + +let VCS_WC_MODIFIED: Bool = ${VCS_WC_MODIFIED} + +/* end */ +EOF +} + +# For Python output +pyOutput() { + case "${VCS_WC_MODIFIED}" in + 0) VCS_WC_MODIFIED="False" ;; + 1) VCS_WC_MODIFIED="True" ;; + esac + cat > "${TARGETFILE}" << EOF +# ${GENERATED_HEADER} + +VCS_TYPE = "${VCS_TYPE}" +VCS_BASENAME = "${VCS_BASENAME}" +VCS_UUID = "${VCS_UUID}" +VCS_NUM = ${VCS_NUM} +VCS_DATE = "${VCS_DATE}" +VCS_BRANCH = "${VCS_BRANCH}" +VCS_TAG = "${VCS_TAG}" +VCS_TICK = ${VCS_TICK} +VCS_EXTRA = "${VCS_EXTRA}" + +VCS_ACTION_STAMP = "${VCS_ACTION_STAMP}" +VCS_FULL_HASH = "${VCS_FULL_HASH}" +VCS_SHORT_HASH = "${VCS_SHORT_HASH}" + +VCS_WC_MODIFIED = ${VCS_WC_MODIFIED} + +# end +EOF +} + +# For Perl output +plOutput() { + cat << EOF +# ${GENERATED_HEADER} + +\$VCS_TYPE = '${VCS_TYPE}'; +\$VCS_BASENAME = '${VCS_BASENAME}'; +\$VCS_UUID = '${VCS_UUID}'; +\$VCS_NUM = ${VCS_NUM}; +\$VCS_DATE = '${VCS_DATE}'; +\$VCS_BRANCH = '${VCS_BRANCH}'; +\$VCS_TAG = '${VCS_TAG}'; +\$VCS_TICK = ${VCS_TICK}; +\$VCS_EXTRA = '${VCS_EXTRA}'; + +\$VCS_ACTION_STAMP = '${VCS_ACTION_STAMP}'; +\$VCS_FULL_HASH = '${VCS_FULL_HASH}'; +\$VCS_SHORT_HASH = '${VCS_SHORT_HASH}'; + +\$VCS_WC_MODIFIED = ${VCS_WC_MODIFIED}; + +# end +1; +EOF +} + +# For lua output +luaOutput() { + case "${VCS_WC_MODIFIED}" in + 0) VCS_WC_MODIFIED="false" ;; + 1) VCS_WC_MODIFIED="true" ;; + esac + cat > "${TARGETFILE}" << EOF +-- ${GENERATED_HEADER} + +VCS_TYPE = "${VCS_TYPE}" +VCS_BASENAME = "${VCS_BASENAME}" +VCS_UUID = "${VCS_UUID}" +VCS_NUM = ${VCS_NUM} +VCS_DATE = "${VCS_DATE}" +VCS_BRANCH = "${VCS_BRANCH}" +VCS_TAG = "${VCS_TAG}" +VCS_TICK = ${VCS_TICK} +VCS_EXTRA = "${VCS_EXTRA}" + +VCS_ACTION_STAMP = "${VCS_ACTION_STAMP}" +VCS_FULL_HASH = "${VCS_FULL_HASH}" +VCS_SHORT_HASH = "${VCS_SHORT_HASH}" + +VCS_WC_MODIFIED = ${VCS_WC_MODIFIED} + +-- end +EOF +} + +# For php output +phpOutput() { + case "${VCS_WC_MODIFIED}" in + 0) VCS_WC_MODIFIED="false" ;; + 1) VCS_WC_MODIFIED="true" ;; + esac + cat > "${TARGETFILE}" << EOF + "${VCS_TYPE}", + "VCS_BASENAME" => "${VCS_BASENAME}", + "VCS_UUID" => "${VCS_UUID}", + "VCS_NUM" => ${VCS_NUM}, + "VCS_DATE" => "${VCS_DATE}", + "VCS_BRANCH" => "${VCS_BRANCH}", + "VCS_TAG" => "${VCS_TAG}", + "VCS_TICK" => ${VCS_TICK}, + "VCS_EXTRA" => "${VCS_EXTRA}", + "VCS_ACTION_STAMP" => "${VCS_ACTION_STAMP}", + "VCS_FULL_HASH" => "${VCS_FULL_HASH}", + "VCS_SHORT_HASH" => "${VCS_SHORT_HASH}", + "VCS_WC_MODIFIED" => ${VCS_WC_MODIFIED} +); + +# end +?> +EOF +} + +# For ini output +iniOutput() { + case "${VCS_WC_MODIFIED}" in + 0) VCS_WC_MODIFIED="false" ;; + 1) VCS_WC_MODIFIED="true" ;; + esac + cat > "${TARGETFILE}" << EOF +; ${GENERATED_HEADER} +[VCS] +VCS_TYPE = "${VCS_TYPE}" +VCS_BASENAME = "${VCS_BASENAME}" +VCS_UUID = "${VCS_UUID}" +VCS_NUM = ${VCS_NUM} +VCS_DATE = "${VCS_DATE}" +VCS_BRANCH = "${VCS_BRANCH}" +VCS_TAG = "${VCS_TAG}" +VCS_TICK = ${VCS_TICK} +VCS_EXTRA = "${VCS_EXTRA}" +VCS_ACTION_STAMP = "${VCS_ACTION_STAMP}" +VCS_FULL_HASH = "${VCS_FULL_HASH}" +VCS_SHORT_HASH = "${VCS_SHORT_HASH}" +VCS_WC_MODIFIED = ${VCS_WC_MODIFIED} +; end +EOF +} + +# For javascript output +jsOutput() { + case "${VCS_WC_MODIFIED}" in + 1) VCS_WC_MODIFIED="true" ;; + 0) VCS_WC_MODIFIED="false" ;; + esac + cat > "${TARGETFILE}" << EOF +/** ${GENERATED_HEADER} */ + +var autorevision = { + VCS_TYPE: "${VCS_TYPE}", + VCS_BASENAME: "${VCS_BASENAME}", + VCS_UUID: "${VCS_UUID}", + VCS_NUM: ${VCS_NUM}, + VCS_DATE: "${VCS_DATE}", + VCS_BRANCH: "${VCS_BRANCH}", + VCS_TAG: "${VCS_TAG}", + VCS_TICK: ${VCS_TICK}, + VCS_EXTRA: "${VCS_EXTRA}", + + VCS_ACTION_STAMP: "${VCS_ACTION_STAMP}", + VCS_FULL_HASH: "${VCS_FULL_HASH}", + VCS_SHORT_HASH: "${VCS_SHORT_HASH}", + + VCS_WC_MODIFIED: ${VCS_WC_MODIFIED} +}; + +/** Node.js compatibility */ +if (typeof module !== 'undefined') { + module.exports = autorevision; +} + +/** end */ +EOF +} + +# For JSON output +jsonOutput() { + case "${VCS_WC_MODIFIED}" in + 1) VCS_WC_MODIFIED="true" ;; + 0) VCS_WC_MODIFIED="false" ;; + esac + cat > "${TARGETFILE}" << EOF +{ + "_comment": "${GENERATED_HEADER}", + "VCS_TYPE": "${VCS_TYPE}", + "VCS_BASENAME": "${VCS_BASENAME}", + "VCS_UUID": "${VCS_UUID}", + "VCS_NUM": ${VCS_NUM}, + "VCS_DATE": "${VCS_DATE}", + "VCS_BRANCH":"${VCS_BRANCH}", + "VCS_TAG": "${VCS_TAG}", + "VCS_TICK": ${VCS_TICK}, + "VCS_EXTRA": "${VCS_EXTRA}", + + "VCS_ACTION_STAMP": "${VCS_ACTION_STAMP}", + "VCS_FULL_HASH": "${VCS_FULL_HASH}", + "VCS_SHORT_HASH": "${VCS_SHORT_HASH}", + + "VCS_WC_MODIFIED": ${VCS_WC_MODIFIED} +} +EOF +} + +# For Java output +javaOutput() { + case "${VCS_WC_MODIFIED}" in + 1) VCS_WC_MODIFIED="true" ;; + 0) VCS_WC_MODIFIED="false" ;; + esac + cat > "${TARGETFILE}" << EOF +/* ${GENERATED_HEADER} */ + +public class autorevision { + public static final String VCS_TYPE = "${VCS_TYPE}"; + public static final String VCS_BASENAME = "${VCS_BASENAME}"; + public static final String VCS_UUID = "${VCS_UUID}"; + public static final long VCS_NUM = ${VCS_NUM}; + public static final String VCS_DATE = "${VCS_DATE}"; + public static final String VCS_BRANCH = "${VCS_BRANCH}"; + public static final String VCS_TAG = "${VCS_TAG}"; + public static final long VCS_TICK = ${VCS_TICK}; + public static final String VCS_EXTRA = "${VCS_EXTRA}"; + + public static final String VCS_ACTION_STAMP = "${VCS_ACTION_STAMP}"; + public static final String VCS_FULL_HASH = "${VCS_FULL_HASH}"; + public static final String VCS_SHORT_HASH = "${VCS_SHORT_HASH}"; + + public static final boolean VCS_WC_MODIFIED = ${VCS_WC_MODIFIED}; +} +EOF +} + +# For Java properties output +javapropOutput() { + case "${VCS_WC_MODIFIED}" in + 1) VCS_WC_MODIFIED="true" ;; + 0) VCS_WC_MODIFIED="false" ;; + esac + cat > "${TARGETFILE}" << EOF +# ${GENERATED_HEADER} + +VCS_TYPE=${VCS_TYPE} +VCS_BASENAME=${VCS_BASENAME} +VCS_UUID=${VCS_UUID} +VCS_NUM=${VCS_NUM} +VCS_DATE=${VCS_DATE} +VCS_BRANCH=${VCS_BRANCH} +VCS_TAG=${VCS_TAG} +VCS_TICK=${VCS_TICK} +VCS_EXTRA=${VCS_EXTRA} + +VCS_ACTION_STAMP=${VCS_ACTION_STAMP} +VCS_FULL_HASH=${VCS_FULL_HASH} +VCS_SHORT_HASH=${VCS_SHORT_HASH} + +VCS_WC_MODIFIED=${VCS_WC_MODIFIED} +EOF +} + +# For m4 output +m4Output() { + cat > "${TARGETFILE}" << EOF +dnl ${GENERATED_HEADER} +define(\`VCS_TYPE', \`${VCS_TYPE}')dnl +define(\`VCS_BASENAME', \`${VCS_BASENAME}')dnl +define(\`VCS_UUID', \`${VCS_UUID}')dnl +define(\`VCS_NUM', \`${VCS_NUM}')dnl +define(\`VCS_DATE', \`${VCS_DATE}')dnl +define(\`VCS_BRANCH', \`${VCS_BRANCH}')dnl +define(\`VCS_TAG', \`${VCS_TAG}')dnl +define(\`VCS_TICK', \`${VCS_TICK}')dnl +define(\`VCS_EXTRA', \`${VCS_EXTRA}')dnl +define(\`VCS_ACTIONSTAMP', \`${VCS_ACTION_STAMP}')dnl +define(\`VCS_FULLHASH', \`${VCS_FULL_HASH}')dnl +define(\`VCS_SHORTHASH', \`${VCS_SHORT_HASH}')dnl +define(\`VCS_WC_MODIFIED', \`${VCS_WC_MODIFIED}')dnl +EOF +} + +# For (La)TeX output +texOutput() { + case "${VCS_WC_MODIFIED}" in + 0) VCS_WC_MODIFIED="false" ;; + 1) VCS_WC_MODIFIED="true" ;; + esac + cat > "${TARGETFILE}" << EOF +% ${GENERATED_HEADER} +\def \vcsType {${VCS_TYPE}} +\def \vcsBasename {${VCS_BASENAME}} +\def \vcsUUID {${VCS_UUID}} +\def \vcsNum {${VCS_NUM}} +\def \vcsDate {${VCS_DATE}} +\def \vcsBranch {${VCS_BRANCH}} +\def \vcsTag {${VCS_TAG}} +\def \vcsTick {${VCS_TICK}} +\def \vcsExtra {${VCS_EXTRA}} +\def \vcsACTIONSTAMP {${VCS_ACTION_STAMP}} +\def \vcsFullHash {${VCS_FULL_HASH}} +\def \vcsShortHash {${VCS_SHORT_HASH}} +\def \vcsWCModified {${VCS_WC_MODIFIED}} +\endinput +EOF +} + +# For scheme output +schemeOutput() { + case "${VCS_WC_MODIFIED}" in + 0) VCS_WC_MODIFIED="#f" ;; + 1) VCS_WC_MODIFIED="#t" ;; + esac + cat > "${TARGETFILE}" << EOF +;; ${GENERATED_HEADER} +(define VCS_TYPE "${VCS_TYPE}") +(define VCS_BASENAME "${VCS_BASENAME}") +(define VCS_UUID "${VCS_UUID}") +(define VCS_NUM ${VCS_NUM}) +(define VCS_DATE "${VCS_DATE}") +(define VCS_BRANCH "${VCS_BRANCH}") +(define VCS_TAG "${VCS_TAG}") +(define VCS_TICK ${VCS_TICK}) +(define VCS_EXTRA "${VCS_EXTRA}") + +(define VCS_ACTION_STAMP "${VCS_ACTION_STAMP}") +(define VCS_FULL_HASH "${VCS_FULL_HASH}") +(define VCS_SHORT_HASH "${VCS_SHORT_HASH}") + +(define VCS_WC_MODIFIED ${VCS_WC_MODIFIED}) +;; end +EOF +} + +# For clojure output +clojureOutput() { + case "${VCS_WC_MODIFIED}" in + 0) VCS_WC_MODIFIED="false" ;; + 1) VCS_WC_MODIFIED="true" ;; + esac + cat > "${TARGETFILE}" << EOF +;; ${GENERATED_HEADER} +(def VCS_TYPE "${VCS_TYPE}") +(def VCS_BASENAME "${VCS_BASENAME}") +(def VCS_UUID "${VCS_UUID}") +(def VCS_NUM ${VCS_NUM}) +(def VCS_DATE "${VCS_DATE}") +(def VCS_BRANCH "${VCS_BRANCH}") +(def VCS_TAG "${VCS_TAG}") +(def VCS_TICK ${VCS_TICK}) +(def VCS_EXTRA "${VCS_EXTRA}") + +(def VCS_ACTION_STAMP "${VCS_ACTION_STAMP}") +(def VCS_FULL_HASH "${VCS_FULL_HASH}") +(def VCS_SHORT_HASH "${VCS_SHORT_HASH}") + +(def VCS_WC_MODIFIED ${VCS_WC_MODIFIED}) +;; end +EOF +} + +# For rpm spec file output +rpmOutput() { + cat > "${TARGETFILE}" << EOF +# ${GENERATED_HEADER} +$([ "${VCS_TYPE}" ] && echo "%define vcs_type ${VCS_TYPE}") +$([ "${VCS_BASENAME}" ] && echo "%define vcs_basename ${VCS_BASENAME}") +$([ "${VCS_UUID}" ] && echo "%define vcs_uuid ${VCS_UUID}") +$([ "${VCS_NUM}" ] && echo "%define vcs_num ${VCS_NUM}") +$([ "${VCS_DATE}" ] && echo "%define vcs_date ${VCS_DATE}") +$([ "${VCS_BRANCH}" ] && echo "%define vcs_branch ${VCS_BRANCH}") +$([ "${VCS_TAG}" ] && echo "%define vcs_tag ${VCS_TAG}") +$([ "${VCS_TICK}" ] && echo "%define vcs_tick ${VCS_TICK}") +$([ "${VCS_EXTRA}" ] && echo "%define vcs_extra ${VCS_EXTRA}") + +$([ "${VCS_ACTION_STAMP}" ] && echo "%define vcs_action_stamp ${VCS_ACTION_STAMP}") +$([ "${VCS_FULL_HASH}" ] && echo "%define vcs_full_hash ${VCS_FULL_HASH}") +$([ "${VCS_SHORT_HASH}" ] && echo "%define vcs_short_hash ${VCS_SHORT_HASH}") + +$([ "${VCS_WC_MODIFIED}" ] && echo "%define vcs_wc_modified ${VCS_WC_MODIFIED}") +# end +EOF +} + +# shellcheck disable=SC2155,SC2039 +hppOutput() { + local NAMESPACE="$(echo "${VCS_BASENAME}" | sed -e 's:_::g' | tr '[:lower:]' '[:upper:]')" + cat > "${TARGETFILE}" << EOF +/* ${GENERATED_HEADER} */ + +#ifndef ${NAMESPACE}_AUTOREVISION_H +#define ${NAMESPACE}_AUTOREVISION_H + +#include + +namespace $(echo "${NAMESPACE}" | tr '[:upper:]' '[:lower:]') +{ + const std::string VCS_TYPE = "${VCS_TYPE}"; + const std::string VCS_BASENAME = "${VCS_BASENAME}"; + const std::string VCS_UUID = "${VCS_UUID}"; + const int VCS_NUM = ${VCS_NUM}; + const std::string VCS_DATE = "${VCS_DATE}"; + const std::string VCS_BRANCH = "${VCS_BRANCH}"; + const std::string VCS_TAG = "${VCS_TAG}"; + const int VCS_TICK = ${VCS_TICK}; + const std::string VCS_EXTRA = "${VCS_EXTRA}"; + + const std::string VCS_ACTION_STAMP = "${VCS_ACTION_STAMP}"; + const std::string VCS_FULL_HASH = "${VCS_FULL_HASH}"; + const std::string VCS_SHORT_HASH = "${VCS_SHORT_HASH}"; + + const int VCS_WC_MODIFIED = ${VCS_WC_MODIFIED}; +} + +#endif + +/* end */ +EOF +} + +matlabOutput() { + case "${VCS_WC_MODIFIED}" in + 0) VCS_WC_MODIFIED="FALSE" ;; + 1) VCS_WC_MODIFIED="TRUE" ;; + esac + cat > "${TARGETFILE}" << EOF +% ${GENERATED_HEADER} + +VCS_TYPE = '${VCS_TYPE}'; +VCS_BASENAME = '${VCS_BASENAME}'; +VCS_UUID = '${VCS_UUID}'; +VCS_NUM = ${VCS_NUM}; +VCS_DATE = '${VCS_DATE}'; +VCS_BRANCH = '${VCS_BRANCH}'; +VCS_TAG = '${VCS_TAG}'; +VCS_TICK = ${VCS_TICK}; +VCS_EXTRA = '${VCS_EXTRA}'; + +VCS_ACTION_STAMP = '${VCS_ACTION_STAMP}'; +VCS_FULL_HASH = '${VCS_FULL_HASH}'; +VCS_SHORT_HASH = '${VCS_SHORT_HASH}'; + +VCS_WC_MODIFIED = ${VCS_WC_MODIFIED}; + +% end +EOF +} + +octaveOutput() { + cat > "${TARGETFILE}" << EOF +% ${GENERATED_HEADER} + +VCS_TYPE = '${VCS_TYPE}'; +VCS_BASENAME = '${VCS_BASENAME}'; +VCS_UUID = '${VCS_UUID}'; +VCS_NUM = ${VCS_NUM}; +VCS_DATE = '${VCS_DATE}'; +VCS_BRANCH = '${VCS_BRANCH}'; +VCS_TAG = '${VCS_TAG}'; +VCS_TICK = ${VCS_TICK}; +VCS_EXTRA = '${VCS_EXTRA}'; + +VCS_ACTION_STAMP = '${VCS_ACTION_STAMP}'; +VCS_FULL_HASH = '${VCS_FULL_HASH}'; +VCS_SHORT_HASH = '${VCS_SHORT_HASH}'; + +VCS_WC_MODIFIED = ${VCS_WC_MODIFIED}; + +% end +EOF +} + +cmakeOutput() { + cat > "${TARGETFILE}" << EOF +# ${GENERATED_HEADER} + +set(VCS_TYPE ${VCS_TYPE}) +set(VCS_BASENAME ${VCS_BASENAME}) +set(VCS_UUID ${VCS_UUID}) +set(VCS_NUM ${VCS_NUM}) +set(VCS_DATE ${VCS_DATE}) +set(VCS_BRANCH ${VCS_BRANCH}) +set(VCS_TAG ${VCS_TAG}) +set(VCS_TICK ${VCS_TICK}) +set(VCS_EXTRA ${VCS_EXTRA}) + +set(VCS_ACTION_STAMP ${VCS_ACTION_STAMP}) +set(VCS_FULL_HASH ${VCS_FULL_HASH}) +set(VCS_SHORT_HASH ${VCS_SHORT_HASH}) + +set(VCS_WC_MODIFIED ${VCS_WC_MODIFIED}) + +# end +EOF +} + + +# Helper functions +# Count path segments +# shellcheck disable=SC2039 +pathSegment() { + local pathz="${1}" + local depth="0" + + if [ ! -z "${pathz}" ]; then + # 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))" + done + fi + echo "${depth}" +} + +# Largest of four numbers +# shellcheck disable=SC2039 +multiCompare() { + local larger="${1}" + local numA="${2}" + local numB="${3}" + local numC="${4}" + + [ "${numA}" -gt "${larger}" ] && larger="${numA}" + [ "${numB}" -gt "${larger}" ] && larger="${numB}" + [ "${numC}" -gt "${larger}" ] && larger="${numC}" + echo "${larger}" +} + +# Test for repositories +# shellcheck disable=SC2155,SC2039 +repoTest() { + REPONUM="0" + if [ ! -z "$(git rev-parse HEAD 2>/dev/null)" ]; then + local gitPath="$(git rev-parse --show-toplevel)" + local gitDepth="$(pathSegment "${gitPath}")" + 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))" + 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))" + else + local bzrDepth="0" + fi + if [ ! -z "$(svn info 2>/dev/null)" ]; then + local stringz="" + local stringx="" + 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 + local svnDepth="1" + else + local svnDepth="$(pathSegment "${svnPath}")" + fi + REPONUM="$((REPONUM+1))" + else + local svnDepth="0" + fi + + # Do not do more work then we have to. + if [ "${REPONUM}" = "0" ]; then + return + fi + + # Figure out which repo is the deepest and use it. + local wonRepo="$(multiCompare "${gitDepth}" "${hgDepth}" "${bzrDepth}" "${svnDepth}")" + if [ "${wonRepo}" = "${gitDepth}" ]; then + gitRepo + elif [ "${wonRepo}" = "${hgDepth}" ]; then + hgRepo + elif [ "${wonRepo}" = "${bzrDepth}" ]; then + bzrRepo + elif [ "${wonRepo}" = "${svnDepth}" ]; then + svnRepo + fi +} + + + +# Detect which repos we are in and gather data. +# shellcheck source=/dev/null +if [ -f "${CACHEFILE}" ] && [ "${CACHEFORCE}" = "1" ]; then + # When requested only read from the cache to populate our symbols. + . "${CACHEFILE}" +else + # If a value is not set through the environment set VCS_EXTRA to nothing. + : "${VCS_EXTRA:=""}" + repoTest + + if [ -f "${CACHEFILE}" ] && [ "${REPONUM}" = "0" ]; then + # We are not in a repo; try to use a previously generated cache to populate our symbols. + . "${CACHEFILE}" + # Do not overwrite the cache if we know we are not going to write anything new. + CACHEFORCE="1" + elif [ "${REPONUM}" = "0" ]; then + echo "error: No repo or cache detected." 1>&2 + exit 1 + fi +fi + + +# -s output is handled here. +if [ ! -z "${VAROUT}" ]; then + if [ "${VAROUT}" = "VCS_TYPE" ]; then + echo "${VCS_TYPE}" + elif [ "${VAROUT}" = "VCS_BASENAME" ]; then + echo "${VCS_BASENAME}" + elif [ "${VAROUT}" = "VCS_NUM" ]; then + echo "${VCS_NUM}" + elif [ "${VAROUT}" = "VCS_DATE" ]; then + echo "${VCS_DATE}" + elif [ "${VAROUT}" = "VCS_BRANCH" ]; then + echo "${VCS_BRANCH}" + elif [ "${VAROUT}" = "VCS_TAG" ]; then + echo "${VCS_TAG}" + elif [ "${VAROUT}" = "VCS_TICK" ]; then + echo "${VCS_TICK}" + elif [ "${VAROUT}" = "VCS_FULL_HASH" ]; then + echo "${VCS_FULL_HASH}" + elif [ "${VAROUT}" = "VCS_SHORT_HASH" ]; then + echo "${VCS_SHORT_HASH}" + elif [ "${VAROUT}" = "VCS_WC_MODIFIED" ]; then + echo "${VCS_WC_MODIFIED}" + elif [ "${VAROUT}" = "VCS_ACTION_STAMP" ]; then + echo "${VCS_ACTION_STAMP}" + else + echo "error: Not a valid output symbol." 1>&2 + exit 1 + fi +fi + + +# Detect requested output type and use it. +if [ ! -z "${AFILETYPE}" ]; then + if [ "${AFILETYPE}" = "c" ]; then + cOutput + elif [ "${AFILETYPE}" = "h" ]; then + hOutput + elif [ "${AFILETYPE}" = "xcode" ]; then + xcodeOutput + elif [ "${AFILETYPE}" = "swift" ]; then + swiftOutput + elif [ "${AFILETYPE}" = "sh" ]; then + shOutput + elif [ "${AFILETYPE}" = "py" ] || [ "${AFILETYPE}" = "python" ]; then + pyOutput + elif [ "${AFILETYPE}" = "pl" ] || [ "${AFILETYPE}" = "perl" ]; then + plOutput + elif [ "${AFILETYPE}" = "lua" ]; then + luaOutput + elif [ "${AFILETYPE}" = "php" ]; then + phpOutput + elif [ "${AFILETYPE}" = "ini" ]; then + iniOutput + elif [ "${AFILETYPE}" = "js" ]; then + jsOutput + elif [ "${AFILETYPE}" = "json" ]; then + jsonOutput + elif [ "${AFILETYPE}" = "java" ]; then + javaOutput + elif [ "${AFILETYPE}" = "javaprop" ]; then + javapropOutput + elif [ "${AFILETYPE}" = "tex" ]; then + texOutput + elif [ "${AFILETYPE}" = "m4" ]; then + m4Output + elif [ "${AFILETYPE}" = "scheme" ]; then + schemeOutput + elif [ "${AFILETYPE}" = "clojure" ]; then + clojureOutput + elif [ "${AFILETYPE}" = "rpm" ]; then + rpmOutput + elif [ "${AFILETYPE}" = "hpp" ]; then + hppOutput + elif [ "${AFILETYPE}" = "matlab" ]; then + matlabOutput + elif [ "${AFILETYPE}" = "octave" ]; then + octaveOutput + elif [ "${AFILETYPE}" = "cmake" ]; then + cmakeOutput + else + echo "error: Not a valid output type." 1>&2 + exit 1 + fi +fi + + +# If requested, make a cache file. +if [ ! -z "${CACHEFILE}" ] && [ ! "${CACHEFORCE}" = "1" ]; then + TARGETFILE="${CACHEFILE}.tmp" + shOutput + + # Check to see if there have been any actual changes. + if [ ! -f "${CACHEFILE}" ]; then + mv -f "${CACHEFILE}.tmp" "${CACHEFILE}" + elif cmp -s "${CACHEFILE}.tmp" "${CACHEFILE}"; then + rm -f "${CACHEFILE}.tmp" + else + mv -f "${CACHEFILE}.tmp" "${CACHEFILE}" + fi +fi diff --git a/bin/ntc_radius_plug.inf b/bin/ntc_radius_plug.inf index f883cb0..0e74f6c 100644 --- a/bin/ntc_radius_plug.inf +++ b/bin/ntc_radius_plug.inf @@ -1,12 +1,9 @@ [PLUGINFO] -PLUGNAME=RADIUS -SO_PATH=./plug/business/radius/radius.so -INIT_FUNC=RADIUS_INIT -DESTROY_FUNC=RADIUS_DESTROY -FLAGCHANGE_FUNC=FLAG_CHANGE -FLAGSTATE_FUNC=PROT_FUNSTAT -GETPLUGID_FUNC=GET_PLUGID +PLUGNAME=NTC_RADIUS_PLUG +SO_PATH=./plug/business/ntc_radius_plug/ntc_radius_plug.so +INIT_FUNC=NTC_RADIUS_PLUG_INIT +DESTROY_FUNC=NTC_RADIUS_PLUG_DESTROY -[UDP] +[RADIUS] FUNC_FLAG=ALL -FUNC_NAME=RADIUS_ENTRY +FUNC_NAME=NTC_RADIUS_PLUG_ENTRY diff --git a/cmake/Package.cmake b/cmake/Package.cmake new file mode 100644 index 0000000..69bc509 --- /dev/null +++ b/cmake/Package.cmake @@ -0,0 +1,41 @@ +if(CMAKE_BUILD_TYPE STREQUAL "Debug") + set(CPACK_PACKAGE_NAME "${PROJECT_NAME}-debug") +else() + set(CPACK_PACKAGE_NAME ${PROJECT_NAME}) +endif() + +message(STATUS "Package: ${CPACK_PACKAGE_NAME}") + +set(CPACK_PACKAGE_VECDOR "MESA") +set(CPACK_PACKAGE_VERSION_MAJOR "${VERSION_MAJOR}") +set(CPACK_PACKAGE_VERSION_MINOR "${VERSION_MINOR}") +set(CPACK_PACKAGE_VERSION_PATCH "${VERSION_PATCH}.${VERSION_BUILD}") +set(CPACK_PACKAGING_INSTALL_PREFIX ${CMAKE_INSTALL_PREFIX}) + +set(CPACK_COMPONENTS_ALL devel) +set(CPACK_RPM_PACKAGE_DEBUG 1) +set(CPACK_RPM_COMPONENT_INSTALL OFF) +set(CPACK_RPM_DEVEL_FILE_NAME "${PROJECT_NAME}-devel.rpm") +set(CPACK_RPM_DEVEL_DEBUGINFO_FILE_NAME "${PROJECT_NAME}-devel-debuginfo.rpm") + +# 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_VENDOR "MESA") +set(CPACK_RPM_PACKAGE_AUTOREQPROV "no") +set(CPACK_RPM_PACKAGE_RELEASE_DIST ON) +set(CPACK_RPM_DEBUGINFO_PACKAGE ON) + + +set(CPACK_BUILD_SOURCE_DIRS "${CMAKE_SOURCE_DIR}") + +# Must uninstall the debug package before install release package +if(CMAKE_BUILD_TYPE STREQUAL "Debug") + set(CPACK_RPM_PACKAGE_CONFLICTS "${PROJECT_NAME}-debug") +else() + set(CPACK_RPM_PACKAGE_CONFLICTS ${PROJECT_NAME}) + # set(CPACK_STRIP_FILES TRUE) +endif() + +include(CPack) diff --git a/cmake/Version.cmake b/cmake/Version.cmake new file mode 100644 index 0000000..752f20f --- /dev/null +++ b/cmake/Version.cmake @@ -0,0 +1,53 @@ + +# Using autorevision.sh to generate version information + +set(__SOURCE_AUTORESIVISION ${CMAKE_SOURCE_DIR}/autorevision.sh) +set(__AUTORESIVISION ${CMAKE_BINARY_DIR}/autorevision.sh) +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) +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}") + +if(NOT VERSION_MAJOR) + set(VERSION_MAJOR 1) +endif() + +if(NOT VERSION_MINOR) + set(VERSION_MINOR 0) +endif() + +if(NOT VERSION_PATCH) + set(VERSION_PATCH 0) +endif() + +set(VERSION "${VERSION_MAJOR}_${VERSION_MINOR}_${VERSION_PATCH}") +set(VERSION_BUILD "${VCS_SHORT_HASH}") + +# print information +message(STATUS "Version: ${VERSION}-${VERSION_BUILD}") + +if(NOT DEFINE_GIT_VERSION) + option(DEFINE_GIT_VERSION "Set DEFINE_GIT_VERSION to OFF" OFF) + +set(GIT_VERSION + "${VERSION}-${CMAKE_BUILD_TYPE}-${VERSION_BUILD}-${VCS_BRANCH}-${VCS_TAG}-${VCS_DATE}") +string(REGEX REPLACE "[-:+/\\.]" "_" GIT_VERSION ${GIT_VERSION}) + +if(DEFINE_GIT_VERSION) + add_definitions(-DGIT_VERSION=${GIT_VERSION}) + option(DEFINE_GIT_VERSION "Set DEFINE_GIT_VERSION to OFF" ON) +endif() + +endif() diff --git a/preinstall/install.sh b/preinstall/install.sh new file mode 100644 index 0000000..397e134 --- /dev/null +++ b/preinstall/install.sh @@ -0,0 +1,26 @@ +#!/bin/sh +CONFILE=conf/radius/radius.conf +DST=${RPM_INSTALL_PREFIX} +mkdir -p ${DST}/plug/business/ +touch ${DST}/plug/conflist.inf +mkdir -p ${DST}/conf/ +touch ${DST}/${CONFILE} + +if [[ -z `grep -rn '\[business\]' ${DST}/plug/conflist.inf` ]];then + echo '[business]' >> ${DST}/plug/conflist.inf +fi + +if [[ -z `grep -rn 'ntc_radius_plug.inf' ${DST}/plug/conflist.inf` ]];then + sed -i '/\[business\]/a\./plug/business/ntc_radius_plug/ntc_radius_plug.inf' ${DST}/plug/conflist.inf +fi + +if [[ -z `grep -rn '\[RADIUS_PLUG\]' ${DST}/${CONFILE}` ]];then + sed -i '1i\\[RADIUS_PLUG\]' ${DST}/${CONFILE} + sed -i '/\[RADIUS_PLUG\]/a\LOG_LEVEL=30' ${DST}/${CONFILE} + sed -i '/\[RADIUS_PLUG\]/a\LOG_PATH=./log/ntc_radius_plug/ntc_radius_plug' ${DST}/${CONFILE} + sed -i '/\[RADIUS_PLUG\]/a\NIC_NAME=lo' ${DST}/${CONFILE} + sed -i '/\[RADIUS_PLUG\]/a\SERVICE_ID=162' ${DST}/${CONFILE} + sed -i '/\[RADIUS_PLUG\]/a\COLLECT_TOPIC=RADIUS-RECORD-LOG' ${DST}/${CONFILE} + sed -i '/\[RADIUS_PLUG\]/a\BROKERLIST=127.0.0.1:9092' ${DST}/${CONFILE} + sed -i '/\[RADIUS_PLUG\]/a\DEVICE_ID=0' ${DST}/${CONFILE} +fi diff --git a/preinstall/uninstall.sh b/preinstall/uninstall.sh new file mode 100644 index 0000000..18703b0 --- /dev/null +++ b/preinstall/uninstall.sh @@ -0,0 +1,8 @@ +#!/bin/sh +CONFILE=conf/radius/radius.conf +DST=${RPM_INSTALL_PREFIX} +mkdir -p ${DST}/plug/business/ +touch ${DST}/plug/conflist.inf +touch ${DST}/${CONFILE} +sed -i '/fw_mail_plug.inf/d' ${DST}/plug/conflist.inf +sed -i '/\[RADIUS_PLUG\]/,+7d' ${DST}/${CONFILE} diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt new file mode 100644 index 0000000..54efa98 --- /dev/null +++ b/src/CMakeLists.txt @@ -0,0 +1,17 @@ +cmake_minimum_required(VERSION 2.8) + +add_definitions(-fPIC) + +set(SRC ntc_radius_plug.cpp) + +include_directories(${CMAKE_SOURCE_DIR}/src) +include_directories(/opt/MESA/include/) + +set(DEPEND_DYN_LIB MESA_handle_logger MESA_prof_load cjson rdkafka) + +add_library(ntc_radius_plug SHARED ${SRC}) +target_link_libraries(ntc_radius_plug ${DEPEND_DYN_LIB}) +set_target_properties(ntc_radius_plug PROPERTIES PREFIX "") + +install(TARGETS ntc_radius_plug DESTINATION ${CMAKE_INSTALL_PREFIX}/plug/business/ntc_radius_plug) +install(FILES ../bin/ntc_radius_plug.inf DESTINATION ${CMAKE_INSTALL_PREFIX}/plug/business/ntc_radius_plug) diff --git a/src/ntc_radius_plug.cpp b/src/ntc_radius_plug.cpp index 28f1c51..4b9598c 100644 --- a/src/ntc_radius_plug.cpp +++ b/src/ntc_radius_plug.cpp @@ -25,8 +25,30 @@ #include "ntc_radius_plug.h" -static int NTC_RADIUS_PLUG_VERSION_20191022=0; -const char *config_file="t1conf/main.conf"; +#ifdef __cplusplus +extern "C" +{ +#endif + +#define GIT_VERSION_CATTER(v) __attribute__((__used__)) const char * GIT_VERSION_##v = NULL +#define GIT_VERSION_EXPEND(v) GIT_VERSION_CATTER(v) + +/* VERSION TAG */ +#ifdef GIT_VERSION +GIT_VERSION_EXPEND(GIT_VERSION); +#else +static __attribute__((__used__)) const char * GIT_VERSION_UNKNOWN = NULL; +#endif +#undef GIT_VERSION_CATTER +#undef GIT_VERSION_EXPEND + +#ifdef __cplusplus +} +#endif + + +static int NTC_RADIUS_PLUG_VERSION_20191211=0; +const char *config_file="conf/radius/radius.conf"; g_ntc_radius_plug_t g_ntc_radius_plug; @@ -65,88 +87,157 @@ error: } -int get_radius_object_element(cJSON *radius_info_object, radius_header_t *radius_header, radius_body_t *radius_body) +int get_radius_object_element(cJSON *radius_info_object, cJSON *radius_debug, radius_header_t *radius_header, radius_body_t *radius_body, int *account_index) { int i=0; - cJSON *radius_json_obj = radius_info_object; - cJSON_AddNumberToObject(radius_json_obj, "CODE", radius_header->code); + cJSON_AddNumberToObject(radius_debug, "radius_packet_type", radius_header->code); + cJSON_AddNumberToObject(radius_info_object, "radius_packet_type", radius_header->code); for(i=0; iattribute_num; i++) { switch(radius_body->attribute[i].type) { - case RADIUS_USER_NAME: - cJSON_AddStringToObject(radius_json_obj, "user_name", (char *)(radius_body->attribute[i].value)); - break; - case CALLBACK_NUMBER: - cJSON_AddStringToObject(radius_json_obj, "CALLBACK_NUMBER", (char *)(radius_body->attribute[i].value)); - break; - case CALLBACK_ID: - cJSON_AddStringToObject(radius_json_obj, "CALLBACK_ID", (char *)(radius_body->attribute[i].value)); - break; - case CALLED_STATION_ID: - cJSON_AddStringToObject(radius_json_obj, "CALLED_STATION_ID", (char *)(radius_body->attribute[i].value)); - break; - case CALLING_STATION_ID: - cJSON_AddStringToObject(radius_json_obj, "CALLING_STATION_ID", (char *)(radius_body->attribute[i].value)); - break; - case ACCT_SESSION_ID: - cJSON_AddStringToObject(radius_json_obj, "ACCT_SESSION_ID", (char *)(radius_body->attribute[i].value)); - break; - case ACCT_MULTI_SESSION_ID: - cJSON_AddStringToObject(radius_json_obj, "ACCT_MULTI_SESSION_ID", (char *)(radius_body->attribute[i].value)); + case USER_NAME: + cJSON_AddStringToObject(radius_debug, "radius_account", (char *)(radius_body->attribute[i].value)); + cJSON_AddStringToObject(radius_info_object, "radius_account", (char *)(radius_body->attribute[i].value)); + *account_index=i; break; case NAS_IP_ADDRESS: - cJSON_AddStringToObject(radius_json_obj, "NAS_IP_ADDRESS", (char *)(radius_body->attribute[i].value)); + cJSON_AddStringToObject(radius_debug, "radius_nas_ip", (char *)(radius_body->attribute[i].value)); + cJSON_AddStringToObject(radius_info_object, "radius_nas_ip", (char *)(radius_body->attribute[i].value)); break; - case FRAMED_IP_ADDRESS: - cJSON_AddStringToObject(radius_json_obj, "FRAMED_IP_ADDRESS", (char *)(radius_body->attribute[i].value)); - break; - case FRAMED_IP_NETMASK: - cJSON_AddStringToObject(radius_json_obj, "FRAMED_IP_NETMASK", (char *)(radius_body->attribute[i].value)); + case NAS_PORT: + cJSON_AddNumberToObject(radius_debug, "radius_nas_port", *(unsigned int *)(radius_body->attribute[i].value)); + cJSON_AddNumberToObject(radius_info_object, "radius_nas_port", *(unsigned int *)(radius_body->attribute[i].value)); break; case SERVICE_TYPE: - cJSON_AddNumberToObject(radius_json_obj, "SERVICE_TYPE", *(unsigned int *)(radius_body->attribute[i].value)); + cJSON_AddNumberToObject(radius_debug, "radius_service_type", *(unsigned int *)(radius_body->attribute[i].value)); + cJSON_AddNumberToObject(radius_info_object, "radius_service_type", *(unsigned int *)(radius_body->attribute[i].value)); + break; + case FRAMED_PROTOCOL: + cJSON_AddNumberToObject(radius_debug, "radius_framed_protocol", *(unsigned int *)(radius_body->attribute[i].value)); + cJSON_AddNumberToObject(radius_info_object, "radius_framed_protocol", *(unsigned int *)(radius_body->attribute[i].value)); + break; + case FRAMED_IP_ADDRESS: + cJSON_AddStringToObject(radius_debug, "radius_framed_ip", (char *)(radius_body->attribute[i].value)); + cJSON_AddStringToObject(radius_info_object, "radius_framed_ip", (char *)(radius_body->attribute[i].value)); + break; + case FRAMED_IP_NETMASK: + cJSON_AddStringToObject(radius_debug, "radius_framed_ip_netmask", (char *)(radius_body->attribute[i].value)); + break; + case FRAMED_ROUTING: + cJSON_AddNumberToObject(radius_debug, "radius_framed_routing", *(unsigned int *)(radius_body->attribute[i].value)); + break; + case FILTER_ID: + cJSON_AddStringToObject(radius_debug, "radius_filter_id", (char *)(radius_body->attribute[i].value)); break; case FRAMED_MTU: - cJSON_AddNumberToObject(radius_json_obj, "FRAMED_MTU", *(unsigned int *)(radius_body->attribute[i].value)); + cJSON_AddNumberToObject(radius_debug, "radius_framed_mtu", *(unsigned int *)(radius_body->attribute[i].value)); + break; + case FRAMED_COMPRESSION: + cJSON_AddNumberToObject(radius_debug, "radius_framed_compression", *(unsigned int *)(radius_body->attribute[i].value)); + break; + case CALLBACK_NUMBER: + cJSON_AddStringToObject(radius_debug, "radius_callback_number", (char *)(radius_body->attribute[i].value)); + cJSON_AddStringToObject(radius_info_object, "radius_callback_number", (char *)(radius_body->attribute[i].value)); break; + case CALLBACK_ID: + cJSON_AddStringToObject(radius_debug, "radius_callback_id", (char *)(radius_body->attribute[i].value)); + cJSON_AddStringToObject(radius_info_object, "radius_callback_id", (char *)(radius_body->attribute[i].value)); + break; + case CLASS: + cJSON_AddStringToObject(radius_debug, "radius_class", (char *)(radius_body->attribute[i].value)); + break; case SESSION_TIMEOUT: - cJSON_AddNumberToObject(radius_json_obj, "SESSION_TIMEOUT", *(unsigned int *)(radius_body->attribute[i].value)); - break; + cJSON_AddNumberToObject(radius_debug, "radius_session_timeout", *(unsigned int *)(radius_body->attribute[i].value)); + cJSON_AddNumberToObject(radius_info_object, "radius_session_timeout", *(unsigned int *)(radius_body->attribute[i].value)); + break; case IDLE_TIMEOUT: - cJSON_AddNumberToObject(radius_json_obj, "IDLE_TIMEOUT", *(unsigned int *)(radius_body->attribute[i].value)); - break; + cJSON_AddNumberToObject(radius_debug, "radius_idle_timeout", *(unsigned int *)(radius_body->attribute[i].value)); + cJSON_AddNumberToObject(radius_info_object, "radius_idle_timeout", *(unsigned int *)(radius_body->attribute[i].value)); + break; case TERMINATION_ACTION: - cJSON_AddNumberToObject(radius_json_obj, "TERMINATION_ACTION", *(unsigned int *)(radius_body->attribute[i].value)); + cJSON_AddNumberToObject(radius_debug, "radius_termination_action", *(unsigned int *)(radius_body->attribute[i].value)); + cJSON_AddNumberToObject(radius_info_object, "radius_termination_action", *(unsigned int *)(radius_body->attribute[i].value)); + break; + case CALLED_STATION_ID: + cJSON_AddStringToObject(radius_debug, "radius_called_station_id", (char *)(radius_body->attribute[i].value)); + cJSON_AddStringToObject(radius_info_object, "radius_called_station_id", (char *)(radius_body->attribute[i].value)); + break; + case CALLING_STATION_ID: + cJSON_AddStringToObject(radius_debug, "radius_calling_station_id", (char *)(radius_body->attribute[i].value)); + cJSON_AddStringToObject(radius_info_object, "radius_calling_station_id", (char *)(radius_body->attribute[i].value)); + break; + case NAS_IDENTIFIER: + cJSON_AddStringToObject(radius_debug, "radius_nas_indentifies", (char *)(radius_body->attribute[i].value)); break; case PROXY_STATE: - cJSON_AddNumberToObject(radius_json_obj, "PROXY_STATE", *(unsigned int *)(radius_body->attribute[i].value)); + cJSON_AddNumberToObject(radius_debug, "radius_proxy_state", *(unsigned int *)(radius_body->attribute[i].value)); break; case ACCT_STATUS_TYPE: - cJSON_AddNumberToObject(radius_json_obj, "ACCT_STATUS_TYPE", *(unsigned int *)(radius_body->attribute[i].value)); + cJSON_AddNumberToObject(radius_debug, "radius_acct_status_type", *(unsigned int *)(radius_body->attribute[i].value)); + cJSON_AddNumberToObject(radius_info_object, "radius_acct_status_type", *(unsigned int *)(radius_body->attribute[i].value)); + break; + case ACCT_DELAY_TIME: + cJSON_AddNumberToObject(radius_debug, "radius_acct_delay_time", *(unsigned int *)(radius_body->attribute[i].value)); + cJSON_AddNumberToObject(radius_info_object, "radius_acct_delay_time", *(unsigned int *)(radius_body->attribute[i].value)); + break; + case ACCT_SESSION_ID: + cJSON_AddStringToObject(radius_debug, "radius_acct_session_id", (char *)(radius_body->attribute[i].value)); + cJSON_AddStringToObject(radius_info_object, "radius_acct_session_id", (char *)(radius_body->attribute[i].value)); + break; + case ACCT_MULTI_SESSION_ID: + cJSON_AddStringToObject(radius_debug, "radius_acct_multi_session_id", (char *)(radius_body->attribute[i].value)); + cJSON_AddStringToObject(radius_info_object, "radius_acct_multi_session_id", (char *)(radius_body->attribute[i].value)); break; case ACCT_INPUT_OCTETS: - cJSON_AddNumberToObject(radius_json_obj, "ACCT_INPUT_OCTETS", *(unsigned int *)(radius_body->attribute[i].value)); + cJSON_AddNumberToObject(radius_debug, "radius_acct_input_octets", *(unsigned int *)(radius_body->attribute[i].value)); + cJSON_AddNumberToObject(radius_info_object, "radius_acct_input_octets", *(unsigned int *)(radius_body->attribute[i].value)); break; case ACCT_OUTPUT_OCTETS: - cJSON_AddNumberToObject(radius_json_obj, "ACCT_OUTPUT_OCTETS", *(unsigned int *)(radius_body->attribute[i].value)); + cJSON_AddNumberToObject(radius_debug, "radius_acct_output_octets", *(unsigned int *)(radius_body->attribute[i].value)); + cJSON_AddNumberToObject(radius_info_object, "radius_acct_output_octets", *(unsigned int *)(radius_body->attribute[i].value)); break; case ACCT_INPUT_PACKETS: - cJSON_AddNumberToObject(radius_json_obj, "ACCT_INPUT_PACKETS", *(unsigned int *)(radius_body->attribute[i].value)); + cJSON_AddNumberToObject(radius_debug, "radius_acct_input_packets", *(unsigned int *)(radius_body->attribute[i].value)); + cJSON_AddNumberToObject(radius_info_object, "radius_acct_input_packets", *(unsigned int *)(radius_body->attribute[i].value)); break; case ACCT_OUTPUT_PACKETS: - cJSON_AddNumberToObject(radius_json_obj, "ACCT_OUTPUT_PACKETS", *(unsigned int *)(radius_body->attribute[i].value)); + cJSON_AddNumberToObject(radius_debug, "radius_acct_output_packets", *(unsigned int *)(radius_body->attribute[i].value)); + cJSON_AddNumberToObject(radius_info_object, "radius_acct_output_packets", *(unsigned int *)(radius_body->attribute[i].value)); + break; + case ACCT_SESSION_TIME: + cJSON_AddNumberToObject(radius_debug, "radius_acct_session_time", *(unsigned int *)(radius_body->attribute[i].value)); + cJSON_AddNumberToObject(radius_info_object, "radius_acct_session_time", *(unsigned int *)(radius_body->attribute[i].value)); break; case ACCT_TERMINATE_CAUSE: - cJSON_AddNumberToObject(radius_json_obj, "ACCT_TERMINATE_CAUSE", *(unsigned int *)(radius_body->attribute[i].value)); + cJSON_AddNumberToObject(radius_debug, "radius_acct_terminate_cause", *(unsigned int *)(radius_body->attribute[i].value)); + cJSON_AddNumberToObject(radius_info_object, "radius_acct_terminate_cause", *(unsigned int *)(radius_body->attribute[i].value)); break; case ACCT_LINK_COUNT: - cJSON_AddNumberToObject(radius_json_obj, "ACCT_LINK_COUNT", *(unsigned int *)(radius_body->attribute[i].value)); + cJSON_AddNumberToObject(radius_debug, "radius_acct_link_count", *(unsigned int *)(radius_body->attribute[i].value)); + cJSON_AddNumberToObject(radius_info_object, "radius_acct_link_count", *(unsigned int *)(radius_body->attribute[i].value)); + break; + case ACCT_INPUT_GIGAWORDS: + cJSON_AddNumberToObject(radius_debug, "radius_acct_input_gigawords", *(unsigned int *)(radius_body->attribute[i].value)); + break; + case ACCT_OUTPUT_GIGAWORDS: + cJSON_AddNumberToObject(radius_debug, "radius_acct_output_gigawords", *(unsigned int *)(radius_body->attribute[i].value)); + break; + case ACCT_EVENT_TIMESTAMP: + cJSON_AddNumberToObject(radius_debug, "radius_event_timestamp", *(unsigned int *)(radius_body->attribute[i].value)); + cJSON_AddNumberToObject(radius_info_object, "radius_event_timestamp", *(unsigned int *)(radius_body->attribute[i].value)); + break; + case NAS_PORT_TYPE: + cJSON_AddNumberToObject(radius_debug, "radius_nas_port_type", *(unsigned int *)(radius_body->attribute[i].value)); break; case ACCT_INTERIM_INTERVAL: - cJSON_AddNumberToObject(radius_json_obj, "ACCT_INTERIM_INTERVAL", *(unsigned int *)(radius_body->attribute[i].value)); + cJSON_AddNumberToObject(radius_debug, "radius_acct_interim_interval", *(unsigned int *)(radius_body->attribute[i].value)); + cJSON_AddNumberToObject(radius_info_object, "radius_acct_interim_interval", *(unsigned int *)(radius_body->attribute[i].value)); + break; + case NAS_PORT_ID: + cJSON_AddStringToObject(radius_debug, "radius_nas_port_id", (char *)(radius_body->attribute[i].value)); break; default: continue; @@ -158,7 +249,8 @@ int get_radius_object_element(cJSON *radius_info_object, radius_header_t *radius static int streamInfo2jsonObject(cJSON *json_obj, const struct streaminfo *a_stream) { - int ret = 0; + time_t cur_time; + int ret=0,con_duration_ms=0; const char *addr_proto = NULL; unsigned short tunnel_type=0; char nest_addr_buf[1024]; @@ -166,37 +258,64 @@ static int streamInfo2jsonObject(cJSON *json_obj, const struct streaminfo *a_str const struct layer_addr *addr=NULL; char src_ip_str[128] = {0}, dst_ip_str[128] = {0}; - cJSON_AddNumberToObject(json_obj, "stream_dir", a_stream->dir); + cJSON_AddNumberToObject(json_obj, "common_stream_dir", a_stream->dir); addr=&(a_stream->addr); switch(addr->addrtype) { case ADDR_TYPE_IPV4: case __ADDR_TYPE_IP_PAIR_V4: - cJSON_AddNumberToObject(json_obj, "addr_type", 4); + cJSON_AddNumberToObject(json_obj, "common_address_type", 4); inet_ntop(AF_INET, &addr->ipv4->saddr, src_ip_str, sizeof(src_ip_str)); inet_ntop(AF_INET, &addr->ipv4->daddr, dst_ip_str, sizeof(dst_ip_str)); - cJSON_AddStringToObject(json_obj, "s_ip", src_ip_str); - cJSON_AddStringToObject(json_obj, "d_ip", dst_ip_str); - cJSON_AddNumberToObject(json_obj, "s_port", ntohs(addr->ipv4->source)); - cJSON_AddNumberToObject(json_obj, "d_port", ntohs(addr->ipv4->dest)); + cJSON_AddStringToObject(json_obj, "common_client_ip", src_ip_str); + cJSON_AddStringToObject(json_obj, "common_server_ip", dst_ip_str); + cJSON_AddNumberToObject(json_obj, "common_client_port", ntohs(addr->ipv4->source)); + cJSON_AddNumberToObject(json_obj, "common_server_port", ntohs(addr->ipv4->dest)); break; case ADDR_TYPE_IPV6: case __ADDR_TYPE_IP_PAIR_V6: - cJSON_AddNumberToObject(json_obj, "addr_type", 6); + cJSON_AddNumberToObject(json_obj, "common_address_type", 6); inet_ntop(AF_INET6, addr->ipv6->saddr, src_ip_str, sizeof(src_ip_str)); inet_ntop(AF_INET6, addr->ipv6->daddr, dst_ip_str, sizeof(dst_ip_str)); - cJSON_AddStringToObject(json_obj, "s_ip", src_ip_str); - cJSON_AddStringToObject(json_obj, "d_ip", dst_ip_str); - cJSON_AddNumberToObject(json_obj, "s_port", ntohs(addr->ipv6->source)); - cJSON_AddNumberToObject(json_obj, "d_port", ntohs(addr->ipv6->dest)); + cJSON_AddStringToObject(json_obj, "common_client_ip", src_ip_str); + cJSON_AddStringToObject(json_obj, "common_server_ip", dst_ip_str); + cJSON_AddNumberToObject(json_obj, "common_client_port", ntohs(addr->ipv6->source)); + cJSON_AddNumberToObject(json_obj, "common_server_port", ntohs(addr->ipv6->dest)); break; default: break; } + cJSON_AddNumberToObject(json_obj, "common_c2s_pkt_num", a_stream->ptcpdetail->serverpktnum); + cJSON_AddNumberToObject(json_obj, "common_s2c_pkt_num", a_stream->ptcpdetail->clientpktnum); + cJSON_AddNumberToObject(json_obj, "common_c2s_byte_num", a_stream->ptcpdetail->serverbytes); + cJSON_AddNumberToObject(json_obj, "common_s2c_byte_num", a_stream->ptcpdetail->clientbytes); + + cur_time = time(NULL); + if(a_stream!=NULL && a_stream->ptcpdetail!=NULL) + { + cJSON_AddNumberToObject(json_obj, "common_start_time", a_stream->ptcpdetail->createtime); + cJSON_AddNumberToObject(json_obj, "common_end_time", a_stream->ptcpdetail->lastmtime); + + con_duration_ms=(a_stream->ptcpdetail->lastmtime-a_stream->ptcpdetail->createtime)*1000; + cJSON_AddNumberToObject(json_obj, "common_con_duration_ms", con_duration_ms); + } + else + { + con_duration_ms=0; + cJSON_AddNumberToObject(json_obj, "common_start_time", cur_time); + cJSON_AddNumberToObject(json_obj, "common_end_time", cur_time); + cJSON_AddNumberToObject(json_obj, "common_con_duration_ms", con_duration_ms); + } + + int device_id_size=sizeof(unsigned long long); + unsigned long long device_id=(unsigned long long)g_ntc_radius_plug.device_id; + MESA_get_stream_opt(a_stream, MSO_GLOBAL_STREAM_ID, (void *)&device_id, &device_id_size); + cJSON_AddNumberToObject(json_obj, "common_stream_trace_id", device_id); + addr_proto = layer_addr_prefix_ntop(a_stream); - cJSON_AddStringToObject(json_obj, "trans_proto", addr_proto); + cJSON_AddStringToObject(json_obj, "common_l4_protocol", addr_proto); ret=MESA_get_stream_opt(a_stream, MSO_STREAM_TUNNEL_TYPE, &tunnel_type, &tunnel_type_size); assert(ret==0); @@ -209,7 +328,7 @@ static int streamInfo2jsonObject(cJSON *json_obj, const struct streaminfo *a_str stream_addr_list_ntop(a_stream,nest_addr_buf, sizeof(nest_addr_buf)); } - cJSON_AddStringToObject(json_obj, "addr_list", nest_addr_buf); + cJSON_AddStringToObject(json_obj, "common_address_list", nest_addr_buf); return 0; } @@ -217,72 +336,50 @@ static int streamInfo2jsonObject(cJSON *json_obj, const struct streaminfo *a_str char NTC_RADIUS_PLUG_ENTRY(stSessionInfo *session_info, void **pme, int thread_seq, struct streaminfo *stream, void *a_packet) { - int ret=0,status=0; + int status=0; int config_id=0; - int payload_len=0; - time_t cur_time; + int payload_len=0,index=0; char *payload=NULL; - struct vxlan_info vinfo; - int opt_val_len = sizeof(vinfo); radius_info_t *radius_info=(radius_info_t *)session_info->app_info; cJSON *radius_info_object=cJSON_CreateObject(); streamInfo2jsonObject(radius_info_object, stream); - get_radius_object_element(radius_info_object, &radius_info->header, &radius_info->body); - cJSON_AddNumberToObject(radius_info_object, "cfg_id", config_id); - cJSON_AddNumberToObject(radius_info_object, "service", g_ntc_radius_plug.service_id); + cJSON_AddNumberToObject(radius_info_object, "common_policy_id", config_id); + cJSON_AddNumberToObject(radius_info_object, "common_service", g_ntc_radius_plug.service_id); + + cJSON_AddStringToObject(radius_info_object, "common_sled_ip", g_ntc_radius_plug.local_ip); + cJSON_AddStringToObject(radius_info_object, "common_schema_type", "RADIUS"); + + cJSON *radius_debug=cJSON_Duplicate(radius_info_object, 1); - cur_time = time(NULL); - if(stream!=NULL && stream->ptcpdetail!=NULL) - { - cJSON_AddNumberToObject(radius_info_object, "recv_time", stream->ptcpdetail->createtime); - } - else - { - cJSON_AddNumberToObject(radius_info_object, "recv_time", cur_time); - } - cJSON_AddNumberToObject(radius_info_object, "found_time", cur_time); - - ret = MESA_get_stream_opt(stream, MSO_STREAM_VXLAN_INFO, &vinfo, &opt_val_len); - if(ret < 0) - { - MESA_handle_runtime_log(g_ntc_radius_plug.logger, RLOG_LV_FATAL, "DNS_COLLECT_LOG", "soq log: get vxlan info error, tuple4: %s", printaddr(&stream->addr, thread_seq)); - } - else - { - cJSON_AddNumberToObject(radius_info_object, "entrance_id", vinfo.entrance_id); - cJSON_AddNumberToObject(radius_info_object, "direction", vinfo.link_dir); - cJSON_AddNumberToObject(radius_info_object, "device_id", vinfo.dev_id); - cJSON_AddNumberToObject(radius_info_object, "encap_type", vinfo.encap_type); - cJSON_AddNumberToObject(radius_info_object, "link_id", vinfo.link_id); - - cJSON_AddStringToObject(radius_info_object, "inner_smac", (char *)vinfo.inner_smac); - cJSON_AddStringToObject(radius_info_object, "inner_dmac", (char *)vinfo.inner_dmac); - } - - cJSON_AddStringToObject(radius_info_object, "cap_ip", g_ntc_radius_plug.local_ip); - + get_radius_object_element(radius_info_object, radius_debug, &radius_info->header, &radius_info->body, &index); payload = cJSON_PrintUnformatted(radius_info_object); payload_len = strlen(payload); - - status = rd_kafka_produce(g_ntc_radius_plug.topic_rkt, RD_KAFKA_PARTITION_UA, RD_KAFKA_MSG_F_COPY, payload, payload_len, NULL, 0, NULL); + status = rd_kafka_produce(g_ntc_radius_plug.topic_rkt, RD_KAFKA_PARTITION_UA, RD_KAFKA_MSG_F_COPY, payload, payload_len, + radius_info->body.attribute[index].value, radius_info->body.attribute[index].len, NULL); if(status < 0) { - MESA_handle_runtime_log(g_ntc_radius_plug.logger,RLOG_LV_INFO,"sendlog", "sendlog to kafka is error, status: %d, topic: %s payload: %s", status, g_ntc_radius_plug.topic_name, payload); + MESA_handle_runtime_log(g_ntc_radius_plug.logger,RLOG_LV_INFO,"SEND_LOG", "sendlog to kafka is error, status: %d, topic: %s payload: %s", status, g_ntc_radius_plug.topic_name, payload); } else { - MESA_handle_runtime_log(g_ntc_radius_plug.logger,RLOG_LV_INFO,"sendlog", "topic: %s %s", g_ntc_radius_plug.topic_name, payload); + MESA_handle_runtime_log(g_ntc_radius_plug.logger,RLOG_LV_INFO,"SEND_LOG", "topic: %s %s", g_ntc_radius_plug.topic_name, payload); } free(payload); cJSON_Delete(radius_info_object); radius_info_object = NULL; + + payload = cJSON_PrintUnformatted(radius_debug); + MESA_handle_runtime_log(g_ntc_radius_plug.logger,RLOG_LV_INFO, "RADIUS_DEBUG", "payload: %s", payload); + free(payload); + cJSON_Delete(radius_debug); + radius_debug = NULL; return APP_STATE_GIVEME; } @@ -297,12 +394,13 @@ int NTC_RADIUS_PLUG_INIT(void) rd_kafka_topic_conf_t *topic_conf; memset(&g_ntc_radius_plug,0,sizeof(g_ntc_radius_plug_t)); - MESA_load_profile_string_def(config_file, "SYSTEM", "NIC_NAME", nic_name, sizeof(nic_name), "eth0"); - MESA_load_profile_string_def(config_file, "RADIUS","LOG_PATH",g_ntc_radius_plug.pathname, sizeof(g_ntc_radius_plug.pathname), "./t1log/ntc_radius_plug/ntc_radius_plug"); - MESA_load_profile_int_def(config_file, "RADIUS", "SERVICE_ID", &g_ntc_radius_plug.service_id, 0xA2); - MESA_load_profile_int_def(config_file, "RADIUS","LEVEL", &g_ntc_radius_plug.level, RLOG_LV_FATAL); - MESA_load_profile_string_def(config_file, "RADIUS", "COLLECT_TOPIC", g_ntc_radius_plug.topic_name, sizeof(g_ntc_radius_plug.topic_name), "eth0"); - MESA_load_profile_string_def(config_file, "RADIUS", "BROKERLIST", g_ntc_radius_plug.brokerlist, sizeof(g_ntc_radius_plug.brokerlist), "127.0.0.1:9092"); + MESA_load_profile_string_def(config_file, "RADIUS_PLUG", "NIC_NAME", nic_name, sizeof(nic_name), "lo"); + MESA_load_profile_string_def(config_file, "RADIUS_PLUG","LOG_PATH",g_ntc_radius_plug.pathname, sizeof(g_ntc_radius_plug.pathname), "./log/ntc_radius_plug/ntc_radius_plug"); + MESA_load_profile_int_def(config_file, "RADIUS_PLUG", "SERVICE_ID", &g_ntc_radius_plug.service_id, 0xA2); + MESA_load_profile_int_def(config_file, "RADIUS_PLUG","LOG_LEVEL", &g_ntc_radius_plug.level, RLOG_LV_FATAL); + MESA_load_profile_string_def(config_file, "RADIUS_PLUG", "COLLECT_TOPIC", g_ntc_radius_plug.topic_name, sizeof(g_ntc_radius_plug.topic_name), "RADIUS-RECORD-LOG"); + MESA_load_profile_string_def(config_file, "RADIUS_PLUG", "BROKERLIST", g_ntc_radius_plug.brokerlist, sizeof(g_ntc_radius_plug.brokerlist), "127.0.0.1:9092"); + MESA_load_profile_int_def(config_file, "RADIUS_PLUG", "DEVICE_ID", &g_ntc_radius_plug.device_id, 0); g_ntc_radius_plug.logger = MESA_create_runtime_log_handle(g_ntc_radius_plug.pathname, g_ntc_radius_plug.level); if(g_ntc_radius_plug.logger == NULL) @@ -345,7 +443,7 @@ int NTC_RADIUS_PLUG_INIT(void) return -1; } - printf("INIT NTC_RADIUS_PLUG SUCCESS, VERSION: %d\n", NTC_RADIUS_PLUG_VERSION_20191022); + printf("INIT NTC_RADIUS_PLUG SUCCESS, VERSION: %d\n", NTC_RADIUS_PLUG_VERSION_20191211); return 0; } diff --git a/src/ntc_radius_plug.h b/src/ntc_radius_plug.h index 905056e..30257ef 100644 --- a/src/ntc_radius_plug.h +++ b/src/ntc_radius_plug.h @@ -11,6 +11,7 @@ typedef struct _ntc_radius_plug { int level; int service_id; + int device_id; void *logger; char pathname[128]; char topic_name[128];