pax_global_header00006660000000000000000000000064147650564400014525gustar00rootroot0000000000000052 comment=484f16ff78ddbb2e4d4b52735564332770af9548 nats.c-3.10.1/000077500000000000000000000000001476505644000127755ustar00rootroot00000000000000nats.c-3.10.1/.github/000077500000000000000000000000001476505644000143355ustar00rootroot00000000000000nats.c-3.10.1/.github/ISSUE_TEMPLATE/000077500000000000000000000000001476505644000165205ustar00rootroot00000000000000nats.c-3.10.1/.github/ISSUE_TEMPLATE/config.yml000066400000000000000000000005101476505644000205040ustar00rootroot00000000000000blank_issues_enabled: false contact_links: - name: Discussion url: https://github.com/nats-io/nats.c/discussions about: Ideal for ideas, feedback, or longer form questions. - name: Chat url: https://slack.nats.io about: Ideal for short, one-off questions, general conversation, and meeting other NATS users! nats.c-3.10.1/.github/ISSUE_TEMPLATE/defect.yml000066400000000000000000000030071476505644000204750ustar00rootroot00000000000000--- name: Defect description: Report a defect, such as a bug or regression. labels: - defect body: - type: textarea id: observed attributes: label: Observed behavior description: Describe the unexpected behavior or performance regression you are observing. validations: required: true - type: textarea id: expected attributes: label: Expected behavior description: Describe the expected behavior or performance characteristics. validations: required: true - type: textarea id: versions attributes: label: Server and client version description: |- Provide the versions you were using when the detect was observed. For the server, use `nats-server --version`, check the startup log output, or the image tag pulled from Docker. For the CLI client, use `nats --version`. For language-specific clients, check the version downloaded by the language dependency manager. validations: required: true - type: textarea id: environment attributes: label: Host environment description: |- Specify any relevant details about the host environment the server and/or client was running in, such as operating system, CPU architecture, container runtime, etc. validations: required: false - type: textarea id: steps attributes: label: Steps to reproduce description: Provide as many concrete steps to reproduce the defect. validations: required: false nats.c-3.10.1/.github/ISSUE_TEMPLATE/proposal.yml000066400000000000000000000013241476505644000211020ustar00rootroot00000000000000--- name: Proposal description: Propose an enhancement or new feature. labels: - proposal body: - type: textarea id: change attributes: label: Proposed change description: This could be a behavior change, enhanced API, or a new feature. validations: required: true - type: textarea id: usecase attributes: label: Use case description: What is the use case or general motivation for this proposal? validations: required: true - type: textarea id: contribute attributes: label: Contribution description: |- Are you intending or interested in contributing code for this proposal if accepted? validations: required: false nats.c-3.10.1/.github/workflows/000077500000000000000000000000001476505644000163725ustar00rootroot00000000000000nats.c-3.10.1/.github/workflows/build-test.yml000066400000000000000000000216521476505644000211770ustar00rootroot00000000000000on: workflow_call: inputs: arch: type: string default: "64" benchmark: type: string default: "OFF" compiler: type: string default: "gcc" coverage: type: string default: "OFF" dev_mode: type: string default: "OFF" experimental: type: string default: "OFF" pool_dispatch: type: string default: "NO-pool" repeat: type: string default: "1" sanitize: type: string description: "sanitize option to use, 'address' or 'thread'" server_version: type: string description: "nats-server version to test with" default: "latest" streaming: type: string default: "ON" tls: type: string default: "TLS" type: type: string description: "Debug or Release." default: "Release" ubuntu_version: type: string description: "Ubuntu version to use, e.g. '20.04'" default: "latest" verbose_make_output: type: string default: "OFF" verbose_test_output: type: string default: "OFF" verify_host: type: string default: "verify_host" write_deadline: type: string default: "NO-write_deadline" secrets: CODECOV_TOKEN: description: "Codecov repo token" permissions: contents: write # to comment on coverage. defaults: run: shell: bash --noprofile --norc -x -eo pipefail {0} jobs: do: runs-on: ubuntu-${{ inputs.ubuntu_version }} name: "${{ inputs.ubuntu_version }} - nats:${{ inputs.server_version }}" steps: - name: Checkout nats.c uses: actions/checkout@v4 - name: "Checkout dependencies (nats.c.deps)" uses: actions/checkout@v4 with: repository: nats-io/nats.c.deps path: deps # configure the cmake flags and NATS_... environment variables - id: cmake-flags name: Configure cmake flags env: flags: -DNATS_BUILD_ARCH=${{ inputs.arch }} -DCMAKE_BUILD_TYPE=${{ inputs.type }} -DNATS_BUILD_STREAMING=${{ inputs.streaming }} -DNATS_BUILD_USE_SODIUM=ON -DNATS_PROTOBUF_DIR=${{ github.workspace}}/deps/pbuf -DNATS_SODIUM_DIR=${{ github.workspace}}/deps/sodium run: | if [[ "${{ inputs.tls }}" == "TLS" ]]; then flags="$flags -DNATS_BUILD_WITH_TLS=ON" if [[ "${{ inputs.verify_host }}" == "verify_host" ]]; then flags="$flags -DNATS_BUILD_TLS_FORCE_HOST_VERIFY=ON" else flags="$flags -DNATS_BUILD_TLS_FORCE_HOST_VERIFY=OFF" fi else flags="$flags -DNATS_BUILD_WITH_TLS=OFF" fi if [[ "${{ inputs.coverage }}" == "ON" ]]; then flags="$flags -DNATS_COVERAGE=ON" fi if [[ "${{ inputs.dev_mode }}" == "ON" ]]; then flags="$flags -DDEV_MODE=ON" fi if [[ "${{ inputs.experimental }}" == "ON" ]]; then flags="$flags -DNATS_EXPERIMENTAL=ON" fi if [[ -n "${{ inputs.sanitize }}" ]]; then flags="$flags -DNATS_SANITIZE=ON -DCMAKE_C_FLAGS=-fsanitize=${{ inputs.sanitize }}" fi if [[ "${{ inputs.verbose_make_output }}" == "ON" ]]; then flags="$flags -DCMAKE_VERBOSE_MAKEFILE=ON" fi echo "flags=$flags" >> $GITHUB_OUTPUT - id: nats-vars name: Configure NATS_ environment variables run: | if [[ -n "${{ inputs.sanitize }}" ]]; then echo "NATS_TEST_VALGRIND=yes" >> $GITHUB_ENV fi if [[ "${{ inputs.pool_dispatch }}" == "pool" ]]; then echo "NATS_DEFAULT_TO_LIB_MSG_DELIVERY=yes" >> $GITHUB_ENV fi if [[ "${{ inputs.write_deadline }}" == "write_deadline" ]]; then echo "NATS_DEFAULT_LIB_WRITE_DEADLINE=2000" >> $GITHUB_ENV fi echo "CC=${{ inputs.compiler }}" >> $GITHUB_ENV # install build dependencies - name: Install ${{ inputs.compiler }} if needed if: startsWith(inputs.compiler, 'clang-') || startsWith(inputs.compiler, 'gcc-') run: | sudo apt-get -q update sudo apt-get -y install ${{ inputs.compiler }} # otherwise, configure cmake, build, archive and upload - name: CMake run: | mkdir -p build cd build cmake .. ${{ steps.cmake-flags.outputs.flags }} make rebuild_cache && make # testing - name: "Download nats-server version ${{ inputs.server_version }}" if: inputs.server_version working-directory: ./build run: | rel=${{ inputs.server_version }} if [ "$rel" = "latest" ]; then rel=$(curl -s https://api.github.com/repos/nats-io/nats-server/releases/latest | jq -r '.tag_name') fi if [ "$rel" != "${rel#v}" ] && wget https://github.com/nats-io/nats-server/releases/download/$rel/nats-server-$rel-linux-amd64.tar.gz; then tar -xzf nats-server-$rel-linux-amd64.tar.gz cp nats-server-$rel-linux-amd64/nats-server ../deps/nats-server/nats-server else for c in 1 2 3 4 5 do echo "Attempt $c to download binary for main" rm -f ./nats-server curl -sf "https://binaries.nats.dev/nats-io/nats-server/v2@$rel" | PREFIX=. sh # We are sometimes getting nats-server of size 0. Make sure we have a # working nats-server by making sure we get a version number. v="$(./nats-server -v)" if [ "$v" != "" ]; then break fi done mv ./nats-server ../deps/nats-server/nats-server fi - name: "Test" if: inputs.benchmark == 'OFF' working-directory: ./build run: | export PATH=../deps/nats-server:../deps/nats-streaming-server:$PATH export NATS_TEST_SERVER_VERSION="$(nats-server -v)" flags="" ctest -L 'test' --timeout 60 --output-on-failure --repeat-until-fail ${{ inputs.repeat }} - name: Upload coverage reports to Codecov # PRs from external contributors fail: https://github.com/codecov/feedback/issues/301 # Only upload coverage reports for PRs from the same repo (not forks) if: inputs.coverage == 'ON' && github.event.pull_request.head.repo.full_name == github.repository uses: codecov/codecov-action@v4 with: fail_ci_if_error: true token: ${{ secrets.CODECOV_TOKEN }} # verbose: true - name: "Cache for base benchmark for ${{ github.event.pull_request.base.ref }}" id: cache-base-bench if: inputs.benchmark == 'ON' && github.event.pull_request.base.ref uses: actions/cache@v4 with: key: bench-${{ github.event.pull_request.base.ref }} path: ./build/bench-${{ github.event.pull_request.base.ref }}.log - name: "Benchmark" if: inputs.benchmark == 'ON' working-directory: ./build run: | export PATH=../deps/nats-server:../deps/nats-streaming-server:$PATH export NATS_TEST_SERVER_VERSION="$(nats-server -v)" flags="" ctest -L 'bench' --timeout 600 -VV | tee bench.log - name: "Checkout nats.c for ${{ github.event.pull_request.base.ref }}" if: inputs.benchmark == 'ON' && github.event.pull_request.base.ref && steps.cache-base-bench.outputs.cache-hit != 'true' uses: actions/checkout@v4 with: ref: ${{ github.event.pull_request.base.ref }} clean: false - name: "Benchmark ${{ github.event.pull_request.base.ref }} for comparison" if: inputs.benchmark == 'ON' && github.event.pull_request.base.ref && steps.cache-base-bench.outputs.cache-hit != 'true' run: | mkdir -p build cd build rm -rf CMakeFiles CMakeCache.txt cmake .. ${{ steps.cmake-flags.outputs.flags }} make rebuild_cache && make export PATH=../deps/nats-server:../deps/nats-streaming-server:$PATH export NATS_TEST_SERVER_VERSION="$(nats-server -v)" flags="" ctest -L 'bench' --timeout 600 -VV | tee bench-${{ github.event.pull_request.base.ref }}.log - name: "Checkout HEAD ${{ github.event.pull_request.head.ref }}" if: inputs.benchmark == 'ON' && github.event.pull_request.head.ref && steps.cache-base-bench.outputs.cache-hit != 'true' uses: actions/checkout@v4 with: clean: false - name: "Compare benchmark to ${{ github.event.pull_request.base.ref }}" if: inputs.benchmark == 'ON' && github.event.pull_request.base.ref run: | cd build go run ../test/diffstat_sub_async.go bench-${{ github.event.pull_request.base.ref }}.log bench.log nats.c-3.10.1/.github/workflows/on-nightly.yml000066400000000000000000000010271476505644000212050ustar00rootroot00000000000000name: "Nightly" on: schedule: # * is a special character in YAML so you have to quote this string - cron: '37 4 * * *' permissions: contents: write # required by build-test to comment on coverage but not used here. defaults: run: shell: bash --noprofile --norc -x -eo pipefail {0} jobs: quick: name: "DefaultR" strategy: fail-fast: false matrix: server_version: [main, latest] uses: ./.github/workflows/build-test.yml with: server_version: ${{ matrix.server_version }} nats.c-3.10.1/.github/workflows/on-pr-debug.yml000066400000000000000000000111401476505644000212310ustar00rootroot00000000000000name: "PR" on: pull_request: permissions: contents: write # so it can comment jobs: Ubuntu: name: "Ubuntu" strategy: fail-fast: false matrix: compiler: [gcc, clang] uses: ./.github/workflows/build-test.yml with: compiler: ${{ matrix.compiler }} server_version: main type: Debug experimental: ON dev-mode: name: "DEV_MODE" uses: ./.github/workflows/build-test.yml with: dev_mode: ON server_version: main type: Debug verbose_test_output: ON verbose_make_output: ON experimental: ON sanitize: name: "Sanitize" strategy: fail-fast: false matrix: compiler: [gcc, clang] sanitize: [address, thread] pooled_dispatch: [pool, NO-pool] uses: ./.github/workflows/build-test.yml with: server_version: main type: RelWithDebInfo compiler: ${{ matrix.compiler }} sanitize: ${{ matrix.sanitize }} pool_dispatch: ${{ matrix.pooled_dispatch }} experimental: ON coverage-TLS: name: "Coverage: TLS" strategy: fail-fast: false matrix: pooled_dispatch: [pool, NO-pool] write_deadline: [write_deadline, NO-write_deadline] uses: ./.github/workflows/build-test.yml with: coverage: ON type: RelWithDebInfo server_version: main compiler: gcc tls: TLS verify_host: verify_host pool_dispatch: ${{ matrix.pooled_dispatch }} write_deadline: ${{ matrix.write_deadline }} experimental: ON secrets: CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} coverage-NO-verify_host: name: "Coverage: NO-verify_host" uses: ./.github/workflows/build-test.yml with: coverage: ON type: RelWithDebInfo server_version: main compiler: gcc tls: TLS verify_host: NO-verify_host experimental: ON secrets: CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} coverage-NO-TLS: name: "Coverage NO-TLS" uses: ./.github/workflows/build-test.yml with: coverage: ON type: RelWithDebInfo server_version: main compiler: gcc tls: NO-TLS verify_host: NO-verify_host secrets: CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} bench: name: "Benchmark" uses: ./.github/workflows/build-test.yml with: server_version: main benchmark: ON type: Release Windows: name: "Windows" runs-on: windows-latest steps: - name: Export GitHub Actions cache environment variables uses: actions/github-script@v7 with: script: | core.exportVariable('ACTIONS_CACHE_URL', process.env.ACTIONS_CACHE_URL || ''); core.exportVariable('ACTIONS_RUNTIME_TOKEN', process.env.ACTIONS_RUNTIME_TOKEN || ''); - name: Checkout nats.c uses: actions/checkout@v4 - name: Build env: VCPKG_BINARY_SOURCES: "clear;x-gha,readwrite" run: | cmake -B build -S . -DCMAKE_BUILD_TYPE=Debug -DNATS_BUILD_STREAMING=OFF -DNATS_WITH_EXPERIMENTAL=ON cmake --build build - name: Test shell: bash run: | cd build # Download latest nats-server rel="latest" # TODO: parameterize if [ "$rel" = "latest" ]; then rel=$(curl -s https://api.github.com/repos/nats-io/nats-server/releases/latest | jq -r '.tag_name') fi if [ "$rel" != "${rel#v}" ] && wget https://github.com/nats-io/nats-server/releases/download/$rel/nats-server-$rel-windows-amd64.tar.gz; then tar -xzf nats-server-$rel-linux-amd64.tar.gz cp nats-server-$rel-windows-amd64/nats-server.exe ../deps/nats-server/nats-server.exe else for c in 1 2 3 4 5 do echo "Attempt $c to download binary for main" rm -f ./nats-server curl -sf "https://binaries.nats.dev/nats-io/nats-server/v2@$rel" | PREFIX=. sh # We are sometimes getting nats-server of size 0. Make sure we have a # working nats-server by making sure we get a version number. mv ./nats-server ./nats-server.exe v="$(./nats-server.exe -v)" if [ "$v" != "" ]; then break fi done mkdir -p ../deps/nats-server mv ./nats-server.exe ../deps/nats-server/nats-server.exe fi export PATH=../deps/nats-server:$PATH export NATS_TEST_SERVER_VERSION="$(nats-server -v)" ctest -L test -C Debug --timeout 60 --output-on-failure --repeat until-pass:3 nats.c-3.10.1/.github/workflows/on-push-release-extra.yml000066400000000000000000000030361476505644000232470ustar00rootroot00000000000000name: "Release" on: push: branches: - main - release_* permissions: contents: write # required by build-test to comment on coverage but not used here. defaults: run: shell: bash --noprofile --norc -x -eo pipefail {0} jobs: flakes: name: "check for flaky tests" uses: ./.github/workflows/build-test.yml with: server_version: main repeat: 5 server-versions: strategy: fail-fast: false matrix: server_version: [latest, v2.9.11] uses: ./.github/workflows/build-test.yml name: "Other servers" with: server_version: ${{ matrix.server_version }} TLS-OFF: strategy: fail-fast: false matrix: compiler: [gcc, clang] uses: ./.github/workflows/build-test.yml name: "No TLS" with: tls: OFF older-cc: strategy: fail-fast: false matrix: compiler: [gcc-7, gcc-8, clang-8] uses: ./.github/workflows/build-test.yml name: "Older compilers" with: ubuntu_version: 20.04 compiler: ${{ matrix.compiler }} no-streaming: uses: ./.github/workflows/build-test.yml name: "No Streaming" with: streaming: OFF coverage: name: "Coverage" uses: ./.github/workflows/build-test.yml with: coverage: ON server_version: main type: Debug secrets: CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} bench: name: "Benchmark" uses: ./.github/workflows/build-test.yml with: server_version: main benchmark: ON type: Release nats.c-3.10.1/.github/workflows/on-push-release.yml000066400000000000000000000010211476505644000221160ustar00rootroot00000000000000name: "Release" on: push: permissions: contents: write # required by build-test to comment on coverage but not used here. defaults: run: shell: bash --noprofile --norc -x -eo pipefail {0} jobs: quick: name: "Ubuntu" strategy: fail-fast: false matrix: compiler: [gcc, clang] ubuntu_version: [latest, 20.04] uses: ./.github/workflows/build-test.yml with: server_version: main ubuntu_version: ${{ matrix.ubuntu_version }} compiler: ${{ matrix.compiler }} nats.c-3.10.1/.github/workflows/update-docs.yml000066400000000000000000000025751476505644000213360ustar00rootroot00000000000000name: Update Docs on: push: branches: - main - release_* jobs: update-docs: runs-on: ubuntu-latest permissions: contents: write # to push branches pull-requests: write # to create pull requests steps: - name: Checkout Repository uses: actions/checkout@v4 - name: Set up Doxygen run: | sudo apt-get update sudo apt-get install -y doxygen - name: Generate Documentation id: update run: | cd doc rm -rf ./html/* doxygen DoxyFile.NATS.Client git diff --quiet || echo "CHANGES=true" >> $GITHUB_OUTPUT echo "SOURCE_TITLE=$(git log -1 --pretty=%s)" >> $GITHUB_OUTPUT echo "SOURCE_SHA=$(git log -1 --pretty=%h)" >> $GITHUB_OUTPUT - name: Create Pull Request uses: peter-evans/create-pull-request@v6 if: steps.update.outputs.CHANGES == 'true' with: token: ${{ secrets.GITHUB_TOKEN }} commit-message: "[skip ci] Update docs: ${{ steps.update.outputs.SOURCE_SHA }}: ${{ steps.update.outputs.SOURCE_TITLE }}" branch: update-docs-${{ github.ref_name }} title: Auto-generated documentation update for ${{ github.ref_name }} body: Documentation changes were detected. Please review and merge. labels: documentation delete-branch: true nats.c-3.10.1/.gitignore000066400000000000000000000004421476505644000147650ustar00rootroot00000000000000Compiled Object files, Static and Dynamic libs (Shared Objects) *.o *.a *.so *.dylib *.gcov # Folders build*/ cmake-build*/ install/ html/ !doc/html/ test/datastore_*/ test/conf_* # Emacs *~ \#*\# .\#* # Eclipse .cproject .project .settings/ .vscode/ .idea/ .vs/ out/ # Mac .DS_Store nats.c-3.10.1/.travis.yml000066400000000000000000000136411476505644000151130ustar00rootroot00000000000000language: cpp dist: focal os: linux cache: directories: - $HOME/deps compiler: - gcc - clang before_install: - bash install_deps.sh - if [ "$DO_COVERAGE" = "coverage" ]; then pip install --user cpp-coveralls; fi - eval "${MATRIX_EVAL}" before_script: - export PATH=$HOME/deps/cmake-install:$HOME/deps/cmake-install/bin:$HOME/deps/nats-server:$HOME/deps/nats-streaming-server:$PATH - mkdir build && cd build env: - DO_COVERAGE="coverage" BUILD_OPT="-DNATS_COVERAGE=ON -DNATS_BUILD_ARCH=64 -DCMAKE_BUILD_TYPE=Debug -DNATS_BUILD_TLS_USE_OPENSSL_1_1_API=ON" jobs: include: - name: "NATS server - latest release" compiler: gcc addons: apt: sources: - ubuntu-toolchain-r-test - sourceline: ppa:ubuntu-toolchain-r/test packages: - g++-9 env: - NATS_TEST_SERVER_VERSION=latest - MATRIX_EVAL="CC=gcc-9" - BUILD_OPT="-DNATS_BUILD_ARCH=64 -DCMAKE_BUILD_TYPE=Release" DO_COVERAGE="no" - name: "NATS server - main" compiler: gcc addons: apt: sources: - ubuntu-toolchain-r-test - sourceline: ppa:ubuntu-toolchain-r/test packages: - g++-9 env: - NATS_TEST_SERVER_VERSION=main - MATRIX_EVAL="CC=gcc-9" - BUILD_OPT="-DNATS_BUILD_ARCH=64 -DCMAKE_BUILD_TYPE=Release" DO_COVERAGE="no" - name: "gcc-9 - TLS OFF" compiler: gcc addons: apt: sources: - ubuntu-toolchain-r-test - sourceline: ppa:ubuntu-toolchain-r/test packages: - g++-9 env: - NATS_TEST_SERVER_VERSION=main - MATRIX_EVAL="CC=gcc-9" - BUILD_OPT="-DNATS_BUILD_WITH_TLS=OFF -DNATS_BUILD_ARCH=64 -DCMAKE_BUILD_TYPE=Release" DO_COVERAGE="no" - name: "gcc-9 - Streaming OFF" compiler: gcc addons: apt: sources: - ubuntu-toolchain-r-test - sourceline: ppa:ubuntu-toolchain-r/test packages: - g++-9 env: - MATRIX_EVAL="CC=gcc-9" - BUILD_OPT="-DNATS_BUILD_STREAMING=OFF -DNATS_BUILD_ARCH=64 -DCMAKE_BUILD_TYPE=Release" DO_COVERAGE="no" CTEST_OPT="-I 1,1" - name: "gcc-9 - Default - sanitize address" compiler: gcc addons: apt: sources: - ubuntu-toolchain-r-test - sourceline: ppa:ubuntu-toolchain-r/test packages: - g++-9 env: - NATS_TEST_SERVER_VERSION=main - MATRIX_EVAL="CC=gcc-9" - BUILD_OPT="-DNATS_BUILD_ARCH=64 -DCMAKE_BUILD_TYPE=Debug -DCMAKE_C_FLAGS=-fsanitize=address" NATS_TEST_VALGRIND=yes DO_COVERAGE="no" - name: "gcc-9 - Lib msg delivery - sanitize address" compiler: gcc addons: apt: sources: - ubuntu-toolchain-r-test - sourceline: ppa:ubuntu-toolchain-r/test packages: - g++-9 env: - NATS_TEST_SERVER_VERSION=main - MATRIX_EVAL="CC=gcc-9" - NATS_DEFAULT_TO_LIB_MSG_DELIVERY=yes BUILD_OPT="-DNATS_BUILD_ARCH=64 -DCMAKE_BUILD_TYPE=Debug -DCMAKE_C_FLAGS=-fsanitize=address" NATS_TEST_VALGRIND=yes DO_COVERAGE="no" - name: "gcc-9 - Write deadline - sanitize address" compiler: gcc addons: apt: sources: - ubuntu-toolchain-r-test - sourceline: ppa:ubuntu-toolchain-r/test packages: - g++-9 env: - NATS_TEST_SERVER_VERSION=main - MATRIX_EVAL="CC=gcc-9" - NATS_DEFAULT_LIB_WRITE_DEADLINE=2000 BUILD_OPT="-DNATS_BUILD_ARCH=64 -DCMAKE_BUILD_TYPE=Release -DCMAKE_C_FLAGS=-fsanitize=address" NATS_TEST_VALGRIND=yes DO_COVERAGE="no" # - name: "gcc-9 - Default - sanitize thread" # compiler: gcc # addons: # apt: # sources: # - ubuntu-toolchain-r-test # - sourceline: ppa:ubuntu-toolchain-r/test # packages: # - g++-9 # env: # - MATRIX_EVAL="CC=gcc-9" # - BUILD_OPT="-DNATS_BUILD_ARCH=64 -DCMAKE_BUILD_TYPE=Release -DCMAKE_C_FLAGS=-fsanitize=thread" NATS_TEST_VALGRIND=yes DO_COVERAGE="no" - name: "clang-8 - TLS OFF" compiler: clang addons: apt: sources: - llvm-toolchain-xenial-8 packages: - clang-8 env: - MATRIX_EVAL="CC=clang-8" # Run only one test, this matrix is just to make sure that we compile ok. - BUILD_OPT="-DNATS_BUILD_WITH_TLS=OFF -DNATS_BUILD_ARCH=64 -DCMAKE_BUILD_TYPE=Release" DO_COVERAGE="no" CTEST_OPT="-I 1,1" - name: "clang-8 - Default - sanitize address" compiler: clang addons: apt: sources: - llvm-toolchain-xenial-8 packages: - clang-8 env: - NATS_TEST_SERVER_VERSION=main - MATRIX_EVAL="CC=clang-8" - BUILD_OPT="-DNATS_BUILD_ARCH=64 -DCMAKE_BUILD_TYPE=Release -DCMAKE_C_FLAGS=-fsanitize=address" NATS_TEST_VALGRIND=yes DO_COVERAGE="no" - name: "clang-8 - Default - sanitize thread" compiler: clang addons: apt: sources: - llvm-toolchain-xenial-8 packages: - clang-8 env: - NATS_TEST_SERVER_VERSION=main - MATRIX_EVAL="CC=clang-8" - BUILD_OPT="-DNATS_BUILD_ARCH=64 -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_C_FLAGS=-fsanitize=thread" NATS_TEST_VALGRIND=yes DO_COVERAGE="no" script: - $TRAVIS_BUILD_DIR/buildOnTravis.sh "$CC" "$DO_COVERAGE" "$BUILD_OPT -DNATS_SANITIZE=ON -DNATS_BUILD_TLS_USE_OPENSSL_1_1_API=ON -DNATS_PROTOBUF_DIR=$HOME/deps/pbuf -DNATS_BUILD_USE_SODIUM=ON -DNATS_SODIUM_DIR=$HOME/deps/sodium" "$CTEST_OPT" after_success: - cd .. - if [[ "$DO_COVERAGE" == "coverage" && "$TRAVIS_COMPILER" == "gcc" ]]; then coveralls --gcov-options '\-lp' -r . -i "src/" -e "src/win/" -e "src/unix/" -e "src/stan/protocol.pb-c.c" -E ".*\.h$"; fi notifications: email: false nats.c-3.10.1/CMakeLists.txt000066400000000000000000000247271476505644000155510ustar00rootroot00000000000000cmake_minimum_required(VERSION 3.13) project(cnats) include(CTest) include(FindPackageHandleStandardArgs) include(CMakePackageConfigHelpers) # Uncomment to have the build process verbose # set(CMAKE_VERBOSE_MAKEFILE TRUE) set(CMAKE_C_STANDARD 99) set(CMAKE_C_STANDARD_REQUIRED ON) # Set output directories for libraries and executables. # This is important for Windows builds to have the DLLs in the same directory as the executables. set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) # Set a default build type if none was specified set(default_build_type "Release") if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) message(STATUS "Setting build type to '${default_build_type}' as none was specified.") set(CMAKE_BUILD_TYPE "${default_build_type}" CACHE STRING "Choose the type of build." FORCE) # Set the possible values of build type for cmake-gui set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Release" "Debug" "MinSizeRel" "RelWithDebInfo") endif() option(NATS_UPDATE_VERSION "Update the version file" OFF) option(NATS_UPDATE_DOC "Update the doc template file" OFF) option(NATS_COVERAGE "Code coverage" OFF) option(NATS_BUILD_NO_SPIN "Enable if spin code does not compile on your arch" OFF) option(NATS_BUILD_WITH_TLS "Build with TLS support" ON) option(NATS_BUILD_TLS_FORCE_HOST_VERIFY "Forces hostname verification" ON) option(NATS_BUILD_TLS_USE_OPENSSL_1_1_API "Build for OpenSSL 1.1+" ON) option(NATS_BUILD_USE_SODIUM "Build using libsodium library" OFF) option(NATS_BUILD_EXAMPLES "Build examples" ON) option(NATS_BUILD_LIBUV_EXAMPLE "Build libuv examples" OFF) option(NATS_BUILD_LIBEVENT_EXAMPLE "Build libevent examples" OFF) option(NATS_BUILD_STATIC_EXAMPLES "Statically link examples" OFF) option(NATS_BUILD_STREAMING "Build NATS Streaming" ON) option(NATS_BUILD_NO_PREFIX_CONNSTS "No prefix for connection status enum" OFF) option(NATS_BUILD_LIB_STATIC "Build static library" ON) option(NATS_BUILD_LIB_SHARED "Build shared library" ON) option(NATS_COMPILER_HARDENING "Compiler hardening flags" OFF) option(NATS_WITH_EXPERIMENTAL "Build with EXPERIMENTAL API support" OFF) if(UNIX AND APPLE) option(CMAKE_MACOSX_RPATH "Build with macOS RPath" ON) endif() if(DEFINED ENV{NATS_SANITIZE}) set(NATS_STANITIZE "$ENV{NATS_SANITIZE}") mark_as_advanced(NATS_SANITIZE) endif() set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_BINARY_DIR}) if(NATS_COVERAGE) message("-- Coverage Enabled") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} --coverage -fprofile-arcs -ftest-coverage") endif(NATS_COVERAGE) if(NATS_BUILD_WITH_TLS) set(OPENSSL_USE_STATIC_LIBS ${NATS_BUILD_OPENSSL_STATIC_LIBS}) find_package(OpenSSL REQUIRED) endif(NATS_BUILD_WITH_TLS) set(LIBUV_DIR "" CACHE PATH "Libuv install directory") set(LIBEVENT_DIR "" CACHE PATH "Libevent install directory") set(NATS_DOC_PROJECT_NAME "NATS C Client with JetStream support") if(NATS_BUILD_STREAMING) IF(DEFINED ENV{NATS_PROTOBUF_DIR}) SET(NATS_PROTOBUF_DIR "$ENV{NATS_PROTOBUF_DIR}") ENDIF() FIND_PATH( NATS_PROTOBUF_INCLUDE_DIR protobuf-c/protobuf-c.h HINTS ${NATS_PROTOBUF_DIR} ) FIND_LIBRARY(NATS_PROTOBUF_LIBRARY NAMES libprotobuf-c.so libprotobuf-c.dylib libprotobuf-c.a protobuf-c.lib protobuf-c.dll HINTS ${NATS_PROTOBUF_DIR} ) FIND_PACKAGE_HANDLE_STANDARD_ARGS(libprotobuf-c DEFAULT_MSG NATS_PROTOBUF_INCLUDE_DIR NATS_PROTOBUF_LIBRARY ) IF(libprotobuf-c_FOUND) SET(NATS_PROTOBUF_INCLUDE_DIRS ${NATS_PROTOBUF_INCLUDE_DIR}) SET(NATS_PROTOBUF_LIBRARIES ${NATS_PROTOBUF_LIBRARY}) MARK_AS_ADVANCED( NATS_PROTOBUF_LIBRARY NATS_PROTOBUF_INCLUDE_DIR NATS_PROTOBUF_DIR ) ELSE() SET(NATS_PROTOBUF_DIR "" CACHE STRING "An optional hint to a directory for finding `libprotobuf-c`" ) MESSAGE(FATAL_ERROR "Could not find libprotobuf-c package. Check build instructions: https://github.com/nats-io/nats.c#building-with-streaming") ENDIF() add_definitions(-DNATS_HAS_STREAMING) set(NATS_DOC_INCLUDE_STREAMING "NATS_HAS_STREAMING") set(NATS_DOC_PROJECT_NAME "NATS C Client with JetStream and Streaming support") endif(NATS_BUILD_STREAMING) if(NATS_BUILD_USE_SODIUM) IF(DEFINED ENV{NATS_SODIUM_DIR}) SET(NATS_SODIUM_DIR "$ENV{NATS_SODIUM_DIR}") ENDIF() FIND_PATH( NATS_SODIUM_INCLUDE_DIR sodium.h HINTS ${NATS_SODIUM_DIR} ) FIND_LIBRARY(NATS_SODIUM_LIBRARY NAMES libsodium.so libsodium.dylib libsodium.a libsodium.lib libsodium.dll HINTS ${NATS_SODIUM_DIR} ) FIND_PACKAGE_HANDLE_STANDARD_ARGS(libsodium DEFAULT_MSG NATS_SODIUM_INCLUDE_DIR NATS_SODIUM_LIBRARY ) IF(libsodium_FOUND) SET(NATS_SODIUM_INCLUDE_DIRS ${NATS_SODIUM_INCLUDE_DIR}) SET(NATS_SODIUM_LIBRARIES ${NATS_SODIUM_LIBRARY}) MARK_AS_ADVANCED( NATS_SODIUM_LIBRARY NATS_SODIUM_INCLUDE_DIR NATS_SODIUM_DIR ) ELSE() SET(NATS_SODIUM_DIR "" CACHE STRING "An optional hint to a directory for finding `libsodium`" ) MESSAGE(FATAL_ERROR "Could not find libsodium package. Check build instructions: https://github.com/nats-io/nats.c#building-with-libsodium") ENDIF() add_definitions(-DNATS_USE_LIBSODIUM) endif(NATS_BUILD_USE_SODIUM) if(NATS_BUILD_NO_PREFIX_CONNSTS) add_definitions(-DNATS_CONN_STATUS_NO_PREFIX) endif(NATS_BUILD_NO_PREFIX_CONNSTS) if(NATS_WITH_EXPERIMENTAL) add_definitions(-DNATS_WITH_EXPERIMENTAL) endif(NATS_WITH_EXPERIMENTAL) # Platform specific settings if(UNIX) #--------------------------------------------------------------------------- # Define NATS cache variables that override the CMAKE and MEMCHECK variables #--------------------------------------------------------------------------- include(GNUInstallDirs) set(NATS_LIBDIR ${CMAKE_INSTALL_LIBDIR}) set(NATS_INCLUDE_DIR ${CMAKE_INSTALL_INCLUDEDIR}) set(NATS_BUILD_ARCH "64" CACHE STRING "32 for 32bits builds") find_program(MEMORYCHECK_COMMAND valgrind) set(NATS_MEMCHECK_CMD_OPTS "--leak-check=full --track-fds=yes --show-reachable=yes --num-callers=50" CACHE STRING "Memcheck options") set(MEMORYCHECK_COMMAND_OPTIONS ${NATS_MEMCHECK_CMD_OPTS} CACHE INTERNAL "") set(NATS_COMMON_C_FLAGS "-std=c99 -pedantic") # Some compiler hardening flags. if(NATS_COMPILER_HARDENING) set(NATS_COMMON_C_FLAGS "${NATS_COMMON_C_FLAGS} -fPIE -fstack-protector-all -D_FORTIFY_SOURCE=2 -O1") # Works only with GCC. if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") set(NATS_COMMON_C_FLAGS "${NATS_COMMON_C_FLAGS} -Wl,-z,relro,-z,now -pie") endif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") endif(NATS_COMPILER_HARDENING) set(NATS_WARNINGS "-fstrict-aliasing -Wall -W -Wno-unused-parameter -Wno-unused-function -Wstrict-prototypes -Wwrite-strings") set(NATS_PLATFORM_INCLUDE "unix") if(APPLE) set(NATS_OS "DARWIN") else(APPLE) set(NATS_OS "LINUX") set(NATS_USE_PTHREAD "-pthread") if(NOT ANDROID) set(NATS_EXTRA_LIB "rt -lpthread") endif() endif(APPLE) if (${NATS_BUILD_ARCH} MATCHES "32") if(NOT APPLE) message("-----------------------------------------------------------") message("If build fails, you probably need to install libc6-dev-i386") message("apt-get install libc6-dev-i386") message("-----------------------------------------------------------") endif(NOT APPLE) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -m32") set(CMAKE_C_LINKER_FLAGS "${CMAKE_C_LINKER_FLAGS} -m32") endif(${NATS_BUILD_ARCH} MATCHES "32") elseif(WIN32) set(NATS_LIBDIR "lib") set(NATS_INCLUDE_DIR "include") set(NATS_EXTRA_LIB "ws2_32") set(NATS_OS "_WIN32") set(NATS_PLATFORM_INCLUDE "win") # Warning control. if(MSVC) # Set warning level to maximum, then disable: # /wd4100 unreferenced formal parameter # /wd4200 nonstandard extension used: zero-sized array in struct/union # /wd4130 logical operation on address of string constant # /wd4127 conditional expression is constant add_compile_options(/W4 /wd4100 /wd4200 /wd4130 /wd4127) else() add_compile_options(-Wall -Wextra -Wno-unused-parameter -Wno-pedantic -Wno-address -Wno-constant-conditional) endif() if(sodium_USE_STATIC_LIBS) add_definitions( -DSODIUM_STATIC -DSODIUM_EXPORT= ) endif(sodium_USE_STATIC_LIBS) endif(UNIX) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${NATS_COMMON_C_FLAGS} ${NATS_USE_PTHREAD} ${NATS_WARNINGS}") if(NATS_SANITIZE) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fno-omit-frame-pointer -fno-optimize-sibling-calls") endif(NATS_SANITIZE) if(UNIX) if(APPLE) else(APPLE) add_definitions(-D_GNU_SOURCE) if(NATS_BUILD_NO_SPIN) add_definitions(-DNATS_NO_SPIN) endif(NATS_BUILD_NO_SPIN) endif(APPLE) endif(UNIX) add_definitions(-D${NATS_OS}) add_definitions(-D_REENTRANT) if(NATS_BUILD_WITH_TLS) add_definitions(-DNATS_HAS_TLS) if(NATS_BUILD_TLS_USE_OPENSSL_1_1_API) add_definitions(-DNATS_USE_OPENSSL_1_1) endif(NATS_BUILD_TLS_USE_OPENSSL_1_1_API) if(NATS_BUILD_TLS_FORCE_HOST_VERIFY) add_definitions(-DNATS_FORCE_HOST_VERIFICATION) endif(NATS_BUILD_TLS_FORCE_HOST_VERIFY) set(NATS_DOC_INCLUDE_TLS "NATS_HAS_TLS") endif(NATS_BUILD_WITH_TLS) #------------ # Versionning and Doc set(NATS_VERSION_MAJOR 3) set(NATS_VERSION_MINOR 10) set(NATS_VERSION_PATCH 1) set(NATS_VERSION_SUFFIX "") set(NATS_VERSION_REQUIRED_NUMBER 0x030A00) write_basic_package_version_file( "${PROJECT_BINARY_DIR}/cnats-config-version.cmake" COMPATIBILITY SameMinorVersion VERSION ${NATS_VERSION_MAJOR}.${NATS_VERSION_MINOR}.${NATS_VERSION_PATCH}${NATS_VERSION_SUFFIX}) if(NATS_UPDATE_VERSION OR NATS_UPDATE_DOC) configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/src/version.h.in ${CMAKE_CURRENT_SOURCE_DIR}/src/version.h @ONLY) configure_file( ${CMAKE_SOURCE_DIR}/doc/DoxyFile.NATS.Client.in ${CMAKE_SOURCE_DIR}/doc/DoxyFile.NATS.Client @ONLY) endif(NATS_UPDATE_VERSION OR NATS_UPDATE_DOC) #------------ #------------ # pkg-config if(UNIX) configure_file( ${PROJECT_SOURCE_DIR}/src/libnats.pc.in ${PROJECT_BINARY_DIR}/libnats.pc @ONLY ) install ( FILES "${PROJECT_BINARY_DIR}/libnats.pc" DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig") endif(UNIX) #------------ #---------------------------- # Add the project directories add_subdirectory(src) add_subdirectory(examples) add_subdirectory(examples/getstarted) if(NATS_BUILD_STREAMING) add_subdirectory(examples/stan) endif() add_subdirectory(test) add_subdirectory(test/dylib) add_subdirectory(test/check_cpp) #---------------------------- nats.c-3.10.1/CODE-OF-CONDUCT.md000066400000000000000000000002121476505644000154230ustar00rootroot00000000000000## Community Code of Conduct NATS follows the [CNCF Code of Conduct](https://github.com/cncf/foundation/blob/master/code-of-conduct.md). nats.c-3.10.1/GOVERNANCE.md000066400000000000000000000002721476505644000147470ustar00rootroot00000000000000# NATS C Client Governance NATS C Client (nats.c) is part of the NATS project and is subject to the [NATS Governance](https://github.com/nats-io/nats-general/blob/master/GOVERNANCE.md).nats.c-3.10.1/LICENSE000066400000000000000000000261341476505644000140100ustar00rootroot00000000000000 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.nats.c-3.10.1/MAINTAINERS.md000066400000000000000000000004531476505644000150730ustar00rootroot00000000000000# Maintainers Maintainership is on a per project basis. ### Maintainers - Derek Collison [@derekcollison](https://github.com/derekcollison) - Ivan Kozlovic [@kozlovic](https://github.com/kozlovic) - Lev Brouk [@levb](https://github.com/levb) nats.c-3.10.1/README.md000066400000000000000000002360561476505644000142700ustar00rootroot00000000000000# NATS & NATS Streaming - C Client A C client for the [NATS messaging system](https://nats.io). Go [here](http://nats-io.github.io/nats.c) for the online documentation, and check the [frequently asked questions](https://github.com/nats-io/nats.c#faq). This NATS Client implementation is heavily based on the [NATS GO Client](https://github.com/nats-io/nats.go). There is support for Mac OS/X, Linux and Windows (although we don't have specific platform support matrix). [![License Apache 2](https://img.shields.io/badge/License-Apache2-blue.svg)](https://www.apache.org/licenses/LICENSE-2.0) [![Build Status](https://travis-ci.com/nats-io/nats.c.svg?branch=main)](https://travis-ci.com/github/nats-io/nats.c) [![Coverage Status](https://coveralls.io/repos/github/nats-io/nats.c/badge.svg?branch=main)](https://coveralls.io/github/nats-io/nats.c?branch=main) [![Release](https://img.shields.io/badge/release-v3.10.0-blue.svg?style=flat)](https://github.com/nats-io/nats.c/releases/tag/v3.10.0) [![Documentation](https://img.shields.io/badge/doc-Doxygen-brightgreen.svg?style=flat)](http://nats-io.github.io/nats.c) # Table of Contents - [Installing](#installing) - [Building](#building) * [TLS Support](#tls-support) * [Link statically](#link-statically) * [Building with EXPERIMENTAL API support](#building-with-experimental-API-support) * [Building with Streaming](#building-with-streaming) * [Building with Libsodium](#building-with-libsodium) * [Testing](#testing) - [Documentation](#documentation) - [NATS Client](#nats-client) * [Important Changes](#important-changes) * [JetStream](#jetstream) * [JetStream Basic Usage](#jetstream-basic-usage) * [JetStream Basic Management](#jetstream-basic-usage) * [KeyValue](#keyvalue) * [KeyValue Management](#keyvalue-management) * [KeyValue APIs](#keyvalue-apis) * [Getting Started](#getting-started) * [Basic Usage](#basic-usage) * [Headers](#headers) * [Wildcard Subscriptions](#wildcard-subscriptions) * [Queue Groups](#queue-groups) * [TLS](#tls) * [New Authentication (Nkeys and User Credentials)](#new-authentication-nkeys-and-user-credentials) * [Advanced Usage](#advanced-usage) * [Clustered Usage](#clustered-usage) * [Using an Event Loop Library](#using-an-event-loop-library) * [FAQ](#faq) - [NATS Streaming Client](#nats-streaming-client) * [Streaming Basic Usage](#streaming-basic-usage) * [Streaming Subscriptions](#streaming-subscriptions) * [Streaming Durable Subscriptions](#streaming-durable-subscriptions) * [Streaming Queue Groups](#streaming-queue-groups) * [Creating a Queue Group](#creating-a-queue-group) * [Start Position](#start-position) * [Leaving the Group](#leaving-the-group) * [Closing a Queue Group](#closing-a-queue-group) * [Streaming Durable Queue Groups](#streaming-durable-queue-groups) * [Creating a Durable Queue Group](#creating-a-durable-queue-group) * [Start Position of the Durable Queue Group](#start-position-of-the-durable-queue-group) * [Leaving the Durable Queue Group](#leaving-the-durable-queue-group) * [Closing the Durable Queue Group](#closing-the-durable-queue-group) * [Streaming Wildcard Subscriptions](#streaming-wildcard-subscriptions) * [Streaming Advanced Usage](#streaming-advanced-usage) * [Connection Status](#connection-status) * [Asynchronous Publishing](#asynchronous-publishing) * [Message Acknowledgments and Redelivery](#message-acknowledgments-and-redelivery) * [Rate limiting/matching](#rate-limitingmatching) * [Publisher Rate Limiting](#publisher-rate-limiting) * [Subscriber Rate Limiting](#subscriber-rate-limiting) - [License](#license) ## Installing There are several package managers with NATS C client library available. If you know one that is not in this list, please submit a PR to add it! - [conan](https://conan.io/center) The "cnats" recipe is [here](https://github.com/conan-io/conan-center-index/tree/master/recipes/cnats) - [Homebrew](https://github.com/Homebrew/homebrew-core) The "cnats" formula is [here](https://github.com/Homebrew/homebrew-core/blob/master/Formula/c/cnats.rb) - [vcpkg](https://vcpkg.io) The "cnats" port is [here](https://github.com/microsoft/vcpkg/tree/master/ports/cnats) ## Building First, download the source code: ``` git clone git@github.com:nats-io/nats.c.git . ``` To build the library, use [CMake](https://cmake.org/download/). Note that by default the NATS Streaming API will be built and included in the NATS library. See below if you do not want to build the Streaming related APIs. Make sure that CMake is added to your path. If building on Windows, open a command shell from the Visual Studio Tools menu, and select the appropriate command shell (x64 or x86 for 64 or 32 bit builds respectively). You will also probably need to run this with administrator privileges. Create a `build` directory (any name would work) from the root source tree, and `cd` into it. Then issue this command for the first time: ``` cmake .. ``` In some architectures, you may experience a compilation error for `mutex.c.o` because there is no support for the assembler instruction that we use to yield when spinning trying to acquire a lock. You may get this sort of build error: ``` /tmp/cc1Yp7sD.s: Assembler messages: /tmp/cc1Yp7sD.s:302: Error: selected processor does not support ARM mode `yield' src/CMakeFiles/nats_static.dir/build.make:542: recipe for target 'src/CMakeFiles/nats_static.dir/unix/mutex.c.o' failed ``` If that's the case, you can solve this by enabling the `NATS_BUILD_NO_SPIN` flag (or use `-DNATS_NO_SPIN` if you compile without CMake): ``` cmake .. -DNATS_BUILD_NO_SPIN=ON ``` If you had previously built the library, you may need to do a `make clean`, or simply delete and re-create the build directory before executing the cmake command. To build on Windows, you would need to select the build generator. For instance, to select `nmake`, you would run: ``` cmake .. -G "NMake Makefiles" ``` Running `cmake -h` would give you the list of possible options and all the generator names. Alternatively, you can run the GUI version. From that same *build* command shell, start the GUI: ``` c:\program files (x86)\CMake\bin\cmake-gui.exe ``` If you started with an empty build directory, you would need to select the source and build directory, then click `Configure`. Here, you will be able to select from the drop-down box the name of the build generator. When done, click `Generate`. Then you can go back to your command shell, or Visual Studio and build. To modify some of the build options, you need to edit the cache and rebuild. ``` make edit_cache ``` Note that if you build on Windows and have selected "NMake Makefiles", replace all following references to `make` with `nmake`. Editing the cache allows you to select the build type (Debug, Release, etc), the architecture (64 or 32bit), and so on. The default target will build everything, that is, the static and shared NATS libraries and also the examples and the test program. Each are located in their respective directories under your build directory: `src`, `examples` and `test`. ``` make install ``` Will copy both the static and shared libraries in the folder `install/lib` and the public headers in `install/include`. ## TLS Support By default, the library is built with TLS support. You can disable this from the cmake gui `make edit_cache` and switch the `NATS_BUILD_WITH_TLS` option to `OFF`, or pass the option directly to the `cmake` command: ``` cmake .. -DNATS_BUILD_WITH_TLS=OFF ``` Starting `2.0.0`, when building with TLS/SSL support, the server certificate's expected hostname is always verified. It means that the hostname provided in the URL(s) or through the option `natsOptions_SetExpectedHostname()` will be used to check the hostname present in the certificate. Prior to `2.0.0`, the hostname would be verified *only* if the option `natsOptions_SetExpectedHostname()` was invoked. Although we recommend leaving the new default behavior, you can restore the previous behavior by building the library with this option off: ``` cmake .. -DNATS_BUILD_TLS_FORCE_HOST_VERIFY=OFF ``` The NATS C client is built using APIs from the [OpenSSL](https://github.com/openssl/openssl) library. By default we use `3.0+` APIs. Since OpenSSL `1.0.2` is no longer supported, starting with NATS C Client `v3.6.0` version, the CMake variable `NATS_BUILD_TLS_USE_OPENSSL_1_1_API` is now set to `ON` by default (if you are setting up a new environment) and will use OpenSSL APIs from `1.1+`/`3.0+` APIs. You will still be able to compile with the OpenSSL `1.0.2` library by setting this CMake option to `OFF`: ``` cmake .. -DNATS_BUILD_TLS_USE_OPENSSL_1_1_API=OFF ``` The variable `NATS_BUILD_TLS_USE_OPENSSL_1_1_API` is deprecated, meaning that in the future this option will simply be removed and only OpenSSL `3.0+` APIs will be used. The code in the library using older OpenSSL APIs will be removed too. Note that the variable `NATS_BUILD_WITH_TLS_CLIENT_METHOD` that was deprecated in `v2.0.0` has now been removed. Since the NATS C client dynamically links to the OpenSSL library, you need to make sure that you are then running your application against an OpenSSL 1.1+/3.0+ library. ### Link statically If you want to link to the static OpenSSL library, you need to delete the `CMakeCache.txt` and regenerate it with the additional option: ``` rm CMakeCache.txt cmake .. -DNATS_BUILD_OPENSSL_STATIC_LIBS=ON ``` Then call `make` (or equivalent depending on your platform) and this should ensure that the library (and examples and/or test suite executable) are linked against the OpenSSL library, if it was found by CMake. ## Building with EXPERIMENTAL API support At times we may introduce APIs that are not stable yet. To build with them, define NATS_WITH_EXPERIMENTAL: ``` # cd ./build rm CMakeCache.txt cmake .. -DNATS_WITH_EXPERIMENTALON make ``` Note that experimental APIs may have other dependencies (like SSL). ## Building with Streaming When building the library with Streaming support, the NATS library uses the [libprotobuf-c](https://github.com/protobuf-c/protobuf-c) library. When cmake runs for the first time (or after removing `CMakeCache.txt` and calling `cmake ..` again), it is looking for the libprotobuf-c library. If it does not find it, a message is printed and the build process fails. CMake searches for the library in directories where libraries are usually found. However, if you want to specify a specific directory where the library is located, you need to do this: ``` cmake .. -DNATS_PROTOBUF_DIR= ``` The static library will be used by default. If you want to change that, or if the library has not the expected name, you need to do this: ``` # Use the library named mylibproto.so located at /my/location cmake .. -DNATS_PROTOBUF_LIBRARY=/my/location/mylibproto.so ``` The two could be combined if the include header is located in a different directory ``` # Use the library named mylibproto.so located at /my/location and the directory protobuf-c/ containing protobuf-c.h located at /my/other/location cmake .. -DNATS_PROTOBUF_LIBRARY=/my/location/mylibproto.so -DNATS_PROTOBUF_DIR=/my/other/location ``` If you don't want to build the NATS Streaming APIs to be included in the NATS library: ``` cmake .. -DNATS_BUILD_STREAMING=OFF ``` ## Building with Libsodium When using the new NATS 2.0 security features, the library needs to sign some "nonce" sent by the server during a connect or reconnect. We use [Ed25519](https://ed25519.cr.yp.to/) public-key signature. The library comes with some code to perform the signature. In most case, it will be fine, but if performance is an issue (especially if you plan to use the `natsConnection_Sign()` function a lot), you will have the option to build with the [Libsodium](https://github.com/jedisct1/libsodium) library. Follow instructions on how to install the libsodium library [here](https://download.libsodium.org/doc/). On macOS, you could use `brew`: ``` brew install libsodium ``` On Linux, you could use `apt-get` ``` apt-get install libsodium-dev ``` Once installed, you can rebuild the NATS C client by first enabling the use of the libsodium library: ``` cmake .. -DNATS_BUILD_USE_SODIUM=ON ``` If you have the libsodium library installed in a non standard location that CMake cannot find, you can specify the location of this directory: ``` cmake .. -DNATS_BUILD_USE_SODIUM=ON -DNATS_SODIUM_DIR=/my/path/to/libsodium ``` ## Testing On platforms where `valgrind` is available, you can run the tests with memory checks. Here is an example: ``` make test ARGS="-T memcheck" ``` Or, you can invoke directly the `ctest` program: ``` ctest -T memcheck -V -I 1,4 ``` The above command would run the tests with `valgrind` (`-T memcheck`), with verbose output (`-V`), and run the tests from 1 to 4 (`-I 1,4`). If you add a test to `test/test.c`, you need to add it into the `list_test.txt` file. Each entry contains just the test name, the function must be named identically, with a `test_` prefix. The list is in alphabetical order, but it does not need to be, you can add anywhere. If you are adding a benchmark, it should be added to the `list_bench.txt`. These tests are labeled differently (`-L 'bench'`) and executed separately on CI. You need to re-run `cmake` for the changes to take effect: ``` cmake .. -- Configuring done -- Generating done -- Build files have been written to: /home/ivan/nats.c/build ``` You can use the following environment variables to influence the testsuite behavior. When running with memory check, timing changes and overall performance is slower. The following variable allows the testsuite to adjust some of values used during the test: ``` export NATS_TEST_VALGRIND=yes ``` On Windows, it would be `set` instead of `export`. When running the tests in verbose mode, the following environment variable allows you to see the server output from within the test itself. Without this option, the server output is silenced: ``` export NATS_TEST_KEEP_SERVER_OUTPUT=yes ``` If you want to change the default server executable name (`nats-server.exe`) or specify a specific location, use this environment variable: ``` set NATS_TEST_SERVER_EXE=c:\test\nats-server.exe ``` # Documentation The public API has been documented using [Doxygen](http://www.stack.nl/~dimitri/doxygen/). To generate the documentation, go to the `doc` directory and type the following command: ``` doxygen DoxyFile.NATS.Client ``` If you toggle the build of the Streaming APIs, and the documentation is no longer matching what is being built, you can update the documentation by switching the `NATS_UPDATE_DOC` build flag and rebuild the documentation. From the build directory: ``` cmake .. -DNATS_UPDATE_DOC=ON make cd /doc doxygen DoxyFile.NATS.Client ``` The generated documentation will be located in the `html` directory. To see the documentation, point your browser to the file `index.html` in that directory. Go [here](http://nats-io.github.io/nats.c) for the online documentation. The source code is also quite documented. # NATS Client ## Important Changes This section lists important changes such as deprecation notices, etc... ### Version `2.0.0` This version introduces the security concepts used by NATS Server `2.0.0` and therefore aligns with the server version. There have been new APIs introduced, but the most important change is the new default behavior with TLS connections: * When establishing a secure connection, the server certificate's hostname is now always verified, regardless if the user has invoked `natsOptions_SetExpectedHostname()`. This may break applications that were for instance using an IP to connect to a server that had only the hostname in the certificate. This can be solved by changing your application to use the hostname in the URL or make use of `natsOptions_SetExpectedHostname()`. If this is not possible, you can restore the old behavior by building the library with the new behavior disabled. See #tls-support for more information. * This repository used to include precompiled libraries of [libprotobuf-c](https://github.com/protobuf-c/protobuf-c) for macOS, Linux and Windows along with the header files (in the `/pbuf` directory). We have now removed this directory and require that the user installs the libprotobuf-c library separately. See the [building instructions](#building) to specify the library location if CMake cannot find it directly. ### Version `1.8.0` * The `natsConnStatus` enum values have been prefixed with `NATS_CONN_STATUS_`. If your application is not using referencing any original value, such as `CONNECTED` or `CLOSED`, etc.. then there is nothing that you need to do. If you do, you have two options: * Replace all references from the orignal values to the new value (adding the prefix) * Compile the library with the option to use the original values (no prefix). Edit the CMake cache and turn on the option `NATS_BUILD_NO_PREFIX_CONNSTS`. This can be done this way from the build directory: `cmake .. -DNATS_BUILD_NO_PREFIX_CONNSTS=ON` ## Getting Started The `examples/getstarted` directory has a set of simple examples that are fully functional, yet very simple. The goal is to demonstrate how easy to use the API is. A more complex set of examples are in `examples/` directory and can also be used to benchmark the client library. ## Basic Usage Note that for simplicity, error checking is not performed here. ```c natsConnection *nc = NULL; natsSubscription *sub = NULL; natsMsg *msg = NULL; // Connects to the default NATS Server running locally natsConnection_ConnectTo(&nc, NATS_DEFAULT_URL); // Connects to a server with username and password natsConnection_ConnectTo(&nc, "nats://ivan:secret@localhost:4222"); // Connects to a server with token authentication natsConnection_ConnectTo(&nc, "nats://myTopSecretAuthenticationToken@localhost:4222"); // Simple publisher, sending the given string to subject "foo" natsConnection_PublishString(nc, "foo", "hello world"); // Publish binary data. Content is not interpreted as a string. char data[] = {1, 2, 0, 4, 5}; natsConnection_Publish(nc, "foo", (const void*) data, 5); // Simple asynchronous subscriber on subject foo, invoking message // handler 'onMsg' when messages are received, and not providing a closure. natsConnection_Subscribe(&sub, nc, "foo", onMsg, NULL); // Simple synchronous subscriber natsConnection_SubscribeSync(&sub, nc, "foo"); // Using a synchronous subscriber, gets the first message available, waiting // up to 1000 milliseconds (1 second) natsSubscription_NextMsg(&msg, sub, 1000); // Destroy any message received (asynchronously or synchronously) or created // by your application. Note that if 'msg' is NULL, the call has no effect. natsMsg_Destroy(msg); // Unsubscribing natsSubscription_Unsubscribe(sub); // Destroying the subscription (this will release the object, which may // result in freeing the memory). After this call, the object must no // longer be used. natsSubscription_Destroy(sub); // Publish requests to the given reply subject: natsConnection_PublishRequestString(nc, "foo", "bar", "help!"); // Sends a request (internally creates an inbox) and Auto-Unsubscribe the // internal subscriber, which means that the subscriber is unsubscribed // when receiving the first response from potentially many repliers. // This call will wait for the reply for up to 1000 milliseconds (1 second). natsConnection_RequestString(&reply, nc, "foo", "help", 1000); // Closing a connection (but not releasing the connection object) natsConnection_Close(nc); // When done with the object, free the memory. Note that this call // closes the connection first, in other words, you could have simply // this call instead of natsConnection_Close() followed by the destroy // call. natsConnection_Destroy(nc); // Message handler void onMsg(natsConnection *nc, natsSubscription *sub, natsMsg *msg, void *closure) { // Prints the message, using the message getters: printf("Received msg: %s - %.*s\n", natsMsg_GetSubject(msg), natsMsg_GetDataLength(msg), natsMsg_GetData(msg)); // Don't forget to destroy the message! natsMsg_Destroy(msg); } ``` ## JetStream Support for JetStream starts with the version `v3.0.0` of the library and NATS Server `v2.2.0+`, although getting JetStream specific error codes requires the server at version `v2.3.0+`. Some of the configuration options are only available starting `v2.3.3`, so we recommend that you use the latest NATS Server release to have a better experience. Look at examples named `js-xxx.c` in the `examples` directory for examples on how to use the API. The new objects and APIs are full documented in the online [documentation](http://nats-io.github.io/nats.c/group__js_group.html). ### JetStream Basic Usage ```c // Connect to NATS natsConnection_Connect(&conn, opts); // Initialize and set some JetStream options jsOptions jsOpts; jsOptions_Init(&jsOpts); jsOpts.PublishAsync.MaxPending = 256; // Create JetStream Context natsConnection_JetStream(&js, conn, &jsOpts); // Simple Stream Publisher js_Publish(&pa, js, "ORDERS.scratch", (const void*) "hello", 5, NULL, &jerr); // Simple Async Stream Publisher for (i=0; i < 500; i++) { js_PublishAsync(js, "ORDERS.scratch", (const void*) "hello", 5, NULL); } // Wait for up to 5 seconds to receive all publish acknowledgments. jsPubOptions_Init(&jsPubOpts); jsPubOpts.MaxWait = 5000; js_PublishAsyncComplete(js, &jsPubOpts); // One can get the list of all pending publish async messages, // to either resend them or simply destroy them. natsMsgList pending; s = js_PublishAsyncGetPendingList(&pending, js); if (s == NATS_OK) { int i; for (i=0; i` wildcard matches any length of the fail of a subject, and can only be the last token. ```c natsConnection_Subscribe(&sub, nc, "foo.>", onMsg, NULL); ``` This subscriber would receive any message sent to: * foo.bar * foo.bar.baz * foo.foo.bar.bax.22 * etc... However, it would not receive messages sent on: * foo * bar.foo.baz * etc... Publishing on this subject would cause the two above subscriber to receive the message: ```c natsConnection_PublishString(nc, "foo.bar.baz", "got it?"); ``` ## Queue Groups All subscriptions with the same queue name will form a queue group. Each message will be delivered to only one subscriber per queue group, using queue sematics. You can have as many queue groups as you wish. Normal subscribers will continue to work as expected. ```c natsConnection_QueueSubscribe(&sub, nc, "foo", "job_workers", onMsg, NULL); ``` ## TLS (Note that the library needs to be built with TLS support - which is by default - for these APIs to work. See the Build chapter on how to build with or without TLS for more details). An SSL/TLS connection is configured through the use of `natsOptions`. Depending on the level of security you desire, it can be as simple as setting the secure boolean to true on the `natsOptions_SetSecure()` call. Even with full security (client verifying server certificate, and server requiring client certificates), the setup involves only a few calls. ```c // Here is the minimum to create a TLS/SSL connection: // Create an options object. natsOptions_Create(&opts); // Set the secure flag. natsOptions_SetSecure(opts, true); // You may not need this, but suppose that the server certificate // is self-signed and you would normally provide the root CA, but // don't want to. You can disable the server certificate verification // like this: natsOptions_SkipServerVerification(opts, true); // Connect now... natsConnection_Connect(&nc, opts); // That's it! On success you will have a secure connection with the server! (...) // This example shows what it takes to have a full SSL configuration, // including server expected's hostname, root CA, client certificates // and specific ciphers to use. // Create an options object. natsOptions_Create(&opts); // Set the secure flag. natsOptions_SetSecure(opts, true); // For a server with a trusted chain built into the client host, // simply designate the server name that is expected. Without this // call, the server certificate is still verified, but not the // hostname. natsOptions_SetExpectedHostname(opts, "localhost"); // Instead, if you are using a self-signed cert and need to load in the CA. natsOptions_LoadCATrustedCertificates(opts, caCertFileName); // If the server requires client certificates, provide them along with the // private key, all in one call. natsOptions_LoadCertificatesChain(opts, certChainFileName, privateKeyFileName); // You can also specify preferred ciphers if you want. natsOptions_SetCiphers(opts, "-ALL:HIGH"); // Then simply pass the options object to the connect call: natsConnection_Connect(&nc, opts); // That's it! On success you will have a secure connection with the server! ``` ## New Authentication (Nkeys and User Credentials) This requires server with version >= 2.0.0 NATS servers have a new security and authentication mechanism to authenticate with user credentials and Nkeys. The simplest form is to use the helper option `natsOptions_SetUserCredentialsFromFiles()`. ```c // Retrieve both user JWT and NKey seed from single file `user.creds`. s = natsOptions_SetUserCredentialsFromFiles(opts, "user.creds", NULL); if (s == NATS_OK) s = natsConnection_Connect(&nc, opts); ``` With this option, the library will load the user JWT and NKey seed from a single file. Note that the library wipes the buffers used to read the files. If you prefer to store the JWT and seed in two distinct files, use this form instead: ```c // Retrieve the user JWT from the file `user.jwt` and the seed from the file `user.nk`. s = natsOptions_SetUserCredentialsFromFiles(opts, "user.jwt", "user.nk"); if (s == NATS_OK) s = natsConnection_Connect(&nc, opts); ``` You can also set the callback handlers and manage challenge signing directly. ```c /* * myUserJWTCb is a callback that is supposed to return the user JWT. * An optional closure can be specified. * mySignatureCB is a callback that is presented with a nonce and is * responsible for returning the signature for this nonce. * An optional closure can be specified. */ s = natsOptions_SetUserCredentialsCallbacks(opts, myUserJWTCb, NULL, mySignatureCb, NULL); if (s == NATS_OK) s = natsConnection_Connect(&nc, opts); ``` For NKey authentication, it is possible to specify the public NKey and the file containing the corresponding NKey seed. On connect, the library will load this file to look for the NKey seed and use it to sign the nonce sent by the server. The library takes care of clearing the memory where the seed is copied as soon as the nonce is signed. ```c s = natsOptions_SetNKeyFromSeed(opts, "UDXU4RCSJNZOIQHZNWXHXORDPRTGNJAHAHFRGZNEEJCPQTT2M7NLCNF4", "seed.nk"); if (s == NATS_OK) s = natsConnection_Connect(&nc, opts); ``` The "seed.nk" file contains the NKey seed (private key). Here is an example: ``` $ more seed.nk SUACSSL3UAHUDXKFSNVUZRF5UHPMWZ6BFDTJ7M6USDXIEDNPPQYYYCU3VY ``` Finally, it is possible to specify the public NKey and the signature callback. The public key will be sent to the server and the provided callback is responsible for signing the server's nonce. When the server receives the signed nonce, it can check that it was signed poperly using the provided public key. ```c /* * myPublicKey is the user's public key, which will be sent to the server. * mySignatureCB is a callback that is presented with a nonce and is * responsible for returning the signature for this nonce. * An optional closure can be specified. */ s = natsOptions_SetNKey(opts, myPublicKey, mySignatureCb, NULL); if (s == NATS_OK) s = natsConnection_Connect(&nc, opts); ``` The signature callback can use any crypto library to sign the nonce, but also the provided `nats_Sign()` function. ```c natsStatus mySignatureCb( char **customErrTxt, unsigned char **signature, int *signatureLength, const char *nonce, void *closure) { // This approach requires to provide the seed (private key). // Hardcoding it in the application (like in this example) may not be really safe. return nats_Sign( "SUACSSL3UAHUDXKFSNVUZRF5UHPMWZ6BFDTJ7M6USDXIEDNPPQYYYCU3VY", nonce, signature, signatureLength); } ``` You can sign any content and get the signature in return. The connection must have been created with the `natsOptions_SetUserCredentialsFromFiles()` option for that to work. ```c s = natsOptions_Create(&opts); if (s == NATS_OK) s = natsOptions_SetUserCredentialsFromFiles(opts, "user.creds", NULL); if (s == NATS_OK) s = natsConnection_Connect(&nc, opts); // Sign some arbitrary content const unsigned char *content = (const unsigned char*) "hello"; int contentLen = 5; unsigned char sig[64]; s = natsConnection_Sign(nc, content, contentLen, sig); if (s == NATS_OK) { // Do something with signature... } ``` ## Advanced Usage Flushing a connection ensures that any data buffered is flushed (sent to) the NATS Server. ```c // Flush connection to server, returns when all messages have been processed. natsConnection_Flush(nc); printf("All clear!\n"); // Same as above but with a timeout value, expressed in milliseconds. s = natsConnection_FlushTimeout(nc, 1000); if (s == NATS_OK) printf("All clear!\n"); else if (s == NATS_TIMEOUT) printf("Flushed timed out!\n"); else printf("Error during flush: %d - %s\n", s, natsStatus_GetText(s)); ``` Auto-unsubscribe allows a subscription to be automatically removed when the subscriber has received a given number of messages. This is used internally by the `natsConnection_Request()` call. ```c // Auto-unsubscribe after 100 messages received natsConnection_Subscribe(&sub, nc, "foo", onMsg, NULL); natsSubscription_AutoUnsubscribe(sub, 100); ``` Subscriptions can be drained. This ensures that the interest is removed from the server but that all messages that were internally queued are processed. ```c // This call does not block. natsSubscription_Drain(sub); // If you want to wait for the drain to complete, call this // and specify a timeout. Zero or negative to wait for ever. natsSubscription_WaitForDrainCompletion(sub, 0); ``` Connections can be drained. This process will first put all registered subscriptions in drain mode and prevent any new subscription from being created. When all subscriptions are drained, the publish calls are drained (by the mean of a connection flush) and new publish calls will fail at this point. Then the connection is closed. ```c // Use default timeout of 30 seconds. // But this call does not block. Use natsOptions_SetClosedCB() to be notified // that the connection is closed. natsConnection_Drain(nc); // To specify a timeout for the operation to complete, after which the connection // is forcefully closed. Here is an exampel of a timeout of 10 seconds (10,000 ms). natsConnection_DrainTimeout(nc, 10000); ``` You can have multiple connections in your application, mixing subscribers and publishers. ```c // Create a connection 'nc1' to host1 natsConnection_ConnectTo(&nc1, "nats://host1:4222"); // Create a connection 'nc2' to host2 natsConnection_ConnectTo(&nc2, "nats://host2:4222"); // Create a subscription on 'foo' from connection 'nc1' natsConnection_Subscribe(&sub, nc1, "foo", onMsg, NULL); // Uses connection 'nc2' to publish a message on subject 'foo'. The subscriber // created previously will receive it through connection 'nc1'. natsConnection_PublishString(nc2, "foo", "hello"); ``` The use of `natsOptions` allows you to specify options used by the `natsConnection_Connect()` call. Note that the `natsOptions` object that is passed to this call is cloned, whhich means that any modification done to the options object will not have any effect on the connected connection. ```c natsOptions *opts = NULL; // Create an options object natsOptions_Create(&opts); // Set some properties, starting with the URL to connect to: natsOptions_SetURL(opts, "nats://host1:4222"); // Set a callback for asynchronous errors. This is useful when having an asynchronous // subscriber, which would otherwise have no other way of reporting an error. natsOptions_SetErrorHandler(opts, asyncCb, NULL); // Connect using those options: natsConnection_Connect(&nc, opts); // Destroy the options object to free memory. The object was cloned by the connection, // so the options can be safely destroyed. natsOptions_Destroy(opts); ``` As we have seen, all callbacks have a `void *closure` parameter. This is useful when the callback needs to perform some work and need a reference to some object. When setting up the callback, you can specify a pointer to that object. ```c // Our object definition typedef struct __Errors { int count; } Errors; (...) int main(int argc, char **argv) { // Declare an 'Errors' object on the stack. Errors asyncErrors; // Initialize this object memset(&asyncErrors, 0, sizeof(asyncErrors); // Create a natsOptions object. (...) // Set the error callback, and pass the address of our Errors object. natsOptions_SetErrorHandler(opts, asyncCb, (void*) &asyncErrors); // Create the connection and subscriber. (...) // Say that we are done subscribing, we could check the number of errors: if (asyncErrors.count > 1000) { printf("That's a lot of errors!\n"); } (...) } ``` The callback would use the closure this way: ```c static void asyncCb(natsConnection *nc, natsSubscription *sub, natsStatus err, void *closure) { Errors *errors = (Errors*) closure; printf("Async error: %d - %s\n", err, natsStatus_GetText(err)); errors->count++; } ``` This is the same for all other callbacks used in the C NATS library. The library can automaticall reconnect to a NATS Server if the connection breaks. However, the initial connect itself would fail if no server is available at the time of the connect. An option has been added to make the connect behaves as the reconnect, using the reconnect attempts and wait: ```c s = natsOptions_SetMaxReconnect(opts, 5); if (s == NATS_OK) s = natsOptions_SetReconnectWait(opts, 1000); // Instruct the library to block the connect call for that // long until it can get a connection or fails. if (s == NATS_OK) s = natsOptions_SetRetryOnFailedConnect(opts, true, NULL, NULL); // If the server is not running, this will block for about 5 seconds. s = natsConnection_Connect(&conn, opts); ``` You can make the connect asynchronous (if it can't connect immediately) by passing a connection handler: ```c s = natsOptions_SetMaxReconnect(opts, 5); if (s == NATS_OK) s = natsOptions_SetReconnectWait(opts, 1000); if (s == NATS_OK) s = natsOptions_SetRetryOnFailedConnect(opts, true, connectedCB, NULL); // Start the connect. If no server is running, it should return NATS_NOT_YET_CONNECTED. s = natsConnection_Connect(&conn, opts); printf("natsConnection_Connect call returned: %s\n", natsStatus_GetText(s)); // Connection can be used to create subscription and publish messages (as // long as the reconnect buffer is not full). ``` Check the example `examples/connect.c` for more use cases. You can also specify a write deadline which means that when the library is trying to send bytes to the NATS Server, if the connection if unhealthy but as not been reported as closed, calls will fail with a `NATS_TIMEOUT` error. The socket will be closed and the library will attempt to reconnect (unless disabled). Note that this could also happen in the event the server is not consuming fast enough. ```c // Sets a write deadline of 2 seconds (value is in milliseconds). s = natsOptions_SetWriteDeadline(opts, 2000); ``` ## Clustered Usage ```c static char *servers[] = { "nats://localhost:1222", "nats://localhost:1223", "nats://localhost:1224"}; // Setup options to include all servers in the cluster. // We first created an options object, and pass the list of servers, specifying // the number of servers on that list. natsOptions_SetServers(opts, servers, 3); // We could also set the amount to sleep between each reconnect attempt (expressed in // milliseconds), and the number of reconnect attempts. natsOptions_SetMaxReconnect(opts, 5); natsOptions_SetReconnectWait(opts, 2000); // We could also disable the randomization of the server pool natsOptions_SetNoRandomize(opts, true); // Setup a callback to be notified on disconnects... natsOptions_SetDisconnectedCB(opts, disconnectedCb, NULL); // And on reconncet natsOptions_SetReconnectedCB(opts, reconnectedCb, NULL); // This callback could be used to see who we are connected to on reconnect static void reconnectedCb(natsConnection *nc, void *closure) { // Define a buffer to receive the url char buffer[64]; buffer[0] = '\0'; natsConnection_GetConnectedUrl(nc, buffer, sizeof(buffer)); printf("Got reconnected to: %s\n", buffer); } ``` ## Using an Event Loop Library For each connection, the `NATS` library creates a thread reading data from the socket. Publishing data results in the data being appended to a buffer, which is 'flushed' from a timer callback or in place when the buffer reaches a certain size. Flushing means that we write to the socket (and the socket is in blocking-mode). If you have multiple connections running in your process, the number of threads will increase (because each connection uses a thread for receiving data from the socket). If this becomes an issue, or if you are already using an event notification library, you can instruct the `NATS` library to use that event library instead of using a thread to do the reads, and directly writing to the socket when data is published. This works by setting the event loop and various callbacks through the `natsOptions_SetEventLoop()` API. Depending of the event loop you are using, you then have extra API calls to make. The API is in the `adapters` directory and is documented. We provide adapters for two event notification libraries: [libevent](https://github.com/libevent/libevent), and [libuv](https://github.com/libuv/libuv). ```c // Create an event loop object uv_loop_t *uvLoop = uv_default_loop(); // Set it into an options object natsOptions_SetEventLoop(opts, (void*) uvLoop, natsLibuv_Attach, natsLibuv_Read, natsLibuv_Write, natsLibuv_Detach); // Connect (as usual) natsConnection_Connect(&conn, opts); // Subscribe (as usual) natsConnection_Subscribe(&sub, conn, subj, onMsg, NULL); // Run the event loop uv_run(uvLoop, UV_RUN_DEFAULT); ``` The callback `onMsg` that you have registered will be triggered as usual when data becomes available. Where it becomes tricky is when publishing data. Indeed, publishing is merely putting data in a buffer, and it is the event library that will notify a callback that write to the socket should be performed. For that, the event loop needs to be 'running'. So if you publish from the thread where the event loop is running, you need to 'run' the loop after each (or a number) of publish calls in order for data to actually be sent out. Alternatively, you can publish from a different thread than the thread running the event loop. The above is important to keep in mind regarding calls that are doing request-reply. They should not be made from the thread running the event loop. Here is an example of such calls: ``` natsConnection_Request() natsConnection_Flush() natsConnection_FlushTimeout() ... ``` Indeed, since these calls publish data and wait for a 'response', if you execute then in the event loop thread (or while the loop is not 'running'), then data will not be sent out. Calls will fail to get a response and timeout. For `natsConnection_Request()`, use the `natsConnection_PublishRequest()` instead, and have a subscriber for the response registered. For others, asynchronous version of these calls should be made available. See examples in the `examples` directory for complete usage. ## FAQ Here are some of the frequently asked questions: Where do I start? There are several resources that will help you get started using the NATS C Client library.
The `examples/getstarted` directory contains very basic programs that use the library for simple functions such as sending a message or setting up a subscription.
The `examples` directory itself contains more elaborated examples that include error handling and more advanced APIs. You will also find examples to that show the use of the NATS C Client library and external event loops. What about support for platform XYZ? We support platforms that are available to us for development and testing. This is currently limited to Linux, macOS and Windows. Even then, there may be OS versions that you may have problem building with and we will gladly accept PRs to fix the build process as long as it does not break the ones we support! How do I build? We use cmake since it allows cross-platforms builds. This works for us. You are free to create your own makefile or Windows solution. If you want to use cmake, follow these [instructions](https://github.com/nats-io/nats.c#build). I have found a bug in your library, what do I do? Please report an issue [here](https://github.com/nats-io/nats.c/issues/new). Give us as much as possible information on how you can reproduce this. If you have a fix for it, you can also open a PR. Is the library thread-safe? All calls use internal locking where needed. As a user, you would need to do your own locking if you were to share the same callback with different subscribers (since the callback would be invoked from different threads for each subscriber).
Note that this is true for any kind of callback that exist in the NATS C library, such as connection or error handlers, etc.. if you specify the same callback you take the risk that the code in that callback may be executed from different internal threads. What is the threading model of the library? The library uses some threads to handle internal timers or dispatch asynchronous errors for instance. Here is a list of threads created as a result of the user creating NATS objects: - Each connection has a thread to read data from the socket. If you use an external event loop, this thread is not created. - Each connection has a thread responsible for flushing its outgoing buffer. If you create the connection with the `natsOptions_SetSendAsap()` option, this thread is not created since any outgoing data is flushed right away. - Each asynchronous subscription has a thread used to dispatch messages to the user callback. If you use `nats_SetMessageDeliveryPoolSize()`, a global thread pool (of the size given as a parameter to that function) is used instead of a per-async-subscription thread. How do I send binary data? NATS is a text protocol with message payload being a byte array. The server never interprets the content of a message. The natsConnection_Publish() API accepts a pointer to memory and the user provides how many bytes from that location need to be sent. The natsConnection_PublishString() is added for convenience if you want to send strings, but it is really equivalent to calling natsConnection_Publish() with `strlen` for the number of bytes. Is the data sent in place or from a different thread? For throughput reasons (and to mimic the Go client this library is based on), the client library uses a buffer for all socket writes. This buffer is flushed in the thread where the publish occurs if the buffer is full. The buffer size can be configured with natsOptions_SetIOBufSize(). You can query how much data is in that buffer using the natsConnection_Buffered() function. When a publish call does not fill the buffer, the call returns without any data actually sent to the server. A dedicated thread (the flusher thread) will flush this buffer automatically. This helps with throughput since the number of system calls are reduced and the number of bytes sent at once is higher, however, it can add latency for request/reply situations where one wants to send one message at a time. To that effect, natsConnection_Request() call does flush the buffer in place and does not rely on the flusher thread. The option natsOptions_SetSendAsap() can be used to force all publish calls from the connection created with this option to flush the socket buffer at every call and not add delay by relying on the flusher thread. The publish call did not return an error, is the message guaranteed to be sent to a subscriber? No! It is not even guaranteed that the server got that message. As described above, the message could simply be in connection's buffer, even if each publish call is flushing the socket buffer, after that, the call returns. There is no feedback from the server that it has actually processed that message. The server could have crashed after reading from the socket. Regardless if the server has gotten the message or not, there is a total decoupling between publishing and subscribing. If the publisher needs to know that its message has bee received and processed by the subscribing application, request/reply pattern should be used. Check natsConnection_Request() and natsConnection_PublishRequest() for more details. Do I need to call natsConnection_Flush() everywhere? This function is not merely flushing the socket buffer, instead it sends a `PING` protocol message to the server and gets a `PONG` back in a synchronous way. As previously described, if you want to flush the socket buffer to reduce latency in all publish calls, you should create the connection with the "send asap" option. The natsConnection_Flush() API is often used to ensure that the server has processed one of the protocol messages. For instance, creating a subscription is asynchronous. When the call returns, you may get an error if the connection was previously closed, but you would not get an error if your connection user has no permission to create this subscription for instance. Instead, the server sends an error message that is asynchronously received by the client library. Calling natsConnection_Flush() on the same connection that created the subscription ensures that the server has processed the subscription and if there was an error has sent that error back before the `PONG`. It is then possible to check the natsConnection_ReadLastError() to figure out if the subscription was successfully registered or not. How is data and protocols received from the server? When you create a connection, a library thread is created to read protocols (including messages) from the socket. You do not have to do anything in that regard. When data is read from the socket it will be turned into protocols or messages and distributed to appropriate callbacks. Lot of things are asynchronous, how do I know if there is an error? You should set error callbacks to be notified when asynchronous errors occur. These can be set through the use of natsOptions. Check natsOptions_SetErrorHandler() for instance. If you register an error callback for a connection, should an error occurs, your registered error handler will be invoked. Are messages from an asynchronous subscription dispatched in parallel? When you create an asynchronous subscription, the library will create a thread that is responsible to dispatch messages for that subscription. Messages for a given subscription are dispatched sequentially. That is, your callback is invoked with one message at a time, and only after the callback returns that the library invokes it again with the next pending message. So there is a thread per connection draining data from the socket, and then messages are passed to the matching subscription thread that is then responsible to dispatch them. If you plan to have many subscriptions and to reduce the number of threads used by the library, you should look at using a library level thread pool that will take care of messages dispatching. See nats_SetMessageDeliveryPoolSize(). A subscription will make use of the library pool if the connection it was created from had the natsOptions_UseGlobalMessageDelivery() option set to true. Even when using the global pool, messages from a given subscription are always dispatched sequentially and from the same thread. What is the SLOW CONSUMER error that I see in the server? The server when sending data to a client (or route) connection sets a write deadline. That is, if the socket write blocks for that amount of time, it will simply close the connection. This error occurs when the client (or other server) is not reading data fast enough from the socket. As we have seen earlier, a client connection creates a thread whose job is to read data from the socket, parse it and move protocol or messages to appropriate handlers. So this is not really symptomatic of a message handler processing messages too slowly, instead it is probably the result of resources issues (not enough CPU cycles to read from the socket, or not reading fast enough) or internal locking contention that prevents the thread reading from the socket to read data fast enough because it is blocked trying to acquire some lock. What is the SLOW CONSUMER error in the client then? This error, in contrast with the error reported by the server, has to do with the disptaching of messages to the user callback. As explained, messages are moved from the connection's thread reading from the socket to the subscription's thread responsible for dispatching. The subscription's internal queue as a default limited size. When the connection's thread cannot add a message to that queue because it is full, it will drop the message and if an error handler has been set, a message will be posted there. For instance, having a message handler that takes too much time processing a message is likely to cause a slow consumer client error if the incoming message rate is high and/or the subscription pending limits are not big enough. The natsSubscription_SetPendingLimits() API can be used to set the subscription's internal queue limits. Values of `-1` for count and/or size means that the corresponding metric will not be checked. Setting both to `-1` mean that the client library will queued all incoming messages, regardless at which speed they are dispatched, which could cause your application to use lots of memory. What happens if the server is restarted or there is a disconnect? By default, the library will try to reconnect. Reconnection options can be set to either disable reconnect logic entirely, or set the number of attempts and delay between attempts. See natsOptions_SetAllowReconnect(), natsOptions_SetMaxReconnect(), etc... for more information. If you have not set natsOptions_SetNoRadomize() to true, then the list of given URLs are randomized when the connection is created. When a disconnect occurs, the next URL is tried. If that fails, the library moves to the next. When all have been tried, the loop restart from the first until they have all been tried the max reconnect attempts defined through options. The library will pause for as long as defined in the options when trying to reconnect to a server it was previously connected to. If you connect to a server that has the connect URL advertise enabled (default for servers 0.9.2+), when servers are added to the cluster of NATS Servers, the server will send URLs of this new server to its clients. This augments the "pool" or URLs that the connection may have been created with and allows the library to reconnect to servers that have been added to the cluster. While the library is disconnected from the server, all publish or new subscription calls are buffered in memory. This buffer as a default size but can be configured. When this buffer is full, further publish or new subscription calls will report failures.
When the client library has reconnected to the server, the pending buffer will be flushed to the server. If your application needs to know if a disconnect occurs, or when the library has reconnected, you should again set some callbacks to be notified of such events. Use natsOptions_SetDisconnectedCB(), natsOptions_SetReconnectedCB() and natsOptions_SetClosedCB(). Note that the later is a final event for a connection. When this callback is invoked, the connection is no longer valid, that is, you will no longer receive or be able to send data with this connection. Do I need to free NATS objects? All objects that you create and that have a `_Destroy()` API should indeed be destroyed if you want to not leak memory.One that is important and often missed is `natsMsg_Destroy()` that needs to be called in the message handler once you are done processing the message. The message has been created by the library and given to you in the message handler, but you are responsible for calling `natsMsg_Destroy()`. What is nats_ReleaseThreadMemory() doing? The NATS C library may store objects using local thread storage. Threads that are created and handled by the library are automatically cleaned-up, however, if the user creates a thread and invokes some NATS APIs, there is a possibility that the library stored something in that thread local storage. When the thread exits, the user should call this function so that the library can destroy objects that it may have stored. # NATS Streaming Client ## Streaming Basic Usage Note that error checking is being ignored for clarity. Check the `examples/stan` directory for complete usage. ``` // Connect without options stanConnection_Connect(&sc, cluster, clientID, NULL); // Simple Synchronous Publisher. // This does not return until an ack has been received from NATS Streaming stanConnection_Publish(sc, "foo", (const void*) "hello", 5); // Simple Async Subscriber stanConnection_PublishAsync(sc, "foo", (const void*) "hello", 5, _pubAckHandler, NULL); // Simple Subscription without options (default to non durable, receive new only) stanConnection_Subscribe(&sub, sc, "foo", onMsg, NULL, NULL); // Unsubscribe (note that for non durable subscriptions, Unsubscribe() and Close() are the same stanSubscription_Unsubscribe(sub); // Close connection stanConnection_Close(sc); ``` ### Streaming Subscriptions NATS Streaming subscriptions are similar to NATS subscriptions, but clients may start their subscription at an earlier point in the message stream, allowing them to receive messages that were published before this client registered interest. The options are described with examples below: ``` // Create a Subscription Options: stanSubOptions *subOpts = NULL; stanSubOptions_Create(&subOpts); // Subscribe starting with most recently published value stanSubOptions_StartWithLastReceived(subOpts); // OR: Receive all stored messages stanSubOptions_DeliverAllAvailable(subOpts); // OR: Receive messages starting at a specific sequence number stanSubOptions_StartAtSequence(subOpts, 22); // OR: Start at messages that were stored 30 seconds ago. Value is expressed in milliseconds. stanSubOptions_StartAtTimeDelta(subOpts, 30000); // Create the subscription with options stanConnection_Subscribe(&sub, sc, "foo", onMsg, NULL, subOpts); ``` ### Streaming Durable Subscriptions Replay of messages offers great flexibility for clients wishing to begin processing at some earlier point in the data stream. However, some clients just need to pick up where they left off from an earlier session, without having to manually track their position in the stream of messages. Durable subscriptions allow clients to assign a durable name to a subscription when it is created. Doing this causes the NATS Streaming server to track the last acknowledged message for that clientID + durable name, so that only messages since the last acknowledged message will be delivered to the client. ``` stanConnection_Connect(&sc, "test-cluster", "client-123", NULL); // Create subscription options stanSubOptions_Create(&subOpts); // Set a durable name stanSubOptions_SetDurableName(subOpts, "my-durable"); // Subscribe stanConnection_Subscribe(&sub, sc, "foo", onMsg, NULL, subOpts); ... // client receives message sequence 1-40 ... // client disconnects for an hour ... // client reconnects with same clientID "client-123" stanConnection_Connect(&sc, "test-cluster", "client-123", NULL); // client re-subscribes to "foo" with same durable name "my-durable" stanSubOptions_Create(&subOpts); stanSubOptions_SetDurableName(subOpts, "my-durable"); stanConnection_Subscribe(&sub, sc, "foo", onMsg, NULL, subOpts); ... // client receives messages 41-current ``` ### Streaming Queue Groups All subscriptions with the same queue name (regardless of the connection they originate from) will form a queue group. Each message will be delivered to only one subscriber per queue group, using queuing semantics. You can have as many queue groups as you wish. Normal subscribers will continue to work as expected. #### Creating a Queue Group A queue group is automatically created when the first queue subscriber is created. If the group already exists, the member is added to the group. ``` stanConnection_Connect(&sc, "test-cluster", "clientid", NULL); // Create a queue subscriber on "foo" for group "bar" stanConnection_QueueSubscribe(&qsub1, "foo", "bar", onMsg, NULL, NULL); // Add a second member stanConnection_QueueSubscribe(&qsub2, "foo", "bar", onMsg, NULL, NULL); // Notice that you can have a regular subscriber on that subject stanConnection_Subscribe(&sub, sc, "foo", onMsg, NULL, NULL); // A message on "foo" will be received by sub and qsub1 or qsub2. ``` #### Start Position Note that once a queue group is formed, a member's start position is ignored when added to the group. It will start receive messages from the last position in the group. Suppose the channel `foo` exists and there are `500` messages stored, the group `bar` is already created, there are two members and the last message sequence sent is `100`. A new member is added. Note its start position: ``` stanSubOptions_Create(&subOpts); stanSubOptions_StartAtSequence(subOpts, 200); stanConnection_QueueSubscribe(&qsub, "foo", "bar", onMsg, NULL, subOpts); ``` This will not produce an error, but the start position will be ignored. Assuming this member would be the one receiving the next message, it would receive message sequence `101`. #### Leaving the Group There are two ways of leaving the group: closing the subscriber's connection or calling `Unsubscribe`: ``` // Have qsub leave the queue group stanSubscription_Unsubscribe(qsub); ``` If the leaving member had un-acknowledged messages, those messages are reassigned to the remaining members. #### Closing a Queue Group There is no special API for that. Once all members have left (either calling `Unsubscribe`, or their connections are closed), the group is removed from the server. The next call to `QueueSubscribe` with the same group name will create a brand new group, that is, the start position will take effect and delivery will start from there. ### Streaming Durable Queue Groups As described above, for non durable queue subscribers, when the last member leaves the group, that group is removed. A durable queue group allows you to have all members leave but still maintain state. When a member re-joins, it starts at the last position in that group. #### Creating a Durable Queue Group A durable queue group is created in a similar manner as that of a standard queue group, except the `DurableName` option must be used to specify durability. ``` stanSubOptions_Create(&subOpts); stanSubOptions_SetDurableName(subOpts, "dur"); stanConnection_QueueSubscribe(&qsub, "foo", "bar", onMsg, NULL, subOpts); ``` A group called `dur:bar` (the concatenation of durable name and group name) is created in the server. This means two things: - The character `:` is not allowed for a queue subscriber's durable name. - Durable and non-durable queue groups with the same name can coexist. ``` // Non durable queue subscriber on group "bar" stanConnection_QueueSubscribe(&qsub, "foo", "bar", onMsg, NULL, NULL); // Durable queue subscriber on group "bar" stanSubOptions_Create(&subOpts); stanSubOptions_SetDurableName(subOpts, "mydurablegroup"); stanConnection_QueueSubscribe(&qsub, "foo", "bar", onMsg, NULL, subOpts); // The same message produced on "foo" would be received by both queue subscribers. ``` #### Start Position of the Durable Queue Group The rules for non-durable queue subscribers apply to durable subscribers. #### Leaving the Durable Queue Group As for non-durable queue subscribers, if a member's connection is closed, or if `Unsubscribe` its called, the member leaves the group. Any unacknowledged message is transferred to remaining members. See *Closing the Group* for important difference with non-durable queue subscribers. #### Closing the Durable Queue Group The *last* member calling `Unsubscribe` will close (that is destroy) the group. So if you want to maintain durability of the group, you should not be calling `Unsubscribe`. So unlike for non-durable queue subscribers, it is possible to maintain a queue group with no member in the server. When a new member re-joins the durable queue group, it will resume from where the group left of, actually first receiving all unacknowledged messages that may have been left when the last member previously left. ### Streaming Wildcard Subscriptions NATS Streaming subscriptions **do not** support wildcards. ## Streaming Advanced Usage ### Connection Status The fact that the NATS Streaming server and clients are not directly connected poses a challenge when it comes to know if a client is still valid. When a client disconnects, the streaming server is not notified, hence the importance of calling `stanConnection_Close()`. The server sends heartbeats to the client's private inbox and if it misses a certain number of responses, it will consider the client's connection lost and remove it from its state. Why do we need PINGs? Picture the case where a client connects to a NATS Server which has a route to a NATS Streaming server (either connecting to a standalone NATS Server or the server it embeds). If the connection between the streaming server and the client's NATS Server is broken, the client's NATS connection would still be ok, yet, no communication with the streaming server is possible. Starting with NATS Streaming Server `0.10.2`, the client library will send PINGs at regular intervals (default is 5 seconds) and will close the streaming connection after a certain number of PINGs have been sent without any response (default is 3). When that happens, a callback - if one is registered - will be invoked to notify the user that the connection is permanently lost, and the reason for the failure. Here is how you would specify your own PING values and the callback: ``` stanConnOptions_Create(&connOpts); // Send PINGs every 10 seconds, and fail after 5 PINGs without any response. stanConnOptions_SetPings(connOpts, 10, 5); // Add a callback to be notified if the STAN connection is lost for good. stanConnOptions_SetConnectionLostHandler(connOpts, connectionLostCB, NULL); // Here is an example of the `connectionLostCB`: connectionLostCB(stanConnection *sc, const char *errTxt, void *closure) { printf("Connection lost: %s\n", errTxt); } ``` Note that the only way to be notified in your application is to set the callback. If the callback is not set, PINGs are still sent and the connection will be closed if needed, but the application won't know if it has only subscriptions. A default callback is used to simply print to standard error the clusterID, the clientID and the error that caused the connection to be lost: ``` Connection permanently lost: clusterID=test-cluster clientID=client error=connection lost due to PING failure ``` When the connection is lost, your application would have to re-create it and all subscriptions if any. The library creates its own NATS connection and sets set the reconnect attempts to "infinite". It should therefore be possible for the library to always reconnect, but this does not mean that the streaming connection will not be closed, even if you set a very high threshold for the PINGs max out value. Keep in mind that while the client is disconnected, the server is sending heartbeats to the clients too, and when not getting any response, it will remove that client from its state. When the communication is restored, the PINGs sent to the server will allow to detect this condition and report to the client that the connection is now closed. Also, while a client is "disconnected" from the server, another application with connectivity to the streaming server may connect and uses the same client ID. The server, when detecting the duplicate client ID, will try to contact the first client to know if it should reject the connect request of the second client. Since the communication between the server and the first client is broken, the server will not get a response and therefore will replace the first client with the second one. Prior to NATS Streaming Server `0.10.2`, if the communication between the first client and server were to be restored, and the application would send messages, the server would accept those because the published messages client ID would be valid, although the client is not. With a server `0.10.2+`, additional information is sent with each message to allow the server to reject messages from a client that has been replaced by another client. ### Asynchronous Publishing The basic publish API (`stanConnection_Publish()`) is synchronous; it does not return control to the caller until the NATS Streaming server has acknowledged receipt of the message. To accomplish this, a unique identifier (GUID) is generated for the message on creation, and the client library waits for a publish acknowledgment from the server with a matching GUID before it returns control to the caller, possibly with an error indicating that the operation was not successful due to some server problem or authorization error. Advanced users may wish to process these publish acknowledgments manually to achieve higher publish throughput by not waiting on individual acknowledgments during the publish operation. An asynchronous publish API is provided for this purpose: ``` static void _pubAckHandler(const char *guid, const char *error, void *closure) { // Note: this callback can be invoked by different threads if (error != NULL) printf("pub ack for guid:%s error:%s\n", guid, error); else printf("Received ack for msg id %s\n", guid); } (...) s = stanConnection_PublishAsync(sc, "foo", (const void*) "hello", 5, _pubAckHandler, NULL); if (s != NULL) { printf("Error on publish: %d - %s\n", s, natsStatus_GetText(s)); nats_PrintLastErrorStack(stderr); } ``` If you want to correlate the published message with the guid in the acknowledgment handler, you should pass a unique closure as the last argument of the `stanConnection_PublishAsync()` call. Check the `examples/stan/pub-async.c` file for an example on how to do so. ### Message Acknowledgments and Redelivery NATS Streaming offers At-Least-Once delivery semantics, meaning that once a message has been delivered to an eligible subscriber, if an acknowledgment is not received within the configured timeout interval, NATS Streaming will attempt redelivery of the message. This timeout interval is specified by the subscription option `stanSubOptions_SetAckWait()`, which defaults to 30 seconds. By default, messages are automatically acknowledged by the NATS Streaming client library after the subscriber's message handler is invoked. However, there may be cases in which the subscribing client wishes to accelerate or defer acknowledgment of the message. To do this, the client must set manual acknowledgment mode on the subscription, and invoke `stanSubscription_AckMsg()`. ex: ``` // Subscribe with manual ack mode, and set AckWait to 60 seconds stanSubOptions_Create(&subOpts); stanSubOptions_SetManualAckMode(subOpts, true); stanSubOptions_SetAckWait(subOpts, 60000); stanConnection_Subscribe(&sub, sc, "foo", onMsg, NULL, subOpts); // In the callback void onMsg(stanConnection *sc, stanSubscription *sub, const char *channel, stanMsg *msg, void *closure) { // ack message before performing I/O intensive operation stanSubscription_AckMsg(sub, msg); printf("Received a message on %s: %.*s\n", channel, stanMsg_GetDataLength(msg), stanMsg_GetData(msg)); } ``` ## Rate limiting/matching A classic problem of publish-subscribe messaging is matching the rate of message producers with the rate of message consumers. Message producers can often outpace the speed of the subscribers that are consuming their messages. This mismatch is commonly called a "fast producer/slow consumer" problem, and may result in dramatic resource utilization spikes in the underlying messaging system as it tries to buffer messages until the slow consumer(s) can catch up. ### Publisher rate limiting NATS Streaming provides a connection option called `stanConnOptions_SetMaxPubAcksInflight()` that effectively limits the number of unacknowledged messages that a publisher may have in-flight at any given time. When this maximum is reached, further publish calls will block until the number of unacknowledged messages falls below the specified limit. ex: ``` stanConnOptions_Create(&connOpts); stanConnOptions_SetMaxPubAcksInflight(connOpts, 25, 1.0); stanConnection_Connect(&sc, cluster, clientID, connOpts); (...) static void _pubAckHandler(const char *guid, const char *error, void *closure) { // process the ack ... } (...) for (i = 1; i < 1000; i++) { // If the server is unable to keep up with the publisher, the number of outstanding acks will eventually // reach the max and this call will block stanConnection_PublishAsync(sc, "foo", (const void*) "hello", 5, _pubAckHandler, NULL); } ``` Note the last parameter of `stanConnOptions_SetMaxPubAcksInflight()`. This is a float indicating the percentage of outstanding ACKs to fall below before being allowed to send more messages. For instance, if the maximum is 1000 and percentage is 50% (0.5), the it means that if the publish calls were to be blocked because the library has sent 1000 messages and not received an ACK yet from the server, the publish calls would be unblocked only when the library has received 500 ACKs from the server. This prevents the connection from being blocked and unblocked for each message when the limit has been reached. ### Subscriber rate limiting Rate limiting may also be accomplished on the subscriber side, on a per-subscription basis, using a subscription option called `stanSubOptions_SetMaxInflight()`. This option specifies the maximum number of outstanding acknowledgments (messages that have been delivered but not acknowledged) that NATS Streaming will allow for a given subscription. When this limit is reached, NATS Streaming will suspend delivery of messages to this subscription until the number of unacknowledged messages falls below the specified limit. ex: ``` // Subscribe with manual ack mode and a max in-flight limit of 25 stanSubOptions_Create(&subOpts); stanSubOptions_SetManualAckMode(subOpts, true); stanSubOptions_SetMaxInflight(subOpts, 25); stanConnection_Subscribe(&sub, "foo", onMsg, NULL, subOpts); // In the callback void onMsg(stanConnection *sc, stanSubscription *sub, const char *channel, stanMsg *msg, void *closure) { printf("Received a message\n"); ... // Does not ack, or takes a very long time to ack ... // Message delivery will suspend when the number of unacknowledged messages reaches 25 } ``` However, the server will redeliver messages for which it did not receive an acknowledgment for more than the value passed in `stanSubOptions_SetAckWait()` (or 30 seconds by default). # License Unless otherwise noted, the NATS source files are distributed under the Apache Version 2.0 license found in the LICENSE file. nats.c-3.10.1/buildOnTravis.sh000077500000000000000000000044001476505644000161170ustar00rootroot00000000000000#!/bin/sh # $1 is compiler (gcc, clang) # $2 is "coverage" for coverage # $3 is build options to pass to cmake # $4 is test options to pass to ctest echo "compiler = " $1 echo "coverage = " $2 echo "build opts = " $3 echo "test opts = " $4 if [ "$NATS_TEST_SERVER_VERSION" != "" ]; then rm -fr $HOME/nats-server* rel=$NATS_TEST_SERVER_VERSION mkdir -p $HOME/nats-server-$rel if [ "$rel" = "latest" ]; then rel=$(curl -s https://api.github.com/repos/nats-io/nats-server/releases/latest | jq -r '.tag_name') fi if [ "$rel" != "${rel#v}" ] && wget https://github.com/nats-io/nats-server/releases/download/$rel/nats-server-$rel-linux-amd64.tar.gz; then tar -xzf nats-server-$rel-linux-amd64.tar.gz mv nats-server-$rel-linux-amd64 nats-server else for c in 1 2 3 4 5 do echo "Attempt $c to download binary for main" rm ./nats-server curl -sf "https://binaries.nats.dev/nats-io/nats-server/v2@$rel" | PREFIX=. sh # We are sometimes getting nats-server of size 0. Make sure we have a # working nats-server by making sure we get a version number. v="$(./nats-server -v)" if [ "$v" != "" ]; then break fi done fi mv nats-server $HOME/nats-server-$rel PATH=$HOME/nats-server-$rel:$PATH fi export NATS_TEST_SERVER_VERSION="$(nats-server -v)" if [ "$NATS_TEST_SERVER_VERSION" = "" ]; then echo "===============================================" echo "= Unable to get the server version, aborting! =" echo "===============================================" exit 1 fi if [ "$1" != "gcc" ]; then if [ "$2" = "coverage" ]; then # only coverage for gcc compiler exit 0 fi fi cmake .. $3 res=$? if [ $res -ne 0 ]; then exit $res fi make rebuild_cache && make res=$? if [ $res -ne 0 ]; then exit $res fi echo "Test app using dynamic library does not crash if no NATS call is made" bin/nonats res=$? if [ $res -ne 0 ]; then exit $res fi echo "Test C++ compiler compatibility" # There is mo need to run check, just make sure it's compiled bin/check_cpp res=$? if [ $res -ne 0 ]; then exit $res fi export NATS_TEST_TRAVIS=yes echo "Using NATS server version: $NATS_TEST_SERVER_VERSION" ctest -L 'test' --timeout 60 --output-on-failure $4 res=$? if [ $res -ne 0 ]; then exit $res fi nats.c-3.10.1/codecov.yml000066400000000000000000000006341476505644000151450ustar00rootroot00000000000000ignore: - "test/**" - "examples/**" - "src/win/**" - "src/unix/**" - "src/stan/protocol.pb-c.c" coverage: precision: 2 round: down range: "60...80" status: project: default: target: auto threshold: 5% patch: default: target: auto threshold: 20% informational: true github_checks: annotations: true comment: require_changes: false nats.c-3.10.1/dependencies.md000066400000000000000000000022331476505644000157450ustar00rootroot00000000000000# External Dependencies This file lists the dependencies used in this repository. | Dependency | Version(s) | License | |----------------------------------------------|-------------|----------------------------------------------------------------------------------| | github.com/nats-io/nats-server | various | [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0) | | github.com/JoakimSoderberg/coveralls-cmake | N/A | [MIT](https://github.com/JoakimSoderberg/coveralls-cmake/blob/master/LICENSE.md) | | https://github.com/doxygen | v1.9.8 | [GNU](https://github.com/doxygen/doxygen/blob/master/LICENSE) | | https://github.com/openssl/openssl | | [Apache License 2.0](https://github.com/openssl/openssl/blob/master/LICENSE.txt) | | https://github.com/protobuf-c/protobuf-c | 1.0 | [custom](https://github.com/protobuf-c/protobuf-c/blob/master/LICENSE) | | https://github.com/jedisct1/libsodium | v23 | [ISC](https://github.com/jedisct1/libsodium/blob/master/LICENSE) | nats.c-3.10.1/doc/000077500000000000000000000000001476505644000135425ustar00rootroot00000000000000nats.c-3.10.1/doc/DoxyFile.NATS.Client000066400000000000000000003517351476505644000172070ustar00rootroot00000000000000# Doxyfile 1.9.5 # This file describes the settings to be used by the documentation system # doxygen (www.doxygen.org) for a project. # # All text after a double hash (##) is considered a comment and is placed in # front of the TAG it is preceding. # # All text after a single hash (#) is considered a comment and will be ignored. # The format is: # TAG = value [value, ...] # For lists, items can also be appended using: # TAG += value [value, ...] # Values that contain spaces should be placed between quotes (\" \"). # # Note: # # Use doxygen to compare the used configuration file with the template # configuration file: # doxygen -x [configFile] # Use doxygen to compare the used configuration file with the template # configuration file without replacing the environment variables or CMake type # replacement variables: # doxygen -x_noenv [configFile] #--------------------------------------------------------------------------- # Project related configuration options #--------------------------------------------------------------------------- # This tag specifies the encoding used for all characters in the configuration # file that follow. The default is UTF-8 which is also the encoding used for all # text before the first occurrence of this tag. Doxygen uses libiconv (or the # iconv built into libc) for the transcoding. See # https://www.gnu.org/software/libiconv/ for the list of possible encodings. # The default value is: UTF-8. DOXYFILE_ENCODING = UTF-8 # The PROJECT_NAME tag is a single word (or a sequence of words surrounded by # double-quotes, unless you are using Doxywizard) that should identify the # project for which the documentation is generated. This name is used in the # title of most generated pages and in a few other places. # The default value is: My Project. PROJECT_NAME = NATS C Client with JetStream and Streaming support # The PROJECT_NUMBER tag can be used to enter a project or revision number. This # could be handy for archiving the generated documentation or if some version # control system is used. PROJECT_NUMBER = 3.10.1 # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a # quick idea about the purpose of the project. Keep the description short. PROJECT_BRIEF = "The nats.io C Client, Supported by Synadia Communications Inc." # With the PROJECT_LOGO tag one can specify a logo or an icon that is included # in the documentation. The maximum height of the logo should not exceed 55 # pixels and the maximum width should not exceed 200 pixels. Doxygen will copy # the logo to the output directory. PROJECT_LOGO = # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path # into which the generated documentation will be written. If a relative path is # entered, it will be relative to the location where doxygen was started. If # left blank the current directory will be used. OUTPUT_DIRECTORY = . # If the CREATE_SUBDIRS tag is set to YES then doxygen will create up to 4096 # sub-directories (in 2 levels) under the output directory of each output format # and will distribute the generated files over these directories. Enabling this # option can be useful when feeding doxygen a huge amount of source files, where # putting all generated files in the same directory would otherwise causes # performance problems for the file system. Adapt CREATE_SUBDIRS_LEVEL to # control the number of sub-directories. # The default value is: NO. CREATE_SUBDIRS = NO # Controls the number of sub-directories that will be created when # CREATE_SUBDIRS tag is set to YES. Level 0 represents 16 directories, and every # level increment doubles the number of directories, resulting in 4096 # directories at level 8 which is the default and also the maximum value. The # sub-directories are organized in 2 levels, the first level always has a fixed # numer of 16 directories. # Minimum value: 0, maximum value: 8, default value: 8. # This tag requires that the tag CREATE_SUBDIRS is set to YES. CREATE_SUBDIRS_LEVEL = 8 # If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII # characters to appear in the names of generated files. If set to NO, non-ASCII # characters will be escaped, for example _xE3_x81_x84 will be used for Unicode # U+3044. # The default value is: NO. ALLOW_UNICODE_NAMES = NO # The OUTPUT_LANGUAGE tag is used to specify the language in which all # documentation generated by doxygen is written. Doxygen will use this # information to generate all constant output in the proper language. # Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Bulgarian, # Catalan, Chinese, Chinese-Traditional, Croatian, Czech, Danish, Dutch, English # (United States), Esperanto, Farsi (Persian), Finnish, French, German, Greek, # Hindi, Hungarian, Indonesian, Italian, Japanese, Japanese-en (Japanese with # English messages), Korean, Korean-en (Korean with English messages), Latvian, # Lithuanian, Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, # Romanian, Russian, Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, # Swedish, Turkish, Ukrainian and Vietnamese. # The default value is: English. OUTPUT_LANGUAGE = English # If the BRIEF_MEMBER_DESC tag is set to YES, doxygen will include brief member # descriptions after the members that are listed in the file and class # documentation (similar to Javadoc). Set to NO to disable this. # The default value is: YES. BRIEF_MEMBER_DESC = YES # If the REPEAT_BRIEF tag is set to YES, doxygen will prepend the brief # description of a member or function before the detailed description # # Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the # brief descriptions will be completely suppressed. # The default value is: YES. REPEAT_BRIEF = NO # This tag implements a quasi-intelligent brief description abbreviator that is # used to form the text in various listings. Each string in this list, if found # as the leading text of the brief description, will be stripped from the text # and the result, after processing the whole list, is used as the annotated # text. Otherwise, the brief description is used as-is. If left blank, the # following values are used ($name is automatically replaced with the name of # the entity):The $name class, The $name widget, The $name file, is, provides, # specifies, contains, represents, a, an and the. ABBREVIATE_BRIEF = "The $name class" \ "The $name widget" \ "The $name file" \ is \ provides \ specifies \ contains \ represents \ a \ an \ the # If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then # doxygen will generate a detailed section even if there is only a brief # description. # The default value is: NO. ALWAYS_DETAILED_SEC = NO # If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all # inherited members of a class in the documentation of that class as if those # members were ordinary class members. Constructors, destructors and assignment # operators of the base classes will not be shown. # The default value is: NO. INLINE_INHERITED_MEMB = NO # If the FULL_PATH_NAMES tag is set to YES, doxygen will prepend the full path # before files name in the file list and in the header files. If set to NO the # shortest path that makes the file name unique will be used # The default value is: YES. FULL_PATH_NAMES = NO # The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path. # Stripping is only done if one of the specified strings matches the left-hand # part of the path. The tag can be used to show relative paths in the file list. # If left blank the directory from which doxygen is run is used as the path to # strip. # # Note that you can specify absolute paths here, but also relative paths, which # will be relative from the directory where doxygen is started. # This tag requires that the tag FULL_PATH_NAMES is set to YES. STRIP_FROM_PATH = # The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the # path mentioned in the documentation of a class, which tells the reader which # header file to include in order to use a class. If left blank only the name of # the header file containing the class definition is used. Otherwise one should # specify the list of include paths that are normally passed to the compiler # using the -I flag. STRIP_FROM_INC_PATH = # If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but # less readable) file names. This can be useful is your file systems doesn't # support long names like on DOS, Mac, or CD-ROM. # The default value is: NO. SHORT_NAMES = NO # If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the # first line (until the first dot) of a Javadoc-style comment as the brief # description. If set to NO, the Javadoc-style will behave just like regular Qt- # style comments (thus requiring an explicit @brief command for a brief # description.) # The default value is: NO. JAVADOC_AUTOBRIEF = NO # If the JAVADOC_BANNER tag is set to YES then doxygen will interpret a line # such as # /*************** # as being the beginning of a Javadoc-style comment "banner". If set to NO, the # Javadoc-style will behave just like regular comments and it will not be # interpreted by doxygen. # The default value is: NO. JAVADOC_BANNER = NO # If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first # line (until the first dot) of a Qt-style comment as the brief description. If # set to NO, the Qt-style will behave just like regular Qt-style comments (thus # requiring an explicit \brief command for a brief description.) # The default value is: NO. QT_AUTOBRIEF = NO # The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a # multi-line C++ special comment block (i.e. a block of //! or /// comments) as # a brief description. This used to be the default behavior. The new default is # to treat a multi-line C++ comment block as a detailed description. Set this # tag to YES if you prefer the old behavior instead. # # Note that setting this tag to YES also means that rational rose comments are # not recognized any more. # The default value is: NO. MULTILINE_CPP_IS_BRIEF = NO # By default Python docstrings are displayed as preformatted text and doxygen's # special commands cannot be used. By setting PYTHON_DOCSTRING to NO the # doxygen's special commands can be used and the contents of the docstring # documentation blocks is shown as doxygen documentation. # The default value is: YES. PYTHON_DOCSTRING = YES # If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the # documentation from any documented member that it re-implements. # The default value is: YES. INHERIT_DOCS = YES # If the SEPARATE_MEMBER_PAGES tag is set to YES then doxygen will produce a new # page for each member. If set to NO, the documentation of a member will be part # of the file/class/namespace that contains it. # The default value is: NO. SEPARATE_MEMBER_PAGES = NO # The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen # uses this value to replace tabs by spaces in code fragments. # Minimum value: 1, maximum value: 16, default value: 4. TAB_SIZE = 4 # This tag can be used to specify a number of aliases that act as commands in # the documentation. An alias has the form: # name=value # For example adding # "sideeffect=@par Side Effects:^^" # will allow you to put the command \sideeffect (or @sideeffect) in the # documentation, which will result in a user-defined paragraph with heading # "Side Effects:". Note that you cannot put \n's in the value part of an alias # to insert newlines (in the resulting output). You can put ^^ in the value part # of an alias to insert a newline as if a physical newline was in the original # file. When you need a literal { or } or , in the value part of an alias you # have to escape them by means of a backslash (\), this can lead to conflicts # with the commands \{ and \} for these it is advised to use the version @{ and # @} or use a double escape (\\{ and \\}) ALIASES = # Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources # only. Doxygen will then generate output that is more tailored for C. For # instance, some of the names that are used will be different. The list of all # members will be omitted, etc. # The default value is: NO. OPTIMIZE_OUTPUT_FOR_C = NO # Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or # Python sources only. Doxygen will then generate output that is more tailored # for that language. For instance, namespaces will be presented as packages, # qualified scopes will look different, etc. # The default value is: NO. OPTIMIZE_OUTPUT_JAVA = YES # Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran # sources. Doxygen will then generate output that is tailored for Fortran. # The default value is: NO. OPTIMIZE_FOR_FORTRAN = NO # Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL # sources. Doxygen will then generate output that is tailored for VHDL. # The default value is: NO. OPTIMIZE_OUTPUT_VHDL = NO # Set the OPTIMIZE_OUTPUT_SLICE tag to YES if your project consists of Slice # sources only. Doxygen will then generate output that is more tailored for that # language. For instance, namespaces will be presented as modules, types will be # separated into more groups, etc. # The default value is: NO. OPTIMIZE_OUTPUT_SLICE = NO # Doxygen selects the parser to use depending on the extension of the files it # parses. With this tag you can assign which parser to use for a given # extension. Doxygen has a built-in mapping, but you can override or extend it # using this tag. The format is ext=language, where ext is a file extension, and # language is one of the parsers supported by doxygen: IDL, Java, JavaScript, # Csharp (C#), C, C++, Lex, D, PHP, md (Markdown), Objective-C, Python, Slice, # VHDL, Fortran (fixed format Fortran: FortranFixed, free formatted Fortran: # FortranFree, unknown formatted Fortran: Fortran. In the later case the parser # tries to guess whether the code is fixed or free formatted code, this is the # default for Fortran type files). For instance to make doxygen treat .inc files # as Fortran files (default is PHP), and .f files as C (default is Fortran), # use: inc=Fortran f=C. # # Note: For files without extension you can use no_extension as a placeholder. # # Note that for custom extensions you also need to set FILE_PATTERNS otherwise # the files are not read by doxygen. When specifying no_extension you should add # * to the FILE_PATTERNS. # # Note see also the list of default file extension mappings. EXTENSION_MAPPING = # If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments # according to the Markdown format, which allows for more readable # documentation. See https://daringfireball.net/projects/markdown/ for details. # The output of markdown processing is further processed by doxygen, so you can # mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in # case of backward compatibilities issues. # The default value is: YES. MARKDOWN_SUPPORT = YES # When the TOC_INCLUDE_HEADINGS tag is set to a non-zero value, all headings up # to that level are automatically included in the table of contents, even if # they do not have an id attribute. # Note: This feature currently applies only to Markdown headings. # Minimum value: 0, maximum value: 99, default value: 5. # This tag requires that the tag MARKDOWN_SUPPORT is set to YES. TOC_INCLUDE_HEADINGS = 5 # When enabled doxygen tries to link words that correspond to documented # classes, or namespaces to their corresponding documentation. Such a link can # be prevented in individual cases by putting a % sign in front of the word or # globally by setting AUTOLINK_SUPPORT to NO. # The default value is: YES. AUTOLINK_SUPPORT = YES # If you use STL classes (i.e. std::string, std::vector, etc.) but do not want # to include (a tag file for) the STL sources as input, then you should set this # tag to YES in order to let doxygen match functions declarations and # definitions whose arguments contain STL classes (e.g. func(std::string); # versus func(std::string) {}). This also make the inheritance and collaboration # diagrams that involve STL classes more complete and accurate. # The default value is: NO. BUILTIN_STL_SUPPORT = NO # If you use Microsoft's C++/CLI language, you should set this option to YES to # enable parsing support. # The default value is: NO. CPP_CLI_SUPPORT = NO # Set the SIP_SUPPORT tag to YES if your project consists of sip (see: # https://www.riverbankcomputing.com/software/sip/intro) sources only. Doxygen # will parse them like normal C++ but will assume all classes use public instead # of private inheritance when no explicit protection keyword is present. # The default value is: NO. SIP_SUPPORT = NO # For Microsoft's IDL there are propget and propput attributes to indicate # getter and setter methods for a property. Setting this option to YES will make # doxygen to replace the get and set methods by a property in the documentation. # This will only work if the methods are indeed getting or setting a simple # type. If this is not the case, or you want to show the methods anyway, you # should set this option to NO. # The default value is: YES. IDL_PROPERTY_SUPPORT = YES # If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC # tag is set to YES then doxygen will reuse the documentation of the first # member in the group (if any) for the other members of the group. By default # all members of a group must be documented explicitly. # The default value is: NO. DISTRIBUTE_GROUP_DOC = NO # If one adds a struct or class to a group and this option is enabled, then also # any nested class or struct is added to the same group. By default this option # is disabled and one has to add nested compounds explicitly via \ingroup. # The default value is: NO. GROUP_NESTED_COMPOUNDS = NO # Set the SUBGROUPING tag to YES to allow class member groups of the same type # (for instance a group of public functions) to be put as a subgroup of that # type (e.g. under the Public Functions section). Set it to NO to prevent # subgrouping. Alternatively, this can be done per class using the # \nosubgrouping command. # The default value is: YES. SUBGROUPING = NO # When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions # are shown inside the group in which they are included (e.g. using \ingroup) # instead of on a separate page (for HTML and Man pages) or section (for LaTeX # and RTF). # # Note that this feature does not work in combination with # SEPARATE_MEMBER_PAGES. # The default value is: NO. INLINE_GROUPED_CLASSES = NO # When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions # with only public data fields or simple typedef fields will be shown inline in # the documentation of the scope in which they are defined (i.e. file, # namespace, or group documentation), provided this scope is documented. If set # to NO, structs, classes, and unions are shown on a separate page (for HTML and # Man pages) or section (for LaTeX and RTF). # The default value is: NO. INLINE_SIMPLE_STRUCTS = NO # When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or # enum is documented as struct, union, or enum with the name of the typedef. So # typedef struct TypeS {} TypeT, will appear in the documentation as a struct # with name TypeT. When disabled the typedef will appear as a member of a file, # namespace, or class. And the struct will be named TypeS. This can typically be # useful for C code in case the coding convention dictates that all compound # types are typedef'ed and only the typedef is referenced, never the tag name. # The default value is: NO. TYPEDEF_HIDES_STRUCT = NO # The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This # cache is used to resolve symbols given their name and scope. Since this can be # an expensive process and often the same symbol appears multiple times in the # code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small # doxygen will become slower. If the cache is too large, memory is wasted. The # cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range # is 0..9, the default is 0, corresponding to a cache size of 2^16=65536 # symbols. At the end of a run doxygen will report the cache usage and suggest # the optimal cache size from a speed point of view. # Minimum value: 0, maximum value: 9, default value: 0. LOOKUP_CACHE_SIZE = 0 # The NUM_PROC_THREADS specifies the number of threads doxygen is allowed to use # during processing. When set to 0 doxygen will based this on the number of # cores available in the system. You can set it explicitly to a value larger # than 0 to get more control over the balance between CPU load and processing # speed. At this moment only the input processing can be done using multiple # threads. Since this is still an experimental feature the default is set to 1, # which effectively disables parallel processing. Please report any issues you # encounter. Generating dot graphs in parallel is controlled by the # DOT_NUM_THREADS setting. # Minimum value: 0, maximum value: 32, default value: 1. NUM_PROC_THREADS = 1 #--------------------------------------------------------------------------- # Build related configuration options #--------------------------------------------------------------------------- # If the EXTRACT_ALL tag is set to YES, doxygen will assume all entities in # documentation are documented, even if no documentation was available. Private # class members and static file members will be hidden unless the # EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES. # Note: This will also disable the warnings about undocumented members that are # normally produced when WARNINGS is set to YES. # The default value is: NO. EXTRACT_ALL = YES # If the EXTRACT_PRIVATE tag is set to YES, all private members of a class will # be included in the documentation. # The default value is: NO. EXTRACT_PRIVATE = NO # If the EXTRACT_PRIV_VIRTUAL tag is set to YES, documented private virtual # methods of a class will be included in the documentation. # The default value is: NO. EXTRACT_PRIV_VIRTUAL = NO # If the EXTRACT_PACKAGE tag is set to YES, all members with package or internal # scope will be included in the documentation. # The default value is: NO. EXTRACT_PACKAGE = NO # If the EXTRACT_STATIC tag is set to YES, all static members of a file will be # included in the documentation. # The default value is: NO. EXTRACT_STATIC = NO # If the EXTRACT_LOCAL_CLASSES tag is set to YES, classes (and structs) defined # locally in source files will be included in the documentation. If set to NO, # only classes defined in header files are included. Does not have any effect # for Java sources. # The default value is: YES. EXTRACT_LOCAL_CLASSES = YES # This flag is only useful for Objective-C code. If set to YES, local methods, # which are defined in the implementation section but not in the interface are # included in the documentation. If set to NO, only methods in the interface are # included. # The default value is: NO. EXTRACT_LOCAL_METHODS = NO # If this flag is set to YES, the members of anonymous namespaces will be # extracted and appear in the documentation as a namespace called # 'anonymous_namespace{file}', where file will be replaced with the base name of # the file that contains the anonymous namespace. By default anonymous namespace # are hidden. # The default value is: NO. EXTRACT_ANON_NSPACES = NO # If this flag is set to YES, the name of an unnamed parameter in a declaration # will be determined by the corresponding definition. By default unnamed # parameters remain unnamed in the output. # The default value is: YES. RESOLVE_UNNAMED_PARAMS = YES # If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all # undocumented members inside documented classes or files. If set to NO these # members will be included in the various overviews, but no documentation # section is generated. This option has no effect if EXTRACT_ALL is enabled. # The default value is: NO. HIDE_UNDOC_MEMBERS = YES # If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all # undocumented classes that are normally visible in the class hierarchy. If set # to NO, these classes will be included in the various overviews. This option # has no effect if EXTRACT_ALL is enabled. # The default value is: NO. HIDE_UNDOC_CLASSES = YES # If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend # declarations. If set to NO, these declarations will be included in the # documentation. # The default value is: NO. HIDE_FRIEND_COMPOUNDS = NO # If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any # documentation blocks found inside the body of a function. If set to NO, these # blocks will be appended to the function's detailed documentation block. # The default value is: NO. HIDE_IN_BODY_DOCS = NO # The INTERNAL_DOCS tag determines if documentation that is typed after a # \internal command is included. If the tag is set to NO then the documentation # will be excluded. Set it to YES to include the internal documentation. # The default value is: NO. INTERNAL_DOCS = NO # With the correct setting of option CASE_SENSE_NAMES doxygen will better be # able to match the capabilities of the underlying filesystem. In case the # filesystem is case sensitive (i.e. it supports files in the same directory # whose names only differ in casing), the option must be set to YES to properly # deal with such files in case they appear in the input. For filesystems that # are not case sensitive the option should be set to NO to properly deal with # output files written for symbols that only differ in casing, such as for two # classes, one named CLASS and the other named Class, and to also support # references to files without having to specify the exact matching casing. On # Windows (including Cygwin) and MacOS, users should typically set this option # to NO, whereas on Linux or other Unix flavors it should typically be set to # YES. # Possible values are: SYSTEM, NO and YES. # The default value is: SYSTEM. CASE_SENSE_NAMES = NO # If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with # their full class and namespace scopes in the documentation. If set to YES, the # scope will be hidden. # The default value is: NO. HIDE_SCOPE_NAMES = NO # If the HIDE_COMPOUND_REFERENCE tag is set to NO (default) then doxygen will # append additional text to a page's title, such as Class Reference. If set to # YES the compound reference will be hidden. # The default value is: NO. HIDE_COMPOUND_REFERENCE= NO # If the SHOW_HEADERFILE tag is set to YES then the documentation for a class # will show which file needs to be included to use the class. # The default value is: YES. SHOW_HEADERFILE = YES # If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of # the files that are included by a file in the documentation of that file. # The default value is: YES. SHOW_INCLUDE_FILES = YES # If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each # grouped member an include statement to the documentation, telling the reader # which file to include in order to use the member. # The default value is: NO. SHOW_GROUPED_MEMB_INC = NO # If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include # files with double quotes in the documentation rather than with sharp brackets. # The default value is: NO. FORCE_LOCAL_INCLUDES = NO # If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the # documentation for inline members. # The default value is: YES. INLINE_INFO = YES # If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the # (detailed) documentation of file and class members alphabetically by member # name. If set to NO, the members will appear in declaration order. # The default value is: YES. SORT_MEMBER_DOCS = NO # If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief # descriptions of file, namespace and class members alphabetically by member # name. If set to NO, the members will appear in declaration order. Note that # this will also influence the order of the classes in the class list. # The default value is: NO. SORT_BRIEF_DOCS = NO # If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the # (brief and detailed) documentation of class members so that constructors and # destructors are listed first. If set to NO the constructors will appear in the # respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS. # Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief # member documentation. # Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting # detailed member documentation. # The default value is: NO. SORT_MEMBERS_CTORS_1ST = NO # If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy # of group names into alphabetical order. If set to NO the group names will # appear in their defined order. # The default value is: NO. SORT_GROUP_NAMES = NO # If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by # fully-qualified names, including namespaces. If set to NO, the class list will # be sorted only by class name, not including the namespace part. # Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. # Note: This option applies only to the class list, not to the alphabetical # list. # The default value is: NO. SORT_BY_SCOPE_NAME = NO # If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper # type resolution of all parameters of a function it will reject a match between # the prototype and the implementation of a member function even if there is # only one candidate or it is obvious which candidate to choose by doing a # simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still # accept a match between prototype and implementation in such cases. # The default value is: NO. STRICT_PROTO_MATCHING = NO # The GENERATE_TODOLIST tag can be used to enable (YES) or disable (NO) the todo # list. This list is created by putting \todo commands in the documentation. # The default value is: YES. GENERATE_TODOLIST = NO # The GENERATE_TESTLIST tag can be used to enable (YES) or disable (NO) the test # list. This list is created by putting \test commands in the documentation. # The default value is: YES. GENERATE_TESTLIST = NO # The GENERATE_BUGLIST tag can be used to enable (YES) or disable (NO) the bug # list. This list is created by putting \bug commands in the documentation. # The default value is: YES. GENERATE_BUGLIST = NO # The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or disable (NO) # the deprecated list. This list is created by putting \deprecated commands in # the documentation. # The default value is: YES. GENERATE_DEPRECATEDLIST= YES # The ENABLED_SECTIONS tag can be used to enable conditional documentation # sections, marked by \if ... \endif and \cond # ... \endcond blocks. ENABLED_SECTIONS = # The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the # initial value of a variable or macro / define can have for it to appear in the # documentation. If the initializer consists of more lines than specified here # it will be hidden. Use a value of 0 to hide initializers completely. The # appearance of the value of individual variables and macros / defines can be # controlled using \showinitializer or \hideinitializer command in the # documentation regardless of this setting. # Minimum value: 0, maximum value: 10000, default value: 30. MAX_INITIALIZER_LINES = 30 # Set the SHOW_USED_FILES tag to NO to disable the list of files generated at # the bottom of the documentation of classes and structs. If set to YES, the # list will mention the files that were used to generate the documentation. # The default value is: YES. SHOW_USED_FILES = YES # Set the SHOW_FILES tag to NO to disable the generation of the Files page. This # will remove the Files entry from the Quick Index and from the Folder Tree View # (if specified). # The default value is: YES. SHOW_FILES = YES # Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces # page. This will remove the Namespaces entry from the Quick Index and from the # Folder Tree View (if specified). # The default value is: YES. SHOW_NAMESPACES = YES # The FILE_VERSION_FILTER tag can be used to specify a program or script that # doxygen should invoke to get the current version for each file (typically from # the version control system). Doxygen will invoke the program by executing (via # popen()) the command command input-file, where command is the value of the # FILE_VERSION_FILTER tag, and input-file is the name of an input file provided # by doxygen. Whatever the program writes to standard output is used as the file # version. For an example see the documentation. FILE_VERSION_FILTER = # The LAYOUT_FILE tag can be used to specify a layout file which will be parsed # by doxygen. The layout file controls the global structure of the generated # output files in an output format independent way. To create the layout file # that represents doxygen's defaults, run doxygen with the -l option. You can # optionally specify a file name after the option, if omitted DoxygenLayout.xml # will be used as the name of the layout file. See also section "Changing the # layout of pages" for information. # # Note that if you run doxygen from a directory containing a file called # DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE # tag is left empty. LAYOUT_FILE = # The CITE_BIB_FILES tag can be used to specify one or more bib files containing # the reference definitions. This must be a list of .bib files. The .bib # extension is automatically appended if omitted. This requires the bibtex tool # to be installed. See also https://en.wikipedia.org/wiki/BibTeX for more info. # For LaTeX the style of the bibliography can be controlled using # LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the # search path. See also \cite for info how to create references. CITE_BIB_FILES = #--------------------------------------------------------------------------- # Configuration options related to warning and progress messages #--------------------------------------------------------------------------- # The QUIET tag can be used to turn on/off the messages that are generated to # standard output by doxygen. If QUIET is set to YES this implies that the # messages are off. # The default value is: NO. QUIET = NO # The WARNINGS tag can be used to turn on/off the warning messages that are # generated to standard error (stderr) by doxygen. If WARNINGS is set to YES # this implies that the warnings are on. # # Tip: Turn warnings on while writing the documentation. # The default value is: YES. WARNINGS = YES # If the WARN_IF_UNDOCUMENTED tag is set to YES then doxygen will generate # warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag # will automatically be disabled. # The default value is: YES. WARN_IF_UNDOCUMENTED = YES # If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for # potential errors in the documentation, such as documenting some parameters in # a documented function twice, or documenting parameters that don't exist or # using markup commands wrongly. # The default value is: YES. WARN_IF_DOC_ERROR = YES # If WARN_IF_INCOMPLETE_DOC is set to YES, doxygen will warn about incomplete # function parameter documentation. If set to NO, doxygen will accept that some # parameters have no documentation without warning. # The default value is: YES. WARN_IF_INCOMPLETE_DOC = YES # This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that # are documented, but have no documentation for their parameters or return # value. If set to NO, doxygen will only warn about wrong parameter # documentation, but not about the absence of documentation. If EXTRACT_ALL is # set to YES then this flag will automatically be disabled. See also # WARN_IF_INCOMPLETE_DOC # The default value is: NO. WARN_NO_PARAMDOC = NO # If the WARN_AS_ERROR tag is set to YES then doxygen will immediately stop when # a warning is encountered. If the WARN_AS_ERROR tag is set to FAIL_ON_WARNINGS # then doxygen will continue running as if WARN_AS_ERROR tag is set to NO, but # at the end of the doxygen process doxygen will return with a non-zero status. # Possible values are: NO, YES and FAIL_ON_WARNINGS. # The default value is: NO. WARN_AS_ERROR = NO # The WARN_FORMAT tag determines the format of the warning messages that doxygen # can produce. The string should contain the $file, $line, and $text tags, which # will be replaced by the file and line number from which the warning originated # and the warning text. Optionally the format may contain $version, which will # be replaced by the version of the file (if it could be obtained via # FILE_VERSION_FILTER) # See also: WARN_LINE_FORMAT # The default value is: $file:$line: $text. WARN_FORMAT = "$file:$line: $text" # In the $text part of the WARN_FORMAT command it is possible that a reference # to a more specific place is given. To make it easier to jump to this place # (outside of doxygen) the user can define a custom "cut" / "paste" string. # Example: # WARN_LINE_FORMAT = "'vi $file +$line'" # See also: WARN_FORMAT # The default value is: at line $line of file $file. WARN_LINE_FORMAT = "at line $line of file $file" # The WARN_LOGFILE tag can be used to specify a file to which warning and error # messages should be written. If left blank the output is written to standard # error (stderr). In case the file specified cannot be opened for writing the # warning and error messages are written to standard error. When as file - is # specified the warning and error messages are written to standard output # (stdout). WARN_LOGFILE = #--------------------------------------------------------------------------- # Configuration options related to the input files #--------------------------------------------------------------------------- # The INPUT tag is used to specify the files and/or directories that contain # documented source files. You may enter file names like myfile.cpp or # directories like /usr/src/myproject. Separate the files or directories with # spaces. See also FILE_PATTERNS and EXTENSION_MAPPING # Note: If this tag is empty the current directory is searched. INPUT = ../src \ ../src/adapters # This tag can be used to specify the character encoding of the source files # that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses # libiconv (or the iconv built into libc) for the transcoding. See the libiconv # documentation (see: # https://www.gnu.org/software/libiconv/) for the list of possible encodings. # See also: INPUT_FILE_ENCODING # The default value is: UTF-8. INPUT_ENCODING = UTF-8 # This tag can be used to specify the character encoding of the source files # that doxygen parses The INPUT_FILE_ENCODING tag can be used to specify # character encoding on a per file pattern basis. Doxygen will compare the file # name with each pattern and apply the encoding instead of the default # INPUT_ENCODING) if there is a match. The character encodings are a list of the # form: pattern=encoding (like *.php=ISO-8859-1). See cfg_input_encoding # "INPUT_ENCODING" for further information on supported encodings. INPUT_FILE_ENCODING = # If the value of the INPUT tag contains directories, you can use the # FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and # *.h) to filter out the source-files in the directories. # # Note that for custom extensions or not directly supported extensions you also # need to set EXTENSION_MAPPING for the extension otherwise the files are not # read by doxygen. # # Note the list of default checked file patterns might differ from the list of # default file extension mappings. # # If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cpp, # *.c++, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, # *.hh, *.hxx, *.hpp, *.h++, *.l, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, # *.inc, *.m, *.markdown, *.md, *.mm, *.dox (to be provided as doxygen C # comment), *.py, *.pyw, *.f90, *.f95, *.f03, *.f08, *.f18, *.f, *.for, *.vhd, # *.vhdl, *.ucf, *.qsf and *.ice. FILE_PATTERNS = nats.h \ status.h \ libevent.h \ libuv.h # The RECURSIVE tag can be used to specify whether or not subdirectories should # be searched for input files as well. # The default value is: NO. RECURSIVE = NO # The EXCLUDE tag can be used to specify files and/or directories that should be # excluded from the INPUT source files. This way you can easily exclude a # subdirectory from a directory tree whose root is specified with the INPUT tag. # # Note that relative paths are relative to the directory from which doxygen is # run. EXCLUDE = # The EXCLUDE_SYMLINKS tag can be used to select whether or not files or # directories that are symbolic links (a Unix file system feature) are excluded # from the input. # The default value is: NO. EXCLUDE_SYMLINKS = NO # If the value of the INPUT tag contains directories, you can use the # EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude # certain files from those directories. # # Note that the wildcards are matched against the file with absolute path, so to # exclude all test directories for example use the pattern */test/* EXCLUDE_PATTERNS = # The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names # (namespaces, classes, functions, etc.) that should be excluded from the # output. The symbol name can be a fully qualified name, a word, or if the # wildcard * is used, a substring. Examples: ANamespace, AClass, # ANamespace::AClass, ANamespace::*Test # # Note that the wildcards are matched against the file with absolute path, so to # exclude all test directories use the pattern */test/* EXCLUDE_SYMBOLS = # The EXAMPLE_PATH tag can be used to specify one or more files or directories # that contain example code fragments that are included (see the \include # command). EXAMPLE_PATH = # If the value of the EXAMPLE_PATH tag contains directories, you can use the # EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and # *.h) to filter out the source-files in the directories. If left blank all # files are included. EXAMPLE_PATTERNS = * # If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be # searched for input files to be used with the \include or \dontinclude commands # irrespective of the value of the RECURSIVE tag. # The default value is: NO. EXAMPLE_RECURSIVE = NO # The IMAGE_PATH tag can be used to specify one or more files or directories # that contain images that are to be included in the documentation (see the # \image command). IMAGE_PATH = # The INPUT_FILTER tag can be used to specify a program that doxygen should # invoke to filter for each input file. Doxygen will invoke the filter program # by executing (via popen()) the command: # # # # where is the value of the INPUT_FILTER tag, and is the # name of an input file. Doxygen will then use the output that the filter # program writes to standard output. If FILTER_PATTERNS is specified, this tag # will be ignored. # # Note that the filter must not add or remove lines; it is applied before the # code is scanned, but not when the output code is generated. If lines are added # or removed, the anchors will not be placed correctly. # # Note that doxygen will use the data processed and written to standard output # for further processing, therefore nothing else, like debug statements or used # commands (so in case of a Windows batch file always use @echo OFF), should be # written to standard output. # # Note that for custom extensions or not directly supported extensions you also # need to set EXTENSION_MAPPING for the extension otherwise the files are not # properly processed by doxygen. INPUT_FILTER = # The FILTER_PATTERNS tag can be used to specify filters on a per file pattern # basis. Doxygen will compare the file name with each pattern and apply the # filter if there is a match. The filters are a list of the form: pattern=filter # (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how # filters are used. If the FILTER_PATTERNS tag is empty or if none of the # patterns match the file name, INPUT_FILTER is applied. # # Note that for custom extensions or not directly supported extensions you also # need to set EXTENSION_MAPPING for the extension otherwise the files are not # properly processed by doxygen. FILTER_PATTERNS = # If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using # INPUT_FILTER) will also be used to filter the input files that are used for # producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES). # The default value is: NO. FILTER_SOURCE_FILES = NO # The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file # pattern. A pattern will override the setting for FILTER_PATTERN (if any) and # it is also possible to disable source filtering for a specific pattern using # *.ext= (so without naming a filter). # This tag requires that the tag FILTER_SOURCE_FILES is set to YES. FILTER_SOURCE_PATTERNS = # If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that # is part of the input, its contents will be placed on the main page # (index.html). This can be useful if you have a project on for instance GitHub # and want to reuse the introduction page also for the doxygen output. USE_MDFILE_AS_MAINPAGE = # The Fortran standard specifies that for fixed formatted Fortran code all # characters from position 72 are to be considered as comment. A common # extension is to allow longer lines before the automatic comment starts. The # setting FORTRAN_COMMENT_AFTER will also make it possible that longer lines can # be processed before the automatic comment starts. # Minimum value: 7, maximum value: 10000, default value: 72. FORTRAN_COMMENT_AFTER = 72 #--------------------------------------------------------------------------- # Configuration options related to source browsing #--------------------------------------------------------------------------- # If the SOURCE_BROWSER tag is set to YES then a list of source files will be # generated. Documented entities will be cross-referenced with these sources. # # Note: To get rid of all source code in the generated output, make sure that # also VERBATIM_HEADERS is set to NO. # The default value is: NO. SOURCE_BROWSER = NO # Setting the INLINE_SOURCES tag to YES will include the body of functions, # classes and enums directly into the documentation. # The default value is: NO. INLINE_SOURCES = NO # Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any # special comment blocks from generated source code fragments. Normal C, C++ and # Fortran comments will always remain visible. # The default value is: YES. STRIP_CODE_COMMENTS = YES # If the REFERENCED_BY_RELATION tag is set to YES then for each documented # entity all documented functions referencing it will be listed. # The default value is: NO. REFERENCED_BY_RELATION = NO # If the REFERENCES_RELATION tag is set to YES then for each documented function # all documented entities called/used by that function will be listed. # The default value is: NO. REFERENCES_RELATION = NO # If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set # to YES then the hyperlinks from functions in REFERENCES_RELATION and # REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will # link to the documentation. # The default value is: YES. REFERENCES_LINK_SOURCE = YES # If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the # source code will show a tooltip with additional information such as prototype, # brief description and links to the definition and documentation. Since this # will make the HTML file larger and loading of large files a bit slower, you # can opt to disable this feature. # The default value is: YES. # This tag requires that the tag SOURCE_BROWSER is set to YES. SOURCE_TOOLTIPS = YES # If the USE_HTAGS tag is set to YES then the references to source code will # point to the HTML generated by the htags(1) tool instead of doxygen built-in # source browser. The htags tool is part of GNU's global source tagging system # (see https://www.gnu.org/software/global/global.html). You will need version # 4.8.6 or higher. # # To use it do the following: # - Install the latest version of global # - Enable SOURCE_BROWSER and USE_HTAGS in the configuration file # - Make sure the INPUT points to the root of the source tree # - Run doxygen as normal # # Doxygen will invoke htags (and that will in turn invoke gtags), so these # tools must be available from the command line (i.e. in the search path). # # The result: instead of the source browser generated by doxygen, the links to # source code will now point to the output of htags. # The default value is: NO. # This tag requires that the tag SOURCE_BROWSER is set to YES. USE_HTAGS = NO # If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a # verbatim copy of the header file for each class for which an include is # specified. Set to NO to disable this. # See also: Section \class. # The default value is: YES. VERBATIM_HEADERS = YES #--------------------------------------------------------------------------- # Configuration options related to the alphabetical class index #--------------------------------------------------------------------------- # If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all # compounds will be generated. Enable this if the project contains a lot of # classes, structs, unions or interfaces. # The default value is: YES. ALPHABETICAL_INDEX = YES # In case all classes in a project start with a common prefix, all classes will # be put under the same header in the alphabetical index. The IGNORE_PREFIX tag # can be used to specify a prefix (or a list of prefixes) that should be ignored # while generating the index headers. # This tag requires that the tag ALPHABETICAL_INDEX is set to YES. IGNORE_PREFIX = #--------------------------------------------------------------------------- # Configuration options related to the HTML output #--------------------------------------------------------------------------- # If the GENERATE_HTML tag is set to YES, doxygen will generate HTML output # The default value is: YES. GENERATE_HTML = YES # The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a # relative path is entered the value of OUTPUT_DIRECTORY will be put in front of # it. # The default directory is: html. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_OUTPUT = html # The HTML_FILE_EXTENSION tag can be used to specify the file extension for each # generated HTML page (for example: .htm, .php, .asp). # The default value is: .html. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_FILE_EXTENSION = .html # The HTML_HEADER tag can be used to specify a user-defined HTML header file for # each generated HTML page. If the tag is left blank doxygen will generate a # standard header. # # To get valid HTML the header file that includes any scripts and style sheets # that doxygen needs, which is dependent on the configuration options used (e.g. # the setting GENERATE_TREEVIEW). It is highly recommended to start with a # default header using # doxygen -w html new_header.html new_footer.html new_stylesheet.css # YourConfigFile # and then modify the file new_header.html. See also section "Doxygen usage" # for information on how to generate the default header that doxygen normally # uses. # Note: The header is subject to change so you typically have to regenerate the # default header when upgrading to a newer version of doxygen. For a description # of the possible markers and block names see the documentation. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_HEADER = header.html # The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each # generated HTML page. If the tag is left blank doxygen will generate a standard # footer. See HTML_HEADER for more information on how to generate a default # footer and what special commands can be used inside the footer. See also # section "Doxygen usage" for information on how to generate the default footer # that doxygen normally uses. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_FOOTER = footer.html # The HTML_STYLESHEET tag can be used to specify a user-defined cascading style # sheet that is used by each HTML page. It can be used to fine-tune the look of # the HTML output. If left blank doxygen will generate a default style sheet. # See also section "Doxygen usage" for information on how to generate the style # sheet that doxygen normally uses. # Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as # it is more robust and this tag (HTML_STYLESHEET) will in the future become # obsolete. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_STYLESHEET = customdoxygen.css # The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined # cascading style sheets that are included after the standard style sheets # created by doxygen. Using this option one can overrule certain style aspects. # This is preferred over using HTML_STYLESHEET since it does not replace the # standard style sheet and is therefore more robust against future updates. # Doxygen will copy the style sheet files to the output directory. # Note: The order of the extra style sheet files is of importance (e.g. the last # style sheet in the list overrules the setting of the previous ones in the # list). For an example see the documentation. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_EXTRA_STYLESHEET = # The HTML_EXTRA_FILES tag can be used to specify one or more extra images or # other source files which should be copied to the HTML output directory. Note # that these files will be copied to the base HTML output directory. Use the # $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these # files. In the HTML_STYLESHEET file, use the file name only. Also note that the # files will be copied as-is; there are no commands or markers available. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_EXTRA_FILES = # The HTML_COLORSTYLE tag can be used to specify if the generated HTML output # should be rendered with a dark or light theme. Default setting AUTO_LIGHT # enables light output unless the user preference is dark output. Other options # are DARK to always use dark mode, LIGHT to always use light mode, AUTO_DARK to # default to dark mode unless the user prefers light mode, and TOGGLE to let the # user toggle between dark and light mode via a button. # Possible values are: LIGHT Always generate light output., DARK Always generate # dark output., AUTO_LIGHT Automatically set the mode according to the user # preference, use light mode if no preference is set (the default)., AUTO_DARK # Automatically set the mode according to the user preference, use dark mode if # no preference is set. and TOGGLE Allow to user to switch between light and # dark mode via a button.. # The default value is: AUTO_LIGHT. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_COLORSTYLE = AUTO_LIGHT # The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen # will adjust the colors in the style sheet and background images according to # this color. Hue is specified as an angle on a color-wheel, see # https://en.wikipedia.org/wiki/Hue for more information. For instance the value # 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300 # purple, and 360 is red again. # Minimum value: 0, maximum value: 359, default value: 220. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_COLORSTYLE_HUE = 220 # The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors # in the HTML output. For a value of 0 the output will use gray-scales only. A # value of 255 will produce the most vivid colors. # Minimum value: 0, maximum value: 255, default value: 100. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_COLORSTYLE_SAT = 100 # The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the # luminance component of the colors in the HTML output. Values below 100 # gradually make the output lighter, whereas values above 100 make the output # darker. The value divided by 100 is the actual gamma applied, so 80 represents # a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not # change the gamma. # Minimum value: 40, maximum value: 240, default value: 80. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_COLORSTYLE_GAMMA = 80 # If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML # page will contain the date and time when the page was generated. Setting this # to YES can help to show when doxygen was last run and thus if the # documentation is up to date. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. # HTML_TIMESTAMP = NO # If the HTML_DYNAMIC_MENUS tag is set to YES then the generated HTML # documentation will contain a main index with vertical navigation menus that # are dynamically created via JavaScript. If disabled, the navigation index will # consists of multiple levels of tabs that are statically embedded in every HTML # page. Disable this option to support browsers that do not have JavaScript, # like the Qt help browser. # The default value is: YES. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_DYNAMIC_MENUS = YES # If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML # documentation will contain sections that can be hidden and shown after the # page has loaded. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_DYNAMIC_SECTIONS = NO # With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries # shown in the various tree structured indices initially; the user can expand # and collapse entries dynamically later on. Doxygen will expand the tree to # such a level that at most the specified number of entries are visible (unless # a fully collapsed tree already exceeds this amount). So setting the number of # entries 1 will produce a full collapsed tree by default. 0 is a special value # representing an infinite number of entries and will result in a full expanded # tree by default. # Minimum value: 0, maximum value: 9999, default value: 100. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_INDEX_NUM_ENTRIES = 100 # If the GENERATE_DOCSET tag is set to YES, additional index files will be # generated that can be used as input for Apple's Xcode 3 integrated development # environment (see: # https://developer.apple.com/xcode/), introduced with OSX 10.5 (Leopard). To # create a documentation set, doxygen will generate a Makefile in the HTML # output directory. Running make will produce the docset in that directory and # running make install will install the docset in # ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at # startup. See https://developer.apple.com/library/archive/featuredarticles/Doxy # genXcode/_index.html for more information. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_DOCSET = NO # This tag determines the name of the docset feed. A documentation feed provides # an umbrella under which multiple documentation sets from a single provider # (such as a company or product suite) can be grouped. # The default value is: Doxygen generated docs. # This tag requires that the tag GENERATE_DOCSET is set to YES. DOCSET_FEEDNAME = "Doxygen generated docs" # This tag determines the URL of the docset feed. A documentation feed provides # an umbrella under which multiple documentation sets from a single provider # (such as a company or product suite) can be grouped. # This tag requires that the tag GENERATE_DOCSET is set to YES. DOCSET_FEEDURL = # This tag specifies a string that should uniquely identify the documentation # set bundle. This should be a reverse domain-name style string, e.g. # com.mycompany.MyDocSet. Doxygen will append .docset to the name. # The default value is: org.doxygen.Project. # This tag requires that the tag GENERATE_DOCSET is set to YES. DOCSET_BUNDLE_ID = org.doxygen.Project # The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify # the documentation publisher. This should be a reverse domain-name style # string, e.g. com.mycompany.MyDocSet.documentation. # The default value is: org.doxygen.Publisher. # This tag requires that the tag GENERATE_DOCSET is set to YES. DOCSET_PUBLISHER_ID = org.doxygen.Publisher # The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher. # The default value is: Publisher. # This tag requires that the tag GENERATE_DOCSET is set to YES. DOCSET_PUBLISHER_NAME = Publisher # If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three # additional HTML index files: index.hhp, index.hhc, and index.hhk. The # index.hhp is a project file that can be read by Microsoft's HTML Help Workshop # on Windows. In the beginning of 2021 Microsoft took the original page, with # a.o. the download links, offline the HTML help workshop was already many years # in maintenance mode). You can download the HTML help workshop from the web # archives at Installation executable (see: # http://web.archive.org/web/20160201063255/http://download.microsoft.com/downlo # ad/0/A/9/0A939EF6-E31C-430F-A3DF-DFAE7960D564/htmlhelp.exe). # # The HTML Help Workshop contains a compiler that can convert all HTML output # generated by doxygen into a single compiled HTML file (.chm). Compiled HTML # files are now used as the Windows 98 help format, and will replace the old # Windows help format (.hlp) on all Windows platforms in the future. Compressed # HTML files also contain an index, a table of contents, and you can search for # words in the documentation. The HTML workshop also contains a viewer for # compressed HTML files. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_HTMLHELP = NO # The CHM_FILE tag can be used to specify the file name of the resulting .chm # file. You can add a path in front of the file if the result should not be # written to the html output directory. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. CHM_FILE = # The HHC_LOCATION tag can be used to specify the location (absolute path # including file name) of the HTML help compiler (hhc.exe). If non-empty, # doxygen will try to run the HTML help compiler on the generated index.hhp. # The file has to be specified with full path. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. HHC_LOCATION = # The GENERATE_CHI flag controls if a separate .chi index file is generated # (YES) or that it should be included in the main .chm file (NO). # The default value is: NO. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. GENERATE_CHI = NO # The CHM_INDEX_ENCODING is used to encode HtmlHelp index (hhk), content (hhc) # and project file content. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. CHM_INDEX_ENCODING = # The BINARY_TOC flag controls whether a binary table of contents is generated # (YES) or a normal table of contents (NO) in the .chm file. Furthermore it # enables the Previous and Next buttons. # The default value is: NO. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. BINARY_TOC = NO # The TOC_EXPAND flag can be set to YES to add extra items for group members to # the table of contents of the HTML help documentation and to the tree view. # The default value is: NO. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. TOC_EXPAND = NO # If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and # QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that # can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help # (.qch) of the generated HTML documentation. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_QHP = NO # If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify # the file name of the resulting .qch file. The path specified is relative to # the HTML output folder. # This tag requires that the tag GENERATE_QHP is set to YES. QCH_FILE = # The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help # Project output. For more information please see Qt Help Project / Namespace # (see: # https://doc.qt.io/archives/qt-4.8/qthelpproject.html#namespace). # The default value is: org.doxygen.Project. # This tag requires that the tag GENERATE_QHP is set to YES. QHP_NAMESPACE = org.doxygen.Project # The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt # Help Project output. For more information please see Qt Help Project / Virtual # Folders (see: # https://doc.qt.io/archives/qt-4.8/qthelpproject.html#virtual-folders). # The default value is: doc. # This tag requires that the tag GENERATE_QHP is set to YES. QHP_VIRTUAL_FOLDER = doc # If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom # filter to add. For more information please see Qt Help Project / Custom # Filters (see: # https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-filters). # This tag requires that the tag GENERATE_QHP is set to YES. QHP_CUST_FILTER_NAME = # The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the # custom filter to add. For more information please see Qt Help Project / Custom # Filters (see: # https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-filters). # This tag requires that the tag GENERATE_QHP is set to YES. QHP_CUST_FILTER_ATTRS = # The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this # project's filter section matches. Qt Help Project / Filter Attributes (see: # https://doc.qt.io/archives/qt-4.8/qthelpproject.html#filter-attributes). # This tag requires that the tag GENERATE_QHP is set to YES. QHP_SECT_FILTER_ATTRS = # The QHG_LOCATION tag can be used to specify the location (absolute path # including file name) of Qt's qhelpgenerator. If non-empty doxygen will try to # run qhelpgenerator on the generated .qhp file. # This tag requires that the tag GENERATE_QHP is set to YES. QHG_LOCATION = # If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be # generated, together with the HTML files, they form an Eclipse help plugin. To # install this plugin and make it available under the help contents menu in # Eclipse, the contents of the directory containing the HTML and XML files needs # to be copied into the plugins directory of eclipse. The name of the directory # within the plugins directory should be the same as the ECLIPSE_DOC_ID value. # After copying Eclipse needs to be restarted before the help appears. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_ECLIPSEHELP = NO # A unique identifier for the Eclipse help plugin. When installing the plugin # the directory name containing the HTML and XML files should also have this # name. Each documentation set should have its own identifier. # The default value is: org.doxygen.Project. # This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES. ECLIPSE_DOC_ID = org.doxygen.Project # If you want full control over the layout of the generated HTML pages it might # be necessary to disable the index and replace it with your own. The # DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top # of each HTML page. A value of NO enables the index and the value YES disables # it. Since the tabs in the index contain the same information as the navigation # tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. DISABLE_INDEX = NO # The GENERATE_TREEVIEW tag is used to specify whether a tree-like index # structure should be generated to display hierarchical information. If the tag # value is set to YES, a side panel will be generated containing a tree-like # index structure (just like the one that is generated for HTML Help). For this # to work a browser that supports JavaScript, DHTML, CSS and frames is required # (i.e. any modern browser). Windows users are probably better off using the # HTML help feature. Via custom style sheets (see HTML_EXTRA_STYLESHEET) one can # further fine tune the look of the index (see "Fine-tuning the output"). As an # example, the default style sheet generated by doxygen has an example that # shows how to put an image at the root of the tree instead of the PROJECT_NAME. # Since the tree basically has the same information as the tab index, you could # consider setting DISABLE_INDEX to YES when enabling this option. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_TREEVIEW = YES # When both GENERATE_TREEVIEW and DISABLE_INDEX are set to YES, then the # FULL_SIDEBAR option determines if the side bar is limited to only the treeview # area (value NO) or if it should extend to the full height of the window (value # YES). Setting this to YES gives a layout similar to # https://docs.readthedocs.io with more room for contents, but less room for the # project logo, title, and description. If either GENERATE_TREEVIEW or # DISABLE_INDEX is set to NO, this option has no effect. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. FULL_SIDEBAR = NO # The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that # doxygen will group on one line in the generated HTML documentation. # # Note that a value of 0 will completely suppress the enum values from appearing # in the overview section. # Minimum value: 0, maximum value: 20, default value: 4. # This tag requires that the tag GENERATE_HTML is set to YES. ENUM_VALUES_PER_LINE = 4 # If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used # to set the initial width (in pixels) of the frame in which the tree is shown. # Minimum value: 0, maximum value: 1500, default value: 250. # This tag requires that the tag GENERATE_HTML is set to YES. TREEVIEW_WIDTH = 250 # If the EXT_LINKS_IN_WINDOW option is set to YES, doxygen will open links to # external symbols imported via tag files in a separate window. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. EXT_LINKS_IN_WINDOW = NO # If the OBFUSCATE_EMAILS tag is set to YES, doxygen will obfuscate email # addresses. # The default value is: YES. # This tag requires that the tag GENERATE_HTML is set to YES. OBFUSCATE_EMAILS = YES # If the HTML_FORMULA_FORMAT option is set to svg, doxygen will use the pdf2svg # tool (see https://github.com/dawbarton/pdf2svg) or inkscape (see # https://inkscape.org) to generate formulas as SVG images instead of PNGs for # the HTML output. These images will generally look nicer at scaled resolutions. # Possible values are: png (the default) and svg (looks nicer but requires the # pdf2svg or inkscape tool). # The default value is: png. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_FORMULA_FORMAT = png # Use this tag to change the font size of LaTeX formulas included as images in # the HTML documentation. When you change the font size after a successful # doxygen run you need to manually remove any form_*.png images from the HTML # output directory to force them to be regenerated. # Minimum value: 8, maximum value: 50, default value: 10. # This tag requires that the tag GENERATE_HTML is set to YES. FORMULA_FONTSIZE = 10 # The FORMULA_MACROFILE can contain LaTeX \newcommand and \renewcommand commands # to create new LaTeX commands to be used in formulas as building blocks. See # the section "Including formulas" for details. FORMULA_MACROFILE = # Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see # https://www.mathjax.org) which uses client side JavaScript for the rendering # instead of using pre-rendered bitmaps. Use this if you do not have LaTeX # installed or if you want to formulas look prettier in the HTML output. When # enabled you may also need to install MathJax separately and configure the path # to it using the MATHJAX_RELPATH option. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. USE_MATHJAX = NO # With MATHJAX_VERSION it is possible to specify the MathJax version to be used. # Note that the different versions of MathJax have different requirements with # regards to the different settings, so it is possible that also other MathJax # settings have to be changed when switching between the different MathJax # versions. # Possible values are: MathJax_2 and MathJax_3. # The default value is: MathJax_2. # This tag requires that the tag USE_MATHJAX is set to YES. MATHJAX_VERSION = MathJax_2 # When MathJax is enabled you can set the default output format to be used for # the MathJax output. For more details about the output format see MathJax # version 2 (see: # http://docs.mathjax.org/en/v2.7-latest/output.html) and MathJax version 3 # (see: # http://docs.mathjax.org/en/latest/web/components/output.html). # Possible values are: HTML-CSS (which is slower, but has the best # compatibility. This is the name for Mathjax version 2, for MathJax version 3 # this will be translated into chtml), NativeMML (i.e. MathML. Only supported # for NathJax 2. For MathJax version 3 chtml will be used instead.), chtml (This # is the name for Mathjax version 3, for MathJax version 2 this will be # translated into HTML-CSS) and SVG. # The default value is: HTML-CSS. # This tag requires that the tag USE_MATHJAX is set to YES. MATHJAX_FORMAT = HTML-CSS # When MathJax is enabled you need to specify the location relative to the HTML # output directory using the MATHJAX_RELPATH option. The destination directory # should contain the MathJax.js script. For instance, if the mathjax directory # is located at the same level as the HTML output directory, then # MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax # Content Delivery Network so you can quickly see the result without installing # MathJax. However, it is strongly recommended to install a local copy of # MathJax from https://www.mathjax.org before deployment. The default value is: # - in case of MathJax version 2: https://cdn.jsdelivr.net/npm/mathjax@2 # - in case of MathJax version 3: https://cdn.jsdelivr.net/npm/mathjax@3 # This tag requires that the tag USE_MATHJAX is set to YES. MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest # The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax # extension names that should be enabled during MathJax rendering. For example # for MathJax version 2 (see # https://docs.mathjax.org/en/v2.7-latest/tex.html#tex-and-latex-extensions): # MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols # For example for MathJax version 3 (see # http://docs.mathjax.org/en/latest/input/tex/extensions/index.html): # MATHJAX_EXTENSIONS = ams # This tag requires that the tag USE_MATHJAX is set to YES. MATHJAX_EXTENSIONS = # The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces # of code that will be used on startup of the MathJax code. See the MathJax site # (see: # http://docs.mathjax.org/en/v2.7-latest/output.html) for more details. For an # example see the documentation. # This tag requires that the tag USE_MATHJAX is set to YES. MATHJAX_CODEFILE = # When the SEARCHENGINE tag is enabled doxygen will generate a search box for # the HTML output. The underlying search engine uses javascript and DHTML and # should work on any modern browser. Note that when using HTML help # (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET) # there is already a search function so this one should typically be disabled. # For large projects the javascript based search engine can be slow, then # enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to # search using the keyboard; to jump to the search box use + S # (what the is depends on the OS and browser, but it is typically # , /